From 1707e6d5bb4de2b6160faa91870480d9118c06e7 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 19:41:18 +0100
Subject: [PATCH 01/37] 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.
---
 doc/APIchanges      |  4 ++++
 libavutil/frame.c   |  2 ++
 libavutil/frame.h   |  7 +++++++
 libavutil/pixdesc.c | 25 +++++++++++++++++++++++++
 libavutil/pixdesc.h | 10 ++++++++++
 libavutil/pixfmt.h  | 10 ++++++++++
 libavutil/version.h |  2 +-
 7 files changed, 59 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 1ed8337d04..a701e30dab 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-08-xx - xxxxxxxxxx - lavu 60.10.100 - frame.h pixfmt.h
+  Add AVAlphaMode, AVFrame.alpha_mode, av_alpha_mode_name() and
+  av_alpha_mode_from_name().
+
 2025-07-29 - 1c85a3832af - lavc 62.10.100 - smpte_436m.h
   Add a new public header smpte_436m.h with API for
   manipulating AV_CODEC_ID_SMPTE_436M_ANC data.
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 d440cfba2e..cb7e7ebaf9 100644
--- a/libavutil/frame.h
+++ b/libavutil/frame.h
@@ -767,6 +767,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 5cde712c9f..27b9fe73d8 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
  */
 
 #define LIBAVUTIL_VERSION_MAJOR  60
-#define LIBAVUTIL_VERSION_MINOR   9
+#define LIBAVUTIL_VERSION_MINOR  10
 #define LIBAVUTIL_VERSION_MICRO 100
 
 #define LIBAVUTIL_VERSION_INT   AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
-- 
2.49.1


From 695ee251e75eb21e087a2b0044daec580c1ebb0d Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 11:26:13 +0200
Subject: [PATCH 02/37] avfilter/formats: fix param name on
 ff_set_common_color_spaces*

Purely cosmetic.
---
 libavfilter/formats.c | 8 ++++----
 libavfilter/formats.h | 2 +-
 2 files changed, 5 insertions(+), 5 deletions(-)

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,
-- 
2.49.1


From f70f71ebadc1c1307df77b20901307dd25512682 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Sun, 17 Aug 2025 19:30:56 +0200
Subject: [PATCH 03/37] 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.

Notably, it's now also possible to add format mergers for which no conversion
filter exists, in case we want to extand the property list to cover properties
with nontrivial conversions or whose conversion filters do not (yet) exist.

In such a case, the filter code will simply return a "failed to find common
format" error, the same as if we had disabled auto-conversion filters.
---
 libavfilter/avfiltergraph.c | 31 ++++++++++++++++++-------------
 libavfilter/formats.c       | 18 ++++++++++++++----
 libavfilter/formats.h       |  4 ++--
 3 files changed, 34 insertions(+), 19 deletions(-)

diff --git a/libavfilter/avfiltergraph.c b/libavfilter/avfiltergraph.c
index bf80391869..01486a777e 100644
--- a/libavfilter/avfiltergraph.c
+++ b/libavfilter/avfiltergraph.c
@@ -536,8 +536,9 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
         for (j = 0; j < filter->nb_inputs; j++) {
             AVFilterLink *link = filter->inputs[j];
             const AVFilterNegotiation *neg;
+            const char *conv = NULL;
+            const char *opts = NULL;
             unsigned neg_step;
-            int convert_needed = 0;
 
             if (!link)
                 continue;
@@ -549,7 +550,9 @@ 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;
+                    conv = m->conversion_filter;
+                    if (m->conversion_opts_offset)
+                        opts = FF_FIELD_AT(char *, m->conversion_opts_offset, *graph);
                     break;
                 }
             }
@@ -557,26 +560,28 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
                 const AVFilterFormatsMerger *m = &neg->mergers[neg_step];
                 void *a = FF_FIELD_AT(void *, m->offset, link->incfg);
                 void *b = FF_FIELD_AT(void *, m->offset, link->outcfg);
-                if (!(a && b)) {
+                if (!(a && b) || (conv && conv != m->conversion_filter)) {
                     count_delayed++;
                 } else if (a == b) {
                     count_already_merged++;
-                } else if (!convert_needed) {
+                } else if (!conv) {
                     count_merged++;
                     ret = m->merge(a, b);
                     if (ret < 0)
                         return ret;
-                    if (!ret)
-                        convert_needed = 1;
+                    if (!ret) {
+                        conv = m->conversion_filter;
+                        if (m->conversion_opts_offset)
+                            opts = FF_FIELD_AT(char *, m->conversion_opts_offset, *graph);
+                    }
                 }
             }
 
-            if (convert_needed) {
+            if (conv) {
                 AVFilterContext *convert;
                 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,
@@ -588,16 +593,15 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
                 }
 
                 /* 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))) {
                     av_log(log_ctx, AV_LOG_ERROR,
                            "'%s' filter not present, cannot convert formats.\n",
-                           neg->conversion_filter);
+                           conv);
                     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);
+                         conv, converter_count++);
                 ret = avfilter_graph_create_filter(&convert, filter, inst_name, opts, NULL, graph);
                 if (ret < 0)
                     return ret;
@@ -637,7 +641,8 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
                      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 ((ret = MERGE(m,  inlink)) <= 0 ||
+                    if (conv == m->conversion_filter &&
+                        (ret = MERGE(m,  inlink)) <= 0 ||
                         (ret = MERGE(m, outlink)) <= 0) {
                         if (ret < 0)
                             return ret;
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);
-- 
2.49.1


From 76e50bb65ef5456a0e2fd5d0069c85f9ebe6da70 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 11:27:32 +0200
Subject: [PATCH 04/37] avfilter: add link negotiation for AVAlphaMode

---
 doc/APIchanges              |  3 ++
 libavfilter/avfilter.c      |  5 +++
 libavfilter/avfilter.h      |  7 ++++
 libavfilter/avfiltergraph.c | 32 +++++++++++++++---
 libavfilter/formats.c       | 66 +++++++++++++++++++++++++++++++++++++
 libavfilter/formats.h       | 47 ++++++++++++++++++++++++++
 libavfilter/version.h       |  2 +-
 libavfilter/video.c         |  1 +
 8 files changed, 158 insertions(+), 5 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index a701e30dab..76259c2fed 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-08-xx - xxxxxxxxxx - lavfi 11.6.100 - avfilter.h
+  Add AVFilterLink.alpha_mode.
+
 2025-08-xx - xxxxxxxxxx - lavu 60.10.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 01486a777e..8ba52c5726 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 &&
@@ -626,6 +629,10 @@ static int query_formats(AVFilterGraph *graph, void *log_ctx)
                     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);
@@ -794,8 +801,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)
@@ -830,6 +837,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;
 
@@ -868,6 +888,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;
 }
@@ -921,6 +943,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;
 }
-- 
2.49.1


From 4ebdf3ea610fd3e458433c97bfdea380bbeada8f Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 20:38:15 +0100
Subject: [PATCH 05/37] 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.
---
 libavfilter/vf_premultiply.c | 22 ++++++++++++++++++++--
 1 file changed, 20 insertions(+), 2 deletions(-)

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;
-- 
2.49.1


From 07f2d5a403697945e9021cbb21e4e3966233d559 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Sun, 17 Aug 2025 19:26:04 +0200
Subject: [PATCH 06/37] 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.
---
 doc/filters.texi             | 14 ++++++++
 libavfilter/allfilters.c     |  1 +
 libavfilter/vf_premultiply.c | 62 ++++++++++++++++++++++++++++++------
 3 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 908c98a3cf..deeb8b95f6 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -19626,6 +19626,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 */
-- 
2.49.1


From 0a931cea8ce8d5dac13be3be5ee63f75f26b8083 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Sun, 17 Aug 2025 19:43:35 +0200
Subject: [PATCH 07/37] avfilter/formats: use vf_premultiply_dynamic for alpha
 mode autoconversion

---
 libavfilter/formats.c | 1 +
 1 file changed, 1 insertion(+)

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",
     },
 };
 
