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