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