Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
 help / color / mirror / Atom feed
From: Anton Khirnov <anton@khirnov.net>
To: ffmpeg-devel@ffmpeg.org
Subject: [FFmpeg-devel] [PATCH 5/8] lavc/libvpxenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
Date: Tue, 28 Feb 2023 13:01:01 +0100
Message-ID: <20230228120104.2347-5-anton@khirnov.net> (raw)
In-Reply-To: <20230228120104.2347-1-anton@khirnov.net>

---
 libavcodec/libvpxenc.c | 139 +++++++++++++++++++++++++++++------------
 libavcodec/version.h   |   2 +-
 2 files changed, 100 insertions(+), 41 deletions(-)

diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c
index 77921badba..af16e53deb 100644
--- a/libavcodec/libvpxenc.c
+++ b/libavcodec/libvpxenc.c
@@ -68,6 +68,14 @@ struct FrameListData {
 
 typedef struct FrameData {
     int64_t pts;
+    int64_t duration;
+
+#if FF_API_REORDERED_OPAQUE
+    int64_t      reordered_opaque;
+#endif
+    void        *frame_opaque;
+    AVBufferRef *frame_opaque_ref;
+
     AVBufferRef *hdr10_plus;
 } FrameData;
 
@@ -329,32 +337,101 @@ static av_cold void free_frame_list(struct FrameListData *list)
     }
 }
 
+static void frame_data_uninit(FrameData *fd)
+{
+    av_buffer_unref(&fd->frame_opaque_ref);
+    av_buffer_unref(&fd->hdr10_plus);
+}
+
 static av_cold void fifo_free(AVFifo **fifo)
 {
     FrameData fd;
     while (av_fifo_read(*fifo, &fd, 1) >= 0)
-        av_buffer_unref(&fd.hdr10_plus);
+        frame_data_uninit(&fd);
     av_fifo_freep2(fifo);
 }
 
-static int frame_data_apply(AVFifo *fifo, AVPacket *pkt)
+static int frame_data_submit(AVCodecContext *avctx, AVFifo *fifo,
+                             const AVFrame *frame)
+{
+    VPxContext *ctx = avctx->priv_data;
+    const struct vpx_codec_enc_cfg *enccfg = ctx->encoder.config.enc;
+
+    FrameData        fd = { .pts = frame->pts };
+
+    AVFrameSideData *av_uninit(sd);
+    int ret;
+
+#if CONFIG_LIBVPX_VP9_ENCODER
+    // Keep HDR10+ if it has bit depth higher than 8 and
+    // it has PQ trc (SMPTE2084).
+    sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS);
+    if (avctx->codec_id == AV_CODEC_ID_VP9 && sd &&
+        enccfg->g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) {
+        fd.hdr10_plus = av_buffer_ref(sd->buf);
+        if (!fd.hdr10_plus)
+            return AVERROR(ENOMEM);
+    }
+#endif
+
+    fd.duration     = frame->duration;
+    fd.frame_opaque = frame->opaque;
+    if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE && frame->opaque_ref) {
+        ret = av_buffer_replace(&fd.frame_opaque_ref, frame->opaque_ref);
+        if (ret < 0)
+            goto fail;
+    }
+#if FF_API_REORDERED_OPAQUE
+FF_DISABLE_DEPRECATION_WARNINGS
+    fd.reordered_opaque = frame->reordered_opaque;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    ret = av_fifo_write(fifo, &fd, 1);
+    if (ret < 0)
+        goto fail;
+
+    return 0;
+fail:
+    frame_data_uninit(&fd);
+    return ret;
+}
+
+static int frame_data_apply(AVCodecContext *avctx, AVFifo *fifo, AVPacket *pkt)
 {
     FrameData fd;
     uint8_t *data;
     if (!pkt || av_fifo_peek(fifo, &fd, 1, 0) < 0)
         return 0;
-    if (!fd.hdr10_plus || fd.pts != pkt->pts)
+    if (fd.pts != pkt->pts)
         return 0;
     av_fifo_drain2(fifo, 1);
 
-    data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size);
-    if (!data) {
+#if FF_API_REORDERED_OPAQUE
+FF_DISABLE_DEPRECATION_WARNINGS
+    avctx->reordered_opaque = fd.reordered_opaque;
+FF_ENABLE_DEPRECATION_WARNINGS
+#endif
+
+    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);
+
+    if (fd.hdr10_plus) {
+        data = av_packet_new_side_data(pkt, AV_PKT_DATA_DYNAMIC_HDR10_PLUS, fd.hdr10_plus->size);
+        if (!data) {
+            av_buffer_unref(&fd.hdr10_plus);
+            return AVERROR(ENOMEM);
+        }
+
+        memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size);
         av_buffer_unref(&fd.hdr10_plus);
-        return AVERROR(ENOMEM);
     }
 
-    memcpy(data, fd.hdr10_plus->data, fd.hdr10_plus->size);
-    av_buffer_unref(&fd.hdr10_plus);
     return 0;
 }
 
@@ -914,17 +991,14 @@ static av_cold int vpx_init(AVCodecContext *avctx,
         return AVERROR(EINVAL);
     }
 
