refactor: FFmpeg 7.1 support (#101)

* feat: FFmpeg 7.1

* test: reset golden

* fix encoder

* test: update golden files
This commit is contained in:
Adrian Shum 2025-07-21 20:43:26 +08:00 committed by GitHub
parent 1b26cf82f8
commit d01256b982
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
35 changed files with 73 additions and 65 deletions

View file

@ -13,17 +13,17 @@ jobs:
env:
CGO_CFLAGS_ALLOW: -Xpreprocessor
VIPS_VERSION: 8.17.1
FFMPEG_VERSION: 5.1.2
V: 4
FFMPEG_VERSION: 7.1.1
V: 5
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
uses: actions/setup-go@v4
with:
go-version: ^1.24
- name: Check out code
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Install linux dependencies
run: |
@ -38,7 +38,7 @@ jobs:
libopenslide-dev libcfitsio-dev liborc-0.4-dev libpango1.0-dev \
libtiff5-dev libgsf-1-dev giflib-tools libwebp-dev \
yasm libx264-dev libx265-dev libnuma-dev libvpx-dev libtheora-dev \
librtmp-dev libvorbis-dev \
librtmp-dev libvorbis-dev libdav1d-dev libaom-dev \
libopenjp2-7-dev libcgif-dev
# Install newer libheif from backports
sudo apt-get install -y -t jammy-backports libheif-dev || sudo apt-get install -y libheif-dev
@ -78,13 +78,12 @@ jobs:
restore-keys: |
${{ runner.os }}-ffmpeg-${{ env.V }}-
- name: Build ffmpeg from source
run: |
if [ ! -d "ffmpeg-${{ env.FFMPEG_VERSION }}" ]
then
wget https://ffmpeg.org/releases/ffmpeg-${{ env.FFMPEG_VERSION }}.tar.bz2
tar jvxf ffmpeg-${{ env.FFMPEG_VERSION }}.tar.bz2
wget https://ffmpeg.org/releases/ffmpeg-${{ env.FFMPEG_VERSION }}.tar.xz
tar xf ffmpeg-${{ env.FFMPEG_VERSION }}.tar.xz
fi
cd ffmpeg-${{ env.FFMPEG_VERSION }}
./configure --prefix=/usr/local \
@ -101,7 +100,9 @@ jobs:
--enable-libwebp \
--enable-libvpx \
--enable-libx265 \
--enable-libx264
--enable-libx264 \
--enable-libdav1d \
--enable-libaom
make && sudo make install
sudo ldconfig

View file

@ -1,14 +1,13 @@
ARG GOLANG_VERSION=1.24.5
FROM golang:${GOLANG_VERSION}-bookworm as builder
ARG FFMPEG_VERSION=5.1.2
ARG FFMPEG_VERSION=7.1.1
ARG VIPS_VERSION=8.17.1
ARG TARGETARCH
ENV PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
ENV MAKEFLAGS="-j8"
# Installs libvips + required libraries
RUN DEBIAN_FRONTEND=noninteractive \
apt-get update && \
@ -21,7 +20,7 @@ RUN DEBIAN_FRONTEND=noninteractive \
swig libpango1.0-dev libmatio-dev libopenslide-dev libcfitsio-dev libopenjp2-7-dev \
libgsf-1-dev libfftw3-dev liborc-0.4-dev librsvg2-dev libimagequant-dev libaom-dev libheif-dev \
yasm libx264-dev libx265-dev libnuma-dev libvpx-dev libtheora-dev \
libspng-dev libcgif-dev librtmp-dev libvorbis-dev && \
libspng-dev libcgif-dev librtmp-dev libvorbis-dev libdav1d-dev && \
cd /tmp && \
curl -fsSLO https://github.com/libvips/libvips/releases/download/v${VIPS_VERSION}/vips-${VIPS_VERSION}.tar.xz && \
tar xf vips-${VIPS_VERSION}.tar.xz && \
@ -36,8 +35,8 @@ RUN DEBIAN_FRONTEND=noninteractive \
ninja -C _build && \
ninja -C _build install && \
cd /tmp && \
curl -fsSLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
tar jvxf ffmpeg-${FFMPEG_VERSION}.tar.bz2 && \
curl -fsSLO https://ffmpeg.org/releases/ffmpeg-${FFMPEG_VERSION}.tar.xz && \
tar xf ffmpeg-${FFMPEG_VERSION}.tar.xz && \
cd /tmp/ffmpeg-${FFMPEG_VERSION} && \
./configure --prefix=/usr/local \
--disable-debug \
@ -53,7 +52,9 @@ RUN DEBIAN_FRONTEND=noninteractive \
--enable-libwebp \
--enable-libvpx \
--enable-libx265 \
--enable-libx264 && \
--enable-libx264 \
--enable-libdav1d \
--enable-libaom && \
make && make install && \
ldconfig && \
rm -rf /usr/local/lib/python* && \
@ -89,7 +90,7 @@ RUN echo "deb http://deb.debian.org/debian bookworm-backports main" > /etc/apt/s
libpango1.0-0 libmatio11 libopenslide0 libopenjp2-7 libjemalloc2 \
libgsf-1-114 libfftw3-bin liborc-0.4-0 librsvg2-2 libcfitsio10 libimagequant0 libaom3 \
libx264-dev libx265-dev libnuma-dev libvpx7 libtheora0 libvorbis-dev \
libspng0 libcgif0 && \
libspng0 libcgif0 libdav1d6 && \
apt-get install --no-install-recommends -y -t bookworm-backports libheif1 && \
ln -s /usr/lib/$(uname -m)-linux-gnu/libjemalloc.so.2 /usr/local/lib/libjemalloc.so && \
apt-get autoremove -y && \

View file

@ -210,23 +210,28 @@ AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha) {
return output_frame;
}
AVPacket create_packet() {
AVPacket *create_packet() {
AVPacket *pkt = av_packet_alloc();
if (!pkt) {
return NULL;
}
pkt->data = NULL;
pkt->size = 0;
return *pkt;
return pkt;
}
int
obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame) {
int obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame) {
int err = 0, retry = 0;
if (!(*frame) && !(*frame = av_frame_alloc())) {
err = AVERROR(ENOMEM);
return err;
}
// Try to receive a frame from the decoder first
if ((err = avcodec_receive_frame(dec_ctx, *frame)) != AVERROR(EAGAIN)) {
return err;
}
while (1) {
if ((err = av_read_frame(fmt_ctx, pkt)) < 0) {
break;
@ -239,6 +244,7 @@ obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_
if (retry++ >= 10) {
break;
}
av_packet_unref(pkt);
continue;
}
if (!(*frame) && !(*frame = av_frame_alloc())) {
@ -251,7 +257,7 @@ obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_
}
av_packet_unref(pkt);
}
if (pkt->buf) {
if (pkt->data) {
av_packet_unref(pkt);
}
return err;

View file

@ -301,8 +301,13 @@ func populateFrames(av *AVContext, frames <-chan *C.AVFrame) <-chan struct{} {
func createThumbContext(av *AVContext, maxFrames C.int) error {
pkt := C.create_packet()
if pkt == nil {
return avError(C.int(ErrNoMem))
}
defer C.av_packet_free(&pkt)
var frame *C.AVFrame
err := C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, &pkt, &frame)
err := C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, pkt, &frame)
if err >= 0 {
incrementDuration(av, frame, 0)
av.thumbContext = C.create_thumb_context(av.stream, frame)
@ -311,9 +316,6 @@ func createThumbContext(av *AVContext, maxFrames C.int) error {
}
}
if err < 0 {
if pkt.buf != nil {
C.av_packet_unref(&pkt)
}
if frame != nil {
C.av_frame_free(&frame)
}
@ -332,18 +334,20 @@ func createThumbContext(av *AVContext, maxFrames C.int) error {
frames := make(chan *C.AVFrame, n)
done := populateFrames(av, frames)
frames <- frame
if pkt.buf != nil {
C.av_packet_unref(&pkt)
}
return populateThumbContext(av, frames, n, done)
}
func populateThumbContext(av *AVContext, frames chan *C.AVFrame, n C.int, done <-chan struct{}) error {
pkt := C.create_packet()
if pkt == nil {
return avError(C.int(ErrNoMem))
}
defer C.av_packet_free(&pkt)
var frame *C.AVFrame
var err C.int
for i := C.int(1); i < n; i++ {
err = C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, &pkt, &frame)
err = C.obtain_next_frame(av.formatContext, av.codecContext, av.stream.index, pkt, &frame)
if err < 0 {
break
}
@ -362,9 +366,6 @@ func populateThumbContext(av *AVContext, frames chan *C.AVFrame, n C.int, done <
av.selectedIndex = av.availableIndex
}
close(frames)
if pkt.buf != nil {
C.av_packet_unref(&pkt)
}
if frame != nil {
C.av_frame_free(&frame)
}

View file

@ -47,10 +47,9 @@ int create_codec_context(AVStream *video_stream, AVCodecContext **dec_ctx);
AVFrame *convert_frame_to_rgb(AVFrame *frame, int alpha);
AVPacket create_packet();
AVPacket *create_packet();
int
obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame);
int obtain_next_frame(AVFormatContext *fmt_ctx, AVCodecContext *dec_ctx, int stream_index, AVPacket *pkt, AVFrame **frame);
ThumbContext *create_thumb_context(AVStream *stream, AVFrame *frame);

View file

@ -1 +1 @@
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":3925,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":3924,"width":492,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":1,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":1,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":3,"duration":2544,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":3,"duration":2535,"width":480,"height":360,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":6,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":6,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}

View file

@ -1 +1 @@
{"orientation":8,"duration":2544,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}
{"orientation":8,"duration":2535,"width":360,"height":480,"fps":29.97002997002997,"has_video":true,"has_audio":true}