Shaka Packager SDK
avc_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/avc_decoder_configuration_record.h>
8 
9 #include <absl/strings/ascii.h>
10 #include <absl/strings/escaping.h>
11 
12 #include <packager/macros/logging.h>
13 #include <packager/media/base/buffer_reader.h>
14 #include <packager/media/base/rcheck.h>
15 #include <packager/media/codecs/h264_parser.h>
16 #include <packager/utils/bytes_to_string_view.h>
17 
18 namespace shaka {
19 namespace media {
20 
21 AVCDecoderConfigurationRecord::AVCDecoderConfigurationRecord() = default;
22 
23 AVCDecoderConfigurationRecord::~AVCDecoderConfigurationRecord() = default;
24 
25 bool AVCDecoderConfigurationRecord::ParseInternal() {
26  // See ISO 14496-15 sec 5.3.3.1.2
27  BufferReader reader(data(), data_size());
28 
29  RCHECK(reader.Read1(&version_) && version_ == 1 &&
30  reader.Read1(&profile_indication_) &&
31  reader.Read1(&profile_compatibility_) && reader.Read1(&avc_level_));
32 
33  uint8_t length_size_minus_one;
34  RCHECK(reader.Read1(&length_size_minus_one));
35  if ((length_size_minus_one & 0x3) == 2) {
36  LOG(ERROR) << "Invalid NALU length size.";
37  return false;
38  }
39  set_nalu_length_size((length_size_minus_one & 0x3) + 1);
40 
41  uint8_t num_sps;
42  RCHECK(reader.Read1(&num_sps));
43  num_sps &= 0x1f;
44  if (num_sps < 1) {
45  VLOG(1) << "No SPS found.";
46  }
47 
48  for (uint8_t i = 0; i < num_sps; i++) {
49  uint16_t size = 0;
50  RCHECK(reader.Read2(&size));
51  const uint8_t* nalu_data = reader.data() + reader.pos();
52  RCHECK(reader.SkipBytes(size));
53 
54  Nalu nalu;
55  RCHECK(nalu.Initialize(Nalu::kH264, nalu_data, size));
56  RCHECK(nalu.type() == Nalu::H264_SPS);
57  AddNalu(nalu);
58 
59  if (i == 0) {
60  // It is unlikely to have more than one SPS in practice. Also there's
61  // no way to change the {coded,pixel}_{width,height} dynamically from
62  // VideoStreamInfo.
63  int sps_id = 0;
64  H264Parser parser;
65  RCHECK(parser.ParseSps(nalu, &sps_id) == H264Parser::kOk);
67  parser.GetSps(sps_id)->transfer_characteristics);
68  RCHECK(ExtractResolutionFromSps(*parser.GetSps(sps_id), &coded_width_,
69  &coded_height_, &pixel_width_,
70  &pixel_height_));
71  }
72  }
73 
74  uint8_t pps_count;
75  RCHECK(reader.Read1(&pps_count));
76  for (uint8_t i = 0; i < pps_count; i++) {
77  uint16_t size = 0;
78  RCHECK(reader.Read2(&size));
79  const uint8_t* nalu_data = reader.data() + reader.pos();
80  RCHECK(reader.SkipBytes(size));
81 
82  Nalu nalu;
83  RCHECK(nalu.Initialize(Nalu::kH264, nalu_data, size));
84  RCHECK(nalu.type() == Nalu::H264_PPS);
85  AddNalu(nalu);
86  }
87 
88  if (profile_indication_ == 100 || profile_indication_ == 110 ||
89  profile_indication_ == 122 || profile_indication_ == 144) {
90 
91  uint8_t sps_ext_count;
92  if (!reader.Read1(&chroma_format_) || !reader.Read1(&bit_depth_luma_minus8_) ||
93  !reader.Read1(&bit_depth_chroma_minus8_) || !reader.Read1(&sps_ext_count)) {
94  LOG(WARNING) << "Insufficient bits in bitstream for given AVC profile";
95  return true;
96  }
97  chroma_format_ &= 0x3;
98  bit_depth_luma_minus8_ &= 0x7;
99  bit_depth_chroma_minus8_ &= 0x7;
100  for (uint8_t i = 0; i < sps_ext_count; i++) {
101  uint16_t size = 0;
102  RCHECK(reader.Read2(&size));
103  const uint8_t* nalu_data = reader.data() + reader.pos();
104  RCHECK(reader.SkipBytes(size));
105 
106  Nalu nalu;
107  RCHECK(nalu.Initialize(Nalu::kH264, nalu_data, size));
108  RCHECK(nalu.type() == Nalu::H264_SPSExtension);
109  AddNalu(nalu);
110  }
111  }
112  return true;
113 }
114 
116  FourCC codec_fourcc) const {
117  return GetCodecString(codec_fourcc, profile_indication_,
118  profile_compatibility_, avc_level_);
119 }
120 
122  FourCC codec_fourcc,
123  uint8_t profile_indication,
124  uint8_t profile_compatibility,
125  uint8_t avc_level) {
126  const uint8_t bytes[] = {profile_indication, profile_compatibility,
127  avc_level};
128  return FourCCToString(codec_fourcc) + "." +
129  absl::AsciiStrToLower(absl::BytesToHexString(
130  byte_array_to_string_view(bytes, std::size(bytes))));
131 }
132 
133 } // namespace media
134 } // namespace shaka
void AddNalu(const Nalu &nalu)
Adds the given Nalu to the configuration.
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.