1 // Copyright 2021 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 //#define LOG_NDEBUG 0
6 #define LOG_TAG "NalParser"
7
8 #include <v4l2_codec2/common/NalParser.h>
9
10 #include <algorithm>
11
12 #include <media/stagefright/foundation/ABitReader.h>
13 #include <utils/Log.h>
14
15 namespace android {
16
17 namespace {
18
19 enum H264ProfileIDC {
20 kProfileIDCAVLC444 = 44,
21 kProfileIDScalableBaseline = 83,
22 kProfileIDScalableHigh = 86,
23 kProfileIDCHigh = 100,
24 kProfileIDHigh10 = 110,
25 kProfileIDSMultiviewHigh = 118,
26 kProfileIDHigh422 = 122,
27 kProfileIDStereoHigh = 128,
28 kProfileIDHigh444Predictive = 244,
29 };
30
31 constexpr uint32_t kYUV444Idc = 3;
32
33 // Read unsigned int encoded with exponential-golomb.
parseUE(ABitReader * br)34 uint32_t parseUE(ABitReader* br) {
35 uint32_t numZeroes = 0;
36 while (br->getBits(1) == 0) {
37 ++numZeroes;
38 }
39 uint32_t val = br->getBits(numZeroes);
40 return val + (1u << numZeroes) - 1;
41 }
42
43 // Read signed int encoded with exponential-golomb.
parseSE(ABitReader * br)44 int32_t parseSE(ABitReader* br) {
45 uint32_t codeNum = parseUE(br);
46 return (codeNum & 1) ? (codeNum + 1) >> 1 : -static_cast<int32_t>(codeNum >> 1);
47 }
48
49 // Skip a H.264 sequence scaling list in the specified bitstream.
skipScalingList(ABitReader * br,size_t scalingListSize)50 void skipScalingList(ABitReader* br, size_t scalingListSize) {
51 size_t nextScale = 8;
52 size_t lastScale = 8;
53 for (size_t j = 0; j < scalingListSize; ++j) {
54 if (nextScale != 0) {
55 int32_t deltaScale = parseSE(br); // delta_sl
56 if (deltaScale < -128) {
57 ALOGW("delta scale (%d) is below range, capping to -128", deltaScale);
58 deltaScale = -128;
59 } else if (deltaScale > 127) {
60 ALOGW("delta scale (%d) is above range, capping to 127", deltaScale);
61 deltaScale = 127;
62 }
63 nextScale = (lastScale + (deltaScale + 256)) % 256;
64 }
65 lastScale = (nextScale == 0) ? lastScale : nextScale;
66 }
67 }
68
69 // Skip the H.264 sequence scaling matrix in the specified bitstream.
skipScalingMatrix(ABitReader * br,size_t numScalingLists)70 void skipScalingMatrix(ABitReader* br, size_t numScalingLists) {
71 for (size_t i = 0; i < numScalingLists; ++i) {
72 if (br->getBits(1)) { // seq_scaling_list_present_flag
73 if (i < 6) {
74 skipScalingList(br, 16);
75 } else {
76 skipScalingList(br, 64);
77 }
78 }
79 }
80 }
81
82 } // namespace
83
NalParser(const uint8_t * data,size_t length)84 NalParser::NalParser(const uint8_t* data, size_t length)
85 : mCurrNalDataPos(data), mDataEnd(data + length) {
86 mNextNalStartCodePos = findNextStartCodePos();
87 }
88
locateNextNal()89 bool NalParser::locateNextNal() {
90 if (mNextNalStartCodePos == mDataEnd) return false;
91 mCurrNalDataPos = mNextNalStartCodePos + kNalStartCodeLength; // skip start code.
92 mNextNalStartCodePos = findNextStartCodePos();
93 return true;
94 }
95
locateSPS()96 bool NalParser::locateSPS() {
97 while (locateNextNal()) {
98 if (length() == 0) continue;
99 if (type() != kSPSType) continue;
100 return true;
101 }
102
103 return false;
104 }
105
data() const106 const uint8_t* NalParser::data() const {
107 return mCurrNalDataPos;
108 }
109
length() const110 size_t NalParser::length() const {
111 if (mNextNalStartCodePos == mDataEnd) return mDataEnd - mCurrNalDataPos;
112 size_t length = mNextNalStartCodePos - mCurrNalDataPos;
113 // The start code could be 3 or 4 bytes, i.e., 0x000001 or 0x00000001.
114 return *(mNextNalStartCodePos - 1) == 0x00 ? length - 1 : length;
115 }
116
type() const117 uint8_t NalParser::type() const {
118 // First byte is forbidden_zero_bit (1) + nal_ref_idc (2) + nal_unit_type (5)
119 constexpr uint8_t kNALTypeMask = 0x1f;
120 return *mCurrNalDataPos & kNALTypeMask;
121 }
122
findNextStartCodePos() const123 const uint8_t* NalParser::findNextStartCodePos() const {
124 return std::search(mCurrNalDataPos, mDataEnd, kNalStartCode,
125 kNalStartCode + kNalStartCodeLength);
126 }
127
findCodedColorAspects(ColorAspects * colorAspects)128 bool NalParser::findCodedColorAspects(ColorAspects* colorAspects) {
129 ALOG_ASSERT(colorAspects);
130 ALOG_ASSERT(type() == kSPSType);
131
132 // Unfortunately we can't directly jump to the Video Usability Information (VUI) parameters that
133 // contain the color aspects. We need to parse the entire SPS header up until the values we
134 // need.
135
136 // Skip first byte containing type.
137 ABitReader br(mCurrNalDataPos + 1, length() - 1);
138
139 uint32_t profileIDC = br.getBits(8); // profile_idc
140 br.skipBits(16); // constraint flags + reserved bits + level_idc
141 parseUE(&br); // seq_parameter_set_id
142
143 if (profileIDC == kProfileIDCHigh || profileIDC == kProfileIDHigh10 ||
144 profileIDC == kProfileIDHigh422 || profileIDC == kProfileIDHigh444Predictive ||
145 profileIDC == kProfileIDCAVLC444 || profileIDC == kProfileIDScalableBaseline ||
146 profileIDC == kProfileIDScalableHigh || profileIDC == kProfileIDSMultiviewHigh ||
147 profileIDC == kProfileIDStereoHigh) {
148 uint32_t chromaFormatIDC = parseUE(&br);
149 if (chromaFormatIDC == kYUV444Idc) { // chroma_format_idc
150 br.skipBits(1); // separate_colour_plane_flag
151 }
152 parseUE(&br); // bit_depth_luma_minus8
153 parseUE(&br); // bit_depth_chroma_minus8
154 br.skipBits(1); // lossless_qpprime_y_zero_flag
155
156 if (br.getBits(1)) { // seq_scaling_matrix_present_flag
157 const size_t numScalingLists = (chromaFormatIDC != kYUV444Idc) ? 8 : 12;
158 skipScalingMatrix(&br, numScalingLists);
159 }
160 }
161
162 parseUE(&br); // log2_max_frame_num_minus4
163 uint32_t pictureOrderCountType = parseUE(&br); // pic_order_cnt_type
164 if (pictureOrderCountType == 0) {
165 parseUE(&br); // log2_max_pic_order_cnt_lsb_minus4
166 } else if (pictureOrderCountType == 1) {
167 br.skipBits(1); // delta_pic_order_always_zero_flag
168 parseSE(&br); // offset_for_non_ref_pic
169 parseSE(&br); // offset_for_top_to_bottom_field
170 uint32_t numReferenceFrames = parseUE(&br); // num_ref_frames_in_pic_order_cnt_cycle
171 for (uint32_t i = 0; i < numReferenceFrames; ++i) {
172 parseUE(&br); // offset_for_ref_frame
173 }
174 }
175
176 parseUE(&br); // num_ref_frames
177 br.skipBits(1); // gaps_in_frame_num_value_allowed_flag
178 parseUE(&br); // pic_width_in_mbs_minus1
179 parseUE(&br); // pic_height_in_map_units_minus1
180 if (!br.getBits(1)) { // frame_mbs_only_flag
181 br.skipBits(1); // mb_adaptive_frame_field_flag
182 }
183 br.skipBits(1); // direct_8x8_inference_flag
184
185 if (br.getBits(1)) { // frame_cropping_flag
186 parseUE(&br); // frame_cropping_rect_left_offset
187 parseUE(&br); // frame_cropping_rect_right_offset
188 parseUE(&br); // frame_cropping_rect_top_offset
189 parseUE(&br); // frame_cropping_rect_bottom_offset
190 }
191
192 if (br.getBits(1)) { // vui_parameters_present_flag
193 if (br.getBits(1)) { // VUI aspect_ratio_info_present_flag
194 if (br.getBits(8) == 255) { // VUI aspect_ratio_idc == extended sample aspect ratio
195 br.skipBits(32); // VUI sar_width + sar_height
196 }
197 }
198
199 if (br.getBits(1)) { // VUI overscan_info_present_flag
200 br.skipBits(1); // VUI overscan_appropriate_flag
201 }
202 if (br.getBits(1)) { // VUI video_signal_type_present_flag
203 br.skipBits(3); // VUI video_format
204 colorAspects->fullRange = br.getBits(1); // VUI video_full_range_flag
205 if (br.getBits(1)) { // VUI color_description_present_flag
206 colorAspects->primaries = br.getBits(8); // VUI colour_primaries
207 colorAspects->transfer = br.getBits(8); // VUI transfer_characteristics
208 colorAspects->coeffs = br.getBits(8); // VUI matrix_coefficients
209 return !br.overRead();
210 }
211 }
212 }
213
214 return false;
215 }
216
217 } // namespace android
218