diff --git a/doc/APIchanges b/doc/APIchanges index d1957e2e19..297a5a2061 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -15,6 +15,11 @@ libavutil: 2017-10-21 API changes, most recent first: +2018-03-xx - xxxxxxx - lavc 58.14.100 - mediacodec.h + Change the default behavior of avcodec_flush() on mediacodec + video decoders. To restore the previous behavior, use the new + delay_flush=1 option. + 2018-03-xx - xxxxxxx - lavu 56.8.100 - frame.h Add av_frame_new_side_data_from_buf(). diff --git a/libavcodec/mediacodec.c b/libavcodec/mediacodec.c index d492eefe0b..bf1b7477f1 100644 --- a/libavcodec/mediacodec.c +++ b/libavcodec/mediacodec.c @@ -91,7 +91,7 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render) MediaCodecDecContext *ctx = buffer->ctx; int released = atomic_fetch_add(&buffer->released, 1); - if (!released) { + if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { return ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, render); } diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index 0fe14846c3..89d2421ae9 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -41,10 +41,14 @@ typedef struct MediaCodecH264DecContext { + AVClass *avclass; + MediaCodecDecContext *ctx; AVPacket buffered_pkt; + int delay_flush; + } MediaCodecH264DecContext; static av_cold int mediacodec_decode_close(AVCodecContext *avctx) @@ -366,6 +370,8 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) goto done; } + s->ctx->delay_flush = s->delay_flush; + if ((ret = ff_mediacodec_dec_init(avctx, s->ctx, codec_mime, format)) < 0) { s->ctx = NULL; goto done; @@ -485,12 +491,30 @@ static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { NULL }; +#define OFFSET(x) offsetof(MediaCodecH264DecContext, x) +#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM +static const AVOption ff_mediacodec_vdec_options[] = { + { "delay_flush", "Delay flush until hw output buffers are returned to the decoder", + OFFSET(delay_flush), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VD }, + { NULL } +}; + +#define DECLARE_MEDIACODEC_VCLASS(short_name) \ +static const AVClass ff_##short_name##_mediacodec_dec_class = { \ + .class_name = #short_name "_mediacodec", \ + .item_name = av_default_item_name, \ + .option = ff_mediacodec_vdec_options, \ + .version = LIBAVUTIL_VERSION_INT, \ +}; + #define DECLARE_MEDIACODEC_VDEC(short_name, full_name, codec_id, bsf) \ +DECLARE_MEDIACODEC_VCLASS(short_name) \ AVCodec ff_##short_name##_mediacodec_decoder = { \ .name = #short_name "_mediacodec", \ .long_name = NULL_IF_CONFIG_SMALL(full_name " Android MediaCodec decoder"), \ .type = AVMEDIA_TYPE_VIDEO, \ .id = codec_id, \ + .priv_class = &ff_##short_name##_mediacodec_dec_class, \ .priv_data_size = sizeof(MediaCodecH264DecContext), \ .init = mediacodec_decode_init, \ .receive_frame = mediacodec_receive_frame, \ diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index 0bd660f7c9..693524abd6 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -178,11 +178,12 @@ static void mediacodec_buffer_release(void *opaque, uint8_t *data) MediaCodecDecContext *ctx = buffer->ctx; int released = atomic_load(&buffer->released); - if (!released) { + if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0); } - ff_mediacodec_dec_unref(ctx); + if (ctx->delay_flush) + ff_mediacodec_dec_unref(ctx); av_freep(&buffer); } @@ -236,7 +237,9 @@ FF_ENABLE_DEPRECATION_WARNINGS } buffer->ctx = s; - ff_mediacodec_dec_ref(s); + buffer->serial = atomic_load(&s->serial); + if (s->delay_flush) + ff_mediacodec_dec_ref(s); buffer->index = index; buffer->pts = info->presentationTimeUs; @@ -425,6 +428,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex s->draining = 0; s->flushing = 0; s->eos = 0; + atomic_fetch_add(&s->serial, 1); status = ff_AMediaCodec_flush(codec); if (status < 0) { @@ -449,6 +453,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, }; atomic_init(&s->refcount, 1); + atomic_init(&s->serial, 1); pix_fmt = ff_get_format(avctx, pix_fmts); if (pix_fmt == AV_PIX_FMT_MEDIACODEC) { diff --git a/libavcodec/mediacodecdec_common.h b/libavcodec/mediacodecdec_common.h index 85df507ffb..afb98ffed9 100644 --- a/libavcodec/mediacodecdec_common.h +++ b/libavcodec/mediacodecdec_common.h @@ -62,6 +62,9 @@ typedef struct MediaCodecDecContext { uint64_t output_buffer_count; + bool delay_flush; + atomic_int serial; + } MediaCodecDecContext; int ff_mediacodec_dec_init(AVCodecContext *avctx, @@ -93,6 +96,7 @@ typedef struct MediaCodecBuffer { ssize_t index; int64_t pts; atomic_int released; + int serial; } MediaCodecBuffer; diff --git a/libavcodec/version.h b/libavcodec/version.h index d8256bff21..ed34095c77 100644 --- a/libavcodec/version.h +++ b/libavcodec/version.h @@ -28,8 +28,8 @@ #include "libavutil/version.h" #define LIBAVCODEC_VERSION_MAJOR 58 -#define LIBAVCODEC_VERSION_MINOR 13 -#define LIBAVCODEC_VERSION_MICRO 102 +#define LIBAVCODEC_VERSION_MINOR 14 +#define LIBAVCODEC_VERSION_MICRO 100 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \ LIBAVCODEC_VERSION_MINOR, \