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.
Unified · Split
| @@ -14,6 +14,9 @@ libavutil: 2021-04-27 · 13 unmodified lines | |||
| 14 | 14 | ||
| 15 | API changes, most recent first: | 15 | API changes, most recent first: |
| 16 | 16 | ||
| 17 | 2023-01-xx - xxxxxxxxxx - lavc 59.59.100 - avcodec.h | ||
| 18 | Add AV_CODEC_FLAG_COPY_OPAQUE. | ||
| 19 | |||
| 17 | 2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h | 20 | 2023-01-13 - xxxxxxxxxx - lavu 57.44.100 - ambient_viewing_environment.h frame.h |
| 18 | Adds a new structure for holding H.274 Ambient Viewing Environment metadata, | 21 | Adds a new structure for holding H.274 Ambient Viewing Environment metadata, |
| 19 | AVAmbientViewingEnvironment. | 22 | AVAmbientViewingEnvironment. |
| @@ -241,6 +241,32 @@ typedef struct RcOverride{ · 240 unmodified lines | |||
| 241 | * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. | 241 | * @ref AV_CODEC_CAP_ENCODER_RECON_FRAME capability. |
| 242 | */ | 242 | */ |
| 243 | #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) | 243 | #define AV_CODEC_FLAG_RECON_FRAME (1 << 6) |
| 244 | /** | ||
| 245 | * Request the encoder to propagate each frame's AVFrame.opaque and | ||
| 246 | * AVFrame.opaque_ref values to its corresponding output AVPacket. | ||
| 247 | * | ||
| 248 | * May only be set on encoders that have the | ||
| 249 | * @ref AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability flag. | ||
| 250 | * | ||
| 251 | * @note | ||
| 252 | * While in typical cases one input frame produces exactly one output packet | ||
| 253 | * (perhaps after a delay), in general the mapping of frames to packets is | ||
| 254 | * M-to-N, so | ||
| 255 | * - Any number of input frames may be associated with any given output packet. | ||
| 256 | * This includes zero - e.g. some encoders may output packets that carry only | ||
| 257 | * metadata about the whole stream. | ||
| 258 | * - A given input frame may be associated with any number of output packets. | ||
| 259 | * Again this includes zero - e.g. some encoders may drop frames under certain | ||
| 260 | * conditions. | ||
| 261 | * . | ||
| 262 | * This implies that when using this flag, the caller must NOT assume that | ||
| 263 | * - a given input frame's opaques will necessarily appear on some output packet; | ||
| 264 | * - every output packet will have some non-NULL opaque value. | ||
| 265 | * . | ||
| 266 | * When an output packet contains multiple frames, the opaque values will be | ||
| 267 | * taken from the first of those. | ||
| 268 | */ | ||
| 269 | #define AV_CODEC_FLAG_COPY_OPAQUE (1 << 7) | ||
| 244 | /** | 270 | /** |
| 245 | * Use internal 2pass ratecontrol in first pass mode. | 271 | * Use internal 2pass ratecontrol in first pass mode. |
| 246 | */ | 272 | */ |
| @@ -636,6 +636,13 @@ int ff_encode_preinit(AVCodecContext *avctx) · 635 unmodified lines | |||
| 636 | return AVERROR(EINVAL); | 636 | return AVERROR(EINVAL); |
| 637 | } | 637 | } |
| 638 | 638 | ||
| 639 | if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE && | ||
| 640 | !(avctx->codec->capabilities & AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE)) { | ||
| 641 | av_log(avctx, AV_LOG_ERROR, "The copy_opaque flag is set, but the " | ||
| 642 | "encoder does not support it.\n"); | ||
| 643 | return AVERROR(EINVAL); | ||
| 644 | } | ||
| 645 | |||
| 639 | switch (avctx->codec_type) { | 646 | switch (avctx->codec_type) { |
| 640 | case AVMEDIA_TYPE_VIDEO: ret = encode_preinit_video(avctx); break; | 647 | case AVMEDIA_TYPE_VIDEO: ret = encode_preinit_video(avctx); break; |
| 641 | case AVMEDIA_TYPE_AUDIO: ret = encode_preinit_audio(avctx); break; | 648 | case AVMEDIA_TYPE_AUDIO: ret = encode_preinit_audio(avctx); break; |
| @@ -21,6 +21,7 @@ · 20 unmodified lines | |||
| 21 | 21 | ||
| 22 | #include "config_components.h" | 22 | #include "config_components.h" |
| 23 | 23 | ||
| 24 | #include "libavutil/buffer.h" | ||
| 24 | #include "libavutil/eval.h" | 25 | #include "libavutil/eval.h" |
| 25 | #include "libavutil/internal.h" | 26 | #include "libavutil/internal.h" |
| 26 | #include "libavutil/opt.h" | 27 | #include "libavutil/opt.h" |
| @@ -51,6 +52,9 @@ · 24 unmodified lines | |||
| 51 | typedef struct X264Opaque { | 52 | typedef struct X264Opaque { |
| 52 | int64_t reordered_opaque; | 53 | int64_t reordered_opaque; |
| 53 | int64_t wallclock; | 54 | int64_t wallclock; |
| 55 | |||
| 56 | void *frame_opaque; | ||
| 57 | AVBufferRef *frame_opaque_ref; | ||
| 54 | } X264Opaque; | 58 | } X264Opaque; |
| 55 | 59 | ||
| 56 | typedef struct X264Context { | 60 | typedef struct X264Context { |
| @@ -133,6 +137,11 @@ static void X264_log(void *p, int level, const char *fmt, va_list args) · 76 unmodified lines | |||
| 133 | av_vlog(p, level_map[level], fmt, args); | 137 | av_vlog(p, level_map[level], fmt, args); |
| 134 | } | 138 | } |
| 135 | 139 | ||
| 140 | static void opaque_uninit(X264Opaque *o) | ||
| 141 | { | ||
| 142 | av_buffer_unref(&o->frame_opaque_ref); | ||
| 143 | memset(o, 0, sizeof(*o)); | ||
| 144 | } | ||
| 136 | 145 | ||
| 137 | static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, | 146 | static int encode_nals(AVCodecContext *ctx, AVPacket *pkt, |
| 138 | const x264_nal_t *nals, int nnal) | 147 | const x264_nal_t *nals, int nnal) |
| @@ -440,6 +449,15 @@ static int setup_frame(AVCodecContext *ctx, const AVFrame *frame, · 301 unmodified lines | |||
| 440 | 449 | ||
| 441 | pic->i_pts = frame->pts; | 450 | pic->i_pts = frame->pts; |
| 442 | 451 | ||
| 452 | opaque_uninit(opaque); | ||
| 453 | |||
| 454 | if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { | ||
| 455 | opaque->frame_opaque = frame->opaque; | ||
| 456 | ret = av_buffer_replace(&opaque->frame_opaque_ref, frame->opaque_ref); | ||
| 457 | if (ret < 0) | ||
| 458 | goto fail; | ||
| 459 | } | ||
| 460 | |||
| 443 | opaque->reordered_opaque = frame->reordered_opaque; | 461 | opaque->reordered_opaque = frame->reordered_opaque; |
| 444 | opaque->wallclock = wallclock; | 462 | opaque->wallclock = wallclock; |
| 445 | if (ctx->export_side_data & AV_CODEC_EXPORT_DATA_PRFT) | 463 | 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, · 148 unmodified lines | |||
| 594 | out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { | 612 | out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) { |
| 595 | ctx->reordered_opaque = out_opaque->reordered_opaque; | 613 | ctx->reordered_opaque = out_opaque->reordered_opaque; |
| 596 | wallclock = out_opaque->wallclock; | 614 | wallclock = out_opaque->wallclock; |
| 615 | |||
| 616 | if (ctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { | ||
| 617 | pkt->opaque = out_opaque->frame_opaque; | ||
| 618 | pkt->opaque_ref = out_opaque->frame_opaque_ref; | ||
| 619 | out_opaque->frame_opaque_ref = NULL; | ||
| 620 | } | ||
| 621 | |||
| 622 | opaque_uninit(out_opaque); | ||
| 597 | } else { | 623 | } else { |
| 598 | // Unexpected opaque pointer on picture output | 624 | // Unexpected opaque pointer on picture output |
| 599 | av_log(ctx, AV_LOG_ERROR, "Unexpected opaque pointer; " | 625 | av_log(ctx, AV_LOG_ERROR, "Unexpected opaque pointer; " |
| @@ -634,6 +660,9 @@ static av_cold int X264_close(AVCodecContext *avctx) · 34 unmodified lines | |||
| 634 | X264Context *x4 = avctx->priv_data; | 660 | X264Context *x4 = avctx->priv_data; |
| 635 | 661 | ||
| 636 | av_freep(&x4->sei); | 662 | av_freep(&x4->sei); |
| 663 | |||
| 664 | for (int i = 0; i < x4->nb_reordered_opaque; i++) | ||
| 665 | opaque_uninit(&x4->reordered_opaque[i]); | ||
| 637 | av_freep(&x4->reordered_opaque); | 666 | av_freep(&x4->reordered_opaque); |
| 638 | 667 | ||
| 639 | #if X264_BUILD >= 161 | 668 | #if X264_BUILD >= 161 |
| @@ -28,6 +28,7 @@ · 27 unmodified lines | |||
| 28 | #include <float.h> | 28 | #include <float.h> |
| 29 | 29 | ||
| 30 | #include "libavutil/avassert.h" | 30 | #include "libavutil/avassert.h" |
| 31 | #include "libavutil/buffer.h" | ||
| 31 | #include "libavutil/internal.h" | 32 | #include "libavutil/internal.h" |
| 32 | #include "libavutil/common.h" | 33 | #include "libavutil/common.h" |
| 33 | #include "libavutil/opt.h" | 34 | #include "libavutil/opt.h" |
| @@ -43,6 +44,9 @@ · 9 unmodified lines | |||
| 43 | typedef struct ReorderedData { | 44 | typedef struct ReorderedData { |
| 44 | int64_t reordered_opaque; | 45 | int64_t reordered_opaque; |
| 45 | 46 | ||
| 47 | void *frame_opaque; | ||
| 48 | AVBufferRef *frame_opaque_ref; | ||
| 49 | |||
| 46 | int in_use; | 50 | int in_use; |
| 47 | } ReorderedData; | 51 | } ReorderedData; |
| 48 | 52 | ||
| @@ -121,7 +125,7 @@ static int rd_get(libx265Context *ctx) · 72 unmodified lines | |||
| 121 | static void rd_release(libx265Context *ctx, int idx) | 125 | static void rd_release(libx265Context *ctx, int idx) |
| 122 | { | 126 | { |
| 123 | av_assert0(idx >= 0 && idx < ctx->nb_rd); | 127 | av_assert0(idx >= 0 && idx < ctx->nb_rd); |
| 124 | 128 | av_buffer_unref(&ctx->rd[idx].frame_opaque_ref); | |
| 125 | memset(&ctx->rd[idx], 0, sizeof(ctx->rd[idx])); | 129 | memset(&ctx->rd[idx], 0, sizeof(ctx->rd[idx])); |
| 126 | } | 130 | } |
| 127 | 131 | ||
| @@ -132,6 +136,8 @@ static av_cold int libx265_encode_close(AVCodecContext *avctx) · 4 unmodified lines | |||
| 132 | ctx->api->param_free(ctx->params); | 136 | ctx->api->param_free(ctx->params); |
| 133 | av_freep(&ctx->sei_data); | 137 | av_freep(&ctx->sei_data); |
| 134 | 138 | ||
| 139 | for (int i = 0; i < ctx->nb_rd; i++) | ||
| 140 | rd_release(ctx, i); | ||
| 135 | av_freep(&ctx->rd); | 141 | av_freep(&ctx->rd); |
| 136 | 142 | ||
| 137 | if (ctx->encoder) | 143 | if (ctx->encoder) |
| @@ -582,6 +588,9 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, · 444 unmodified lines | |||
| 582 | sei->numPayloads = 0; | 588 | sei->numPayloads = 0; |
| 583 | 589 | ||
| 584 | if (pic) { | 590 | if (pic) { |
| 591 | ReorderedData *rd; | ||
| 592 | int rd_idx; | ||
| 593 | |||
| 585 | for (i = 0; i < 3; i++) { | 594 | for (i = 0; i < 3; i++) { |
| 586 | x265pic.planes[i] = pic->data[i]; | 595 | x265pic.planes[i] = pic->data[i]; |
| 587 | x265pic.stride[i] = pic->linesize[i]; | 596 | x265pic.stride[i] = pic->linesize[i]; |
| @@ -600,21 +609,26 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, · 12 unmodified lines | |||
| 600 | if (ret < 0) | 609 | if (ret < 0) |
| 601 | return ret; | 610 | return ret; |
| 602 | 611 | ||
| 603 | if (pic->reordered_opaque) { | 612 | rd_idx = rd_get(ctx); |
| 604 | ReorderedData *rd; | 613 | if (rd_idx < 0) { |
| 605 | int rd_idx = rd_get(ctx); | 614 | free_picture(ctx, &x265pic); |
| 615 | return rd_idx; | ||
| 616 | } | ||
| 617 | rd = &ctx->rd[rd_idx]; | ||
| 606 | 618 | ||
| 607 | if (rd_idx < 0) { | 619 | rd->reordered_opaque = pic->reordered_opaque; |
| 620 | if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { | ||
| 621 | rd->frame_opaque = pic->opaque; | ||
| 622 | ret = av_buffer_replace(&rd->frame_opaque_ref, pic->opaque_ref); | ||
| 623 | if (ret < 0) { | ||
| 624 | rd_release(ctx, rd_idx); | ||
| 608 | free_picture(ctx, &x265pic); | 625 | free_picture(ctx, &x265pic); |
| 609 | return rd_idx; | 626 | return ret; |
| 610 | } | 627 | } |
| 611 | |||
| 612 | x265pic.userData = (void*)(intptr_t)(rd_idx + 1); | ||
| 613 | |||
| 614 | rd = &ctx->rd[rd_idx]; | ||
| 615 | rd->reordered_opaque = pic->reordered_opaque; | ||
| 616 | } | 628 | } |
| 617 | 629 | ||
| 630 | x265pic.userData = (void*)(intptr_t)(rd_idx + 1); | ||
| 631 | |||
| 618 | if (ctx->a53_cc) { | 632 | if (ctx->a53_cc) { |
| 619 | void *sei_data; | 633 | void *sei_data; |
| 620 | size_t sei_size; | 634 | size_t sei_size; |
| @@ -742,6 +756,12 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt, · 121 unmodified lines | |||
| 742 | 756 | ||
| 743 | avctx->reordered_opaque = rd->reordered_opaque; | 757 | avctx->reordered_opaque = rd->reordered_opaque; |
| 744 | 758 | ||
| 759 | if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) { | ||
| 760 | pkt->opaque = rd->frame_opaque; | ||
| 761 | pkt->opaque_ref = rd->frame_opaque_ref; | ||
| 762 | rd->frame_opaque_ref = NULL; | ||
| 763 | } | ||
| 764 | |||
| 745 | rd_release(ctx, idx); | 765 | rd_release(ctx, idx); |
| 746 | } else | 766 | } else |
| 747 | avctx->reordered_opaque = 0; | 767 | avctx->reordered_opaque = 0; |
| @@ -58,6 +58,7 @@ static const AVOption avcodec_options[] = { · 57 unmodified lines | |||
| 58 | {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, | 58 | {"loop", "use loop filter", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_LOOP_FILTER }, INT_MIN, INT_MAX, V|E, "flags"}, |
| 59 | {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, | 59 | {"qscale", "use fixed qscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_QSCALE }, INT_MIN, INT_MAX, 0, "flags"}, |
| 60 | {"recon_frame", "export reconstructed frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_RECON_FRAME}, .unit = "flags"}, | 60 | {"recon_frame", "export reconstructed frames", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_RECON_FRAME}, .unit = "flags"}, |
| 61 | {"copy_opaque", "propagate opaque values", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_COPY_OPAQUE}, .unit = "flags"}, | ||
| 61 | {"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"}, | 62 | {"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"}, |
| 62 | {"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"}, | 63 | {"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"}, |
| 63 | {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, | 64 | {"gray", "only decode/encode grayscale", 0, AV_OPT_TYPE_CONST, {.i64 = AV_CODEC_FLAG_GRAY }, INT_MIN, INT_MAX, V|E|D, "flags"}, |
| @@ -29,7 +29,7 @@ · 28 unmodified lines | |||
| 29 | 29 | ||
| 30 | #include "version_major.h" | 30 | #include "version_major.h" |
| 31 | 31 | ||
| 32 | #define LIBAVCODEC_VERSION_MINOR 58 | 32 | #define LIBAVCODEC_VERSION_MINOR 59 |
| 33 | #define LIBAVCODEC_VERSION_MICRO 100 | 33 | #define LIBAVCODEC_VERSION_MICRO 100 |
| 34 | 34 | ||
| 35 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ | 35 | #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ |