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