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