mirror of https://git.ffmpeg.org/ffmpeg.git
lavc/mediacodecdec: switch to new decoding API
Using the new API gives the decoder the ability to produce N frames per input packet. This is particularly useful with mpeg2 decoders on some android devices, which automatically deinterlace video and produce one frame per field. Signed-off-by: Aman Gupta <aman@tmm1.net> Signed-off-by: Matthieu Bouron <matthieu.bouron@gmail.com>
This commit is contained in:
parent
8bbd8c8d52
commit
9d9835017f
|
@ -31,6 +31,7 @@
|
|||
#include "libavutil/pixfmt.h"
|
||||
|
||||
#include "avcodec.h"
|
||||
#include "decode.h"
|
||||
#include "h264_parse.h"
|
||||
#include "hevc_parse.h"
|
||||
#include "hwaccel.h"
|
||||
|
@ -424,29 +425,13 @@ static int mediacodec_process_data(AVCodecContext *avctx, AVFrame *frame,
|
|||
return ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, pkt);
|
||||
}
|
||||
|
||||
static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
|
||||
int *got_frame, AVPacket *avpkt)
|
||||
static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||
{
|
||||
MediaCodecH264DecContext *s = avctx->priv_data;
|
||||
AVFrame *frame = data;
|
||||
int ret;
|
||||
|
||||
/* buffer the input packet */
|
||||
if (avpkt->size) {
|
||||
AVPacket input_pkt = { 0 };
|
||||
|
||||
if (av_fifo_space(s->fifo) < sizeof(input_pkt)) {
|
||||
ret = av_fifo_realloc2(s->fifo,
|
||||
av_fifo_size(s->fifo) + sizeof(input_pkt));
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = av_packet_ref(&input_pkt, avpkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
av_fifo_generic_write(s->fifo, &input_pkt, sizeof(input_pkt), NULL);
|
||||
}
|
||||
int got_frame = 0;
|
||||
int is_eof = 0;
|
||||
AVPacket pkt = { 0 };
|
||||
|
||||
/*
|
||||
* MediaCodec.flush() discards both input and output buffers, thus we
|
||||
|
@ -470,26 +455,57 @@ static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
|
|||
*/
|
||||
if (ff_mediacodec_dec_is_flushing(avctx, s->ctx)) {
|
||||
if (!ff_mediacodec_dec_flush(avctx, s->ctx)) {
|
||||
return avpkt->size;
|
||||
return AVERROR(EAGAIN);
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
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) {
|
||||
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)) {
|
||||
return avpkt->size ? avpkt->size :
|
||||
ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, avpkt);
|
||||
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);
|
||||
}
|
||||
|
||||
ret = mediacodec_process_data(avctx, frame, got_frame, &s->buffered_pkt);
|
||||
ret = mediacodec_process_data(avctx, frame, &got_frame, &s->buffered_pkt);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
|
@ -497,7 +513,7 @@ static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
|
|||
s->buffered_pkt.data += ret;
|
||||
}
|
||||
|
||||
return avpkt->size;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mediacodec_decode_flush(AVCodecContext *avctx)
|
||||
|
@ -537,7 +553,7 @@ AVCodec ff_h264_mediacodec_decoder = {
|
|||
.id = AV_CODEC_ID_H264,
|
||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||
.init = mediacodec_decode_init,
|
||||
.decode = mediacodec_decode_frame,
|
||||
.receive_frame = mediacodec_receive_frame,
|
||||
.flush = mediacodec_decode_flush,
|
||||
.close = mediacodec_decode_close,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||
|
@ -556,7 +572,7 @@ AVCodec ff_hevc_mediacodec_decoder = {
|
|||
.id = AV_CODEC_ID_HEVC,
|
||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||
.init = mediacodec_decode_init,
|
||||
.decode = mediacodec_decode_frame,
|
||||
.receive_frame = mediacodec_receive_frame,
|
||||
.flush = mediacodec_decode_flush,
|
||||
.close = mediacodec_decode_close,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||
|
@ -575,7 +591,7 @@ AVCodec ff_mpeg2_mediacodec_decoder = {
|
|||
.id = AV_CODEC_ID_MPEG2VIDEO,
|
||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||
.init = mediacodec_decode_init,
|
||||
.decode = mediacodec_decode_frame,
|
||||
.receive_frame = mediacodec_receive_frame,
|
||||
.flush = mediacodec_decode_flush,
|
||||
.close = mediacodec_decode_close,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||
|
@ -593,7 +609,7 @@ AVCodec ff_mpeg4_mediacodec_decoder = {
|
|||
.id = AV_CODEC_ID_MPEG4,
|
||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||
.init = mediacodec_decode_init,
|
||||
.decode = mediacodec_decode_frame,
|
||||
.receive_frame = mediacodec_receive_frame,
|
||||
.flush = mediacodec_decode_flush,
|
||||
.close = mediacodec_decode_close,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||
|
@ -611,7 +627,7 @@ AVCodec ff_vp8_mediacodec_decoder = {
|
|||
.id = AV_CODEC_ID_VP8,
|
||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||
.init = mediacodec_decode_init,
|
||||
.decode = mediacodec_decode_frame,
|
||||
.receive_frame = mediacodec_receive_frame,
|
||||
.flush = mediacodec_decode_flush,
|
||||
.close = mediacodec_decode_close,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||
|
@ -629,7 +645,7 @@ AVCodec ff_vp9_mediacodec_decoder = {
|
|||
.id = AV_CODEC_ID_VP9,
|
||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||
.init = mediacodec_decode_init,
|
||||
.decode = mediacodec_decode_frame,
|
||||
.receive_frame = mediacodec_receive_frame,
|
||||
.flush = mediacodec_decode_flush,
|
||||
.close = mediacodec_decode_close,
|
||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||
|
|
Loading…
Reference in New Issue