-- 
2.49.1


From 7f87d5c71c776ae768296e9792e12e1321b5d740 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 20:24:56 +0100
Subject: [PATCH 08/37] 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.
---
 doc/APIchanges              | 4 ++++
 doc/codecs.texi             | 8 ++++++++
 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/options_table.h  | 5 +++++
 libavcodec/version.h        | 2 +-
 10 files changed, 47 insertions(+), 1 deletion(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 76259c2fed..64b6630fd2 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-08-xx - xxxxxxxxxx - lavc 62.13.100 - avcodec.h codec_par.h
+  Add AVCodecContext.alpha_mode, AVCodecParameters.alpha_mode, and
+  AV_CODEC_CONFIG_ALPHA_MODE.
+
 2025-08-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 834b7ad242..aa92d50ad8 100644
--- a/libavcodec/avcodec.c
+++ b/libavcodec/avcodec.c
@@ -758,6 +758,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:
@@ -785,6 +787,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 2319e76e4b..76ee1ae31f 100644
--- a/libavcodec/decode.c
+++ b/libavcodec/decode.c
@@ -567,6 +567,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 25da169343..13eacb50b8 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 da2264a097..755c90bbc1 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 
 #include "version_major.h"
 
-#define LIBAVCODEC_VERSION_MINOR  12
+#define LIBAVCODEC_VERSION_MINOR  13
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
-- 
2.49.1


From 4a8ca91f8ff4cef74a53f1eda8ce8dac5b088e1a Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 21:21:52 +0100
Subject: [PATCH 09/37] avcodec/encode: enforce alpha mode compatibility at
 encode time

Error out if trying to encode frames with an incompatible alpha mode.
---
 libavcodec/encode.c | 27 +++++++++++++++++++++++++++
 1 file changed, 27 insertions(+)

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",
-- 
2.49.1


From ff9cfe69e5bd1bca16dbe73430aa133bbdb4df9a Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 20:35:20 +0100
Subject: [PATCH 10/37] 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.
---
 libavcodec/pngdec.c | 5 +++++
 libavcodec/pngenc.c | 6 ++++++
 2 files changed, 11 insertions(+)

diff --git a/libavcodec/pngdec.c b/libavcodec/pngdec.c
index b9c997ab0e..d2a61d3bce 100644
--- a/libavcodec/pngdec.c
+++ b/libavcodec/pngdec.c
@@ -875,6 +875,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 9bbb8267cf..ddafd4ed08 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -1239,6 +1239,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,
 };
@@ -1259,6 +1262,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,
 };
-- 
2.49.1


From 7025daf6f54e4fdde4aff587c5821321c4624386 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 23 Jul 2025 12:41:23 +0200
Subject: [PATCH 11/37] avcodec/exr: set correct alpha mode
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

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.
---
 libavcodec/exr.c    | 3 +++
 libavcodec/exrenc.c | 3 +++
 2 files changed, 6 insertions(+)

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
+    },
 };
-- 
2.49.1


From 941869ada718674675ee1f390d7f52cb086c15b7 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 23 Jul 2025 12:51:26 +0200
Subject: [PATCH 12/37] 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.
---
 libavcodec/libjxldec.c |  6 ++++++
 libavcodec/libjxlenc.c | 15 +++++++++++++++
 2 files changed, 21 insertions(+)

diff --git a/libavcodec/libjxldec.c b/libavcodec/libjxldec.c
index 96c338d1b4..0c4091850c 100644
--- a/libavcodec/libjxldec.c
+++ b/libavcodec/libjxldec.c
@@ -433,6 +433,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 40d5f760b1..d7ed1a6ff4 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -351,6 +351,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;
@@ -713,6 +722,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",
 };
@@ -733,6 +745,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",
 };
-- 
2.49.1


