Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
* [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy
@ 2023-01-25 16:55 Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 02/19] lavc/avcodec: improve AV_CODEC_FLAG_RECON_FRAME doxy Anton Khirnov
                   ` (19 more replies)
  0 siblings, 20 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

Change return value descriptions into proper lists.
---
 libavcodec/avcodec.h | 81 +++++++++++++++++++++++---------------------
 1 file changed, 42 insertions(+), 39 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 0ac581d660..f3ca41f126 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2605,17 +2605,18 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
  *                  still has frames buffered, it will return them after sending
  *                  a flush packet.
  *
- * @return 0 on success, otherwise negative error code:
- *      AVERROR(EAGAIN):   input is not accepted in the current state - user
- *                         must read output with avcodec_receive_frame() (once
- *                         all output is read, the packet should be resent, and
- *                         the call will not fail with EAGAIN).
- *      AVERROR_EOF:       the decoder has been flushed, and no new packets can
- *                         be sent to it (also returned if more than 1 flush
- *                         packet is sent)
- *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
- *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
- *      other errors: legitimate decoding errors
+ * @return
+ * - 0:                 success
+ * - AVERROR(EAGAIN):   input is not accepted in the current state - user must
+ *                      read output with avcodec_receive_frame() (once all
+ *                      output is read, the packet should be resent, and the
+ *                      call will not fail with EAGAIN).
+ * - AVERROR_EOF:       the decoder has been flushed, and no new packets can be
+ *                      sent to it (also returned if more than 1 flush packet is
+ *                      sent)
+ * - AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
+ * - AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
+ * - other errors:      legitimate decoding errors
  */
 int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
 
@@ -2630,17 +2631,17 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
  *              av_frame_unref(frame) before doing anything else.
  *
  * @return
- *      0:                 success, a frame was returned
- *      AVERROR(EAGAIN):   output is not available in this state - user must try
- *                         to send new input
- *      AVERROR_EOF:       the codec has been fully flushed, and there will be
- *                         no more output frames
- *      AVERROR(EINVAL):   codec not opened, or it is an encoder without
- *                         the AV_CODEC_FLAG_RECON_FRAME flag enabled
- *      AVERROR_INPUT_CHANGED:   current decoded frame has changed parameters
- *                               with respect to first decoded frame. Applicable
- *                               when flag AV_CODEC_FLAG_DROPCHANGED is set.
- *      other negative values: legitimate decoding errors
+ * - 0:                     success, a frame was returned
+ * - AVERROR(EAGAIN):       output is not available in this state - user must
+ *                          try to send new input
+ * - AVERROR_EOF:           the codec has been fully flushed, and there will be
+ *                          no more output frames
+ * - AVERROR(EINVAL):       codec not opened, or it is an encoder without the
+ *                          AV_CODEC_FLAG_RECON_FRAME flag enabled
+ * - AVERROR_INPUT_CHANGED: current decoded frame has changed parameters with
+ *                          respect to first decoded frame. Applicable when flag
+ *                          AV_CODEC_FLAG_DROPCHANGED is set.
+ * - other negative values: legitimate decoding errors
  */
 int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
 
@@ -2667,16 +2668,17 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
  *                  If it is not set, frame->nb_samples must be equal to
  *                  avctx->frame_size for all frames except the last.
  *                  The final frame may be smaller than avctx->frame_size.
- * @return 0 on success, otherwise negative error code:
- *      AVERROR(EAGAIN):   input is not accepted in the current state - user
- *                         must read output with avcodec_receive_packet() (once
- *                         all output is read, the packet should be resent, and
- *                         the call will not fail with EAGAIN).
- *      AVERROR_EOF:       the encoder has been flushed, and no new frames can
- *                         be sent to it
- *      AVERROR(EINVAL):   codec not opened, it is a decoder, or requires flush
- *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
- *      other errors: legitimate encoding errors
+ * @return
+ * - 0:                 success
+ * - AVERROR(EAGAIN):   input is not accepted in the current state - user must
+ *                      read output with avcodec_receive_packet() (once all
+ *                      output is read, the packet should be resent, and the
+ *                      call will not fail with EAGAIN).
+ * - AVERROR_EOF:       the encoder has been flushed, and no new frames can
+ *                      be sent to it
+ * - AVERROR(EINVAL):   codec not opened, it is a decoder, or requires flush
+ * - AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
+ * - other errors:      legitimate encoding errors
  */
 int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
 
@@ -2687,13 +2689,14 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
  * @param avpkt This will be set to a reference-counted packet allocated by the
  *              encoder. Note that the function will always call
  *              av_packet_unref(avpkt) before doing anything else.
- * @return 0 on success, otherwise negative error code:
- *      AVERROR(EAGAIN):   output is not available in the current state - user
- *                         must try to send input
- *      AVERROR_EOF:       the encoder has been fully flushed, and there will be
- *                         no more output packets
- *      AVERROR(EINVAL):   codec not opened, or it is a decoder
- *      other errors: legitimate encoding errors
+ * @return
+ * - 0:                 success
+ * - AVERROR(EAGAIN):   output is not available in the current state - user must
+ *                      try to send input
+ * - AVERROR_EOF:       the encoder has been fully flushed, and there will be no
+ *                      more output packets
+ * - AVERROR(EINVAL):   codec not opened, or it is a decoder
+ * - other errors:      legitimate encoding errors
  */
 int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 02/19] lavc/avcodec: improve AV_CODEC_FLAG_RECON_FRAME doxy
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 03/19] lavc: add a private cap for fake-delay encoders Anton Khirnov
                   ` (18 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

Do not break a sentence on a period after "i.e.".

Link to the definition of AV_CODEC_CAP_ENCODER_RECON_FRAME.
---
 libavcodec/avcodec.h | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index f3ca41f126..e11e0ae3ee 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -232,13 +232,13 @@ typedef struct RcOverride{
  */
 #define AV_CODEC_FLAG_DROPCHANGED     (1 <<  5)
 /**
- * Request the encoder to output reconstructed frames, i.e. frames that would be
- * produced by decoding the encoded bistream. These frames may be retrieved by
- * calling avcodec_receive_frame() immediately after a successful call to
+ * Request the encoder to output reconstructed frames, i.e.\ frames that would
+ * be produced by decoding the encoded bistream. These frames may be retrieved
+ * by calling avcodec_receive_frame() immediately after a successful call to
  * avcodec_receive_packet().
  *
  * Should only be used with encoders flagged with the
- * AV_CODEC_CAP_ENCODER_RECON_FRAME capability.
+ * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability.
  */
 #define AV_CODEC_FLAG_RECON_FRAME     (1 <<  6)
 /**
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 03/19] lavc: add a private cap for fake-delay encoders
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 02/19] lavc/avcodec: improve AV_CODEC_FLAG_RECON_FRAME doxy Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 04/19] lavc: add a codec flag for propagating opaque from frames to packets Anton Khirnov
                   ` (17 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

Some encoders (ffv1, flac, adx) are marked with AV_CODEC_CAP_DELAY onky
in order to be flushed at the end, otherwise they behave as no-delay
encoders.

Add a capability to mark these encoders. Use it for setting pts
generically.
---
 libavcodec/adxenc.c         | 3 +--
 libavcodec/codec_internal.h | 8 ++++++++
 libavcodec/encode.c         | 6 ++++--
 libavcodec/ffv1enc.c        | 4 +---
 libavcodec/flacenc.c        | 7 ++-----
 libavcodec/tests/avcodec.c  | 4 ++++
 6 files changed, 20 insertions(+), 12 deletions(-)

diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index 153c91b852..6e12a58b16 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -183,8 +183,6 @@ static int adx_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
         dst += BLOCK_SIZE;
     }
 
-    avpkt->pts = frame->pts;
-    avpkt->duration = frame->nb_samples;
     *got_packet_ptr = 1;
     return 0;
 }
@@ -200,4 +198,5 @@ const FFCodec ff_adpcm_adx_encoder = {
     FF_CODEC_ENCODE_CB(adx_encode_frame),
     .p.sample_fmts  = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16,
                                                       AV_SAMPLE_FMT_NONE },
+    .caps_internal  = FF_CODEC_CAP_EOF_FLUSH,
 };
diff --git a/libavcodec/codec_internal.h b/libavcodec/codec_internal.h
index e3b77e6dea..130a7dc3cd 100644
--- a/libavcodec/codec_internal.h
+++ b/libavcodec/codec_internal.h
@@ -80,6 +80,14 @@
  * Codec supports embedded ICC profiles (AV_FRAME_DATA_ICC_PROFILE).
  */
 #define FF_CODEC_CAP_ICC_PROFILES           (1 << 9)
+/**
+ * The encoder has AV_CODEC_CAP_DELAY set, but does not actually have delay - it
+ * only wants to be flushed at the end to update some context variables (e.g.
+ * 2pass stats) or produce a trailing packet. Besides that it immediately
+ * produces exactly one output packet per each input frame, just as no-delay
+ * encoders do.
+ */
+#define FF_CODEC_CAP_EOF_FLUSH              (1 << 10)
 
 /**
  * FFCodec.codec_tags termination value
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index fbe2c97cd6..e0b3e43840 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -211,7 +211,8 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
 
         // set the timestamps for the simple no-delay case
         // encoders with delay have to set the timestamps themselves
-        if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)) {
+        if (!(avctx->codec->capabilities & AV_CODEC_CAP_DELAY) ||
+            (frame && (codec->caps_internal & FF_CODEC_CAP_EOF_FLUSH))) {
             if (avpkt->pts == AV_NOPTS_VALUE)
                 avpkt->pts = frame->pts;
 
@@ -225,7 +226,8 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
         // dts equals pts unless there is reordering
         // there can be no reordering if there is no encoder delay
         if (!(avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) ||
-            !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY))
+            !(avctx->codec->capabilities & AV_CODEC_CAP_DELAY)        ||
+            (codec->caps_internal & FF_CODEC_CAP_EOF_FLUSH))
             avpkt->dts = avpkt->pts;
     } else {
 unref:
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 0237ac48eb..6649ec7e88 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1231,8 +1231,6 @@ static int encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
     f->picture_number++;
     pkt->size   = buf_p - pkt->data;
-    pkt->pts    =
-    pkt->dts    = pict->pts;
     pkt->flags |= AV_PKT_FLAG_KEY * f->key_frame;
     *got_packet = 1;
 
@@ -1301,5 +1299,5 @@ const FFCodec ff_ffv1_encoder = {
 
     },
     .p.priv_class   = &ffv1_class,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
 };
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index 8aacc93e28..9a9835dfa6 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -1690,10 +1690,7 @@ static int flac_encode_frame(AVCodecContext *avctx, AVPacket *avpkt,
     if (out_bytes < s->min_framesize)
         s->min_framesize = out_bytes;
 
-    avpkt->pts      = frame->pts;
-    avpkt->duration = ff_samples_to_time_base(avctx, frame->nb_samples);
-
-    s->next_pts = avpkt->pts + avpkt->duration;
+    s->next_pts = frame->pts + ff_samples_to_time_base(avctx, frame->nb_samples);
 
     av_shrink_packet(avpkt, out_bytes);
 
@@ -1766,5 +1763,5 @@ const FFCodec ff_flac_encoder = {
                                                      AV_SAMPLE_FMT_S32,
                                                      AV_SAMPLE_FMT_NONE },
     .p.priv_class   = &flac_encoder_class,
-    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
+    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_EOF_FLUSH,
 };
diff --git a/libavcodec/tests/avcodec.c b/libavcodec/tests/avcodec.c
index 3288a85f64..4c1730425d 100644
--- a/libavcodec/tests/avcodec.c
+++ b/libavcodec/tests/avcodec.c
@@ -158,6 +158,10 @@ int main(void){
             if (codec->capabilities & AV_CODEC_CAP_FRAME_THREADS &&
                 codec->capabilities & AV_CODEC_CAP_DELAY)
                 ERR("Frame-threaded encoder %s claims to have delay\n");
+
+            if (codec2->caps_internal & FF_CODEC_CAP_EOF_FLUSH &&
+                !(codec->capabilities & AV_CODEC_CAP_DELAY))
+                ERR("EOF_FLUSH encoder %s is not marked as having delay\n");
         } else {
             if ((codec->type == AVMEDIA_TYPE_SUBTITLE) != (codec2->cb_type == FF_CODEC_CB_TYPE_DECODE_SUB))
                 ERR("Subtitle decoder %s does not implement decode_sub callback\n");
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 04/19] lavc: add a codec flag for propagating opaque from frames to packets
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 02/19] lavc/avcodec: improve AV_CODEC_FLAG_RECON_FRAME doxy Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 03/19] lavc: add a private cap for fake-delay encoders Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 05/19] lavc: support AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE in all no-delay encoders Anton Khirnov
                   ` (16 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

This is intended to be a more convenient replacement for
reordered_opaque.

Add support for it in the two encoders that offer
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE: libx264 and libx265. Other
encoders will be supported in future commits.
---
 doc/APIchanges             |  3 +++
 libavcodec/avcodec.h       | 26 +++++++++++++++++++++++
 libavcodec/encode.c        |  7 +++++++
 libavcodec/libx264.c       | 29 ++++++++++++++++++++++++++
 libavcodec/libx265.c       | 42 ++++++++++++++++++++++++++++----------
 libavcodec/options_table.h |  1 +
 libavcodec/version.h       |  2 +-
 7 files changed, 98 insertions(+), 12 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index a11acadecd..f52337990f 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -14,6 +14,9 @@ libavutil:     2021-04-27
 
 API changes, most recent first:
 
+2023-01-xx - xxxxxxxxxx - lavc 59.57.100 - avcodec.h
+  Add AV_CODEC_FLAG_COPY_OPAQUE.
+
 2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h
   Adds a new structure for holding H.274 Ambient Viewing Environment metadata,
   AVAmbientViewingEnvironment.
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index e11e0ae3ee..54ab7b81f9 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -241,6 +241,32 @@ typedef struct RcOverride{
  * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability.
  */
 #define AV_CODEC_FLAG_RECON_FRAME     (1 <<  6)
+/**
+ * Request the encoder to propagate each frame's AVFrame.opaque and
+ * AVFrame.opaque_ref values to its corresponding output AVPacket.
+ *
+ * May only be set on encoders that have the
+ * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag.
+ *
+ * @note
+ * While in typical cases one input frame produces exactly one output packet
+ * (perhaps after a delay), in general the mapping of frames to packets is
+ * M-to-N, so
+ * - Any number of input frames may be associated with any given output packet.
+ *   This includes zero - e.g. some encoders may output packets that carry only
+ *   metadata about the whole stream.
+ * - A given input frame may be associated with any number of output packets.
+ *   Again this includes zero - e.g. some encoders may drop frames under certain
+ *   conditions.
+ * .
+ * This implies that when using this flag, the caller must NOT assume that
+ * - a given input frame's opaques will necessarily appear on some output packet;
+ * - every output packet will have some non-NULL opaque value.
+ * .
+ * When an output packet contains multiple frames, the opaque values will be
+ * taken from the first of those.
+ */
+#define AV_CODEC_FLAG_COPY_OPAQUE     (1 <<  7)
 /**
  * Use internal 2pass ratecontrol in first pass mode.
  */
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index e0b3e43840..d6c73dc044 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -636,6 +636,13 @@ int ff_encode_preinit(AVCodecContext *avctx)
         return AVERROR(EINVAL);
     }
 
+    if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE &&
+        !(avctx->codec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)) {
+        av_log(avctx, AV_LOG_ERROR, "The copy_opaque flag is set, but the "
+               "encoder does not support it.\n");
+        return AVERROR(EINVAL);
+    }
+
     switch (avctx->codec_type) {
     case AVMEDIA_TYPE_VIDEO: ret = encode_preinit_video(avctx); break;
     case AVMEDIA_TYPE_AUDIO: ret = encode_preinit_audio(avctx); break;
diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 2bbd9044b6..6d22a1726e 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -21,6 +21,7 @@
 
 #include "config_components.h"
 
+#include "libavutil/buffer.h"
 #include "libavutil/eval.h"
 #include "libavutil/internal.h"
 #include "libavutil/opt.h"
@@ -51,6 +52,9 @@
 typedef struct X264Opaque {
     int64_t reordered_opaque;
     int64_t wallclock;
+
+    void        *frame_opaque;
+    AVBufferRef *frame_opaque_ref;
 } X264Opaque;
 
 typedef struct X264Context {
@@ -133,6 +137,11 @@ static void X264_log(void *p, int level, const char *fmt, va_list args)
     av_vlog(p, level_map[level], fmt, args);
 }
 
+static void opaque_uninit(X264Opaque *o)
+{
+    av_buffer_unref(&o->frame_opaque_ref);
+    memset(o, 0, sizeof(*o));
+}
 
 static int encode_nals(AVCodecContext *ctx, AVPacket *pkt,
                        const x264_nal_t *nals, int nnal)
@@ -440,6 +449,15 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
 
     pic->i_pts  = frame->pts;
 
+    opaque_uninit(opaque);
+
+    if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+        opaque->frame_opaque = frame->opaque;
+        ret = av_buffer_replace(&opaque->frame_opaque_ref, frame->opaque_ref);
+        if (ret < 0)
+            goto fail;
+    }
+
     opaque->reordered_opaque = frame->reordered_opaque;
     opaque->wallclock = wallclock;
     if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT)
