1*0ec5a0ecSAndroid Build Coastguard Worker // Copyright 2022 The Chromium Authors. All rights reserved.
2*0ec5a0ecSAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*0ec5a0ecSAndroid Build Coastguard Worker // found in the LICENSE file.
4*0ec5a0ecSAndroid Build Coastguard Worker
5*0ec5a0ecSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
6*0ec5a0ecSAndroid Build Coastguard Worker #define LOG_TAG "NalParser"
7*0ec5a0ecSAndroid Build Coastguard Worker
8*0ec5a0ecSAndroid Build Coastguard Worker #include <v4l2_codec2/common/HEVCNalParser.h>
9*0ec5a0ecSAndroid Build Coastguard Worker
10*0ec5a0ecSAndroid Build Coastguard Worker #include <algorithm>
11*0ec5a0ecSAndroid Build Coastguard Worker
12*0ec5a0ecSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ABitReader.h>
13*0ec5a0ecSAndroid Build Coastguard Worker #include <utils/Log.h>
14*0ec5a0ecSAndroid Build Coastguard Worker
15*0ec5a0ecSAndroid Build Coastguard Worker namespace android {
16*0ec5a0ecSAndroid Build Coastguard Worker
17*0ec5a0ecSAndroid Build Coastguard Worker namespace {
18*0ec5a0ecSAndroid Build Coastguard Worker
19*0ec5a0ecSAndroid Build Coastguard Worker constexpr uint32_t kMaxShortTermRefPicSets = 64;
20*0ec5a0ecSAndroid Build Coastguard Worker
21*0ec5a0ecSAndroid Build Coastguard Worker struct StRefPicSet {
22*0ec5a0ecSAndroid Build Coastguard Worker // Syntax elements.
23*0ec5a0ecSAndroid Build Coastguard Worker int numNegativePics;
24*0ec5a0ecSAndroid Build Coastguard Worker int numPositivePics;
25*0ec5a0ecSAndroid Build Coastguard Worker int deltaPocS0[kMaxShortTermRefPicSets];
26*0ec5a0ecSAndroid Build Coastguard Worker int deltaPocS1[kMaxShortTermRefPicSets];
27*0ec5a0ecSAndroid Build Coastguard Worker
28*0ec5a0ecSAndroid Build Coastguard Worker // Calculated fields.
29*0ec5a0ecSAndroid Build Coastguard Worker int numDeltaPocs;
30*0ec5a0ecSAndroid Build Coastguard Worker };
31*0ec5a0ecSAndroid Build Coastguard Worker
32*0ec5a0ecSAndroid Build Coastguard Worker // Skip an HEVC ProfileTierLevel in the specified bitstream.
skipProfileTierLevel(ABitReader * br,uint32_t spsMaxSublayersMinus1)33*0ec5a0ecSAndroid Build Coastguard Worker bool skipProfileTierLevel(ABitReader* br, uint32_t spsMaxSublayersMinus1) {
34*0ec5a0ecSAndroid Build Coastguard Worker // general_profile_space(2), general_tier_flag(1), general_profile_idc(5),
35*0ec5a0ecSAndroid Build Coastguard Worker // general_profile_compatibility_flag(32), general_progressive_source_flag(1),
36*0ec5a0ecSAndroid Build Coastguard Worker // general_interlaced_source_flag(1), general_non_packed_constraint_flag(1),
37*0ec5a0ecSAndroid Build Coastguard Worker // general_frame_only_constraint_flag(1), compatibility_flags(43), general_inbld_flag(1),
38*0ec5a0ecSAndroid Build Coastguard Worker // general_level_idc(8)
39*0ec5a0ecSAndroid Build Coastguard Worker br->skipBits(96);
40*0ec5a0ecSAndroid Build Coastguard Worker if (spsMaxSublayersMinus1 > 6) return false;
41*0ec5a0ecSAndroid Build Coastguard Worker uint32_t subLayerProfilePresentFlag[6];
42*0ec5a0ecSAndroid Build Coastguard Worker uint32_t subLayerLevelPresentFlag[6];
43*0ec5a0ecSAndroid Build Coastguard Worker for (uint32_t i = 0; i < spsMaxSublayersMinus1; ++i) {
44*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &subLayerProfilePresentFlag[i])) return false;
45*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &subLayerLevelPresentFlag[i])) return false;
46*0ec5a0ecSAndroid Build Coastguard Worker }
47*0ec5a0ecSAndroid Build Coastguard Worker if (spsMaxSublayersMinus1 > 0) {
48*0ec5a0ecSAndroid Build Coastguard Worker br->skipBits(2 * (8 - spsMaxSublayersMinus1));
49*0ec5a0ecSAndroid Build Coastguard Worker }
50*0ec5a0ecSAndroid Build Coastguard Worker for (uint32_t i = 0; i < spsMaxSublayersMinus1; ++i) {
51*0ec5a0ecSAndroid Build Coastguard Worker if (subLayerProfilePresentFlag[i]) {
52*0ec5a0ecSAndroid Build Coastguard Worker // sub_layer_profile_space(2), sub_layer_tier_flag(1), sub_layer_profile_idc(5),
53*0ec5a0ecSAndroid Build Coastguard Worker // sub_layer_profile_compatibility_flag(32), sub_layer_progressive_source_flag(1),
54*0ec5a0ecSAndroid Build Coastguard Worker // sub_layer_interlaced_source_flag(1), sub_layer_non_packed_constraint_flag(1),
55*0ec5a0ecSAndroid Build Coastguard Worker // sub_layer_frame_only_constraint_flag(1), compatibility_flags(43),
56*0ec5a0ecSAndroid Build Coastguard Worker // sub_layer_inbld_flag(1)
57*0ec5a0ecSAndroid Build Coastguard Worker br->skipBits(88);
58*0ec5a0ecSAndroid Build Coastguard Worker }
59*0ec5a0ecSAndroid Build Coastguard Worker if (subLayerLevelPresentFlag[i]) {
60*0ec5a0ecSAndroid Build Coastguard Worker br->skipBits(8); // sub_layer_level_idc
61*0ec5a0ecSAndroid Build Coastguard Worker }
62*0ec5a0ecSAndroid Build Coastguard Worker }
63*0ec5a0ecSAndroid Build Coastguard Worker return true;
64*0ec5a0ecSAndroid Build Coastguard Worker }
65*0ec5a0ecSAndroid Build Coastguard Worker
66*0ec5a0ecSAndroid Build Coastguard Worker // Skip an HEVC ScalingListData in the specified bitstream.
skipScalingListData(ABitReader * br)67*0ec5a0ecSAndroid Build Coastguard Worker bool skipScalingListData(ABitReader* br) {
68*0ec5a0ecSAndroid Build Coastguard Worker for (int sizeId = 0; sizeId < 4; ++sizeId) {
69*0ec5a0ecSAndroid Build Coastguard Worker for (int matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
70*0ec5a0ecSAndroid Build Coastguard Worker uint32_t scalingListPredModeFlag;
71*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &scalingListPredModeFlag)) return false;
72*0ec5a0ecSAndroid Build Coastguard Worker if (!scalingListPredModeFlag) {
73*0ec5a0ecSAndroid Build Coastguard Worker uint32_t unused;
74*0ec5a0ecSAndroid Build Coastguard Worker NalParser::parseUE(br, &unused); // scaling_list_pred_matrix_id_delta
75*0ec5a0ecSAndroid Build Coastguard Worker } else {
76*0ec5a0ecSAndroid Build Coastguard Worker int32_t unused;
77*0ec5a0ecSAndroid Build Coastguard Worker if (sizeId > 1)
78*0ec5a0ecSAndroid Build Coastguard Worker NalParser::parseSE(br, &unused); // scaling_list_dc_coef_16x16 or 32x32
79*0ec5a0ecSAndroid Build Coastguard Worker int coefNum = std::min(64, (1 << (4 + (sizeId << 1))));
80*0ec5a0ecSAndroid Build Coastguard Worker for (int i = 0; i < coefNum; ++i)
81*0ec5a0ecSAndroid Build Coastguard Worker NalParser::parseSE(br, &unused); // scaling_list_delta_coef
82*0ec5a0ecSAndroid Build Coastguard Worker }
83*0ec5a0ecSAndroid Build Coastguard Worker }
84*0ec5a0ecSAndroid Build Coastguard Worker }
85*0ec5a0ecSAndroid Build Coastguard Worker return true;
86*0ec5a0ecSAndroid Build Coastguard Worker }
87*0ec5a0ecSAndroid Build Coastguard Worker
88*0ec5a0ecSAndroid Build Coastguard Worker // Skip an HEVC StRefPicSet in the specified bitstream.
skipStRefPicSet(ABitReader * br,uint32_t stRpsIdx,uint32_t numShortTermRefPicSets,StRefPicSet * allRefPicSets,StRefPicSet * currRefPicSet)89*0ec5a0ecSAndroid Build Coastguard Worker bool skipStRefPicSet(ABitReader* br, uint32_t stRpsIdx, uint32_t numShortTermRefPicSets,
90*0ec5a0ecSAndroid Build Coastguard Worker StRefPicSet* allRefPicSets, StRefPicSet* currRefPicSet) {
91*0ec5a0ecSAndroid Build Coastguard Worker uint32_t interRefPicSetPredictionFlag = 0;
92*0ec5a0ecSAndroid Build Coastguard Worker if (stRpsIdx != 0) {
93*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &interRefPicSetPredictionFlag)) return false;
94*0ec5a0ecSAndroid Build Coastguard Worker }
95*0ec5a0ecSAndroid Build Coastguard Worker if (interRefPicSetPredictionFlag) {
96*0ec5a0ecSAndroid Build Coastguard Worker uint32_t deltaIdxMinus1 = 0;
97*0ec5a0ecSAndroid Build Coastguard Worker if (stRpsIdx == numShortTermRefPicSets) {
98*0ec5a0ecSAndroid Build Coastguard Worker if (!NalParser::parseUE(br, &deltaIdxMinus1)) return false;
99*0ec5a0ecSAndroid Build Coastguard Worker if (deltaIdxMinus1 + 1 > stRpsIdx) {
100*0ec5a0ecSAndroid Build Coastguard Worker ALOGW("deltaIdxMinus1 is out of range");
101*0ec5a0ecSAndroid Build Coastguard Worker return false;
102*0ec5a0ecSAndroid Build Coastguard Worker }
103*0ec5a0ecSAndroid Build Coastguard Worker }
104*0ec5a0ecSAndroid Build Coastguard Worker int refRpsIdx = stRpsIdx - (static_cast<int>(deltaIdxMinus1) + 1);
105*0ec5a0ecSAndroid Build Coastguard Worker uint32_t deltaRpsSign;
106*0ec5a0ecSAndroid Build Coastguard Worker uint32_t absDeltaRpsMinus1;
107*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &deltaRpsSign)) return false;
108*0ec5a0ecSAndroid Build Coastguard Worker if (!NalParser::parseUE(br, &absDeltaRpsMinus1)) return false;
109*0ec5a0ecSAndroid Build Coastguard Worker int deltaRps = (1 - 2 * static_cast<int>(deltaRpsSign)) *
110*0ec5a0ecSAndroid Build Coastguard Worker (static_cast<int>(absDeltaRpsMinus1) + 1);
111*0ec5a0ecSAndroid Build Coastguard Worker const StRefPicSet& refSet = allRefPicSets[refRpsIdx];
112*0ec5a0ecSAndroid Build Coastguard Worker uint32_t useDeltaFlag[kMaxShortTermRefPicSets];
113*0ec5a0ecSAndroid Build Coastguard Worker // useDeltaFlag defaults to 1 if not present.
114*0ec5a0ecSAndroid Build Coastguard Worker std::fill_n(useDeltaFlag, kMaxShortTermRefPicSets, 1);
115*0ec5a0ecSAndroid Build Coastguard Worker
116*0ec5a0ecSAndroid Build Coastguard Worker for (int j = 0; j <= refSet.numDeltaPocs; j++) {
117*0ec5a0ecSAndroid Build Coastguard Worker uint32_t usedByCurrPicFlag;
118*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &usedByCurrPicFlag)) return false;
119*0ec5a0ecSAndroid Build Coastguard Worker if (!usedByCurrPicFlag)
120*0ec5a0ecSAndroid Build Coastguard Worker if (!br->getBitsGraceful(1, &useDeltaFlag[j])) return false;
121*0ec5a0ecSAndroid Build Coastguard Worker }
122*0ec5a0ecSAndroid Build Coastguard Worker int i = 0;
123*0ec5a0ecSAndroid Build Coastguard Worker for (int j = refSet.numPositivePics - 1; j >= 0; --j) {
124*0ec5a0ecSAndroid Build Coastguard Worker int dPoc = refSet.deltaPocS1[j] + deltaRps;
125*0ec5a0ecSAndroid Build Coastguard Worker if (dPoc < 0 && useDeltaFlag[refSet.numNegativePics + j])
126*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS0[i++] = dPoc;
127*0ec5a0ecSAndroid Build Coastguard Worker }
128*0ec5a0ecSAndroid Build Coastguard Worker if (deltaRps < 0 && useDeltaFlag[refSet.numDeltaPocs]) {
129*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS0[i++] = deltaRps;
130*0ec5a0ecSAndroid Build Coastguard Worker }
131*0ec5a0ecSAndroid Build Coastguard Worker for (int j = 0; j < refSet.numNegativePics; ++j) {
132*0ec5a0ecSAndroid Build Coastguard Worker int dPoc = refSet.deltaPocS0[j] + deltaRps;
133*0ec5a0ecSAndroid Build Coastguard Worker if (dPoc < 0 && useDeltaFlag[j]) currRefPicSet->deltaPocS0[i++] = dPoc;
134*0ec5a0ecSAndroid Build Coastguard Worker }
135*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->numNegativePics = i;
136*0ec5a0ecSAndroid Build Coastguard Worker i = 0;
137*0ec5a0ecSAndroid Build Coastguard Worker for (int j = refSet.numNegativePics - 1; j >= 0; --j) {
138*0ec5a0ecSAndroid Build Coastguard Worker int dPoc = refSet.deltaPocS0[j] + deltaRps;
139*0ec5a0ecSAndroid Build Coastguard Worker if (dPoc > 0 && useDeltaFlag[j]) currRefPicSet->deltaPocS1[i++] = dPoc;
140*0ec5a0ecSAndroid Build Coastguard Worker }
141*0ec5a0ecSAndroid Build Coastguard Worker if (deltaRps > 0 && useDeltaFlag[refSet.numDeltaPocs])
142*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS1[i++] = deltaRps;
143*0ec5a0ecSAndroid Build Coastguard Worker for (int j = 0; j < refSet.numPositivePics; ++j) {
144*0ec5a0ecSAndroid Build Coastguard Worker int dPoc = refSet.deltaPocS1[j] + deltaRps;
145*0ec5a0ecSAndroid Build Coastguard Worker if (dPoc > 0 && useDeltaFlag[refSet.numNegativePics + j])
146*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS1[i++] = dPoc;
147*0ec5a0ecSAndroid Build Coastguard Worker }
148*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->numPositivePics = i;
149*0ec5a0ecSAndroid Build Coastguard Worker } else {
150*0ec5a0ecSAndroid Build Coastguard Worker uint32_t uintForRead;
151*0ec5a0ecSAndroid Build Coastguard Worker if (!NalParser::parseUE(br, &uintForRead)) return false;
152*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->numNegativePics = static_cast<int>(uintForRead);
153*0ec5a0ecSAndroid Build Coastguard Worker if (!NalParser::parseUE(br, &uintForRead)) return false;
154*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->numPositivePics = static_cast<int>(uintForRead);
155*0ec5a0ecSAndroid Build Coastguard Worker if (currRefPicSet->numNegativePics > kMaxShortTermRefPicSets ||
156*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->numPositivePics > kMaxShortTermRefPicSets) {
157*0ec5a0ecSAndroid Build Coastguard Worker ALOGW("num_negative_pics or num_positive_pics is out of range");
158*0ec5a0ecSAndroid Build Coastguard Worker return false;
159*0ec5a0ecSAndroid Build Coastguard Worker }
160*0ec5a0ecSAndroid Build Coastguard Worker for (int i = 0; i < currRefPicSet->numNegativePics; ++i) {
161*0ec5a0ecSAndroid Build Coastguard Worker uint32_t deltaPocS0Minus1;
162*0ec5a0ecSAndroid Build Coastguard Worker if (!NalParser::parseUE(br, &deltaPocS0Minus1)) return false;
163*0ec5a0ecSAndroid Build Coastguard Worker if (i == 0) {
164*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS0[i] = -(static_cast<int>(deltaPocS0Minus1) + 1);
165*0ec5a0ecSAndroid Build Coastguard Worker } else {
166*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS0[i] =
167*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS0[i - 1] - (static_cast<int>(deltaPocS0Minus1) + 1);
168*0ec5a0ecSAndroid Build Coastguard Worker }
169*0ec5a0ecSAndroid Build Coastguard Worker br->skipBits(1); // used_by_curr_pic_s0
170*0ec5a0ecSAndroid Build Coastguard Worker }
171*0ec5a0ecSAndroid Build Coastguard Worker for (int i = 0; i < currRefPicSet->numPositivePics; ++i) {
172*0ec5a0ecSAndroid Build Coastguard Worker uint32_t deltaPocS1Minus1;
173*0ec5a0ecSAndroid Build Coastguard Worker if (!NalParser::parseUE(br, &deltaPocS1Minus1)) return false;
174*0ec5a0ecSAndroid Build Coastguard Worker if (i == 0) {
175*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS1[i] = static_cast<int>(deltaPocS1Minus1) + 1;
176*0ec5a0ecSAndroid Build Coastguard Worker } else {
177*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS1[i] =
178*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->deltaPocS1[i - 1] + static_cast<int>(deltaPocS1Minus1) + 1;
179*0ec5a0ecSAndroid Build Coastguard Worker }
180*0ec5a0ecSAndroid Build Coastguard Worker br->skipBits(1); // used_by_curr_pic_s1
181*0ec5a0ecSAndroid Build Coastguard Worker }
182*0ec5a0ecSAndroid Build Coastguard Worker }
183*0ec5a0ecSAndroid Build Coastguard Worker currRefPicSet->numDeltaPocs = currRefPicSet->numNegativePics + currRefPicSet->numPositivePics;
184*0ec5a0ecSAndroid Build Coastguard Worker if (currRefPicSet->numDeltaPocs > kMaxShortTermRefPicSets) {
185*0ec5a0ecSAndroid Build Coastguard Worker ALOGW("numDeltaPocs is out of range");
186*0ec5a0ecSAndroid Build Coastguard Worker return false;
187*0ec5a0ecSAndroid Build Coastguard Worker }
188*0ec5a0ecSAndroid Build Coastguard Worker return true;
189*0ec5a0ecSAndroid Build Coastguard Worker }
190*0ec5a0ecSAndroid Build Coastguard Worker
191*0ec5a0ecSAndroid Build Coastguard Worker } // namespace
192*0ec5a0ecSAndroid Build Coastguard Worker
HEVCNalParser(const uint8_t * data,size_t length)193*0ec5a0ecSAndroid Build Coastguard Worker HEVCNalParser::HEVCNalParser(const uint8_t* data, size_t length) : NalParser(data, length) {}
194*0ec5a0ecSAndroid Build Coastguard Worker
locateSPS()195*0ec5a0ecSAndroid Build Coastguard Worker bool HEVCNalParser::locateSPS() {
196*0ec5a0ecSAndroid Build Coastguard Worker while (locateNextNal()) {
197*0ec5a0ecSAndroid Build Coastguard Worker if (length() == 0) continue;
198*0ec5a0ecSAndroid Build Coastguard Worker if (type() != kSPSType) continue;
199*0ec5a0ecSAndroid Build Coastguard Worker return true;
200*0ec5a0ecSAndroid Build Coastguard Worker }
201*0ec5a0ecSAndroid Build Coastguard Worker
202*0ec5a0ecSAndroid Build Coastguard Worker return false;
203*0ec5a0ecSAndroid Build Coastguard Worker }
204*0ec5a0ecSAndroid Build Coastguard Worker
locateIDR()205*0ec5a0ecSAndroid Build Coastguard Worker bool HEVCNalParser::locateIDR() {
206*0ec5a0ecSAndroid Build Coastguard Worker while (locateNextNal()) {
207*0ec5a0ecSAndroid Build Coastguard Worker if (length() == 0) continue;
208*0ec5a0ecSAndroid Build Coastguard Worker if (type() != kIDRType) continue;
209*0ec5a0ecSAndroid Build Coastguard Worker return true;
210*0ec5a0ecSAndroid Build Coastguard Worker }
211*0ec5a0ecSAndroid Build Coastguard Worker
212*0ec5a0ecSAndroid Build Coastguard Worker return false;
213*0ec5a0ecSAndroid Build Coastguard Worker }
214*0ec5a0ecSAndroid Build Coastguard Worker
type() const215*0ec5a0ecSAndroid Build Coastguard Worker uint8_t HEVCNalParser::type() const {
216*0ec5a0ecSAndroid Build Coastguard Worker // First bit is forbidden_zero_bit, next 6 are nal_unit_type
217*0ec5a0ecSAndroid Build Coastguard Worker constexpr uint8_t kNALTypeMask = 0x7e;
218*0ec5a0ecSAndroid Build Coastguard Worker return (*mCurrNalDataPos & kNALTypeMask) >> 1;
219*0ec5a0ecSAndroid Build Coastguard Worker }
220*0ec5a0ecSAndroid Build Coastguard Worker
findCodedColorAspects(ColorAspects * colorAspects)221*0ec5a0ecSAndroid Build Coastguard Worker bool HEVCNalParser::findCodedColorAspects(ColorAspects* colorAspects) {
222*0ec5a0ecSAndroid Build Coastguard Worker ALOG_ASSERT(colorAspects);
223*0ec5a0ecSAndroid Build Coastguard Worker ALOG_ASSERT(type() == kSPSType);
224*0ec5a0ecSAndroid Build Coastguard Worker
225*0ec5a0ecSAndroid Build Coastguard Worker // Unfortunately we can't directly jump to the Video Usability Information (VUI) parameters that
226*0ec5a0ecSAndroid Build Coastguard Worker // contain the color aspects. We need to parse the entire SPS header up until the values we
227*0ec5a0ecSAndroid Build Coastguard Worker // need.
228*0ec5a0ecSAndroid Build Coastguard Worker // Skip first 2 bytes for the NALU header.
229*0ec5a0ecSAndroid Build Coastguard Worker if (length() <= 2) return false;
230*0ec5a0ecSAndroid Build Coastguard Worker NALBitReader br(mCurrNalDataPos + 2, length() - 2);
231*0ec5a0ecSAndroid Build Coastguard Worker
232*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(4); // sps_video_parameter_set_id
233*0ec5a0ecSAndroid Build Coastguard Worker uint32_t spsMaxSublayersMinus1;
234*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(3, &spsMaxSublayersMinus1)) return false;
235*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(1); // sps_temporal_id_nesting_flag
236*0ec5a0ecSAndroid Build Coastguard Worker
237*0ec5a0ecSAndroid Build Coastguard Worker if (!skipProfileTierLevel(&br, spsMaxSublayersMinus1)) return false;
238*0ec5a0ecSAndroid Build Coastguard Worker
239*0ec5a0ecSAndroid Build Coastguard Worker uint32_t unused;
240*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // sps_seq_parameter_set_id
241*0ec5a0ecSAndroid Build Coastguard Worker uint32_t chromaFormatIdc;
242*0ec5a0ecSAndroid Build Coastguard Worker if (!parseUE(&br, &chromaFormatIdc)) return false;
243*0ec5a0ecSAndroid Build Coastguard Worker if (chromaFormatIdc == 3) br.skipBits(1); // separate_colour_plane_flag
244*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // pic_width_in_luma_samples
245*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // pic_height_in_luma_samples
246*0ec5a0ecSAndroid Build Coastguard Worker
247*0ec5a0ecSAndroid Build Coastguard Worker uint32_t conformanceWindowFlag;
248*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &conformanceWindowFlag)) return false;
249*0ec5a0ecSAndroid Build Coastguard Worker if (conformanceWindowFlag) {
250*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // conf_win_left_offset
251*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // conf_win_right_offset
252*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // conf_win_top_offset
253*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // conf_win_bottom_offset
254*0ec5a0ecSAndroid Build Coastguard Worker }
255*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // bit_depth_luma_minus8
256*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // bit_depth_chroma_minus8
257*0ec5a0ecSAndroid Build Coastguard Worker uint32_t log2MaxPicOrderCntLsbMinus4;
258*0ec5a0ecSAndroid Build Coastguard Worker if (!parseUE(&br, &log2MaxPicOrderCntLsbMinus4)) return false;
259*0ec5a0ecSAndroid Build Coastguard Worker
260*0ec5a0ecSAndroid Build Coastguard Worker uint32_t spsSubLayerOrderingInfoPresentFlag;
261*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &spsSubLayerOrderingInfoPresentFlag)) return false;
262*0ec5a0ecSAndroid Build Coastguard Worker for (uint32_t i = spsSubLayerOrderingInfoPresentFlag ? 0 : spsMaxSublayersMinus1;
263*0ec5a0ecSAndroid Build Coastguard Worker i <= spsMaxSublayersMinus1; ++i) {
264*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // sps_max_dec_pic_buffering_minus1
265*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // sps_max_num_reorder_pics
266*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // sps_max_latency_increase_plus1
267*0ec5a0ecSAndroid Build Coastguard Worker }
268*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // log2_min_luma_coding_block_size_minus3
269*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // log2_diff_max_min_luma_coding_block_size
270*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // log2_min_luma_transform_block_size_minus2
271*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // log2_diff_max_min_luma_transform_block_size
272*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // max_transform_hierarchy_depth_inter
273*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // max_transform_hierarchy_depth_intra
274*0ec5a0ecSAndroid Build Coastguard Worker uint32_t scalingListEnabledFlag;
275*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &scalingListEnabledFlag)) return false;
276*0ec5a0ecSAndroid Build Coastguard Worker if (scalingListEnabledFlag) {
277*0ec5a0ecSAndroid Build Coastguard Worker uint32_t spsScalingListDataPresentFlag;
278*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &spsScalingListDataPresentFlag)) return false;
279*0ec5a0ecSAndroid Build Coastguard Worker if (spsScalingListDataPresentFlag) {
280*0ec5a0ecSAndroid Build Coastguard Worker if (!skipScalingListData(&br)) return false;
281*0ec5a0ecSAndroid Build Coastguard Worker }
282*0ec5a0ecSAndroid Build Coastguard Worker }
283*0ec5a0ecSAndroid Build Coastguard Worker
284*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(2); // amp_enabled_flag(1), sample_adaptive_offset_enabled_flag(1)
285*0ec5a0ecSAndroid Build Coastguard Worker uint32_t pcmEnabledFlag;
286*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &pcmEnabledFlag)) return false;
287*0ec5a0ecSAndroid Build Coastguard Worker if (pcmEnabledFlag) {
288*0ec5a0ecSAndroid Build Coastguard Worker // pcm_sample_bit_depth_luma_minus1(4), pcm_sample_bit_depth_chroma_minus1(4)
289*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(8);
290*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // log2_min_pcm_luma_coding_block_size_minus3
291*0ec5a0ecSAndroid Build Coastguard Worker parseUE(&br, &unused); // log2_diff_max_min_pcm_luma_coding_block_size
292*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(1); // pcm_loop_filter_disabled_flag
293*0ec5a0ecSAndroid Build Coastguard Worker }
294*0ec5a0ecSAndroid Build Coastguard Worker
295*0ec5a0ecSAndroid Build Coastguard Worker uint32_t numShortTermRefPicSets;
296*0ec5a0ecSAndroid Build Coastguard Worker if (!parseUE(&br, &numShortTermRefPicSets)) return false;
297*0ec5a0ecSAndroid Build Coastguard Worker if (numShortTermRefPicSets > kMaxShortTermRefPicSets) {
298*0ec5a0ecSAndroid Build Coastguard Worker ALOGW("numShortTermRefPicSets out of range");
299*0ec5a0ecSAndroid Build Coastguard Worker return false;
300*0ec5a0ecSAndroid Build Coastguard Worker }
301*0ec5a0ecSAndroid Build Coastguard Worker StRefPicSet allRefPicSets[kMaxShortTermRefPicSets];
302*0ec5a0ecSAndroid Build Coastguard Worker memset(allRefPicSets, 0, sizeof(StRefPicSet) * kMaxShortTermRefPicSets);
303*0ec5a0ecSAndroid Build Coastguard Worker for (uint32_t i = 0; i < numShortTermRefPicSets; ++i) {
304*0ec5a0ecSAndroid Build Coastguard Worker if (!skipStRefPicSet(&br, i, numShortTermRefPicSets, allRefPicSets, &allRefPicSets[i]))
305*0ec5a0ecSAndroid Build Coastguard Worker return false;
306*0ec5a0ecSAndroid Build Coastguard Worker }
307*0ec5a0ecSAndroid Build Coastguard Worker
308*0ec5a0ecSAndroid Build Coastguard Worker uint32_t longTermRefPicsPresentFlag;
309*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &longTermRefPicsPresentFlag)) return false;
310*0ec5a0ecSAndroid Build Coastguard Worker if (longTermRefPicsPresentFlag) {
311*0ec5a0ecSAndroid Build Coastguard Worker uint32_t numLongTermRefPicsSps;
312*0ec5a0ecSAndroid Build Coastguard Worker if (!parseUE(&br, &numLongTermRefPicsSps)) return false;
313*0ec5a0ecSAndroid Build Coastguard Worker for (uint32_t i = 0; i < numLongTermRefPicsSps; ++i) {
314*0ec5a0ecSAndroid Build Coastguard Worker // lt_ref_pic_poc_lsb_sps
315*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(log2MaxPicOrderCntLsbMinus4 + 4, &unused)) return false;
316*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &unused)) return false; // used_by_curr_pic_lt_sps_flag
317*0ec5a0ecSAndroid Build Coastguard Worker }
318*0ec5a0ecSAndroid Build Coastguard Worker }
319*0ec5a0ecSAndroid Build Coastguard Worker // sps_temporal_mvp_enabled_flag(1), strong_intra_smoothing_enabled_flag(1)
320*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(2);
321*0ec5a0ecSAndroid Build Coastguard Worker uint32_t vuiParametersPresentFlag;
322*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &vuiParametersPresentFlag)) return false;
323*0ec5a0ecSAndroid Build Coastguard Worker if (vuiParametersPresentFlag) {
324*0ec5a0ecSAndroid Build Coastguard Worker uint32_t aspectRatioInfoPresentFlag;
325*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &aspectRatioInfoPresentFlag))
326*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI aspect_ratio_info_present_flag
327*0ec5a0ecSAndroid Build Coastguard Worker if (aspectRatioInfoPresentFlag) {
328*0ec5a0ecSAndroid Build Coastguard Worker uint32_t aspectRatioIdc;
329*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(8, &aspectRatioIdc)) return false; // VUI aspect_ratio_idc
330*0ec5a0ecSAndroid Build Coastguard Worker if (aspectRatioIdc == 255) { // VUI aspect_ratio_idc == extended sample aspect ratio
331*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(32); // VUI sar_width + sar_height
332*0ec5a0ecSAndroid Build Coastguard Worker }
333*0ec5a0ecSAndroid Build Coastguard Worker }
334*0ec5a0ecSAndroid Build Coastguard Worker
335*0ec5a0ecSAndroid Build Coastguard Worker uint32_t overscanInfoPresentFlag;
336*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &overscanInfoPresentFlag))
337*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI overscan_info_present_flag
338*0ec5a0ecSAndroid Build Coastguard Worker if (overscanInfoPresentFlag) br.skipBits(1); // VUI overscan_appropriate_flag
339*0ec5a0ecSAndroid Build Coastguard Worker uint32_t videoSignalTypePresentFlag;
340*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &videoSignalTypePresentFlag))
341*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI video_signal_type_present_flag
342*0ec5a0ecSAndroid Build Coastguard Worker if (videoSignalTypePresentFlag) {
343*0ec5a0ecSAndroid Build Coastguard Worker br.skipBits(3); // VUI video_format
344*0ec5a0ecSAndroid Build Coastguard Worker uint32_t videoFullRangeFlag;
345*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &videoFullRangeFlag))
346*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI videoFullRangeFlag
347*0ec5a0ecSAndroid Build Coastguard Worker colorAspects->fullRange = videoFullRangeFlag;
348*0ec5a0ecSAndroid Build Coastguard Worker uint32_t color_description_present_flag;
349*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(1, &color_description_present_flag))
350*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI color_description_present_flag
351*0ec5a0ecSAndroid Build Coastguard Worker if (color_description_present_flag) {
352*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(8, &colorAspects->primaries))
353*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI colour_primaries
354*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(8, &colorAspects->transfer))
355*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI transfer_characteristics
356*0ec5a0ecSAndroid Build Coastguard Worker if (!br.getBitsGraceful(8, &colorAspects->coeffs))
357*0ec5a0ecSAndroid Build Coastguard Worker return false; // VUI matrix_coefficients
358*0ec5a0ecSAndroid Build Coastguard Worker return true;
359*0ec5a0ecSAndroid Build Coastguard Worker }
360*0ec5a0ecSAndroid Build Coastguard Worker }
361*0ec5a0ecSAndroid Build Coastguard Worker }
362*0ec5a0ecSAndroid Build Coastguard Worker
363*0ec5a0ecSAndroid Build Coastguard Worker return false; // The NAL unit doesn't contain color aspects info.
364*0ec5a0ecSAndroid Build Coastguard Worker }
365*0ec5a0ecSAndroid Build Coastguard Worker
366*0ec5a0ecSAndroid Build Coastguard Worker } // namespace android
367