From b6824c4437c16b47dc26d1699168afd72ab48d0e Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 23 Jul 2025 15:29:41 +0200
Subject: [PATCH 13/37] 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.
---
 libavcodec/libjxlenc.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
index d7ed1a6ff4..805a39c723 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -394,6 +394,19 @@ static int libjxl_preprocess_stream(AVCodecContext *avctx, const AVFrame *frame,
         return AVERROR_EXTERNAL;
     }
 
+    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");
-- 
2.49.1


From 44ad4df19420822ca27ed94ffcfbc72ddc8a37f0 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 23 Jul 2025 13:10:57 +0200
Subject: [PATCH 14/37] avcodec/jpegxl: parse and signal correct alpha mode

This header bit ("alpha_associated") was incorrectly ignored.
---
 libavcodec/jpegxl_parse.c  | 7 +++++--
 libavcodec/jpegxl_parse.h  | 1 +
 libavcodec/jpegxl_parser.c | 5 +++++
 3 files changed, 11 insertions(+), 2 deletions(-)

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)
-- 
2.49.1


From e8bb0fdbf3f464f0ff68ca464970f1fb47f069a2 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 13:53:26 +0200
Subject: [PATCH 15/37] avfilter/buffersink: add support for alpha modes

---
 doc/APIchanges           |  3 +++
 libavfilter/buffersink.c | 27 ++++++++++++++++++++++++++-
 libavfilter/buffersink.h |  2 ++
 libavfilter/version.h    |  2 +-
 4 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 64b6630fd2..24bc030438 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-08-xx - xxxxxxxxxx - lavfi 11.7.100 - buffersink.h
+  Add av_buffersink_get_alpha_mode().
+
 2025-08-xx - xxxxxxxxxx - lavc 62.13.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
 
 
-- 
2.49.1


From 2f76f13a1000e6f24a927398d096f4cfaf1bf127 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 14:10:24 +0200
Subject: [PATCH 16/37] avfilter/buffersrc: add alpha_mode parameter

---
 doc/APIchanges          |  3 +++
 doc/filters.texi        |  5 +++++
 libavfilter/buffersrc.c | 43 ++++++++++++++++++++++++++++++++---------
 libavfilter/buffersrc.h |  5 +++++
 libavfilter/version.h   |  2 +-
 5 files changed, 48 insertions(+), 10 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index 24bc030438..2bbfee2dbc 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-08-xx - xxxxxxxxxx - lavfi 11.7.100 - buffersrc.h
+  Add AVBufferSrcParameters.alpha_mode.
+
 2025-08-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 deeb8b95f6..c90e14bce1 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -29272,6 +29272,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
 
 
-- 
2.49.1


From 9aaa2115c5b16677b8bbe305ad978fcc13ff7447 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 14:00:40 +0200
Subject: [PATCH 17/37] avfilter/vf_format: add alpha_modes parameter

---
 doc/filters.texi        |  4 ++++
 libavfilter/vf_format.c | 22 +++++++++++++++++++---
 2 files changed, 23 insertions(+), 3 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index c90e14bce1..4ce8263405 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 }
 };
 
-- 
2.49.1


From 6df867f65dc87ee971c1b9e120aeb7b3888ea3f2 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 19:56:46 +0100
Subject: [PATCH 18/37] avfilter/vf_showinfo: print alpha mode when relevant

---
 libavfilter/vf_showinfo.c | 8 ++++++++
 1 file changed, 8 insertions(+)

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);
 }
 
-- 
2.49.1


From f9cb88ddb394f97a08d5d8ce1c33d92541e11db4 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 14:13:21 +0200
Subject: [PATCH 19/37] fftools/ffmpeg: add alpha_mode support

