DASH Media Packaging SDK
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator
hevc_decoder_configuration.cc
1 // Copyright 2015 Google Inc. 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/filters/hevc_decoder_configuration.h"
8 
9 #include "packager/base/strings/string_number_conversions.h"
10 #include "packager/base/strings/string_util.h"
11 #include "packager/media/base/buffer_reader.h"
12 #include "packager/media/base/rcheck.h"
13 
14 namespace shaka {
15 namespace media {
16 
17 namespace {
18 
19 // ISO/IEC 14496-15:2014 Annex E.
20 std::string GeneralProfileSpaceAsString(uint8_t general_profile_space) {
21  switch (general_profile_space) {
22  case 0:
23  return "";
24  case 1:
25  return "A";
26  case 2:
27  return "B";
28  case 3:
29  return "C";
30  default:
31  LOG(WARNING) << "Unexpected general_profile_space "
32  << general_profile_space;
33  return "";
34  }
35 }
36 
37 std::string TrimLeadingZeros(const std::string& str) {
38  DCHECK_GT(str.size(), 0u);
39  for (size_t i = 0; i < str.size(); ++i) {
40  if (str[i] == '0') continue;
41  return str.substr(i);
42  }
43  return "0";
44 }
45 
46 // Encode the 32 bits input, but in reverse bit order, i.e. bit [31] as the most
47 // significant bit, followed by, bit [30], and down to bit [0] as the least
48 // significant bit, where bits [i] for i in the range of 0 to 31, inclusive, are
49 // specified in ISO/IEC 23008‐2, encoded in hexadecimal (leading zeroes may be
50 // omitted).
51 std::string ReverseBitsAndHexEncode(uint32_t x) {
52  x = ((x & 0x55555555) << 1) | ((x & 0xAAAAAAAA) >> 1);
53  x = ((x & 0x33333333) << 2) | ((x & 0xCCCCCCCC) >> 2);
54  x = ((x & 0x0F0F0F0F) << 4) | ((x & 0xF0F0F0F0) >> 4);
55  const uint8_t bytes[] = {static_cast<uint8_t>(x & 0xFF),
56  static_cast<uint8_t>((x >> 8) & 0xFF),
57  static_cast<uint8_t>((x >> 16) & 0xFF),
58  static_cast<uint8_t>((x >> 24) & 0xFF)};
59  return TrimLeadingZeros(base::HexEncode(bytes, arraysize(bytes)));
60 }
61 
62 std::string CodecAsString(VideoCodec codec) {
63  switch (codec) {
64  case kCodecHEV1:
65  return "hev1";
66  case kCodecHVC1:
67  return "hvc1";
68  default:
69  LOG(WARNING) << "Unknown codec: " << codec;
70  return std::string();
71  }
72 }
73 
74 } // namespace
75 
76 HEVCDecoderConfiguration::HEVCDecoderConfiguration()
77  : version_(0),
78  general_profile_space_(0),
79  general_tier_flag_(false),
80  general_profile_idc_(0),
81  general_profile_compatibility_flags_(0),
82  general_level_idc_(0) {}
83 
84 HEVCDecoderConfiguration::~HEVCDecoderConfiguration() {}
85 
86 bool HEVCDecoderConfiguration::ParseInternal() {
87  BufferReader reader(data(), data_size());
88 
89  uint8_t profile_indication = 0;
90  uint8_t length_size_minus_one = 0;
91  uint8_t num_of_arrays = 0;
92  RCHECK(reader.Read1(&version_) && version_ == 1 &&
93  reader.Read1(&profile_indication) &&
94  reader.Read4(&general_profile_compatibility_flags_) &&
95  reader.ReadToVector(&general_constraint_indicator_flags_, 6) &&
96  reader.Read1(&general_level_idc_) &&
97  reader.SkipBytes(8) && // Skip uninterested fields.
98  reader.Read1(&length_size_minus_one) &&
99  reader.Read1(&num_of_arrays));
100 
101  general_profile_space_ = profile_indication >> 6;
102  RCHECK(general_profile_space_ <= 3u);
103  general_tier_flag_ = ((profile_indication >> 5) & 1) == 1;
104  general_profile_idc_ = profile_indication & 0x1f;
105 
106  if ((length_size_minus_one & 0x3) == 2) {
107  LOG(ERROR) << "Invalid NALU length size.";
108  return false;
109  }
110  set_nalu_length_size((length_size_minus_one & 0x3) + 1);
111 
112  for (int i = 0; i < num_of_arrays; i++) {
113  uint8_t nal_unit_type;
114  uint16_t num_nalus;
115  RCHECK(reader.Read1(&nal_unit_type));
116  nal_unit_type &= 0x3f;
117  RCHECK(reader.Read2(&num_nalus));
118  for (int j = 0; j < num_nalus; j++) {
119  uint16_t nalu_length;
120  RCHECK(reader.Read2(&nalu_length));
121  uint64_t nalu_offset = reader.pos();
122  RCHECK(reader.SkipBytes(nalu_length));
123 
124  Nalu nalu;
125  RCHECK(nalu.Initialize(Nalu::kH265, data() + nalu_offset, nalu_length));
126  RCHECK(nalu.type() == nal_unit_type);
127  AddNalu(nalu);
128  }
129  }
130 
131  // TODO(kqyang): Parse SPS to get resolutions.
132  return true;
133 }
134 
135 std::string HEVCDecoderConfiguration::GetCodecString(VideoCodec codec) const {
136  // ISO/IEC 14496-15:2014 Annex E.
137  std::vector<std::string> fields;
138  fields.push_back(CodecAsString(codec));
139  fields.push_back(GeneralProfileSpaceAsString(general_profile_space_) +
140  base::IntToString(general_profile_idc_));
141  fields.push_back(
142  ReverseBitsAndHexEncode(general_profile_compatibility_flags_));
143  fields.push_back((general_tier_flag_ ? "H" : "L") +
144  base::IntToString(general_level_idc_));
145 
146  // Remove trailing bytes that are zero.
147  std::vector<uint8_t> constraints = general_constraint_indicator_flags_;
148  size_t size = constraints.size();
149  for (; size > 0; --size) {
150  if (constraints[size - 1] != 0) break;
151  }
152  constraints.resize(size);
153  for (uint8_t constraint : constraints)
154  fields.push_back(TrimLeadingZeros(base::HexEncode(&constraint, 1)));
155 
156  return base::JoinString(fields, ".");
157 }
158 
159 } // namespace media
160 } // namespace shaka
void AddNalu(const Nalu &nalu)
Adds the given Nalu to the configuration.
void set_nalu_length_size(uint8_t nalu_length_size)
Sets the size of the NAL unit length field.
const Nalu & nalu(size_t i) const
std::string GetCodecString(VideoCodec codec) const