X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmediacodecdec_common.c;h=7c2661f6726b41c99b6838e9cf79d1456146a43f;hb=50ae1f7e0ff1fa00236622415039f7e28d919a25;hp=e31adb487c964bd343f8dcf191e537ee5f184a2a;hpb=c00b218a8f75ed3eb87c213d95bd5775c0af5e12;p=ffmpeg diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index e31adb487c9..7c2661f6726 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -209,7 +209,7 @@ static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx, if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) { frame->pts = av_rescale_q(info->presentationTimeUs, - av_make_q(1, 1000000), + AV_TIME_BASE_Q, avctx->pkt_timebase); } else { frame->pts = info->presentationTimeUs; @@ -298,7 +298,7 @@ static int mediacodec_wrap_sw_buffer(AVCodecContext *avctx, * * 0-sized avpackets are pushed to flush remaining frames at EOS */ if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) { frame->pts = av_rescale_q(info->presentationTimeUs, - av_make_q(1, 1000000), + AV_TIME_BASE_Q, avctx->pkt_timebase); } else { frame->pts = info->presentationTimeUs; @@ -312,7 +312,7 @@ FF_ENABLE_DEPRECATION_WARNINGS av_log(avctx, AV_LOG_TRACE, "Frame: width=%d stride=%d height=%d slice-height=%d " - "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s\n" + "crop-top=%d crop-bottom=%d crop-left=%d crop-right=%d encoder=%s " "destination linesizes=%d,%d,%d\n" , avctx->width, s->stride, avctx->height, s->slice_height, s->crop_top, s->crop_bottom, s->crop_left, s->crop_right, s->codec_name, @@ -385,17 +385,18 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte AMEDIAFORMAT_GET_INT32(s->width, "width", 1); AMEDIAFORMAT_GET_INT32(s->height, "height", 1); - AMEDIAFORMAT_GET_INT32(s->stride, "stride", 1); + AMEDIAFORMAT_GET_INT32(s->stride, "stride", 0); s->stride = s->stride > 0 ? s->stride : s->width; - AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 1); - s->slice_height = s->slice_height > 0 ? s->slice_height : s->height; + AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 0); - if (strstr(s->codec_name, "OMX.Nvidia.")) { + if (strstr(s->codec_name, "OMX.Nvidia.") && s->slice_height == 0) { s->slice_height = FFALIGN(s->height, 16); } else if (strstr(s->codec_name, "OMX.SEC.avc.dec")) { s->slice_height = avctx->height; s->stride = avctx->width; + } else if (s->slice_height == 0) { + s->slice_height = s->height; } AMEDIAFORMAT_GET_INT32(s->color_format, "color-format", 1); @@ -450,6 +451,7 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex s->eos = 0; atomic_fetch_add(&s->serial, 1); atomic_init(&s->hw_buffer_count, 0); + s->current_input_buffer = -1; status = ff_AMediaCodec_flush(codec); if (status < 0) { @@ -477,6 +479,7 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, atomic_init(&s->refcount, 1); atomic_init(&s->hw_buffer_count, 0); atomic_init(&s->serial, 1); + s->current_input_buffer = -1; pix_fmt = ff_get_format(avctx, pix_fmts); if (pix_fmt == AV_PIX_FMT_MEDIACODEC) { @@ -561,16 +564,17 @@ fail: } int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, - AVPacket *pkt) + AVPacket *pkt, bool wait) { int offset = 0; int need_draining = 0; uint8_t *data; - ssize_t index; + ssize_t index = s->current_input_buffer; size_t size; FFAMediaCodec *codec = s->codec; int status; - int64_t input_dequeue_timeout_us = INPUT_DEQUEUE_TIMEOUT_US; + int64_t input_dequeue_timeout_us = wait ? INPUT_DEQUEUE_TIMEOUT_US : 0; + int64_t pts; if (s->flushing) { av_log(avctx, AV_LOG_ERROR, "Decoder is flushing and cannot accept new buffer " @@ -587,17 +591,19 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, } while (offset < pkt->size || (need_draining && !s->draining)) { - - index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us); - if (ff_AMediaCodec_infoTryAgainLater(codec, index)) { - av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n"); - break; - } - if (index < 0) { - av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index); - return AVERROR_EXTERNAL; + index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us); + if (ff_AMediaCodec_infoTryAgainLater(codec, index)) { + av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n"); + break; + } + + if (index < 0) { + av_log(avctx, AV_LOG_ERROR, "Failed to dequeue input buffer (status=%zd)\n", index); + return AVERROR_EXTERNAL; + } } + s->current_input_buffer = -1; data = ff_AMediaCodec_getInputBuffer(codec, index, &size); if (!data) { @@ -605,14 +611,14 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, return AVERROR_EXTERNAL; } + pts = pkt->pts; + if (pts != AV_NOPTS_VALUE && avctx->pkt_timebase.num && avctx->pkt_timebase.den) { + pts = av_rescale_q(pts, avctx->pkt_timebase, AV_TIME_BASE_Q); + } + if (need_draining) { - int64_t pts = pkt->pts; uint32_t flags = ff_AMediaCodec_getBufferFlagEndOfStream(codec); - if (s->surface) { - pts = av_rescale_q(pts, avctx->pkt_timebase, av_make_q(1, 1000000)); - } - av_log(avctx, AV_LOG_DEBUG, "Sending End Of Stream signal\n"); status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, 0, pts, flags); @@ -627,16 +633,10 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, s->draining = 1; break; } else { - int64_t pts = pkt->pts; - size = FFMIN(pkt->size - offset, size); memcpy(data, pkt->data + offset, size); offset += size; - if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) { - pts = av_rescale_q(pts, avctx->pkt_timebase, av_make_q(1, 1000000)); - } - status = ff_AMediaCodec_queueInputBuffer(codec, index, 0, size, pts, 0); if (status < 0) { av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status); @@ -764,6 +764,18 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s, return AVERROR(EAGAIN); } +/* +* ff_mediacodec_dec_flush returns 0 if the flush cannot be performed on +* the codec (because the user retains frames). The codec stays in the +* flushing state. +* +* ff_mediacodec_dec_flush returns 1 if the flush can actually be +* performed on the codec. The codec leaves the flushing state and can +* process again packets. +* +* ff_mediacodec_dec_flush returns a negative value if an error has +* occurred. +*/ int ff_mediacodec_dec_flush(AVCodecContext *avctx, MediaCodecDecContext *s) { if (!s->surface || atomic_load(&s->refcount) == 1) {