summaryrefslogtreecommitdiff
path: root/libavcodec/mediacodecdec.c
diff options
context:
space:
mode:
Diffstat (limited to 'libavcodec/mediacodecdec.c')
-rw-r--r--libavcodec/mediacodecdec.c107
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);