Skip to content

Commit d3be9b2

Browse files
committed
merge
1 parent d42bf11 commit d3be9b2

155 files changed

Lines changed: 3888 additions & 1037 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.forgejo/PULL_REQUEST_TEMPLATE.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Summary of changes
2+
3+
Briefly describe what this PR does and why.
4+
5+
<!--
6+
If this PR requires new FATE test samples, attach them to the PR and
7+
list their target paths below (relative to the fate-suite root).
8+
9+
Attached filenames must match the sample's filename:
10+
11+
```fate-samples
12+
# e.g. vorbis/new-sample.ogg
13+
```
14+
-->

.forgejo/inject-pr-samples.py

Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#!/usr/bin/env python3
2+
# Copyright (c) 2026 Romain Beauxis <romain.beauxis@gmail.com>
3+
#
4+
# Redistribution and use in source and binary forms, with or without
5+
# modification, are permitted provided that the following conditions are met:
6+
#
7+
# 1. Redistributions of source code must retain the above copyright notice,
8+
# this list of conditions and the following disclaimer.
9+
# 2. Redistributions in binary form must reproduce the above copyright notice,
10+
# this list of conditions and the following disclaimer in the documentation
11+
# and/or other materials provided with the distribution.
12+
#
13+
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14+
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15+
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16+
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
17+
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18+
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19+
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20+
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21+
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22+
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
23+
# POSSIBILITY OF SUCH DAMAGE.
24+
25+
"""Inject PR attachment samples into the fate-suite directory.
26+
27+
Usage: inject-pr-samples.py <pr-number>
28+
29+
Reads SAMPLES from the environment (defaults to fate-suite). For each path
30+
listed in a ```fate-samples``` block in the PR description, downloads the
31+
matching PR attachment into $SAMPLES/<path>.
32+
33+
The PR description should contain a block like:
34+
35+
```fate-samples
36+
vorbis/tos.ogg
37+
mov/some-new-sample.mov
38+
```
39+
40+
Each filename must match a file attached to the PR.
41+
"""
42+
43+
import hashlib
44+
import json
45+
import os
46+
import re
47+
import sys
48+
import tempfile
49+
import urllib.request
50+
from pathlib import Path, PurePosixPath
51+
52+
FORGEJO_API = "https://code.ffmpeg.org/api/v1/repos/ffmpeg/ffmpeg/issues"
53+
ATTACHMENT_BASE = "https://code.ffmpeg.org/attachments/"
54+
55+
56+
def fetch_json(url):
57+
with urllib.request.urlopen(url) as r:
58+
return json.load(r)
59+
60+
61+
def parse_fate_samples(body):
62+
paths = []
63+
in_block = False
64+
for line in body.splitlines():
65+
if line == "```fate-samples":
66+
in_block = True
67+
elif line == "```" and in_block:
68+
break
69+
elif in_block:
70+
parts = line.split()
71+
if len(parts) == 1:
72+
paths.append(parts[0])
73+
return paths
74+
75+
76+
MAX_PATH_DEPTH = 3
77+
78+
79+
def validate_path(path):
80+
p = PurePosixPath(path)
81+
if p.is_absolute():
82+
raise ValueError(f"path must be relative: {path!r}")
83+
if ".." in p.parts:
84+
raise ValueError(f"path must not contain '..': {path!r}")
85+
if not p.parts:
86+
raise ValueError(f"empty path")
87+
if len(p.parts) > MAX_PATH_DEPTH:
88+
raise ValueError(f"path too deep (max {MAX_PATH_DEPTH} components): {path!r}")
89+
90+
91+
def validate_url(url):
92+
if not url.startswith(ATTACHMENT_BASE):
93+
raise ValueError(f"unexpected attachment URL: {url!r}")
94+
95+
96+
def digest(path):
97+
h = hashlib.sha256()
98+
with open(path, "rb") as f:
99+
while chunk := f.read(1 << 16):
100+
h.update(chunk)
101+
return h.digest()
102+
103+
104+
def download(url, dst):
105+
dst.parent.mkdir(parents=True, exist_ok=True)
106+
with tempfile.NamedTemporaryFile(dir=dst.parent, delete=False) as tmp:
107+
tmp_path = Path(tmp.name)
108+
try:
109+
with urllib.request.urlopen(url) as r:
110+
while chunk := r.read(1 << 16):
111+
tmp.write(chunk)
112+
if dst.exists() and digest(dst) != digest(tmp_path):
113+
raise ValueError(f"already exists with different content: {dst}")
114+
tmp_path.rename(dst)
115+
except:
116+
tmp_path.unlink(missing_ok=True)
117+
raise
118+
119+
120+
def main():
121+
if len(sys.argv) != 2 or not re.fullmatch(r"[0-9]+", sys.argv[1]):
122+
print(f"Usage: {sys.argv[0]} <pr-number>", file=sys.stderr)
123+
sys.exit(1)
124+
125+
pr_number = sys.argv[1]
126+
samples_dir = Path(os.environ.get("SAMPLES", "fate-suite"))
127+
128+
pr = fetch_json(f"{FORGEJO_API}/{pr_number}")
129+
assets = {a["name"]: a["browser_download_url"] for a in pr.get("assets", [])}
130+
paths = parse_fate_samples(pr.get("body", ""))
131+
132+
if not paths:
133+
sys.exit(0)
134+
135+
new_samples = False
136+
137+
for path in paths:
138+
try:
139+
validate_path(path)
140+
except ValueError as e:
141+
print(f"fate-samples: {e}", file=sys.stderr)
142+
sys.exit(1)
143+
144+
name = PurePosixPath(path).name
145+
url = assets.get(name)
146+
if url is None:
147+
print(f"fate-samples: no attachment named {name!r}", file=sys.stderr)
148+
sys.exit(1)
149+
150+
try:
151+
validate_url(url)
152+
except ValueError as e:
153+
print(f"fate-samples: {e}", file=sys.stderr)
154+
sys.exit(1)
155+
156+
dst = samples_dir / path
157+
is_new = not dst.exists()
158+
try:
159+
download(url, dst)
160+
except ValueError as e:
161+
print(f"fate-samples: {e}", file=sys.stderr)
162+
sys.exit(1)
163+
if is_new:
164+
new_samples = True
165+
print(f"Injected: {path}")
166+
167+
output_file = os.environ.get("FORGEJO_OUTPUT")
168+
if output_file:
169+
with open(output_file, "a") as f:
170+
print(f"new_samples={'true' if new_samples else 'false'}", file=f)
171+
172+
173+
if __name__ == "__main__":
174+
main()

