Commit 882ae091 authored by Martin Storsjö's avatar Martin Storsjö

libx264: Pass the reordered_opaque field through the encoder

libx264 does have a field for opaque data to pass along with frames
through the encoder, but it is a pointer, while the libavcodec
reordered_opaque field is an int64_t. Therefore, allocate an array
within the libx264 wrapper, where reordered_opaque values in flight
are stored, and pass a pointer to this array to libx264.

Update the public libavcodec documentation for the AVCodecContext
field to explain this usage, and add a codec capability that allows
detecting whether an encoder handles this field.
Signed-off-by: 's avatarMartin Storsjö <martin@martin.st>
parent 4e9cff28
...@@ -1071,6 +1071,13 @@ typedef struct RcOverride{ ...@@ -1071,6 +1071,13 @@ typedef struct RcOverride{
*/ */
#define AV_CODEC_CAP_HYBRID (1 << 19) #define AV_CODEC_CAP_HYBRID (1 << 19)
/**
* This codec takes the reordered_opaque field from input AVFrames
* and returns it in the corresponding field in AVCodecContext after
* encoding.
*/
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE (1 << 20)
/** /**
* Pan Scan area. * Pan Scan area.
* This specifies the area which should be displayed. * This specifies the area which should be displayed.
...@@ -2677,7 +2684,10 @@ typedef struct AVCodecContext { ...@@ -2677,7 +2684,10 @@ typedef struct AVCodecContext {
/** /**
* opaque 64-bit number (generally a PTS) that will be reordered and * opaque 64-bit number (generally a PTS) that will be reordered and
* output in AVFrame.reordered_opaque * output in AVFrame.reordered_opaque
* - encoding: unused * - encoding: Set by libavcodec to the reordered_opaque of the input
* frame corresponding to the last returned packet. Only
* supported by encoders with the
* AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE capability.
* - decoding: Set by user. * - decoding: Set by user.
*/ */
int64_t reordered_opaque; int64_t reordered_opaque;
......
...@@ -92,6 +92,9 @@ typedef struct X264Context { ...@@ -92,6 +92,9 @@ typedef struct X264Context {
int noise_reduction; int noise_reduction;
char *x264_params; char *x264_params;
int nb_reordered_opaque, next_reordered_opaque;
int64_t *reordered_opaque;
} X264Context; } X264Context;
static void X264_log(void *p, int level, const char *fmt, va_list args) static void X264_log(void *p, int level, const char *fmt, va_list args)
...@@ -278,6 +281,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, ...@@ -278,6 +281,7 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
int nnal, i, ret; int nnal, i, ret;
x264_picture_t pic_out = {0}; x264_picture_t pic_out = {0};
int pict_type; int pict_type;
int64_t *out_opaque;
x264_picture_init( &x4->pic ); x264_picture_init( &x4->pic );
x4->pic.img.i_csp = x4->params.i_csp; x4->pic.img.i_csp = x4->params.i_csp;
...@@ -297,6 +301,11 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, ...@@ -297,6 +301,11 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
x4->pic.i_pts = frame->pts; x4->pic.i_pts = frame->pts;
x4->reordered_opaque[x4->next_reordered_opaque] = frame->reordered_opaque;
x4->pic.opaque = &x4->reordered_opaque[x4->next_reordered_opaque];
x4->next_reordered_opaque++;
x4->next_reordered_opaque %= x4->nb_reordered_opaque;
switch (frame->pict_type) { switch (frame->pict_type) {
case AV_PICTURE_TYPE_I: case AV_PICTURE_TYPE_I:
x4->pic.i_type = x4->forced_idr > 0 ? X264_TYPE_IDR x4->pic.i_type = x4->forced_idr > 0 ? X264_TYPE_IDR
...@@ -350,6 +359,14 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame, ...@@ -350,6 +359,14 @@ static int X264_frame(AVCodecContext *ctx, AVPacket *pkt, const AVFrame *frame,
pkt->pts = pic_out.i_pts; pkt->pts = pic_out.i_pts;
pkt->dts = pic_out.i_dts; pkt->dts = pic_out.i_dts;
out_opaque = pic_out.opaque;
if (out_opaque >= x4->reordered_opaque &&
out_opaque < &x4->reordered_opaque[x4->nb_reordered_opaque]) {
ctx->reordered_opaque = *out_opaque;
} else {
// Unexpected opaque pointer on picture output
ctx->reordered_opaque = 0;
}
switch (pic_out.i_type) { switch (pic_out.i_type) {
case X264_TYPE_IDR: case X264_TYPE_IDR:
...@@ -393,6 +410,7 @@ static av_cold int X264_close(AVCodecContext *avctx) ...@@ -393,6 +410,7 @@ static av_cold int X264_close(AVCodecContext *avctx)
av_freep(&avctx->extradata); av_freep(&avctx->extradata);
av_freep(&x4->sei); av_freep(&x4->sei);
av_freep(&x4->reordered_opaque);
if (x4->enc) { if (x4->enc) {
x264_encoder_close(x4->enc); x264_encoder_close(x4->enc);
...@@ -846,6 +864,14 @@ FF_ENABLE_DEPRECATION_WARNINGS ...@@ -846,6 +864,14 @@ FF_ENABLE_DEPRECATION_WARNINGS
cpb_props->max_bitrate = x4->params.rc.i_vbv_max_bitrate * 1000; cpb_props->max_bitrate = x4->params.rc.i_vbv_max_bitrate * 1000;
cpb_props->avg_bitrate = x4->params.rc.i_bitrate * 1000; cpb_props->avg_bitrate = x4->params.rc.i_bitrate * 1000;
// Overestimate the reordered opaque buffer size, in case a runtime
// reconfigure would increase the delay (which it shouldn't).
x4->nb_reordered_opaque = x264_encoder_maximum_delayed_frames(x4->enc) + 17;
x4->reordered_opaque = av_malloc_array(x4->nb_reordered_opaque,
sizeof(*x4->reordered_opaque));
if (!x4->reordered_opaque)
return AVERROR(ENOMEM);
return 0; return 0;
} }
...@@ -1059,7 +1085,8 @@ AVCodec ff_libx264_encoder = { ...@@ -1059,7 +1085,8 @@ AVCodec ff_libx264_encoder = {
.init = X264_init, .init = X264_init,
.encode2 = X264_frame, .encode2 = X264_frame,
.close = X264_close, .close = X264_close,
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
.priv_class = &x264_class, .priv_class = &x264_class,
.defaults = x264_defaults, .defaults = x264_defaults,
.init_static_data = X264_init_static, .init_static_data = X264_init_static,
...@@ -1085,7 +1112,8 @@ AVCodec ff_libx264rgb_encoder = { ...@@ -1085,7 +1112,8 @@ AVCodec ff_libx264rgb_encoder = {
.init = X264_init, .init = X264_init,
.encode2 = X264_frame, .encode2 = X264_frame,
.close = X264_close, .close = X264_close,
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
.priv_class = &rgbclass, .priv_class = &rgbclass,
.defaults = x264_defaults, .defaults = x264_defaults,
.pix_fmts = pix_fmts_8bit_rgb, .pix_fmts = pix_fmts_8bit_rgb,
...@@ -1110,7 +1138,8 @@ AVCodec ff_libx262_encoder = { ...@@ -1110,7 +1138,8 @@ AVCodec ff_libx262_encoder = {
.init = X264_init, .init = X264_init,
.encode2 = X264_frame, .encode2 = X264_frame,
.close = X264_close, .close = X264_close,
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS, .capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AUTO_THREADS |
AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
.priv_class = &X262_class, .priv_class = &X262_class,
.defaults = x264_defaults, .defaults = x264_defaults,
.pix_fmts = pix_fmts_8bit, .pix_fmts = pix_fmts_8bit,
......
...@@ -28,7 +28,7 @@ ...@@ -28,7 +28,7 @@
#include "libavutil/version.h" #include "libavutil/version.h"
#define LIBAVCODEC_VERSION_MAJOR 58 #define LIBAVCODEC_VERSION_MAJOR 58
#define LIBAVCODEC_VERSION_MINOR 36 #define LIBAVCODEC_VERSION_MINOR 37
#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_MICRO 100
#define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment