diff --git a/libavcodec/libvpxenc.c b/libavcodec/libvpxenc.c index 5b7c7735a1..e08df5fb96 100644 --- a/libavcodec/libvpxenc.c +++ b/libavcodec/libvpxenc.c @@ -56,8 +56,6 @@ struct FrameListData { void *buf; /**< compressed data buffer */ size_t sz; /**< length of compressed data */ - void *buf_alpha; - size_t sz_alpha; int64_t pts; /**< time stamp to show frame (in timebase units) */ unsigned long duration; /**< duration to show frame @@ -87,6 +85,7 @@ typedef struct VPxEncoderContext { int have_sse; /**< true if we have pending sse[] */ uint64_t frame_number; struct FrameListData *coded_frame_list; + struct FrameListData *alpha_coded_frame_list; int cpu_used; int sharpness; @@ -311,8 +310,6 @@ static void coded_frame_add(void *list, struct FrameListData *cx_frame) static av_cold void free_coded_frame(struct FrameListData *cx_frame) { av_freep(&cx_frame->buf); - if (cx_frame->buf_alpha) - av_freep(&cx_frame->buf_alpha); av_freep(&cx_frame); } @@ -446,6 +443,7 @@ static av_cold int vpx_free(AVCodecContext *avctx) av_freep(&ctx->twopass_stats.buf); av_freep(&avctx->stats_out); free_frame_list(ctx->coded_frame_list); + free_frame_list(ctx->alpha_coded_frame_list); if (ctx->hdr10_plus_fifo) free_hdr10_plus_fifo(&ctx->hdr10_plus_fifo); return 0; @@ -1205,7 +1203,6 @@ static av_cold int vpx_init(AVCodecContext *avctx, static inline void cx_pktcpy(struct FrameListData *dst, const struct vpx_codec_cx_pkt *src, - const struct vpx_codec_cx_pkt *src_alpha, VPxContext *ctx) { dst->pts = src->data.frame.pts; @@ -1229,13 +1226,6 @@ static inline void cx_pktcpy(struct FrameListData *dst, } else { dst->frame_number = -1; /* sanity marker */ } - if (src_alpha) { - dst->buf_alpha = src_alpha->data.frame.buf; - dst->sz_alpha = src_alpha->data.frame.sz; - } else { - dst->buf_alpha = NULL; - dst->sz_alpha = 0; - } } /** @@ -1246,7 +1236,7 @@ static inline void cx_pktcpy(struct FrameListData *dst, * @return a negative AVERROR on error */ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, - AVPacket *pkt) + struct FrameListData *alpha_cx_frame, AVPacket *pkt) { VPxContext *ctx = avctx->priv_data; int ret = ff_get_encode_buffer(avctx, pkt, cx_frame->sz, 0); @@ -1279,16 +1269,16 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, avctx->error[i] += cx_frame->sse[i + 1]; cx_frame->have_sse = 0; } - if (cx_frame->sz_alpha > 0) { + if (alpha_cx_frame) { side_data = av_packet_new_side_data(pkt, AV_PKT_DATA_MATROSKA_BLOCKADDITIONAL, - cx_frame->sz_alpha + 8); + alpha_cx_frame->sz + 8); if (!side_data) { av_packet_unref(pkt); return AVERROR(ENOMEM); } AV_WB64(side_data, 1); - memcpy(side_data + 8, cx_frame->buf_alpha, cx_frame->sz_alpha); + memcpy(side_data + 8, alpha_cx_frame->buf, alpha_cx_frame->sz); } if (cx_frame->frame_number != -1) { if (ctx->hdr10_plus_fifo) { @@ -1309,40 +1299,37 @@ static int storeframe(AVCodecContext *avctx, struct FrameListData *cx_frame, * @return AVERROR(EINVAL) on output size error * @return AVERROR(ENOMEM) on coded frame queue data allocation error */ -static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) +static int queue_frames(AVCodecContext *avctx, struct vpx_codec_ctx *encoder, + struct FrameListData **frame_list, AVPacket *pkt_out) { VPxContext *ctx = avctx->priv_data; const struct vpx_codec_cx_pkt *pkt; - const struct vpx_codec_cx_pkt *pkt_alpha = NULL; const void *iter = NULL; - const void *iter_alpha = NULL; int size = 0; - if (ctx->coded_frame_list) { - struct FrameListData *cx_frame = ctx->coded_frame_list; + if (!ctx->is_alpha && *frame_list) { + struct FrameListData *cx_frame = *frame_list; /* return the leading frame if we've already begun queueing */ - size = storeframe(avctx, cx_frame, pkt_out); + size = storeframe(avctx, cx_frame, NULL, pkt_out); if (size < 0) return size; - ctx->coded_frame_list = cx_frame->next; + *frame_list = cx_frame->next; free_coded_frame(cx_frame); } /* consume all available output from the encoder before returning. buffers are only good through the next vpx_codec call */ - while ((pkt = vpx_codec_get_cx_data(&ctx->encoder, &iter)) && - (!ctx->is_alpha || - (pkt_alpha = vpx_codec_get_cx_data(&ctx->encoder_alpha, &iter_alpha)))) { + while (pkt = vpx_codec_get_cx_data(encoder, &iter)) { switch (pkt->kind) { case VPX_CODEC_CX_FRAME_PKT: - if (!size) { + if (!ctx->is_alpha && !size) { struct FrameListData cx_frame; /* avoid storing the frame when the list is empty and we haven't yet provided a frame for output */ av_assert0(!ctx->coded_frame_list); - cx_pktcpy(&cx_frame, pkt, pkt_alpha, ctx); - size = storeframe(avctx, &cx_frame, pkt_out); + cx_pktcpy(&cx_frame, pkt, ctx); + size = storeframe(avctx, &cx_frame, NULL, pkt_out); if (size < 0) return size; } else { @@ -1353,7 +1340,7 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) "Frame queue element alloc failed\n"); return AVERROR(ENOMEM); } - cx_pktcpy(cx_frame, pkt, pkt_alpha, ctx); + cx_pktcpy(cx_frame, pkt, ctx); cx_frame->buf = av_malloc(cx_frame->sz); if (!cx_frame->buf) { @@ -1364,23 +1351,14 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) return AVERROR(ENOMEM); } memcpy(cx_frame->buf, pkt->data.frame.buf, pkt->data.frame.sz); - if (ctx->is_alpha) { - cx_frame->buf_alpha = av_malloc(cx_frame->sz_alpha); - if (!cx_frame->buf_alpha) { - av_log(avctx, AV_LOG_ERROR, - "Data buffer alloc (%"SIZE_SPECIFIER" bytes) failed\n", - cx_frame->sz_alpha); - av_free(cx_frame); - return AVERROR(ENOMEM); - } - memcpy(cx_frame->buf_alpha, pkt_alpha->data.frame.buf, pkt_alpha->data.frame.sz); - } - coded_frame_add(&ctx->coded_frame_list, cx_frame); + coded_frame_add(frame_list, cx_frame); } break; case VPX_CODEC_STATS_PKT: { struct vpx_fixed_buf *stats = &ctx->twopass_stats; int err; + if (!pkt_out) + break; if ((err = av_reallocp(&stats->buf, stats->sz + pkt->data.twopass_stats.sz)) < 0) { @@ -1394,6 +1372,8 @@ static int queue_frames(AVCodecContext *avctx, AVPacket *pkt_out) break; } case VPX_CODEC_PSNR_PKT: + if (!pkt_out) + break; av_assert0(!ctx->have_sse); ctx->sse[0] = pkt->data.psnr.sse[0]; ctx->sse[1] = pkt->data.psnr.sse[1]; @@ -1788,7 +1768,24 @@ static int vpx_encode(AVCodecContext *avctx, AVPacket *pkt, } } - coded_size = queue_frames(avctx, pkt); + coded_size = queue_frames(avctx, &ctx->encoder, &ctx->coded_frame_list, pkt); + if (ctx->is_alpha) { + queue_frames(avctx, &ctx->encoder_alpha, &ctx->alpha_coded_frame_list, NULL); + + if (ctx->coded_frame_list && ctx->alpha_coded_frame_list) { + struct FrameListData *cx_frame = ctx->coded_frame_list; + struct FrameListData *alpha_cx_frame = ctx->alpha_coded_frame_list; + av_assert0(!coded_size); + /* return the leading frame if we've already begun queueing */ + coded_size = storeframe(avctx, cx_frame, alpha_cx_frame, pkt); + if (coded_size < 0) + return coded_size; + ctx->coded_frame_list = cx_frame->next; + ctx->alpha_coded_frame_list = alpha_cx_frame->next; + free_coded_frame(cx_frame); + free_coded_frame(alpha_cx_frame); + } + } if (!frame && avctx->flags & AV_CODEC_FLAG_PASS1) { unsigned int b64_size = AV_BASE64_SIZE(ctx->twopass_stats.sz);