The implementation exactly mirrors the existing plumbing for color_ranges
and color_spaces.
---
 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 ++++++
 5 files changed, 35 insertions(+), 3 deletions(-)

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(&param_out->side_data, &param_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 4a973e5286..5f279f5d02 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,
-- 
2.49.1


From 94fee6a707b022487b098acad6715359cfb7a818 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 14:24:56 +0200
Subject: [PATCH 20/37] fftools/ffplay: add alpha_mode support

SDL seems to hard-code straight alpha compositing.
---
 fftools/ffplay.c | 10 ++++++++++
 1 file changed, 10 insertions(+)

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;
-- 
2.49.1


From a9fc422e97fd0899ee0d8ee5822ab7ddfd10b0ac Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 19:55:56 +0100
Subject: [PATCH 21/37] fftools/ffprobe: add AVFrame.alpha_mode support

---
 fftools/ffprobe.c                      |  11 +++
 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 +
 17 files changed, 130 insertions(+), 81 deletions(-)

diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index b8d51071e6..e68b0f2f41 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -1154,6 +1154,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;
@@ -1406,6 +1416,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 2b258b228d..3fc718a12b 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:UserComment=AppleMark
 
 [/FRAME]
diff --git a/tests/ref/fate/exif-image-jpg b/tests/ref/fate/exif-image-jpg
index 9915f80aed..a123f3dca4 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 0e604d4271..d8a95412f5 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:software=ImageMagick 6.5.8-0 2010-02-09 Q16 http://www.imagemagick.org
diff --git a/tests/ref/fate/exif-image-webp b/tests/ref/fate/exif-image-webp
index eaae281a86..e841b62673 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:non_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
-- 
2.49.1


From 225b65daa0b22192b39467f6d04f4e26e5a0db14 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 20:39:58 +0100
Subject: [PATCH 22/37] avfilter/vf_alphamerge: configure correct alpha mode

---
 libavfilter/vf_alphamerge.c | 7 +++++++
 1 file changed, 7 insertions(+)

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;
 }
 
-- 
2.49.1


From 51c7c6080e891b1ba030baa89b47ca96f95e151d Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Thu, 14 Aug 2025 16:07:00 +0200
Subject: [PATCH 23/37] avfilter/vf_extractplanes: require straight alpha input

---
 libavfilter/vf_extractplanes.c | 4 ++++
 1 file changed, 4 insertions(+)

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;
-- 
2.49.1


From ad452e94968700b2da66a30c274e5d031206e732 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Thu, 14 Aug 2025 17:15:30 +0200
Subject: [PATCH 24/37] 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).
---
 libavfilter/vf_scale.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index aec765b441..dd8144d766 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)
-- 
2.49.1


From b6e55a1b05249f6182df092e8dceacce774713e9 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 21:26:54 +0100
Subject: [PATCH 25/37] avfilter/vf_setparams: add alpha_mode parameter

---
 doc/filters.texi           | 13 +++++++++++++
 libavfilter/vf_setparams.c | 19 +++++++++++++++++++
 2 files changed, 32 insertions(+)

diff --git a/doc/filters.texi b/doc/filters.texi
index 4ce8263405..e20ade0a67 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -21756,6 +21756,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;
 }
 
-- 
2.49.1


From 9ef6e7cb822a2865a2d6faa017c67f171b99202c Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 21:36:58 +0100
Subject: [PATCH 26/37] 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.
---
 doc/filters.texi            |  4 ++++
 libavfilter/vf_libplacebo.c | 14 ++++++++++++++
 2 files changed, 18 insertions(+)

diff --git a/doc/filters.texi b/doc/filters.texi
index e20ade0a67..9684b778b5 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 af18a05258..d42edb8470 100644
--- a/libavfilter/vf_libplacebo.c
+++ b/libavfilter/vf_libplacebo.c
@@ -204,6 +204,7 @@ typedef struct LibplaceboContext {
     int color_primaries;
     int color_trc;
     int rotation;
+    int alpha_mode;
     AVDictionary *extra_opts;
 
 #if PL_API_VER >= 351
@@ -964,6 +965,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->fps.num)
         out->duration = 1;
     if (s->deinterlace)
@@ -1325,6 +1327,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));
@@ -1336,6 +1339,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:
@@ -1597,6 +1604,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 },
-- 
2.49.1


