|
39 | 39 | get_ffmpeg_minor_version, |
40 | 40 | get_python_version, |
41 | 41 | H264_10BITS, |
42 | | - H265_10BITS, |
43 | 42 | H265_VIDEO, |
44 | 43 | in_fbcode, |
45 | 44 | make_video_decoder, |
@@ -1643,8 +1642,6 @@ def test_10bit_gpu_fallsback_to_cpu(self): |
1643 | 1642 | # do the color conversion on the CPU. |
1644 | 1643 | # Here we just assert that the GPU results are the same as the CPU |
1645 | 1644 | # results. |
1646 | | - # TODO see other TODO below in test_10bit_videos_cpu: we should validate |
1647 | | - # the frames against a reference. |
1648 | 1645 | # |
1649 | 1646 | # This test exercises the FFmpeg CUDA interface specifically: its CPU |
1650 | 1647 | # fallback delegates directly to CpuDeviceInterface, so the output |
@@ -1675,15 +1672,6 @@ def test_10bit_gpu_fallsback_to_cpu(self): |
1675 | 1672 | frames_cpu = decoder_cpu.get_frames_at(frame_indices).data |
1676 | 1673 | assert_frames_equal(frames_gpu.cpu(), frames_cpu) |
1677 | 1674 |
|
1678 | | - @pytest.mark.parametrize("device", all_supported_devices()) |
1679 | | - @pytest.mark.parametrize("asset", (H264_10BITS, H265_10BITS)) |
1680 | | - def test_10bit_videos(self, device, asset): |
1681 | | - # This just validates that we can decode 10-bit videos. |
1682 | | - # TODO validate against the ref that the decoded frames are correct |
1683 | | - |
1684 | | - decoder, _ = make_video_decoder(asset.path, device=device) |
1685 | | - decoder.get_frame_at(10) |
1686 | | - |
1687 | 1675 | def setup_frame_mappings(tmp_path, file, stream_index): |
1688 | 1676 | json_path = tmp_path / "custom_frame_mappings.json" |
1689 | 1677 | custom_frame_mappings = NASA_VIDEO.generate_custom_frame_mappings(stream_index) |
@@ -1811,20 +1799,21 @@ def test_get_frames_at_tensor_indices(self): |
1811 | 1799 | decoder.get_frames_played_at(torch.tensor([0, 1], dtype=torch.int)) |
1812 | 1800 | decoder.get_frames_played_at(torch.tensor([0, 1], dtype=torch.float)) |
1813 | 1801 |
|
1814 | | - # TODONVDEC P1: |
1815 | | - # - unskip equality assertion checks on FFMpeg4. The comparison |
1816 | | - # checks are failing on very few pixels, e.g.: |
| 1802 | + # Note [NVDEC vs FFmpeg CUDA pixel mismatches]: |
| 1803 | + # These tests compare the NVDEC (beta) CUDA backend against the FFmpeg |
| 1804 | + # CUDA backend. There are two known sources of pixel mismatches: |
1817 | 1805 | # |
1818 | | - # E Mismatched elements: 648586 / 82944000 (0.8%) |
1819 | | - # E Greatest absolute difference: 164 at index (20, 2, 27, 96) |
1820 | | - # E Greatest relative difference: inf at index (5, 1, 112, 186) |
| 1806 | + # 1. FFmpeg 4: small pixel differences on a few pixels (< 1%), cause |
| 1807 | + # unknown. We don't investigate further since FFmpeg 4 is not a |
| 1808 | + # priority. |
1821 | 1809 | # |
1822 | | - # So we're skipping them to unblock for now, but we should call |
1823 | | - # assert_tensor_close_on_at_least or something like that. |
1824 | | - # - unskip equality assertion checks for MPEG4 asset. The frames are decoded |
1825 | | - # fine, it's the color conversion that's different. The frame from the |
1826 | | - # NVDEC interface is mapped to 709 by the matrix coefficient |
1827 | | - # using NVCUVID while the one from the FFmpeg CUDA interface is 601. |
| 1810 | + # 2. MPEG4 asset: NVCUVID's parser reports matrix_coefficients=1 |
| 1811 | + # (BT.709) for the MPEG4 asset, even though the bitstream has no |
| 1812 | + # color metadata. This is an NVIDIA-internal heuristic. FFmpeg's |
| 1813 | + # parser leaves colorspace as UNSPECIFIED, which both swscale (CPU) |
| 1814 | + # and our color conversion code treat as BT.601. So the NVDEC |
| 1815 | + # backend uses BT.709 while the FFmpeg CUDA backend (and CPU) use |
| 1816 | + # BT.601 for this asset, leading to different RGB output. |
1828 | 1817 |
|
1829 | 1818 | @needs_cuda |
1830 | 1819 | @pytest.mark.parametrize( |
@@ -1864,7 +1853,7 @@ def test_nvdec_cuda_interface_get_frame_at( |
1864 | 1853 | for frame_index in indices: |
1865 | 1854 | ref_frame = ref_decoder.get_frame_at(frame_index) |
1866 | 1855 | nvdec_frame = nvdec_decoder.get_frame_at(frame_index) |
1867 | | - # TODONVDEC P1 see above |
| 1856 | + # See Note [NVDEC vs FFmpeg CUDA pixel mismatches] |
1868 | 1857 | if ffmpeg_major_version > 5 and asset is not TEST_SRC_2_720P_MPEG4: |
1869 | 1858 | torch.testing.assert_close( |
1870 | 1859 | nvdec_frame.data, ref_frame.data, rtol=0, atol=0 |
@@ -1911,7 +1900,7 @@ def test_nvdec_cuda_interface_get_frames_at( |
1911 | 1900 |
|
1912 | 1901 | ref_frames = ref_decoder.get_frames_at(indices) |
1913 | 1902 | nvdec_frames = nvdec_decoder.get_frames_at(indices) |
1914 | | - # TODONVDEC P1 see above |
| 1903 | + # See Note [NVDEC vs FFmpeg CUDA pixel mismatches] |
1915 | 1904 | if ffmpeg_major_version > 5 and asset is not TEST_SRC_2_720P_MPEG4: |
1916 | 1905 | torch.testing.assert_close( |
1917 | 1906 | nvdec_frames.data, ref_frames.data, rtol=0, atol=0 |
@@ -1954,7 +1943,7 @@ def test_nvdec_cuda_interface_get_frame_played_at(self, asset, seek_mode): |
1954 | 1943 | for pts in timestamps: |
1955 | 1944 | ref_frame = ref_decoder.get_frame_played_at(pts) |
1956 | 1945 | nvdec_frame = nvdec_decoder.get_frame_played_at(pts) |
1957 | | - # TODONVDEC P1 see above |
| 1946 | + # See Note [NVDEC vs FFmpeg CUDA pixel mismatches] |
1958 | 1947 | if ffmpeg_major_version > 5 and asset is not TEST_SRC_2_720P_MPEG4: |
1959 | 1948 | torch.testing.assert_close( |
1960 | 1949 | nvdec_frame.data, ref_frame.data, rtol=0, atol=0 |
@@ -1996,7 +1985,7 @@ def test_nvdec_cuda_interface_get_frames_played_at(self, asset, seek_mode): |
1996 | 1985 |
|
1997 | 1986 | ref_frames = ref_decoder.get_frames_played_at(timestamps) |
1998 | 1987 | nvdec_frames = nvdec_decoder.get_frames_played_at(timestamps) |
1999 | | - # TODONVDEC P1 see above |
| 1988 | + # See Note [NVDEC vs FFmpeg CUDA pixel mismatches] |
2000 | 1989 | if ffmpeg_major_version > 5 and asset is not TEST_SRC_2_720P_MPEG4: |
2001 | 1990 | torch.testing.assert_close( |
2002 | 1991 | nvdec_frames.data, ref_frames.data, rtol=0, atol=0 |
@@ -2043,7 +2032,7 @@ def test_nvdec_cuda_interface_backwards(self, asset, seek_mode): |
2043 | 2032 |
|
2044 | 2033 | ref_frame = ref_decoder.get_frame_at(frame_index) |
2045 | 2034 | nvdec_frame = nvdec_decoder.get_frame_at(frame_index) |
2046 | | - # TODONVDEC P1 see above |
| 2035 | + # See Note [NVDEC vs FFmpeg CUDA pixel mismatches] |
2047 | 2036 | if ffmpeg_major_version > 5 and asset is not TEST_SRC_2_720P_MPEG4: |
2048 | 2037 | torch.testing.assert_close( |
2049 | 2038 | nvdec_frame.data, ref_frame.data, rtol=0, atol=0 |
@@ -2071,8 +2060,9 @@ def test_cuda_mpeg4_mp4_first_frame(self, seek_mode): |
2071 | 2060 | assert frame0.pts_seconds == expected_frame0.pts_seconds |
2072 | 2061 | assert frame0.duration_seconds == expected_frame0.duration_seconds |
2073 | 2062 | assert frame0.data.shape == expected_frame0.data.shape |
2074 | | - # Strict pixel equality is skipped — TODONVDEC P1 above (BT.601 vs |
2075 | | - # BT.709 color matrix mismatch between the ffmpeg and default cuda). |
| 2063 | + # Strict pixel equality is skipped — see Note [NVDEC vs FFmpeg CUDA |
| 2064 | + # pixel mismatches] (BT.601 vs BT.709 color matrix mismatch between the |
| 2065 | + # ffmpeg and default cuda backend for this MPEG4 asset). |
2076 | 2066 |
|
2077 | 2067 | @needs_cuda |
2078 | 2068 | def test_nvdec_cuda_interface_cpu_fallback(self): |
|
0 commit comments