• 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 #include "image_log.h"
18 
19 static const uint8_t GENGERAL_PROFILE_SPACE_SHIFT = 6;
20 static const uint8_t GENERAL_TIER_FLAG_SHIFT = 5;
21 static const uint8_t CONST_FRMAE_RATE_SHIFT = 6;
22 static const uint8_t NUM_TEMPORAL_LAYERS_SHIFT = 3;
23 static const uint8_t TEMPORAL_ID_NESTED_SHIFT = 2;
24 static const uint8_t ARRAY_COMPLETENESS_SHIFT = 6;
25 static const uint8_t BIT_DEPTH_DIFF = 8;
26 static const uint8_t NAL_UNIT_LENGTH_SIZE_DIFF = 1;
27 
28 static const uint8_t SKIP_DOUBLE_DATA_PROCESS_BYTE = 2;
29 static const uint8_t READ_BIT_NUM_FLAG = 1;
30 static const uint8_t READ_BYTE_NUM_FLAG = 8;
31 static const uint8_t READ_GENERAL_PROFILE_IDC_NUM = 32;
32 static const uint8_t READ_SUB_LAYER_PROFILE_IDCS = 48;
33 
34 static const uint8_t SPS_BOX_TYPE = 33;
35 static const uint8_t EXTENDED_SAR = 255;
36 static const uint8_t NALU_TYPE_ID_SIZE = 6;
37 static const uint8_t SUB_LAYER_MINUS = 3;
38 static const uint8_t GENERAL_PROFILE_SIZE = 4;
39 static const uint8_t SUB_LAYER_PRESENT_PROFILE_SIZE = 3;
40 static const uint8_t SUB_LAYER_PROFILE_IDC_SIZE = 5;
41 static const uint8_t PCM_ENABLED_FLAG = 4;
42 static const uint8_t NUM_TEMPORAL_ID_SIZE = 6;
43 static const uint8_t MAX_COEF_NUM = 64;
44 static uint32_t HEIF_MAX_IMAGE_DPB_SIZE = 32;
45 static uint32_t HEIF_NUM_DELTA_POCS = 1;
46 static uint32_t HEIF_BASE_DELTA_FlAG = 1;
47 
48 namespace OHOS {
49 namespace ImagePlugin {
ParseNalUnitArray(HeifStreamReader & reader,std::vector<std::vector<uint8_t>> & nalUnits)50 heif_error HeifHvccBox::ParseNalUnitArray(HeifStreamReader& reader, std::vector<std::vector<uint8_t>>& nalUnits)
51 {
52     int nalUnitNum = reader.Read16();
53     for (int unitIndex = 0; unitIndex < nalUnitNum && !reader.HasError(); ++unitIndex) {
54         int nalUnitSize = reader.Read16();
55         if (!nalUnitSize || !reader.CheckSize(nalUnitSize)) {
56             continue;
57         }
58         std::vector<uint8_t> nalUnit(nalUnitSize);
59         bool res = reader.ReadData(nalUnit.data(), nalUnitSize);
60         if (!res) {
61             return heif_error_eof;
62         }
63         nalUnits.push_back(nalUnit);
64     }
65     return reader.GetError();
66 }
67 
ParseContent(HeifStreamReader & reader)68 heif_error HeifHvccBox::ParseContent(HeifStreamReader& reader)
69 {
70     config_.version = reader.Read8();
71     uint8_t tempByte = reader.Read8();
72     config_.generalProfileSpace = (tempByte >> GENGERAL_PROFILE_SPACE_SHIFT) & 0x03;
73     config_.generalTierFlag = (tempByte >> GENERAL_TIER_FLAG_SHIFT) & 0x01;
74     config_.generalProfileIdc = (tempByte & 0x1F);
75     config_.generalProfileCompatibilityFlags = reader.Read32();
76     uint32_t indicatorFlagsPre = reader.Read32();
77     uint16_t indicatorFlagsLast = reader.Read16();
78     config_.generalConstraintIndicatorFlags = uint64_t((indicatorFlagsPre << TWO_BYTES_SHIFT) | indicatorFlagsLast);
79     config_.generalLevelIdc = reader.Read8();
80     config_.minSpatialSegmentationIdc = reader.Read16() & 0x0FFF;
81     config_.parallelismType = reader.Read8() & 0x03;
82     config_.chromaFormat = reader.Read8() & 0x03;
83 
84     // box store content is bitDepthLumaMinus8
85     config_.bitDepthLuma = (reader.Read8() & 0x07) + BIT_DEPTH_DIFF;
86     config_.bitDepthChroma = (reader.Read8() & 0x07) + BIT_DEPTH_DIFF;
87     config_.avgFrameRate = reader.Read16();
88 
89     tempByte = reader.Read8();
90     config_.constFrameRate = (tempByte >> CONST_FRMAE_RATE_SHIFT) & 0x03;
91     config_.numTemporalLayers = (tempByte >> NUM_TEMPORAL_LAYERS_SHIFT) & 0x07;
92     config_.temporalIdNested = (tempByte >> TEMPORAL_ID_NESTED_SHIFT) & 0x01;
93 
94     // box store content is lengthSizeMinus1
95     nalUnitLengthSize_ = static_cast<uint8_t>((tempByte & 0x03) + NAL_UNIT_LENGTH_SIZE_DIFF);
96     int nalArrayNum = reader.Read8();
97     for (int arrayIndex = 0; arrayIndex < nalArrayNum && !reader.HasError(); ++arrayIndex) {
98         tempByte = reader.Read8();
99         HvccNalArray array;
100         array.arrayCompleteness = (tempByte >> ARRAY_COMPLETENESS_SHIFT) & 0x01;
101         array.nalUnitType = (tempByte & 0x3F);
102         heif_error error = ParseNalUnitArray(reader, array.nalUnits);
103         if (error) {
104             return error;
105         }
106         nalArrays_.push_back(std::move(array));
107     }
108     return reader.GetError();
109 }
110 
GetHeaders(std::vector<uint8_t> * outData) const111 bool HeifHvccBox::GetHeaders(std::vector<uint8_t>* outData) const
112 {
113     for (const auto& array : nalArrays_) {
114         for (const auto& unit : array.nalUnits) {
115             outData->push_back((unit.size() >> THREE_BYTES_SHIFT) & 0xFF);
116             outData->push_back((unit.size() >> TWO_BYTES_SHIFT) & 0xFF);
117             outData->push_back((unit.size() >> ONE_BYTE_SHIFT) & 0xFF);
118             outData->push_back((unit.size()) & 0xFF);
119             outData->insert(outData->end(), unit.begin(), unit.end());
120         }
121     }
122 
123     return true;
124 }
125 
AppendNalData(const std::vector<uint8_t> & nalData)126 void HeifHvccBox::AppendNalData(const std::vector<uint8_t>& nalData)
127 {
128     HvccNalArray array;
129     array.arrayCompleteness = 0;
130     array.nalUnitType = uint8_t(nalData[0] >> 1);
131     array.nalUnits.push_back(nalData);
132     nalArrays_.push_back(array);
133 }
134 
Write(HeifStreamWriter & writer) const135 heif_error HeifHvccBox::Write(HeifStreamWriter& writer) const
136 {
137     size_t boxStart = ReserveHeader(writer);
138 
139     const HvccConfig& config = config_;
140     writer.Write8(config.version);
141     writer.Write8((uint8_t) (((config.generalProfileSpace & 0x03) << GENGERAL_PROFILE_SPACE_SHIFT) |
142                              ((config.generalTierFlag & 0x01) << GENERAL_TIER_FLAG_SHIFT) |
143                              (config.generalProfileIdc & 0x1F)));
144     writer.Write32(config.generalProfileCompatibilityFlags);
145     writer.Write32((config.generalConstraintIndicatorFlags >> TWO_BYTES_SHIFT) & 0xFFFFFFFF);
146     writer.Write16((config.generalConstraintIndicatorFlags) & 0xFFFF);
147     writer.Write8(config.generalLevelIdc);
148     writer.Write16((config.minSpatialSegmentationIdc & 0x0FFF) | 0xF000);
149     writer.Write8((config.parallelismType & 0x03) | 0xFC);
150     writer.Write8((config.chromaFormat & 0x03) | 0xFC);
151     writer.Write8(((config.bitDepthLuma - BIT_DEPTH_DIFF) & 0x07) | 0xF8);
152     writer.Write8(((config.bitDepthChroma - BIT_DEPTH_DIFF) & 0x07) | 0xF8);
153     writer.Write16(config.avgFrameRate);
154     writer.Write8((uint8_t) (((config.constFrameRate & 0x03) << CONST_FRMAE_RATE_SHIFT) |
155                              ((config.numTemporalLayers & 0x07) << NUM_TEMPORAL_LAYERS_SHIFT) |
156                              ((config.temporalIdNested & 0x01) << TEMPORAL_ID_NESTED_SHIFT) |
157                              ((nalUnitLengthSize_ - NAL_UNIT_LENGTH_SIZE_DIFF) & 0x03)));
158 
159     size_t nArrays = nalArrays_.size();
160     writer.Write8((uint8_t) nArrays);
161     for (const HvccNalArray& array : nalArrays_) {
162         writer.Write8((uint8_t) (((array.arrayCompleteness & 0x01) << ARRAY_COMPLETENESS_SHIFT) |
163                                  (array.nalUnitType & 0x3F)));
164         size_t nUnits = array.nalUnits.size();
165         writer.Write16((uint16_t) nUnits);
166         for (const std::vector<uint8_t>& nalUnit : array.nalUnits) {
167             writer.Write16((uint16_t) nalUnit.size());
168             writer.Write(nalUnit);
169         }
170     }
171 
172     WriteCalculatedHeader(writer, boxStart);
173     return heif_error_ok;
174 }
175 
GetWord(const std::vector<uint8_t> & nalu,uint32_t length)176 uint32_t HeifHvccBox::GetWord(const std::vector<uint8_t>& nalu, uint32_t length)
177 {
178     uint32_t res = 0;
179     for (uint32_t i = 0; i < length && pos_ < boxBitLength_; ++i, ++pos_) {
180         uint32_t bit = ((nalu[pos_ / BIT_DEPTH_DIFF] >>
181                         (BIT_DEPTH_DIFF - BIT_SHIFT - (pos_ % BIT_DEPTH_DIFF)))
182                         & 0x01);
183         res <<= BIT_SHIFT;
184         res |= bit;
185     }
186     return res;
187 }
188 
GetGolombCode(const std::vector<uint8_t> & nalu)189 uint32_t HeifHvccBox::GetGolombCode(const std::vector<uint8_t> &nalu)
190 {
191     uint32_t zeros = 0;
192     while (pos_ < boxBitLength_ && ((nalu[pos_ / ONE_BYTE_SHIFT] >>
193            (ONE_BYTE_SHIFT - BIT_SHIFT - (pos_ % ONE_BYTE_SHIFT))) &
194            0x01) == 0x00) {
195         zeros++;
196         pos_++;
197     }
198     pos_++;
199     return GetWord(nalu, zeros) + ((BIT_SHIFT << zeros) - BIT_SHIFT);
200 }
201 
GetNaluTypeId(std::vector<uint8_t> & nalUnits)202 uint32_t HeifHvccBox::GetNaluTypeId(std::vector<uint8_t> &nalUnits)
203 {
204     if (nalUnits.empty()) {
205         return -1;
206     }
207     GetWord(nalUnits, READ_BIT_NUM_FLAG);
208     return GetWord(nalUnits, NALU_TYPE_ID_SIZE);
209 }
210 
GetNaluData(const std::vector<HvccNalArray> & nalArrays,uint8_t naluId)211 std::vector<uint8_t> HeifHvccBox::GetNaluData(const std::vector<HvccNalArray> &nalArrays,
212                                               uint8_t naluId)
213 {
214     for (auto HvccNalunit : nalArrays) {
215         if (HvccNalunit.nalUnitType == naluId && (!HvccNalunit.nalUnits.empty())) {
216             return HvccNalunit.nalUnits[0];
217         }
218     }
219     return std::vector<uint8_t>();
220 }
221 
ProcessBoxData(std::vector<uint8_t> & nalu)222 void HeifHvccBox::ProcessBoxData(std::vector<uint8_t> &nalu)
223 {
224     uint32_t naluSize = nalu.size();
225     std::vector<uint32_t> indicesToDelete;
226     for (uint32_t i = UINT16_BYTES_NUM; i < naluSize; ++i) {
227         if (nalu[i - UINT8_BYTES_NUM] == 0x00 &&
228             nalu[i - SKIP_DOUBLE_DATA_PROCESS_BYTE] == 0x00 && nalu[i] == 0x03) {
229             indicesToDelete.push_back(i);
230         }
231     }
232     for (auto it = indicesToDelete.rbegin(); it != indicesToDelete.rend(); ++it) {
233         nalu.erase(nalu.begin() + *it);
234     }
235 }
236 
ParserHvccColorRangeFlag(const std::vector<HvccNalArray> & nalArrays)237 bool HeifHvccBox::ParserHvccColorRangeFlag(const std::vector<HvccNalArray> &nalArrays)
238 {
239     auto spsBox = GetNaluData(nalArrays, SPS_BOX_TYPE);
240     if (spsBox.empty()) {
241         return false;
242     }
243     ProcessBoxData(spsBox);
244     if (!ParseNalUnitAnalysisSps(spsBox)) {
245         IMAGE_LOGD("Sps does not return a range flag");
246         return false;
247     }
248     return true;
249 }
250 
ProfileTierLevel(std::vector<uint8_t> & nalUnits,uint32_t profilePresentFlag,uint32_t maxNumSubLayerMinus1)251 void HeifHvccBox::ProfileTierLevel(std::vector<uint8_t> &nalUnits, uint32_t profilePresentFlag,
252                                    uint32_t maxNumSubLayerMinus1)
253 {
254     std::vector<uint32_t> generalProfileCompatibilityFlags;
255     std::vector<uint32_t> subLayerProfilePresentFlag;
256     std::vector<uint32_t> subLayerLevelPresentFlags;
257     std::vector<uint32_t> subLayerProfileIdcs;
258     std::vector<std::vector<uint32_t>> subLayerProfileCompatibilityFlags;
259     if (profilePresentFlag) {
260         GetWord(nalUnits, TEMPORAL_ID_NESTED_SHIFT);
261         GetWord(nalUnits, READ_BIT_NUM_FLAG);
262         GetWord(nalUnits, SUB_LAYER_PROFILE_IDC_SIZE); // general_profile_idc
263 
264         for (uint32_t j = 0; j < READ_GENERAL_PROFILE_IDC_NUM; ++j) {
265             uint32_t flag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
266             generalProfileCompatibilityFlags.push_back(flag);
267         }
268         GetWord(nalUnits, READ_BYTE_NUM_FLAG);
269         GetWord(nalUnits, READ_BYTE_NUM_FLAG);
270         GetWord(nalUnits, READ_GENERAL_PROFILE_IDC_NUM);
271     }
272     GetWord(nalUnits, READ_BYTE_NUM_FLAG);
273     subLayerProfilePresentFlag.resize(maxNumSubLayerMinus1);
274     for (uint32_t i = 0; i < maxNumSubLayerMinus1; ++i) {
275         subLayerProfilePresentFlag[i] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
276         subLayerLevelPresentFlags.push_back(GetWord(nalUnits, READ_BIT_NUM_FLAG));
277     }
278 
279     if (maxNumSubLayerMinus1 > 0) {
280         for (uint32_t i = maxNumSubLayerMinus1; i < READ_BYTE_NUM_FLAG; ++i) {
281             GetWord(nalUnits, READ_BIT_NUM_FLAG);
282             GetWord(nalUnits, READ_BIT_NUM_FLAG);
283         }
284     }
285 
286     subLayerProfileIdcs.resize(maxNumSubLayerMinus1);
287     subLayerProfileCompatibilityFlags.resize(maxNumSubLayerMinus1,
288                                              std::vector<uint32_t>(GENERAL_PROFILE_SIZE));
289     for (uint32_t i = 0; i < maxNumSubLayerMinus1; i++) {
290         if (subLayerProfilePresentFlag[i]) {
291             GetWord(nalUnits, SUB_LAYER_PRESENT_PROFILE_SIZE);
292             subLayerProfileIdcs[i] = GetWord(nalUnits, SUB_LAYER_PROFILE_IDC_SIZE);
293             for (uint32_t j = 0; j < GENERAL_PROFILE_SIZE; ++j) {
294                 subLayerProfileCompatibilityFlags[i][j] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
295             }
296 
297             // skip sub_layer_profile_idcs judge;
298             GetWord(nalUnits, READ_SUB_LAYER_PROFILE_IDCS);
299         }
300         if (subLayerLevelPresentFlags[i]) {
301             GetWord(nalUnits, READ_BYTE_NUM_FLAG);
302         }
303     }
304 }
305 
ParseNalUnitAnalysisSps(std::vector<uint8_t> & nalUnits)306 bool HeifHvccBox::ParseNalUnitAnalysisSps(std::vector<uint8_t> &nalUnits)
307 {
308     boxBitLength_ = nalUnits.size() * BIT_DEPTH_DIFF;
309     spsConfig_.forbiddenZeroBit = GetWord(nalUnits, READ_BIT_NUM_FLAG);
310     spsConfig_.nalUnitType = GetWord(nalUnits, NALU_TYPE_ID_SIZE);
311     if (spsConfig_.nalUnitType != SPS_BOX_TYPE) {
312         return false;
313     }
314     spsConfig_.nuhLayerId = GetWord(nalUnits, NUM_TEMPORAL_ID_SIZE);
315     GetWord(nalUnits, SUB_LAYER_MINUS);
316     return ParseSpsSyntax(nalUnits);
317 }
318 
ParseSpsSyntax(std::vector<uint8_t> & nalUnits)319 bool HeifHvccBox::ParseSpsSyntax(std::vector<uint8_t> &nalUnits)
320 {
321     //General sequence parameter set RBSP syntax
322     spsConfig_.spsVideoParameterSetId = GetWord(nalUnits, GENERAL_PROFILE_SIZE);
323     spsConfig_.spsMaxSubLayersMinus1 = GetWord(nalUnits, SUB_LAYER_MINUS);
324     spsConfig_.spsTemporalIdNestingFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
325 
326     //go to profile_tier_level parser
327     ProfileTierLevel(nalUnits,
328                      spsConfig_.spsTemporalIdNestingFlag,
329                      spsConfig_.spsMaxSubLayersMinus1);
330 
331     spsConfig_.spsVideoParameterSetId = GetGolombCode(nalUnits);
332     spsConfig_.chromaFormatIdc = GetGolombCode(nalUnits);
333     IMAGE_LOGD("HeifParser::SPS chromaFormatIdc is %{public}d", spsConfig_.chromaFormatIdc);
334     if (spsConfig_.chromaFormatIdc == SUB_LAYER_MINUS) {
335         spsConfig_.separateColourPlaneFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
336     }
337     spsConfig_.picWidthInLumaSamples = GetGolombCode(nalUnits);
338     spsConfig_.picHeightInLumaSamples = GetGolombCode(nalUnits);
339     IMAGE_LOGD("HeifParser::SPS picWidthInLumaSamples : %{public}d", spsConfig_.picWidthInLumaSamples);
340     IMAGE_LOGD("HeifParser::SPS picHeightInLumaSamples : %{public}d", spsConfig_.picHeightInLumaSamples);
341     spsConfig_.conformanceWindowFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
342     if (spsConfig_.conformanceWindowFlag == READ_BIT_NUM_FLAG) {
343         spsConfig_.confWinLefOffset = GetGolombCode(nalUnits);
344         spsConfig_.confWinRightOffset = GetGolombCode(nalUnits);
345         spsConfig_.confWinTopOffset = GetGolombCode(nalUnits);
346         spsConfig_.confWinBottomOffset = GetGolombCode(nalUnits);
347     }
348     spsConfig_.bitDepthLumaMinus8 = GetGolombCode(nalUnits);
349     spsConfig_.bitDepthChromaMinus8 = GetGolombCode(nalUnits);
350     IMAGE_LOGD("HeifParser::SPS bitDepthLumaMinus8 : %{public}d", spsConfig_.bitDepthLumaMinus8);
351     IMAGE_LOGD("HeifParser::SPS bitDepthChromaMinus8 : %{public}d", spsConfig_.bitDepthChromaMinus8);
352     spsConfig_.log2MaxPicOrderCntLsbMinus4 = GetGolombCode(nalUnits);
353     spsConfig_.spsSubLayerOrderingInfoPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
354     uint32_t i = spsConfig_.spsSubLayerOrderingInfoPresentFlag ? 0 : spsConfig_.spsMaxSubLayersMinus1;
355     for (; i <= spsConfig_.spsMaxSubLayersMinus1; i++) {
356         GetGolombCode(nalUnits);
357         GetGolombCode(nalUnits);
358         GetGolombCode(nalUnits);
359     }
360     GetGolombCode(nalUnits);
361     GetGolombCode(nalUnits);
362     GetGolombCode(nalUnits);
363     GetGolombCode(nalUnits);
364     GetGolombCode(nalUnits);
365     GetGolombCode(nalUnits);
366     return ParseSpsSyntaxScalingList(nalUnits);
367 }
368 
ReadGolombCodesForSizeId(std::vector<uint8_t> & nalUnits,uint32_t sizeId)369 void HeifHvccBox::ReadGolombCodesForSizeId(std::vector<uint8_t> &nalUnits, uint32_t sizeId)
370 {
371     uint8_t minCoefNum = READ_BIT_NUM_FLAG << (GENERAL_PROFILE_SIZE + (static_cast<uint8_t>(sizeId)
372                          << READ_BIT_NUM_FLAG));
373     uint32_t coefNum = MAX_COEF_NUM < minCoefNum ? MAX_COEF_NUM : minCoefNum;
374     if (sizeId > READ_BIT_NUM_FLAG) {
375         GetGolombCode(nalUnits);
376     }
377     for (uint32_t i = 0; i < coefNum; i++) {
378         GetGolombCode(nalUnits);
379     }
380 }
381 
ParseSpsScallListData(std::vector<uint8_t> & nalUnits)382 void HeifHvccBox::ParseSpsScallListData(std::vector<uint8_t> &nalUnits)
383 {
384     for (uint32_t sizeId = 0; sizeId < GENERAL_PROFILE_SIZE; ++sizeId) {
385         for (uint32_t matrixId = 0; matrixId < NUM_TEMPORAL_ID_SIZE;
386             matrixId += ((sizeId == SUB_LAYER_MINUS) ? SUB_LAYER_MINUS : READ_BIT_NUM_FLAG)) {
387             uint32_t tmpFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
388             if (!tmpFlag) {
389                 GetGolombCode(nalUnits);
390             } else {
391                 ReadGolombCodesForSizeId(nalUnits, sizeId);
392             }
393         }
394     }
395 }
396 
ParseSpsVuiParameter(std::vector<uint8_t> & nalUnits)397 bool HeifHvccBox::ParseSpsVuiParameter(std::vector<uint8_t> &nalUnits)
398 {
399     uint8_t aspectRatioInfoPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
400     if (aspectRatioInfoPresentFlag) {
401         uint32_t aspectRatioIdc = GetWord(nalUnits, READ_BYTE_NUM_FLAG);
402         if (aspectRatioIdc == EXTENDED_SAR) {
403             GetWord(nalUnits, READ_BIT_NUM_FLAG);
404         }
405     }
406     uint32_t overscanInfoPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
407     if (overscanInfoPresentFlag) {
408         GetWord(nalUnits, GENERAL_PROFILE_SIZE);
409     }
410     uint32_t videoSignalTypePresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
411     if (videoSignalTypePresentFlag) {
412         GetWord(nalUnits, SUB_LAYER_MINUS);
413         spsConfig_.videoRangeFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
414         IMAGE_LOGD("HeifParser::SPS videoRangeFlag : %{public}d", spsConfig_.videoRangeFlag);
415     }
416     return true;
417 }
418 
ParseStRefPicSet(std::vector<uint8_t> & nalUnits,uint32_t stRpsIdx,uint32_t numShortTermRefPicSets)419 void HeifHvccBox::ParseStRefPicSet(std::vector<uint8_t> &nalUnits, uint32_t stRpsIdx, uint32_t numShortTermRefPicSets)
420 {
421     RefPicSet rps;
422     if (stRpsIdx != 0) {
423         rps.interRefPicSetPredictionFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
424     } else {
425         rps.interRefPicSetPredictionFlag = 0;
426     }
427     if (rps.interRefPicSetPredictionFlag) {
428         if (stRpsIdx == numShortTermRefPicSets) {
429             rps.deltaIdxMinus1 = GetGolombCode(nalUnits);
430         } else {
431             rps.deltaIdxMinus1 = 0;
432         }
433         rps.deltaRpsSign = GetWord(nalUnits, READ_BIT_NUM_FLAG);
434         rps.absDeltaRpsMinus1 = GetGolombCode(nalUnits);
435 
436         uint32_t refRpsIdx = stRpsIdx - (rps.deltaIdxMinus1 + 1);
437         IMAGE_LOGD("HeifParser::SPS refRpsIdx : %{public}d", refRpsIdx);
438 
439         rps.usedByCurrPicFlag.resize(HEIF_NUM_DELTA_POCS);
440         rps.usedDeltaFlag.resize(HEIF_NUM_DELTA_POCS);
441 
442         for (uint32_t i = 0; i < HEIF_NUM_DELTA_POCS; i++) {
443             rps.usedDeltaFlag[i] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
444             if (!rps.usedByCurrPicFlag[i]) {
445                 rps.usedDeltaFlag[i] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
446             } else {
447                 rps.usedDeltaFlag[i] = HEIF_BASE_DELTA_FlAG;
448             }
449         }
450     } else {
451         rps.numNegativePics = GetGolombCode(nalUnits);
452         rps.numPositivePics = GetGolombCode(nalUnits);
453 
454         if (rps.numNegativePics > HEIF_MAX_IMAGE_DPB_SIZE || rps.numPositivePics > HEIF_MAX_IMAGE_DPB_SIZE) {
455             IMAGE_LOGE("HeifParser:: RPS pics-Buffering more than max");
456             return;
457         }
458         rps.deltaPocS0Minus1.resize(rps.numNegativePics);
459         rps.usedBycurrPicS0Flag.resize(rps.numNegativePics);
460 
461         for (uint32_t i = 0; i < rps.numNegativePics; i++) {
462             rps.deltaPocS0Minus1[i] = GetGolombCode(nalUnits);
463             rps.usedBycurrPicS0Flag[i] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
464         }
465 
466         rps.deltaPocS1Minus1.resize(rps.numPositivePics);
467         rps.usedBycurrPicS1Flag.resize(rps.numPositivePics);
468 
469         for (uint32_t i = 0; i < rps.numPositivePics; i++) {
470             rps.deltaPocS1Minus1[i] = GetGolombCode(nalUnits);
471             rps.usedBycurrPicS1Flag[i] = GetWord(nalUnits, READ_BIT_NUM_FLAG);
472         }
473     }
474 }
475 
ParseSpsSyntaxScalingList(std::vector<uint8_t> & nalUnits)476 bool HeifHvccBox::ParseSpsSyntaxScalingList(std::vector<uint8_t> &nalUnits)
477 {
478     spsConfig_.scalingListEnabeldFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
479     if (spsConfig_.scalingListEnabeldFlag == READ_BIT_NUM_FLAG) {
480         spsConfig_.scalingListEnabeldFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
481         if (spsConfig_.scalingListEnabeldFlag) {
482             ParseSpsScallListData(nalUnits);
483         }
484     }
485     GetWord(nalUnits, READ_BIT_NUM_FLAG);
486     GetWord(nalUnits, READ_BIT_NUM_FLAG);
487     spsConfig_.pcmEnabledFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
488     if (spsConfig_.pcmEnabledFlag == READ_BIT_NUM_FLAG) {
489         GetWord(nalUnits, PCM_ENABLED_FLAG);
490         GetWord(nalUnits, PCM_ENABLED_FLAG);
491         GetGolombCode(nalUnits);
492         GetGolombCode(nalUnits);
493         GetWord(nalUnits, READ_BIT_NUM_FLAG);
494     }
495     spsConfig_.numShortTermRefPicSets = GetGolombCode(nalUnits);
496     IMAGE_LOGD("HeifParser:: SPS numShortTermRefPicSets : %{public}d", spsConfig_.numShortTermRefPicSets);
497     for (uint32_t i = 0; i < spsConfig_.numShortTermRefPicSets; i++) {
498         ParseStRefPicSet(nalUnits, i, spsConfig_.numShortTermRefPicSets);
499     }
500     spsConfig_.longTermRefPicsPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
501     if (spsConfig_.longTermRefPicsPresentFlag == READ_BIT_NUM_FLAG) {
502         uint32_t numLongTermRefPicSps = GetGolombCode(nalUnits);
503         for (uint32_t i = 0; i < numLongTermRefPicSps; i++) {
504             // itRefPicPocLsbSps[i] == log2MaxPicOrderCntLsbMinus4 + 4
505             GetWord(nalUnits, spsConfig_.log2MaxPicOrderCntLsbMinus4 + GENERAL_PROFILE_SIZE);
506             GetWord(nalUnits, READ_BIT_NUM_FLAG);
507         }
508     }
509     GetWord(nalUnits, READ_BIT_NUM_FLAG);
510     GetWord(nalUnits, READ_BIT_NUM_FLAG);
511     spsConfig_.vuiParameterPresentFlag = GetWord(nalUnits, READ_BIT_NUM_FLAG);
512     if (spsConfig_.vuiParameterPresentFlag == READ_BIT_NUM_FLAG) {
513         return ParseSpsVuiParameter(nalUnits);
514     }
515     return false; // Skip parsing subsequent content
516 }
517 } // namespace ImagePlugin
518 } // namespace OHOS
519