diff options
Diffstat (limited to 'libavcodec/mediacodecdec.c')
-rw-r--r-- | libavcodec/mediacodecdec.c | 107 |
1 files changed, 38 insertions, 69 deletions
diff --git a/libavcodec/mediacodecdec.c b/libavcodec/mediacodecdec.c index cb1151a195..363e12427e 100644 --- a/libavcodec/mediacodecdec.c +++ b/libavcodec/mediacodecdec.c @@ -25,7 +25,6 @@ #include "libavutil/avassert.h" #include "libavutil/common.h" -#include "libavutil/fifo.h" #include "libavutil/opt.h" #include "libavutil/intreadwrite.h" #include "libavutil/pixfmt.h" @@ -43,8 +42,6 @@ typedef struct MediaCodecH264DecContext { MediaCodecDecContext *ctx; - AVFifoBuffer *fifo; - AVPacket buffered_pkt; } MediaCodecH264DecContext; @@ -56,8 +53,6 @@ static av_cold int mediacodec_decode_close(AVCodecContext *avctx) ff_mediacodec_dec_close(avctx, s->ctx); s->ctx = NULL; - av_fifo_free(s->fifo); - av_packet_unref(&s->buffered_pkt); return 0; @@ -400,12 +395,6 @@ static av_cold int mediacodec_decode_init(AVCodecContext *avctx) av_log(avctx, AV_LOG_INFO, "MediaCodec started successfully, ret = %d\n", ret); - s->fifo = av_fifo_alloc(sizeof(AVPacket)); - if (!s->fifo) { - ret = AVERROR(ENOMEM); - goto done; - } - done: if (format) { ff_AMediaFormat_delete(format); @@ -418,13 +407,33 @@ 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; - int got_frame = 0; - int is_eof = 0; - AVPacket pkt = { 0 }; /* * MediaCodec.flush() discards both input and output buffers, thus we @@ -452,74 +461,34 @@ static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame) } } - ret = ff_decode_get_packet(avctx, &pkt); - if (ret == AVERROR_EOF) - is_eof = 1; - else if (ret == AVERROR(EAGAIN)) - ; /* no input packet, but fallthrough to check for pending frames */ - else if (ret < 0) + /* flush buffered packet and check for new frame */ + ret = mediacodec_send_receive(avctx, s, frame, false); + if (ret != AVERROR(EAGAIN)) return ret; - /* buffer the input packet */ - if (pkt.size) { - if (av_fifo_space(s->fifo) < sizeof(pkt)) { - ret = av_fifo_realloc2(s->fifo, - av_fifo_size(s->fifo) + sizeof(pkt)); - if (ret < 0) { - av_packet_unref(&pkt); - return ret; - } - } - av_fifo_generic_write(s->fifo, &pkt, sizeof(pkt), NULL); - } - - /* process buffered data */ - while (!got_frame) { - /* prepare the input data */ - if (s->buffered_pkt.size <= 0) { - av_packet_unref(&s->buffered_pkt); - - /* no more data */ - if (av_fifo_size(s->fifo) < sizeof(AVPacket)) { - AVPacket null_pkt = { 0 }; - if (is_eof) { - ret = ff_mediacodec_dec_decode(avctx, s->ctx, frame, - &got_frame, &null_pkt); - if (ret < 0) - return ret; - else if (got_frame) - return 0; - else - return AVERROR_EOF; - } - return AVERROR(EAGAIN); - } - - av_fifo_generic_read(s->fifo, &s->buffered_pkt, sizeof(s->buffered_pkt), NULL); - } + /* skip fetching new packet if we still have one buffered */ + if (s->buffered_pkt.size > 0) + return AVERROR(EAGAIN); - ret = ff_mediacodec_dec_decode(avctx, s->ctx, frame, &got_frame, &s->buffered_pkt); + /* 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) return ret; - - s->buffered_pkt.size -= ret; - s->buffered_pkt.data += ret; } + else if (ret < 0) + return ret; - return 0; + /* crank decoder with new packet */ + return mediacodec_send_receive(avctx, s, frame, true); } static void mediacodec_decode_flush(AVCodecContext *avctx) { MediaCodecH264DecContext *s = avctx->priv_data; - while (av_fifo_size(s->fifo)) { - AVPacket pkt; - av_fifo_generic_read(s->fifo, &pkt, sizeof(pkt), NULL); - av_packet_unref(&pkt); - } - av_fifo_reset(s->fifo); - av_packet_unref(&s->buffered_pkt); ff_mediacodec_dec_flush(avctx, s->ctx); |