X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=libavcodec%2Fmediacodecdec_common.c;h=e59cf19aad8a048a93d57fe4457ee6d3160d15a6;hb=f09fdf2d9c0f5acc60c4572b6d7bb211f7a2aca0;hp=b44abaef7fe67a908d673ec280c5c2b96ad4e0fc;hpb=6dea6c4b9718132fbe32984942bcafaeb2712f73;p=ffmpeg diff --git a/libavcodec/mediacodecdec_common.c b/libavcodec/mediacodecdec_common.c index b44abaef7fe..e59cf19aad8 100644 --- a/libavcodec/mediacodecdec_common.c +++ b/libavcodec/mediacodecdec_common.c @@ -178,11 +178,16 @@ static void mediacodec_buffer_release(void *opaque, uint8_t *data) MediaCodecDecContext *ctx = buffer->ctx; int released = atomic_load(&buffer->released); - if (!released) { + if (!released && (ctx->delay_flush || buffer->serial == atomic_load(&ctx->serial))) { + atomic_fetch_sub(&ctx->hw_buffer_count, 1); + av_log(ctx->avctx, AV_LOG_DEBUG, + "Releasing output buffer %zd (%p) ts=%"PRId64" on free() [%d pending]\n", + buffer->index, buffer, buffer->pts, atomic_load(&ctx->hw_buffer_count)); ff_AMediaCodec_releaseOutputBuffer(ctx->codec, buffer->index, 0); } - ff_mediacodec_dec_unref(ctx); + if (ctx->delay_flush) + ff_mediacodec_dec_unref(ctx); av_freep(&buffer); } @@ -200,6 +205,7 @@ static int mediacodec_wrap_hw_buffer(AVCodecContext *avctx, frame->width = avctx->width; frame->height = avctx->height; frame->format = avctx->pix_fmt; + frame->sample_aspect_ratio = avctx->sample_aspect_ratio; if (avctx->pkt_timebase.num && avctx->pkt_timebase.den) { frame->pts = av_rescale_q(info->presentationTimeUs, @@ -236,13 +242,20 @@ FF_ENABLE_DEPRECATION_WARNINGS } buffer->ctx = s; - ff_mediacodec_dec_ref(s); + buffer->serial = atomic_load(&s->serial); + if (s->delay_flush) + ff_mediacodec_dec_ref(s); buffer->index = index; buffer->pts = info->presentationTimeUs; frame->data[3] = (uint8_t *)buffer; + atomic_fetch_add(&s->hw_buffer_count, 1); + av_log(avctx, AV_LOG_DEBUG, + "Wrapping output buffer %zd (%p) ts=%"PRId64" [%d pending]\n", + buffer->index, buffer, buffer->pts, atomic_load(&s->hw_buffer_count)); + return 0; fail: av_freep(buffer); @@ -297,7 +310,7 @@ FF_ENABLE_DEPRECATION_WARNINGS #endif frame->pkt_dts = AV_NOPTS_VALUE; - av_log(avctx, AV_LOG_DEBUG, + 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" "destination linesizes=%d,%d,%d\n" , @@ -339,11 +352,22 @@ done: return ret; } +#define AMEDIAFORMAT_GET_INT32(name, key, mandatory) do { \ + int32_t value = 0; \ + if (ff_AMediaFormat_getInt32(s->format, key, &value)) { \ + (name) = value; \ + } else if (mandatory) { \ + av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", key, format); \ + ret = AVERROR_EXTERNAL; \ + goto fail; \ + } \ +} while (0) \ + static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecContext *s) { + int ret = 0; int width = 0; int height = 0; - int32_t value = 0; char *format = NULL; if (!s->format) { @@ -356,40 +380,16 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte return AVERROR_EXTERNAL; } av_log(avctx, AV_LOG_DEBUG, "Parsing MediaFormat %s\n", format); - av_freep(&format); /* Mandatory fields */ - if (!ff_AMediaFormat_getInt32(s->format, "width", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "width", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->width = value; + AMEDIAFORMAT_GET_INT32(s->width, "width", 1); + AMEDIAFORMAT_GET_INT32(s->height, "height", 1); - if (!ff_AMediaFormat_getInt32(s->format, "height", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "height", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->height = value; + AMEDIAFORMAT_GET_INT32(s->stride, "stride", 0); + s->stride = s->stride > 0 ? s->stride : s->width; - if (!ff_AMediaFormat_getInt32(s->format, "stride", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "stride", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->stride = value > 0 ? value : s->width; - - if (!ff_AMediaFormat_getInt32(s->format, "slice-height", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "slice-height", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->slice_height = value > 0 ? value : s->height; + AMEDIAFORMAT_GET_INT32(s->slice_height, "slice-height", 0); + s->slice_height = s->slice_height > 0 ? s->slice_height : s->height; if (strstr(s->codec_name, "OMX.Nvidia.")) { s->slice_height = FFALIGN(s->height, 16); @@ -398,46 +398,46 @@ static int mediacodec_dec_parse_format(AVCodecContext *avctx, MediaCodecDecConte s->stride = avctx->width; } - if (!ff_AMediaFormat_getInt32(s->format, "color-format", &value)) { - format = ff_AMediaFormat_toString(s->format); - av_log(avctx, AV_LOG_ERROR, "Could not get %s from format %s\n", "color-format", format); - av_freep(&format); - return AVERROR_EXTERNAL; - } - s->color_format = value; - - s->pix_fmt = avctx->pix_fmt = mcdec_map_color_format(avctx, s, value); + AMEDIAFORMAT_GET_INT32(s->color_format, "color-format", 1); + avctx->pix_fmt = mcdec_map_color_format(avctx, s, s->color_format); if (avctx->pix_fmt == AV_PIX_FMT_NONE) { av_log(avctx, AV_LOG_ERROR, "Output color format is not supported\n"); - return AVERROR(EINVAL); + ret = AVERROR(EINVAL); + goto fail; } /* Optional fields */ - if (ff_AMediaFormat_getInt32(s->format, "crop-top", &value)) - s->crop_top = value; - - if (ff_AMediaFormat_getInt32(s->format, "crop-bottom", &value)) - s->crop_bottom = value; - - if (ff_AMediaFormat_getInt32(s->format, "crop-left", &value)) - s->crop_left = value; - - if (ff_AMediaFormat_getInt32(s->format, "crop-right", &value)) - s->crop_right = value; + AMEDIAFORMAT_GET_INT32(s->crop_top, "crop-top", 0); + AMEDIAFORMAT_GET_INT32(s->crop_bottom, "crop-bottom", 0); + AMEDIAFORMAT_GET_INT32(s->crop_left, "crop-left", 0); + AMEDIAFORMAT_GET_INT32(s->crop_right, "crop-right", 0); width = s->crop_right + 1 - s->crop_left; height = s->crop_bottom + 1 - s->crop_top; + AMEDIAFORMAT_GET_INT32(s->display_width, "display-width", 0); + AMEDIAFORMAT_GET_INT32(s->display_height, "display-height", 0); + + if (s->display_width && s->display_height) { + AVRational sar = av_div_q( + (AVRational){ s->display_width, s->display_height }, + (AVRational){ width, height }); + ff_set_sar(avctx, sar); + } + av_log(avctx, AV_LOG_INFO, "Output crop parameters top=%d bottom=%d left=%d right=%d, " "resulting dimensions width=%d height=%d\n", s->crop_top, s->crop_bottom, s->crop_left, s->crop_right, width, height); + av_freep(&format); return ff_set_dimensions(avctx, width, height); +fail: + av_freep(&format); + return ret; } - static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContext *s) { FFAMediaCodec *codec = s->codec; @@ -448,6 +448,8 @@ static int mediacodec_dec_flush_codec(AVCodecContext *avctx, MediaCodecDecContex s->draining = 0; s->flushing = 0; s->eos = 0; + atomic_fetch_add(&s->serial, 1); + atomic_init(&s->hw_buffer_count, 0); status = ff_AMediaCodec_flush(codec); if (status < 0) { @@ -471,7 +473,10 @@ int ff_mediacodec_dec_init(AVCodecContext *avctx, MediaCodecDecContext *s, AV_PIX_FMT_NONE, }; + s->avctx = avctx; atomic_init(&s->refcount, 1); + atomic_init(&s->hw_buffer_count, 0); + atomic_init(&s->serial, 1); pix_fmt = ff_get_format(avctx, pix_fmts); if (pix_fmt == AV_PIX_FMT_MEDIACODEC) { @@ -585,7 +590,7 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, index = ff_AMediaCodec_dequeueInputBuffer(codec, input_dequeue_timeout_us); if (ff_AMediaCodec_infoTryAgainLater(codec, index)) { - av_log(avctx, AV_LOG_TRACE, "Failed to dequeue input buffer, try again later..\n"); + av_log(avctx, AV_LOG_TRACE, "No input buffer available, try again later\n"); break; } @@ -616,8 +621,8 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, return AVERROR_EXTERNAL; } - av_log(avctx, AV_LOG_TRACE, "Queued input buffer %zd" - " size=%zd ts=%" PRIi64 "\n", index, size, pts); + av_log(avctx, AV_LOG_TRACE, + "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts); s->draining = 1; break; @@ -637,6 +642,9 @@ int ff_mediacodec_dec_send(AVCodecContext *avctx, MediaCodecDecContext *s, av_log(avctx, AV_LOG_ERROR, "Failed to queue input buffer (status = %d)\n", status); return AVERROR_EXTERNAL; } + + av_log(avctx, AV_LOG_TRACE, + "Queued input buffer %zd size=%zd ts=%"PRIi64"\n", index, size, pts); } } @@ -746,7 +754,7 @@ int ff_mediacodec_dec_receive(AVCodecContext *avctx, MediaCodecDecContext *s, "while draining remaining frames, output will probably lack frames\n", output_dequeue_timeout_us / 1000); } else { - av_log(avctx, AV_LOG_DEBUG, "No output buffer available, try again later\n"); + av_log(avctx, AV_LOG_TRACE, "No output buffer available, try again later\n"); } } else { av_log(avctx, AV_LOG_ERROR, "Failed to dequeue output buffer (status=%zd)\n", index);