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:
committed by
Matthieu Bouron
parent
8bbd8c8d52
commit
9d9835017f
@@ -31,6 +31,7 @@
|
|||||||
#include "libavutil/pixfmt.h"
|
#include "libavutil/pixfmt.h"
|
||||||
|
|
||||||
#include "avcodec.h"
|
#include "avcodec.h"
|
||||||
|
#include "decode.h"
|
||||||
#include "h264_parse.h"
|
#include "h264_parse.h"
|
||||||
#include "hevc_parse.h"
|
#include "hevc_parse.h"
|
||||||
#include "hwaccel.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);
|
return ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, pkt);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
|
static int mediacodec_receive_frame(AVCodecContext *avctx, AVFrame *frame)
|
||||||
int *got_frame, AVPacket *avpkt)
|
|
||||||
{
|
{
|
||||||
MediaCodecH264DecContext *s = avctx->priv_data;
|
MediaCodecH264DecContext *s = avctx->priv_data;
|
||||||
AVFrame *frame = data;
|
|
||||||
int ret;
|
int ret;
|
||||||
|
int got_frame = 0;
|
||||||
/* buffer the input packet */
|
int is_eof = 0;
|
||||||
if (avpkt->size) {
|
AVPacket pkt = { 0 };
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* MediaCodec.flush() discards both input and output buffers, thus we
|
* 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_is_flushing(avctx, s->ctx)) {
|
||||||
if (!ff_mediacodec_dec_flush(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 */
|
/* process buffered data */
|
||||||
while (!*got_frame) {
|
while (!got_frame) {
|
||||||
/* prepare the input data */
|
/* prepare the input data */
|
||||||
if (s->buffered_pkt.size <= 0) {
|
if (s->buffered_pkt.size <= 0) {
|
||||||
av_packet_unref(&s->buffered_pkt);
|
av_packet_unref(&s->buffered_pkt);
|
||||||
|
|
||||||
/* no more data */
|
/* no more data */
|
||||||
if (av_fifo_size(s->fifo) < sizeof(AVPacket)) {
|
if (av_fifo_size(s->fifo) < sizeof(AVPacket)) {
|
||||||
return avpkt->size ? avpkt->size :
|
AVPacket null_pkt = { 0 };
|
||||||
ff_mediacodec_dec_decode(avctx, s->ctx, frame, got_frame, avpkt);
|
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);
|
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)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
@@ -497,7 +513,7 @@ static int mediacodec_decode_frame(AVCodecContext *avctx, void *data,
|
|||||||
s->buffered_pkt.data += ret;
|
s->buffered_pkt.data += ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
return avpkt->size;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mediacodec_decode_flush(AVCodecContext *avctx)
|
static void mediacodec_decode_flush(AVCodecContext *avctx)
|
||||||
@@ -537,7 +553,7 @@ AVCodec ff_h264_mediacodec_decoder = {
|
|||||||
.id = AV_CODEC_ID_H264,
|
.id = AV_CODEC_ID_H264,
|
||||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||||
.init = mediacodec_decode_init,
|
.init = mediacodec_decode_init,
|
||||||
.decode = mediacodec_decode_frame,
|
.receive_frame = mediacodec_receive_frame,
|
||||||
.flush = mediacodec_decode_flush,
|
.flush = mediacodec_decode_flush,
|
||||||
.close = mediacodec_decode_close,
|
.close = mediacodec_decode_close,
|
||||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
.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,
|
.id = AV_CODEC_ID_HEVC,
|
||||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||||
.init = mediacodec_decode_init,
|
.init = mediacodec_decode_init,
|
||||||
.decode = mediacodec_decode_frame,
|
.receive_frame = mediacodec_receive_frame,
|
||||||
.flush = mediacodec_decode_flush,
|
.flush = mediacodec_decode_flush,
|
||||||
.close = mediacodec_decode_close,
|
.close = mediacodec_decode_close,
|
||||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
.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,
|
.id = AV_CODEC_ID_MPEG2VIDEO,
|
||||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||||
.init = mediacodec_decode_init,
|
.init = mediacodec_decode_init,
|
||||||
.decode = mediacodec_decode_frame,
|
.receive_frame = mediacodec_receive_frame,
|
||||||
.flush = mediacodec_decode_flush,
|
.flush = mediacodec_decode_flush,
|
||||||
.close = mediacodec_decode_close,
|
.close = mediacodec_decode_close,
|
||||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
.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,
|
.id = AV_CODEC_ID_MPEG4,
|
||||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||||
.init = mediacodec_decode_init,
|
.init = mediacodec_decode_init,
|
||||||
.decode = mediacodec_decode_frame,
|
.receive_frame = mediacodec_receive_frame,
|
||||||
.flush = mediacodec_decode_flush,
|
.flush = mediacodec_decode_flush,
|
||||||
.close = mediacodec_decode_close,
|
.close = mediacodec_decode_close,
|
||||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
.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,
|
.id = AV_CODEC_ID_VP8,
|
||||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||||
.init = mediacodec_decode_init,
|
.init = mediacodec_decode_init,
|
||||||
.decode = mediacodec_decode_frame,
|
.receive_frame = mediacodec_receive_frame,
|
||||||
.flush = mediacodec_decode_flush,
|
.flush = mediacodec_decode_flush,
|
||||||
.close = mediacodec_decode_close,
|
.close = mediacodec_decode_close,
|
||||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
.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,
|
.id = AV_CODEC_ID_VP9,
|
||||||
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
.priv_data_size = sizeof(MediaCodecH264DecContext),
|
||||||
.init = mediacodec_decode_init,
|
.init = mediacodec_decode_init,
|
||||||
.decode = mediacodec_decode_frame,
|
.receive_frame = mediacodec_receive_frame,
|
||||||
.flush = mediacodec_decode_flush,
|
.flush = mediacodec_decode_flush,
|
||||||
.close = mediacodec_decode_close,
|
.close = mediacodec_decode_close,
|
||||||
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_AVOID_PROBING | AV_CODEC_CAP_HARDWARE,
|
||||||
|
Reference in New Issue
Block a user