Skip to content

Commit a47f5ed

Browse files
authored
[Release 0.7] remove custom_frame_mappings from 0.7 release branch (#871)
1 parent d2055ba commit a47f5ed

File tree

2 files changed

+110
-132
lines changed

2 files changed

+110
-132
lines changed

src/torchcodec/decoders/_video_decoder.py

Lines changed: 1 addition & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -63,25 +63,6 @@ class VideoDecoder:
6363
probably is. Default: "exact".
6464
Read more about this parameter in:
6565
:ref:`sphx_glr_generated_examples_decoding_approximate_mode.py`
66-
custom_frame_mappings (str, bytes, or file-like object, optional):
67-
Mapping of frames to their metadata, typically generated via ffprobe.
68-
This enables accurate frame seeking without requiring a full video scan.
69-
Do not set seek_mode when custom_frame_mappings is provided.
70-
Expected JSON format:
71-
72-
.. code-block:: json
73-
74-
{
75-
"frames": [
76-
{
77-
"pts": 0,
78-
"duration": 1001,
79-
"key_frame": 1
80-
}
81-
]
82-
}
83-
84-
Alternative field names "pkt_pts" and "pkt_duration" are also supported.
8566
8667
Attributes:
8768
metadata (VideoStreamMetadata): Metadata of the video stream.
@@ -99,9 +80,6 @@ def __init__(
9980
num_ffmpeg_threads: int = 1,
10081
device: Optional[Union[str, torch_device]] = "cpu",
10182
seek_mode: Literal["exact", "approximate"] = "exact",
102-
custom_frame_mappings: Optional[
103-
Union[str, bytes, io.RawIOBase, io.BufferedReader]
104-
] = None,
10583
):
10684
torch._C._log_api_usage_once("torchcodec.decoders.VideoDecoder")
10785
allowed_seek_modes = ("exact", "approximate")
@@ -111,6 +89,7 @@ def __init__(
11189
f"Supported values are {', '.join(allowed_seek_modes)}."
11290
)
11391

92+
custom_frame_mappings = None
11493
# Validate seek_mode and custom_frame_mappings are not mismatched
11594
if custom_frame_mappings is not None and seek_mode == "approximate":
11695
raise ValueError(

test/test_decoders.py

Lines changed: 109 additions & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import contextlib
88
import gc
99
import json
10-
from functools import partial
1110
from unittest.mock import patch
1211

1312
import numpy
@@ -1280,115 +1279,115 @@ def test_10bit_videos_cpu(self, asset):
12801279
decoder = VideoDecoder(asset.path)
12811280
decoder.get_frame_at(10)
12821281

1283-
def setup_frame_mappings(tmp_path, file, stream_index):
1284-
json_path = tmp_path / "custom_frame_mappings.json"
1285-
custom_frame_mappings = NASA_VIDEO.generate_custom_frame_mappings(stream_index)
1286-
if file:
1287-
# Write the custom frame mappings to a JSON file
1288-
with open(json_path, "w") as f:
1289-
f.write(custom_frame_mappings)
1290-
return json_path
1291-
else:
1292-
# Return the custom frame mappings as a JSON string
1293-
return custom_frame_mappings
1294-
1295-
@pytest.mark.parametrize("device", all_supported_devices())
1296-
@pytest.mark.parametrize("stream_index", [0, 3])
1297-
@pytest.mark.parametrize(
1298-
"method",
1299-
(
1300-
partial(setup_frame_mappings, file=True),
1301-
partial(setup_frame_mappings, file=False),
1302-
),
1303-
)
1304-
def test_custom_frame_mappings_json_and_bytes(
1305-
self, tmp_path, device, stream_index, method
1306-
):
1307-
custom_frame_mappings = method(tmp_path=tmp_path, stream_index=stream_index)
1308-
# Optionally open the custom frame mappings file if it is a file path
1309-
# or use a null context if it is a string.
1310-
with (
1311-
open(custom_frame_mappings, "r")
1312-
if hasattr(custom_frame_mappings, "read")
1313-
else contextlib.nullcontext()
1314-
) as custom_frame_mappings:
1315-
decoder = VideoDecoder(
1316-
NASA_VIDEO.path,
1317-
stream_index=stream_index,
1318-
device=device,
1319-
custom_frame_mappings=custom_frame_mappings,
1320-
)
1321-
frame_0 = decoder.get_frame_at(0)
1322-
frame_5 = decoder.get_frame_at(5)
1323-
assert_frames_equal(
1324-
frame_0.data,
1325-
NASA_VIDEO.get_frame_data_by_index(0, stream_index=stream_index).to(device),
1326-
)
1327-
assert_frames_equal(
1328-
frame_5.data,
1329-
NASA_VIDEO.get_frame_data_by_index(5, stream_index=stream_index).to(device),
1330-
)
1331-
frames0_5 = decoder.get_frames_played_in_range(
1332-
frame_0.pts_seconds, frame_5.pts_seconds
1333-
)
1334-
assert_frames_equal(
1335-
frames0_5.data,
1336-
NASA_VIDEO.get_frame_data_by_range(0, 5, stream_index=stream_index).to(
1337-
device
1338-
),
1339-
)
1340-
1341-
@pytest.mark.parametrize("device", all_supported_devices())
1342-
@pytest.mark.parametrize(
1343-
"custom_frame_mappings,expected_match",
1344-
[
1345-
pytest.param(
1346-
NASA_VIDEO.generate_custom_frame_mappings(0),
1347-
"seek_mode",
1348-
id="valid_content_approximate",
1349-
),
1350-
("{}", "The input is empty or missing the required 'frames' key."),
1351-
(
1352-
'{"valid": "json"}',
1353-
"The input is empty or missing the required 'frames' key.",
1354-
),
1355-
(
1356-
'{"frames": [{"missing": "keys"}]}',
1357-
"keys are required in the frame metadata.",
1358-
),
1359-
],
1360-
)
1361-
def test_custom_frame_mappings_init_fails(
1362-
self, device, custom_frame_mappings, expected_match
1363-
):
1364-
with pytest.raises(ValueError, match=expected_match):
1365-
VideoDecoder(
1366-
NASA_VIDEO.path,
1367-
stream_index=0,
1368-
device=device,
1369-
custom_frame_mappings=custom_frame_mappings,
1370-
seek_mode=("approximate" if expected_match == "seek_mode" else "exact"),
1371-
)
1372-
1373-
@pytest.mark.parametrize("device", all_supported_devices())
1374-
def test_custom_frame_mappings_init_fails_invalid_json(self, tmp_path, device):
1375-
invalid_json_path = tmp_path / "invalid_json"
1376-
with open(invalid_json_path, "w+") as f:
1377-
f.write("invalid input")
1378-
1379-
# Test both file object and string
1380-
with open(invalid_json_path, "r") as file_obj:
1381-
for custom_frame_mappings in [
1382-
file_obj,
1383-
file_obj.read(),
1384-
]:
1385-
with pytest.raises(ValueError, match="Invalid custom frame mappings"):
1386-
VideoDecoder(
1387-
NASA_VIDEO.path,
1388-
stream_index=0,
1389-
device=device,
1390-
custom_frame_mappings=custom_frame_mappings,
1391-
)
1282+
# def setup_frame_mappings(tmp_path, file, stream_index):
1283+
# json_path = tmp_path / "custom_frame_mappings.json"
1284+
# custom_frame_mappings = NASA_VIDEO.generate_custom_frame_mappings(stream_index)
1285+
# if file:
1286+
# # Write the custom frame mappings to a JSON file
1287+
# with open(json_path, "w") as f:
1288+
# f.write(custom_frame_mappings)
1289+
# return json_path
1290+
# else:
1291+
# # Return the custom frame mappings as a JSON string
1292+
# return custom_frame_mappings
1293+
1294+
# @pytest.mark.parametrize("device", all_supported_devices())
1295+
# @pytest.mark.parametrize("stream_index", [0, 3])
1296+
# @pytest.mark.parametrize(
1297+
# "method",
1298+
# (
1299+
# partial(setup_frame_mappings, file=True),
1300+
# partial(setup_frame_mappings, file=False),
1301+
# ),
1302+
# )
1303+
# def test_custom_frame_mappings_json_and_bytes(
1304+
# self, tmp_path, device, stream_index, method
1305+
# ):
1306+
# custom_frame_mappings = method(tmp_path=tmp_path, stream_index=stream_index)
1307+
# # Optionally open the custom frame mappings file if it is a file path
1308+
# # or use a null context if it is a string.
1309+
# with (
1310+
# open(custom_frame_mappings, "r")
1311+
# if hasattr(custom_frame_mappings, "read")
1312+
# else contextlib.nullcontext()
1313+
# ) as custom_frame_mappings:
1314+
# decoder = VideoDecoder(
1315+
# NASA_VIDEO.path,
1316+
# stream_index=stream_index,
1317+
# device=device,
1318+
# custom_frame_mappings=custom_frame_mappings,
1319+
# )
1320+
# frame_0 = decoder.get_frame_at(0)
1321+
# frame_5 = decoder.get_frame_at(5)
1322+
# assert_frames_equal(
1323+
# frame_0.data,
1324+
# NASA_VIDEO.get_frame_data_by_index(0, stream_index=stream_index).to(device),
1325+
# )
1326+
# assert_frames_equal(
1327+
# frame_5.data,
1328+
# NASA_VIDEO.get_frame_data_by_index(5, stream_index=stream_index).to(device),
1329+
# )
1330+
# frames0_5 = decoder.get_frames_played_in_range(
1331+
# frame_0.pts_seconds, frame_5.pts_seconds
1332+
# )
1333+
# assert_frames_equal(
1334+
# frames0_5.data,
1335+
# NASA_VIDEO.get_frame_data_by_range(0, 5, stream_index=stream_index).to(
1336+
# device
1337+
# ),
1338+
# )
1339+
1340+
# @pytest.mark.parametrize("device", all_supported_devices())
1341+
# @pytest.mark.parametrize(
1342+
# "custom_frame_mappings,expected_match",
1343+
# [
1344+
# pytest.param(
1345+
# NASA_VIDEO.generate_custom_frame_mappings(0),
1346+
# "seek_mode",
1347+
# id="valid_content_approximate",
1348+
# ),
1349+
# ("{}", "The input is empty or missing the required 'frames' key."),
1350+
# (
1351+
# '{"valid": "json"}',
1352+
# "The input is empty or missing the required 'frames' key.",
1353+
# ),
1354+
# (
1355+
# '{"frames": [{"missing": "keys"}]}',
1356+
# "keys are required in the frame metadata.",
1357+
# ),
1358+
# ],
1359+
# )
1360+
# def test_custom_frame_mappings_init_fails(
1361+
# self, device, custom_frame_mappings, expected_match
1362+
# ):
1363+
# with pytest.raises(ValueError, match=expected_match):
1364+
# VideoDecoder(
1365+
# NASA_VIDEO.path,
1366+
# stream_index=0,
1367+
# device=device,
1368+
# custom_frame_mappings=custom_frame_mappings,
1369+
# seek_mode=("approximate" if expected_match == "seek_mode" else "exact"),
1370+
# )
1371+
1372+
# @pytest.mark.parametrize("device", all_supported_devices())
1373+
# def test_custom_frame_mappings_init_fails_invalid_json(self, tmp_path, device):
1374+
# invalid_json_path = tmp_path / "invalid_json"
1375+
# with open(invalid_json_path, "w+") as f:
1376+
# f.write("invalid input")
1377+
1378+
# # Test both file object and string
1379+
# with open(invalid_json_path, "r") as file_obj:
1380+
# for custom_frame_mappings in [
1381+
# file_obj,
1382+
# file_obj.read(),
1383+
# ]:
1384+
# with pytest.raises(ValueError, match="Invalid custom frame mappings"):
1385+
# VideoDecoder(
1386+
# NASA_VIDEO.path,
1387+
# stream_index=0,
1388+
# device=device,
1389+
# custom_frame_mappings=custom_frame_mappings,
1390+
# )
13921391

13931392

13941393
class TestAudioDecoder:

0 commit comments

Comments
 (0)