From 782127d876f52400e61f78536ae759c2f3775528 Mon Sep 17 00:00:00 2001 From: Anton Khirnov Date: Tue, 10 Jan 2023 13:31:22 +0100 Subject: [PATCH] lavc/libwebpenc_animencoder: handle frame durations and AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE --- 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",