diff mbox series

[FFmpeg-devel,05/23] avcodec/hevc/sei: add support for 3D Reference Displays Information SEI

Message ID 20240914111036.17164-6-anton@khirnov.net
State New
Headers show
Series [FFmpeg-devel,01/23] compat: drop gcc, suncc, and pthreads stdatomic emulation | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Anton Khirnov Sept. 14, 2024, 10:45 a.m. UTC
From: James Almer <jamrial@gmail.com>

Signed-off-by: James Almer <jamrial@gmail.com>
Signed-off-by: Anton Khirnov <anton@khirnov.net>
---
 libavcodec/hevc/sei.c | 55 +++++++++++++++++++++++++++++++++++++++++++
 libavcodec/hevc/sei.h | 17 +++++++++++++
 2 files changed, 72 insertions(+)
diff mbox series

Patch

diff --git a/libavcodec/hevc/sei.c b/libavcodec/hevc/sei.c
index b55ba71a8d..e11a33773c 100644
--- a/libavcodec/hevc/sei.c
+++ b/libavcodec/hevc/sei.c
@@ -150,6 +150,59 @@  static int decode_nal_sei_timecode(HEVCSEITimeCode *s, GetBitContext *gb)
     return 0;
 }
 
+static int decode_nal_sei_3d_reference_displays_info(HEVCSEITDRDI *s, GetBitContext *gb)
+{
+    s->prec_ref_display_width = get_ue_golomb(gb);
+    if (s->prec_ref_display_width > 31)
+        return AVERROR_INVALIDDATA;
+    s->ref_viewing_distance_flag = get_bits1(gb);
+    if (s->ref_viewing_distance_flag) {
+        s->prec_ref_viewing_dist = get_ue_golomb(gb);
+        if (s->prec_ref_viewing_dist > 31)
+            return AVERROR_INVALIDDATA;
+    }
+    s->num_ref_displays = get_ue_golomb(gb);
+    if (s->num_ref_displays > 31)
+        return AVERROR_INVALIDDATA;
+    s->num_ref_displays += 1;
+
+    for (int i = 0; i < s->num_ref_displays; i++) {
+        int length;
+        s->left_view_id[i] = get_ue_golomb(gb);
+        s->right_view_id[i] = get_ue_golomb(gb);
+        s->exponent_ref_display_width[i] = get_bits(gb, 6);
+        if (s->exponent_ref_display_width[i] > 62)
+            return AVERROR_INVALIDDATA;
+        else if (!s->exponent_ref_display_width[i])
+            length = FFMAX(0, (int)s->prec_ref_display_width - 30);
+        else
+            length = FFMAX(0, (int)s->exponent_ref_display_width[i] +
+                              (int)s->prec_ref_display_width - 31);
+        s->mantissa_ref_display_width[i] = get_bits_long(gb, length);
+        if (s->ref_viewing_distance_flag) {
+            s->exponent_ref_viewing_distance[i] = get_bits(gb, 6);
+            if (s->exponent_ref_viewing_distance[i] > 62)
+                return AVERROR_INVALIDDATA;
+            else if (!s->exponent_ref_viewing_distance[i])
+                length = FFMAX(0, (int)s->prec_ref_viewing_dist - 30);
+            else
+                length = FFMAX(0, (int)s->exponent_ref_viewing_distance[i] +
+                                  (int)s->prec_ref_viewing_dist - 31);
+            s->mantissa_ref_viewing_distance[i] = get_bits_long(gb, length);
+        }
+        s->additional_shift_present_flag[i] = get_bits1(gb);
+        if (s->additional_shift_present_flag[i]) {
+            s->num_sample_shift[i] = get_bits(gb, 10);
+            if (s->num_sample_shift[i] > 1023)
+                return AVERROR_INVALIDDATA;
+            s->num_sample_shift[i] -= 512;
+        }
+    }
+    s->three_dimensional_reference_displays_extension_flag = get_bits1(gb);
+
+    return 0;
+}
+
 static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte,
                                  void *logctx, HEVCSEI *s,
                                  const HEVCParamSets *ps, int type)
@@ -163,6 +216,8 @@  static int decode_nal_sei_prefix(GetBitContext *gb, GetByteContext *gbyte,
         return decode_nal_sei_active_parameter_sets(s, gb, logctx);
     case SEI_TYPE_TIME_CODE:
         return decode_nal_sei_timecode(&s->timecode, gb);
+    case SEI_TYPE_THREE_DIMENSIONAL_REFERENCE_DISPLAYS_INFO:
+        return decode_nal_sei_3d_reference_displays_info(&s->tdrdi, gb);
     default: {
         int ret = ff_h2645_sei_message_decode(&s->common, type, AV_CODEC_ID_HEVC,
                                               gb, gbyte, logctx);
diff --git a/libavcodec/hevc/sei.h b/libavcodec/hevc/sei.h
index c97d22d423..a9d6a52080 100644
--- a/libavcodec/hevc/sei.h
+++ b/libavcodec/hevc/sei.h
@@ -79,12 +79,29 @@  typedef struct HEVCSEITimeCode {
     int32_t  time_offset_value[3];
 } HEVCSEITimeCode;
 
+typedef struct HEVCSEITDRDI {
+    uint8_t prec_ref_display_width;
+    uint8_t ref_viewing_distance_flag;
+    uint8_t prec_ref_viewing_dist;
+    uint8_t num_ref_displays;
+    uint16_t left_view_id[31];
+    uint16_t right_view_id[31];
+    uint8_t exponent_ref_display_width[31];
+    uint8_t mantissa_ref_display_width[31];
+    uint8_t exponent_ref_viewing_distance[31];
+    uint8_t mantissa_ref_viewing_distance[31];
+    uint8_t additional_shift_present_flag[31];
+    int16_t num_sample_shift[31];
+    uint8_t three_dimensional_reference_displays_extension_flag;
+} HEVCSEITDRDI;
+
 typedef struct HEVCSEI {
     H2645SEI common;
     HEVCSEIPictureHash picture_hash;
     HEVCSEIPictureTiming picture_timing;
     int active_seq_parameter_set_id;
     HEVCSEITimeCode timecode;
+    HEVCSEITDRDI tdrdi;
 } HEVCSEI;
 
 struct HEVCParamSets;