+    ctx->fifo = av_fifo_alloc2(1, sizeof(FrameData), AV_FIFO_FLAG_AUTO_GROW);
+    if (!ctx->fifo)
+        return AVERROR(ENOMEM);
+
 #if CONFIG_LIBVPX_VP9_ENCODER
     if (avctx->codec_id == AV_CODEC_ID_VP9) {
         if (set_pix_fmt(avctx, codec_caps, &enccfg, &flags, &img_fmt))
             return AVERROR(EINVAL);
-        // Keep HDR10+ if it has bit depth higher than 8 and
-        // it has PQ trc (SMPTE2084).
-        if (enccfg.g_bit_depth > 8 && avctx->color_trc == AVCOL_TRC_SMPTE2084) {
-            ctx->fifo = av_fifo_alloc2(1, sizeof(FrameData), AV_FIFO_FLAG_AUTO_GROW);
-            if (!ctx->fifo)
-                return AVERROR(ENOMEM);
-        }
     }
 #endif
 
@@ -1285,11 +1359,9 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame,
         AV_WB64(side_data, 1);
         memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz);
     }
-    if (ctx->fifo) {
-        int err = frame_data_apply(ctx->fifo, pkt);
-        if (err < 0)
-            return err;
-    }
+    ret = frame_data_apply(avctx, ctx->fifo, pkt);
+    if (ret < 0)
+        return ret;
 
     return pkt->size;
 }
@@ -1703,24 +1775,9 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt,
             }
         }
 
-        if (ctx->fifo) {
-            AVFrameSideData *hdr10_plus_metadata;
-            // Add HDR10+ metadata to queue.
-            hdr10_plus_metadata = av_frame_get_side_data(frame, AV_FRAME_DATA_DYNAMIC_HDR_PLUS);
-            if (hdr10_plus_metadata) {
-                int err;
-                FrameData data;
-                data.pts = frame->pts;
-                data.hdr10_plus = av_buffer_ref(hdr10_plus_metadata->buf);
-                if (!data.hdr10_plus)
-                    return AVERROR(ENOMEM);
-                err = av_fifo_write(ctx->fifo, &data, 1);
-                if (err < 0) {
-                    av_buffer_unref(&data.hdr10_plus);
-                    return err;
-                }
-            }
-        }
+        res = frame_data_submit(avctx, ctx->fifo, frame);
+        if (res < 0)
+            return res;
     }
 
     // this is for encoding with preset temporal layering patterns defined in
@@ -1953,7 +2010,8 @@ const FFCodec ff_libvpx_vp8_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_VP8,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_OTHER_THREADS,
+                      AV_CODEC_CAP_OTHER_THREADS            |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .priv_data_size = sizeof(VPxContext),
     .init           = vp8_init,
     FF_CODEC_ENCODE_CB(vpx_encode),
@@ -1986,7 +2044,8 @@ FFCodec ff_libvpx_vp9_encoder = {
     .p.type         = AVMEDIA_TYPE_VIDEO,
     .p.id           = AV_CODEC_ID_VP9,
     .p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
-                      AV_CODEC_CAP_OTHER_THREADS,
+                      AV_CODEC_CAP_OTHER_THREADS            |
+                      AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
     .p.profiles     = NULL_IF_CONFIG_SMALL(ff_vp9_profiles),
     .p.priv_class   = &class_vp9,
     .p.wrapper_name = "libvpx",
diff --git a/libavcodec/version.h b/libavcodec/version.h
index 06631ffa8c..789d9047c2 100644
--- a/libavcodec/version.h
+++ b/libavcodec/version.h
@@ -30,7 +30,7 @@
 #include "version_major.h"
 
 #define LIBAVCODEC_VERSION_MINOR   4
-#define LIBAVCODEC_VERSION_MICRO 100
+#define LIBAVCODEC_VERSION_MICRO 101
 
 #define LIBAVCODEC_VERSION_INT  AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
                                                LIBAVCODEC_VERSION_MINOR, \
-- 
2.39.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".

  parent reply	other threads:[~2023-02-28 12:01 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2023-02-28 12:00 [FFmpeg-devel] [PATCH 1/8] lavu/frame: improve AVFrame.opaque[_ref] documentation Anton Khirnov
2023-02-28 12:00 ` [FFmpeg-devel] [PATCH 2/8] lavc/libvpxenc: drop frame_number Anton Khirnov
2023-02-28 20:50   ` James Zern
2023-02-28 12:00 ` [FFmpeg-devel] [PATCH 3/8] lavc/libvpxenc: reindent Anton Khirnov
2023-02-28 20:50   ` James Zern
2023-02-28 12:01 ` [FFmpeg-devel] [PATCH 4/8] lavc/libvpxenc: rename hdr10_plus_fifo and related objects Anton Khirnov
2023-02-28 20:55   ` James Zern
2023-02-28 12:01 ` Anton Khirnov [this message]
2023-02-28 21:11   ` [FFmpeg-devel] [PATCH 5/8] lavc/libvpxenc: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE James Zern
2023-03-01 12:01     ` Anton Khirnov
2023-02-28 23:30   ` James Almer
2023-03-01 12:04     ` Anton Khirnov
2023-02-28 12:01 ` [FFmpeg-devel] [PATCH 6/8] lavc/libvpxenc: drop a useless condition Anton Khirnov
2023-02-28 21:12   ` James Zern
2023-02-28 12:01 ` [FFmpeg-devel] [PATCH 7/8] lavc/libvpxenc: handle queue desync more gracefully Anton Khirnov
2023-02-28 12:01 ` [FFmpeg-devel] [PATCH 8/8] lavc/libvpxenc: drop FrameListData.duration Anton Khirnov
2023-02-28 21:16   ` James Zern
2023-03-01 12:07     ` Anton Khirnov

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20230228120104.2347-5-anton@khirnov.net \
    --to=anton@khirnov.net \
    --cc=ffmpeg-devel@ffmpeg.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

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