From 7097197a45e45afcff9c98ffa6f1e87bf8701232 Mon Sep 17 00:00:00 2001 From: Hertz Wang Date: Wed, 9 Oct 2019 16:57:17 +0800 Subject: [PATCH 4/4] fix destination align not suitable to RGA in Chromium test pass on Debian 9.11 with Mozilla Firefox 68.1.0esr and Chromium 76.0.3809.100 built on Debian bullseye/sid Signed-off-by: Hertz Wang Change-Id: I424cfb30afd004417f25ab3b399b11e4b619a829 --- libavcodec/rkmppdec.c | 80 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 65 insertions(+), 15 deletions(-) diff --git a/libavcodec/rkmppdec.c b/libavcodec/rkmppdec.c index e74a15c..71b720d 100644 --- a/libavcodec/rkmppdec.c +++ b/libavcodec/rkmppdec.c @@ -42,7 +42,7 @@ #include "libavutil/imgutils.h" #include "libavutil/log.h" -#define RECEIVE_FRAME_TIMEOUT 10 +#define RECEIVE_FRAME_TIMEOUT 100 #define FRAMEGROUP_MAX_FRAMES 16 #define INPUT_MAX_PACKETS 4 @@ -86,8 +86,8 @@ static int rkmpp_write_nv12(MppBuffer mpp_buffer, int mpp_vir_width, int mpp_vir_height, AVFrame* dst_frame) { rga_info_t src_info = {0}; rga_info_t dst_info = {0}; - int width = dst_frame->width; - int height = dst_frame->height; + int width = dst_frame->width - (dst_frame->crop_right + dst_frame->crop_left); + int height = dst_frame->height - (dst_frame->crop_bottom + dst_frame->crop_top); int possible_height; int rga_format = get_rga_format(dst_frame->format); @@ -109,11 +109,6 @@ static int rkmpp_write_nv12(MppBuffer mpp_buffer, int mpp_vir_width, goto bail; // mostly is not continuous memory } - if (possible_height != height && possible_height != mpp_vir_height) - av_log(NULL, AV_LOG_WARNING, - "dst frame possiable %d is strange, expect %d or %d\n", - possible_height, height, mpp_vir_height); - src_info.fd = mpp_buffer_get_fd(mpp_buffer); src_info.mmuFlag = 1; // mpp decoder always return nv12(yuv420sp) @@ -124,8 +119,9 @@ static int rkmpp_write_nv12(MppBuffer mpp_buffer, int mpp_vir_width, // dst_frame data[*] must be continuous dst_info.virAddr = dst_frame->data[0]; dst_info.mmuFlag = 1; - rga_set_rect(&dst_info.rect, 0, 0, width, height, dst_frame->linesize[0], - possible_height, rga_format); + rga_set_rect(&dst_info.rect, dst_frame->crop_left, dst_frame->crop_top, + width, height, dst_frame->linesize[0], possible_height, + rga_format); if (c_RkRgaBlit(&src_info, &dst_info, NULL) < 0) { av_log(NULL, AV_LOG_ERROR, "Failed to do rga blit\n"); goto bail; @@ -465,6 +461,51 @@ static void rkmpp_setinfo_avframe(AVFrame *frame, MppFrame mppframe) { frame->top_field_first = ((mode & MPP_FRAME_FLAG_FIELD_ORDER_MASK) == MPP_FRAME_FLAG_TOP_FIRST); } +static int rkmpp_get_continue_video_buffer(AVFrame *frame) { + const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(frame->format); + int ret, i, padded_height; + + if (!desc) + return AVERROR(EINVAL); + + if ((ret = av_image_check_size(frame->width, frame->height, 0, NULL)) < 0) + return ret; + + if (!frame->linesize[0]) { + for(i=1; i<=16; i+=i) { + ret = av_image_fill_linesizes(frame->linesize, frame->format, + FFALIGN(frame->width, i)); + if (ret < 0) + return ret; + // rga need 16 align + if (!(frame->linesize[0] & (16-1))) + break; + } + } + + padded_height = frame->height; + if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height, + NULL, frame->linesize)) < 0) + return ret; + + frame->buf[0] = av_buffer_alloc(ret + 4 * 16); + if (!frame->buf[0]) { + ret = AVERROR(ENOMEM); + goto fail; + } + + if ((ret = av_image_fill_pointers(frame->data, frame->format, padded_height, + frame->buf[0]->data, frame->linesize)) < 0) + goto fail; + + frame->extended_data = frame->data; + + return 0; +fail: + av_frame_unref(frame); + return ret; +} + static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) { RKMPPDecodeContext *rk_context = avctx->priv_data; @@ -496,6 +537,9 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) avctx->width = mpp_frame_get_width(mppframe); avctx->height = mpp_frame_get_height(mppframe); + // chromium will align u/v width height to 32 + avctx->coded_width = FFALIGN(avctx->width, 64); + avctx->coded_height = FFALIGN(avctx->height, 64); decoder->mpi->control(decoder->ctx, MPP_DEC_SET_INFO_CHANGE_READY, NULL); @@ -546,8 +590,12 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) // setup general frame fields frame->format = avctx->pix_fmt; - frame->width = mpp_frame_get_width(mppframe); - frame->height = mpp_frame_get_height(mppframe); + frame->width = avctx->coded_width; + frame->height = avctx->coded_height; + frame->crop_left = 0; + frame->crop_right = avctx->coded_width - mpp_frame_get_width(mppframe); + frame->crop_top = 0; + frame->crop_bottom = avctx->coded_height - mpp_frame_get_height(mppframe); mppformat = mpp_frame_get_fmt(mppframe); drmformat = rkmpp_get_frameformat(mppformat); @@ -556,10 +604,12 @@ static int rkmpp_retrieve_frame(AVCodecContext *avctx, AVFrame *frame) buffer = mpp_frame_get_buffer(mppframe); if (buffer) { if (avctx->pix_fmt != AV_PIX_FMT_DRM_PRIME) { - if (avctx->get_buffer2 == avcodec_default_get_buffer2) - ret = av_frame_get_buffer(frame, 0); - else + if (avctx->get_buffer2 == avcodec_default_get_buffer2) { + // firefox path + ret = rkmpp_get_continue_video_buffer(frame); + } else { ret = ff_get_buffer(avctx, frame, 0); + } if (ret) { av_log(avctx, AV_LOG_ERROR, "Fail to alloc frame.\n"); goto fail; -- 2.7.4