From 7097197a45e45afcff9c98ffa6f1e87bf8701232 Mon Sep 17 00:00:00 2001
|
From: Hertz Wang <wangh@rock-chips.com>
|
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 <wangh@rock-chips.com>
|
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
|