Skip to content

Add codec ffmpeg #621

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
157 changes: 157 additions & 0 deletions .github/workflows/pkg-codec-ffmpeg-ci.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
name: pkg/codec/ffmpeg CI
on:
pull_request:
branches:
- master
paths:
- pkg/codec/ffmepg
push:
branches:
- master
paths:
- pkg/codec/ffmepg

jobs:
build-linux:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
go:
- '1.21' # oldest version this package supports
- '1.22' # oldstable Go version
- '1.23' # stable Go version
name: Linux Go ${{ matrix.go }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: Install dependencies
run: |
sudo apt-get update -qq
sudo apt-get install --no-install-recommends -y \
libopus-dev \
libva-dev \
libvpx-dev \
libx11-dev \
libx264-dev \
libxext-dev \
nasm \
yasm
- name: Cache FFmpeg build
uses: actions/cache@v4
id: ffmpeg-cache
with:
path: |
pkg/codec/ffmpeg/tmp/n7.0
key: ffmpeg-linux-n7.0-${{ hashFiles('pkg/codec/ffmpeg/Makefile') }}
restore-keys: |
ffmpeg-linux-n7.0-
- name: Check if FFmpeg libraries exist
id: ffmpeg-check
working-directory: pkg/codec/ffmpeg
run: |
echo "=== Checking FFmpeg cache status ==="
if [ -f "tmp/n7.0/lib/libavcodec.a" ] && [ -f "tmp/n7.0/lib/pkgconfig/libavcodec.pc" ]; then
echo "FFmpeg libraries found in cache"
echo "ffmpeg_exists=true" >> $GITHUB_OUTPUT
else
echo "FFmpeg libraries missing or incomplete"
ls -la tmp/ 2>/dev/null || echo "tmp directory does not exist"
ls -la tmp/n7.0/ 2>/dev/null || echo "n7.0 directory does not exist"
ls -la tmp/n7.0/lib/ 2>/dev/null || echo "lib directory does not exist"
echo "ffmpeg_exists=false" >> $GITHUB_OUTPUT
fi
- name: Build FFmpeg (if not cached or incomplete)
if: steps.ffmpeg-cache.outputs.cache-hit != 'true' || steps.ffmpeg-check.outputs.ffmpeg_exists != 'true'
working-directory: pkg/codec/ffmpeg
run: make build-ffmpeg
- name: Verify FFmpeg installation
working-directory: pkg/codec/ffmpeg
run: |
ls -la tmp/n7.0/
ls -la tmp/n7.0/lib/ || echo "lib directory not found"
ls -la tmp/n7.0/include/ || echo "include directory not found"
pkg-config --exists --print-errors libavcodec || echo "pkg-config check failed"
env:
PKG_CONFIG_PATH: ${{ github.workspace }}/pkg/codec/ffmpeg/tmp/n7.0/lib/pkgconfig
- name: Run pkg/codec/ffmpeg Test Suite
working-directory: pkg/codec/ffmpeg
run: |
make test
env:
PKG_CONFIG_PATH: ${{ github.workspace }}/pkg/codec/ffmpeg/tmp/n7.0/lib/pkgconfig
- uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
build-darwin:
strategy:
fail-fast: false
matrix:
go:
- '1.22'
- '1.23'
runs-on: macos-latest
name: Darwin Go ${{ matrix.go }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ matrix.go }}
- name: Install dependencies
run: |
brew install \
pkg-config \
opus \
libvpx \
x264
- name: Cache FFmpeg build
uses: actions/cache@v4
id: ffmpeg-cache
with:
path: |
pkg/codec/ffmpeg/tmp/n7.0
key: ffmpeg-darwin-n7.0-${{ hashFiles('pkg/codec/ffmpeg/Makefile') }}
restore-keys: |
ffmpeg-darwin-n7.0-
- name: Check if FFmpeg libraries exist
id: ffmpeg-check
working-directory: pkg/codec/ffmpeg
run: |
if [ -f "tmp/n7.0/lib/libavcodec.a" ] && [ -f "tmp/n7.0/lib/pkgconfig/libavcodec.pc" ]; then
echo "ffmpeg_exists=true" >> $GITHUB_OUTPUT
else
echo "ffmpeg_exists=false" >> $GITHUB_OUTPUT
fi
- name: Build FFmpeg (if not cached or incomplete)
if: steps.ffmpeg-cache.outputs.cache-hit != 'true' || steps.ffmpeg-check.outputs.ffmpeg_exists != 'true'
working-directory: pkg/codec/ffmpeg
run: make build-ffmpeg
- name: Run Test Suite
working-directory: pkg/codec/ffmpeg
run: |
make test
env:
PKG_CONFIG_PATH: ${{ github.workspace }}/pkg/codec/ffmpeg/tmp/n7.0/lib/pkgconfig
- uses: codecov/codecov-action@v5
with:
token: ${{ secrets.CODECOV_TOKEN }}
check-licenses:
runs-on: ubuntu-latest
name: Check Licenses
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: stable
- name: Installing go-licenses
run: go install github.com/google/go-licenses@latest
- name: Checking licenses
run: go-licenses check ./...
18 changes: 18 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,24 @@ An open source API that allows applications such as VLC media player or GStreame
* Installation:
* Ubuntu: `apt install libva-dev`

