diff mbox series

[FFmpeg-devel,1/2] avcodec/avutil: move dynamic HDR metadata parsing to libavutil

Message ID c48f36db-9f22-e8e6-b492-0f2be47fa447@vimeo.com
State New
Headers show
Series [FFmpeg-devel,1/2] avcodec/avutil: move dynamic HDR metadata parsing to libavutil | expand

Checks

Context Check Description
andriy/configure_x86 warning Failed to apply patch
yinshiyou/configure_loongarch64 warning Failed to apply patch

Commit Message

Raphaël Zumer Feb. 27, 2023, 4:53 p.m. UTC
This patch set implements serialization for HDR10+ dynamic metadata 
(AVDynamicHDRPlus), which is the inverse operation of the existing 
ff_parse_itu_t_t35_to_dynamic_hdr10_plus() function. It also moves both 
functions from libavcodec to libavutil and makes them public. For 
consistency, the equivalent vivid HDR parsing function is also migrated, 
but I did not implement serialization for it. Finally, the patch renames 
those functions to av_dynamic_hdr_plus_from_t35() (for parsing) and 
av_dynamic_hdr_plus_to_t35 (for serialization), with the equivalent 
change being made for vivid as well.

The motivation for this change is to allow users to easily convert 
HDR10+ side data (which is parsed into AVDynamicHDRPlus) to a standard 
ITU-T T.35 payload that can be passed directly to applications that 
expect HDR10+ dynamic metadata in that format (e.g. x265 and rav1e 
encoders).

The return value of the serialization function is AVBufferRef*, which I 
expect to be contentious. Payload size is not embedded in the T.35 data, 
so it must be calculated, used to allocate a buffer, and returned along 
with that buffer to the user. As far as I'm aware, AVBufferRef is the 
simplest way to do that, but I will be happy to consider alternative 
solutions.

Please let me know if it is preferred to bump libavutil with the first 
commit, or with both of them, considering there are public API changes 
associated with each one.

Raphaël Zumer

Signed-off-by: Raphaël Zumer <rzumer@tebako.net>
---
  libavcodec/Makefile                    |   3 +-
  libavcodec/dynamic_hdr10_plus.c        | 198 -------------------------
  libavcodec/dynamic_hdr10_plus.h        |  35 -----
  libavcodec/dynamic_hdr_vivid.c         | 139 -----------------
  libavcodec/dynamic_hdr_vivid.h         |  35 -----
  libavcodec/h2645_sei.c                 |  12 +-
  libavutil/hdr_dynamic_metadata.c       | 180 ++++++++++++++++++++++
  libavutil/hdr_dynamic_metadata.h       |  11 ++
  libavutil/hdr_dynamic_vivid_metadata.c | 120 +++++++++++++++
  libavutil/hdr_dynamic_vivid_metadata.h |  11 ++
  10 files changed, 329 insertions(+), 415 deletions(-)
  delete mode 100644 libavcodec/dynamic_hdr10_plus.c
  delete mode 100644 libavcodec/dynamic_hdr10_plus.h
  delete mode 100644 libavcodec/dynamic_hdr_vivid.c
  delete mode 100644 libavcodec/dynamic_hdr_vivid.h

+
  #endif /* AVUTIL_HDR_DYNAMIC_VIVID_METADATA_H */
diff mbox series

Patch

diff --git a/libavcodec/Makefile b/libavcodec/Makefile
index 389253f5d0..4bdfcbab12 100644
--- a/libavcodec/Makefile
+++ b/libavcodec/Makefile
@@ -103,8 +103,7 @@  OBJS-$(CONFIG_H264QPEL)                += h264qpel.o
  OBJS-$(CONFIG_H264_SEI)                += h264_sei.o h2645_sei.o
  OBJS-$(CONFIG_HEVCPARSE)               += hevc_parse.o hevc_ps.o 
hevc_data.o \
                                            h2645data.o h2645_parse.o 
h2645_vui.o
-OBJS-$(CONFIG_HEVC_SEI)                += hevc_sei.o h2645_sei.o \
-                                          dynamic_hdr10_plus.o 
dynamic_hdr_vivid.o
+OBJS-$(CONFIG_HEVC_SEI)                += hevc_sei.o h2645_sei.o
  OBJS-$(CONFIG_HPELDSP)                 += hpeldsp.o
  OBJS-$(CONFIG_HUFFMAN)                 += huffman.o
  OBJS-$(CONFIG_HUFFYUVDSP)              += huffyuvdsp.o
