video-hdr: introduce HDR10+ parser
Video can now parse a HDR10+ data structure coming from a SEI message. Part-of: <https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/-/merge_requests/650>
This commit is contained in:
parent
7d6f72e956
commit
a1ed7a8f49
@ -22,9 +22,13 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <gst/base/gstbitreader.h>
|
||||||
|
|
||||||
#include "video-hdr.h"
|
#include "video-hdr.h"
|
||||||
|
|
||||||
|
#define HDR10_PLUS_MAX_BEZIER_CURVE_ANCHORS 9
|
||||||
|
#define HDR10_PLUS_MAX_DIST_MAXRGB_PERCENTILES 9
|
||||||
|
|
||||||
#define N_ELEMENT_MASTERING_DISPLAY_INFO 10
|
#define N_ELEMENT_MASTERING_DISPLAY_INFO 10
|
||||||
#define MASTERING_FORMAT \
|
#define MASTERING_FORMAT \
|
||||||
"%d:%d:" \
|
"%d:%d:" \
|
||||||
@ -496,3 +500,198 @@ gst_buffer_add_video_hdr_meta (GstBuffer * buffer,
|
|||||||
|
|
||||||
return meta;
|
return meta;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CHECK_HDR10PLUS_REMAINING(br, needed) \
|
||||||
|
if (gst_bit_reader_get_remaining (&br) < needed) { \
|
||||||
|
GST_DEBUG ("Not enough bits remaining %d, needed %d", gst_bit_reader_get_remaining (&br), needed); \
|
||||||
|
return FALSE; \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gst_video_hdr_parse_hdr10_plus:
|
||||||
|
* @data: HDR10+ data
|
||||||
|
* @size: size of data
|
||||||
|
* @hdr10_plus: (out): #GstVideoHDR10Plus structure to fill in.
|
||||||
|
*
|
||||||
|
* Parse HDR10+ (SMPTE2094-40) user data and store in @hdr10_plus
|
||||||
|
* For more details, see:
|
||||||
|
* https://www.atsc.org/wp-content/uploads/2018/02/S34-301r2-A341-Amendment-2094-40-1.pdf
|
||||||
|
* and SMPTE ST2094-40
|
||||||
|
*
|
||||||
|
* Returns: %TRUE if @data was successfully parsed to @hdr10_plus
|
||||||
|
*
|
||||||
|
* Since: 1.20
|
||||||
|
*/
|
||||||
|
gboolean
|
||||||
|
gst_video_hdr_parse_hdr10_plus (const guint8 * data, gsize size,
|
||||||
|
GstVideoHDR10Plus * hdr10_plus)
|
||||||
|
{
|
||||||
|
guint16 provider_oriented_code;
|
||||||
|
int w, i, j;
|
||||||
|
GstBitReader br;
|
||||||
|
|
||||||
|
/* there must be at least one byte, and not more than GST_VIDEO_HDR10_PLUS_MAX_BYTES bytes */
|
||||||
|
g_return_val_if_fail (data != NULL, FALSE);
|
||||||
|
|
||||||
|
memset (hdr10_plus, 0, sizeof (GstVideoHDR10Plus));
|
||||||
|
gst_bit_reader_init (&br, data, size);
|
||||||
|
GST_MEMDUMP ("HDR10+", data, size);
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 2 + 8 + 8 + 2);
|
||||||
|
provider_oriented_code = gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
if (provider_oriented_code != 0x0001)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
|
||||||
|
hdr10_plus->application_identifier =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
|
||||||
|
hdr10_plus->application_version =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
|
||||||
|
hdr10_plus->num_windows = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
|
||||||
|
if (hdr10_plus->num_windows != GST_VIDEO_HDR10_PLUS_NUM_WINDOWS)
|
||||||
|
return FALSE;
|
||||||
|
for (w = 0; w < hdr10_plus->num_windows; w++) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br,
|
||||||
|
16 + 16 + 16 + 16 + 16 + 16 + 8 + 16 + 16 + 16 + 1);
|
||||||
|
hdr10_plus->processing_window[w].window_upper_left_corner_x =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].window_upper_left_corner_y =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].window_lower_right_corner_x =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].window_lower_right_corner_y =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].center_of_ellipse_x =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].center_of_ellipse_y =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].rotation_angle =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 8);
|
||||||
|
hdr10_plus->processing_window[w].semimajor_axis_internal_ellipse =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].semimajor_axis_external_ellipse =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].semiminor_axis_external_ellipse =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 16);
|
||||||
|
hdr10_plus->processing_window[w].overlap_process_option =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||||
|
}
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 27 + 1);
|
||||||
|
hdr10_plus->targeted_system_display_maximum_luminance =
|
||||||
|
gst_bit_reader_get_bits_uint32_unchecked (&br, 27);
|
||||||
|
hdr10_plus->targeted_system_display_actual_peak_luminance_flag =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||||
|
if (hdr10_plus->targeted_system_display_actual_peak_luminance_flag) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 5 + 5);
|
||||||
|
hdr10_plus->num_rows_targeted_system_display_actual_peak_luminance =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 5);
|
||||||
|
hdr10_plus->num_cols_targeted_system_display_actual_peak_luminance =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 5);
|
||||||
|
if (hdr10_plus->num_rows_targeted_system_display_actual_peak_luminance >
|
||||||
|
GST_VIDEO_HDR10_PLUS_MAX_TSD_APL)
|
||||||
|
return FALSE;
|
||||||
|
if (hdr10_plus->num_cols_targeted_system_display_actual_peak_luminance >
|
||||||
|
GST_VIDEO_HDR10_PLUS_MAX_TSD_APL)
|
||||||
|
return FALSE;
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br,
|
||||||
|
hdr10_plus->num_rows_targeted_system_display_actual_peak_luminance *
|
||||||
|
hdr10_plus->num_cols_targeted_system_display_actual_peak_luminance * 4);
|
||||||
|
for (i = 0;
|
||||||
|
i < hdr10_plus->num_rows_targeted_system_display_actual_peak_luminance;
|
||||||
|
i++) {
|
||||||
|
for (j = 0;
|
||||||
|
j <
|
||||||
|
hdr10_plus->num_cols_targeted_system_display_actual_peak_luminance;
|
||||||
|
j++)
|
||||||
|
hdr10_plus->targeted_system_display_actual_peak_luminance[i][j] =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 4);
|
||||||
|
}
|
||||||
|
for (w = 0; w < hdr10_plus->num_windows; w++) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, (17 * 3));
|
||||||
|
for (i = 0; i < 3; i++)
|
||||||
|
hdr10_plus->processing_window[w].maxscl[i] =
|
||||||
|
gst_bit_reader_get_bits_uint32_unchecked (&br, 17);
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 17 + 4);
|
||||||
|
hdr10_plus->processing_window[w].average_maxrgb =
|
||||||
|
gst_bit_reader_get_bits_uint32_unchecked (&br, 17);
|
||||||
|
hdr10_plus->processing_window[w].num_distribution_maxrgb_percentiles =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 4);
|
||||||
|
if (hdr10_plus->
|
||||||
|
processing_window[w].num_distribution_maxrgb_percentiles !=
|
||||||
|
HDR10_PLUS_MAX_DIST_MAXRGB_PERCENTILES)
|
||||||
|
return FALSE;
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br,
|
||||||
|
hdr10_plus->processing_window[w].num_distribution_maxrgb_percentiles *
|
||||||
|
(17 + 7));
|
||||||
|
for (i = 0;
|
||||||
|
i <
|
||||||
|
hdr10_plus->processing_window[w].num_distribution_maxrgb_percentiles;
|
||||||
|
i++) {
|
||||||
|
hdr10_plus->processing_window[w].distribution_maxrgb_percentages[i] =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 7);
|
||||||
|
hdr10_plus->processing_window[w].distribution_maxrgb_percentiles[i] =
|
||||||
|
gst_bit_reader_get_bits_uint32_unchecked (&br, 17);
|
||||||
|
}
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 10)
|
||||||
|
hdr10_plus->processing_window[w].fraction_bright_pixels =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 1)
|
||||||
|
hdr10_plus->mastering_display_actual_peak_luminance_flag =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||||
|
if (hdr10_plus->targeted_system_display_actual_peak_luminance_flag) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 5 + 5)
|
||||||
|
hdr10_plus->num_rows_mastering_display_actual_peak_luminance =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 5);
|
||||||
|
hdr10_plus->num_cols_mastering_display_actual_peak_luminance =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 5);
|
||||||
|
if (hdr10_plus->num_rows_mastering_display_actual_peak_luminance >
|
||||||
|
GST_VIDEO_HDR10_PLUS_MAX_MD_APL)
|
||||||
|
return FALSE;
|
||||||
|
if (hdr10_plus->num_cols_mastering_display_actual_peak_luminance >
|
||||||
|
GST_VIDEO_HDR10_PLUS_MAX_MD_APL)
|
||||||
|
return FALSE;
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br,
|
||||||
|
hdr10_plus->num_rows_mastering_display_actual_peak_luminance *
|
||||||
|
hdr10_plus->num_cols_mastering_display_actual_peak_luminance * 4)
|
||||||
|
for (i = 0;
|
||||||
|
i < hdr10_plus->num_rows_mastering_display_actual_peak_luminance; i++) {
|
||||||
|
for (j = 0;
|
||||||
|
j < hdr10_plus->num_cols_mastering_display_actual_peak_luminance; j++)
|
||||||
|
hdr10_plus->mastering_display_actual_peak_luminance[i][j] =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 4);
|
||||||
|
}
|
||||||
|
for (w = 0; w < hdr10_plus->num_windows; w++) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 1)
|
||||||
|
hdr10_plus->processing_window[w].tone_mapping_flag =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||||
|
if (hdr10_plus->processing_window[w].tone_mapping_flag) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 12 + 12 + 4)
|
||||||
|
hdr10_plus->processing_window[w].knee_point_x =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 12);
|
||||||
|
hdr10_plus->processing_window[w].knee_point_y =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 12);
|
||||||
|
hdr10_plus->processing_window[w].num_bezier_curve_anchors =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 4);
|
||||||
|
if (hdr10_plus->processing_window[w].num_bezier_curve_anchors >
|
||||||
|
HDR10_PLUS_MAX_BEZIER_CURVE_ANCHORS)
|
||||||
|
return FALSE;
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br,
|
||||||
|
10 * hdr10_plus->processing_window[w].num_bezier_curve_anchors);
|
||||||
|
for (i = 0;
|
||||||
|
i < hdr10_plus->processing_window[w].num_bezier_curve_anchors; i++)
|
||||||
|
hdr10_plus->processing_window[w].bezier_curve_anchors[i] =
|
||||||
|
gst_bit_reader_get_bits_uint16_unchecked (&br, 10);
|
||||||
|
}
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 1);
|
||||||
|
hdr10_plus->processing_window[w].color_saturation_mapping_flag =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
|
||||||
|
if (hdr10_plus->processing_window[w].color_saturation_mapping_flag) {
|
||||||
|
CHECK_HDR10PLUS_REMAINING (br, 6);
|
||||||
|
hdr10_plus->processing_window[w].color_saturation_weight =
|
||||||
|
gst_bit_reader_get_bits_uint8_unchecked (&br, 6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
@ -44,6 +44,7 @@ typedef enum {
|
|||||||
GST_VIDEO_HDR_FORMAT_DOLBY_VISION,
|
GST_VIDEO_HDR_FORMAT_DOLBY_VISION,
|
||||||
} GstVideoHDRFormat;
|
} GstVideoHDRFormat;
|
||||||
|
|
||||||
|
#define GST_VIDEO_HDR10_PLUS_MAX_BYTES 1024
|
||||||
/* defined in CTA-861-G */
|
/* defined in CTA-861-G */
|
||||||
#define GST_VIDEO_HDR10_PLUS_NUM_WINDOWS 1 /* number of windows, shall be 1. */
|
#define GST_VIDEO_HDR10_PLUS_NUM_WINDOWS 1 /* number of windows, shall be 1. */
|
||||||
#define GST_VIDEO_HDR10_PLUS_MAX_TSD_APL 25 /* targeted_system_display_actual_peak_luminance max value */
|
#define GST_VIDEO_HDR10_PLUS_MAX_TSD_APL 25 /* targeted_system_display_actual_peak_luminance max value */
|
||||||
@ -335,6 +336,10 @@ struct _GstVideoHDR10Plus
|
|||||||
gpointer _gst_reserved[GST_PADDING];
|
gpointer _gst_reserved[GST_PADDING];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
GST_VIDEO_API gboolean
|
||||||
|
gst_video_hdr_parse_hdr10_plus (const guint8 * data, gsize size,
|
||||||
|
GstVideoHDR10Plus * hdr10_plus);
|
||||||
|
|
||||||
G_END_DECLS
|
G_END_DECLS
|
||||||
|
|
||||||
#endif /* __GST_VIDEO_HDR_H__ */
|
#endif /* __GST_VIDEO_HDR_H__ */
|
||||||
|
Loading…
x
Reference in New Issue
Block a user