From ade9d9b54d172437be84797300b25a85c4164cd4 Mon Sep 17 00:00:00 2001 From: CTCaer Date: Fri, 18 Mar 2022 21:39:48 +0000 Subject: [PATCH 09/39] codecs: nvv4l2: align line width to 64B Transformations of formats to formats of simply Block linear to Pitch are done in HW. VIC is responsible for that and has the limitation that width must be aligned to 64 Bytes. This allows the decoder to work with every single non standard resolution, effectively bringing full support to any video. That is particularly important on emulators that use ffmpeg for decoding in game videos which sometimes are used as backgrounds. These have weird dimensions and need that fix. The output frame of course has the original line width. --- libavcodec/nvv4l2_dec.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/libavcodec/nvv4l2_dec.c b/libavcodec/nvv4l2_dec.c index 83abdc24e2..640b6836de 100644 --- a/libavcodec/nvv4l2_dec.c +++ b/libavcodec/nvv4l2_dec.c @@ -160,8 +160,11 @@ static void query_set_capture(AVCodecContext *avctx, nvv4l2_ctx_t *ctx) return; } - ctx->codec_height = crop.c.height; + av_log(avctx, AV_LOG_VERBOSE, "Resolution changed to: %dx%d\n", + crop.c.width, crop.c.height); + ctx->codec_width = crop.c.width; + ctx->codec_height = crop.c.height; for (uint32_t i = 0; i < NV_MAX_BUFFERS; i++) { if (ctx->plane_dma_fd[i] != -1) { @@ -170,6 +173,17 @@ static void query_set_capture(AVCodecContext *avctx, nvv4l2_ctx_t *ctx) } } + /* + ** Due to VIC constrains the transformation from Block Linear to Pitch + ** must have aligned widths to 64B. Otherwise the frame might be produced + ** as scrambled. + */ + ctx->plane_width_aligned = NVALIGN(crop.c.width, 64); + if (ctx->plane_width_aligned != crop.c.width) + av_log(avctx, AV_LOG_VERBOSE, "Linesize got aligned: %d -> %d\n", + crop.c.width, ctx->plane_width_aligned); + crop.c.width = ctx->plane_width_aligned; + /* Create transform/export DMA buffers. */ for (uint32_t i = 0; i < NV_MAX_BUFFERS; i++) { input_params.width = crop.c.width; @@ -1042,6 +1056,11 @@ nvv4l2dec_decode(AVCodecContext *avctx, void *data, int *got_frame, if (nvv4l2_decoder_get_frame(avctx, ctx, &buf_index, &_nvframe)) return processed_size; + /* Set coded width to aligned size to fit the transformation. + ** It gets restored after transformation by default. + */ + avctx->coded_width = ctx->plane_width_aligned; + /* Get frame data buffers. */ if (ff_get_buffer(avctx, avframe, 0) < 0) return AVERROR(ENOMEM); -- 2.25.1