From patchwork Sat Jan 30 09:19:03 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Christophe Gisquet X-Patchwork-Id: 25272 Return-Path: X-Original-To: patchwork@ffaux-bg.ffmpeg.org Delivered-To: patchwork@ffaux-bg.ffmpeg.org Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org [79.124.17.100]) by ffaux.localdomain (Postfix) with ESMTP id 5992E44B489 for ; Sat, 30 Jan 2021 11:20:27 +0200 (EET) Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 33F0E6891F1; Sat, 30 Jan 2021 11:20:27 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from mail-wr1-f54.google.com (mail-wr1-f54.google.com [209.85.221.54]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTPS id D9F74688104 for ; Sat, 30 Jan 2021 11:20:20 +0200 (EET) Received: by mail-wr1-f54.google.com with SMTP id q7so11163419wre.13 for ; Sat, 30 Jan 2021 01:20:20 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:subject:date:message-id:in-reply-to:references:mime-version :content-transfer-encoding; bh=2SofKRLXs3ghLoKK58NwVVXOpm0/wmnKtTLgHTp8mKg=; b=htO83+7TdK8uQxoOuAD8LGEZT9Nfb/jWlIGtf9IuYm2DoLyr46Jxy91NTdk6Yy4dlN /evznogGSjc1qwVYv17tPgC3cwvOjq9mLlcYkP1ft7w8uDxj/ZtqOb3h0SfpjTNq2yu7 kD2UjE/Vvm5/T2aD4nZzvkJ+rDeOhKQhxNxOMtxpjB8UwfiSjXV5y9cR0VDi35vt9RmU GYNE5g+mxHb1UGMuW3j5USOXM+7DtmqVN815FELhOYEihA8TdCw6nG1TpIR3QlfcwpqZ oBB9t2AiMvMAE2bb7HvkgYnXAIldQ0dJ+uiUrwWX/QAsiLxXxqsBkNhJvhm8tSMF+YV/ Y/Qw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=2SofKRLXs3ghLoKK58NwVVXOpm0/wmnKtTLgHTp8mKg=; b=DWeN3G+FahuSBkkxG6Nq9nI7+M2p5KDW56hk/aSAlq997O4f5GPo42UU0xkZ+wTZiR DIMDPxWDVE5k3PkVMGCkb42N2j0rQhsdrHG+4BDnRkizJW6GEYZrNlgLKg8UKIrmIiJR AjWDtSV/d9aL2LP8R+tGg8PM122QCfijN23rSdgYcQ06E/ecx2xKPZXhK1sj5+tCNEQo bTtbXUs393SOF0WGI7o/OE3IlDd3gQiwd2/Qm+ZLMzZf7eUDhukp/rAMNYkCkQRa1nL+ X9FIDD6zZVHdluOUIn6GvUdBIn4I2l05PsRyh9n2/pYJuTrOhNi3x7YXqkRJiLD8f9xa na2w== X-Gm-Message-State: AOAM533qhIqQb5stPFwHRsQal+I9cowvrIxb9KX+YREkL0Sb1NZgnULr pNVUFtdOLR8S2NqIMPSww7N4tPd+fw== X-Google-Smtp-Source: ABdhPJwkx1Y1tstprI9OSo7OAIG6SpJksw405iCFswtG6uQkT5uGl4v5tDrP+q/NoB5SdlYRyUIUFQ== X-Received: by 2002:a5d:4443:: with SMTP id x3mr8970322wrr.409.1611998420422; Sat, 30 Jan 2021 01:20:20 -0800 (PST) Received: from localhost.localdomain (lfbn-ren-1-785-160.w83-197.abo.wanadoo.fr. [83.197.112.160]) by smtp.gmail.com with ESMTPSA id w14sm16657582wro.86.2021.01.30.01.20.19 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 30 Jan 2021 01:20:19 -0800 (PST) From: Christophe Gisquet To: ffmpeg-devel@ffmpeg.org Date: Sat, 30 Jan 2021 09:19:03 +0000 Message-Id: <20210130091906.312-2-christophe.gisquet@gmail.com> X-Mailer: git-send-email 2.29.2 In-Reply-To: <20210130091906.312-1-christophe.gisquet@gmail.com> References: <20210130091906.312-1-christophe.gisquet@gmail.com> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/4] lav/dnxhd: better support 4:2:0 in DNXHR profiles X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: FFmpeg development discussions and patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Reply-To: FFmpeg development discussions and patches Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" From: Christophe Gisquet Where they are allowed. No validation of profile + colorformat is performed, however. --- libavcodec/dnxhddec.c | 55 +++++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/libavcodec/dnxhddec.c b/libavcodec/dnxhddec.c index c78d55aee5..359588f963 100644 --- a/libavcodec/dnxhddec.c +++ b/libavcodec/dnxhddec.c @@ -49,6 +49,13 @@ typedef struct RowContext { int format; } RowContext; +typedef enum { + DNX_CHROMAFORMAT_422 = 0, + DNX_CHROMAFORMAT_420 = 1, + DNX_CHROMAFORMAT_444 = 2, + DNX_CHROMAFORMAT_UNKNOWN = 3, +} DNXChromaFormat; + typedef struct DNXHDContext { AVCodecContext *avctx; RowContext *rows; @@ -67,7 +74,7 @@ typedef struct DNXHDContext { ScanTable scantable; const CIDEntry *cid_table; int bit_depth; // 8, 10, 12 or 0 if not initialized at all. - int is_444; + int chromafmt; int alpha; int lla; int mbaff; @@ -168,6 +175,7 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, const uint8_t *buf, int buf_size, int first_field) { + static const char* cfname[4] = { "4:2:2", "4:2:0", "4:4:4", "Unknown" }; int i, cid, ret; int old_bit_depth = ctx->bit_depth, bitdepth; uint64_t header_prefix; @@ -234,8 +242,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, av_log(ctx->avctx, AV_LOG_WARNING, "Adaptive color transform in an unsupported profile.\n"); - ctx->is_444 = (buf[0x2C] >> 6) & 1; - if (ctx->is_444) { + ctx->chromafmt = (buf[0x2C] >> 5) & 3; + if (ctx->chromafmt == DNX_CHROMAFORMAT_444) { if (bitdepth == 8) { avpriv_request_sample(ctx->avctx, "4:4:4 8 bits"); return AVERROR_INVALIDDATA; @@ -250,16 +258,16 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, } } else if (bitdepth == 12) { ctx->decode_dct_block = dnxhd_decode_dct_block_12; - ctx->pix_fmt = AV_PIX_FMT_YUV422P12; + ctx->pix_fmt = ctx->chromafmt == DNX_CHROMAFORMAT_420 ? AV_PIX_FMT_YUV420P12 : AV_PIX_FMT_YUV422P12; } else if (bitdepth == 10) { if (ctx->avctx->profile == FF_PROFILE_DNXHR_HQX) ctx->decode_dct_block = dnxhd_decode_dct_block_10_444; else ctx->decode_dct_block = dnxhd_decode_dct_block_10; - ctx->pix_fmt = AV_PIX_FMT_YUV422P10; + ctx->pix_fmt = ctx->chromafmt == DNX_CHROMAFORMAT_420 ? AV_PIX_FMT_YUV420P10 : AV_PIX_FMT_YUV422P10; } else { ctx->decode_dct_block = dnxhd_decode_dct_block_8; - ctx->pix_fmt = AV_PIX_FMT_YUV422P; + ctx->pix_fmt = ctx->chromafmt == DNX_CHROMAFORMAT_420 ? AV_PIX_FMT_YUV420P : AV_PIX_FMT_YUV422P; } ctx->avctx->bits_per_raw_sample = ctx->bit_depth = bitdepth; @@ -292,8 +300,8 @@ static int dnxhd_decode_header(DNXHDContext *ctx, AVFrame *frame, if ((ctx->height + 15) >> 4 == ctx->mb_height && frame->interlaced_frame) ctx->height <<= 1; - av_log(ctx->avctx, AV_LOG_VERBOSE, "%dx%d, 4:%s %d bits, MBAFF=%d ACT=%d\n", - ctx->width, ctx->height, ctx->is_444 ? "4:4" : "2:2", + av_log(ctx->avctx, AV_LOG_VERBOSE, "%dx%d, %s %d bits, MBAFF=%d ACT=%d\n", + ctx->width, ctx->height, cfname[ctx->chromafmt], ctx->bit_depth, ctx->mbaff, ctx->act); // Newer format supports variable mb_scan_index sizes @@ -360,7 +368,7 @@ static av_always_inline int dnxhd_decode_dct_block(const DNXHDContext *ctx, ctx->bdsp.clear_block(block); - if (!ctx->is_444) { + if (ctx->chromafmt != DNX_CHROMAFORMAT_444) { if (n & 2) { component = 1 + (n & 1); scale = row->chroma_scale; @@ -478,6 +486,9 @@ static int dnxhd_decode_dct_block_12_444(const DNXHDContext *ctx, static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, AVFrame *frame, int x, int y) { + static const char yoff[4] = { 1, 0, 1, 0 }; + static const char xoff[4] = { 0, 0, 1, 0 }; + static const uint8_t num_blocks[4] = { 8, 6, 12, 0 }; int shift1 = ctx->bit_depth >= 10; int dct_linesize_luma = frame->linesize[0]; int dct_linesize_chroma = frame->linesize[1]; @@ -516,7 +527,7 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, row->last_qscale = qscale; } - for (i = 0; i < 8 + 4 * ctx->is_444; i++) { + for (i = 0; i < num_blocks[ctx->chromafmt]; i++) { if (ctx->decode_dct_block(ctx, row, i) < 0) return AVERROR_INVALIDDATA; } @@ -526,9 +537,9 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, dct_linesize_chroma <<= 1; } - dest_y = frame->data[0] + ((y * dct_linesize_luma) << 4) + (x << (4 + shift1)); - dest_u = frame->data[1] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444)); - dest_v = frame->data[2] + ((y * dct_linesize_chroma) << 4) + (x << (3 + shift1 + ctx->is_444)); + dest_y = frame->data[0] + ((y * dct_linesize_luma) << 4) + (x << (4 + shift1)); + dest_u = frame->data[1] + ((y * dct_linesize_chroma) << (3 + yoff[ctx->chromafmt])) + (x << (3 + shift1 + xoff[ctx->chromafmt])); + dest_v = frame->data[2] + ((y * dct_linesize_chroma) << (3 + yoff[ctx->chromafmt])) + (x << (3 + shift1 + xoff[ctx->chromafmt])); if (frame->interlaced_frame && ctx->cur_field) { dest_y += frame->linesize[0]; @@ -542,7 +553,8 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, dct_y_offset = interlaced_mb ? frame->linesize[0] : (dct_linesize_luma << 3); dct_x_offset = 8 << shift1; - if (!ctx->is_444) { + switch (ctx->chromafmt) { + case DNX_CHROMAFORMAT_422: ctx->idsp.idct_put(dest_y, dct_linesize_luma, row->blocks[0]); ctx->idsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, row->blocks[1]); ctx->idsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, row->blocks[4]); @@ -555,7 +567,8 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, ctx->idsp.idct_put(dest_u + dct_y_offset, dct_linesize_chroma, row->blocks[6]); ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, row->blocks[7]); } - } else { + break; + case DNX_CHROMAFORMAT_444: ctx->idsp.idct_put(dest_y, dct_linesize_luma, row->blocks[0]); ctx->idsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, row->blocks[1]); ctx->idsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, row->blocks[6]); @@ -572,6 +585,18 @@ static int dnxhd_decode_macroblock(const DNXHDContext *ctx, RowContext *row, ctx->idsp.idct_put(dest_v + dct_y_offset, dct_linesize_chroma, row->blocks[10]); ctx->idsp.idct_put(dest_v + dct_y_offset + dct_x_offset, dct_linesize_chroma, row->blocks[11]); } + break; + case DNX_CHROMAFORMAT_420: + ctx->idsp.idct_put(dest_y, dct_linesize_luma, row->blocks[0]); + ctx->idsp.idct_put(dest_y + dct_x_offset, dct_linesize_luma, row->blocks[1]); + ctx->idsp.idct_put(dest_y + dct_y_offset, dct_linesize_luma, row->blocks[4]); + ctx->idsp.idct_put(dest_y + dct_y_offset + dct_x_offset, dct_linesize_luma, row->blocks[5]); + + if (!(ctx->avctx->flags & AV_CODEC_FLAG_GRAY)) { + ctx->idsp.idct_put(dest_u, dct_linesize_chroma, row->blocks[2]); + ctx->idsp.idct_put(dest_v, dct_linesize_chroma, row->blocks[3]); + } + break; } return 0;