.forgejo/workflows/test.yml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,20 @@ jobs:
5858
with:
5959
path: fate-suite
6060
key: fate-suite-${{ steps.fate.outputs.hash }}
61+
- name: Inject PR Samples
62+
id: inject
63+
if: ${{ forge.event_name == 'pull_request' }}
64+
run: SAMPLES=$PWD/fate-suite .forgejo/inject-pr-samples.py ${{ forge.event.pull_request.number }}
6165
- name: Run Fate
6266
run: |
6367
LD_LIBRARY_PATH="$(printf "%s:" "$PWD"/lib*)$PWD" make fate fate-build SAMPLES="$PWD/fate-suite" -j$(nproc) || FATERES=$?
6468
find . -name "*.err" -exec printf '::group::%s\n' {} \; -exec cat {} \; -exec printf '::endgroup::\n' \;
6569
exit ${FATERES:-0}
70+
- name: Fail if new samples were injected
71+
if: ${{ steps.inject.outputs.new_samples == 'true' }}
72+
run: |
73+
echo "New FATE samples were injected from PR attachments. Please add them to the official fate-suite before merging."
74+
exit 1
6675
run_fate_full:
6776
name: Fate (Full, ${{ matrix.target_exec }})
6877
strategy:
@@ -110,6 +119,10 @@ jobs:
110119
with:
111120
path: fate-suite
112121
key: fate-suite-${{ steps.fate.outputs.hash }}
122+
- name: Inject PR Samples
123+
id: inject
124+
if: ${{ forge.event_name == 'pull_request' }}
125+
run: SAMPLES=$PWD/fate-suite ffmpeg/.forgejo/inject-pr-samples.py ${{ forge.event.pull_request.number }}
113126
- name: Run Fate
114127
run: |
115128
if [[ "${{ matrix.target_exec }}" == "wine" ]]; then
@@ -119,3 +132,8 @@ jobs:
119132
LD_LIBRARY_PATH="$(printf "%s:" "$PWD"/lib*)$PWD" make -C build fate fate-build SAMPLES="$PWD/fate-suite" -j$(nproc) || FATERES=$?
120133
find . -name "*.err" -exec printf '::group::%s\n' {} \; -exec cat {} \; -exec printf '::endgroup::\n' \;
121134
exit ${FATERES:-0}
135+
- name: Fail if new samples were injected
136+
if: ${{ steps.inject.outputs.new_samples == 'true' }}
137+
run: |
138+
echo "New FATE samples were injected from PR attachments. Please add them to the official fate-suite before merging."
139+
exit 1

Changelog

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ version <next>:
1616
- Animated WebP demuxer
1717
- Remove CELT decoding support (doesn't affect Opus CELT)
1818
- Remove ogg/celt parsing
19+
- Bitstream filter to split Dolby Vision multi-layer HEVC
1920

2021

2122
version 8.1:

configure

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2796,6 +2796,7 @@ CONFIG_EXTRA="
27962796
intrax8
27972797
iso_media
27982798
iso_writer
2799+
itut_t35
27992800
ividsp
28002801
jpegtables
28012802
lgplv3
@@ -3099,6 +3100,7 @@ iamfenc_deps="iamf"
30993100
inflate_wrapper_deps="zlib"
31003101
intrax8_select="blockdsp wmv2dsp"
31013102
iso_media_select="mpeg4audio"
3103+
itut_t35_select="atsc_a53 dovi_rpudec"
31023104
me_cmp_select="idctdsp"
31033105
mpeg_er_select="error_resilience"
31043106
mpegaudio_select="mpegaudiodsp mpegaudioheader"
@@ -3154,7 +3156,7 @@ asv2_encoder_select="aandcttables bswapdsp fdctdsp pixblockdsp"
31543156
atrac1_decoder_select="sinewin"
31553157
atrac3p_decoder_select="sinewin"
31563158
atrac3pal_decoder_select="sinewin"
3157-
av1_decoder_select="atsc_a53 cbs_av1 dovi_rpudec"
3159+
av1_decoder_select="cbs_av1 itut_t35"
31583160
bink_decoder_select="blockdsp hpeldsp"
31593161
binkaudio_dct_decoder_select="wma_freqs"
31603162
binkaudio_rdft_decoder_select="wma_freqs"
@@ -3759,6 +3761,7 @@ av1_frame_merge_bsf_select="cbs_av1"
37593761
av1_frame_split_bsf_select="cbs_av1"
37603762
av1_metadata_bsf_select="cbs_av1"
37613763
dovi_rpu_bsf_select="cbs_h265 cbs_av1 dovi_rpudec dovi_rpuenc"
3764+
dovi_split_bsf_select="hevcparse"
37623765
dts2pts_bsf_select="cbs_h264 h264parse cbs_h265 hevc_parser"
37633766
eac3_core_bsf_select="ac3_parser"
37643767
eia608_to_smpte436m_bsf_select="smpte_436m"
@@ -3819,14 +3822,15 @@ hevc_videotoolbox_encoder_select="atsc_a53 videotoolbox_encoder"
38193822
prores_videotoolbox_encoder_deps="pthreads"
38203823
prores_videotoolbox_encoder_select="videotoolbox_encoder"
38213824
libaom_av1_decoder_deps="libaom"
3825+
libaom_av1_decoder_select="itut_t35"
38223826
libaom_av1_encoder_deps="libaom"
38233827
libaom_av1_encoder_select="extract_extradata_bsf dovi_rpuenc"
38243828
libaribb24_decoder_deps="libaribb24"
38253829
libaribcaption_decoder_deps="libaribcaption"
38263830
libcodec2_decoder_deps="libcodec2"
38273831
libcodec2_encoder_deps="libcodec2"
38283832
libdav1d_decoder_deps="libdav1d"
3829-
libdav1d_decoder_select="atsc_a53 dovi_rpudec"
3833+
libdav1d_decoder_select="itut_t35"
38303834
libdavs2_decoder_deps="libdavs2"
38313835
libdavs2_decoder_select="avs2_parser"
38323836
libfdk_aac_decoder_deps="libfdk_aac"
@@ -7885,7 +7889,7 @@ if enabled x86; then
78857889
esac
78867890
elif enabled_any aarch64 ppc64 && ! enabled bigendian; then
78877891
case $target_os in
7888-
linux)
7892+
linux|mingw32*|mingw64*|win32|win64)
78897893
;;
78907894
*)
78917895
disable ffnvcodec cuvid nvdec nvenc

