From patchwork Sat Mar 23 17:37:30 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 47379 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c889:b0:1a3:b6bb:3029 with SMTP id hb9csp328616pzb; Sat, 23 Mar 2024 10:38:21 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCWknfoI5DzZN7lF/859IPdKjo8QuEqR/5Fy6NZ77FboJIcXPNs3MtDBVIiQR53j0Cy7GPKSW5+lO56p6pUpRKZ04G4A2FbonVZY8Q== X-Google-Smtp-Source: AGHT+IFP3E1EXt48ufdIC7wOsZPEGbmrtLbAjpkS6SGiCZDSL+/l89EHXEuIWtpQ4LJskmNVFsRo X-Received: by 2002:a2e:b16e:0:b0:2d6:c04b:599f with SMTP id a14-20020a2eb16e000000b002d6c04b599fmr2005265ljm.42.1711215500833; Sat, 23 Mar 2024 10:38:20 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1711215500; cv=none; d=google.com; s=arc-20160816; b=N7RWnig1+CJw6HPU2jYDRoUksGsFbSfpfVfV40nD3PS2OXvN7UvAVrmvmKbH6vwDHH VTip+PN/oDmtW1VXuGku0l6ETD6Ctv7jJ4SfWd+UnQpzXGH6sp8xZ7h0WhCZ03oS19jo IBomMXbhEMieTfuIpWM1rp9TX42eJJJ6gyt/QSdIUlbUcJmYum8A+ydBI0wu9HAJb+7b TH5Oi4SKcBTXZkA/Ba92kZNxtb233H/4LM4QSC39nO7r5zwkwaNBmwgZWq+ZyzCYLy1C l+wlcB/BK/4jeJ2ZXJOQ20Gv/AzjEVdiWmLWPHqtzvCsd9h3gWsFhvrAk2AnCdy4MU/I cSqA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:message-id:date:to:from :dkim-signature:delivered-to; bh=pU03Z2XxKpWP23J52fyJCzZsc4I4praA+7C8EtctMTU=; fh=C56SNERGsx7JRMjLZiHmpTAKnRl/jfaA+FIG9zHupRY=; b=GyFKQJqajSzSA8aAaGyN5fQdeluTxpa4P6ofEdDCtDtJ8KiCIMwJM9kPwhG1iCs6ZZ fOnHnwPjydvKIpD6h6IGyKMTFGGHCS0sZ3skvgUAokAY+tlfn4OCujOFT3h4QUc5KODz ERSHXFZHRPjVggzTjD/Bb0o4KYu5izfDXjjwl1jXiKK1so0T8M0UIyqyvz47MlMufXSG jmslaHEkwCHr0zXRdzt8uAlQPT8XZe7zXHsrkf9KQ4/AHlUmQDnnsWMYyfmO1XppdBQv m1caay2sU7/W9PZbRa6VhgSp3v7n1kIUw6MCADS5kAI7oE/I922UDYVSwVR2YFKrXNPE OP9w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=CqXvsKeB; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id qk25-20020a170906d9d900b00a4735d92ef5si1019078ejb.193.2024.03.23.10.38.20; Sat, 23 Mar 2024 10:38:20 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=CqXvsKeB; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 563CE68D316; Sat, 23 Mar 2024 19:37:52 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1A6EB68D329 for ; Sat, 23 Mar 2024 19:37:42 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1711215461; bh=UV+7GcBmwo5wgEs7bcHEIr2C4JP7DiZE/POvPBQVutg=; h=From:To:Cc:Subject:Date:From; b=CqXvsKeBz/lzDebaVVCu+WmLiPFlPkgKzTXHBGqzBOxOfznnPvqb/8DzYyTOaU6+Z LgHkJwTtsLIQPkkYdBOX/aqJ95D+dRFpoSvfrwyJr1amPLNgVallqSfpQyrg66bMQ/ y6mHcgYpUl3GoSiKche+z4kBzmj/1GuRbpCtWeOQ= Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 168E640015; Sat, 23 Mar 2024 18:37:41 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Sat, 23 Mar 2024 18:37:30 +0100 Message-ID: <20240323173735.26224-1-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.44.0 MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 1/6] avutil/dovi_meta: add AVDOVIDataMapping.nlq_pivots X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: quietvoid , Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 5AiOe300/GDW From: quietvoid The NLQ pivots are not documented but should be present in the header for profile 7 RPU format. It has been verified using Dolby's verification toolkit. Signed-off-by: quietvoid Signed-off-by: Niklas Haas --- doc/APIchanges | 3 +++ libavcodec/dovi_rpu.c | 9 ++++++++- libavutil/dovi_meta.h | 1 + libavutil/version.h | 2 +- 4 files changed, 13 insertions(+), 2 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 2796b4d0c25..739f33501e9 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,9 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-03-xx - xxxxxxxxxx - lavu 59.5.100 - dovi_meta.h + Add AVDOVIDataMapping.nlq_pivots. + 2024-03-xx - xxxxxxxxxx - lavc 61.3.100 - jni.h Add av_jni_set_android_app_ctx() and av_jni_get_android_app_ctx(). diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c index 31c64fb0602..c84a942f476 100644 --- a/libavcodec/dovi_rpu.c +++ b/libavcodec/dovi_rpu.c @@ -109,7 +109,7 @@ int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame) /* Copy only the parts of these structs known to us at compiler-time. */ #define COPY(t, a, b, last) memcpy(a, b, offsetof(t, last) + sizeof((b)->last)) COPY(AVDOVIRpuDataHeader, av_dovi_get_header(dovi), &s->header, disable_residual_flag); - COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq[2].linear_deadzone_threshold); + COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq_pivots); COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal); return 0; } @@ -346,7 +346,14 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) } if (use_nlq) { + int nlq_pivot = 0; vdr->mapping.nlq_method_idc = get_bits(gb, 3); + + for (int i = 0; i < 2; i++) { + nlq_pivot += get_bits(gb, hdr->bl_bit_depth); + vdr->mapping.nlq_pivots[i] = av_clip_uint16(nlq_pivot); + } + /** * The patent mentions another legal value, NLQ_MU_LAW, but it's * not documented anywhere how to parse or apply that type of NLQ. diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h index 3d11e02bffc..6afc7b055a7 100644 --- a/libavutil/dovi_meta.h +++ b/libavutil/dovi_meta.h @@ -147,6 +147,7 @@ typedef struct AVDOVIDataMapping { uint32_t num_x_partitions; uint32_t num_y_partitions; AVDOVINLQParams nlq[3]; /* per component */ + uint16_t nlq_pivots[2]; /* nlq_pred_pivot_value */ } AVDOVIDataMapping; /** diff --git a/libavutil/version.h b/libavutil/version.h index 882003f7199..8a1ecd44516 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 4 +#define LIBAVUTIL_VERSION_MINOR 5 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From patchwork Sat Mar 23 17:37:31 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 47377 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c889:b0:1a3:b6bb:3029 with SMTP id hb9csp328558pzb; Sat, 23 Mar 2024 10:38:12 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCWZWNsafp4oTu4916w2kkQB31GQQ067+OS9KaMXqHfEVt61mtn26B2LqkDy0sL70rqSctHJNawimuuPLRMb9MFvrJb39ITsDlJMAw== X-Google-Smtp-Source: AGHT+IGlrTTdtAhth8fldH/MZ1JlwMdv52MpvDcQHo5ucEFAluNdn2O0bsWfEnfm+WPfBMSgem21 X-Received: by 2002:a50:a69b:0:b0:565:f7c7:f23c with SMTP id e27-20020a50a69b000000b00565f7c7f23cmr2347649edc.3.1711215492599; Sat, 23 Mar 2024 10:38:12 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1711215492; cv=none; d=google.com; s=arc-20160816; b=cKzB5xRJ25kAk+VwbR6QxuygUvacwSBHplh0V+mDje8LADAk/BHQAELdwi8nF11DVs vI1sLklvu8CJ0Bn2NP4AxDBDRAzdm1aREhoZ4IdaHs36QRMV+Vpn+TzKpEtlF8kBT++i k/UT/q+bq9egSBCC5eyCpnJzr6vRqFDgmELQN9hAa0CxwthUTzBh5gWbGGMOAQrm+3KJ RkLFmm8tz6HMnMjKOoLYEqDMK9/n5IQCVXupELEzZTluz0HUkvmWD0FegLZce8gxy4fL hUVebSbhJowpHLusysvfZGLCekJJSpGYfv88qJ0bmJx005USlnR/4CmWlicgrn7TZuS6 x6WA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=ey11Nj+I03JQuX1FKLpaG2c9GKWm7azXkZ+P8NNve0o=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=zIgK/ZhnuV9O/wd/o3xr8pod1xoE1ic5Pb3vIawWar77rytNroB4AfpBFIydIGSpv0 7CtqE3fqfDgdsxZQpw8cXAxGQ+MINkUnc/ZaeM/uAUmTlEEWfqXJ9/5yVmfdS2FIMgt0 kmkMMEKxVcsgNEgsk3ErqpOwNykxDIyLdt0LDpIWFCfd9NINZSxOblaad8EMvofZuo1F nSO0fbBMF9ZAa/MlA27Hpa6oIZFZqlnDKnKidlQiOdH82VwqS7G/hHf6I+McV8dsM0Fh UmiEk4k7IeW8hypiZbb62ie9+ptRNNgQ/9zp/0Enn4Lrj1ZOAdFiEVU13R1NKeCX24A5 8YQg==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=FryFZgwv; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id dk14-20020a0564021d8e00b00568beae376asi970654edb.586.2024.03.23.10.38.12; Sat, 23 Mar 2024 10:38:12 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=FryFZgwv; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3472E68D42A; Sat, 23 Mar 2024 19:37:51 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1D65C68D32A for ; Sat, 23 Mar 2024 19:37:42 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1711215461; bh=I7IxDp6Quyiej5LEb/7s4hnQ9i1t1imgmvaq78LEgRk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=FryFZgwvM2ekxsymrvVgtvB/zofZsHSMvajZfepI59DTMrZ1zEQnGPz4A+VLZ+TzB wZIpFCnsABRUlm0FH5aSm74wc8mf6EQcAgmaV3DcaT7o55VE19pDpuqVa44AqBmsg1 lJ9qODrh5TQSf50U1wgrA3a5JTAqrvjn6CLOXEH8= Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 4D9C642824; Sat, 23 Mar 2024 18:37:41 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Sat, 23 Mar 2024 18:37:31 +0100 Message-ID: <20240323173735.26224-2-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240323173735.26224-1-ffmpeg@haasn.xyz> References: <20240323173735.26224-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 2/6] avutil/dovi_meta: add dolby vision extension blocks X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 5VnyE4qreDZA From: Niklas Haas As well as accessors plus a function for allocating this struct with extension blocks, Definitions generously taken from quietvoid/dovi_tool, which is assembled as a collection of various patent fragments, as well as output by the official Dolby Vision bitstream verifier tool. --- doc/APIchanges | 5 ++ libavutil/dovi_meta.c | 36 ++++++++-- libavutil/dovi_meta.h | 154 ++++++++++++++++++++++++++++++++++++++++++ libavutil/version.h | 2 +- 4 files changed, 190 insertions(+), 7 deletions(-) diff --git a/doc/APIchanges b/doc/APIchanges index 739f33501e9..8b59150dc1f 100644 --- a/doc/APIchanges +++ b/doc/APIchanges @@ -2,6 +2,11 @@ The last version increases of all libraries were on 2024-03-07 API changes, most recent first: +2024-03-xx - xxxxxxxxxx - lavu 59.6.100 - dovi_meta.h + Add AVDOVIMetadata.ext_block_{offset,size}, AVDOVIMetadata.num_ext_blocks, + AVDOVIDmData and AVDOVIDmLevel{1..6,8..11,254..255}, av_dovi_get_ext(), + av_dovi_find_level() and av_dovi_metadata_alloc_ext(), + 2024-03-xx - xxxxxxxxxx - lavu 59.5.100 - dovi_meta.h Add AVDOVIDataMapping.nlq_pivots. diff --git a/libavutil/dovi_meta.c b/libavutil/dovi_meta.c index 9c50da561ed..17e18bf95f9 100644 --- a/libavutil/dovi_meta.c +++ b/libavutil/dovi_meta.c @@ -18,6 +18,8 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ +#include + #include "dovi_meta.h" #include "mem.h" @@ -39,22 +41,44 @@ typedef struct AVDOVIMetadataInternal { AVDOVIRpuDataHeader header; AVDOVIDataMapping mapping; AVDOVIColorMetadata color; + AVDOVIDmData ext_blocks[]; } AVDOVIMetadataInternal; -AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size) +AVDOVIMetadata *av_dovi_metadata_alloc_ext(int num_ext_blocks, size_t *size) { - AVDOVIMetadataInternal *dovi = av_mallocz(sizeof(AVDOVIMetadataInternal)); + const size_t alloc_size = sizeof(AVDOVIMetadataInternal) + + num_ext_blocks * sizeof(AVDOVIDmData); + + AVDOVIMetadataInternal *dovi = av_mallocz(alloc_size); if (!dovi) return NULL; if (size) - *size = sizeof(*dovi); + *size = alloc_size; dovi->metadata = (struct AVDOVIMetadata) { - .header_offset = offsetof(AVDOVIMetadataInternal, header), - .mapping_offset = offsetof(AVDOVIMetadataInternal, mapping), - .color_offset = offsetof(AVDOVIMetadataInternal, color), + .header_offset = offsetof(AVDOVIMetadataInternal, header), + .mapping_offset = offsetof(AVDOVIMetadataInternal, mapping), + .color_offset = offsetof(AVDOVIMetadataInternal, color), + .ext_block_offset = offsetof(AVDOVIMetadataInternal, ext_blocks), + .ext_block_size = sizeof(AVDOVIDmData), }; return &dovi->metadata; } + +AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size) +{ + return av_dovi_metadata_alloc_ext(0, size); +} + +AVDOVIDmData *av_dovi_find_level(const AVDOVIMetadata *data, uint8_t level) +{ + for (int i = 0; i < data->num_ext_blocks; i++) { + AVDOVIDmData *ext = av_dovi_get_ext(data, i); + if (ext->level == level) + return ext; + } + + return NULL; +} diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h index 6afc7b055a7..e77d9853f67 100644 --- a/libavutil/dovi_meta.h +++ b/libavutil/dovi_meta.h @@ -29,7 +29,9 @@ #include #include + #include "rational.h" +#include "csp.h" /* * DOVI configuration @@ -187,6 +189,130 @@ typedef struct AVDOVIColorMetadata { uint16_t source_diagonal; } AVDOVIColorMetadata; +typedef struct AVDOVIDmLevel1 { + /* Per-frame brightness metadata */ + uint16_t min_pq; + uint16_t max_pq; + uint16_t avg_pq; +} AVDOVIDmLevel1; + +typedef struct AVDOVIDmLevel2 { + /* Usually derived from level 8 (at different levels) */ + uint16_t target_max_pq; + uint16_t trim_slope; + uint16_t trim_offset; + uint16_t trim_power; + uint16_t trim_chroma_weight; + uint16_t trim_saturation_gain; + int16_t ms_weight; +} AVDOVIDmLevel2; + +typedef struct AVDOVIDmLevel3 { + uint16_t min_pq_offset; + uint16_t max_pq_offset; + uint16_t avg_pq_offset; +} AVDOVIDmLevel3; + +typedef struct AVDOVIDmLevel4 { + uint16_t anchor_pq; + uint16_t anchor_power; +} AVDOVIDmLevel4; + +typedef struct AVDOVIDmLevel5 { + /* Active area definition */ + uint16_t left_offset; + uint16_t right_offset; + uint16_t top_offset; + uint16_t bottom_offset; +} AVDOVIDmLevel5; + +typedef struct AVDOVIDmLevel6 { + /* Static HDR10 metadata */ + uint16_t max_luminance; + uint16_t min_luminance; + uint16_t max_cll; + uint16_t max_fall; +} AVDOVIDmLevel6; + +typedef struct AVDOVIDmLevel8 { + /* Extended version of level 2 */ + uint8_t target_display_index; + uint16_t trim_slope; + uint16_t trim_offset; + uint16_t trim_power; + uint16_t trim_chroma_weight; + uint16_t trim_saturation_gain; + uint16_t ms_weight; + uint16_t target_mid_contrast; + uint16_t clip_trim; + uint8_t saturation_vector_field[6]; + uint8_t hue_vector_field[6]; +} AVDOVIDmLevel8; + +typedef struct AVDOVIDmLevel9 { + /* Source display characteristics */ + uint8_t source_primary_index; + AVColorPrimariesDesc source_display_primaries; +} AVDOVIDmLevel9; + +typedef struct AVDOVIDmLevel10 { + /* Target display characteristics */ + uint8_t target_display_index; + uint16_t target_max_pq; + uint16_t target_min_pq; + uint8_t target_primary_index; + AVColorPrimariesDesc target_display_primaries; +} AVDOVIDmLevel10; + +typedef struct AVDOVIDmLevel11 { + uint8_t content_type; + uint8_t whitepoint; + uint8_t reference_mode_flag; + uint8_t sharpness; + uint8_t noise_reduction; + uint8_t mpeg_noise_reduction; + uint8_t frame_rate_conversion; + uint8_t brightness; + uint8_t color; +} AVDOVIDmLevel11; + +typedef struct AVDOVIDmLevel254 { + /* DMv2 info block, always present in samples with DMv2 metadata */ + uint8_t dm_mode; + uint8_t dm_version_index; +} AVDOVIDmLevel254; + +typedef struct AVDOVIDmLevel255 { + /* Debug block, not really used in samples */ + uint8_t dm_run_mode; + uint8_t dm_run_version; + uint8_t dm_debug[4]; +} AVDOVIDmLevel255; + +/** + * Dolby Vision metadata extension block. + * + * @note sizeof(AVDOVIDmData) is not part of the public API. + */ +typedef struct AVDOVIDmData { + uint8_t level; /* [1, 255] */ + union { + AVDOVIDmLevel1 l1; + AVDOVIDmLevel2 l2; /* may appear multiple times */ + AVDOVIDmLevel3 l3; + AVDOVIDmLevel4 l4; + AVDOVIDmLevel5 l5; + AVDOVIDmLevel6 l6; + /* level 7 is currently unused */ + AVDOVIDmLevel8 l8; /* may appear multiple times */ + AVDOVIDmLevel9 l9; + AVDOVIDmLevel10 l10; /* may appear multiple times */ + AVDOVIDmLevel11 l11; + AVDOVIDmLevel254 l254; + AVDOVIDmLevel255 l255; + }; +} AVDOVIDmData; + /** * Combined struct representing a combination of header, mapping and color * metadata, for attaching to frames as side data. @@ -203,6 +329,10 @@ typedef struct AVDOVIMetadata { size_t header_offset; /* AVDOVIRpuDataHeader */ size_t mapping_offset; /* AVDOVIDataMapping */ size_t color_offset; /* AVDOVIColorMetadata */ + + size_t ext_block_offset; /* offset to start of ext blocks array */ + size_t ext_block_size; /* size per element */ + int num_ext_blocks; /* number of extension blocks */ } AVDOVIMetadata; static av_always_inline AVDOVIRpuDataHeader * @@ -223,6 +353,19 @@ av_dovi_get_color(const AVDOVIMetadata *data) return (AVDOVIColorMetadata *)((uint8_t *) data + data->color_offset); } +static av_always_inline AVDOVIDmData * +av_dovi_get_ext(const AVDOVIMetadata *data, int index) +{ + return (AVDOVIDmData *)((uint8_t *) data + data->ext_block_offset + + data->ext_block_size * index); +} + +/** + * Find an extension block with a given level, or NULL. In the case of + * multiple extension blocks, only the first is returned. + */ +AVDOVIDmData *av_dovi_find_level(const AVDOVIMetadata *data, uint8_t level); + /** * Allocate an AVDOVIMetadata structure and initialize its * fields to default values. @@ -234,4 +377,15 @@ av_dovi_get_color(const AVDOVIMetadata *data) */ AVDOVIMetadata *av_dovi_metadata_alloc(size_t *size); +/** + * Allocate an AVDOVIMetadata with a given number of extension blocks. + * + * @param num_ext_blocks The number of extension blocks to allocate + * @param size If this parameter is non-NULL, the size in bytes of the + * allocated struct will be written here on success + * + * @return the newly allocated struct or NULL on failure + */ +AVDOVIMetadata *av_dovi_metadata_alloc_ext(int num_ext_blocks, size_t *size); + #endif /* AVUTIL_DOVI_META_H */ diff --git a/libavutil/version.h b/libavutil/version.h index 8a1ecd44516..f874a4fd439 100644 --- a/libavutil/version.h +++ b/libavutil/version.h @@ -79,7 +79,7 @@ */ #define LIBAVUTIL_VERSION_MAJOR 59 -#define LIBAVUTIL_VERSION_MINOR 5 +#define LIBAVUTIL_VERSION_MINOR 6 #define LIBAVUTIL_VERSION_MICRO 100 #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \ From patchwork Sat Mar 23 17:37:32 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 47376 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c889:b0:1a3:b6bb:3029 with SMTP id hb9csp328516pzb; Sat, 23 Mar 2024 10:38:04 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCULGnohP3lyGLb3+0VZyo4FGK19norpRkCF/x3CkWhVDJH6Y3R10kSSl+ZXkGHbfMb1ajC0Ejl71blYXUgMDeZvCDeIggqR7bwzVg== X-Google-Smtp-Source: AGHT+IHR9o0osgVlc05HUeBvEIQa892FDvz+qxMpONVJTj4W7KdZQ1v3dUQf5ZPbPbuqKVai4DFU X-Received: by 2002:a05:6512:282:b0:515:9578:d3bb with SMTP id j2-20020a056512028200b005159578d3bbmr1609967lfp.69.1711215483932; Sat, 23 Mar 2024 10:38:03 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1711215483; cv=none; d=google.com; s=arc-20160816; b=KmorhNwtFXz/83j/jsyQgbeKOY8X/pJU/5I3oxp4bKfLvyAo4QHCoGU1tAMcZlCocR rr8kTwAtRf27f+wpLBvepWiLQg2FHknDR924q9skA3APFRlC98DiN6LbKa2MFwwAV0jh 9cT3dEOaMvYxuOHz8E/wuFNlr/M0kR4WwYS9vxxH4BAWwfR+vWoz26YUEuWYhVcaUZtr 8RvxOBRatsc1HXvyzzpDnSrV4IxaUZejKBxtmnmaMYhQzrIsB6tj6Q5gxO/ixKMh8hhF wXehYvMTOqI2tdhghLIWxfwgbVOTcbclE2SHHOf91zhIZpOPc0joBPcYTdDkxDpo3K2z lbnA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=QmxjolZaYijgoWJt453sEkcydLgAaxGzfuRrKKhOXzQ=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=S0mZ8dLd3WZ9INBUxuPDeOBoYrfD5+0brCaoyXKRFi8q4al2mkhAgoUTiXMBOhUF18 ME8yRIIFZPSO0YDAKH1t4CU+NHlWQ+l35m21hZuaJm4kT8I6BGHPoFhTCiMEubRruulx fvw0IFZj9+X7doY0s1/lGZY6cecbvCCCFCCy2zG/0yh7T9cCoOmvM7675vBEvU5Y1a9C drpHfOfKONa9ZEjQdfk5g4iTNtvlnj3d4PGuJawu5CYWsd+/G1xSZySt3L0AHG1QAm9H 9T+SvRpdCRvtbd2toAkCkXpVmiMiMju1/BI0sZ+HRCeM0BVd4W+cemICYInfWx8/lvtA Wh7w==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b="uLO/dIdr"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id s2-20020a170906454200b00a4653cc39fesi973557ejq.829.2024.03.23.10.38.03; Sat, 23 Mar 2024 10:38:03 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b="uLO/dIdr"; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 29F0568D3F1; Sat, 23 Mar 2024 19:37:50 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1803768D326 for ; Sat, 23 Mar 2024 19:37:42 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1711215461; bh=W381fYEgYXdI81GoAsyaxPbQgqCIJAYDoxfq0UVU/ac=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=uLO/dIdrwW9kObPuPllUvZcQNljY6HokyULyknYObMFDs33H1VMUomTtJgkoARkMQ UOGntX4jVNH3iXC+HBIiguxfl3yMCuexKRqz+OKXBcZgS7sumKPpdJEZG9ylXj7jAV 5BelYHVnsQc+cr+B8pXXikTPY+Aax3/TTCvFvfJk= Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 83462428A0; Sat, 23 Mar 2024 18:37:41 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Sat, 23 Mar 2024 18:37:32 +0100 Message-ID: <20240323173735.26224-3-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240323173735.26224-1-ffmpeg@haasn.xyz> References: <20240323173735.26224-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 3/6] avcodec/dovi_rpu: strip container in separate step X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: 0D95mbHFX4BO From: Niklas Haas This ensures that `gb` in the following section is fully byte-aligned, points at the start of the actual RPU, and ends on the CRC terminator. This is important for both calculation of the CRC, as well as dovi extension block parsing (which aligns to byte boundaries in various places). --- libavcodec/dovi_rpu.c | 48 +++++++++++++++++++++++++++++++++++-------- libavcodec/dovi_rpu.h | 2 ++ 2 files changed, 41 insertions(+), 9 deletions(-) diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c index c84a942f476..24a1cdf39a8 100644 --- a/libavcodec/dovi_rpu.c +++ b/libavcodec/dovi_rpu.c @@ -23,6 +23,7 @@ #include "libavutil/buffer.h" +#include "avcodec.h" #include "dovi_rpu.h" #include "golomb.h" #include "get_bits.h" @@ -45,6 +46,7 @@ void ff_dovi_ctx_unref(DOVIContext *s) { for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr); i++) ff_refstruct_unref(&s->vdr[i]); + av_free(s->rpu_buf); *s = (DOVIContext) { .logctx = s->logctx, @@ -202,17 +204,17 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) DOVIVdr *vdr; int ret; - uint8_t nal_prefix; uint8_t rpu_type; uint8_t vdr_seq_info_present; uint8_t vdr_dm_metadata_present; uint8_t use_prev_vdr_rpu; uint8_t use_nlq; uint8_t profile; - if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) - return ret; - /* Container header */ + if (rpu_size < 5) + goto fail; + + /* Container */ if (s->dv_profile == 10 /* dav1.10 */) { /* DV inside AV1 re-uses an EMDF container skeleton, but with fixed * values - so we can effectively treat this as a magic byte sequence. @@ -229,18 +231,46 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) * discard_unknown_payload : f(1) = 1 */ const unsigned header_magic = 0x01be6841u; - unsigned header, emdf_payload_size; - header = get_bits_long(gb, 27); - VALIDATE(header, header_magic, header_magic); + unsigned emdf_header, emdf_payload_size, emdf_protection; + if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) + return ret; + emdf_header = get_bits_long(gb, 27); + VALIDATE(emdf_header, header_magic, header_magic); emdf_payload_size = get_variable_bits(gb, 8); VALIDATE(emdf_payload_size, 6, 512); if (emdf_payload_size * 8 > get_bits_left(gb)) return AVERROR_INVALIDDATA; + + /* The payload is not byte-aligned (off by *one* bit, curse Dolby), + * so copy into a fresh buffer to preserve byte alignment of the + * RPU struct */ + av_fast_padded_malloc(&s->rpu_buf, &s->rpu_buf_sz, emdf_payload_size); + if (!s->rpu_buf) + return AVERROR(ENOMEM); + for (int i = 0; i < emdf_payload_size; i++) + s->rpu_buf[i] = get_bits(gb, 8); + rpu = s->rpu_buf; + rpu_size = emdf_payload_size; + + /* Validate EMDF footer */ + emdf_protection = get_bits(gb, 5 + 12); + VALIDATE(emdf_protection, 0x400, 0x400); + + if ((ret = init_get_bits8(gb, s->rpu_buf, emdf_payload_size)) < 0) + return ret; } else { - nal_prefix = get_bits(gb, 8); - VALIDATE(nal_prefix, 25, 25); + /* NAL RBSP with prefix and trailing zeroes */ + VALIDATE(rpu[0], 25, 25); /* NAL prefix */ + rpu++; + rpu_size--; + /* Strip trailing padding bytes */ + while (rpu_size && rpu[rpu_size - 1] == 0) + rpu_size--; } + if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) + return ret; + /* RPU header */ rpu_type = get_bits(gb, 6); if (rpu_type != 2) { diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h index 51c5fdbb879..506974a74bf 100644 --- a/libavcodec/dovi_rpu.h +++ b/libavcodec/dovi_rpu.h @@ -49,6 +49,8 @@ typedef struct DOVIContext { */ struct DOVIVdr *vdr[DOVI_MAX_DM_ID+1]; ///< RefStruct references uint8_t dv_profile; + uint8_t *rpu_buf; ///< temporary buffer + unsigned rpu_buf_sz; } DOVIContext; From patchwork Sat Mar 23 17:37:33 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 47378 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c889:b0:1a3:b6bb:3029 with SMTP id hb9csp328572pzb; Sat, 23 Mar 2024 10:38:14 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUi6YSQq5AXhxRZ7uI63y7PY3CH1gk+THPJkmunzCEgkz2SJufBddvzj4PNfr4TqFK4Y2hXLZRiWooLTrEe+qu50VDiTeVveWUFMg== X-Google-Smtp-Source: AGHT+IHeO4v0y3WMjMpbTZB+wq0t4ekvuVq9m2kb46miQqJp1M97FFTYCRWLAX/OeYKaZBqYzMdR X-Received: by 2002:a17:907:970a:b0:a47:4750:32bf with SMTP id jg10-20020a170907970a00b00a47475032bfmr1491134ejc.2.1711215473915; Sat, 23 Mar 2024 10:37:53 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1711215473; cv=none; d=google.com; s=arc-20160816; b=JAqHmpM98jLK3TYlOoL6q0KGxlx+5+myK+qZgBVu6PdRHVGTfO5obuSM7BOAtYXJIC D0pciICi2O/7Bma+cWAPPD2cKeQKhudUmOrTxuBcrNajItaws+SPhbIDdW2eUYwnJXZd ff/K2iHN3K1Hhj0iYrmainsh0p5Ho3MjJeqiFt6iY8wSdSogU4jZbhKaPKbDvMIluu6S GoiaXdpH5+1EIWJOcvWZUty4sddGPXqoqcr7HRAAig8guym3N7c34PztsjCykv6b0AV5 nsUtJH8hyhUSR8a6IdAaYe2RHdvFpwEjtcu0M8JDCqv21x8TvM+rPtI2jBIoIoMH20hu 4/Nw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=VXNkekXfBGYKp0uSisL6zdZ2Daf0Cl6+R+gnZcQLosE=; fh=C56SNERGsx7JRMjLZiHmpTAKnRl/jfaA+FIG9zHupRY=; b=hncbtNJJ6bKtLdMJHA7d03Wy2a1ikx+E8vbzipVKqEo+bLJ8xhDyiVm9d+ILCkZaNV I2/LfZ3eZB6OVQ6v2uKE6WgFg+G8FrIsh24eEHYT55AEULSnsvytKqZCrCe4sykvHXTW BzUEHEEDFctIUWUFeZuSseVsR46IiiRuV9dXYoiTIK1w4TKJbd+G9qU7xcZcYw782xm8 fA+LWn5lceq12lw+26rnm7C/vYd2UE8HsZKe7aV+67SgOAWnL5/8MZenGm+nUaxXUjJP Ur4FtfzT3g+2+Aj3LcQFXI7FAskyvlWXNxwdcGrRErDp1Kyuki3Aas4qGIk2BoGPsi83 Hapw==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=KHbY1YaM; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id v24-20020a1709064e9800b00a473a9525a8si908418eju.83.2024.03.23.10.37.53; Sat, 23 Mar 2024 10:37:53 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=KHbY1YaM; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id E0E9868D3BA; Sat, 23 Mar 2024 19:37:48 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 1541F68D316 for ; Sat, 23 Mar 2024 19:37:42 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1711215461; bh=MXsJoaPbcoJS8laj3T/eCHtsE1/le0QYVLof2JQULXw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=KHbY1YaM8Y8cZKtU6SpN7XSgRXmHhScCMzoUHnYY1/OQa8D11KB7gJragWlkGv6Y9 74MIBbQdKejDvKlxj9lkCBIDuQyw8/7WA7JAMsUhYlTl6IuTTC0YMiTf5VO67hcne/ Bv+//yWIn48q/lXAhjyF+a53ty/TWumqWZcsCVtI= Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id B6724429D1; Sat, 23 Mar 2024 18:37:41 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Sat, 23 Mar 2024 18:37:33 +0100 Message-ID: <20240323173735.26224-4-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240323173735.26224-1-ffmpeg@haasn.xyz> References: <20240323173735.26224-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 4/6] avcodec/dovi_rpu: verify RPU data CRC32 X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: quietvoid , Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: SjThsB7Xkzki From: Niklas Haas The Dolby Vision RPU contains a CRC32 to validate the payload against. The implementation is CRC32/MPEG-2. The CRC is only verified with the AV_EF_CRCCHECK flag. Co-authored-by: quietvoid --- libavcodec/av1dec.c | 3 ++- libavcodec/dovi_rpu.c | 18 ++++++++++++++++-- libavcodec/dovi_rpu.h | 3 ++- libavcodec/hevcdec.c | 3 ++- libavcodec/libdav1d.c | 3 ++- 5 files changed, 24 insertions(+), 6 deletions(-) diff --git a/libavcodec/av1dec.c b/libavcodec/av1dec.c index 4d074c39087..bff921a12b2 100644 --- a/libavcodec/av1dec.c +++ b/libavcodec/av1dec.c @@ -1001,7 +1001,8 @@ static int export_itut_t35(AVCodecContext *avctx, AVFrame *frame, provider_oriented_code != 0x800) break; - ret = ff_dovi_rpu_parse(&s->dovi, gb.buffer, gb.buffer_end - gb.buffer); + ret = ff_dovi_rpu_parse(&s->dovi, gb.buffer, gb.buffer_end - gb.buffer, + avctx->err_recognition); if (ret < 0) { av_log(avctx, AV_LOG_WARNING, "Error parsing DOVI OBU.\n"); break; // ignore diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c index 24a1cdf39a8..cd54c8716dc 100644 --- a/libavcodec/dovi_rpu.c +++ b/libavcodec/dovi_rpu.c @@ -22,6 +22,7 @@ */ #include "libavutil/buffer.h" +#include "libavutil/crc.h" #include "avcodec.h" #include "dovi_rpu.h" @@ -197,7 +198,8 @@ static inline unsigned get_variable_bits(GetBitContext *gb, int n) } \ } while (0) -int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size, + int err_recognition) { AVDOVIRpuDataHeader *hdr = &s->header; GetBitContext *gb = &(GetBitContext){0}; @@ -268,6 +270,19 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) rpu_size--; } + if (!rpu_size || rpu[rpu_size - 1] != 0x80) + goto fail; + + if (err_recognition & AV_EF_CRCCHECK) { + uint32_t crc = av_bswap32(av_crc(av_crc_get_table(AV_CRC_32_IEEE), + -1, rpu, rpu_size - 1)); /* exclude 0x80 */ + if (crc) { + av_log(s->logctx, AV_LOG_ERROR, "RPU CRC mismatch: %X\n", crc); + if (err_recognition & AV_EF_EXPLODE) + goto fail; + } + } + if ((ret = init_get_bits8(gb, rpu, rpu_size)) < 0) return ret; @@ -508,7 +523,6 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size) color->source_diagonal = get_bits(gb, 10); } - /* FIXME: verify CRC32, requires implementation of AV_CRC_32_MPEG_2 */ return 0; fail: diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h index 506974a74bf..f88fbf9b558 100644 --- a/libavcodec/dovi_rpu.h +++ b/libavcodec/dovi_rpu.h @@ -79,7 +79,8 @@ void ff_dovi_update_cfg(DOVIContext *s, const AVDOVIDecoderConfigurationRecord * * * Returns 0 or an error code. */ -int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size); +int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size, + int err_recognition); /** * Attach the decoded AVDOVIMetadata as side data to an AVFrame. diff --git a/libavcodec/hevcdec.c b/libavcodec/hevcdec.c index 76aa6b45882..ebd70eda234 100644 --- a/libavcodec/hevcdec.c +++ b/libavcodec/hevcdec.c @@ -3193,7 +3193,8 @@ static int decode_nal_units(HEVCContext *s, const uint8_t *buf, int length) return AVERROR(ENOMEM); memcpy(s->rpu_buf->data, nal->raw_data + 2, nal->raw_size - 2); - ret = ff_dovi_rpu_parse(&s->dovi_ctx, nal->data + 2, nal->size - 2); + ret = ff_dovi_rpu_parse(&s->dovi_ctx, nal->data + 2, nal->size - 2, + s->avctx->err_recognition); if (ret < 0) { av_buffer_unref(&s->rpu_buf); av_log(s->avctx, AV_LOG_WARNING, "Error parsing DOVI NAL unit.\n"); diff --git a/libavcodec/libdav1d.c b/libavcodec/libdav1d.c index 17b0743cf0c..af95e46c343 100644 --- a/libavcodec/libdav1d.c +++ b/libavcodec/libdav1d.c @@ -567,7 +567,8 @@ static int libdav1d_receive_frame(AVCodecContext *c, AVFrame *frame) provider_oriented_code != 0x800) break; - res = ff_dovi_rpu_parse(&dav1d->dovi, gb.buffer, gb.buffer_end - gb.buffer); + res = ff_dovi_rpu_parse(&dav1d->dovi, gb.buffer, gb.buffer_end - gb.buffer, + c->err_recognition); if (res < 0) { av_log(c, AV_LOG_WARNING, "Error parsing DOVI OBU.\n"); break; // ignore From patchwork Sat Mar 23 17:37:34 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 47380 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c889:b0:1a3:b6bb:3029 with SMTP id hb9csp328659pzb; Sat, 23 Mar 2024 10:38:29 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCXulpTqN3zhkvoPiYWT8gaRr2iVeQLrEskUXfiiEXgLcplNcr0Pftqmm8LXmzcNCQlVcug9GicsLazTvQEFsd4ryuPDufSGN0Cdzg== X-Google-Smtp-Source: AGHT+IFdQPFiDiOOHs/qikemaGPrDOUEeLhst6itS8OvFLXfmBczzqL+HMrYzqoKGIfRiENJNFrX X-Received: by 2002:a50:9f65:0:b0:56b:f954:35da with SMTP id b92-20020a509f65000000b0056bf95435damr1295528edf.20.1711215509438; Sat, 23 Mar 2024 10:38:29 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1711215509; cv=none; d=google.com; s=arc-20160816; b=XkVuN411bA28UWdBG909K2ciTd5OTBLNa0P663ndR1znsXaw5L4/+ynJfHkv0sp1ML NFfVNELZqFpDZ04xI56LNdm0QGVSGdTMWKK9CiclCKc2HOZ373gjxNn4A3/3P9EJptd8 MEbiZr4FO/ReAGOgfTT/XRnHlztvUZ0wAsmQM0SXkO8vhRtAmW9wKw0yxZp9kOkhml2X MfVjU/VsoHTp0HmgolzOH8kBYEY8sanmzAceQ8QYDSdmPY7hxLp/FvAvlXFGoFqb4KA6 ZoD/Ej1bMfLGC7br7B43z92GpBviCmT4ldWUBQyUIwWaRZFFP8Di/j2orpKck7rjl0vC TnGw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=skKY32FP8RSElmnrHG2QYk+SBCvrn2UipxCYmGJYPuA=; fh=xmAeKtysnShNOmkhiJmYkS30uw4Fu2hvBJ7qlIwukxQ=; b=EM1AjbHEcOn/d7BQtB/u9uUOTHmUMvldIxPLmJAT510nHCqadxLMrWr36OwlCy7o+c +9uhdsf2kMyIF9chZH8n86vSKa/kDprv6vJYllNjBpOtcw3LK/s3kmGX93vQufowYR8e WAo6zHUoekcGzGKGkA5jDsh7A45VoJscpWbeiVnLc3SgOJHI88FDg66iOpv3sxBb5n7e hcrZeWBjRvmxJVSet2pbH7DhusXxEcJhaOztjgI5CIojiR9E0thGrdBeQ+uQ78AyoL5e yosVJeffT6PEKkdKrjUw4PsapGwpoAanuoaqLi79JdnCcSkEAr85LGlx6zJ4Gx1rieVm p/Ew==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=RUYhGc5i; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id y7-20020a056402440700b00567f8c8b3fdsi1040590eda.275.2024.03.23.10.38.29; Sat, 23 Mar 2024 10:38:29 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=RUYhGc5i; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 9EC1168D47E; Sat, 23 Mar 2024 19:37:53 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 3409968D33F for ; Sat, 23 Mar 2024 19:37:42 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1711215462; bh=QBzakJp46eM72L5l2pDevG8laU7rCQxT75HJiFeudnk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=RUYhGc5iIBQCT/++QggxUJe/Tk/4VTBD5PPk+Gh2j27DMhvhnEngYSU7yrwYJAOqL 679zmRLjXsPWfHnW5ov1GpSgT8t4q2kwpBDMx2T2MtPQfP4tcXHhFXFVe0ovO0mGNE 71AHp0vZBsykYv3L21UBpjMWDvZQKsKaGYwZL9OM= Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id EBD05429E8; Sat, 23 Mar 2024 18:37:41 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Sat, 23 Mar 2024 18:37:34 +0100 Message-ID: <20240323173735.26224-5-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240323173735.26224-1-ffmpeg@haasn.xyz> References: <20240323173735.26224-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 5/6] avcodec/dovi_rpu: add ext_blocks array to DOVIContext X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: TpPId3QDFcAE From: Niklas Haas --- libavcodec/dovi_rpu.c | 1 + libavcodec/dovi_rpu.h | 7 +++++++ 2 files changed, 8 insertions(+) diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c index cd54c8716dc..21cb1850e3e 100644 --- a/libavcodec/dovi_rpu.c +++ b/libavcodec/dovi_rpu.c @@ -48,6 +48,7 @@ void ff_dovi_ctx_unref(DOVIContext *s) for (int i = 0; i < FF_ARRAY_ELEMS(s->vdr); i++) ff_refstruct_unref(&s->vdr[i]); av_free(s->rpu_buf); + av_free(s->ext_blocks); *s = (DOVIContext) { .logctx = s->logctx, diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h index f88fbf9b558..c632a83f46b 100644 --- a/libavcodec/dovi_rpu.h +++ b/libavcodec/dovi_rpu.h @@ -44,6 +44,12 @@ typedef struct DOVIContext { const AVDOVIDataMapping *mapping; const AVDOVIColorMetadata *color; + /** + * Currently active extension blocks, updates on every ff_dovi_rpu_parse() + */ + AVDOVIDmData *ext_blocks; + int num_ext_blocks; + /** * Private fields internal to dovi_rpu.c */ @@ -51,6 +57,7 @@ typedef struct DOVIContext { uint8_t dv_profile; uint8_t *rpu_buf; ///< temporary buffer unsigned rpu_buf_sz; + unsigned ext_blocks_sz; } DOVIContext; From patchwork Sat Mar 23 17:37:35 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Niklas Haas X-Patchwork-Id: 47381 Delivered-To: ffmpegpatchwork2@gmail.com Received: by 2002:a05:6a20:c889:b0:1a3:b6bb:3029 with SMTP id hb9csp328704pzb; Sat, 23 Mar 2024 10:38:38 -0700 (PDT) X-Forwarded-Encrypted: i=2; AJvYcCUte9z5GuniNuJ8YnNbM2t5OoSUEJHHwc5dlWvoGs78+jSHC6pcL6bFxTSsLiTe/iuSDKBRpWxoamIhO99l8ngtCSi4UiFyNJs22A== X-Google-Smtp-Source: AGHT+IEVI9qFvt/3kRQd80AtSxYXlIG5793a8JErC+1pWvOzzWIVHn7cPzAk7HaWL2CsO3o+khkF X-Received: by 2002:a17:906:724f:b0:a47:3555:6b73 with SMTP id n15-20020a170906724f00b00a4735556b73mr1815829ejk.39.1711215517940; Sat, 23 Mar 2024 10:38:37 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1711215517; cv=none; d=google.com; s=arc-20160816; b=xNr+ImiA4M0MIf4X7T9ca86bWAWFO0L6zA6TZX9HxhewL9RQKRjJhPAFo1UezjEzMq a9h6y04GcLRnwRsdoFY/4ySZ4JcIZrOEzDivMcETyNaGB1rG+BFtSLmiz5api8A6r3GK 7uIg5jY7njj/A8xNmjMdtm93t54ujWLRFODgcQR7cSQx8oUIU5OQIq1kQZTpY6Vxy0LR q0RgEx15eszIC8vew3sRv0Z1DfVkxyfcYHwA49HKhOEahQteHXmJv8gg91RAG9XYzz84 dVDt/taGlW1dc0oOXQQ0OAC71Btyfnra9iyWl/lYYnUgWqibcUfcabRXtrEYhVscRmdF vPoQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=sender:errors-to:content-transfer-encoding:cc:reply-to :list-subscribe:list-help:list-post:list-archive:list-unsubscribe :list-id:precedence:subject:mime-version:references:in-reply-to :message-id:date:to:from:dkim-signature:delivered-to; bh=G7DbSeqwTLEiBgtKenxLewOS4tcxmlbRpXvYdZEgYTM=; fh=C56SNERGsx7JRMjLZiHmpTAKnRl/jfaA+FIG9zHupRY=; b=JzvIiOPz/8V/8//21ANo0KIAzyd8AYPUa+5RRe7x7As/nnTQjBU3U0DRgniTMF/z6E N7eNAOXI36L+TRqJ1DIp1cW5JvSDIAFCmtAqu5Y5saeF/pOeeIADu9E/GBl4cFOuJIg5 zT405BFZ0HV9/uawb3HY6iWLCkNdO3OBAAluu6JSUO4Ly3H2pcooohF6iPZSmSlPONB/ cuBz2R5k2EPZl/WM1UGLor1rWLElmtv0uPs65N8NeuK2fQ/CURlQbZm5GTcB8xkSlprL l13HU0rbbIPGcd/QXQMhvJwcR2b0Fg27rsKbCZEZjzwVBNM5eSX68tD4gBlr28xyNWvh 0NNQ==; dara=google.com ARC-Authentication-Results: i=1; mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=OpIA9Xb6; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Return-Path: Received: from ffbox0-bg.mplayerhq.hu (ffbox0-bg.ffmpeg.org. [79.124.17.100]) by mx.google.com with ESMTP id u9-20020a170906780900b00a47377535c9si964982ejm.1034.2024.03.23.10.38.37; Sat, 23 Mar 2024 10:38:37 -0700 (PDT) Received-SPF: pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) client-ip=79.124.17.100; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@haasn.xyz header.s=mail header.b=OpIA9Xb6; spf=pass (google.com: domain of ffmpeg-devel-bounces@ffmpeg.org designates 79.124.17.100 as permitted sender) smtp.mailfrom=ffmpeg-devel-bounces@ffmpeg.org Received: from [127.0.1.1] (localhost [127.0.0.1]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id CE16F68D4C7; Sat, 23 Mar 2024 19:37:54 +0200 (EET) X-Original-To: ffmpeg-devel@ffmpeg.org Delivered-To: ffmpeg-devel@ffmpeg.org Received: from haasn.dev (haasn.dev [78.46.187.166]) by ffbox0-bg.mplayerhq.hu (Postfix) with ESMTP id 8811368D32A for ; Sat, 23 Mar 2024 19:37:47 +0200 (EET) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=haasn.xyz; s=mail; t=1711215462; bh=F6scTwm7NKfsaxABUoezB1krxiEn4SCF13KavFT7uwg=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=OpIA9Xb6JoZQtLS1lrMkGvds9LAwlQyIEHUwZYj8q4MGC95R0S3i3zRecMjo4+oys q/FLjzDHZ36qLSywCh2Y2ySXe8w4lrY7d+vjGM4vkSo/crMSTdAvE8KH6nGDZukjnb FmaW7B16wByHzfZsSuIPmYSZZmt159wR8zxQAGV8= Received: from haasn.dev (unknown [10.30.0.2]) by haasn.dev (Postfix) with ESMTP id 359D8429F3; Sat, 23 Mar 2024 18:37:42 +0100 (CET) From: Niklas Haas To: ffmpeg-devel@ffmpeg.org Date: Sat, 23 Mar 2024 18:37:35 +0100 Message-ID: <20240323173735.26224-6-ffmpeg@haasn.xyz> X-Mailer: git-send-email 2.44.0 In-Reply-To: <20240323173735.26224-1-ffmpeg@haasn.xyz> References: <20240323173735.26224-1-ffmpeg@haasn.xyz> MIME-Version: 1.0 Subject: [FFmpeg-devel] [PATCH 6/6] avcodec/dovi_rpu: parse extension blocks X-BeenThere: ffmpeg-devel@ffmpeg.org X-Mailman-Version: 2.1.29 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 Cc: quietvoid , Niklas Haas Errors-To: ffmpeg-devel-bounces@ffmpeg.org Sender: "ffmpeg-devel" X-TUID: mYiNmI3/W2BK From: Niklas Haas We split the inner loop between v1 and v2 extension blocks to print a warning where an extension block was encountered in an unexpected context. Co-authored-by: quietvoid --- libavcodec/dovi_rpu.c | 178 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 178 insertions(+) diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c index 21cb1850e3e..99a983f65dd 100644 --- a/libavcodec/dovi_rpu.c +++ b/libavcodec/dovi_rpu.c @@ -199,6 +199,174 @@ static inline unsigned get_variable_bits(GetBitContext *gb, int n) } \ } while (0) +static void parse_ext_v1(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm) +{ + switch (dm->level) { + case 1: + dm->l1.min_pq = get_bits(gb, 12); + dm->l1.max_pq = get_bits(gb, 12); + dm->l1.avg_pq = get_bits(gb, 12); + break; + case 2: + dm->l2.target_max_pq = get_bits(gb, 12); + dm->l2.trim_slope = get_bits(gb, 12); + dm->l2.trim_offset = get_bits(gb, 12); + dm->l2.trim_power = get_bits(gb, 12); + dm->l2.trim_chroma_weight = get_bits(gb, 12); + dm->l2.trim_saturation_gain = get_bits(gb, 12); + dm->l2.ms_weight = get_bits(gb, 13) - 8192; + break; + case 4: + dm->l4.anchor_pq = get_bits(gb, 12); + dm->l4.anchor_power = get_bits(gb, 12); + break; + case 5: + dm->l5.left_offset = get_bits(gb, 13); + dm->l5.right_offset = get_bits(gb, 13); + dm->l5.top_offset = get_bits(gb, 13); + dm->l5.bottom_offset = get_bits(gb, 13); + break; + case 6: + dm->l6.max_luminance = get_bits(gb, 16); + dm->l6.min_luminance = get_bits(gb, 16); + dm->l6.max_cll = get_bits(gb, 16); + dm->l6.max_fall = get_bits(gb, 16); + break; + case 255: + dm->l255.dm_run_mode = get_bits(gb, 8); + dm->l255.dm_run_version = get_bits(gb, 8); + for (int i = 0; i < 4; i++) + dm->l255.dm_debug[i] = get_bits(gb, 8); + break; + default: + av_log(s->logctx, AV_LOG_WARNING, + "Unknown Dolby Vision DM v1 level: %u\n", dm->level); + } +} + +static inline AVCIExy get_cie_xy(GetBitContext *gb) +{ + const int denom = 32767; + return (AVCIExy) { + .x = { get_sbits(gb, 16), denom }, + .y = { get_sbits(gb, 16), denom }, + }; +} + +static void parse_ext_v2(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm, + int ext_block_length) +{ + switch (dm->level) { + case 3: + dm->l3.min_pq_offset = get_bits(gb, 12); + dm->l3.max_pq_offset = get_bits(gb, 12); + dm->l3.avg_pq_offset = get_bits(gb, 12); + break; + case 8: + dm->l8.target_display_index = get_bits(gb, 8); + dm->l8.trim_slope = get_bits(gb, 12); + dm->l8.trim_offset = get_bits(gb, 12); + dm->l8.trim_power = get_bits(gb, 12); + dm->l8.trim_chroma_weight = get_bits(gb, 12); + dm->l8.trim_saturation_gain = get_bits(gb, 12); + dm->l8.ms_weight = get_bits(gb, 12) - 8192; + if (ext_block_length < 12) + break; + dm->l8.target_mid_contrast = get_bits(gb, 12); + if (ext_block_length < 13) + break; + dm->l8.clip_trim = get_bits(gb, 12); + if (ext_block_length < 19) + break; + for (int i = 0; i < 6; i++) + dm->l8.saturation_vector_field[i] = get_bits(gb, 8); + if (ext_block_length < 25) + break; + for (int i = 0; i < 6; i++) + dm->l8.hue_vector_field[i] = get_bits(gb, 8); + break; + case 9: + dm->l9.source_primary_index = get_bits(gb, 8); + if (ext_block_length < 17) + break; + dm->l9.source_display_primaries.prim.r = get_cie_xy(gb); + dm->l9.source_display_primaries.prim.g = get_cie_xy(gb); + dm->l9.source_display_primaries.prim.b = get_cie_xy(gb); + dm->l9.source_display_primaries.wp = get_cie_xy(gb); + break; + case 10: + dm->l10.target_display_index = get_bits(gb, 8); + dm->l10.target_max_pq = get_bits(gb, 12); + dm->l10.target_min_pq = get_bits(gb, 12); + dm->l10.target_primary_index = get_bits(gb, 8); + if (ext_block_length < 21) + break; + dm->l10.target_display_primaries.prim.r = get_cie_xy(gb); + dm->l10.target_display_primaries.prim.g = get_cie_xy(gb); + dm->l10.target_display_primaries.prim.b = get_cie_xy(gb); + dm->l10.target_display_primaries.wp = get_cie_xy(gb); + break; + case 11: + dm->l11.content_type = get_bits(gb, 8); + dm->l11.whitepoint = get_bits(gb, 4); + dm->l11.reference_mode_flag = get_bits(gb, 1); + skip_bits(gb, 3); /* reserved */ + dm->l11.sharpness = get_bits(gb, 2); + dm->l11.noise_reduction = get_bits(gb, 2); + dm->l11.mpeg_noise_reduction = get_bits(gb, 2); + dm->l11.frame_rate_conversion = get_bits(gb, 2); + dm->l11.brightness = get_bits(gb, 2); + dm->l11.color = get_bits(gb, 2); + break; + case 254: + dm->l254.dm_mode = get_bits(gb, 8); + dm->l254.dm_version_index = get_bits(gb, 8); + break; + default: + av_log(s->logctx, AV_LOG_WARNING, + "Unknown Dolby Vision DM v2 level: %u\n", dm->level); + } +} + +static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver) +{ + int num_ext_blocks, ext_block_length, start_pos, parsed_bits; + AVDOVIDmData *ext_blocks; + size_t alloc_sz; + + num_ext_blocks = get_ue_golomb_31(gb); + align_get_bits(gb); + + alloc_sz = (s->num_ext_blocks + num_ext_blocks) * sizeof(AVDOVIDmData); + ext_blocks = av_fast_realloc(s->ext_blocks, &s->ext_blocks_sz, alloc_sz); + if (!ext_blocks) { + ff_dovi_ctx_unref(s); + return AVERROR(ENOMEM); + } + s->ext_blocks = ext_blocks; + + while (num_ext_blocks--) { + AVDOVIDmData *dm = &s->ext_blocks[s->num_ext_blocks++]; + ext_block_length = get_ue_golomb_31(gb); + dm->level = get_bits(gb, 8); + start_pos = get_bits_count(gb); + + switch (ver) { + case 1: parse_ext_v1(s, gb, dm); break; + case 2: parse_ext_v2(s, gb, dm, ext_block_length); break; + } + + parsed_bits = get_bits_count(gb) - start_pos; + if (parsed_bits > ext_block_length * 8) { + ff_dovi_ctx_unref(s); + return AVERROR_INVALIDDATA; + } + skip_bits(gb, ext_block_length * 8 - parsed_bits); + } + + return 0; +} + int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size, int err_recognition) { @@ -524,6 +692,16 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size, color->source_diagonal = get_bits(gb, 10); } + /* Parse extension blocks */ + s->num_ext_blocks = 0; + if ((ret = parse_ext_blocks(s, gb, 1)) < 0) + return ret; + + if (get_bits_left(gb) > 48 /* padding + CRC32 + terminator */) { + if ((ret = parse_ext_blocks(s, gb, 2)) < 0) + return ret; + } + return 0; fail: