text: //----------------------------------------------------------------------------
  //
  // TSDuck - The MPEG Transport Stream Toolkit
  // Copyright (c) 2005-2021, Thierry Lelegard
  // All rights reserved.
  //
  // Redistribution and use in source and binary forms, with or without
  // modification, are permitted provided that the following conditions are met:
  //
  // 1. Redistributions of source code must retain the above copyright notice,
  //    this list of conditions and the following disclaimer.
  // 2. Redistributions in binary form must reproduce the above copyright
  //    notice, this list of conditions and the following disclaimer in the
  //    documentation and/or other materials provided with the distribution.
  //
  // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
  // THE POSSIBILITY OF SUCH DAMAGE.
  //
  //----------------------------------------------------------------------------
  
  #include "tsHEVCVUIParameters.h"
  TSDUCK_SOURCE;
  
  
  //----------------------------------------------------------------------------
  // Constructors.
  //----------------------------------------------------------------------------
  
  ts::HEVCVUIParameters::HEVCVUIParameters(const uint8_t* data, size_t size, size_t sps_max_sub_layers_minus1) :
      SuperClass(),
      aspect_ratio_info_present_flag(0),
      aspect_ratio_idc(0),
      sar_width(0),
      sar_height(0),
      overscan_info_present_flag(0),
      overscan_appropriate_flag(0),
      video_signal_type_present_flag(0),
      video_format(0),
      video_full_range_flag(0),
      colour_description_present_flag(0),
      colour_primaries(0),
      transfer_characteristics(0),
      matrix_coefficients(0),
      chroma_loc_info_present_flag(0),
      chroma_sample_loc_type_top_field(0),
      chroma_sample_loc_type_bottom_field(0),
      neutral_chroma_indication_flag(0),
      field_seq_flag(0),
      frame_field_info_present_flag(0),
      default_display_window_flag(0),
      def_disp_win_left_offset(0),
      def_disp_win_right_offset(0),
      def_disp_win_top_offset(0),
      def_disp_win_bottom_offset(0),
      vui_timing_info_present_flag(0),
      vui_num_units_in_tick(0),
      vui_time_scale(0),
      vui_poc_proportional_to_timing_flag(0),
      vui_num_ticks_poc_diff_one_minus1(0),
      vui_hrd_parameters_present_flag(0),
      hrd_parameters(),
      bitstream_restriction_flag(0),
      tiles_fixed_structure_flag(0),
      motion_vectors_over_pic_boundaries_flag(0),
      restricted_ref_pic_lists_flag(0),
      min_spatial_segmentation_idc(0),
      max_bytes_per_pic_denom(0),
      max_bits_per_min_cu_denom(0),
      log2_max_mv_length_horizontal(0),
      log2_max_mv_length_vertical(0)
  {
      parse(data, size, {uint32_t(sps_max_sub_layers_minus1)});
  }
  
  
  //----------------------------------------------------------------------------
  // Clear all values
  //----------------------------------------------------------------------------
  
  void ts::HEVCVUIParameters::clear()
  {
      SuperClass::clear();
      aspect_ratio_info_present_flag = 0;
      aspect_ratio_idc = 0;
      sar_width = 0;
      sar_height = 0;
      overscan_info_present_flag = 0;
      overscan_appropriate_flag = 0;
      video_signal_type_present_flag = 0;
      video_format = 0;
      video_full_range_flag = 0;
      colour_description_present_flag = 0;
      colour_primaries = 0;
      transfer_characteristics = 0;
      matrix_coefficients = 0;
      chroma_loc_info_present_flag = 0;
      chroma_sample_loc_type_top_field = 0;
      chroma_sample_loc_type_bottom_field = 0;
      neutral_chroma_indication_flag = 0;
      field_seq_flag = 0;
      frame_field_info_present_flag = 0;
      default_display_window_flag = 0;
      def_disp_win_left_offset = 0;
      def_disp_win_right_offset = 0;
      def_disp_win_top_offset = 0;
      def_disp_win_bottom_offset = 0;
      vui_timing_info_present_flag = 0;
      vui_num_units_in_tick = 0;
      vui_time_scale = 0;
      vui_poc_proportional_to_timing_flag = 0;
      vui_num_ticks_poc_diff_one_minus1 = 0;
      vui_hrd_parameters_present_flag = 0;
      hrd_parameters.clear();
      bitstream_restriction_flag = 0;
      tiles_fixed_structure_flag = 0;
      motion_vectors_over_pic_boundaries_flag = 0;
      restricted_ref_pic_lists_flag = 0;
      min_spatial_segmentation_idc = 0;
      max_bytes_per_pic_denom = 0;
      max_bits_per_min_cu_denom = 0;
      log2_max_mv_length_horizontal = 0;
      log2_max_mv_length_vertical = 0;
  }
  
  
  //----------------------------------------------------------------------------
  // Parse a memory area.
  //----------------------------------------------------------------------------
  
  bool ts::HEVCVUIParameters::parse(const uint8_t* data, size_t size, std::initializer_list<uint32_t> params)
  {
      return SuperClass::parse(data, size, params);
  }
  
  bool ts::HEVCVUIParameters::parse(AVCParser& parser, std::initializer_list<uint32_t> params)
  {
      clear();
  
      // The parameter @a sps_max_sub_layers_minus1 must be passed in the initializer list of the parse() methods.
      valid = params.size() >= 1;
      const uint32_t sps_max_sub_layers_minus1 = valid ? *params.begin() : 0;
  
      valid = valid && parser.u(aspect_ratio_info_present_flag, 1);
      if (valid && aspect_ratio_info_present_flag == 1) {
          valid = parser.u(aspect_ratio_idc, 8);
          if (valid && aspect_ratio_idc == 255) {  // EXTENDED_SAR
              valid = valid &&
                      parser.u(sar_width, 16) &&
                      parser.u(sar_height, 16);
          }
      }
  
      valid = valid && parser.u(overscan_info_present_flag, 1);
      if (valid && overscan_info_present_flag == 1) {
          valid = parser.u(overscan_appropriate_flag, 1);
      }
  
      valid = valid && parser.u(video_signal_type_present_flag, 1);
      if (valid && video_signal_type_present_flag == 1) {
          valid = parser.u(video_format, 3) &&
                  parser.u(video_full_range_flag, 1) &&
                  parser.u(colour_description_present_flag, 1);
          if (valid && colour_description_present_flag == 1) {
              valid = parser.u(colour_primaries, 8) &&
                      parser.u(transfer_characteristics, 8) &&
                      parser.u(matrix_coefficients, 8);
          }
      }
  
      valid = valid && parser.u(chroma_loc_info_present_flag, 1);
      if (valid && chroma_loc_info_present_flag == 1) {
          valid = parser.ue(chroma_sample_loc_type_top_field) &&
                  parser.ue(chroma_sample_loc_type_bottom_field);
      }
  
      valid = valid &&
              parser.u(neutral_chroma_indication_flag, 1) &&
              parser.u(field_seq_flag, 1) &&
              parser.u(frame_field_info_present_flag, 1) &&
              parser.u(default_display_window_flag, 1);
  
      if (valid && default_display_window_flag == 1) {
          valid = parser.ue(def_disp_win_left_offset) &&
                  parser.ue(def_disp_win_right_offset) &&
                  parser.ue(def_disp_win_top_offset) &&
                  parser.ue(def_disp_win_bottom_offset);
      }
  
      valid = valid && parser.u(vui_timing_info_present_flag, 1);
      if (valid && vui_timing_info_present_flag == 1) {
          valid = parser.u(vui_num_units_in_tick, 32) &&
                  parser.u(vui_time_scale, 32) &&
                  parser.u(vui_poc_proportional_to_timing_flag, 1);
          if (valid && vui_poc_proportional_to_timing_flag == 1) {
              valid = parser.ue(vui_num_ticks_poc_diff_one_minus1);
          }
          valid = valid && parser.u(vui_hrd_parameters_present_flag, 1);
          if (valid && vui_hrd_parameters_present_flag == 1) {
              hrd_parameters.parse(parser, {1, sps_max_sub_layers_minus1});
          }
      }
  
      valid = valid && parser.u(bitstream_restriction_flag, 1);
      if (valid && bitstream_restriction_flag == 1) {
          valid = parser.u(tiles_fixed_structure_flag, 1) &&
                  parser.u(motion_vectors_over_pic_boundaries_flag, 1) &&
                  parser.u(restricted_ref_pic_lists_flag, 1) &&
                  parser.ue(min_spatial_segmentation_idc) &&
                  parser.ue(max_bytes_per_pic_denom) &&
                  parser.ue(max_bits_per_min_cu_denom) &&
                  parser.ue(log2_max_mv_length_horizontal) &&
                  parser.ue(log2_max_mv_length_vertical);
      }
  
      return valid;
  }
  
  
  //----------------------------------------------------------------------------
  // Display structure content
  //----------------------------------------------------------------------------
  
  std::ostream& ts::HEVCVUIParameters::display(std::ostream& out, const UString& margin) const
  {
  #define DISP(n) disp(out, margin, u ## #n, n)
  
      if (valid) {
          DISP(aspect_ratio_info_present_flag);
          if (aspect_ratio_info_present_flag) {
              DISP(aspect_ratio_idc);
              if (aspect_ratio_idc == 255) {  // EXTENDED_SAR
                  DISP(sar_width);
                  DISP(sar_height);
              }
          }
          DISP(overscan_info_present_flag);
          if (overscan_info_present_flag) {
              DISP(overscan_appropriate_flag);
          }
          DISP(video_signal_type_present_flag);
          if (video_signal_type_present_flag) {
              DISP(video_format);
              DISP(video_full_range_flag);
              DISP(colour_description_present_flag);
              if (colour_description_present_flag) {
                  DISP(colour_primaries);
                  DISP(transfer_characteristics);
                  DISP(matrix_coefficients);
              }
          }
          DISP(chroma_loc_info_present_flag);
          if (chroma_loc_info_present_flag) {
              DISP(chroma_sample_loc_type_top_field);
              DISP(chroma_sample_loc_type_bottom_field);
          }
          DISP(neutral_chroma_indication_flag);
          DISP(field_seq_flag);
          DISP(frame_field_info_present_flag);
          DISP(default_display_window_flag);
          if (default_display_window_flag) {
              DISP(def_disp_win_left_offset);
              DISP(def_disp_win_right_offset);
              DISP(def_disp_win_top_offset);
              DISP(def_disp_win_bottom_offset);
          }
          DISP(vui_timing_info_present_flag);
          if (vui_timing_info_present_flag) {
              DISP(vui_num_units_in_tick);
              DISP(vui_time_scale);
              DISP(vui_poc_proportional_to_timing_flag);
              if (vui_poc_proportional_to_timing_flag) {
                  DISP(vui_num_ticks_poc_diff_one_minus1);
              }
              DISP(vui_hrd_parameters_present_flag);
              if (vui_hrd_parameters_present_flag) {
                  hrd_parameters.display(out, margin + u"hrd.");
              }
          }
          DISP(bitstream_restriction_flag);
          if (bitstream_restriction_flag) {
              DISP(tiles_fixed_structure_flag);
              DISP(motion_vectors_over_pic_boundaries_flag);
              DISP(restricted_ref_pic_lists_flag);
              DISP(min_spatial_segmentation_idc);
              DISP(max_bytes_per_pic_denom);
              DISP(max_bits_per_min_cu_denom);
              DISP(log2_max_mv_length_horizontal);
              DISP(log2_max_mv_length_vertical);
          }
      }
      return out;
  
  #undef DISP
  }
  