diff --git a/.github/workflows/linux_cuda_wheel.yaml b/.github/workflows/linux_cuda_wheel.yaml index f1801c0f6..17f18fe8b 100644 --- a/.github/workflows/linux_cuda_wheel.yaml +++ b/.github/workflows/linux_cuda_wheel.yaml @@ -71,7 +71,7 @@ jobs: # but for releases we should add 12.8. cuda-version: ['12.6', '13.0'] # TODO: put back ffmpeg 5 https://github.com/pytorch/torchcodec/issues/325 - ffmpeg-version-for-tests: ['4.4.2', '6', '7'] + ffmpeg-version-for-tests: ['4.4.2', '6', '7', '8.0'] container: image: "pytorch/manylinux2_28-builder:cuda${{ matrix.cuda-version }}" diff --git a/.github/workflows/linux_wheel.yaml b/.github/workflows/linux_wheel.yaml index 020068269..bd6ba26e4 100644 --- a/.github/workflows/linux_wheel.yaml +++ b/.github/workflows/linux_wheel.yaml @@ -63,7 +63,7 @@ jobs: fail-fast: false matrix: python-version: ['3.10'] - ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1'] + ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1', '8.0'] needs: build steps: - uses: actions/download-artifact@v4 diff --git a/.github/workflows/macos_wheel.yaml b/.github/workflows/macos_wheel.yaml index 8392aec99..1cee43f22 100644 --- a/.github/workflows/macos_wheel.yaml +++ b/.github/workflows/macos_wheel.yaml @@ -65,7 +65,7 @@ jobs: fail-fast: false matrix: python-version: ['3.10'] - ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1'] + ffmpeg-version-for-tests: ['4.4.2', '5.1.2', '6.1.1', '7.0.1', '8.0'] needs: build steps: - name: Download wheel diff --git a/.github/workflows/windows_wheel.yaml b/.github/workflows/windows_wheel.yaml index b5b3fc4ac..38cc53be9 100644 --- a/.github/workflows/windows_wheel.yaml +++ b/.github/workflows/windows_wheel.yaml @@ -71,6 +71,7 @@ jobs: # TODO: FFmpeg 5 on Windows segfaults in avcodec_open2() when passing # bad parameters. # See https://github.com/pytorch/torchcodec/pull/806 + # TODO: Support FFmpeg 8 on Windows ffmpeg-version-for-tests: ['4.4.2', '6.1.1', '7.0.1'] needs: build steps: diff --git a/src/torchcodec/_core/CMakeLists.txt b/src/torchcodec/_core/CMakeLists.txt index ab6583526..75d1b036c 100644 --- a/src/torchcodec/_core/CMakeLists.txt +++ b/src/torchcodec/_core/CMakeLists.txt @@ -263,11 +263,12 @@ if(DEFINED ENV{BUILD_AGAINST_ALL_FFMPEG_FROM_S3}) you still need a different FFmpeg to be installed for run time!" ) - # This will expose the ffmpeg4, ffmpeg5, ffmpeg6, and ffmpeg7 targets + # This will expose the ffmpeg4, ffmpeg5, ffmpeg6, ffmpeg7, and ffmpeg8 targets include( ${CMAKE_CURRENT_SOURCE_DIR}/fetch_and_expose_non_gpl_ffmpeg_libs.cmake ) + make_torchcodec_libraries(8 ffmpeg8) make_torchcodec_libraries(7 ffmpeg7) make_torchcodec_libraries(6 ffmpeg6) make_torchcodec_libraries(4 ffmpeg4) diff --git a/src/torchcodec/_core/fetch_and_expose_non_gpl_ffmpeg_libs.cmake b/src/torchcodec/_core/fetch_and_expose_non_gpl_ffmpeg_libs.cmake index 22fbdff4c..07abd2e87 100644 --- a/src/torchcodec/_core/fetch_and_expose_non_gpl_ffmpeg_libs.cmake +++ b/src/torchcodec/_core/fetch_and_expose_non_gpl_ffmpeg_libs.cmake @@ -44,6 +44,10 @@ if (LINUX) f7_sha256 1cb946d8b7c6393c2c3ebe1f900b8de7a2885fe614c45d4ec32c9833084f2f26 ) + set( + f8_sha256 + c55b3c1a4b5e4d5fdd7c632bea3ab6f45b4e37cc8e0999dda3f84a8ed8defad8 + ) set( f4_library_file_names libavutil.so.56 @@ -84,6 +88,16 @@ if (LINUX) libswscale.so.8 libswresample.so.5 ) + set( + f8_library_file_names + libavutil.so.60 + libavcodec.so.62 + libavformat.so.62 + libavdevice.so.62 + libavfilter.so.11 + libswscale.so.9 + libswresample.so.6 + ) elseif (APPLE) set(lib_dir "lib") set( @@ -106,6 +120,10 @@ elseif (APPLE) f7_sha256 48a4fc8ce098305cfd4a58f40889249c523ca3c285f66ba704b5bad0e3ada53a ) + set( + f8_sha256 + beb936b76f25d2621228a12cdb67c9ae3d1eff7aa713ef8d1167ebf0c25bd5ec + ) set( f4_library_file_names @@ -147,6 +165,16 @@ elseif (APPLE) libswscale.8.dylib libswresample.5.dylib ) + set( + f8_library_file_names + libavutil.60.dylib + libavcodec.62.dylib + libavformat.62.dylib + libavdevice.62.dylib + libavfilter.11.dylib + libswscale.9.dylib + libswresample.6.dylib + ) elseif (WIN32) set(lib_dir "bin") @@ -170,6 +198,10 @@ elseif (WIN32) f7_sha256 ae391ace382330e912793b70b68529ee7c91026d2869b4df7e7c3e7d3656bdd5 ) + set( + f8_sha256 + bac845ac79876b104959cb0e7b9dec772a261116344dd17d2f97e7ddfac4a73f + ) set( f4_library_file_names @@ -211,6 +243,16 @@ elseif (WIN32) swscale.lib swresample.lib ) + set( + f8_library_file_names + avutil.lib + avcodec.lib + avformat.lib + avdevice.lib + avfilter.lib + swscale.lib + swresample.lib + ) else() message( FATAL_ERROR @@ -242,19 +284,27 @@ FetchContent_Declare( URL_HASH SHA256=${f7_sha256} ) +FetchContent_Declare( + f8 + URL ${platform_url}/8.0.tar.gz + URL_HASH + SHA256=${f8_sha256} +) -FetchContent_MakeAvailable(f4 f5 f6 f7) +FetchContent_MakeAvailable(f4 f5 f6 f7 f8) add_library(ffmpeg4 INTERFACE) add_library(ffmpeg5 INTERFACE) add_library(ffmpeg6 INTERFACE) add_library(ffmpeg7 INTERFACE) +add_library(ffmpeg8 INTERFACE) # Note: the f?_SOURCE_DIR variables were set by FetchContent_MakeAvailable target_include_directories(ffmpeg4 INTERFACE ${f4_SOURCE_DIR}/include) target_include_directories(ffmpeg5 INTERFACE ${f5_SOURCE_DIR}/include) target_include_directories(ffmpeg6 INTERFACE ${f6_SOURCE_DIR}/include) target_include_directories(ffmpeg7 INTERFACE ${f7_SOURCE_DIR}/include) +target_include_directories(ffmpeg8 INTERFACE ${f8_SOURCE_DIR}/include) list( @@ -277,6 +327,11 @@ list( PREPEND ${f7_SOURCE_DIR}/${lib_dir}/ OUTPUT_VARIABLE f7_library_paths ) +list( + TRANSFORM f8_library_file_names + PREPEND ${f8_SOURCE_DIR}/${lib_dir}/ + OUTPUT_VARIABLE f8_library_paths +) target_link_libraries( ffmpeg4 @@ -298,3 +353,8 @@ target_link_libraries( INTERFACE ${f7_library_paths} ) +target_link_libraries( + ffmpeg8 + INTERFACE + ${f8_library_paths} +) diff --git a/test/test_decoders.py b/test/test_decoders.py index 951da0c40..297548f16 100644 --- a/test/test_decoders.py +++ b/test/test_decoders.py @@ -1717,8 +1717,13 @@ def test_metadata(self, asset): == decoder.metadata.stream_index == asset.default_stream_index ) + + expected_duration_seconds_from_header = asset.duration_seconds + if asset == NASA_AUDIO_MP3 and get_ffmpeg_major_version() >= 8: + expected_duration_seconds_from_header = 13.056 + assert decoder.metadata.duration_seconds_from_header == pytest.approx( - asset.duration_seconds + expected_duration_seconds_from_header ) assert decoder.metadata.sample_rate == asset.sample_rate assert decoder.metadata.num_channels == asset.num_channels diff --git a/test/test_metadata.py b/test/test_metadata.py index bf1419a00..628b7a68d 100644 --- a/test/test_metadata.py +++ b/test/test_metadata.py @@ -131,7 +131,16 @@ def test_get_metadata_audio_file(metadata_getter): best_audio_stream_metadata = metadata.streams[metadata.best_audio_stream_index] assert isinstance(best_audio_stream_metadata, AudioStreamMetadata) assert best_audio_stream_metadata is metadata.best_audio_stream - assert best_audio_stream_metadata.duration_seconds_from_header == 13.248 + + ffmpeg_major_version = get_ffmpeg_major_version() + expected_duration_seconds_from_header = ( + 13.056 if ffmpeg_major_version >= 8 else 13.248 + ) + + assert ( + best_audio_stream_metadata.duration_seconds_from_header + == expected_duration_seconds_from_header + ) assert best_audio_stream_metadata.begin_stream_seconds_from_header == 0.138125 assert best_audio_stream_metadata.bit_rate == 64000 assert best_audio_stream_metadata.codec == "mp3" @@ -281,11 +290,15 @@ def test_repr(): average_fps: 29.97002997002997 """ ) + ffmpeg_major_version = get_ffmpeg_major_version() + expected_duration_seconds_from_header = ( + 13.056 if ffmpeg_major_version >= 8 else 13.248 + ) assert ( str(AudioDecoder(NASA_AUDIO_MP3.path).metadata) - == """AudioStreamMetadata: - duration_seconds_from_header: 13.248 + == f"""AudioStreamMetadata: + duration_seconds_from_header: {expected_duration_seconds_from_header} begin_stream_seconds_from_header: 0.138125 bit_rate: 64000.0 codec: mp3