Re: [FFmpeg-devel] [PATCH v2 2/4] avcodec/mediacodecdec: restructure mediacodec_receive_frame

2018-05-04 Thread Aman Gupta
On Fri, May 4, 2018 at 8:13 AM, Matthieu Bouron 
wrote:

> 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 
> > > >
> > > > 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 
> > > > ---
> > > >  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,
> >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(>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, >buffered_pkt);
> > > > -if (ret == AVERROR_EOF) {
> > > > -AVPacket null_pkt = { 0 };
> > > > -ret = ff_mediacodec_dec_send(avctx, s->ctx, _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,
> > > >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(>buffered_pkt);
> > > > +} else if (ret < 0 && ret != AVERROR(EAGAIN)) {
> > > > +return ret;
> > > > +}
> > > > +
> > > > +/* poll for space again */
> > > > +continue;
> > > > +}
> > > > +
> > > > +/* fetch new packet or eof */
> > > > +ret = 

Re: [FFmpeg-devel] [PATCH v2 2/4] avcodec/mediacodecdec: restructure mediacodec_receive_frame

2018-05-04 Thread Matthieu Bouron
On Thu, May 03, 2018 at 10:24:49AM -0700, Aman Gupta wrote:
> On Thu, May 3, 2018 at 12:33 AM, Matthieu Bouron 
> wrote:
> 
> > On Wed, May 02, 2018 at 07:24:58PM -0700, Aman Gupta wrote:
> > > From: Aman Gupta 
> > >
> > > 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 
> > > ---
> > >  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, >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(>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, >buffered_pkt);
> > > -if (ret == AVERROR_EOF) {
> > > -AVPacket null_pkt = { 0 };
> > > -ret = ff_mediacodec_dec_send(avctx, s->ctx, _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,
> > >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(>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, >buffered_pkt);
> > > +if (ret == AVERROR_EOF) {
> > > +AVPacket null_pkt = { 0 };
> > > +ret = ff_mediacodec_dec_send(avctx, s->ctx, _pkt,
> > true);
> > > +if (ret < 0)
> > > +return ret;
> > > +} else if (ret == AVERROR(EAGAIN) &&
> > 

Re: [FFmpeg-devel] [PATCH v2 2/4] avcodec/mediacodecdec: restructure mediacodec_receive_frame

2018-05-03 Thread Aman Gupta
On Thu, May 3, 2018 at 12:33 AM, Matthieu Bouron 
wrote:

> On Wed, May 02, 2018 at 07:24:58PM -0700, Aman Gupta wrote:
> > From: Aman Gupta 
> >
> > 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 
> > ---
> >  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, >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(>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, >buffered_pkt);
> > -if (ret == AVERROR_EOF) {
> > -AVPacket null_pkt = { 0 };
> > -ret = ff_mediacodec_dec_send(avctx, s->ctx, _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,
> >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(>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, >buffered_pkt);
> > +if (ret == AVERROR_EOF) {
> > +AVPacket null_pkt = { 0 };
> > +ret = ff_mediacodec_dec_send(avctx, s->ctx, _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:
> 

Re: [FFmpeg-devel] [PATCH v2 2/4] avcodec/mediacodecdec: restructure mediacodec_receive_frame

2018-05-03 Thread Matthieu Bouron
On Wed, May 02, 2018 at 07:24:58PM -0700, Aman Gupta wrote:
> From: Aman Gupta 
> 
> 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 
> ---
>  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, >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(>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, >buffered_pkt);
> -if (ret == AVERROR_EOF) {
> -AVPacket null_pkt = { 0 };
> -ret = ff_mediacodec_dec_send(avctx, s->ctx, _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, >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(>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, >buffered_pkt);
> +if (ret == AVERROR_EOF) {
> +AVPacket null_pkt = { 0 };
> +ret = ff_mediacodec_dec_send(avctx, s->ctx, _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

[...]

-- 
Matthieu B.
___
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel


[FFmpeg-devel] [PATCH v2 2/4] avcodec/mediacodecdec: restructure mediacodec_receive_frame

2018-05-02 Thread Aman Gupta
From: Aman Gupta 

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 
---
 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, >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(>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, >buffered_pkt);
-if (ret == AVERROR_EOF) {
-AVPacket null_pkt = { 0 };
-ret = ff_mediacodec_dec_send(avctx, s->ctx, _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, >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(>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, >buffered_pkt);
+if (ret == AVERROR_EOF) {
+AVPacket null_pkt = { 0 };
+ret = ff_mediacodec_dec_send(avctx, s->ctx, _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;
+}
 }
-else if (ret < 0)
-return ret;
 
-/* crank decoder with new packet */
-return mediacodec_send_receive(avctx, s, frame, true);
+return AVERROR(EAGAIN);
 }
 
 static void mediacodec_decode_flush(AVCodecContext *avctx)
diff --git a/libavcodec/mediacodecdec_common.c 
b/libavcodec/mediacodecdec_common.c
index c0f0a6b983..887865a281 100644
--- a/libavcodec/mediacodecdec_common.c
+++ b/libavcodec/mediacodecdec_common.c
@@ -450,6 +450,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext 
*avctx, MediaCodecDecContex
 s->eos = 0;
 atomic_fetch_add(>serial, 1);
 atomic_init(>hw_buffer_count, 0);
+s->current_input_buffer = -1;
 
 status = ff_AMediaCodec_flush(codec);
 if