On Thu, May 03, 2018 at 10:24:49AM -0700, Aman Gupta wrote: > On Thu, May 3, 2018 at 12:33 AM, Matthieu Bouron <matthieu.bou...@gmail.com> > wrote: > > > On Wed, May 02, 2018 at 07:24:58PM -0700, Aman Gupta wrote: > > > From: Aman Gupta <a...@tmm1.net> > > > > > > The new logic follows a recommendation by @rcombs to use > > > dequeueInputBuffer with a timeout of 0 as a way to detect > > > whether the codec wants more data. The dequeued buffer index is > > > kept in MediaCodecDecContext until it can be used next. > > > > > > A similar technique is also used by the Google's official media > > > player Exoplayer: see MediaCodecRenderer.feedInputBuffer(). > > > > > > Signed-off-by: Aman Gupta <a...@tmm1.net> > > > --- > > > libavcodec/mediacodecdec.c | 80 ++++++++++++++++++++---------- > > --------- > > > libavcodec/mediacodecdec_common.c | 28 ++++++++------ > > > libavcodec/mediacodecdec_common.h | 4 +- > > > 3 files changed, 61 insertions(+), 51 deletions(-) > > > > > > diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c > > > index 86ceee5a83..2ac22dd1f6 100644 > > > --- a/libavcodec/mediacodecdec.c > > > +++ b/libavcodec/mediacodecdec.c > > > @@ -391,33 +391,11 @@ done: > > > return ret; > > > } > > > > > > -static int mediacodec_send_receive(AVCodecContext *avctx, > > > - MediaCodecH264DecContext *s, > > > - AVFrame *frame, bool wait) > > > -{ > > > - int ret; > > > - > > > - /* send any pending data from buffered packet */ > > > - while (s->buffered_pkt.size) { > > > - ret = ff_mediacodec_dec_send(avctx, s->ctx, &s->buffered_pkt); > > > - if (ret == AVERROR(EAGAIN)) > > > - break; > > > - else if (ret < 0) > > > - return ret; > > > - s->buffered_pkt.size -= ret; > > > - s->buffered_pkt.data += ret; > > > - if (s->buffered_pkt.size <= 0) > > > - av_packet_unref(&s->buffered_pkt); > > > - } > > > - > > > - /* check for new frame */ > > > - return ff_mediacodec_dec_receive(avctx, s->ctx, frame, wait); > > > -} > > > - > > > static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame > > *frame) > > > { > > > MediaCodecH264DecContext *s = avctx->priv_data; > > > int ret; > > > + ssize_t index; > > > > > > /* In delay_flush mode, wait until the user has released or rendered > > > all retained frames. */ > > > @@ -427,28 +405,54 @@ static int mediacodec_receive_frame(AVCodecContext > > *avctx, AVFrame *frame) > > > } > > > } > > > > > > - /* flush buffered packet and check for new frame */ > > > - ret = mediacodec_send_receive(avctx, s, frame, false); > > > + /* poll for new frame */ > > > + ret = ff_mediacodec_dec_receive(avctx, s->ctx, frame, false); > > > if (ret != AVERROR(EAGAIN)) > > > return ret; > > > > > > - /* skip fetching new packet if we still have one buffered */ > > > - if (s->buffered_pkt.size > 0) > > > - return mediacodec_send_receive(avctx, s, frame, true); > > > + /* feed decoder */ > > > + while (1) { > > > + if (s->ctx->current_input_buffer < 0) { > > > + /* poll for input space */ > > > + index = ff_AMediaCodec_dequeueInputBuffer(s->ctx->codec, > > 0); > > > + if (index < 0) { > > > + /* no space, block for an output frame to appear */ > > > + return ff_mediacodec_dec_receive(avctx, s->ctx, frame, > > true); > > > + } > > > + s->ctx->current_input_buffer = index; > > > + } > > > > > > - /* fetch new packet or eof */ > > > - ret = ff_decode_get_packet(avctx, &s->buffered_pkt); > > > - if (ret == AVERROR_EOF) { > > > - AVPacket null_pkt = { 0 }; > > > - ret = ff_mediacodec_dec_send(avctx, s->ctx, &null_pkt); > > > - if (ret < 0) > > > + /* try to flush any buffered packet data */ > > > + if (s->buffered_pkt.size > 0) { > > > + ret = ff_mediacodec_dec_send(avctx, s->ctx, > > &s->buffered_pkt, false); > > > + if (ret >= 0) { > > > + s->buffered_pkt.size -= ret; > > > + s->buffered_pkt.data += ret; > > > + if (s->buffered_pkt.size <= 0) > > > + av_packet_unref(&s->buffered_pkt); > > > + } else if (ret < 0 && ret != AVERROR(EAGAIN)) { > > > + return ret; > > > + } > > > + > > > + /* poll for space again */ > > > + continue; > > > + } > > > + > > > + /* fetch new packet or eof */ > > > + ret = ff_decode_get_packet(avctx, &s->buffered_pkt); > > > + if (ret == AVERROR_EOF) { > > > + AVPacket null_pkt = { 0 }; > > > + ret = ff_mediacodec_dec_send(avctx, s->ctx, &null_pkt, > > true); > > > + if (ret < 0) > > > + return ret; > > > + } else if (ret == AVERROR(EAGAIN) && > > s->ctx->current_input_buffer < 0) { > > > + return ff_mediacodec_dec_receive(avctx, s->ctx, frame, > > true); > > > + } else if (ret < 0) { > > > return ret; > > > + } > > > > Same comment as for the previous version of the patch: > > https://ffmpeg.org/pipermail/ffmpeg-devel/2018-April/228978.html > > > I think that comment has been addressed in this version of the patch. The > wait here only happens if current_input_buffer is not available, > meaning that the decoder is not accepting new packets. If there is space > for new input packets, the wait will not happen. > > I think the bug in the version you tested (presumably from my GH fork) was > the missing "poll for space again" continue above.
Sorry, I re-did some test on my devices and the issue has been addressed with this patch. So, LGTM. [...] -- Matthieu B. _______________________________________________ ffmpeg-devel mailing list ffmpeg-devel@ffmpeg.org http://ffmpeg.org/mailman/listinfo/ffmpeg-devel