debian/patches/0004-add-cuda-tonemap-impl.patch

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Index: FFmpeg/configure
22
===================================================================
33
--- FFmpeg.orig/configure
44
+++ FFmpeg/configure
5-
@@ -3581,6 +3581,8 @@ scale_cuda_filter_deps="ffnvcodec"
5+
@@ -3583,6 +3583,8 @@ scale_cuda_filter_deps="ffnvcodec"
66
scale_cuda_filter_deps_any="cuda_nvcc cuda_llvm"
77
thumbnail_cuda_filter_deps="ffnvcodec"
88
thumbnail_cuda_filter_deps_any="cuda_nvcc cuda_llvm"
@@ -11,7 +11,7 @@ Index: FFmpeg/configure
1111
transpose_cuda_filter_deps="ffnvcodec"
1212
transpose_cuda_filter_deps_any="cuda_nvcc cuda_llvm"
1313
transpose_npp_filter_deps="ffnvcodec libnpp"
14-
@@ -5048,8 +5050,10 @@ if enabled cuda_nvcc; then
14+
@@ -5052,8 +5054,10 @@ if enabled cuda_nvcc; then
1515
nvcc_default="nvcc"
1616
nvccflags_default="-gencode arch=compute_30,code=sm_30 -O2"
1717
else
@@ -23,7 +23,7 @@ Index: FFmpeg/configure
2323
NVCC_C=""
2424
fi
2525

26-
@@ -5062,6 +5066,11 @@ if enabled cuda_nvcc; then
26+
@@ -5066,6 +5070,11 @@ if enabled cuda_nvcc; then
2727
if $nvcc $nvccflags_default 2>&1 | grep -qi unsupported; then
2828
nvccflags_default="-gencode arch=compute_75,code=sm_75 -O2"
2929
fi
@@ -35,7 +35,7 @@ Index: FFmpeg/configure
3535
fi
3636

3737
set_default arch cc cxx doxygen pkg_config ranlib strip sysinclude \
38-
@@ -7192,7 +7201,7 @@ fi
38+
@@ -7196,7 +7205,7 @@ fi
3939
if enabled cuda_nvcc; then
4040
nvccflags="$nvccflags -ptx"
4141
else

debian/patches/0006-add-opencl-scaler-and-pixfmt-converter-impl.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Index: FFmpeg/configure
22
===================================================================
33
--- FFmpeg.orig/configure
44
+++ FFmpeg/configure
5-
@@ -4259,6 +4259,7 @@ rubberband_filter_deps="librubberband"
5+
@@ -4263,6 +4263,7 @@ rubberband_filter_deps="librubberband"
66
sab_filter_deps="gpl swscale"
77
scale2ref_filter_deps="swscale"
88
scale_filter_deps="swscale"

debian/patches/0014-add-vaapi-hwupload-filter.patch

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Index: FFmpeg/configure
22
===================================================================
33
--- FFmpeg.orig/configure
44
+++ FFmpeg/configure
5-
@@ -4205,6 +4205,7 @@ gblur_vulkan_filter_deps="vulkan spirv_c
5+
@@ -4209,6 +4209,7 @@ gblur_vulkan_filter_deps="vulkan spirv_c
66
hflip_vulkan_filter_deps="vulkan spirv_compiler"
77
histeq_filter_deps="gpl"
88
hqdn3d_filter_deps="gpl"

debian/patches/0019-backport-fixes-for-qsv-from-cartwheel.patch

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ Index: FFmpeg/libavcodec/qsvenc.c
247247
}
248248

249249
static void dump_video_vp9_param(AVCodecContext *avctx, QSVEncContext *q,
250-
@@ -1211,6 +1219,18 @@ static int init_video_param(AVCodecConte
250+
@@ -1213,6 +1221,18 @@ static int init_video_param(AVCodecConte
251251
q->extparam_internal[q->nb_extparam_internal++] = (mfxExtBuffer *)&q->exthevctiles;
252252
}
253253

@@ -266,7 +266,7 @@ Index: FFmpeg/libavcodec/qsvenc.c
266266
q->extvsi.VideoFullRange = (avctx->color_range == AVCOL_RANGE_JPEG);
267267
q->extvsi.ColourDescriptionPresent = 0;
268268

269-
@@ -1463,12 +1483,17 @@ static int qsv_retrieve_enc_params(AVCod
269+
@@ -1465,12 +1485,17 @@ static int qsv_retrieve_enc_params(AVCod
270270
};
271271
#endif
272272

@@ -285,7 +285,7 @@ Index: FFmpeg/libavcodec/qsvenc.c
285285
ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&extradata;
286286
ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&co;
287287

288-
@@ -1496,6 +1521,10 @@ static int qsv_retrieve_enc_params(AVCod
288+
@@ -1498,6 +1523,10 @@ static int qsv_retrieve_enc_params(AVCod
289289
ext_buffers[ext_buf_num++] = (mfxExtBuffer*)&hyper_mode_param_buf;
290290
}
291291
#endif

0 commit comments

Comments
 (0)