[FFmpeg-devel] [PATCH v5 3/6] ffprobe: Support AV_FRAME_DATA_DOVI_METADATA
Niklas Haas
ffmpeg at haasn.xyz
Sun Dec 12 13:55:43 EET 2021
From: Jan Ekström <jeebjp at gmail.com>
Co-authored-by: Niklas Haas <git at haasn.dev>
---
fftools/ffprobe.c | 173 +++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 170 insertions(+), 3 deletions(-)
diff --git a/fftools/ffprobe.c b/fftools/ffprobe.c
index 0711e02922..75263cd3a9 100644
--- a/fftools/ffprobe.c
+++ b/fftools/ffprobe.c
@@ -175,6 +175,10 @@ typedef enum {
SECTION_ID_FRAME_SIDE_DATA,
SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST,
SECTION_ID_FRAME_SIDE_DATA_TIMECODE,
+ SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST,
+ SECTION_ID_FRAME_SIDE_DATA_COMPONENT,
+ SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST,
+ SECTION_ID_FRAME_SIDE_DATA_PIECE,
SECTION_ID_FRAME_LOG,
SECTION_ID_FRAME_LOGS,
SECTION_ID_LIBRARY_VERSION,
@@ -219,9 +223,13 @@ static struct section sections[] = {
[SECTION_ID_FRAME] = { SECTION_ID_FRAME, "frame", 0, { SECTION_ID_FRAME_TAGS, SECTION_ID_FRAME_SIDE_DATA_LIST, SECTION_ID_FRAME_LOGS, -1 } },
[SECTION_ID_FRAME_TAGS] = { SECTION_ID_FRAME_TAGS, "tags", SECTION_FLAG_HAS_VARIABLE_FIELDS, { -1 }, .element_name = "tag", .unique_name = "frame_tags" },
[SECTION_ID_FRAME_SIDE_DATA_LIST] ={ SECTION_ID_FRAME_SIDE_DATA_LIST, "side_data_list", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA, -1 }, .element_name = "side_data", .unique_name = "frame_side_data_list" },
- [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, -1 } },
- [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
- [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA] = { SECTION_ID_FRAME_SIDE_DATA, "side_data", 0, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE_LIST, "timecodes", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_TIMECODE] = { SECTION_ID_FRAME_SIDE_DATA_TIMECODE, "timecode", 0, { -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST, "components", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_COMPONENT] = { SECTION_ID_FRAME_SIDE_DATA_COMPONENT, "component", 0, { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST] = { SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST, "pieces", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_SIDE_DATA_PIECE, -1 } },
+ [SECTION_ID_FRAME_SIDE_DATA_PIECE] = { SECTION_ID_FRAME_SIDE_DATA_PIECE, "section", 0, { -1 } },
[SECTION_ID_FRAME_LOGS] = { SECTION_ID_FRAME_LOGS, "logs", SECTION_FLAG_IS_ARRAY, { SECTION_ID_FRAME_LOG, -1 } },
[SECTION_ID_FRAME_LOG] = { SECTION_ID_FRAME_LOG, "log", 0, { -1 }, },
[SECTION_ID_LIBRARY_VERSIONS] = { SECTION_ID_LIBRARY_VERSIONS, "library_versions", SECTION_FLAG_IS_ARRAY, { SECTION_ID_LIBRARY_VERSION, -1 } },
@@ -1807,6 +1815,16 @@ static void writer_register_all(void)
writer_print_string(w, k, pbuf.str, 0); \
} while (0)
+#define print_list_fmt(k, f, n, ...) do { \
+ av_bprint_clear(&pbuf); \
+ for (int idx = 0; idx < n; idx++) { \
+ if (idx > 0) \
+ av_bprint_chars(&pbuf, ' ', 1); \
+ av_bprintf(&pbuf, f, __VA_ARGS__); \
+ } \
+ writer_print_string(w, k, pbuf.str, 0); \
+} while (0)
+
#define print_int(k, v) writer_print_integer(w, k, v)
#define print_q(k, v, s) writer_print_rational(w, k, v, s)
#define print_str(k, v) writer_print_string(w, k, v, 0)
@@ -1852,6 +1870,153 @@ static inline int show_tags(WriterContext *w, AVDictionary *tags, int section_id
return ret;
}
+static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *dovi)
+{
+ if (!dovi)
+ return;
+
+ {
+ const AVDOVIRpuDataHeader *hdr = &dovi->header;
+ const AVDOVIDataMapping *mapping = &dovi->mapping;
+ const AVDOVIColorMetadata *color = &dovi->color;
+ AVBPrint pbuf;
+
+ av_bprint_init(&pbuf, 1, AV_BPRINT_SIZE_UNLIMITED);
+
+ // header
+ print_int("rpu_type", hdr->rpu_type);
+ print_int("rpu_format", hdr->rpu_format);
+ print_int("vdr_rpu_profile", hdr->vdr_rpu_profile);
+ print_int("vdr_rpu_level", hdr->vdr_rpu_level);
+ print_int("chroma_resampling_explicit_filter_flag",
+ hdr->chroma_resampling_explicit_filter_flag);
+ print_int("coef_data_type", hdr->coef_data_type);
+ print_int("coef_log2_denom", hdr->coef_log2_denom);
+ print_int("vdr_rpu_normalized_idc", hdr->vdr_rpu_normalized_idc);
+ print_int("bl_video_full_range_flag", hdr->bl_video_full_range_flag);
+ print_int("bl_bit_depth", hdr->bl_bit_depth);
+ print_int("el_bit_depth", hdr->el_bit_depth);
+ print_int("vdr_bit_depth", hdr->vdr_bit_depth);
+ print_int("spatial_resampling_filter_flag",
+ hdr->spatial_resampling_filter_flag);
+ print_int("el_spatial_resampling_filter_flag",
+ hdr->el_spatial_resampling_filter_flag);
+ print_int("disable_residual_flag", hdr->disable_residual_flag);
+
+ // data mapping values
+ print_int("vdr_rpu_id", mapping->vdr_rpu_id);
+ print_int("mapping_color_space", mapping->mapping_color_space);
+ print_int("mapping_chroma_format_idc",
+ mapping->mapping_chroma_format_idc);
+
+ print_int("nlq_method_idc", mapping->nlq_method_idc);
+ switch (mapping->nlq_method_idc) {
+ case AV_DOVI_NLQ_NONE:
+ print_str("nlq_method_idc_name", "none");
+ break;
+ case AV_DOVI_NLQ_LINEAR_DZ:
+ print_str("nlq_method_idc_name", "linear_dz");
+ break;
+ default:
+ print_str("nlq_method_idc_name", "unknown");
+ break;
+ }
+
+ print_int("num_x_partitions", mapping->num_x_partitions);
+ print_int("num_y_partitions", mapping->num_y_partitions);
+
+ writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST);
+
+ for (int c = 0; c < 3; c++) {
+ const AVDOVIReshapingCurve *curve = &mapping->curves[c];
+ writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_COMPONENT);
+
+ print_list_fmt("pivots", "%"PRIu16, curve->num_pivots, curve->pivots[idx]);
+
+ writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST);
+ for (int i = 0; i < curve->num_pivots - 1; i++) {
+
+ writer_print_section_header(w, SECTION_ID_FRAME_SIDE_DATA_PIECE);
+ print_int("mapping_idc", curve->mapping_idc[i]);
+ switch (curve->mapping_idc[i]) {
+ case AV_DOVI_MAPPING_POLYNOMIAL:
+ print_str("mapping_idc_name", "polynomial");
+ print_int("poly_order", curve->poly_order[i]);
+ print_list_fmt("poly_coef", "%"PRIi64,
+ curve->poly_order[i] + 1,
+ curve->poly_coef[i][idx]);
+ break;
+ case AV_DOVI_MAPPING_MMR:
+ print_str("mapping_idc_name", "mmr");
+ print_int("mmr_order", curve->mmr_order[i]);
+ print_int("mmr_constant", curve->mmr_constant[i]);
+ print_list_fmt("mmr_coef", "%"PRIi64,
+ curve->mmr_order[i] * 7,
+ curve->mmr_coef[i][0][idx]);
+ break;
+ default:
+ print_str("mapping_idc_name", "unknown");
+ break;
+ }
+
+ // SECTION_ID_FRAME_SIDE_DATA_PIECE
+ writer_print_section_footer(w);
+ }
+
+ // SECTION_ID_FRAME_SIDE_DATA_PIECE_LIST
+ writer_print_section_footer(w);
+
+ if (mapping->nlq_method_idc != AV_DOVI_NLQ_NONE) {
+ const AVDOVINLQParams *nlq = &mapping->nlq[c];
+ print_int("nlq_offset", nlq->nlq_offset);
+ print_int("vdr_in_max", nlq->vdr_in_max);
+
+ switch (mapping->nlq_method_idc) {
+ case AV_DOVI_NLQ_LINEAR_DZ:
+ print_int("linear_deadzone_slope", nlq->linear_deadzone_slope);
+ print_int("linear_deadzone_threshold", nlq->linear_deadzone_threshold);
+ break;
+ }
+ }
+
+ // SECTION_ID_FRAME_SIDE_DATA_COMPONENT
+ writer_print_section_footer(w);
+ }
+
+ // SECTION_ID_FRAME_SIDE_DATA_COMPONENT_LIST
+ writer_print_section_footer(w);
+
+ // color metadata
+ print_int("dm_metadata_id", color->dm_metadata_id);
+ print_int("scene_refresh_flag", color->scene_refresh_flag);
+ print_list_fmt("ycc_to_rgb_matrix", "%d/%d",
+ FF_ARRAY_ELEMS(color->ycc_to_rgb_matrix),
+ color->ycc_to_rgb_matrix[idx].num,
+ color->ycc_to_rgb_matrix[idx].den);
+ print_list_fmt("ycc_to_rgb_offset", "%d/%d",
+ FF_ARRAY_ELEMS(color->ycc_to_rgb_offset),
+ color->ycc_to_rgb_offset[idx].num,
+ color->ycc_to_rgb_offset[idx].den);
+ print_list_fmt("rgb_to_lms_matrix", "%d/%d",
+ FF_ARRAY_ELEMS(color->rgb_to_lms_matrix),
+ color->rgb_to_lms_matrix[idx].num,
+ color->rgb_to_lms_matrix[idx].den);
+ print_int("signal_eotf", color->signal_eotf);
+ print_int("signal_eotf_param0", color->signal_eotf_param0);
+ print_int("signal_eotf_param1", color->signal_eotf_param1);
+ print_int("signal_eotf_param2", color->signal_eotf_param2);
+ print_int("signal_bit_depth", color->signal_bit_depth);
+ print_int("signal_color_space", color->signal_color_space);
+ print_int("signal_chroma_format", color->signal_chroma_format);
+ print_int("signal_full_range_flag", color->signal_full_range_flag);
+ print_int("source_min_pq", color->source_min_pq);
+ print_int("source_max_pq", color->source_max_pq);
+ print_int("source_diagonal", color->source_diagonal);
+
+ av_bprint_finalize(&pbuf, NULL);
+ }
+}
+
static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHDRPlus *metadata)
{
if (!metadata)
@@ -2368,6 +2533,8 @@ static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
if (tag)
print_str(tag->key, tag->value);
print_int("size", sd->size);
+ } else if (sd->type == AV_FRAME_DATA_DOVI_METADATA) {
+ print_dovi_metadata(w, (const AVDOVIMetadata *)sd->data);
}
writer_print_section_footer(w);
}
--
2.34.1
More information about the ffmpeg-devel
mailing list