#### Video codecs implemented using ffmpeg

* Package: [github.com/pion/mediadevices/pkg/codec/ffmpeg](https://pkg.go.dev/github.com/pion/mediadevices/pkg/codec/ffmpeg)
* Installation: You need to enable CGO, and provide the ffmpeg headers and libraries when compiling. For more detail, checkout
https://github.com/asticode/go-astiav?tab=readme-ov-file#install-ffmpeg-from-source.
* NVENC: If you want to use nvenc, you need to install [FFmpeg/nv-codec-headers](https://github.com/FFmpeg/nv-codec-headers) too.
Make sure that your driver's version is supported by the nv-codec-headers version you are installing.
To install it, clone the repo, checkout to wanted version, and `sudo make install`.

> Currently, only ffmpeg n7.0 and n7.1 are supported.

##### nvenc

Requires ffmpeg build with `--enable-nonfree --enable-nvenc`.

##### x264

Requires ffmpeg build with `--enable-libx264 --enable-gpl`.

#### Audio Codecs

Expand Down
1 change: 1 addition & 0 deletions pkg/codec/ffmpeg/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
tmp
41 changes: 41 additions & 0 deletions pkg/codec/ffmpeg/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
version=n7.0
srcPath=tmp/$(version)/src
installPath=tmp/$(version)
CGO_CFLAGS := -I$(CURDIR)/$(installPath)/include/
CGO_LDFLAGS := -L$(CURDIR)/$(installPath)/lib/
PKG_CONFIG_PATH := $(CURDIR)/$(installPath)/lib/pkgconfig
configure := --enable-libx264 --enable-gpl

# Main test target - depends on FFmpeg being built
test: $(installPath)/lib/libavcodec.a
PKG_CONFIG_PATH=$(PKG_CONFIG_PATH) CGO_CFLAGS="$(CGO_CFLAGS)" CGO_LDFLAGS="$(CGO_LDFLAGS)" go test -v .

# Separate target for building FFmpeg (used by CI when cache miss)
build-ffmpeg: $(installPath)/lib/libavcodec.a
@echo "FFmpeg build completed"

# Clean incomplete builds before starting
clean-incomplete:
@if [ -d "$(srcPath)" ] && [ ! -f "$(installPath)/lib/libavcodec.a" ]; then \
echo "Cleaning incomplete build..."; \
rm -rf $(srcPath); \
fi

# FFmpeg build rule
$(installPath)/lib/libavcodec.a: clean-incomplete $(srcPath)/Makefile
cd $(srcPath) && make -j4
cd $(srcPath) && make install
@echo "Installation completed, checking results..."
@ls -la $(installPath)/lib/ || echo "lib directory not found"
@ls -la $(installPath)/include/ || echo "include directory not found"

$(srcPath)/Makefile: $(srcPath)/.git
cd $(srcPath) && ./configure --prefix=$(CURDIR)/$(installPath) $(configure)

$(srcPath)/.git:
rm -rf $(srcPath)
mkdir -p $(srcPath)
cd $(srcPath) && git clone https://github.com/FFmpeg/FFmpeg .
cd $(srcPath) && git checkout $(version)

.PHONY: test build-ffmpeg clean-incomplete
18 changes: 18 additions & 0 deletions pkg/codec/ffmpeg/errors.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ffmpeg

import (
"errors"
)

var (
errFailedToCreateHwDevice = errors.New("ffmpeg: failed to create device")
errCodecNotFound = errors.New("ffmpeg: codec not found")
errFailedToCreateCodecCtx = errors.New("ffmpeg: failed to allocate codec context")
errFailedToCreateHwFramesCtx = errors.New("ffmpeg: failed to create hardware frames context")
errFailedToInitHwFramesCtx = errors.New("ffmpeg: failed to initialize hardware frames context")
errFailedToOpenCodecCtx = errors.New("ffmpeg: failed to open codec context")
errFailedToAllocFrame = errors.New("ffmpeg: failed to allocate frame")
errFailedToAllocSwBuf = errors.New("ffmpeg: failed to allocate software buffer")
errFailedToAllocHwBuf = errors.New("ffmpeg: failed to allocate hardware buffer")
errFailedToAllocPacket = errors.New("ffmpeg: failed to allocate packet")
)
Loading
Loading