@@ -594,6 +612,14 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
         out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) {
         ctx->reordered_opaque = out_opaque->reordered_opaque;
         wallclock = out_opaque->wallclock;
+
+        if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+            pkt->opaque                  = out_opaque->frame_opaque;
+            pkt->opaque_ref              = out_opaque->frame_opaque_ref;
+            out_opaque->frame_opaque_ref = NULL;
+        }
+
+        opaque_uninit(out_opaque);
     } else {
         // Unexpected opaque pointer on picture output
         av_log(ctx, AV_LOG_ERROR, "Unexpected opaque pointer; "
@@ -634,6 +660,9 @@ static av_cold int X264_close(AVCodecContext *avctx)
     X264Context *x4 = avctx->priv_data;
 
     av_freep(&x4->sei);
+
+    for (int i = 0; i < x4->nb_reordered_opaque; i++)
+        opaque_uninit(&x4->reordered_opaque[i]);
     av_freep(&x4->reordered_opaque);
 
 #if X264_BUILD >= 161
diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index 25de3c669b..a71f1f76d3 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -28,6 +28,7 @@
 #include <float.h>
 
 #include "libavutil/avassert.h"
+#include "libavutil/buffer.h"
 #include "libavutil/internal.h"
 #include "libavutil/common.h"
 #include "libavutil/opt.h"
@@ -43,6 +44,9 @@
 typedef struct ReorderedData {
     int64_t reordered_opaque;
 
+    void        *frame_opaque;
+    AVBufferRef *frame_opaque_ref;
+
     int in_use;
 } ReorderedData;
 
@@ -121,7 +125,7 @@ static int rd_get(libx265Context *ctx)
 static void rd_release(libx265Context *ctx, int idx)
 {
     av_assert0(idx >= 0 && idx < ctx->nb_rd);
-
+    av_buffer_unref(&ctx->rd[idx].frame_opaque_ref);
     memset(&ctx->rd[idx], 0, sizeof(ctx->rd[idx]));
 }
 
@@ -132,6 +136,8 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx)
     ctx->api->param_free(ctx->params);
     av_freep(&ctx->sei_data);
 
+    for (int i = 0; i < ctx->nb_rd; i++)
+        rd_release(ctx, i);
     av_freep(&ctx->rd);
 
     if (ctx->encoder)
@@ -582,6 +588,9 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
     sei->numPayloads = 0;
 
     if (pic) {
+        ReorderedData *rd;
+        int rd_idx;
+
         for (i = 0; i < 3; i++) {
            x265pic.planes[i] = pic->data[i];
            x265pic.stride[i] = pic->linesize[i];
@@ -600,21 +609,26 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         if (ret < 0)
             return ret;
 
-        if (pic->reordered_opaque) {
-            ReorderedData *rd;
-            int rd_idx = rd_get(ctx);
+        rd_idx = rd_get(ctx);
+        if (rd_idx < 0) {
+            free_picture(ctx, &x265pic);
+            return rd_idx;
+        }
+        rd = &ctx->rd[rd_idx];
 
-            if (rd_idx < 0) {
+        rd->reordered_opaque = pic->reordered_opaque;
+        if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+            rd->frame_opaque = pic->opaque;
+            ret = av_buffer_replace(&rd->frame_opaque_ref, pic->opaque_ref);
+            if (ret < 0) {
+                rd_release(ctx, rd_idx);
                 free_picture(ctx, &x265pic);
-                return rd_idx;
+                return ret;
             }
-
-            x265pic.userData = (void*)(intptr_t)(rd_idx + 1);
-
-            rd = &ctx->rd[rd_idx];
-            rd->reordered_opaque = pic->reordered_opaque;
         }
 
+        x265pic.userData = (void*)(intptr_t)(rd_idx + 1);
+
         if (ctx->a53_cc) {
             void *sei_data;
             size_t sei_size;
@@ -742,6 +756,12 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
 
         avctx->reordered_opaque = rd->reordered_opaque;
 
+        if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+            pkt->opaque          = rd->frame_opaque;
+            pkt->opaque_ref      = rd->frame_opaque_ref;
+            rd->frame_opaque_ref = NULL;
+        }
+
         rd_release(ctx, idx);
     } else
         avctx->reordered_opaque = 0;
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 7924ca6144..4b38c42043 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -58,6 +58,7 @@ static const AVOption avcodec_options[] = {
 {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"},
 {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"},
 {"recon_frame", "export reconstructed frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_RECON_FRAME}, .unit = "flags"},
+{"copy_opaque", "propagate opaque values", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_COPY_OPAQUE}, .unit = "flags"},
 {"pass1", "use internal 2-pass ratecontrol in first  pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"},
 {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"},
 {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"},
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 6b8a1dbb79..dfd3d5d7e5 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -29,7 +29,7 @@
 
 #include "version_major.h"
 
-#define LIBAVCODEC_VERSION_MINOR  56
+#define LIBAVCODEC_VERSION_MINOR  57
 #define LIBAVCODEC_VERSION_MICRO 100
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 05/19] lavc: support AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE in all no-delay encoders
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (2 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 04/19] lavc: add a codec flag for propagating opaque from frames to packets Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 06/19] lavc/encode: pass through frame durations to encoded packets Anton Khirnov
                   ` (15 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

Including fake-delay encoders marked with FF_CODEC_CAP_EOF_FLUSH.
---
 libavcodec/ac3enc_fixed.c       |  2 +-
 libavcodec/ac3enc_float.c       |  2 +-
 libavcodec/adpcmenc.c           |  3 ++-
 libavcodec/adxenc.c             |  3 ++-
 libavcodec/alacenc.c            |  3 ++-
 libavcodec/aliaspixenc.c        |  2 +-
 libavcodec/aptxenc.c            |  4 ++--
 libavcodec/asvenc.c             |  4 ++--
 libavcodec/avuienc.c            |  3 ++-
 libavcodec/bitpacked_enc.c      |  3 ++-
 libavcodec/bmpenc.c             |  2 +-
 libavcodec/cfhdenc.c            |  3 ++-
 libavcodec/cinepakenc.c         |  2 +-
 libavcodec/cljrenc.c            |  2 +-
 libavcodec/cngenc.c             |  2 +-
 libavcodec/dcaenc.c             |  3 ++-
 libavcodec/dfpwmenc.c           |  3 ++-
 libavcodec/dnxhdenc.c           |  2 +-
 libavcodec/dvenc.c              |  3 ++-
 libavcodec/eac3enc.c            |  2 +-
 libavcodec/encode.c             | 19 +++++++++++++++++++
 libavcodec/encode.h             |  6 ++++++
 libavcodec/exrenc.c             |  3 ++-
 libavcodec/ffv1enc.c            |  3 ++-
 libavcodec/fitsenc.c            |  2 +-
 libavcodec/flacenc.c            |  3 ++-
 libavcodec/flashsv2enc.c        |  2 +-
 libavcodec/flashsvenc.c         |  2 +-
 libavcodec/flvenc.c             |  1 +
 libavcodec/g722enc.c            |  3 ++-
 libavcodec/g723_1enc.c          |  2 +-
 libavcodec/g726.c               |  6 ++++--
 libavcodec/gif.c                |  2 +-
 libavcodec/h261enc.c            |  1 +
 libavcodec/hapenc.c             |  3 ++-
 libavcodec/hdrenc.c             |  3 ++-
 libavcodec/huffyuvenc.c         |  6 ++++--
 libavcodec/ituh263enc.c         |  3 ++-
 libavcodec/j2kenc.c             |  2 +-
 libavcodec/jpeglsenc.c          |  3 ++-
 libavcodec/lclenc.c             |  3 ++-
 libavcodec/libcodec2.c          |  3 ++-
 libavcodec/libgsmenc.c          |  4 ++--
 libavcodec/libilbc.c            |  2 +-
 libavcodec/libjxlenc.c          |  3 ++-
 libavcodec/libopenh264enc.c     |  3 ++-
 libavcodec/libopenjpegenc.c     |  3 ++-
 libavcodec/libvo-amrwbenc.c     |  3 ++-
 libavcodec/libwebpenc.c         |  2 +-
 libavcodec/libxvid.c            |  2 +-
 libavcodec/ljpegenc.c           |  3 ++-
 libavcodec/magicyuvenc.c        |  3 ++-
 libavcodec/mjpegenc.c           |  4 +++-
 libavcodec/mpegaudioenc_fixed.c |  2 +-
 libavcodec/mpegaudioenc_float.c |  2 +-
 libavcodec/msmpeg4enc.c         |  3 +++
 libavcodec/msvideo1enc.c        |  1 +
 libavcodec/pamenc.c             |  2 +-
 libavcodec/pcm-blurayenc.c      |  2 +-
 libavcodec/pcm-dvdenc.c         |  3 ++-
 libavcodec/pcm.c                |  3 ++-
 libavcodec/pcxenc.c             |  2 +-
 libavcodec/pngenc.c             |  3 ++-
 libavcodec/pnmenc.c             | 12 ++++++------
 libavcodec/proresenc_anatoliy.c |  6 ++++--
 libavcodec/proresenc_kostya.c   |  3 ++-
 libavcodec/qoienc.c             |  3 ++-
 libavcodec/qtrleenc.c           |  2 +-
 libavcodec/r210enc.c            |  6 +++---
 libavcodec/rawenc.c             |  3 ++-
 libavcodec/roqvideoenc.c        |  2 +-
 libavcodec/rpzaenc.c            |  2 +-
 libavcodec/rv10enc.c            |  1 +
 libavcodec/rv20enc.c            |  1 +
 libavcodec/s302menc.c           |  3 ++-
 libavcodec/sbcenc.c             |  3 ++-
 libavcodec/sgienc.c             |  2 +-
 libavcodec/smcenc.c             |  2 +-
 libavcodec/snowenc.c            |  2 +-
 libavcodec/sonic.c              |  6 ++++--
 libavcodec/speedhqenc.c         |  1 +
 libavcodec/sunrastenc.c         |  2 +-
 libavcodec/svq1enc.c            |  2 +-
 libavcodec/targaenc.c           |  2 +-
 libavcodec/tiffenc.c            |  3 ++-
 libavcodec/ttaenc.c             |  3 ++-
 libavcodec/utvideoenc.c         |  3 ++-
 libavcodec/v210enc.c            |  3 ++-
 libavcodec/v308enc.c            |  2 +-
 libavcodec/v408enc.c            |  4 ++--
 libavcodec/v410enc.c            |  2 +-
 libavcodec/vaapi_encode_mjpeg.c |  3 ++-
 libavcodec/vbnenc.c             |  3 ++-
 libavcodec/vc2enc.c             |  3 ++-
 libavcodec/wavpackenc.c         |  3 ++-
 libavcodec/wbmpenc.c            |  3 ++-
 libavcodec/wmaenc.c             |  4 ++--
 libavcodec/wmv2enc.c            |  1 +
 libavcodec/wrapped_avframe.c    |  1 +
 libavcodec/xbmenc.c             |  2 +-
 libavcodec/xfaceenc.c           |  2 +-
 libavcodec/xwdenc.c             |  2 +-
 libavcodec/y41penc.c            |  2 +-
 libavcodec/yuv4enc.c            |  2 +-
 libavcodec/zmbvenc.c            |  2 +-
 105 files changed, 198 insertions(+), 110 deletions(-)

diff --git a/libavcodec/ac3enc_fixed.c b/libavcodec/ac3enc_fixed.c
index 5a5f1cc2e9..88dfd66b91 100644
--- a/libavcodec/ac3enc_fixed.c
+++ b/libavcodec/ac3enc_fixed.c
@@ -112,7 +112,7 @@ const FFCodec ff_ac3_fixed_encoder = {
     CODEC_LONG_NAME("ATSC A/52A (AC-3)"),
     .p.type          = AVMEDIA_TYPE_AUDIO,
     .p.id            = AV_CODEC_ID_AC3,
-    .p.capabilities  = AV_CODEC_CAP_DR1,
+    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size  = sizeof(AC3EncodeContext),
     .init            = ac3_fixed_encode_init,
     FF_CODEC_ENCODE_CB(ff_ac3_fixed_encode_frame),
diff --git a/libavcodec/ac3enc_float.c b/libavcodec/ac3enc_float.c
index 4c4d18ce56..ae351a535e 100644
--- a/libavcodec/ac3enc_float.c
+++ b/libavcodec/ac3enc_float.c
@@ -116,7 +116,7 @@ const FFCodec ff_ac3_encoder = {
     CODEC_LONG_NAME("ATSC A/52A (AC-3)"),
     .p.type          = AVMEDIA_TYPE_AUDIO,
     .p.id            = AV_CODEC_ID_AC3,
-    .p.capabilities  = AV_CODEC_CAP_DR1,
+    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size  = sizeof(AC3EncodeContext),
     .init            = ff_ac3_float_encode_init,
     FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame),
diff --git a/libavcodec/adpcmenc.c b/libavcodec/adpcmenc.c
index 57709b19a1..63afffc58f 100644
--- a/libavcodec/adpcmenc.c
+++ b/libavcodec/adpcmenc.c
@@ -1003,7 +1003,8 @@ const FFCodec ff_ ## name_ ## _encoder = {                                 \
     .p.id           = id_,                                                 \
     .p.sample_fmts  = sample_fmts_,                                        \
     .p.ch_layouts   = ch_layouts,                                          \
-    .p.capabilities = capabilities_ | AV_CODEC_CAP_DR1,                    \
+    .p.capabilities = capabilities_ | AV_CODEC_CAP_DR1 |                   \
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,               \
     .p.priv_class   = &adpcm_encoder_class,                                \
     .priv_data_size = sizeof(ADPCMEncodeContext),                          \
     .init           = adpcm_encode_init,                                   \
diff --git a/libavcodec/adxenc.c b/libavcodec/adxenc.c
index 6e12a58b16..796efdab63 100644
--- a/libavcodec/adxenc.c
+++ b/libavcodec/adxenc.c
@@ -192,7 +192,8 @@ const FFCodec ff_adpcm_adx_encoder = {
     CODEC_LONG_NAME("SEGA CRI ADX ADPCM"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_ADPCM_ADX,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(ADXContext),
     .init           = adx_encode_init,
     FF_CODEC_ENCODE_CB(adx_encode_frame),
diff --git a/libavcodec/alacenc.c b/libavcodec/alacenc.c
index 0f685d71d6..9598e5861e 100644
--- a/libavcodec/alacenc.c
+++ b/libavcodec/alacenc.c
@@ -653,7 +653,8 @@ const FFCodec ff_alac_encoder = {
     CODEC_LONG_NAME("ALAC (Apple Lossless Audio Codec)"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_ALAC,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(AlacEncodeContext),
     .p.priv_class   = &alacenc_class,
     .init           = alac_encode_init,
diff --git a/libavcodec/aliaspixenc.c b/libavcodec/aliaspixenc.c
index 6593d3f047..90d2a63319 100644
--- a/libavcodec/aliaspixenc.c
+++ b/libavcodec/aliaspixenc.c
@@ -106,7 +106,7 @@ const FFCodec ff_alias_pix_encoder = {
     CODEC_LONG_NAME("Alias/Wavefront PIX image"),
     .p.type    = AVMEDIA_TYPE_VIDEO,
     .p.id      = AV_CODEC_ID_ALIAS_PIX,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_BGR24, AV_PIX_FMT_GRAY8, AV_PIX_FMT_NONE
diff --git a/libavcodec/aptxenc.c b/libavcodec/aptxenc.c
index 5fc0378f5d..6deebaf2cb 100644
--- a/libavcodec/aptxenc.c
+++ b/libavcodec/aptxenc.c
@@ -271,7 +271,7 @@ const FFCodec ff_aptx_encoder = {
     CODEC_LONG_NAME("aptX (Audio Processing Technology for Bluetooth)"),
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_APTX,
-    .p.capabilities        = AV_CODEC_CAP_DR1,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(AptXEncContext),
     .init                  = aptx_encode_init,
     FF_CODEC_ENCODE_CB(aptx_encode_frame),
@@ -290,7 +290,7 @@ const FFCodec ff_aptx_hd_encoder = {
     CODEC_LONG_NAME("aptX HD (Audio Processing Technology for Bluetooth)"),
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_APTX_HD,
-    .p.capabilities        = AV_CODEC_CAP_DR1,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(AptXEncContext),
     .init                  = aptx_encode_init,
     FF_CODEC_ENCODE_CB(aptx_encode_frame),
diff --git a/libavcodec/asvenc.c b/libavcodec/asvenc.c
index 9da7cbb986..4a14bcf8fa 100644
--- a/libavcodec/asvenc.c
+++ b/libavcodec/asvenc.c
@@ -362,7 +362,7 @@ const FFCodec ff_asv1_encoder = {
     CODEC_LONG_NAME("ASUS V1"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_ASV1,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(ASVEncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
@@ -377,7 +377,7 @@ const FFCodec ff_asv2_encoder = {
     CODEC_LONG_NAME("ASUS V2"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_ASV2,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(ASVEncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/avuienc.c b/libavcodec/avuienc.c
index 0b82848cb3..8a093d3d19 100644
--- a/libavcodec/avuienc.c
+++ b/libavcodec/avuienc.c
@@ -96,7 +96,8 @@ const FFCodec ff_avui_encoder = {
     CODEC_LONG_NAME("Avid Meridien Uncompressed"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_AVUI,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_UYVY422, AV_PIX_FMT_NONE },
     .init         = avui_encode_init,
     FF_CODEC_ENCODE_CB(avui_encode_frame),
diff --git a/libavcodec/bitpacked_enc.c b/libavcodec/bitpacked_enc.c
index ca4d5c887d..3c4e11293d 100644
--- a/libavcodec/bitpacked_enc.c
+++ b/libavcodec/bitpacked_enc.c
@@ -110,7 +110,8 @@ const FFCodec ff_bitpacked_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_BITPACKED,
     .priv_data_size = sizeof(struct BitpackedContext),
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV422P10,
diff --git a/libavcodec/bmpenc.c b/libavcodec/bmpenc.c
index abf644bd99..3e3ca324ea 100644
--- a/libavcodec/bmpenc.c
+++ b/libavcodec/bmpenc.c
@@ -161,7 +161,7 @@ const FFCodec ff_bmp_encoder = {
     CODEC_LONG_NAME("BMP (Windows and OS/2 bitmap)"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_BMP,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = bmp_encode_init,
     FF_CODEC_ENCODE_CB(bmp_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
diff --git a/libavcodec/cfhdenc.c b/libavcodec/cfhdenc.c
index 29fb56f25a..f447438491 100644
--- a/libavcodec/cfhdenc.c
+++ b/libavcodec/cfhdenc.c
@@ -859,7 +859,8 @@ const FFCodec ff_cfhd_encoder = {
     CODEC_LONG_NAME("GoPro CineForm HD"),
     .p.type           = AVMEDIA_TYPE_VIDEO,
     .p.id             = AV_CODEC_ID_CFHD,
-    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                        AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size   = sizeof(CFHDEncContext),
     .p.priv_class     = &cfhd_class,
     .init             = cfhd_encode_init,
diff --git a/libavcodec/cinepakenc.c b/libavcodec/cinepakenc.c
index c05449e89c..f15325ad0d 100644
--- a/libavcodec/cinepakenc.c
+++ b/libavcodec/cinepakenc.c
@@ -1219,7 +1219,7 @@ const FFCodec ff_cinepak_encoder = {
     CODEC_LONG_NAME("Cinepak"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_CINEPAK,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(CinepakEncContext),
     .init           = cinepak_encode_init,
     FF_CODEC_ENCODE_CB(cinepak_encode_frame),
diff --git a/libavcodec/cljrenc.c b/libavcodec/cljrenc.c
index c1f8810a5a..d658931520 100644
--- a/libavcodec/cljrenc.c
+++ b/libavcodec/cljrenc.c
@@ -113,7 +113,7 @@ const FFCodec ff_cljr_encoder = {
     CODEC_LONG_NAME("Cirrus Logic AccuPak"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_CLJR,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(CLJRContext),
     FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P,
diff --git a/libavcodec/cngenc.c b/libavcodec/cngenc.c
index ff40017f0d..596d6f8c2a 100644
--- a/libavcodec/cngenc.c
+++ b/libavcodec/cngenc.c
@@ -101,7 +101,7 @@ const FFCodec ff_comfortnoise_encoder = {
     CODEC_LONG_NAME("RFC 3389 comfort noise generator"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_COMFORT_NOISE,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(CNGContext),
     .init           = cng_encode_init,
     FF_CODEC_ENCODE_CB(cng_encode_frame),
diff --git a/libavcodec/dcaenc.c b/libavcodec/dcaenc.c
index 4cab54ef1b..c731d79381 100644
--- a/libavcodec/dcaenc.c
+++ b/libavcodec/dcaenc.c
@@ -1315,7 +1315,8 @@ const FFCodec ff_dca_encoder = {
     CODEC_LONG_NAME("DCA (DTS Coherent Acoustics)"),
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_DTS,
-    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL |
+                             AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(DCAEncContext),
     .init                  = encode_init,
     .close                 = encode_close,
diff --git a/libavcodec/dfpwmenc.c b/libavcodec/dfpwmenc.c
index 7f465a446e..5318b04a39 100644
--- a/libavcodec/dfpwmenc.c
+++ b/libavcodec/dfpwmenc.c
@@ -116,5 +116,6 @@ const FFCodec ff_dfpwm_encoder = {
     .init            = dfpwm_enc_init,
     FF_CODEC_ENCODE_CB(dfpwm_enc_frame),
     .p.sample_fmts   = (const enum AVSampleFormat[]){AV_SAMPLE_FMT_U8, AV_SAMPLE_FMT_NONE},
-    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
+    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE |
+                       AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
 };
diff --git a/libavcodec/dnxhdenc.c b/libavcodec/dnxhdenc.c
index b7dc54f86a..176bf972d8 100644
--- a/libavcodec/dnxhdenc.c
+++ b/libavcodec/dnxhdenc.c
@@ -1359,7 +1359,7 @@ const FFCodec ff_dnxhd_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DNXHD,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
-                      AV_CODEC_CAP_SLICE_THREADS,
+                      AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(DNXHDEncContext),
     .init           = dnxhd_encode_init,
     FF_CODEC_ENCODE_CB(dnxhd_encode_picture),
diff --git a/libavcodec/dvenc.c b/libavcodec/dvenc.c
index 4c747ef71f..8f5fa050b0 100644
--- a/libavcodec/dvenc.c
+++ b/libavcodec/dvenc.c
@@ -1239,7 +1239,8 @@ const FFCodec ff_dvvideo_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DVVIDEO,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
-                      AV_CODEC_CAP_SLICE_THREADS,
+                      AV_CODEC_CAP_SLICE_THREADS                    |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(DVEncContext),
     .init           = dvvideo_encode_init,
     FF_CODEC_ENCODE_CB(dvvideo_encode_frame),
diff --git a/libavcodec/eac3enc.c b/libavcodec/eac3enc.c
index 78d4f1399a..ab9eda261f 100644
--- a/libavcodec/eac3enc.c
+++ b/libavcodec/eac3enc.c
@@ -254,7 +254,7 @@ const FFCodec ff_eac3_encoder = {
     CODEC_LONG_NAME("ATSC A/52 E-AC-3"),
     .p.type          = AVMEDIA_TYPE_AUDIO,
     .p.id            = AV_CODEC_ID_EAC3,
-    .p.capabilities  = AV_CODEC_CAP_DR1,
+    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size  = sizeof(AC3EncodeContext),
     .init            = ff_ac3_float_encode_init,
     FF_CODEC_ENCODE_CB(ff_ac3_float_encode_frame),
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index d6c73dc044..555bd3ff96 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -190,6 +190,21 @@ int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
     return 0;
 }
 
+int ff_encode_reordered_opaque(AVCodecContext *avctx,
+                               AVPacket *pkt, const AVFrame *frame)
+{
+    avctx->reordered_opaque = frame->reordered_opaque;
+
+    if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+        int ret = av_buffer_replace(&pkt->opaque_ref, frame->opaque_ref);
+        if (ret < 0)
+            return ret;
+        pkt->opaque = frame->opaque;
+    }
+
+    return 0;
+}
+
 int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
                         AVFrame *frame, int *got_packet)
 {
@@ -221,6 +236,10 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
                     avpkt->duration = ff_samples_to_time_base(avctx,
                                                               frame->nb_samples);
             }
+
+            ret = ff_encode_reordered_opaque(avctx, avpkt, frame);
+            if (ret < 0)
+                goto unref;
         }
 
         // dts equals pts unless there is reordering
diff --git a/libavcodec/encode.h b/libavcodec/encode.h
index 81d18d6ead..26a3304045 100644
--- a/libavcodec/encode.h
+++ b/libavcodec/encode.h
@@ -69,6 +69,12 @@ int ff_encode_alloc_frame(AVCodecContext *avctx, AVFrame *frame);
  */
 int ff_alloc_packet(AVCodecContext *avctx, AVPacket *avpkt, int64_t size);
 
+/**
+ * Propagate user opaque values from the frame to avctx/pkt as needed.
+ */
+int ff_encode_reordered_opaque(AVCodecContext *avctx,
+                               AVPacket *pkt, const AVFrame *frame);
+
 /*
  * Perform encoder initialization and validation.
  * Called when opening the encoder, before the FFCodec.init() call.
diff --git a/libavcodec/exrenc.c b/libavcodec/exrenc.c
index 10ed876888..36327f498c 100644
--- a/libavcodec/exrenc.c
+++ b/libavcodec/exrenc.c
@@ -547,7 +547,8 @@ const FFCodec ff_exr_encoder = {
     .p.priv_class   = &exr_class,
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_EXR,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
     .close          = encode_close,
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index 6649ec7e88..fb12776cc2 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -1270,7 +1270,8 @@ const FFCodec ff_ffv1_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_FFV1,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_SLICE_THREADS,
+                      AV_CODEC_CAP_SLICE_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(FFV1Context),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/fitsenc.c b/libavcodec/fitsenc.c
index ac910499e5..12952278ac 100644
--- a/libavcodec/fitsenc.c
+++ b/libavcodec/fitsenc.c
@@ -114,7 +114,7 @@ const FFCodec ff_fits_encoder = {
     CODEC_LONG_NAME("Flexible Image Transport System"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_FITS,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(fits_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_GBRAP16BE,
                                                      AV_PIX_FMT_GBRP16BE,
diff --git a/libavcodec/flacenc.c b/libavcodec/flacenc.c
index 9a9835dfa6..a449b73235 100644
--- a/libavcodec/flacenc.c
+++ b/libavcodec/flacenc.c
@@ -1754,7 +1754,8 @@ const FFCodec ff_flac_encoder = {
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_FLAC,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_SMALL_LAST_FRAME,
+                      AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(FlacEncodeContext),
     .init           = flac_encode_init,
     FF_CODEC_ENCODE_CB(flac_encode_frame),
diff --git a/libavcodec/flashsv2enc.c b/libavcodec/flashsv2enc.c
index 668ca6a85f..46e24a9c1e 100644
--- a/libavcodec/flashsv2enc.c
+++ b/libavcodec/flashsv2enc.c
@@ -915,7 +915,7 @@ const FFCodec ff_flashsv2_encoder = {
     CODEC_LONG_NAME("Flash Screen Video Version 2"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_FLASHSV2,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(FlashSV2Context),
     .init           = flashsv2_encode_init,
     FF_CODEC_ENCODE_CB(flashsv2_encode_frame),
diff --git a/libavcodec/flashsvenc.c b/libavcodec/flashsvenc.c
index 3a35876d9c..6192bc25db 100644
--- a/libavcodec/flashsvenc.c
+++ b/libavcodec/flashsvenc.c
@@ -251,7 +251,7 @@ const FFCodec ff_flashsv_encoder = {
     CODEC_LONG_NAME("Flash Screen Video"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_FLASHSV,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(FlashSVContext),
     .init           = flashsv_encode_init,
     FF_CODEC_ENCODE_CB(flashsv_encode_frame),
diff --git a/libavcodec/flvenc.c b/libavcodec/flvenc.c
index b49ca2e0d5..1ebe6e8736 100644
--- a/libavcodec/flvenc.c
+++ b/libavcodec/flvenc.c
@@ -105,4 +105,5 @@ const FFCodec ff_flv_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
                                                      AV_PIX_FMT_NONE},
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
 };
diff --git a/libavcodec/g722enc.c b/libavcodec/g722enc.c
index bc08211b1d..47811cee4d 100644
--- a/libavcodec/g722enc.c
+++ b/libavcodec/g722enc.c
@@ -375,7 +375,8 @@ const FFCodec ff_adpcm_g722_encoder = {
     CODEC_LONG_NAME("G.722 ADPCM"),
     .p.type          = AVMEDIA_TYPE_AUDIO,
     .p.id            = AV_CODEC_ID_ADPCM_G722,
-    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities  = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                       AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size  = sizeof(G722Context),
     .init            = g722_encode_init,
     .close           = g722_encode_close,
diff --git a/libavcodec/g723_1enc.c b/libavcodec/g723_1enc.c
index 8466067185..be80153130 100644
--- a/libavcodec/g723_1enc.c
+++ b/libavcodec/g723_1enc.c
@@ -1241,7 +1241,7 @@ const FFCodec ff_g723_1_encoder = {
     CODEC_LONG_NAME("G.723.1"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_G723_1,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(G723_1_Context),
     .init           = g723_1_encode_init,
     FF_CODEC_ENCODE_CB(g723_1_encode_frame),
diff --git a/libavcodec/g726.c b/libavcodec/g726.c
index 7bbb7f900c..6c5638760d 100644
--- a/libavcodec/g726.c
+++ b/libavcodec/g726.c
@@ -405,7 +405,8 @@ const FFCodec ff_adpcm_g726_encoder = {
     CODEC_LONG_NAME("G.726 ADPCM"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_ADPCM_G726,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(G726Context),
     .init           = g726_encode_init,
     FF_CODEC_ENCODE_CB(g726_encode_frame),
@@ -422,7 +423,8 @@ const FFCodec ff_adpcm_g726le_encoder = {
     CODEC_LONG_NAME("G.726 little endian ADPCM (\"right-justified\")"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_ADPCM_G726LE,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(G726Context),
     .init           = g726_encode_init,
     FF_CODEC_ENCODE_CB(g726_encode_frame),
diff --git a/libavcodec/gif.c b/libavcodec/gif.c
index 7e717d8220..e17ead0f82 100644
--- a/libavcodec/gif.c
+++ b/libavcodec/gif.c
@@ -553,7 +553,7 @@ const FFCodec ff_gif_encoder = {
     CODEC_LONG_NAME("GIF (Graphics Interchange Format)"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_GIF,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(GIFContext),
     .init           = gif_encode_init,
     FF_CODEC_ENCODE_CB(gif_encode_frame),
diff --git a/libavcodec/h261enc.c b/libavcodec/h261enc.c
index e8ea357cbb..6c80809bca 100644
--- a/libavcodec/h261enc.c
+++ b/libavcodec/h261enc.c
@@ -413,4 +413,5 @@ const FFCodec ff_h261_encoder = {
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
                                                      AV_PIX_FMT_NONE },
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
 };
diff --git a/libavcodec/hapenc.c b/libavcodec/hapenc.c
index a890dc6492..7de7358e3d 100644
--- a/libavcodec/hapenc.c
+++ b/libavcodec/hapenc.c
@@ -351,7 +351,8 @@ const FFCodec ff_hap_encoder = {
     CODEC_LONG_NAME("Vidvox Hap"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_HAP,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(HapContext),
     .p.priv_class   = &hapenc_class,
     .init           = hap_init,
diff --git a/libavcodec/hdrenc.c b/libavcodec/hdrenc.c
index d8c3111c93..40d283ee61 100644
--- a/libavcodec/hdrenc.c
+++ b/libavcodec/hdrenc.c
@@ -177,7 +177,8 @@ const FFCodec ff_hdr_encoder = {
     .priv_data_size = sizeof(HDREncContext),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_RADIANCE_HDR,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = hdr_encode_init,
     FF_CODEC_ENCODE_CB(hdr_encode_frame),
     .close          = hdr_encode_close,
diff --git a/libavcodec/huffyuvenc.c b/libavcodec/huffyuvenc.c
index db274e37ad..72d6246ebe 100644
--- a/libavcodec/huffyuvenc.c
+++ b/libavcodec/huffyuvenc.c
@@ -1082,7 +1082,8 @@ const FFCodec ff_huffyuv_encoder = {
     CODEC_LONG_NAME("Huffyuv / HuffYUV"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_HUFFYUV,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(HYuvEncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
@@ -1101,7 +1102,8 @@ const FFCodec ff_ffvhuff_encoder = {
     CODEC_LONG_NAME("Huffyuv FFmpeg variant"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_FFVHUFF,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(HYuvEncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/ituh263enc.c b/libavcodec/ituh263enc.c
index 22e5a8368d..719effa41d 100644
--- a/libavcodec/ituh263enc.c
+++ b/libavcodec/ituh263enc.c
@@ -903,6 +903,7 @@ const FFCodec ff_h263_encoder = {
     .p.id           = AV_CODEC_ID_H263,
     .p.pix_fmts = (const enum AVPixelFormat[]){AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE},
     .p.priv_class   = &h263_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
@@ -933,7 +934,7 @@ const FFCodec ff_h263p_encoder = {
     .p.id           = AV_CODEC_ID_H263P,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     .p.priv_class   = &h263p_class,
-    .p.capabilities = AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
diff --git a/libavcodec/j2kenc.c b/libavcodec/j2kenc.c
index e883d5deb7..6406f90ac2 100644
--- a/libavcodec/j2kenc.c
+++ b/libavcodec/j2kenc.c
@@ -1835,7 +1835,7 @@ const FFCodec ff_jpeg2000_encoder = {
     CODEC_LONG_NAME("JPEG 2000"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_JPEG2000,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(Jpeg2000EncoderContext),
     .init           = j2kenc_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/jpeglsenc.c b/libavcodec/jpeglsenc.c
index 5ee39ac2d6..53394102df 100644
--- a/libavcodec/jpeglsenc.c
+++ b/libavcodec/jpeglsenc.c
@@ -476,7 +476,8 @@ const FFCodec ff_jpegls_encoder = {
     CODEC_LONG_NAME("JPEG-LS"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_JPEGLS,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(JPEGLSContext),
     .p.priv_class   = &jpegls_class,
     .init           = encode_jpegls_init,
diff --git a/libavcodec/lclenc.c b/libavcodec/lclenc.c
index 2c9add5215..dd5eed9d63 100644
--- a/libavcodec/lclenc.c
+++ b/libavcodec/lclenc.c
@@ -156,7 +156,8 @@ const FFCodec ff_zlib_encoder = {
     CODEC_LONG_NAME("LCL (LossLess Codec Library) ZLIB"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_ZLIB,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(LclEncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/libcodec2.c b/libavcodec/libcodec2.c
index 5728d915c2..83f68e85c7 100644
--- a/libavcodec/libcodec2.c
+++ b/libavcodec/libcodec2.c
@@ -197,7 +197,8 @@ const FFCodec ff_libcodec2_encoder = {
     CODEC_LONG_NAME("codec2 encoder using libcodec2"),
     .p.type                 = AVMEDIA_TYPE_AUDIO,
     .p.id                   = AV_CODEC_ID_CODEC2,
-    .p.capabilities         = AV_CODEC_CAP_DR1,
+    .p.capabilities         = AV_CODEC_CAP_DR1 |
+                              AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.supported_samplerates = (const int[]){ 8000, 0 },
     .p.sample_fmts          = (const enum AVSampleFormat[]) { AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_NONE },
     .p.ch_layouts           = (const AVChannelLayout[]) { AV_CHANNEL_LAYOUT_MONO, { 0 } },
diff --git a/libavcodec/libgsmenc.c b/libavcodec/libgsmenc.c
index bd3b1420aa..640954491a 100644
--- a/libavcodec/libgsmenc.c
+++ b/libavcodec/libgsmenc.c
@@ -122,7 +122,7 @@ const FFCodec ff_libgsm_encoder = {
     CODEC_LONG_NAME("libgsm GSM"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_GSM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = libgsm_encode_init,
     FF_CODEC_ENCODE_CB(libgsm_encode_frame),
     .close          = libgsm_encode_close,
@@ -141,7 +141,7 @@ const FFCodec ff_libgsm_ms_encoder = {
     CODEC_LONG_NAME("libgsm GSM Microsoft variant"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_GSM_MS,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = libgsm_encode_init,
     FF_CODEC_ENCODE_CB(libgsm_encode_frame),
     .close          = libgsm_encode_close,
diff --git a/libavcodec/libilbc.c b/libavcodec/libilbc.c
index 9ef6e16bc5..9ca90bf0c6 100644
--- a/libavcodec/libilbc.c
+++ b/libavcodec/libilbc.c
@@ -205,7 +205,7 @@ const FFCodec ff_libilbc_encoder = {
     CODEC_LONG_NAME("iLBC (Internet Low Bitrate Codec)"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_ILBC,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
     .priv_data_size = sizeof(ILBCEncContext),
     .init           = ilbc_encode_init,
diff --git a/libavcodec/libjxlenc.c b/libavcodec/libjxlenc.c
index 0793ed251b..06581b268d 100644
--- a/libavcodec/libjxlenc.c
+++ b/libavcodec/libjxlenc.c
@@ -467,7 +467,8 @@ const FFCodec ff_libjxl_encoder = {
     .init             = libjxl_encode_init,
     FF_CODEC_ENCODE_CB(libjxl_encode_frame),
     .close            = libjxl_encode_close,
-    .p.capabilities   = AV_CODEC_CAP_OTHER_THREADS,
+    .p.capabilities   = AV_CODEC_CAP_OTHER_THREADS |
+                        AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal    = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                         FF_CODEC_CAP_AUTO_THREADS | FF_CODEC_CAP_INIT_CLEANUP |
                         FF_CODEC_CAP_ICC_PROFILES,
diff --git a/libavcodec/libopenh264enc.c b/libavcodec/libopenh264enc.c
index bbd6969568..6934fd481c 100644
--- a/libavcodec/libopenh264enc.c
+++ b/libavcodec/libopenh264enc.c
@@ -456,7 +456,8 @@ const FFCodec ff_libopenh264_encoder = {
     CODEC_LONG_NAME("OpenH264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_H264,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_OTHER_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SVCContext),
     .init           = svc_encode_init,
     FF_CODEC_ENCODE_CB(svc_encode_frame),
diff --git a/libavcodec/libopenjpegenc.c b/libavcodec/libopenjpegenc.c
index 6f77780391..009c7a4377 100644
--- a/libavcodec/libopenjpegenc.c
+++ b/libavcodec/libopenjpegenc.c
@@ -763,7 +763,8 @@ const FFCodec ff_libopenjpeg_encoder = {
     .priv_data_size = sizeof(LibOpenJPEGContext),
     .init           = libopenjpeg_encode_init,
     FF_CODEC_ENCODE_CB(libopenjpeg_encode_frame),
-    .p.capabilities = AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB48,
         AV_PIX_FMT_RGBA64, AV_PIX_FMT_GBR24P,
diff --git a/libavcodec/libvo-amrwbenc.c b/libavcodec/libvo-amrwbenc.c
index 76a6b69994..02b8941a6d 100644
--- a/libavcodec/libvo-amrwbenc.c
+++ b/libavcodec/libvo-amrwbenc.c
@@ -144,7 +144,8 @@ const FFCodec ff_libvo_amrwbenc_encoder = {
     CODEC_LONG_NAME("Android VisualOn AMR-WB (Adaptive Multi-Rate Wide-Band)"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_AMR_WB,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.priv_class   = &amrwb_class,
     .p.wrapper_name = "libvo_amrwbenc",
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
diff --git a/libavcodec/libwebpenc.c b/libavcodec/libwebpenc.c
index ee5795f041..d6edd86603 100644
--- a/libavcodec/libwebpenc.c
+++ b/libavcodec/libwebpenc.c
@@ -92,7 +92,7 @@ const FFCodec ff_libwebp_encoder = {
     CODEC_LONG_NAME("libwebp WebP image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WEBP,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = ff_libwebpenc_pix_fmts,
     .p.priv_class   = &ff_libwebpenc_class,
     .p.wrapper_name = "libwebp",
diff --git a/libavcodec/libxvid.c b/libavcodec/libxvid.c
index 4e04b3c098..aba875b6b8 100644
--- a/libavcodec/libxvid.c
+++ b/libavcodec/libxvid.c
@@ -902,7 +902,7 @@ const FFCodec ff_libxvid_encoder = {
     CODEC_LONG_NAME("libxvidcore MPEG-4 part 2"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_MPEG4,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(struct xvid_context),
     .init           = xvid_encode_init,
     FF_CODEC_ENCODE_CB(xvid_encode_frame),
diff --git a/libavcodec/ljpegenc.c b/libavcodec/ljpegenc.c
index 81c52a7c78..aa62beac71 100644
--- a/libavcodec/ljpegenc.c
+++ b/libavcodec/ljpegenc.c
@@ -316,7 +316,8 @@ const FFCodec ff_ljpeg_encoder = {
     CODEC_LONG_NAME("Lossless JPEG"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_LJPEG,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(LJpegEncContext),
     .p.priv_class   = &ljpeg_class,
     .init           = ljpeg_encode_init,
diff --git a/libavcodec/magicyuvenc.c b/libavcodec/magicyuvenc.c
index 7f9ff72834..9e41c1b0fe 100644
--- a/libavcodec/magicyuvenc.c
+++ b/libavcodec/magicyuvenc.c
@@ -569,7 +569,8 @@ const FFCodec ff_magicyuv_encoder = {
     CODEC_LONG_NAME("MagicYUV video"),
     .p.type           = AVMEDIA_TYPE_VIDEO,
     .p.id             = AV_CODEC_ID_MAGICYUV,
-    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities   = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                        AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size   = sizeof(MagicYUVContext),
     .p.priv_class     = &magicyuv_class,
     .init             = magy_encode_init,
diff --git a/libavcodec/mjpegenc.c b/libavcodec/mjpegenc.c
index eafe7130e2..508772987f 100644
--- a/libavcodec/mjpegenc.c
+++ b/libavcodec/mjpegenc.c
@@ -651,7 +651,8 @@ const FFCodec ff_mjpeg_encoder = {
     .init           = ff_mpv_encode_init,
     FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = mjpeg_encode_close,
-    .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_ICC_PROFILES,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
         AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ444P,
@@ -685,5 +686,6 @@ const FFCodec ff_amv_encoder = {
         AV_PIX_FMT_YUVJ420P, AV_PIX_FMT_NONE
     },
     .p.priv_class   = &amv_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
 };
 #endif
diff --git a/libavcodec/mpegaudioenc_fixed.c b/libavcodec/mpegaudioenc_fixed.c
index afbffe766b..a523b5d533 100644
--- a/libavcodec/mpegaudioenc_fixed.c
+++ b/libavcodec/mpegaudioenc_fixed.c
@@ -28,7 +28,7 @@ const FFCodec ff_mp2fixed_encoder = {
     CODEC_LONG_NAME("MP2 fixed point (MPEG audio layer 2)"),
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_MP2,
-    .p.capabilities        = AV_CODEC_CAP_DR1,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(MpegAudioContext),
     .init                  = MPA_encode_init,
     FF_CODEC_ENCODE_CB(MPA_encode_frame),
diff --git a/libavcodec/mpegaudioenc_float.c b/libavcodec/mpegaudioenc_float.c
index 212709c291..6a13d09573 100644
--- a/libavcodec/mpegaudioenc_float.c
+++ b/libavcodec/mpegaudioenc_float.c
@@ -29,7 +29,7 @@ const FFCodec ff_mp2_encoder = {
     CODEC_LONG_NAME("MP2 (MPEG audio layer 2)"),
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_MP2,
-    .p.capabilities        = AV_CODEC_CAP_DR1,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(MpegAudioContext),
     .init                  = MPA_encode_init,
     FF_CODEC_ENCODE_CB(MPA_encode_frame),
diff --git a/libavcodec/msmpeg4enc.c b/libavcodec/msmpeg4enc.c
index 9b6e5efa0c..737a7f7dce 100644
--- a/libavcodec/msmpeg4enc.c
+++ b/libavcodec/msmpeg4enc.c
@@ -684,6 +684,7 @@ const FFCodec ff_msmpeg4v2_encoder = {
     .p.id           = AV_CODEC_ID_MSMPEG4V2,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MSMPEG4EncContext),
     .init           = ff_mpv_encode_init,
@@ -698,6 +699,7 @@ const FFCodec ff_msmpeg4v3_encoder = {
     .p.id           = AV_CODEC_ID_MSMPEG4V3,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MSMPEG4EncContext),
     .init           = ff_mpv_encode_init,
@@ -712,6 +714,7 @@ const FFCodec ff_wmv1_encoder = {
     .p.id           = AV_CODEC_ID_WMV1,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(MSMPEG4EncContext),
     .init           = ff_mpv_encode_init,
diff --git a/libavcodec/msvideo1enc.c b/libavcodec/msvideo1enc.c
index a349b42ca0..36cfd39a85 100644
--- a/libavcodec/msvideo1enc.c
+++ b/libavcodec/msvideo1enc.c
@@ -307,6 +307,7 @@ const FFCodec ff_msvideo1_encoder = {
     CODEC_LONG_NAME("Microsoft Video-1"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_MSVIDEO1,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(Msvideo1EncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/pamenc.c b/libavcodec/pamenc.c
index 7d01e89f74..45ec29ccb3 100644
--- a/libavcodec/pamenc.c
+++ b/libavcodec/pamenc.c
@@ -133,7 +133,7 @@ const FFCodec ff_pam_encoder = {
     CODEC_LONG_NAME("PAM (Portable AnyMap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PAM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pam_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGBA,
diff --git a/libavcodec/pcm-blurayenc.c b/libavcodec/pcm-blurayenc.c
index 62e86e722f..bfbfa91d7a 100644
--- a/libavcodec/pcm-blurayenc.c
+++ b/libavcodec/pcm-blurayenc.c
@@ -304,5 +304,5 @@ const FFCodec ff_pcm_bluray_encoder = {
         { 0 } },
     .p.sample_fmts         = (const enum AVSampleFormat[]) {
         AV_SAMPLE_FMT_S16, AV_SAMPLE_FMT_S32, AV_SAMPLE_FMT_NONE },
-    .p.capabilities        = AV_CODEC_CAP_DR1,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
 };
diff --git a/libavcodec/pcm-dvdenc.c b/libavcodec/pcm-dvdenc.c
index 011d0a2f00..a2e5cbdc2e 100644
--- a/libavcodec/pcm-dvdenc.c
+++ b/libavcodec/pcm-dvdenc.c
@@ -176,7 +176,8 @@ const FFCodec ff_pcm_dvd_encoder = {
     CODEC_LONG_NAME("PCM signed 16|20|24-bit big-endian for DVD media"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_PCM_DVD,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(PCMDVDContext),
     .init           = pcm_dvd_encode_init,
     FF_CODEC_ENCODE_CB(pcm_dvd_encode_frame),
diff --git a/libavcodec/pcm.c b/libavcodec/pcm.c
index ee36a364c8..23955ba2dd 100644
--- a/libavcodec/pcm.c
+++ b/libavcodec/pcm.c
@@ -553,7 +553,8 @@ const FFCodec ff_ ## name_ ## _encoder = {                                  \
     CODEC_LONG_NAME(long_name_),                                            \
     .p.type       = AVMEDIA_TYPE_AUDIO,                                     \
     .p.id         = AV_CODEC_ID_ ## id_,                                    \
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE,    \
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_VARIABLE_FRAME_SIZE | \
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,                \
     .init         = pcm_encode_init,                                        \
     FF_CODEC_ENCODE_CB(pcm_encode_frame),                                   \
     .p.sample_fmts = (const enum AVSampleFormat[]){ sample_fmt_,             \
diff --git a/libavcodec/pcxenc.c b/libavcodec/pcxenc.c
index 509158ba0f..cf9b41b752 100644
--- a/libavcodec/pcxenc.c
+++ b/libavcodec/pcxenc.c
@@ -197,7 +197,7 @@ const FFCodec ff_pcx_encoder = {
     CODEC_LONG_NAME("PC Paintbrush PCX image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PCX,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pcx_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24,
diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index ca1a186ca8..d1448bd0cd 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -1196,7 +1196,8 @@ const FFCodec ff_png_encoder = {
     CODEC_LONG_NAME("PNG (Portable Network Graphics) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PNG,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(PNGEncContext),
     .init           = png_enc_init,
     .close          = png_enc_close,
diff --git a/libavcodec/pnmenc.c b/libavcodec/pnmenc.c
index 4bdd2e032f..9e1b11382b 100644
--- a/libavcodec/pnmenc.c
+++ b/libavcodec/pnmenc.c
@@ -229,7 +229,7 @@ const FFCodec ff_pgm_encoder = {
     CODEC_LONG_NAME("PGM (Portable GrayMap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PGM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_GRAY8, AV_PIX_FMT_GRAY16BE, AV_PIX_FMT_NONE
@@ -243,7 +243,7 @@ const FFCodec ff_pgmyuv_encoder = {
     CODEC_LONG_NAME("PGMYUV (Portable GrayMap YUV) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PGMYUV,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_YUV420P, AV_PIX_FMT_YUV420P16BE, AV_PIX_FMT_NONE
@@ -257,7 +257,7 @@ const FFCodec ff_ppm_encoder = {
     CODEC_LONG_NAME("PPM (Portable PixelMap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PPM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGB24, AV_PIX_FMT_RGB48BE, AV_PIX_FMT_NONE
@@ -271,7 +271,7 @@ const FFCodec ff_pbm_encoder = {
     CODEC_LONG_NAME("PBM (Portable BitMap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PBM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_MONOWHITE,
                                                   AV_PIX_FMT_NONE },
@@ -284,7 +284,7 @@ const FFCodec ff_pfm_encoder = {
     CODEC_LONG_NAME("PFM (Portable FloatMap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PFM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(pnm_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_GBRPF32LE,
                                                     AV_PIX_FMT_GRAYF32LE,
@@ -309,7 +309,7 @@ const FFCodec ff_phm_encoder = {
     CODEC_LONG_NAME("PHM (Portable HalfFloatMap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PHM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(PHMEncContext),
     .init           = phm_enc_init,
     FF_CODEC_ENCODE_CB(pnm_encode_frame),
diff --git a/libavcodec/proresenc_anatoliy.c b/libavcodec/proresenc_anatoliy.c
index bd1b70cc5d..09196c7aa1 100644
--- a/libavcodec/proresenc_anatoliy.c
+++ b/libavcodec/proresenc_anatoliy.c
@@ -944,7 +944,8 @@ const FFCodec ff_prores_aw_encoder = {
     CODEC_LONG_NAME("Apple ProRes"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PRORES,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = pix_fmts,
     .priv_data_size = sizeof(ProresContext),
     .init           = prores_encode_init,
@@ -960,7 +961,8 @@ const FFCodec ff_prores_encoder = {
     CODEC_LONG_NAME("Apple ProRes"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_PRORES,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = pix_fmts,
     .priv_data_size = sizeof(ProresContext),
     .init           = prores_encode_init,
diff --git a/libavcodec/proresenc_kostya.c b/libavcodec/proresenc_kostya.c
index 5b38437d0a..1940e0378a 100644
--- a/libavcodec/proresenc_kostya.c
+++ b/libavcodec/proresenc_kostya.c
@@ -1428,7 +1428,8 @@ const FFCodec ff_prores_ks_encoder = {
     .init           = encode_init,
     .close          = encode_close,
     FF_CODEC_ENCODE_CB(encode_frame),
-    .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_SLICE_THREADS | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = (const enum AVPixelFormat[]) {
                           AV_PIX_FMT_YUV422P10, AV_PIX_FMT_YUV444P10,
                           AV_PIX_FMT_YUVA444P10, AV_PIX_FMT_NONE
diff --git a/libavcodec/qoienc.c b/libavcodec/qoienc.c
index 6d574e0da9..b9efdc2fa5 100644
--- a/libavcodec/qoienc.c
+++ b/libavcodec/qoienc.c
@@ -131,7 +131,8 @@ const FFCodec ff_qoi_encoder = {
     CODEC_LONG_NAME("QOI (Quite OK Image format) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_QOI,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(qoi_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_RGBA, AV_PIX_FMT_RGB24,
diff --git a/libavcodec/qtrleenc.c b/libavcodec/qtrleenc.c
index 855494d3df..3d51fcf843 100644
--- a/libavcodec/qtrleenc.c
+++ b/libavcodec/qtrleenc.c
@@ -404,7 +404,7 @@ const FFCodec ff_qtrle_encoder = {
     CODEC_LONG_NAME("QuickTime Animation (RLE) video"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_QTRLE,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(QtrleEncContext),
     .init           = qtrle_encode_init,
     FF_CODEC_ENCODE_CB(qtrle_encode_frame),
diff --git a/libavcodec/r210enc.c b/libavcodec/r210enc.c
index d87f42ce4a..91e3452874 100644
--- a/libavcodec/r210enc.c
+++ b/libavcodec/r210enc.c
@@ -96,7 +96,7 @@ const FFCodec ff_r210_encoder = {
     CODEC_LONG_NAME("Uncompressed RGB 10-bit"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_R210,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = pix_fmt,
@@ -108,7 +108,7 @@ const FFCodec ff_r10k_encoder = {
     CODEC_LONG_NAME("AJA Kona 10-bit RGB Codec"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_R10K,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = pix_fmt,
@@ -120,7 +120,7 @@ const FFCodec ff_avrp_encoder = {
     CODEC_LONG_NAME("Avid 1:1 10-bit RGB Packer"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_AVRP,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
     .p.pix_fmts     = pix_fmt,
diff --git a/libavcodec/rawenc.c b/libavcodec/rawenc.c
index c2643e6d80..8c577006d9 100644
--- a/libavcodec/rawenc.c
+++ b/libavcodec/rawenc.c
@@ -86,7 +86,8 @@ const FFCodec ff_rawvideo_encoder = {
     CODEC_LONG_NAME("raw video"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_RAWVIDEO,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init           = raw_encode_init,
     FF_CODEC_ENCODE_CB(raw_encode),
 };
diff --git a/libavcodec/roqvideoenc.c b/libavcodec/roqvideoenc.c
index 273686a147..c25aa39b73 100644
--- a/libavcodec/roqvideoenc.c
+++ b/libavcodec/roqvideoenc.c
@@ -1122,7 +1122,7 @@ const FFCodec ff_roq_encoder = {
     CODEC_LONG_NAME("id RoQ video"),
     .p.type               = AVMEDIA_TYPE_VIDEO,
     .p.id                 = AV_CODEC_ID_ROQ,
-    .p.capabilities       = AV_CODEC_CAP_DR1,
+    .p.capabilities       = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size       = sizeof(RoqEncContext),
     .init                 = roq_encode_init,
     FF_CODEC_ENCODE_CB(roq_encode_frame),
diff --git a/libavcodec/rpzaenc.c b/libavcodec/rpzaenc.c
index 1ea579d2d3..da9500e424 100644
--- a/libavcodec/rpzaenc.c
+++ b/libavcodec/rpzaenc.c
@@ -873,7 +873,7 @@ const FFCodec ff_rpza_encoder = {
     CODEC_LONG_NAME("QuickTime video (RPZA)"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_RPZA,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(RpzaContext),
     .p.priv_class   = &rpza_class,
     .init           = rpza_encode_init,
diff --git a/libavcodec/rv10enc.c b/libavcodec/rv10enc.c
index d0704c5a4b..d19d693e18 100644
--- a/libavcodec/rv10enc.c
+++ b/libavcodec/rv10enc.c
@@ -71,6 +71,7 @@ const FFCodec ff_rv10_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_RV10,
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
     FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
diff --git a/libavcodec/rv20enc.c b/libavcodec/rv20enc.c
index a6bacacb48..c7149fb267 100644
--- a/libavcodec/rv20enc.c
+++ b/libavcodec/rv20enc.c
@@ -68,6 +68,7 @@ const FFCodec ff_rv20_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_RV20,
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(MpegEncContext),
     .init           = ff_mpv_encode_init,
     FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
diff --git a/libavcodec/s302menc.c b/libavcodec/s302menc.c
index 3bd657f945..4b8996f9ac 100644
--- a/libavcodec/s302menc.c
+++ b/libavcodec/s302menc.c
@@ -176,7 +176,8 @@ const FFCodec ff_s302m_encoder = {
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_S302M,
     .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL |
-                             AV_CODEC_CAP_VARIABLE_FRAME_SIZE,
+                             AV_CODEC_CAP_VARIABLE_FRAME_SIZE             |
+                             AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(S302MEncContext),
     .init                  = s302m_encode_init,
     FF_CODEC_ENCODE_CB(s302m_encode2_frame),
diff --git a/libavcodec/sbcenc.c b/libavcodec/sbcenc.c
index 721c97e1ea..fccb0e3ea3 100644
--- a/libavcodec/sbcenc.c
+++ b/libavcodec/sbcenc.c
@@ -348,7 +348,8 @@ const FFCodec ff_sbc_encoder = {
     CODEC_LONG_NAME("SBC (low-complexity subband codec)"),
     .p.type                = AVMEDIA_TYPE_AUDIO,
     .p.id                  = AV_CODEC_ID_SBC,
-    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities        = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                             AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size        = sizeof(SBCEncContext),
     .init                  = sbc_encode_init,
     FF_CODEC_ENCODE_CB(sbc_encode_frame),
diff --git a/libavcodec/sgienc.c b/libavcodec/sgienc.c
index 901e0a74f9..5bbb72c03a 100644
--- a/libavcodec/sgienc.c
+++ b/libavcodec/sgienc.c
@@ -275,7 +275,7 @@ const FFCodec ff_sgi_encoder = {
     CODEC_LONG_NAME("SGI image"),
     .p.type    = AVMEDIA_TYPE_VIDEO,
     .p.id      = AV_CODEC_ID_SGI,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SgiContext),
     .p.priv_class = &sgi_class,
     .init      = encode_init,
diff --git a/libavcodec/smcenc.c b/libavcodec/smcenc.c
index e3ea7e5e9f..3e8b5afcf6 100644
--- a/libavcodec/smcenc.c
+++ b/libavcodec/smcenc.c
@@ -595,7 +595,7 @@ const FFCodec ff_smc_encoder = {
     CODEC_LONG_NAME("QuickTime Graphics (SMC)"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SMC,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SMCContext),
     .init           = smc_encode_init,
     FF_CODEC_ENCODE_CB(smc_encode_frame),
diff --git a/libavcodec/snowenc.c b/libavcodec/snowenc.c
index 7fad95b69a..749c8067d2 100644
--- a/libavcodec/snowenc.c
+++ b/libavcodec/snowenc.c
@@ -1935,7 +1935,7 @@ const FFCodec ff_snow_encoder = {
     CODEC_LONG_NAME("Snow"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SNOW,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SnowContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/sonic.c b/libavcodec/sonic.c
index 77bdb418a7..62e6193ac6 100644
--- a/libavcodec/sonic.c
+++ b/libavcodec/sonic.c
@@ -1096,7 +1096,8 @@ const FFCodec ff_sonic_encoder = {
     CODEC_LONG_NAME("Sonic"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_SONIC,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SonicContext),
     .init           = sonic_encode_init,
     FF_CODEC_ENCODE_CB(sonic_encode_frame),
@@ -1112,7 +1113,8 @@ const FFCodec ff_sonic_ls_encoder = {
     CODEC_LONG_NAME("Sonic lossless"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_SONIC_LS,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_EXPERIMENTAL |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SonicContext),
     .init           = sonic_encode_init,
     FF_CODEC_ENCODE_CB(sonic_encode_frame),
diff --git a/libavcodec/speedhqenc.c b/libavcodec/speedhqenc.c
index 7269e345d3..5b4ff4c139 100644
--- a/libavcodec/speedhqenc.c
+++ b/libavcodec/speedhqenc.c
@@ -288,6 +288,7 @@ const FFCodec ff_speedhq_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SPEEDHQ,
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SpeedHQEncContext),
     .init           = ff_mpv_encode_init,
     FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
diff --git a/libavcodec/sunrastenc.c b/libavcodec/sunrastenc.c
index 9b82f9921a..b2d57f7235 100644
--- a/libavcodec/sunrastenc.c
+++ b/libavcodec/sunrastenc.c
@@ -213,7 +213,7 @@ const FFCodec ff_sunrast_encoder = {
     CODEC_LONG_NAME("Sun Rasterfile image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SUNRAST,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SUNRASTContext),
     .init           = sunrast_encode_init,
     FF_CODEC_ENCODE_CB(sunrast_encode_frame),
diff --git a/libavcodec/svq1enc.c b/libavcodec/svq1enc.c
index 8f09e634a5..e3ea0c1e47 100644
--- a/libavcodec/svq1enc.c
+++ b/libavcodec/svq1enc.c
@@ -752,7 +752,7 @@ const FFCodec ff_svq1_encoder = {
     CODEC_LONG_NAME("Sorenson Vector Quantizer 1 / Sorenson Video 1 / SVQ1"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_SVQ1,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(SVQ1EncContext),
     .p.priv_class   = &svq1enc_class,
     .init           = svq1_encode_init,
diff --git a/libavcodec/targaenc.c b/libavcodec/targaenc.c
index bb3cb93187..d9c500b97d 100644
--- a/libavcodec/targaenc.c
+++ b/libavcodec/targaenc.c
@@ -207,7 +207,7 @@ const FFCodec ff_targa_encoder = {
     CODEC_LONG_NAME("Truevision Targa image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_TARGA,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(TargaContext),
     .p.priv_class   = &targa_class,
     .init           = targa_encode_init,
diff --git a/libavcodec/tiffenc.c b/libavcodec/tiffenc.c
index 6dfbdaeb40..06d7dcc99d 100644
--- a/libavcodec/tiffenc.c
+++ b/libavcodec/tiffenc.c
@@ -574,7 +574,8 @@ const FFCodec ff_tiff_encoder = {
     CODEC_LONG_NAME("TIFF image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_TIFF,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(TiffEncoderContext),
     .init           = encode_init,
     .close          = encode_close,
diff --git a/libavcodec/ttaenc.c b/libavcodec/ttaenc.c
index d41d2e6fa5..db79c38b43 100644
--- a/libavcodec/ttaenc.c
+++ b/libavcodec/ttaenc.c
@@ -204,7 +204,8 @@ const FFCodec ff_tta_encoder = {
     CODEC_LONG_NAME("TTA (True Audio)"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_TTA,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(TTAEncContext),
     .init           = tta_encode_init,
     .close          = tta_encode_close,
diff --git a/libavcodec/utvideoenc.c b/libavcodec/utvideoenc.c
index d4388da8ba..6e87bbc2b6 100644
--- a/libavcodec/utvideoenc.c
+++ b/libavcodec/utvideoenc.c
@@ -648,7 +648,8 @@ const FFCodec ff_utvideo_encoder = {
     CODEC_LONG_NAME("Ut Video"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_UTVIDEO,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(UtvideoContext),
     .p.priv_class   = &utvideo_class,
     .init           = utvideo_encode_init,
diff --git a/libavcodec/v210enc.c b/libavcodec/v210enc.c
index abbbf4ff9d..2a30ed77da 100644
--- a/libavcodec/v210enc.c
+++ b/libavcodec/v210enc.c
@@ -112,7 +112,8 @@ const FFCodec ff_v210_encoder = {
     CODEC_LONG_NAME("Uncompressed 4:2:2 10-bit"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_V210,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(V210EncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
diff --git a/libavcodec/v308enc.c b/libavcodec/v308enc.c
index 78e33c0a8a..68f9c3310b 100644
--- a/libavcodec/v308enc.c
+++ b/libavcodec/v308enc.c
@@ -75,7 +75,7 @@ const FFCodec ff_v308_encoder = {
     CODEC_LONG_NAME("Uncompressed packed 4:4:4"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_V308,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init         = v308_encode_init,
     FF_CODEC_ENCODE_CB(v308_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P, AV_PIX_FMT_NONE },
diff --git a/libavcodec/v408enc.c b/libavcodec/v408enc.c
index 514f41be4e..1faac7cc36 100644
--- a/libavcodec/v408enc.c
+++ b/libavcodec/v408enc.c
@@ -94,7 +94,7 @@ const FFCodec ff_ayuv_encoder = {
     CODEC_LONG_NAME("Uncompressed packed MS 4:4:4:4"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_AYUV,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init         = v408_encode_init,
     FF_CODEC_ENCODE_CB(v408_encode_frame),
     .p.pix_fmts   = pix_fmt,
@@ -107,7 +107,7 @@ const FFCodec ff_v408_encoder = {
     CODEC_LONG_NAME("Uncompressed packed QT 4:4:4:4"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_V408,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init         = v408_encode_init,
     FF_CODEC_ENCODE_CB(v408_encode_frame),
     .p.pix_fmts   = pix_fmt,
diff --git a/libavcodec/v410enc.c b/libavcodec/v410enc.c
index bad13c371a..89ee3a7278 100644
--- a/libavcodec/v410enc.c
+++ b/libavcodec/v410enc.c
@@ -79,7 +79,7 @@ const FFCodec ff_v410_encoder = {
     CODEC_LONG_NAME("Uncompressed 4:4:4 10-bit"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_V410,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init         = v410_encode_init,
     FF_CODEC_ENCODE_CB(v410_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV444P10, AV_PIX_FMT_NONE },
diff --git a/libavcodec/vaapi_encode_mjpeg.c b/libavcodec/vaapi_encode_mjpeg.c
index 5ef93cd102..cb7588b94b 100644
--- a/libavcodec/vaapi_encode_mjpeg.c
+++ b/libavcodec/vaapi_encode_mjpeg.c
@@ -574,7 +574,8 @@ const FFCodec ff_mjpeg_vaapi_encoder = {
     FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
     .close          = &vaapi_encode_mjpeg_close,
     .p.priv_class   = &vaapi_encode_mjpeg_class,
-    .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_HARDWARE | AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .defaults       = vaapi_encode_mjpeg_defaults,
diff --git a/libavcodec/vbnenc.c b/libavcodec/vbnenc.c
index 45101382a3..7ce91863d7 100644
--- a/libavcodec/vbnenc.c
+++ b/libavcodec/vbnenc.c
@@ -153,7 +153,8 @@ const FFCodec ff_vbn_encoder = {
     CODEC_LONG_NAME("Vizrt Binary Image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_VBN,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.priv_class   = &vbnenc_class,
     .init           = vbn_init,
     FF_CODEC_ENCODE_CB(vbn_encode),
diff --git a/libavcodec/vc2enc.c b/libavcodec/vc2enc.c
index 82d11462aa..d978c67a3b 100644
--- a/libavcodec/vc2enc.c
+++ b/libavcodec/vc2enc.c
@@ -1228,7 +1228,8 @@ const FFCodec ff_vc2_encoder = {
     CODEC_LONG_NAME("SMPTE VC-2"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_DIRAC,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SLICE_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .priv_data_size = sizeof(VC2EncContext),
     .init           = vc2_encode_init,
diff --git a/libavcodec/wavpackenc.c b/libavcodec/wavpackenc.c
index bdb536382f..3d2d45360d 100644
--- a/libavcodec/wavpackenc.c
+++ b/libavcodec/wavpackenc.c
@@ -2963,7 +2963,8 @@ const FFCodec ff_wavpack_encoder = {
     CODEC_LONG_NAME("WavPack"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_WAVPACK,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_SMALL_LAST_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(WavPackEncodeContext),
     .p.priv_class   = &wavpack_encoder_class,
     .init           = wavpack_encode_init,
diff --git a/libavcodec/wbmpenc.c b/libavcodec/wbmpenc.c
index 25fac746fc..abb66b4ca9 100644
--- a/libavcodec/wbmpenc.c
+++ b/libavcodec/wbmpenc.c
@@ -80,7 +80,8 @@ const FFCodec ff_wbmp_encoder = {
     CODEC_LONG_NAME("WBMP (Wireless Application Protocol Bitmap) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WBMP,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_FRAME_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(wbmp_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]){
         AV_PIX_FMT_MONOBLACK,
diff --git a/libavcodec/wmaenc.c b/libavcodec/wmaenc.c
index 2c647af13b..80ff696be6 100644
--- a/libavcodec/wmaenc.c
+++ b/libavcodec/wmaenc.c
@@ -440,7 +440,7 @@ const FFCodec ff_wmav1_encoder = {
     CODEC_LONG_NAME("Windows Media Audio 1"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_WMAV1,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(WMACodecContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_superframe),
@@ -456,7 +456,7 @@ const FFCodec ff_wmav2_encoder = {
     CODEC_LONG_NAME("Windows Media Audio 2"),
     .p.type         = AVMEDIA_TYPE_AUDIO,
     .p.id           = AV_CODEC_ID_WMAV2,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(WMACodecContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_superframe),
diff --git a/libavcodec/wmv2enc.c b/libavcodec/wmv2enc.c
index 05f993525d..6d991909fb 100644
--- a/libavcodec/wmv2enc.c
+++ b/libavcodec/wmv2enc.c
@@ -242,6 +242,7 @@ const FFCodec ff_wmv2_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WMV2,
     .p.priv_class   = &ff_mpv_enc_class,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(WMV2EncContext),
     .init           = wmv2_encode_init,
     FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
diff --git a/libavcodec/wrapped_avframe.c b/libavcodec/wrapped_avframe.c
index c9579848e6..0278ea42ba 100644
--- a/libavcodec/wrapped_avframe.c
+++ b/libavcodec/wrapped_avframe.c
@@ -109,6 +109,7 @@ const FFCodec ff_wrapped_avframe_encoder = {
     CODEC_LONG_NAME("AVFrame to AVPacket passthrough"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WRAPPED_AVFRAME,
+    .p.capabilities = AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(wrapped_avframe_encode),
 };
 
diff --git a/libavcodec/xbmenc.c b/libavcodec/xbmenc.c
index 664c6599bf..cd8b73afa3 100644
--- a/libavcodec/xbmenc.c
+++ b/libavcodec/xbmenc.c
@@ -82,7 +82,7 @@ const FFCodec ff_xbm_encoder = {
     CODEC_LONG_NAME("XBM (X BitMap) image"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_XBM,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(xbm_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE,
                                                    AV_PIX_FMT_NONE },
diff --git a/libavcodec/xfaceenc.c b/libavcodec/xfaceenc.c
index 7125f1f085..4998d42ea5 100644
--- a/libavcodec/xfaceenc.c
+++ b/libavcodec/xfaceenc.c
@@ -216,7 +216,7 @@ const FFCodec ff_xface_encoder = {
     CODEC_LONG_NAME("X-face image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_XFACE,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_MONOWHITE, AV_PIX_FMT_NONE },
     .priv_data_size = sizeof(XFaceContext),
     FF_CODEC_ENCODE_CB(xface_encode_frame),
diff --git a/libavcodec/xwdenc.c b/libavcodec/xwdenc.c
index 6c588f3acc..08554d8632 100644
--- a/libavcodec/xwdenc.c
+++ b/libavcodec/xwdenc.c
@@ -216,7 +216,7 @@ const FFCodec ff_xwd_encoder = {
     CODEC_LONG_NAME("XWD (X Window Dump) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_XWD,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     FF_CODEC_ENCODE_CB(xwd_encode_frame),
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_BGRA,
                                                  AV_PIX_FMT_RGBA,
diff --git a/libavcodec/y41penc.c b/libavcodec/y41penc.c
index d3ef88c2ce..e86769da66 100644
--- a/libavcodec/y41penc.c
+++ b/libavcodec/y41penc.c
@@ -82,7 +82,7 @@ const FFCodec ff_y41p_encoder = {
     CODEC_LONG_NAME("Uncompressed YUV 4:1:1 12-bit"),
     .p.type       = AVMEDIA_TYPE_VIDEO,
     .p.id         = AV_CODEC_ID_Y41P,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .init         = y41p_encode_init,
     FF_CODEC_ENCODE_CB(y41p_encode_frame),
     .p.pix_fmts   = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV411P,
diff --git a/libavcodec/yuv4enc.c b/libavcodec/yuv4enc.c
index 27e786dd54..8123260d5d 100644
--- a/libavcodec/yuv4enc.c
+++ b/libavcodec/yuv4enc.c
@@ -64,7 +64,7 @@ const FFCodec ff_yuv4_encoder = {
     CODEC_LONG_NAME("Uncompressed packed 4:2:0"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_YUV4,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = (const enum AVPixelFormat[]){ AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
     FF_CODEC_ENCODE_CB(yuv4_encode_frame),
 };
diff --git a/libavcodec/zmbvenc.c b/libavcodec/zmbvenc.c
index c12f783d5a..d20330568d 100644
--- a/libavcodec/zmbvenc.c
+++ b/libavcodec/zmbvenc.c
@@ -416,7 +416,7 @@ const FFCodec ff_zmbv_encoder = {
     CODEC_LONG_NAME("Zip Motion Blocks Video"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_ZMBV,
-    .p.capabilities = AV_CODEC_CAP_DR1,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(ZmbvEncContext),
     .init           = encode_init,
     FF_CODEC_ENCODE_CB(encode_frame),
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 06/19] lavc/encode: pass through frame durations to encoded packets
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (3 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 05/19] lavc: support AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE in all no-delay encoders Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 07/19] lavc/librav1e: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
                   ` (14 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

The generic code can only handle the no-delay case. Encoders with delay
need to be handled individually, which will be done in the following
commits.
---
 doc/APIchanges             |  2 +-
 libavcodec/avcodec.h       |  7 +++++++
 libavcodec/encode.c        | 14 ++++++++++++--
 libavcodec/options_table.h |  1 +
 4 files changed, 21 insertions(+), 3 deletions(-)

diff --git a/doc/APIchanges b/doc/APIchanges
index f52337990f..a20a899365 100644
--- a/doc/APIchanges
+++ b/doc/APIchanges
@@ -15,7 +15,7 @@ libavutil:     2021-04-27
 API changes, most recent first:
 
 2023-01-xx - xxxxxxxxxx - lavc 59.57.100 - avcodec.h
-  Add AV_CODEC_FLAG_COPY_OPAQUE.
+  Add AV_CODEC_FLAG_COPY_OPAQUE and AV_CODEC_FLAG_FRAME_DURATION.
 
 2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h
   Adds a new structure for holding H.274 Ambient Viewing Environment metadata,
diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 54ab7b81f9..1daa1106aa 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -267,6 +267,13 @@ typedef struct RcOverride{
  * taken from the first of those.
  */
 #define AV_CODEC_FLAG_COPY_OPAQUE     (1 <<  7)
+/**
+ * Signal to the encoder that the values of AVFrame.duration are valid and
+ * should be used (typically for transferring them to output packets).
+ *
+ * If this flag is not set, frame durations are ignored.
+ */
+#define AV_CODEC_FLAG_FRAME_DURATION  (1 <<  8)
 /**
  * Use internal 2pass ratecontrol in first pass mode.
  */
diff --git a/libavcodec/encode.c b/libavcodec/encode.c
index 555bd3ff96..c92beaf8e1 100644
--- a/libavcodec/encode.c
+++ b/libavcodec/encode.c
@@ -231,10 +231,13 @@ int ff_encode_encode_cb(AVCodecContext *avctx, AVPacket *avpkt,
             if (avpkt->pts == AV_NOPTS_VALUE)
                 avpkt->pts = frame->pts;
 
-            if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
-                if (!avpkt->duration)
+            if (!avpkt->duration) {
+                if (frame->duration)
+                    avpkt->duration = frame->duration;
+                else if (avctx->codec->type == AVMEDIA_TYPE_AUDIO) {
                     avpkt->duration = ff_samples_to_time_base(avctx,
                                                               frame->nb_samples);
+                }
             }
 
             ret = ff_encode_reordered_opaque(avctx, avpkt, frame);
@@ -463,6 +466,13 @@ FF_ENABLE_DEPRECATION_WARNINGS
             return ret;
     }
 
+    // unset frame duration unless AV_CODEC_FLAG_FRAME_DURATION is set,
+    // since otherwise we cannot be sure that whatever value it has is in the
+    // right timebase, so we would produce an incorrect value, which is worse
+    // than none at all
+    if (!(avctx->flags & AV_CODEC_FLAG_FRAME_DURATION))
+        dst->duration = 0;
+
     return 0;
 }
 
diff --git a/libavcodec/options_table.h b/libavcodec/options_table.h
index 4b38c42043..322ec7a156 100644
--- a/libavcodec/options_table.h
+++ b/libavcodec/options_table.h
@@ -59,6 +59,7 @@ static const AVOption avcodec_options[] = {
 {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"},
 {"recon_frame", "export reconstructed frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_RECON_FRAME}, .unit = "flags"},
 {"copy_opaque", "propagate opaque values", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_COPY_OPAQUE}, .unit = "flags"},
+{"frame_duration", "use frame durations", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_FRAME_DURATION}, .unit = "flags"},
 {"pass1", "use internal 2-pass ratecontrol in first  pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS1 }, INT_MIN, INT_MAX, 0, "flags"},
 {"pass2", "use internal 2-pass ratecontrol in second pass mode", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_PASS2 }, INT_MIN, INT_MAX, 0, "flags"},
 {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"},
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 07/19] lavc/librav1e: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (4 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 06/19] lavc/encode: pass through frame durations to encoded packets Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 08/19] lavc/nvenc: " Anton Khirnov
                   ` (13 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/librav1e.c | 61 +++++++++++++++++++++++++++++++++++++------
 1 file changed, 53 insertions(+), 8 deletions(-)

diff --git a/libavcodec/librav1e.c b/libavcodec/librav1e.c
index 3481b7637d..00d69328fb 100644
--- a/libavcodec/librav1e.c
+++ b/libavcodec/librav1e.c
@@ -22,6 +22,7 @@
 
 #include <rav1e.h>
 
+#include "libavutil/buffer.h"
 #include "libavutil/internal.h"
 #include "libavutil/avassert.h"
 #include "libavutil/base64.h"
@@ -53,6 +54,15 @@ typedef struct librav1eContext {
     int tile_cols;
 } librav1eContext;
 
+typedef struct FrameData {
+    int64_t pts;
+    int64_t duration;
+    int64_t reordered_opaque;
+
+    void        *frame_opaque;
+    AVBufferRef *frame_opaque_ref;
+} FrameData;
+
 static inline RaPixelRange range_map(enum AVPixelFormat pix_fmt, enum AVColorRange range)
 {
     switch (pix_fmt) {
@@ -419,11 +429,23 @@ end:
     return ret;
 }
 
+static void frame_data_free(void *data)
+{
+    FrameData *fd = data;
+
+    if (!fd)
+        return;
+
+    av_buffer_unref(&fd->frame_opaque_ref);
+    av_free(data);
+}
+
 static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
 {
     librav1eContext *ctx = avctx->priv_data;
     RaFrame *rframe = ctx->rframe;
     RaPacket *rpkt = NULL;
+    FrameData *fd;
     int ret;
 
     if (!rframe) {
@@ -436,18 +458,30 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
         if (frame->buf[0]) {
             const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format);
 
-            int64_t *pts = av_malloc(sizeof(int64_t));
-            if (!pts) {
+            fd = av_mallocz(sizeof(*fd));
+            if (!fd) {
                 av_log(avctx, AV_LOG_ERROR, "Could not allocate PTS buffer.\n");
                 return AVERROR(ENOMEM);
             }
-            *pts = frame->pts;
+            fd->pts      = frame->pts;
+            fd->duration = frame->duration;
+            fd->reordered_opaque = frame->reordered_opaque;
+
+            if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+                fd->frame_opaque = frame->opaque;
+                ret = av_buffer_replace(&fd->frame_opaque_ref, frame->opaque_ref);
+                if (ret < 0) {
+                    frame_data_free(fd);
+                    av_frame_unref(frame);
+                    return ret;
+                }
+            }
 
             rframe = rav1e_frame_new(ctx->ctx);
             if (!rframe) {
                 av_log(avctx, AV_LOG_ERROR, "Could not allocate new rav1e frame.\n");
                 av_frame_unref(frame);
-                av_freep(&pts);
+                frame_data_free(fd);
                 return AVERROR(ENOMEM);
             }
 
@@ -459,7 +493,7 @@ static int librav1e_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
                                        frame->linesize[i], bytes);
             }
             av_frame_unref(frame);
-            rav1e_frame_set_opaque(rframe, pts, av_free);
+            rav1e_frame_set_opaque(rframe, fd, frame_data_free);
         }
     }
 
@@ -535,8 +569,18 @@ retry:
     if (rpkt->frame_type == RA_FRAME_TYPE_KEY)
         pkt->flags |= AV_PKT_FLAG_KEY;
 
-    pkt->pts = pkt->dts = *((int64_t *) rpkt->opaque);
-    av_free(rpkt->opaque);
+    fd = rpkt->opaque;
+    pkt->pts = pkt->dts = fd->pts;
+    pkt->duration = fd->duration;
+    avctx->reordered_opaque = fd->reordered_opaque;
+
+    if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+        pkt->opaque          = fd->frame_opaque;
+        pkt->opaque_ref      = fd->frame_opaque_ref;
+        fd->frame_opaque_ref = NULL;
+    }
+
+    frame_data_free(fd);
 
     if (avctx->flags & AV_CODEC_FLAG_RECON_FRAME) {
         AVCodecInternal *avci = avctx->internal;
@@ -626,7 +670,8 @@ const FFCodec ff_librav1e_encoder = {
     .defaults       = librav1e_defaults,
     .p.pix_fmts     = librav1e_pix_fmts,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_OTHER_THREADS |
-                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_RECON_FRAME,
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_RECON_FRAME |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP | FF_CODEC_CAP_AUTO_THREADS,
     .p.wrapper_name = "librav1e",
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 08/19] lavc/nvenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (5 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 07/19] lavc/librav1e: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 09/19] lavc/pngenc: " Anton Khirnov
                   ` (12 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/nvenc.c      | 102 ++++++++++++++++++++++++++++++++--------
 libavcodec/nvenc.h      |   2 +-
 libavcodec/nvenc_av1.c  |   3 +-
 libavcodec/nvenc_h264.c |   3 +-
 libavcodec/nvenc_hevc.c |   3 +-
 5 files changed, 89 insertions(+), 24 deletions(-)

diff --git a/libavcodec/nvenc.c b/libavcodec/nvenc.c
index f6df7cb6ac..ab42dc9690 100644
--- a/libavcodec/nvenc.c
+++ b/libavcodec/nvenc.c
@@ -28,6 +28,7 @@
 #include "av1.h"
 #endif
 
+#include "libavutil/buffer.h"
 #include "libavutil/hwcontext_cuda.h"
 #include "libavutil/hwcontext.h"
 #include "libavutil/cuda_check.h"
@@ -162,6 +163,23 @@ static int nvenc_print_error(AVCodecContext *avctx, NVENCSTATUS err,
     return ret;
 }
 
+typedef struct FrameData {
+    int64_t pts;
+    int64_t duration;
+    int64_t reordered_opaque;
+
+    void        *frame_opaque;
+    AVBufferRef *frame_opaque_ref;
+} FrameData;
+
+static void reorder_queue_flush(AVFifo *queue)
+{
+    FrameData fd;
+
+    while (av_fifo_read(queue, &fd, 1) >= 0)
+        av_buffer_unref(&fd.frame_opaque_ref);
+}
+
 typedef struct GUIDTuple {
     const GUID guid;
     int flags;
@@ -1748,8 +1766,8 @@ static av_cold int nvenc_setup_surfaces(AVCodecContext *avctx)
     if (!ctx->surfaces)
         return AVERROR(ENOMEM);
 
-    ctx->timestamp_list = av_fifo_alloc2(ctx->nb_surfaces, sizeof(int64_t), 0);
-    if (!ctx->timestamp_list)
+    ctx->reorder_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(FrameData), 0);
+    if (!ctx->reorder_queue)
         return AVERROR(ENOMEM);
 
     ctx->unused_surface_queue = av_fifo_alloc2(ctx->nb_surfaces, sizeof(NvencSurface*), 0);
@@ -1833,7 +1851,8 @@ av_cold int ff_nvenc_encode_close(AVCodecContext *avctx)
         p_nvenc->nvEncEncodePicture(ctx->nvencoder, &params);
     }
 
-    av_fifo_freep2(&ctx->timestamp_list);
+    reorder_queue_flush(ctx->reorder_queue);
+    av_fifo_freep2(&ctx->reorder_queue);
     av_fifo_freep2(&ctx->output_surface_ready_queue);
     av_fifo_freep2(&ctx->output_surface_queue);
     av_fifo_freep2(&ctx->unused_surface_queue);
@@ -2177,18 +2196,45 @@ static void nvenc_codec_specific_pic_params(AVCodecContext *avctx,
     }
 }
 
-static inline void timestamp_queue_enqueue(AVFifo *queue, int64_t timestamp)
+static void reorder_queue_enqueue(AVFifo *queue, const AVCodecContext *avctx,
+                                  const AVFrame *frame, AVBufferRef **opaque_ref)
 {
-    av_fifo_write(queue, &timestamp, 1);
+    FrameData fd;
+
+    fd.pts              = frame->pts;
+    fd.duration         = frame->duration;
+    fd.reordered_opaque = frame->reordered_opaque;
+    fd.frame_opaque     = frame->opaque;
+    fd.frame_opaque_ref = *opaque_ref;
+
+    *opaque_ref = NULL;
+
+    av_fifo_write(queue, &fd, 1);
 }
 
-static inline int64_t timestamp_queue_dequeue(AVFifo *queue)
+static int64_t reorder_queue_dequeue(AVFifo *queue, AVCodecContext *avctx,
+                                     AVPacket *pkt)
 {
-    int64_t timestamp = AV_NOPTS_VALUE;
+    FrameData fd;
+
     // The following call might fail if the queue is empty.
-    av_fifo_read(queue, &timestamp, 1);
+    if (av_fifo_read(queue, &fd, 1) < 0)
+        return AV_NOPTS_VALUE;
+
+    if (pkt) {
+        avctx->reordered_opaque = fd.reordered_opaque;
+        pkt->duration           = fd.duration;
+
+        if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+            pkt->opaque             = fd.frame_opaque;
+            pkt->opaque_ref         = fd.frame_opaque_ref;
+            fd.frame_opaque_ref     = NULL;
+        }
+    }
+
+    av_buffer_unref(&fd.frame_opaque_ref);
 
-    return timestamp;
+    return fd.pts;
 }
 
 static int nvenc_set_timestamp(AVCodecContext *avctx,
@@ -2196,12 +2242,14 @@ static int nvenc_set_timestamp(AVCodecContext *avctx,
                                AVPacket *pkt)
 {
     NvencContext *ctx = avctx->priv_data;
+    int64_t dts;
 
     pkt->pts = params->outputTimeStamp;
 
+    dts = reorder_queue_dequeue(ctx->reorder_queue, avctx, pkt);
+
     if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER) {
-        pkt->dts = timestamp_queue_dequeue(ctx->timestamp_list);
-        pkt->dts -= FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1);
+        pkt->dts = dts - FFMAX(ctx->encode_config.frameIntervalP - 1, 0) * FFMAX(avctx->ticks_per_frame, 1);
     } else {
         pkt->dts = pkt->pts;
     }
@@ -2298,7 +2346,7 @@ static int process_output_surface(AVCodecContext *avctx, AVPacket *pkt, NvencSur
     return 0;
 
 error:
-    timestamp_queue_dequeue(ctx->timestamp_list);
+    reorder_queue_dequeue(ctx->reorder_queue, avctx, NULL);
 
 error2:
     return res;
@@ -2528,6 +2576,8 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
     int sei_count = 0;
     int i;
 
+    AVBufferRef *opaque_ref = NULL;
+
     NvencContext *ctx = avctx->priv_data;
     NvencDynLoadFunctions *dl_fn = &ctx->nvenc_dload_funcs;
     NV_ENCODE_API_FUNCTION_LIST *p_nvenc = &dl_fn->nvenc_funcs;
@@ -2595,9 +2645,17 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
         pic_params.encodePicFlags = NV_ENC_PIC_FLAG_EOS;
     }
 
+    // make a reference for enqueing in the reorder queue here,
+    // so that reorder_queue_enqueue() cannot fail
+    if (frame && frame->opaque_ref && avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+        opaque_ref = av_buffer_ref(frame->opaque_ref);
+        if (!opaque_ref)
+            return AVERROR(ENOMEM);
+    }
+
     res = nvenc_push_context(avctx);
     if (res < 0)
-        return res;
+        goto opaque_ref_fail;
 
     nv_status = p_nvenc->nvEncEncodePicture(ctx->nvencoder, &pic_params);
 
@@ -2606,17 +2664,17 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
 
     res = nvenc_pop_context(avctx);
     if (res < 0)
-        return res;
+        goto opaque_ref_fail;
 
     if (nv_status != NV_ENC_SUCCESS &&
-        nv_status != NV_ENC_ERR_NEED_MORE_INPUT)
-        return nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
+        nv_status != NV_ENC_ERR_NEED_MORE_INPUT) {
+        res = nvenc_print_error(avctx, nv_status, "EncodePicture failed!");
+        goto opaque_ref_fail;
+    }
 
     if (frame && frame->buf[0]) {
         av_fifo_write(ctx->output_surface_queue, &in_surf, 1);
-
-        if (avctx->codec_descriptor->props & AV_CODEC_PROP_REORDER)
-            timestamp_queue_enqueue(ctx->timestamp_list, frame->pts);
+        reorder_queue_enqueue(ctx->reorder_queue, avctx, frame, &opaque_ref);
     }
 
     /* all the pending buffers are now ready for output */
@@ -2626,6 +2684,10 @@ static int nvenc_send_frame(AVCodecContext *avctx, const AVFrame *frame)
     }
 
     return 0;
+
+opaque_ref_fail:
+    av_buffer_unref(&opaque_ref);
+    return res;
 }
 
 int ff_nvenc_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
@@ -2684,5 +2746,5 @@ av_cold void ff_nvenc_encode_flush(AVCodecContext *avctx)
     NvencContext *ctx = avctx->priv_data;
 
     nvenc_send_frame(avctx, NULL);
-    av_fifo_reset2(ctx->timestamp_list);
+    reorder_queue_flush(ctx->reorder_queue);
 }
diff --git a/libavcodec/nvenc.h b/libavcodec/nvenc.h
index 05a7ac48b1..411c83aa94 100644
--- a/libavcodec/nvenc.h
+++ b/libavcodec/nvenc.h
@@ -171,7 +171,7 @@ typedef struct NvencContext
     AVFifo *unused_surface_queue;
     AVFifo *output_surface_queue;
     AVFifo *output_surface_ready_queue;
-    AVFifo *timestamp_list;
+    AVFifo *reorder_queue;
 
     NV_ENC_SEI_PAYLOAD *sei_data;
     int sei_data_size;
diff --git a/libavcodec/nvenc_av1.c b/libavcodec/nvenc_av1.c
index 2ed99d948b..2b349c7b61 100644
--- a/libavcodec/nvenc_av1.c
+++ b/libavcodec/nvenc_av1.c
@@ -181,7 +181,8 @@ const FFCodec ff_av1_nvenc_encoder = {
     .defaults       = defaults,
     .p.pix_fmts     = ff_nvenc_pix_fmts,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .p.wrapper_name = "nvenc",
diff --git a/libavcodec/nvenc_h264.c b/libavcodec/nvenc_h264.c
index a69358b03b..5dc2961c3b 100644
--- a/libavcodec/nvenc_h264.c
+++ b/libavcodec/nvenc_h264.c
@@ -232,7 +232,8 @@ const FFCodec ff_h264_nvenc_encoder = {
     .p.priv_class   = &h264_nvenc_class,
     .defaults       = defaults,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .p.pix_fmts     = ff_nvenc_pix_fmts,
diff --git a/libavcodec/nvenc_hevc.c b/libavcodec/nvenc_hevc.c
index 5ad423444a..1362a927c8 100644
--- a/libavcodec/nvenc_hevc.c
+++ b/libavcodec/nvenc_hevc.c
@@ -214,7 +214,8 @@ const FFCodec ff_hevc_nvenc_encoder = {
     .defaults       = defaults,
     .p.pix_fmts     = ff_nvenc_pix_fmts,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_ENCODER_FLUSH | AV_CODEC_CAP_DR1 |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .p.wrapper_name = "nvenc",
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 09/19] lavc/pngenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (6 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 08/19] lavc/nvenc: " Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 10/19] lavc/pngenc: stop setting dts unnecessarily for APNG Anton Khirnov
                   ` (11 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/pngenc.c | 8 +++++++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index d1448bd0cd..3738df297e 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -977,6 +977,11 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt,
 
         memcpy(pkt->data, s->last_frame_packet, s->last_frame_packet_size);
         pkt->pts = pkt->dts = s->last_frame->pts;
+        pkt->duration = s->last_frame->duration;
+
+        ret = ff_encode_reordered_opaque(avctx, pkt, s->last_frame);
+        if (ret < 0)
+            return ret;
     }
 
     if (pict) {
@@ -1219,7 +1224,8 @@ const FFCodec ff_apng_encoder = {
     CODEC_LONG_NAME("APNG (Animated Portable Network Graphics) image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_APNG,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(PNGEncContext),
     .init           = png_enc_init,
     .close          = png_enc_close,
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 10/19] lavc/pngenc: stop setting dts unnecessarily for APNG
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (7 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 09/19] lavc/pngenc: " Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 11/19] lavc/libtheoraenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
                   ` (10 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

APNG is not marked as supporting reordering, so dts will be set from pts
by the generic code.
---
 libavcodec/pngenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/pngenc.c b/libavcodec/pngenc.c
index 3738df297e..4392220fbb 100644
--- a/libavcodec/pngenc.c
+++ b/libavcodec/pngenc.c
@@ -976,7 +976,7 @@ static int encode_apng(AVCodecContext *avctx, AVPacket *pkt,
             return ret;
 
         memcpy(pkt->data, s->last_frame_packet, s->last_frame_packet_size);
-        pkt->pts = pkt->dts = s->last_frame->pts;
+        pkt->pts = s->last_frame->pts;
         pkt->duration = s->last_frame->duration;
 
         ret = ff_encode_reordered_opaque(avctx, pkt, s->last_frame);
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 11/19] lavc/libtheoraenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (8 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 10/19] lavc/pngenc: stop setting dts unnecessarily for APNG Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 12/19] lavc/libtheoraenc: stop setting dts unnecessarily Anton Khirnov
                   ` (9 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/libtheoraenc.c | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c
index da16c6372e..73295e22b9 100644
--- a/libavcodec/libtheoraenc.c
+++ b/libavcodec/libtheoraenc.c
@@ -347,6 +347,12 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt,
     // HACK: assumes no encoder delay, this is true until libtheora becomes
     // multithreaded (which will be disabled unless explicitly requested)
     pkt->pts = pkt->dts = frame->pts;
+    pkt->duration = frame->duration;
+
+    ret = ff_encode_reordered_opaque(avc_context, pkt, frame);
+    if (ret < 0)
+        return ret;
+
     if (!(o_packet.granulepos & h->keyframe_mask))
         pkt->flags |= AV_PKT_FLAG_KEY;
     *got_packet = 1;
@@ -373,7 +379,9 @@ const FFCodec ff_libtheora_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_THEORA,
     .p.capabilities = AV_CODEC_CAP_DR1 |
-                      AV_CODEC_CAP_DELAY /* for statsfile summary */,
+                      /* for statsfile summary */
+                      AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE,
     .priv_data_size = sizeof(TheoraContext),
     .init           = encode_init,
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 12/19] lavc/libtheoraenc: stop setting dts unnecessarily
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (9 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 11/19] lavc/libtheoraenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 13/19] lavc/mpegvideo_enc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
                   ` (8 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

Theora is not marked as supporting reordering, so dts will be set from
pts by the generic code.
---
 libavcodec/libtheoraenc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/libtheoraenc.c b/libavcodec/libtheoraenc.c
index 73295e22b9..06eeaae006 100644
--- a/libavcodec/libtheoraenc.c
+++ b/libavcodec/libtheoraenc.c
@@ -346,7 +346,7 @@ static int encode_frame(AVCodecContext* avc_context, AVPacket *pkt,
 
     // HACK: assumes no encoder delay, this is true until libtheora becomes
     // multithreaded (which will be disabled unless explicitly requested)
-    pkt->pts = pkt->dts = frame->pts;
+    pkt->pts = frame->pts;
     pkt->duration = frame->duration;
 
     ret = ff_encode_reordered_opaque(avc_context, pkt, frame);
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 13/19] lavc/mpegvideo_enc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (10 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 12/19] lavc/libtheoraenc: stop setting dts unnecessarily Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 14/19] lavc/vaapi_encode*: " Anton Khirnov
                   ` (7 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

For delay-capable encoders, i.e. mpeg12 and mpeg4video. Generic code in
encode.c already handles this for all other mpegvideo encoders.
---
 libavcodec/mpeg12enc.c     | 6 ++++--
 libavcodec/mpeg4videoenc.c | 3 ++-
 libavcodec/mpegvideo_enc.c | 9 +++++++++
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/libavcodec/mpeg12enc.c b/libavcodec/mpeg12enc.c
index 3ad1cd84a1..ff3d737e2a 100644
--- a/libavcodec/mpeg12enc.c
+++ b/libavcodec/mpeg12enc.c
@@ -1246,7 +1246,8 @@ const FFCodec ff_mpeg1video_encoder = {
     .p.supported_framerates = ff_mpeg12_frame_rate_tab + 1,
     .p.pix_fmts           = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
                                                            AV_PIX_FMT_NONE },
-    .p.capabilities       = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities       = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
+                            AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal        = FF_CODEC_CAP_INIT_CLEANUP,
     .p.priv_class         = &mpeg1_class,
 };
@@ -1264,7 +1265,8 @@ const FFCodec ff_mpeg2video_encoder = {
     .p.pix_fmts           = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P,
                                                            AV_PIX_FMT_YUV422P,
                                                            AV_PIX_FMT_NONE },
-    .p.capabilities       = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities       = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
+                            AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal        = FF_CODEC_CAP_INIT_CLEANUP,
     .p.priv_class         = &mpeg2_class,
 };
diff --git a/libavcodec/mpeg4videoenc.c b/libavcodec/mpeg4videoenc.c
index a2a14afbd0..f7d48490f9 100644
--- a/libavcodec/mpeg4videoenc.c
+++ b/libavcodec/mpeg4videoenc.c
@@ -1403,7 +1403,8 @@ const FFCodec ff_mpeg4_encoder = {
     FF_CODEC_ENCODE_CB(ff_mpv_encode_picture),
     .close          = ff_mpv_encode_end,
     .p.pix_fmts     = (const enum AVPixelFormat[]) { AV_PIX_FMT_YUV420P, AV_PIX_FMT_NONE },
-    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS,
+    .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_SLICE_THREADS |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
     .p.priv_class   = &mpeg4enc_class,
 };
diff --git a/libavcodec/mpegvideo_enc.c b/libavcodec/mpegvideo_enc.c
index 9b11c5c05a..e77d5bcd57 100644
--- a/libavcodec/mpegvideo_enc.c
+++ b/libavcodec/mpegvideo_enc.c
@@ -1952,6 +1952,7 @@ vbv_retry:
         s->total_bits     += s->frame_bits;
 
         pkt->pts = s->current_picture.f->pts;
+        pkt->duration = s->current_picture.f->duration;
         if (!s->low_delay && s->pict_type != AV_PICTURE_TYPE_B) {
             if (!s->current_picture.f->coded_picture_number)
                 pkt->dts = pkt->pts - s->dts_delta;
@@ -1960,6 +1961,14 @@ vbv_retry:
             s->reordered_pts = pkt->pts;
         } else
             pkt->dts = pkt->pts;
+
+        // the no-delay case is handled in generic code
+        if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY) {
+            ret = ff_encode_reordered_opaque(avctx, pkt, s->current_picture.f);
+            if (ret < 0)
+                return ret;
+        }
+
         if (s->current_picture.f->key_frame)
             pkt->flags |= AV_PKT_FLAG_KEY;
         if (s->mb_info)
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 14/19] lavc/vaapi_encode*: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (11 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 13/19] lavc/mpegvideo_enc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 15/19] lavc/libwebpenc_animencoder: stop setting dts unnecessarily Anton Khirnov
                   ` (6 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

Except for the mjpeg_vaapi encoder, which is already handled
generically.
---
 libavcodec/vaapi_encode.c       | 8 ++++++++
 libavcodec/vaapi_encode_h264.c  | 2 +-
 libavcodec/vaapi_encode_h265.c  | 2 +-
 libavcodec/vaapi_encode_mpeg2.c | 2 +-
 libavcodec/vaapi_encode_vp8.c   | 2 +-
 libavcodec/vaapi_encode_vp9.c   | 2 +-
 6 files changed, 13 insertions(+), 5 deletions(-)

diff --git a/libavcodec/vaapi_encode.c b/libavcodec/vaapi_encode.c
index 9a58661b51..6787b90e8d 100644
--- a/libavcodec/vaapi_encode.c
+++ b/libavcodec/vaapi_encode.c
@@ -695,6 +695,7 @@ static int vaapi_encode_output(AVCodecContext *avctx,
         pkt->flags |= AV_PKT_FLAG_KEY;
 
     pkt->pts = pic->pts;
+    pkt->duration = pic->input_image->duration;
 
     vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
     if (vas != VA_STATUS_SUCCESS) {
@@ -704,6 +705,13 @@ static int vaapi_encode_output(AVCodecContext *avctx,
         goto fail;
     }
 
+    // for no-delay encoders this is handled in generic codec
+    if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY) {
+        err = ff_encode_reordered_opaque(avctx, pkt, pic->input_image);
+        if (err < 0)
+            goto fail;
+    }
+
     av_buffer_unref(&pic->output_buffer_ref);
     pic->output_buffer = VA_INVALID_ID;
 
diff --git a/libavcodec/vaapi_encode_h264.c b/libavcodec/vaapi_encode_h264.c
index f15bcc6ea8..0fe3905666 100644
--- a/libavcodec/vaapi_encode_h264.c
+++ b/libavcodec/vaapi_encode_h264.c
@@ -1361,7 +1361,7 @@ const FFCodec ff_h264_vaapi_encoder = {
     .close          = &vaapi_encode_h264_close,
     .p.priv_class   = &vaapi_encode_h264_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .defaults       = vaapi_encode_h264_defaults,
diff --git a/libavcodec/vaapi_encode_h265.c b/libavcodec/vaapi_encode_h265.c
index 946f2e7640..aa7e532f9a 100644
--- a/libavcodec/vaapi_encode_h265.c
+++ b/libavcodec/vaapi_encode_h265.c
@@ -1487,7 +1487,7 @@ const FFCodec ff_hevc_vaapi_encoder = {
     .close          = &vaapi_encode_h265_close,
     .p.priv_class   = &vaapi_encode_h265_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .defaults       = vaapi_encode_h265_defaults,
diff --git a/libavcodec/vaapi_encode_mpeg2.c b/libavcodec/vaapi_encode_mpeg2.c
index 38e1d83f68..9261d19a83 100644
--- a/libavcodec/vaapi_encode_mpeg2.c
+++ b/libavcodec/vaapi_encode_mpeg2.c
@@ -698,7 +698,7 @@ const FFCodec ff_mpeg2_vaapi_encoder = {
     .close          = &vaapi_encode_mpeg2_close,
     .p.priv_class   = &vaapi_encode_mpeg2_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .defaults       = vaapi_encode_mpeg2_defaults,
diff --git a/libavcodec/vaapi_encode_vp8.c b/libavcodec/vaapi_encode_vp8.c
index 93e543d798..ae6a8d313c 100644
--- a/libavcodec/vaapi_encode_vp8.c
+++ b/libavcodec/vaapi_encode_vp8.c
@@ -253,7 +253,7 @@ const FFCodec ff_vp8_vaapi_encoder = {
     .close          = &ff_vaapi_encode_close,
     .p.priv_class   = &vaapi_encode_vp8_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .defaults       = vaapi_encode_vp8_defaults,
diff --git a/libavcodec/vaapi_encode_vp9.c b/libavcodec/vaapi_encode_vp9.c
index b4c5588730..af1353cea8 100644
--- a/libavcodec/vaapi_encode_vp9.c
+++ b/libavcodec/vaapi_encode_vp9.c
@@ -308,7 +308,7 @@ const FFCodec ff_vp9_vaapi_encoder = {
     .close          = &ff_vaapi_encode_close,
     .p.priv_class   = &vaapi_encode_vp9_class,
     .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
-                      AV_CODEC_CAP_DR1,
+                      AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .caps_internal  = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
                       FF_CODEC_CAP_INIT_CLEANUP,
     .defaults       = vaapi_encode_vp9_defaults,
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 15/19] lavc/libwebpenc_animencoder: stop setting dts unnecessarily
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (12 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 14/19] lavc/vaapi_encode*: " Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 16/19] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
                   ` (5 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

WebP does not have reordering, so dts=pts is set by the generic code.
---
 libavcodec/libwebpenc_animencoder.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c
index 0f2c190c8c..977f880d6c 100644
--- a/libavcodec/libwebpenc_animencoder.c
+++ b/libavcodec/libwebpenc_animencoder.c
@@ -77,7 +77,7 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                 memcpy(pkt->data, assembled_data.bytes, assembled_data.size);
                 WebPDataClear(&assembled_data);
                 s->done = 1;
-                pkt->pts = pkt->dts = s->first_frame_pts;
+                pkt->pts = s->first_frame_pts;
                 *got_packet = 1;
                 return 0;
             } else {
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 16/19] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (13 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 15/19] lavc/libwebpenc_animencoder: stop setting dts unnecessarily Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 20:51   ` Michael Niedermayer
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 17/19] lavc/libx264: pass through frame durations to encoded packets Anton Khirnov
                   ` (4 subsequent siblings)
  19 siblings, 1 reply; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/libwebpenc_animencoder.c | 35 +++++++++++++++++++++++++++--
 1 file changed, 33 insertions(+), 2 deletions(-)

diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c
index 977f880d6c..617ceb3186 100644
--- a/libavcodec/libwebpenc_animencoder.c
+++ b/libavcodec/libwebpenc_animencoder.c
@@ -24,6 +24,8 @@
  * WebP encoder using libwebp (WebPAnimEncoder API)
  */
 
+#include "libavutil/buffer.h"
+
 #include "config.h"
 #include "codec_internal.h"
 #include "encode.h"
@@ -35,6 +37,11 @@ typedef struct LibWebPAnimContext {
     LibWebPContextCommon cc;
     WebPAnimEncoder *enc;     // the main AnimEncoder object
     int64_t first_frame_pts;  // pts of the first encoded frame.
+
+    int64_t         reordered_opaque;
+    void           *first_frame_opaque;
+    AVBufferRef    *first_frame_opaque_ref;
+
     int done;                 // If true, we have assembled the bitstream already
 } LibWebPAnimContext;
 
@@ -78,6 +85,17 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                 WebPDataClear(&assembled_data);
                 s->done = 1;
                 pkt->pts = s->first_frame_pts;
+
+                if (pkt->pts != AV_NOPTS_VALUE && frame->pts != AV_NOPTS_VALUE)
+                    pkt->duration = frame->pts + frame->duration - pkt->pts;
+
+                avctx->reordered_opaque = s->reordered_opaque;
+                if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+                    pkt->opaque               = s->first_frame_opaque;
+                    pkt->opaque_ref           = s->first_frame_opaque_ref;
+                    s->first_frame_opaque_ref = NULL;
+                }
+
                 *got_packet = 1;
                 return 0;
             } else {
@@ -107,8 +125,18 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
             goto end;
         }
 
-        if (!avctx->frame_number)
+        if (!avctx->frame_number) {
             s->first_frame_pts = frame->pts;
+            s->reordered_opaque = frame->reordered_opaque;
+
+            if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+                s->first_frame_opaque = frame->opaque;
+                ret = av_buffer_replace(&s->first_frame_opaque_ref, frame->opaque_ref);
+                if (ret < 0)
+                    goto end;
+            }
+        }
+
         ret = 0;
         *got_packet = 0;
 
@@ -126,6 +154,8 @@ static int libwebp_anim_encode_close(AVCodecContext *avctx)
     av_frame_free(&s->cc.ref);
     WebPAnimEncoderDelete(s->enc);
 
+    av_buffer_unref(&s->first_frame_opaque_ref);
+
     return 0;
 }
 
@@ -134,7 +164,8 @@ const FFCodec ff_libwebp_anim_encoder = {
     CODEC_LONG_NAME("libwebp WebP image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WEBP,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = ff_libwebpenc_pix_fmts,
     .p.priv_class   = &ff_libwebpenc_class,
     .p.wrapper_name = "libwebp",
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 17/19] lavc/libx264: pass through frame durations to encoded packets
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (14 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 16/19] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 18/19] lavc/libx265: " Anton Khirnov
                   ` (3 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/libx264.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavcodec/libx264.c b/libavcodec/libx264.c
index 6d22a1726e..2742fb11a0 100644
--- a/libavcodec/libx264.c
+++ b/libavcodec/libx264.c
@@ -52,6 +52,7 @@
 typedef struct X264Opaque {
     int64_t reordered_opaque;
     int64_t wallclock;
+    int64_t duration;
 
     void        *frame_opaque;
     AVBufferRef *frame_opaque_ref;
@@ -459,6 +460,7 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame,
     }
 
     opaque->reordered_opaque = frame->reordered_opaque;
+    opaque->duration         = frame->duration;
     opaque->wallclock = wallclock;
     if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT)
         opaque->wallclock = av_gettime();
@@ -612,6 +614,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
         out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) {
         ctx->reordered_opaque = out_opaque->reordered_opaque;
         wallclock = out_opaque->wallclock;
+        pkt->duration = out_opaque->duration;
 
         if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
             pkt->opaque                  = out_opaque->frame_opaque;
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 18/19] lavc/libx265: pass through frame durations to encoded packets
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (15 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 17/19] lavc/libx264: pass through frame durations to encoded packets Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 19/19] lavc/libaomenc: " Anton Khirnov
                   ` (2 subsequent siblings)
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/libx265.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index a71f1f76d3..6fc189f1b5 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -43,6 +43,7 @@
 
 typedef struct ReorderedData {
     int64_t reordered_opaque;
+    int64_t duration;
 
     void        *frame_opaque;
     AVBufferRef *frame_opaque_ref;
@@ -616,6 +617,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         }
         rd = &ctx->rd[rd_idx];
 
+        rd->duration         = pic->duration;
         rd->reordered_opaque = pic->reordered_opaque;
         if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
             rd->frame_opaque = pic->opaque;
@@ -755,6 +757,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
         ReorderedData *rd = &ctx->rd[idx];
 
         avctx->reordered_opaque = rd->reordered_opaque;
+        pkt->duration           = rd->duration;
 
         if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
             pkt->opaque          = rd->frame_opaque;
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH 19/19] lavc/libaomenc: pass through frame durations to encoded packets
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (16 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 18/19] lavc/libx265: " Anton Khirnov
@ 2023-01-25 16:55 ` Anton Khirnov
  2023-01-28 11:11 ` [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
  2023-01-28 11:37 ` Marvin Scholz
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-25 16:55 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/libaomenc.c | 14 ++++++++++++--
 1 file changed, 12 insertions(+), 2 deletions(-)

diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index bd576fdd3a..0b88102c77 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -23,6 +23,8 @@
  * AV1 encoder support via libaom
  */
 
+#include <limits.h>
+
 #define AOM_DISABLE_CTRL_TYPECHECKS 1
 #include <aom/aom_encoder.h>
 #include <aom/aomcx.h>
@@ -1094,6 +1096,7 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
     }
     memcpy(pkt->data, cx_frame->buf, pkt->size);
     pkt->pts = pkt->dts = cx_frame->pts;
+    pkt->duration = cx_frame->duration;
 
     if (!!(cx_frame->flags & AOM_FRAME_IS_KEY)) {
         pkt->flags |= AV_PKT_FLAG_KEY;
@@ -1275,6 +1278,7 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
     AOMContext *ctx = avctx->priv_data;
     struct aom_image *rawimg = NULL;
     int64_t timestamp = 0;
+    unsigned long duration = 0;
     int res, coded_size;
     aom_enc_frame_flags_t flags = 0;
 
@@ -1287,6 +1291,13 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
         rawimg->stride[AOM_PLANE_U] = frame->linesize[1];
         rawimg->stride[AOM_PLANE_V] = frame->linesize[2];
         timestamp                   = frame->pts;
+
+        if (frame->duration > ULONG_MAX) {
+            av_log(avctx, AV_LOG_WARNING,
+                   "Frame duration too large: %"PRId64"\n", frame->duration);
+        } else
+            duration = frame->duration ? frame->duration : avctx->ticks_per_frame;
+
         switch (frame->color_range) {
         case AVCOL_RANGE_MPEG:
             rawimg->range = AOM_CR_STUDIO_RANGE;
@@ -1300,8 +1311,7 @@ static int aom_encode(AVCodecContext *avctx, AVPacket *pkt,
             flags |= AOM_EFLAG_FORCE_KF;
     }
 
-    res = aom_codec_encode(&ctx->encoder, rawimg, timestamp,
-                           avctx->ticks_per_frame, flags);
+    res = aom_codec_encode(&ctx->encoder, rawimg, timestamp, duration, flags);
     if (res != AOM_CODEC_OK) {
         log_encoder_error(avctx, "Error encoding frame");
         return AVERROR_INVALIDDATA;
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FFmpeg-devel] [PATCH 16/19] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 16/19] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
@ 2023-01-25 20:51   ` Michael Niedermayer
  2023-01-26  9:45     ` [FFmpeg-devel] [PATCH] " Anton Khirnov
  0 siblings, 1 reply; 26+ messages in thread
From: Michael Niedermayer @ 2023-01-25 20:51 UTC (permalink / raw)
  To: FFmpeg development discussions and patches


[-- Attachment #1.1: Type: text/plain, Size: 1074 bytes --]

On Wed, Jan 25, 2023 at 05:55:34PM +0100, Anton Khirnov wrote:
> ---
>  libavcodec/libwebpenc_animencoder.c | 35 +++++++++++++++++++++++++++--
>  1 file changed, 33 insertions(+), 2 deletions(-)

breaks:
ffmpeg  -i lena.pnm -bitexact -y /tmp/file.webp
...
[libwebp_anim @ 0x2d19bdc0] Using libwebp for RGB-to-YUV conversion. You may want to consider passing in YUV instead for lossy encoding.
==11922== Invalid read of size 8
==11922==    at 0x99F606: libwebp_anim_encode_frame (in ffmpeg_g)
==11922==    by 0x86EA44: ff_encode_encode_cb (in ffmpeg_g)
==11922==    by 0x86EE59: encode_receive_packet_internal (in ffmpeg_g)
==11922==    by 0x86F04F: avcodec_send_frame (in ffmpeg_g)
==11922==    by 0x30EDB2: encode_frame (in ffmpeg_g)
==11922==    by 0x3185A8: transcode (in ffmpeg_g)
==11922==    by 0x2EDD63: main (in ffmpeg_g)
==11922==  Address 0x88 is not stack'd, malloc'd or (recently) free'd


[...]
-- 
Michael     GnuPG fingerprint: 9FF2128B147EF6730BADF133611EC787040B0FAB

Avoid a single point of failure, be that a person or equipment.

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 195 bytes --]

[-- Attachment #2: Type: text/plain, Size: 251 bytes --]

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
  2023-01-25 20:51   ` Michael Niedermayer
@ 2023-01-26  9:45     ` Anton Khirnov
  0 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-26  9:45 UTC (permalink / raw)
  To: ffmpeg-devel

---
 libavcodec/libwebpenc_animencoder.c | 39 +++++++++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/libavcodec/libwebpenc_animencoder.c b/libavcodec/libwebpenc_animencoder.c
index 977f880d6c..440cae1de5 100644
--- a/libavcodec/libwebpenc_animencoder.c
+++ b/libavcodec/libwebpenc_animencoder.c
@@ -24,6 +24,8 @@
  * WebP encoder using libwebp (WebPAnimEncoder API)
  */
 
+#include "libavutil/buffer.h"
+
 #include "config.h"
 #include "codec_internal.h"
 #include "encode.h"
@@ -35,6 +37,12 @@ typedef struct LibWebPAnimContext {
     LibWebPContextCommon cc;
     WebPAnimEncoder *enc;     // the main AnimEncoder object
     int64_t first_frame_pts;  // pts of the first encoded frame.
+    int64_t end_pts;          // pts + duration of the last frame
+
+    int64_t         reordered_opaque;
+    void           *first_frame_opaque;
+    AVBufferRef    *first_frame_opaque_ref;
+
     int done;                 // If true, we have assembled the bitstream already
 } LibWebPAnimContext;
 
@@ -78,6 +86,17 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
                 WebPDataClear(&assembled_data);
                 s->done = 1;
                 pkt->pts = s->first_frame_pts;
+
+                if (pkt->pts != AV_NOPTS_VALUE && s->end_pts > pkt->pts)
+                    pkt->duration = s->end_pts - pkt->pts;
+
+                avctx->reordered_opaque = s->reordered_opaque;
+                if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+                    pkt->opaque               = s->first_frame_opaque;
+                    pkt->opaque_ref           = s->first_frame_opaque_ref;
+                    s->first_frame_opaque_ref = NULL;
+                }
+
                 *got_packet = 1;
                 return 0;
             } else {
@@ -107,8 +126,21 @@ static int libwebp_anim_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
             goto end;
         }
 
-        if (!avctx->frame_number)
+        if (!avctx->frame_number) {
             s->first_frame_pts = frame->pts;
+            s->reordered_opaque = frame->reordered_opaque;
+
+            if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
+                s->first_frame_opaque = frame->opaque;
+                ret = av_buffer_replace(&s->first_frame_opaque_ref, frame->opaque_ref);
+                if (ret < 0)
+                    goto end;
+            }
+        }
+
+        if (frame->pts != AV_NOPTS_VALUE)
+            s->end_pts = frame->pts + frame->duration;
+
         ret = 0;
         *got_packet = 0;
 
@@ -126,6 +158,8 @@ static int libwebp_anim_encode_close(AVCodecContext *avctx)
     av_frame_free(&s->cc.ref);
     WebPAnimEncoderDelete(s->enc);
 
+    av_buffer_unref(&s->first_frame_opaque_ref);
+
     return 0;
 }
 
@@ -134,7 +168,8 @@ const FFCodec ff_libwebp_anim_encoder = {
     CODEC_LONG_NAME("libwebp WebP image"),
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_WEBP,
-    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY,
+    .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.pix_fmts     = ff_libwebpenc_pix_fmts,
     .p.priv_class   = &ff_libwebpenc_class,
     .p.wrapper_name = "libwebp",
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (17 preceding siblings ...)
  2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 19/19] lavc/libaomenc: " Anton Khirnov
@ 2023-01-28 11:11 ` Anton Khirnov
  2023-01-28 11:37 ` Marvin Scholz
  19 siblings, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-28 11:11 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Will push the set tomorrow if nobody has further comments.

-- 
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy
  2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
                   ` (18 preceding siblings ...)
  2023-01-28 11:11 ` [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
@ 2023-01-28 11:37 ` Marvin Scholz
  2023-01-28 13:23   ` Anton Khirnov
  2023-01-28 13:45   ` [FFmpeg-devel] [PATCH] " Anton Khirnov
  19 siblings, 2 replies; 26+ messages in thread
From: Marvin Scholz @ 2023-01-28 11:37 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On 25 Jan 2023, at 17:55, Anton Khirnov wrote:

> Change return value descriptions into proper lists.
> ---
>  libavcodec/avcodec.h | 81 +++++++++++++++++++++++---------------------
>  1 file changed, 42 insertions(+), 39 deletions(-)
>
> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> index 0ac581d660..f3ca41f126 100644
> --- a/libavcodec/avcodec.h
> +++ b/libavcodec/avcodec.h
> @@ -2605,17 +2605,18 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
>   *                  still has frames buffered, it will return them after sending
>   *                  a flush packet.
>   *
> - * @return 0 on success, otherwise negative error code:
> - *      AVERROR(EAGAIN):   input is not accepted in the current state - user
> - *                         must read output with avcodec_receive_frame() (once
> - *                         all output is read, the packet should be resent, and
> - *                         the call will not fail with EAGAIN).
> - *      AVERROR_EOF:       the decoder has been flushed, and no new packets can
> - *                         be sent to it (also returned if more than 1 flush
> - *                         packet is sent)
> - *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
> - *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
> - *      other errors: legitimate decoding errors
> + * @return
> + * - 0:                 success
> + * - AVERROR(EAGAIN):   input is not accepted in the current state - user must
> + *                      read output with avcodec_receive_frame() (once all
> + *                      output is read, the packet should be resent, and the
> + *                      call will not fail with EAGAIN).
> + * - AVERROR_EOF:       the decoder has been flushed, and no new packets can be
> + *                      sent to it (also returned if more than 1 flush packet is
> + *                      sent)
> + * - AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
> + * - AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
> + * - other errors:      legitimate decoding errors
>   */

Wouldn't @retval work better for such return value documentation?

>  int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
>
> @@ -2630,17 +2631,17 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
>   *              av_frame_unref(frame) before doing anything else.
>   *
>   * @return
> - *      0:                 success, a frame was returned
> - *      AVERROR(EAGAIN):   output is not available in this state - user must try
> - *                         to send new input
> - *      AVERROR_EOF:       the codec has been fully flushed, and there will be
> - *                         no more output frames
> - *      AVERROR(EINVAL):   codec not opened, or it is an encoder without
> - *                         the AV_CODEC_FLAG_RECON_FRAME flag enabled
> - *      AVERROR_INPUT_CHANGED:   current decoded frame has changed parameters
> - *                               with respect to first decoded frame. Applicable
> - *                               when flag AV_CODEC_FLAG_DROPCHANGED is set.
> - *      other negative values: legitimate decoding errors
> + * - 0:                     success, a frame was returned
> + * - AVERROR(EAGAIN):       output is not available in this state - user must
> + *                          try to send new input
> + * - AVERROR_EOF:           the codec has been fully flushed, and there will be
> + *                          no more output frames
> + * - AVERROR(EINVAL):       codec not opened, or it is an encoder without the
> + *                          AV_CODEC_FLAG_RECON_FRAME flag enabled
> + * - AVERROR_INPUT_CHANGED: current decoded frame has changed parameters with
> + *                          respect to first decoded frame. Applicable when flag
> + *                          AV_CODEC_FLAG_DROPCHANGED is set.
> + * - other negative values: legitimate decoding errors
>   */
>  int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
>
> @@ -2667,16 +2668,17 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
>   *                  If it is not set, frame->nb_samples must be equal to
>   *                  avctx->frame_size for all frames except the last.
>   *                  The final frame may be smaller than avctx->frame_size.
> - * @return 0 on success, otherwise negative error code:
> - *      AVERROR(EAGAIN):   input is not accepted in the current state - user
> - *                         must read output with avcodec_receive_packet() (once
> - *                         all output is read, the packet should be resent, and
> - *                         the call will not fail with EAGAIN).
> - *      AVERROR_EOF:       the encoder has been flushed, and no new frames can
> - *                         be sent to it
> - *      AVERROR(EINVAL):   codec not opened, it is a decoder, or requires flush
> - *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
> - *      other errors: legitimate encoding errors
> + * @return
> + * - 0:                 success
> + * - AVERROR(EAGAIN):   input is not accepted in the current state - user must
> + *                      read output with avcodec_receive_packet() (once all
> + *                      output is read, the packet should be resent, and the
> + *                      call will not fail with EAGAIN).
> + * - AVERROR_EOF:       the encoder has been flushed, and no new frames can
> + *                      be sent to it
> + * - AVERROR(EINVAL):   codec not opened, it is a decoder, or requires flush
> + * - AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
> + * - other errors:      legitimate encoding errors
>   */
>  int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
>
> @@ -2687,13 +2689,14 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
>   * @param avpkt This will be set to a reference-counted packet allocated by the
>   *              encoder. Note that the function will always call
>   *              av_packet_unref(avpkt) before doing anything else.
> - * @return 0 on success, otherwise negative error code:
> - *      AVERROR(EAGAIN):   output is not available in the current state - user
> - *                         must try to send input
> - *      AVERROR_EOF:       the encoder has been fully flushed, and there will be
> - *                         no more output packets
> - *      AVERROR(EINVAL):   codec not opened, or it is a decoder
> - *      other errors: legitimate encoding errors
> + * @return
> + * - 0:                 success
> + * - AVERROR(EAGAIN):   output is not available in the current state - user must
> + *                      try to send input
> + * - AVERROR_EOF:       the encoder has been fully flushed, and there will be no
> + *                      more output packets
> + * - AVERROR(EINVAL):   codec not opened, or it is a decoder
> + * - other errors:      legitimate encoding errors
>   */
>  int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
>
> -- 
> 2.35.1
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy
  2023-01-28 11:37 ` Marvin Scholz
@ 2023-01-28 13:23   ` Anton Khirnov
  2023-01-28 14:47     ` Marvin Scholz
  2023-01-28 13:45   ` [FFmpeg-devel] [PATCH] " Anton Khirnov
  1 sibling, 1 reply; 26+ messages in thread
From: Anton Khirnov @ 2023-01-28 13:23 UTC (permalink / raw)
  To: FFmpeg development discussions and patches

Quoting Marvin Scholz (2023-01-28 12:37:42)
> 
> 
> On 25 Jan 2023, at 17:55, Anton Khirnov wrote:
> 
> > Change return value descriptions into proper lists.
> > ---
> >  libavcodec/avcodec.h | 81 +++++++++++++++++++++++---------------------
> >  1 file changed, 42 insertions(+), 39 deletions(-)
> >
> > diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
> > index 0ac581d660..f3ca41f126 100644
> > --- a/libavcodec/avcodec.h
> > +++ b/libavcodec/avcodec.h
> > @@ -2605,17 +2605,18 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
> >   *                  still has frames buffered, it will return them after sending
> >   *                  a flush packet.
> >   *
> > - * @return 0 on success, otherwise negative error code:
> > - *      AVERROR(EAGAIN):   input is not accepted in the current state - user
> > - *                         must read output with avcodec_receive_frame() (once
> > - *                         all output is read, the packet should be resent, and
> > - *                         the call will not fail with EAGAIN).
> > - *      AVERROR_EOF:       the decoder has been flushed, and no new packets can
> > - *                         be sent to it (also returned if more than 1 flush
> > - *                         packet is sent)
> > - *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
> > - *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
> > - *      other errors: legitimate decoding errors
> > + * @return
> > + * - 0:                 success
> > + * - AVERROR(EAGAIN):   input is not accepted in the current state - user must
> > + *                      read output with avcodec_receive_frame() (once all
> > + *                      output is read, the packet should be resent, and the
> > + *                      call will not fail with EAGAIN).
> > + * - AVERROR_EOF:       the decoder has been flushed, and no new packets can be
> > + *                      sent to it (also returned if more than 1 flush packet is
> > + *                      sent)
> > + * - AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
> > + * - AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
> > + * - other errors:      legitimate decoding errors
> >   */
> 
> Wouldn't @retval work better for such return value documentation?

I don't know, how is it better?

-- 
Anton Khirnov
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* [FFmpeg-devel] [PATCH] lavc/avcodec: improve enc/dec API doxy
  2023-01-28 11:37 ` Marvin Scholz
  2023-01-28 13:23   ` Anton Khirnov
@ 2023-01-28 13:45   ` Anton Khirnov
  1 sibling, 0 replies; 26+ messages in thread
From: Anton Khirnov @ 2023-01-28 13:45 UTC (permalink / raw)
  To: ffmpeg-devel

Change return value descriptions into proper lists.
---
 libavcodec/avcodec.h | 79 ++++++++++++++++++++++----------------------
 1 file changed, 39 insertions(+), 40 deletions(-)

diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
index 0ac581d660..ad6377e8d8 100644
--- a/libavcodec/avcodec.h
+++ b/libavcodec/avcodec.h
@@ -2605,17 +2605,17 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
  *                  still has frames buffered, it will return them after sending
  *                  a flush packet.
  *
- * @return 0 on success, otherwise negative error code:
- *      AVERROR(EAGAIN):   input is not accepted in the current state - user
- *                         must read output with avcodec_receive_frame() (once
- *                         all output is read, the packet should be resent, and
- *                         the call will not fail with EAGAIN).
- *      AVERROR_EOF:       the decoder has been flushed, and no new packets can
- *                         be sent to it (also returned if more than 1 flush
- *                         packet is sent)
- *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
- *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
- *      other errors: legitimate decoding errors
+ * @retval 0                 success
+ * @retval AVERROR(EAGAIN)   input is not accepted in the current state - user
+ *                           must read output with avcodec_receive_frame() (once
+ *                           all output is read, the packet should be resent,
+ *                           and the call will not fail with EAGAIN).
+ * @retval AVERROR_EOF       the decoder has been flushed, and no new packets can be
+ *                           sent to it (also returned if more than 1 flush
+ *                           packet is sent)
+ * @retval AVERROR(EINVAL)   codec not opened, it is an encoder, or requires flush
+ * @retval AVERROR(ENOMEM)   failed to add packet to internal queue, or similar
+ * @retval "another negative error code" legitimate decoding errors
  */
 int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
 
@@ -2629,18 +2629,17 @@ int avcodec_send_packet(AVCodecContext *avctx, const AVPacket *avpkt);
  *              codec. Note that the function will always call
  *              av_frame_unref(frame) before doing anything else.
  *
- * @return
- *      0:                 success, a frame was returned
- *      AVERROR(EAGAIN):   output is not available in this state - user must try
- *                         to send new input
- *      AVERROR_EOF:       the codec has been fully flushed, and there will be
- *                         no more output frames
- *      AVERROR(EINVAL):   codec not opened, or it is an encoder without
- *                         the AV_CODEC_FLAG_RECON_FRAME flag enabled
- *      AVERROR_INPUT_CHANGED:   current decoded frame has changed parameters
- *                               with respect to first decoded frame. Applicable
- *                               when flag AV_CODEC_FLAG_DROPCHANGED is set.
- *      other negative values: legitimate decoding errors
+ * @retval 0                success, a frame was returned
+ * @retval AVERROR(EAGAIN)  output is not available in this state - user must
+ *                          try to send new input
+ * @retval AVERROR_EOF      the codec has been fully flushed, and there will be
+ *                          no more output frames
+ * @retval AVERROR(EINVAL)  codec not opened, or it is an encoder without the
+ *                          AV_CODEC_FLAG_RECON_FRAME flag enabled
+ * @retval AVERROR_INPUT_CHANGED current decoded frame has changed parameters with
+ *                          respect to first decoded frame. Applicable when flag
+ *                          AV_CODEC_FLAG_DROPCHANGED is set.
+ * @retval "other negative error code" legitimate decoding errors
  */
 int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
 
@@ -2667,16 +2666,16 @@ int avcodec_receive_frame(AVCodecContext *avctx, AVFrame *frame);
  *                  If it is not set, frame->nb_samples must be equal to
  *                  avctx->frame_size for all frames except the last.
  *                  The final frame may be smaller than avctx->frame_size.
- * @return 0 on success, otherwise negative error code:
- *      AVERROR(EAGAIN):   input is not accepted in the current state - user
- *                         must read output with avcodec_receive_packet() (once
- *                         all output is read, the packet should be resent, and
- *                         the call will not fail with EAGAIN).
- *      AVERROR_EOF:       the encoder has been flushed, and no new frames can
- *                         be sent to it
- *      AVERROR(EINVAL):   codec not opened, it is a decoder, or requires flush
- *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
- *      other errors: legitimate encoding errors
+ * @retval 0                 success
+ * @retval AVERROR(EAGAIN)   input is not accepted in the current state - user must
+ *                           read output with avcodec_receive_packet() (once all
+ *                           output is read, the packet should be resent, and the
+ *                           call will not fail with EAGAIN).
+ * @retval AVERROR_EOF       the encoder has been flushed, and no new frames can
+ *                           be sent to it
+ * @retval AVERROR(EINVAL)   codec not opened, it is a decoder, or requires flush
+ * @retval AVERROR(ENOMEM)   failed to add packet to internal queue, or similar
+ * @retval "another negative error code" legitimate encoding errors
  */
 int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
 
@@ -2687,13 +2686,13 @@ int avcodec_send_frame(AVCodecContext *avctx, const AVFrame *frame);
  * @param avpkt This will be set to a reference-counted packet allocated by the
  *              encoder. Note that the function will always call
  *              av_packet_unref(avpkt) before doing anything else.
- * @return 0 on success, otherwise negative error code:
- *      AVERROR(EAGAIN):   output is not available in the current state - user
- *                         must try to send input
- *      AVERROR_EOF:       the encoder has been fully flushed, and there will be
- *                         no more output packets
- *      AVERROR(EINVAL):   codec not opened, or it is a decoder
- *      other errors: legitimate encoding errors
+ * @retval 0               success
+ * @retval AVERROR(EAGAIN) output is not available in the current state - user must
+ *                         try to send input
+ * @retval AVERROR_EOF     the encoder has been fully flushed, and there will be no
+ *                         more output packets
+ * @retval AVERROR(EINVAL) codec not opened, or it is a decoder
+ * @retval "another negative error code" legitimate encoding errors
  */
 int avcodec_receive_packet(AVCodecContext *avctx, AVPacket *avpkt);
 
-- 
2.35.1

_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

* Re: [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy
  2023-01-28 13:23   ` Anton Khirnov
@ 2023-01-28 14:47     ` Marvin Scholz
  0 siblings, 0 replies; 26+ messages in thread
From: Marvin Scholz @ 2023-01-28 14:47 UTC (permalink / raw)
  To: FFmpeg development discussions and patches



On 28 Jan 2023, at 14:23, Anton Khirnov wrote:

> Quoting Marvin Scholz (2023-01-28 12:37:42)
>>
>>
>> On 25 Jan 2023, at 17:55, Anton Khirnov wrote:
>>
>>> Change return value descriptions into proper lists.
>>> ---
>>>  libavcodec/avcodec.h | 81 +++++++++++++++++++++++---------------------
>>>  1 file changed, 42 insertions(+), 39 deletions(-)
>>>
>>> diff --git a/libavcodec/avcodec.h b/libavcodec/avcodec.h
>>> index 0ac581d660..f3ca41f126 100644
>>> --- a/libavcodec/avcodec.h
>>> +++ b/libavcodec/avcodec.h
>>> @@ -2605,17 +2605,18 @@ int avcodec_decode_subtitle2(AVCodecContext *avctx, AVSubtitle *sub,
>>>   *                  still has frames buffered, it will return them after sending
>>>   *                  a flush packet.
>>>   *
>>> - * @return 0 on success, otherwise negative error code:
>>> - *      AVERROR(EAGAIN):   input is not accepted in the current state - user
>>> - *                         must read output with avcodec_receive_frame() (once
>>> - *                         all output is read, the packet should be resent, and
>>> - *                         the call will not fail with EAGAIN).
>>> - *      AVERROR_EOF:       the decoder has been flushed, and no new packets can
>>> - *                         be sent to it (also returned if more than 1 flush
>>> - *                         packet is sent)
>>> - *      AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
>>> - *      AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
>>> - *      other errors: legitimate decoding errors
>>> + * @return
>>> + * - 0:                 success
>>> + * - AVERROR(EAGAIN):   input is not accepted in the current state - user must
>>> + *                      read output with avcodec_receive_frame() (once all
>>> + *                      output is read, the packet should be resent, and the
>>> + *                      call will not fail with EAGAIN).
>>> + * - AVERROR_EOF:       the decoder has been flushed, and no new packets can be
>>> + *                      sent to it (also returned if more than 1 flush packet is
>>> + *                      sent)
>>> + * - AVERROR(EINVAL):   codec not opened, it is an encoder, or requires flush
>>> + * - AVERROR(ENOMEM):   failed to add packet to internal queue, or similar
>>> + * - other errors:      legitimate decoding errors
>>>   */
>>
>> Wouldn't @retval work better for such return value documentation?
>
> I don't know, how is it better?
>

It should produce a more consistent output like in other places that use retval and is
semantically the more correct choice here.

Currently the documentation of possible return values is a bit all over the place with
some using lists, others just explain the values in a sentence, other places use retval.

IMO we should consistently try to use retval where it makes sense.

> -- 
> Anton Khirnov
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".

^ permalink raw reply	[flat|nested] 26+ messages in thread

end of thread, other threads:[~2023-01-28 14:47 UTC | newest]

Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-01-25 16:55 [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 02/19] lavc/avcodec: improve AV_CODEC_FLAG_RECON_FRAME doxy Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 03/19] lavc: add a private cap for fake-delay encoders Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 04/19] lavc: add a codec flag for propagating opaque from frames to packets Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 05/19] lavc: support AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE in all no-delay encoders Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 06/19] lavc/encode: pass through frame durations to encoded packets Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 07/19] lavc/librav1e: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 08/19] lavc/nvenc: " Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 09/19] lavc/pngenc: " Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 10/19] lavc/pngenc: stop setting dts unnecessarily for APNG Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 11/19] lavc/libtheoraenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 12/19] lavc/libtheoraenc: stop setting dts unnecessarily Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 13/19] lavc/mpegvideo_enc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 14/19] lavc/vaapi_encode*: " Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 15/19] lavc/libwebpenc_animencoder: stop setting dts unnecessarily Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 16/19] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE Anton Khirnov
2023-01-25 20:51   ` Michael Niedermayer
2023-01-26  9:45     ` [FFmpeg-devel] [PATCH] " Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 17/19] lavc/libx264: pass through frame durations to encoded packets Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 18/19] lavc/libx265: " Anton Khirnov
2023-01-25 16:55 ` [FFmpeg-devel] [PATCH 19/19] lavc/libaomenc: " Anton Khirnov
2023-01-28 11:11 ` [FFmpeg-devel] [PATCH 01/19] lavc/avcodec: improve enc/dec API doxy Anton Khirnov
2023-01-28 11:37 ` Marvin Scholz
2023-01-28 13:23   ` Anton Khirnov
2023-01-28 14:47     ` Marvin Scholz
2023-01-28 13:45   ` [FFmpeg-devel] [PATCH] " Anton Khirnov

Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel

This inbox may be cloned and mirrored by anyone:

	git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
		ffmpegdev@gitmailbox.com
	public-inbox-index ffmpegdev

Example config snippet for mirrors.


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git