This source file includes following definitions.
- read_depth_rep_info_element
 
- read_depth_representation_info
 
- decode_hevc_aux_sei_messages
 
- remove_start_code_emulation
 
- parse_sps_for_hvcC_configuration
 
#include <assert.h>
#include <math.h>
#include "heif_hevc.h"
#include "bitstream.h"
using namespace heif;
static double read_depth_rep_info_element(BitReader& reader)
{
  int sign_flag = reader.get_bits(1);
  int exponent  = reader.get_bits(7);
  int mantissa_len = reader.get_bits(5)+1;
  if (mantissa_len<1 || mantissa_len>32) {
    
  }
  if (exponent==127) {
    
  }
  int mantissa = reader.get_bits(mantissa_len);
  double value;
  
  if (exponent > 0) {
    value = pow(2, exponent-31) * (1.0 + mantissa / pow(2,mantissa_len));
  }
  else {
    value = pow(2, -(30+mantissa_len)) * mantissa;
  }
  if (sign_flag) {
    value = -value;
  }
  return value;
}
static std::shared_ptr<SEIMessage> read_depth_representation_info(BitReader& reader)
{
  auto msg = std::make_shared<SEIMessage_depth_representation_info>();
  
  msg->version = 1;
  msg->disparity_reference_view = 0;
  msg->depth_nonlinear_representation_model_size = 0;
  msg->depth_nonlinear_representation_model = nullptr;
  
  msg->has_z_near = (uint8_t)reader.get_bits(1);
  msg->has_z_far  = (uint8_t)reader.get_bits(1);
  msg->has_d_min  = (uint8_t)reader.get_bits(1);
  msg->has_d_max  = (uint8_t)reader.get_bits(1);
  int rep_type;
  if (!reader.get_uvlc(&rep_type)) {
    
  }
  
  msg->depth_representation_type = (enum heif_depth_representation_type)rep_type;
  
  
  if (msg->has_d_min || msg->has_d_max) {
    int ref_view;
    if (!reader.get_uvlc(&ref_view)) {
      
    }
    msg->disparity_reference_view = ref_view;
    
  }
  if (msg->has_z_near) msg->z_near = read_depth_rep_info_element(reader);
  if (msg->has_z_far ) msg->z_far  = read_depth_rep_info_element(reader);
  if (msg->has_d_min ) msg->d_min  = read_depth_rep_info_element(reader);
  if (msg->has_d_max ) msg->d_max  = read_depth_rep_info_element(reader);
  
  if (msg->depth_representation_type == heif_depth_representation_type_nonuniform_disparity) {
    
  }
  return msg;
}
Error heif::decode_hevc_aux_sei_messages(const std::vector<uint8_t>& data,
                                         std::vector<std::shared_ptr<SEIMessage>>& msgs)
{
  
  
  BitReader reader(data.data(), (int)data.size());
  uint32_t len = (uint32_t)reader.get_bits(32);
  if (len > data.size()-4) {
    
  }
  while (reader.get_current_byte_index() < (int)len) {
    int currPos = reader.get_current_byte_index();
    BitReader sei_reader(data.data() + currPos, (int)data.size()-currPos);
    uint32_t nal_size = (uint32_t)sei_reader.get_bits(32);
    (void)nal_size;
    uint8_t nal_type = (uint8_t)(sei_reader.get_bits(8) >> 1);
    sei_reader.skip_bits(8);
    
    if (nal_type == 39 ||
        nal_type == 40) {
      
      uint8_t payload_id = (uint8_t)(sei_reader.get_bits(8));
      uint8_t payload_size = (uint8_t)(sei_reader.get_bits(8));
      (void)payload_size;
      switch (payload_id) {
      case 177: 
        std::shared_ptr<SEIMessage> sei = read_depth_representation_info(sei_reader);
        msgs.push_back(sei);
        break;
      }
    }
    break; 
  }
  return Error::Ok;
}
static std::vector<uint8_t> remove_start_code_emulation(const uint8_t* sps, size_t size)
{
  std::vector<uint8_t> out_data;
  for (size_t i=0;i<size;i++) {
    if (i+2<size &&
        sps[i  ] == 0 &&
        sps[i+1] == 0 &&
        sps[i+2] == 3) {
      out_data.push_back(0);
      out_data.push_back(0);
      i+=2;
    }
    else {
      out_data.push_back(sps[i]);
    }
  }
  return out_data;
}
Error heif::parse_sps_for_hvcC_configuration(const uint8_t* sps, size_t size,
                                             Box_hvcC::configuration* config,
                                             int* width, int* height)
{
  
  std::vector<uint8_t> sps_no_emul = remove_start_code_emulation(sps, size);
  sps = sps_no_emul.data();
  size = sps_no_emul.size();
  BitReader reader(sps, (int)size);
  
  reader.skip_bits(2*8);
  
  reader.skip_bits(4);
  int nMaxSubLayersMinus1 = reader.get_bits(3);
  config->temporal_id_nested = (uint8_t)reader.get_bits(1);
  
  config->general_profile_space = (uint8_t)reader.get_bits(2);
  config->general_tier_flag = (uint8_t)reader.get_bits(1);
  config->general_profile_idc = (uint8_t)reader.get_bits(5);
  config->general_profile_compatibility_flags = reader.get_bits(32);
  reader.skip_bits(16); 
  reader.skip_bits(16); 
  reader.skip_bits(16); 
  config->general_level_idc = (uint8_t)reader.get_bits(8);
  std::vector<bool> layer_profile_present(nMaxSubLayersMinus1);
  std::vector<bool> layer_level_present(nMaxSubLayersMinus1);
  for (int i=0 ; i<nMaxSubLayersMinus1 ; i++) {
    layer_profile_present[i] = reader.get_bits(1);
    layer_level_present[i] = reader.get_bits(1);
  }
  for (int i=0 ; i<nMaxSubLayersMinus1 ; i++) {
    if (layer_profile_present[i]) {
      reader.skip_bits(2+1+5);
      reader.skip_bits(32);
      reader.skip_bits(16);
    }
    if (layer_level_present[i]) {
      reader.skip_bits(8);
    }
  }
  
  int dummy, value;
  reader.get_uvlc(&dummy); 
  reader.get_uvlc(&value);
  config->chroma_format = (uint8_t)value;
  if (config->chroma_format==3) {
    reader.skip_bits(1);
  }
  reader.get_uvlc(width);
  reader.get_uvlc(height);
  bool conformance_window = reader.get_bits(1);
  if (conformance_window) {
    int left,right,top,bottom;
    reader.get_uvlc(&left);
    reader.get_uvlc(&right);
    reader.get_uvlc(&top);
    reader.get_uvlc(&bottom);
    
    *width -= 2*(left+right);
    *height -= 2*(top+bottom);
  }
  reader.get_uvlc(&value);
  config->bit_depth_luma = (uint8_t)(value + 8);
  reader.get_uvlc(&value);
  config->bit_depth_chroma = (uint8_t)(value + 8);
  
  config->configuration_version = 1;
  config->min_spatial_segmentation_idc = 0; 
  config->parallelism_type = 0; 
  config->avg_frame_rate = 0; 
  config->constant_frame_rate = 0; 
  config->num_temporal_layers = 1; 
  return Error::Ok;
}