• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "box/item_property_hvcc_box.h"
17 
18 static const uint8_t GENGERAL_PROFILE_SPACE_SHIFT = 6;
19 static const uint8_t GENERAL_TIER_FLAG_SHIFT = 5;
20 static const uint8_t CONST_FRMAE_RATE_SHIFT = 6;
21 static const uint8_t NUM_TEMPORAL_LAYERS_SHIFT = 3;
22 static const uint8_t TEMPORAL_ID_NESTED_SHIFT = 2;
23 static const uint8_t ARRAY_COMPLETENESS_SHIFT = 6;
24 static const uint8_t BIT_DEPTH_DIFF = 8;
25 static const uint8_t NAL_UNIT_LENGTH_SIZE_DIFF = 1;
26 
27 static const uint8_t SKIP_DOUBLE_DATA_PROCESS_BYTE = 2;
28 static const uint8_t READ_BIT_NUM_FLAG = 1;
29 static const uint8_t READ_BYTE_NUM_FLAG = 8;
30 static const uint8_t READ_GENERAL_PROFILE_IDC_NUM = 32;
31 static const uint8_t READ_SUB_LAYER_PROFILE_IDCS = 48;
32 
33 static const uint8_t SPS_BOX_TYPE = 33;
34 static const uint8_t EXTENDED_SAR = 255;
35 static const uint8_t NALU_TYPE_ID_SIZE = 6;
36 static const uint8_t SUB_LAYER_MINUS = 3;
37 static const uint8_t GENERAL_PROFILE_SIZE = 4;
38 static const uint8_t SUB_LAYER_PRESENT_PROFILE_SIZE = 3;
39 static const uint8_t SUB_LAYER_PROFILE_IDC_SIZE = 5;
40 static const uint8_t PCM_ENABLED_FLAG = 4;
41 static const uint8_t NUM_TEMPORAL_ID_SIZE = 6;
42 static const uint8_t MAX_COEF_NUM = 64;
43 
44 namespace OHOS {
45 namespace ImagePlugin {
ParseNalUnitArray(HeifStreamReader & reader,std::vector<std::vector<uint8_t>> & nalUnits)46 heif_error HeifHvccBox::ParseNalUnitArray(HeifStreamReader& reader, std::vector<std::vector<uint8_t>>& nalUnits)
47 {
48     int nalUnitNum = reader.Read16();
49     for (int unitIndex = 0; unitIndex < nalUnitNum && !reader.HasError(); ++unitIndex) {
50         int nalUnitSize = reader.Read16();
51         if (!nalUnitSize || !reader.CheckSize(nalUnitSize)) {
52             continue;
53         }
54         std::vector<uint8_t> nalUnit(nalUnitSize);
55         bool res = reader.ReadData(nalUnit.data(), nalUnitSize);
56         if (!res) {
57             return heif_error_eof;
58         }
59         nalUnits.push_back(nalUnit);
60     }
61     return reader.GetError();
62 }
63 
ParseContent(HeifStreamReader & reader)64 heif_error HeifHvccBox::ParseContent(HeifStreamReader& reader)
65 {
66     config_.version = reader.Read8();
67     uint8_t tempByte = reader.Read8();
68     config_.generalProfileSpace = (tempByte >> GENGERAL_PROFILE_SPACE_SHIFT) & 0x03;
69     config_.generalTierFlag = (tempByte >> GENERAL_TIER_FLAG_SHIFT) & 0x01;
70     config_.generalProfileIdc = (tempByte & 0x1F);
71     config_.generalProfileCompatibilityFlags = reader.Read32();
72     uint32_t indicatorFlagsPre = reader.Read32();
73     uint16_t indicatorFlagsLast = reader.Read16();
74     config_.generalConstraintIndicatorFlags = uint64_t((indicatorFlagsPre << TWO_BYTES_SHIFT) | indicatorFlagsLast);
75     config_.generalLevelIdc = reader.Read8();
76     config_.minSpatialSegmentationIdc = reader.Read16() & 0x0FFF;
77     config_.parallelismType = reader.Read8() & 0x03;
78     config_.chromaFormat = reader.Read8() & 0x03;
79 
80     // box store content is bitDepthLumaMinus8
81     config_.bitDepthLuma = (reader.Read8() & 0x07) + BIT_DEPTH_DIFF;
82     config_.bitDepthChroma = (reader.Read8() & 0x07) + BIT_DEPTH_DIFF;
83     config_.avgFrameRate = reader.Read16();
84 
85     tempByte = reader.Read8();
86     config_.constFrameRate = (tempByte >> CONST_FRMAE_RATE_SHIFT) & 0x03;
87     config_.numTemporalLayers = (tempByte >> NUM_TEMPORAL_LAYERS_SHIFT) & 0x07;
88     config_.temporalIdNested = (tempByte >> TEMPORAL_ID_NESTED_SHIFT) & 0x01;
89 
90     // box store content is lengthSizeMinus1
91     nalUnitLengthSize_ = static_cast<uint8_t>((tempByte & 0x03) + NAL_UNIT_LENGTH_SIZE_DIFF);
92     int nalArrayNum = reader.Read8();
93     for (int arrayIndex = 0; arrayIndex < nalArrayNum && !reader.HasError(); ++arrayIndex) {
94         tempByte = reader.Read8();
95         HvccNalArray array;
96         array.arrayCompleteness = (tempByte >> ARRAY_COMPLETENESS_SHIFT) & 0x01;
97         array.nalUnitType = (tempByte & 0x3F);
98         heif_error error = ParseNalUnitArray(reader, array.nalUnits);
99         if (error) {
100             return error;
101         }
102         nalArrays_.push_back(std::move(array));
103     }
104     return reader.GetError();
105 }
106 
GetHeaders(std::vector<uint8_t> * outData) const107 bool HeifHvccBox::GetHeaders(std::vector<uint8_t>* outData) const
108 {
109     for (const auto& array : nalArrays_) {
110         for (const auto& unit : array.nalUnits) {
111             outData->push_back((unit.size() >> THREE_BYTES_SHIFT) & 0xFF);
112             outData->push_back((unit.size() >> TWO_BYTES_SHIFT) & 0xFF);
113             outData->push_back((unit.size() >> ONE_BYTE_SHIFT) & 0xFF);
114             outData->push_back((unit.size()) & 0xFF);
115             outData->insert(outData->end(), unit.begin(), unit.end());
116         }
117     }
118 
119     return true;
120 }
121 
AppendNalData(const std::vector<uint8_t> & nalData)122 void HeifHvccBox::AppendNalData(const std::vector<uint8_t>& nalData)
123 {
124     HvccNalArray array;
125     array.arrayCompleteness = 0;
126     array.nalUnitType = uint8_t(nalData[0] >> 1);
127     array.nalUnits.push_back(nalData);
128     nalArrays_.push_back(array);
129 }
130 
Write(HeifStreamWriter & writer) const131 heif_error HeifHvccBox::Write(HeifStreamWriter& writer) const
132 {
133     size_t boxStart = ReserveHeader(writer);
134 
135     const HvccConfig& config = config_;
136     writer.Write8(config.version);
137     writer.Write8((uint8_t) (((config.generalProfileSpace & 0x03) << GENGERAL_PROFILE_SPACE_SHIFT) |
138                              ((config.generalTierFlag & 0x01) << GENERAL_TIER_FLAG_SHIFT) |
139                              (config.generalProfileIdc & 0x1F)));
140     writer.Write32(config.generalProfileCompatibilityFlags);
141     writer.Write32((config.generalConstraintIndicatorFlags >> TWO_BYTES_SHIFT) & 0xFFFFFFFF);
142     writer.Write16((config.generalConstraintIndicatorFlags) & 0xFFFF);
143     writer.Write8(config.generalLevelIdc);
144     writer.Write16((config.minSpatialSegmentationIdc & 0x0FFF) | 0xF000);
145     writer.Write8((config.parallelismType & 0x03) | 0xFC);
146     writer.Write8((config.chromaFormat & 0x03) | 0xFC);
147     writer.Write8(((config.bitDepthLuma - BIT_DEPTH_DIFF) & 0x07) | 0xF8);
148     writer.Write8(((config.bitDepthChroma - BIT_DEPTH_DIFF) & 0x07) | 0xF8);
149     writer.Write16(config.avgFrameRate);
150     writer.Write8((uint8_t) (((config.constFrameRate & 0x03) << CONST_FRMAE_RATE_SHIFT) |
151                              ((config.numTemporalLayers & 0x07) << NUM_TEMPORAL_LAYERS_SHIFT) |
152                              ((config.temporalIdNested & 0x01) << TEMPORAL_ID_NESTED_SHIFT) |
153                              ((nalUnitLengthSize_ - NAL_UNIT_LENGTH_SIZE_DIFF) & 0x03)));
154 
155     size_t nArrays = nalArrays_.size();
156     writer.Write8((uint8_t) nArrays);
157     for (const HvccNalArray& array : nalArrays_) {
158         writer.Write8((uint8_t) (((array.arrayCompleteness & 0x01) << ARRAY_COMPLETENESS_SHIFT) |
159                                  (array.nalUnitType & 0x3F)));
160         size_t nUnits = array.nalUnits.size();
161         writer.Write16((uint16_t) nUnits);
162         for (const std::vector<uint8_t>& nalUnit : array.nalUnits) {
163             writer.Write16((uint16_t) nalUnit.size());
164             writer.Write(nalUnit);
165         }
166     }
167 
168     WriteCalculatedHeader(writer, boxStart);
169     return heif_error_ok;
170 }
171 
GetWord(const std::vector<uint8_t> & nalu,uint32_t length)172 uint32_t HeifHvccBox::GetWord(const std::vector<uint8_t>& nalu, uint32_t length)
173 {
174     uint32_t res = 0;
175     for (uint32_t i = 0; i < length && pos_ < boxBitLength_; ++i, ++pos_) {
176         uint32_t bit = ((nalu[pos_ / BIT_DEPTH_DIFF] >>
177                         (BIT_DEPTH_DIFF - BIT_SHIFT - (pos_ % BIT_DEPTH_DIFF)))
178                         & 0x01);
179         res <<= BIT_SHIFT;
180         res |= bit;
181     }
182     return res;
183 }
184 
GetGolombCode(const std::vector<uint8_t> & nalu)185 uint32_t HeifHvccBox::GetGolombCode(const std::vector<uint8_t> &nalu)
186 {
187     uint32_t zeros = 0;
188     while (pos_ < boxBitLength_ && ((nalu[pos_ / ONE_BYTE_SHIFT] >>
189            (ONE_BYTE_SHIFT - BIT_SHIFT - (pos_ % ONE_BYTE_SHIFT))) &
190            0x01) == 0x00) {
191         zeros++;
192         pos_++;
193     }
194     pos_++;
195     return GetWord(nalu, zeros) + ((BIT_SHIFT << zeros) - BIT_SHIFT);
196 }
197 
GetNaluTypeId(std::vector<uint8_t> & nalUnits)198 uint32_t HeifHvccBox::GetNaluTypeId(std::vector<uint8_t> &nalUnits)
199 {
200     if (nalUnits.empty()) {
201         return -1;
202     }
203     GetWord(nalUnits, READ_BIT_NUM_FLAG);
204     return GetWord(nalUnits, NALU_TYPE_ID_SIZE);
205 }
206 
GetNaluData(const std::vector<HvccNalArray> & nalArrays,uint8_t naluId)207 std::vector<uint8_t> HeifHvccBox::GetNaluData(const std::vector<HvccNalArray> &nalArrays,
208                                               uint8_t naluId)
209 {
210     for (auto HvccNalunit : nalArrays) {
211         if (HvccNalunit.nalUnitType == naluId && (!HvccNalunit.nalUnits.empty())) {
212             return HvccNalunit.nalUnits[0];
213         }
214     }
215     return std::vector<uint8_t>();
216 }
217 
ProcessBoxData(std::vector<uint8_t> & nalu)218 void HeifHvccBox::ProcessBoxData(std::vector<uint8_t> &nalu)
219 {
220     uint32_t naluSize = nalu.size();
221     std::vector<uint32_t> indicesToDelete;
222     for (uint32_t i = UINT16_BYTES_NUM; i < naluSize; ++i) {
223         if (nalu[i - UINT8_BYTES_NUM] == 0x00 &&
224             nalu[i - SKIP_DOUBLE_DATA_PROCESS_BYTE] == 0x00 && nalu[i] == 0x03) {
225             indicesToDelete.push_back(i);
226         }
227     }
228     for (auto it = indicesToDelete.rbegin(); it != indicesToDelete.rend(); ++it) {
229         nalu.erase(nalu.begin() + *it);
230     }
231 }
232 
ParserHvccColorRangeFlag(const std::vector<HvccNalArray> & nalArrays)233 void HeifHvccBox::ParserHvccColorRangeFlag(const std::vector<HvccNalArray> &nalArrays)
234 {
235     auto spsBox = GetNaluData(nalArrays, SPS_BOX_TYPE);
236     ProcessBoxData(spsBox);
237     ParseNalUnitAnalysisSps(spsBox);
238 }
239 
ProfileTierLevel(std::vector<uint8_t> & nalUnits,uint32_t profilePresentFlag,uint32_t maxNumSubLayerMinus1)240 void HeifHvccBox::ProfileTierLevel(std::vector<uint8_t> &nalUnits, uint32_t profilePresentFlag,
241                                    uint32_t maxNumSubLayerMinus1)
242 {
243     std::vector<uint32_t> generalProfileCompatibilityFlags;
244     std::vector<uint32_t> subLayerProfilePresentFlag;
245     std::vector<uint32_t> subLayerLevelPresentFlags;
246     std::vector<uint32_t> subLayerProfileIdcs;
247     std::vector<std::vector<uint32_t>> subLayerProfileCompatibilityFlags;
248     if (profilePresentFlag) {
249         GetWord(nalUnits, READ_BIT_NUM_FLAG); // general_profile_idc
250 
251         for (uint32_t j = 0; j < READ_GENERAL_PROFILE_IDC_NUM; ++j) {
252             uint32_t flag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
253             generalProfileCompatibilityFlags.push_back(flag);
254         }
255         GetWord(nalUnits, READ_BYTE_NUM_FLAG);
256         GetWord(nalUnits, READ_BYTE_NUM_FLAG);
257         GetWord(nalUnits, READ_GENERAL_PROFILE_IDC_NUM);
258     }
259     GetWord(nalUnits, READ_BYTE_NUM_FLAG);
260     subLayerProfilePresentFlag.resize(maxNumSubLayerMinus1);
261     for (uint32_t i = 0; i < maxNumSubLayerMinus1; ++i) {
262         subLayerProfilePresentFlag[i] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
263         subLayerLevelPresentFlags.push_back(GetWord(nalUnits, READ_BIT_NUM_FLAG));
264     }
265 
266     if (maxNumSubLayerMinus1 > 0) {
267         for (uint32_t i = maxNumSubLayerMinus1; i < READ_BYTE_NUM_FLAG; ++i) {
268             GetWord(nalUnits, READ_BIT_NUM_FLAG);
269             GetWord(nalUnits, READ_BIT_NUM_FLAG);
270         }
271     }
272 
273     subLayerProfileIdcs.resize(maxNumSubLayerMinus1);
274     subLayerProfileCompatibilityFlags.resize(maxNumSubLayerMinus1,
275                                              std::vector<uint32_t>(GENERAL_PROFILE_SIZE));
276     for (uint32_t i = 0; i < maxNumSubLayerMinus1; i++) {
277         if (subLayerProfilePresentFlag[i]) {
278             GetWord(nalUnits, SUB_LAYER_PRESENT_PROFILE_SIZE);
279             subLayerProfileIdcs[i] = GetWord(nalUnits, SUB_LAYER_PROFILE_IDC_SIZE);
280             for (uint32_t j = 0; j < GENERAL_PROFILE_SIZE; ++j) {
281                 subLayerProfileCompatibilityFlags[i][j] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
282             }
283 
284             // skip sub_layer_profile_idcs judge;
285             GetWord(nalUnits, READ_SUB_LAYER_PROFILE_IDCS);
286         }
287         if (subLayerLevelPresentFlags[i]) {
288             GetWord(nalUnits, READ_BYTE_NUM_FLAG);
289         }
290     }
291 }
292 
ParseNalUnitAnalysisSps(std::vector<uint8_t> & nalUnits)293 bool HeifHvccBox::ParseNalUnitAnalysisSps(std::vector<uint8_t> &nalUnits)
294 {
295     boxBitLength_ = nalUnits.size() * BIT_DEPTH_DIFF;
296     spsConfig_.forbiddenZeroBit = GetWord(nalUnits, READ_BIT_NUM_FLAG);
297     spsConfig_.nuhTemporalIdPlus1 = GetWord(nalUnits, NUM_TEMPORAL_ID_SIZE);
298     spsConfig_.nalUnitType = GetWord(nalUnits, NALU_TYPE_ID_SIZE);
299     GetWord(nalUnits, SUB_LAYER_MINUS);
300     return ParseSpsSyntax(nalUnits);
301 }
302 
ParseSpsSyntax(std::vector<uint8_t> & nalUnits)303 bool HeifHvccBox::ParseSpsSyntax(std::vector<uint8_t> &nalUnits)
304 {
305     //General sequence parameter set RBSP syntax
306     spsConfig_.spsVideoParameterSetId = GetWord(nalUnits, GENERAL_PROFILE_SIZE);
307     spsConfig_.spsMaxSubLayersMinus1 = GetWord(nalUnits, SUB_LAYER_MINUS);
308     spsConfig_.spsTemporalIdNestingFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
309 
310     //go to profile_tier_level parser
311     ProfileTierLevel(nalUnits,
312                      spsConfig_.spsTemporalIdNestingFlag,
313                      spsConfig_.spsMaxSubLayersMinus1);
314 
315     spsConfig_.spsVideoParameterSetId = GetGolombCode(nalUnits);
316     spsConfig_.chromaFormatIdc = GetGolombCode(nalUnits);
317     if (spsConfig_.chromaFormatIdc == SUB_LAYER_MINUS) {
318         spsConfig_.separateColourPlaneFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
319     }
320     spsConfig_.picWidthInLumaSamples = GetGolombCode(nalUnits);
321     spsConfig_.picHeightInLumaSamples = GetGolombCode(nalUnits);
322     spsConfig_.conformanceWindowFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
323     if (spsConfig_.conformanceWindowFlag == READ_BIT_NUM_FLAG) {
324         spsConfig_.confWinLefOffset = GetGolombCode(nalUnits);
325         spsConfig_.confWinRightOffset = GetGolombCode(nalUnits);
326         spsConfig_.confWinTopOffset = GetGolombCode(nalUnits);
327         spsConfig_.confWinBottomOffset = GetGolombCode(nalUnits);
328     }
329     spsConfig_.bitDepthLumaMinus8 = GetGolombCode(nalUnits);
330     spsConfig_.bitDepthChromaMinus8 = GetGolombCode(nalUnits);
331     spsConfig_.log2MaxPicOrderCntLsbMinus4 = GetGolombCode(nalUnits);
332     spsConfig_.spsSubLayerOrderingInfoPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
333     uint32_t i = spsConfig_.spsSubLayerOrderingInfoPresentFlag ? 0 : spsConfig_.spsMaxSubLayersMinus1;
334     for (; i <= spsConfig_.spsMaxSubLayersMinus1; i++) {
335         GetGolombCode(nalUnits);
336         GetGolombCode(nalUnits);
337         GetGolombCode(nalUnits);
338     }
339     GetGolombCode(nalUnits);
340     GetGolombCode(nalUnits);
341     GetGolombCode(nalUnits);
342     GetGolombCode(nalUnits);
343     GetGolombCode(nalUnits);
344     GetGolombCode(nalUnits);
345     return ParseSpsSyntaxScalingList(nalUnits);
346 }
347 
ReadGolombCodesForSizeId(std::vector<uint8_t> & nalUnits,uint32_t sizeId)348 void HeifHvccBox::ReadGolombCodesForSizeId(std::vector<uint8_t> &nalUnits, uint32_t sizeId)
349 {
350     uint8_t minCoefNum = READ_BIT_NUM_FLAG << (GENERAL_PROFILE_SIZE + (static_cast<uint8_t>(sizeId)
351                          << READ_BIT_NUM_FLAG));
352     uint32_t coefNum = MAX_COEF_NUM < minCoefNum ? MAX_COEF_NUM : minCoefNum;
353     if (sizeId > READ_BIT_NUM_FLAG) {
354         GetGolombCode(nalUnits);
355     }
356     for (uint32_t i = 0; i < coefNum; i++) {
357         GetGolombCode(nalUnits);
358     }
359 }
360 
ParseSpsScallListData(std::vector<uint8_t> & nalUnits)361 void HeifHvccBox::ParseSpsScallListData(std::vector<uint8_t> &nalUnits)
362 {
363     for (uint32_t sizeId = 0; sizeId < GENERAL_PROFILE_SIZE; ++sizeId) {
364         for (uint32_t matrixId = 0; matrixId < NUM_TEMPORAL_ID_SIZE;
365             matrixId += ((sizeId == SUB_LAYER_MINUS) ? SUB_LAYER_MINUS : READ_BIT_NUM_FLAG)) {
366             uint32_t tmpFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
367             if (!tmpFlag) {
368                 GetGolombCode(nalUnits);
369             } else {
370                 ReadGolombCodesForSizeId(nalUnits, sizeId);
371             }
372         }
373     }
374 }
375 
ParseSpsVuiParameter(std::vector<uint8_t> & nalUnits)376 bool HeifHvccBox::ParseSpsVuiParameter(std::vector<uint8_t> &nalUnits)
377 {
378     uint8_t aspectRatioInfoPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
379     if (aspectRatioInfoPresentFlag) {
380         uint32_t aspectRatioIdc = GetWord(nalUnits, READ_BYTE_NUM_FLAG);
381         if (aspectRatioIdc == EXTENDED_SAR) {
382             GetWord(nalUnits, READ_BIT_NUM_FLAG);
383         }
384     }
385     uint32_t overscanInfoPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
386     if (overscanInfoPresentFlag) {
387         GetWord(nalUnits, GENERAL_PROFILE_SIZE);
388     }
389     uint32_t videoSignalTypePresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
390     if (videoSignalTypePresentFlag) {
391         GetWord(nalUnits, SUB_LAYER_MINUS);
392         spsConfig_.videoRangeFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
393     }
394     return true;
395 }
396 
ParseSpsSyntaxScalingList(std::vector<uint8_t> & nalUnits)397 bool HeifHvccBox::ParseSpsSyntaxScalingList(std::vector<uint8_t> &nalUnits)
398 {
399     spsConfig_.scalingListEnabeldFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
400     if (spsConfig_.scalingListEnabeldFlag == READ_BIT_NUM_FLAG) {
401         spsConfig_.scalingListEnabeldFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
402         if (spsConfig_.scalingListEnabeldFlag) {
403             ParseSpsScallListData(nalUnits);
404         }
405     }
406     GetWord(nalUnits, READ_BIT_NUM_FLAG);
407     GetWord(nalUnits, READ_BIT_NUM_FLAG);
408     spsConfig_.pcmEnabledFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
409     if (spsConfig_.pcmEnabledFlag == READ_BIT_NUM_FLAG) {
410         GetWord(nalUnits, PCM_ENABLED_FLAG);
411         GetWord(nalUnits, PCM_ENABLED_FLAG);
412         GetGolombCode(nalUnits);
413         GetGolombCode(nalUnits);
414         GetWord(nalUnits, READ_BIT_NUM_FLAG);
415     }
416     spsConfig_.numShortTermRefPicSets = GetGolombCode(nalUnits);
417     spsConfig_.longTermRefPicsPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
418     if (spsConfig_.longTermRefPicsPresentFlag == READ_BIT_NUM_FLAG) {
419         uint32_t numLongTermRefPicSps = GetGolombCode(nalUnits);
420         for (uint32_t i = 0; i < numLongTermRefPicSps; i++) {
421             // itRefPicPocLsbSps[i] == log2MaxPicOrderCntLsbMinus4 + 4
422             GetWord(nalUnits, spsConfig_.log2MaxPicOrderCntLsbMinus4 + GENERAL_PROFILE_SIZE);
423             GetWord(nalUnits, READ_BIT_NUM_FLAG);
424         }
425     }
426     GetWord(nalUnits, READ_BIT_NUM_FLAG);
427     GetWord(nalUnits, READ_BIT_NUM_FLAG);
428     spsConfig_.vuiParameterPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
429     if (spsConfig_.vuiParameterPresentFlag == READ_BIT_NUM_FLAG) {
430         return ParseSpsVuiParameter(nalUnits);
431     }
432     return false; // Skip parsing subsequent content
433 }
434 } // namespace ImagePlugin
435 } // namespace OHOS
436