diff --git a/libavcodec/dynamic_hdr10_plus.c 
b/libavcodec/dynamic_hdr10_plus.c
deleted file mode 100644
index 34a44aac65..0000000000
--- a/libavcodec/dynamic_hdr10_plus.c
+++ /dev/null
@@ -1,198 +0,0 @@ 
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
02110-1301 USA
- */
-
-#include "dynamic_hdr10_plus.h"
-#include "get_bits.h"
-
-static const int64_t luminance_den = 1;
-static const int32_t peak_luminance_den = 15;
-static const int64_t rgb_den = 100000;
-static const int32_t fraction_pixel_den = 1000;
-static const int32_t knee_point_den = 4095;
-static const int32_t bezier_anchor_den = 1023;
-static const int32_t saturation_weight_den = 8;
-
-int ff_parse_itu_t_t35_to_dynamic_hdr10_plus(AVDynamicHDRPlus *s, const 
uint8_t *data,
-                                             int size)
-{
-    GetBitContext gbc, *gb = &gbc;
-    int ret;
-
-    if (!s)
-        return AVERROR(ENOMEM);
-
-    ret = init_get_bits8(gb, data, size);
-    if (ret < 0)
-        return ret;
-
-    if (get_bits_left(gb) < 10)
-        return AVERROR_INVALIDDATA;
-
-    s->application_version = get_bits(gb, 8);
-    s->num_windows = get_bits(gb, 2);
-
-    if (s->num_windows < 1 || s->num_windows > 3) {
-        return AVERROR_INVALIDDATA;
-    }
-
-    if (get_bits_left(gb) < ((19 * 8 + 1) * (s->num_windows - 1)))
-        return AVERROR_INVALIDDATA;
-
-    for (int w = 1; w < s->num_windows; w++) {
-        // The corners are set to absolute coordinates here. They should be
-        // converted to the relative coordinates (in [0, 1]) in the 
decoder.
-        AVHDRPlusColorTransformParams *params = &s->params[w];
-        params->window_upper_left_corner_x =
-            (AVRational){get_bits(gb, 16), 1};
-        params->window_upper_left_corner_y =
-            (AVRational){get_bits(gb, 16), 1};
-        params->window_lower_right_corner_x =
-            (AVRational){get_bits(gb, 16), 1};
-        params->window_lower_right_corner_y =
-            (AVRational){get_bits(gb, 16), 1};
-
-        params->center_of_ellipse_x = get_bits(gb, 16);
-        params->center_of_ellipse_y = get_bits(gb, 16);
-        params->rotation_angle = get_bits(gb, 8);
-        params->semimajor_axis_internal_ellipse = get_bits(gb, 16);
-        params->semimajor_axis_external_ellipse = get_bits(gb, 16);
-        params->semiminor_axis_external_ellipse = get_bits(gb, 16);
-        params->overlap_process_option = get_bits1(gb);
-    }
-
-    if (get_bits_left(gb) < 28)
-        return AVERROR_INVALIDDATA;
-
-    s->targeted_system_display_maximum_luminance =
-        (AVRational){get_bits_long(gb, 27), luminance_den};
-    s->targeted_system_display_actual_peak_luminance_flag = get_bits1(gb);
-
-    if (s->targeted_system_display_actual_peak_luminance_flag) {
-        int rows, cols;
-        if (get_bits_left(gb) < 10)
-            return AVERROR_INVALIDDATA;
-        rows = get_bits(gb, 5);
-        cols = get_bits(gb, 5);
-        if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) {
-            return AVERROR_INVALIDDATA;
-        }
-        s->num_rows_targeted_system_display_actual_peak_luminance = rows;
-        s->num_cols_targeted_system_display_actual_peak_luminance = cols;
-
-        if (get_bits_left(gb) < (rows * cols * 4))
-            return AVERROR_INVALIDDATA;
-
-        for (int i = 0; i < rows; i++) {
-            for (int j = 0; j < cols; j++) {
-                s->targeted_system_display_actual_peak_luminance[i][j] =
-                    (AVRational){get_bits(gb, 4), peak_luminance_den};
-            }
-        }
-    }
-    for (int w = 0; w < s->num_windows; w++) {
-        AVHDRPlusColorTransformParams *params = &s->params[w];
-        if (get_bits_left(gb) < (3 * 17 + 17 + 4))
-            return AVERROR_INVALIDDATA;
-
-        for (int i = 0; i < 3; i++) {
-            params->maxscl[i] =
-                (AVRational){get_bits(gb, 17), rgb_den};
-        }
-        params->average_maxrgb =
-            (AVRational){get_bits(gb, 17), rgb_den};
-        params->num_distribution_maxrgb_percentiles = get_bits(gb, 4);
-
-        if (get_bits_left(gb) <
-            (params->num_distribution_maxrgb_percentiles * 24))
-            return AVERROR_INVALIDDATA;
-
-        for (int i = 0; i < 
params->num_distribution_maxrgb_percentiles; i++) {
-            params->distribution_maxrgb[i].percentage = get_bits(gb, 7);
-            params->distribution_maxrgb[i].percentile =
-                (AVRational){get_bits(gb, 17), rgb_den};
-        }
-
-        if (get_bits_left(gb) < 10)
-            return AVERROR_INVALIDDATA;
-
-        params->fraction_bright_pixels = (AVRational){get_bits(gb, 10), 
fraction_pixel_den};
-    }
-    if (get_bits_left(gb) < 1)
-        return AVERROR_INVALIDDATA;
-    s->mastering_display_actual_peak_luminance_flag = get_bits1(gb);
-    if (s->mastering_display_actual_peak_luminance_flag) {
-        int rows, cols;
-        if (get_bits_left(gb) < 10)
-            return AVERROR_INVALIDDATA;
-        rows = get_bits(gb, 5);
-        cols = get_bits(gb, 5);
-        if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) {
-            return AVERROR_INVALIDDATA;
-        }
-        s->num_rows_mastering_display_actual_peak_luminance = rows;
-        s->num_cols_mastering_display_actual_peak_luminance = cols;
-
-        if (get_bits_left(gb) < (rows * cols * 4))
-            return AVERROR_INVALIDDATA;
-
-        for (int i = 0; i < rows; i++) {
-            for (int j = 0; j < cols; j++) {
-                s->mastering_display_actual_peak_luminance[i][j] =
-                    (AVRational){get_bits(gb, 4), peak_luminance_den};
-            }
-        }
-    }
-
-    for (int w = 0; w < s->num_windows; w++) {
-        AVHDRPlusColorTransformParams *params = &s->params[w];
-        if (get_bits_left(gb) < 1)
-            return AVERROR_INVALIDDATA;
-
-        params->tone_mapping_flag = get_bits1(gb);
-        if (params->tone_mapping_flag) {
-            if (get_bits_left(gb) < 28)
-                return AVERROR_INVALIDDATA;
-
-            params->knee_point_x =
-                (AVRational){get_bits(gb, 12), knee_point_den};
-            params->knee_point_y =
-                (AVRational){get_bits(gb, 12), knee_point_den};
-            params->num_bezier_curve_anchors = get_bits(gb, 4);
-
-            if (get_bits_left(gb) < (params->num_bezier_curve_anchors * 
10))
-                return AVERROR_INVALIDDATA;
-
-            for (int i = 0; i < params->num_bezier_curve_anchors; i++) {
-                params->bezier_curve_anchors[i] =
-                    (AVRational){get_bits(gb, 10), bezier_anchor_den};
-            }
-        }
-
-        if (get_bits_left(gb) < 1)
-            return AVERROR_INVALIDDATA;
-        params->color_saturation_mapping_flag = get_bits1(gb);
-        if (params->color_saturation_mapping_flag) {
-            if (get_bits_left(gb) < 6)
-                return AVERROR_INVALIDDATA;
-            params->color_saturation_weight =
-                (AVRational){get_bits(gb, 6), saturation_weight_den};
-        }
-    }
-
-    return 0;
-}
diff --git a/libavcodec/dynamic_hdr10_plus.h 
b/libavcodec/dynamic_hdr10_plus.h
deleted file mode 100644
index cd7acf0432..0000000000
--- a/libavcodec/dynamic_hdr10_plus.h
+++ /dev/null
@@ -1,35 +0,0 @@ 
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
02110-1301 USA
- */
-
-#ifndef AVCODEC_DYNAMIC_HDR10_PLUS_H
-#define AVCODEC_DYNAMIC_HDR10_PLUS_H
-
-#include "libavutil/hdr_dynamic_metadata.h"
-
-/**
- * Parse the user data registered ITU-T T.35 to AVbuffer 
(AVDynamicHDRPlus).
- * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
- * @param data The byte array containing the raw ITU-T T.35 data.
- * @param size Size of the data array in bytes.
- *
- * @return 0 if succeed. Otherwise, returns the appropriate AVERROR.
- */
-int ff_parse_itu_t_t35_to_dynamic_hdr10_plus(AVDynamicHDRPlus *s, const 
uint8_t *data,
-                                             int size);
-
-#endif /* AVCODEC_DYNAMIC_HDR10_PLUS_H */
diff --git a/libavcodec/dynamic_hdr_vivid.c b/libavcodec/dynamic_hdr_vivid.c
deleted file mode 100644
index d689669dec..0000000000
--- a/libavcodec/dynamic_hdr_vivid.c
+++ /dev/null
@@ -1,139 +0,0 @@ 
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
02110-1301 USA
- */
-
-#include "dynamic_hdr_vivid.h"
-#include "get_bits.h"
-
-static const int32_t maxrgb_den = 4095;
-static const int32_t color_saturation_gain_den = 128;
-static const int32_t maximum_luminance_den = 4095;
-static const int32_t base_param_m_p_den = 16383;
-static const int32_t base_param_m_m_den = 10;
-static const int32_t base_param_m_a_den = 1023;
-static const int32_t base_param_m_b_den = 1023;
-static const int32_t base_param_m_n_den = 10;
-static const int32_t base_param_Delta_den = 127;
-
-int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const 
uint8_t *data,
-                                             int size)
-{
-    GetBitContext gbc, *gb = &gbc;
-    int ret;
-
-    if (!s)
-        return AVERROR(ENOMEM);
-
-    ret = init_get_bits8(gb, data, size);
-    if (ret < 0)
-        return ret;
-
-    if (get_bits_left(gb) < 8)
-        return AVERROR_INVALIDDATA;
-
-    s->system_start_code = get_bits(gb, 8);
-    if (s->system_start_code == 0x01) {
-        s->num_windows = 1;
-
-        if (get_bits_left(gb) < 12 * 4 * s->num_windows)
-            return AVERROR_INVALIDDATA;
-        for (int w = 0; w < s->num_windows; w++) {
-            AVHDRVividColorTransformParams *params = &s->params[w];
-
-            params->minimum_maxrgb  = (AVRational){get_bits(gb, 12), 
maxrgb_den};
-            params->average_maxrgb  = (AVRational){get_bits(gb, 12), 
maxrgb_den};
-            params->variance_maxrgb = (AVRational){get_bits(gb, 12), 
maxrgb_den};
-            params->maximum_maxrgb  = (AVRational){get_bits(gb, 12), 
maxrgb_den};
-        }
-
-        if (get_bits_left(gb) < 2 * s->num_windows)
-            return AVERROR_INVALIDDATA;
-        for (int w = 0; w < s->num_windows; w++) {
-            AVHDRVividColorTransformParams *params = &s->params[w];
-
-            params->tone_mapping_mode_flag = get_bits(gb, 1);
-            if (params->tone_mapping_mode_flag) {
-                if (get_bits_left(gb) < 1 )
-                    return AVERROR_INVALIDDATA;
-                params->tone_mapping_param_num = get_bits(gb, 1) + 1;
-                for (int i = 0; i < params->tone_mapping_param_num; i++) {
-                    AVHDRVividColorToneMappingParams *tm_params = 
&params->tm_params[i];
-
-                    if (get_bits_left(gb) < 13)
-                        return AVERROR_INVALIDDATA;
- tm_params->targeted_system_display_maximum_luminance = 
(AVRational){get_bits(gb, 12), maximum_luminance_den};
-                    tm_params->base_enable_flag = get_bits(gb, 1);
-                    if (tm_params->base_enable_flag) {
-                        if (get_bits_left(gb) < (14 + 6 + 10 + 10 + 6 + 
8 + 10))
-                            return AVERROR_INVALIDDATA;
-                        tm_params->base_param_m_p = 
(AVRational){get_bits(gb, 14), base_param_m_p_den};
-                        tm_params->base_param_m_m = 
(AVRational){get_bits(gb,  6), base_param_m_m_den};
-                        tm_params->base_param_m_a = 
(AVRational){get_bits(gb, 10), base_param_m_a_den};
-                        tm_params->base_param_m_b = 
(AVRational){get_bits(gb, 10), base_param_m_b_den};
-                        tm_params->base_param_m_n = 
(AVRational){get_bits(gb,  6), base_param_m_n_den};
-                        tm_params->base_param_k1 = get_bits(gb, 2);
-                        tm_params->base_param_k2 = get_bits(gb, 2);
-                        tm_params->base_param_k3 = get_bits(gb, 4);
-                        tm_params->base_param_Delta_enable_mode = 
get_bits(gb, 3);
-                        if (tm_params->base_param_Delta_enable_mode == 
2 || tm_params->base_param_Delta_enable_mode == 6)
-                            tm_params->base_param_Delta = 
(AVRational){get_bits(gb, 7) * -1, base_param_Delta_den};
-                        else
-                            tm_params->base_param_Delta = 
(AVRational){get_bits(gb, 7), base_param_Delta_den};
-
-                        if (get_bits_left(gb) < 1)
-                            return AVERROR_INVALIDDATA;
-                        tm_params->three_Spline_enable_flag = 
get_bits(gb, 1);
-                        if (tm_params->three_Spline_enable_flag) {
-                            if (get_bits_left(gb) < 1 + 
tm_params->three_Spline_num * (2 + 12 + 28 + 1))
-                                return AVERROR_INVALIDDATA;
-                            tm_params->three_Spline_num = get_bits(gb, 
1) + 1;
-                            for (int j = 0; j < 
tm_params->three_Spline_num; j++) {
-                                tm_params->three_Spline_TH_mode = 
get_bits(gb, 2);
-                                if (tm_params->three_Spline_TH_mode == 
0 || tm_params->three_Spline_TH_mode == 2) {
-                                    if (get_bits_left(gb) < 8)
-                                        return AVERROR_INVALIDDATA;
- tm_params->three_Spline_TH_enable_MB = (AVRational){get_bits(gb, 8), 
255};
-                                }
-                                tm_params->three_Spline_TH_enable = 
(AVRational){get_bits(gb, 12),  4095};
-                                tm_params->three_Spline_TH_Delta1 = 
(AVRational){get_bits(gb, 10),  1023};
-                                tm_params->three_Spline_TH_Delta2 = 
(AVRational){get_bits(gb, 10),  1023};
-                                tm_params->three_Spline_enable_Strength 
= (AVRational){get_bits(gb,  8),  255};
-                            }
-                        } else {
-                            tm_params->three_Spline_num     = 1;
-                            tm_params->three_Spline_TH_mode = 0;
-                        }
-
-                    }
-                }
-            }
-
-            params->color_saturation_mapping_flag = get_bits(gb, 1);
-            if (params->color_saturation_mapping_flag) {
-                if (get_bits_left(gb) < 3 + 
params->color_saturation_num * 8)
-                    return AVERROR_INVALIDDATA;
-
-                params->color_saturation_num = get_bits(gb, 3);
-                for (int i = 0; i < params->color_saturation_num; i++) {
-                    params->color_saturation_gain[i] = 
(AVRational){get_bits(gb, 8), color_saturation_gain_den};
-                }
-            }
-        }
-    }
-
-    return 0;
-}
diff --git a/libavcodec/dynamic_hdr_vivid.h b/libavcodec/dynamic_hdr_vivid.h
deleted file mode 100644
index d521b3d263..0000000000
--- a/libavcodec/dynamic_hdr_vivid.h
+++ /dev/null
@@ -1,35 +0,0 @@ 
-/*
- * This file is part of FFmpeg.
- *
- * FFmpeg is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * FFmpeg is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with FFmpeg; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 
02110-1301 USA
- */
-
-#ifndef AVCODEC_DYNAMIC_HDR_VIVID_H
-#define AVCODEC_DYNAMIC_HDR_VIVID_H
-
-#include "libavutil/hdr_dynamic_vivid_metadata.h"
-
-/**
- * Parse the user data registered ITU-T T.35 to AVbuffer 
(AVDynamicHDRVivid).
- * @param s A pointer containing the decoded AVDynamicHDRVivid structure.
- * @param data The byte array containing the raw ITU-T T.35 data.
- * @param size Size of the data array in bytes.
- *
- * @return 0 if succeed. Otherwise, returns the appropriate AVERROR.
- */
-int ff_parse_itu_t_t35_to_dynamic_hdr_vivid(AVDynamicHDRVivid *s, const 
uint8_t *data,
-                                             int size);
-
-#endif /* AVCODEC_DYNAMIC_HDR_VIVID_H */
diff --git a/libavcodec/h2645_sei.c b/libavcodec/h2645_sei.c
index 6e4a9a1af2..7a96bc6056 100644
--- a/libavcodec/h2645_sei.c
+++ b/libavcodec/h2645_sei.c
@@ -27,14 +27,14 @@ 
   #include "libavutil/ambient_viewing_environment.h"
  #include "libavutil/display.h"
+#include "libavutil/hdr_dynamic_metadata.h"
+#include "libavutil/hdr_dynamic_vivid_metadata.h"
  #include "libavutil/film_grain_params.h"
  #include "libavutil/pixdesc.h"
  #include "libavutil/stereo3d.h"
   #include "atsc_a53.h"
  #include "avcodec.h"
-#include "dynamic_hdr10_plus.h"
-#include "dynamic_hdr_vivid.h"
  #include "get_bits.h"
  #include "golomb.h"
  #include "h2645_sei.h"
@@ -52,8 +52,8 @@  static int 
decode_registered_user_data_dynamic_hdr_plus(HEVCSEIDynamicHDRPlus *s
      if (!metadata)
          return AVERROR(ENOMEM);
  -    err = ff_parse_itu_t_t35_to_dynamic_hdr10_plus(metadata, gb->buffer,
- bytestream2_get_bytes_left(gb));
+    err = av_dynamic_hdr_plus_from_t35(metadata, gb->buffer,
+                                       bytestream2_get_bytes_left(gb));
      if (err < 0) {
          av_free(metadata);
          return err;
@@ -78,8 +78,8 @@  static int 
decode_registered_user_data_dynamic_hdr_vivid(HEVCSEIDynamicHDRVivid
      if (!metadata)
          return AVERROR(ENOMEM);
  -    err = ff_parse_itu_t_t35_to_dynamic_hdr_vivid(metadata,
-                                                  gb->buffer, 
bytestream2_get_bytes_left(gb));
+    err = av_dynamic_hdr_vivid_from_t35(metadata,
+                                        gb->buffer, 
bytestream2_get_bytes_left(gb));
      if (err < 0) {
          av_free(metadata);
          return err;
diff --git a/libavutil/hdr_dynamic_metadata.c 
b/libavutil/hdr_dynamic_metadata.c
index 0fa1ee82de..98f399b032 100644
--- a/libavutil/hdr_dynamic_metadata.c
+++ b/libavutil/hdr_dynamic_metadata.c
@@ -20,6 +20,16 @@ 
   #include "hdr_dynamic_metadata.h"
  #include "mem.h"
+#include "libavcodec/get_bits.h"
+#include "libavcodec/put_bits.h"
+
+static const int64_t luminance_den = 1;
+static const int32_t peak_luminance_den = 15;
+static const int64_t rgb_den = 100000;
+static const int32_t fraction_pixel_den = 1000;
+static const int32_t knee_point_den = 4095;
+static const int32_t bezier_anchor_den = 1023;
+static const int32_t saturation_weight_den = 8;
   AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t *size)
  {
@@ -45,3 +55,173 @@  AVDynamicHDRPlus 
*av_dynamic_hdr_plus_create_side_data(AVFrame *frame)
       return (AVDynamicHDRPlus *)side_data->data;
  }
+
+int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
+                                 int size)
+{
+    GetBitContext gbc, *gb = &gbc;
+    int ret;
+
+    if (!s)
+        return AVERROR(ENOMEM);
+
+    ret = init_get_bits8(gb, data, size);
+    if (ret < 0)
+        return ret;
+
+    if (get_bits_left(gb) < 10)
+        return AVERROR_INVALIDDATA;
+
+    s->application_version = get_bits(gb, 8);
+    s->num_windows = get_bits(gb, 2);
+
+    if (s->num_windows < 1 || s->num_windows > 3) {
+        return AVERROR_INVALIDDATA;
+    }
+
+    if (get_bits_left(gb) < ((19 * 8 + 1) * (s->num_windows - 1)))
+        return AVERROR_INVALIDDATA;
+
+    for (int w = 1; w < s->num_windows; w++) {
+        // The corners are set to absolute coordinates here. They should be
+        // converted to the relative coordinates (in [0, 1]) in the 
decoder.
+        AVHDRPlusColorTransformParams *params = &s->params[w];
+        params->window_upper_left_corner_x =
+            (AVRational){get_bits(gb, 16), 1};
+        params->window_upper_left_corner_y =
+            (AVRational){get_bits(gb, 16), 1};
+        params->window_lower_right_corner_x =
+            (AVRational){get_bits(gb, 16), 1};
+        params->window_lower_right_corner_y =
+            (AVRational){get_bits(gb, 16), 1};
+
+        params->center_of_ellipse_x = get_bits(gb, 16);
+        params->center_of_ellipse_y = get_bits(gb, 16);
+        params->rotation_angle = get_bits(gb, 8);
+        params->semimajor_axis_internal_ellipse = get_bits(gb, 16);
+        params->semimajor_axis_external_ellipse = get_bits(gb, 16);
+        params->semiminor_axis_external_ellipse = get_bits(gb, 16);
+        params->overlap_process_option = get_bits1(gb);
+    }
+
+    if (get_bits_left(gb) < 28)
+        return AVERROR_INVALIDDATA;
+
+    s->targeted_system_display_maximum_luminance =
+        (AVRational){get_bits_long(gb, 27), luminance_den};
+    s->targeted_system_display_actual_peak_luminance_flag = get_bits1(gb);
+
+    if (s->targeted_system_display_actual_peak_luminance_flag) {
+        int rows, cols;
+        if (get_bits_left(gb) < 10)
+            return AVERROR_INVALIDDATA;
+        rows = get_bits(gb, 5);
+        cols = get_bits(gb, 5);
+        if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) {
+            return AVERROR_INVALIDDATA;
+        }
+        s->num_rows_targeted_system_display_actual_peak_luminance = rows;
+        s->num_cols_targeted_system_display_actual_peak_luminance = cols;
+
+        if (get_bits_left(gb) < (rows * cols * 4))
+            return AVERROR_INVALIDDATA;
+
+        for (int i = 0; i < rows; i++) {
+            for (int j = 0; j < cols; j++) {
+                s->targeted_system_display_actual_peak_luminance[i][j] =
+                    (AVRational){get_bits(gb, 4), peak_luminance_den};
+            }
+        }
+    }
+    for (int w = 0; w < s->num_windows; w++) {
+        AVHDRPlusColorTransformParams *params = &s->params[w];
+        if (get_bits_left(gb) < (3 * 17 + 17 + 4))
+            return AVERROR_INVALIDDATA;
+
+        for (int i = 0; i < 3; i++) {
+            params->maxscl[i] =
+                (AVRational){get_bits(gb, 17), rgb_den};
+        }
+        params->average_maxrgb =
+            (AVRational){get_bits(gb, 17), rgb_den};
+        params->num_distribution_maxrgb_percentiles = get_bits(gb, 4);
+
+        if (get_bits_left(gb) <
+            (params->num_distribution_maxrgb_percentiles * 24))
+            return AVERROR_INVALIDDATA;
+
+        for (int i = 0; i < 
params->num_distribution_maxrgb_percentiles; i++) {
+            params->distribution_maxrgb[i].percentage = get_bits(gb, 7);
+            params->distribution_maxrgb[i].percentile =
+                (AVRational){get_bits(gb, 17), rgb_den};
+        }
+
+        if (get_bits_left(gb) < 10)
+            return AVERROR_INVALIDDATA;
+
+        params->fraction_bright_pixels = (AVRational){get_bits(gb, 10), 
fraction_pixel_den};
+    }
+    if (get_bits_left(gb) < 1)
+        return AVERROR_INVALIDDATA;
+    s->mastering_display_actual_peak_luminance_flag = get_bits1(gb);
+    if (s->mastering_display_actual_peak_luminance_flag) {
+        int rows, cols;
+        if (get_bits_left(gb) < 10)
+            return AVERROR_INVALIDDATA;
+        rows = get_bits(gb, 5);
+        cols = get_bits(gb, 5);
+        if (((rows < 2) || (rows > 25)) || ((cols < 2) || (cols > 25))) {
+            return AVERROR_INVALIDDATA;
+        }
+        s->num_rows_mastering_display_actual_peak_luminance = rows;
+        s->num_cols_mastering_display_actual_peak_luminance = cols;
+
+        if (get_bits_left(gb) < (rows * cols * 4))
+            return AVERROR_INVALIDDATA;
+
+        for (int i = 0; i < rows; i++) {
+            for (int j = 0; j < cols; j++) {
+                s->mastering_display_actual_peak_luminance[i][j] =
+                    (AVRational){get_bits(gb, 4), peak_luminance_den};
+            }
+        }
+    }
+
+    for (int w = 0; w < s->num_windows; w++) {
+        AVHDRPlusColorTransformParams *params = &s->params[w];
+        if (get_bits_left(gb) < 1)
+            return AVERROR_INVALIDDATA;
+
+        params->tone_mapping_flag = get_bits1(gb);
+        if (params->tone_mapping_flag) {
+            if (get_bits_left(gb) < 28)
+                return AVERROR_INVALIDDATA;
+
+            params->knee_point_x =
+                (AVRational){get_bits(gb, 12), knee_point_den};
+            params->knee_point_y =
+                (AVRational){get_bits(gb, 12), knee_point_den};
+            params->num_bezier_curve_anchors = get_bits(gb, 4);
+
+            if (get_bits_left(gb) < (params->num_bezier_curve_anchors * 
10))
+                return AVERROR_INVALIDDATA;
+
+            for (int i = 0; i < params->num_bezier_curve_anchors; i++) {
+                params->bezier_curve_anchors[i] =
+                    (AVRational){get_bits(gb, 10), bezier_anchor_den};
+            }
+        }
+
+        if (get_bits_left(gb) < 1)
+            return AVERROR_INVALIDDATA;
+        params->color_saturation_mapping_flag = get_bits1(gb);
+        if (params->color_saturation_mapping_flag) {
+            if (get_bits_left(gb) < 6)
+                return AVERROR_INVALIDDATA;
+            params->color_saturation_weight =
+                (AVRational){get_bits(gb, 6), saturation_weight_den};
+        }
+    }
+
+    return 0;
+}
diff --git a/libavutil/hdr_dynamic_metadata.h 
b/libavutil/hdr_dynamic_metadata.h
index 2d72de56ae..1f953ef1f5 100644
--- a/libavutil/hdr_dynamic_metadata.h
+++ b/libavutil/hdr_dynamic_metadata.h
@@ -340,4 +340,15 @@  AVDynamicHDRPlus *av_dynamic_hdr_plus_alloc(size_t 
*size);
   */
  AVDynamicHDRPlus *av_dynamic_hdr_plus_create_side_data(AVFrame *frame);
  +/**
+ * Parse the user data registered ITU-T T.35 to AVbuffer 
(AVDynamicHDRPlus).
+ * @param s A pointer containing the decoded AVDynamicHDRPlus structure.
+ * @param data The byte array containing the raw ITU-T T.35 data.
+ * @param size Size of the data array in bytes.
+ *
+ * @return 0 if succeed. Otherwise, returns the appropriate AVERROR.
+ */
+int av_dynamic_hdr_plus_from_t35(AVDynamicHDRPlus *s, const uint8_t *data,
+                                 int size);
+
  #endif /* AVUTIL_HDR_DYNAMIC_METADATA_H */
diff --git a/libavutil/hdr_dynamic_vivid_metadata.c 
b/libavutil/hdr_dynamic_vivid_metadata.c
index 32da01f587..1218644123 100644
--- a/libavutil/hdr_dynamic_vivid_metadata.c
+++ b/libavutil/hdr_dynamic_vivid_metadata.c
@@ -20,6 +20,17 @@ 
   #include "hdr_dynamic_vivid_metadata.h"
  #include "mem.h"
+#include "libavcodec/get_bits.h"
+
+static const int32_t maxrgb_den = 4095;
+static const int32_t color_saturation_gain_den = 128;
+static const int32_t maximum_luminance_den = 4095;
+static const int32_t base_param_m_p_den = 16383;
+static const int32_t base_param_m_m_den = 10;
+static const int32_t base_param_m_a_den = 1023;
+static const int32_t base_param_m_b_den = 1023;
+static const int32_t base_param_m_n_den = 10;
+static const int32_t base_param_Delta_den = 127;
   AVDynamicHDRVivid *av_dynamic_hdr_vivid_alloc(size_t *size)
  {
@@ -45,3 +56,112 @@  AVDynamicHDRVivid 
*av_dynamic_hdr_vivid_create_side_data(AVFrame *frame)
       return (AVDynamicHDRVivid *)side_data->data;
  }
+
+int av_dynamic_hdr_vivid_from_t35(AVDynamicHDRVivid *s, const uint8_t 
*data,
+                                  int size)
+{
+    GetBitContext gbc, *gb = &gbc;
+    int ret;
+
+    if (!s)
+        return AVERROR(ENOMEM);
+
+    ret = init_get_bits8(gb, data, size);
+    if (ret < 0)
+        return ret;
+
+    if (get_bits_left(gb) < 8)
+        return AVERROR_INVALIDDATA;
+
+    s->system_start_code = get_bits(gb, 8);
+    if (s->system_start_code == 0x01) {
+        s->num_windows = 1;
+
+        if (get_bits_left(gb) < 12 * 4 * s->num_windows)
+            return AVERROR_INVALIDDATA;
+        for (int w = 0; w < s->num_windows; w++) {
+            AVHDRVividColorTransformParams *params = &s->params[w];
+
+            params->minimum_maxrgb  = (AVRational){get_bits(gb, 12), 
maxrgb_den};
+            params->average_maxrgb  = (AVRational){get_bits(gb, 12), 
maxrgb_den};
+            params->variance_maxrgb = (AVRational){get_bits(gb, 12), 
maxrgb_den};
+            params->maximum_maxrgb  = (AVRational){get_bits(gb, 12), 
maxrgb_den};
+        }
+
+        if (get_bits_left(gb) < 2 * s->num_windows)
+            return AVERROR_INVALIDDATA;
+        for (int w = 0; w < s->num_windows; w++) {
+            AVHDRVividColorTransformParams *params = &s->params[w];
+
+            params->tone_mapping_mode_flag = get_bits(gb, 1);
+            if (params->tone_mapping_mode_flag) {
+                if (get_bits_left(gb) < 1 )
+                    return AVERROR_INVALIDDATA;
+                params->tone_mapping_param_num = get_bits(gb, 1) + 1;
+                for (int i = 0; i < params->tone_mapping_param_num; i++) {
+                    AVHDRVividColorToneMappingParams *tm_params = 
&params->tm_params[i];
+
+                    if (get_bits_left(gb) < 13)
+                        return AVERROR_INVALIDDATA;
+ tm_params->targeted_system_display_maximum_luminance = 
(AVRational){get_bits(gb, 12), maximum_luminance_den};
+                    tm_params->base_enable_flag = get_bits(gb, 1);
+                    if (tm_params->base_enable_flag) {
+                        if (get_bits_left(gb) < (14 + 6 + 10 + 10 + 6 + 
8 + 10))
+                            return AVERROR_INVALIDDATA;
+                        tm_params->base_param_m_p = 
(AVRational){get_bits(gb, 14), base_param_m_p_den};
+                        tm_params->base_param_m_m = 
(AVRational){get_bits(gb,  6), base_param_m_m_den};
+                        tm_params->base_param_m_a = 
(AVRational){get_bits(gb, 10), base_param_m_a_den};
+                        tm_params->base_param_m_b = 
(AVRational){get_bits(gb, 10), base_param_m_b_den};
+                        tm_params->base_param_m_n = 
(AVRational){get_bits(gb,  6), base_param_m_n_den};
+                        tm_params->base_param_k1 = get_bits(gb, 2);
+                        tm_params->base_param_k2 = get_bits(gb, 2);
+                        tm_params->base_param_k3 = get_bits(gb, 4);
+                        tm_params->base_param_Delta_enable_mode = 
get_bits(gb, 3);
+                        if (tm_params->base_param_Delta_enable_mode == 
2 || tm_params->base_param_Delta_enable_mode == 6)
+                            tm_params->base_param_Delta = 
(AVRational){get_bits(gb, 7) * -1, base_param_Delta_den};
+                        else
+                            tm_params->base_param_Delta = 
(AVRational){get_bits(gb, 7), base_param_Delta_den};
+
+                        if (get_bits_left(gb) < 1)
+                            return AVERROR_INVALIDDATA;
+                        tm_params->three_Spline_enable_flag = 
get_bits(gb, 1);
+                        if (tm_params->three_Spline_enable_flag) {
+                            if (get_bits_left(gb) < 1 + 
tm_params->three_Spline_num * (2 + 12 + 28 + 1))
+                                return AVERROR_INVALIDDATA;
+                            tm_params->three_Spline_num = get_bits(gb, 
1) + 1;
+                            for (int j = 0; j < 
tm_params->three_Spline_num; j++) {
+                                tm_params->three_Spline_TH_mode = 
get_bits(gb, 2);
+                                if (tm_params->three_Spline_TH_mode == 
0 || tm_params->three_Spline_TH_mode == 2) {
+                                    if (get_bits_left(gb) < 8)
+                                        return AVERROR_INVALIDDATA;
+ tm_params->three_Spline_TH_enable_MB = (AVRational){get_bits(gb, 8), 
255};
+                                }
+                                tm_params->three_Spline_TH_enable = 
(AVRational){get_bits(gb, 12),  4095};
+                                tm_params->three_Spline_TH_Delta1 = 
(AVRational){get_bits(gb, 10),  1023};
+                                tm_params->three_Spline_TH_Delta2 = 
(AVRational){get_bits(gb, 10),  1023};
+                                tm_params->three_Spline_enable_Strength 
= (AVRational){get_bits(gb,  8),  255};
+                            }
+                        } else {
+                            tm_params->three_Spline_num     = 1;
+                            tm_params->three_Spline_TH_mode = 0;
+                        }
+
+                    }
+                }
+            }
+
+            params->color_saturation_mapping_flag = get_bits(gb, 1);
+            if (params->color_saturation_mapping_flag) {
+                if (get_bits_left(gb) < 3 + 
params->color_saturation_num * 8)
+                    return AVERROR_INVALIDDATA;
+
+                params->color_saturation_num = get_bits(gb, 3);
+                for (int i = 0; i < params->color_saturation_num; i++) {
+                    params->color_saturation_gain[i] = 
(AVRational){get_bits(gb, 8), color_saturation_gain_den};
+                }
+            }
+        }
+    }
+
+    return 0;
+}
diff --git a/libavutil/hdr_dynamic_vivid_metadata.h 
b/libavutil/hdr_dynamic_vivid_metadata.h
index a34f83072c..16a84ce343 100644
--- a/libavutil/hdr_dynamic_vivid_metadata.h
+++ b/libavutil/hdr_dynamic_vivid_metadata.h
@@ -282,4 +282,15 @@  AVDynamicHDRVivid 
*av_dynamic_hdr_vivid_alloc(size_t *size);
   */
  AVDynamicHDRVivid *av_dynamic_hdr_vivid_create_side_data(AVFrame *frame);
  +/**
+ * Parse the user data registered ITU-T T.35 to AVbuffer 
(AVDynamicHDRVivid).
+ * @param s A pointer containing the decoded AVDynamicHDRVivid structure.
+ * @param data The byte array containing the raw ITU-T T.35 data.
+ * @param size Size of the data array in bytes.
+ *
+ * @return 0 if succeed. Otherwise, returns the appropriate AVERROR.
+ */
+int av_dynamic_hdr_vivid_from_t35(AVDynamicHDRVivid *s, const uint8_t 
*data,
+                                  int size);