* [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
@ 2023-02-27 17:34 Raphaël Zumer
2023-03-02 18:33 ` quietvoid
0 siblings, 1 reply; 21+ messages in thread
From: Raphaël Zumer @ 2023-02-27 17:34 UTC (permalink / raw)
To: ffmpeg-devel
Resent due to my mail client incorrectly re-wrapping lines in the version I sent earlier.
See the previous patch for context.
Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
---
libavutil/hdr_dynamic_metadata.c | 147 +++++++++++++++++++++++++++++++
libavutil/hdr_dynamic_metadata.h | 10 +++
libavutil/version.h | 2 +-
3 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
index 98f399b032..72d310e633 100644
--- a/libavutil/hdr_dynamic_metadata.c
+++ b/libavutil/hdr_dynamic_metadata.c
@@ -225,3 +225,150 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
return 0;
}
+
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
+{
+ AVBufferRef *buf;
+ size_t size_bits, size_bytes;
+ PutBitContext pbc, *pb = &pbc;
+
+ if (!s)
+ return NULL;
+
+ // Buffer size per CTA-861-H p.253-254:
+ size_bits =
+ // 56 bits for the header
+ 58 +
+ // 2 bits for num_windows
+ 2 +
+ // 937 bits for window geometry for each window above 1
+ FFMAX((s->num_windows - 1), 0) * 937 +
+ // 27 bits for targeted_system_display_maximum_luminance
+ 27 +
+ // 1-3855 bits for targeted system display peak luminance information
+ 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_targeted_system_display_actual_peak_luminance *
+ s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
+ // 0-442 bits for intra-window pixel distribution information
+ s->num_windows * 82;
+ for (int w = 0; w < s->num_windows; w++) {
+ size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
+ }
+ // 1-3855 bits for mastering display peak luminance information
+ size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_mastering_display_actual_peak_luminance *
+ s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
+ // 0-537 bits for per-window tonemapping information
+ s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].tone_mapping_flag) {
+ size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
+ }
+ }
+ // 0-21 bits for per-window color saturation mapping information
+ size_bits += s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].color_saturation_mapping_flag) {
+ size_bits += 6;
+ }
+ }
+
+ size_bytes = (size_bits + 7) / 8;
+
+ buf = av_buffer_alloc(size_bytes);
+ if (!buf) {
+ return NULL;
+ }
+
+ init_put_bits(pb, buf->data, size_bytes);
+
+ // itu_t_t35_country_code shall be 0xB5 (USA)
+ put_bits(pb, 8, 0xB5);
+ // itu_t_t35_terminal_provider_code shall be 0x003C
+ put_bits(pb, 16, 0x003C);
+ // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
+ put_bits(pb, 16, 0x0001);
+ // application_identifier shall be set to 4
+ put_bits(pb, 8, 4);
+ // application_mode is set to Application Version 1
+ put_bits(pb, 8, 1);
+
+ // Payload as per CTA-861-H p.253-254
+ put_bits(pb, 2, s->num_windows);
+
+ for (int w = 1; w < s->num_windows; w++) {
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_x);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_y);
+ put_bits(pb, 8, s->params[w].rotation_angle);
+ put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
+ put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
+ put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
+ put_bits(pb, 1, s->params[w].overlap_process_option);
+ }
+
+ put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
+ s->targeted_system_display_maximum_luminance.den);
+ put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
+ if (s->targeted_system_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
+ put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
+ for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
+ for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++) {
+ put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->targeted_system_display_actual_peak_luminance[i][j].den);
+ }
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ for (int i = 0; i < 3; i++) {
+ put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
+ }
+ put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
+ put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
+ for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
+ put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
+ put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
+ s->params[w].distribution_maxrgb[i].percentile.den);
+ }
+ put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
+ s->params[w].fraction_bright_pixels.den);
+ }
+
+ put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
+ if (s->mastering_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
+ put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
+ for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
+ for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++) {
+ put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->mastering_display_actual_peak_luminance[i][j].den);
+ }
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ put_bits(pb, 1, s->params[w].tone_mapping_flag);
+ if (s->params[w].tone_mapping_flag) {
+ put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
+ put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
+ put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
+ for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++) {
+ put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
+ s->params[w].bezier_curve_anchors[i].den);
+ }
+ put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
+ if (s->params[w].color_saturation_mapping_flag) {
+ put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
+ s->params[w].color_saturation_weight.den);
+ }
+ }
+ }
+
+ flush_put_bits(pb);
+ return buf;
+}
diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
index 1f953ef1f5..f75d3e0739 100644
--- a/libavutil/hdr_dynamic_metadata.h
+++ b/libavutil/hdr_dynamic_metadata.h
@@ -21,6 +21,7 @@
#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
#define AVUTIL_HDR_DYNAMIC_METADATA_H
+#include "buffer.h"
#include "frame.h"
#include "rational.h"
@@ -351,4 +352,13 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
int size);
+/**
+ * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer.
+ * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
+ *
+ * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
+ * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
+ */
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
+
#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
diff --git a/libavutil/version.h b/libavutil/version.h
index 900b798971..7635672985 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 3
+#define LIBAVUTIL_VERSION_MINOR 4
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
--
2.39.1
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-02-27 17:34 [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function Raphaël Zumer
@ 2023-03-02 18:33 ` quietvoid
2023-03-02 18:57 ` Raphaël Zumer
2023-03-02 18:57 ` James Almer
0 siblings, 2 replies; 21+ messages in thread
From: quietvoid @ 2023-03-02 18:33 UTC (permalink / raw)
To: ffmpeg-devel
On 27/02/2023 12.34, Raphaël Zumer wrote:
> Resent due to my mail client incorrectly re-wrapping lines in the version I sent earlier.
> See the previous patch for context.
>
> Signed-off-by: Raphaël Zumer<rzumer@tebako.net>
> ---
> libavutil/hdr_dynamic_metadata.c | 147 +++++++++++++++++++++++++++++++
> libavutil/hdr_dynamic_metadata.h | 10 +++
> libavutil/version.h | 2 +-
> 3 files changed, 158 insertions(+), 1 deletion(-)
>
> diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
> index 98f399b032..72d310e633 100644
> --- a/libavutil/hdr_dynamic_metadata.c
> +++ b/libavutil/hdr_dynamic_metadata.c
> @@ -225,3 +225,150 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
>
> return 0;
> }
> +
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
> +{
> + AVBufferRef *buf;
> + size_t size_bits, size_bytes;
> + PutBitContext pbc, *pb = &pbc;
> +
> + if (!s)
> + return NULL;
> +
> + // Buffer size per CTA-861-H p.253-254:
> + size_bits =
> + // 56 bits for the header
> + 58 +
> + // 2 bits for num_windows
> + 2 +
> + // 937 bits for window geometry for each window above 1
> + FFMAX((s->num_windows - 1), 0) * 937 +
> + // 27 bits for targeted_system_display_maximum_luminance
> + 27 +
> + // 1-3855 bits for targeted system display peak luminance information
> + 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_targeted_system_display_actual_peak_luminance *
> + s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
> + // 0-442 bits for intra-window pixel distribution information
> + s->num_windows * 82;
> + for (int w = 0; w < s->num_windows; w++) {
> + size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
> + }
> + // 1-3855 bits for mastering display peak luminance information
> + size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_mastering_display_actual_peak_luminance *
> + s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
> + // 0-537 bits for per-window tonemapping information
> + s->num_windows * 1;
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].tone_mapping_flag) {
> + size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
> + }
> + }
> + // 0-21 bits for per-window color saturation mapping information
> + size_bits += s->num_windows * 1;
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].color_saturation_mapping_flag) {
> + size_bits += 6;
> + }
> + }
> +
> + size_bytes = (size_bits + 7) / 8;
> +
> + buf = av_buffer_alloc(size_bytes);
> + if (!buf) {
> + return NULL;
> + }
> +
> + init_put_bits(pb, buf->data, size_bytes);
> +
> + // itu_t_t35_country_code shall be 0xB5 (USA)
> + put_bits(pb, 8, 0xB5);
This patch series mentions that it would be used for AV1, however the AV1
specification is clear that the payload does not contain the country code.
https://aomediacodec.github.io/av1-hdr10plus/#hdr10plus-metadata, Figure 1.
So far all the AV1 HDR10+ conformance samples also respect this.
There would probably be a need to specify which behaviour is wanted.
The SEI for HEVC does keep the country code in the payload, but not AV1.
> + // itu_t_t35_terminal_provider_code shall be 0x003C
> + put_bits(pb, 16, 0x003C);
> + // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
> + put_bits(pb, 16, 0x0001);
> + // application_identifier shall be set to 4
> + put_bits(pb, 8, 4);
> + // application_mode is set to Application Version 1
> + put_bits(pb, 8, 1);
> +
> + // Payload as per CTA-861-H p.253-254
> + put_bits(pb, 2, s->num_windows);
> +
> + for (int w = 1; w < s->num_windows; w++) {
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_x);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_y);
> + put_bits(pb, 8, s->params[w].rotation_angle);
> + put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
> + put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
> + put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
> + put_bits(pb, 1, s->params[w].overlap_process_option);
> + }
> +
> + put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
> + s->targeted_system_display_maximum_luminance.den);
> + put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
> + if (s->targeted_system_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++) {
> + put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->targeted_system_display_actual_peak_luminance[i][j].den);
> + }
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + for (int i = 0; i < 3; i++) {
> + put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
> + }
> + put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
> + put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
> + for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
> + put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
> + put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
> + s->params[w].distribution_maxrgb[i].percentile.den);
> + }
> + put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
> + s->params[w].fraction_bright_pixels.den);
> + }
> +
> + put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
> + if (s->mastering_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++) {
> + put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->mastering_display_actual_peak_luminance[i][j].den);
> + }
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + put_bits(pb, 1, s->params[w].tone_mapping_flag);
> + if (s->params[w].tone_mapping_flag) {
> + put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
> + put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
> + put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
> + for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++) {
> + put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
> + s->params[w].bezier_curve_anchors[i].den);
> + }
> + put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
> + if (s->params[w].color_saturation_mapping_flag) {
> + put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
> + s->params[w].color_saturation_weight.den);
> + }
> + }
> + }
> +
> + flush_put_bits(pb);
> + return buf;
> +}
> diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
> index 1f953ef1f5..f75d3e0739 100644
> --- a/libavutil/hdr_dynamic_metadata.h
> +++ b/libavutil/hdr_dynamic_metadata.h
> @@ -21,6 +21,7 @@
> #ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
> #define AVUTIL_HDR_DYNAMIC_METADATA_H
>
> +#include "buffer.h"
> #include "frame.h"
> #include "rational.h"
>
> @@ -351,4 +352,13 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
> int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
> int size);
>
> +/**
> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer.
> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
> + *
> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
> + */
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
> +
> #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 900b798971..7635672985 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
> */
>
> #define LIBAVUTIL_VERSION_MAJOR 58
> -#define LIBAVUTIL_VERSION_MINOR 3
> +#define LIBAVUTIL_VERSION_MINOR 4
> #define LIBAVUTIL_VERSION_MICRO 100
>
> #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 18:33 ` quietvoid
@ 2023-03-02 18:57 ` Raphaël Zumer
2023-03-02 18:57 ` James Almer
1 sibling, 0 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-02 18:57 UTC (permalink / raw)
To: ffmpeg-devel
On 3/2/23 13:33, quietvoid wrote:
> This patch series mentions that it would be used for AV1, however the AV1
> specification is clear that the payload does not contain the country code.
> https://aomediacodec.github.io/av1-hdr10plus/#hdr10plus-metadata, Figure 1.
>
> So far all the AV1 HDR10+ conformance samples also respect this.
> There would probably be a need to specify which behaviour is wanted.
> The SEI for HEVC does keep the country code in the payload, but not AV1.
As you pointed out, HEVC does include the country code in the payload, so either approach can be seen as reasonable. There are a few reasons why I don't think it makes sense to reproduce the AV1 specification:
- it does not make sense to exclude the country code from the payload while including other static headers like the terminal provider codes and the application identifier, so there is no particular advantage or logic that I can see in splitting the payload in that way.
- pragmatically, it is much less inconvenient to deal with a 1-byte offset in the payload for AV1 than it is to insert that byte into the payload for HEVC and other applications that expect the country code to be included in the header. For the same reason, I think that an option to include or exclude the country code byte would be more trouble than it's worth.
- perhaps most importantly, the payload syntax is standardized in ANSI/CTA-861-H, which does not make any distinction between the header (country code, terminal provider code, etc.) and the remainder of the payload, so the AV1 specification does not conform either to other implementations nor to the standard. Following the most authoritative document is the safest route in my opinion.
Raphaël Zumer
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 18:33 ` quietvoid
2023-03-02 18:57 ` Raphaël Zumer
@ 2023-03-02 18:57 ` James Almer
2023-03-02 19:14 ` Raphaël Zumer
1 sibling, 1 reply; 21+ messages in thread
From: James Almer @ 2023-03-02 18:57 UTC (permalink / raw)
To: ffmpeg-devel
On 3/2/2023 3:33 PM, quietvoid wrote:> On 27/02/2023 12.34, Raphaël
Zumer wrote:
>
>> Resent due to my mail client incorrectly re-wrapping lines in the
>> version I sent earlier.
>> See the previous patch for context.
>>
>> Signed-off-by: Raphaël Zumer<rzumer@tebako.net>
>> ---
>> libavutil/hdr_dynamic_metadata.c | 147 +++++++++++++++++++++++++++++++
>> libavutil/hdr_dynamic_metadata.h | 10 +++
>> libavutil/version.h | 2 +-
>> 3 files changed, 158 insertions(+), 1 deletion(-)
>>
>> diff --git a/libavutil/hdr_dynamic_metadata.c
>> b/libavutil/hdr_dynamic_metadata.c
>> index 98f399b032..72d310e633 100644
>> --- a/libavutil/hdr_dynamic_metadata.c
>> +++ b/libavutil/hdr_dynamic_metadata.c
>> @@ -225,3 +225,150 @@ int
>> av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
>> return 0;
>> }
>> +
>> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
>> +{
>> + AVBufferRef *buf;
>> + size_t size_bits, size_bytes;
>> + PutBitContext pbc, *pb = &pbc;
>> +
>> + if (!s)
>> + return NULL;
>> +
>> + // Buffer size per CTA-861-H p.253-254:
>> + size_bits =
>> + // 56 bits for the header
>> + 58 +
>> + // 2 bits for num_windows
>> + 2 +
>> + // 937 bits for window geometry for each window above 1
>> + FFMAX((s->num_windows - 1), 0) * 937 +
>> + // 27 bits for targeted_system_display_maximum_luminance
>> + 27 +
>> + // 1-3855 bits for targeted system display peak luminance
>> information
>> + 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
>> + s->num_rows_targeted_system_display_actual_peak_luminance *
>> + s->num_cols_targeted_system_display_actual_peak_luminance * 4
>> : 0) +
>> + // 0-442 bits for intra-window pixel distribution information
>> + s->num_windows * 82;
>> + for (int w = 0; w < s->num_windows; w++) {
>> + size_bits += s->params[w].num_distribution_maxrgb_percentiles
>> * 24;
>> + }
>> + // 1-3855 bits for mastering display peak luminance information
>> + size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag
>> ? 10 +
>> + s->num_rows_mastering_display_actual_peak_luminance *
>> + s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
>> + // 0-537 bits for per-window tonemapping information
>> + s->num_windows * 1;
>> + for (int w = 0; w < s->num_windows; w++) {
>> + if (s->params[w].tone_mapping_flag) {
>> + size_bits += 28 + s->params[w].num_bezier_curve_anchors *
>> 10;
>> + }
>> + }
>> + // 0-21 bits for per-window color saturation mapping information
>> + size_bits += s->num_windows * 1;
>> + for (int w = 0; w < s->num_windows; w++) {
>> + if (s->params[w].color_saturation_mapping_flag) {
>> + size_bits += 6;
>> + }
>> + }
>> +
>> + size_bytes = (size_bits + 7) / 8;
>> +
>> + buf = av_buffer_alloc(size_bytes);
>> + if (!buf) {
>> + return NULL;
>> + }
>> +
>> + init_put_bits(pb, buf->data, size_bytes);
>> +
>> + // itu_t_t35_country_code shall be 0xB5 (USA)
>> + put_bits(pb, 8, 0xB5);
>
> This patch series mentions that it would be used for AV1, however the AV1
> specification is clear that the payload does not contain the country
code.
> https://aomediacodec.github.io/av1-hdr10plus/#hdr10plus-metadata,
Figure 1.
>
> So far all the AV1 HDR10+ conformance samples also respect this.
> There would probably be a need to specify which behaviour is wanted.
> The SEI for HEVC does keep the country code in the payload, but not AV1.
Are you sure about HEVC? I just checked a sample and trace_headers
reported this:
[trace_headers] Prefix Supplemental Enhancement Information
[trace_headers] 0 forbidden_zero_bit 0 = 0
[trace_headers] 1 nal_unit_type 100111 = 39
[trace_headers] 7 nuh_layer_id 000000 = 0
[trace_headers] 13 nuh_temporal_id_plus1 001 = 1
[trace_headers] 16 last_payload_type_byte 00000100 = 4
[trace_headers] 24 last_payload_size_byte 01000000 = 64
[trace_headers] User Data Registered ITU-T T.35
[trace_headers] 32 itu_t_t35_country_code 10110101 = 181
[trace_headers] 40 itu_t_t35_payload_byte[1] 00000000 = 0
[trace_headers] 48 itu_t_t35_payload_byte[2] 00111100 = 60
[trace_headers] 56 itu_t_t35_payload_byte[3] 00000000 = 0
[trace_headers] 64 itu_t_t35_payload_byte[4] 00000001 = 1
[trace_headers] 72 itu_t_t35_payload_byte[5] 00000100 = 4
[trace_headers] 80 itu_t_t35_payload_byte[6] 00000001 = 1
Which is in line with section 8.3.1 of ITU-T Rec. H.274 as well as
section D.2.6 of ITU-T Rec. H.265.
So i think this function should not set the country code at all as part
of the payload, and start with itu_t_t35_terminal_provider_code.
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 18:57 ` James Almer
@ 2023-03-02 19:14 ` Raphaël Zumer
0 siblings, 0 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-02 19:14 UTC (permalink / raw)
To: ffmpeg-devel
On 3/2/23 13:57, James Almer wrote:
> > The SEI for HEVC does keep the country code in the payload, but not AV1.
> Are you sure about HEVC? I just checked a sample and trace_headers
> reported this:
>
> [trace_headers] Prefix Supplemental Enhancement Information
> [trace_headers] 0 forbidden_zero_bit 0 = 0
> [trace_headers] 1 nal_unit_type 100111 = 39
> [trace_headers] 7 nuh_layer_id 000000 = 0
> [trace_headers] 13 nuh_temporal_id_plus1 001 = 1
> [trace_headers] 16 last_payload_type_byte 00000100 = 4
> [trace_headers] 24 last_payload_size_byte 01000000 = 64
> [trace_headers] User Data Registered ITU-T T.35
> [trace_headers] 32 itu_t_t35_country_code 10110101 = 181
> [trace_headers] 40 itu_t_t35_payload_byte[1] 00000000 = 0
> [trace_headers] 48 itu_t_t35_payload_byte[2] 00111100 = 60
> [trace_headers] 56 itu_t_t35_payload_byte[3] 00000000 = 0
> [trace_headers] 64 itu_t_t35_payload_byte[4] 00000001 = 1
> [trace_headers] 72 itu_t_t35_payload_byte[5] 00000100 = 4
> [trace_headers] 80 itu_t_t35_payload_byte[6] 00000001 = 1
>
> Which is in line with section 8.3.1 of ITU-T Rec. H.274 as well as
> section D.2.6 of ITU-T Rec. H.265.
>
> So i think this function should not set the country code at all as part
> of the payload, and start with itu_t_t35_terminal_provider_code.
OK, I will make that change since both HEVC and AV1 implementations seem to match.
Thanks
Raphaël Zumer
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-13 22:25 ` Andreas Rheinhardt
@ 2023-03-13 22:32 ` James Almer
0 siblings, 0 replies; 21+ messages in thread
From: James Almer @ 2023-03-13 22:32 UTC (permalink / raw)
To: ffmpeg-devel
On 3/13/2023 7:25 PM, Andreas Rheinhardt wrote:
> James Almer:
>> On 3/9/2023 11:18 AM, Raphaël Zumer wrote:
>>> Hi,
>>>
>>> While I omitted adding v2/v3 here, I believe all comments on this set
>>> of patches have been addressed so far, unless anyone strongly
>>> disagrees with the rationale for moving dynamic HDR parsing and
>>> serialization to libavutil or with the function signature.
>>>
>>> Please let me know if I missed anything.
>>>
>>> Thanks,
>>> Raphaël Zumer
>>
>> I'll apply this (and patch 1/1) in a few days if nobody comments.
>> The code needs to be in lavu if we want muxers and demuxers to use this
>> functionality, so moving the existing lavc functions is fine unless we
>> add more avpriv_ functions that people tend to dislike.
>
> Can we wait with this until we have the actual patches that make use of it?
> (And is lavfi actually supposed to make use of this? Or why is it moved
> to lavu at all? lavf can also use it in lavc.)
I have patches ready to make use of one of the two functions in the
matroska demuxer. Will send them after this is pushed. And I'll attempt
to write one to make use of the serialization function in the matroska
muxer too.
And it makes sense for this to be in lavu even if only lavf uses these,
given there's a public header for it already. Installing two headers for
HDR10+ functions in two separate libraries seems overkill when they use
the same struct.
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-12 15:21 ` James Almer
@ 2023-03-13 22:25 ` Andreas Rheinhardt
2023-03-13 22:32 ` James Almer
0 siblings, 1 reply; 21+ messages in thread
From: Andreas Rheinhardt @ 2023-03-13 22:25 UTC (permalink / raw)
To: ffmpeg-devel
James Almer:
> On 3/9/2023 11:18 AM, Raphaël Zumer wrote:
>> Hi,
>>
>> While I omitted adding v2/v3 here, I believe all comments on this set
>> of patches have been addressed so far, unless anyone strongly
>> disagrees with the rationale for moving dynamic HDR parsing and
>> serialization to libavutil or with the function signature.
>>
>> Please let me know if I missed anything.
>>
>> Thanks,
>> Raphaël Zumer
>
> I'll apply this (and patch 1/1) in a few days if nobody comments.
> The code needs to be in lavu if we want muxers and demuxers to use this
> functionality, so moving the existing lavc functions is fine unless we
> add more avpriv_ functions that people tend to dislike.
Can we wait with this until we have the actual patches that make use of it?
(And is lavfi actually supposed to make use of this? Or why is it moved
to lavu at all? lavf can also use it in lavc.)
- 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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-12 21:50 ` Raphaël Zumer
2023-03-12 21:52 ` James Almer
@ 2023-03-13 13:36 ` Anton Khirnov
1 sibling, 0 replies; 21+ messages in thread
From: Anton Khirnov @ 2023-03-13 13:36 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Raphaël Zumer (2023-03-12 22:50:27)
> I expanded on this in another email in the chain, but the buffer size needs to be communicated to the user, as it is not embedded in the payload. It seems needlessly convoluted to me to create a separate function solely to calculate the size of the buffer so that it can be allocated by the user and passed to the serialization function, and I cannot think of another solution that would not be even more convoluted and awkward for the user.
>
> I don't understand how going from AVBufferRef to uint8_t* is more complicated than the reverse. The buffer in the AVBufferRef is allocated via av_malloc() and is directly accessible through the data field. Am I missing some detail?
What I mean is that once data is wrapped in an AVBufer, it is "locked
in", you always have to keep an AVBufferRef around.
--
Anton Khirnov
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-12 21:52 ` James Almer
@ 2023-03-12 21:56 ` Raphaël Zumer
0 siblings, 0 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-12 21:56 UTC (permalink / raw)
To: ffmpeg-devel
On 3/12/23 17:52, James Almer wrote:
> On 3/12/2023 6:50 PM, Raphaël Zumer wrote:
>> I expanded on this in another email in the chain, but the buffer size needs to be communicated to the user, as it is not embedded in the payload. It seems needlessly convoluted to me to create a separate function solely to calculate the size of the buffer so that it can be allocated by the user and passed to the serialization function, and I cannot think of another solution that would not be even more convoluted and awkward for the user.
>>
>> I don't understand how going from AVBufferRef to uint8_t* is more complicated than the reverse. The buffer in the AVBufferRef is allocated via av_malloc() and is directly accessible through the data field. Am I missing some detail?
>>
>> Raphaël Zumer
> You can do it like how the AVDynamicHDRPlus struct is allocated and its
> size returned to the user in av_dynamic_hdr_plus_alloc(). That is
>
> uint8_t *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s, size_t *size);
>
> The function would then store the calculated size of the array on *size.
OK great, I will do that and address the remaining comments tomorrow.
Thanks
>> On 3/12/23 15:48, Anton Khirnov wrote:
>>> Quoting Raphaël Zumer (2023-03-02 22:43:29)
>>>> +/**
>>>> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
>>>> + * excluding the country code and beginning with the terminal provider code.
>>>> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
>>>> + *
>>>> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
>>>> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
>>>> + */
>>>> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
>>> Why is this an AVBufferRef rather than a plain av_malloced() uint8_t
>>> array? You can very easily turn the latter into the former, but the
>>> reverse is a lot more annoying.
>>>
>> _______________________________________________
>> 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".
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-12 21:50 ` Raphaël Zumer
@ 2023-03-12 21:52 ` James Almer
2023-03-12 21:56 ` Raphaël Zumer
2023-03-13 13:36 ` Anton Khirnov
1 sibling, 1 reply; 21+ messages in thread
From: James Almer @ 2023-03-12 21:52 UTC (permalink / raw)
To: ffmpeg-devel
On 3/12/2023 6:50 PM, Raphaël Zumer wrote:
> I expanded on this in another email in the chain, but the buffer size needs to be communicated to the user, as it is not embedded in the payload. It seems needlessly convoluted to me to create a separate function solely to calculate the size of the buffer so that it can be allocated by the user and passed to the serialization function, and I cannot think of another solution that would not be even more convoluted and awkward for the user.
>
> I don't understand how going from AVBufferRef to uint8_t* is more complicated than the reverse. The buffer in the AVBufferRef is allocated via av_malloc() and is directly accessible through the data field. Am I missing some detail?
>
> Raphaël Zumer
You can do it like how the AVDynamicHDRPlus struct is allocated and its
size returned to the user in av_dynamic_hdr_plus_alloc(). That is
uint8_t *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s, size_t *size);
The function would then store the calculated size of the array on *size.
>
> On 3/12/23 15:48, Anton Khirnov wrote:
>> Quoting Raphaël Zumer (2023-03-02 22:43:29)
>>> +/**
>>> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
>>> + * excluding the country code and beginning with the terminal provider code.
>>> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
>>> + *
>>> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
>>> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
>>> + */
>>> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
>> Why is this an AVBufferRef rather than a plain av_malloced() uint8_t
>> array? You can very easily turn the latter into the former, but the
>> reverse is a lot more annoying.
>>
> _______________________________________________
> 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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-12 19:48 ` Anton Khirnov
@ 2023-03-12 21:50 ` Raphaël Zumer
2023-03-12 21:52 ` James Almer
2023-03-13 13:36 ` Anton Khirnov
0 siblings, 2 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-12 21:50 UTC (permalink / raw)
To: ffmpeg-devel
I expanded on this in another email in the chain, but the buffer size needs to be communicated to the user, as it is not embedded in the payload. It seems needlessly convoluted to me to create a separate function solely to calculate the size of the buffer so that it can be allocated by the user and passed to the serialization function, and I cannot think of another solution that would not be even more convoluted and awkward for the user.
I don't understand how going from AVBufferRef to uint8_t* is more complicated than the reverse. The buffer in the AVBufferRef is allocated via av_malloc() and is directly accessible through the data field. Am I missing some detail?
Raphaël Zumer
On 3/12/23 15:48, Anton Khirnov wrote:
> Quoting Raphaël Zumer (2023-03-02 22:43:29)
>> +/**
>> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
>> + * excluding the country code and beginning with the terminal provider code.
>> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
>> + *
>> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
>> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
>> + */
>> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
> Why is this an AVBufferRef rather than a plain av_malloced() uint8_t
> array? You can very easily turn the latter into the former, but the
> reverse is a lot more annoying.
>
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 21:43 Raphaël Zumer
2023-03-09 14:18 ` Raphaël Zumer
2023-03-12 16:25 ` Zhao Zhili
@ 2023-03-12 19:48 ` Anton Khirnov
2023-03-12 21:50 ` Raphaël Zumer
2 siblings, 1 reply; 21+ messages in thread
From: Anton Khirnov @ 2023-03-12 19:48 UTC (permalink / raw)
To: FFmpeg development discussions and patches
Quoting Raphaël Zumer (2023-03-02 22:43:29)
> +/**
> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
> + * excluding the country code and beginning with the terminal provider code.
> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
> + *
> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
> + */
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
Why is this an AVBufferRef rather than a plain av_malloced() uint8_t
array? You can very easily turn the latter into the former, but the
reverse is a lot more annoying.
--
Anton Khirnov
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 21:43 Raphaël Zumer
2023-03-09 14:18 ` Raphaël Zumer
@ 2023-03-12 16:25 ` Zhao Zhili
2023-03-12 19:48 ` Anton Khirnov
2 siblings, 0 replies; 21+ messages in thread
From: Zhao Zhili @ 2023-03-12 16:25 UTC (permalink / raw)
To: 'FFmpeg development discussions and patches'
> From: ffmpeg-devel <ffmpeg-devel-bounces@ffmpeg.org> On Behalf Of Raphaël Zumer
> Sent: 2023年3月3日 5:43
> To: ffmpeg-devel@ffmpeg.org
> Subject: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
>
> Fixed brace style and moved inline buffer size calculation comments to a single block at the top.
>
>
> Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
> ---
> libavutil/hdr_dynamic_metadata.c | 142 +++++++++++++++++++++++++++++++
> libavutil/hdr_dynamic_metadata.h | 11 +++
> libavutil/version.h | 2 +-
> 3 files changed, 154 insertions(+), 1 deletion(-)
>
> diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
> index 98f399b032..24dd3dab2d 100644
> --- a/libavutil/hdr_dynamic_metadata.c
> +++ b/libavutil/hdr_dynamic_metadata.c
> @@ -225,3 +225,145 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
>
> return 0;
> }
> +
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
> +{
How about add 'const' modifier to AVDynamicHDRPlus *s ?
> + AVBufferRef *buf;
> + size_t size_bits, size_bytes;
> + PutBitContext pbc, *pb = &pbc;
> +
> + if (!s)
> + return NULL;
> +
> + /**
> + * Buffer size per CTA-861-H p.253-254:
> + * 48 bits for the header (56 minus excluded 8-bit country code)
> + * 2 bits for num_windows
> + * 937 bits for window geometry, for each window above 1
> + * 27 bits for targeted_system_display_maximum_luminance
> + * 1-3855 bits for targeted system display peak luminance information
> + * 0-442 bits for intra-window pixel distribution information
> + * 1-3855 bits for mastering display peak luminance information
> + * 0-537 bits for per-window tonemapping information
> + * 0-21 bits for per-window color saturation mapping information
> + */
> + size_bits = 48 +
> + 2 +
> + FFMAX((s->num_windows - 1), 0) * 937 +
> + 27 +
> + 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_targeted_system_display_actual_peak_luminance *
> + s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
> + s->num_windows * 82;
> +
> + for (int w = 0; w < s->num_windows; w++)
> + size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
> +
> + size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_mastering_display_actual_peak_luminance *
> + s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
> + s->num_windows * 1;
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].tone_mapping_flag)
> + size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
> + }
> +
> + size_bits += s->num_windows * 1;
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].color_saturation_mapping_flag)
> + size_bits += 6;
> + }
> +
> + size_bytes = (size_bits + 7) / 8;
> +
> + buf = av_buffer_alloc(size_bytes);
> + if (!buf)
> + return NULL;
> +
> + init_put_bits(pb, buf->data, size_bytes);
> +
> + // itu_t_t35_country_code shall be 0xB5 (USA) (excluded from the payload)
> + // itu_t_t35_terminal_provider_code shall be 0x003C
> + put_bits(pb, 16, 0x003C);
> + // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
> + put_bits(pb, 16, 0x0001);
> + // application_identifier shall be set to 4
> + put_bits(pb, 8, 4);
> + // application_mode is set to Application Version 1
> + put_bits(pb, 8, 1);
> +
> + // Payload as per CTA-861-H p.253-254
> + put_bits(pb, 2, s->num_windows);
> +
> + for (int w = 1; w < s->num_windows; w++) {
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_x);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_y);
> + put_bits(pb, 8, s->params[w].rotation_angle);
> + put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
> + put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
> + put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
> + put_bits(pb, 1, s->params[w].overlap_process_option);
> + }
> +
> + put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
> + s->targeted_system_display_maximum_luminance.den);
> + put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
> + if (s->targeted_system_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++)
> + put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->targeted_system_display_actual_peak_luminance[i][j].den);
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + for (int i = 0; i < 3; i++)
> + put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
> + put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
> + put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
> + for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
> + put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
> + put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
> + s->params[w].distribution_maxrgb[i].percentile.den);
> + }
> + put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
> + s->params[w].fraction_bright_pixels.den);
> + }
> +
> + put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
> + if (s->mastering_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++)
> + put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->mastering_display_actual_peak_luminance[i][j].den);
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + put_bits(pb, 1, s->params[w].tone_mapping_flag);
> + if (s->params[w].tone_mapping_flag) {
> + put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
> + put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
> + put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
> + for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++)
> + put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
> + s->params[w].bezier_curve_anchors[i].den);
> + put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
> + if (s->params[w].color_saturation_mapping_flag)
> + put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
> + s->params[w].color_saturation_weight.den);
> + }
> + }
> +
> + flush_put_bits(pb);
> + return buf;
> +}
> diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
> index 1f953ef1f5..797a5c64ae 100644
> --- a/libavutil/hdr_dynamic_metadata.h
> +++ b/libavutil/hdr_dynamic_metadata.h
> @@ -21,6 +21,7 @@
> #ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
> #define AVUTIL_HDR_DYNAMIC_METADATA_H
>
> +#include "buffer.h"
> #include "frame.h"
> #include "rational.h"
>
> @@ -351,4 +352,14 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
> int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
> int size);
>
> +/**
> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
> + * excluding the country code and beginning with the terminal provider code.
> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
> + *
> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
> + */
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
> +
> #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 900b798971..7635672985 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
> */
>
> #define LIBAVUTIL_VERSION_MAJOR 58
> -#define LIBAVUTIL_VERSION_MINOR 3
> +#define LIBAVUTIL_VERSION_MINOR 4
> #define LIBAVUTIL_VERSION_MICRO 100
>
> #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
> --
> 2.39.1
>
> _______________________________________________
> 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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-09 14:18 ` Raphaël Zumer
@ 2023-03-12 15:21 ` James Almer
2023-03-13 22:25 ` Andreas Rheinhardt
0 siblings, 1 reply; 21+ messages in thread
From: James Almer @ 2023-03-12 15:21 UTC (permalink / raw)
To: ffmpeg-devel
On 3/9/2023 11:18 AM, Raphaël Zumer wrote:
> Hi,
>
> While I omitted adding v2/v3 here, I believe all comments on this set of patches have been addressed so far, unless anyone strongly disagrees with the rationale for moving dynamic HDR parsing and serialization to libavutil or with the function signature.
>
> Please let me know if I missed anything.
>
> Thanks,
> Raphaël Zumer
I'll apply this (and patch 1/1) in a few days if nobody comments.
The code needs to be in lavu if we want muxers and demuxers to use this
functionality, so moving the existing lavc functions is fine unless we
add more avpriv_ functions that people tend to dislike.
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 21:43 Raphaël Zumer
@ 2023-03-09 14:18 ` Raphaël Zumer
2023-03-12 15:21 ` James Almer
2023-03-12 16:25 ` Zhao Zhili
2023-03-12 19:48 ` Anton Khirnov
2 siblings, 1 reply; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-09 14:18 UTC (permalink / raw)
To: ffmpeg-devel
Hi,
While I omitted adding v2/v3 here, I believe all comments on this set of patches have been addressed so far, unless anyone strongly disagrees with the rationale for moving dynamic HDR parsing and serialization to libavutil or with the function signature.
Please let me know if I missed anything.
Thanks,
Raphaël Zumer
On 3/2/23 16:43, Raphaël Zumer wrote:
> Fixed brace style and moved inline buffer size calculation comments to a single block at the top.
>
>
> Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
> ---
> libavutil/hdr_dynamic_metadata.c | 142 +++++++++++++++++++++++++++++++
> libavutil/hdr_dynamic_metadata.h | 11 +++
> libavutil/version.h | 2 +-
> 3 files changed, 154 insertions(+), 1 deletion(-)
>
> diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
> index 98f399b032..24dd3dab2d 100644
> --- a/libavutil/hdr_dynamic_metadata.c
> +++ b/libavutil/hdr_dynamic_metadata.c
> @@ -225,3 +225,145 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
>
> return 0;
> }
> +
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
> +{
> + AVBufferRef *buf;
> + size_t size_bits, size_bytes;
> + PutBitContext pbc, *pb = &pbc;
> +
> + if (!s)
> + return NULL;
> +
> + /**
> + * Buffer size per CTA-861-H p.253-254:
> + * 48 bits for the header (56 minus excluded 8-bit country code)
> + * 2 bits for num_windows
> + * 937 bits for window geometry, for each window above 1
> + * 27 bits for targeted_system_display_maximum_luminance
> + * 1-3855 bits for targeted system display peak luminance information
> + * 0-442 bits for intra-window pixel distribution information
> + * 1-3855 bits for mastering display peak luminance information
> + * 0-537 bits for per-window tonemapping information
> + * 0-21 bits for per-window color saturation mapping information
> + */
> + size_bits = 48 +
> + 2 +
> + FFMAX((s->num_windows - 1), 0) * 937 +
> + 27 +
> + 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_targeted_system_display_actual_peak_luminance *
> + s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
> + s->num_windows * 82;
> +
> + for (int w = 0; w < s->num_windows; w++)
> + size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
> +
> + size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_mastering_display_actual_peak_luminance *
> + s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
> + s->num_windows * 1;
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].tone_mapping_flag)
> + size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
> + }
> +
> + size_bits += s->num_windows * 1;
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].color_saturation_mapping_flag)
> + size_bits += 6;
> + }
> +
> + size_bytes = (size_bits + 7) / 8;
> +
> + buf = av_buffer_alloc(size_bytes);
> + if (!buf)
> + return NULL;
> +
> + init_put_bits(pb, buf->data, size_bytes);
> +
> + // itu_t_t35_country_code shall be 0xB5 (USA) (excluded from the payload)
> + // itu_t_t35_terminal_provider_code shall be 0x003C
> + put_bits(pb, 16, 0x003C);
> + // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
> + put_bits(pb, 16, 0x0001);
> + // application_identifier shall be set to 4
> + put_bits(pb, 8, 4);
> + // application_mode is set to Application Version 1
> + put_bits(pb, 8, 1);
> +
> + // Payload as per CTA-861-H p.253-254
> + put_bits(pb, 2, s->num_windows);
> +
> + for (int w = 1; w < s->num_windows; w++) {
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_x);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_y);
> + put_bits(pb, 8, s->params[w].rotation_angle);
> + put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
> + put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
> + put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
> + put_bits(pb, 1, s->params[w].overlap_process_option);
> + }
> +
> + put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
> + s->targeted_system_display_maximum_luminance.den);
> + put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
> + if (s->targeted_system_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++)
> + put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->targeted_system_display_actual_peak_luminance[i][j].den);
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + for (int i = 0; i < 3; i++)
> + put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
> + put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
> + put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
> + for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
> + put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
> + put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
> + s->params[w].distribution_maxrgb[i].percentile.den);
> + }
> + put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
> + s->params[w].fraction_bright_pixels.den);
> + }
> +
> + put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
> + if (s->mastering_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++)
> + put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->mastering_display_actual_peak_luminance[i][j].den);
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + put_bits(pb, 1, s->params[w].tone_mapping_flag);
> + if (s->params[w].tone_mapping_flag) {
> + put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
> + put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
> + put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
> + for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++)
> + put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
> + s->params[w].bezier_curve_anchors[i].den);
> + put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
> + if (s->params[w].color_saturation_mapping_flag)
> + put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
> + s->params[w].color_saturation_weight.den);
> + }
> + }
> +
> + flush_put_bits(pb);
> + return buf;
> +}
> diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
> index 1f953ef1f5..797a5c64ae 100644
> --- a/libavutil/hdr_dynamic_metadata.h
> +++ b/libavutil/hdr_dynamic_metadata.h
> @@ -21,6 +21,7 @@
> #ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
> #define AVUTIL_HDR_DYNAMIC_METADATA_H
>
> +#include "buffer.h"
> #include "frame.h"
> #include "rational.h"
>
> @@ -351,4 +352,14 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
> int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
> int size);
>
> +/**
> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
> + * excluding the country code and beginning with the terminal provider code.
> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
> + *
> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
> + */
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
> +
> #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 900b798971..7635672985 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
> */
>
> #define LIBAVUTIL_VERSION_MAJOR 58
> -#define LIBAVUTIL_VERSION_MINOR 3
> +#define LIBAVUTIL_VERSION_MINOR 4
> #define LIBAVUTIL_VERSION_MICRO 100
>
> #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
_______________________________________________
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] 21+ messages in thread
* [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
@ 2023-03-02 21:43 Raphaël Zumer
2023-03-09 14:18 ` Raphaël Zumer
` (2 more replies)
0 siblings, 3 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-02 21:43 UTC (permalink / raw)
To: ffmpeg-devel
Fixed brace style and moved inline buffer size calculation comments to a single block at the top.
Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
---
libavutil/hdr_dynamic_metadata.c | 142 +++++++++++++++++++++++++++++++
libavutil/hdr_dynamic_metadata.h | 11 +++
libavutil/version.h | 2 +-
3 files changed, 154 insertions(+), 1 deletion(-)
diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
index 98f399b032..24dd3dab2d 100644
--- a/libavutil/hdr_dynamic_metadata.c
+++ b/libavutil/hdr_dynamic_metadata.c
@@ -225,3 +225,145 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
return 0;
}
+
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
+{
+ AVBufferRef *buf;
+ size_t size_bits, size_bytes;
+ PutBitContext pbc, *pb = &pbc;
+
+ if (!s)
+ return NULL;
+
+ /**
+ * Buffer size per CTA-861-H p.253-254:
+ * 48 bits for the header (56 minus excluded 8-bit country code)
+ * 2 bits for num_windows
+ * 937 bits for window geometry, for each window above 1
+ * 27 bits for targeted_system_display_maximum_luminance
+ * 1-3855 bits for targeted system display peak luminance information
+ * 0-442 bits for intra-window pixel distribution information
+ * 1-3855 bits for mastering display peak luminance information
+ * 0-537 bits for per-window tonemapping information
+ * 0-21 bits for per-window color saturation mapping information
+ */
+ size_bits = 48 +
+ 2 +
+ FFMAX((s->num_windows - 1), 0) * 937 +
+ 27 +
+ 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_targeted_system_display_actual_peak_luminance *
+ s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
+ s->num_windows * 82;
+
+ for (int w = 0; w < s->num_windows; w++)
+ size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
+
+ size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_mastering_display_actual_peak_luminance *
+ s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
+ s->num_windows * 1;
+
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].tone_mapping_flag)
+ size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
+ }
+
+ size_bits += s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].color_saturation_mapping_flag)
+ size_bits += 6;
+ }
+
+ size_bytes = (size_bits + 7) / 8;
+
+ buf = av_buffer_alloc(size_bytes);
+ if (!buf)
+ return NULL;
+
+ init_put_bits(pb, buf->data, size_bytes);
+
+ // itu_t_t35_country_code shall be 0xB5 (USA) (excluded from the payload)
+ // itu_t_t35_terminal_provider_code shall be 0x003C
+ put_bits(pb, 16, 0x003C);
+ // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
+ put_bits(pb, 16, 0x0001);
+ // application_identifier shall be set to 4
+ put_bits(pb, 8, 4);
+ // application_mode is set to Application Version 1
+ put_bits(pb, 8, 1);
+
+ // Payload as per CTA-861-H p.253-254
+ put_bits(pb, 2, s->num_windows);
+
+ for (int w = 1; w < s->num_windows; w++) {
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_x);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_y);
+ put_bits(pb, 8, s->params[w].rotation_angle);
+ put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
+ put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
+ put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
+ put_bits(pb, 1, s->params[w].overlap_process_option);
+ }
+
+ put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
+ s->targeted_system_display_maximum_luminance.den);
+ put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
+ if (s->targeted_system_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
+ put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
+ for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
+ for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++)
+ put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->targeted_system_display_actual_peak_luminance[i][j].den);
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ for (int i = 0; i < 3; i++)
+ put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
+ put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
+ put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
+ for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
+ put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
+ put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
+ s->params[w].distribution_maxrgb[i].percentile.den);
+ }
+ put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
+ s->params[w].fraction_bright_pixels.den);
+ }
+
+ put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
+ if (s->mastering_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
+ put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
+ for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
+ for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++)
+ put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->mastering_display_actual_peak_luminance[i][j].den);
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ put_bits(pb, 1, s->params[w].tone_mapping_flag);
+ if (s->params[w].tone_mapping_flag) {
+ put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
+ put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
+ put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
+ for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++)
+ put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
+ s->params[w].bezier_curve_anchors[i].den);
+ put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
+ if (s->params[w].color_saturation_mapping_flag)
+ put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
+ s->params[w].color_saturation_weight.den);
+ }
+ }
+
+ flush_put_bits(pb);
+ return buf;
+}
diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
index 1f953ef1f5..797a5c64ae 100644
--- a/libavutil/hdr_dynamic_metadata.h
+++ b/libavutil/hdr_dynamic_metadata.h
@@ -21,6 +21,7 @@
#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
#define AVUTIL_HDR_DYNAMIC_METADATA_H
+#include "buffer.h"
#include "frame.h"
#include "rational.h"
@@ -351,4 +352,14 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
int size);
+/**
+ * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
+ * excluding the country code and beginning with the terminal provider code.
+ * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
+ *
+ * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
+ * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
+ */
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
+
#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
diff --git a/libavutil/version.h b/libavutil/version.h
index 900b798971..7635672985 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 3
+#define LIBAVUTIL_VERSION_MINOR 4
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
--
2.39.1
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 20:24 ` Leo Izen
2023-03-02 20:37 ` Derek Buitenhuis
@ 2023-03-02 20:45 ` Raphaël Zumer
1 sibling, 0 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-02 20:45 UTC (permalink / raw)
To: ffmpeg-devel
On 3/2/23 15:24, Leo Izen wrote:
> On 3/2/23 14:25, Raphaël Zumer wrote:
>> Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
>> ---
>> libavutil/hdr_dynamic_metadata.c | 146 +++++++++++++++++++++++++++++++
>> libavutil/hdr_dynamic_metadata.h | 11 +++
>> libavutil/version.h | 2 +-
>> 3 files changed, 158 insertions(+), 1 deletion(-)
>>
> Why not put this in avcodec/dynamic_hdr10_plus.c? You reference
> put_bits.h which is in avcodec, so that can possibly be an issue, even
> though it is inlined (i.e. it sends the wrong message since avutil is
> supposed to not depend on avcodec).
I agree it is somewhat awkward to introduce a circular dependency (albeit to header-only files). On the other hand, I think those functions make more sense in libavutil than libavcodec, and it improves readability by not splitting files that are logically connected between libraries. If there is a general consensus that it is better to keep them in libavcodec, I don't mind reverting that change, or moving get_bits and put_bits to libavutil if that is doable.
>> diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
>> index 98f399b032..39a7886a2e 100644
>> --- a/libavutil/hdr_dynamic_metadata.c
>> +++ b/libavutil/hdr_dynamic_metadata.c
>> @@ -225,3 +225,149 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
>>
>> return 0;
>> }
>> +
>> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
>> +{
> av_dynamic_hdr_plus_from_t35 returns an int status code and takes a
> pointer as an argument, is there any particular reason you didn't mirror
> user interface here?
Mainly the added complexity of buffer size calculation. I think it would be doable by adding an additional function such as av_dynamic_hdr_plus_to_t35_size() that would return the serialized buffer size, which could be then used by the user to allocate a buffer to be written by av_dynamic_hdr_plus_to_t35(). But adding an additional function just to make the function signatures consistent feels contrived to me, and there aren't several errors that could happen in that function that would need to be disambiguated by the user.
>> + AVBufferRef *buf;
>> + size_t size_bits, size_bytes;
>> + PutBitContext pbc, *pb = &pbc;
>> +
>> + if (!s)
>> + return NULL;
>> +
>> + // Buffer size per CTA-861-H p.253-254:
>> + size_bits =
>> + // 56 bits for the header, minus 8-bit excluded country code
>> + 48 +
>> + // 2 bits for num_windows
>> + 2 +
>> + // 937 bits for window geometry for each window above 1
>> + FFMAX((s->num_windows - 1), 0) * 937 +
>> + // 27 bits for targeted_system_display_maximum_luminance
>> + 27 +
>> + // 1-3855 bits for targeted system display peak luminance information
>> + 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
>> + s->num_rows_targeted_system_display_actual_peak_luminance *
>> + s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
>> + // 0-442 bits for intra-window pixel distribution information
>> + s->num_windows * 82;
> This sequence above is difficult to read due to the inline // comments.
> It should be more readable to just have the entire expression be
> contiguous with a /* */ multiline block comment above it explaining each
> item.
>> + for (int w = 0; w < s->num_windows; w++) {
>> + size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
>> + }
> Likewise, another code style issue, don't use {} to enclose a single
> line unless it's unavoidable. This occurs in several places in this patch.
OK, will correct.
Thanks
Raphaël Zumer
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 20:24 ` Leo Izen
@ 2023-03-02 20:37 ` Derek Buitenhuis
2023-03-02 20:45 ` Raphaël Zumer
1 sibling, 0 replies; 21+ messages in thread
From: Derek Buitenhuis @ 2023-03-02 20:37 UTC (permalink / raw)
To: ffmpeg-devel
On 3/2/2023 8:24 PM, Leo Izen wrote:
> Why not put this in avcodec/dynamic_hdr10_plus.c? You reference
> put_bits.h which is in avcodec, so that can possibly be an issue, even
> though it is inlined (i.e. it sends the wrong message since avutil is
> supposed to not depend on avcodec).
put_bits is a header-only implementation, isn't it? No dependency is
introduced.
Putting it in avutil was my suggested, as it is a function which takes
side data as input, FWIW.
- Derek
_______________________________________________
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] 21+ messages in thread
* Re: [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
2023-03-02 19:25 Raphaël Zumer
@ 2023-03-02 20:24 ` Leo Izen
2023-03-02 20:37 ` Derek Buitenhuis
2023-03-02 20:45 ` Raphaël Zumer
0 siblings, 2 replies; 21+ messages in thread
From: Leo Izen @ 2023-03-02 20:24 UTC (permalink / raw)
To: ffmpeg-devel
On 3/2/23 14:25, Raphaël Zumer wrote:
> Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
> ---
> libavutil/hdr_dynamic_metadata.c | 146 +++++++++++++++++++++++++++++++
> libavutil/hdr_dynamic_metadata.h | 11 +++
> libavutil/version.h | 2 +-
> 3 files changed, 158 insertions(+), 1 deletion(-)
>
Why not put this in avcodec/dynamic_hdr10_plus.c? You reference
put_bits.h which is in avcodec, so that can possibly be an issue, even
though it is inlined (i.e. it sends the wrong message since avutil is
supposed to not depend on avcodec).
> diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
> index 98f399b032..39a7886a2e 100644
> --- a/libavutil/hdr_dynamic_metadata.c
> +++ b/libavutil/hdr_dynamic_metadata.c
> @@ -225,3 +225,149 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
>
> return 0;
> }
> +
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
> +{
av_dynamic_hdr_plus_from_t35 returns an int status code and takes a
pointer as an argument, is there any particular reason you didn't mirror
user interface here?
> + AVBufferRef *buf;
> + size_t size_bits, size_bytes;
> + PutBitContext pbc, *pb = &pbc;
> +
> + if (!s)
> + return NULL;
> +
> + // Buffer size per CTA-861-H p.253-254:
> + size_bits =
> + // 56 bits for the header, minus 8-bit excluded country code
> + 48 +
> + // 2 bits for num_windows
> + 2 +
> + // 937 bits for window geometry for each window above 1
> + FFMAX((s->num_windows - 1), 0) * 937 +
> + // 27 bits for targeted_system_display_maximum_luminance
> + 27 +
> + // 1-3855 bits for targeted system display peak luminance information
> + 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_targeted_system_display_actual_peak_luminance *
> + s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
> + // 0-442 bits for intra-window pixel distribution information
> + s->num_windows * 82;
This sequence above is difficult to read due to the inline // comments.
It should be more readable to just have the entire expression be
contiguous with a /* */ multiline block comment above it explaining each
item.
> + for (int w = 0; w < s->num_windows; w++) {
> + size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
> + }
Likewise, another code style issue, don't use {} to enclose a single
line unless it's unavoidable. This occurs in several places in this patch.
> + // 1-3855 bits for mastering display peak luminance information
> + size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
> + s->num_rows_mastering_display_actual_peak_luminance *
> + s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
> + // 0-537 bits for per-window tonemapping information
> + s->num_windows * 1;
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].tone_mapping_flag) {
> + size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
> + }
> + }
> + // 0-21 bits for per-window color saturation mapping information
> + size_bits += s->num_windows * 1;
> + for (int w = 0; w < s->num_windows; w++) {
> + if (s->params[w].color_saturation_mapping_flag) {
> + size_bits += 6;
> + }
> + }
> +
> + size_bytes = (size_bits + 7) / 8;
> +
> + buf = av_buffer_alloc(size_bytes);
> + if (!buf) {
> + return NULL;
> +
If you update this to match the status code, this becomes AVERROR(ENOMEM);
> +
> + init_put_bits(pb, buf->data, size_bytes);
> +
> + // itu_t_t35_country_code shall be 0xB5 (USA) (excluded from the payload)
> + // itu_t_t35_terminal_provider_code shall be 0x003C
> + put_bits(pb, 16, 0x003C);
> + // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
> + put_bits(pb, 16, 0x0001);
> + // application_identifier shall be set to 4
> + put_bits(pb, 8, 4);
> + // application_mode is set to Application Version 1
> + put_bits(pb, 8, 1);
> +
> + // Payload as per CTA-861-H p.253-254
> + put_bits(pb, 2, s->num_windows);
> +
> + for (int w = 1; w < s->num_windows; w++) {
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
> + put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_x);
> + put_bits(pb, 16, s->params[w].center_of_ellipse_y);
> + put_bits(pb, 8, s->params[w].rotation_angle);
> + put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
> + put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
> + put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
> + put_bits(pb, 1, s->params[w].overlap_process_option);
> + }
> +
> + put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
> + s->targeted_system_display_maximum_luminance.den);
> + put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
> + if (s->targeted_system_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++) {
> + put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->targeted_system_display_actual_peak_luminance[i][j].den);
> + }
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + for (int i = 0; i < 3; i++) {
> + put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
> + }
> + put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
> + put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
> + for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
> + put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
> + put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
> + s->params[w].distribution_maxrgb[i].percentile.den);
> + }
> + put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
> + s->params[w].fraction_bright_pixels.den);
> + }
> +
> + put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
> + if (s->mastering_display_actual_peak_luminance_flag) {
> + put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
> + put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
> + for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
> + for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++) {
> + put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
> + s->mastering_display_actual_peak_luminance[i][j].den);
> + }
> + }
> + }
> +
> + for (int w = 0; w < s->num_windows; w++) {
> + put_bits(pb, 1, s->params[w].tone_mapping_flag);
> + if (s->params[w].tone_mapping_flag) {
> + put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
> + put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
> + put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
> + for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++) {
> + put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
> + s->params[w].bezier_curve_anchors[i].den);
> + }
> + put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
> + if (s->params[w].color_saturation_mapping_flag) {
> + put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
> + s->params[w].color_saturation_weight.den);
> + }
> + }
> + }
> +
> + flush_put_bits(pb);
> + return buf;
> +}
> diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
> index 1f953ef1f5..797a5c64ae 100644
> --- a/libavutil/hdr_dynamic_metadata.h
> +++ b/libavutil/hdr_dynamic_metadata.h
> @@ -21,6 +21,7 @@
> #ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
> #define AVUTIL_HDR_DYNAMIC_METADATA_H
>
> +#include "buffer.h"
> #include "frame.h"
> #include "rational.h"
>
> @@ -351,4 +352,14 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
> int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
> int size);
>
> +/**
> + * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
> + * excluding the country code and beginning with the terminal provider code.
> + * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
> + *
> + * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
> + * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
> + */
> +AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
> +
> #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
> diff --git a/libavutil/version.h b/libavutil/version.h
> index 900b798971..7635672985 100644
> --- a/libavutil/version.h
> +++ b/libavutil/version.h
> @@ -79,7 +79,7 @@
> */
>
> #define LIBAVUTIL_VERSION_MAJOR 58
> -#define LIBAVUTIL_VERSION_MINOR 3
> +#define LIBAVUTIL_VERSION_MINOR 4
> #define LIBAVUTIL_VERSION_MICRO 100
>
> #define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
- Leo Izen (thebombzen)
_______________________________________________
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] 21+ messages in thread
* [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
@ 2023-03-02 19:25 Raphaël Zumer
2023-03-02 20:24 ` Leo Izen
0 siblings, 1 reply; 21+ messages in thread
From: Raphaël Zumer @ 2023-03-02 19:25 UTC (permalink / raw)
To: ffmpeg-devel
Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
---
libavutil/hdr_dynamic_metadata.c | 146 +++++++++++++++++++++++++++++++
libavutil/hdr_dynamic_metadata.h | 11 +++
libavutil/version.h | 2 +-
3 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/libavutil/hdr_dynamic_metadata.c b/libavutil/hdr_dynamic_metadata.c
index 98f399b032..39a7886a2e 100644
--- a/libavutil/hdr_dynamic_metadata.c
+++ b/libavutil/hdr_dynamic_metadata.c
@@ -225,3 +225,149 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
return 0;
}
+
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
+{
+ AVBufferRef *buf;
+ size_t size_bits, size_bytes;
+ PutBitContext pbc, *pb = &pbc;
+
+ if (!s)
+ return NULL;
+
+ // Buffer size per CTA-861-H p.253-254:
+ size_bits =
+ // 56 bits for the header, minus 8-bit excluded country code
+ 48 +
+ // 2 bits for num_windows
+ 2 +
+ // 937 bits for window geometry for each window above 1
+ FFMAX((s->num_windows - 1), 0) * 937 +
+ // 27 bits for targeted_system_display_maximum_luminance
+ 27 +
+ // 1-3855 bits for targeted system display peak luminance information
+ 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_targeted_system_display_actual_peak_luminance *
+ s->num_cols_targeted_system_display_actual_peak_luminance * 4 : 0) +
+ // 0-442 bits for intra-window pixel distribution information
+ s->num_windows * 82;
+ for (int w = 0; w < s->num_windows; w++) {
+ size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
+ }
+ // 1-3855 bits for mastering display peak luminance information
+ size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_mastering_display_actual_peak_luminance *
+ s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
+ // 0-537 bits for per-window tonemapping information
+ s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].tone_mapping_flag) {
+ size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
+ }
+ }
+ // 0-21 bits for per-window color saturation mapping information
+ size_bits += s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].color_saturation_mapping_flag) {
+ size_bits += 6;
+ }
+ }
+
+ size_bytes = (size_bits + 7) / 8;
+
+ buf = av_buffer_alloc(size_bytes);
+ if (!buf) {
+ return NULL;
+ }
+
+ init_put_bits(pb, buf->data, size_bytes);
+
+ // itu_t_t35_country_code shall be 0xB5 (USA) (excluded from the payload)
+ // itu_t_t35_terminal_provider_code shall be 0x003C
+ put_bits(pb, 16, 0x003C);
+ // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
+ put_bits(pb, 16, 0x0001);
+ // application_identifier shall be set to 4
+ put_bits(pb, 8, 4);
+ // application_mode is set to Application Version 1
+ put_bits(pb, 8, 1);
+
+ // Payload as per CTA-861-H p.253-254
+ put_bits(pb, 2, s->num_windows);
+
+ for (int w = 1; w < s->num_windows; w++) {
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num / s->params[w].window_upper_left_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num / s->params[w].window_upper_left_corner_y.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num / s->params[w].window_lower_right_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num / s->params[w].window_lower_right_corner_y.den);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_x);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_y);
+ put_bits(pb, 8, s->params[w].rotation_angle);
+ put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
+ put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
+ put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
+ put_bits(pb, 1, s->params[w].overlap_process_option);
+ }
+
+ put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num * luminance_den /
+ s->targeted_system_display_maximum_luminance.den);
+ put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
+ if (s->targeted_system_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5, s->num_rows_targeted_system_display_actual_peak_luminance);
+ put_bits(pb, 5, s->num_cols_targeted_system_display_actual_peak_luminance);
+ for (int i = 0; i < s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
+ for (int j = 0; j < s->num_cols_targeted_system_display_actual_peak_luminance; j++) {
+ put_bits(pb, 4, s->targeted_system_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->targeted_system_display_actual_peak_luminance[i][j].den);
+ }
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ for (int i = 0; i < 3; i++) {
+ put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den / s->params[w].maxscl[i].den);
+ }
+ put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den / s->params[w].average_maxrgb.den);
+ put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
+ for (int i = 0; i < s->params[w].num_distribution_maxrgb_percentiles; i++) {
+ put_bits(pb, 7, s->params[w].distribution_maxrgb[i].percentage);
+ put_bits(pb, 17, s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
+ s->params[w].distribution_maxrgb[i].percentile.den);
+ }
+ put_bits(pb, 10, s->params[w].fraction_bright_pixels.num * fraction_pixel_den /
+ s->params[w].fraction_bright_pixels.den);
+ }
+
+ put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
+ if (s->mastering_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5, s->num_rows_mastering_display_actual_peak_luminance);
+ put_bits(pb, 5, s->num_cols_mastering_display_actual_peak_luminance);
+ for (int i = 0; i < s->num_rows_mastering_display_actual_peak_luminance; i++) {
+ for (int j = 0; j < s->num_cols_mastering_display_actual_peak_luminance; j++) {
+ put_bits(pb, 4, s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->mastering_display_actual_peak_luminance[i][j].den);
+ }
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ put_bits(pb, 1, s->params[w].tone_mapping_flag);
+ if (s->params[w].tone_mapping_flag) {
+ put_bits(pb, 12, s->params[w].knee_point_x.num * knee_point_den / s->params[w].knee_point_x.den);
+ put_bits(pb, 12, s->params[w].knee_point_y.num * knee_point_den / s->params[w].knee_point_y.den);
+ put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
+ for (int i = 0; i < s->params[w].num_bezier_curve_anchors; i++) {
+ put_bits(pb, 10, s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
+ s->params[w].bezier_curve_anchors[i].den);
+ }
+ put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
+ if (s->params[w].color_saturation_mapping_flag) {
+ put_bits(pb, 6, s->params[w].color_saturation_weight.num * saturation_weight_den /
+ s->params[w].color_saturation_weight.den);
+ }
+ }
+ }
+
+ flush_put_bits(pb);
+ return buf;
+}
diff --git a/libavutil/hdr_dynamic_metadata.h b/libavutil/hdr_dynamic_metadata.h
index 1f953ef1f5..797a5c64ae 100644
--- a/libavutil/hdr_dynamic_metadata.h
+++ b/libavutil/hdr_dynamic_metadata.h
@@ -21,6 +21,7 @@
#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
#define AVUTIL_HDR_DYNAMIC_METADATA_H
+#include "buffer.h"
#include "frame.h"
#include "rational.h"
@@ -351,4 +352,14 @@ AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
int size);
+/**
+ * Serialize dynamic HDR10+ metadata to a user data registered ITU-T T.35 buffer,
+ * excluding the country code and beginning with the terminal provider code.
+ * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
+ *
+ * @return Pointer to an AVBufferRef containing the raw ITU-T T.35 representation
+ * of the HDR10+ metadata if succeed, or NULL if buffer allocation fails.
+ */
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
+
#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
diff --git a/libavutil/version.h b/libavutil/version.h
index 900b798971..7635672985 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 3
+#define LIBAVUTIL_VERSION_MINOR 4
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
--
2.39.1
_______________________________________________
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] 21+ messages in thread
* [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function
[not found] <62782188-8dba-b4f0-6e54-571149f09040@tebako.net>
@ 2023-02-27 16:54 ` Raphaël Zumer
0 siblings, 0 replies; 21+ messages in thread
From: Raphaël Zumer @ 2023-02-27 16:54 UTC (permalink / raw)
To: ffmpeg-devel
See the previous patch for context.
Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
---
libavutil/hdr_dynamic_metadata.c | 147 +++++++++++++++++++++++++++++++
libavutil/hdr_dynamic_metadata.h | 10 +++
libavutil/version.h | 2 +-
3 files changed, 158 insertions(+), 1 deletion(-)
diff --git a/libavutil/hdr_dynamic_metadata.c
b/libavutil/hdr_dynamic_metadata.c
index 98f399b032..72d310e633 100644
--- a/libavutil/hdr_dynamic_metadata.c
+++ b/libavutil/hdr_dynamic_metadata.c
@@ -225,3 +225,150 @@ int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus
*s, const uint8_t *data,
return 0;
}
+
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s)
+{
+ AVBufferRef *buf;
+ size_t size_bits, size_bytes;
+ PutBitContext pbc, *pb = &pbc;
+
+ if (!s)
+ return NULL;
+
+ // Buffer size per CTA-861-H p.253-254:
+ size_bits =
+ // 56 bits for the header
+ 58 +
+ // 2 bits for num_windows
+ 2 +
+ // 937 bits for window geometry for each window above 1
+ FFMAX((s->num_windows - 1), 0) * 937 +
+ // 27 bits for targeted_system_display_maximum_luminance
+ 27 +
+ // 1-3855 bits for targeted system display peak luminance information
+ 1 + (s->targeted_system_display_actual_peak_luminance_flag ? 10 +
+ s->num_rows_targeted_system_display_actual_peak_luminance *
+ s->num_cols_targeted_system_display_actual_peak_luminance * 4 :
0) +
+ // 0-442 bits for intra-window pixel distribution information
+ s->num_windows * 82;
+ for (int w = 0; w < s->num_windows; w++) {
+ size_bits += s->params[w].num_distribution_maxrgb_percentiles * 24;
+ }
+ // 1-3855 bits for mastering display peak luminance information
+ size_bits += 1 + (s->mastering_display_actual_peak_luminance_flag ?
10 +
+ s->num_rows_mastering_display_actual_peak_luminance *
+ s->num_cols_mastering_display_actual_peak_luminance * 4 : 0) +
+ // 0-537 bits for per-window tonemapping information
+ s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].tone_mapping_flag) {
+ size_bits += 28 + s->params[w].num_bezier_curve_anchors * 10;
+ }
+ }
+ // 0-21 bits for per-window color saturation mapping information
+ size_bits += s->num_windows * 1;
+ for (int w = 0; w < s->num_windows; w++) {
+ if (s->params[w].color_saturation_mapping_flag) {
+ size_bits += 6;
+ }
+ }
+
+ size_bytes = (size_bits + 7) / 8;
+
+ buf = av_buffer_alloc(size_bytes);
+ if (!buf) {
+ return NULL;
+ }
+
+ init_put_bits(pb, buf->data, size_bytes);
+
+ // itu_t_t35_country_code shall be 0xB5 (USA)
+ put_bits(pb, 8, 0xB5);
+ // itu_t_t35_terminal_provider_code shall be 0x003C
+ put_bits(pb, 16, 0x003C);
+ // itu_t_t35_terminal_provider_oriented_code is set to ST 2094-40
+ put_bits(pb, 16, 0x0001);
+ // application_identifier shall be set to 4
+ put_bits(pb, 8, 4);
+ // application_mode is set to Application Version 1
+ put_bits(pb, 8, 1);
+
+ // Payload as per CTA-861-H p.253-254
+ put_bits(pb, 2, s->num_windows);
+
+ for (int w = 1; w < s->num_windows; w++) {
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_x.num /
s->params[w].window_upper_left_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_upper_left_corner_y.num /
s->params[w].window_upper_left_corner_y.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_x.num /
s->params[w].window_lower_right_corner_x.den);
+ put_bits(pb, 16, s->params[w].window_lower_right_corner_y.num /
s->params[w].window_lower_right_corner_y.den);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_x);
+ put_bits(pb, 16, s->params[w].center_of_ellipse_y);
+ put_bits(pb, 8, s->params[w].rotation_angle);
+ put_bits(pb, 16, s->params[w].semimajor_axis_internal_ellipse);
+ put_bits(pb, 16, s->params[w].semimajor_axis_external_ellipse);
+ put_bits(pb, 16, s->params[w].semiminor_axis_external_ellipse);
+ put_bits(pb, 1, s->params[w].overlap_process_option);
+ }
+
+ put_bits(pb, 27, s->targeted_system_display_maximum_luminance.num *
luminance_den /
+ s->targeted_system_display_maximum_luminance.den);
+ put_bits(pb, 1, s->targeted_system_display_actual_peak_luminance_flag);
+ if (s->targeted_system_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5,
s->num_rows_targeted_system_display_actual_peak_luminance);
+ put_bits(pb, 5,
s->num_cols_targeted_system_display_actual_peak_luminance);
+ for (int i = 0; i <
s->num_rows_targeted_system_display_actual_peak_luminance; i++) {
+ for (int j = 0; j <
s->num_cols_targeted_system_display_actual_peak_luminance; j++) {
+ put_bits(pb, 4,
s->targeted_system_display_actual_peak_luminance[i][j].num *
peak_luminance_den /
+ s->targeted_system_display_actual_peak_luminance[i][j].den);
+ }
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ for (int i = 0; i < 3; i++) {
+ put_bits(pb, 17, s->params[w].maxscl[i].num * rgb_den /
s->params[w].maxscl[i].den);
+ }
+ put_bits(pb, 17, s->params[w].average_maxrgb.num * rgb_den /
s->params[w].average_maxrgb.den);
+ put_bits(pb, 4, s->params[w].num_distribution_maxrgb_percentiles);
+ for (int i = 0; i <
s->params[w].num_distribution_maxrgb_percentiles; i++) {
+ put_bits(pb, 7,
s->params[w].distribution_maxrgb[i].percentage);
+ put_bits(pb, 17,
s->params[w].distribution_maxrgb[i].percentile.num * rgb_den /
+ s->params[w].distribution_maxrgb[i].percentile.den);
+ }
+ put_bits(pb, 10, s->params[w].fraction_bright_pixels.num *
fraction_pixel_den /
+ s->params[w].fraction_bright_pixels.den);
+ }
+
+ put_bits(pb, 1, s->mastering_display_actual_peak_luminance_flag);
+ if (s->mastering_display_actual_peak_luminance_flag) {
+ put_bits(pb, 5,
s->num_rows_mastering_display_actual_peak_luminance);
+ put_bits(pb, 5,
s->num_cols_mastering_display_actual_peak_luminance);
+ for (int i = 0; i <
s->num_rows_mastering_display_actual_peak_luminance; i++) {
+ for (int j = 0; j <
s->num_cols_mastering_display_actual_peak_luminance; j++) {
+ put_bits(pb, 4,
s->mastering_display_actual_peak_luminance[i][j].num * peak_luminance_den /
+ s->mastering_display_actual_peak_luminance[i][j].den);
+ }
+ }
+ }
+
+ for (int w = 0; w < s->num_windows; w++) {
+ put_bits(pb, 1, s->params[w].tone_mapping_flag);
+ if (s->params[w].tone_mapping_flag) {
+ put_bits(pb, 12, s->params[w].knee_point_x.num *
knee_point_den / s->params[w].knee_point_x.den);
+ put_bits(pb, 12, s->params[w].knee_point_y.num *
knee_point_den / s->params[w].knee_point_y.den);
+ put_bits(pb, 4, s->params[w].num_bezier_curve_anchors);
+ for (int i = 0; i < s->params[w].num_bezier_curve_anchors;
i++) {
+ put_bits(pb, 10,
s->params[w].bezier_curve_anchors[i].num * bezier_anchor_den /
+ s->params[w].bezier_curve_anchors[i].den);
+ }
+ put_bits(pb, 1, s->params[w].color_saturation_mapping_flag);
+ if (s->params[w].color_saturation_mapping_flag) {
+ put_bits(pb, 6,
s->params[w].color_saturation_weight.num * saturation_weight_den /
+ s->params[w].color_saturation_weight.den);
+ }
+ }
+ }
+
+ flush_put_bits(pb);
+ return buf;
+}
diff --git a/libavutil/hdr_dynamic_metadata.h
b/libavutil/hdr_dynamic_metadata.h
index 1f953ef1f5..f75d3e0739 100644
--- a/libavutil/hdr_dynamic_metadata.h
+++ b/libavutil/hdr_dynamic_metadata.h
@@ -21,6 +21,7 @@
#ifndef AVUTIL_HDR_DYNAMIC_METADATA_H
#define AVUTIL_HDR_DYNAMIC_METADATA_H
+#include "buffer.h"
#include "frame.h"
#include "rational.h"
@@ -351,4 +352,13 @@ AVDynamicHDRPlus
*av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
int size);
+/**
+ * Serialize dynamic HDR10+ metadata to a user data registered ITU-T
T.35 buffer.
+ * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
+ *
+ * @return Pointer to an AVBufferRef containing the raw ITU-T T.35
representation
+ * of the HDR10+ metadata if succeed, or NULL if buffer
allocation fails.
+ */
+AVBufferRef *av_dynamic_hdr_plus_to_t35(AVDynamicHDRPlus *s);
+
#endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
diff --git a/libavutil/version.h b/libavutil/version.h
index 900b798971..7635672985 100644
--- a/libavutil/version.h
+++ b/libavutil/version.h
@@ -79,7 +79,7 @@
*/
#define LIBAVUTIL_VERSION_MAJOR 58
-#define LIBAVUTIL_VERSION_MINOR 3
+#define LIBAVUTIL_VERSION_MINOR 4
#define LIBAVUTIL_VERSION_MICRO 100
#define LIBAVUTIL_VERSION_INT AV_VERSION_INT(LIBAVUTIL_VERSION_MAJOR, \
--
2.39.1
_______________________________________________
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] 21+ messages in thread
end of thread, other threads:[~2023-03-13 22:32 UTC | newest]
Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-02-27 17:34 [FFmpeg-devel] [PATCH 2/2] avutil: add HDR10+ dynamic metadata serialization function Raphaël Zumer
2023-03-02 18:33 ` quietvoid
2023-03-02 18:57 ` Raphaël Zumer
2023-03-02 18:57 ` James Almer
2023-03-02 19:14 ` Raphaël Zumer
-- strict thread matches above, loose matches on Subject: below --
2023-03-02 21:43 Raphaël Zumer
2023-03-09 14:18 ` Raphaël Zumer
2023-03-12 15:21 ` James Almer
2023-03-13 22:25 ` Andreas Rheinhardt
2023-03-13 22:32 ` James Almer
2023-03-12 16:25 ` Zhao Zhili
2023-03-12 19:48 ` Anton Khirnov
2023-03-12 21:50 ` Raphaël Zumer
2023-03-12 21:52 ` James Almer
2023-03-12 21:56 ` Raphaël Zumer
2023-03-13 13:36 ` Anton Khirnov
2023-03-02 19:25 Raphaël Zumer
2023-03-02 20:24 ` Leo Izen
2023-03-02 20:37 ` Derek Buitenhuis
2023-03-02 20:45 ` Raphaël Zumer
[not found] <62782188-8dba-b4f0-6e54-571149f09040@tebako.net>
2023-02-27 16:54 ` Raphaël Zumer
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