From 8f89208e36af87c52f604a2ff83545ef79534bf8 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 19 Feb 2025 20:55:37 +0100
Subject: [PATCH 27/37] avfilter/vf_overlay: configure alpha mode on the link

And use the link-tagged value instead of the hard-coded parameter.
---
 doc/filters.texi                  |   3 +-
 libavfilter/vf_overlay.c          | 222 ++++++++++++++++--------------
 libavfilter/vf_overlay.h          |   4 +-
 libavfilter/x86/vf_overlay_init.c |   8 +-
 4 files changed, 130 insertions(+), 107 deletions(-)

diff --git a/doc/filters.texi b/doc/filters.texi
index 9684b778b5..2e3f9bbb2e 100644
--- a/doc/filters.texi
+++ b/doc/filters.texi
@@ -18873,7 +18873,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;
+
+    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 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 (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;
     }
 
-    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;
-            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_assert0(0);
-            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;
-- 
2.49.1


From 7c7d884788653978ea398fa831fa39d8106d07e9 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:12:05 +0200
Subject: [PATCH 28/37] 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.
---
 libavfilter/vf_overlay.c          | 28 ++++++++++++++--------------
 libavfilter/vf_overlay.h          |  2 +-
 libavfilter/x86/vf_overlay_init.c |  8 ++++----
 3 files changed, 19 insertions(+), 19 deletions(-)

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;
-- 
2.49.1


From 83b2ec4ecd18e69d7e338cc95114b53b4457a5db Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:13:38 +0200
Subject: [PATCH 29/37] 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.
---
 libavfilter/vf_overlay.c | 270 +++++++++++++++++----------------------
 1 file changed, 114 insertions(+), 156 deletions(-)

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_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)
 
-#define DEFINE_BLEND_SLICE_PACKED_FMT(format_, blend_slice_fn_suffix_, main_has_alpha_, direct_) \
+//                            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;
-            break;
-        case OVERLAY_FORMAT_GBRP:
-            s->blend_slice = s->main_has_alpha ? blend_slice_gbrap : blend_slice_gbrp;
-            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;
-            }
-            break;
-        }
+    #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 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 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_YUV422:
-            s->blend_slice = s->main_has_alpha ? blend_slice_yuva422_pm : blend_slice_yuv422_pm;
+        case AV_PIX_FMT_YUVA420P10:
+            ASSIGN_BLEND_SLICE(blend_slice_yuv420p10);
             break;
-        case OVERLAY_FORMAT_YUV444:
-            s->blend_slice = s->main_has_alpha ? blend_slice_yuva444_pm : blend_slice_yuv444_pm;
+        case AV_PIX_FMT_YUVA422P:
+            ASSIGN_BLEND_SLICE(blend_slice_yuv422);
             break;
-        case OVERLAY_FORMAT_RGB:
-            s->blend_slice = s->main_has_alpha ? blend_slice_rgba_pm : blend_slice_rgb_pm;
+        case AV_PIX_FMT_YUVA422P10:
+            ASSIGN_BLEND_SLICE(blend_slice_yuv422p10);
             break;
-        case OVERLAY_FORMAT_GBRP:
-            s->blend_slice = s->main_has_alpha ? blend_slice_gbrap_pm : blend_slice_gbrp_pm;
+        case AV_PIX_FMT_YUVA444P:
+            ASSIGN_BLEND_SLICE(blend_slice_yuv444);
             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;
-            }
+        case AV_PIX_FMT_YUVA444P10:
+            ASSIGN_BLEND_SLICE(blend_slice_yuv444p10);
+            break;
+        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 AV_PIX_FMT_GBRAP:
+            ASSIGN_BLEND_SLICE(blend_slice_gbrp);
+            break;
+        default:
+            av_unreachable("Invalid pixel format for overlay");
             break;
         }
         break;
-- 
2.49.1


From a99e5b35a43dfd9a4d0ee62da4f30f50f1b088ff Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:16:38 +0200
Subject: [PATCH 30/37] avfilter/x86/vf_overlay: simplify function signature

No reason to pass all the variables again, if we're already passing the
context.
---
 libavfilter/vf_overlay.c          |  2 +-
 libavfilter/vf_overlay.h          |  3 +--
 libavfilter/x86/vf_overlay_init.c | 23 +++++++++++++----------
 3 files changed, 15 insertions(+), 13 deletions(-)

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;
-- 
2.49.1


From 38c955444cdd8ed876aaf7f635afc0a0a6055b54 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:29:32 +0200
Subject: [PATCH 31/37] 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.
---
 libavfilter/vf_fade.c | 19 ++++++++++++++++++-
 1 file changed, 18 insertions(+), 1 deletion(-)

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);
 }
 
-- 
2.49.1


From a2d1e65c48186312b97fc822c2e26ae947cd99f6 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:39:16 +0200
Subject: [PATCH 32/37] 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.
---
 libavfilter/drawutils.c | 6 ++++++
 libavfilter/drawutils.h | 7 +++++++
 2 files changed, 13 insertions(+)

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.
  */
-- 
2.49.1


From d6bda1278c1822334aacf45cdf1f2b48462da2ce Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:43:35 +0200
Subject: [PATCH 33/37] avfilter: use ff_draw_init_from_link() where possible

---
 libavfilter/qrencode.c       | 8 +++-----
 libavfilter/src_avsynctest.c | 2 +-
 libavfilter/vf_datascope.c   | 2 +-
 libavfilter/vf_drawtext.c    | 2 +-
 libavfilter/vf_pad.c         | 2 +-
 libavfilter/vf_rotate.c      | 2 +-
 libavfilter/vf_shear.c       | 2 +-
 libavfilter/vf_stack.c       | 2 +-
 libavfilter/vf_tile.c        | 2 +-
 libavfilter/vf_tinterlace.c  | 2 +-
 libavfilter/vf_tpad.c        | 2 +-
 libavfilter/vsrc_testsrc.c   | 9 +++------
 12 files changed, 16 insertions(+), 21 deletions(-)

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);
-- 
2.49.1


From fdd0a196ef612012c6115ecc1ac035da3af25d60 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Wed, 13 Aug 2025 15:45:51 +0200
Subject: [PATCH 34/37] avfilter/drawutils: add alpha mode support

This allows drawing colors onto images with premultiplied alpha, by first
premultiplying the specified RGBA values.
---
 libavfilter/drawutils.c    | 12 +++++++++---
 libavfilter/drawutils.h    |  3 ++-
 libavfilter/vf_subtitles.c |  2 +-
 3 files changed, 12 insertions(+), 5 deletions(-)

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;
-- 
2.49.1


From 84d8148369d36df6b06436efe83e911b47bcca42 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Thu, 14 Aug 2025 17:38:36 +0200
Subject: [PATCH 35/37] avfilter: add alpha_mode consistency assertion

---
 libavfilter/avfilter.c | 2 ++
 1 file changed, 2 insertions(+)

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;
-- 
2.49.1


From c6456b95906d75978b8b4f752b4dd96693ea6ff7 Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Thu, 14 Aug 2025 18:32:23 +0200
Subject: [PATCH 36/37] 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.
---
 libavfilter/vf_scale.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/libavfilter/vf_scale.c b/libavfilter/vf_scale.c
index dd8144d766..50d4b8eccd 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;
 }
 
-- 
2.49.1


From 72d1d7a7795f81395a1b0e6793cfa7ad3e69b11d Mon Sep 17 00:00:00 2001
From: Niklas Haas <git@haasn.dev>
Date: Mon, 18 Aug 2025 13:24:16 +0200
Subject: [PATCH 37/37] 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).
---
 libavfilter/vf_zscale.c | 97 +++++------------------------------------
 1 file changed, 10 insertions(+), 87 deletions(-)

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;
-        }
     }
 }
 
-- 
2.49.1

