History

avcodec/mediacodecdec: add delay_flush option

The default behavior of the mediacodec decoder before this commit was to delay flushes until all pending hardware frames were returned to the decoder. This was useful for certain types of applications, but was unexpected behavior for others. The new default behavior with this commit is now to execute flushes immediately to invalidate all pending frames. The old behavior can be enabled by setting delay_flush=1. With the new behavior, video players implementing seek can simply call flush on the decoder without having to worry about whether they have one or more mediacodec frames still buffered in their rendering pipeline. Previously, all these frames had to be explictly freed (or rendered) before the seek/flush would execute. The new behavior matches the behavior of all other lavc decoders, reducing the amount of special casing required when using the mediacodec decoder.

Aman Gupta committed 8 years ago

Commit 2a0eb861 parent 840f6eb6 files · +44 −6Browse files

Unified · Split

6 files
  1. doc/APIchanges +5 −0
  2. libavcodec/mediacodec.c +1 −1
  3. libavcodec/mediacodecdec.c +24 −0
  4. libavcodec/mediacodecdec_common.c +8 −3
  5. libavcodec/mediacodecdec_common.h +4 −0
  6. libavcodec/version.h +2 −2
doc/APIchanges+5−0
@@ -15,6 +15,11 @@ libavutil: 2017-10-21 · 14 unmodified lines
1515
1616 API changes, most recent first:
1717
18+2018-03-xx - xxxxxxx - lavc 58.14.100 - mediacodec.h
19+ Change the default behavior of avcodec_flush() on mediacodec
20+ video decoders. To restore the previous behavior, use the new
21+ delay_flush=1 option.
22+
1823 2018-03-xx - xxxxxxx - lavu 56.8.100 - frame.h
1924 Add av_frame_new_side_data_from_buf().
2025
libavcodec/mediacodec.c+1−1
@@ -91,7 +91,7 @@ int av_mediacodec_release_buffer(AVMediaCodecBuffer *buffer, int render) · 90 unmodified lines
9191 MediaCodecDecContext *ctx = buffer->ctx;
9292 int released = atomic_fetch_add(&buffer->released, 1);
9393
94− if (!released) {
94+ if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
9595 return ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, render);
9696 }
9797
libavcodec/mediacodecdec.c+24−0
@@ -41,10 +41,14 @@ · 40 unmodified lines
4141
4242 typedef struct MediaCodecH264DecContext {
4343
44+ AVClass *avclass;
45+
4446 MediaCodecDecContext *ctx;
4547
4648 AVPacket buffered_pkt;
4749
50+ int delay_flush;
51+
4852 } MediaCodecH264DecContext;
4953
5054 static av_cold int mediacodec_decode_close(AVCodecContext *avctx)
@@ -366,6 +370,8 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) · 315 unmodified lines
366370 goto done;
367371 }
368372
373+ s->ctx->delay_flush = s->delay_flush;
374+
369375 if ((ret = ff_mediacodec_dec_init(avctx, s->ctx, codec_mime, format)) < 0) {
370376 s->ctx = NULL;
371377 goto done;
@@ -485,12 +491,30 @@ static const AVCodecHWConfigInternal *mediacodec_hw_configs[] = { · 113 unmodified lines
485491 NULL
486492 };
487493
494+#define OFFSET(x) offsetof(MediaCodecH264DecContext, x)
495+#define VD AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_DECODING_PARAM
496+static const AVOption ff_mediacodec_vdec_options[] = {
497+ { "delay_flush", "Delay flush until hw output buffers are returned to the decoder",
498+ OFFSET(delay_flush), AV_OPT_TYPE_BOOL, {.i64 = 0}, 0, 1, VD },
499+ { NULL }
500+};
501+
502+#define DECLARE_MEDIACODEC_VCLASS(short_name) \
503+static const AVClass ff_##short_name##_mediacodec_dec_class = { \
504+ .class_name = #short_name "_mediacodec", \
505+ .item_name = av_default_item_name, \
506+ .option = ff_mediacodec_vdec_options, \
507+ .version = LIBAVUTIL_VERSION_INT, \
508+};
509+
488510 #define DECLARE_MEDIACODEC_VDEC(short_name, full_name, codec_id, bsf) \
511+DECLARE_MEDIACODEC_VCLASS(short_name) \
489512 AVCodec ff_##short_name##_mediacodec_decoder = { \
490513 .name = #short_name "_mediacodec", \
491514 .long_name = NULL_IF_CONFIG_SMALL(full_name " Android MediaCodec decoder"), \
492515 .type = AVMEDIA_TYPE_VIDEO, \
493516 .id = codec_id, \
517+ .priv_class = &ff_##short_name##_mediacodec_dec_class, \
494518 .priv_data_size = sizeof(MediaCodecH264DecContext), \
495519 .init = mediacodec_decode_init, \
496520 .receive_frame = mediacodec_receive_frame, \
libavcodec/mediacodecdec_common.c+8−3
@@ -178,11 +178,12 @@ static void mediacodec_buffer_release(void *opaque, uint8_t *data) · 177 unmodified lines
178178 MediaCodecDecContext *ctx = buffer->ctx;
179179 int released = atomic_load(&buffer->released);
180180
181− if (!released) {
181+ if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) {
182182 ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0);
183183 }
184184
185− ff_mediacodec_dec_unref(ctx);
185+ if (ctx->delay_flush)
186+ ff_mediacodec_dec_unref(ctx);
186187 av_freep(&buffer);
187188 }
188189
@@ -236,7 +237,9 @@ FF_ENABLE_DEPRECATION_WARNINGS · 47 unmodified lines
236237 }
237238
238239 buffer->ctx = s;
239− ff_mediacodec_dec_ref(s);
240+ buffer->serial = atomic_load(&s->serial);
241+ if (s->delay_flush)
242+ ff_mediacodec_dec_ref(s);
240243
241244 buffer->index = index;
242245 buffer->pts = info->presentationTimeUs;
@@ -425,6 +428,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex · 182 unmodified lines
425428 s->draining = 0;
426429 s->flushing = 0;
427430 s->eos = 0;
431+ atomic_fetch_add(&s->serial, 1);
428432
429433 status = ff_AMediaCodec_flush(codec);
430434 if (status < 0) {
@@ -449,6 +453,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, · 18 unmodified lines
449453 };
450454
451455 atomic_init(&s->refcount, 1);
456+ atomic_init(&s->serial, 1);
452457
453458 pix_fmt = ff_get_format(avctx, pix_fmts);
454459 if (pix_fmt == AV_PIX_FMT_MEDIACODEC) {
libavcodec/mediacodecdec_common.h+4−0
@@ -62,6 +62,9 @@ typedef struct MediaCodecDecContext { · 61 unmodified lines
6262
6363 uint64_t output_buffer_count;
6464
65+ bool delay_flush;
66+ atomic_int serial;
67+
6568 } MediaCodecDecContext;
6669
6770 int ff_mediacodec_dec_init(AVCodecContext *avctx,
@@ -93,6 +96,7 @@ typedef struct MediaCodecBuffer { · 25 unmodified lines
9396 ssize_t index;
9497 int64_t pts;
9598 atomic_int released;
99+ int serial;
96100
97101 } MediaCodecBuffer;
98102
libavcodec/version.h+2−2
@@ -28,8 +28,8 @@ · 27 unmodified lines
2828 #include "libavutil/version.h"
2929
3030 #define LIBAVCODEC_VERSION_MAJOR 58
31−#define LIBAVCODEC_VERSION_MINOR 13
32−#define LIBAVCODEC_VERSION_MICRO 102
31+#define LIBAVCODEC_VERSION_MINOR 14
32+#define LIBAVCODEC_VERSION_MICRO 100
3333
3434 #define LIBAVCODEC_VERSION_INT AV_VERSION_INT(LIBAVCODEC_VERSION_MAJOR, \
3535 LIBAVCODEC_VERSION_MINOR, \

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t