Shaka Packager SDK
hevc_decoder_configuration_record.cc
1 // Copyright 2015 Google LLC. All rights reserved.
2 //
3 // Use of this source code is governed by a BSD-style
4 // license that can be found in the LICENSE file or at
5 // https://developers.google.com/open-source/licenses/bsd
6 
7 #include <packager/media/codecs/hevc_decoder_configuration_record.h>
8 
9 #include <absl/log/check.h>
10 #include <absl/strings/escaping.h>
11 #include <absl/strings/str_format.h>
12 #include <absl/strings/str_join.h>
13 
14 #include <packager/media/base/buffer_reader.h>
15 #include <packager/media/base/rcheck.h>
16 #include <packager/media/codecs/h265_parser.h>
17 #include <packager/utils/bytes_to_string_view.h>
18 
19 namespace shaka {
20 namespace media {
21 
22 namespace {
23 
24 // ISO/IEC 14496-15:2014 Annex E.
25 std::string GeneralProfileSpaceAsString(uint8_t general_profile_space) {
26  switch (general_profile_space) {
27  case 0:
28  return "";
29  case 1:
30  return "A";
31  case 2:
32  return "B";
33  case 3:
34  return "C";
35  default:
36  LOG(WARNING) << "Unexpected general_profile_space "
37  << general_profile_space;
38  return "";
39  }
40 }
41 
42 std::string TrimLeadingZeros(const std::string& str) {
43  DCHECK_GT(str.size(), 0u);
44  for (size_t i = 0; i < str.size(); ++i) {
45  if (str[i] == '0') continue;
46  return str.substr(i);
47  }
48  return "0";
49 }
50 
51 // Encode the 32 bits input, but in reverse bit order, i.e. bit [31] as the most
52 // significant bit, followed by, bit [30], and down to bit [0] as the least
53 // significant bit, where bits [i] for i in the range of 0 to 31, inclusive, are
54 // specified in ISO/IEC 23008‐2, encoded in hexadecimal (leading zeroes may be
55 // omitted).
56 std::string ReverseBitsAndHexEncode(uint32_t x) {
57  x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1);
58  x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2);
59  x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4);
60  const uint8_t bytes[] = {static_cast<uint8_t>(x & 0xFF),
61  static_cast<uint8_t>((x >> 8) & 0xFF),
62  static_cast<uint8_t>((x >> 16) & 0xFF),
63  static_cast<uint8_t>((x >> 24) & 0xFF)};
64  return TrimLeadingZeros(absl::BytesToHexString(
65  byte_array_to_string_view(bytes, std::size(bytes))));
66 }
67 
68 } // namespace
69 
70 HEVCDecoderConfigurationRecord::HEVCDecoderConfigurationRecord() = default;
71 
72 HEVCDecoderConfigurationRecord::~HEVCDecoderConfigurationRecord() = default;
73 
74 bool HEVCDecoderConfigurationRecord::ParseInternal() {
75  BufferReader reader(data(), data_size());
76 
77  uint8_t profile_indication = 0;
78  uint8_t length_size_minus_one = 0;
79  uint8_t num_of_arrays = 0;
80  RCHECK(reader.Read1(&version_) && version_ == 1 &&
81  reader.Read1(&profile_indication) &&
82  reader.Read4(&general_profile_compatibility_flags_) &&
83  reader.ReadToVector(&general_constraint_indicator_flags_, 6) &&
84  reader.Read1(&general_level_idc_) &&
85  reader.SkipBytes(8) && // Skip uninterested fields.
86  reader.Read1(&length_size_minus_one) &&
87  reader.Read1(&num_of_arrays));
88 
89  general_profile_space_ = profile_indication >> 6;
90  RCHECK(general_profile_space_ <= 3u);
91  general_tier_flag_ = ((profile_indication >> 5) & 1) == 1;
92  general_profile_idc_ = profile_indication & 0x1f;
93 
94  if ((length_size_minus_one & 0x3) == 2) {
95  LOG(ERROR) << "Invalid NALU length size.";
96  return false;
97  }
98  set_nalu_length_size((length_size_minus_one & 0x3) + 1);
99 
100  for (int i = 0; i < num_of_arrays; i++) {
101  uint8_t nal_unit_type;
102  uint16_t num_nalus;
103  RCHECK(reader.Read1(&nal_unit_type));
104  nal_unit_type &= 0x3f;
105  RCHECK(reader.Read2(&num_nalus));
106  for (int j = 0; j < num_nalus; j++) {
107  uint16_t nalu_length;
108  RCHECK(reader.Read2(&nalu_length));
109  uint64_t nalu_offset = reader.pos();
110  RCHECK(reader.SkipBytes(nalu_length));
111 
112  Nalu nalu;
113  RCHECK(nalu.Initialize(Nalu::kH265, data() + nalu_offset, nalu_length));
114  RCHECK(nalu.type() == nal_unit_type);
115  AddNalu(nalu);
116 
117  if (nalu.type() == Nalu::H265_SPS) {
118  H265Parser parser;
119  int sps_id = 0;
120  RCHECK(parser.ParseSps(nalu, &sps_id) == H265Parser::kOk);
122  parser.GetSps(sps_id)->vui_parameters.transfer_characteristics);
124  parser.GetSps(sps_id)->vui_parameters.color_primaries);
126  parser.GetSps(sps_id)->vui_parameters.matrix_coefficients);
127  }
128  }
129  }
130 
131  // TODO(kqyang): Parse SPS to get resolutions.
132  return true;
133 }
134 
136  FourCC codec_fourcc) const {
137  // ISO/IEC 14496-15:2014 Annex E.
138  std::vector<std::string> fields;
139  fields.push_back(FourCCToString(codec_fourcc));
140  fields.push_back(GeneralProfileSpaceAsString(general_profile_space_) +
141  absl::StrFormat("%d", general_profile_idc_));
142  fields.push_back(
143  ReverseBitsAndHexEncode(general_profile_compatibility_flags_));
144  fields.push_back((general_tier_flag_ ? "H" : "L") +
145  absl::StrFormat("%d", general_level_idc_));
146 
147  // Remove trailing bytes that are zero.
148  std::vector<uint8_t> constraints = general_constraint_indicator_flags_;
149  size_t size = constraints.size();
150  for (; size > 0; --size) {
151  if (constraints[size - 1] != 0) break;
152  }
153  constraints.resize(size);
154  for (uint8_t constraint : constraints)
155  fields.push_back(TrimLeadingZeros(
156  absl::BytesToHexString(byte_array_to_string_view(&constraint, 1))));
157 
158  return absl::StrJoin(fields, ".");
159 }
160 
161 } // namespace media
162 } // namespace shaka
void set_matrix_coefficients(uint8_t matrix_coefficients)
Sets the matrix coeffs.
void AddNalu(const Nalu &nalu)
Adds the given Nalu to the configuration.
void set_color_primaries(uint8_t color_primaries)
Sets the colour primaries.
void set_transfer_characteristics(uint8_t transfer_characteristics)
Sets the transfer characteristics.
void set_nalu_length_size(uint8_t nalu_length_size)
Sets the size of the NAL unit length field.
int type() const
Definition: nalu_reader.h:112
All the methods that are virtual are virtual for mocking.
Definition: crypto_flags.cc:66
std::string_view byte_array_to_string_view(const uint8_t *bytes, size_t bytes_size)
Convert byte array to string_view.