* [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks
@ 2024-07-28 10:25 Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 02/22] avcodec/dovi_rpudec: implement validation for compression Niklas Haas
` (21 more replies)
0 siblings, 22 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
---
libavutil/dovi_meta.h | 28 +++++++++++++++-------------
1 file changed, 15 insertions(+), 13 deletions(-)
diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h
index c942d0e133..5e8a1e43d7 100644
--- a/libavutil/dovi_meta.h
+++ b/libavutil/dovi_meta.h
@@ -301,26 +301,28 @@ typedef struct AVDOVIDmLevel255 {
} AVDOVIDmLevel255;
/**
- * Dolby Vision metadata extension block.
+ * Dolby Vision metadata extension block. Dynamic extension blocks may change
+ * from frame to frame, while static blocks are constant throughout the entire
+ * sequence.
*
* @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;
+ AVDOVIDmLevel1 l1; /* dynamic */
+ AVDOVIDmLevel2 l2; /* dynamic, may appear multiple times */
+ AVDOVIDmLevel3 l3; /* dynamic */
+ AVDOVIDmLevel4 l4; /* dynamic */
+ AVDOVIDmLevel5 l5; /* dynamic */
+ AVDOVIDmLevel6 l6; /* static */
/* 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;
+ AVDOVIDmLevel8 l8; /* dynamic, may appear multiple times */
+ AVDOVIDmLevel9 l9; /* dynamic */
+ AVDOVIDmLevel10 l10; /* static, may appear multiple times */
+ AVDOVIDmLevel11 l11; /* dynamic */
+ AVDOVIDmLevel254 l254; /* static */
+ AVDOVIDmLevel255 l255; /* static */
};
} AVDOVIDmData;
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 02/22] avcodec/dovi_rpudec: implement validation for compression
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 03/22] avcodec/dovi_rpuenc: also copy ext blocks to dovi ctx Niklas Haas
` (20 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Add some error checking. I've limited it to AV_EF_CAREFUL and
AV_EF_COMPLIANT for now, because we can technically decode such RPUs
just fine.
---
libavcodec/dovi_rpudec.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 375e6e560b..bf6e5075d1 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -314,6 +314,7 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
uint8_t use_prev_vdr_rpu;
uint8_t use_nlq;
uint8_t profile;
+ uint8_t compression = s->cfg.dv_profile ? s->cfg.dv_md_compression : 0;
if (rpu_size < 5)
return AVERROR_INVALIDDATA;
@@ -459,6 +460,20 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
return AVERROR_INVALIDDATA;
}
+ if (err_recognition & (AV_EF_COMPLIANT | AV_EF_CAREFUL)) {
+ if (profile < 8 && compression) {
+ av_log(s->logctx, AV_LOG_ERROR, "Profile %d RPUs should not use "
+ "metadata compression.", profile);
+ return AVERROR_INVALIDDATA;
+ }
+
+ if (use_prev_vdr_rpu && !compression) {
+ av_log(s->logctx, AV_LOG_ERROR, "Uncompressed RPUs should not have "
+ "use_prev_vdr_rpu=1\n");
+ return AVERROR_INVALIDDATA;
+ }
+ }
+
if (use_prev_vdr_rpu) {
int prev_vdr_rpu_id = get_ue_golomb_31(gb);
VALIDATE(prev_vdr_rpu_id, 0, DOVI_MAX_DM_ID);
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 03/22] avcodec/dovi_rpuenc: also copy ext blocks to dovi ctx
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 02/22] avcodec/dovi_rpudec: implement validation for compression Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 04/22] avcodec/dovi_rpuenc: eliminate unnecessary loop Niklas Haas
` (19 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
As the comment implies, DOVIContext.ext_blocks should also reflect the
current state after ff_dovi_rpu_generate().
Fluff for now, but will be needed once we start implementing metadata
compression for extension blocks as well.
---
libavcodec/dovi_rpuenc.c | 12 ++++++++++++
1 file changed, 12 insertions(+)
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index a14c9cc181..f0cfecc91b 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -506,6 +506,12 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
}
+ if (metadata->num_ext_blocks && !s->ext_blocks) {
+ s->ext_blocks = ff_refstruct_allocz(sizeof(AVDOVIDmData) * AV_DOVI_MAX_EXT_BLOCKS);
+ if (!s->ext_blocks)
+ return AVERROR(ENOMEM);
+ }
+
vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
use_prev_vdr_rpu = !memcmp(s->vdr[vdr_rpu_id], mapping, sizeof(*mapping));
if (num_ext_blocks_v1 || num_ext_blocks_v2)
@@ -636,6 +642,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
if (vdr_dm_metadata_present) {
+ size_t ext_sz;
const int denom = profile == 4 ? (1 << 30) : (1 << 28);
set_ue_golomb(pb, color->dm_metadata_id); /* affected_dm_id */
set_ue_golomb(pb, color->dm_metadata_id); /* current_dm_id */
@@ -673,6 +680,11 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
for (int i = 0; i < metadata->num_ext_blocks; i++)
generate_ext_v2(pb, av_dovi_get_ext(metadata, i));
}
+
+ ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
+ for (int i = 0; i < metadata->num_ext_blocks; i++)
+ memcpy(&s->ext_blocks[i], av_dovi_get_ext(metadata, i), ext_sz);
+ s->num_ext_blocks = metadata->num_ext_blocks;
} else {
s->color = &ff_dovi_color_default;
s->num_ext_blocks = 0;
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 04/22] avcodec/dovi_rpuenc: eliminate unnecessary loop
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 02/22] avcodec/dovi_rpudec: implement validation for compression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 03/22] avcodec/dovi_rpuenc: also copy ext blocks to dovi ctx Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 05/22] avcodec/dovi_rpuenc: respect dv_md_compression Niklas Haas
` (18 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
This struct itself contains vdr_rpu_id, so we can never match it except
in the case of i == vdr_rpu_id. So just directly use this ID.
---
libavcodec/dovi_rpuenc.c | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index f0cfecc91b..63cbde8718 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -463,16 +463,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
return AVERROR_INVALIDDATA;
}
- vdr_rpu_id = -1;
- for (int i = 0; i <= DOVI_MAX_DM_ID; i++) {
- if (s->vdr[i] && !memcmp(s->vdr[i], mapping, sizeof(*mapping))) {
- vdr_rpu_id = i;
- break;
- } else if (vdr_rpu_id < 0 && (!s->vdr[i] || i == DOVI_MAX_DM_ID)) {
- vdr_rpu_id = i;
- }
- }
-
+ vdr_rpu_id = mapping->vdr_rpu_id;
if (!s->vdr[vdr_rpu_id]) {
s->vdr[vdr_rpu_id] = ff_refstruct_allocz(sizeof(AVDOVIDataMapping));
if (!s->vdr[vdr_rpu_id])
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 05/22] avcodec/dovi_rpuenc: respect dv_md_compression
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (2 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 04/22] avcodec/dovi_rpuenc: eliminate unnecessary loop Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 06/22] avcodec/dovi_rpuenc: add `flags` to ff_dovi_rpu_generate() Niklas Haas
` (17 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Limited mode can only ever maintain a single VDR RPU reference, and
furthermore requires vdr_rpu_id == 0. So in practice, it will only ever
use VDR RPU slot 0. All remaining slots get flushed in this case, to
avoid leaking partial state.
---
libavcodec/dovi_rpuenc.c | 26 +++++++++++++++++++++++++-
1 file changed, 25 insertions(+), 1 deletion(-)
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 63cbde8718..2a6131eff5 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -464,12 +464,37 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
vdr_rpu_id = mapping->vdr_rpu_id;
+ use_prev_vdr_rpu = 0;
+
if (!s->vdr[vdr_rpu_id]) {
s->vdr[vdr_rpu_id] = ff_refstruct_allocz(sizeof(AVDOVIDataMapping));
if (!s->vdr[vdr_rpu_id])
return AVERROR(ENOMEM);
}
+ switch (s->cfg.dv_md_compression) {
+ case AV_DOVI_COMPRESSION_LIMITED:
+ /* Limited metadata compression requires vdr_rpi_id == 0 */
+ if (vdr_rpu_id != 0)
+ break;
+ /* fall through */
+ case AV_DOVI_COMPRESSION_EXTENDED:
+ if (s->vdr[vdr_rpu_id])
+ use_prev_vdr_rpu = !memcmp(s->vdr[vdr_rpu_id], mapping, sizeof(*mapping));
+ break;
+ case AV_DOVI_COMPRESSION_RESERVED:
+ return AVERROR(EINVAL);
+ }
+
+ if (s->cfg.dv_md_compression != AV_DOVI_COMPRESSION_EXTENDED) {
+ /* Flush VDRs to avoid leaking old state; maintaining multiple VDR
+ * references requires extended compression */
+ for (int i = 0; i <= DOVI_MAX_DM_ID; i++) {
+ if (i != vdr_rpu_id)
+ ff_refstruct_unref(&s->vdr[i]);
+ }
+ }
+
num_ext_blocks_v1 = num_ext_blocks_v2 = 0;
for (int i = 0; i < metadata->num_ext_blocks; i++) {
const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
@@ -504,7 +529,6 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
- use_prev_vdr_rpu = !memcmp(s->vdr[vdr_rpu_id], mapping, sizeof(*mapping));
if (num_ext_blocks_v1 || num_ext_blocks_v2)
vdr_dm_metadata_present = 1;
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 06/22] avcodec/dovi_rpuenc: add `flags` to ff_dovi_rpu_generate()
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (3 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 05/22] avcodec/dovi_rpuenc: respect dv_md_compression Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 07/22] avcodec/dovi_rpuenc: make encapsulation optional Niklas Haas
` (16 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Will be used to control compression, encapsulation etc.
---
libavcodec/dovi_rpu.h | 2 +-
libavcodec/dovi_rpuenc.c | 2 +-
libavcodec/libaomenc.c | 2 +-
libavcodec/libsvtav1.c | 2 +-
libavcodec/libx265.c | 3 ++-
5 files changed, 6 insertions(+), 5 deletions(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index 205d16ffbc..65a4529106 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -135,7 +135,7 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx);
* including the EMDF header (profile 10) or NAL encapsulation (otherwise).
*/
int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
- uint8_t **out_rpu, int *out_size);
+ int flags, uint8_t **out_rpu, int *out_size);
/***************************************************
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 2a6131eff5..e1a70be42d 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -435,7 +435,7 @@ static void generate_ext_v2(PutBitContext *pb, const AVDOVIDmData *dm)
}
int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
- uint8_t **out_rpu, int *out_size)
+ int flags, uint8_t **out_rpu, int *out_size)
{
PutBitContext *pb = &(PutBitContext){0};
const AVDOVIRpuDataHeader *hdr;
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index dec74ebecd..aa51c89e29 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -1294,7 +1294,7 @@ FF_ENABLE_DEPRECATION_WARNINGS
const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data;
uint8_t *t35;
int size;
- if ((res = ff_dovi_rpu_generate(&ctx->dovi, metadata, &t35, &size)) < 0)
+ if ((res = ff_dovi_rpu_generate(&ctx->dovi, metadata, 0, &t35, &size)) < 0)
return res;
res = aom_img_add_metadata(rawimg, OBU_METADATA_TYPE_ITUT_T35,
t35, size, AOM_MIF_ANY_FRAME);
diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
index 2fef8c8971..b6db63fd7a 100644
--- a/libavcodec/libsvtav1.c
+++ b/libavcodec/libsvtav1.c
@@ -541,7 +541,7 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data;
uint8_t *t35;
int size;
- if ((ret = ff_dovi_rpu_generate(&svt_enc->dovi, metadata, &t35, &size)) < 0)
+ if ((ret = ff_dovi_rpu_generate(&svt_enc->dovi, metadata, 0, &t35, &size)) < 0)
return ret;
ret = svt_add_metadata(headerPtr, EB_AV1_METADATA_TYPE_ITUT_T35, t35, size);
av_free(t35);
diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index 0dc7ab6eeb..4302c3d587 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -783,7 +783,8 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
sd = av_frame_get_side_data(pic, AV_FRAME_DATA_DOVI_METADATA);
if (ctx->dovi.cfg.dv_profile && sd) {
const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data;
- ret = ff_dovi_rpu_generate(&ctx->dovi, metadata, &x265pic.rpu.payload,
+ ret = ff_dovi_rpu_generate(&ctx->dovi, metadata, 0,
+ &x265pic.rpu.payload,
&x265pic.rpu.payloadSize);
if (ret < 0) {
free_picture(ctx, &x265pic);
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 07/22] avcodec/dovi_rpuenc: make encapsulation optional
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (4 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 06/22] avcodec/dovi_rpuenc: add `flags` to ff_dovi_rpu_generate() Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 08/22] avcodec/dovi_rpuenc: add a flag to enable compression Niklas Haas
` (15 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
And move the choice of desired container to `flags`. This is needed to
handle differing API requirements (e.g. libx265 requires the NAL RBSP,
but CBS BSF requires the unescaped bytes).
---
libavcodec/dovi_rpu.h | 16 ++++++++++------
libavcodec/dovi_rpuenc.c | 22 ++++++++++------------
libavcodec/libaomenc.c | 3 ++-
libavcodec/libsvtav1.c | 3 ++-
libavcodec/libx265.c | 2 +-
5 files changed, 25 insertions(+), 21 deletions(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index 65a4529106..226a769bff 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -123,16 +123,20 @@ int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame);
*/
int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx);
+enum {
+ FF_DOVI_WRAP_NAL = 1 << 0, ///< wrap inside NAL RBSP
+ FF_DOVI_WRAP_T35 = 1 << 1, ///< wrap inside T.35+EMDF
+};
+
/**
- * Synthesize a Dolby Vision RPU reflecting the current state. Note that this
- * assumes all previous calls to `ff_dovi_rpu_generate` have been appropriately
- * signalled, i.e. it will not re-send already transmitted redundant data.
+ * Synthesize a Dolby Vision RPU reflecting the current state. By default, the
+ * RPU is not encapsulated (see `flags` for more options). Note that this
+ * assumes all previous calls to `ff_dovi_rpu_generate` have been
+ * appropriately signalled, i.e. it will not re-send already transmitted
+ * redundant data.
*
* Mutates the internal state of DOVIContext to reflect the change.
* Returns 0 or a negative error code.
- *
- * This generates a fully formed RPU ready for inclusion in the bitstream,
- * including the EMDF header (profile 10) or NAL encapsulation (otherwise).
*/
int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
int flags, uint8_t **out_rpu, int *out_size);
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index e1a70be42d..73db9437a0 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -713,9 +713,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
flush_put_bits(pb);
rpu_size = put_bytes_output(pb);
- switch (s->cfg.dv_profile) {
- case 10:
- /* AV1 uses T.35 OBU with EMDF header */
+ if (flags & FF_DOVI_WRAP_T35) {
*out_rpu = av_malloc(rpu_size + 15);
if (!*out_rpu)
return AVERROR(ENOMEM);
@@ -742,10 +740,8 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
flush_put_bits(pb);
*out_size = put_bytes_output(pb);
return 0;
-
- case 5:
- case 8:
- *out_rpu = dst = av_malloc(1 + rpu_size * 3 / 2); /* worst case */
+ } else if (flags & FF_DOVI_WRAP_NAL) {
+ *out_rpu = dst = av_malloc(4 + rpu_size * 3 / 2); /* worst case */
if (!*out_rpu)
return AVERROR(ENOMEM);
*dst++ = 25; /* NAL prefix */
@@ -768,10 +764,12 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
*out_size = dst - *out_rpu;
return 0;
-
- default:
- /* Should be unreachable */
- av_assert0(0);
- return AVERROR_BUG;
+ } else {
+ /* Return intermediate buffer directly */
+ *out_rpu = s->rpu_buf;
+ *out_size = rpu_size;
+ s->rpu_buf = NULL;
+ s->rpu_buf_sz = 0;
+ return 0;
}
}
diff --git a/libavcodec/libaomenc.c b/libavcodec/libaomenc.c
index aa51c89e29..fd9bea2505 100644
--- a/libavcodec/libaomenc.c
+++ b/libavcodec/libaomenc.c
@@ -1294,7 +1294,8 @@ FF_ENABLE_DEPRECATION_WARNINGS
const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data;
uint8_t *t35;
int size;
- if ((res = ff_dovi_rpu_generate(&ctx->dovi, metadata, 0, &t35, &size)) < 0)
+ if ((res = ff_dovi_rpu_generate(&ctx->dovi, metadata, FF_DOVI_WRAP_T35,
+ &t35, &size)) < 0)
return res;
res = aom_img_add_metadata(rawimg, OBU_METADATA_TYPE_ITUT_T35,
t35, size, AOM_MIF_ANY_FRAME);
diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
index b6db63fd7a..e7b12fb488 100644
--- a/libavcodec/libsvtav1.c
+++ b/libavcodec/libsvtav1.c
@@ -541,7 +541,8 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data;
uint8_t *t35;
int size;
- if ((ret = ff_dovi_rpu_generate(&svt_enc->dovi, metadata, 0, &t35, &size)) < 0)
+ if ((ret = ff_dovi_rpu_generate(&svt_enc->dovi, metadata, FF_DOVI_WRAP_T35,
+ &t35, &size)) < 0)
return ret;
ret = svt_add_metadata(headerPtr, EB_AV1_METADATA_TYPE_ITUT_T35, t35, size);
av_free(t35);
diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index 4302c3d587..718bd21b20 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -783,7 +783,7 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
sd = av_frame_get_side_data(pic, AV_FRAME_DATA_DOVI_METADATA);
if (ctx->dovi.cfg.dv_profile && sd) {
const AVDOVIMetadata *metadata = (const AVDOVIMetadata *)sd->data;
- ret = ff_dovi_rpu_generate(&ctx->dovi, metadata, 0,
+ ret = ff_dovi_rpu_generate(&ctx->dovi, metadata, FF_DOVI_WRAP_NAL,
&x265pic.rpu.payload,
&x265pic.rpu.payloadSize);
if (ret < 0) {
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 08/22] avcodec/dovi_rpuenc: add a flag to enable compression
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (5 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 07/22] avcodec/dovi_rpuenc: make encapsulation optional Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 09/22] avcodec/dovi_rpu: add ff_dovi_get_metadata() Niklas Haas
` (14 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Keyframes must reset the metadata compression state, so we need to
also signal this at rpu generation time.
Default to uncompressed, because encoders cannot generally know if
a given frame will be a keyframe before they finish encoding, but also
cannot retroactively attach the RPU. (Within the confines of current
APIs)
---
libavcodec/dovi_rpu.h | 1 +
libavcodec/dovi_rpuenc.c | 6 +++++-
2 files changed, 6 insertions(+), 1 deletion(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index 226a769bff..e2e7635cfb 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -126,6 +126,7 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx);
enum {
FF_DOVI_WRAP_NAL = 1 << 0, ///< wrap inside NAL RBSP
FF_DOVI_WRAP_T35 = 1 << 1, ///< wrap inside T.35+EMDF
+ FF_DOVI_COMPRESS_RPU = 1 << 2, ///< enable compression for this RPU
};
/**
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 73db9437a0..0d4e613a72 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -444,6 +444,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
int vdr_dm_metadata_present, vdr_rpu_id, use_prev_vdr_rpu, profile,
buffer_size, rpu_size, pad, zero_run;
int num_ext_blocks_v1, num_ext_blocks_v2;
+ int dv_md_compression = s->cfg.dv_md_compression;
uint32_t crc;
uint8_t *dst;
if (!metadata) {
@@ -463,6 +464,9 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
return AVERROR_INVALIDDATA;
}
+ if (!(flags & FF_DOVI_COMPRESS_RPU))
+ dv_md_compression = AV_DOVI_COMPRESSION_NONE;
+
vdr_rpu_id = mapping->vdr_rpu_id;
use_prev_vdr_rpu = 0;
@@ -472,7 +476,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
return AVERROR(ENOMEM);
}
- switch (s->cfg.dv_md_compression) {
+ switch (dv_md_compression) {
case AV_DOVI_COMPRESSION_LIMITED:
/* Limited metadata compression requires vdr_rpi_id == 0 */
if (vdr_rpu_id != 0)
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 09/22] avcodec/dovi_rpu: add ff_dovi_get_metadata()
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (6 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 08/22] avcodec/dovi_rpuenc: add a flag to enable compression Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 10/22] avcodec/dovi_rpuenc: add ff_dovi_configure_ext() Niklas Haas
` (13 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Provides direct access to the AVDOVIMetadata without having to attach it
to a frame.
---
libavcodec/dovi_rpu.h | 9 +++++++++
libavcodec/dovi_rpudec.c | 40 +++++++++++++++++++++++++++-------------
2 files changed, 36 insertions(+), 13 deletions(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index e2e7635cfb..4eb4bc0873 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -108,8 +108,17 @@ void ff_dovi_ctx_flush(DOVIContext *s);
int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
int err_recognition);
+/**
+ * Get the decoded AVDOVIMetadata. Ownership passes to the caller.
+ *
+ * Returns the size of *out_metadata, a negative error code, or 0 if no
+ * metadata is available to return.
+ */
+int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata);
+
/**
* Attach the decoded AVDOVIMetadata as side data to an AVFrame.
+ * Returns 0 or a negative error code.
*/
int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame);
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index bf6e5075d1..0ddc923539 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -30,10 +30,8 @@
#include "get_bits.h"
#include "refstruct.h"
-int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame)
+int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
{
- AVFrameSideData *sd;
- AVBufferRef *buf;
AVDOVIMetadata *dovi;
size_t dovi_size, ext_sz;
@@ -44,7 +42,32 @@ int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame)
if (!dovi)
return AVERROR(ENOMEM);
- buf = av_buffer_create((uint8_t *) dovi, dovi_size, NULL, NULL, 0);
+ /* 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, ext_mapping_idc_5_7);
+ COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq_pivots);
+ COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal);
+ ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
+ for (int i = 0; i < s->num_ext_blocks; i++)
+ memcpy(av_dovi_get_ext(dovi, i), &s->ext_blocks[i], ext_sz);
+ dovi->num_ext_blocks = s->num_ext_blocks;
+
+ *out_metadata = dovi;
+ return dovi_size;
+}
+
+int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame)
+{
+ AVFrameSideData *sd;
+ AVDOVIMetadata *dovi;
+ AVBufferRef *buf;
+ int size;
+
+ size = ff_dovi_get_metadata(s, &dovi);
+ if (size <= 0)
+ return size;
+
+ buf = av_buffer_create((uint8_t *) dovi, size, NULL, NULL, 0);
if (!buf) {
av_free(dovi);
return AVERROR(ENOMEM);
@@ -56,15 +79,6 @@ int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame)
return AVERROR(ENOMEM);
}
- /* 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, ext_mapping_idc_5_7);
- COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq_pivots);
- COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal);
- ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
- for (int i = 0; i < s->num_ext_blocks; i++)
- memcpy(av_dovi_get_ext(dovi, i), &s->ext_blocks[i], ext_sz);
- dovi->num_ext_blocks = s->num_ext_blocks;
return 0;
}
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 10/22] avcodec/dovi_rpuenc: add ff_dovi_configure_ext()
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (7 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 09/22] avcodec/dovi_rpu: add ff_dovi_get_metadata() Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 11/22] avcodec/dovi_rpuenc: add configuration for compression Niklas Haas
` (12 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
More flexible version of ff_dovi_configure() which does not require an
AVCodecContext. Usable, for example, inside a bitstream filter.
---
libavcodec/dovi_rpu.h | 16 +++++++-
libavcodec/dovi_rpuenc.c | 85 +++++++++++++++++++++++++++-------------
2 files changed, 72 insertions(+), 29 deletions(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index 4eb4bc0873..1bbc6ef02c 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -26,7 +26,9 @@
#include "libavutil/dovi_meta.h"
#include "libavutil/frame.h"
+
#include "avcodec.h"
+#include "codec_par.h"
#define DOVI_MAX_DM_ID 15
typedef struct DOVIContext {
@@ -125,11 +127,23 @@ int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame);
/**
* Configure the encoder for Dolby Vision encoding. Generates a configuration
* record in s->cfg, and attaches it to avctx->coded_side_data. Sets the correct
- * profile and compatibility ID based on the tagged AVCodecContext colorspace
+ * profile and compatibility ID based on the tagged AVCodecParameters colorspace
* metadata, and the correct level based on the resolution and tagged framerate.
*
+ * `metadata` should point to the first frame's RPU, if available. If absent,
+ * auto-detection will be performed, but this can sometimes lead to inaccurate
+ * results (in particular for HEVC streams with enhancement layers).
+ *
* Returns 0 or a negative error code.
*/
+int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
+ const AVDOVIMetadata *metadata,
+ int strict_std_compliance);
+
+/**
+ * Helper wrapper around `ff_dovi_configure_ext` which infers the codec
+ * parameters from an AVCodecContext.
+ */
int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx);
enum {
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 0d4e613a72..ad161809a9 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -52,11 +52,12 @@ static struct {
[13] = {7680*4320*120u, 7680, 240, 800},
};
-int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
+int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
+ const AVDOVIMetadata *metadata,
+ int strict_std_compliance)
{
AVDOVIDecoderConfigurationRecord *cfg;
const AVDOVIRpuDataHeader *hdr = NULL;
- const AVFrameSideData *sd;
int dv_profile, dv_level, bl_compat_id = -1;
size_t cfg_size;
uint64_t pps;
@@ -64,16 +65,13 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
if (!s->enable)
goto skip;
- sd = av_frame_side_data_get(avctx->decoded_side_data,
- avctx->nb_decoded_side_data, AV_FRAME_DATA_DOVI_METADATA);
-
- if (sd)
- hdr = av_dovi_get_header((const AVDOVIMetadata *) sd->data);
+ if (metadata)
+ hdr = av_dovi_get_header(metadata);
if (s->enable == FF_DOVI_AUTOMATIC && !hdr)
goto skip;
- switch (avctx->codec_id) {
+ switch (codecpar->codec_id) {
case AV_CODEC_ID_AV1: dv_profile = 10; break;
case AV_CODEC_ID_H264: dv_profile = 9; break;
case AV_CODEC_ID_HEVC: dv_profile = hdr ? ff_dovi_guess_profile_hevc(hdr) : 8; break;
@@ -83,12 +81,12 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
return AVERROR_BUG;
}
- if (avctx->strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
+ if (strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
if (dv_profile == 9) {
- if (avctx->pix_fmt != AV_PIX_FMT_YUV420P)
+ if (codecpar->format != AV_PIX_FMT_YUV420P)
dv_profile = 0;
} else {
- if (avctx->pix_fmt != AV_PIX_FMT_YUV420P10)
+ if (codecpar->format != AV_PIX_FMT_YUV420P10)
dv_profile = 0;
}
}
@@ -115,17 +113,17 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
}
/* fall through */
case 8: /* HEVC (or AV1) with BL compatibility */
- if (avctx->colorspace == AVCOL_SPC_BT2020_NCL &&
- avctx->color_primaries == AVCOL_PRI_BT2020 &&
- avctx->color_trc == AVCOL_TRC_SMPTE2084) {
+ if (codecpar->color_space == AVCOL_SPC_BT2020_NCL &&
+ codecpar->color_primaries == AVCOL_PRI_BT2020 &&
+ codecpar->color_trc == AVCOL_TRC_SMPTE2084) {
bl_compat_id = 1;
- } else if (avctx->colorspace == AVCOL_SPC_BT2020_NCL &&
- avctx->color_primaries == AVCOL_PRI_BT2020 &&
- avctx->color_trc == AVCOL_TRC_ARIB_STD_B67) {
+ } else if (codecpar->color_space == AVCOL_SPC_BT2020_NCL &&
+ codecpar->color_primaries == AVCOL_PRI_BT2020 &&
+ codecpar->color_trc == AVCOL_TRC_ARIB_STD_B67) {
bl_compat_id = 4;
- } else if (avctx->colorspace == AVCOL_SPC_BT709 &&
- avctx->color_primaries == AVCOL_PRI_BT709 &&
- avctx->color_trc == AVCOL_TRC_BT709) {
+ } else if (codecpar->color_space == AVCOL_SPC_BT709 &&
+ codecpar->color_primaries == AVCOL_PRI_BT709 &&
+ codecpar->color_trc == AVCOL_TRC_BT709) {
bl_compat_id = 2;
}
}
@@ -140,9 +138,9 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
goto skip;
}
- pps = avctx->width * avctx->height;
- if (avctx->framerate.num) {
- pps = pps * avctx->framerate.num / avctx->framerate.den;
+ pps = codecpar->width * codecpar->height;
+ if (codecpar->framerate.num) {
+ pps = pps * codecpar->framerate.num / codecpar->framerate.den;
} else {
pps *= 25; /* sanity fallback */
}
@@ -151,7 +149,7 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
for (int i = 1; i < FF_ARRAY_ELEMS(dv_levels); i++) {
if (pps > dv_levels[i].pps)
continue;
- if (avctx->width > dv_levels[i].width)
+ if (codecpar->width > dv_levels[i].width)
continue;
/* In theory, we should also test the bitrate when known, and
* distinguish between main and high tier. In practice, just ignore
@@ -162,14 +160,14 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
}
if (!dv_level) {
- if (avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
+ if (strict_std_compliance >= FF_COMPLIANCE_STRICT) {
av_log(s->logctx, AV_LOG_ERROR, "Coded PPS (%"PRIu64") and width (%d) "
- "exceed Dolby Vision limitations\n", pps, avctx->width);
+ "exceed Dolby Vision limitations\n", pps, codecpar->width);
return AVERROR(EINVAL);
} else {
av_log(s->logctx, AV_LOG_WARNING, "Coded PPS (%"PRIu64") and width (%d) "
"exceed Dolby Vision limitations. Ignoring, resulting file "
- "may be non-conforming.\n", pps, avctx->width);
+ "may be non-conforming.\n", pps, codecpar->width);
dv_level = FF_ARRAY_ELEMS(dv_levels) - 1;
}
}
@@ -178,7 +176,8 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
if (!cfg)
return AVERROR(ENOMEM);
- if (!av_packet_side_data_add(&avctx->coded_side_data, &avctx->nb_coded_side_data,
+ if (!av_packet_side_data_add(&codecpar->coded_side_data,
+ &codecpar->nb_coded_side_data,
AV_PKT_DATA_DOVI_CONF, cfg, cfg_size, 0)) {
av_free(cfg);
return AVERROR(ENOMEM);
@@ -201,6 +200,36 @@ skip:
return 0;
}
+int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
+{
+ int ret;
+ const AVFrameSideData *sd;
+ const AVDOVIMetadata *metadata = NULL;
+ AVCodecParameters *codecpar = avcodec_parameters_alloc();
+ if (!codecpar)
+ return AVERROR(ENOMEM);
+
+ ret = avcodec_parameters_from_context(codecpar, avctx);
+ if (ret < 0)
+ goto fail;
+
+ sd = av_frame_side_data_get(avctx->decoded_side_data,
+ avctx->nb_decoded_side_data,
+ AV_FRAME_DATA_DOVI_METADATA);
+ if (sd)
+ metadata = (const AVDOVIMetadata *) sd->data;
+
+ ret = ff_dovi_configure_ext(s, codecpar, metadata, avctx->strict_std_compliance);
+ if (ret < 0)
+ goto fail;
+
+ ret = avcodec_parameters_to_context(avctx, codecpar);
+
+fail:
+ avcodec_parameters_free(&codecpar);
+ return ret;
+}
+
static inline void put_ue_coef(PutBitContext *pb, const AVDOVIRpuDataHeader *hdr,
uint64_t coef)
{
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 11/22] avcodec/dovi_rpuenc: add configuration for compression
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (8 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 10/22] avcodec/dovi_rpuenc: add ff_dovi_configure_ext() Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 12/22] avcodec/bsf/dovi_rpu: add new bitstream filter Niklas Haas
` (11 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
In particular, validate that the chosen compression level is compatible
with the chosen profile.
---
libavcodec/dovi_rpu.h | 1 +
libavcodec/dovi_rpuenc.c | 29 ++++++++++++++++++++++++++++-
2 files changed, 29 insertions(+), 1 deletion(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index 1bbc6ef02c..24a8353bdc 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -138,6 +138,7 @@ int ff_dovi_attach_side_data(DOVIContext *s, AVFrame *frame);
*/
int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
const AVDOVIMetadata *metadata,
+ enum AVDOVICompression compression,
int strict_std_compliance);
/**
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index ad161809a9..25e520dd92 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -54,6 +54,7 @@ static struct {
int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
const AVDOVIMetadata *metadata,
+ enum AVDOVICompression compression,
int strict_std_compliance)
{
AVDOVIDecoderConfigurationRecord *cfg;
@@ -71,6 +72,10 @@ int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
if (s->enable == FF_DOVI_AUTOMATIC && !hdr)
goto skip;
+ if (compression == AV_DOVI_COMPRESSION_RESERVED ||
+ compression > AV_DOVI_COMPRESSION_EXTENDED)
+ return AVERROR(EINVAL);
+
switch (codecpar->codec_id) {
case AV_CODEC_ID_AV1: dv_profile = 10; break;
case AV_CODEC_ID_H264: dv_profile = 9; break;
@@ -138,6 +143,25 @@ int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
goto skip;
}
+ if (compression != AV_DOVI_COMPRESSION_NONE) {
+ if (dv_profile < 8 && strict_std_compliance > FF_COMPLIANCE_UNOFFICIAL) {
+ av_log(s->logctx, AV_LOG_ERROR, "Dolby Vision metadata compression "
+ "is not permitted for profiles 7 and earlier. (dv_profile: %d, "
+ "compression: %d)\n", dv_profile, compression);
+ return AVERROR(EINVAL);
+ } else if (compression == AV_DOVI_COMPRESSION_EXTENDED &&
+ strict_std_compliance > FF_COMPLIANCE_EXPERIMENTAL) {
+ av_log(s->logctx, AV_LOG_ERROR, "Dolby Vision extended metadata "
+ "compression is experimental and not supported by "
+ "devices.");
+ return AVERROR(EINVAL);
+ } else if (dv_profile == 8) {
+ av_log(s->logctx, AV_LOG_WARNING, "Dolby Vision metadata compression "
+ "for profile 8 is known to be unsupported by many devices, "
+ "use with caution.\n");
+ }
+ }
+
pps = codecpar->width * codecpar->height;
if (codecpar->framerate.num) {
pps = pps * codecpar->framerate.num / codecpar->framerate.den;
@@ -191,6 +215,7 @@ int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
cfg->el_present_flag = 0;
cfg->bl_present_flag = 1;
cfg->dv_bl_signal_compatibility_id = bl_compat_id;
+ cfg->dv_md_compression = compression;
s->cfg = *cfg;
return 0;
@@ -219,7 +244,9 @@ int ff_dovi_configure(DOVIContext *s, AVCodecContext *avctx)
if (sd)
metadata = (const AVDOVIMetadata *) sd->data;
- ret = ff_dovi_configure_ext(s, codecpar, metadata, avctx->strict_std_compliance);
+ /* Current encoders cannot handle metadata compression during encoding */
+ ret = ff_dovi_configure_ext(s, codecpar, metadata, AV_DOVI_COMPRESSION_NONE,
+ avctx->strict_std_compliance);
if (ret < 0)
goto fail;
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 12/22] avcodec/bsf/dovi_rpu: add new bitstream filter
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (9 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 11/22] avcodec/dovi_rpuenc: add configuration for compression Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 13/22] avcodec/dovi_rpu: move ext blocks into dedicated struct Niklas Haas
` (10 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
This can be used to strip dovi metadata, or enable/disable dovi
metadata compression. Possibly more use cases in the future.
---
configure | 1 +
doc/bitstream_filters.texi | 23 +++
libavcodec/bitstream_filters.c | 1 +
libavcodec/bsf/Makefile | 1 +
libavcodec/bsf/dovi_rpu.c | 279 +++++++++++++++++++++++++++++++++
5 files changed, 305 insertions(+)
create mode 100644 libavcodec/bsf/dovi_rpu.c
diff --git a/configure b/configure
index f6f5c29fea..6107fb8745 100755
--- a/configure
+++ b/configure
@@ -3443,6 +3443,7 @@ aac_adtstoasc_bsf_select="adts_header mpeg4audio"
av1_frame_merge_bsf_select="cbs_av1"
av1_frame_split_bsf_select="cbs_av1"
av1_metadata_bsf_select="cbs_av1"
+dovi_rpu_bsf_select="cbs_h265 cbs_av1 dovi_rpudec dovi_rpuenc"
dts2pts_bsf_select="cbs_h264 h264parse"
eac3_core_bsf_select="ac3_parser"
evc_frame_merge_bsf_select="evcparse"
diff --git a/doc/bitstream_filters.texi b/doc/bitstream_filters.texi
index c03f04f858..e1cb87a522 100644
--- a/doc/bitstream_filters.texi
+++ b/doc/bitstream_filters.texi
@@ -101,6 +101,29 @@ Remove zero padding at the end of a packet.
Extract the core from a DCA/DTS stream, dropping extensions such as
DTS-HD.
+@section dovi_rpu
+
+Manipulate Dolby Vision metadata in a HEVC/AV1 bitstream, optionally enabling
+metadata compression.
+
+@table @option
+@item strip
+If enabled, strip all Dolby Vision metadata (configuration record + RPU data
+blocks) from the stream.
+@item compression
+Which compression level to enable.
+@table @samp
+@item none
+No metadata compression.
+@item limited
+Limited metadata compression scheme. Should be compatible with most devices.
+This is the default.
+@item extended
+Extended metadata compression. Devices are not required to support this. Note
+that this level currently behaves the same as @samp{limited} in libavcodec.
+@end table
+@end table
+
@section dump_extra
Add extradata to the beginning of the filtered packets except when
diff --git a/libavcodec/bitstream_filters.c b/libavcodec/bitstream_filters.c
index 138246c50e..f923411bee 100644
--- a/libavcodec/bitstream_filters.c
+++ b/libavcodec/bitstream_filters.c
@@ -31,6 +31,7 @@ extern const FFBitStreamFilter ff_av1_metadata_bsf;
extern const FFBitStreamFilter ff_chomp_bsf;
extern const FFBitStreamFilter ff_dump_extradata_bsf;
extern const FFBitStreamFilter ff_dca_core_bsf;
+extern const FFBitStreamFilter ff_dovi_rpu_bsf;
extern const FFBitStreamFilter ff_dts2pts_bsf;
extern const FFBitStreamFilter ff_dv_error_marker_bsf;
extern const FFBitStreamFilter ff_eac3_core_bsf;
diff --git a/libavcodec/bsf/Makefile b/libavcodec/bsf/Makefile
index fb70ad0c21..40b7fc6e9b 100644
--- a/libavcodec/bsf/Makefile
+++ b/libavcodec/bsf/Makefile
@@ -19,6 +19,7 @@ OBJS-$(CONFIG_H264_MP4TOANNEXB_BSF) += bsf/h264_mp4toannexb.o
OBJS-$(CONFIG_H264_REDUNDANT_PPS_BSF) += bsf/h264_redundant_pps.o
OBJS-$(CONFIG_HAPQA_EXTRACT_BSF) += bsf/hapqa_extract.o
OBJS-$(CONFIG_HEVC_METADATA_BSF) += bsf/h265_metadata.o
+OBJS-$(CONFIG_DOVI_RPU_BSF) += bsf/dovi_rpu.o
OBJS-$(CONFIG_HEVC_MP4TOANNEXB_BSF) += bsf/hevc_mp4toannexb.o
OBJS-$(CONFIG_IMX_DUMP_HEADER_BSF) += bsf/imx_dump_header.o
OBJS-$(CONFIG_MEDIA100_TO_MJPEGB_BSF) += bsf/media100_to_mjpegb.o
diff --git a/libavcodec/bsf/dovi_rpu.c b/libavcodec/bsf/dovi_rpu.c
new file mode 100644
index 0000000000..29e6e57bd9
--- /dev/null
+++ b/libavcodec/bsf/dovi_rpu.c
@@ -0,0 +1,279 @@
+/*
+ * This file is part of FFmpeg.
+ *
+ * FFmpeg is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * FFmpeg is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with FFmpeg; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "libavutil/common.h"
+#include "libavutil/mem.h"
+#include "libavutil/opt.h"
+
+#include "bsf.h"
+#include "bsf_internal.h"
+#include "cbs.h"
+#include "cbs_bsf.h"
+#include "cbs_av1.h"
+#include "cbs_h265.h"
+#include "dovi_rpu.h"
+#include "h2645data.h"
+#include "h265_profile_level.h"
+#include "itut35.h"
+
+#include "hevc/hevc.h"
+
+typedef struct DoviRpuContext {
+ CBSBSFContext common;
+ DOVIContext dec;
+ DOVIContext enc;
+
+ int strip;
+ int compression;
+} DoviRpuContext;
+
+static int update_rpu(AVBSFContext *bsf, const AVPacket *pkt, int flags,
+ const uint8_t *rpu, size_t rpu_size,
+ uint8_t **out_rpu, int *out_size)
+{
+ DoviRpuContext *s = bsf->priv_data;
+ AVDOVIMetadata *metadata = NULL;
+ int ret;
+
+ ret = ff_dovi_rpu_parse(&s->dec, rpu, rpu_size, 0);
+ if (ret < 0) {
+ ff_dovi_ctx_flush(&s->dec);
+ return ret;
+ }
+
+ ret = ff_dovi_get_metadata(&s->dec, &metadata);
+ if (ret == 0 /* no metadata */) {
+ *out_rpu = NULL;
+ *out_size = 0;
+ return 0;
+ } else if (ret < 0) {
+ ff_dovi_ctx_flush(&s->dec);
+ return ret;
+ }
+
+ if (pkt && !(pkt->flags & AV_PKT_FLAG_KEY))
+ flags |= FF_DOVI_COMPRESS_RPU;
+ ret = ff_dovi_rpu_generate(&s->enc, metadata, flags, out_rpu, out_size);
+ av_free(metadata);
+ if (ret < 0)
+ ff_dovi_ctx_flush(&s->enc);
+
+ return ret;
+}
+
+static int dovi_rpu_update_fragment_hevc(AVBSFContext *bsf, AVPacket *pkt,
+ CodedBitstreamFragment *au)
+{
+ DoviRpuContext *s = bsf->priv_data;
+ CodedBitstreamUnit *nal = au->nb_units ? &au->units[au->nb_units - 1] : NULL;
+ uint8_t *rpu = NULL;
+ int rpu_size, ret;
+
+ if (!nal || nal->type != HEVC_NAL_UNSPEC62)
+ return 0;
+
+ if (s->strip) {
+ ff_cbs_delete_unit(au, au->nb_units - 1);
+ return 0;
+ }
+
+ ret = update_rpu(bsf, pkt, 0, nal->data + 2, nal->data_size - 2, &rpu, &rpu_size);
+ if (ret < 0)
+ return ret;
+
+ /* NAL unit header + NAL prefix */
+ if (rpu_size + 3 <= nal->data_size && av_buffer_is_writable(nal->data_ref)) {
+ memcpy(nal->data + 3, rpu, rpu_size);
+ av_free(rpu);
+ nal->data_size = rpu_size + 3;
+ } else {
+ AVBufferRef *ref = av_buffer_alloc(rpu_size + 3);
+ if (!ref) {
+ av_free(rpu);
+ return AVERROR(ENOMEM);
+ }
+
+ memcpy(ref->data, nal->data, 3);
+ memcpy(ref->data + 3, rpu, rpu_size);
+ av_buffer_unref(&nal->data_ref);
+ av_free(rpu);
+ nal->data = ref->data;
+ nal->data_size = rpu_size + 3;
+ nal->data_ref = ref;
+ nal->data_bit_padding = 0;
+ }
+
+ return 0;
+}
+
+static int dovi_rpu_update_fragment_av1(AVBSFContext *bsf, AVPacket *pkt,
+ CodedBitstreamFragment *frag)
+{
+ DoviRpuContext *s = bsf->priv_data;
+ int provider_code, provider_oriented_code, rpu_size, ret;
+ AVBufferRef *ref;
+ uint8_t *rpu;
+
+ for (int i = 0; i < frag->nb_units; i++) {
+ AV1RawOBU *obu = frag->units[i].content;
+ AV1RawMetadataITUTT35 *t35 = &obu->obu.metadata.metadata.itut_t35;
+ if (frag->units[i].type != AV1_OBU_METADATA ||
+ obu->obu.metadata.metadata_type != AV1_METADATA_TYPE_ITUT_T35 ||
+ t35->itu_t_t35_country_code != ITU_T_T35_COUNTRY_CODE_US ||
+ t35->payload_size < 6)
+ continue;
+
+ provider_code = AV_RB16(t35->payload);
+ provider_oriented_code = AV_RB32(t35->payload + 2);
+ if (provider_code != ITU_T_T35_PROVIDER_CODE_DOLBY ||
+ provider_oriented_code != 0x800)
+ continue;
+
+ if (s->strip) {
+ ff_cbs_delete_unit(frag, i);
+ return 0;
+ }
+
+ ret = update_rpu(bsf, pkt, FF_DOVI_WRAP_T35,
+ t35->payload + 6, t35->payload_size - 6,
+ &rpu, &rpu_size);
+ if (ret < 0)
+ return ret;
+
+ ref = av_buffer_create(rpu, rpu_size, av_buffer_default_free, NULL, 0);
+ if (!ref) {
+ av_free(rpu);
+ return AVERROR(ENOMEM);
+ }
+
+ av_buffer_unref(&t35->payload_ref);
+ t35->payload_ref = ref;
+ t35->payload = rpu + 1; /* skip country code */
+ t35->payload_size = rpu_size - 1;
+ break; /* should be only one RPU per packet */
+ }
+
+ return 0;
+}
+
+static const CBSBSFType dovi_rpu_hevc_type = {
+ .codec_id = AV_CODEC_ID_HEVC,
+ .fragment_name = "access unit",
+ .unit_name = "NAL unit",
+ .update_fragment = &dovi_rpu_update_fragment_hevc,
+};
+
+static const CBSBSFType dovi_rpu_av1_type = {
+ .codec_id = AV_CODEC_ID_AV1,
+ .fragment_name = "temporal unit",
+ .unit_name = "OBU",
+ .update_fragment = &dovi_rpu_update_fragment_av1,
+};
+
+static int dovi_rpu_init(AVBSFContext *bsf)
+{
+ int ret;
+ DoviRpuContext *s = bsf->priv_data;
+ s->dec.logctx = s->enc.logctx = bsf;
+ s->enc.enable = 1;
+
+ if (s->compression == AV_DOVI_COMPRESSION_RESERVED) {
+ av_log(bsf, AV_LOG_ERROR, "Invalid compression level: %d\n", s->compression);
+ return AVERROR(EINVAL);
+ }
+
+ if (s->strip) {
+ av_packet_side_data_remove(bsf->par_out->coded_side_data,
+ &bsf->par_out->nb_coded_side_data,
+ AV_PKT_DATA_DOVI_CONF);
+ } else {
+ const AVPacketSideData *sd;
+ sd = av_packet_side_data_get(bsf->par_in->coded_side_data,
+ bsf->par_in->nb_coded_side_data,
+ AV_PKT_DATA_DOVI_CONF);
+
+ if (sd) {
+ s->dec.cfg = s->enc.cfg = *(AVDOVIDecoderConfigurationRecord *) sd->data;
+ s->enc.cfg.dv_md_compression = s->compression;
+ if (s->compression && s->dec.cfg.dv_profile < 8) {
+ av_log(bsf, AV_LOG_ERROR, "Invalid compression level %d for "
+ "Dolby Vision profile %d.\n", s->compression, s->dec.cfg.dv_profile);
+ return AVERROR(EINVAL);
+ }
+ } else {
+ av_log(bsf, AV_LOG_WARNING, "No Dolby Vision configuration record "
+ "found? Generating one, but results may be invalid.\n");
+ ret = ff_dovi_configure_ext(&s->enc, bsf->par_out, NULL, s->compression,
+ FF_COMPLIANCE_NORMAL);
+ if (ret < 0)
+ return ret;
+ /* Be conservative in accepting all compressed RPUs */
+ s->dec.cfg = s->enc.cfg;
+ s->dec.cfg.dv_md_compression = AV_DOVI_COMPRESSION_EXTENDED;
+ }
+ }
+
+ switch (bsf->par_in->codec_id) {
+ case AV_CODEC_ID_HEVC:
+ return ff_cbs_bsf_generic_init(bsf, &dovi_rpu_hevc_type);
+ case AV_CODEC_ID_AV1:
+ return ff_cbs_bsf_generic_init(bsf, &dovi_rpu_av1_type);
+ default:
+ return AVERROR_BUG;
+ }
+}
+
+static void dovi_rpu_close(AVBSFContext *bsf)
+{
+ DoviRpuContext *s = bsf->priv_data;
+ ff_dovi_ctx_unref(&s->dec);
+ ff_dovi_ctx_unref(&s->enc);
+ ff_cbs_bsf_generic_close(bsf);
+}
+
+#define OFFSET(x) offsetof(DoviRpuContext, x)
+#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_BSF_PARAM)
+static const AVOption dovi_rpu_options[] = {
+ { "strip", "Strip Dolby Vision metadata", OFFSET(strip), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
+ { "compression", "DV metadata compression mode", OFFSET(compression), AV_OPT_TYPE_INT, { .i64 = AV_DOVI_COMPRESSION_LIMITED }, 0, AV_DOVI_COMPRESSION_EXTENDED, FLAGS, .unit = "compression" },
+ { "none", "Don't compress metadata", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, .flags = FLAGS, .unit = "compression" },
+ { "limited", "Limited metadata compression", 0, AV_OPT_TYPE_CONST, {.i64 = AV_DOVI_COMPRESSION_LIMITED}, .flags = FLAGS, .unit = "compression" },
+ { "extended", "Extended metadata compression",0, AV_OPT_TYPE_CONST, {.i64 = AV_DOVI_COMPRESSION_EXTENDED}, .flags = FLAGS, .unit = "compression" },
+ { NULL }
+};
+
+static const AVClass dovi_rpu_class = {
+ .class_name = "dovi_rpu_bsf",
+ .item_name = av_default_item_name,
+ .option = dovi_rpu_options,
+ .version = LIBAVUTIL_VERSION_INT,
+};
+
+static const enum AVCodecID dovi_rpu_codec_ids[] = {
+ AV_CODEC_ID_HEVC, AV_CODEC_ID_AV1, AV_CODEC_ID_NONE,
+};
+
+const FFBitStreamFilter ff_dovi_rpu_bsf = {
+ .p.name = "dovi_rpu",
+ .p.codec_ids = dovi_rpu_codec_ids,
+ .p.priv_class = &dovi_rpu_class,
+ .priv_data_size = sizeof(DoviRpuContext),
+ .init = &dovi_rpu_init,
+ .close = &dovi_rpu_close,
+ .filter = &ff_cbs_bsf_generic_filter,
+};
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 13/22] avcodec/dovi_rpu: move ext blocks into dedicated struct
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (10 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 12/22] avcodec/bsf/dovi_rpu: add new bitstream filter Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 14/22] avcodec/dovi_rpu: separate static ext blocks Niklas Haas
` (9 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Slightly re-organize the logic around extension blocks in order to allow
expanding the state tracking in a following commit.
---
libavcodec/dovi_rpu.c | 1 -
libavcodec/dovi_rpu.h | 9 +++++++--
libavcodec/dovi_rpudec.c | 35 ++++++++++++++++++++++-------------
libavcodec/dovi_rpuenc.c | 16 +++++++++-------
4 files changed, 38 insertions(+), 23 deletions(-)
diff --git a/libavcodec/dovi_rpu.c b/libavcodec/dovi_rpu.c
index b67978403f..5130a9598d 100644
--- a/libavcodec/dovi_rpu.c
+++ b/libavcodec/dovi_rpu.c
@@ -66,7 +66,6 @@ void ff_dovi_ctx_replace(DOVIContext *s, const DOVIContext *s0)
for (int i = 0; i <= DOVI_MAX_DM_ID; i++)
ff_refstruct_replace(&s->vdr[i], s0->vdr[i]);
ff_refstruct_replace(&s->ext_blocks, s0->ext_blocks);
- s->num_ext_blocks = s0->num_ext_blocks;
}
int ff_dovi_guess_profile_hevc(const AVDOVIRpuDataHeader *hdr)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index 24a8353bdc..ed5bfa7b26 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -31,6 +31,12 @@
#include "codec_par.h"
#define DOVI_MAX_DM_ID 15
+
+typedef struct DOVIExt {
+ AVDOVIDmData dm[AV_DOVI_MAX_EXT_BLOCKS];
+ int num_dm;
+} DOVIExt;
+
typedef struct DOVIContext {
void *logctx;
@@ -70,8 +76,7 @@ typedef struct DOVIContext {
* Currently active extension blocks, updates on every ff_dovi_rpu_parse()
* or ff_dovi_rpu_generate().
*/
- AVDOVIDmData *ext_blocks;
- int num_ext_blocks;
+ DOVIExt *ext_blocks; ///< RefStruct, or NULL if no extension blocks
/**
* Private fields internal to dovi_rpu.c
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 0ddc923539..1650547c80 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -33,7 +33,7 @@
int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
{
AVDOVIMetadata *dovi;
- size_t dovi_size, ext_sz;
+ size_t dovi_size;
if (!s->mapping || !s->color)
return 0; /* incomplete dovi metadata */
@@ -47,10 +47,14 @@ int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
COPY(AVDOVIRpuDataHeader, av_dovi_get_header(dovi), &s->header, ext_mapping_idc_5_7);
COPY(AVDOVIDataMapping, av_dovi_get_mapping(dovi), s->mapping, nlq_pivots);
COPY(AVDOVIColorMetadata, av_dovi_get_color(dovi), s->color, source_diagonal);
- ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
- for (int i = 0; i < s->num_ext_blocks; i++)
- memcpy(av_dovi_get_ext(dovi, i), &s->ext_blocks[i], ext_sz);
- dovi->num_ext_blocks = s->num_ext_blocks;
+
+ if (s->ext_blocks) {
+ const DOVIExt *ext = s->ext_blocks;
+ size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
+ for (int i = 0; i < ext->num_dm; i++)
+ memcpy(av_dovi_get_ext(dovi, i), &ext->dm[i], ext_sz);
+ dovi->num_ext_blocks = ext->num_dm;
+ }
*out_metadata = dovi;
return dovi_size;
@@ -279,20 +283,24 @@ static int parse_ext_v2(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm,
static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
{
int num_ext_blocks, ext_block_length, start_pos, parsed_bits, ret;
+ DOVIExt *ext = s->ext_blocks;
num_ext_blocks = get_ue_golomb_31(gb);
align_get_bits(gb);
- if (s->num_ext_blocks + num_ext_blocks > AV_DOVI_MAX_EXT_BLOCKS)
- return AVERROR_INVALIDDATA;
- if (!s->ext_blocks) {
- s->ext_blocks = ff_refstruct_allocz(sizeof(AVDOVIDmData) * AV_DOVI_MAX_EXT_BLOCKS);
- if (!s->ext_blocks)
+ if (!ext) {
+ ext = s->ext_blocks = ff_refstruct_allocz(sizeof(*s->ext_blocks));
+ if (!ext)
return AVERROR(ENOMEM);
}
while (num_ext_blocks--) {
- AVDOVIDmData *dm = &s->ext_blocks[s->num_ext_blocks++];
+ AVDOVIDmData *dm;
+
+ if (ext->num_dm >= FF_ARRAY_ELEMS(ext->dm))
+ return AVERROR_INVALIDDATA;
+ dm = &ext->dm[ext->num_dm++];
+
ext_block_length = get_ue_golomb_31(gb);
dm->level = get_bits(gb, 8);
start_pos = get_bits_count(gb);
@@ -666,7 +674,8 @@ 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 (s->ext_blocks)
+ s->ext_blocks->num_dm = 0;
if ((ret = parse_ext_blocks(s, gb, 1)) < 0) {
ff_dovi_ctx_unref(s);
return ret;
@@ -680,7 +689,7 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
}
} else {
s->color = &ff_dovi_color_default;
- s->num_ext_blocks = 0;
+ ff_refstruct_unref(&s->ext_blocks);
}
return 0;
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 25e520dd92..667d681c25 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -583,7 +583,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
if (metadata->num_ext_blocks && !s->ext_blocks) {
- s->ext_blocks = ff_refstruct_allocz(sizeof(AVDOVIDmData) * AV_DOVI_MAX_EXT_BLOCKS);
+ s->ext_blocks = ff_refstruct_allocz(sizeof(*s->ext_blocks));
if (!s->ext_blocks)
return AVERROR(ENOMEM);
}
@@ -717,7 +717,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
if (vdr_dm_metadata_present) {
- size_t ext_sz;
+ DOVIExt *ext = s->ext_blocks;
const int denom = profile == 4 ? (1 << 30) : (1 << 28);
set_ue_golomb(pb, color->dm_metadata_id); /* affected_dm_id */
set_ue_golomb(pb, color->dm_metadata_id); /* current_dm_id */
@@ -756,13 +756,15 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
generate_ext_v2(pb, av_dovi_get_ext(metadata, i));
}
- ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
- for (int i = 0; i < metadata->num_ext_blocks; i++)
- memcpy(&s->ext_blocks[i], av_dovi_get_ext(metadata, i), ext_sz);
- s->num_ext_blocks = metadata->num_ext_blocks;
+ if (ext) {
+ size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
+ for (int i = 0; i < metadata->num_ext_blocks; i++)
+ memcpy(&ext->dm[i], av_dovi_get_ext(metadata, i), ext_sz);
+ ext->num_dm = metadata->num_ext_blocks;
+ }
} else {
s->color = &ff_dovi_color_default;
- s->num_ext_blocks = 0;
+ ff_refstruct_unref(&s->ext_blocks);
}
flush_put_bits(pb);
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 14/22] avcodec/dovi_rpu: separate static ext blocks
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (11 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 13/22] avcodec/dovi_rpu: move ext blocks into dedicated struct Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 15/22] avcodec/dovi_rpudec: don't unnecessarily allocate DOVIExt Niklas Haas
` (8 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Static and dynamic extension blocks are handled differently by metadata
compression, so we need to separate the extension block array into two.
---
libavcodec/dovi_rpu.h | 20 ++++++++++++++++++--
libavcodec/dovi_rpudec.c | 31 +++++++++++++++++++++----------
libavcodec/dovi_rpuenc.c | 11 ++++++++---
3 files changed, 47 insertions(+), 15 deletions(-)
diff --git a/libavcodec/dovi_rpu.h b/libavcodec/dovi_rpu.h
index ed5bfa7b26..f3ccc27ae8 100644
--- a/libavcodec/dovi_rpu.h
+++ b/libavcodec/dovi_rpu.h
@@ -33,8 +33,10 @@
#define DOVI_MAX_DM_ID 15
typedef struct DOVIExt {
- AVDOVIDmData dm[AV_DOVI_MAX_EXT_BLOCKS];
- int num_dm;
+ AVDOVIDmData dm_static[7]; ///< static extension blocks
+ AVDOVIDmData dm_dynamic[25]; ///< dynamic extension blocks
+ int num_static;
+ int num_dynamic;
} DOVIExt;
typedef struct DOVIContext {
@@ -191,4 +193,18 @@ int ff_dovi_guess_profile_hevc(const AVDOVIRpuDataHeader *hdr);
/* Default values for AVDOVIColorMetadata */
extern const AVDOVIColorMetadata ff_dovi_color_default;
+static inline int ff_dovi_rpu_extension_is_static(int level)
+{
+ switch (level) {
+ case 6:
+ case 10:
+ case 32: /* reserved as static by spec */
+ case 254:
+ case 255:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
#endif /* AVCODEC_DOVI_RPU_H */
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 1650547c80..6ef7a88ffd 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -51,9 +51,10 @@ int ff_dovi_get_metadata(DOVIContext *s, AVDOVIMetadata **out_metadata)
if (s->ext_blocks) {
const DOVIExt *ext = s->ext_blocks;
size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), dovi->ext_block_size);
- for (int i = 0; i < ext->num_dm; i++)
- memcpy(av_dovi_get_ext(dovi, i), &ext->dm[i], ext_sz);
- dovi->num_ext_blocks = ext->num_dm;
+ for (int i = 0; i < ext->num_static; i++)
+ memcpy(av_dovi_get_ext(dovi, dovi->num_ext_blocks++), &ext->dm_static[i], ext_sz);
+ for (int i = 0; i < ext->num_dynamic; i++)
+ memcpy(av_dovi_get_ext(dovi, dovi->num_ext_blocks++), &ext->dm_dynamic[i], ext_sz);
}
*out_metadata = dovi;
@@ -296,15 +297,23 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
while (num_ext_blocks--) {
AVDOVIDmData *dm;
-
- if (ext->num_dm >= FF_ARRAY_ELEMS(ext->dm))
- return AVERROR_INVALIDDATA;
- dm = &ext->dm[ext->num_dm++];
+ uint8_t level;
ext_block_length = get_ue_golomb_31(gb);
- dm->level = get_bits(gb, 8);
+ level = get_bits(gb, 8);
start_pos = get_bits_count(gb);
+ if (ff_dovi_rpu_extension_is_static(level)) {
+ if (ext->num_static >= FF_ARRAY_ELEMS(ext->dm_static))
+ return AVERROR_INVALIDDATA;
+ dm = &ext->dm_static[ext->num_static++];
+ } else {
+ if (ext->num_dynamic >= FF_ARRAY_ELEMS(ext->dm_dynamic))
+ return AVERROR_INVALIDDATA;
+ dm = &ext->dm_dynamic[ext->num_dynamic++];
+ }
+
+ dm->level = level;
switch (ver) {
case 1: ret = parse_ext_v1(s, gb, dm); break;
case 2: ret = parse_ext_v2(s, gb, dm, ext_block_length); break;
@@ -674,8 +683,10 @@ 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 */
- if (s->ext_blocks)
- s->ext_blocks->num_dm = 0;
+ if (s->ext_blocks) {
+ DOVIExt *ext = s->ext_blocks;
+ ext->num_static = ext->num_dynamic = 0;
+ }
if ((ret = parse_ext_blocks(s, gb, 1)) < 0) {
ff_dovi_ctx_unref(s);
return ret;
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 667d681c25..7193e2d9c8 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -758,9 +758,14 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
if (ext) {
size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
- for (int i = 0; i < metadata->num_ext_blocks; i++)
- memcpy(&ext->dm[i], av_dovi_get_ext(metadata, i), ext_sz);
- ext->num_dm = metadata->num_ext_blocks;
+ ext->num_static = ext->num_dynamic = 0;
+ for (int i = 0; i < metadata->num_ext_blocks; i++) {
+ const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
+ if (ff_dovi_rpu_extension_is_static(dm->level))
+ memcpy(&ext->dm_static[ext->num_static++], dm, ext_sz);
+ else
+ memcpy(&ext->dm_dynamic[ext->num_dynamic++], dm, ext_sz);
+ }
}
} else {
s->color = &ff_dovi_color_default;
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 15/22] avcodec/dovi_rpudec: don't unnecessarily allocate DOVIExt
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (12 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 14/22] avcodec/dovi_rpu: separate static ext blocks Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 16/22] avcodec/dovi_rpudec: implement limited DM decompression Niklas Haas
` (7 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
---
libavcodec/dovi_rpudec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 6ef7a88ffd..3465665961 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -289,7 +289,7 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
num_ext_blocks = get_ue_golomb_31(gb);
align_get_bits(gb);
- if (!ext) {
+ if (num_ext_blocks && !ext) {
ext = s->ext_blocks = ff_refstruct_allocz(sizeof(*s->ext_blocks));
if (!ext)
return AVERROR(ENOMEM);
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 16/22] avcodec/dovi_rpudec: implement limited DM decompression
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (13 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 15/22] avcodec/dovi_rpudec: don't unnecessarily allocate DOVIExt Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 17/22] avcodec/dovi_rpudec: sanitize DM data before decoding Niklas Haas
` (6 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
This implements the limited DM metadata compression scheme described in
chapter 9 of the dolby vision bitstream specification.
The spec is a bit unclear about how to handle the presence of static
metadata inside compressed frames; in that it doesn't explicitly forbid
an encoder from repeating redundant metadata. In theory, we would need
to detect this case and then strip the corresponding duplicate metadata
from the existing set of static metadata. However, this is difficult to
implement - esspecially for the case of metadata blocks which may be
internally repeated (e.g. level 10).
That said, the spec states outright that static metadata should be
constant throughout the entire sequence, so a sane bitstream should not
have any static metadata values changing from one frame to the next (at
least up to a keyframe boundary), and therefore they should never be
present in compressed frames. As a consequence, it makes sense to treat
this as an error state regardless. (Ignoring them by default, or
erroring if either AV_EF_EXPLODE or AV_EF_AGGRESSIVE are set)
I was not able to find such samples in the wild (outside of artificially
produced test cases for this exact scenario), so I don't think we need
to worry about it until somebody produces one.
---
libavcodec/dovi_rpudec.c | 100 +++++++++++++++++++++++++--------------
1 file changed, 65 insertions(+), 35 deletions(-)
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 3465665961..91c9e41926 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -281,7 +281,8 @@ static int parse_ext_v2(DOVIContext *s, GetBitContext *gb, AVDOVIDmData *dm,
return 0;
}
-static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
+static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver,
+ int compression, int err_recognition)
{
int num_ext_blocks, ext_block_length, start_pos, parsed_bits, ret;
DOVIExt *ext = s->ext_blocks;
@@ -296,6 +297,7 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
}
while (num_ext_blocks--) {
+ AVDOVIDmData dummy;
AVDOVIDmData *dm;
uint8_t level;
@@ -304,9 +306,17 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver)
start_pos = get_bits_count(gb);
if (ff_dovi_rpu_extension_is_static(level)) {
- if (ext->num_static >= FF_ARRAY_ELEMS(ext->dm_static))
- return AVERROR_INVALIDDATA;
- dm = &ext->dm_static[ext->num_static++];
+ if (compression) {
+ av_log(s->logctx, AV_LOG_WARNING, "Compressed DM RPU contains "
+ "static extension block level %d\n", level);
+ if (err_recognition & (AV_EF_AGGRESSIVE | AV_EF_EXPLODE))
+ return AVERROR_INVALIDDATA;
+ dm = &dummy;
+ } else {
+ if (ext->num_static >= FF_ARRAY_ELEMS(ext->dm_static))
+ return AVERROR_INVALIDDATA;
+ dm = &ext->dm_static[ext->num_static++];
+ }
} else {
if (ext->num_dynamic >= FF_ARRAY_ELEMS(ext->dm_dynamic))
return AVERROR_INVALIDDATA;
@@ -342,6 +352,7 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
uint8_t rpu_type;
uint8_t vdr_seq_info_present;
uint8_t vdr_dm_metadata_present;
+ uint8_t dm_compression = 0;
uint8_t use_prev_vdr_rpu;
uint8_t use_nlq;
uint8_t profile;
@@ -454,7 +465,6 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
int bl_bit_depth_minus8 = get_ue_golomb_31(gb);
int el_bit_depth_minus8 = get_ue_golomb_long(gb);
int vdr_bit_depth_minus8 = get_ue_golomb_31(gb);
- int reserved_zero_3bits;
/* ext_mapping_idc is in the upper 8 bits of el_bit_depth_minus8 */
int ext_mapping_idc = el_bit_depth_minus8 >> 8;
el_bit_depth_minus8 = el_bit_depth_minus8 & 0xFF;
@@ -468,8 +478,7 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
hdr->ext_mapping_idc_5_7 = ext_mapping_idc >> 5;
hdr->vdr_bit_depth = vdr_bit_depth_minus8 + 8;
hdr->spatial_resampling_filter_flag = get_bits1(gb);
- reserved_zero_3bits = get_bits(gb, 3);
- VALIDATE(reserved_zero_3bits, 0, 0);
+ dm_compression = get_bits(gb, 3);
hdr->el_spatial_resampling_filter_flag = get_bits1(gb);
hdr->disable_residual_flag = get_bits1(gb);
}
@@ -481,6 +490,17 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
}
vdr_dm_metadata_present = get_bits1(gb);
+ if (dm_compression > 1) {
+ /* It seems no device supports this */
+ av_log(s->logctx, AV_LOG_ERROR, "Dynamic metadata compression is not "
+ "yet implemented");
+ return AVERROR_PATCHWELCOME;
+ } else if (dm_compression && !vdr_dm_metadata_present) {
+ av_log(s->logctx, AV_LOG_ERROR, "Nonzero DM metadata compression method "
+ "but no DM metadata present");
+ return AVERROR_INVALIDDATA;
+ }
+
use_prev_vdr_rpu = get_bits1(gb);
use_nlq = (hdr->rpu_format & 0x700) == 0 && !hdr->disable_residual_flag;
@@ -503,6 +523,12 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
"use_prev_vdr_rpu=1\n");
return AVERROR_INVALIDDATA;
}
+
+ if (dm_compression && !compression) {
+ av_log(s->logctx, AV_LOG_ERROR, "Uncompressed RPUs should not use "
+ "dm_compression=%d\n", dm_compression);
+ return AVERROR_INVALIDDATA;
+ }
}
if (use_prev_vdr_rpu) {
@@ -654,46 +680,50 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
s->color = color = s->dm;
color->dm_metadata_id = affected_dm_id;
color->scene_refresh_flag = get_ue_golomb_31(gb);
- for (int i = 0; i < 9; i++)
- color->ycc_to_rgb_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 13);
- for (int i = 0; i < 3; i++) {
- int denom = profile == 4 ? (1 << 30) : (1 << 28);
- unsigned offset = get_bits_long(gb, 32);
- if (offset > INT_MAX) {
- /* Ensure the result fits inside AVRational */
- offset >>= 1;
- denom >>= 1;
+ if (!dm_compression) {
+ for (int i = 0; i < 9; i++)
+ color->ycc_to_rgb_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 13);
+ for (int i = 0; i < 3; i++) {
+ int denom = profile == 4 ? (1 << 30) : (1 << 28);
+ unsigned offset = get_bits_long(gb, 32);
+ if (offset > INT_MAX) {
+ /* Ensure the result fits inside AVRational */
+ offset >>= 1;
+ denom >>= 1;
+ }
+ color->ycc_to_rgb_offset[i] = av_make_q(offset, denom);
}
- color->ycc_to_rgb_offset[i] = av_make_q(offset, denom);
+ for (int i = 0; i < 9; i++)
+ color->rgb_to_lms_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 14);
+
+ color->signal_eotf = get_bits(gb, 16);
+ color->signal_eotf_param0 = get_bits(gb, 16);
+ color->signal_eotf_param1 = get_bits(gb, 16);
+ color->signal_eotf_param2 = get_bits_long(gb, 32);
+ color->signal_bit_depth = get_bits(gb, 5);
+ VALIDATE(color->signal_bit_depth, 8, 16);
+ color->signal_color_space = get_bits(gb, 2);
+ color->signal_chroma_format = get_bits(gb, 2);
+ color->signal_full_range_flag = get_bits(gb, 2);
+ color->source_min_pq = get_bits(gb, 12);
+ color->source_max_pq = get_bits(gb, 12);
+ color->source_diagonal = get_bits(gb, 10);
}
- for (int i = 0; i < 9; i++)
- color->rgb_to_lms_matrix[i] = av_make_q(get_sbits(gb, 16), 1 << 14);
-
- color->signal_eotf = get_bits(gb, 16);
- color->signal_eotf_param0 = get_bits(gb, 16);
- color->signal_eotf_param1 = get_bits(gb, 16);
- color->signal_eotf_param2 = get_bits_long(gb, 32);
- color->signal_bit_depth = get_bits(gb, 5);
- VALIDATE(color->signal_bit_depth, 8, 16);
- color->signal_color_space = get_bits(gb, 2);
- color->signal_chroma_format = get_bits(gb, 2);
- color->signal_full_range_flag = get_bits(gb, 2);
- color->source_min_pq = get_bits(gb, 12);
- color->source_max_pq = get_bits(gb, 12);
- color->source_diagonal = get_bits(gb, 10);
/* Parse extension blocks */
if (s->ext_blocks) {
DOVIExt *ext = s->ext_blocks;
- ext->num_static = ext->num_dynamic = 0;
+ if (!dm_compression)
+ ext->num_static = 0;
+ ext->num_dynamic = 0;
}
- if ((ret = parse_ext_blocks(s, gb, 1)) < 0) {
+ if ((ret = parse_ext_blocks(s, gb, 1, dm_compression, err_recognition)) < 0) {
ff_dovi_ctx_unref(s);
return ret;
}
if (get_bits_left(gb) > 48 /* padding + CRC32 + terminator */) {
- if ((ret = parse_ext_blocks(s, gb, 2)) < 0) {
+ if ((ret = parse_ext_blocks(s, gb, 2, dm_compression, err_recognition)) < 0) {
ff_dovi_ctx_unref(s);
return ret;
}
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 17/22] avcodec/dovi_rpudec: sanitize DM data before decoding
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (14 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 16/22] avcodec/dovi_rpudec: implement limited DM decompression Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 18/22] avcodec/dovi_rpuenc: implement DM metadata compression Niklas Haas
` (5 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Some DM types do not fill the whole struct, so just clear it entirely
before going filling the decoded values.
---
libavcodec/dovi_rpudec.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 91c9e41926..9f295d4fe4 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -323,6 +323,7 @@ static int parse_ext_blocks(DOVIContext *s, GetBitContext *gb, int ver,
dm = &ext->dm_dynamic[ext->num_dynamic++];
}
+ memset(dm, 0, sizeof(*dm));
dm->level = level;
switch (ver) {
case 1: ret = parse_ext_v1(s, gb, dm); break;
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 18/22] avcodec/dovi_rpuenc: implement DM metadata compression
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (15 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 17/22] avcodec/dovi_rpudec: sanitize DM data before decoding Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 19/22] avcodec/dovi_rpuenc: slightly improve profile autodetection Niklas Haas
` (4 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
This implements limited metadata compression. To be a bit more lenient,
we try and re-order the static extension blocks when testing for an
exact match.
For sanity, and to avoid producing bitstreams we couldn't ourselves
decode, we don't accept partial matches - if some extension blocks
change while others remain static, compression is disabled for the
entire frame.
This shouldn't be an issue in practice because static extension blocks
are stated to remain constant throughout the entire sequence.
---
libavcodec/dovi_rpuenc.c | 166 +++++++++++++++++++++++++++++----------
1 file changed, 124 insertions(+), 42 deletions(-)
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index 7193e2d9c8..c73805037c 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -257,6 +257,62 @@ fail:
return ret;
}
+/* Compares only the static DM metadata parts of AVDOVIColorMetadata (excluding
+ * dm_metadata_id and scene_refresh_flag) */
+static int cmp_dm_level0(const AVDOVIColorMetadata *dm1,
+ const AVDOVIColorMetadata *dm2)
+{
+ int ret;
+ for (int i = 0; i < FF_ARRAY_ELEMS(dm1->ycc_to_rgb_matrix); i++) {
+ if ((ret = av_cmp_q(dm1->ycc_to_rgb_matrix[i], dm2->ycc_to_rgb_matrix[i])))
+ return ret;
+ }
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(dm1->ycc_to_rgb_offset); i++) {
+ if ((ret = av_cmp_q(dm1->ycc_to_rgb_offset[i], dm2->ycc_to_rgb_offset[i])))
+ return ret;
+ }
+
+ for (int i = 0; i < FF_ARRAY_ELEMS(dm1->rgb_to_lms_matrix); i++) {
+ if ((ret = av_cmp_q(dm1->rgb_to_lms_matrix[i], dm2->rgb_to_lms_matrix[i])))
+ return ret;
+ }
+
+ return memcmp(&dm1->signal_eotf, &dm2->signal_eotf,
+ sizeof(AVDOVIColorMetadata) -offsetof(AVDOVIColorMetadata, signal_eotf));
+}
+
+/* Tries to re-use the static ext blocks. May reorder `ext->dm_static` */
+static int try_reuse_ext(DOVIExt *ext, const AVDOVIMetadata *metadata)
+{
+ int i, j, idx = 0;
+
+ for (i = 0; i < metadata->num_ext_blocks; i++) {
+ const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
+ if (!ff_dovi_rpu_extension_is_static(dm->level))
+ continue;
+
+ /* Find the first matching ext block and move it to [idx] */
+ for (j = idx; j < ext->num_static; j++) {
+ if (!memcmp(&ext->dm_static[j], dm, sizeof(*dm))) {
+ if (j != idx)
+ FFSWAP(AVDOVIDmData, ext->dm_static[j], ext->dm_static[idx]);
+ idx++;
+ break;
+ }
+ }
+
+ if (j == ext->num_static) {
+ /* Found no matching ext block */
+ return 0;
+ }
+ }
+
+ /* If idx is less than ext->num_static, then there are extra unmatched
+ * ext blocks inside ext->dm_static */
+ return idx == ext->num_static;
+}
+
static inline void put_ue_coef(PutBitContext *pb, const AVDOVIRpuDataHeader *hdr,
uint64_t coef)
{
@@ -498,7 +554,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
const AVDOVIDataMapping *mapping;
const AVDOVIColorMetadata *color;
int vdr_dm_metadata_present, vdr_rpu_id, use_prev_vdr_rpu, profile,
- buffer_size, rpu_size, pad, zero_run;
+ buffer_size, rpu_size, pad, zero_run, dm_compression;
int num_ext_blocks_v1, num_ext_blocks_v2;
int dv_md_compression = s->cfg.dv_md_compression;
uint32_t crc;
@@ -514,6 +570,11 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
color = av_dovi_get_color(metadata);
av_assert0(s->cfg.dv_profile);
+ if (!(flags & FF_DOVI_COMPRESS_RPU))
+ dv_md_compression = AV_DOVI_COMPRESSION_NONE;
+ else if (dv_md_compression == AV_DOVI_COMPRESSION_RESERVED)
+ return AVERROR(EINVAL);
+
if (hdr->rpu_type != 2) {
av_log(s->logctx, AV_LOG_ERROR, "Unhandled RPU type %"PRIu8"\n",
hdr->rpu_type);
@@ -555,9 +616,34 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
}
+ if (metadata->num_ext_blocks && !s->ext_blocks) {
+ s->ext_blocks = ff_refstruct_allocz(sizeof(*s->ext_blocks));
+ if (!s->ext_blocks)
+ return AVERROR(ENOMEM);
+ }
+
+ vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
+ if (metadata->num_ext_blocks)
+ vdr_dm_metadata_present = 1;
+
+ if (vdr_dm_metadata_present && !s->dm) {
+ s->dm = ff_refstruct_allocz(sizeof(AVDOVIColorMetadata));
+ if (!s->dm)
+ return AVERROR(ENOMEM);
+ }
+
+ dm_compression = 0;
+ if (dv_md_compression != AV_DOVI_COMPRESSION_NONE) {
+ if (!cmp_dm_level0(s->dm, color) && try_reuse_ext(s->ext_blocks, metadata))
+ dm_compression = 1;
+ }
+
num_ext_blocks_v1 = num_ext_blocks_v2 = 0;
for (int i = 0; i < metadata->num_ext_blocks; i++) {
const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
+ if (dm_compression && ff_dovi_rpu_extension_is_static(dm->level))
+ continue;
+
switch (dm->level) {
case 1:
case 2:
@@ -582,22 +668,6 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
}
}
- if (metadata->num_ext_blocks && !s->ext_blocks) {
- s->ext_blocks = ff_refstruct_allocz(sizeof(*s->ext_blocks));
- if (!s->ext_blocks)
- return AVERROR(ENOMEM);
- }
-
- vdr_dm_metadata_present = memcmp(color, &ff_dovi_color_default, sizeof(*color));
- if (num_ext_blocks_v1 || num_ext_blocks_v2)
- vdr_dm_metadata_present = 1;
-
- if (vdr_dm_metadata_present && !s->dm) {
- s->dm = ff_refstruct_allocz(sizeof(AVDOVIColorMetadata));
- if (!s->dm)
- return AVERROR(ENOMEM);
- }
-
buffer_size = 12 /* vdr seq info */ + 5 /* CRC32 + terminator */;
buffer_size += num_ext_blocks_v1 * 13;
buffer_size += num_ext_blocks_v2 * 28;
@@ -638,7 +708,7 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
set_ue_golomb(pb, (ext_mapping_idc << 8) | (hdr->el_bit_depth - 8));
set_ue_golomb(pb, hdr->vdr_bit_depth - 8);
put_bits(pb, 1, hdr->spatial_resampling_filter_flag);
- put_bits(pb, 3, 0); /* reserved_zero_3bits */
+ put_bits(pb, 3, dm_compression);
put_bits(pb, 1, hdr->el_spatial_resampling_filter_flag);
put_bits(pb, 1, hdr->disable_residual_flag);
}
@@ -722,23 +792,25 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
set_ue_golomb(pb, color->dm_metadata_id); /* affected_dm_id */
set_ue_golomb(pb, color->dm_metadata_id); /* current_dm_id */
set_ue_golomb(pb, color->scene_refresh_flag);
- for (int i = 0; i < 9; i++)
- put_sbits(pb, 16, av_q2den(color->ycc_to_rgb_matrix[i], 1 << 13));
- for (int i = 0; i < 3; i++)
- put_bits32(pb, av_q2den(color->ycc_to_rgb_offset[i], denom));
- for (int i = 0; i < 9; i++)
- put_sbits(pb, 16, av_q2den(color->rgb_to_lms_matrix[i], 1 << 14));
- put_bits(pb, 16, color->signal_eotf);
- put_bits(pb, 16, color->signal_eotf_param0);
- put_bits(pb, 16, color->signal_eotf_param1);
- put_bits32(pb, color->signal_eotf_param2);
- put_bits(pb, 5, color->signal_bit_depth);
- put_bits(pb, 2, color->signal_color_space);
- put_bits(pb, 2, color->signal_chroma_format);
- put_bits(pb, 2, color->signal_full_range_flag);
- put_bits(pb, 12, color->source_min_pq);
- put_bits(pb, 12, color->source_max_pq);
- put_bits(pb, 10, color->source_diagonal);
+ if (!dm_compression) {
+ for (int i = 0; i < 9; i++)
+ put_sbits(pb, 16, av_q2den(color->ycc_to_rgb_matrix[i], 1 << 13));
+ for (int i = 0; i < 3; i++)
+ put_bits32(pb, av_q2den(color->ycc_to_rgb_offset[i], denom));
+ for (int i = 0; i < 9; i++)
+ put_sbits(pb, 16, av_q2den(color->rgb_to_lms_matrix[i], 1 << 14));
+ put_bits(pb, 16, color->signal_eotf);
+ put_bits(pb, 16, color->signal_eotf_param0);
+ put_bits(pb, 16, color->signal_eotf_param1);
+ put_bits32(pb, color->signal_eotf_param2);
+ put_bits(pb, 5, color->signal_bit_depth);
+ put_bits(pb, 2, color->signal_color_space);
+ put_bits(pb, 2, color->signal_chroma_format);
+ put_bits(pb, 2, color->signal_full_range_flag);
+ put_bits(pb, 12, color->source_min_pq);
+ put_bits(pb, 12, color->source_max_pq);
+ put_bits(pb, 10, color->source_diagonal);
+ }
memcpy(s->dm, color, sizeof(*color));
s->color = s->dm;
@@ -746,25 +818,35 @@ int ff_dovi_rpu_generate(DOVIContext *s, const AVDOVIMetadata *metadata,
/* Extension blocks */
set_ue_golomb(pb, num_ext_blocks_v1);
align_put_bits(pb);
- for (int i = 0; i < metadata->num_ext_blocks; i++)
- generate_ext_v1(pb, av_dovi_get_ext(metadata, i));
+ for (int i = 0; i < metadata->num_ext_blocks; i++) {
+ const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
+ if (dm_compression && ff_dovi_rpu_extension_is_static(dm->level))
+ continue;
+ generate_ext_v1(pb, dm);
+ }
if (num_ext_blocks_v2) {
set_ue_golomb(pb, num_ext_blocks_v2);
align_put_bits(pb);
- for (int i = 0; i < metadata->num_ext_blocks; i++)
+ for (int i = 0; i < metadata->num_ext_blocks; i++) {
+ const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
+ if (dm_compression && ff_dovi_rpu_extension_is_static(dm->level))
+ continue;
generate_ext_v2(pb, av_dovi_get_ext(metadata, i));
+ }
}
if (ext) {
size_t ext_sz = FFMIN(sizeof(AVDOVIDmData), metadata->ext_block_size);
- ext->num_static = ext->num_dynamic = 0;
+ ext->num_dynamic = 0;
+ if (!dm_compression)
+ ext->num_static = 0;
for (int i = 0; i < metadata->num_ext_blocks; i++) {
const AVDOVIDmData *dm = av_dovi_get_ext(metadata, i);
- if (ff_dovi_rpu_extension_is_static(dm->level))
- memcpy(&ext->dm_static[ext->num_static++], dm, ext_sz);
- else
+ if (!ff_dovi_rpu_extension_is_static(dm->level))
memcpy(&ext->dm_dynamic[ext->num_dynamic++], dm, ext_sz);
+ else if (!dm_compression)
+ memcpy(&ext->dm_static[ext->num_static++], dm, ext_sz);
}
}
} else {
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 19/22] avcodec/dovi_rpuenc: slightly improve profile autodetection
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (16 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 18/22] avcodec/dovi_rpuenc: implement DM metadata compression Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 20/22] avcodec/dovi_rpudec: error out on strange RPU formats Niklas Haas
` (3 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
In the absence of an RPU header, we can consult the colorspace tags to
make a more informed guess about whether we're looking at profile 5 or
profile 8.
---
libavcodec/dovi_rpuenc.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/libavcodec/dovi_rpuenc.c b/libavcodec/dovi_rpuenc.c
index c73805037c..8113ec44bf 100644
--- a/libavcodec/dovi_rpuenc.c
+++ b/libavcodec/dovi_rpuenc.c
@@ -79,7 +79,20 @@ int ff_dovi_configure_ext(DOVIContext *s, AVCodecParameters *codecpar,
switch (codecpar->codec_id) {
case AV_CODEC_ID_AV1: dv_profile = 10; break;
case AV_CODEC_ID_H264: dv_profile = 9; break;
- case AV_CODEC_ID_HEVC: dv_profile = hdr ? ff_dovi_guess_profile_hevc(hdr) : 8; break;
+ case AV_CODEC_ID_HEVC:
+ if (hdr) {
+ dv_profile = ff_dovi_guess_profile_hevc(hdr);
+ break;
+ }
+
+ /* This is likely to be proprietary IPTPQc2 */
+ if (codecpar->color_space == AVCOL_SPC_IPT_C2 ||
+ (codecpar->color_space == AVCOL_SPC_UNSPECIFIED &&
+ codecpar->color_trc == AVCOL_TRC_UNSPECIFIED))
+ dv_profile = 5;
+ else
+ dv_profile = 8;
+ break;
default:
/* No other encoder should be calling this! */
av_assert0(0);
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 20/22] avcodec/dovi_rpudec: error out on strange RPU formats
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (17 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 19/22] avcodec/dovi_rpuenc: slightly improve profile autodetection Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error Niklas Haas
` (2 subsequent siblings)
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
Better safe than sorry.
---
libavcodec/dovi_rpudec.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/libavcodec/dovi_rpudec.c b/libavcodec/dovi_rpudec.c
index 9f295d4fe4..878950d66d 100644
--- a/libavcodec/dovi_rpudec.c
+++ b/libavcodec/dovi_rpudec.c
@@ -482,6 +482,10 @@ int ff_dovi_rpu_parse(DOVIContext *s, const uint8_t *rpu, size_t rpu_size,
dm_compression = get_bits(gb, 3);
hdr->el_spatial_resampling_filter_flag = get_bits1(gb);
hdr->disable_residual_flag = get_bits1(gb);
+ } else {
+ avpriv_request_sample(s->logctx, "Unsupported RPU format 0x%x\n", hdr->rpu_format);
+ ff_dovi_ctx_unref(s);
+ return AVERROR_PATCHWELCOME;
}
} else {
/* lack of documentation/samples */
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (18 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 20/22] avcodec/dovi_rpudec: error out on strange RPU formats Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-08-03 18:08 ` Andreas Rheinhardt
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 22/22] avcodec/libx265: " Niklas Haas
2024-07-31 12:14 ` [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
21 siblings, 1 reply; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
While this is technically a spec violation, the result is still
decodable (and will look perfectly fine to clients ignoring Dolby Vision
metadata). It will also only happen in garbage in, garbage out scenarios.
---
libavcodec/libsvtav1.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
index e7b12fb488..4c91750fbe 100644
--- a/libavcodec/libsvtav1.c
+++ b/libavcodec/libsvtav1.c
@@ -551,10 +551,10 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
} else if (svt_enc->dovi.cfg.dv_profile) {
av_log(avctx, AV_LOG_ERROR, "Dolby Vision enabled, but received frame "
"without AV_FRAME_DATA_DOVI_METADATA\n");
- return AVERROR_INVALIDDATA;
+ if (avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)
+ return AVERROR_INVALIDDATA;
}
-
svt_ret = svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr);
if (svt_ret != EB_ErrorNone)
return svt_print_error(avctx, svt_ret, "Error sending a frame to encoder");
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* [FFmpeg-devel] [PATCH 22/22] avcodec/libx265: raise strictness of missing DV error
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (19 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error Niklas Haas
@ 2024-07-28 10:25 ` Niklas Haas
2024-07-31 12:14 ` [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
21 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-07-28 10:25 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
From: Niklas Haas <git@haasn.dev>
See previous commit for justification
---
libavcodec/libx265.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/libavcodec/libx265.c b/libavcodec/libx265.c
index 718bd21b20..325c4fdd07 100644
--- a/libavcodec/libx265.c
+++ b/libavcodec/libx265.c
@@ -792,9 +792,11 @@ static int libx265_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
}
} else if (ctx->dovi.cfg.dv_profile) {
av_log(avctx, AV_LOG_ERROR, "Dolby Vision enabled, but received frame "
- "without AV_FRAME_DATA_DOVI_METADATA");
- free_picture(ctx, &x265pic);
- return AVERROR_INVALIDDATA;
+ "without AV_FRAME_DATA_DOVI_METADATA\n");
+ if (avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT) {
+ free_picture(ctx, &x265pic);
+ return AVERROR_INVALIDDATA;
+ }
}
#endif
}
--
2.45.2
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
` (20 preceding siblings ...)
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 22/22] avcodec/libx265: " Niklas Haas
@ 2024-07-31 12:14 ` Niklas Haas
[not found] ` <D964CDCD-7D3D-4373-9F37-0404669324FE@cosmin.at>
21 siblings, 1 reply; 26+ messages in thread
From: Niklas Haas @ 2024-07-31 12:14 UTC (permalink / raw)
To: ffmpeg-devel; +Cc: Niklas Haas
On Sun, 28 Jul 2024 12:25:06 +0200 Niklas Haas <ffmpeg@haasn.xyz> wrote:
> From: Niklas Haas <git@haasn.dev>
>
> ---
> libavutil/dovi_meta.h | 28 +++++++++++++++-------------
> 1 file changed, 15 insertions(+), 13 deletions(-)
>
> diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h
> index c942d0e133..5e8a1e43d7 100644
> --- a/libavutil/dovi_meta.h
> +++ b/libavutil/dovi_meta.h
> @@ -301,26 +301,28 @@ typedef struct AVDOVIDmLevel255 {
> } AVDOVIDmLevel255;
>
> /**
> - * Dolby Vision metadata extension block.
> + * Dolby Vision metadata extension block. Dynamic extension blocks may change
> + * from frame to frame, while static blocks are constant throughout the entire
> + * sequence.
> *
> * @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;
> + AVDOVIDmLevel1 l1; /* dynamic */
> + AVDOVIDmLevel2 l2; /* dynamic, may appear multiple times */
> + AVDOVIDmLevel3 l3; /* dynamic */
> + AVDOVIDmLevel4 l4; /* dynamic */
> + AVDOVIDmLevel5 l5; /* dynamic */
> + AVDOVIDmLevel6 l6; /* static */
> /* 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;
> + AVDOVIDmLevel8 l8; /* dynamic, may appear multiple times */
> + AVDOVIDmLevel9 l9; /* dynamic */
> + AVDOVIDmLevel10 l10; /* static, may appear multiple times */
> + AVDOVIDmLevel11 l11; /* dynamic */
> + AVDOVIDmLevel254 l254; /* static */
> + AVDOVIDmLevel255 l255; /* static */
> };
> } AVDOVIDmData;
>
> --
> 2.45.2
>
Ping for review. Code passes DV bitstream validator, so will consider merging
soon if there are no objections.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks
[not found] ` <D964CDCD-7D3D-4373-9F37-0404669324FE@cosmin.at>
@ 2024-08-03 3:53 ` Cosmin Stejerean via ffmpeg-devel
0 siblings, 0 replies; 26+ messages in thread
From: Cosmin Stejerean via ffmpeg-devel @ 2024-08-03 3:53 UTC (permalink / raw)
To: FFmpeg development discussions and patches; +Cc: Cosmin Stejerean, Niklas Haas
> On Jul 31, 2024, at 5:14 AM, Niklas Haas <ffmpeg@haasn.xyz> wrote:
>
> On Sun, 28 Jul 2024 12:25:06 +0200 Niklas Haas <ffmpeg@haasn.xyz> wrote:
>> From: Niklas Haas <git@haasn.dev>
>>
>> ---
>> libavutil/dovi_meta.h | 28 +++++++++++++++-------------
>> 1 file changed, 15 insertions(+), 13 deletions(-)
>>
>> diff --git a/libavutil/dovi_meta.h b/libavutil/dovi_meta.h
>> index c942d0e133..5e8a1e43d7 100644
>> --- a/libavutil/dovi_meta.h
>> +++ b/libavutil/dovi_meta.h
>> @@ -301,26 +301,28 @@ typedef struct AVDOVIDmLevel255 {
>> } AVDOVIDmLevel255;
>>
>> /**
>> - * Dolby Vision metadata extension block.
>> + * Dolby Vision metadata extension block. Dynamic extension blocks may change
>> + * from frame to frame, while static blocks are constant throughout the entire
>> + * sequence.
>> *
>> * @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;
>> + AVDOVIDmLevel1 l1; /* dynamic */
>> + AVDOVIDmLevel2 l2; /* dynamic, may appear multiple times */
>> + AVDOVIDmLevel3 l3; /* dynamic */
>> + AVDOVIDmLevel4 l4; /* dynamic */
>> + AVDOVIDmLevel5 l5; /* dynamic */
>> + AVDOVIDmLevel6 l6; /* static */
>> /* 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;
>> + AVDOVIDmLevel8 l8; /* dynamic, may appear multiple times */
>> + AVDOVIDmLevel9 l9; /* dynamic */
>> + AVDOVIDmLevel10 l10; /* static, may appear multiple times */
>> + AVDOVIDmLevel11 l11; /* dynamic */
>> + AVDOVIDmLevel254 l254; /* static */
>> + AVDOVIDmLevel255 l255; /* static */
>> };
>> } AVDOVIDmData;
>>
>> --
>> 2.45.2
>>
>
> Ping for review. Code passes DV bitstream validator, so will consider merging
> soon if there are no objections.
>
lgtm
- Cosmin
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error Niklas Haas
@ 2024-08-03 18:08 ` Andreas Rheinhardt
2024-08-04 16:31 ` Niklas Haas
0 siblings, 1 reply; 26+ messages in thread
From: Andreas Rheinhardt @ 2024-08-03 18:08 UTC (permalink / raw)
To: ffmpeg-devel
Niklas Haas:
> From: Niklas Haas <git@haasn.dev>
>
> While this is technically a spec violation, the result is still
> decodable (and will look perfectly fine to clients ignoring Dolby Vision
> metadata). It will also only happen in garbage in, garbage out scenarios.
> ---
> libavcodec/libsvtav1.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
> index e7b12fb488..4c91750fbe 100644
> --- a/libavcodec/libsvtav1.c
> +++ b/libavcodec/libsvtav1.c
> @@ -551,10 +551,10 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
> } else if (svt_enc->dovi.cfg.dv_profile) {
> av_log(avctx, AV_LOG_ERROR, "Dolby Vision enabled, but received frame "
> "without AV_FRAME_DATA_DOVI_METADATA\n");
> - return AVERROR_INVALIDDATA;
> + if (avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)
> + return AVERROR_INVALIDDATA;
> }
>
> -
> svt_ret = svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr);
> if (svt_ret != EB_ErrorNone)
> return svt_print_error(avctx, svt_ret, "Error sending a frame to encoder");
Encoders are supposed to be picky and only produce spec-compliant output.
- Andreas
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
* Re: [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error
2024-08-03 18:08 ` Andreas Rheinhardt
@ 2024-08-04 16:31 ` Niklas Haas
0 siblings, 0 replies; 26+ messages in thread
From: Niklas Haas @ 2024-08-04 16:31 UTC (permalink / raw)
To: ffmpeg-devel
On Sat, 03 Aug 2024 20:08:26 +0200 Andreas Rheinhardt <andreas.rheinhardt@outlook.com> wrote:
> Niklas Haas:
> > From: Niklas Haas <git@haasn.dev>
> >
> > While this is technically a spec violation, the result is still
> > decodable (and will look perfectly fine to clients ignoring Dolby Vision
> > metadata). It will also only happen in garbage in, garbage out scenarios.
> > ---
> > libavcodec/libsvtav1.c | 4 ++--
> > 1 file changed, 2 insertions(+), 2 deletions(-)
> >
> > diff --git a/libavcodec/libsvtav1.c b/libavcodec/libsvtav1.c
> > index e7b12fb488..4c91750fbe 100644
> > --- a/libavcodec/libsvtav1.c
> > +++ b/libavcodec/libsvtav1.c
> > @@ -551,10 +551,10 @@ static int eb_send_frame(AVCodecContext *avctx, const AVFrame *frame)
> > } else if (svt_enc->dovi.cfg.dv_profile) {
> > av_log(avctx, AV_LOG_ERROR, "Dolby Vision enabled, but received frame "
> > "without AV_FRAME_DATA_DOVI_METADATA\n");
> > - return AVERROR_INVALIDDATA;
> > + if (avctx->strict_std_compliance >= FF_COMPLIANCE_STRICT)
> > + return AVERROR_INVALIDDATA;
> > }
> >
> > -
> > svt_ret = svt_av1_enc_send_picture(svt_enc->svt_handle, headerPtr);
> > if (svt_ret != EB_ErrorNone)
> > return svt_print_error(avctx, svt_ret, "Error sending a frame to encoder");
>
> Encoders are supposed to be picky and only produce spec-compliant output.
Okay, I could either drop this commit or raise it to UNOFFICIAL.
But it probably makes more sense to drop it, such files should be phased out
if they exist anyway.
>
> - Andreas
>
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
>
> To unsubscribe, visit link above, or email
> ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
To unsubscribe, visit link above, or email
ffmpeg-devel-request@ffmpeg.org with subject "unsubscribe".
^ permalink raw reply [flat|nested] 26+ messages in thread
end of thread, other threads:[~2024-08-04 16:31 UTC | newest]
Thread overview: 26+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-07-28 10:25 [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 02/22] avcodec/dovi_rpudec: implement validation for compression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 03/22] avcodec/dovi_rpuenc: also copy ext blocks to dovi ctx Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 04/22] avcodec/dovi_rpuenc: eliminate unnecessary loop Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 05/22] avcodec/dovi_rpuenc: respect dv_md_compression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 06/22] avcodec/dovi_rpuenc: add `flags` to ff_dovi_rpu_generate() Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 07/22] avcodec/dovi_rpuenc: make encapsulation optional Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 08/22] avcodec/dovi_rpuenc: add a flag to enable compression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 09/22] avcodec/dovi_rpu: add ff_dovi_get_metadata() Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 10/22] avcodec/dovi_rpuenc: add ff_dovi_configure_ext() Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 11/22] avcodec/dovi_rpuenc: add configuration for compression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 12/22] avcodec/bsf/dovi_rpu: add new bitstream filter Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 13/22] avcodec/dovi_rpu: move ext blocks into dedicated struct Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 14/22] avcodec/dovi_rpu: separate static ext blocks Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 15/22] avcodec/dovi_rpudec: don't unnecessarily allocate DOVIExt Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 16/22] avcodec/dovi_rpudec: implement limited DM decompression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 17/22] avcodec/dovi_rpudec: sanitize DM data before decoding Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 18/22] avcodec/dovi_rpuenc: implement DM metadata compression Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 19/22] avcodec/dovi_rpuenc: slightly improve profile autodetection Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 20/22] avcodec/dovi_rpudec: error out on strange RPU formats Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 21/22] avcodec/libsvtav1: raise strictness of missing DV error Niklas Haas
2024-08-03 18:08 ` Andreas Rheinhardt
2024-08-04 16:31 ` Niklas Haas
2024-07-28 10:25 ` [FFmpeg-devel] [PATCH 22/22] avcodec/libx265: " Niklas Haas
2024-07-31 12:14 ` [FFmpeg-devel] [PATCH 01/22] avutil/dovi_meta: document static vs dynamic ext blocks Niklas Haas
[not found] ` <D964CDCD-7D3D-4373-9F37-0404669324FE@cosmin.at>
2024-08-03 3:53 ` Cosmin Stejerean via ffmpeg-devel
Git Inbox Mirror of the ffmpeg-devel mailing list - see https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
This inbox may be cloned and mirrored by anyone:
git clone --mirror https://master.gitmailbox.com/ffmpegdev/0 ffmpegdev/git/0.git
# If you have public-inbox 1.1+ installed, you may
# initialize and index your mirror using the following commands:
public-inbox-init -V2 ffmpegdev ffmpegdev/ https://master.gitmailbox.com/ffmpegdev \
ffmpegdev@gitmailbox.com
public-inbox-index ffmpegdev
Example config snippet for mirrors.
AGPL code for this site: git clone https://public-inbox.org/public-inbox.git