Pass NULL for automatic hardware device selection #113
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Continuous integration for go-ffmpeg-ffi | |
| name: CI | |
| on: | |
| push: | |
| branches: [master, main] | |
| pull_request: | |
| branches: [master, main] | |
| env: | |
| GO_VERSION: '1.23' | |
| jobs: | |
| shim-contract: | |
| runs-on: ubuntu-latest | |
| name: Verify shim contract | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Reject stale C/Go contract output | |
| run: go run ./internal/shim/cmd/gencontract -check | |
| # Test without FFmpeg (should pass - tests mock/skip FFmpeg deps) | |
| test-no-ffmpeg: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Run tests without FFmpeg | |
| run: go test -v -short ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| # Compile the complete module and every test binary with the pinned Android | |
| # NDK. Runtime and hardware-codec qualification are separate device gates. | |
| android-compile: | |
| runs-on: ubuntu-latest | |
| name: Compile (Android API 33, ${{ matrix.arch }}) | |
| timeout-minutes: 30 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| arch: [arm64, amd64] | |
| env: | |
| ANDROID_API: "33" | |
| ANDROID_NDK_VERSION: "26.3.11579264" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| # Ebitengine 2.9.9 declares Go 1.24. The binding itself retains its | |
| # older language floor and is compiled by the other jobs as well. | |
| go-version: '1.24' | |
| - name: Install pinned Android NDK | |
| run: | | |
| sdk_root="${ANDROID_SDK_ROOT:-$ANDROID_HOME}" | |
| set +o pipefail | |
| yes | "$sdk_root/cmdline-tools/latest/bin/sdkmanager" --licenses >/dev/null | |
| set -o pipefail | |
| "$sdk_root/cmdline-tools/latest/bin/sdkmanager" "ndk;$ANDROID_NDK_VERSION" | |
| - name: Compile packages and tests | |
| run: ./scripts/verify-android-build.sh "${{ matrix.arch }}" | |
| - name: Install pinned Ebitengine mobile binder | |
| run: go install github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile@v2.9.9 | |
| - name: Bind downstream Ebitengine fixture | |
| run: | | |
| output="$GITHUB_WORKSPACE/.build/android-ebiten/${{ matrix.arch }}/game.aar" | |
| mkdir -p "$(dirname "$output")" | |
| cd integration/android-ebiten | |
| ebitenmobile bind \ | |
| -target "android/${{ matrix.arch }}" \ | |
| -javapkg dev.bstk.ffmpeg.probe.corelib \ | |
| -o "$output" . | |
| test -s "$output" | |
| # PureGo requires CGO on iOS. Compile the complete module for the physical | |
| # device and both simulator architectures, then bind a downstream | |
| # Ebitengine fixture into the same XCFramework shape consumed by Xcode apps. | |
| ios-compile: | |
| runs-on: macos-14 | |
| name: Compile (iOS 13, device + simulator) | |
| timeout-minutes: 45 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| # Ebitengine 2.9.9 declares Go 1.24. | |
| go-version: '1.24' | |
| cache-dependency-path: | | |
| go.sum | |
| integration/ios-ebiten/go.sum | |
| - name: Record Xcode toolchain | |
| run: | | |
| xcodebuild -version | |
| xcrun --sdk iphoneos --show-sdk-version | |
| xcrun --sdk iphonesimulator --show-sdk-version | |
| - name: Compile packages and tests for iPhone ARM64 | |
| run: ./scripts/verify-ios-build.sh iphoneos arm64 | |
| - name: Compile packages and tests for simulator ARM64 | |
| run: ./scripts/verify-ios-build.sh iphonesimulator arm64 | |
| - name: Compile packages and tests for simulator x86-64 | |
| run: ./scripts/verify-ios-build.sh iphonesimulator amd64 | |
| - name: Install pinned Ebitengine mobile binder | |
| run: go install github.com/hajimehoshi/ebiten/v2/cmd/ebitenmobile@v2.9.9 | |
| - name: Bind downstream Ebitengine fixture | |
| working-directory: integration/ios-ebiten | |
| run: make compile | |
| - name: Verify XCFramework slices | |
| run: | | |
| info=integration/ios-ebiten/.build/FFmpegProbe.xcframework/Info.plist | |
| plutil -lint "$info" | |
| plutil -convert json -o - "$info" | grep -q 'ios-arm64' | |
| plutil -convert json -o - "$info" | grep -q 'ios-arm64_x86_64-simulator' | |
| # Keep the complete desktop package and test surface buildable without CGO. | |
| # Native runtime jobs below qualify the architectures for which GitHub | |
| # provides runners; Windows ARM64 remains a compile-only target. | |
| desktop-compile: | |
| runs-on: ubuntu-latest | |
| name: Compile (${{ matrix.goos }}/${{ matrix.goarch }}) | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - goos: windows | |
| goarch: amd64 | |
| - goos: windows | |
| goarch: arm64 | |
| - goos: darwin | |
| goarch: amd64 | |
| - goos: darwin | |
| goarch: arm64 | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Compile packages and tests | |
| run: go test -exec /bin/true -run '^$' ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| GOOS: ${{ matrix.goos }} | |
| GOARCH: ${{ matrix.goarch }} | |
| # Test every supported FFmpeg release line on one pinned platform. | |
| test-with-ffmpeg-linux: | |
| runs-on: ubuntu-latest | |
| name: Test (Linux amd64, FFmpeg ${{ matrix.ffmpeg }}) | |
| timeout-minutes: 45 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - ffmpeg: '6.0.1' | |
| major: '6' | |
| sha256: '9b16b8731d78e596b4be0d720428ca42df642bb2d78342881ff7f5bc29fc9623' | |
| - ffmpeg: '6.1.6' | |
| major: '6' | |
| sha256: 'd4fcb164028dd3beee5d92c0ac72e46aac6973c75ea12dc14de07bf8f407370a' | |
| - ffmpeg: '7.0.3' | |
| major: '7' | |
| sha256: 'bbb18f3cc5c1c34b21cf176c0168c4d9aa97697542a97f60d491a58a814dea65' | |
| - ffmpeg: '7.1.5' | |
| major: '7' | |
| sha256: 'de668509caf9e35e3cd162473441fdb29538c6d96ed080292b3cf9e6fc5d558f' | |
| - ffmpeg: '8.0.3' | |
| major: '8' | |
| sha256: '6136812ea6d4e68bdba27e33c2a94382711cdf4f8602ffef056ff792bd6f9818' | |
| - ffmpeg: '8.1.2' | |
| major: '8' | |
| sha256: '464beb5e7bf0c311e68b45ae2f04e9cc2af88851abb4082231742a74d97b524c' | |
| - ffmpeg: '9.0.1' | |
| major: '9' | |
| sha256: 'cf38e0e28c7e5605942c4a77755349b0145804a397af37eb1fb4c77cb237f635' | |
| env: | |
| FFMPEG_PREFIX: ${{ github.workspace }}/.ffmpeg/${{ matrix.ffmpeg }} | |
| FFMPEG_EXPECTED_MAJOR: ${{ matrix.major }} | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Prepare workspace temp directory | |
| run: | | |
| mkdir -p .work/tmp | |
| echo "TMPDIR=$GITHUB_WORKSPACE/.work/tmp" >> "$GITHUB_ENV" | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y build-essential curl nasm pkg-config libx264-dev zlib1g-dev | |
| - name: Restore FFmpeg build | |
| id: ffmpeg-cache | |
| uses: actions/cache@v4 | |
| with: | |
| path: ${{ env.FFMPEG_PREFIX }} | |
| key: ffmpeg-linux-amd64-${{ matrix.ffmpeg }}-v1 | |
| - name: Build FFmpeg ${{ matrix.ffmpeg }} | |
| if: steps.ffmpeg-cache.outputs.cache-hit != 'true' | |
| run: | | |
| mkdir -p .work/ffmpeg-source "$FFMPEG_PREFIX" "$TMPDIR" | |
| curl --fail --location --retry 3 \ | |
| --output .work/ffmpeg.tar.xz \ | |
| "https://ffmpeg.org/releases/ffmpeg-${{ matrix.ffmpeg }}.tar.xz" | |
| echo "${{ matrix.sha256 }} .work/ffmpeg.tar.xz" | sha256sum --check --strict | |
| tar -xf .work/ffmpeg.tar.xz --strip-components=1 -C .work/ffmpeg-source | |
| cd .work/ffmpeg-source | |
| ./configure \ | |
| --prefix="$FFMPEG_PREFIX" \ | |
| --enable-shared \ | |
| --disable-static \ | |
| --disable-doc \ | |
| --disable-debug \ | |
| --disable-autodetect \ | |
| --disable-network \ | |
| --disable-ffplay \ | |
| --enable-gpl \ | |
| --enable-libx264 \ | |
| --enable-zlib | |
| make -j4 | |
| make install | |
| - name: Select FFmpeg ${{ matrix.ffmpeg }} | |
| run: | | |
| echo "$FFMPEG_PREFIX/bin" >> "$GITHUB_PATH" | |
| echo "LD_LIBRARY_PATH=$FFMPEG_PREFIX/lib" >> "$GITHUB_ENV" | |
| echo "PKG_CONFIG_PATH=$FFMPEG_PREFIX/lib/pkgconfig" >> "$GITHUB_ENV" | |
| - name: Verify selected FFmpeg release | |
| run: ffmpeg -version | head -n 1 | grep -F "ffmpeg version ${{ matrix.ffmpeg }} " | |
| - name: Verify selected FFmpeg runtime | |
| run: go test -count=1 -run '^TestConfiguredFFmpegFamily$' -v ./internal/bindings | |
| env: | |
| CGO_ENABLED: "0" | |
| - name: Verify FFmpeg ABI layout | |
| run: | | |
| mkdir -p .work "$TMPDIR" | |
| cc -std=c11 -Wall -Wextra -Werror \ | |
| $(pkg-config --cflags libavutil libavcodec libavformat libavfilter libavdevice libswscale libswresample) \ | |
| internal/abi/testdata/layout_probe.c \ | |
| -o .work/layout-probe | |
| .work/layout-probe > .work/layout.txt | |
| go run ./internal/abi/cmd/check-layout < .work/layout.txt | |
| - name: Build shim | |
| working-directory: shim | |
| run: ./build.sh | |
| - name: Run unit and integration tests | |
| run: go test -count=1 -v ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| FFMPEG_SHIM_DIR: ${{ github.workspace }}/shim | |
| # Test with FFmpeg (Windows amd64). Windows ARM64 has no public native | |
| # GitHub-hosted runner, so it is covered by the compile matrix above. | |
| test-with-ffmpeg-windows-amd64: | |
| runs-on: windows-latest | |
| name: Test (Windows amd64) | |
| timeout-minutes: 45 | |
| env: | |
| WINDOWS_FFMPEG_VERSION: "9.0.1" | |
| WINDOWS_FFMPEG_SHA256: "6fd54b3b4f49117a307877b570f5e1659090f178973298658b41f5c559b5b5ab" | |
| WINDOWS_FFMPEG_URL: "https://github.com/GyanD/codexffmpeg/releases/download/9.0.1/ffmpeg-9.0.1-full_build-shared.zip" | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install UCRT64 toolchain | |
| uses: msys2/setup-msys2@v2 | |
| with: | |
| msystem: UCRT64 | |
| update: true | |
| install: >- | |
| make | |
| mingw-w64-ucrt-x86_64-gcc | |
| - name: Restore pinned FFmpeg build | |
| id: ffmpeg-cache | |
| uses: actions/cache/restore@v4 | |
| with: | |
| path: .work/ffmpeg-windows-${{ env.WINDOWS_FFMPEG_VERSION }} | |
| key: ffmpeg-windows-amd64-gyan-${{ env.WINDOWS_FFMPEG_VERSION }}-v1 | |
| - name: Install public shared FFmpeg ${{ env.WINDOWS_FFMPEG_VERSION }} build | |
| if: steps.ffmpeg-cache.outputs.cache-hit != 'true' | |
| shell: pwsh | |
| run: | | |
| $work = Join-Path $env:GITHUB_WORKSPACE ".work" | |
| $archive = Join-Path $work "ffmpeg-$env:WINDOWS_FFMPEG_VERSION-full_build-shared.zip" | |
| $expanded = Join-Path $work "ffmpeg-$env:WINDOWS_FFMPEG_VERSION-full_build-shared" | |
| $prefix = Join-Path $work "ffmpeg-windows-$env:WINDOWS_FFMPEG_VERSION" | |
| New-Item -ItemType Directory -Force -Path $work | Out-Null | |
| curl.exe --fail --location --retry 3 --output $archive $env:WINDOWS_FFMPEG_URL | |
| $actual = (Get-FileHash -Algorithm SHA256 $archive).Hash.ToLowerInvariant() | |
| if ($actual -ne $env:WINDOWS_FFMPEG_SHA256) { | |
| throw "FFmpeg archive checksum mismatch: $actual" | |
| } | |
| Expand-Archive -LiteralPath $archive -DestinationPath $work | |
| Move-Item -LiteralPath $expanded -Destination $prefix | |
| - name: Save pinned FFmpeg build | |
| if: steps.ffmpeg-cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@v4 | |
| with: | |
| path: .work/ffmpeg-windows-${{ env.WINDOWS_FFMPEG_VERSION }} | |
| key: ffmpeg-windows-amd64-gyan-${{ env.WINDOWS_FFMPEG_VERSION }}-v1 | |
| - name: Expose FFmpeg and shim to native Windows processes | |
| shell: msys2 {0} | |
| run: | | |
| github_path="$(cygpath -u "$GITHUB_PATH")" | |
| github_env="$(cygpath -u "$GITHUB_ENV")" | |
| workspace="$(cygpath -u "$GITHUB_WORKSPACE")" | |
| prefix="$workspace/.work/ffmpeg-windows-$WINDOWS_FFMPEG_VERSION" | |
| printf '%s\n' "$(cygpath -w "$prefix/bin")" >> "$github_path" | |
| printf '%s\n' "$(cygpath -w /ucrt64/bin)" >> "$github_path" | |
| printf 'WINDOWS_FFMPEG_BIN=%s\n' "$(cygpath -w "$prefix/bin")" >> "$github_env" | |
| printf 'FFMPEG_SHIM_DIR=%s\n' "$(cygpath -w "$workspace/shim")" >> "$github_env" | |
| - name: Verify installed FFmpeg | |
| shell: pwsh | |
| run: | | |
| $env:Path = "$env:WINDOWS_FFMPEG_BIN;$env:Path" | |
| $version = ffmpeg -version | Select-Object -First 1 | |
| if ($version -notmatch "^ffmpeg version $env:WINDOWS_FFMPEG_VERSION(?:-| )") { | |
| throw "Unexpected FFmpeg version: $version" | |
| } | |
| - name: Probe FFmpeg ABI layout | |
| shell: msys2 {0} | |
| run: | | |
| workspace="$(cygpath -u "$GITHUB_WORKSPACE")" | |
| prefix="$workspace/.work/ffmpeg-windows-$WINDOWS_FFMPEG_VERSION" | |
| mkdir -p .work | |
| gcc -std=c11 -Wall -Wextra -Werror \ | |
| -I"$prefix/include" \ | |
| internal/abi/testdata/layout_probe.c \ | |
| -o .work/layout-probe.exe | |
| ./.work/layout-probe.exe > .work/layout.txt | |
| - name: Verify FFmpeg ABI layout | |
| shell: pwsh | |
| run: Get-Content .work\layout.txt | go run ./internal/abi/cmd/check-layout | |
| - name: Build shim | |
| shell: msys2 {0} | |
| working-directory: shim | |
| run: | | |
| workspace="$(cygpath -u "$GITHUB_WORKSPACE")" | |
| prefix="$workspace/.work/ffmpeg-windows-$WINDOWS_FFMPEG_VERSION" | |
| make native \ | |
| CFLAGS_NATIVE="-Wall -Wextra -O2 -fPIC -DFFSHIM_HAVE_AVDEVICE=1 -I$prefix/include" \ | |
| LDFLAGS_NATIVE="-L$prefix/lib -lavdevice -lavformat -lavcodec -lavutil" | |
| - name: Run unit and integration tests | |
| shell: pwsh | |
| run: | | |
| $env:Path = "$env:WINDOWS_FFMPEG_BIN;$env:Path" | |
| go test -count=1 -v ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| # Test with FFmpeg (macOS Intel) | |
| test-with-ffmpeg-macos-intel: | |
| runs-on: macos-15-intel | |
| name: Test (macOS Intel) | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install FFmpeg | |
| run: brew install ffmpeg | |
| - name: Verify FFmpeg ABI layout | |
| run: | | |
| mkdir -p .work | |
| cc -std=c11 -Wall -Wextra -Werror \ | |
| $(pkg-config --cflags libavutil libavcodec libavformat libavfilter libavdevice libswscale libswresample) \ | |
| internal/abi/testdata/layout_probe.c \ | |
| -o .work/layout-probe | |
| .work/layout-probe | go run ./internal/abi/cmd/check-layout | |
| - name: Build shim | |
| working-directory: shim | |
| run: ./build.sh | |
| - name: Set library path | |
| run: echo "DYLD_LIBRARY_PATH=${{ github.workspace }}/shim:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV | |
| - name: Run tests | |
| run: go test -v ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| FFMPEG_SHIM_DIR: ${{ github.workspace }}/shim | |
| - name: Run integration tests | |
| run: go test -v -run Integration ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| FFMPEG_SHIM_DIR: ${{ github.workspace }}/shim | |
| # Test with FFmpeg (macOS ARM64) | |
| test-with-ffmpeg-macos-arm64: | |
| runs-on: macos-15 | |
| name: Test (macOS ARM64) | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install FFmpeg | |
| run: brew install ffmpeg | |
| - name: Verify FFmpeg ABI layout | |
| run: | | |
| mkdir -p .work | |
| cc -std=c11 -Wall -Wextra -Werror \ | |
| $(pkg-config --cflags libavutil libavcodec libavformat libavfilter libavdevice libswscale libswresample) \ | |
| internal/abi/testdata/layout_probe.c \ | |
| -o .work/layout-probe | |
| .work/layout-probe | go run ./internal/abi/cmd/check-layout | |
| - name: Build shim | |
| working-directory: shim | |
| run: ./build.sh | |
| - name: Set library path | |
| run: echo "DYLD_LIBRARY_PATH=${{ github.workspace }}/shim:$DYLD_LIBRARY_PATH" >> $GITHUB_ENV | |
| - name: Run tests | |
| run: go test -v ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| FFMPEG_SHIM_DIR: ${{ github.workspace }}/shim | |
| - name: Run integration tests | |
| run: go test -v -run Integration ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| FFMPEG_SHIM_DIR: ${{ github.workspace }}/shim | |
| # Test graceful degradation without shim | |
| test-degraded-mode: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: Install FFmpeg (without building shim) | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y ffmpeg libavcodec-dev libavformat-dev libavutil-dev \ | |
| libswscale-dev libswresample-dev libavfilter-dev | |
| - name: Run tests (no shim - degraded mode) | |
| run: go test -v ./... | |
| env: | |
| CGO_ENABLED: "0" | |
| # Explicitly unset shim directory to test degraded mode | |
| FFMPEG_SHIM_DIR: "" | |
| # Lint and vet | |
| lint: | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Set up Go | |
| uses: actions/setup-go@v5 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| - name: golangci-lint | |
| uses: golangci/golangci-lint-action@v4 | |
| with: | |
| version: latest | |
| args: --timeout=5m | |
| - name: go vet | |
| run: go vet ./... |