ffmpeg-cvslog
Threads by month
- ----- 2026 -----
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
September 2025
- 1 participants
- 195 discussions
[ffmpeg-web] branch master updated. 8830305 web: Add funding.json
by ffmpeg-git@ffmpeg.org 03 Sep '25
by ffmpeg-git@ffmpeg.org 03 Sep '25
03 Sep '25
The branch, master has been updated
via 8830305f52defcfa30f15b8aeb46a4f07ad42d6d (commit)
via 7238ff304c4912796adbbddd7b7f9c6298b2f166 (commit)
from cbfe12e6dedb1ca81a308d8a396ae678747bbc2b (commit)
- Log -----------------------------------------------------------------
commit 8830305f52defcfa30f15b8aeb46a4f07ad42d6d
Author: Michael Niedermayer <michael(a)niedermayer.cc>
AuthorDate: Thu Aug 28 21:59:49 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Wed Sep 3 14:55:53 2025 +0200
web: Add funding.json
See: https://fundingjson.org/
See: https://floss.fund/
Based on: https://www.python.org/funding.json and the example from fundingjson.org
It is put in the web repository so its all on the plain ffmpeg.org domain otherwise extra files are needed
Discussed in the General Assembly: 0830 9:53 Sponsors and funding.json
As of 3rd September there are no objections and no requests for changes in the General Assembly
diff --git a/htdocs/funding.json b/htdocs/funding.json
new file mode 100644
index 0000000..42664c7
--- /dev/null
+++ b/htdocs/funding.json
@@ -0,0 +1,126 @@
+{
+ "version": "v1.0.0",
+
+ "entity": {
+ "type": "group",
+ "role": "owner",
+ "name": "FFmpeg",
+ "email": "ffmpeg-devel(a)ffmpeg.org",
+ "description": "FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. It supports the most obscure ancient formats up to the cutting edge. No matter if they were designed by some standards committee, the community or a corporation. It is also highly portable: FFmpeg compiles, runs, and passes our testing infrastructure FATE across Linux, Mac OS X, Microsoft Windows, the BSDs, Solaris, etc. under a wide variety of build environments, machine architectures, and configurations.",
+ "webpageUrl": {
+ "url": "https://ffmpeg.org/"
+ }
+ },
+
+ "projects": [{
+ "guid": "ffmpeg",
+ "name": "FFmpeg",
+ "description": "FFmpeg is the leading multimedia framework, able to decode, encode, transcode, mux, demux, stream, filter and play pretty much anything that humans and machines have created. It supports the most obscure ancient formats up to the cutting edge. No matter if they were designed by some standards committee, the community or a corporation. It is also highly portable: FFmpeg compiles, runs, and passes our testing infrastructure FATE across Linux, Mac OS X, Microsoft Windows, the BSDs, Solaris, etc. under a wide variety of build environments, machine architectures, and configurations.",
+ "webpageUrl": {
+ "url": "https://ffmpeg.org/"
+ },
+ "repositoryUrl": {
+ "url": "https://ffmpeg.org/download"
+ },
+ "licenses": ["spdx:LGPL-2.1-or-later", "spdx:GPL-2.0-or-later"],
+ "tags": ["audio", "graphics"]
+ }],
+
+ "funding": {
+ "channels": [{
+ "guid": "ffmpeg-spi",
+ "type": "other",
+ "address": "https://ffmpeg.org/donations.html",
+ "description": "Paypal, CreditCard, Check, Money Order"
+ },{
+ "guid": "ffmpeg-spi-bank",
+ "type": "bank",
+ "address": "Please email us for payment details.",
+ "description": "Bank transfer"
+ }
+ ],
+
+ "plans": [{
+ "guid": "ffmpeg-individual",
+ "status": "active",
+ "name": "FFmpeg individual",
+ "description": "Pay as much or as little as you want",
+ "amount": 0,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi"]
+ },{
+ "guid": "visionary",
+ "status": "active",
+ "name": "Visionary Sponsor",
+ "amount": 155000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ },{
+ "guid": "sustainability",
+ "status": "active",
+ "name": "Sustainability Sponsor",
+ "amount": 95000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ },{
+ "guid": "maintaining",
+ "status": "active",
+ "name": "Maintaining Sponsor",
+ "amount": 63000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ },{
+ "guid": "contributing",
+ "status": "active",
+ "name": "Contributing Sponsor",
+ "amount": 33000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ },{
+ "guid": "supporting",
+ "status": "active",
+ "name": "Supporting Sponsor",
+ "amount": 16500,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ },{
+ "guid": "partner",
+ "status": "active",
+ "name": "Partner Sponsor",
+ "amount": 11000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ },{
+ "guid": "participating",
+ "status": "active",
+ "name": "Participating Sponsor",
+ "amount": 4000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi", "ffmpeg-spi-bank"]
+ },{
+ "guid": "associate",
+ "status": "active",
+ "name": "Associate Sponsor",
+ "amount": 1500,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi", "ffmpeg-spi-bank"]
+ },{
+ "guid": "ffmpeg-maintainer",
+ "status": "active",
+ "name": "Sponsor a full time maintainer and patch reviewer",
+ "amount": 100000,
+ "currency": "USD",
+ "frequency": "yearly",
+ "channels": ["ffmpeg-spi-bank"]
+ }]
+ }
+}
commit 7238ff304c4912796adbbddd7b7f9c6298b2f166
Author: Michael Niedermayer <michael(a)niedermayer.cc>
AuthorDate: Wed Sep 3 14:54:22 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Wed Sep 3 14:55:46 2025 +0200
CVE-2024-7272 ticket number
diff --git a/src/security b/src/security
index d05e369..b80fd98 100644
--- a/src/security
+++ b/src/security
@@ -149,6 +149,7 @@ CVE-2022-2566, c953baa084607dd1d84c3bfcce3cf6a87c3e6e05
CVE-2022-3964, 92f9b28ed84a77138105475beba16c146bdaf984
CVE-2022-3965, 13c13109759090b7f7182480d075e13b36ed8edd
CVE-2022-48434, cc867f2c09d2b69cee8a0eccd62aff002cbbfe11
+CVE-2024-7272, 9903ba28c28ab18dc7b7b6fb8571cc8b5caae1a6, ticket/9908
</pre>
@@ -178,7 +179,7 @@ Fixes following vulnerabilities:
</p>
<pre>
CVE-2024-7055, 5372bfe01e4a04357ab4465c1426cf8c6412dfd5 / 3faadbe2a27e74ff5bb5f7904ec27bb1f5287dc8
-CVE-2024-7272, a937b3c58babae893fb46b286a4792cd24a01d3d / 9903ba28c28ab18dc7b7b6fb8571cc8b5caae1a6
+CVE-2024-7272, a937b3c58babae893fb46b286a4792cd24a01d3d / 9903ba28c28ab18dc7b7b6fb8571cc8b5caae1a6, ticket/9908
</pre>
<h3>5.1.5</h3>
-----------------------------------------------------------------------
Summary of changes:
htdocs/funding.json | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++++
src/security | 3 +-
2 files changed, 128 insertions(+), 1 deletion(-)
create mode 100644 htdocs/funding.json
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. 66e40840d1 avcodec/pcm_tablegen: Fix CONFIG_HARDCODED_TABLES
by ffmpeg-git@ffmpeg.org 03 Sep '25
by ffmpeg-git@ffmpeg.org 03 Sep '25
03 Sep '25
The branch, master has been updated
via 66e40840d15b514f275ce3ce2a4bf72ec68c7311 (commit)
from c2ce387385996c4e6824116931930b08cfcaecc9 (commit)
- Log -----------------------------------------------------------------
commit 66e40840d15b514f275ce3ce2a4bf72ec68c7311
Author: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
AuthorDate: Wed Sep 3 01:48:55 2025 +0200
Commit: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
CommitDate: Wed Sep 3 14:13:37 2025 +0200
avcodec/pcm_tablegen: Fix CONFIG_HARDCODED_TABLES
Broken in ae448e00afb43d7f72dfa9c82a4c45994e4fea6a.
Notice that config_components.h is safe to include,
as it is valid for both the host and the target
(in contrast to config.h).
Reviewed-by: Zhao Zhili <quinkblack(a)foxmail.com>
Signed-off-by: Andreas Rheinhardt <andreas.rheinhardt(a)outlook.com>
diff --git a/libavcodec/pcm_tablegen.h b/libavcodec/pcm_tablegen.h
index 590ba59814..60ef9656d5 100644
--- a/libavcodec/pcm_tablegen.h
+++ b/libavcodec/pcm_tablegen.h
@@ -24,6 +24,7 @@
#define AVCODEC_PCM_TABLEGEN_H
#include <stdint.h>
+#include "config_components.h"
#include "libavutil/attributes.h"
/* from g711.c by SUN microsystems (unrestricted use) */
-----------------------------------------------------------------------
Summary of changes:
libavcodec/pcm_tablegen.h | 1 +
1 file changed, 1 insertion(+)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. c2ce387385 avcodec/d3d12va_encode: texture array support for HEVC
by ffmpeg-git@ffmpeg.org 03 Sep '25
by ffmpeg-git@ffmpeg.org 03 Sep '25
03 Sep '25
The branch, master has been updated
via c2ce387385996c4e6824116931930b08cfcaecc9 (commit)
from 6ce02bcc3acbfcd48052fd21456722f4d35cda8e (commit)
- Log -----------------------------------------------------------------
commit c2ce387385996c4e6824116931930b08cfcaecc9
Author: Araz Iusubov <Primeadvice(a)gmail.com>
AuthorDate: Mon Aug 11 12:48:47 2025 +0200
Commit: Araz Iusubov <Primeadvice(a)gmail.com>
CommitDate: Wed Sep 3 11:56:06 2025 +0200
avcodec/d3d12va_encode: texture array support for HEVC
This patch adds support for the texture array feature
used by AMD boards in the D3D12 HEVC encoder.
In texture array mode, a single texture array is shared for all
reference and reconstructed pictures using different subresources.
The implementation ensures compatibility
and has been successfully tested on AMD, Intel, and NVIDIA GPUs.
diff --git a/doc/APIchanges b/doc/APIchanges
index a3626d3c20..d69aaf2215 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,14 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavu 60.12.100 - hwcontext_d3d12va.h
+ Add support for texture array mode AVD3D12VAFrame.subresource_index,
+ AVD3D12VAFramesContext.texture_array
+ Add enum AVD3D12VAFrameFlags to define the behaviours of frame allocation.
+ Renanme AVD3D12VAFramesContext.flags to AVD3D12VAFramesContext.resource_flags.
+ Add flags to AVD3D12VAFramesContext
+ Add flags to AVD3D12VAFrame
+
2025-09-xx - xxxxxxxxxx - lavfi 11.8.100 - buffersrc.h
Add AVBufferSrcParameters.alpha_mode.
diff --git a/libavcodec/d3d12va_encode.c b/libavcodec/d3d12va_encode.c
index 008b0ddc2a..f34605ec41 100644
--- a/libavcodec/d3d12va_encode.c
+++ b/libavcodec/d3d12va_encode.c
@@ -191,7 +191,7 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
D3D12VAEncodeContext *ctx = avctx->priv_data;
D3D12VAEncodePicture *pic = base_pic->priv;
- AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
+ AVD3D12VAFramesContext *frames_hwctx = base_ctx->input_frames->hwctx;
int err, i, j;
HRESULT hr;
char data[MAX_PARAM_BUFFER_SIZE];
@@ -201,6 +201,8 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
ID3D12VideoEncodeCommandList2 *cmd_list = ctx->command_list;
D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
D3D12_VIDEO_ENCODE_REFERENCE_FRAMES d3d12_refs = { 0 };
+ int barriers_ref_index = 0;
+ D3D12_RESOURCE_BARRIER *barriers_ref = NULL;
D3D12_VIDEO_ENCODER_ENCODEFRAME_INPUT_ARGUMENTS input_args = {
.SequenceControlDesc = {
@@ -268,6 +270,8 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
av_log(avctx, AV_LOG_DEBUG, "Recon surface is %p.\n",
pic->recon_surface->texture);
+ pic->subresource_index = ctx->is_texture_array ? pic->recon_surface->subresource_index : 0;
+
pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);
if (!pic->output_buffer_ref) {
err = AVERROR(ENOMEM);
@@ -324,11 +328,28 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
goto fail;
}
+ if (ctx->is_texture_array) {
+ d3d12_refs.pSubresources = av_calloc(d3d12_refs.NumTexture2Ds,
+ sizeof(*d3d12_refs.pSubresources));
+ if (!d3d12_refs.pSubresources) {
+ err = AVERROR(ENOMEM);
+ goto fail;
+ }
+ }
+
i = 0;
- for (j = 0; j < base_pic->nb_refs[0]; j++)
- d3d12_refs.ppTexture2Ds[i++] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->recon_surface->texture;
- for (j = 0; j < base_pic->nb_refs[1]; j++)
- d3d12_refs.ppTexture2Ds[i++] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->recon_surface->texture;
+ for (j = 0; j < base_pic->nb_refs[0]; j++) {
+ d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->recon_surface->texture;
+ if (ctx->is_texture_array)
+ d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[0][j]->priv)->subresource_index;
+ i++;
+ }
+ for (j = 0; j < base_pic->nb_refs[1]; j++) {
+ d3d12_refs.ppTexture2Ds[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->recon_surface->texture;
+ if (ctx->is_texture_array)
+ d3d12_refs.pSubresources[i] = ((D3D12VAEncodePicture *)base_pic->refs[1][j]->priv)->subresource_index;
+ i++;
+ }
}
input_args.PictureControlDesc.IntraRefreshFrameIndex = 0;
@@ -342,7 +363,7 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
output_args.Bitstream.pBuffer = pic->output_buffer;
output_args.Bitstream.FrameStartOffset = pic->aligned_header_size;
output_args.ReconstructedPicture.pReconstructedPicture = pic->recon_surface->texture;
- output_args.ReconstructedPicture.ReconstructedPictureSubresource = 0;
+ output_args.ReconstructedPicture.ReconstructedPictureSubresource = ctx->is_texture_array ? pic->subresource_index : 0;
output_args.EncoderOutputMetadata.pBuffer = pic->encoded_metadata;
output_args.EncoderOutputMetadata.Offset = 0;
@@ -368,52 +389,89 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
goto fail;
}
-#define TRANSITION_BARRIER(res, before, after) \
+#define TRANSITION_BARRIER(res, subres, before, after) \
(D3D12_RESOURCE_BARRIER) { \
.Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \
.Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \
.Transition = { \
.pResource = res, \
- .Subresource = D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES, \
+ .Subresource = subres, \
.StateBefore = before, \
.StateAfter = after, \
}, \
}
barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
- barriers[2] = TRANSITION_BARRIER(pic->recon_surface->texture,
- D3D12_RESOURCE_STATE_COMMON,
- D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
- barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata,
+ barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
- barriers[4] = TRANSITION_BARRIER(pic->resolved_metadata,
+ barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_COMMON,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
- ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 5, barriers);
+ ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
- if (d3d12_refs.NumTexture2Ds) {
- D3D12_RESOURCE_BARRIER refs_barriers[3];
-
- for (i = 0; i < d3d12_refs.NumTexture2Ds; i++)
- refs_barriers[i] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i],
- D3D12_RESOURCE_STATE_COMMON,
- D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
-
- ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, d3d12_refs.NumTexture2Ds,
- refs_barriers);
+ if (ctx->is_texture_array)
+ barriers_ref = av_calloc(base_ctx->recon_frames->initial_pool_size * ctx->plane_count,
+ sizeof(D3D12_RESOURCE_BARRIER));
+ else
+ barriers_ref = av_calloc(MAX_DPB_SIZE, sizeof(D3D12_RESOURCE_BARRIER));
+
+ if (ctx->is_texture_array) {
+ D3D12_RESOURCE_DESC references_tex_array_desc = { 0 };
+ pic->recon_surface->texture->lpVtbl->GetDesc(pic->recon_surface->texture, &references_tex_array_desc);
+
+ for (uint32_t reference_subresource = 0; reference_subresource < references_tex_array_desc.DepthOrArraySize;
+ reference_subresource++) {
+
+ uint32_t array_size = references_tex_array_desc.DepthOrArraySize;
+ uint32_t mip_slice = reference_subresource % references_tex_array_desc.MipLevels;
+ uint32_t array_slice = (reference_subresource / references_tex_array_desc.MipLevels) % array_size;
+
+ for (uint32_t plane_slice = 0; plane_slice < ctx->plane_count; plane_slice++) {
+ uint32_t outputSubresource = mip_slice + array_slice * references_tex_array_desc.MipLevels +
+ plane_slice * references_tex_array_desc.MipLevels * array_size;
+ if (reference_subresource == pic->subresource_index) {
+ barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
+ D3D12_RESOURCE_STATE_COMMON,
+ D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
+ } else {
+ barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture, outputSubresource,
+ D3D12_RESOURCE_STATE_COMMON,
+ D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
+ }
+ }
+ }
+ } else {
+ barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(pic->recon_surface->texture,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
+ D3D12_RESOURCE_STATE_COMMON,
+ D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
+
+ if (d3d12_refs.NumTexture2Ds) {
+ for (i = 0; i < d3d12_refs.NumTexture2Ds; i++)
+ barriers_ref[barriers_ref_index++] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i],
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
+ D3D12_RESOURCE_STATE_COMMON,
+ D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
+ }
}
+ ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index, barriers_ref);
ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list, ctx->encoder, ctx->encoder_heap,
&input_args, &output_args);
barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
@@ -421,35 +479,32 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, &input_metadata, &output_metadata);
- if (d3d12_refs.NumTexture2Ds) {
- D3D12_RESOURCE_BARRIER refs_barriers[3];
-
- for (i = 0; i < d3d12_refs.NumTexture2Ds; i++)
- refs_barriers[i] = TRANSITION_BARRIER(d3d12_refs.ppTexture2Ds[i],
- D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
- D3D12_RESOURCE_STATE_COMMON);
+ if (barriers_ref_index > 0) {
+ for (i = 0; i < barriers_ref_index; i++)
+ FFSWAP(D3D12_RESOURCE_STATES, barriers_ref[i].Transition.StateBefore, barriers_ref[i].Transition.StateAfter);
- ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, d3d12_refs.NumTexture2Ds,
- refs_barriers);
+ ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index,
+ barriers_ref);
}
barriers[0] = TRANSITION_BARRIER(pic->input_surface->texture,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
D3D12_RESOURCE_STATE_COMMON);
barriers[1] = TRANSITION_BARRIER(pic->output_buffer,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
D3D12_RESOURCE_STATE_COMMON);
- barriers[2] = TRANSITION_BARRIER(pic->recon_surface->texture,
- D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
- D3D12_RESOURCE_STATE_COMMON);
- barriers[3] = TRANSITION_BARRIER(pic->encoded_metadata,
+ barriers[2] = TRANSITION_BARRIER(pic->encoded_metadata,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
D3D12_RESOURCE_STATE_COMMON);
- barriers[4] = TRANSITION_BARRIER(pic->resolved_metadata,
+ barriers[3] = TRANSITION_BARRIER(pic->resolved_metadata,
+ D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
D3D12_RESOURCE_STATE_COMMON);
- ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 5, barriers);
+ ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
hr = ID3D12VideoEncodeCommandList2_Close(cmd_list);
if (FAILED(hr)) {
@@ -488,6 +543,12 @@ static int d3d12va_encode_issue(AVCodecContext *avctx,
if (d3d12_refs.ppTexture2Ds)
av_freep(&d3d12_refs.ppTexture2Ds);
+ if (ctx->is_texture_array && d3d12_refs.pSubresources)
+ av_freep(&d3d12_refs.pSubresources);
+
+ if (barriers_ref)
+ av_freep(&barriers_ref);
+
return 0;
fail:
@@ -497,6 +558,12 @@ fail:
if (d3d12_refs.ppTexture2Ds)
av_freep(&d3d12_refs.ppTexture2Ds);
+ if (ctx->is_texture_array && d3d12_refs.pSubresources)
+ av_freep(&d3d12_refs.pSubresources);
+
+ if (barriers_ref)
+ av_freep(&barriers_ref);
+
if (ctx->codec->free_picture_params)
ctx->codec->free_picture_params(pic);
@@ -1354,6 +1421,7 @@ fail:
static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx)
{
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
+ D3D12VAEncodeContext *ctx = avctx->priv_data;
AVD3D12VAFramesContext *hwctx;
enum AVPixelFormat recon_format;
int err;
@@ -1374,8 +1442,12 @@ static int d3d12va_encode_create_recon_frames(AVCodecContext *avctx)
base_ctx->recon_frames->width = base_ctx->surface_width;
base_ctx->recon_frames->height = base_ctx->surface_height;
- hwctx->flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
- D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
+ hwctx->resource_flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
+ D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
+ if (ctx->is_texture_array) {
+ base_ctx->recon_frames->initial_pool_size = MAX_DPB_SIZE + 1;
+ hwctx->flags |= AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY;
+ }
err = av_hwframe_ctx_init(base_ctx->recon_frames_ref);
if (err < 0) {
@@ -1409,6 +1481,7 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx)
FFHWBaseEncodeContext *base_ctx = avctx->priv_data;
D3D12VAEncodeContext *ctx = avctx->priv_data;
D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 };
+ D3D12_FEATURE_DATA_FORMAT_INFO format_info = { 0 };
int err;
HRESULT hr;
@@ -1444,6 +1517,15 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx)
goto fail;
}
+ format_info.Format = ((AVD3D12VAFramesContext *)base_ctx->input_frames->hwctx)->format;
+ if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(ctx->hwctx->device, D3D12_FEATURE_FORMAT_INFO,
+ &format_info, sizeof(format_info)))) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to query format plane count: 0x%x\n", hr);
+ err = AVERROR_EXTERNAL;
+ goto fail;
+ }
+ ctx->plane_count = format_info.PlaneCount;
+
err = d3d12va_encode_set_profile(avctx);
if (err < 0)
goto fail;
@@ -1471,10 +1553,6 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx)
if (err < 0)
goto fail;
- err = d3d12va_encode_create_recon_frames(avctx);
- if (err < 0)
- goto fail;
-
err = d3d12va_encode_prepare_output_buffers(avctx);
if (err < 0)
goto fail;
@@ -1500,6 +1578,10 @@ int ff_d3d12va_encode_init(AVCodecContext *avctx)
goto fail;
}
+ err = d3d12va_encode_create_recon_frames(avctx);
+ if (err < 0)
+ goto fail;
+
base_ctx->output_delay = base_ctx->b_per_p;
base_ctx->decode_delay = base_ctx->max_b_depth;
diff --git a/libavcodec/d3d12va_encode.h b/libavcodec/d3d12va_encode.h
index 8af5554626..5bd1eedb7f 100644
--- a/libavcodec/d3d12va_encode.h
+++ b/libavcodec/d3d12va_encode.h
@@ -52,6 +52,8 @@ typedef struct D3D12VAEncodePicture {
ID3D12Resource *encoded_metadata;
ID3D12Resource *resolved_metadata;
+ int subresource_index;
+
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA pic_ctl;
int fence_value;
@@ -194,6 +196,16 @@ typedef struct D3D12VAEncodeContext {
*/
AVBufferPool *output_buffer_pool;
+ /**
+ * Flag indicates if the HW is texture array mode.
+ */
+ int is_texture_array;
+
+ /**
+ * The number of planes in the input DXGI FORMAT.
+ */
+ int plane_count;
+
/**
* D3D12 video encoder.
*/
diff --git a/libavcodec/d3d12va_encode_hevc.c b/libavcodec/d3d12va_encode_hevc.c
index 4f4dda1f8f..01e5b4cb4c 100644
--- a/libavcodec/d3d12va_encode_hevc.c
+++ b/libavcodec/d3d12va_encode_hevc.c
@@ -279,9 +279,8 @@ static int d3d12va_encode_hevc_init_sequence_params(AVCodecContext *avctx)
}
if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
- av_log(avctx, AV_LOG_ERROR, "D3D12 video encode on this device requires texture array support, "
- "but it's not implemented.\n");
- return AVERROR_PATCHWELCOME;
+ ctx->is_texture_array = 1;
+ av_log(avctx, AV_LOG_DEBUG, "D3D12 video encode on this device uses texture array mode.\n");
}
desc = av_pix_fmt_desc_get(base_ctx->input_frames->sw_format);
diff --git a/libavutil/hwcontext_d3d12va.c b/libavutil/hwcontext_d3d12va.c
index 6507cf69c1..9368341d6d 100644
--- a/libavutil/hwcontext_d3d12va.c
+++ b/libavutil/hwcontext_d3d12va.c
@@ -49,6 +49,7 @@ typedef struct D3D12VAFramesContext {
ID3D12GraphicsCommandList *command_list;
AVD3D12VASyncContext sync_ctx;
UINT luma_component_size;
+ int nb_surfaces_used;
} D3D12VAFramesContext;
typedef struct D3D12VADevicePriv {
@@ -174,7 +175,8 @@ fail:
static void d3d12va_frames_uninit(AVHWFramesContext *ctx)
{
- D3D12VAFramesContext *s = ctx->hwctx;
+ D3D12VAFramesContext *s = ctx->hwctx;
+ AVD3D12VAFramesContext *hwctx = ctx->hwctx;
D3D12_OBJECT_RELEASE(s->sync_ctx.fence);
if (s->sync_ctx.event)
@@ -185,6 +187,9 @@ static void d3d12va_frames_uninit(AVHWFramesContext *ctx)
D3D12_OBJECT_RELEASE(s->command_allocator);
D3D12_OBJECT_RELEASE(s->command_list);
D3D12_OBJECT_RELEASE(s->command_queue);
+
+ if (hwctx->texture_array)
+ D3D12_OBJECT_RELEASE(hwctx->texture_array);
}
static int d3d12va_frames_get_constraints(AVHWDeviceContext *ctx, const void *hwconfig, AVHWFramesConstraints *constraints)
@@ -220,7 +225,9 @@ static void free_texture(void *opaque, uint8_t *data)
{
AVD3D12VAFrame *frame = (AVD3D12VAFrame *)data;
- D3D12_OBJECT_RELEASE(frame->texture);
+ if (!(frame->flags & AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY))
+ D3D12_OBJECT_RELEASE(frame->texture);
+
D3D12_OBJECT_RELEASE(frame->sync_ctx.fence);
if (frame->sync_ctx.event)
CloseHandle(frame->sync_ctx.event);
@@ -228,6 +235,42 @@ static void free_texture(void *opaque, uint8_t *data)
av_freep(&data);
}
+static AVBufferRef *d3d12va_pool_alloc_texture_array(AVHWFramesContext *ctx)
+{
+ AVD3D12VAFrame *frame = av_mallocz(sizeof(*frame));
+ D3D12VAFramesContext *s = ctx->hwctx;
+ AVD3D12VAFramesContext *hwctx = ctx->hwctx;
+ AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+ AVBufferRef *buf;
+
+ frame->flags |= AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY;
+
+ DX_CHECK(ID3D12Device_CreateFence(device_hwctx->device, 0, D3D12_FENCE_FLAG_NONE,
+ &IID_ID3D12Fence, (void **)&frame->sync_ctx.fence));
+ frame->sync_ctx.event = CreateEvent(NULL, FALSE, FALSE, NULL);
+ if (!frame->sync_ctx.event)
+ goto fail;
+
+ if (s->nb_surfaces_used >= ctx->initial_pool_size) {
+ av_log(ctx, AV_LOG_ERROR, "Static surface pool size exceeded.\n");
+ goto fail;
+ }
+
+ frame->texture = hwctx->texture_array;
+ frame->subresource_index = s->nb_surfaces_used;
+
+ buf = av_buffer_create((uint8_t *)frame, sizeof(*frame), free_texture, NULL, 0);
+
+ if (!buf)
+ goto fail;
+
+ s->nb_surfaces_used++;
+ return buf;
+fail:
+ free_texture(NULL, (uint8_t *)frame);
+ return NULL;
+}
+
static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size)
{
AVHWFramesContext *ctx = (AVHWFramesContext *)opaque;
@@ -236,6 +279,10 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size)
AVBufferRef *buf;
AVD3D12VAFrame *frame;
+
+ if (ctx->initial_pool_size > 0 && hwctx->flags & AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY)
+ return d3d12va_pool_alloc_texture_array(ctx);
+
D3D12_HEAP_PROPERTIES props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
D3D12_RESOURCE_DESC desc = {
.Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
@@ -247,7 +294,7 @@ static AVBufferRef *d3d12va_pool_alloc(void *opaque, size_t size)
.Format = hwctx->format,
.SampleDesc = {.Count = 1, .Quality = 0 },
.Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
- .Flags = hwctx->flags,
+ .Flags = hwctx->resource_flags,
};
frame = av_mallocz(sizeof(AVD3D12VAFrame));
@@ -278,6 +325,34 @@ fail:
return NULL;
}
+static int d3d12va_texture_array_init(AVHWFramesContext *ctx)
+{
+ AVD3D12VAFramesContext *hwctx = ctx->hwctx;
+ AVD3D12VADeviceContext *device_hwctx = ctx->device_ctx->hwctx;
+
+ D3D12_HEAP_PROPERTIES props = { .Type = D3D12_HEAP_TYPE_DEFAULT };
+
+ D3D12_RESOURCE_DESC desc = {
+ .Dimension = D3D12_RESOURCE_DIMENSION_TEXTURE2D,
+ .Alignment = 0,
+ .Width = ctx->width,
+ .Height = ctx->height,
+ .DepthOrArraySize = ctx->initial_pool_size,
+ .MipLevels = 1,
+ .Format = hwctx->format,
+ .SampleDesc = {.Count = 1, .Quality = 0 },
+ .Layout = D3D12_TEXTURE_LAYOUT_UNKNOWN,
+ .Flags = hwctx->resource_flags,
+ };
+
+ if (FAILED(ID3D12Device_CreateCommittedResource(device_hwctx->device, &props, D3D12_HEAP_FLAG_NONE, &desc,
+ D3D12_RESOURCE_STATE_COMMON, NULL, &IID_ID3D12Resource, (void **)&hwctx->texture_array))) {
+ av_log(ctx, AV_LOG_ERROR, "Could not create the texture array\n");
+ return AVERROR(EINVAL);
+ }
+ return 0;
+}
+
static int d3d12va_frames_init(AVHWFramesContext *ctx)
{
AVD3D12VAFramesContext *hwctx = ctx->hwctx;
@@ -298,6 +373,12 @@ static int d3d12va_frames_init(AVHWFramesContext *ctx)
return AVERROR(EINVAL);
}
+ if (ctx->initial_pool_size > 0 && hwctx->flags & AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY) {
+ int err = d3d12va_texture_array_init(ctx);
+ if (err < 0)
+ return err;
+ }
+
ffhwframesctx(ctx)->pool_internal = av_buffer_pool_init2(sizeof(AVD3D12VAFrame),
ctx, d3d12va_pool_alloc, NULL);
diff --git a/libavutil/hwcontext_d3d12va.h b/libavutil/hwcontext_d3d12va.h
index 212a6a6146..1530de8b3c 100644
--- a/libavutil/hwcontext_d3d12va.h
+++ b/libavutil/hwcontext_d3d12va.h
@@ -99,6 +99,18 @@ typedef struct AVD3D12VASyncContext {
uint64_t fence_value;
} AVD3D12VASyncContext;
+/**
+ * Define the behaviours of frame allocation.
+ */
+typedef enum AVD3D12VAFrameFlags {
+ AV_D3D12VA_FRAME_FLAG_NONE = 0,
+
+ /**
+ * Indicates that frame data should be allocated using a texture array resource.
+ */
+ AV_D3D12VA_FRAME_FLAG_TEXTURE_ARRAY = (1 << 1),
+} AVD3D12VAFrameFlags;
+
/**
* @brief D3D12VA frame descriptor for pool allocation.
*
@@ -111,12 +123,26 @@ typedef struct AVD3D12VAFrame {
*/
ID3D12Resource *texture;
+ /**
+ * Index of the subresource within the texture.
+ *
+ * In texture array mode, this specifies the array slice index.
+ * When texture array mode is not used, this value is always 0.
+ */
+ int subresource_index;
+
/**
* The sync context for the texture
*
* @see: https://learn.microsoft.com/en-us/windows/win32/medfound/direct3d-12-video-…
*/
AVD3D12VASyncContext sync_ctx;
+
+ /**
+ * A combination of AVD3D12VAFrameFlags.
+ * Set by AVD3D12VAFramesContext.
+ */
+ AVD3D12VAFrameFlags flags;
} AVD3D12VAFrame;
/**
@@ -136,7 +162,20 @@ typedef struct AVD3D12VAFramesContext {
*
* @see https://learn.microsoft.com/en-us/windows/win32/api/d3d12/ne-d3d12-d3d12_re…
*/
- D3D12_RESOURCE_FLAGS flags;
+ D3D12_RESOURCE_FLAGS resource_flags;
+
+ /**
+ * In texture array mode, the D3D12 uses the same texture array (resource)for all
+ * pictures.
+ */
+ ID3D12Resource *texture_array;
+
+ /**
+ * A combination of AVD3D12VAFrameFlags. Unless AV_D3D12VA_FRAME_FLAG_NONE is set,
+ * autodetected flags will be OR'd based on the device and frame features during
+ * av_hwframe_ctx_init().
+ */
+ AVD3D12VAFrameFlags flags;
} AVD3D12VAFramesContext;
#endif /* AVUTIL_HWCONTEXT_D3D12VA_H */
-----------------------------------------------------------------------
Summary of changes:
doc/APIchanges | 8 ++
libavcodec/d3d12va_encode.c | 172 +++++++++++++++++++++++++++++----------
libavcodec/d3d12va_encode.h | 12 +++
libavcodec/d3d12va_encode_hevc.c | 5 +-
libavutil/hwcontext_d3d12va.c | 87 +++++++++++++++++++-
libavutil/hwcontext_d3d12va.h | 41 +++++++++-
6 files changed, 273 insertions(+), 52 deletions(-)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. 6ce02bcc3a avcodec/aarch64/vvc: Optimize apply_bdof
by ffmpeg-git@ffmpeg.org 03 Sep '25
by ffmpeg-git@ffmpeg.org 03 Sep '25
03 Sep '25
The branch, master has been updated
via 6ce02bcc3acbfcd48052fd21456722f4d35cda8e (commit)
via 2e924176036b415d5c9534a605f7f6a87cae423d (commit)
from 3800421e7cb4372b756542ff4918102505ffb5f4 (commit)
- Log -----------------------------------------------------------------
commit 6ce02bcc3acbfcd48052fd21456722f4d35cda8e
Author: Zhao Zhili <quinkblack(a)foxmail.com>
AuthorDate: Thu Aug 14 12:42:38 2025 +0800
Commit: Zhao Zhili <quink(a)noreply.code.ffmpeg.org>
CommitDate: Wed Sep 3 06:55:37 2025 +0000
avcodec/aarch64/vvc: Optimize apply_bdof
Before this patch, prof_grad_filter calculate
gh[0], gh[1], gv[0], gv[1] and save them to stack.
derive_bdof_vx_vy load them from stack and calculate
gh[0] + gh[1], gv[0] + gv[1].
apply_bdof_min_block load them from stack and calculate
gh[0] - gh[1], gv[0] - gv[1]
This patch add bdof_grad_filter, which calculate gh[0] + gh[1],
gh[0] - gh[1], gv[0] + gv[1], gv[0] - gv[1], and save them to
stack, so derive_bdof_vx_vy and apply_bdof_min_block can use the
results directly.
prof_grad_filter is kept for reuse by other functions in the future.
Benchmark on rpi5 with gcc 12
Before After
--------------------------------------------------------------------
apply_bdof_8_8x16_c: | 7431.4 ( 1.00x) | 7371.7 ( 1.00x)
apply_bdof_8_8x16_neon: | 1175.4 ( 6.32x) | 1036.3 ( 7.11x)
apply_bdof_8_16x8_c: | 7182.2 ( 1.00x) | 7201.1 ( 1.00x)
apply_bdof_8_16x8_neon: | 1021.7 ( 7.03x) | 879.9 ( 8.18x)
apply_bdof_8_16x16_c: | 14577.1 ( 1.00x) | 14589.3 ( 1.00x)
apply_bdof_8_16x16_neon: | 2012.8 ( 7.24x) | 1743.3 ( 8.37x)
apply_bdof_10_8x16_c: | 7292.4 ( 1.00x) | 7308.5 ( 1.00x)
apply_bdof_10_8x16_neon: | 1156.3 ( 6.31x) | 1045.3 ( 6.99x)
apply_bdof_10_16x8_c: | 7112.4 ( 1.00x) | 7214.4 ( 1.00x)
apply_bdof_10_16x8_neon: | 1007.6 ( 7.06x) | 904.8 ( 7.97x)
apply_bdof_10_16x16_c: | 14363.3 ( 1.00x) | 14476.4 ( 1.00x)
apply_bdof_10_16x16_neon: | 1986.9 ( 7.23x) | 1783.1 ( 8.12x)
apply_bdof_12_8x16_c: | 7433.3 ( 1.00x) | 7374.7 ( 1.00x)
apply_bdof_12_8x16_neon: | 1155.9 ( 6.43x) | 1040.8 ( 7.09x)
apply_bdof_12_16x8_c: | 7171.1 ( 1.00x) | 7376.3 ( 1.00x)
apply_bdof_12_16x8_neon: | 1010.8 ( 7.09x) | 899.4 ( 8.20x)
apply_bdof_12_16x16_c: | 14515.5 ( 1.00x) | 14731.5 ( 1.00x)
apply_bdof_12_16x16_neon: | 1988.4 ( 7.30x) | 1785.2 ( 8.25x)
diff --git a/libavcodec/aarch64/vvc/dsp_init.c b/libavcodec/aarch64/vvc/dsp_init.c
index 3626d28ed6..df0b536539 100644
--- a/libavcodec/aarch64/vvc/dsp_init.c
+++ b/libavcodec/aarch64/vvc/dsp_init.c
@@ -30,38 +30,16 @@
#define BDOF_BLOCK_SIZE 16
#define BDOF_MIN_BLOCK_SIZE 4
-void ff_vvc_prof_grad_filter_8x_neon(int16_t *gradient_h,
- int16_t *gradient_v,
- ptrdiff_t gradient_stride,
- const int16_t *_src,
- ptrdiff_t src_stride,
- int width, int height);
-
-void ff_vvc_derive_bdof_vx_vy_8x_neon(const int16_t *_src0,
- const int16_t *_src1,
- int16_t *const gradient_h[2],
- int16_t *const gradient_v[2],
- int16_t vx[16], int16_t vy[16],
- int block_h);
-void ff_vvc_derive_bdof_vx_vy_16x_neon(const int16_t *_src0,
- const int16_t *_src1,
- int16_t *const gradient_h[2],
- int16_t *const gradient_v[2],
- int16_t vx[16], int16_t vy[16],
- int block_h);
#define BIT_DEPTH 8
#include "alf_template.c"
-#include "of_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 10
#include "alf_template.c"
-#include "of_template.c"
#undef BIT_DEPTH
#define BIT_DEPTH 12
#include "alf_template.c"
-#include "of_template.c"
#undef BIT_DEPTH
int ff_vvc_sad_neon(const int16_t *src0, const int16_t *src1, int dx, int dy,
@@ -121,6 +99,15 @@ DMVR_FUN(hv_, 8)
DMVR_FUN(hv_, 10)
DMVR_FUN(hv_, 12)
+#define APPLY_BDOF_FUNC(bd) \
+ void ff_vvc_apply_bdof_ ## bd ## _neon(uint8_t *_dst, ptrdiff_t _dst_stride, \
+ const int16_t *_src0, const int16_t *_src1, \
+ int block_w, int block_h);
+
+APPLY_BDOF_FUNC(8)
+APPLY_BDOF_FUNC(10)
+APPLY_BDOF_FUNC(12)
+
void ff_vvc_dsp_init_aarch64(VVCDSPContext *const c, const int bd)
{
int cpu_flags = av_get_cpu_flags();
@@ -202,7 +189,7 @@ void ff_vvc_dsp_init_aarch64(VVCDSPContext *const c, const int bd)
c->inter.w_avg = vvc_w_avg_8;
c->inter.dmvr[0][0] = ff_vvc_dmvr_8_neon;
c->inter.dmvr[1][1] = ff_vvc_dmvr_hv_8_neon;
- c->inter.apply_bdof = apply_bdof_8;
+ c->inter.apply_bdof = ff_vvc_apply_bdof_8_neon;
c->sao.band_filter[0] = ff_h26x_sao_band_filter_8x8_8_neon;
for (int i = 1; i < FF_ARRAY_ELEMS(c->sao.band_filter); i++)
@@ -246,7 +233,7 @@ void ff_vvc_dsp_init_aarch64(VVCDSPContext *const c, const int bd)
c->inter.avg = ff_vvc_avg_10_neon;
c->inter.w_avg = vvc_w_avg_10;
c->inter.dmvr[1][1] = ff_vvc_dmvr_hv_10_neon;
- c->inter.apply_bdof = apply_bdof_10;
+ c->inter.apply_bdof = ff_vvc_apply_bdof_10_neon;
c->alf.filter[LUMA] = alf_filter_luma_10_neon;
c->alf.filter[CHROMA] = alf_filter_chroma_10_neon;
@@ -255,7 +242,7 @@ void ff_vvc_dsp_init_aarch64(VVCDSPContext *const c, const int bd)
c->inter.w_avg = vvc_w_avg_12;
c->inter.dmvr[0][0] = ff_vvc_dmvr_12_neon;
c->inter.dmvr[1][1] = ff_vvc_dmvr_hv_12_neon;
- c->inter.apply_bdof = apply_bdof_12;
+ c->inter.apply_bdof = ff_vvc_apply_bdof_12_neon;
c->alf.filter[LUMA] = alf_filter_luma_12_neon;
c->alf.filter[CHROMA] = alf_filter_chroma_12_neon;
diff --git a/libavcodec/aarch64/vvc/inter.S b/libavcodec/aarch64/vvc/inter.S
index 1c79c6022a..50fc073dc9 100644
--- a/libavcodec/aarch64/vvc/inter.S
+++ b/libavcodec/aarch64/vvc/inter.S
@@ -716,7 +716,93 @@ function ff_vvc_prof_grad_filter_8x_neon, export=1
.unreq height
endfunc
-.macro vvc_apply_bdof_block bit_depth
+function vvc_bdof_grad_filter_8x_neon, export=0
+ gh0 .req x0
+ gh1 .req x1
+ gv0 .req x2
+ gv1 .req x3
+ src0 .req x4
+ src1 .req x5
+ width .req w6
+ height .req w7
+
+1:
+ mov x10, src0
+ mov w11, width
+ mov x12, gh0
+ mov x13, gv0
+ mov x14, src1
+ mov x15, gh1
+ mov x16, gv1
+2:
+ ldur q0, [x10, #2]
+ ldur q1, [x10, #-2]
+ ldr q2, [x10, #(VVC_MAX_PB_SIZE << 1)]
+ ldr q3, [x10, #-(VVC_MAX_PB_SIZE << 1)]
+ sshr v0.8h, v0.8h, #6
+ sshr v1.8h, v1.8h, #6
+ ldur q4, [x14, #2]
+ ldur q5, [x14, #-2]
+ sshr v2.8h, v2.8h, #6
+ sshr v3.8h, v3.8h, #6
+ ldr q6, [x14, #(VVC_MAX_PB_SIZE << 1)]
+ ldr q7, [x14, #-(VVC_MAX_PB_SIZE << 1)]
+ // results of gradient_h0
+ sub v0.8h, v0.8h, v1.8h
+ // results of gradient_v0
+ sub v2.8h, v2.8h, v3.8h
+
+ sshr v4.8h, v4.8h, #6
+ sshr v5.8h, v5.8h, #6
+ sshr v6.8h, v6.8h, #6
+ sshr v7.8h, v7.8h, #6
+ // results of gradient_h1
+ sub v4.8h, v4.8h, v5.8h
+ // results of gradient_v1
+ sub v6.8h, v6.8h, v7.8h
+
+ add x10, x10, #16
+ add x14, x14, #16
+
+ // (gradient_h0 + gradient_h1) >> 1
+ shadd v1.8h, v0.8h, v4.8h
+ // gradient_h0 - gradient_h1
+ sub v5.8h, v0.8h, v4.8h
+
+ subs w11, w11, #8
+
+ // (gradient_v0 + gradient_v1) >> 1
+ shadd v3.8h, v2.8h, v6.8h
+ // gradient_v0 - gradient_v1
+ sub v7.8h, v2.8h, v6.8h
+
+ st1 {v1.8h}, [x12], #16
+ st1 {v5.8h}, [x15], #16
+ st1 {v3.8h}, [x13], #16
+ st1 {v7.8h}, [x16], #16
+ b.ne 2b
+
+ subs height, height, #1
+ add gh0, gh0, #(BDOF_BLOCK_SIZE << 1)
+ add gv0, gv0, #(BDOF_BLOCK_SIZE << 1)
+ add src0, src0, #(VVC_MAX_PB_SIZE << 1)
+ add gh1, gh1, #(BDOF_BLOCK_SIZE << 1)
+ add gv1, gv1, #(BDOF_BLOCK_SIZE << 1)
+ add src1, src1, #(VVC_MAX_PB_SIZE << 1)
+ b.ne 1b
+ ret
+
+.unreq gh0
+.unreq gh1
+.unreq gv0
+.unreq gv1
+.unreq src0
+.unreq src1
+.unreq width
+.unreq height
+endfunc
+
+.macro vvc_apply_bdof_block_8x bit_depth
dst .req x0
dst_stride .req x1
src0 .req x2
@@ -726,33 +812,28 @@ endfunc
vx .req x6
vy .req x7
- ld1r {v0.8h}, [vx], #2
- ld1r {v1.8h}, [vy], #2
- ld1r {v2.8h}, [vx]
- ld1r {v3.8h}, [vy]
- ins v0.d[1], v2.d[1]
- ins v1.d[1], v3.d[1]
-
+ ldr w8, [sp]
movi v7.4s, #(1 << (14 - \bit_depth))
- ldp x8, x9, [gh]
- ldp x10, x11, [gv]
mov x12, #(BDOF_BLOCK_SIZE * 2)
- mov w13, #(BDOF_MIN_BLOCK_SIZE)
mov x14, #(VVC_MAX_PB_SIZE * 2)
.if \bit_depth >= 10
// clip pixel
mov w15, #((1 << \bit_depth) - 1)
movi v18.8h, #0
- lsl dst_stride, dst_stride, #1
dup v19.8h, w15
.endif
+
+0:
+ ld1r {v0.8h}, [vx], #2
+ ld1r {v1.8h}, [vy], #2
+ ld1r {v2.8h}, [vx]
+ ld1r {v3.8h}, [vy]
+ mov w13, #(BDOF_MIN_BLOCK_SIZE)
+ ins v0.d[1], v2.d[1]
+ ins v1.d[1], v3.d[1]
1:
- ld1 {v2.8h}, [x8], x12
- ld1 {v3.8h}, [x9], x12
- ld1 {v4.8h}, [x10], x12
- ld1 {v5.8h}, [x11], x12
- sub v2.8h, v2.8h, v3.8h
- sub v4.8h, v4.8h, v5.8h
+ ld1 {v2.8h}, [gh], x12
+ ld1 {v4.8h}, [gv], x12
smull v3.4s, v0.4h, v2.4h
smull2 v16.4s, v0.8h, v2.8h
smlal v3.4s, v1.4h, v4.4h
@@ -780,6 +861,123 @@ endfunc
st1 {v5.8h}, [dst], dst_stride
.endif
b.ne 1b
+
+ subs w8, w8, #(BDOF_MIN_BLOCK_SIZE)
+ add vx, vx, #(2 * BDOF_MIN_BLOCK_SIZE - 2)
+ add vy, vy, #(2 * BDOF_MIN_BLOCK_SIZE - 2)
+ b.ne 0b
+ ret
+
+.unreq dst
+.unreq dst_stride
+.unreq src0
+.unreq src1
+.unreq gh
+.unreq gv
+.unreq vx
+.unreq vy
+.endm
+
+function vvc_apply_bdof_block_8x_8_neon, export=0
+ vvc_apply_bdof_block_8x 8
+endfunc
+
+function vvc_apply_bdof_block_8x_10_neon, export=0
+ vvc_apply_bdof_block_8x 10
+endfunc
+
+function vvc_apply_bdof_block_8x_12_neon, export=0
+ vvc_apply_bdof_block_8x 12
+endfunc
+
+.macro vvc_apply_bdof_block_16x bit_depth
+ dst .req x0
+ dst_stride .req x1
+ src0 .req x2
+ src1 .req x3
+ gh .req x4
+ gv .req x5
+ vx .req x6
+ vy .req x7
+
+ ldr w8, [sp]
+ movi v7.4s, #(1 << (14 - \bit_depth))
+.if \bit_depth >= 10
+ // clip pixel
+ mov w15, #((1 << \bit_depth) - 1)
+ movi v18.8h, #0
+ dup v19.8h, w15
+.endif
+
+0:
+ ld1r {v0.8h}, [vx], #2
+ ld1r {v1.8h}, [vy], #2
+ ld1r {v2.8h}, [vx], #2
+ ld1r {v3.8h}, [vy], #2
+
+ mov w13, #(BDOF_MIN_BLOCK_SIZE)
+
+ ld1r {v20.8h}, [vx], #2
+ ld1r {v21.8h}, [vy], #2
+ ld1r {v22.8h}, [vx], #2
+ ld1r {v23.8h}, [vy], #2
+
+ ins v0.d[1], v2.d[1]
+ ins v1.d[1], v3.d[1]
+ ins v20.d[1], v22.d[1]
+ ins v21.d[1], v23.d[1]
+1:
+ ldp q2, q22, [gh], #(BDOF_BLOCK_SIZE * 2)
+ ldp q4, q24, [gv], #(BDOF_BLOCK_SIZE * 2)
+ smull v3.4s, v0.4h, v2.4h
+ smull2 v16.4s, v0.8h, v2.8h
+ smlal v3.4s, v1.4h, v4.4h
+ smlal2 v16.4s, v1.8h, v4.8h
+
+ ldp q5, q25, [src0], #(VVC_MAX_PB_SIZE * 2)
+ ldp q6, q26, [src1], #(VVC_MAX_PB_SIZE * 2)
+
+ smull v23.4s, v20.4h, v22.4h
+ smull2 v27.4s, v20.8h, v22.8h
+ smlal v23.4s, v21.4h, v24.4h
+ smlal2 v27.4s, v21.8h, v24.8h
+
+ saddl v2.4s, v5.4h, v6.4h
+ add v2.4s, v2.4s, v7.4s
+ add v2.4s, v2.4s, v3.4s
+ saddl2 v4.4s, v5.8h, v6.8h
+ add v4.4s, v4.4s, v7.4s
+ add v4.4s, v4.4s, v16.4s
+
+ saddl v22.4s, v25.4h, v26.4h
+ add v22.4s, v22.4s, v7.4s
+ add v22.4s, v22.4s, v23.4s
+ saddl2 v24.4s, v25.8h, v26.8h
+ add v24.4s, v24.4s, v7.4s
+ add v24.4s, v24.4s, v27.4s
+
+ sqshrn v5.4h, v2.4s, #(15 - \bit_depth)
+ sqshrn2 v5.8h, v4.4s, #(15 - \bit_depth)
+ sqshrn v25.4h, v22.4s, #(15 - \bit_depth)
+ sqshrn2 v25.8h, v24.4s, #(15 - \bit_depth)
+
+ subs w13, w13, #1
+.if \bit_depth == 8
+ sqxtun v5.8b, v5.8h
+ sqxtun2 v5.16b, v25.8h
+ str q5, [dst]
+.else
+ smin v5.8h, v5.8h, v19.8h
+ smax v5.8h, v5.8h, v18.8h
+ smin v25.8h, v25.8h, v19.8h
+ smax v25.8h, v25.8h, v18.8h
+ stp q5, q25, [dst]
+.endif
+ add dst, dst, dst_stride
+ b.ne 1b
+
+ subs w8, w8, #(BDOF_MIN_BLOCK_SIZE)
+ b.ne 0b
ret
.unreq dst
@@ -792,16 +990,16 @@ endfunc
.unreq vy
.endm
-function ff_vvc_apply_bdof_block_8_neon, export=1
- vvc_apply_bdof_block 8
+function vvc_apply_bdof_block_16x_8_neon, export=0
+ vvc_apply_bdof_block_16x 8
endfunc
-function ff_vvc_apply_bdof_block_10_neon, export=1
- vvc_apply_bdof_block 10
+function vvc_apply_bdof_block_16x_10_neon, export=0
+ vvc_apply_bdof_block_16x 10
endfunc
-function ff_vvc_apply_bdof_block_12_neon, export=1
- vvc_apply_bdof_block 12
+function vvc_apply_bdof_block_16x_12_neon, export=0
+ vvc_apply_bdof_block_16x 12
endfunc
const bdof_vx_vy_8x_tbl
@@ -919,18 +1117,16 @@ endconst
* ----------------------------------------------------------------------
* x0: const int16_t *_src0,
* x1: const int16_t *_src1,
- * x2: int16_t *const gradient_h[2],
- * x3: int16_t *const gradient_v[2],
+ * x2: const int16_t *gradient_h,
+ * x3: const int16_t *gradient_v,
* x4: int16_t vx[16],
* x5: int16_t vy[16],
* w6: int block_h
*/
-function ff_vvc_derive_bdof_vx_vy_8x_neon, export=1
+function vvc_derive_bdof_vx_vy_8x_neon, export=0
stp d11, d10, [sp, #-0x20]!
stp d9, d8, [sp, #0x10]
- ldp x14, x13, [x2] // gh0, gh1
- ldp x10, x9, [x3] // gv0, gv1
movrel x11, bdof_vx_vy_8x_tbl
ldr q0, [x11] // table
mvni v2.4s, #30 // -31, for log2
@@ -998,17 +1194,13 @@ function ff_vvc_derive_bdof_vx_vy_8x_neon, export=1
9:
ldr q28, [x0] // src0
ldr q29, [x1] // src1
- ldr q30, [x14], #(BDOF_BLOCK_SIZE * 2) // gh0
- ldr q31, [x13], #(BDOF_BLOCK_SIZE * 2) // gh1
- ldr q8, [x10], #(BDOF_BLOCK_SIZE * 2) // gv0
- ldr q9, [x9], #(BDOF_BLOCK_SIZE * 2) // gv1
+ ldr q30, [x2], #(BDOF_BLOCK_SIZE * 2) // (gh0 + gh1) >> 1
+ ldr q31, [x3], #(BDOF_BLOCK_SIZE * 2) // (gv0 + gv1) >> 1
add x0, x0, #(VVC_MAX_PB_SIZE * 2)
add x1, x1, #(VVC_MAX_PB_SIZE * 2)
sshr v28.8h, v28.8h, #0x4
sshr v29.8h, v29.8h, #0x4
- shadd v30.8h, v30.8h, v31.8h // tmph
- shadd v31.8h, v8.8h, v9.8h // tmpv
sub v8.8h, v28.8h, v29.8h // diff
abs v28.8h, v30.8h
@@ -1067,20 +1259,18 @@ endfunc
/*
* x0: const int16_t *_src0,
* x1: const int16_t *_src1,
- * x2: int16_t *const gradient_h[2],
- * x3: int16_t *const gradient_v[2],
+ * x2: const int16_t *gradient_h,
+ * x3: const int16_t *gradient_v,
* x4: int16_t vx[16],
* x5: int16_t vy[16],
* w6: int block_h
*/
-function ff_vvc_derive_bdof_vx_vy_16x_neon, export=1
+function vvc_derive_bdof_vx_vy_16x_neon, export=0
stp d15, d14, [sp, #-0x40]!
stp d13, d12, [sp, #0x10]
stp d11, d10, [sp, #0x20]
stp d9, d8, [sp, #0x30]
- ldp x8, x9, [x2] // gh0, gh1
- ldp x10, x11, [x3] // gv0, gv1
movrel x12, bdof_vx_vy_16x_tbl
ldp q0, q1, [x12] // table
mov w13, w6 // y = block_h
@@ -1142,17 +1332,11 @@ function ff_vvc_derive_bdof_vx_vy_16x_neon, export=1
sshr v31.8h, v29.8h, #0x4
ld1 {v8.8h, v9.8h}, [x1] // src1
sshr v10.8h, v8.8h, #0x4
- ld1 {v11.8h, v12.8h}, [x8], #32 // gh0
+ ldp q13, q8, [x2], #32 // (gh0 + gh1) >> 1
sshr v29.8h, v30.8h, #0x4
sshr v30.8h, v9.8h, #0x4
- ld1 {v8.8h, v9.8h}, [x9], #32 // gh1
- shadd v13.8h, v11.8h, v8.8h // (gh0 + gh1) >> 1, left half
- ld1 {v14.8h, v15.8h}, [x10], #32 // gv0
- ld1 {v3.8h, v4.8h}, [x11], #32 // gv1
- shadd v5.8h, v14.8h, v3.8h // (gv0 + gv1) >> 1, left half
+ ldp q5, q3, [x3], #32 // (gv0 + gv1) >> 1
sub v31.8h, v31.8h, v10.8h // diff, left half
- shadd v8.8h, v12.8h, v9.8h // (gh0 + gh1) >> 1, right half
- shadd v3.8h, v15.8h, v4.8h // (gv0 + gv1) >> 1, right half
sub v4.8h, v29.8h, v30.8h // diff, right half
abs v29.8h, v13.8h
@@ -1219,3 +1403,129 @@ function ff_vvc_derive_bdof_vx_vy_16x_neon, export=1
ldp d15, d14, [sp], #0x40
ret
endfunc
+
+function ff_vvc_apply_bdof_10_neon, export=1
+ mov w6, #10
+ b 0f
+endfunc
+
+function ff_vvc_apply_bdof_12_neon, export=1
+ mov w6, #12
+ b 0f
+endfunc
+
+// int16_t gradient_buf_h[2][BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2]
+// int16_t gradient_buf_v[2][BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2]
+// int16_t vx[BDOF_BLOCK_SIZE], vy[BDOF_BLOCK_SIZE];
+#define APPLY_BDOF_STACK_SIZE ((BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2) * 8 + BDOF_BLOCK_SIZE * 4)
+#define GRADIENT_H0_OFFSET 2
+#define GRADIENT_H1_OFFSET ((BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2) * 2 + 2)
+#define GRADIENT_V0_OFFSET ((BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2) * 4 + 2)
+#define GRADIENT_V1_OFFSET ((BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2) * 6 + 2)
+#define VX_OFFSET ((BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2) * 8)
+#define VY_OFFSET ((BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2) * 8 + BDOF_BLOCK_SIZE * 2)
+function ff_vvc_apply_bdof_8_neon, export=1
+ mov w6, #8
+0:
+ stp x19, x20, [sp, #-0x40]!
+ stp x21, x22, [sp, #0x10]
+ stp x23, x24, [sp, #0x20]
+ stp x25, x30, [sp, #0x30]
+
+ sub sp, sp, #APPLY_BDOF_STACK_SIZE
+ mov w19, w6 // bit_depth
+ mov x20, x0 // dst
+ mov x21, x1 // dst_stride
+ mov x22, x2 // src0
+ mov x23, x3 // src1
+ mov w24, w4 // block_w
+ mov w25, w5 // block_h
+
+ // int16_t *gradient_h[2] = {&gradient_buf_h[0][1], &gradient_buf_h[1][1]};
+ add x0, sp, #GRADIENT_H0_OFFSET
+ add x1, sp, #GRADIENT_H1_OFFSET
+ add x2, sp, #GRADIENT_V0_OFFSET
+ add x3, sp, #GRADIENT_V1_OFFSET
+ mov x4, x22
+ mov x5, x23
+ mov w6, w24
+ mov w7, w25
+ bl vvc_bdof_grad_filter_8x_neon
+
+ cmp w24, #8
+ mov x0, x22 // src0
+ mov x1, x23 // src1
+ add x2, sp, #GRADIENT_H0_OFFSET // gh0
+ add x3, sp, #GRADIENT_V0_OFFSET // gv0
+ add x4, sp, #VX_OFFSET // vx
+ add x5, sp, #VY_OFFSET // vy
+ mov w6, w25 // block_h
+
+ b.gt 16f
+
+ bl vvc_derive_bdof_vx_vy_8x_neon
+ cmp w19, #10 // check bitdepth
+ mov x0, x20 // dst
+ mov x1, x21 // dst_stride
+ mov x2, x22 // src0
+ mov x3, x23 // src1
+ add x4, sp, #GRADIENT_H1_OFFSET // gh1
+ add x5, sp, #GRADIENT_V1_OFFSET // gv1
+ add x6, sp, #VX_OFFSET
+ add x7, sp, #VY_OFFSET
+ str w25, [sp]
+ b.eq 1f
+ b.gt 2f
+ // 8bit
+0:
+ bl vvc_apply_bdof_block_8x_8_neon
+ b 32f
+1:
+ // 10bit
+ bl vvc_apply_bdof_block_8x_10_neon
+ b 32f
+2:
+ // 12bit
+ bl vvc_apply_bdof_block_8x_12_neon
+ b 32f
+16:
+ bl vvc_derive_bdof_vx_vy_16x_neon
+
+ cmp w19, #10 // check bitdepth
+ mov x0, x20 // dst
+ mov x1, x21 // dst_stride
+ mov x2, x22 // src0
+ mov x3, x23 // src1
+ add x4, sp, #GRADIENT_H1_OFFSET // gh1
+ add x5, sp, #GRADIENT_V1_OFFSET // gv1
+ add x6, sp, #VX_OFFSET
+ add x7, sp, #VY_OFFSET
+ str w25, [sp]
+ b.eq 17f
+ b.gt 18f
+ // 8bit
+ bl vvc_apply_bdof_block_16x_8_neon
+ b 32f
+17:
+ // 10bit
+ bl vvc_apply_bdof_block_16x_10_neon
+ b 32f
+18:
+ // 12bit
+ bl vvc_apply_bdof_block_16x_12_neon
+32:
+ add sp, sp, #APPLY_BDOF_STACK_SIZE
+ ldp x25, x30, [sp, #0x30]
+ ldp x23, x24, [sp, #0x20]
+ ldp x21, x22, [sp, #0x10]
+ ldp x19, x20, [sp], #0x40
+ ret
+endfunc
+
+#undef APPLY_BDOF_STACK_SIZE
+#undef GRADIENT_H0_OFFSET
+#undef GRADIENT_H1_OFFSET
+#undef GRADIENT_V0_OFFSET
+#undef GRADIENT_V1_OFFSET
+#undef VX_OFFSET
+#undef VY_OFFSET
diff --git a/libavcodec/aarch64/vvc/of_template.c b/libavcodec/aarch64/vvc/of_template.c
deleted file mode 100644
index dd934398a1..0000000000
--- a/libavcodec/aarch64/vvc/of_template.c
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * Copyright (c) 2024 Zhao Zhili <quinkblack(a)foxmail.com>
- *
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#include "libavcodec/bit_depth_template.c"
-
-void FUNC2(ff_vvc_apply_bdof_block, BIT_DEPTH, _neon)(pixel* dst,
- ptrdiff_t dst_stride, const int16_t *src0, const int16_t *src1,
- const int16_t **gh, const int16_t **gv, int16_t *vx, int16_t *vy);
-
-static void FUNC(apply_bdof)(uint8_t *_dst, ptrdiff_t _dst_stride,
- const int16_t *_src0, const int16_t *_src1,
- int block_w, int block_h) {
- // +2 for pad left and right
- int16_t gradient_buf_h[2][BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2];
- int16_t gradient_buf_v[2][BDOF_BLOCK_SIZE * BDOF_BLOCK_SIZE + 2];
- int16_t *gradient_h[2] = {&gradient_buf_h[0][1], &gradient_buf_h[1][1]};
- int16_t *gradient_v[2] = {&gradient_buf_v[0][1], &gradient_buf_v[1][1]};
- ptrdiff_t dst_stride = _dst_stride / sizeof(pixel);
- pixel *dst = (pixel *) _dst;
-
- ff_vvc_prof_grad_filter_8x_neon(gradient_h[0], gradient_v[0],
- BDOF_BLOCK_SIZE,
- _src0, MAX_PB_SIZE, block_w, block_h);
- ff_vvc_prof_grad_filter_8x_neon(gradient_h[1], gradient_v[1],
- BDOF_BLOCK_SIZE,
- _src1, MAX_PB_SIZE, block_w, block_h);
- int16_t vx[BDOF_BLOCK_SIZE], vy[BDOF_BLOCK_SIZE];
- if (block_w == 8)
- ff_vvc_derive_bdof_vx_vy_8x_neon(_src0, _src1, gradient_h, gradient_v, vx, vy, block_h);
- else
- ff_vvc_derive_bdof_vx_vy_16x_neon(_src0, _src1, gradient_h, gradient_v, vx, vy, block_h);
-
- for (int y = 0; y < block_h; y += BDOF_MIN_BLOCK_SIZE) {
- for (int x = 0; x < block_w; x += BDOF_MIN_BLOCK_SIZE * 2) {
- const int16_t *src0 = _src0 + y * MAX_PB_SIZE + x;
- const int16_t *src1 = _src1 + y * MAX_PB_SIZE + x;
- pixel *d = dst + x;
- int idx = BDOF_BLOCK_SIZE * y + x;
- const int16_t *gh[] = {gradient_h[0] + idx, gradient_h[1] + idx};
- const int16_t *gv[] = {gradient_v[0] + idx, gradient_v[1] + idx};
- int idx1 = y + x / BDOF_MIN_BLOCK_SIZE;
- FUNC2(ff_vvc_apply_bdof_block, BIT_DEPTH, _neon)(d, dst_stride,
- src0, src1, gh, gv,
- vx + idx1, vy + idx1);
- }
- dst += BDOF_MIN_BLOCK_SIZE * dst_stride;
- }
-}
commit 2e924176036b415d5c9534a605f7f6a87cae423d
Author: Zhao Zhili <quinkblack(a)foxmail.com>
AuthorDate: Fri Jun 20 21:15:20 2025 +0800
Commit: Zhao Zhili <quink(a)noreply.code.ffmpeg.org>
CommitDate: Wed Sep 3 06:55:37 2025 +0000
avcodec/aarch64/vvc: Optimize derive_bdof_vx_vy
Implement line tricks and pixel tricks. See comments in inter.S
for details.
Benchmark on rpi5 with gcc 12
Before After
-----------------------------------------------------------------
apply_bdof_8_8x16_c: | 7375.5 ( 1.00x) | 7473.8 ( 1.00x)
apply_bdof_8_8x16_neon: | 1875.1 ( 3.93x) | 1135.8 ( 6.58x)
apply_bdof_8_16x8_c: | 7273.9 ( 1.00x) | 7204.0 ( 1.00x)
apply_bdof_8_16x8_neon: | 1738.2 ( 4.18x) | 1013.0 ( 7.11x)
apply_bdof_8_16x16_c: | 14744.9 ( 1.00x) | 14712.6 ( 1.00x)
apply_bdof_8_16x16_neon: | 3446.7 ( 4.28x) | 1997.7 ( 7.36x)
apply_bdof_10_8x16_c: | 7352.4 ( 1.00x) | 7485.7 ( 1.00x)
apply_bdof_10_8x16_neon: | 1861.0 ( 3.95x) | 1134.1 ( 6.60x)
apply_bdof_10_16x8_c: | 7330.5 ( 1.00x) | 7232.8 ( 1.00x)
apply_bdof_10_16x8_neon: | 1747.2 ( 4.20x) | 1002.6 ( 7.21x)
apply_bdof_10_16x16_c: | 14522.4 ( 1.00x) | 14664.8 ( 1.00x)
apply_bdof_10_16x16_neon: | 3490.5 ( 4.16x) | 1978.4 ( 7.41x)
apply_bdof_12_8x16_c: | 7389.0 ( 1.00x) | 7380.1 ( 1.00x)
apply_bdof_12_8x16_neon: | 1861.3 ( 3.97x) | 1134.0 ( 6.51x)
apply_bdof_12_16x8_c: | 7283.1 ( 1.00x) | 7336.9 ( 1.00x)
apply_bdof_12_16x8_neon: | 1749.1 ( 4.16x) | 1002.3 ( 7.32x)
apply_bdof_12_16x16_c: | 14580.7 ( 1.00x) | 14502.7 ( 1.00x)
apply_bdof_12_16x16_neon: | 3472.9 ( 4.20x) | 1978.3 ( 7.33x)
Signed-off-by: Zhao Zhili <zhilizhao(a)tencent.com>
diff --git a/libavcodec/aarch64/vvc/dsp_init.c b/libavcodec/aarch64/vvc/dsp_init.c
index 9a171234f6..3626d28ed6 100644
--- a/libavcodec/aarch64/vvc/dsp_init.c
+++ b/libavcodec/aarch64/vvc/dsp_init.c
@@ -37,11 +37,18 @@ void ff_vvc_prof_grad_filter_8x_neon(int16_t *gradient_h,
ptrdiff_t src_stride,
int width, int height);
-void ff_vvc_derive_bdof_vx_vy_neon(const int16_t *_src0, const int16_t *_src1,
- int pad_mask,
- const int16_t **gradient_h,
- const int16_t **gradient_v,
- int16_t *vx, int16_t *vy);
+void ff_vvc_derive_bdof_vx_vy_8x_neon(const int16_t *_src0,
+ const int16_t *_src1,
+ int16_t *const gradient_h[2],
+ int16_t *const gradient_v[2],
+ int16_t vx[16], int16_t vy[16],
+ int block_h);
+void ff_vvc_derive_bdof_vx_vy_16x_neon(const int16_t *_src0,
+ const int16_t *_src1,
+ int16_t *const gradient_h[2],
+ int16_t *const gradient_v[2],
+ int16_t vx[16], int16_t vy[16],
+ int block_h);
#define BIT_DEPTH 8
#include "alf_template.c"
#include "of_template.c"
diff --git a/libavcodec/aarch64/vvc/inter.S b/libavcodec/aarch64/vvc/inter.S
index c299e6f68b..1c79c6022a 100644
--- a/libavcodec/aarch64/vvc/inter.S
+++ b/libavcodec/aarch64/vvc/inter.S
@@ -804,262 +804,418 @@ function ff_vvc_apply_bdof_block_12_neon, export=1
vvc_apply_bdof_block 12
endfunc
-function ff_vvc_derive_bdof_vx_vy_neon, export=1
- src0 .req x0
- src1 .req x1
- pad_mask .req w2
- gh .req x3
- gv .req x4
- vx .req x5
- vy .req x6
-
- gh0 .req x7
- gh1 .req x8
- gv0 .req x9
- gv1 .req x10
- y .req x12
-
- sgx2 .req w7
- sgy2 .req w8
- sgxgy .req w9
- sgxdi .req w10
- sgydi .req w11
-
- sgx2_v .req v22
- sgy2_v .req v23
- sgxgy_v .req v24
- sgxdi_v .req v25
- sgydi_v .req v26
-
- sgx2_v2 .req v27
- sgy2_v2 .req v28
- sgxgy_v2 .req v29
- sgxdi_v2 .req v30
- sgydi_v2 .req v31
-
- ldp gh0, gh1, [gh]
- ldp gv0, gv1, [gv]
- movi sgx2_v.4s, #0
- movi sgy2_v.4s, #0
- movi sgxgy_v.4s, #0
- movi sgxdi_v.4s, #0
- movi sgydi_v.4s, #0
- movi sgx2_v2.4s, #0
- movi sgy2_v2.4s, #0
- movi sgxgy_v2.4s, #0
- movi sgxdi_v2.4s, #0
- movi sgydi_v2.4s, #0
- mov x13, #-1 // dy
- movi v6.4s, #0
- mov y, #-1
- tbz pad_mask, #1, 1f // check pad top
- mov x13, #0 // dy: pad top
+const bdof_vx_vy_8x_tbl
+ .byte 0, 1, 16, 16, 16, 16, 8, 9
+ .byte 6, 7, 16, 16, 16, 16, 14, 15
+endconst
+
+const bdof_vx_vy_16x_tbl
+ .byte 0, 1, 64, 64, 64, 64, 8, 9
+ .byte 6, 7, 64, 64, 64, 64, 16, 17
+ .byte 14, 15, 64, 64, 64, 64, 24, 25
+ .byte 22, 23, 64, 64, 64, 64, 30, 31
+endconst
+
+// line(-1), line0, line1, line2, line3, line4
+// line3 and line4 becomes line(-1) and line0 in the next block.
+.macro bdof_vx_vy_8x_save_line tmp0, tmp1, tmp2, tmp3, tmp4
+ mov \tmp0\().16b, v28.16b
+ mov \tmp1\().16b, v29.16b
+ mov \tmp2\().16b, v30.16b
+ mov \tmp3\().16b, v31.16b
+ mov \tmp4\().16b, v8.16b
+.endm
+
+.macro bdof_vx_vy_8x_add_line tmp0, tmp1, tmp2, tmp3, tmp4
+ add v25.4s, v25.4s, \tmp0\().4s
+ add v27.4s, v27.4s, \tmp1\().4s
+ add v23.4s, v23.4s, \tmp2\().4s
+ sub v26.4s, v26.4s, \tmp3\().4s
+ sub v24.4s, v24.4s, \tmp4\().4s
+.endm
+
+.macro bdof_vx_vy_8x_padding_left_right src, tmp0, tmp1, dst
+ tbl \tmp0\().16b, { \src\().16b }, v0.16b
+ saddl \tmp1\().4s, \tmp0\().4h, \src\().4h
+ saddl2 \dst\().4s, \tmp0\().8h, \src\().8h
+ addp \dst\().4s, \tmp1\().4s, \dst\().4s
+.endm
+
+.macro bdof_vx_vy_sign src, tmp0, tmp1, dst
+ cmlt \tmp0\().8h, \src\().8h, #0
+ cmgt \tmp1\().8h, \src\().8h, #0
+ sub \dst\().8h, \tmp0\().8h, \tmp1\().8h
+.endm
+
+.macro bdof_vx_vy_clip_mask src, max, min, mask, dst
+ smin \src\().4s, \src\().4s, \max\().4s
+ smax \src\().4s, \src\().4s, \min\().4s
+ cmgt \mask\().4s, \mask\().4s, #0
+ and \dst\().16b, \src\().16b, \mask\().16b
+.endm
+
+.macro bdof_vx_vy_16x_save_line tmp0, tmp1, tmp2, tmp3, tmp4
+ mov \tmp0\().16b, v29.16b
+ mov \tmp1\().16b, v30.16b
+ mov \tmp2\().16b, v31.16b
+ mov \tmp3\().16b, v8.16b
+ mov \tmp4\().16b, v9.16b
+.endm
+
+.macro bdof_vx_vy_16x_add_line tmp0, tmp1, tmp2, tmp3, tmp4
+ add v25.4s, v25.4s, \tmp0\().4s
+ add v24.4s, v24.4s, \tmp1\().4s
+ add v26.4s, v26.4s, \tmp2\().4s
+ sub v28.4s, v28.4s, \tmp3\().4s
+ sub v27.4s, v27.4s, \tmp4\().4s
+.endm
+
+.macro bdof_vx_vy_16x_padding_left_right src0, src1, tmp0, tmp1, tmp2, dst
+ tbl \tmp0\().16b, {\src0\().16b, \src1\().16b}, v0.16b
+ tbl v2.16b, {\src0\().16b, \src1\().16b}, v1.16b
+ saddl \tmp1\().4s, \tmp0\().4h, \src0\().4h
+ saddl \tmp2\().4s, v2.4h, \src1\().4h
+ saddl2 \tmp0\().4s, \tmp0\().8h, \src0\().8h
+ saddl2 \dst\().4s, v2.8h, \src1\().8h
+ addp \tmp0\().4s, \tmp1\().4s, \tmp0\().4s
+ addp \dst\().4s, \tmp2\().4s, \dst\().4s
+ addp \dst\().4s, \tmp0\().4s, \dst\().4s
+.endm
+
+/*
+ * Line tricks:
+ * We need 6 lines of information, from 4N-1, 4N, 4N+1 to 4N+4. 4N-1
+ * and 4N+0 are processed in the last group, so they can be reused.
+ *
+ * (4N-1) [xxxxxxxxxxxxx] <--- reuse
+ * (4N) [xxxxxxxxxxxxx] <--- reuse
+ * (4N+1) [xxxxxxxxxxxxx]
+ * (4N+2) [xxxxxxxxxxxxx]
+ * (4N+3) [xxxxxxxxxxxxx] ---> save for reuse
+ * (4N+4) [xxxxxxxxxxxxx] ---> save for reuse
+ *
+ * Special case:
+ * 1. Line -1 needs to duplicate line 0.
+ * 2. Last line +1 needs to duplicate the last line.
+ *
+ * ---------------------------------------------------------------------
+ * Pixel tricks:
+ *
+ * [C-1, C0, C1, C2, ... C16]
+ *
+ * For each line, we need to sum parameters for 4 * 6 pixels:
+ * - C-1 + C0 + C1 + C2 + C3 + C4
+ * - C3 + C4 + C5 + C6 + C7 + C8
+ * - C7 + C8 + C9 + C10 + C11 + C12
+ * - C11 + C12 + C13 + C14 + C15 + C16
+ *
+ * C-1 is C0, C16 is C15, so we can do:
+ *
+ * [C0, C1, C2, C3, | C4, C5, C6, C7, | C8, ... C15]
+ * + | + |
+ * [C0, 0, 0, C4, | C3, 0, 0, C8, | C7, ... C15]
+ *
+ * 8x is similar.
+ * ----------------------------------------------------------------------
+ * x0: const int16_t *_src0,
+ * x1: const int16_t *_src1,
+ * x2: int16_t *const gradient_h[2],
+ * x3: int16_t *const gradient_v[2],
+ * x4: int16_t vx[16],
+ * x5: int16_t vy[16],
+ * w6: int block_h
+ */
+function ff_vvc_derive_bdof_vx_vy_8x_neon, export=1
+ stp d11, d10, [sp, #-0x20]!
+ stp d9, d8, [sp, #0x10]
+
+ ldp x14, x13, [x2] // gh0, gh1
+ ldp x10, x9, [x3] // gv0, gv1
+ movrel x11, bdof_vx_vy_8x_tbl
+ ldr q0, [x11] // table
+ mvni v2.4s, #30 // -31, for log2
+ movi v3.4s, #15 // clip to 15
+ mvni v4.4s, #14 // clip to -15
+
+ mov w11, #0x8
+ mov w12, w6 // y = block_h
+ b 4f
+
1:
- mov x16, #-2 // dx
- add x14, src0, x13, lsl #8 // local src0
- add x15, src1, x13, lsl #8 // local src1
- add x17, x16, x13, lsl #5
- ldr q0, [x14, x16]
- ldr q1, [x15, x16]
- ldr q2, [gh0, x17]
- ldr q3, [gh1, x17]
- ldr q4, [gv0, x17]
- ldr q5, [gv1, x17]
- add x16, x16, #8
- add x17, x17, #8
- ins v0.s[3], v6.s[3]
- ins v1.s[3], v6.s[3]
- ins v2.s[3], v6.s[3]
- ins v3.s[3], v6.s[3]
- ins v4.s[3], v6.s[3]
- ins v5.s[3], v6.s[3]
-
- ldr q16, [x14, x16]
- ldr q17, [x15, x16]
- ldr q18, [gh0, x17]
- ldr q19, [gh1, x17]
- ldr q20, [gv0, x17]
- ldr q21, [gv1, x17]
- ins v16.s[3], v6.s[3]
- ins v17.s[3], v6.s[3]
- ins v18.s[3], v6.s[3]
- ins v19.s[3], v6.s[3]
- ins v20.s[3], v6.s[3]
- ins v21.s[3], v6.s[3]
-
- tbz pad_mask, #0, 20f
- // pad left
- ins v0.h[0], v0.h[1]
- ins v1.h[0], v1.h[1]
- ins v2.h[0], v2.h[1]
- ins v3.h[0], v3.h[1]
- ins v4.h[0], v4.h[1]
- ins v5.h[0], v5.h[1]
-20:
- tbz pad_mask, #2, 21f
- // pad right
- ins v16.h[5], v16.h[4]
- ins v17.h[5], v17.h[4]
- ins v18.h[5], v18.h[4]
- ins v19.h[5], v19.h[4]
- ins v20.h[5], v20.h[4]
- ins v21.h[5], v21.h[4]
-21:
- sshr v0.8h, v0.8h, #4
- sshr v1.8h, v1.8h, #4
- add v2.8h, v2.8h, v3.8h
- add v4.8h, v4.8h, v5.8h
- sub v0.8h, v0.8h, v1.8h // diff
- sshr v2.8h, v2.8h, #1 // temph
- sshr v4.8h, v4.8h, #1 // tempv
-
- sshr v16.8h, v16.8h, #4
- sshr v17.8h, v17.8h, #4
- add v18.8h, v18.8h, v19.8h
- add v20.8h, v20.8h, v21.8h
- sub v16.8h, v16.8h, v17.8h // diff
- sshr v18.8h, v18.8h, #1 // temph
- sshr v20.8h, v20.8h, #1 // tempv
-
- abs v3.8h, v2.8h
- abs v5.8h, v4.8h
- uxtl v19.4s, v3.4h
- uxtl v21.4s, v5.4h
- uxtl2 v3.4s, v3.8h
- uxtl2 v5.4s, v5.8h
- add v3.4s, v3.4s, v19.4s
- add v5.4s, v5.4s, v21.4s
- add sgx2_v.4s, sgx2_v.4s, v3.4s
- add sgy2_v.4s, sgy2_v.4s, v5.4s
-
- abs v3.8h, v18.8h
- abs v5.8h, v20.8h
- uxtl v19.4s, v3.4h
- uxtl v21.4s, v5.4h
- uxtl2 v3.4s, v3.8h
- uxtl2 v5.4s, v5.8h
- add v3.4s, v3.4s, v19.4s
- add v5.4s, v5.4s, v21.4s
- add sgx2_v2.4s, sgx2_v2.4s, v3.4s
- add sgy2_v2.4s, sgy2_v2.4s, v5.4s
-
- cmgt v17.8h, v4.8h, #0
- cmlt v7.8h, v4.8h, #0
- cmgt v19.8h, v20.8h, #0
- cmlt v21.8h, v20.8h, #0
- sub v17.8h, v7.8h, v17.8h // VVC_SIGN(tempv)
- sub v19.8h, v21.8h, v19.8h // VVC_SIGN(tempv)
-
- smlal sgxgy_v.4s, v17.4h, v2.4h
- smlal2 sgxgy_v.4s, v17.8h, v2.8h
- smlsl sgydi_v.4s, v17.4h, v0.4h
- smlsl2 sgydi_v.4s, v17.8h, v0.8h
-
- cmgt v3.8h, v2.8h, #0
- cmlt v5.8h, v2.8h, #0
- cmgt v17.8h, v18.8h, #0
- cmlt v21.8h, v18.8h, #0
- sub v3.8h, v5.8h, v3.8h // VVC_SIGN(temph)
- sub v17.8h, v21.8h, v17.8h // VVC_SIGN(temph)
-
- smlal sgxgy_v2.4s, v19.4h, v18.4h
- smlal2 sgxgy_v2.4s, v19.8h, v18.8h
- smlsl sgydi_v2.4s, v19.4h, v16.4h
- smlsl2 sgydi_v2.4s, v19.8h, v16.8h
-
- smlsl sgxdi_v.4s, v3.4h, v0.4h
- smlsl2 sgxdi_v.4s, v3.8h, v0.8h
- smlsl sgxdi_v2.4s, v17.4h, v16.4h
- smlsl2 sgxdi_v2.4s, v17.8h, v16.8h
-3:
- add y, y, #1
- cmp y, #(BDOF_MIN_BLOCK_SIZE)
- mov x13, y
- b.gt 4f
- b.lt 1b
- tbz pad_mask, #3, 1b
- sub x13, x13, #1 // pad bottom
- b 1b
+ // save line4 results
+ bdof_vx_vy_8x_save_line v5, v6, v7, v16, v17
+2:
+ addp v25.4s, v25.4s, v25.4s
+ addp v27.4s, v27.4s, v27.4s
+ addp v26.4s, v26.4s, v26.4s
+ addp v23.4s, v23.4s, v23.4s
+ addp v24.4s, v24.4s, v24.4s
+
+ clz v28.4s, v25.4s
+ add v28.4s, v28.4s, v2.4s // log2
+ shl v26.4s, v26.4s, #0x2
+ sshl v26.4s, v26.4s, v28.4s
+
+ bdof_vx_vy_clip_mask v26, v3, v4, v25, v25
+ sqxtn v26.4h, v25.4s
+ st1 {v26.s}[0], [x4], x11
+
+ subs x12, x12, #(BDOF_MIN_BLOCK_SIZE)
+
+ clz v26.4s, v27.4s
+ add v26.4s, v26.4s, v2.4s
+ shl v24.4s, v24.4s, #0x2
+ mul v23.4s, v25.4s, v23.4s
+ sshr v23.4s, v23.4s, #0x1
+ sub v23.4s, v24.4s, v23.4s
+ sshl v23.4s, v23.4s, v26.4s
+
+ bdof_vx_vy_clip_mask v23, v3, v4, v27, v23
+ sqxtn v23.4h, v23.4s
+ st1 {v23.s}[0], [x5], x11
+
+ b.eq 16f
4:
- addv s22, sgx2_v.4s
- addv s23, sgy2_v.4s
- addv s24, sgxgy_v.4s
- addv s25, sgxdi_v.4s
- addv s26, sgydi_v.4s
-
- mov w3, #31
- mov w16, #-15
- mov w17, #15
-40:
- mov w14, #0
-
- mov sgx2, v22.s[0]
- mov sgy2, v23.s[0]
- mov sgxgy, v24.s[0]
- mov sgxdi, v25.s[0]
- mov sgydi, v26.s[0]
-
- cbz sgx2, 5f
- clz w12, sgx2
- lsl sgxdi, sgxdi, #2
- sub w13, w3, w12 // log2(sgx2)
- asr sgxdi, sgxdi, w13
- cmp sgxdi, w16
- csel w14, w16, sgxdi, lt // clip to -15
- b.le 5f
- cmp sgxdi, w17
- csel w14, w17, sgxdi, gt // clip to 15
+ mov x15, #0x0 // dy, inner loop
+
+ movi v25.2d, #0
+ movi v27.2d, #0
+ movi v23.2d, #0
+ movi v26.2d, #0
+ movi v24.2d, #0
+ b 8f
+
5:
- strh w14, [vx], #2
-
- mov w15, #0
- cbz sgy2, 6f
- lsl sgydi, sgydi, #2
- smull x14, w14, sgxgy
- asr w14, w14, #1
- sub sgydi, sgydi, w14
- clz w12, sgy2
- sub w13, w3, w12 // log2(sgy2)
- asr sgydi, sgydi, w13
- cmp sgydi, w16
- csel w15, w16, sgydi, lt // clip to -15
- b.le 6f
- cmp sgydi, w17
- csel w15, w17, sgydi, gt // clip to 15
-6:
- strh w15, [vy], #2
- cbz x0, 7f
- addv s22, sgx2_v2.4s
- addv s23, sgy2_v2.4s
- addv s24, sgxgy_v2.4s
- addv s25, sgxdi_v2.4s
- addv s26, sgydi_v2.4s
- mov x0, #0
- b 40b
-7:
+ // add line(-1) and line0 from previous results
+ bdof_vx_vy_8x_add_line v18, v19, v20, v21, v22
+ bdof_vx_vy_8x_add_line v5, v6, v7, v16, v17
+ add x15, x15, #1
+8:
+ cmp w12, w6
+ b.hs 9f
+ // y < block_h && dy == 0, reuse previous results
+ cbz x15, 5b
+9:
+ ldr q28, [x0] // src0
+ ldr q29, [x1] // src1
+ ldr q30, [x14], #(BDOF_BLOCK_SIZE * 2) // gh0
+ ldr q31, [x13], #(BDOF_BLOCK_SIZE * 2) // gh1
+ ldr q8, [x10], #(BDOF_BLOCK_SIZE * 2) // gv0
+ ldr q9, [x9], #(BDOF_BLOCK_SIZE * 2) // gv1
+ add x0, x0, #(VVC_MAX_PB_SIZE * 2)
+ add x1, x1, #(VVC_MAX_PB_SIZE * 2)
+
+ sshr v28.8h, v28.8h, #0x4
+ sshr v29.8h, v29.8h, #0x4
+ shadd v30.8h, v30.8h, v31.8h // tmph
+ shadd v31.8h, v8.8h, v9.8h // tmpv
+ sub v8.8h, v28.8h, v29.8h // diff
+
+ abs v28.8h, v30.8h
+ abs v29.8h, v31.8h
+
+ bdof_vx_vy_8x_padding_left_right v28, v9, v10, v28
+ bdof_vx_vy_8x_padding_left_right v29, v9, v10, v29
+
+ bdof_vx_vy_sign v30, v9, v10, v9
+ bdof_vx_vy_sign v31, v10, v31, v31
+
+ mul v30.8h, v31.8h, v30.8h
+ mul v9.8h, v9.8h, v8.8h
+ mul v8.8h, v31.8h, v8.8h
+
+ bdof_vx_vy_8x_padding_left_right v30, v31, v10, v30
+ bdof_vx_vy_8x_padding_left_right v9, v31, v10, v31
+ bdof_vx_vy_8x_padding_left_right v8, v9, v10, v8
+
+ bdof_vx_vy_8x_add_line v28, v29, v30, v31, v8
+
+ cmp w12, w6
+ b.ne 10f
+ cbnz x15, 10f
+
+ // y == block_h && dy == 0, duplicate first line results
+ bdof_vx_vy_8x_add_line v28, v29, v30, v31, v8
+ add x15, x15, #0x1
+ b 9b
+10:
+ cmp x15, #(BDOF_MIN_BLOCK_SIZE - 1)
+ b.eq 11f
+ cmp x15, #(BDOF_MIN_BLOCK_SIZE)
+ b.ne 12f
+ b 1b
+11:
+ // y == BDOF_MIN_BLOCK_SIZE && dy == BDOF_MIN_BLOCK_SIZE - 1
+ // duplicate the results and break
+ cmp x12, #(BDOF_MIN_BLOCK_SIZE)
+ b.eq 13f
+ bdof_vx_vy_8x_save_line v18, v19, v20, v21, v22
+12:
+ add x15, x15, #1
+ b 8b
+13:
+ // y == BDOF_MIN_BLOCK_SIZE && dy == BDOF_MIN_BLOCK_SIZE - 1
+ // padding bottom then break
+ bdof_vx_vy_8x_add_line v28, v29, v30, v31, v8
+ b 2b
+16:
+ ldp d9, d8, [sp, #0x10]
+ ldp d11, d10, [sp], #0x20
ret
+endfunc
-.unreq src0
-.unreq src1
-.unreq pad_mask
-.unreq gh
-.unreq gv
-.unreq vx
-.unreq vy
-.unreq sgx2
-.unreq sgy2
-.unreq sgxgy
-.unreq sgxdi
-.unreq sgydi
-.unreq sgx2_v
-.unreq sgy2_v
-.unreq sgxgy_v
-.unreq sgxdi_v
-.unreq sgydi_v
-.unreq sgx2_v2
-.unreq sgy2_v2
-.unreq sgxgy_v2
-.unreq sgxdi_v2
-.unreq sgydi_v2
-.unreq y
+/*
+ * x0: const int16_t *_src0,
+ * x1: const int16_t *_src1,
+ * x2: int16_t *const gradient_h[2],
+ * x3: int16_t *const gradient_v[2],
+ * x4: int16_t vx[16],
+ * x5: int16_t vy[16],
+ * w6: int block_h
+ */
+function ff_vvc_derive_bdof_vx_vy_16x_neon, export=1
+ stp d15, d14, [sp, #-0x40]!
+ stp d13, d12, [sp, #0x10]
+ stp d11, d10, [sp, #0x20]
+ stp d9, d8, [sp, #0x30]
+
+ ldp x8, x9, [x2] // gh0, gh1
+ ldp x10, x11, [x3] // gv0, gv1
+ movrel x12, bdof_vx_vy_16x_tbl
+ ldp q0, q1, [x12] // table
+ mov w13, w6 // y = block_h
+ b 4f
+
+1:
+ // save line4
+ bdof_vx_vy_16x_save_line v6, v7, v16, v17, v18
+2:
+ clz v3.4s, v25.4s
+ mvni v5.4s, #0x1e
+ add v3.4s, v3.4s, v5.4s // -log2()
+ shl v4.4s, v28.4s, #0x2
+ sshl v3.4s, v4.4s, v3.4s
+
+ movi v28.4s, #0xf // clip to 15
+ mvni v29.4s, #0xe // clip to -15
+ bdof_vx_vy_clip_mask v3, v28, v29, v25, v3
+ sqxtn v4.4h, v3.4s
+ st1 {v4.d}[0], [x4], #(BDOF_MIN_BLOCK_SIZE * 2)
+
+ subs x13, x13, #(BDOF_MIN_BLOCK_SIZE) // y -= BDOF_MIN_BLOCK_SIZE
+
+ clz v4.4s, v24.4s
+ add v4.4s, v4.4s, v5.4s // -log2()
+ shl v5.4s, v27.4s, #0x2
+ mul v3.4s, v3.4s, v26.4s
+ sshr v3.4s, v3.4s, #0x1
+ sub v3.4s, v5.4s, v3.4s
+ sshl v3.4s, v3.4s, v4.4s
+
+ bdof_vx_vy_clip_mask v3, v28, v29, v24, v3
+ sqxtn v3.4h, v3.4s
+ st1 {v3.d}[0], [x5], #(BDOF_MIN_BLOCK_SIZE * 2)
+ b.eq 16f
+4:
+ mov w14, #0x0 // dy, inner loop
+
+ movi v25.2d, #0
+ movi v24.2d, #0
+ movi v26.2d, #0
+ movi v28.2d, #0
+ movi v27.2d, #0
+ b 8f
+
+5:
+ // add line(-1) and line0 from previous results
+ bdof_vx_vy_16x_add_line v19, v20, v21, v22, v23
+ bdof_vx_vy_16x_add_line v6, v7, v16, v17, v18
+ add w14, w14, #0x1
+
+ 8:
+ cmp w13, w6
+ b.hs 9f
+ // y < block_h && dy == 0, reuse previous results
+ cbz w14, 5b
+9:
+ ld1 {v29.8h, v30.8h}, [x0] // src0
+ sshr v31.8h, v29.8h, #0x4
+ ld1 {v8.8h, v9.8h}, [x1] // src1
+ sshr v10.8h, v8.8h, #0x4
+ ld1 {v11.8h, v12.8h}, [x8], #32 // gh0
+ sshr v29.8h, v30.8h, #0x4
+ sshr v30.8h, v9.8h, #0x4
+ ld1 {v8.8h, v9.8h}, [x9], #32 // gh1
+ shadd v13.8h, v11.8h, v8.8h // (gh0 + gh1) >> 1, left half
+ ld1 {v14.8h, v15.8h}, [x10], #32 // gv0
+ ld1 {v3.8h, v4.8h}, [x11], #32 // gv1
+ shadd v5.8h, v14.8h, v3.8h // (gv0 + gv1) >> 1, left half
+ sub v31.8h, v31.8h, v10.8h // diff, left half
+ shadd v8.8h, v12.8h, v9.8h // (gh0 + gh1) >> 1, right half
+ shadd v3.8h, v15.8h, v4.8h // (gv0 + gv1) >> 1, right half
+ sub v4.8h, v29.8h, v30.8h // diff, right half
+
+ abs v29.8h, v13.8h
+ abs v30.8h, v8.8h
+ abs v9.8h, v5.8h
+ abs v10.8h, v3.8h
+
+ add x0, x0, #(VVC_MAX_PB_SIZE * 2)
+ add x1, x1, #(VVC_MAX_PB_SIZE * 2)
+
+ bdof_vx_vy_16x_padding_left_right v29, v30, v11, v12, v14, v29
+ bdof_vx_vy_16x_padding_left_right v9, v10, v11, v12, v14, v30
+
+ bdof_vx_vy_sign v13, v9, v10, v9
+ bdof_vx_vy_sign v8, v10, v11, v10
+ bdof_vx_vy_sign v5, v11, v5, v5
+ bdof_vx_vy_sign v3, v11, v3, v3
+
+ mul v11.8h, v5.8h, v13.8h
+ mul v12.8h, v3.8h, v8.8h
+ mul v8.8h, v9.8h, v31.8h
+ mul v9.8h, v10.8h, v4.8h
+ mul v13.8h, v5.8h, v31.8h
+ mul v14.8h, v3.8h, v4.8h
+
+ bdof_vx_vy_16x_padding_left_right v11, v12, v3, v4, v5, v31
+ bdof_vx_vy_16x_padding_left_right v8, v9, v3, v4, v5, v8
+ bdof_vx_vy_16x_padding_left_right v13, v14, v3, v4, v5, v9
+
+ bdof_vx_vy_16x_add_line v29, v30, v31, v8, v9
+ // check whether padding top
+ cmp w13, w6
+ b.ne 10f
+ cbnz w14, 10f
+ // y == block_h && dy == 0, padding top
+ bdof_vx_vy_16x_add_line v29, v30, v31, v8, v9
+ add w14, w14, #0x1
+ b 9b
+10:
+ cmp w14, #(BDOF_MIN_BLOCK_SIZE - 1)
+ b.eq 11f
+ cmp w14, #(BDOF_MIN_BLOCK_SIZE)
+ b.ne 12f
+ // save line4
+ b 1b
+ 11:
+ // y == BDOF_MIN_BLOCK_SIZE && dy == BDOF_MIN_BLOCK_SIZE - 1, padding bottom
+ cmp x13, #(BDOF_MIN_BLOCK_SIZE)
+ b.eq 13f
+ // save line3
+ bdof_vx_vy_16x_save_line v19, v20, v21, v22, v23
+12:
+ add w14, w14, #0x1 // dy++
+ b 8b
+13:
+ // padding bottom
+ bdof_vx_vy_16x_add_line v29, v30, v31, v8, v9
+ b 2b
+16:
+ // restore
+ ldp d9, d8, [sp, #0x30]
+ ldp d11, d10, [sp, #0x20]
+ ldp d13, d12, [sp, #0x10]
+ ldp d15, d14, [sp], #0x40
+ ret
endfunc
diff --git a/libavcodec/aarch64/vvc/of_template.c b/libavcodec/aarch64/vvc/of_template.c
index ac6182b09d..dd934398a1 100644
--- a/libavcodec/aarch64/vvc/of_template.c
+++ b/libavcodec/aarch64/vvc/of_template.c
@@ -41,6 +41,11 @@ static void FUNC(apply_bdof)(uint8_t *_dst, ptrdiff_t _dst_stride,
ff_vvc_prof_grad_filter_8x_neon(gradient_h[1], gradient_v[1],
BDOF_BLOCK_SIZE,
_src1, MAX_PB_SIZE, block_w, block_h);
+ int16_t vx[BDOF_BLOCK_SIZE], vy[BDOF_BLOCK_SIZE];
+ if (block_w == 8)
+ ff_vvc_derive_bdof_vx_vy_8x_neon(_src0, _src1, gradient_h, gradient_v, vx, vy, block_h);
+ else
+ ff_vvc_derive_bdof_vx_vy_16x_neon(_src0, _src1, gradient_h, gradient_v, vx, vy, block_h);
for (int y = 0; y < block_h; y += BDOF_MIN_BLOCK_SIZE) {
for (int x = 0; x < block_w; x += BDOF_MIN_BLOCK_SIZE * 2) {
@@ -50,14 +55,10 @@ static void FUNC(apply_bdof)(uint8_t *_dst, ptrdiff_t _dst_stride,
int idx = BDOF_BLOCK_SIZE * y + x;
const int16_t *gh[] = {gradient_h[0] + idx, gradient_h[1] + idx};
const int16_t *gv[] = {gradient_v[0] + idx, gradient_v[1] + idx};
- int16_t vx[2], vy[2];
- int pad_mask = !x | ((!y) << 1) |
- ((x + 2 * BDOF_MIN_BLOCK_SIZE == block_w) << 2) |
- ((y + BDOF_MIN_BLOCK_SIZE == block_h) << 3);
- ff_vvc_derive_bdof_vx_vy_neon(src0, src1, pad_mask, gh, gv, vx, vy);
+ int idx1 = y + x / BDOF_MIN_BLOCK_SIZE;
FUNC2(ff_vvc_apply_bdof_block, BIT_DEPTH, _neon)(d, dst_stride,
src0, src1, gh, gv,
- vx, vy);
+ vx + idx1, vy + idx1);
}
dst += BDOF_MIN_BLOCK_SIZE * dst_stride;
}
-----------------------------------------------------------------------
Summary of changes:
libavcodec/aarch64/vvc/dsp_init.c | 30 +-
libavcodec/aarch64/vvc/inter.S | 1012 +++++++++++++++++++++++++---------
libavcodec/aarch64/vvc/of_template.c | 64 ---
3 files changed, 751 insertions(+), 355 deletions(-)
delete mode 100644 libavcodec/aarch64/vvc/of_template.c
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. 3800421e7c add clamping for escpase coeff
by ffmpeg-git@ffmpeg.org 03 Sep '25
by ffmpeg-git@ffmpeg.org 03 Sep '25
03 Sep '25
The branch, master has been updated
via 3800421e7cb4372b756542ff4918102505ffb5f4 (commit)
from a700f0f72d1f073e5adcfbb16f4633850b0ef51c (commit)
- Log -----------------------------------------------------------------
commit 3800421e7cb4372b756542ff4918102505ffb5f4
Author: damitha <damitha.gunawardena(a)gmail.com>
AuthorDate: Sun Aug 31 06:50:48 2025 +1000
Commit: Lynne <dev(a)lynne.ee>
CommitDate: Wed Sep 3 06:48:02 2025 +0000
add clamping for escpase coeff
diff --git a/libavcodec/aaccoder.c b/libavcodec/aaccoder.c
index 96915c9731..7f1c4cdcc1 100644
--- a/libavcodec/aaccoder.c
+++ b/libavcodec/aaccoder.c
@@ -173,7 +173,7 @@ static av_always_inline float quantize_and_encode_band_cost_template(
if (BT_ESC) {
for (int j = 0; j < 2; j++) {
if (ff_aac_codebook_vectors[cb-1][curidx*2+j] == 64.0f) {
- int coef = av_clip_uintp2(quant(fabsf(in[i+j]), Q, ROUNDING), 13);
+ int coef = av_clip(quant(fabsf(in[i+j]), Q, ROUNDING), 16, (1 << 13) - 1);
int len = av_log2(coef);
put_bits(pb, len - 4 + 1, (1 << (len - 4 + 1)) - 2);
-----------------------------------------------------------------------
Summary of changes:
libavcodec/aaccoder.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. a700f0f72d avfilter/vf_zscale: simplify and fix alpha handling
by ffmpeg-git@ffmpeg.org 02 Sep '25
by ffmpeg-git@ffmpeg.org 02 Sep '25
02 Sep '25
The branch, master has been updated
via a700f0f72d1f073e5adcfbb16f4633850b0ef51c (commit)
via c7adeb75ac94efd41e08d3cd928a0d4468b820f8 (commit)
via 446a25b70f340960b9f0df598ae704e64bd68d32 (commit)
via 39631c99d4dff0185638e7f16f97732808d08718 (commit)
via a90e8f1c1d1a6a9c4552605a3b98220c51d08f37 (commit)
via eddbdc8b7c70c562ff90c62c31070ce92a296233 (commit)
via d05484757a3dca825642234bdefc639bdfb0c5b8 (commit)
via ba8aa0e7b383d88624e8513e69a944fc5cb9de8d (commit)
via 59bb51a8f2a6fa336dbbd136bdcac230f7ba58ec (commit)
via 6d6bbdaab0596b8254e3d367dfd808c9eb7ba4ee (commit)
via 6f3eddbeddc7ffbea30504eb5e2f4e525ec2f360 (commit)
via 1c8ca56a8805727339e4e52ec14d903b099cee28 (commit)
via dc02514f6bdd959f9b2f7b8a9b286e39c57ee85c (commit)
via e6ab7fe5825c380386d2423d3b2c23df16699361 (commit)
via a3d518a57cf8cb9cbc9c203a179d7c9ebe8c65d6 (commit)
via ab1bc440f752fded5998d61f8587d723a0b0c5cf (commit)
via 2032820e90ce0e94b9214c8df36002ef74e2bbb0 (commit)
via 4f99026c9f453c83c168eac99615234583791c8b (commit)
via f07573f49646bc29210ab1e9b9bb3f6312039c83 (commit)
via 2e2ca4e74080207a48c455377eb0ec049979268e (commit)
via 2b1ef029eb00731908dac044f409300b4b378c83 (commit)
via de297ae2fca90a4ab3f2b30f64e886be13365ae1 (commit)
via 0fbd90d78f8d534a97e83331c6448f54fdf0a277 (commit)
via 65580592c91be88065951adac4403b5b94b88984 (commit)
via 51572ff08abe44bc042a6004459bd1326d31bbce (commit)
via a88cc0a53ea55576431c74ebd4c0a982d1052e99 (commit)
via 702a5ac29b5c402ab6ff9e40621e6e12f38826ca (commit)
via d6ce720765d0684d596f3238ba77f6c16c0cee44 (commit)
via 02d531ca05eaf3cc6e9299d45ac2cc60d8c8eac7 (commit)
via ecebf9c69351f011a2e43079621bcdd5ab23a4d9 (commit)
via fb3a4f61806bebf68ccff188256c5faf1d71a098 (commit)
via c39a67e64f71943e7c23c11f5d8d233ef66d9259 (commit)
via 6bac13d20a3177e511cf7531ab9eeeb0f438a8e4 (commit)
via eea99a77eda6aa843a52e1996fcf10408248aa38 (commit)
via 8b375b2ffd4377909180241cdc65d63d372a35a3 (commit)
via dbcdcaede8544705af0c3d63d0831fe20d5c1ff4 (commit)
via 22929bd044cdf971ea2a5b906c6fadbe653a7c19 (commit)
from f24474dcfc719e29dc87e6483d6187ea233f4e0f (commit)
- Log -----------------------------------------------------------------
commit a700f0f72d1f073e5adcfbb16f4633850b0ef51c
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Mon Aug 18 13:24:16 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_zscale: simplify and fix alpha handling
There's no reason to use a completely separate graph just to process the
alpha plane in isolation - zimg supports native alpha handling as part of the
main image.
Fixes several issues with this filter when adding or removing alpha planes,
and also adds support for scaling premultiplied alpha (which reduces artefacts
near the image borders).
diff --git a/libavfilter/vf_zscale.c b/libavfilter/vf_zscale.c
index 45b89ebc39..9ea50133c6 100644
--- a/libavfilter/vf_zscale.c
+++ b/libavfilter/vf_zscale.c
@@ -121,12 +121,10 @@ typedef struct ZScaleContext {
int out_slice_end[MAX_THREADS];
zimg_image_format src_format, dst_format;
- zimg_image_format alpha_src_format, alpha_dst_format;
zimg_image_format src_format_tmp, dst_format_tmp;
- zimg_image_format alpha_src_format_tmp, alpha_dst_format_tmp;
- zimg_graph_builder_params alpha_params, params;
- zimg_graph_builder_params alpha_params_tmp, params_tmp;
- zimg_filter_graph *alpha_graph[MAX_THREADS], *graph[MAX_THREADS];
+ zimg_graph_builder_params params;
+ zimg_graph_builder_params params_tmp;
+ zimg_filter_graph *graph[MAX_THREADS];
} ZScaleContext;
typedef struct ThreadData {
@@ -143,15 +141,8 @@ static av_cold int init(AVFilterContext *ctx)
zimg_image_format_default(&s->src_format_tmp, ZIMG_API_VERSION);
zimg_image_format_default(&s->dst_format_tmp, ZIMG_API_VERSION);
- zimg_image_format_default(&s->alpha_src_format, ZIMG_API_VERSION);
- zimg_image_format_default(&s->alpha_dst_format, ZIMG_API_VERSION);
- zimg_image_format_default(&s->alpha_src_format_tmp, ZIMG_API_VERSION);
- zimg_image_format_default(&s->alpha_dst_format_tmp, ZIMG_API_VERSION);
-
zimg_graph_builder_params_default(&s->params, ZIMG_API_VERSION);
zimg_graph_builder_params_default(&s->params_tmp, ZIMG_API_VERSION);
- zimg_graph_builder_params_default(&s->alpha_params, ZIMG_API_VERSION);
- zimg_graph_builder_params_default(&s->alpha_params_tmp, ZIMG_API_VERSION);
if (s->size_str && (s->w_expr || s->h_expr)) {
av_log(ctx, AV_LOG_ERROR,
@@ -240,6 +231,10 @@ static int query_formats(const AVFilterContext *ctx,
if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_ranges)) < 0)
return ret;
+ if ((ret = ff_formats_ref(ff_all_alpha_modes(), &cfg_in[0]->alpha_modes)) < 0 ||
+ (ret = ff_formats_ref(ff_all_alpha_modes(), &cfg_out[0]->alpha_modes)) < 0)
+ return ret;
+
return 0;
}
@@ -594,6 +589,8 @@ static void format_init(zimg_image_format *format, AVFrame *frame, const AVPixFm
format->transfer_characteristics = transfer == -1 ? convert_trc(frame->color_trc) : transfer;
format->pixel_range = (desc->flags & AV_PIX_FMT_FLAG_RGB) ? ZIMG_RANGE_FULL : range == -1 ? convert_range(frame->color_range) : range;
format->chroma_location = location == -1 ? convert_chroma_location(frame->chroma_location) : location;
+ if (desc->flags & AV_PIX_FMT_FLAG_ALPHA)
+ format->alpha = frame->alpha_mode == AVALPHA_MODE_PREMULTIPLIED ? ZIMG_ALPHA_PREMULTIPLIED : ZIMG_ALPHA_STRAIGHT;
}
static int graphs_build(AVFrame *in, AVFrame *out, const AVPixFmtDescriptor *desc, const AVPixFmtDescriptor *out_desc,
@@ -604,8 +601,6 @@ static int graphs_build(AVFrame *in, AVFrame *out, const AVPixFmtDescriptor *des
size_t size;
zimg_image_format src_format;
zimg_image_format dst_format;
- zimg_image_format alpha_src_format;
- zimg_image_format alpha_dst_format;
const double in_slice_start = s->in_slice_start[job_nr];
const double in_slice_end = s->in_slice_end[job_nr];
const int out_slice_start = s->out_slice_start[job_nr];
@@ -644,26 +639,6 @@ static int graphs_build(AVFrame *in, AVFrame *out, const AVPixFmtDescriptor *des
if (!s->tmp[job_nr])
return AVERROR(ENOMEM);
- if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && out_desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
- alpha_src_format = s->alpha_src_format;
- alpha_dst_format = s->alpha_dst_format;
- /* The input slice is specified through the active_region field, unlike the output slice.
- according to zimg requirements input and output slices should have even dimensions */
- alpha_src_format.active_region.width = in->width;
- alpha_src_format.active_region.height = in_slice_end - in_slice_start;
- alpha_src_format.active_region.left = 0;
- alpha_src_format.active_region.top = in_slice_start;
- //dst now is the single tile only!!
- alpha_dst_format.width = out->width;
- alpha_dst_format.height = out_slice_end - out_slice_start;
-
- if (s->alpha_graph[job_nr]) {
- zimg_filter_graph_free(s->alpha_graph[job_nr]);
- }
- s->alpha_graph[job_nr] = zimg_filter_graph_build(&alpha_src_format, &alpha_dst_format, &s->alpha_params);
- if (!s->alpha_graph[job_nr])
- return print_zimg_error(ctx);
- }
return 0;
}
@@ -726,17 +701,13 @@ static int filter_slice(AVFilterContext *ctx, void *data, int job_nr, int n_jobs
need_gb = compare_zimg_image_formats(&s->src_format, &s->src_format_tmp) ||
compare_zimg_image_formats(&s->dst_format, &s->dst_format_tmp) ||
compare_zimg_graph_builder_params(&s->params, &s->params_tmp);
- if(td->desc->flags & AV_PIX_FMT_FLAG_ALPHA && td->odesc->flags & AV_PIX_FMT_FLAG_ALPHA)
- need_gb = need_gb || compare_zimg_image_formats(&s->alpha_src_format, &s->alpha_src_format_tmp) ||
- compare_zimg_image_formats(&s->alpha_dst_format, &s->alpha_dst_format_tmp) ||
- compare_zimg_graph_builder_params(&s->alpha_params, &s->alpha_params_tmp);
if (need_gb){
ret = graphs_build(td->in, td->out, td->desc, td->odesc, ctx, job_nr, n_jobs);
if (ret < 0)
return print_zimg_error(ctx);
}
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 4; i++) {
const int vsamp = i >= 1 ? td->odesc->log2_chroma_h : 0;
p = td->desc->comp[i].plane;
@@ -762,23 +733,6 @@ static int filter_slice(AVFilterContext *ctx, void *data, int job_nr, int n_jobs
if (ret)
return print_zimg_error(ctx);
- if (td->desc->flags & AV_PIX_FMT_FLAG_ALPHA && td->odesc->flags & AV_PIX_FMT_FLAG_ALPHA) {
- src_buf.plane[0].data = td->in->data[3];
- src_buf.plane[0].stride = td->in->linesize[3];
- src_buf.plane[0].mask = -1;
-
- dst_buf.plane[0].data = td->out->data[3] + td->out->linesize[3] * out_slice_start;
- dst_buf.plane[0].stride = td->out->linesize[3];
- dst_buf.plane[0].mask = -1;
-
- if (!s->alpha_graph[job_nr])
- return AVERROR(EINVAL);
- ret = zimg_filter_graph_process(s->alpha_graph[job_nr], &src_buf, &dst_buf,
- (uint8_t *)FFALIGN((uintptr_t)s->tmp[job_nr], ZIMG_ALIGNMENT),
- 0, 0, 0, 0);
- if (ret)
- return print_zimg_error(ctx);
- }
return 0;
}
@@ -858,28 +812,6 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
s->params.filter_param_a = s->params.filter_param_a_uv = s->param_a;
s->params.filter_param_b = s->params.filter_param_b_uv = s->param_b;
- if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) {
- zimg_image_format_default(&s->alpha_src_format, ZIMG_API_VERSION);
- zimg_image_format_default(&s->alpha_dst_format, ZIMG_API_VERSION);
- zimg_graph_builder_params_default(&s->alpha_params, ZIMG_API_VERSION);
-
- s->alpha_params.dither_type = s->dither;
- s->alpha_params.cpu_type = ZIMG_CPU_AUTO_64B;
- s->alpha_params.resample_filter = s->filter;
-
- s->alpha_src_format.width = in->width;
- s->alpha_src_format.height = in->height;
- s->alpha_src_format.depth = desc->comp[0].depth;
- s->alpha_src_format.pixel_type = (desc->flags & AV_PIX_FMT_FLAG_FLOAT) ? (desc->comp[0].depth > 16 ? ZIMG_PIXEL_FLOAT : ZIMG_PIXEL_HALF)
- : (desc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE);
- s->alpha_src_format.color_family = ZIMG_COLOR_GREY;
-
- s->alpha_dst_format.depth = odesc->comp[0].depth;
- s->alpha_dst_format.pixel_type = (odesc->flags & AV_PIX_FMT_FLAG_FLOAT) ? (odesc->comp[0].depth > 16 ? ZIMG_PIXEL_FLOAT : ZIMG_PIXEL_HALF)
- : (odesc->comp[0].depth > 8 ? ZIMG_PIXEL_WORD : ZIMG_PIXEL_BYTE);
- s->alpha_dst_format.color_family = ZIMG_COLOR_GREY;
- }
-
update_output_color_information(s, out);
av_reduce(&out->sample_aspect_ratio.num, &out->sample_aspect_ratio.den,
(int64_t)in->sample_aspect_ratio.num * outlink->h * link->w,
@@ -911,11 +843,6 @@ static int filter_frame(AVFilterLink *link, AVFrame *in)
s->src_format_tmp = s->src_format;
s->dst_format_tmp = s->dst_format;
s->params_tmp = s->params;
- if (desc->flags & AV_PIX_FMT_FLAG_ALPHA && odesc->flags & AV_PIX_FMT_FLAG_ALPHA) {
- s->alpha_src_format_tmp = s->alpha_src_format;
- s->alpha_dst_format_tmp = s->alpha_dst_format;
- s->alpha_params_tmp = s->alpha_params;
- }
if ((!(desc->flags & AV_PIX_FMT_FLAG_ALPHA)) && (odesc->flags & AV_PIX_FMT_FLAG_ALPHA) ){
int x, y;
@@ -969,10 +896,6 @@ static av_cold void uninit(AVFilterContext *ctx)
zimg_filter_graph_free(s->graph[i]);
s->graph[i] = NULL;
}
- if (s->alpha_graph[i]) {
- zimg_filter_graph_free(s->alpha_graph[i]);
- s->alpha_graph[i] = NULL;
- }
}
}
commit c7adeb75ac94efd41e08d3cd928a0d4468b820f8
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Thu Aug 14 18:32:23 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_scale: require straight alpha for alpha blending
Fortunately, we only care if this flag is set - otherwise, this filter is
alpha mode agnostic (since it is purely scaling, etc).
That said, there is an argument to be made that we should prefer premul
alpha when scaling, because scaling in straight alpha will leak garbage
pixels; but I think that would be a too backwards-incompatible change to
be worth thinking about at this time.
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index 33212a47c0..c0cd1b96c6 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -520,6 +520,12 @@ static int query_formats(const AVFilterContext *ctx,
if ((ret = ff_formats_ref(formats, &cfg_out[0]->color_ranges)) < 0)
return ret;
+ if (scale->sws->alpha_blend) {
+ if ((ret = ff_formats_ref(ff_make_formats_list_singleton(AVALPHA_MODE_STRAIGHT),
+ &cfg_in[0]->alpha_modes)) < 0)
+ return ret;
+ }
+
return 0;
}
commit 446a25b70f340960b9f0df598ae704e64bd68d32
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Thu Aug 14 17:38:36 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter: add alpha_mode consistency assertion
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index f9b64810b8..169c2baa42 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -1081,6 +1081,8 @@ int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
av_assert1(frame->format == link->format);
av_assert1(frame->width == link->w);
av_assert1(frame->height == link->h);
+ if (av_pix_fmt_desc_get(link->format)->flags & AV_PIX_FMT_FLAG_ALPHA)
+ av_assert1(frame->alpha_mode == link->alpha_mode);
}
frame->sample_aspect_ratio = link->sample_aspect_ratio;
commit 39631c99d4dff0185638e7f16f97732808d08718
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:45:51 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/drawutils: add alpha mode support
This allows drawing colors onto images with premultiplied alpha, by first
premultiplying the specified RGBA values.
diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c
index f7e3adf9e8..75bf8f4755 100644
--- a/libavfilter/drawutils.c
+++ b/libavfilter/drawutils.c
@@ -94,7 +94,7 @@ int ff_fill_ayuv_map(uint8_t *ayuv_map, enum AVPixelFormat pix_fmt)
}
int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp,
- enum AVColorRange range, unsigned flags)
+ enum AVColorRange range, enum AVAlphaMode alpha, unsigned flags)
{
const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(format);
const AVLumaCoefficients *luma = NULL;
@@ -155,6 +155,7 @@ int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSp
draw->nb_planes = nb_planes;
draw->range = range;
draw->csp = csp;
+ draw->alpha = alpha;
draw->flags = flags;
if (luma)
ff_fill_rgb2yuv_table(luma, draw->rgb2yuv);
@@ -167,12 +168,12 @@ int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSp
int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link,
unsigned flags)
{
- return ff_draw_init2(draw, link->format, link->colorspace, link->color_range, flags);
+ return ff_draw_init2(draw, link->format, link->colorspace, link->color_range, link->alpha_mode, flags);
}
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
{
- return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, flags);
+ return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, AVALPHA_MODE_UNSPECIFIED, flags);
}
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
@@ -189,6 +190,11 @@ void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4
for (int i = 0; i < 4; i++)
rgbad[i] = color->rgba[i] / 255.;
+ if (draw->alpha == AVALPHA_MODE_PREMULTIPLIED) {
+ for (int i = 0; i < 3; i++)
+ rgbad[i] *= rgbad[3];
+ }
+
if (draw->desc->flags & AV_PIX_FMT_FLAG_RGB)
memcpy(yuvad, rgbad, sizeof(double) * 3);
else
diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h
index c68a78e84b..a7fc967a85 100644
--- a/libavfilter/drawutils.h
+++ b/libavfilter/drawutils.h
@@ -45,6 +45,7 @@ typedef struct FFDrawContext {
enum AVColorRange range;
unsigned flags;
enum AVColorSpace csp;
+ enum AVAlphaMode alpha;
double rgb2yuv[3][3];
} FFDrawContext;
@@ -78,7 +79,7 @@ typedef struct FFDrawColor {
* @return 0 for success, < 0 for error
*/
int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp,
- enum AVColorRange range, unsigned flags);
+ enum AVColorRange range, enum AVAlphaMode alpha, unsigned flags);
/**
* Init a draw context, taking the format, colorspace and range from the given
diff --git a/libavfilter/vf_subtitles.c b/libavfilter/vf_subtitles.c
index cf23b7822a..dde45357ce 100644
--- a/libavfilter/vf_subtitles.c
+++ b/libavfilter/vf_subtitles.c
@@ -189,7 +189,7 @@ static int config_input(AVFilterLink *inlink)
ret = ff_draw_init2(&ass->draw, inlink->format,
ass_get_color_space(ass->track->YCbCrMatrix, inlink->colorspace),
ass_get_color_range(ass->track->YCbCrMatrix, inlink->color_range),
- ass->alpha ? FF_DRAW_PROCESS_ALPHA : 0);
+ inlink->alpha_mode, ass->alpha ? FF_DRAW_PROCESS_ALPHA : 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
commit a90e8f1c1d1a6a9c4552605a3b98220c51d08f37
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:43:35 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter: use ff_draw_init_from_link() where possible
diff --git a/libavfilter/qrencode.c b/libavfilter/qrencode.c
index 8c09b605ad..29fa5d3785 100644
--- a/libavfilter/qrencode.c
+++ b/libavfilter/qrencode.c
@@ -645,7 +645,7 @@ static int qrencodesrc_config_props(AVFilterLink *outlink)
ff_draw_color(&qr->draw, &qr->draw_foreground_color, (const uint8_t *)&qr->foreground_color);
ff_draw_color(&qr->draw, &qr->draw_background_color, (const uint8_t *)&qr->background_color);
- ret = ff_draw_init2(&qr->draw0, outlink->format, outlink->colorspace, outlink->color_range, FF_DRAW_PROCESS_ALPHA);
+ ret = ff_draw_init_from_link(&qr->draw0, outlink, FF_DRAW_PROCESS_ALPHA);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
@@ -743,8 +743,7 @@ static int qrencode_config_input(AVFilterLink *inlink)
qr->is_source = 0;
- ret = ff_draw_init2(&qr->draw, inlink->format, inlink->colorspace, inlink->color_range,
- FF_DRAW_PROCESS_ALPHA);
+ ret = ff_draw_init_from_link(&qr->draw, inlink, FF_DRAW_PROCESS_ALPHA);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
@@ -777,8 +776,7 @@ static int qrencode_config_input(AVFilterLink *inlink)
PARSE_EXPR(rendered_qrcode_width);
PARSE_EXPR(rendered_padded_qrcode_width);
- ret = ff_draw_init2(&qr->draw, inlink->format, inlink->colorspace, inlink->color_range,
- FF_DRAW_PROCESS_ALPHA);
+ ret = ff_draw_init_from_link(&qr->draw, inlink, FF_DRAW_PROCESS_ALPHA);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/src_avsynctest.c b/libavfilter/src_avsynctest.c
index 9c71a9fee8..e2c66fd6be 100644
--- a/libavfilter/src_avsynctest.c
+++ b/libavfilter/src_avsynctest.c
@@ -161,7 +161,7 @@ static av_cold int config_props(AVFilterLink *outlink)
s->dir = 1;
s->prev_intpart = INT64_MIN;
- ret = ff_draw_init2(&s->draw, outlink->format, outlink->colorspace, outlink->color_range, 0);
+ ret = ff_draw_init_from_link(&s->draw, outlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_datascope.c b/libavfilter/vf_datascope.c
index 87137cee83..3b37fd162e 100644
--- a/libavfilter/vf_datascope.c
+++ b/libavfilter/vf_datascope.c
@@ -390,7 +390,7 @@ static int config_input(AVFilterLink *inlink)
int ret;
s->nb_planes = av_pix_fmt_count_planes(inlink->format);
- ret = ff_draw_init2(&s->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&s->draw, inlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_drawtext.c b/libavfilter/vf_drawtext.c
index c2f6f52f43..867536aa61 100644
--- a/libavfilter/vf_drawtext.c
+++ b/libavfilter/vf_drawtext.c
@@ -1144,7 +1144,7 @@ static int config_input(AVFilterLink *inlink)
char *expr;
int ret;
- ret = ff_draw_init2(&s->dc, inlink->format, inlink->colorspace, inlink->color_range, FF_DRAW_PROCESS_ALPHA);
+ ret = ff_draw_init_from_link(&s->dc, inlink, FF_DRAW_PROCESS_ALPHA);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_pad.c b/libavfilter/vf_pad.c
index 0c7a1d2b44..8348043e1a 100644
--- a/libavfilter/vf_pad.c
+++ b/libavfilter/vf_pad.c
@@ -114,7 +114,7 @@ static int config_input(AVFilterLink *inlink)
double var_values[VARS_NB], res;
char *expr;
- ret = ff_draw_init2(&s->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&s->draw, inlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_rotate.c b/libavfilter/vf_rotate.c
index 3dc57bbb08..740acfe3bd 100644
--- a/libavfilter/vf_rotate.c
+++ b/libavfilter/vf_rotate.c
@@ -288,7 +288,7 @@ static int config_props(AVFilterLink *outlink)
double res;
char *expr;
- ret = ff_draw_init2(&rot->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&rot->draw, inlink, 0);
if (ret < 0)
return ret;
ff_draw_color(&rot->draw, &rot->color, rot->fillcolor);
diff --git a/libavfilter/vf_shear.c b/libavfilter/vf_shear.c
index 2e558c0044..11edd1063d 100644
--- a/libavfilter/vf_shear.c
+++ b/libavfilter/vf_shear.c
@@ -261,7 +261,7 @@ static int config_output(AVFilterLink *outlink)
s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(ctx->inputs[0]->h, desc->log2_chroma_h);
s->planeheight[0] = s->planeheight[3] = ctx->inputs[0]->h;
- ret = ff_draw_init2(&s->draw, outlink->format, outlink->colorspace, outlink->color_range, 0);
+ ret = ff_draw_init_from_link(&s->draw, outlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_stack.c b/libavfilter/vf_stack.c
index fa202ee0cc..a36e1bab64 100644
--- a/libavfilter/vf_stack.c
+++ b/libavfilter/vf_stack.c
@@ -312,7 +312,7 @@ static int config_output(AVFilterLink *outlink)
if (s->fillcolor_enable) {
const AVFilterLink *inlink = ctx->inputs[0];
- ret = ff_draw_init2(&s->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&s->draw, inlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_tile.c b/libavfilter/vf_tile.c
index 7f2f212c4a..8c87b44af8 100644
--- a/libavfilter/vf_tile.c
+++ b/libavfilter/vf_tile.c
@@ -144,7 +144,7 @@ static int config_props(AVFilterLink *outlink)
outlink->h = tile->h * inlink->h + total_margin_h;
outlink->sample_aspect_ratio = inlink->sample_aspect_ratio;
ol->frame_rate = av_mul_q(il->frame_rate, av_make_q(1, tile->nb_frames - tile->overlap));
- ret = ff_draw_init2(&tile->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&tile->draw, inlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_tinterlace.c b/libavfilter/vf_tinterlace.c
index ad02ba4405..7d5217c364 100644
--- a/libavfilter/vf_tinterlace.c
+++ b/libavfilter/vf_tinterlace.c
@@ -228,7 +228,7 @@ static int config_out_props(AVFilterLink *outlink)
if (tinterlace->mode == MODE_PAD) {
uint8_t black[4] = { 0, 0, 0, 16 };
- ret = ff_draw_init2(&tinterlace->draw, outlink->format, outlink->colorspace, outlink->color_range, 0);
+ ret = ff_draw_init_from_link(&tinterlace->draw, outlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vf_tpad.c b/libavfilter/vf_tpad.c
index f498bf4a3e..7580fbaa5b 100644
--- a/libavfilter/vf_tpad.c
+++ b/libavfilter/vf_tpad.c
@@ -209,7 +209,7 @@ static int config_input(AVFilterLink *inlink)
int ret;
if (needs_drawing(s)) {
- ret = ff_draw_init2(&s->draw, inlink->format, inlink->colorspace, inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&s->draw, inlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
diff --git a/libavfilter/vsrc_testsrc.c b/libavfilter/vsrc_testsrc.c
index 81301edbfe..23ecb5bdb2 100644
--- a/libavfilter/vsrc_testsrc.c
+++ b/libavfilter/vsrc_testsrc.c
@@ -257,8 +257,7 @@ static int color_config_props(AVFilterLink *inlink)
TestSourceContext *test = ctx->priv;
int ret;
- ret = ff_draw_init2(&test->draw, inlink->format, inlink->colorspace,
- inlink->color_range, 0);
+ ret = ff_draw_init_from_link(&test->draw, inlink, 0);
if (ret < 0) {
av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
return ret;
@@ -941,8 +940,7 @@ static int test2_config_props(AVFilterLink *inlink)
AVFilterContext *ctx = inlink->src;
TestSourceContext *s = ctx->priv;
- av_assert0(ff_draw_init2(&s->draw, inlink->format, inlink->colorspace,
- inlink->color_range, 0) >= 0);
+ av_assert0(ff_draw_init_from_link(&s->draw, inlink, 0) >= 0);
s->w = ff_draw_round_to_sub(&s->draw, 0, -1, s->w);
s->h = ff_draw_round_to_sub(&s->draw, 1, -1, s->h);
if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
@@ -2022,8 +2020,7 @@ static int colorchart_config_props(AVFilterLink *inlink)
AVFilterContext *ctx = inlink->src;
TestSourceContext *s = ctx->priv;
- av_assert0(ff_draw_init2(&s->draw, inlink->format, inlink->colorspace,
- inlink->color_range, 0) >= 0);
+ av_assert0(ff_draw_init_from_link(&s->draw, inlink, 0) >= 0);
if (av_image_check_size(s->w, s->h, 0, ctx) < 0)
return AVERROR(EINVAL);
return config_props(inlink);
commit eddbdc8b7c70c562ff90c62c31070ce92a296233
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:39:16 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/drawutils: add ff_draw_init_from_link()
The overwhelming majority of references to ff_draw_init2() just set the
colorspace properties from a filter link. This wrapper allows us to update
all such referencen automatically.
diff --git a/libavfilter/drawutils.c b/libavfilter/drawutils.c
index 6f7dca021b..f7e3adf9e8 100644
--- a/libavfilter/drawutils.c
+++ b/libavfilter/drawutils.c
@@ -164,6 +164,12 @@ int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSp
return 0;
}
+int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link,
+ unsigned flags)
+{
+ return ff_draw_init2(draw, link->format, link->colorspace, link->color_range, flags);
+}
+
int ff_draw_init(FFDrawContext *draw, enum AVPixelFormat format, unsigned flags)
{
return ff_draw_init2(draw, format, AVCOL_SPC_UNSPECIFIED, AVCOL_RANGE_UNSPECIFIED, flags);
diff --git a/libavfilter/drawutils.h b/libavfilter/drawutils.h
index f4903d1a86..c68a78e84b 100644
--- a/libavfilter/drawutils.h
+++ b/libavfilter/drawutils.h
@@ -80,6 +80,13 @@ typedef struct FFDrawColor {
int ff_draw_init2(FFDrawContext *draw, enum AVPixelFormat format, enum AVColorSpace csp,
enum AVColorRange range, unsigned flags);
+/**
+ * Init a draw context, taking the format, colorspace and range from the given
+ * filter link.
+ */
+int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link,
+ unsigned flags);
+
/*
* Legacy wrapper for ff_draw_init2.
*/
commit d05484757a3dca825642234bdefc639bdfb0c5b8
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:29:32 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_fade: set correct alpha mode requirement
Fading to black in non-alpha mode works for either straight or premultiplied
alpha, but fading to a color does not.
diff --git a/libavfilter/vf_fade.c b/libavfilter/vf_fade.c
index 69198ea1d1..794586af07 100644
--- a/libavfilter/vf_fade.c
+++ b/libavfilter/vf_fade.c
@@ -151,19 +151,36 @@ static int query_formats(const AVFilterContext *ctx,
AV_PIX_FMT_GBRAP,
AV_PIX_FMT_NONE
};
+ const static int straight_alpha[] = {
+ AVALPHA_MODE_UNSPECIFIED,
+ AVALPHA_MODE_STRAIGHT,
+ -1,
+ };
const enum AVPixelFormat *pixel_fmts;
+ int need_straight = 0;
+ int ret;
if (s->alpha) {
if (s->black_fade)
pixel_fmts = pix_fmts_alpha;
else
pixel_fmts = pix_fmts_rgba;
+ need_straight = 1;
} else {
if (s->black_fade)
pixel_fmts = pix_fmts;
- else
+ else {
pixel_fmts = pix_fmts_rgb;
+ need_straight = 1;
+ }
}
+
+ if (need_straight) {
+ ret = ff_set_common_alpha_modes_from_list2(ctx, cfg_in, cfg_out, straight_alpha);
+ if (ret < 0)
+ return ret;
+ }
+
return ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out, pixel_fmts);
}
commit ba8aa0e7b383d88624e8513e69a944fc5cb9de8d
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:16:38 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/x86/vf_overlay: simplify function signature
No reason to pass all the variables again, if we're already passing the
context.
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index a2419a60e9..673c92d6af 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -836,7 +836,7 @@ static int init_slice_fn(AVFilterContext *ctx)
}
#if ARCH_X86
- ff_overlay_init_x86(s, s->format, main->format, overlay->alpha_mode, s->main_has_alpha);
+ ff_overlay_init_x86(ctx);
#endif
return 0;
diff --git a/libavfilter/vf_overlay.h b/libavfilter/vf_overlay.h
index e4ba956fe7..22e84362b7 100644
--- a/libavfilter/vf_overlay.h
+++ b/libavfilter/vf_overlay.h
@@ -82,7 +82,6 @@ typedef struct OverlayContext {
int (*blend_slice)(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
} OverlayContext;
-void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
- enum AVAlphaMode overlay_alpha, int main_has_alpha);
+void ff_overlay_init_x86(AVFilterContext *ctx);
#endif /* AVFILTER_OVERLAY_H */
diff --git a/libavfilter/x86/vf_overlay_init.c b/libavfilter/x86/vf_overlay_init.c
index 30cfe2cbe8..d1686505f8 100644
--- a/libavfilter/x86/vf_overlay_init.c
+++ b/libavfilter/x86/vf_overlay_init.c
@@ -32,32 +32,35 @@ int ff_overlay_row_20_sse4(uint8_t *d, uint8_t *da, uint8_t *s, uint8_t *a,
int ff_overlay_row_22_sse4(uint8_t *d, uint8_t *da, uint8_t *s, uint8_t *a,
int w, ptrdiff_t alinesize);
-av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
- enum AVAlphaMode overlay_alpha, int main_has_alpha)
+av_cold void ff_overlay_init_x86(AVFilterContext *ctx)
{
+ OverlayContext *s = ctx->priv;
+ const AVFilterLink *main = ctx->inputs[0];
+ const AVFilterLink *overlay = ctx->inputs[0];
int cpu_flags = av_get_cpu_flags();
+ int main_has_alpha = s->main_has_alpha;
if (EXTERNAL_SSE4(cpu_flags) &&
- (format == OVERLAY_FORMAT_YUV444 ||
- format == OVERLAY_FORMAT_GBRP) &&
- overlay_alpha != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
+ (s->format == OVERLAY_FORMAT_YUV444 ||
+ s->format == OVERLAY_FORMAT_GBRP) &&
+ overlay->alpha_mode != AVALPHA_MODE_PREMULTIPLIED && !main_has_alpha) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_44_sse4;
s->blend_row[2] = ff_overlay_row_44_sse4;
}
if (EXTERNAL_SSE4(cpu_flags) &&
- (pix_format == AV_PIX_FMT_YUV420P) &&
- (format == OVERLAY_FORMAT_YUV420) &&
- overlay_alpha != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
+ (main->format == AV_PIX_FMT_YUV420P) &&
+ (s->format == OVERLAY_FORMAT_YUV420) &&
+ overlay->alpha_mode != AVALPHA_MODE_PREMULTIPLIED && !main_has_alpha) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_20_sse4;
s->blend_row[2] = ff_overlay_row_20_sse4;
}
if (EXTERNAL_SSE4(cpu_flags) &&
- (format == OVERLAY_FORMAT_YUV422) &&
- overlay_alpha != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
+ (s->format == OVERLAY_FORMAT_YUV422) &&
+ overlay->alpha_mode != AVALPHA_MODE_PREMULTIPLIED && !main_has_alpha) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_22_sse4;
s->blend_row[2] = ff_overlay_row_22_sse4;
commit 59bb51a8f2a6fa336dbbd136bdcac230f7ba58ec
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:13:38 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_overlay: support premultiplied base layers
Conceptually, these are pretty simple to handle, since they are basically
equivalent to the case of alpha being absent, since the only thing the
destination alpha plane is used for is unpremultiplyng straight alpha.
For planar formats, the total number of cases doesn't change in principle,
since before this patch we have:
- alpha present, overlay straight
- alpha present, overlay premultiplied
- alpha absent, overlay straight
- alpha absent, overlay premultiplied
And now we have:
- main straight, overlay straight
- main straight, overlay premultiplied
- main premultiplied, overlay straight
- main premultiplied, overlay premultiplied
That said, we do gain some cases now that we used to (incorrectly) ignore,
like premultiplied yuva420p10.
Notably, we can skip defining separate functions for the case of main alpha
being absent, since that can be a single cheap branch inside the function
itself, on whether or not to also process the alpha plane. Otherwise, as long
as we treat "alpha absent" as "main premultiplied", the per-plane logic will
skip touching the nonexistent alpha plane.
The only format that actually needs extra cases is packed rgb, but that's only
two additional cases in total.
Also arguably simplifies the assignment logic massively.
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index 369cb33516..a2419a60e9 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -358,6 +358,7 @@ static int config_output(AVFilterLink *outlink)
// alpha = alpha_overlay / ( (alpha_main + alpha_overlay) - (alpha_main * alpha_overlay) )
// (((x) << 16) - ((x) << 9) + (x)) is a faster version of: 255 * 255 * x
// ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)) is a faster version of: 255 * (x + y)
+// this is only needed when blending onto straight alpha main images
#define UNPREMULTIPLY_ALPHA(x, y) ((((x) << 16) - ((x) << 9) + (x)) / ((((x) + (y)) << 8) - ((x) + (y)) - (y) * (x)))
#define PTR_ADD(TYPE, ptr, byte_addend) ((TYPE*)((uint8_t*)ptr + (byte_addend)))
@@ -370,7 +371,8 @@ static int config_output(AVFilterLink *outlink)
static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
AVFrame *dst, const AVFrame *src,
int main_has_alpha, int x, int y,
- int overlay_straight, int jobnr, int nb_jobs)
+ int overlay_straight, int main_straight,
+ int jobnr, int nb_jobs)
{
OverlayContext *s = ctx->priv;
int i, imax, j, jmax;
@@ -411,7 +413,7 @@ static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
// if the main channel has an alpha channel, alpha has to be calculated
// to create an un-premultiplied (straight) alpha value
- if (main_has_alpha && alpha != 0 && alpha != 255) {
+ if (main_straight && alpha != 0 && alpha != 255) {
uint8_t alpha_d = d[da];
alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d);
}
@@ -461,7 +463,7 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
int dst_w, int dst_h, \
int i, int hsub, int vsub, \
int x, int y, \
- int main_has_alpha, \
+ int main_straight, \
int dst_plane, \
int dst_offset, \
int dst_step, \
@@ -490,13 +492,13 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
+ (yp + slice_start) * dst->linesize[dst_plane] \
+ dst_offset; \
const uint8_t *ap = src->data[3] + (slice_start << vsub) * src->linesize[3]; \
- const uint8_t *dap = main_has_alpha ? dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3] : NULL; \
+ const uint8_t *dap = main_straight ? dst->data[3] + ((yp + slice_start) << vsub) * dst->linesize[3] : NULL; \
\
for (int j = slice_start; j < slice_end; ++j) { \
int k = kmin; \
const T *s = (const T *)sp + k; \
const T *a = (const T *)ap + (k << hsub); \
- const T *da = main_has_alpha ? (T *)dap + ((xp + k) << hsub) : NULL; \
+ const T *da = main_straight ? (T *)dap + ((xp + k) << hsub) : NULL; \
T *d = (T *)(dp + (xp + k) * dst_step); \
\
if (nbits == 8 && ((vsub && j+1 < src_hp) || !vsub) && octx->blend_row[i]) { \
@@ -505,7 +507,7 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
\
s += c; \
d = PTR_ADD(T, d, dst_step * c); \
- if (main_has_alpha) \
+ if (main_straight) \
da += (1 << hsub) * c; \
a += (1 << hsub) * c; \
k += c; \
@@ -528,7 +530,7 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
alpha = a[0]; \
/* if the main channel has an alpha channel, alpha has to be calculated */ \
/* to create an un-premultiplied (straight) alpha value */ \
- if (main_has_alpha && alpha != 0 && alpha != max) { \
+ if (main_straight && alpha != 0 && alpha != max) { \
/* average alpha for color components, improve quality */ \
uint8_t alpha_d; \
if (hsub && vsub && j+1 < src_hp && k+1 < src_wp) { \
@@ -566,14 +568,14 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
} \
s++; \
d = PTR_ADD(T, d, dst_step); \
- if (main_has_alpha) \
+ if (main_straight) \
da += 1 << hsub; \
a += 1 << hsub; \
} \
dp += dst->linesize[dst_plane]; \
sp += src->linesize[i]; \
ap += (1 << vsub) * src->linesize[3]; \
- if (main_has_alpha) \
+ if (main_straight) \
dap += (1 << vsub) * dst->linesize[3]; \
} \
}
@@ -584,7 +586,7 @@ DEFINE_BLEND_PLANE(16, uint16_t, 10)
static inline void alpha_composite_##depth##_##nbits##bits(const AVFrame *src, const AVFrame *dst, \
int src_w, int src_h, \
int dst_w, int dst_h, \
- int x, int y, \
+ int x, int y, int main_straight, \
int jobnr, int nb_jobs) \
{ \
T alpha; /* the amount of overlay to blend on to main */ \
@@ -604,7 +606,7 @@ static inline void alpha_composite_##depth##_##nbits##bits(const AVFrame *src, c
\
for (int j = jmin; j < jmax; ++j) { \
alpha = *s; \
- if (alpha != 0 && alpha != max) { \
+ if (main_straight && alpha != 0 && alpha != max) { \
uint8_t alpha_d = *d; \
alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); \
} \
@@ -631,7 +633,7 @@ DEFINE_ALPHA_COMPOSITE(16, uint16_t, 10)
static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterContext *ctx, \
AVFrame *dst, const AVFrame *src, \
int hsub, int vsub, \
- int main_has_alpha, \
+ int main_straight, \
int x, int y, \
int overlay_straight, \
int jobnr, int nb_jobs) \
@@ -643,17 +645,17 @@ static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterCon
const int dst_h = dst->height; \
\
blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, \
- x, y, main_has_alpha, s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, \
+ x, y, main_straight, s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, \
s->main_desc->comp[0].step, overlay_straight, 1, jobnr, nb_jobs); \
blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, \
- x, y, main_has_alpha, s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, \
+ x, y, main_straight, s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, \
s->main_desc->comp[1].step, overlay_straight, 1, jobnr, nb_jobs); \
blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, \
- x, y, main_has_alpha, s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, \
+ x, y, main_straight, s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, \
s->main_desc->comp[2].step, overlay_straight, 1, jobnr, nb_jobs); \
\
- if (main_has_alpha) \
- alpha_composite_##depth##_##nbits##bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, \
+ if (s->main_has_alpha) \
+ alpha_composite_##depth##_##nbits##bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, main_straight, \
jobnr, nb_jobs); \
}
DEFINE_BLEND_SLICE_YUV(8, 8)
@@ -662,7 +664,7 @@ DEFINE_BLEND_SLICE_YUV(16, 10)
static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx,
AVFrame *dst, const AVFrame *src,
int hsub, int vsub,
- int main_has_alpha,
+ int main_straight,
int x, int y,
int overlay_straight,
int jobnr,
@@ -674,73 +676,68 @@ static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx,
const int dst_w = dst->width;
const int dst_h = dst->height;
- blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha,
+ blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_straight,
s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, overlay_straight, 0,
jobnr, nb_jobs);
- blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha,
+ blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_straight,
s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, overlay_straight, 0,
jobnr, nb_jobs);
- blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha,
+ blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_straight,
s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, overlay_straight, 0,
jobnr, nb_jobs);
- if (main_has_alpha)
- alpha_composite_8_8bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, jobnr, nb_jobs);
+ if (s->main_has_alpha)
+ alpha_composite_8_8bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, main_straight, jobnr, nb_jobs);
}
-#define DEFINE_BLEND_SLICE_PLANAR_FMT(format_, blend_slice_fn_suffix_, hsub_, vsub_, main_has_alpha_, direct_) \
+#define DEFINE_BLEND_SLICE_PLANAR_FMT_(format_, blend_slice_fn_suffix_, hsub_, vsub_, main_straight_, overlay_straight_) \
static int blend_slice_##format_(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
{ \
OverlayContext *s = ctx->priv; \
ThreadData *td = arg; \
blend_slice_##blend_slice_fn_suffix_(ctx, td->dst, td->src, \
- hsub_, vsub_, main_has_alpha_, \
- s->x, s->y, direct_, \
+ hsub_, vsub_, main_straight_, \
+ s->x, s->y, overlay_straight_, \
jobnr, nb_jobs); \
return 0; \
}
-// FMT FN H V A D
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv420, yuv_8_8bits, 1, 1, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva420, yuv_8_8bits, 1, 1, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv420p10, yuv_16_10bits, 1, 1, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva420p10, yuv_16_10bits, 1, 1, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv422p10, yuv_16_10bits, 1, 0, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva422p10, yuv_16_10bits, 1, 0, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv422, yuv_8_8bits, 1, 0, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva422, yuv_8_8bits, 1, 0, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv444, yuv_8_8bits, 0, 0, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva444, yuv_8_8bits, 0, 0, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv444p10, yuv_16_10bits, 0, 0, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva444p10, yuv_16_10bits, 0, 0, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(gbrp, planar_rgb, 0, 0, 0, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(gbrap, planar_rgb, 0, 0, 1, 1)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv420_pm, yuv_8_8bits, 1, 1, 0, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva420_pm, yuv_8_8bits, 1, 1, 1, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv422_pm, yuv_8_8bits, 1, 0, 0, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva422_pm, yuv_8_8bits, 1, 0, 1, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuv444_pm, yuv_8_8bits, 0, 0, 0, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(yuva444_pm, yuv_8_8bits, 0, 0, 1, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(gbrp_pm, planar_rgb, 0, 0, 0, 0)
-DEFINE_BLEND_SLICE_PLANAR_FMT(gbrap_pm, planar_rgb, 0, 0, 1, 0)
-
-#define DEFINE_BLEND_SLICE_PACKED_FMT(format_, blend_slice_fn_suffix_, main_has_alpha_, direct_) \
+#define DEFINE_BLEND_SLICE_PLANAR_FMT(format_, blend_slice_fn_suffix_, hsub_, vsub_) \
+DEFINE_BLEND_SLICE_PLANAR_FMT_(format_ ## _ss, blend_slice_fn_suffix_, hsub_, vsub_, 1, 1) \
+DEFINE_BLEND_SLICE_PLANAR_FMT_(format_ ## _sp, blend_slice_fn_suffix_, hsub_, vsub_, 1, 0) \
+DEFINE_BLEND_SLICE_PLANAR_FMT_(format_ ## _ps, blend_slice_fn_suffix_, hsub_, vsub_, 0, 1) \
+DEFINE_BLEND_SLICE_PLANAR_FMT_(format_ ## _pp, blend_slice_fn_suffix_, hsub_, vsub_, 0, 0)
+
+// FMT FN H V
+DEFINE_BLEND_SLICE_PLANAR_FMT(yuv420, yuv_8_8bits, 1, 1)
+DEFINE_BLEND_SLICE_PLANAR_FMT(yuv420p10, yuv_16_10bits, 1, 1)
+DEFINE_BLEND_SLICE_PLANAR_FMT(yuv422p10, yuv_16_10bits, 1, 0)
+DEFINE_BLEND_SLICE_PLANAR_FMT(yuv422, yuv_8_8bits, 1, 0)
+DEFINE_BLEND_SLICE_PLANAR_FMT(yuv444, yuv_8_8bits, 0, 0)
+DEFINE_BLEND_SLICE_PLANAR_FMT(yuv444p10, yuv_16_10bits, 0, 0)
+DEFINE_BLEND_SLICE_PLANAR_FMT(gbrp, planar_rgb, 0, 0)
+
+#define DEFINE_BLEND_SLICE_PACKED_FMT(format_, blend_slice_fn_suffix_, main_has_alpha_, main_straight_, overlay_straight_) \
static int blend_slice_##format_(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs) \
{ \
OverlayContext *s = ctx->priv; \
ThreadData *td = arg; \
blend_slice_packed_##blend_slice_fn_suffix_(ctx, td->dst, td->src, \
main_has_alpha_, \
- s->x, s->y, direct_, \
+ s->x, s->y, \
+ overlay_straight_, \
+ main_straight_, \
jobnr, nb_jobs); \
return 0; \
}
-// FMT FN A D
-DEFINE_BLEND_SLICE_PACKED_FMT(rgb, rgb, 0, 1)
-DEFINE_BLEND_SLICE_PACKED_FMT(rgba, rgb, 1, 1)
-DEFINE_BLEND_SLICE_PACKED_FMT(rgb_pm, rgb, 0, 0)
-DEFINE_BLEND_SLICE_PACKED_FMT(rgba_pm, rgb, 1, 0)
+// FMT FN A MS OS
+DEFINE_BLEND_SLICE_PACKED_FMT(rgb, rgb, 0, 0, 1)
+DEFINE_BLEND_SLICE_PACKED_FMT(rgb_pm, rgb, 0, 0, 0)
+DEFINE_BLEND_SLICE_PACKED_FMT(rgba_ss, rgb, 1, 1, 1)
+DEFINE_BLEND_SLICE_PACKED_FMT(rgba_sp, rgb, 1, 1, 0)
+DEFINE_BLEND_SLICE_PACKED_FMT(rgba_ps, rgb, 1, 0, 1)
+DEFINE_BLEND_SLICE_PACKED_FMT(rgba_pp, rgb, 1, 0, 0)
static int config_input_main(AVFilterLink *inlink)
{
@@ -765,113 +762,74 @@ static int init_slice_fn(AVFilterContext *ctx)
OverlayContext *s = ctx->priv;
const AVFilterLink *main = ctx->inputs[MAIN];
const AVFilterLink *overlay = ctx->inputs[OVERLAY];
+ const int main_straight = s->main_has_alpha && main->alpha_mode != AVALPHA_MODE_PREMULTIPLIED;
+ const int overlay_straight = overlay->alpha_mode != AVALPHA_MODE_PREMULTIPLIED;
- switch (overlay->alpha_mode) {
- case AVALPHA_MODE_UNSPECIFIED:
- case AVALPHA_MODE_STRAIGHT:
- switch (s->format) {
- case OVERLAY_FORMAT_YUV420:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva420 : blend_slice_yuv420;
- break;
- case OVERLAY_FORMAT_YUV420P10:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva420p10 : blend_slice_yuv420p10;
- break;
- case OVERLAY_FORMAT_YUV422:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva422 : blend_slice_yuv422;
- break;
- case OVERLAY_FORMAT_YUV422P10:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva422p10 : blend_slice_yuv422p10;
- break;
- case OVERLAY_FORMAT_YUV444:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva444 : blend_slice_yuv444;
- break;
- case OVERLAY_FORMAT_YUV444P10:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva444p10 : blend_slice_yuv444p10;
- break;
- case OVERLAY_FORMAT_RGB:
- s->blend_slice = s->main_has_alpha ? blend_slice_rgba : blend_slice_rgb;
+ #define ASSIGN_BLEND_SLICE(format_) \
+ do { \
+ s->blend_slice = main_straight ? (overlay_straight ? format_##_ss : format_##_sp) \
+ : (overlay_straight ? format_##_ps : format_##_pp); \
+ } while (0)
+
+ switch (s->format) {
+ case OVERLAY_FORMAT_YUV420:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv420);
+ break;
+ case OVERLAY_FORMAT_YUV420P10:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv420p10);
+ break;
+ case OVERLAY_FORMAT_YUV422:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv422);
+ break;
+ case OVERLAY_FORMAT_YUV422P10:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv422p10);
+ break;
+ case OVERLAY_FORMAT_YUV444:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv444);
+ break;
+ case OVERLAY_FORMAT_YUV444P10:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv444p10);
+ break;
+ case OVERLAY_FORMAT_RGB:
+ if (s->main_has_alpha)
+ ASSIGN_BLEND_SLICE(blend_slice_rgba);
+ else
+ s->blend_slice = overlay_straight ? blend_slice_rgb : blend_slice_rgb_pm;
+ break;
+ case OVERLAY_FORMAT_GBRP:
+ ASSIGN_BLEND_SLICE(blend_slice_gbrp);
+ break;
+ case OVERLAY_FORMAT_AUTO:
+ switch (main->format) {
+ case AV_PIX_FMT_YUVA420P:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv420);
break;
- case OVERLAY_FORMAT_GBRP:
- s->blend_slice = s->main_has_alpha ? blend_slice_gbrap : blend_slice_gbrp;
+ case AV_PIX_FMT_YUVA420P10:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv420p10);
break;
- case OVERLAY_FORMAT_AUTO:
- switch (main->format) {
- case AV_PIX_FMT_YUVA420P:
- s->blend_slice = blend_slice_yuva420;
- break;
- case AV_PIX_FMT_YUVA420P10:
- s->blend_slice = blend_slice_yuva420p10;
- break;
- case AV_PIX_FMT_YUVA422P:
- s->blend_slice = blend_slice_yuva422;
- break;
- case AV_PIX_FMT_YUVA422P10:
- s->blend_slice = blend_slice_yuva422p10;
- break;
- case AV_PIX_FMT_YUVA444P:
- s->blend_slice = blend_slice_yuva444;
- break;
- case AV_PIX_FMT_YUVA444P10:
- s->blend_slice = blend_slice_yuva444p10;
- break;
- case AV_PIX_FMT_ARGB:
- case AV_PIX_FMT_RGBA:
- case AV_PIX_FMT_BGRA:
- case AV_PIX_FMT_ABGR:
- s->blend_slice = blend_slice_rgba;
- break;
- case AV_PIX_FMT_GBRAP:
- s->blend_slice = blend_slice_gbrap;
- break;
- default:
- av_unreachable("Invalid pixel format for overlay");
- break;
- }
+ case AV_PIX_FMT_YUVA422P:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv422);
break;
- }
- break;
-
- case AVALPHA_MODE_PREMULTIPLIED:
- switch (s->format) {
- case OVERLAY_FORMAT_YUV420:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva420_pm : blend_slice_yuv420_pm;
+ case AV_PIX_FMT_YUVA422P10:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv422p10);
break;
- case OVERLAY_FORMAT_YUV422:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva422_pm : blend_slice_yuv422_pm;
+ case AV_PIX_FMT_YUVA444P:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv444);
break;
- case OVERLAY_FORMAT_YUV444:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva444_pm : blend_slice_yuv444_pm;
+ case AV_PIX_FMT_YUVA444P10:
+ ASSIGN_BLEND_SLICE(blend_slice_yuv444p10);
break;
- case OVERLAY_FORMAT_RGB:
- s->blend_slice = s->main_has_alpha ? blend_slice_rgba_pm : blend_slice_rgb_pm;
+ case AV_PIX_FMT_ARGB:
+ case AV_PIX_FMT_RGBA:
+ case AV_PIX_FMT_BGRA:
+ case AV_PIX_FMT_ABGR:
+ ASSIGN_BLEND_SLICE(blend_slice_rgba);
break;
- case OVERLAY_FORMAT_GBRP:
- s->blend_slice = s->main_has_alpha ? blend_slice_gbrap_pm : blend_slice_gbrp_pm;
+ case AV_PIX_FMT_GBRAP:
+ ASSIGN_BLEND_SLICE(blend_slice_gbrp);
break;
- case OVERLAY_FORMAT_AUTO:
- switch (main->format) {
- case AV_PIX_FMT_YUVA420P:
- s->blend_slice = blend_slice_yuva420_pm;
- break;
- case AV_PIX_FMT_YUVA422P:
- s->blend_slice = blend_slice_yuva422_pm;
- break;
- case AV_PIX_FMT_YUVA444P:
- s->blend_slice = blend_slice_yuva444_pm;
- break;
- case AV_PIX_FMT_ARGB:
- case AV_PIX_FMT_RGBA:
- case AV_PIX_FMT_BGRA:
- case AV_PIX_FMT_ABGR:
- s->blend_slice = blend_slice_rgba_pm;
- break;
- case AV_PIX_FMT_GBRAP:
- s->blend_slice = blend_slice_gbrap_pm;
- break;
- default:
- av_unreachable("Invalid pixel format for overlay");
- break;
- }
+ default:
+ av_unreachable("Invalid pixel format for overlay");
break;
}
break;
commit 6d6bbdaab0596b8254e3d367dfd808c9eb7ba4ee
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 15:12:05 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_overlay: rename variables for clarity
`is_straight`, `alpha_mode` etc. are more consistently named to refer to
either the main image, or the overlay.
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index bcf095310d..369cb33516 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -370,7 +370,7 @@ static int config_output(AVFilterLink *outlink)
static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
AVFrame *dst, const AVFrame *src,
int main_has_alpha, int x, int y,
- int is_straight, int jobnr, int nb_jobs)
+ int overlay_straight, int jobnr, int nb_jobs)
{
OverlayContext *s = ctx->priv;
int i, imax, j, jmax;
@@ -427,11 +427,11 @@ static av_always_inline void blend_slice_packed_rgb(AVFilterContext *ctx,
default:
// main_value = main_value * (1 - alpha) + overlay_value * alpha
// since alpha is in the range 0-255, the result must divided by 255
- d[dr] = is_straight ? FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha) :
+ d[dr] = overlay_straight ? FAST_DIV255(d[dr] * (255 - alpha) + S[sr] * alpha) :
FFMIN(FAST_DIV255(d[dr] * (255 - alpha)) + S[sr], 255);
- d[dg] = is_straight ? FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha) :
+ d[dg] = overlay_straight ? FAST_DIV255(d[dg] * (255 - alpha) + S[sg] * alpha) :
FFMIN(FAST_DIV255(d[dg] * (255 - alpha)) + S[sg], 255);
- d[db] = is_straight ? FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha) :
+ d[db] = overlay_straight ? FAST_DIV255(d[db] * (255 - alpha) + S[sb] * alpha) :
FFMIN(FAST_DIV255(d[db] * (255 - alpha)) + S[sb], 255);
}
if (main_has_alpha) {
@@ -465,7 +465,7 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
int dst_plane, \
int dst_offset, \
int dst_step, \
- int straight, \
+ int overlay_straight, \
int yuv, \
int jobnr, \
int nb_jobs) \
@@ -545,7 +545,7 @@ static av_always_inline void blend_plane_##depth##_##nbits##bits(AVFilterContext
alpha_d = da[0]; \
alpha = UNPREMULTIPLY_ALPHA(alpha, alpha_d); \
} \
- if (straight) { \
+ if (overlay_straight) { \
if (nbits > 8) \
*d = (*d * (max - alpha) + *s * alpha) / max; \
else \
@@ -633,7 +633,7 @@ static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterCon
int hsub, int vsub, \
int main_has_alpha, \
int x, int y, \
- int is_straight, \
+ int overlay_straight, \
int jobnr, int nb_jobs) \
{ \
OverlayContext *s = ctx->priv; \
@@ -644,13 +644,13 @@ static av_always_inline void blend_slice_yuv_##depth##_##nbits##bits(AVFilterCon
\
blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, \
x, y, main_has_alpha, s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, \
- s->main_desc->comp[0].step, is_straight, 1, jobnr, nb_jobs); \
+ s->main_desc->comp[0].step, overlay_straight, 1, jobnr, nb_jobs); \
blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, \
x, y, main_has_alpha, s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, \
- s->main_desc->comp[1].step, is_straight, 1, jobnr, nb_jobs); \
+ s->main_desc->comp[1].step, overlay_straight, 1, jobnr, nb_jobs); \
blend_plane_##depth##_##nbits##bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, \
x, y, main_has_alpha, s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, \
- s->main_desc->comp[2].step, is_straight, 1, jobnr, nb_jobs); \
+ s->main_desc->comp[2].step, overlay_straight, 1, jobnr, nb_jobs); \
\
if (main_has_alpha) \
alpha_composite_##depth##_##nbits##bits(src, dst, src_w, src_h, dst_w, dst_h, x, y, \
@@ -664,7 +664,7 @@ static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx,
int hsub, int vsub,
int main_has_alpha,
int x, int y,
- int is_straight,
+ int overlay_straight,
int jobnr,
int nb_jobs)
{
@@ -675,13 +675,13 @@ static av_always_inline void blend_slice_planar_rgb(AVFilterContext *ctx,
const int dst_h = dst->height;
blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 0, 0, 0, x, y, main_has_alpha,
- s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, is_straight, 0,
+ s->main_desc->comp[1].plane, s->main_desc->comp[1].offset, s->main_desc->comp[1].step, overlay_straight, 0,
jobnr, nb_jobs);
blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 1, hsub, vsub, x, y, main_has_alpha,
- s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, is_straight, 0,
+ s->main_desc->comp[2].plane, s->main_desc->comp[2].offset, s->main_desc->comp[2].step, overlay_straight, 0,
jobnr, nb_jobs);
blend_plane_8_8bits(ctx, dst, src, src_w, src_h, dst_w, dst_h, 2, hsub, vsub, x, y, main_has_alpha,
- s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, is_straight, 0,
+ s->main_desc->comp[0].plane, s->main_desc->comp[0].offset, s->main_desc->comp[0].step, overlay_straight, 0,
jobnr, nb_jobs);
if (main_has_alpha)
diff --git a/libavfilter/vf_overlay.h b/libavfilter/vf_overlay.h
index 253b2514b7..e4ba956fe7 100644
--- a/libavfilter/vf_overlay.h
+++ b/libavfilter/vf_overlay.h
@@ -83,6 +83,6 @@ typedef struct OverlayContext {
} OverlayContext;
void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
- enum AVAlphaMode, int main_has_alpha);
+ enum AVAlphaMode overlay_alpha, int main_has_alpha);
#endif /* AVFILTER_OVERLAY_H */
diff --git a/libavfilter/x86/vf_overlay_init.c b/libavfilter/x86/vf_overlay_init.c
index b698ee61a1..30cfe2cbe8 100644
--- a/libavfilter/x86/vf_overlay_init.c
+++ b/libavfilter/x86/vf_overlay_init.c
@@ -33,14 +33,14 @@ int ff_overlay_row_22_sse4(uint8_t *d, uint8_t *da, uint8_t *s, uint8_t *a,
int w, ptrdiff_t alinesize);
av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
- enum AVAlphaMode alpha_mode, int main_has_alpha)
+ enum AVAlphaMode overlay_alpha, int main_has_alpha)
{
int cpu_flags = av_get_cpu_flags();
if (EXTERNAL_SSE4(cpu_flags) &&
(format == OVERLAY_FORMAT_YUV444 ||
format == OVERLAY_FORMAT_GBRP) &&
- alpha_mode != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
+ overlay_alpha != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_44_sse4;
s->blend_row[2] = ff_overlay_row_44_sse4;
@@ -49,7 +49,7 @@ av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
if (EXTERNAL_SSE4(cpu_flags) &&
(pix_format == AV_PIX_FMT_YUV420P) &&
(format == OVERLAY_FORMAT_YUV420) &&
- alpha_mode != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
+ overlay_alpha != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_20_sse4;
s->blend_row[2] = ff_overlay_row_20_sse4;
@@ -57,7 +57,7 @@ av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
if (EXTERNAL_SSE4(cpu_flags) &&
(format == OVERLAY_FORMAT_YUV422) &&
- alpha_mode != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
+ overlay_alpha != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_22_sse4;
s->blend_row[2] = ff_overlay_row_22_sse4;
commit 6f3eddbeddc7ffbea30504eb5e2f4e525ec2f360
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 20:55:37 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_overlay: configure alpha mode on the link
And use the link-tagged value instead of the hard-coded parameter.
diff --git a/doc/filters.texi b/doc/filters.texi
index f240f66ffe..1b5665d36e 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -18875,7 +18875,8 @@ See @ref{framesync}.
@item alpha
Set format of alpha of the overlaid video, it can be @var{straight} or
-@var{premultiplied}. Default is @var{straight}.
+@var{premultiplied}, or @var{auto} to choose the alpha mode automatically.
+Default is @var{auto}.
@end table
The @option{x}, and @option{y} expressions can contain the following
diff --git a/libavfilter/vf_overlay.c b/libavfilter/vf_overlay.c
index d77fe87c05..bcf095310d 100644
--- a/libavfilter/vf_overlay.c
+++ b/libavfilter/vf_overlay.c
@@ -233,6 +233,13 @@ static int query_formats(const AVFilterContext *ctx,
AVFilterFormats *formats;
int ret;
+ if (s->alpha_mode != AVALPHA_MODE_UNSPECIFIED) {
+ formats = ff_make_formats_list_singleton(s->alpha_mode);
+ ret = ff_formats_ref(formats, &cfg_in[OVERLAY]->alpha_modes);
+ if (ret < 0)
+ return ret;
+ }
+
switch (s->format) {
case OVERLAY_FORMAT_YUV420:
main_formats = main_pix_fmts_yuv420;
@@ -750,117 +757,128 @@ static int config_input_main(AVFilterLink *inlink)
s->main_is_packed_rgb =
ff_fill_rgba_map(s->main_rgba_map, inlink->format) >= 0;
s->main_has_alpha = ff_fmt_is_in(inlink->format, alpha_pix_fmts);
- switch (s->format) {
- case OVERLAY_FORMAT_YUV420:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva420 : blend_slice_yuv420;
- break;
- case OVERLAY_FORMAT_YUV420P10:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva420p10 : blend_slice_yuv420p10;
- break;
- case OVERLAY_FORMAT_YUV422:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva422 : blend_slice_yuv422;
- break;
- case OVERLAY_FORMAT_YUV422P10:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva422p10 : blend_slice_yuv422p10;
- break;
- case OVERLAY_FORMAT_YUV444:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva444 : blend_slice_yuv444;
- break;
- case OVERLAY_FORMAT_YUV444P10:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva444p10 : blend_slice_yuv444p10;
- break;
- case OVERLAY_FORMAT_RGB:
- s->blend_slice = s->main_has_alpha ? blend_slice_rgba : blend_slice_rgb;
- break;
- case OVERLAY_FORMAT_GBRP:
- s->blend_slice = s->main_has_alpha ? blend_slice_gbrap : blend_slice_gbrp;
- break;
- case OVERLAY_FORMAT_AUTO:
- switch (inlink->format) {
- case AV_PIX_FMT_YUVA420P:
- s->blend_slice = blend_slice_yuva420;
+ return 0;
+}
+
+static int init_slice_fn(AVFilterContext *ctx)
+{
+ OverlayContext *s = ctx->priv;
+ const AVFilterLink *main = ctx->inputs[MAIN];
+ const AVFilterLink *overlay = ctx->inputs[OVERLAY];
+
+ switch (overlay->alpha_mode) {
+ case AVALPHA_MODE_UNSPECIFIED:
+ case AVALPHA_MODE_STRAIGHT:
+ switch (s->format) {
+ case OVERLAY_FORMAT_YUV420:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva420 : blend_slice_yuv420;
break;
- case AV_PIX_FMT_YUVA420P10:
- s->blend_slice = blend_slice_yuva420p10;
+ case OVERLAY_FORMAT_YUV420P10:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva420p10 : blend_slice_yuv420p10;
break;
- case AV_PIX_FMT_YUVA422P:
- s->blend_slice = blend_slice_yuva422;
+ case OVERLAY_FORMAT_YUV422:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva422 : blend_slice_yuv422;
break;
- case AV_PIX_FMT_YUVA422P10:
- s->blend_slice = blend_slice_yuva422p10;
+ case OVERLAY_FORMAT_YUV422P10:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva422p10 : blend_slice_yuv422p10;
break;
- case AV_PIX_FMT_YUVA444P:
- s->blend_slice = blend_slice_yuva444;
+ case OVERLAY_FORMAT_YUV444:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva444 : blend_slice_yuv444;
break;
- case AV_PIX_FMT_YUVA444P10:
- s->blend_slice = blend_slice_yuva444p10;
+ case OVERLAY_FORMAT_YUV444P10:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva444p10 : blend_slice_yuv444p10;
break;
- case AV_PIX_FMT_ARGB:
- case AV_PIX_FMT_RGBA:
- case AV_PIX_FMT_BGRA:
- case AV_PIX_FMT_ABGR:
- s->blend_slice = blend_slice_rgba;
+ case OVERLAY_FORMAT_RGB:
+ s->blend_slice = s->main_has_alpha ? blend_slice_rgba : blend_slice_rgb;
break;
- case AV_PIX_FMT_GBRAP:
- s->blend_slice = blend_slice_gbrap;
+ case OVERLAY_FORMAT_GBRP:
+ s->blend_slice = s->main_has_alpha ? blend_slice_gbrap : blend_slice_gbrp;
break;
- default:
- av_assert0(0);
+ case OVERLAY_FORMAT_AUTO:
+ switch (main->format) {
+ case AV_PIX_FMT_YUVA420P:
+ s->blend_slice = blend_slice_yuva420;
+ break;
+ case AV_PIX_FMT_YUVA420P10:
+ s->blend_slice = blend_slice_yuva420p10;
+ break;
+ case AV_PIX_FMT_YUVA422P:
+ s->blend_slice = blend_slice_yuva422;
+ break;
+ case AV_PIX_FMT_YUVA422P10:
+ s->blend_slice = blend_slice_yuva422p10;
+ break;
+ case AV_PIX_FMT_YUVA444P:
+ s->blend_slice = blend_slice_yuva444;
+ break;
+ case AV_PIX_FMT_YUVA444P10:
+ s->blend_slice = blend_slice_yuva444p10;
+ break;
+ case AV_PIX_FMT_ARGB:
+ case AV_PIX_FMT_RGBA:
+ case AV_PIX_FMT_BGRA:
+ case AV_PIX_FMT_ABGR:
+ s->blend_slice = blend_slice_rgba;
+ break;
+ case AV_PIX_FMT_GBRAP:
+ s->blend_slice = blend_slice_gbrap;
+ break;
+ default:
+ av_unreachable("Invalid pixel format for overlay");
+ break;
+ }
break;
}
break;
- }
-
- if (!s->alpha_format)
- goto end;
- switch (s->format) {
- case OVERLAY_FORMAT_YUV420:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva420_pm : blend_slice_yuv420_pm;
- break;
- case OVERLAY_FORMAT_YUV422:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva422_pm : blend_slice_yuv422_pm;
- break;
- case OVERLAY_FORMAT_YUV444:
- s->blend_slice = s->main_has_alpha ? blend_slice_yuva444_pm : blend_slice_yuv444_pm;
- break;
- case OVERLAY_FORMAT_RGB:
- s->blend_slice = s->main_has_alpha ? blend_slice_rgba_pm : blend_slice_rgb_pm;
- break;
- case OVERLAY_FORMAT_GBRP:
- s->blend_slice = s->main_has_alpha ? blend_slice_gbrap_pm : blend_slice_gbrp_pm;
- break;
- case OVERLAY_FORMAT_AUTO:
- switch (inlink->format) {
- case AV_PIX_FMT_YUVA420P:
- s->blend_slice = blend_slice_yuva420_pm;
+ case AVALPHA_MODE_PREMULTIPLIED:
+ switch (s->format) {
+ case OVERLAY_FORMAT_YUV420:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva420_pm : blend_slice_yuv420_pm;
break;
- case AV_PIX_FMT_YUVA422P:
- s->blend_slice = blend_slice_yuva422_pm;
+ case OVERLAY_FORMAT_YUV422:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva422_pm : blend_slice_yuv422_pm;
break;
- case AV_PIX_FMT_YUVA444P:
- s->blend_slice = blend_slice_yuva444_pm;
+ case OVERLAY_FORMAT_YUV444:
+ s->blend_slice = s->main_has_alpha ? blend_slice_yuva444_pm : blend_slice_yuv444_pm;
break;
- case AV_PIX_FMT_ARGB:
- case AV_PIX_FMT_RGBA:
- case AV_PIX_FMT_BGRA:
- case AV_PIX_FMT_ABGR:
- s->blend_slice = blend_slice_rgba_pm;
+ case OVERLAY_FORMAT_RGB:
+ s->blend_slice = s->main_has_alpha ? blend_slice_rgba_pm : blend_slice_rgb_pm;
break;
- case AV_PIX_FMT_GBRAP:
- s->blend_slice = blend_slice_gbrap_pm;
+ case OVERLAY_FORMAT_GBRP:
+ s->blend_slice = s->main_has_alpha ? blend_slice_gbrap_pm : blend_slice_gbrp_pm;
break;
- default:
- av_assert0(0);
+ case OVERLAY_FORMAT_AUTO:
+ switch (main->format) {
+ case AV_PIX_FMT_YUVA420P:
+ s->blend_slice = blend_slice_yuva420_pm;
+ break;
+ case AV_PIX_FMT_YUVA422P:
+ s->blend_slice = blend_slice_yuva422_pm;
+ break;
+ case AV_PIX_FMT_YUVA444P:
+ s->blend_slice = blend_slice_yuva444_pm;
+ break;
+ case AV_PIX_FMT_ARGB:
+ case AV_PIX_FMT_RGBA:
+ case AV_PIX_FMT_BGRA:
+ case AV_PIX_FMT_ABGR:
+ s->blend_slice = blend_slice_rgba_pm;
+ break;
+ case AV_PIX_FMT_GBRAP:
+ s->blend_slice = blend_slice_gbrap_pm;
+ break;
+ default:
+ av_unreachable("Invalid pixel format for overlay");
+ break;
+ }
break;
}
break;
}
-end:
#if ARCH_X86
- ff_overlay_init_x86(s, s->format, inlink->format,
- s->alpha_format, s->main_has_alpha);
+ ff_overlay_init_x86(s, s->format, main->format, overlay->alpha_mode, s->main_has_alpha);
#endif
return 0;
@@ -903,6 +921,8 @@ static int do_blend(FFFrameSync *fs)
s->y < mainpic->height && s->y + second->height >= 0) {
ThreadData td;
+ init_slice_fn(ctx);
+
td.dst = mainpic;
td.src = second;
ff_filter_execute(ctx, s->blend_slice, &td, NULL, FFMIN(FFMAX(1, FFMIN3(s->y + second->height, FFMIN(second->height, mainpic->height), mainpic->height - s->y)),
@@ -953,9 +973,11 @@ static const AVOption overlay_options[] = {
{ "gbrp", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_GBRP}, .flags = FLAGS, .unit = "format" },
{ "auto", "", 0, AV_OPT_TYPE_CONST, {.i64=OVERLAY_FORMAT_AUTO}, .flags = FLAGS, .unit = "format" },
{ "repeatlast", "repeat overlay of the last overlay frame", OFFSET(fs.opt_repeatlast), AV_OPT_TYPE_BOOL, {.i64=1}, 0, 1, FLAGS },
- { "alpha", "alpha format", OFFSET(alpha_format), AV_OPT_TYPE_INT, {.i64=0}, 0, 1, FLAGS, .unit = "alpha_format" },
- { "straight", "", 0, AV_OPT_TYPE_CONST, {.i64=0}, .flags = FLAGS, .unit = "alpha_format" },
- { "premultiplied", "", 0, AV_OPT_TYPE_CONST, {.i64=1}, .flags = FLAGS, .unit = "alpha_format" },
+ { "alpha", "alpha format", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, AVALPHA_MODE_NB-1, FLAGS, .unit = "alpha_mode" },
+ { "auto", "", 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, .flags = FLAGS, .unit = "alpha_mode" },
+ { "unknown", "", 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, .flags = FLAGS, .unit = "alpha_mode" },
+ { "straight", "", 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_STRAIGHT}, .flags = FLAGS, .unit = "alpha_mode" },
+ { "premultiplied", "", 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_PREMULTIPLIED}, .flags = FLAGS, .unit = "alpha_mode" },
{ NULL }
};
diff --git a/libavfilter/vf_overlay.h b/libavfilter/vf_overlay.h
index 3ad378ce42..253b2514b7 100644
--- a/libavfilter/vf_overlay.h
+++ b/libavfilter/vf_overlay.h
@@ -62,7 +62,7 @@ typedef struct OverlayContext {
uint8_t overlay_rgba_map[4];
uint8_t overlay_has_alpha;
int format; ///< OverlayFormat
- int alpha_format;
+ int alpha_mode;
int eval_mode; ///< EvalMode
FFFrameSync fs;
@@ -83,6 +83,6 @@ typedef struct OverlayContext {
} OverlayContext;
void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
- int alpha_format, int main_has_alpha);
+ enum AVAlphaMode, int main_has_alpha);
#endif /* AVFILTER_OVERLAY_H */
diff --git a/libavfilter/x86/vf_overlay_init.c b/libavfilter/x86/vf_overlay_init.c
index d4218b18f6..b698ee61a1 100644
--- a/libavfilter/x86/vf_overlay_init.c
+++ b/libavfilter/x86/vf_overlay_init.c
@@ -33,14 +33,14 @@ int ff_overlay_row_22_sse4(uint8_t *d, uint8_t *da, uint8_t *s, uint8_t *a,
int w, ptrdiff_t alinesize);
av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
- int alpha_format, int main_has_alpha)
+ enum AVAlphaMode alpha_mode, int main_has_alpha)
{
int cpu_flags = av_get_cpu_flags();
if (EXTERNAL_SSE4(cpu_flags) &&
(format == OVERLAY_FORMAT_YUV444 ||
format == OVERLAY_FORMAT_GBRP) &&
- alpha_format == 0 && main_has_alpha == 0) {
+ alpha_mode != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_44_sse4;
s->blend_row[2] = ff_overlay_row_44_sse4;
@@ -49,7 +49,7 @@ av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
if (EXTERNAL_SSE4(cpu_flags) &&
(pix_format == AV_PIX_FMT_YUV420P) &&
(format == OVERLAY_FORMAT_YUV420) &&
- alpha_format == 0 && main_has_alpha == 0) {
+ alpha_mode != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_20_sse4;
s->blend_row[2] = ff_overlay_row_20_sse4;
@@ -57,7 +57,7 @@ av_cold void ff_overlay_init_x86(OverlayContext *s, int format, int pix_format,
if (EXTERNAL_SSE4(cpu_flags) &&
(format == OVERLAY_FORMAT_YUV422) &&
- alpha_format == 0 && main_has_alpha == 0) {
+ alpha_mode != AVALPHA_MODE_PREMULTIPLIED && main_has_alpha == 0) {
s->blend_row[0] = ff_overlay_row_44_sse4;
s->blend_row[1] = ff_overlay_row_22_sse4;
s->blend_row[2] = ff_overlay_row_22_sse4;
commit 1c8ca56a8805727339e4e52ec14d903b099cee28
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 21:36:58 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_libplacebo: add an alpha_mode setting
Chooses the desired output alpha mode. Note that this depends on
an upstream version of libplacebo new enough to respect the corresponding
AVFrame field in pl_map_avframe_ex.
diff --git a/doc/filters.texi b/doc/filters.texi
index 2ef9537786..f240f66ffe 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -16521,6 +16521,10 @@ leading to no change. For any other value, conversion will be performed.
See the @ref{setparams} filter for a list of possible values.
+@item alpha_mode
+Choose the desired output alpha mode, when the output format has an alpha
+channel. See the @ref{setparams} filter for a list of possible values.
+
@item apply_filmgrain
Apply film grain (e.g. AV1 or H.274) if present in source frames, and strip
it from the output. Enabled by default.
diff --git a/libavfilter/vf_libplacebo.c b/libavfilter/vf_libplacebo.c
index 2e7e83e8db..f4b5ac6b03 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -203,6 +203,7 @@ typedef struct LibplaceboContext {
int color_primaries;
int color_trc;
int rotation;
+ int alpha_mode;
AVDictionary *extra_opts;
#if PL_API_VER >= 351
@@ -962,6 +963,7 @@ static int output_frame(AVFilterContext *ctx, int64_t pts)
out->height = outlink->h;
out->colorspace = outlink->colorspace;
out->color_range = outlink->color_range;
+ out->alpha_mode = outlink->alpha_mode;
if (s->deinterlace)
out->flags &= ~(AV_FRAME_FLAG_INTERLACED | AV_FRAME_FLAG_TOP_FIELD_FIRST);
@@ -1339,6 +1341,7 @@ static int libplacebo_query_format(const AVFilterContext *ctx,
RET(ff_formats_ref(infmts, &cfg_in[i]->formats));
RET(ff_formats_ref(ff_all_color_spaces(), &cfg_in[i]->color_spaces));
RET(ff_formats_ref(ff_all_color_ranges(), &cfg_in[i]->color_ranges));
+ RET(ff_formats_ref(ff_all_alpha_modes(), &cfg_in[i]->alpha_modes));
}
RET(ff_formats_ref(outfmts, &cfg_out[0]->formats));
@@ -1350,6 +1353,10 @@ static int libplacebo_query_format(const AVFilterContext *ctx,
outfmts = s->color_range > 0 ? ff_make_formats_list_singleton(s->color_range)
: ff_all_color_ranges();
RET(ff_formats_ref(outfmts, &cfg_out[0]->color_ranges));
+
+ outfmts = s->alpha_mode > 0 ? ff_make_formats_list_singleton(s->alpha_mode)
+ : ff_all_alpha_modes();
+ RET(ff_formats_ref(outfmts, &cfg_out[0]->alpha_modes));
return 0;
fail:
@@ -1611,6 +1618,13 @@ static const AVOption libplacebo_options[] = {
{"270", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_270}, .flags = STATIC, .unit = "rotation"},
{"360", NULL, 0, AV_OPT_TYPE_CONST, {.i64=PL_ROTATION_360}, .flags = STATIC, .unit = "rotation"},
+ {"alpha_mode", "select alpha moda", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVALPHA_MODE_NB-1, DYNAMIC, .unit = "alpha_mode"},
+ {"auto", "keep the same alpha mode", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
+ {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
+ {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
+ {"premultiplied", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_PREMULTIPLIED}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
+ {"straight", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_STRAIGHT}, 0, 0, DYNAMIC, .unit = "alpha_mode"},
+
{ "upscaler", "Upscaler function", OFFSET(upscaler), AV_OPT_TYPE_STRING, {.str = "spline36"}, .flags = DYNAMIC },
{ "downscaler", "Downscaler function", OFFSET(downscaler), AV_OPT_TYPE_STRING, {.str = "mitchell"}, .flags = DYNAMIC },
{ "frame_mixer", "Frame mixing function", OFFSET(frame_mixer), AV_OPT_TYPE_STRING, {.str = "none"}, .flags = DYNAMIC },
commit dc02514f6bdd959f9b2f7b8a9b286e39c57ee85c
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 21:26:54 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_setparams: add alpha_mode parameter
diff --git a/doc/filters.texi b/doc/filters.texi
index 7efc7fa689..2ef9537786 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -21758,6 +21758,19 @@ Keep the same chroma location (default).
@item bottomleft
@item bottom
@end table
+
+@item alpha_mode
+Set the alpha moda.
+Available values are:
+
+@table @samp
+@item auto
+Keep the same alpha mode (default).
+
+@item unspecified, unknown
+@item premultiplied
+@item straight
+@end table
@end table
@section shear
diff --git a/libavfilter/vf_setparams.c b/libavfilter/vf_setparams.c
index 1e37876e42..f32757f940 100644
--- a/libavfilter/vf_setparams.c
+++ b/libavfilter/vf_setparams.c
@@ -42,6 +42,7 @@ typedef struct SetParamsContext {
int color_trc;
int colorspace;
int chroma_location;
+ int alpha_mode;
} SetParamsContext;
#define OFFSET(x) offsetof(SetParamsContext, x)
@@ -131,6 +132,13 @@ static const AVOption setparams_options[] = {
{"top", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_TOP}, 0, 0, FLAGS, .unit = "chroma_location"},
{"bottomleft", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOMLEFT}, 0, 0, FLAGS, .unit = "chroma_location"},
{"bottom", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCHROMA_LOC_BOTTOM}, 0, 0, FLAGS, .unit = "chroma_location"},
+
+ {"alpha_mode", "select alpha moda", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=-1}, -1, AVALPHA_MODE_NB-1, FLAGS, .unit = "alpha_mode"},
+ {"auto", "keep the same alpha mode", 0, AV_OPT_TYPE_CONST, {.i64=-1}, 0, 0, FLAGS, .unit = "alpha_mode"},
+ {"unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, FLAGS, .unit = "alpha_mode"},
+ {"unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, FLAGS, .unit = "alpha_mode"},
+ {"premultiplied", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_PREMULTIPLIED}, 0, 0, FLAGS, .unit = "alpha_mode"},
+ {"straight", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_STRAIGHT}, 0, 0, FLAGS, .unit = "alpha_mode"},
{NULL}
};
@@ -157,6 +165,13 @@ static int query_formats(const AVFilterContext *ctx,
return ret;
}
+ if (s->alpha_mode >= 0) {
+ ret = ff_formats_ref(ff_make_formats_list_singleton(s->alpha_mode),
+ &cfg_out[0]->alpha_modes);
+ if (ret < 0)
+ return ret;
+ }
+
return 0;
}
@@ -187,6 +202,8 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
frame->colorspace = s->colorspace;
if (s->chroma_location >= 0)
frame->chroma_location = s->chroma_location;
+ if (s->alpha_mode >= 0)
+ frame->alpha_mode = s->alpha_mode;
return ff_filter_frame(ctx->outputs[0], frame);
}
@@ -237,6 +254,7 @@ static av_cold int init_setrange(AVFilterContext *ctx)
s->color_trc = -1;
s->colorspace = -1;
s->chroma_location = -1;
+ s->alpha_mode = -1;
return 0;
}
@@ -274,6 +292,7 @@ static av_cold int init_setfield(AVFilterContext *ctx)
s->color_trc = -1;
s->colorspace = -1;
s->chroma_location = -1;
+ s->alpha_mode = -1;
return 0;
}
commit e6ab7fe5825c380386d2423d3b2c23df16699361
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Thu Aug 14 17:15:30 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_scale: set correct alpha mode after format change
While vf_scale cannot directly convert between premultiplied and straight
alpha, the effective tagging can still change as a result of a change in
the pixel format (i.e. adding or removing an alpha channel).
diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index a376fbe0ca..33212a47c0 100644
--- a/libavfilter/vf_scale.c
+++ b/libavfilter/vf_scale.c
@@ -837,6 +837,7 @@ scale:
out->height = outlink->h;
out->color_range = outlink->color_range;
out->colorspace = outlink->colorspace;
+ out->alpha_mode = outlink->alpha_mode;
if (scale->out_chroma_loc != AVCHROMA_LOC_UNSPECIFIED)
out->chroma_location = scale->out_chroma_loc;
if (scale->out_primaries != -1)
commit a3d518a57cf8cb9cbc9c203a179d7c9ebe8c65d6
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Thu Aug 14 16:07:00 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_extractplanes: require straight alpha input
diff --git a/libavfilter/vf_extractplanes.c b/libavfilter/vf_extractplanes.c
index 99e37ba04a..19cbb987fb 100644
--- a/libavfilter/vf_extractplanes.c
+++ b/libavfilter/vf_extractplanes.c
@@ -213,6 +213,10 @@ static int query_formats(AVFilterContext *ctx)
else
out_pixfmts = out32le_pixfmts;
+ /* Splitting planes apart only makes sense for straight alpha */
+ if ((ret = ff_formats_ref(ff_make_formats_list_singleton(AVALPHA_MODE_STRAIGHT), &ctx->inputs[0]->outcfg.alpha_modes)) < 0)
+ return ret;
+
for (i = 0; i < ctx->nb_outputs; i++)
if ((ret = ff_formats_ref(ff_make_format_list(out_pixfmts), &ctx->outputs[i]->incfg.formats)) < 0)
return ret;
commit ab1bc440f752fded5998d61f8587d723a0b0c5cf
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 20:39:58 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_alphamerge: configure correct alpha mode
diff --git a/libavfilter/vf_alphamerge.c b/libavfilter/vf_alphamerge.c
index f5779484a9..c17a647dbe 100644
--- a/libavfilter/vf_alphamerge.c
+++ b/libavfilter/vf_alphamerge.c
@@ -49,6 +49,7 @@ typedef struct AlphaMergeContext {
static int do_alphamerge(FFFrameSync *fs)
{
AVFilterContext *ctx = fs->parent;
+ AVFilterLink *outlink = ctx->outputs[0];
AlphaMergeContext *s = ctx->priv;
AVFrame *main_buf, *alpha_buf;
int ret;
@@ -56,6 +57,7 @@ static int do_alphamerge(FFFrameSync *fs)
ret = ff_framesync_dualinput_get_writable(fs, &main_buf, &alpha_buf);
if (ret < 0)
return ret;
+ main_buf->alpha_mode = outlink->alpha_mode;
if (!alpha_buf)
return ff_filter_frame(ctx->outputs[0], main_buf);
@@ -118,6 +120,11 @@ static int query_formats(const AVFilterContext *ctx,
if (ret < 0)
return ret;
+ ret = ff_formats_ref(ff_make_formats_list_singleton(AVALPHA_MODE_STRAIGHT),
+ &cfg_out[0]->alpha_modes);
+ if (ret < 0)
+ return ret;
+
return 0;
}
commit 2032820e90ce0e94b9214c8df36002ef74e2bbb0
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 19:55:56 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
fftools/ffprobe: add AVFrame.alpha_mode support
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index f4eb87aefa..89b8dd3802 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -1156,6 +1156,16 @@ static void print_chroma_location(AVTextFormatContext *tfc, enum AVChromaLocatio
}
}
+static void print_alpha_mode(AVTextFormatContext *tfc, enum AVAlphaMode alpha_mode)
+{
+ const char *val = av_alpha_mode_name(alpha_mode);
+ if (!val || alpha_mode == AVALPHA_MODE_UNSPECIFIED) {
+ print_str_opt("alpha_mode", "unspecified");
+ } else {
+ print_str("alpha_mode", val);
+ }
+}
+
static void clear_log(int need_lock)
{
int i;
@@ -1410,6 +1420,7 @@ static void show_frame(AVTextFormatContext *tfc, AVFrame *frame, AVStream *strea
print_primaries(tfc, frame->color_primaries);
print_color_trc(tfc, frame->color_trc);
print_chroma_location(tfc, frame->chroma_location);
+ print_alpha_mode(tfc, frame->alpha_mode);
break;
case AVMEDIA_TYPE_AUDIO:
diff --git a/tests/ref/fate/enhanced-flv-hevc-hdr10 b/tests/ref/fate/enhanced-flv-hevc-hdr10
index 4d93f98e57..525f056d66 100644
--- a/tests/ref/fate/enhanced-flv-hevc-hdr10
+++ b/tests/ref/fate/enhanced-flv-hevc-hdr10
@@ -37,6 +37,7 @@ color_space=bt2020nc
color_primaries=bt2020
color_transfer=smpte2084
chroma_location=left
+alpha_mode=unspecified
[SIDE_DATA]
side_data_type=Mastering display metadata
red_x=13250/50000
diff --git a/tests/ref/fate/exif-image-embedded b/tests/ref/fate/exif-image-embedded
index 22d4b03d1c..d663368394 100644
--- a/tests/ref/fate/exif-image-embedded
+++ b/tests/ref/fate/exif-image-embedded
@@ -30,6 +30,7 @@ color_space=bt470bg
color_primaries=unknown
color_transfer=unknown
chroma_location=center
+alpha_mode=unspecified
TAG:ExifIFD/UserComment=AppleMark
[SIDE_DATA]
diff --git a/tests/ref/fate/exif-image-jpg b/tests/ref/fate/exif-image-jpg
index d847ae7c7f..25f3b228ff 100644
--- a/tests/ref/fate/exif-image-jpg
+++ b/tests/ref/fate/exif-image-jpg
@@ -30,6 +30,7 @@ color_space=bt470bg
color_primaries=unknown
color_transfer=unknown
chroma_location=center
+alpha_mode=unspecified
TAG:ImageDescription=
TAG:Make=Canon
TAG:Model=Canon PowerShot SX200 IS
diff --git a/tests/ref/fate/exif-image-tiff b/tests/ref/fate/exif-image-tiff
index f0c0946c76..f6314190b2 100644
--- a/tests/ref/fate/exif-image-tiff
+++ b/tests/ref/fate/exif-image-tiff
@@ -30,6 +30,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
TAG:document_name=image_small.tiff
TAG:page_number= 0 / 1
TAG:0x0129= 0, 1
diff --git a/tests/ref/fate/exif-image-webp b/tests/ref/fate/exif-image-webp
index 54c8294362..0f96254aa1 100644
--- a/tests/ref/fate/exif-image-webp
+++ b/tests/ref/fate/exif-image-webp
@@ -30,6 +30,7 @@ color_space=bt470bg
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
TAG:ImageDescription=
TAG:Make=Canon
TAG:Model=Canon PowerShot SX200 IS
diff --git a/tests/ref/fate/ffprobe_compact b/tests/ref/fate/ffprobe_compact
index 68b9acf599..53456ce358 100644
--- a/tests/ref/fate/ffprobe_compact
+++ b/tests/ref/fate/ffprobe_compact
@@ -1,31 +1,31 @@
packet|codec_type=audio|stream_index=0|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=1024|duration_time=0.023220|size=2048|pos=669|flags=K__
frame|media_type=audio|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=1024|duration_time=0.023220|pkt_pos=669|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
packet|codec_type=video|stream_index=1|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=230400|pos=2744|flags=K__
-frame|media_type=video|stream_index=1|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=2048|duration_time=0.040000|pkt_pos=2744|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=1|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=2048|duration_time=0.040000|pkt_pos=2744|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=video|stream_index=2|pts=0|pts_time=0.000000|dts=0|dts_time=0.000000|duration=2048|duration_time=0.040000|size=30000|pos=233165|flags=K__
-frame|media_type=video|stream_index=2|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=2048|duration_time=0.040000|pkt_pos=233165|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=2|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=0|pkt_dts_time=0.000000|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=2048|duration_time=0.040000|pkt_pos=233165|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=audio|stream_index=0|pts=1024|pts_time=0.023220|dts=1024|dts_time=0.023220|duration=1024|duration_time=0.023220|size=2048|pos=263170|flags=K__
frame|media_type=audio|stream_index=0|key_frame=1|pts=1024|pts_time=0.023220|pkt_dts=1024|pkt_dts_time=0.023220|best_effort_timestamp=1024|best_effort_timestamp_time=0.023220|duration=1024|duration_time=0.023220|pkt_pos=263170|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
packet|codec_type=video|stream_index=1|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=230400|pos=265248|flags=K__
-frame|media_type=video|stream_index=1|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|duration=2048|duration_time=0.040000|pkt_pos=265248|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=1|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|duration=2048|duration_time=0.040000|pkt_pos=265248|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=video|stream_index=2|pts=2048|pts_time=0.040000|dts=2048|dts_time=0.040000|duration=2048|duration_time=0.040000|size=30000|pos=495672|flags=K__
-frame|media_type=video|stream_index=2|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|duration=2048|duration_time=0.040000|pkt_pos=495672|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=2|key_frame=1|pts=2048|pts_time=0.040000|pkt_dts=2048|pkt_dts_time=0.040000|best_effort_timestamp=2048|best_effort_timestamp_time=0.040000|duration=2048|duration_time=0.040000|pkt_pos=495672|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=audio|stream_index=0|pts=2048|pts_time=0.046440|dts=2048|dts_time=0.046440|duration=1024|duration_time=0.023220|size=2048|pos=525677|flags=K__
frame|media_type=audio|stream_index=0|key_frame=1|pts=2048|pts_time=0.046440|pkt_dts=2048|pkt_dts_time=0.046440|best_effort_timestamp=2048|best_effort_timestamp_time=0.046440|duration=1024|duration_time=0.023220|pkt_pos=525677|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
packet|codec_type=audio|stream_index=0|pts=3072|pts_time=0.069660|dts=3072|dts_time=0.069660|duration=1024|duration_time=0.023220|size=2048|pos=527748|flags=K__
frame|media_type=audio|stream_index=0|key_frame=1|pts=3072|pts_time=0.069660|pkt_dts=3072|pkt_dts_time=0.069660|best_effort_timestamp=3072|best_effort_timestamp_time=0.069660|duration=1024|duration_time=0.023220|pkt_pos=527748|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
packet|codec_type=video|stream_index=1|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=230400|pos=529826|flags=K__
-frame|media_type=video|stream_index=1|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|duration=2048|duration_time=0.040000|pkt_pos=529826|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=1|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|duration=2048|duration_time=0.040000|pkt_pos=529826|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=video|stream_index=2|pts=4096|pts_time=0.080000|dts=4096|dts_time=0.080000|duration=2048|duration_time=0.040000|size=30000|pos=760250|flags=K__
-frame|media_type=video|stream_index=2|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|duration=2048|duration_time=0.040000|pkt_pos=760250|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=2|key_frame=1|pts=4096|pts_time=0.080000|pkt_dts=4096|pkt_dts_time=0.080000|best_effort_timestamp=4096|best_effort_timestamp_time=0.080000|duration=2048|duration_time=0.040000|pkt_pos=760250|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=audio|stream_index=0|pts=4096|pts_time=0.092880|dts=4096|dts_time=0.092880|duration=1024|duration_time=0.023220|size=2048|pos=790255|flags=K__
frame|media_type=audio|stream_index=0|key_frame=1|pts=4096|pts_time=0.092880|pkt_dts=4096|pkt_dts_time=0.092880|best_effort_timestamp=4096|best_effort_timestamp_time=0.092880|duration=1024|duration_time=0.023220|pkt_pos=790255|pkt_size=2048|sample_fmt=s16|nb_samples=1024|channels=1|channel_layout=unknown
packet|codec_type=audio|stream_index=0|pts=5120|pts_time=0.116100|dts=5120|dts_time=0.116100|duration=393|duration_time=0.008912|size=786|pos=792326|flags=K__
frame|media_type=audio|stream_index=0|key_frame=1|pts=5120|pts_time=0.116100|pkt_dts=5120|pkt_dts_time=0.116100|best_effort_timestamp=5120|best_effort_timestamp_time=0.116100|duration=393|duration_time=0.008912|pkt_pos=792326|pkt_size=786|sample_fmt=s16|nb_samples=393|channels=1|channel_layout=unknown
packet|codec_type=video|stream_index=1|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=230400|pos=793142|flags=K__
-frame|media_type=video|stream_index=1|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|duration=2048|duration_time=0.040000|pkt_pos=793142|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=1|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|duration=2048|duration_time=0.040000|pkt_pos=793142|pkt_size=230400|width=320|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
packet|codec_type=video|stream_index=2|pts=6144|pts_time=0.120000|dts=6144|dts_time=0.120000|duration=2048|duration_time=0.040000|size=30000|pos=1023566|flags=K__
-frame|media_type=video|stream_index=2|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|duration=2048|duration_time=0.040000|pkt_pos=1023566|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified
+frame|media_type=video|stream_index=2|key_frame=1|pts=6144|pts_time=0.120000|pkt_dts=6144|pkt_dts_time=0.120000|best_effort_timestamp=6144|best_effort_timestamp_time=0.120000|duration=2048|duration_time=0.040000|pkt_pos=1023566|pkt_size=30000|width=100|height=100|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=rgb24|sample_aspect_ratio=1:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=unknown|color_space=unknown|color_primaries=unknown|color_transfer=unknown|chroma_location=unspecified|alpha_mode=unspecified
stream|index=0|codec_name=pcm_s16le|profile=unknown|codec_type=audio|codec_tag_string=PSD[16]|codec_tag=0x10445350|sample_fmt=s16|sample_rate=44100|channels=1|channel_layout=unknown|bits_per_sample=16|initial_padding=0|id=N/A|r_frame_rate=0/0|avg_frame_rate=0/0|time_base=1/44100|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=705600|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=6|nb_read_packets=6|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:non_diegetic=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|disposition:multilayer=0|tag:encoder=Lavc pcm_s16le|tag:E=mc²
stream|index=1|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=320|height=240|coded_width=320|coded_height=240|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=4:3|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:non_diegetic=0|disposition:captions=0|disposition:descriptions=0
|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|disposition:multilayer=0|tag:encoder=Lavc rawvideo|tag:title=foobar|tag:duration_ts=field-and-tags-conflict-attempt
stream|index=2|codec_name=rawvideo|profile=unknown|codec_type=video|codec_tag_string=RGB[24]|codec_tag=0x18424752|width=100|height=100|coded_width=100|coded_height=100|has_b_frames=0|sample_aspect_ratio=1:1|display_aspect_ratio=1:1|pix_fmt=rgb24|level=-99|color_range=unknown|color_space=unknown|color_transfer=unknown|color_primaries=unknown|chroma_location=unspecified|field_order=unknown|refs=1|id=N/A|r_frame_rate=25/1|avg_frame_rate=25/1|time_base=1/51200|start_pts=0|start_time=0.000000|duration_ts=N/A|duration=N/A|bit_rate=N/A|max_bit_rate=N/A|bits_per_raw_sample=N/A|nb_frames=N/A|nb_read_frames=4|nb_read_packets=4|disposition:default=0|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:non_diegetic=0|disposition:captions=0|disposition:descriptions=0
|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|disposition:multilayer=0|tag:encoder=Lavc rawvideo
diff --git a/tests/ref/fate/ffprobe_csv b/tests/ref/fate/ffprobe_csv
index 37c67bb4e3..174af6d732 100644
--- a/tests/ref/fate/ffprobe_csv
+++ b/tests/ref/fate/ffprobe_csv
@@ -1,31 +1,31 @@
packet,audio,0,0,0.000000,0,0.000000,1024,0.023220,2048,669,K__
frame,audio,0,1,0,0.000000,0,0.000000,0,0.000000,1024,0.023220,669,2048,s16,1024,1,unknown
packet,video,1,0,0.000000,0,0.000000,2048,0.040000,230400,2744,K__
-frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2744,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,1,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,2744,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,video,2,0,0.000000,0,0.000000,2048,0.040000,30000,233165,K__
-frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233165,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,2,1,0,0.000000,0,0.000000,0,0.000000,2048,0.040000,233165,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,audio,0,1024,0.023220,1024,0.023220,1024,0.023220,2048,263170,K__
frame,audio,0,1,1024,0.023220,1024,0.023220,1024,0.023220,1024,0.023220,263170,2048,s16,1024,1,unknown
packet,video,1,2048,0.040000,2048,0.040000,2048,0.040000,230400,265248,K__
-frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265248,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,1,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,265248,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,video,2,2048,0.040000,2048,0.040000,2048,0.040000,30000,495672,K__
-frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495672,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,2,1,2048,0.040000,2048,0.040000,2048,0.040000,2048,0.040000,495672,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,audio,0,2048,0.046440,2048,0.046440,1024,0.023220,2048,525677,K__
frame,audio,0,1,2048,0.046440,2048,0.046440,2048,0.046440,1024,0.023220,525677,2048,s16,1024,1,unknown
packet,audio,0,3072,0.069660,3072,0.069660,1024,0.023220,2048,527748,K__
frame,audio,0,1,3072,0.069660,3072,0.069660,3072,0.069660,1024,0.023220,527748,2048,s16,1024,1,unknown
packet,video,1,4096,0.080000,4096,0.080000,2048,0.040000,230400,529826,K__
-frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529826,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,1,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,529826,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,video,2,4096,0.080000,4096,0.080000,2048,0.040000,30000,760250,K__
-frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760250,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,2,1,4096,0.080000,4096,0.080000,4096,0.080000,2048,0.040000,760250,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,audio,0,4096,0.092880,4096,0.092880,1024,0.023220,2048,790255,K__
frame,audio,0,1,4096,0.092880,4096,0.092880,4096,0.092880,1024,0.023220,790255,2048,s16,1024,1,unknown
packet,audio,0,5120,0.116100,5120,0.116100,393,0.008912,786,792326,K__
frame,audio,0,1,5120,0.116100,5120,0.116100,5120,0.116100,393,0.008912,792326,786,s16,393,1,unknown
packet,video,1,6144,0.120000,6144,0.120000,2048,0.040000,230400,793142,K__
-frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,793142,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,1,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,793142,230400,320,240,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
packet,video,2,6144,0.120000,6144,0.120000,2048,0.040000,30000,1023566,K__
-frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1023566,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified
+frame,video,2,1,6144,0.120000,6144,0.120000,6144,0.120000,2048,0.040000,1023566,30000,100,100,0,0,0,0,rgb24,1:1,I,0,0,0,0,unknown,unknown,unknown,unknown,unspecified,unspecified
stream,0,pcm_s16le,unknown,audio,PSD[16],0x10445350,s16,44100,1,unknown,16,0,N/A,0/0,0/0,1/44100,0,0.000000,N/A,N/A,705600,N/A,N/A,N/A,6,6,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Lavc pcm_s16le,mc²
stream,1,rawvideo,unknown,video,RGB[24],0x18424752,320,240,320,240,0,1:1,4:3,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo,foobar,field-and-tags-conflict-attempt
stream,2,rawvideo,unknown,video,RGB[24],0x18424752,100,100,100,100,0,1:1,1:1,rgb24,-99,unknown,unknown,unknown,unknown,unspecified,unknown,1,N/A,25/1,25/1,1/51200,0,0.000000,N/A,N/A,N/A,N/A,N/A,N/A,4,4,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,Lavc rawvideo
diff --git a/tests/ref/fate/ffprobe_default b/tests/ref/fate/ffprobe_default
index 2d38d4d211..4289f66bbe 100644
--- a/tests/ref/fate/ffprobe_default
+++ b/tests/ref/fate/ffprobe_default
@@ -75,6 +75,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=video
@@ -121,6 +122,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=audio
@@ -199,6 +201,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=video
@@ -245,6 +248,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=audio
@@ -355,6 +359,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=video
@@ -401,6 +406,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=audio
@@ -511,6 +517,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[PACKET]
codec_type=video
@@ -557,6 +564,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[/FRAME]
[STREAM]
index=0
diff --git a/tests/ref/fate/ffprobe_flat b/tests/ref/fate/ffprobe_flat
index b9aac8a007..114def58bc 100644
--- a/tests/ref/fate/ffprobe_flat
+++ b/tests/ref/fate/ffprobe_flat
@@ -68,6 +68,7 @@ packets_and_frames.frame.1.color_space="unknown"
packets_and_frames.frame.1.color_primaries="unknown"
packets_and_frames.frame.1.color_transfer="unknown"
packets_and_frames.frame.1.chroma_location="unspecified"
+packets_and_frames.frame.1.alpha_mode="unspecified"
packets_and_frames.packet.2.codec_type="video"
packets_and_frames.packet.2.stream_index=2
packets_and_frames.packet.2.pts=0
@@ -110,6 +111,7 @@ packets_and_frames.frame.2.color_space="unknown"
packets_and_frames.frame.2.color_primaries="unknown"
packets_and_frames.frame.2.color_transfer="unknown"
packets_and_frames.frame.2.chroma_location="unspecified"
+packets_and_frames.frame.2.alpha_mode="unspecified"
packets_and_frames.packet.3.codec_type="audio"
packets_and_frames.packet.3.stream_index=0
packets_and_frames.packet.3.pts=1024
@@ -180,6 +182,7 @@ packets_and_frames.frame.4.color_space="unknown"
packets_and_frames.frame.4.color_primaries="unknown"
packets_and_frames.frame.4.color_transfer="unknown"
packets_and_frames.frame.4.chroma_location="unspecified"
+packets_and_frames.frame.4.alpha_mode="unspecified"
packets_and_frames.packet.5.codec_type="video"
packets_and_frames.packet.5.stream_index=2
packets_and_frames.packet.5.pts=2048
@@ -222,6 +225,7 @@ packets_and_frames.frame.5.color_space="unknown"
packets_and_frames.frame.5.color_primaries="unknown"
packets_and_frames.frame.5.color_transfer="unknown"
packets_and_frames.frame.5.chroma_location="unspecified"
+packets_and_frames.frame.5.alpha_mode="unspecified"
packets_and_frames.packet.6.codec_type="audio"
packets_and_frames.packet.6.stream_index=0
packets_and_frames.packet.6.pts=2048
@@ -320,6 +324,7 @@ packets_and_frames.frame.8.color_space="unknown"
packets_and_frames.frame.8.color_primaries="unknown"
packets_and_frames.frame.8.color_transfer="unknown"
packets_and_frames.frame.8.chroma_location="unspecified"
+packets_and_frames.frame.8.alpha_mode="unspecified"
packets_and_frames.packet.9.codec_type="video"
packets_and_frames.packet.9.stream_index=2
packets_and_frames.packet.9.pts=4096
@@ -362,6 +367,7 @@ packets_and_frames.frame.9.color_space="unknown"
packets_and_frames.frame.9.color_primaries="unknown"
packets_and_frames.frame.9.color_transfer="unknown"
packets_and_frames.frame.9.chroma_location="unspecified"
+packets_and_frames.frame.9.alpha_mode="unspecified"
packets_and_frames.packet.10.codec_type="audio"
packets_and_frames.packet.10.stream_index=0
packets_and_frames.packet.10.pts=4096
@@ -460,6 +466,7 @@ packets_and_frames.frame.12.color_space="unknown"
packets_and_frames.frame.12.color_primaries="unknown"
packets_and_frames.frame.12.color_transfer="unknown"
packets_and_frames.frame.12.chroma_location="unspecified"
+packets_and_frames.frame.12.alpha_mode="unspecified"
packets_and_frames.packet.13.codec_type="video"
packets_and_frames.packet.13.stream_index=2
packets_and_frames.packet.13.pts=6144
@@ -502,6 +509,7 @@ packets_and_frames.frame.13.color_space="unknown"
packets_and_frames.frame.13.color_primaries="unknown"
packets_and_frames.frame.13.color_transfer="unknown"
packets_and_frames.frame.13.chroma_location="unspecified"
+packets_and_frames.frame.13.alpha_mode="unspecified"
streams.stream.0.index=0
streams.stream.0.codec_name="pcm_s16le"
streams.stream.0.profile="unknown"
diff --git a/tests/ref/fate/ffprobe_ini b/tests/ref/fate/ffprobe_ini
index d353c09339..c4b6a59b30 100644
--- a/tests/ref/fate/ffprobe_ini
+++ b/tests/ref/fate/ffprobe_ini
@@ -77,6 +77,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.2]
codec_type=video
@@ -123,6 +124,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.3]
codec_type=audio
@@ -201,6 +203,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.5]
codec_type=video
@@ -247,6 +250,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.6]
codec_type=audio
@@ -357,6 +361,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.9]
codec_type=video
@@ -403,6 +408,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.10]
codec_type=audio
@@ -513,6 +519,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[packets_and_frames.packet.13]
codec_type=video
@@ -559,6 +566,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[streams.stream.0]
index=0
diff --git a/tests/ref/fate/h264-dts_5frames b/tests/ref/fate/h264-dts_5frames
index 376e328e89..1e66e3854b 100644
--- a/tests/ref/fate/h264-dts_5frames
+++ b/tests/ref/fate/h264-dts_5frames
@@ -30,6 +30,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
+alpha_mode=unspecified
[/FRAME]
[FRAME]
media_type=video
@@ -63,6 +64,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
+alpha_mode=unspecified
[/FRAME]
[FRAME]
media_type=video
@@ -96,6 +98,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
+alpha_mode=unspecified
[/FRAME]
[FRAME]
media_type=video
@@ -129,6 +132,7 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
+alpha_mode=unspecified
[/FRAME]
[FRAME]
media_type=video
@@ -162,4 +166,5 @@ color_space=unknown
color_primaries=unknown
color_transfer=unknown
chroma_location=left
+alpha_mode=unspecified
[/FRAME]
diff --git a/tests/ref/fate/jpg-icc b/tests/ref/fate/jpg-icc
index e12373e953..4fc058c7ce 100644
--- a/tests/ref/fate/jpg-icc
+++ b/tests/ref/fate/jpg-icc
@@ -38,6 +38,7 @@ color_space=bt470bg
color_primaries=unknown
color_transfer=unknown
chroma_location=center
+alpha_mode=unspecified
[SIDE_DATA]
side_data_type=ICC profile
size=3144
diff --git a/tests/ref/fate/mov-zombie b/tests/ref/fate/mov-zombie
index 5b9cd74f63..84a5168adc 100644
--- a/tests/ref/fate/mov-zombie
+++ b/tests/ref/fate/mov-zombie
@@ -1,132 +1,132 @@
packet|codec_type=video|stream_index=0|pts=0|pts_time=0.000000|dts=-3004|dts_time=-0.033378|duration=2437|duration_time=0.027078|size=4133|pos=11309|flags=K__
packet|codec_type=video|stream_index=0|pts=5440|pts_time=0.060444|dts=-567|dts_time=-0.006300|duration=3003|duration_time=0.033367|size=1077|pos=15442|flags=___
-frame|media_type=video|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=2437|duration_time=0.027078|pkt_pos=11309|pkt_size=4133|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=1|pts=0|pts_time=0.000000|pkt_dts=-567|pkt_dts_time=-0.006300|best_effort_timestamp=0|best_effort_timestamp_time=0.000000|duration=2437|duration_time=0.027078|pkt_pos=11309|pkt_size=4133|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=2437|pts_time=0.027078|dts=2436|dts_time=0.027067|duration=3003|duration_time=0.033367|size=355|pos=16519|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=2437|pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|duration=3003|duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=2437|pts_time=0.027078|pkt_dts=2436|pkt_dts_time=0.027067|best_effort_timestamp=2437|best_effort_timestamp_time=0.027078|duration=3003|duration_time=0.033367|pkt_pos=16519|pkt_size=355|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=11446|pts_time=0.127178|dts=5439|dts_time=0.060433|duration=3003|duration_time=0.033367|size=1110|pos=16874|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=5440|pts_time=0.060444|pkt_dts=5439|pkt_dts_time=0.060433|best_effort_timestamp=5440|best_effort_timestamp_time=0.060444|duration=3003|duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=5440|pts_time=0.060444|pkt_dts=5439|pkt_dts_time=0.060433|best_effort_timestamp=5440|best_effort_timestamp_time=0.060444|duration=3003|duration_time=0.033367|pkt_pos=15442|pkt_size=1077|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=8443|pts_time=0.093811|dts=8442|dts_time=0.093800|duration=3003|duration_time=0.033367|size=430|pos=17984|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=8443|pts_time=0.093811|pkt_dts=8442|pkt_dts_time=0.093800|best_effort_timestamp=8443|best_effort_timestamp_time=0.093811|duration=3003|duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=8443|pts_time=0.093811|pkt_dts=8442|pkt_dts_time=0.093800|best_effort_timestamp=8443|best_effort_timestamp_time=0.093811|duration=3003|duration_time=0.033367|pkt_pos=17984|pkt_size=430|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=17452|pts_time=0.193911|dts=11445|dts_time=0.127167|duration=3003|duration_time=0.033367|size=1485|pos=18414|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=11446|pts_time=0.127178|pkt_dts=11445|pkt_dts_time=0.127167|best_effort_timestamp=11446|best_effort_timestamp_time=0.127178|duration=3003|duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=11446|pts_time=0.127178|pkt_dts=11445|pkt_dts_time=0.127167|best_effort_timestamp=11446|best_effort_timestamp_time=0.127178|duration=3003|duration_time=0.033367|pkt_pos=16874|pkt_size=1110|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=14449|pts_time=0.160544|dts=14448|dts_time=0.160533|duration=3003|duration_time=0.033367|size=1005|pos=19899|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=14449|pts_time=0.160544|pkt_dts=14448|pkt_dts_time=0.160533|best_effort_timestamp=14449|best_effort_timestamp_time=0.160544|duration=3003|duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=14449|pts_time=0.160544|pkt_dts=14448|pkt_dts_time=0.160533|best_effort_timestamp=14449|best_effort_timestamp_time=0.160544|duration=3003|duration_time=0.033367|pkt_pos=19899|pkt_size=1005|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=23458|pts_time=0.260644|dts=17451|dts_time=0.193900|duration=3003|duration_time=0.033367|size=1976|pos=20904|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=17452|pts_time=0.193911|pkt_dts=17451|pkt_dts_time=0.193900|best_effort_timestamp=17452|best_effort_timestamp_time=0.193911|duration=3003|duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=17452|pts_time=0.193911|pkt_dts=17451|pkt_dts_time=0.193900|best_effort_timestamp=17452|best_effort_timestamp_time=0.193911|duration=3003|duration_time=0.033367|pkt_pos=18414|pkt_size=1485|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=20455|pts_time=0.227278|dts=20454|dts_time=0.227267|duration=3003|duration_time=0.033367|size=904|pos=22880|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=20455|pts_time=0.227278|pkt_dts=20454|pkt_dts_time=0.227267|best_effort_timestamp=20455|best_effort_timestamp_time=0.227278|duration=3003|duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=20455|pts_time=0.227278|pkt_dts=20454|pkt_dts_time=0.227267|best_effort_timestamp=20455|best_effort_timestamp_time=0.227278|duration=3003|duration_time=0.033367|pkt_pos=22880|pkt_size=904|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=29464|pts_time=0.327378|dts=23457|dts_time=0.260633|duration=3003|duration_time=0.033367|size=1254|pos=23784|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=23458|pts_time=0.260644|pkt_dts=23457|pkt_dts_time=0.260633|best_effort_timestamp=23458|best_effort_timestamp_time=0.260644|duration=3003|duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=23458|pts_time=0.260644|pkt_dts=23457|pkt_dts_time=0.260633|best_effort_timestamp=23458|best_effort_timestamp_time=0.260644|duration=3003|duration_time=0.033367|pkt_pos=20904|pkt_size=1976|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=26461|pts_time=0.294011|dts=26460|dts_time=0.294000|duration=3003|duration_time=0.033367|size=700|pos=25038|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=26461|pts_time=0.294011|pkt_dts=26460|pkt_dts_time=0.294000|best_effort_timestamp=26461|best_effort_timestamp_time=0.294011|duration=3003|duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=26461|pts_time=0.294011|pkt_dts=26460|pkt_dts_time=0.294000|best_effort_timestamp=26461|best_effort_timestamp_time=0.294011|duration=3003|duration_time=0.033367|pkt_pos=25038|pkt_size=700|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=35470|pts_time=0.394111|dts=29463|dts_time=0.327367|duration=3003|duration_time=0.033367|size=1311|pos=25738|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=29464|pts_time=0.327378|pkt_dts=29463|pkt_dts_time=0.327367|best_effort_timestamp=29464|best_effort_timestamp_time=0.327378|duration=3003|duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=29464|pts_time=0.327378|pkt_dts=29463|pkt_dts_time=0.327367|best_effort_timestamp=29464|best_effort_timestamp_time=0.327378|duration=3003|duration_time=0.033367|pkt_pos=23784|pkt_size=1254|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=32467|pts_time=0.360744|dts=32466|dts_time=0.360733|duration=3003|duration_time=0.033367|size=631|pos=27049|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=32467|pts_time=0.360744|pkt_dts=32466|pkt_dts_time=0.360733|best_effort_timestamp=32467|best_effort_timestamp_time=0.360744|duration=3003|duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=32467|pts_time=0.360744|pkt_dts=32466|pkt_dts_time=0.360733|best_effort_timestamp=32467|best_effort_timestamp_time=0.360744|duration=3003|duration_time=0.033367|pkt_pos=27049|pkt_size=631|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=41476|pts_time=0.460844|dts=35469|dts_time=0.394100|duration=3003|duration_time=0.033367|size=1296|pos=27680|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=35470|pts_time=0.394111|pkt_dts=35469|pkt_dts_time=0.394100|best_effort_timestamp=35470|best_effort_timestamp_time=0.394111|duration=3003|duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=35470|pts_time=0.394111|pkt_dts=35469|pkt_dts_time=0.394100|best_effort_timestamp=35470|best_effort_timestamp_time=0.394111|duration=3003|duration_time=0.033367|pkt_pos=25738|pkt_size=1311|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=38473|pts_time=0.427478|dts=38472|dts_time=0.427467|duration=3003|duration_time=0.033367|size=466|pos=28976|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=38473|pts_time=0.427478|pkt_dts=38472|pkt_dts_time=0.427467|best_effort_timestamp=38473|best_effort_timestamp_time=0.427478|duration=3003|duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=38473|pts_time=0.427478|pkt_dts=38472|pkt_dts_time=0.427467|best_effort_timestamp=38473|best_effort_timestamp_time=0.427478|duration=3003|duration_time=0.033367|pkt_pos=28976|pkt_size=466|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=47482|pts_time=0.527578|dts=41475|dts_time=0.460833|duration=3003|duration_time=0.033367|size=1638|pos=29442|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=41476|pts_time=0.460844|pkt_dts=41475|pkt_dts_time=0.460833|best_effort_timestamp=41476|best_effort_timestamp_time=0.460844|duration=3003|duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=41476|pts_time=0.460844|pkt_dts=41475|pkt_dts_time=0.460833|best_effort_timestamp=41476|best_effort_timestamp_time=0.460844|duration=3003|duration_time=0.033367|pkt_pos=27680|pkt_size=1296|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=44479|pts_time=0.494211|dts=44478|dts_time=0.494200|duration=3003|duration_time=0.033367|size=907|pos=31080|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=44479|pts_time=0.494211|pkt_dts=44478|pkt_dts_time=0.494200|best_effort_timestamp=44479|best_effort_timestamp_time=0.494211|duration=3003|duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=44479|pts_time=0.494211|pkt_dts=44478|pkt_dts_time=0.494200|best_effort_timestamp=44479|best_effort_timestamp_time=0.494211|duration=3003|duration_time=0.033367|pkt_pos=31080|pkt_size=907|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=53488|pts_time=0.594311|dts=47481|dts_time=0.527567|duration=3003|duration_time=0.033367|size=1362|pos=31987|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=47482|pts_time=0.527578|pkt_dts=47481|pkt_dts_time=0.527567|best_effort_timestamp=47482|best_effort_timestamp_time=0.527578|duration=3003|duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=47482|pts_time=0.527578|pkt_dts=47481|pkt_dts_time=0.527567|best_effort_timestamp=47482|best_effort_timestamp_time=0.527578|duration=3003|duration_time=0.033367|pkt_pos=29442|pkt_size=1638|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=50485|pts_time=0.560944|dts=50484|dts_time=0.560933|duration=3003|duration_time=0.033367|size=682|pos=33349|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=50485|pts_time=0.560944|pkt_dts=50484|pkt_dts_time=0.560933|best_effort_timestamp=50485|best_effort_timestamp_time=0.560944|duration=3003|duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=50485|pts_time=0.560944|pkt_dts=50484|pkt_dts_time=0.560933|best_effort_timestamp=50485|best_effort_timestamp_time=0.560944|duration=3003|duration_time=0.033367|pkt_pos=33349|pkt_size=682|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=59494|pts_time=0.661044|dts=53487|dts_time=0.594300|duration=3003|duration_time=0.033367|size=2917|pos=34031|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=53488|pts_time=0.594311|pkt_dts=53487|pkt_dts_time=0.594300|best_effort_timestamp=53488|best_effort_timestamp_time=0.594311|duration=3003|duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=53488|pts_time=0.594311|pkt_dts=53487|pkt_dts_time=0.594300|best_effort_timestamp=53488|best_effort_timestamp_time=0.594311|duration=3003|duration_time=0.033367|pkt_pos=31987|pkt_size=1362|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=56491|pts_time=0.627678|dts=56490|dts_time=0.627667|duration=3003|duration_time=0.033367|size=1174|pos=36948|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=56491|pts_time=0.627678|pkt_dts=56490|pkt_dts_time=0.627667|best_effort_timestamp=56491|best_effort_timestamp_time=0.627678|duration=3003|duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=56491|pts_time=0.627678|pkt_dts=56490|pkt_dts_time=0.627667|best_effort_timestamp=56491|best_effort_timestamp_time=0.627678|duration=3003|duration_time=0.033367|pkt_pos=36948|pkt_size=1174|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=65500|pts_time=0.727778|dts=59493|dts_time=0.661033|duration=3003|duration_time=0.033367|size=1748|pos=38122|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=59494|pts_time=0.661044|pkt_dts=59493|pkt_dts_time=0.661033|best_effort_timestamp=59494|best_effort_timestamp_time=0.661044|duration=3003|duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=59494|pts_time=0.661044|pkt_dts=59493|pkt_dts_time=0.661033|best_effort_timestamp=59494|best_effort_timestamp_time=0.661044|duration=3003|duration_time=0.033367|pkt_pos=34031|pkt_size=2917|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=62497|pts_time=0.694411|dts=62496|dts_time=0.694400|duration=3003|duration_time=0.033367|size=926|pos=39870|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=62497|pts_time=0.694411|pkt_dts=62496|pkt_dts_time=0.694400|best_effort_timestamp=62497|best_effort_timestamp_time=0.694411|duration=3003|duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=62497|pts_time=0.694411|pkt_dts=62496|pkt_dts_time=0.694400|best_effort_timestamp=62497|best_effort_timestamp_time=0.694411|duration=3003|duration_time=0.033367|pkt_pos=39870|pkt_size=926|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=68503|pts_time=0.761144|dts=65499|dts_time=0.727767|duration=3003|duration_time=0.033367|size=918|pos=40796|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=65500|pts_time=0.727778|pkt_dts=65499|pkt_dts_time=0.727767|best_effort_timestamp=65500|best_effort_timestamp_time=0.727778|duration=3003|duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=65500|pts_time=0.727778|pkt_dts=65499|pkt_dts_time=0.727767|best_effort_timestamp=65500|best_effort_timestamp_time=0.727778|duration=3003|duration_time=0.033367|pkt_pos=38122|pkt_size=1748|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=71506|pts_time=0.794511|dts=68502|dts_time=0.761133|duration=3003|duration_time=0.033367|size=3846|pos=41714|flags=K__
-frame|media_type=video|stream_index=0|key_frame=0|pts=68503|pts_time=0.761144|pkt_dts=68502|pkt_dts_time=0.761133|best_effort_timestamp=68503|best_effort_timestamp_time=0.761144|duration=3003|duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=68503|pts_time=0.761144|pkt_dts=68502|pkt_dts_time=0.761133|best_effort_timestamp=68503|best_effort_timestamp_time=0.761144|duration=3003|duration_time=0.033367|pkt_pos=40796|pkt_size=918|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=77512|pts_time=0.861244|dts=71505|dts_time=0.794500|duration=3003|duration_time=0.033367|size=1932|pos=45560|flags=___
-frame|media_type=video|stream_index=0|key_frame=1|pts=71506|pts_time=0.794511|pkt_dts=71505|pkt_dts_time=0.794500|best_effort_timestamp=71506|best_effort_timestamp_time=0.794511|duration=3003|duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=1|pts=71506|pts_time=0.794511|pkt_dts=71505|pkt_dts_time=0.794500|best_effort_timestamp=71506|best_effort_timestamp_time=0.794511|duration=3003|duration_time=0.033367|pkt_pos=41714|pkt_size=3846|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=74509|pts_time=0.827878|dts=74508|dts_time=0.827867|duration=3003|duration_time=0.033367|size=1159|pos=47492|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=74509|pts_time=0.827878|pkt_dts=74508|pkt_dts_time=0.827867|best_effort_timestamp=74509|best_effort_timestamp_time=0.827878|duration=3003|duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=74509|pts_time=0.827878|pkt_dts=74508|pkt_dts_time=0.827867|best_effort_timestamp=74509|best_effort_timestamp_time=0.827878|duration=3003|duration_time=0.033367|pkt_pos=47492|pkt_size=1159|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=83518|pts_time=0.927978|dts=77511|dts_time=0.861233|duration=3003|duration_time=0.033367|size=1522|pos=48651|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=77512|pts_time=0.861244|pkt_dts=77511|pkt_dts_time=0.861233|best_effort_timestamp=77512|best_effort_timestamp_time=0.861244|duration=3003|duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=77512|pts_time=0.861244|pkt_dts=77511|pkt_dts_time=0.861233|best_effort_timestamp=77512|best_effort_timestamp_time=0.861244|duration=3003|duration_time=0.033367|pkt_pos=45560|pkt_size=1932|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=80515|pts_time=0.894611|dts=80514|dts_time=0.894600|duration=3003|duration_time=0.033367|size=719|pos=50173|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=80515|pts_time=0.894611|pkt_dts=80514|pkt_dts_time=0.894600|best_effort_timestamp=80515|best_effort_timestamp_time=0.894611|duration=3003|duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=80515|pts_time=0.894611|pkt_dts=80514|pkt_dts_time=0.894600|best_effort_timestamp=80515|best_effort_timestamp_time=0.894611|duration=3003|duration_time=0.033367|pkt_pos=50173|pkt_size=719|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=89524|pts_time=0.994711|dts=83517|dts_time=0.927967|duration=3003|duration_time=0.033367|size=1700|pos=50892|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=83518|pts_time=0.927978|pkt_dts=83517|pkt_dts_time=0.927967|best_effort_timestamp=83518|best_effort_timestamp_time=0.927978|duration=3003|duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=83518|pts_time=0.927978|pkt_dts=83517|pkt_dts_time=0.927967|best_effort_timestamp=83518|best_effort_timestamp_time=0.927978|duration=3003|duration_time=0.033367|pkt_pos=48651|pkt_size=1522|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=86521|pts_time=0.961344|dts=86520|dts_time=0.961333|duration=3003|duration_time=0.033367|size=1099|pos=52592|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=86521|pts_time=0.961344|pkt_dts=86520|pkt_dts_time=0.961333|best_effort_timestamp=86521|best_effort_timestamp_time=0.961344|duration=3003|duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=86521|pts_time=0.961344|pkt_dts=86520|pkt_dts_time=0.961333|best_effort_timestamp=86521|best_effort_timestamp_time=0.961344|duration=3003|duration_time=0.033367|pkt_pos=52592|pkt_size=1099|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=95530|pts_time=1.061444|dts=89523|dts_time=0.994700|duration=3003|duration_time=0.033367|size=2558|pos=53691|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=89524|pts_time=0.994711|pkt_dts=89523|pkt_dts_time=0.994700|best_effort_timestamp=89524|best_effort_timestamp_time=0.994711|duration=3003|duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=89524|pts_time=0.994711|pkt_dts=89523|pkt_dts_time=0.994700|best_effort_timestamp=89524|best_effort_timestamp_time=0.994711|duration=3003|duration_time=0.033367|pkt_pos=50892|pkt_size=1700|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=92527|pts_time=1.028078|dts=92526|dts_time=1.028067|duration=3003|duration_time=0.033367|size=1008|pos=56249|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=92527|pts_time=1.028078|pkt_dts=92526|pkt_dts_time=1.028067|best_effort_timestamp=92527|best_effort_timestamp_time=1.028078|duration=3003|duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=92527|pts_time=1.028078|pkt_dts=92526|pkt_dts_time=1.028067|best_effort_timestamp=92527|best_effort_timestamp_time=1.028078|duration=3003|duration_time=0.033367|pkt_pos=56249|pkt_size=1008|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=101536|pts_time=1.128178|dts=95529|dts_time=1.061433|duration=3003|duration_time=0.033367|size=1236|pos=57257|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=95530|pts_time=1.061444|pkt_dts=95529|pkt_dts_time=1.061433|best_effort_timestamp=95530|best_effort_timestamp_time=1.061444|duration=3003|duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=95530|pts_time=1.061444|pkt_dts=95529|pkt_dts_time=1.061433|best_effort_timestamp=95530|best_effort_timestamp_time=1.061444|duration=3003|duration_time=0.033367|pkt_pos=53691|pkt_size=2558|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=98533|pts_time=1.094811|dts=98532|dts_time=1.094800|duration=3003|duration_time=0.033367|size=607|pos=58493|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=98533|pts_time=1.094811|pkt_dts=98532|pkt_dts_time=1.094800|best_effort_timestamp=98533|best_effort_timestamp_time=1.094811|duration=3003|duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=98533|pts_time=1.094811|pkt_dts=98532|pkt_dts_time=1.094800|best_effort_timestamp=98533|best_effort_timestamp_time=1.094811|duration=3003|duration_time=0.033367|pkt_pos=58493|pkt_size=607|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=107542|pts_time=1.194911|dts=101535|dts_time=1.128167|duration=3003|duration_time=0.033367|size=1883|pos=59100|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=101536|pts_time=1.128178|pkt_dts=101535|pkt_dts_time=1.128167|best_effort_timestamp=101536|best_effort_timestamp_time=1.128178|duration=3003|duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=101536|pts_time=1.128178|pkt_dts=101535|pkt_dts_time=1.128167|best_effort_timestamp=101536|best_effort_timestamp_time=1.128178|duration=3003|duration_time=0.033367|pkt_pos=57257|pkt_size=1236|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=104539|pts_time=1.161544|dts=104538|dts_time=1.161533|duration=3003|duration_time=0.033367|size=893|pos=60983|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=104539|pts_time=1.161544|pkt_dts=104538|pkt_dts_time=1.161533|best_effort_timestamp=104539|best_effort_timestamp_time=1.161544|duration=3003|duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=104539|pts_time=1.161544|pkt_dts=104538|pkt_dts_time=1.161533|best_effort_timestamp=104539|best_effort_timestamp_time=1.161544|duration=3003|duration_time=0.033367|pkt_pos=60983|pkt_size=893|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=113548|pts_time=1.261644|dts=107541|dts_time=1.194900|duration=3003|duration_time=0.033367|size=1305|pos=61876|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=107542|pts_time=1.194911|pkt_dts=107541|pkt_dts_time=1.194900|best_effort_timestamp=107542|best_effort_timestamp_time=1.194911|duration=3003|duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=107542|pts_time=1.194911|pkt_dts=107541|pkt_dts_time=1.194900|best_effort_timestamp=107542|best_effort_timestamp_time=1.194911|duration=3003|duration_time=0.033367|pkt_pos=59100|pkt_size=1883|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=110545|pts_time=1.228278|dts=110544|dts_time=1.228267|duration=3003|duration_time=0.033367|size=472|pos=63181|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=110545|pts_time=1.228278|pkt_dts=110544|pkt_dts_time=1.228267|best_effort_timestamp=110545|best_effort_timestamp_time=1.228278|duration=3003|duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=110545|pts_time=1.228278|pkt_dts=110544|pkt_dts_time=1.228267|best_effort_timestamp=110545|best_effort_timestamp_time=1.228278|duration=3003|duration_time=0.033367|pkt_pos=63181|pkt_size=472|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=119554|pts_time=1.328378|dts=113547|dts_time=1.261633|duration=3003|duration_time=0.033367|size=1411|pos=63653|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=113548|pts_time=1.261644|pkt_dts=113547|pkt_dts_time=1.261633|best_effort_timestamp=113548|best_effort_timestamp_time=1.261644|duration=3003|duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=113548|pts_time=1.261644|pkt_dts=113547|pkt_dts_time=1.261633|best_effort_timestamp=113548|best_effort_timestamp_time=1.261644|duration=3003|duration_time=0.033367|pkt_pos=61876|pkt_size=1305|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=116551|pts_time=1.295011|dts=116550|dts_time=1.295000|duration=3003|duration_time=0.033367|size=616|pos=65064|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=116551|pts_time=1.295011|pkt_dts=116550|pkt_dts_time=1.295000|best_effort_timestamp=116551|best_effort_timestamp_time=1.295011|duration=3003|duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=116551|pts_time=1.295011|pkt_dts=116550|pkt_dts_time=1.295000|best_effort_timestamp=116551|best_effort_timestamp_time=1.295011|duration=3003|duration_time=0.033367|pkt_pos=65064|pkt_size=616|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=125560|pts_time=1.395111|dts=119553|dts_time=1.328367|duration=3003|duration_time=0.033367|size=1291|pos=65680|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=119554|pts_time=1.328378|pkt_dts=119553|pkt_dts_time=1.328367|best_effort_timestamp=119554|best_effort_timestamp_time=1.328378|duration=3003|duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=119554|pts_time=1.328378|pkt_dts=119553|pkt_dts_time=1.328367|best_effort_timestamp=119554|best_effort_timestamp_time=1.328378|duration=3003|duration_time=0.033367|pkt_pos=63653|pkt_size=1411|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=122557|pts_time=1.361744|dts=122556|dts_time=1.361733|duration=3003|duration_time=0.033367|size=470|pos=66971|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=122557|pts_time=1.361744|pkt_dts=122556|pkt_dts_time=1.361733|best_effort_timestamp=122557|best_effort_timestamp_time=1.361744|duration=3003|duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=122557|pts_time=1.361744|pkt_dts=122556|pkt_dts_time=1.361733|best_effort_timestamp=122557|best_effort_timestamp_time=1.361744|duration=3003|duration_time=0.033367|pkt_pos=66971|pkt_size=470|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=131566|pts_time=1.461844|dts=125559|dts_time=1.395100|duration=3003|duration_time=0.033367|size=1977|pos=67441|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=125560|pts_time=1.395111|pkt_dts=125559|pkt_dts_time=1.395100|best_effort_timestamp=125560|best_effort_timestamp_time=1.395111|duration=3003|duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=125560|pts_time=1.395111|pkt_dts=125559|pkt_dts_time=1.395100|best_effort_timestamp=125560|best_effort_timestamp_time=1.395111|duration=3003|duration_time=0.033367|pkt_pos=65680|pkt_size=1291|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=128563|pts_time=1.428478|dts=128562|dts_time=1.428467|duration=3003|duration_time=0.033367|size=436|pos=69418|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=128563|pts_time=1.428478|pkt_dts=128562|pkt_dts_time=1.428467|best_effort_timestamp=128563|best_effort_timestamp_time=1.428478|duration=3003|duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=128563|pts_time=1.428478|pkt_dts=128562|pkt_dts_time=1.428467|best_effort_timestamp=128563|best_effort_timestamp_time=1.428478|duration=3003|duration_time=0.033367|pkt_pos=69418|pkt_size=436|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=137572|pts_time=1.528578|dts=131565|dts_time=1.461833|duration=3003|duration_time=0.033367|size=2566|pos=69854|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=131566|pts_time=1.461844|pkt_dts=131565|pkt_dts_time=1.461833|best_effort_timestamp=131566|best_effort_timestamp_time=1.461844|duration=3003|duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=131566|pts_time=1.461844|pkt_dts=131565|pkt_dts_time=1.461833|best_effort_timestamp=131566|best_effort_timestamp_time=1.461844|duration=3003|duration_time=0.033367|pkt_pos=67441|pkt_size=1977|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=134569|pts_time=1.495211|dts=134568|dts_time=1.495200|duration=3003|duration_time=0.033367|size=886|pos=72420|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=134569|pts_time=1.495211|pkt_dts=134568|pkt_dts_time=1.495200|best_effort_timestamp=134569|best_effort_timestamp_time=1.495211|duration=3003|duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=134569|pts_time=1.495211|pkt_dts=134568|pkt_dts_time=1.495200|best_effort_timestamp=134569|best_effort_timestamp_time=1.495211|duration=3003|duration_time=0.033367|pkt_pos=72420|pkt_size=886|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=140575|pts_time=1.561944|dts=137571|dts_time=1.528567|duration=3003|duration_time=0.033367|size=1330|pos=73306|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=137572|pts_time=1.528578|pkt_dts=137571|pkt_dts_time=1.528567|best_effort_timestamp=137572|best_effort_timestamp_time=1.528578|duration=3003|duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=137572|pts_time=1.528578|pkt_dts=137571|pkt_dts_time=1.528567|best_effort_timestamp=137572|best_effort_timestamp_time=1.528578|duration=3003|duration_time=0.033367|pkt_pos=69854|pkt_size=2566|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=143578|pts_time=1.595311|dts=140574|dts_time=1.561933|duration=3003|duration_time=0.033367|size=2227|pos=74636|flags=K__
-frame|media_type=video|stream_index=0|key_frame=0|pts=140575|pts_time=1.561944|pkt_dts=140574|pkt_dts_time=1.561933|best_effort_timestamp=140575|best_effort_timestamp_time=1.561944|duration=3003|duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=140575|pts_time=1.561944|pkt_dts=140574|pkt_dts_time=1.561933|best_effort_timestamp=140575|best_effort_timestamp_time=1.561944|duration=3003|duration_time=0.033367|pkt_pos=73306|pkt_size=1330|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=149584|pts_time=1.662044|dts=143577|dts_time=1.595300|duration=3003|duration_time=0.033367|size=2210|pos=76863|flags=___
-frame|media_type=video|stream_index=0|key_frame=1|pts=143578|pts_time=1.595311|pkt_dts=143577|pkt_dts_time=1.595300|best_effort_timestamp=143578|best_effort_timestamp_time=1.595311|duration=3003|duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=1|pts=143578|pts_time=1.595311|pkt_dts=143577|pkt_dts_time=1.595300|best_effort_timestamp=143578|best_effort_timestamp_time=1.595311|duration=3003|duration_time=0.033367|pkt_pos=74636|pkt_size=2227|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=I|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=146581|pts_time=1.628678|dts=146580|dts_time=1.628667|duration=3003|duration_time=0.033367|size=1498|pos=79073|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=146581|pts_time=1.628678|pkt_dts=146580|pkt_dts_time=1.628667|best_effort_timestamp=146581|best_effort_timestamp_time=1.628678|duration=3003|duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=146581|pts_time=1.628678|pkt_dts=146580|pkt_dts_time=1.628667|best_effort_timestamp=146581|best_effort_timestamp_time=1.628678|duration=3003|duration_time=0.033367|pkt_pos=79073|pkt_size=1498|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=155590|pts_time=1.728778|dts=149583|dts_time=1.662033|duration=3003|duration_time=0.033367|size=1721|pos=80571|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=149584|pts_time=1.662044|pkt_dts=149583|pkt_dts_time=1.662033|best_effort_timestamp=149584|best_effort_timestamp_time=1.662044|duration=3003|duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=149584|pts_time=1.662044|pkt_dts=149583|pkt_dts_time=1.662033|best_effort_timestamp=149584|best_effort_timestamp_time=1.662044|duration=3003|duration_time=0.033367|pkt_pos=76863|pkt_size=2210|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=152587|pts_time=1.695411|dts=152586|dts_time=1.695400|duration=3003|duration_time=0.033367|size=1238|pos=82292|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=152587|pts_time=1.695411|pkt_dts=152586|pkt_dts_time=1.695400|best_effort_timestamp=152587|best_effort_timestamp_time=1.695411|duration=3003|duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=152587|pts_time=1.695411|pkt_dts=152586|pkt_dts_time=1.695400|best_effort_timestamp=152587|best_effort_timestamp_time=1.695411|duration=3003|duration_time=0.033367|pkt_pos=82292|pkt_size=1238|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=161596|pts_time=1.795511|dts=155589|dts_time=1.728767|duration=3003|duration_time=0.033367|size=1753|pos=83530|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=155590|pts_time=1.728778|pkt_dts=155589|pkt_dts_time=1.728767|best_effort_timestamp=155590|best_effort_timestamp_time=1.728778|duration=3003|duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=155590|pts_time=1.728778|pkt_dts=155589|pkt_dts_time=1.728767|best_effort_timestamp=155590|best_effort_timestamp_time=1.728778|duration=3003|duration_time=0.033367|pkt_pos=80571|pkt_size=1721|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=158593|pts_time=1.762144|dts=158592|dts_time=1.762133|duration=3003|duration_time=0.033367|size=1014|pos=85283|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=158593|pts_time=1.762144|pkt_dts=158592|pkt_dts_time=1.762133|best_effort_timestamp=158593|best_effort_timestamp_time=1.762144|duration=3003|duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=158593|pts_time=1.762144|pkt_dts=158592|pkt_dts_time=1.762133|best_effort_timestamp=158593|best_effort_timestamp_time=1.762144|duration=3003|duration_time=0.033367|pkt_pos=85283|pkt_size=1014|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=167602|pts_time=1.862244|dts=161595|dts_time=1.795500|duration=3003|duration_time=0.033367|size=2408|pos=86297|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=161596|pts_time=1.795511|pkt_dts=161595|pkt_dts_time=1.795500|best_effort_timestamp=161596|best_effort_timestamp_time=1.795511|duration=3003|duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=161596|pts_time=1.795511|pkt_dts=161595|pkt_dts_time=1.795500|best_effort_timestamp=161596|best_effort_timestamp_time=1.795511|duration=3003|duration_time=0.033367|pkt_pos=83530|pkt_size=1753|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=164599|pts_time=1.828878|dts=164598|dts_time=1.828867|duration=3003|duration_time=0.033367|size=1727|pos=88705|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=164599|pts_time=1.828878|pkt_dts=164598|pkt_dts_time=1.828867|best_effort_timestamp=164599|best_effort_timestamp_time=1.828878|duration=3003|duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=164599|pts_time=1.828878|pkt_dts=164598|pkt_dts_time=1.828867|best_effort_timestamp=164599|best_effort_timestamp_time=1.828878|duration=3003|duration_time=0.033367|pkt_pos=88705|pkt_size=1727|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=173608|pts_time=1.928978|dts=167601|dts_time=1.862233|duration=3003|duration_time=0.033367|size=1504|pos=90432|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=167602|pts_time=1.862244|pkt_dts=167601|pkt_dts_time=1.862233|best_effort_timestamp=167602|best_effort_timestamp_time=1.862244|duration=3003|duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=167602|pts_time=1.862244|pkt_dts=167601|pkt_dts_time=1.862233|best_effort_timestamp=167602|best_effort_timestamp_time=1.862244|duration=3003|duration_time=0.033367|pkt_pos=86297|pkt_size=2408|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=170605|pts_time=1.895611|dts=170604|dts_time=1.895600|duration=3003|duration_time=0.033367|size=957|pos=91936|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=170605|pts_time=1.895611|pkt_dts=170604|pkt_dts_time=1.895600|best_effort_timestamp=170605|best_effort_timestamp_time=1.895611|duration=3003|duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=170605|pts_time=1.895611|pkt_dts=170604|pkt_dts_time=1.895600|best_effort_timestamp=170605|best_effort_timestamp_time=1.895611|duration=3003|duration_time=0.033367|pkt_pos=91936|pkt_size=957|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=179614|pts_time=1.995711|dts=173607|dts_time=1.928967|duration=3003|duration_time=0.033367|size=1890|pos=92893|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=173608|pts_time=1.928978|pkt_dts=173607|pkt_dts_time=1.928967|best_effort_timestamp=173608|best_effort_timestamp_time=1.928978|duration=3003|duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=173608|pts_time=1.928978|pkt_dts=173607|pkt_dts_time=1.928967|best_effort_timestamp=173608|best_effort_timestamp_time=1.928978|duration=3003|duration_time=0.033367|pkt_pos=90432|pkt_size=1504|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=176611|pts_time=1.962344|dts=176610|dts_time=1.962333|duration=3003|duration_time=0.033367|size=1239|pos=94783|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=176611|pts_time=1.962344|pkt_dts=176610|pkt_dts_time=1.962333|best_effort_timestamp=176611|best_effort_timestamp_time=1.962344|duration=3003|duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=176611|pts_time=1.962344|pkt_dts=176610|pkt_dts_time=1.962333|best_effort_timestamp=176611|best_effort_timestamp_time=1.962344|duration=3003|duration_time=0.033367|pkt_pos=94783|pkt_size=1239|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=185620|pts_time=2.062444|dts=179613|dts_time=1.995700|duration=3003|duration_time=0.033367|size=1856|pos=96022|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=179614|pts_time=1.995711|pkt_dts=179613|pkt_dts_time=1.995700|best_effort_timestamp=179614|best_effort_timestamp_time=1.995711|duration=3003|duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=179614|pts_time=1.995711|pkt_dts=179613|pkt_dts_time=1.995700|best_effort_timestamp=179614|best_effort_timestamp_time=1.995711|duration=3003|duration_time=0.033367|pkt_pos=92893|pkt_size=1890|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=182617|pts_time=2.029078|dts=182616|dts_time=2.029067|duration=3003|duration_time=0.033367|size=1302|pos=97878|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=182617|pts_time=2.029078|pkt_dts=182616|pkt_dts_time=2.029067|best_effort_timestamp=182617|best_effort_timestamp_time=2.029078|duration=3003|duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=182617|pts_time=2.029078|pkt_dts=182616|pkt_dts_time=2.029067|best_effort_timestamp=182617|best_effort_timestamp_time=2.029078|duration=3003|duration_time=0.033367|pkt_pos=97878|pkt_size=1302|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=191626|pts_time=2.129178|dts=185619|dts_time=2.062433|duration=3003|duration_time=0.033367|size=1666|pos=99180|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=185620|pts_time=2.062444|pkt_dts=185619|pkt_dts_time=2.062433|best_effort_timestamp=185620|best_effort_timestamp_time=2.062444|duration=3003|duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=185620|pts_time=2.062444|pkt_dts=185619|pkt_dts_time=2.062433|best_effort_timestamp=185620|best_effort_timestamp_time=2.062444|duration=3003|duration_time=0.033367|pkt_pos=96022|pkt_size=1856|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=188623|pts_time=2.095811|dts=188622|dts_time=2.095800|duration=3003|duration_time=0.033367|size=974|pos=100846|flags=___
-frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|duration=3003|duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=188623|pts_time=2.095811|pkt_dts=188622|pkt_dts_time=2.095800|best_effort_timestamp=188623|best_effort_timestamp_time=2.095811|duration=3003|duration_time=0.033367|pkt_pos=100846|pkt_size=974|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=B|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
packet|codec_type=video|stream_index=0|pts=197632|pts_time=2.195911|dts=191625|dts_time=2.129167|duration=3003|duration_time=0.033367|size=580|pos=101820|flags=__C
-frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|duration=3003|duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
+frame|media_type=video|stream_index=0|key_frame=0|pts=191626|pts_time=2.129178|pkt_dts=N/A|pkt_dts_time=N/A|best_effort_timestamp=191626|best_effort_timestamp_time=2.129178|duration=3003|duration_time=0.033367|pkt_pos=99180|pkt_size=1666|width=160|height=240|crop_top=0|crop_bottom=0|crop_left=0|crop_right=0|pix_fmt=yuv420p|sample_aspect_ratio=2:1|pict_type=P|interlaced_frame=0|top_field_first=0|lossless=0|repeat_pict=0|color_range=tv|color_space=smpte170m|color_primaries=smpte170m|color_transfer=bt709|chroma_location=topleft|alpha_mode=unspecified|side_datum/3x3_displaymatrix:side_data_type=3x3 displaymatrix|side_datum/3x3_displaymatrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/3x3_displaymatrix:rotation=0|side_datum/h_26_45__user_data_unregistered_sei_message:side_data_type=H.26[45] User Data Unregistered SEI message
stream|index=0|codec_name=h264|profile=77|codec_type=video|codec_tag_string=avc1|codec_tag=0x31637661|width=160|height=240|coded_width=160|coded_height=240|has_b_frames=1|sample_aspect_ratio=2:1|display_aspect_ratio=4:3|pix_fmt=yuv420p|level=12|color_range=tv|color_space=smpte170m|color_transfer=bt709|color_primaries=smpte170m|chroma_location=topleft|field_order=progressive|refs=2|is_avc=true|nal_length_size=4|id=0x1|r_frame_rate=30000/1001|avg_frame_rate=6372000/212521|time_base=1/90000|start_pts=0|start_time=0.000000|duration_ts=2125200|duration=23.613333|bit_rate=333874|max_bit_rate=N/A|bits_per_raw_sample=8|nb_frames=708|nb_read_frames=65|nb_read_packets=66|extradata_size=34|disposition:default=1|disposition:dub=0|disposition:original=0|disposition:comment=0|disposition:lyrics=0|disposition:karaoke=0|disposition:forced=0|disposition:hearing_impaired=0|disposition:visual_impaired=0|disposition:clean_effects=0|disposition:attached_pic=0|disposition:timed_thumbnails=0|disposition:n
on_diegetic=0|disposition:captions=0|disposition:descriptions=0|disposition:metadata=0|disposition:dependent=0|disposition:still_image=0|disposition:multilayer=0|tag:creation_time=2008-05-12T20:59:27.000000Z|tag:language=eng|tag:handler_name=Apple Video Media Handler|tag:vendor_id=appl|tag:encoder=H.264|side_datum/display_matrix:side_data_type=Display Matrix|side_datum/display_matrix:displaymatrix=\n00000000: 131072 0 0\n00000001: 0 65536 0\n00000002: 0 0 1073741824\n|side_datum/display_matrix:rotation=0
diff --git a/tests/ref/fate/png-icc b/tests/ref/fate/png-icc
index 45e2426459..7f928d44d6 100644
--- a/tests/ref/fate/png-icc
+++ b/tests/ref/fate/png-icc
@@ -38,6 +38,7 @@ color_space=gbr
color_primaries=bt709
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[SIDE_DATA]
side_data_type=ICC profile
name=Photoshop ICC profile
diff --git a/tests/ref/fate/png-icc-parse b/tests/ref/fate/png-icc-parse
index 83f9e07872..2796d7eb6b 100644
--- a/tests/ref/fate/png-icc-parse
+++ b/tests/ref/fate/png-icc-parse
@@ -30,6 +30,7 @@ color_space=gbr
color_primaries=bt709
color_transfer=iec61966-2-1
chroma_location=unspecified
+alpha_mode=unspecified
[SIDE_DATA]
side_data_type=ICC profile
name=Photoshop ICC profile
diff --git a/tests/ref/fate/png-side-data b/tests/ref/fate/png-side-data
index 7af8f257a2..56ad7b0d4d 100644
--- a/tests/ref/fate/png-side-data
+++ b/tests/ref/fate/png-side-data
@@ -30,6 +30,7 @@ color_space=gbr
color_primaries=bt709
color_transfer=unknown
chroma_location=unspecified
+alpha_mode=unspecified
[SIDE_DATA]
side_data_type=ICC profile
name=Photoshop ICC profile
commit 4f99026c9f453c83c168eac99615234583791c8b
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 14:24:56 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
fftools/ffplay: add alpha_mode support
SDL seems to hard-code straight alpha compositing.
diff --git a/fftools/ffplay.c b/fftools/ffplay.c
index 2a572fc3aa..05eadb69a6 100644
--- a/fftools/ffplay.c
+++ b/fftools/ffplay.c
@@ -942,6 +942,11 @@ static enum AVColorSpace sdl_supported_color_spaces[] = {
AVCOL_SPC_SMPTE170M,
};
+static enum AVAlphaMode sdl_supported_alpha_modes[] = {
+ AVALPHA_MODE_UNSPECIFIED,
+ AVALPHA_MODE_STRAIGHT,
+};
+
static void set_sdl_yuv_conversion_mode(AVFrame *frame)
{
#if SDL_VERSION_ATLEAST(2,0,8)
@@ -1906,6 +1911,7 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
par->sample_aspect_ratio = codecpar->sample_aspect_ratio;
par->color_space = frame->colorspace;
par->color_range = frame->color_range;
+ par->alpha_mode = frame->alpha_mode;
par->frame_rate = fr;
par->hw_frames_ctx = frame->hw_frames_ctx;
ret = av_buffersrc_parameters_set(filt_src, par);
@@ -1932,6 +1938,10 @@ static int configure_video_filters(AVFilterGraph *graph, VideoState *is, const c
AV_OPT_TYPE_INT, sdl_supported_color_spaces)) < 0)
goto fail;
+ if ((ret = av_opt_set_array(filt_out, "alpha_modes", AV_OPT_SEARCH_CHILDREN,
+ 0, FF_ARRAY_ELEMS(sdl_supported_alpha_modes),
+ AV_OPT_TYPE_INT, sdl_supported_alpha_modes)) < 0)
+
ret = avfilter_init_dict(filt_out, NULL);
if (ret < 0)
goto fail;
commit f07573f49646bc29210ab1e9b9bb3f6312039c83
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 14:13:21 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
fftools/ffmpeg: add alpha_mode support
The implementation exactly mirrors the existing plumbing for color_ranges
and color_spaces.
diff --git a/fftools/ffmpeg.h b/fftools/ffmpeg.h
index 53f71bc080..c479a0351d 100644
--- a/fftools/ffmpeg.h
+++ b/fftools/ffmpeg.h
@@ -330,6 +330,7 @@ typedef struct OutputFilterOptions {
int height;
enum AVColorSpace color_space;
enum AVColorRange color_range;
+ enum AVAlphaMode alpha_mode;
enum VideoSyncMethod vsync_method;
AVRational frame_rate;
@@ -344,6 +345,7 @@ typedef struct OutputFilterOptions {
const AVRational *frame_rates;
const enum AVColorSpace *color_spaces;
const enum AVColorRange *color_ranges;
+ const enum AVAlphaMode *alpha_modes;
// for simple filtergraphs only, view specifier passed
// along to the decoder
diff --git a/fftools/ffmpeg_dec.c b/fftools/ffmpeg_dec.c
index 1d7158f995..521bd657f3 100644
--- a/fftools/ffmpeg_dec.c
+++ b/fftools/ffmpeg_dec.c
@@ -1635,6 +1635,7 @@ static int dec_open(DecoderPriv *dp, AVDictionary **dec_opts,
param_out->sample_aspect_ratio = dp->dec_ctx->sample_aspect_ratio;
param_out->colorspace = dp->dec_ctx->colorspace;
param_out->color_range = dp->dec_ctx->color_range;
+ param_out->alpha_mode = dp->dec_ctx->alpha_mode;
}
av_frame_side_data_free(¶m_out->side_data, ¶m_out->nb_side_data);
diff --git a/fftools/ffmpeg_enc.c b/fftools/ffmpeg_enc.c
index 4568c15073..84e7e0ca0e 100644
--- a/fftools/ffmpeg_enc.c
+++ b/fftools/ffmpeg_enc.c
@@ -274,6 +274,7 @@ int enc_open(void *opaque, const AVFrame *frame)
enc_ctx->color_primaries = frame->color_primaries;
enc_ctx->color_trc = frame->color_trc;
enc_ctx->colorspace = frame->colorspace;
+ enc_ctx->alpha_mode = frame->alpha_mode;
/* Video properties which are not part of filter graph negotiation */
if (enc_ctx->chroma_sample_location == AVCHROMA_LOC_UNSPECIFIED) {
diff --git a/fftools/ffmpeg_filter.c b/fftools/ffmpeg_filter.c
index bf5e53efa9..2dae6400c8 100644
--- a/fftools/ffmpeg_filter.c
+++ b/fftools/ffmpeg_filter.c
@@ -125,6 +125,7 @@ typedef struct InputFilterPriv {
AVRational sample_aspect_ratio;
enum AVColorSpace color_space;
enum AVColorRange color_range;
+ enum AVAlphaMode alpha_mode;
int sample_rate;
AVChannelLayout ch_layout;
@@ -196,6 +197,7 @@ typedef struct OutputFilterPriv {
AVChannelLayout ch_layout;
enum AVColorSpace color_space;
enum AVColorRange color_range;
+ enum AVAlphaMode alpha_mode;
AVFrameSideData **side_data;
int nb_side_data;
@@ -219,6 +221,7 @@ typedef struct OutputFilterPriv {
const int *sample_rates;
const enum AVColorSpace *color_spaces;
const enum AVColorRange *color_ranges;
+ const enum AVAlphaMode *alpha_modes;
AVRational enc_timebase;
int64_t trim_start_us;
@@ -268,6 +271,7 @@ static int sub2video_get_blank_frame(InputFilterPriv *ifp)
frame->format = ifp->format;
frame->colorspace = ifp->color_space;
frame->color_range = ifp->color_range;
+ frame->alpha_mode = ifp->alpha_mode;
ret = av_frame_get_buffer(frame, 0);
if (ret < 0)
@@ -401,6 +405,9 @@ DEF_CHOOSE_FORMAT(color_spaces, enum AVColorSpace, color_space, color_spaces,
DEF_CHOOSE_FORMAT(color_ranges, enum AVColorRange, color_range, color_ranges,
AVCOL_RANGE_UNSPECIFIED, "%s", av_color_range_name);
+DEF_CHOOSE_FORMAT(alpha_modes, enum AVAlphaMode, alpha_mode, alpha_modes,
+ AVALPHA_MODE_UNSPECIFIED, "%s", av_alpha_mode_name);
+
static void choose_channel_layouts(OutputFilterPriv *ofp, AVBPrint *bprint)
{
if (av_channel_layout_check(&ofp->ch_layout)) {
@@ -650,6 +657,7 @@ static OutputFilter *ofilter_alloc(FilterGraph *fg, enum AVMediaType type)
ofp->format = -1;
ofp->color_space = AVCOL_SPC_UNSPECIFIED;
ofp->color_range = AVCOL_RANGE_UNSPECIFIED;
+ ofp->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
ofilter->index = fg->nb_outputs - 1;
snprintf(ofp->log_name, sizeof(ofp->log_name), "%co%d",
@@ -854,6 +862,11 @@ int ofilter_bind_enc(OutputFilter *ofilter, unsigned sched_idx_enc,
else
ofp->color_ranges = opts->color_ranges;
+ if (opts->alpha_mode != AVALPHA_MODE_UNSPECIFIED)
+ ofp->alpha_mode = opts->alpha_mode;
+ else
+ ofp->alpha_modes = opts->alpha_modes;
+
fgp->disable_conversions |= !!(ofp->flags & OFILTER_FLAG_DISABLE_CONVERT);
ofp->fps.last_frame = av_frame_alloc();
@@ -977,6 +990,7 @@ static InputFilter *ifilter_alloc(FilterGraph *fg)
ifp->format = -1;
ifp->color_space = AVCOL_SPC_UNSPECIFIED;
ifp->color_range = AVCOL_RANGE_UNSPECIFIED;
+ ifp->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
ifp->frame_queue = av_fifo_alloc2(8, sizeof(AVFrame*), AV_FIFO_FLAG_AUTO_GROW);
if (!ifp->frame_queue)
@@ -1553,6 +1567,7 @@ static int configure_output_video_filter(FilterGraphPriv *fgp, AVFilterGraph *gr
choose_pix_fmts(ofp, &bprint);
choose_color_spaces(ofp, &bprint);
choose_color_ranges(ofp, &bprint);
+ choose_alpha_modes(ofp, &bprint);
if (!av_bprint_is_complete(&bprint))
return AVERROR(ENOMEM);
@@ -1723,6 +1738,7 @@ static int configure_input_video_filter(FilterGraph *fg, AVFilterGraph *graph,
ifp->sample_aspect_ratio : (AVRational){ 0, 1 };
par->color_space = ifp->color_space;
par->color_range = ifp->color_range;
+ par->alpha_mode = ifp->alpha_mode;
par->hw_frames_ctx = ifp->hw_frames_ctx;
par->side_data = ifp->side_data;
par->nb_side_data = ifp->nb_side_data;
@@ -2000,6 +2016,7 @@ static int configure_filtergraph(FilterGraph *fg, FilterGraphThread *fgt)
ofp->height = av_buffersink_get_h(sink);
ofp->color_space = av_buffersink_get_colorspace(sink);
ofp->color_range = av_buffersink_get_color_range(sink);
+ ofp->alpha_mode = av_buffersink_get_alpha_mode(sink);
// If the timing parameters are not locked yet, get the tentative values
// here but don't lock them. They will only be used if no output frames
@@ -2096,6 +2113,7 @@ static int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *fr
ifp->sample_aspect_ratio = frame->sample_aspect_ratio;
ifp->color_space = frame->colorspace;
ifp->color_range = frame->color_range;
+ ifp->alpha_mode = frame->alpha_mode;
ifp->sample_rate = frame->sample_rate;
ret = av_channel_layout_copy(&ifp->ch_layout, &frame->ch_layout);
@@ -2809,6 +2827,7 @@ static int send_eof(FilterGraphThread *fgt, InputFilter *ifilter,
ifp->sample_aspect_ratio = ifp->opts.fallback->sample_aspect_ratio;
ifp->color_space = ifp->opts.fallback->colorspace;
ifp->color_range = ifp->opts.fallback->color_range;
+ ifp->alpha_mode = ifp->opts.fallback->alpha_mode;
ifp->time_base = ifp->opts.fallback->time_base;
ret = av_channel_layout_copy(&ifp->ch_layout,
@@ -2877,7 +2896,8 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
ifp->width != frame->width ||
ifp->height != frame->height ||
ifp->color_space != frame->colorspace ||
- ifp->color_range != frame->color_range)
+ ifp->color_range != frame->color_range ||
+ ifp->alpha_mode != frame->alpha_mode)
need_reinit |= VIDEO_CHANGED;
break;
}
@@ -2951,9 +2971,11 @@ static int send_frame(FilterGraph *fg, FilterGraphThread *fgt,
const char *pixel_format_name = av_get_pix_fmt_name(frame->format);
const char *color_space_name = av_color_space_name(frame->colorspace);
const char *color_range_name = av_color_range_name(frame->color_range);
- av_bprintf(&reason, "video parameters changed to %s(%s, %s), %dx%d, ",
+ const char *alpha_mode = av_alpha_mode_name(frame->alpha_mode);
+ av_bprintf(&reason, "video parameters changed to %s(%s, %s), %dx%d, %s alpha,",
unknown_if_null(pixel_format_name), unknown_if_null(color_range_name),
- unknown_if_null(color_space_name), frame->width, frame->height);
+ unknown_if_null(color_space_name), frame->width, frame->height,
+ unknown_if_null(alpha_mode));
}
if (need_reinit & MATRIX_CHANGED)
av_bprintf(&reason, "display matrix changed, ");
diff --git a/fftools/ffmpeg_mux_init.c b/fftools/ffmpeg_mux_init.c
index 17977eb07f..e6c10edd62 100644
--- a/fftools/ffmpeg_mux_init.c
+++ b/fftools/ffmpeg_mux_init.c
@@ -917,6 +917,7 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
.height = enc_ctx->height,
.color_space = enc_ctx->colorspace,
.color_range = enc_ctx->color_range,
+ .alpha_mode = enc_ctx->alpha_mode,
.vsync_method = vsync_method,
.frame_rate = ms->frame_rate,
.max_frame_rate = ms->max_frame_rate,
@@ -964,6 +965,11 @@ ost_bind_filter(const Muxer *mux, MuxStream *ms, OutputFilter *ofilter,
(const void **) &opts.color_ranges, NULL);
if (ret < 0)
return ret;
+ ret = avcodec_get_supported_config(enc_ctx, NULL,
+ AV_CODEC_CONFIG_ALPHA_MODE, 0,
+ (const void **) &opts.alpha_modes, NULL);
+ if (ret < 0)
+ return ret;
} else {
ret = avcodec_get_supported_config(enc_ctx, NULL,
AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
commit 2e2ca4e74080207a48c455377eb0ec049979268e
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 19:56:46 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_showinfo: print alpha mode when relevant
diff --git a/libavfilter/vf_showinfo.c b/libavfilter/vf_showinfo.c
index c706d00c96..a85e894ae5 100644
--- a/libavfilter/vf_showinfo.c
+++ b/libavfilter/vf_showinfo.c
@@ -887,6 +887,14 @@ static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
dump_color_property(ctx, frame);
+ if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
+ const char *alpha_mode_str = av_alpha_mode_name(frame->alpha_mode);
+ if (!alpha_mode_str || frame->alpha_mode == AVALPHA_MODE_UNSPECIFIED)
+ av_log(ctx, AV_LOG_INFO, "alpha_mode:unspecified\n");
+ else
+ av_log(ctx, AV_LOG_INFO, "alpha_mode:%s\n", alpha_mode_str);
+ }
+
return ff_filter_frame(inlink->dst->outputs[0], frame);
}
commit 2b1ef029eb00731908dac044f409300b4b378c83
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 14:00:40 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/vf_format: add alpha_modes parameter
diff --git a/doc/filters.texi b/doc/filters.texi
index 3d6a9aff73..7efc7fa689 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -14307,6 +14307,10 @@ A '|'-separated list of color space names, such as
A '|'-separated list of color range names, such as
"color_ranges=tv|pc".
+@item alpha_modes
+A '|'-separated list of color range names, such as
+"alpha_modes=straight|premultiplied".
+
@end table
@subsection Examples
diff --git a/libavfilter/vf_format.c b/libavfilter/vf_format.c
index ae91b9655a..76d64bb4ae 100644
--- a/libavfilter/vf_format.c
+++ b/libavfilter/vf_format.c
@@ -42,10 +42,12 @@ typedef struct FormatContext {
char *pix_fmts;
char *csps;
char *ranges;
+ char *alphamodes;
AVFilterFormats *formats; ///< parsed from `pix_fmts`
AVFilterFormats *color_spaces; ///< parsed from `csps`
AVFilterFormats *color_ranges; ///< parsed from `ranges`
+ AVFilterFormats *alpha_modes; ///< parsed from `alphamodes`
} FormatContext;
static av_cold void uninit(AVFilterContext *ctx)
@@ -54,6 +56,7 @@ static av_cold void uninit(AVFilterContext *ctx)
ff_formats_unref(&s->formats);
ff_formats_unref(&s->color_spaces);
ff_formats_unref(&s->color_ranges);
+ ff_formats_unref(&s->alpha_modes);
}
static av_cold int invert_formats(AVFilterFormats **fmts,
@@ -133,17 +136,28 @@ static av_cold int init(AVFilterContext *ctx)
return ret;
}
+ for (char *sep, *cur = s->alphamodes; cur; cur = sep) {
+ sep = strchr(cur, '|');
+ if (sep && *sep)
+ *sep++ = 0;
+ if ((ret = av_alpha_mode_from_name(cur)) < 0 ||
+ (ret = ff_add_format(&s->alpha_modes, ret)) < 0)
+ return ret;
+ }
+
if (!strcmp(ctx->filter->name, "noformat")) {
if ((ret = invert_formats(&s->formats, ff_all_formats(AVMEDIA_TYPE_VIDEO))) < 0 ||
(ret = invert_formats(&s->color_spaces, ff_all_color_spaces())) < 0 ||
- (ret = invert_formats(&s->color_ranges, ff_all_color_ranges())) < 0)
+ (ret = invert_formats(&s->color_ranges, ff_all_color_ranges())) < 0 ||
+ (ret = invert_formats(&s->alpha_modes, ff_all_alpha_modes())) < 0)
return ret;
}
/* hold on to a ref for the lifetime of the filter */
if (s->formats && (ret = ff_formats_ref(s->formats, &s->formats)) < 0 ||
s->color_spaces && (ret = ff_formats_ref(s->color_spaces, &s->color_spaces)) < 0 ||
- s->color_ranges && (ret = ff_formats_ref(s->color_ranges, &s->color_ranges)) < 0)
+ s->color_ranges && (ret = ff_formats_ref(s->color_ranges, &s->color_ranges)) < 0 ||
+ s->alpha_modes && (ret = ff_formats_ref(s->alpha_modes, &s->alpha_modes)) < 0)
return ret;
return 0;
@@ -158,7 +172,8 @@ static int query_formats(const AVFilterContext *ctx,
if (s->formats && (ret = ff_set_common_formats2 (ctx, cfg_in, cfg_out, s->formats)) < 0 ||
s->color_spaces && (ret = ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, s->color_spaces)) < 0 ||
- s->color_ranges && (ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, s->color_ranges)) < 0)
+ s->color_ranges && (ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, s->color_ranges)) < 0 ||
+ s->alpha_modes && (ret = ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, s->alpha_modes)) < 0)
return ret;
return 0;
@@ -170,6 +185,7 @@ static const AVOption options[] = {
{ "pix_fmts", "A '|'-separated list of pixel formats", OFFSET(pix_fmts), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM },
{ "color_spaces", "A '|'-separated list of color spaces", OFFSET(csps), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM },
{ "color_ranges", "A '|'-separated list of color ranges", OFFSET(ranges), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM },
+ { "alpha_modes", "A '|'-separated list of alpha modes", OFFSET(alphamodes), AV_OPT_TYPE_STRING, .flags = AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM },
{ NULL }
};
commit de297ae2fca90a4ab3f2b30f64e886be13365ae1
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 14:10:24 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/buffersrc: add alpha_mode parameter
diff --git a/doc/APIchanges b/doc/APIchanges
index 9be59e7b8e..a3626d3c20 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavfi 11.8.100 - buffersrc.h
+ Add AVBufferSrcParameters.alpha_mode.
+
2025-09-xx - xxxxxxxxxx - lavfi 11.7.100 - buffersink.h
Add av_buffersink_get_alpha_mode().
diff --git a/doc/filters.texi b/doc/filters.texi
index 66b6c85979..3d6a9aff73 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -29278,6 +29278,11 @@ A string representing the color range of the buffered video frames.
It may be a number corresponding to a color range, or a color range
name.
+@item alpha_mode
+A string representing the alpha mode of the buffered video frames.
+It may be a number corresponding to an alpha mode, or an alpha mode
+name.
+
@item pixel_aspect, sar
The sample (pixel) aspect ratio of the input video.
diff --git a/libavfilter/buffersrc.c b/libavfilter/buffersrc.c
index 7e86d6ffd3..30f4df83a1 100644
--- a/libavfilter/buffersrc.c
+++ b/libavfilter/buffersrc.c
@@ -52,6 +52,7 @@ typedef struct BufferSourceContext {
enum AVPixelFormat pix_fmt, prev_pix_fmt;
enum AVColorSpace color_space, prev_color_space;
enum AVColorRange color_range, prev_color_range;
+ enum AVAlphaMode alpha_mode, prev_alpha_mode;
AVRational pixel_aspect;
AVBufferRef *hw_frames_ctx;
@@ -69,17 +70,17 @@ typedef struct BufferSourceContext {
int link_delta, prev_delta;
} BufferSourceContext;
-#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, csp, range, pts)\
+#define CHECK_VIDEO_PARAM_CHANGE(s, c, width, height, format, csp, range, alpha, pts)\
c->link_delta = c->w != width || c->h != height || c->pix_fmt != format ||\
- c->color_space != csp || c->color_range != range;\
+ c->color_space != csp || c->color_range != range || c->alpha_mode != alpha;\
c->prev_delta = c->prev_w != width || c->prev_h != height || c->prev_pix_fmt != format ||\
- c->prev_color_space != csp || c->prev_color_range != range;\
+ c->prev_color_space != csp || c->prev_color_range != range || c->prev_alpha_mode != alpha;\
if (c->link_delta) {\
int loglevel = c->prev_delta ? AV_LOG_WARNING : AV_LOG_DEBUG;\
av_log(s, loglevel, "Changing video frame properties on the fly is not supported by all filters.\n");\
- av_log(s, loglevel, "filter context - w: %d h: %d fmt: %d csp: %s range: %s, incoming frame - w: %d h: %d fmt: %d csp: %s range: %s pts_time: %s\n",\
- c->w, c->h, c->pix_fmt, av_color_space_name(c->color_space), av_color_range_name(c->color_range),\
- width, height, format, av_color_space_name(csp), av_color_range_name(range),\
+ av_log(s, loglevel, "filter context - w: %d h: %d fmt: %d csp: %s range: %s alpha: %s, incoming frame - w: %d h: %d fmt: %d csp: %s range: %s alpha: %s pts_time: %s\n",\
+ c->w, c->h, c->pix_fmt, av_color_space_name(c->color_space), av_color_range_name(c->color_range), av_alpha_mode_name(c->alpha_mode),\
+ width, height, format, av_color_space_name(csp), av_color_range_name(range), av_alpha_mode_name(alpha),\
av_ts2timestr(pts, &s->outputs[0]->time_base));\
}\
if (c->prev_delta) {\
@@ -90,6 +91,7 @@ typedef struct BufferSourceContext {
c->prev_pix_fmt = format;\
c->prev_color_space = csp;\
c->prev_color_range = range;\
+ c->prev_alpha_mode = alpha;\
}
#define CHECK_AUDIO_PARAM_CHANGE(s, c, srate, layout, format, pts)\
@@ -111,6 +113,7 @@ AVBufferSrcParameters *av_buffersrc_parameters_alloc(void)
par->format = -1;
par->color_range = AVCOL_RANGE_UNSPECIFIED;
par->color_space = AVCOL_SPC_UNSPECIFIED;
+ par->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
return par;
}
@@ -145,6 +148,8 @@ int av_buffersrc_parameters_set(AVFilterContext *ctx, AVBufferSrcParameters *par
s->color_space = s->prev_color_space = param->color_space;
if (param->color_range != AVCOL_RANGE_UNSPECIFIED)
s->color_range = s->prev_color_range = param->color_range;
+ if (param->alpha_mode != AVALPHA_MODE_UNSPECIFIED)
+ s->alpha_mode = s->prev_alpha_mode = param->alpha_mode;
break;
case AVMEDIA_TYPE_AUDIO:
if (param->format != AV_SAMPLE_FMT_NONE) {
@@ -224,7 +229,7 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra
case AVMEDIA_TYPE_VIDEO:
CHECK_VIDEO_PARAM_CHANGE(ctx, s, frame->width, frame->height,
frame->format, frame->colorspace,
- frame->color_range, frame->pts);
+ frame->color_range, frame->alpha_mode, frame->pts);
break;
case AVMEDIA_TYPE_AUDIO:
/* For layouts unknown on input but known on link after negotiation. */
@@ -256,6 +261,8 @@ int attribute_align_arg av_buffersrc_add_frame_flags(AVFilterContext *ctx, AVFra
copy->colorspace = ctx->outputs[0]->colorspace;
if (copy->color_range == AVCOL_RANGE_UNSPECIFIED)
copy->color_range = ctx->outputs[0]->color_range;
+ if (copy->alpha_mode == AVALPHA_MODE_UNSPECIFIED)
+ copy->alpha_mode = ctx->outputs[0]->alpha_mode;
ret = ff_filter_frame(ctx->outputs[0], copy);
if (ret < 0)
@@ -303,11 +310,12 @@ static av_cold int init_video(AVFilterContext *ctx)
return AVERROR(EINVAL);
}
- av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d csp:%s range:%s\n",
+ av_log(ctx, AV_LOG_VERBOSE, "w:%d h:%d pixfmt:%s tb:%d/%d fr:%d/%d sar:%d/%d csp:%s range:%s alpha:%s\n",
c->w, c->h, av_get_pix_fmt_name(c->pix_fmt),
c->time_base.num, c->time_base.den, c->frame_rate.num, c->frame_rate.den,
c->pixel_aspect.num, c->pixel_aspect.den,
- av_color_space_name(c->color_space), av_color_range_name(c->color_range));
+ av_color_space_name(c->color_space), av_color_range_name(c->color_range),
+ av_alpha_mode_name(c->alpha_mode));
return 0;
}
@@ -357,6 +365,11 @@ static const AVOption buffer_options[] = {
{ "full", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, V, .unit = "range"},
{ "pc", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, V, .unit = "range"},
{ "jpeg", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVCOL_RANGE_JPEG}, 0, 0, V, .unit = "range"},
+ { "alpha_mode", "select alpha mode", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, AVCOL_RANGE_NB-1, V, .unit = "alpha"},
+ { "unspecified", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, V, .unit = "alpha"},
+ { "unknown", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_UNSPECIFIED}, 0, 0, V, .unit = "alpha"},
+ { "straight", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_STRAIGHT}, 0, 0, V, .unit = "alpha"},
+ { "premultiplied", NULL, 0, AV_OPT_TYPE_CONST, {.i64=AVALPHA_MODE_PREMULTIPLIED}, 0, 0, V, .unit = "alpha"},
{ NULL },
};
@@ -442,6 +455,7 @@ static int query_formats(const AVFilterContext *ctx,
AVFilterFormats *samplerates = NULL;
AVFilterFormats *color_spaces = NULL;
AVFilterFormats *color_ranges = NULL;
+ AVFilterFormats *alpha_modes = NULL;
int ret;
switch (ctx->outputs[0]->type) {
@@ -472,6 +486,17 @@ static int query_formats(const AVFilterContext *ctx,
if ((ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, color_ranges)) < 0)
return ret;
}
+ if (av_pix_fmt_desc_get(swfmt)->flags & AV_PIX_FMT_FLAG_ALPHA) {
+ if ((ret = ff_add_format(&alpha_modes, c->alpha_mode)) < 0)
+ return ret;
+ if (c->alpha_mode == AVALPHA_MODE_UNSPECIFIED) {
+ /* allow implicitly promoting unspecified to straight */
+ if ((ret = ff_add_format(&alpha_modes, AVALPHA_MODE_STRAIGHT)) < 0)
+ return ret;
+ }
+ if ((ret = ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, alpha_modes)) < 0)
+ return ret;
+ }
break;
}
case AVMEDIA_TYPE_AUDIO:
diff --git a/libavfilter/buffersrc.h b/libavfilter/buffersrc.h
index 2db9b8fb59..54de1fd1f2 100644
--- a/libavfilter/buffersrc.h
+++ b/libavfilter/buffersrc.h
@@ -123,6 +123,11 @@ typedef struct AVBufferSrcParameters {
AVFrameSideData **side_data;
int nb_side_data;
+
+ /**
+ * Video only, the alpha mode.
+ */
+ enum AVAlphaMode alpha_mode;
} AVBufferSrcParameters;
/**
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 0050874108..ba8a6fdab2 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 7
+#define LIBAVFILTER_VERSION_MINOR 8
#define LIBAVFILTER_VERSION_MICRO 100
commit 0fbd90d78f8d534a97e83331c6448f54fdf0a277
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 13:53:26 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avfilter/buffersink: add support for alpha modes
diff --git a/doc/APIchanges b/doc/APIchanges
index 149ffc506e..9be59e7b8e 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavfi 11.7.100 - buffersink.h
+ Add av_buffersink_get_alpha_mode().
+
2025-09-xx - xxxxxxxxxx - lavc 62.15.100 - avcodec.h codec_par.h
Add AVCodecContext.alpha_mode, AVCodecParameters.alpha_mode, and
AV_CODEC_CONFIG_ALPHA_MODE.
diff --git a/libavfilter/buffersink.c b/libavfilter/buffersink.c
index 50a7da2756..f636d3728f 100644
--- a/libavfilter/buffersink.c
+++ b/libavfilter/buffersink.c
@@ -53,6 +53,8 @@ typedef struct BufferSinkContext {
int color_spaces_size;
enum AVColorRange *color_ranges; ///< list of accepted color ranges
int color_ranges_size;
+ enum AVColorRange *alpha_modes; ///< list of accepted alpha modes
+ int alpha_modes_size;
#endif
enum AVPixelFormat *pixel_formats;
@@ -64,6 +66,9 @@ typedef struct BufferSinkContext {
int *colorranges;
unsigned nb_colorranges;
+ int *alphamodes;
+ unsigned nb_alphamodes;
+
/* only used for audio */
#if FF_API_BUFFERSINK_OPTS
enum AVSampleFormat *sample_fmts; ///< list of accepted sample formats
@@ -175,7 +180,7 @@ static av_cold int common_init(AVFilterContext *ctx)
}
if (ctx->input_pads[0].type == AVMEDIA_TYPE_VIDEO) {
- if ((buf->pixel_fmts_size || buf->color_spaces_size || buf->color_ranges_size) &&
+ if ((buf->pixel_fmts_size || buf->color_spaces_size || buf->color_ranges_size || buf->alpha_modes_size) &&
(buf->nb_pixel_formats || buf->nb_colorspaces || buf->nb_colorranges)) {
av_log(ctx, AV_LOG_ERROR, "Cannot combine old and new format lists\n");
return AVERROR(EINVAL);
@@ -184,6 +189,7 @@ static av_cold int common_init(AVFilterContext *ctx)
CHECK_LIST_SIZE(pixel_fmts)
CHECK_LIST_SIZE(color_spaces)
CHECK_LIST_SIZE(color_ranges)
+ CHECK_LIST_SIZE(alpha_modes)
} else {
if ((buf->sample_fmts_size || buf->channel_layouts_str || buf->sample_rates_size) &&
(buf->nb_sample_formats || buf->nb_samplerates || buf->nb_channel_layouts)) {
@@ -258,6 +264,7 @@ static int init_video(AVFilterContext *ctx)
TERMINATE_ARRAY(pixel_formats, AV_PIX_FMT_NONE);
TERMINATE_ARRAY(colorranges, -1);
TERMINATE_ARRAY(colorspaces, -1);
+ TERMINATE_ARRAY(alphamodes, -1);
return common_init(ctx);
}
@@ -336,6 +343,7 @@ MAKE_AVFILTERLINK_ACCESSOR(int , h )
MAKE_AVFILTERLINK_ACCESSOR(AVRational , sample_aspect_ratio)
MAKE_AVFILTERLINK_ACCESSOR(enum AVColorSpace, colorspace)
MAKE_AVFILTERLINK_ACCESSOR(enum AVColorRange, color_range)
+MAKE_AVFILTERLINK_ACCESSOR(enum AVAlphaMode , alpha_mode)
MAKE_AVFILTERLINK_ACCESSOR(int , sample_rate )
@@ -409,6 +417,11 @@ static int vsink_query_formats(const AVFilterContext *ctx,
if (ret < 0)
return ret;
}
+ if (buf->nb_alphamodes) {
+ ret = ff_set_common_alpha_modes_from_list2(ctx, cfg_in, cfg_out, buf->alphamodes);
+ if (ret < 0)
+ return ret;
+ }
#if FF_API_BUFFERSINK_OPTS
} else {
unsigned i;
@@ -438,6 +451,15 @@ static int vsink_query_formats(const AVFilterContext *ctx,
if ((ret = ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, formats)) < 0)
return ret;
}
+
+ if (buf->alpha_modes_size) {
+ AVFilterFormats *formats = NULL;
+ for (i = 0; i < NB_ITEMS(buf->alpha_modes); i++)
+ if ((ret = ff_add_format(&formats, buf->alpha_modes[i])) < 0)
+ return ret;
+ if ((ret = ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, formats)) < 0)
+ return ret;
+ }
}
#endif
@@ -509,6 +531,7 @@ static const AVOption buffersink_options[] = {
{ "pix_fmts", "set the supported pixel formats", OFFSET(pixel_fmts), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
{ "color_spaces", "set the supported color spaces", OFFSET(color_spaces), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
{ "color_ranges", "set the supported color ranges", OFFSET(color_ranges), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
+ { "alpha_modes", "set the supported alpha modes", OFFSET(alpha_modes), AV_OPT_TYPE_BINARY, .flags = FLAGS | AV_OPT_FLAG_DEPRECATED },
#endif
{ "pixel_formats", "array of supported pixel formats", OFFSET(pixel_formats),
@@ -517,6 +540,8 @@ static const AVOption buffersink_options[] = {
AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
{ "colorranges", "array of supported color ranges", OFFSET(colorranges),
AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
+ { "alphamodes", "array of supported color ranges", OFFSET(alphamodes),
+ AV_OPT_TYPE_INT | AV_OPT_TYPE_FLAG_ARRAY, .max = INT_MAX, .flags = FLAGS },
{ NULL },
};
diff --git a/libavfilter/buffersink.h b/libavfilter/buffersink.h
index a8435eea8f..4e658a9795 100644
--- a/libavfilter/buffersink.h
+++ b/libavfilter/buffersink.h
@@ -58,6 +58,7 @@
* - pixel_formats (array of pixel formats),
* - colorspaces (array of int),
* - colorranges (array of int),
+ * - alphamodes (array of int),
* - sample_formats (array of sample formats),
* - samplerates (array of int),
* - channel_layouts (array of channel layouts)
@@ -115,6 +116,7 @@ int av_buffersink_get_h (const AVFilterContext *c
AVRational av_buffersink_get_sample_aspect_ratio (const AVFilterContext *ctx);
enum AVColorSpace av_buffersink_get_colorspace (const AVFilterContext *ctx);
enum AVColorRange av_buffersink_get_color_range (const AVFilterContext *ctx);
+enum AVAlphaMode av_buffersink_get_alpha_mode (const AVFilterContext *ctx);
int av_buffersink_get_channels (const AVFilterContext *ctx);
int av_buffersink_get_ch_layout (const AVFilterContext *ctx,
diff --git a/libavfilter/version.h b/libavfilter/version.h
index f191d98883..0050874108 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 6
+#define LIBAVFILTER_VERSION_MINOR 7
#define LIBAVFILTER_VERSION_MICRO 100
commit 65580592c91be88065951adac4403b5b94b88984
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Jul 23 13:10:57 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avcodec/jpegxl: parse and signal correct alpha mode
This header bit ("alpha_associated") was incorrectly ignored.
diff --git a/libavcodec/jpegxl_parse.c b/libavcodec/jpegxl_parse.c
index 022eed322d..47b831e2b4 100644
--- a/libavcodec/jpegxl_parse.c
+++ b/libavcodec/jpegxl_parse.c
@@ -190,6 +190,7 @@ static void jpegxl_get_bit_depth(GetBitContext *gb, FFJXLMetadata *meta)
static int jpegxl_read_extra_channel_info(GetBitContext *gb, FFJXLMetadata *meta, int validate)
{
int default_alpha = get_bits1(gb);
+ int alpha_associated = 0;
uint32_t type, name_len = 0;
if (!default_alpha) {
@@ -213,7 +214,7 @@ static int jpegxl_read_extra_channel_info(GetBitContext *gb, FFJXLMetadata *meta
skip_bits_long(gb, name_len);
if (!default_alpha && type == JPEGXL_CT_ALPHA)
- skip_bits1(gb);
+ alpha_associated = get_bits1(gb);
if (type == JPEGXL_CT_SPOT_COLOR)
skip_bits_long(gb, 16 * 4);
@@ -221,8 +222,10 @@ static int jpegxl_read_extra_channel_info(GetBitContext *gb, FFJXLMetadata *meta
if (type == JPEGXL_CT_CFA)
jxl_u32(gb, 1, 0, 3, 19, 0, 2, 4, 8);
- if (meta && type == JPEGXL_CT_ALPHA)
+ if (meta && type == JPEGXL_CT_ALPHA) {
meta->have_alpha = 1;
+ meta->alpha_associated = alpha_associated;
+ }
return 0;
}
diff --git a/libavcodec/jpegxl_parse.h b/libavcodec/jpegxl_parse.h
index 0602f4d409..bb929ccee1 100644
--- a/libavcodec/jpegxl_parse.h
+++ b/libavcodec/jpegxl_parse.h
@@ -35,6 +35,7 @@ typedef struct FFJXLMetadata {
uint32_t coded_height;
int bit_depth;
int have_alpha;
+ int alpha_associated;
/*
* offset, in bits, of the animation header
* zero if not animated
diff --git a/libavcodec/jpegxl_parser.c b/libavcodec/jpegxl_parser.c
index 75acc53708..3981b0cec0 100644
--- a/libavcodec/jpegxl_parser.c
+++ b/libavcodec/jpegxl_parser.c
@@ -1074,6 +1074,11 @@ static void populate_fields(AVCodecParserContext *s, AVCodecContext *avctx, cons
else
s->format = meta->have_alpha ? AV_PIX_FMT_RGBAF32 : AV_PIX_FMT_RGBF32;
}
+
+ if (meta->have_alpha) {
+ avctx->alpha_mode = meta->alpha_associated ? AVALPHA_MODE_PREMULTIPLIED
+ : AVALPHA_MODE_STRAIGHT;
+ }
}
static int skip_icc_profile(void *avctx, JXLParseContext *ctx, GetBitContext *gb)
commit 51572ff08abe44bc042a6004459bd1326d31bbce
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Jul 23 15:29:41 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avcodec/libjxlenc: also attach extra channel info
Works around a bug where older versions of libjxl don't correctly forward
the alpha channel information to the extra channel info.
diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
index 9ad55ae3fa..da538518a5 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -445,6 +445,19 @@ static int libjxl_preprocess_stream(AVCodecContext *avctx, const AVFrame *frame,
goto end;
}
+ if (info.alpha_bits) {
+ JxlExtraChannelInfo extra_info;
+ JxlEncoderInitExtraChannelInfo(JXL_CHANNEL_ALPHA, &extra_info);
+ extra_info.bits_per_sample = info.alpha_bits;
+ extra_info.exponent_bits_per_sample = info.alpha_exponent_bits;
+ extra_info.alpha_premultiplied = info.alpha_premultiplied;
+
+ if (JxlEncoderSetExtraChannelInfo(ctx->encoder, 0, &extra_info) != JXL_ENC_SUCCESS) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to set JxlExtraChannelInfo for alpha!\n");
+ return AVERROR_EXTERNAL;
+ }
+ }
+
sd = av_frame_get_side_data(frame, AV_FRAME_DATA_ICC_PROFILE);
if (sd && sd->size && JxlEncoderSetICCProfile(ctx->encoder, sd->data, sd->size) != JXL_ENC_SUCCESS) {
av_log(avctx, AV_LOG_WARNING, "Could not set ICC Profile\n");
commit a88cc0a53ea55576431c74ebd4c0a982d1052e99
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Jul 23 12:51:26 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avcodec/libjxl: set correct alpha mode
JPEG XL supports both premultiplied and straight alpha, and the basic info
struct contains signalling for this. Forward the correct tagging on decode
and encode.
diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c
index 8ce69015bf..d0f0015c90 100644
--- a/libavcodec/libjxldec.c
+++ b/libavcodec/libjxldec.c
@@ -444,6 +444,12 @@ static int libjxl_receive_frame(AVCodecContext *avctx, AVFrame *frame)
if (ctx->basic_info.have_animation)
ctx->anim_timebase = av_make_q(ctx->basic_info.animation.tps_denominator,
ctx->basic_info.animation.tps_numerator);
+ if (ctx->basic_info.alpha_bits) {
+ if (ctx->basic_info.alpha_premultiplied)
+ avctx->alpha_mode = AVALPHA_MODE_PREMULTIPLIED;
+ else
+ avctx->alpha_mode = AVALPHA_MODE_STRAIGHT;
+ }
continue;
case JXL_DEC_COLOR_ENCODING:
av_log(avctx, AV_LOG_DEBUG, "COLOR_ENCODING event emitted\n");
diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
index 81c8233e40..9ad55ae3fa 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -357,6 +357,15 @@ static int libjxl_preprocess_stream(AVCodecContext *avctx, const AVFrame *frame,
jxl_fmt->data_type = info.bits_per_sample <= 8 ? JXL_TYPE_UINT8 : JXL_TYPE_UINT16;
}
+ if (info.alpha_bits) {
+ if (avctx->alpha_mode == AVALPHA_MODE_PREMULTIPLIED ||
+ avctx->alpha_mode == AVALPHA_MODE_UNSPECIFIED && frame->alpha_mode == AVALPHA_MODE_PREMULTIPLIED) {
+ info.alpha_premultiplied = 1;
+ } else if (avctx->alpha_mode != AVALPHA_MODE_STRAIGHT && frame->alpha_mode != AVALPHA_MODE_STRAIGHT) {
+ av_log(avctx, AV_LOG_WARNING, "Unknown alpha mode, assuming straight (independent)\n");
+ }
+ }
+
#if JPEGXL_NUMERIC_VERSION >= JPEGXL_COMPUTE_NUMERIC_VERSION(0, 8, 0)
jxl_bit_depth.bits_per_sample = bits_per_sample;
jxl_bit_depth.type = JXL_BIT_DEPTH_FROM_PIXEL_FORMAT;
@@ -771,6 +780,9 @@ const FFCodec ff_libjxl_encoder = {
FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP |
FF_CODEC_CAP_ICC_PROFILES,
CODEC_PIXFMTS_ARRAY(libjxl_supported_pixfmts),
+ .alpha_modes = (const enum AVAlphaMode[]) {
+ AVALPHA_MODE_STRAIGHT, AVALPHA_MODE_PREMULTIPLIED, AVALPHA_MODE_UNSPECIFIED
+ },
.p.priv_class = &libjxl_encode_class,
.p.wrapper_name = "libjxl",
};
@@ -791,6 +803,9 @@ const FFCodec ff_libjxl_anim_encoder = {
FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP |
FF_CODEC_CAP_ICC_PROFILES,
CODEC_PIXFMTS_ARRAY(libjxl_supported_pixfmts),
+ .alpha_modes = (const enum AVAlphaMode[]) {
+ AVALPHA_MODE_STRAIGHT, AVALPHA_MODE_PREMULTIPLIED, AVALPHA_MODE_UNSPECIFIED
+ },
.p.priv_class = &libjxl_encode_class,
.p.wrapper_name = "libjxl",
};
commit 702a5ac29b5c402ab6ff9e40621e6e12f38826ca
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Jul 23 12:41:23 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avcodec/exr: set correct alpha mode
OpenEXR always uses premultiplied alpha, as per the spec.
cf. https://openexr.com/en/latest/TechnicalIntroduction.html
> By convention, all color channels are premultiplied by alpha, so that
> `foreground + (1-alpha) x background` performs a correct “over” operation.
> (See Premultiplied vs. Un-Premultiplied Color Channels)
>
> In the visual effects industry premultiplied color channels are the norm,
> and application software packages typically use internal image
> representations that are also premultiplied.
diff --git a/libavcodec/exr.c b/libavcodec/exr.c
index 67f971ff35..e6051567d1 100644
--- a/libavcodec/exr.c
+++ b/libavcodec/exr.c
@@ -2148,6 +2148,9 @@ static int decode_frame(AVCodecContext *avctx, AVFrame *picture,
return AVERROR_INVALIDDATA;
}
+ if (s->channel_offsets[3] >= 0)
+ avctx->alpha_mode = AVALPHA_MODE_PREMULTIPLIED;
+
#if FF_API_EXR_GAMMA
if (s->apply_trc_type != AVCOL_TRC_UNSPECIFIED)
avctx->color_trc = s->apply_trc_type;
diff --git a/libavcodec/exrenc.c b/libavcodec/exrenc.c
index c9685890ea..54f63d9eb6 100644
--- a/libavcodec/exrenc.c
+++ b/libavcodec/exrenc.c
@@ -553,4 +553,7 @@ const FFCodec ff_exr_encoder = {
FF_CODEC_ENCODE_CB(encode_frame),
.close = encode_close,
CODEC_PIXFMTS(AV_PIX_FMT_GRAYF32, AV_PIX_FMT_GBRPF32, AV_PIX_FMT_GBRAPF32),
+ .alpha_modes = (const enum AVAlphaMode[]) {
+ AVALPHA_MODE_PREMULTIPLIED, AVALPHA_MODE_UNSPECIFIED
+ },
};
commit d6ce720765d0684d596f3238ba77f6c16c0cee44
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 20:35:20 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avcodec/png: set correct alpha mode
PNG always uses straight alpha.
cf. https://www.w3.org/TR/PNG-Rationale.html
> Although each form of alpha storage has its advantages, we did not want to
> require all PNG viewers to handle both forms. We standardized on non-
> premultiplied alpha as being the lossless and more general case.
diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index ce817d44fa..fff27305d5 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -998,6 +998,11 @@ static int decode_idat_chunk(AVCodecContext *avctx, PNGDecContext *s,
s->bpp += byte_depth;
}
+ /* PNG spec mandates independent alpha channel */
+ if (s->color_type == PNG_COLOR_TYPE_RGB_ALPHA ||
+ s->color_type == PNG_COLOR_TYPE_GRAY_ALPHA)
+ avctx->alpha_mode = AVALPHA_MODE_STRAIGHT;
+
ff_progress_frame_unref(&s->picture);
if (s->dispose_op == APNG_DISPOSE_OP_PREVIOUS) {
/* We only need a buffer for the current picture. */
diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index 635c89e87e..5baad9aad5 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -1255,6 +1255,9 @@ const FFCodec ff_png_encoder = {
AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A,
AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_YA16BE,
AV_PIX_FMT_MONOBLACK),
+ .alpha_modes = (const enum AVAlphaMode[]) {
+ AVALPHA_MODE_STRAIGHT, AVALPHA_MODE_UNSPECIFIED
+ },
.p.priv_class = &pngenc_class,
.caps_internal = FF_CODEC_CAP_ICC_PROFILES,
};
@@ -1275,6 +1278,9 @@ const FFCodec ff_apng_encoder = {
AV_PIX_FMT_PAL8,
AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY8A,
AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_YA16BE),
+ .alpha_modes = (const enum AVAlphaMode[]) {
+ AVALPHA_MODE_STRAIGHT, AVALPHA_MODE_UNSPECIFIED
+ },
.p.priv_class = &pngenc_class,
.caps_internal = FF_CODEC_CAP_ICC_PROFILES,
};
commit 02d531ca05eaf3cc6e9299d45ac2cc60d8c8eac7
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 21:21:52 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:25 2025 +0200
avcodec/encode: enforce alpha mode compatibility at encode time
Error out if trying to encode frames with an incompatible alpha mode.
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 38833c566c..9012708130 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -587,6 +587,33 @@ static int encode_preinit_video(AVCodecContext *avctx)
avctx->color_range = AVCOL_RANGE_JPEG;
}
+ if (pixdesc->flags & AV_PIX_FMT_FLAG_ALPHA) {
+ const enum AVAlphaMode *alpha_modes;
+ int num_alpha_modes;
+ ret = avcodec_get_supported_config(avctx, NULL, AV_CODEC_CONFIG_ALPHA_MODE,
+ 0, (const void **) &alpha_modes, &num_alpha_modes);
+ if (ret < 0)
+ return ret;
+
+ if (avctx->alpha_mode != AVALPHA_MODE_UNSPECIFIED && alpha_modes) {
+ for (i = 0; i < num_alpha_modes; i++) {
+ if (avctx->alpha_mode == alpha_modes[i])
+ break;
+ }
+ if (i == num_alpha_modes) {
+ av_log(avctx, AV_LOG_ERROR,
+ "Specified alpha mode '%s' is not supported by the %s encoder.\n",
+ av_alpha_mode_name(avctx->alpha_mode), c->name);
+ av_log(avctx, AV_LOG_ERROR, "Supported alpha modes:\n");
+ for (int p = 0; alpha_modes[p] != AVALPHA_MODE_UNSPECIFIED; p++) {
+ av_log(avctx, AV_LOG_ERROR, " %s\n",
+ av_alpha_mode_name(alpha_modes[p]));
+ }
+ return AVERROR(EINVAL);
+ }
+ }
+ }
+
if ( avctx->bits_per_raw_sample < 0
|| (avctx->bits_per_raw_sample > 8 && pixdesc->comp[0].depth <= 8)) {
av_log(avctx, AV_LOG_WARNING, "Specified bit depth %d not possible with the specified pixel formats depth %d\n",
commit ecebf9c69351f011a2e43079621bcdd5ab23a4d9
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 20:24:56 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:24 2025 +0200
avcodec/avcodec: add AVCodecContext.alpha_mode
Following in the footsteps of the previous commit, this commit adds the
new fields to AVCodecContext so we can start properly setting it on codecs,
as well as limiting the list of supported options to detect a format mismatch
during encode.
This commit also sets up the necessary infrastructure to start using the
newly added field in all codecs.
diff --git a/doc/APIchanges b/doc/APIchanges
index 87357e5909..149ffc506e 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,10 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavc 62.15.100 - avcodec.h codec_par.h
+ Add AVCodecContext.alpha_mode, AVCodecParameters.alpha_mode, and
+ AV_CODEC_CONFIG_ALPHA_MODE.
+
2025-09-xx - xxxxxxxxxx - lavfi 11.6.100 - avfilter.h
Add AVFilterLink.alpha_mode.
diff --git a/doc/codecs.texi b/doc/codecs.texi
index f6bd50eb71..eec5d8e8c7 100644
--- a/doc/codecs.texi
+++ b/doc/codecs.texi
@@ -913,6 +913,14 @@ Possible values:
@end table
+@item alpha_mode @var{integer} (@emph{decoding/encoding,video})
+Possible values:
+@table @samp
+@item premultiplied
+@item straight
+@end table
+
+
@item log_level_offset @var{integer}
Set the log level offset.
diff --git a/libavcodec/avcodec.c b/libavcodec/avcodec.c
index 2181439113..0355b7c338 100644
--- a/libavcodec/avcodec.c
+++ b/libavcodec/avcodec.c
@@ -759,6 +759,8 @@ int ff_default_get_supported_config(const AVCodecContext *avctx,
const void **out_configs,
int *out_num_configs)
{
+ const FFCodec *codec2 = ffcodec(codec);
+
switch (config) {
FF_DISABLE_DEPRECATION_WARNINGS
case AV_CODEC_CONFIG_PIX_FORMAT:
@@ -786,6 +788,10 @@ FF_ENABLE_DEPRECATION_WARNINGS
if (out_num_configs)
*out_num_configs = 0;
return 0;
+
+ case AV_CODEC_CONFIG_ALPHA_MODE:
+ WRAP_CONFIG(AVMEDIA_TYPE_VIDEO, codec2->alpha_modes, enum AVAlphaMode, AVALPHA_MODE_UNSPECIFIED);
+
default:
return AVERROR(EINVAL);
}
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 108df5a24e..83a4e56e22 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -1923,6 +1923,13 @@ typedef struct AVCodecContext {
*/
AVFrameSideData **decoded_side_data;
int nb_decoded_side_data;
+
+ /**
+ * Indicates how the alpha channel of the video is represented.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVAlphaMode alpha_mode;
} AVCodecContext;
/**
@@ -2528,6 +2535,7 @@ enum AVCodecConfig {
AV_CODEC_CONFIG_CHANNEL_LAYOUT, ///< AVChannelLayout, terminated by {0}
AV_CODEC_CONFIG_COLOR_RANGE, ///< AVColorRange, terminated by AVCOL_RANGE_UNSPECIFIED
AV_CODEC_CONFIG_COLOR_SPACE, ///< AVColorSpace, terminated by AVCOL_SPC_UNSPECIFIED
+ AV_CODEC_CONFIG_ALPHA_MODE, ///< AVAlphaMode, terminated by AVALPHA_MODE_UNSPECIFIED
};
/**
diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
index 7fa3097aa9..0d13a50fed 100644
--- a/libavcodec/codec_internal.h
+++ b/libavcodec/codec_internal.h
@@ -153,6 +153,11 @@ typedef struct FFCodec {
*/
unsigned cb_type:3;
+ /**
+ * This field determines the alpha modes supported by an encoder.
+ */
+ const enum AVAlphaMode *alpha_modes;
+
int priv_data_size;
/**
* @name Frame-level threading support functions
diff --git a/libavcodec/codec_par.c b/libavcodec/codec_par.c
index 790ea01d10..ddf349ceea 100644
--- a/libavcodec/codec_par.c
+++ b/libavcodec/codec_par.c
@@ -51,6 +51,7 @@ static void codec_parameters_reset(AVCodecParameters *par)
par->framerate = (AVRational){ 0, 1 };
par->profile = AV_PROFILE_UNKNOWN;
par->level = AV_LEVEL_UNKNOWN;
+ par->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
}
AVCodecParameters *avcodec_parameters_alloc(void)
@@ -165,6 +166,7 @@ int avcodec_parameters_from_context(AVCodecParameters *par,
par->sample_aspect_ratio = codec->sample_aspect_ratio;
par->video_delay = codec->has_b_frames;
par->framerate = codec->framerate;
+ par->alpha_mode = codec->alpha_mode;
break;
case AVMEDIA_TYPE_AUDIO:
par->format = codec->sample_fmt;
@@ -229,6 +231,7 @@ int avcodec_parameters_to_context(AVCodecContext *codec,
codec->sample_aspect_ratio = par->sample_aspect_ratio;
codec->has_b_frames = par->video_delay;
codec->framerate = par->framerate;
+ codec->alpha_mode = par->alpha_mode;
break;
case AVMEDIA_TYPE_AUDIO:
codec->sample_fmt = par->format;
diff --git a/libavcodec/codec_par.h b/libavcodec/codec_par.h
index 64b01f7e02..2697605d4d 100644
--- a/libavcodec/codec_par.h
+++ b/libavcodec/codec_par.h
@@ -212,6 +212,11 @@ typedef struct AVCodecParameters {
* Audio only. Number of samples to skip after a discontinuity.
*/
int seek_preroll;
+
+ /**
+ * Video with alpha channel only. Alpha channel handling
+ */
+ enum AVAlphaMode alpha_mode;
} AVCodecParameters;
/**
diff --git a/libavcodec/decode.c b/libavcodec/decode.c
index edd2390490..f395948d60 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -568,6 +568,8 @@ static int fill_frame_props(const AVCodecContext *avctx, AVFrame *frame)
frame->color_range = avctx->color_range;
if (frame->chroma_location == AVCHROMA_LOC_UNSPECIFIED)
frame->chroma_location = avctx->chroma_sample_location;
+ if (frame->alpha_mode == AVALPHA_MODE_UNSPECIFIED)
+ frame->alpha_mode = avctx->alpha_mode;
if (avctx->codec_type == AVMEDIA_TYPE_VIDEO) {
if (!frame->sample_aspect_ratio.num) frame->sample_aspect_ratio = avctx->sample_aspect_ratio;
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 43aec402ba..8567451919 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -352,6 +352,11 @@ static const AVOption avcodec_options[] = {
{"bottomleft", "Bottom-left", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOMLEFT }, INT_MIN, INT_MAX, V|E|D, .unit = "chroma_sample_location_type"},
{"bottom", "Bottom", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_BOTTOM }, INT_MIN, INT_MAX, V|E|D, .unit = "chroma_sample_location_type"},
{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVCHROMA_LOC_UNSPECIFIED }, INT_MIN, INT_MAX, V|E|D, .unit = "chroma_sample_location_type"},
+{"alpha_mode", "alpha mode", OFFSET(alpha_mode), AV_OPT_TYPE_INT, {.i64 = AVALPHA_MODE_UNSPECIFIED }, 0, INT_MAX, V|E|D, .unit = "alpha_mode_type"},
+{"unknown", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVALPHA_MODE_UNSPECIFIED }, 0, 0, V|E|D, .unit = "alpha_mode_type"},
+{"unspecified", "Unspecified", 0, AV_OPT_TYPE_CONST, {.i64 = AVALPHA_MODE_UNSPECIFIED }, 0, 0, V|E|D, .unit = "alpha_mode_type"},
+{"premultiplied", "Premultiplied", 0, AV_OPT_TYPE_CONST, {.i64 = AVALPHA_MODE_PREMULTIPLIED }, 0, 0, V|E|D, .unit = "alpha_mode_type"},
+{"straight", "Straight", 0, AV_OPT_TYPE_CONST, {.i64 = AVALPHA_MODE_STRAIGHT }, 0, 0, V|E|D, .unit = "alpha_mode_type"},
{"log_level_offset", "set the log level offset", OFFSET(log_level_offset), AV_OPT_TYPE_INT, {.i64 = 0 }, INT_MIN, INT_MAX },
{"slices", "set the number of slices, used in parallelized encoding", OFFSET(slices), AV_OPT_TYPE_INT, {.i64 = 0 }, 0, INT_MAX, V|E},
{"thread_type", "select multithreading type", OFFSET(thread_type), AV_OPT_TYPE_FLAGS, {.i64 = FF_THREAD_SLICE|FF_THREAD_FRAME }, 0, INT_MAX, V|A|E|D, .unit = "thread_type"},
diff --git a/libavcodec/version.h b/libavcodec/version.h
index c20072197d..9b8c267529 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,8 +29,8 @@
#include "version_major.h"
-#define LIBAVCODEC_VERSION_MINOR 14
-#define LIBAVCODEC_VERSION_MICRO 101
+#define LIBAVCODEC_VERSION_MINOR 15
+#define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
LIBAVCODEC_VERSION_MINOR, \
commit fb3a4f61806bebf68ccff188256c5faf1d71a098
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Sun Aug 17 19:43:35 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:09 2025 +0200
avfilter/formats: use vf_premultiply_dynamic for alpha mode autoconversion
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 4aa171a06e..11a0f13ac6 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -376,6 +376,7 @@ static const AVFilterFormatsMerger mergers_video[] = {
.offset = offsetof(AVFilterFormatsConfig, alpha_modes),
.merge = merge_generic,
.can_merge = can_merge_generic,
+ .conversion_filter = "premultiply_dynamic",
},
};
commit c39a67e64f71943e7c23c11f5d8d233ef66d9259
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Sun Aug 17 19:26:04 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:09 2025 +0200
avfilter/vf_premultiply: add dynamic variant of this filter
We need a filter that can premultiply and unpremultiply the alpha channel
dynamically, on demand, in response to the negotiated alpha mode, analogous
to how vf_scale operates. Introduce a new filter "vf_premultiply_dynamic"
that accomplishes this.
diff --git a/doc/filters.texi b/doc/filters.texi
index 4c774162e3..66b6c85979 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -19628,6 +19628,20 @@ By default value 0xf, all planes will be processed.
Do not require 2nd input for processing, instead use alpha plane from input stream.
@end table
+@section premultiply_dynamic
+Dynamically premultiply or unpremultiply the input video stream as needed,
+to match the requirements of the downstream filter graph. This is roughly
+equivalent to either @code{premultiply:inplace=yes} or
+@code{unpremultiply:inplace=yes}, or otherwise a noop.
+
+The filter accepts the following option:
+
+@table @option
+@item planes
+Set which planes will be processed, unprocessed planes will be copied.
+By default value 0xf, all planes will be processed.
+@end table
+
@section prewitt
Apply prewitt operator to input video stream.
diff --git a/libavfilter/allfilters.c b/libavfilter/allfilters.c
index cca4ce0288..3ac1502254 100644
--- a/libavfilter/allfilters.c
+++ b/libavfilter/allfilters.c
@@ -410,6 +410,7 @@ extern const FFFilter ff_vf_pixelize;
extern const FFFilter ff_vf_pixscope;
extern const FFFilter ff_vf_pp7;
extern const FFFilter ff_vf_premultiply;
+extern const FFFilter ff_vf_premultiply_dynamic;
extern const FFFilter ff_vf_prewitt;
extern const FFFilter ff_vf_prewitt_opencl;
extern const FFFilter ff_vf_procamp_vaapi;
diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c
index 39a084bfc5..9b4fc39ccb 100644
--- a/libavfilter/vf_premultiply.c
+++ b/libavfilter/vf_premultiply.c
@@ -41,6 +41,7 @@ typedef struct PreMultiplyContext {
int planes;
int inverse;
int inplace;
+ int dynamic;
int half, depth, offset, max;
FFFrameSync fs;
@@ -95,18 +96,25 @@ static int query_formats(const AVFilterContext *ctx,
if (ret < 0)
return ret;
- /* Configure alpha mode corresponding to the chosen direction */
- if (s->inplace) {
- formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_PREMULTIPLIED
- : AVALPHA_MODE_STRAIGHT);
- ret = ff_formats_ref(formats, &cfg_in[0]->alpha_modes);
+ if (s->dynamic) {
+ ret = ff_formats_ref(ff_all_alpha_modes(), &cfg_in[0]->alpha_modes);
if (ret < 0)
return ret;
- }
+ return ff_formats_ref(ff_all_alpha_modes(), &cfg_out[0]->alpha_modes);
+ } else {
+ /* Configure alpha mode corresponding to the chosen direction */
+ if (s->inplace) {
+ formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_PREMULTIPLIED
+ : AVALPHA_MODE_STRAIGHT);
+ ret = ff_formats_ref(formats, &cfg_in[0]->alpha_modes);
+ if (ret < 0)
+ return ret;
+ }
- formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_STRAIGHT
- : AVALPHA_MODE_PREMULTIPLIED);
- return ff_formats_ref(formats, &cfg_out[0]->alpha_modes);
+ formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_STRAIGHT
+ : AVALPHA_MODE_PREMULTIPLIED);
+ return ff_formats_ref(formats, &cfg_out[0]->alpha_modes);
+ }
}
static void premultiply8(const uint8_t *msrc, const uint8_t *asrc,
@@ -530,7 +538,7 @@ static int filter_frame(AVFilterContext *ctx,
PreMultiplyContext *s = ctx->priv;
AVFilterLink *outlink = ctx->outputs[0];
- if (ctx->is_disabled) {
+ if (ctx->is_disabled || outlink->alpha_mode == base->alpha_mode) {
*out = av_frame_clone(base);
if (!*out)
return AVERROR(ENOMEM);
@@ -741,6 +749,9 @@ static int config_output(AVFilterLink *outlink)
outlink->sample_aspect_ratio = base->sample_aspect_ratio;
ol->frame_rate = il->frame_rate;
+ if (s->dynamic)
+ s->inverse = base->alpha_mode == AVALPHA_MODE_PREMULTIPLIED;
+
if (s->inplace)
return 0;
@@ -802,6 +813,11 @@ static av_cold int init(AVFilterContext *ctx)
AVFilterPad pad = { 0 };
int ret;
+ if (!strcmp(ctx->filter->name, "premultiply_dynamic")) {
+ s->dynamic = s->inplace = 1;
+ return 0;
+ }
+
if (!strcmp(ctx->filter->name, "unpremultiply"))
s->inverse = 1;
@@ -877,3 +893,29 @@ const FFFilter ff_vf_unpremultiply = {
};
#endif /* CONFIG_UNPREMULTIPLY_FILTER */
+
+#if CONFIG_PREMULTIPLY_DYNAMIC_FILTER
+
+static const AVFilterPad premultiply_input[] = {
+ {
+ .name = "default",
+ .type = AVMEDIA_TYPE_VIDEO,
+ .config_props = config_input,
+ },
+};
+
+const FFFilter ff_vf_premultiply_dynamic = {
+ .p.name = "premultiply_dynamic",
+ .p.description = NULL_IF_CONFIG_SMALL("Premultiply or unpremultiply an image in-place, as needed."),
+ .p.priv_class = &premultiply_class,
+ .p.flags = AVFILTER_FLAG_SLICE_THREADS,
+ .priv_size = sizeof(PreMultiplyContext),
+ .init = init,
+ .uninit = uninit,
+ .activate = activate,
+ FILTER_INPUTS(premultiply_input),
+ FILTER_OUTPUTS(premultiply_outputs),
+ FILTER_QUERY_FUNC2(query_formats),
+};
+
+#endif /* CONFIG_UNPREMULTIPLY_DYNAMIC_FILTER */
commit 6bac13d20a3177e511cf7531ab9eeeb0f438a8e4
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 20:38:15 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:09 2025 +0200
avfilter/vf_premultiply: signal correct alpha mode
Set the output link according to the chosen direction, and the input link
to its opposite (unless the input is not in-place, in which case there is no
alpha channel).
Also update the alpha mode on the output frame, since it may differ.
diff --git a/libavfilter/vf_premultiply.c b/libavfilter/vf_premultiply.c
index 9647563f57..39a084bfc5 100644
--- a/libavfilter/vf_premultiply.c
+++ b/libavfilter/vf_premultiply.c
@@ -68,6 +68,8 @@ static int query_formats(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_out)
{
const PreMultiplyContext *s = ctx->priv;
+ AVFilterFormats *formats = NULL;
+ int ret;
static const enum AVPixelFormat no_alpha_pix_fmts[] = {
AV_PIX_FMT_YUV444P, AV_PIX_FMT_YUVJ444P,
@@ -88,8 +90,23 @@ static int query_formats(const AVFilterContext *ctx,
AV_PIX_FMT_NONE
};
- return ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out,
- s->inplace ? alpha_pix_fmts : no_alpha_pix_fmts);
+ ret = ff_set_common_formats_from_list2(ctx, cfg_in, cfg_out,
+ s->inplace ? alpha_pix_fmts : no_alpha_pix_fmts);
+ if (ret < 0)
+ return ret;
+
+ /* Configure alpha mode corresponding to the chosen direction */
+ if (s->inplace) {
+ formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_PREMULTIPLIED
+ : AVALPHA_MODE_STRAIGHT);
+ ret = ff_formats_ref(formats, &cfg_in[0]->alpha_modes);
+ if (ret < 0)
+ return ret;
+ }
+
+ formats = ff_make_formats_list_singleton(s->inverse ? AVALPHA_MODE_STRAIGHT
+ : AVALPHA_MODE_PREMULTIPLIED);
+ return ff_formats_ref(formats, &cfg_out[0]->alpha_modes);
}
static void premultiply8(const uint8_t *msrc, const uint8_t *asrc,
@@ -525,6 +542,7 @@ static int filter_frame(AVFilterContext *ctx,
if (!*out)
return AVERROR(ENOMEM);
av_frame_copy_props(*out, base);
+ (*out)->alpha_mode = outlink->alpha_mode;
full = base->color_range == AVCOL_RANGE_JPEG;
limited = base->color_range == AVCOL_RANGE_MPEG;
commit eea99a77eda6aa843a52e1996fcf10408248aa38
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 11:27:32 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:06:08 2025 +0200
avfilter: add link negotiation for AVAlphaMode
diff --git a/doc/APIchanges b/doc/APIchanges
index d49cdd8bdc..87357e5909 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,9 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavfi 11.6.100 - avfilter.h
+ Add AVFilterLink.alpha_mode.
+
2025-09-xx - xxxxxxxxxx - lavu 60.11.100 - frame.h pixfmt.h
Add AVAlphaMode, AVFrame.alpha_mode, av_alpha_mode_name() and
av_alpha_mode_from_name().
diff --git a/libavfilter/avfilter.c b/libavfilter/avfilter.c
index 5bcf0b4ef7..f9b64810b8 100644
--- a/libavfilter/avfilter.c
+++ b/libavfilter/avfilter.c
@@ -312,6 +312,9 @@ int avfilter_insert_filter(AVFilterLink *link, AVFilterContext *filt,
if (link->outcfg.color_ranges)
ff_formats_changeref(&link->outcfg.color_ranges,
&filt->outputs[filt_dstpad_idx]->outcfg.color_ranges);
+ if (link->outcfg.alpha_modes)
+ ff_formats_changeref(&link->outcfg.alpha_modes,
+ &filt->outputs[filt_dstpad_idx]->outcfg.alpha_modes);
if (link->outcfg.samplerates)
ff_formats_changeref(&link->outcfg.samplerates,
&filt->outputs[filt_dstpad_idx]->outcfg.samplerates);
@@ -784,6 +787,8 @@ static void free_link(AVFilterLink *link)
ff_formats_unref(&link->outcfg.color_spaces);
ff_formats_unref(&link->incfg.color_ranges);
ff_formats_unref(&link->outcfg.color_ranges);
+ ff_formats_unref(&link->incfg.alpha_modes);
+ ff_formats_unref(&link->outcfg.alpha_modes);
ff_formats_unref(&link->incfg.samplerates);
ff_formats_unref(&link->outcfg.samplerates);
ff_channel_layouts_unref(&link->incfg.channel_layouts);
diff --git a/libavfilter/avfilter.h b/libavfilter/avfilter.h
index a92144b0a6..02b58c42c2 100644
--- a/libavfilter/avfilter.h
+++ b/libavfilter/avfilter.h
@@ -141,6 +141,11 @@ typedef struct AVFilterFormatsConfig {
AVFilterFormats *color_spaces; ///< AVColorSpace
AVFilterFormats *color_ranges; ///< AVColorRange
+ /**
+ * List of supported alpha modes, only for video with an alpha channel.
+ */
+ AVFilterFormats *alpha_modes; ///< AVAlphaMode
+
} AVFilterFormatsConfig;
/**
@@ -428,6 +433,8 @@ struct AVFilterLink {
AVFrameSideData **side_data;
int nb_side_data;
+ enum AVAlphaMode alpha_mode; ///< alpha mode (for videos with an alpha channel)
+
/*****************************************************************
* All fields below this line are not part of the public API. They
* may not be used outside of libavfilter and can be changed and
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index 91aea7d36c..4c80204f01 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -303,7 +303,8 @@ static int filter_link_check_formats(void *log, AVFilterLink *link, AVFilterForm
case AVMEDIA_TYPE_VIDEO:
if ((ret = ff_formats_check_pixel_formats(log, cfg->formats)) < 0 ||
(ret = ff_formats_check_color_spaces(log, cfg->color_spaces)) < 0 ||
- (ret = ff_formats_check_color_ranges(log, cfg->color_ranges)) < 0)
+ (ret = ff_formats_check_color_ranges(log, cfg->color_ranges)) < 0 ||
+ (ret = ff_formats_check_alpha_modes(log, cfg->alpha_modes)) < 0)
return ret;
break;
@@ -418,7 +419,8 @@ static int formats_declared(AVFilterContext *f)
return 0;
if (f->inputs[i]->type == AVMEDIA_TYPE_VIDEO &&
!(f->inputs[i]->outcfg.color_ranges &&
- f->inputs[i]->outcfg.color_spaces))
+ f->inputs[i]->outcfg.color_spaces &&
+ f->inputs[i]->outcfg.alpha_modes))
return 0;
if (f->inputs[i]->type == AVMEDIA_TYPE_AUDIO &&
!(f->inputs[i]->outcfg.samplerates &&
@@ -430,7 +432,8 @@ static int formats_declared(AVFilterContext *f)
return 0;
if (f->outputs[i]->type == AVMEDIA_TYPE_VIDEO &&
!(f->outputs[i]->incfg.color_ranges &&
- f->outputs[i]->incfg.color_spaces))
+ f->outputs[i]->incfg.color_spaces &&
+ f->outputs[i]->incfg.alpha_modes))
return 0;
if (f->outputs[i]->type == AVMEDIA_TYPE_AUDIO &&
!(f->outputs[i]->incfg.samplerates &&
@@ -641,6 +644,10 @@ retry:
av_assert0( inlink->outcfg.color_ranges->refcount > 0);
av_assert0(outlink-> incfg.color_ranges->refcount > 0);
av_assert0(outlink->outcfg.color_ranges->refcount > 0);
+ av_assert0( inlink-> incfg.alpha_modes->refcount > 0);
+ av_assert0( inlink->outcfg.alpha_modes->refcount > 0);
+ av_assert0(outlink-> incfg.alpha_modes->refcount > 0);
+ av_assert0(outlink->outcfg.alpha_modes->refcount > 0);
} else if (outlink->type == AVMEDIA_TYPE_AUDIO) {
av_assert0( inlink-> incfg.samplerates->refcount > 0);
av_assert0( inlink->outcfg.samplerates->refcount > 0);
@@ -820,8 +827,8 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
swfmt = AV_PIX_FMT_YUV420P;
}
+ const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swfmt);
if (!ff_fmt_is_regular_yuv(swfmt)) {
- const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(swfmt);
/* These fields are explicitly documented as affecting YUV only,
* so set them to sane values for other formats. */
if (desc->flags & AV_PIX_FMT_FLAG_FLOAT)
@@ -856,6 +863,19 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
link->color_range = link->incfg.color_ranges->formats[0];
}
}
+
+ if (desc->flags & AV_PIX_FMT_FLAG_ALPHA) {
+ if (!link->incfg.alpha_modes->nb_formats) {
+ av_log(link->src, AV_LOG_ERROR, "Cannot select alpha mode for"
+ " the link between filters %s and %s.\n", link->src->name,
+ link->dst->name);
+ return AVERROR(EINVAL);
+ }
+ link->incfg.alpha_modes->nb_formats = 1;
+ link->alpha_mode = link->incfg.alpha_modes->formats[0];
+ } else {
+ link->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
+ }
} else if (link->type == AVMEDIA_TYPE_AUDIO) {
int ret;
@@ -894,6 +914,8 @@ static int pick_format(AVFilterLink *link, AVFilterLink *ref)
ff_formats_unref(&link->outcfg.color_spaces);
ff_formats_unref(&link->incfg.color_ranges);
ff_formats_unref(&link->outcfg.color_ranges);
+ ff_formats_unref(&link->incfg.alpha_modes);
+ ff_formats_unref(&link->outcfg.alpha_modes);
return 0;
}
@@ -947,6 +969,8 @@ static int reduce_formats_on_filter(AVFilterContext *filter)
nb_formats, ff_add_format);
REDUCE_FORMATS(int, AVFilterFormats, color_ranges, formats,
nb_formats, ff_add_format);
+ REDUCE_FORMATS(int, AVFilterFormats, alpha_modes, formats,
+ nb_formats, ff_add_format);
/* reduce channel layouts */
for (i = 0; i < filter->nb_inputs; i++) {
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 81c63e50cd..4aa171a06e 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -372,6 +372,11 @@ static const AVFilterFormatsMerger mergers_video[] = {
.can_merge = can_merge_generic,
CONVERSION_FILTER_SWSCALE
},
+ {
+ .offset = offsetof(AVFilterFormatsConfig, alpha_modes),
+ .merge = merge_generic,
+ .can_merge = can_merge_generic,
+ },
};
static const AVFilterFormatsMerger mergers_audio[] = {
@@ -665,6 +670,17 @@ AVFilterFormats *ff_all_color_ranges(void)
return ret;
}
+AVFilterFormats *ff_all_alpha_modes(void)
+{
+ AVFilterFormats *ret = NULL;
+ for (int range = 0; range < AVALPHA_MODE_NB; range++) {
+ if (ff_add_format(&ret, range) < 0)
+ return NULL;
+ }
+
+ return ret;
+}
+
#define FORMATS_REF(f, ref, unref_fn) \
void *tmp; \
\
@@ -870,6 +886,24 @@ int ff_set_common_all_color_ranges(AVFilterContext *ctx)
return ff_set_common_color_ranges(ctx, ff_all_color_ranges());
}
+int ff_set_common_alpha_modes(AVFilterContext *ctx,
+ AVFilterFormats *alpha_modes)
+{
+ SET_COMMON_FORMATS(ctx, alpha_modes, AVMEDIA_TYPE_VIDEO,
+ ff_formats_ref, ff_formats_unref);
+}
+
+int ff_set_common_alpha_modes_from_list(AVFilterContext *ctx,
+ const int *alpha_modes)
+{
+ return ff_set_common_alpha_modes(ctx, ff_make_format_list(alpha_modes));
+}
+
+int ff_set_common_all_alpha_modes(AVFilterContext *ctx)
+{
+ return ff_set_common_alpha_modes(ctx, ff_all_alpha_modes());
+}
+
/**
* A helper for query_formats() which sets all links to the same list of
* formats. If there are no links hooked to this filter, the list of formats is
@@ -1015,6 +1049,30 @@ int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
return ff_set_common_color_ranges2(ctx, cfg_in, cfg_out, ff_all_color_ranges());
}
+int ff_set_common_alpha_modes2(const AVFilterContext *ctx,
+ AVFilterFormatsConfig **cfg_in,
+ AVFilterFormatsConfig **cfg_out,
+ AVFilterFormats *alpha_modes)
+{
+ SET_COMMON_FORMATS2(ctx, cfg_in, cfg_out, alpha_modes, AVMEDIA_TYPE_VIDEO,
+ ff_formats_ref, ff_formats_unref);
+}
+
+int ff_set_common_alpha_modes_from_list2(const AVFilterContext *ctx,
+ AVFilterFormatsConfig **cfg_in,
+ AVFilterFormatsConfig **cfg_out,
+ const int *alpha_modes)
+{
+ return ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, ff_make_format_list(alpha_modes));
+}
+
+int ff_set_common_all_alpha_modes2(const AVFilterContext *ctx,
+ AVFilterFormatsConfig **cfg_in,
+ AVFilterFormatsConfig **cfg_out)
+{
+ return ff_set_common_alpha_modes2(ctx, cfg_in, cfg_out, ff_all_alpha_modes());
+}
+
int ff_set_common_formats2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
@@ -1080,6 +1138,9 @@ int ff_default_query_formats(AVFilterContext *ctx)
ret = ff_set_common_all_color_ranges(ctx);
if (ret < 0)
return ret;
+ ret = ff_set_common_all_alpha_modes(ctx);
+ if (ret < 0)
+ return ret;
}
if (type != AVMEDIA_TYPE_VIDEO) {
ret = ff_set_common_all_channel_counts(ctx);
@@ -1147,6 +1208,11 @@ int ff_formats_check_color_ranges(void *log, const AVFilterFormats *fmts)
return check_list(log, "color range", fmts);
}
+int ff_formats_check_alpha_modes(void *log, const AVFilterFormats *fmts)
+{
+ return check_list(log, "alpha mode", fmts);
+}
+
static int layouts_compatible(const AVChannelLayout *a, const AVChannelLayout *b)
{
return !av_channel_layout_compare(a, b) ||
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index b23ebf82f9..0c92ecad3f 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -144,6 +144,12 @@ AVFilterFormats *ff_all_color_spaces(void);
av_warn_unused_result
AVFilterFormats *ff_all_color_ranges(void);
+/**
+ * Construct an AVFilterFormats representing all possible alpha modes.
+ */
+av_warn_unused_result
+AVFilterFormats *ff_all_alpha_modes(void);
+
/**
* Helpers for query_formats() which set all free audio links to the same list
* of channel layouts/sample rates. If there are no links hooked to this list,
@@ -211,6 +217,23 @@ int ff_set_common_color_ranges_from_list(AVFilterContext *ctx,
av_warn_unused_result
int ff_set_common_all_color_ranges(AVFilterContext *ctx);
+av_warn_unused_result
+int ff_set_common_alpha_modes(AVFilterContext *ctx,
+ AVFilterFormats *alpha_modes);
+/**
+ * Equivalent to ff_set_common_alpha_modes(ctx, ff_make_format_list(alpha_modes))
+ */
+av_warn_unused_result
+int ff_set_common_alpha_modes_from_list(AVFilterContext *ctx,
+ const int *alpha_modes);
+
+/**
+ * Equivalent to ff_set_common_alpha_modes(ctx, ff_all_alpha_modes())
+ */
+av_warn_unused_result
+int ff_set_common_all_alpha_modes(AVFilterContext *ctx);
+
+
/**
* A helper for query_formats() which sets all links to the same list of
* formats. If there are no links hooked to this filter, the list of formats is
@@ -297,6 +320,23 @@ int ff_set_common_all_color_ranges2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out);
+av_warn_unused_result
+int ff_set_common_alpha_modes2(const AVFilterContext *ctx,
+ AVFilterFormatsConfig **cfg_in,
+ AVFilterFormatsConfig **cfg_out,
+ AVFilterFormats *alpha_modes);
+
+av_warn_unused_result
+int ff_set_common_alpha_modes_from_list2(const AVFilterContext *ctx,
+ AVFilterFormatsConfig **cfg_in,
+ AVFilterFormatsConfig **cfg_out,
+ const int *alpha_modes);
+
+av_warn_unused_result
+int ff_set_common_all_alpha_modes2(const AVFilterContext *ctx,
+ AVFilterFormatsConfig **cfg_in,
+ AVFilterFormatsConfig **cfg_out);
+
av_warn_unused_result
int ff_set_common_formats2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
@@ -466,6 +506,13 @@ int ff_formats_check_channel_layouts(void *log, const AVFilterChannelLayouts *fm
int ff_formats_check_color_spaces(void *log, const AVFilterFormats *fmts);
int ff_formats_check_color_ranges(void *log, const AVFilterFormats *fmts);
+/**
+ * Check that fmts is a valid formats list for alpha modes.
+ *
+ * In particular, check for duplicates.
+ */
+int ff_formats_check_alpha_modes(void *log, const AVFilterFormats *fmts);
+
typedef struct AVFilterFormatMerger {
unsigned offset;
int (*merge)(void *a, void *b);
diff --git a/libavfilter/version.h b/libavfilter/version.h
index 523a7fe0a6..f191d98883 100644
--- a/libavfilter/version.h
+++ b/libavfilter/version.h
@@ -31,7 +31,7 @@
#include "version_major.h"
-#define LIBAVFILTER_VERSION_MINOR 5
+#define LIBAVFILTER_VERSION_MINOR 6
#define LIBAVFILTER_VERSION_MICRO 100
diff --git a/libavfilter/video.c b/libavfilter/video.c
index 1de7f2ef59..13dab90b65 100644
--- a/libavfilter/video.c
+++ b/libavfilter/video.c
@@ -104,6 +104,7 @@ AVFrame *ff_default_get_video_buffer2(AVFilterLink *link, int w, int h, int alig
frame->sample_aspect_ratio = link->sample_aspect_ratio;
frame->colorspace = link->colorspace;
frame->color_range = link->color_range;
+ frame->alpha_mode = link->alpha_mode;
return frame;
}
commit 8b375b2ffd4377909180241cdc65d63d372a35a3
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Sun Aug 17 19:30:56 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:05:51 2025 +0200
avfilter/avfiltergraph: allow different conversion filters per merger
Instead of hard-coding the assumption that all video properties are handled
by vf_scale, generalize the struct slightly to allow different conversion
filters for each property being merged. The avfiltergraph code creates a list
of conversion filters needed and inserts all of them at once.
Because a conversion filter might itself e.g. not support all formats,
it's possible that we need to go through the whole process of negotiating
formats multiple times, and keep adding conversion filters until all of them
are settled. Do this by simply jumping back to the beginning of the loop
to ensure that the `convertor_count` field remains contiguous.
diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index bf80391869..91aea7d36c 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -508,7 +508,7 @@ static void print_filter_formats(void *log_ctx, int level, const AVFilterContext
*/
static int query_formats(AVFilterGraph *graph, void *log_ctx)
{
- int i, j, ret;
+ int i, j, k, ret;
int converter_count = 0;
int count_queried = 0; /* successful calls to query_formats() */
int count_merged = 0; /* successful merge of formats lists */
@@ -530,14 +530,16 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
}
/* go through and merge as many format lists as possible */
+retry:
for (i = 0; i < graph->nb_filters; i++) {
AVFilterContext *filter = graph->filters[i];
for (j = 0; j < filter->nb_inputs; j++) {
AVFilterLink *link = filter->inputs[j];
const AVFilterNegotiation *neg;
- unsigned neg_step;
- int convert_needed = 0;
+ AVFilterContext *conv[4];
+ const char *conv_filters[4], *conv_opts[4] = {0};
+ unsigned neg_step, num_conv = 0;
if (!link)
continue;
@@ -549,8 +551,17 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
void *a = FF_FIELD_AT(void *, m->offset, link->incfg);
void *b = FF_FIELD_AT(void *, m->offset, link->outcfg);
if (a && b && a != b && !m->can_merge(a, b)) {
- convert_needed = 1;
- break;
+ for (k = 0; k < num_conv; k++) {
+ if (conv_filters[k] == m->conversion_filter)
+ break;
+ }
+ if (k == num_conv) {
+ av_assert1(num_conv < FF_ARRAY_ELEMS(conv_filters));
+ conv_filters[num_conv] = m->conversion_filter;
+ if (m->conversion_opts_offset)
+ conv_opts[num_conv] = FF_FIELD_AT(char *, m->conversion_opts_offset, *graph);
+ num_conv++;
+ }
}
}
for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) {
@@ -561,22 +572,28 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
count_delayed++;
} else if (a == b) {
count_already_merged++;
- } else if (!convert_needed) {
+ } else if (!num_conv) {
count_merged++;
ret = m->merge(a, b);
if (ret < 0)
return ret;
- if (!ret)
- convert_needed = 1;
+ if (!ret) {
+ conv_filters[num_conv] = m->conversion_filter;
+ if (m->conversion_opts_offset)
+ conv_opts[num_conv] = FF_FIELD_AT(char *, m->conversion_opts_offset, *graph);
+ num_conv++;
+ }
}
}
- if (convert_needed) {
- AVFilterContext *convert;
+ /**
+ * Couldn't merge format lists; auto-insert conversion filters
+ * in reverse order to keep the order consistent with the list
+ * of mergers, since they are prepended onto the existing link
+ */
+ for (k = num_conv - 1; k >= 0; k--) {
const AVFilter *filter;
- AVFilterLink *inlink, *outlink;
char inst_name[30];
- const char *opts;
if (fffiltergraph(graph)->disable_auto_convert) {
av_log(log_ctx, AV_LOG_ERROR,
@@ -587,28 +604,30 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
return AVERROR(EINVAL);
}
- /* couldn't merge format lists. auto-insert conversion filter */
- if (!(filter = avfilter_get_by_name(neg->conversion_filter))) {
+ if (!(filter = avfilter_get_by_name(conv_filters[k]))) {
av_log(log_ctx, AV_LOG_ERROR,
"'%s' filter not present, cannot convert formats.\n",
- neg->conversion_filter);
+ conv_filters[k]);
print_link_formats(log_ctx, AV_LOG_ERROR, link);
return AVERROR(EINVAL);
}
snprintf(inst_name, sizeof(inst_name), "auto_%s_%d",
- neg->conversion_filter, converter_count++);
- opts = FF_FIELD_AT(char *, neg->conversion_opts_offset, *graph);
- ret = avfilter_graph_create_filter(&convert, filter, inst_name, opts, NULL, graph);
+ conv_filters[k], converter_count++);
+ ret = avfilter_graph_create_filter(&conv[k], filter, inst_name,
+ conv_opts[k], NULL, graph);
if (ret < 0)
return ret;
- if ((ret = avfilter_insert_filter(link, convert, 0, 0)) < 0)
+ if ((ret = avfilter_insert_filter(link, conv[k], 0, 0)) < 0)
return ret;
- if ((ret = filter_query_formats(convert)) < 0)
+ if ((ret = filter_query_formats(conv[k])) < 0)
return ret;
+ }
- inlink = convert->inputs[0];
- outlink = convert->outputs[0];
+ /* preemptively settle formats of auto filters */
+ for (k = 0; k < num_conv; k++) {
+ AVFilterLink *inlink = conv[k]->inputs[0];
+ AVFilterLink *outlink = conv[k]->outputs[0];
av_assert0( inlink->incfg.formats->refcount > 0);
av_assert0( inlink->outcfg.formats->refcount > 0);
av_assert0(outlink->incfg.formats->refcount > 0);
@@ -632,11 +651,15 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
av_assert0(outlink-> incfg.channel_layouts->refcount > 0);
av_assert0(outlink->outcfg.channel_layouts->refcount > 0);
}
+
#define MERGE(merger, link) \
((merger)->merge(FF_FIELD_AT(void *, (merger)->offset, (link)->incfg), \
FF_FIELD_AT(void *, (merger)->offset, (link)->outcfg)))
+
for (neg_step = 0; neg_step < neg->nb_mergers; neg_step++) {
const AVFilterFormatsMerger *m = &neg->mergers[neg_step];
+ if (m->conversion_filter != conv_filters[k])
+ continue;
if ((ret = MERGE(m, inlink)) <= 0 ||
(ret = MERGE(m, outlink)) <= 0) {
if (ret < 0)
@@ -646,9 +669,17 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
"'%s' and the filter '%s'\n", link->src->name, link->dst->name);
print_link_formats(log_ctx, AV_LOG_ERROR, link);
return AVERROR(ENOSYS);
+ } else {
+ count_merged += 2;
}
}
}
+
+ /* if there is more than one auto filter, we may need another round
+ * to fully settle formats due to possible cross-incompatibilities
+ * between the auto filters themselves */
+ if (num_conv > 1)
+ goto retry;
}
}
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 652ec99c02..81c63e50cd 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -345,21 +345,32 @@ static int merge_generic(void *a, void *b)
return merge_generic_internal(a, b, 0);
}
+#define CONVERSION_FILTER_SWSCALE \
+ .conversion_filter = "scale", \
+ .conversion_opts_offset = offsetof(AVFilterGraph, scale_sws_opts),
+
+#define CONVERSION_FILTER_ARESAMPLE \
+ .conversion_filter = "aresample", \
+ .conversion_opts_offset = offsetof(AVFilterGraph, aresample_swr_opts),
+
static const AVFilterFormatsMerger mergers_video[] = {
{
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_pix_fmts,
.can_merge = can_merge_pix_fmts,
+ CONVERSION_FILTER_SWSCALE
},
{
.offset = offsetof(AVFilterFormatsConfig, color_spaces),
.merge = merge_generic,
.can_merge = can_merge_generic,
+ CONVERSION_FILTER_SWSCALE
},
{
.offset = offsetof(AVFilterFormatsConfig, color_ranges),
.merge = merge_generic,
.can_merge = can_merge_generic,
+ CONVERSION_FILTER_SWSCALE
},
};
@@ -368,31 +379,30 @@ static const AVFilterFormatsMerger mergers_audio[] = {
.offset = offsetof(AVFilterFormatsConfig, channel_layouts),
.merge = merge_channel_layouts,
.can_merge = can_merge_channel_layouts,
+ CONVERSION_FILTER_ARESAMPLE
},
{
.offset = offsetof(AVFilterFormatsConfig, samplerates),
.merge = merge_samplerates,
.can_merge = can_merge_samplerates,
+ CONVERSION_FILTER_ARESAMPLE
},
{
.offset = offsetof(AVFilterFormatsConfig, formats),
.merge = merge_sample_fmts,
.can_merge = can_merge_sample_fmts,
+ CONVERSION_FILTER_ARESAMPLE
},
};
static const AVFilterNegotiation negotiate_video = {
.nb_mergers = FF_ARRAY_ELEMS(mergers_video),
.mergers = mergers_video,
- .conversion_filter = "scale",
- .conversion_opts_offset = offsetof(AVFilterGraph, scale_sws_opts),
};
static const AVFilterNegotiation negotiate_audio = {
.nb_mergers = FF_ARRAY_ELEMS(mergers_audio),
.mergers = mergers_audio,
- .conversion_filter = "aresample",
- .conversion_opts_offset = offsetof(AVFilterGraph, aresample_swr_opts),
};
const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link)
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index c45e195e54..b23ebf82f9 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -470,6 +470,8 @@ typedef struct AVFilterFormatMerger {
unsigned offset;
int (*merge)(void *a, void *b);
int (*can_merge)(const void *a, const void *b);
+ const char *conversion_filter;
+ unsigned conversion_opts_offset;
} AVFilterFormatsMerger;
/**
@@ -560,8 +562,6 @@ typedef struct AVFilterFormatMerger {
typedef struct AVFilterNegotiation {
unsigned nb_mergers;
const AVFilterFormatsMerger *mergers;
- const char *conversion_filter;
- unsigned conversion_opts_offset;
} AVFilterNegotiation;
const AVFilterNegotiation *ff_filter_get_negotiation(AVFilterLink *link);
commit dbcdcaede8544705af0c3d63d0831fe20d5c1ff4
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Aug 13 11:26:13 2025 +0200
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:05:51 2025 +0200
avfilter/formats: fix param name on ff_set_common_color_spaces*
Purely cosmetic.
diff --git a/libavfilter/formats.c b/libavfilter/formats.c
index 9bd9690df2..652ec99c02 100644
--- a/libavfilter/formats.c
+++ b/libavfilter/formats.c
@@ -832,9 +832,9 @@ int ff_set_common_color_spaces(AVFilterContext *ctx,
}
int ff_set_common_color_spaces_from_list(AVFilterContext *ctx,
- const int *color_ranges)
+ const int *color_spaces)
{
- return ff_set_common_color_spaces(ctx, ff_make_format_list(color_ranges));
+ return ff_set_common_color_spaces(ctx, ff_make_format_list(color_spaces));
}
int ff_set_common_all_color_spaces(AVFilterContext *ctx)
@@ -969,9 +969,9 @@ int ff_set_common_color_spaces2(const AVFilterContext *ctx,
int ff_set_common_color_spaces_from_list2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
- const int *color_ranges)
+ const int *color_spaces)
{
- return ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, ff_make_format_list(color_ranges));
+ return ff_set_common_color_spaces2(ctx, cfg_in, cfg_out, ff_make_format_list(color_spaces));
}
int ff_set_common_all_color_spaces2(const AVFilterContext *ctx,
diff --git a/libavfilter/formats.h b/libavfilter/formats.h
index 380e9dfd00..c45e195e54 100644
--- a/libavfilter/formats.h
+++ b/libavfilter/formats.h
@@ -273,7 +273,7 @@ av_warn_unused_result
int ff_set_common_color_spaces_from_list2(const AVFilterContext *ctx,
AVFilterFormatsConfig **cfg_in,
AVFilterFormatsConfig **cfg_out,
- const int *color_ranges);
+ const int *color_spaces);
av_warn_unused_result
int ff_set_common_all_color_spaces2(const AVFilterContext *ctx,
commit 22929bd044cdf971ea2a5b906c6fadbe653a7c19
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Wed Feb 19 19:41:18 2025 +0100
Commit: Niklas Haas <git(a)haasn.dev>
CommitDate: Tue Sep 2 17:05:50 2025 +0200
avutil/frame: add AVFrame.alpha_mode
FFmpeg currently handles alpha in a quasi-arbitrary way. Some filters/codecs
assume alpha is premultiplied, others assume it is independent. If there is
to be any hope for order in this chaos, we need to start by defining an enum
for the possible range of values.
diff --git a/doc/APIchanges b/doc/APIchanges
index bd5a76cbe6..d49cdd8bdc 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -2,6 +2,10 @@ The last version increases of all libraries were on 2025-03-28
API changes, most recent first:
+2025-09-xx - xxxxxxxxxx - lavu 60.11.100 - frame.h pixfmt.h
+ Add AVAlphaMode, AVFrame.alpha_mode, av_alpha_mode_name() and
+ av_alpha_mode_from_name().
+
2025-09-xx - xxxxxxxxxx - lsws 9.3.100 - swscale.h
Add SWS_UNSTABLE flag.
diff --git a/libavutil/frame.c b/libavutil/frame.c
index 8f3fda2371..be30eb09d2 100644
--- a/libavutil/frame.c
+++ b/libavutil/frame.c
@@ -45,6 +45,7 @@ static void get_frame_defaults(AVFrame *frame)
frame->colorspace = AVCOL_SPC_UNSPECIFIED;
frame->color_range = AVCOL_RANGE_UNSPECIFIED;
frame->chroma_location = AVCHROMA_LOC_UNSPECIFIED;
+ frame->alpha_mode = AVALPHA_MODE_UNSPECIFIED;
frame->flags = 0;
}
@@ -240,6 +241,7 @@ static int frame_copy_props(AVFrame *dst, const AVFrame *src, int force_copy)
dst->colorspace = src->colorspace;
dst->color_range = src->color_range;
dst->chroma_location = src->chroma_location;
+ dst->alpha_mode = src->alpha_mode;
av_dict_copy(&dst->metadata, src->metadata, 0);
diff --git a/libavutil/frame.h b/libavutil/frame.h
index d7d98e67e4..088b24b717 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -773,6 +773,13 @@ typedef struct AVFrame {
* Duration of the frame, in the same units as pts. 0 if unknown.
*/
int64_t duration;
+
+ /**
+ * Indicates how the alpha channel of the video is to be handled.
+ * - encoding: Set by user
+ * - decoding: Set by libavcodec
+ */
+ enum AVAlphaMode alpha_mode;
} AVFrame;
diff --git a/libavutil/pixdesc.c b/libavutil/pixdesc.c
index f0be20d749..3c31ee2132 100644
--- a/libavutil/pixdesc.c
+++ b/libavutil/pixdesc.c
@@ -3345,6 +3345,12 @@ static const char * const chroma_location_names[] = {
[AVCHROMA_LOC_BOTTOM] = "bottom",
};
+static const char * const alpha_mode_names[] = {
+ [AVALPHA_MODE_UNSPECIFIED] = "unspecified",
+ [AVALPHA_MODE_PREMULTIPLIED] = "premultiplied",
+ [AVALPHA_MODE_STRAIGHT] = "straight",
+};
+
static enum AVPixelFormat get_pix_fmt_internal(const char *name)
{
enum AVPixelFormat pix_fmt;
@@ -3878,3 +3884,22 @@ enum AVChromaLocation av_chroma_location_pos_to_enum(int xpos, int ypos)
}
return AVCHROMA_LOC_UNSPECIFIED;
}
+
+const char *av_alpha_mode_name(enum AVAlphaMode mode)
+{
+ return (unsigned) mode < AVALPHA_MODE_NB ?
+ alpha_mode_names[mode] : NULL;
+}
+
+enum AVAlphaMode av_alpha_mode_from_name(const char *name)
+{
+ for (int i = 0; i < FF_ARRAY_ELEMS(alpha_mode_names); i++) {
+ if (!alpha_mode_names[i])
+ continue;
+
+ if (av_strstart(name, alpha_mode_names[i], NULL))
+ return i;
+ }
+
+ return AVERROR(EINVAL);
+}
diff --git a/libavutil/pixdesc.h b/libavutil/pixdesc.h
index ba2f632814..0cc70eb64c 100644
--- a/libavutil/pixdesc.h
+++ b/libavutil/pixdesc.h
@@ -291,6 +291,16 @@ int av_chroma_location_enum_to_pos(int *xpos, int *ypos, enum AVChromaLocation p
*/
enum AVChromaLocation av_chroma_location_pos_to_enum(int xpos, int ypos);
+/**
+ * @return the name for provided alpha mode or NULL if unknown.
+ */
+const char *av_alpha_mode_name(enum AVAlphaMode mode);
+
+/**
+ * @return the AVAlphaMode value for name or an AVError if not found.
+ */
+enum AVAlphaMode av_alpha_mode_from_name(const char *name);
+
/**
* Return the pixel format corresponding to name.
*
diff --git a/libavutil/pixfmt.h b/libavutil/pixfmt.h
index 823ea8edab..6aa1c94cec 100644
--- a/libavutil/pixfmt.h
+++ b/libavutil/pixfmt.h
@@ -794,4 +794,14 @@ enum AVChromaLocation {
AVCHROMA_LOC_NB ///< Not part of ABI
};
+/**
+ * Correlation between the alpha channel and color values.
+ */
+enum AVAlphaMode {
+ AVALPHA_MODE_UNSPECIFIED = 0, ///< Unknown alpha handling, or no alpha channel
+ AVALPHA_MODE_PREMULTIPLIED = 1, ///< Alpha channel is multiplied into color values
+ AVALPHA_MODE_STRAIGHT = 2, ///< Alpha channel is independent of color values
+ AVALPHA_MODE_NB ///< Not part of ABI
+};
+
#endif /* AVUTIL_PIXFMT_H */
diff --git a/libavutil/version.h b/libavutil/version.h
index 27b9fe73d8..a1707d3f4e 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 60
-#define LIBAVUTIL_VERSION_MINOR 10
+#define LIBAVUTIL_VERSION_MINOR 11
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
-----------------------------------------------------------------------
Summary of changes:
doc/APIchanges | 17 +++
doc/codecs.texi | 8 +
doc/filters.texi | 43 +++++-
fftools/ffmpeg.h | 2 +
fftools/ffmpeg_dec.c | 1 +
fftools/ffmpeg_enc.c | 1 +
fftools/ffmpeg_filter.c | 28 +++-
fftools/ffmpeg_mux_init.c | 6 +
fftools/ffplay.c | 10 ++
fftools/ffprobe.c | 11 ++
libavcodec/avcodec.c | 6 +
libavcodec/avcodec.h | 8 +
libavcodec/codec_internal.h | 5 +
libavcodec/codec_par.c | 3 +
libavcodec/codec_par.h | 5 +
libavcodec/decode.c | 2 +
libavcodec/encode.c | 27 ++++
libavcodec/exr.c | 3 +
libavcodec/exrenc.c | 3 +
libavcodec/jpegxl_parse.c | 7 +-
libavcodec/jpegxl_parse.h | 1 +
libavcodec/jpegxl_parser.c | 5 +
libavcodec/libjxldec.c | 6 +
libavcodec/libjxlenc.c | 28 ++++
libavcodec/options_table.h | 5 +
libavcodec/pngdec.c | 5 +
libavcodec/pngenc.c | 6 +
libavcodec/version.h | 4 +-
libavfilter/allfilters.c | 1 +
libavfilter/avfilter.c | 7 +
libavfilter/avfilter.h | 7 +
libavfilter/avfiltergraph.c | 107 ++++++++++----
libavfilter/buffersink.c | 27 +++-
libavfilter/buffersink.h | 2 +
libavfilter/buffersrc.c | 43 ++++--
libavfilter/buffersrc.h | 5 +
libavfilter/drawutils.c | 16 +-
libavfilter/drawutils.h | 10 +-
libavfilter/formats.c | 93 +++++++++++-
libavfilter/formats.h | 53 ++++++-
libavfilter/qrencode.c | 8 +-
libavfilter/src_avsynctest.c | 2 +-
libavfilter/version.h | 2 +-
libavfilter/vf_alphamerge.c | 7 +
libavfilter/vf_datascope.c | 2 +-
libavfilter/vf_drawtext.c | 2 +-
libavfilter/vf_extractplanes.c | 4 +
libavfilter/vf_fade.c | 19 ++-
libavfilter/vf_format.c | 22 ++-
libavfilter/vf_libplacebo.c | 14 ++
libavfilter/vf_overlay.c | 260 +++++++++++++++------------------
libavfilter/vf_overlay.h | 5 +-
libavfilter/vf_pad.c | 2 +-
libavfilter/vf_premultiply.c | 66 ++++++++-
libavfilter/vf_rotate.c | 2 +-
libavfilter/vf_scale.c | 7 +
libavfilter/vf_setparams.c | 19 +++
libavfilter/vf_shear.c | 2 +-
libavfilter/vf_showinfo.c | 8 +
libavfilter/vf_stack.c | 2 +-
libavfilter/vf_subtitles.c | 2 +-
libavfilter/vf_tile.c | 2 +-
libavfilter/vf_tinterlace.c | 2 +-
libavfilter/vf_tpad.c | 2 +-
libavfilter/vf_zscale.c | 97 ++----------
libavfilter/video.c | 1 +
libavfilter/vsrc_testsrc.c | 9 +-
libavfilter/x86/vf_overlay_init.c | 23 +--
libavutil/frame.c | 2 +
libavutil/frame.h | 7 +
libavutil/pixdesc.c | 25 ++++
libavutil/pixdesc.h | 10 ++
libavutil/pixfmt.h | 10 ++
libavutil/version.h | 2 +-
tests/ref/fate/enhanced-flv-hevc-hdr10 | 1 +
tests/ref/fate/exif-image-embedded | 1 +
tests/ref/fate/exif-image-jpg | 1 +
tests/ref/fate/exif-image-tiff | 1 +
tests/ref/fate/exif-image-webp | 1 +
tests/ref/fate/ffprobe_compact | 16 +-
tests/ref/fate/ffprobe_csv | 16 +-
tests/ref/fate/ffprobe_default | 8 +
tests/ref/fate/ffprobe_flat | 8 +
tests/ref/fate/ffprobe_ini | 8 +
tests/ref/fate/h264-dts_5frames | 5 +
tests/ref/fate/jpg-icc | 1 +
tests/ref/fate/mov-zombie | 130 ++++++++---------
tests/ref/fate/png-icc | 1 +
tests/ref/fate/png-icc-parse | 1 +
tests/ref/fate/png-side-data | 1 +
90 files changed, 1066 insertions(+), 410 deletions(-)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. f24474dcfc avcodec/aac_ac3_parser: do not override the profile set by the decoder
by ffmpeg-git@ffmpeg.org 02 Sep '25
by ffmpeg-git@ffmpeg.org 02 Sep '25
02 Sep '25
The branch, master has been updated
via f24474dcfc719e29dc87e6483d6187ea233f4e0f (commit)
via 593b4269027ea6d514b8505d317f6f131693c84e (commit)
via 9bd10fa32cce741fd0dd900ab9db28cc00e3c9b7 (commit)
via 5e210f0552b29c7c369662e12674e724441ac069 (commit)
via a282500087591ef5a22942d204f5743afa2265d4 (commit)
via d7173e982ec815dcf70999c8683c465b99ce249c (commit)
via 173988aa0c2b8710e47a0b4d3651b1fe6d2166ce (commit)
via 5d7e4b7496bc5f6327202d4ed53052311abded2f (commit)
from 5d3538b8dc5d969dcdbc419d5b6903f776845efb (commit)
- Log -----------------------------------------------------------------
commit f24474dcfc719e29dc87e6483d6187ea233f4e0f
Author: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
AuthorDate: Tue Aug 12 12:35:18 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 16:05:46 2025 +0200
avcodec/aac_ac3_parser: do not override the profile set by the decoder
Parsing the ADTS header is not enough to detect HE-AAC v1/v2.
Regression since 64bb91fd3b5a00a8849531c7e8dd207f2a626096.
Fixes #11600
Signed-off-by: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c
index b49ce0277c..51c801214c 100644
--- a/libavcodec/aac_ac3_parser.c
+++ b/libavcodec/aac_ac3_parser.c
@@ -152,7 +152,8 @@ get_next:
ff_adts_header_parse_buf(buf, &hdr) < 0)
return i;
- avctx->profile = hdr.object_type - 1;
+ if (avctx->profile == AV_PROFILE_UNKNOWN)
+ avctx->profile = hdr.object_type - 1;
/* ADTS does not support USAC */
s1->key_frame = 1;
bit_rate = hdr.bit_rate;
commit 593b4269027ea6d514b8505d317f6f131693c84e
Author: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
AuthorDate: Tue Aug 12 12:35:17 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 16:05:46 2025 +0200
avcodec/aac_ac3_parser: simplify
Use ff_adts_header_parse_buf() wrapper to simplify as GetBitContext is
no longer needed (it was introduced for USAC).
Partially reverts 64bb91fd3b5a00a8849531c7e8dd207f2a626096.
Signed-off-by: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c
index ced640dd28..b49ce0277c 100644
--- a/libavcodec/aac_ac3_parser.c
+++ b/libavcodec/aac_ac3_parser.c
@@ -147,11 +147,9 @@ get_next:
} else {
#if CONFIG_AAC_PARSER
AACADTSHeaderInfo hdr;
- GetBitContext gb;
- init_get_bits8(&gb, buf, buf_size);
if (buf_size < AV_AAC_ADTS_HEADER_SIZE ||
- ff_adts_header_parse(&gb, &hdr) < 0)
+ ff_adts_header_parse_buf(buf, &hdr) < 0)
return i;
avctx->profile = hdr.object_type - 1;
commit 9bd10fa32cce741fd0dd900ab9db28cc00e3c9b7
Author: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
AuthorDate: Tue Aug 12 12:35:16 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 16:05:46 2025 +0200
avcodec/aac_ac3_parser: remove unused USAC/ADTS code
ff_adts_header_parse() parse the object_type from a 2 bits field.
See also 696ea1c2236842572df88d573e24a39be3f19c98.
Partially reverts 64bb91fd3b5a00a8849531c7e8dd207f2a626096.
Signed-off-by: Nicolas Gaullier <nicolas.gaullier(a)cji.paris>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/libavcodec/aac_ac3_parser.c b/libavcodec/aac_ac3_parser.c
index e10ce13a3b..ced640dd28 100644
--- a/libavcodec/aac_ac3_parser.c
+++ b/libavcodec/aac_ac3_parser.c
@@ -155,7 +155,8 @@ get_next:
return i;
avctx->profile = hdr.object_type - 1;
- s1->key_frame = (avctx->profile == AV_PROFILE_AAC_USAC) ? get_bits1(&gb) : 1;
+ /* ADTS does not support USAC */
+ s1->key_frame = 1;
bit_rate = hdr.bit_rate;
#endif
}
commit 5e210f0552b29c7c369662e12674e724441ac069
Author: Maryla Ustarroz-Calonge <maryla(a)google.com>
AuthorDate: Mon Aug 11 13:57:03 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 16:05:45 2025 +0200
avcodec/libaom: Add test for HDR10+ metadata support
Signed-off-by: Maryla Ustarroz-Calonge <maryla(a)google.com>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/tests/Makefile b/tests/Makefile
index 3f4dbaabfd..3eef290e41 100644
--- a/tests/Makefile
+++ b/tests/Makefile
@@ -162,6 +162,7 @@ include $(SRC_PATH)/tests/fate/apng.mak
include $(SRC_PATH)/tests/fate/apv.mak
include $(SRC_PATH)/tests/fate/atrac.mak
include $(SRC_PATH)/tests/fate/audio.mak
+include $(SRC_PATH)/tests/fate/av1.mak
include $(SRC_PATH)/tests/fate/bmp.mak
include $(SRC_PATH)/tests/fate/build.mak
include $(SRC_PATH)/tests/fate/caf.mak
diff --git a/tests/fate/av1.mak b/tests/fate/av1.mak
new file mode 100644
index 0000000000..81072be5b8
--- /dev/null
+++ b/tests/fate/av1.mak
@@ -0,0 +1,7 @@
+# Tests that reading and writing with codec libaom-av1 preserves HDR10+ metadata.
+FATE_AV1_FFMPEG_FFPROBE-$(call ENCDEC, LIBAOM_AV1 VP9, IVF MATROSKA) += fate-libaom-hdr10-plus
+fate-libaom-hdr10-plus: CMD = enc_external $(TARGET_SAMPLES)/mkv/hdr10_plus_vp9_sample.webm ivf "-map 0 -c:v libaom-av1 -cpu-used 8" "-show_frames -show_entries frame=side_data_list -codec:v libaom-av1"
+
+FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_AV1_FFMPEG_FFPROBE-yes)
+
+fate-av1: $(FATE_AV1_FFMPEG_FFPROBE-yes)
diff --git a/tests/ref/fate/libaom-hdr10-plus b/tests/ref/fate/libaom-hdr10-plus
new file mode 100644
index 0000000000..ae9618937b
--- /dev/null
+++ b/tests/ref/fate/libaom-hdr10-plus
@@ -0,0 +1,44 @@
+[FRAME]
+[SIDE_DATA]
+side_data_type=HDR Dynamic Metadata SMPTE2094-40 (HDR10+)
+application version=1
+num_windows=1
+targeted_system_display_maximum_luminance=400/1
+maxscl=3340/100000
+maxscl=2870/100000
+maxscl=2720/100000
+average_maxrgb=510/100000
+num_distribution_maxrgb_percentiles=9
+distribution_maxrgb_percentage=1
+distribution_maxrgb_percentile=30/100000
+distribution_maxrgb_percentage=5
+distribution_maxrgb_percentile=2940/100000
+distribution_maxrgb_percentage=10
+distribution_maxrgb_percentile=255/100000
+distribution_maxrgb_percentage=25
+distribution_maxrgb_percentile=70/100000
+distribution_maxrgb_percentage=50
+distribution_maxrgb_percentile=1340/100000
+distribution_maxrgb_percentage=75
+distribution_maxrgb_percentile=1600/100000
+distribution_maxrgb_percentage=90
+distribution_maxrgb_percentile=1850/100000
+distribution_maxrgb_percentage=95
+distribution_maxrgb_percentile=1950/100000
+distribution_maxrgb_percentage=99
+distribution_maxrgb_percentile=2940/100000
+fraction_bright_pixels=1/1000
+knee_point_x=0/4095
+knee_point_y=0/4095
+num_bezier_curve_anchors=9
+bezier_curve_anchors=102/1023
+bezier_curve_anchors=205/1023
+bezier_curve_anchors=307/1023
+bezier_curve_anchors=410/1023
+bezier_curve_anchors=512/1023
+bezier_curve_anchors=614/1023
+bezier_curve_anchors=717/1023
+bezier_curve_anchors=819/1023
+bezier_curve_anchors=922/1023
+[/SIDE_DATA]
+[/FRAME]
commit a282500087591ef5a22942d204f5743afa2265d4
Author: Maryla Ustarroz-Calonge <maryla(a)google.com>
AuthorDate: Mon Aug 11 13:57:02 2025 +0200
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 15:56:56 2025 +0200
avcodec/libaom: Add HDR10+ metadata support
Signed-off-by: Maryla Ustarroz-Calonge <maryla(a)google.com>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/Changelog b/Changelog
index 96d616991d..aaab8d9b54 100644
--- a/Changelog
+++ b/Changelog
@@ -39,6 +39,8 @@ version 8.0:
- AV1 Vulkan encoder
- ProRes RAW decoder
- ProRes RAW Vulkan hwaccel
+- ffprobe -codec option
+- HDR10+ metadata passthrough when decoding/encoding with libaom-av1
version 7.1:
diff --git a/libavcodec/libaomdec.c b/libavcodec/libaomdec.c
index 69eec8b089..cf5986baf4 100644
--- a/libavcodec/libaomdec.c
+++ b/libavcodec/libaomdec.c
@@ -28,11 +28,14 @@
#include "libavutil/common.h"
#include "libavutil/cpu.h"
+#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/imgutils.h"
#include "avcodec.h"
+#include "bytestream.h"
#include "codec_internal.h"
#include "decode.h"
+#include "itut35.h"
#include "libaom.h"
#include "profiles.h"
@@ -137,6 +140,61 @@ static int set_pix_fmt(AVCodecContext *avctx, struct aom_image *img)
}
}
+static int decode_metadata_itu_t_t35(AVFrame *frame,
+ const uint8_t *buffer, size_t buffer_size)
+{
+ if (buffer_size < 6)
+ return AVERROR(EINVAL);
+
+ GetByteContext bc;
+ bytestream2_init(&bc, buffer, buffer_size);
+
+ const int country_code = bytestream2_get_byteu(&bc);
+ const int provider_code = bytestream2_get_be16u(&bc);
+ const int provider_oriented_code = bytestream2_get_be16u(&bc);
+ const int application_identifier = bytestream2_get_byteu(&bc);
+
+ // See "HDR10+ AV1 Metadata Handling Specification" v1.0.1, Section 2.1.
+ if (country_code == ITU_T_T35_COUNTRY_CODE_US
+ && provider_code == ITU_T_T35_PROVIDER_CODE_SAMSUNG
+ && provider_oriented_code == 0x0001
+ && application_identifier == 0x04) {
+ // HDR10+
+ AVDynamicHDRPlus *hdr_plus = av_dynamic_hdr_plus_create_side_data(frame);
+ if (!hdr_plus)
+ return AVERROR(ENOMEM);
+
+ int res = av_dynamic_hdr_plus_from_t35(hdr_plus, bc.buffer,
+ bytestream2_get_bytes_left(&bc));
+ if (res < 0)
+ return res;
+ }
+
+ return 0;
+}
+
+static int decode_metadata(AVFrame *frame, const struct aom_image *img)
+{
+ const size_t num_metadata = aom_img_num_metadata(img);
+ for (size_t i = 0; i < num_metadata; ++i) {
+ const aom_metadata_t *metadata = aom_img_get_metadata(img, i);
+ if (!metadata)
+ continue;
+
+ switch (metadata->type) {
+ case OBU_METADATA_TYPE_ITUT_T35: {
+ int res = decode_metadata_itu_t_t35(frame, metadata->payload, metadata->sz);
+ if (res < 0)
+ return res;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return 0;
+}
+
static int aom_decode(AVCodecContext *avctx, AVFrame *picture,
int *got_frame, AVPacket *avpkt)
{
@@ -215,6 +273,11 @@ static int aom_decode(AVCodecContext *avctx, AVFrame *picture,
av_image_copy(picture->data, picture->linesize, planes,
stride, avctx->pix_fmt, img->d_w, img->d_h);
}
+ ret = decode_metadata(picture, img);
+ if (ret < 0) {
+ av_log(avctx, AV_LOG_ERROR, "Failed to decode metadata\n");
+ return ret;
+ }
*got_frame = 1;
}
return avpkt->size;
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index 46f8d60e46..5d265a54d1 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -33,6 +33,7 @@
#include "libavutil/base64.h"
#include "libavutil/common.h"
#include "libavutil/cpu.h"
+#include "libavutil/hdr_dynamic_metadata.h"
#include "libavutil/imgutils.h"
#include "libavutil/mathematics.h"
#include "libavutil/mem.h"
@@ -42,10 +43,12 @@
#include "av1.h"
#include "avcodec.h"
#include "bsf.h"
+#include "bytestream.h"
#include "codec_internal.h"
#include "dovi_rpu.h"
#include "encode.h"
#include "internal.h"
+#include "itut35.h"
#include "libaom.h"
#include "packet_internal.h"
#include "profiles.h"
@@ -328,6 +331,53 @@ static av_cold int codecctl_int(AVCodecContext *avctx,
return 0;
}
+static int add_hdr_plus(AVCodecContext *avctx, struct aom_image *img, const AVFrame *frame)
+{
+ // Check for HDR10+
+ AVFrameSideData *side_data =
+ av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS);
+ if (!side_data)
+ return 0;
+
+ size_t payload_size;
+ AVDynamicHDRPlus *hdr_plus = (AVDynamicHDRPlus *)side_data->buf->data;
+ int res = av_dynamic_hdr_plus_to_t35(hdr_plus, NULL, &payload_size);
+ if (res < 0) {
+ log_encoder_error(avctx, "Error finding the size of HDR10+");
+ return res;
+ }
+
+ uint8_t *hdr_plus_buf;
+ // Extra bytes for the country code, provider code, provider oriented code and app id.
+ const size_t hdr_plus_buf_size = payload_size + 6;
+ hdr_plus_buf = av_malloc(hdr_plus_buf_size);
+ if (!hdr_plus_buf)
+ return AVERROR(ENOMEM);
+
+ uint8_t *payload = hdr_plus_buf;
+ // See "HDR10+ AV1 Metadata Handling Specification" v1.0.1, Section 2.1.
+ bytestream_put_byte(&payload, ITU_T_T35_COUNTRY_CODE_US);
+ bytestream_put_be16(&payload, ITU_T_T35_PROVIDER_CODE_SAMSUNG);
+ bytestream_put_be16(&payload, 0x0001); // provider_oriented_code
+ bytestream_put_byte(&payload, 0x04); // application_identifier
+
+ res = av_dynamic_hdr_plus_to_t35(hdr_plus, &payload, &payload_size);
+ if (res < 0) {
+ av_free(hdr_plus_buf);
+ log_encoder_error(avctx, "Error encoding HDR10+ from side data");
+ return res;
+ }
+
+ res = aom_img_add_metadata(img, OBU_METADATA_TYPE_ITUT_T35,
+ hdr_plus_buf, hdr_plus_buf_size, AOM_MIF_ANY_FRAME);
+ av_free(hdr_plus_buf);
+ if (res < 0) {
+ log_encoder_error(avctx, "Error adding HDR10+ to aom_img");
+ return res;
+ }
+ return 0;
+}
+
#if defined(AOM_CTRL_AV1E_GET_NUM_OPERATING_POINTS) && \
defined(AOM_CTRL_AV1E_GET_SEQ_LEVEL_IDX) && \
defined(AOM_CTRL_AV1E_GET_TARGET_SEQ_LEVEL_IDX)
@@ -1234,6 +1284,7 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
if (frame) {
rawimg = &ctx->rawimg;
+ aom_img_remove_metadata(rawimg);
rawimg->planes[AOM_PLANE_Y] = frame->data[0];
rawimg->planes[AOM_PLANE_U] = frame->data[1];
rawimg->planes[AOM_PLANE_V] = frame->data[2];
@@ -1284,6 +1335,10 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
if (frame->pict_type == AV_PICTURE_TYPE_I)
flags |= AOM_EFLAG_FORCE_KF;
+
+ res = add_hdr_plus(avctx, rawimg, frame);
+ if (res < 0)
+ return res;
}
res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags);
commit d7173e982ec815dcf70999c8683c465b99ce249c
Author: Patrick Wang <mail6543210(a)gmail.com>
AuthorDate: Fri Aug 29 02:58:16 2025 +0800
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 15:56:27 2025 +0200
fftools/ffmpeg: fix gracefully shutdown
d119ae2fd82a494d9430ff4d4fc262961a68c598 removed the loop-breaking condition
received_sigterm.
Thus, signals no longer gracefully shutdown ffmpeg.
Fixes: #10834
Signed-off-by: Patrick Wang <mail6543210(a)gmail.com>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/fftools/ffmpeg.c b/fftools/ffmpeg.c
index de607cac93..cbeefb71d6 100644
--- a/fftools/ffmpeg.c
+++ b/fftools/ffmpeg.c
@@ -806,8 +806,6 @@ static int check_keyboard_interaction(int64_t cur_time)
{
int i, key;
static int64_t last_time;
- if (received_nb_signals)
- return AVERROR_EXIT;
/* read_key() returns 0 on EOF */
if (cur_time - last_time >= 100000) {
key = read_key();
@@ -891,6 +889,9 @@ static int transcode(Scheduler *sch)
while (!sch_wait(sch, stats_period, &transcode_ts)) {
int64_t cur_time= av_gettime_relative();
+ if (received_nb_signals)
+ break;
+
/* if 'q' pressed, exits */
if (stdin_interaction)
if (check_keyboard_interaction(cur_time) < 0)
commit 173988aa0c2b8710e47a0b4d3651b1fe6d2166ce
Author: Zsolt Vadasz <zsolt_vadasz(a)protonmail.com>
AuthorDate: Fri Aug 29 20:19:53 2025 +0000
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 15:56:23 2025 +0200
libavfilter/vf_minterpolate: Use local variable in array
Signed-off-by: Zsolt Vadasz <zsolt_vadasz(a)protonmail.com>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/libavfilter/vf_minterpolate.c b/libavfilter/vf_minterpolate.c
index 2406259056..ba5c512e03 100644
--- a/libavfilter/vf_minterpolate.c
+++ b/libavfilter/vf_minterpolate.c
@@ -918,9 +918,9 @@ static void set_frame_data(MIContext *mi_ctx, int alpha, AVFrame *avf_out)
int x_mv, y_mv;
int weight_sum = 0;
int i, val = 0;
- PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * avf_out->width];
- PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * avf_out->width];
- PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * avf_out->width];
+ PixelMVS *pixel_mvs = &mi_ctx->pixel_mvs[x + y * width];
+ PixelWeights *pixel_weights = &mi_ctx->pixel_weights[x + y * width];
+ PixelRefs *pixel_refs = &mi_ctx->pixel_refs[x + y * width];
for (i = 0; i < pixel_refs->nb; i++)
weight_sum += pixel_weights->weights[i];
commit 5d7e4b7496bc5f6327202d4ed53052311abded2f
Author: Zsolt Vadasz <zsolt_vadasz(a)protonmail.com>
AuthorDate: Fri Aug 29 20:19:47 2025 +0000
Commit: Michael Niedermayer <michael(a)niedermayer.cc>
CommitDate: Tue Sep 2 15:56:02 2025 +0200
libavfilter/vf_minterpolate: Hoist hot loop in `set_frame_data`
Signed-off-by: Zsolt Vadasz <zsolt_vadasz(a)protonmail.com>
Signed-off-by: Michael Niedermayer <michael(a)niedermayer.cc>
diff --git a/libavfilter/vf_minterpolate.c b/libavfilter/vf_minterpolate.c
index d034783bc5..2406259056 100644
--- a/libavfilter/vf_minterpolate.c
+++ b/libavfilter/vf_minterpolate.c
@@ -939,17 +939,20 @@ static void set_frame_data(MIContext *mi_ctx, int alpha, AVFrame *avf_out)
weight_sum = ALPHA_MAX;
}
- for (i = 0; i < pixel_refs->nb; i++) {
- Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
- if (chroma) {
+ if (chroma) {
+ for (i = 0; i < pixel_refs->nb; i++) {
+ Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
x_mv = (x >> mi_ctx->log2_chroma_w) + pixel_mvs->mvs[i][0] / (1 << mi_ctx->log2_chroma_w);
y_mv = (y >> mi_ctx->log2_chroma_h) + pixel_mvs->mvs[i][1] / (1 << mi_ctx->log2_chroma_h);
- } else {
+ val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
+ }
+ } else {
+ for (i = 0; i < pixel_refs->nb; i++) {
+ Frame *frame = &mi_ctx->frames[pixel_refs->refs[i]];
x_mv = x + pixel_mvs->mvs[i][0];
y_mv = y + pixel_mvs->mvs[i][1];
+ val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
}
-
- val += pixel_weights->weights[i] * frame->avf->data[plane][x_mv + y_mv * frame->avf->linesize[plane]];
}
val = ROUNDED_DIV(val, weight_sum);
-----------------------------------------------------------------------
Summary of changes:
Changelog | 2 +
fftools/ffmpeg.c | 5 +-
libavcodec/aac_ac3_parser.c | 10 ++--
libavcodec/libaomdec.c | 63 ++++++++++++++++++++++
libavcodec/libaomenc.c | 55 +++++++++++++++++++
libavfilter/vf_minterpolate.c | 21 ++++----
tests/Makefile | 1 +
tests/fate/av1.mak | 7 +++
...{hevc-hdr10-plus-metadata => libaom-hdr10-plus} | 18 -------
9 files changed, 148 insertions(+), 34 deletions(-)
create mode 100644 tests/fate/av1.mak
copy tests/ref/fate/{hevc-hdr10-plus-metadata => libaom-hdr10-plus} (77%)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. 5d3538b8dc .forgejo/CODEOWNERS: add myself for various files
by ffmpeg-git@ffmpeg.org 02 Sep '25
by ffmpeg-git@ffmpeg.org 02 Sep '25
02 Sep '25
The branch, master has been updated
via 5d3538b8dc5d969dcdbc419d5b6903f776845efb (commit)
from 5a893c180630fe56e027f0f41f2ef04d8309d11f (commit)
- Log -----------------------------------------------------------------
commit 5d3538b8dc5d969dcdbc419d5b6903f776845efb
Author: Niklas Haas <git(a)haasn.dev>
AuthorDate: Tue Sep 2 14:01:44 2025 +0200
Commit: Niklas Haas <ffmpeg(a)haasn.dev>
CommitDate: Tue Sep 2 13:17:02 2025 +0000
.forgejo/CODEOWNERS: add myself for various files
diff --git a/.forgejo/CODEOWNERS b/.forgejo/CODEOWNERS
index 3b48612be7..1286e8b643 100644
--- a/.forgejo/CODEOWNERS
+++ b/.forgejo/CODEOWNERS
@@ -15,12 +15,14 @@ libavcodec/.*ac3.* @lynne
libavcodec/.*adpcm.* @zane @pross
libavcodec/anm.* @pross
libavcodec/ansi.* @pross
+libavcodec/aom_film_grain.* @haasn
libavcodec/.*atrac9.* @lynne
libavcodec/bink.* @pross
libavcodec/bintext.* @pross
libavcodec/.*bitpacked.* @lynne
libavcodec/.*d3d12va.* @jianhuaw
libavcodec/.*dirac.* @lynne
+libavcodec/.*dovi_rpu.* @haasn
libavcodec/dpx.* @pross
libavcodec/dsd.* @pross
libavcodec/eacmv.* @pross
@@ -34,10 +36,12 @@ libavcodec/gem.* @pross
libavcodec/golomb.* @michaelni
libavcodec/.*h266.* @frankplow @NuoMi @jianhuaw
libavcodec/h26x/.* @frankplow @NuoMi @jianhuaw
+libavcodec/.*h274.* @haasn
libavcodec/iff.* @pross
libavcodec/.*jpegxl.* @lynne @Traneptora
libavcodec/jv.* @pross
libavcodec/.*jxl.* @lynne @Traneptora
+libavcodec/.*lcms2.* @haasn
libavcodec/lead.* @pross
libavcodec/mediacodec* @quink
libavcodec/mmvideo.* @pross
@@ -86,15 +90,26 @@ libavcodec/x86/vpx.* @rbultje
# avfilter
# =======
libavfilter/af_whisper.* @vpalmisano
+libavfilter/avfiltergraph.* @haasn
libavfilter/colorspace.* @rbultje
+libavfilter/formats.* @haasn
+libavfilter/.*f_ebur128.* @haasn
+libavfilter/vf_blackdetect.* @haasn
+libavfilter/vf_colordetect.* @haasn
libavfilter/vf_colorspace.* @rbultje
+libavfilter/vf_icc.* @haasn
+libavfilter/vf_libplacebo.* @haasn
+libavfilter/vf_premultiply.* @haasn
+libavfilter/vf_scale.* @haasn
libavfilter/vf_scale_vt.* @quink
+libavfilter/vf_thumbnail.* @haasn
libavfilter/vf_transpose_vt.* @quink
libavfilter/vf_yadif.* @michaelni
libavfilter/vsrc_mandelbrot.* @michaelni
libavfilter/aarch64/.* @mstorsjo
libavfilter/x86/colorspace.* @rbultje
+libavfilter/x86/scene_sad.* @haasn
# avformat
# =======
@@ -138,8 +153,10 @@ libavformat/wtv.* @pross
# ======
libavutil/.*crc.* @lynne @michaelni
libavutil/.*d3d12va.* @jianhuaw
-libavutil/csp.* @rbultje
+libavutil/csp.* @rbultje @haasn
libavutil/eval.* @michaelni
+libavutil/film_grain.* @haasn
+libavutil/dovi_meta.* @haasn
libavutil/hwcontext_oh.* @quink
libavutil/hwcontext_mediacodec.* @quink
libavutil/iamf.* @jamrial
@@ -173,6 +190,11 @@ libswresample/.* @michaelni
libswscale/aarch64/.* @mstorsjo
libswscale/arm/.* @mstorsjo
libswscale/ppc/.* @sean_mcg
+libswscale/.* @haasn
+
+# tools
+# =====
+fftools/ffplay_renderer.* @haasn
# doc
# ===
@@ -181,7 +203,7 @@ doc/.* @GyanD
# Frameworks
# ==========
.*d3d12va.* @jianhuaw
-.*vulkan.* @lynne
+.*vulkan.* @lynne @haasn
# tests
# =====
-----------------------------------------------------------------------
Summary of changes:
.forgejo/CODEOWNERS | 26 ++++++++++++++++++++++++--
1 file changed, 24 insertions(+), 2 deletions(-)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. 5a893c1806 checkasm: sw_ops: Avoid division by zero
by ffmpeg-git@ffmpeg.org 02 Sep '25
by ffmpeg-git@ffmpeg.org 02 Sep '25
02 Sep '25
The branch, master has been updated
via 5a893c180630fe56e027f0f41f2ef04d8309d11f (commit)
from a0e00bed88cc06b109e446a8f79833b595dba03a (commit)
- Log -----------------------------------------------------------------
commit 5a893c180630fe56e027f0f41f2ef04d8309d11f
Author: Martin Storsjö <martin(a)martin.st>
AuthorDate: Tue Sep 2 14:10:28 2025 +0300
Commit: Martin Storsjö <martin(a)martin.st>
CommitDate: Tue Sep 2 14:28:56 2025 +0300
checkasm: sw_ops: Avoid division by zero
If we're invoked with range == UINT_MAX, we end up doing
"rnd() % (UINT_MAX + 1)", which is equal to "rnd() % 0". On
arm (on all platforms) and on MSVC i386, this ends up crashing
at runtime.
This fixes the crash.
diff --git a/tests/checkasm/sw_ops.c b/tests/checkasm/sw_ops.c
index 35ade0c751..57fd501fa1 100644
--- a/tests/checkasm/sw_ops.c
+++ b/tests/checkasm/sw_ops.c
@@ -80,7 +80,7 @@ static void fill32f(float *line, int num, unsigned range)
static void fill32(uint32_t *line, int num, unsigned range)
{
for (int i = 0; i < num; i++)
- line[i] = range ? rnd() % (range + 1) : rnd();
+ line[i] = (range && range < UINT_MAX) ? rnd() % (range + 1) : rnd();
}
static void fill16(uint16_t *line, int num, unsigned range)
-----------------------------------------------------------------------
Summary of changes:
tests/checkasm/sw_ops.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
1
0
[ffmpeg] branch master updated. a0e00bed88 swscale/ops: fix build with msvc
by ffmpeg-git@ffmpeg.org 02 Sep '25
by ffmpeg-git@ffmpeg.org 02 Sep '25
02 Sep '25
The branch, master has been updated
via a0e00bed88cc06b109e446a8f79833b595dba03a (commit)
from ef856ef93ef6c449f546c10f86c820d4dafe2fdc (commit)
- Log -----------------------------------------------------------------
commit a0e00bed88cc06b109e446a8f79833b595dba03a
Author: Zhao Zhili <quinkblack(a)foxmail.com>
AuthorDate: Tue Sep 2 12:07:32 2025 +0800
Commit: Zhao Zhili <quink(a)noreply.code.ffmpeg.org>
CommitDate: Tue Sep 2 10:28:56 2025 +0000
swscale/ops: fix build with msvc
x86/ops.c(500): error C2099: initializer is not a constant
diff --git a/libswscale/x86/ops.c b/libswscale/x86/ops.c
index 836c5f0d13..b3fe5fb014 100644
--- a/libswscale/x86/ops.c
+++ b/libswscale/x86/ops.c
@@ -130,7 +130,7 @@ static int setup_clear(const SwsOp *op, SwsOpPriv *out)
#define DECL_SWIZZLE(EXT, X, Y, Z, W) \
DECL_ASM(U8, swizzle_##X##Y##Z##W##EXT, \
.op = SWS_OP_SWIZZLE, \
- .swizzle = SWS_SWIZZLE( X, Y, Z, W ), \
+ .swizzle.in = {X, Y, Z, W}, \
);
#define DECL_CONVERT(EXT, FROM, TO) \
-----------------------------------------------------------------------
Summary of changes:
libswscale/x86/ops.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
hooks/post-receive
--
1
0