1 /*
2 * Copyright (C) 2015 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 //#define LOG_NDEBUG 0
18 #define LOG_TAG "HevcUtils"
19
20 #include <cstring>
21 #include <utility>
22
23 #include "include/HevcUtils.h"
24
25 #include <media/stagefright/foundation/ABitReader.h>
26 #include <media/stagefright/foundation/ABuffer.h>
27 #include <media/stagefright/foundation/ADebug.h>
28 #include <media/stagefright/foundation/AMessage.h>
29 #include <media/stagefright/foundation/avc_utils.h>
30 #include <media/stagefright/MediaErrors.h>
31 #include <media/stagefright/Utils.h>
32
33 #define UNUSED_PARAM __attribute__((unused))
34
35 namespace android {
36
37 static const uint8_t kHevcNalUnitTypes[8] = {
38 kHevcNalUnitTypeCodedSliceIdr,
39 kHevcNalUnitTypeCodedSliceIdrNoLP,
40 kHevcNalUnitTypeCodedSliceCra,
41 kHevcNalUnitTypeVps,
42 kHevcNalUnitTypeSps,
43 kHevcNalUnitTypePps,
44 kHevcNalUnitTypePrefixSei,
45 kHevcNalUnitTypeSuffixSei,
46 };
47
HevcParameterSets()48 HevcParameterSets::HevcParameterSets()
49 : mInfo(kInfoNone) {
50 }
51
addNalUnit(const uint8_t * data,size_t size)52 status_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
53 if (size < 1) {
54 ALOGE("empty NAL b/35467107");
55 return ERROR_MALFORMED;
56 }
57 uint8_t nalUnitType = (data[0] >> 1) & 0x3f;
58 status_t err = OK;
59 switch (nalUnitType) {
60 case 32: // VPS
61 if (size < 2) {
62 ALOGE("invalid NAL/VPS size b/35467107");
63 return ERROR_MALFORMED;
64 }
65 err = parseVps(data + 2, size - 2);
66 break;
67 case 33: // SPS
68 if (size < 2) {
69 ALOGE("invalid NAL/SPS size b/35467107");
70 return ERROR_MALFORMED;
71 }
72 err = parseSps(data + 2, size - 2);
73 break;
74 case 34: // PPS
75 if (size < 2) {
76 ALOGE("invalid NAL/PPS size b/35467107");
77 return ERROR_MALFORMED;
78 }
79 err = parsePps(data + 2, size - 2);
80 break;
81 case 39: // Prefix SEI
82 case 40: // Suffix SEI
83 // Ignore
84 break;
85 default:
86 ALOGE("Unrecognized NAL unit type.");
87 return ERROR_MALFORMED;
88 }
89
90 if (err != OK) {
91 ALOGE("error parsing VPS or SPS or PPS");
92 return err;
93 }
94
95 sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
96 buffer->setInt32Data(nalUnitType);
97 mNalUnits.push(buffer);
98 return OK;
99 }
100
101 template <typename T>
findParam(uint32_t key,T * param,KeyedVector<uint32_t,uint64_t> & params)102 static bool findParam(uint32_t key, T *param,
103 KeyedVector<uint32_t, uint64_t> ¶ms) {
104 CHECK(param);
105 ssize_t index = params.indexOfKey(key);
106 if (index < 0) {
107 return false;
108 }
109 *param = (T) params[index];
110 return true;
111 }
112
findParam8(uint32_t key,uint8_t * param)113 bool HevcParameterSets::findParam8(uint32_t key, uint8_t *param) {
114 return findParam(key, param, mParams);
115 }
116
findParam16(uint32_t key,uint16_t * param)117 bool HevcParameterSets::findParam16(uint32_t key, uint16_t *param) {
118 return findParam(key, param, mParams);
119 }
120
findParam32(uint32_t key,uint32_t * param)121 bool HevcParameterSets::findParam32(uint32_t key, uint32_t *param) {
122 return findParam(key, param, mParams);
123 }
124
findParam64(uint32_t key,uint64_t * param)125 bool HevcParameterSets::findParam64(uint32_t key, uint64_t *param) {
126 return findParam(key, param, mParams);
127 }
128
getNumNalUnitsOfType(uint8_t type)129 size_t HevcParameterSets::getNumNalUnitsOfType(uint8_t type) {
130 size_t num = 0;
131 for (size_t i = 0; i < mNalUnits.size(); ++i) {
132 if (getType(i) == type) {
133 ++num;
134 }
135 }
136 return num;
137 }
138
getType(size_t index)139 uint8_t HevcParameterSets::getType(size_t index) {
140 CHECK_LT(index, mNalUnits.size());
141 return mNalUnits[index]->int32Data();
142 }
143
getSize(size_t index)144 size_t HevcParameterSets::getSize(size_t index) {
145 CHECK_LT(index, mNalUnits.size());
146 return mNalUnits[index]->size();
147 }
148
write(size_t index,uint8_t * dest,size_t size)149 bool HevcParameterSets::write(size_t index, uint8_t* dest, size_t size) {
150 CHECK_LT(index, mNalUnits.size());
151 const sp<ABuffer>& nalUnit = mNalUnits[index];
152 if (size < nalUnit->size()) {
153 ALOGE("dest buffer size too small: %zu vs. %zu to be written",
154 size, nalUnit->size());
155 return false;
156 }
157 memcpy(dest, nalUnit->data(), nalUnit->size());
158 return true;
159 }
160
parseVps(const uint8_t * data,size_t size)161 status_t HevcParameterSets::parseVps(const uint8_t* data, size_t size) {
162 // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.1 for reference
163 NALBitReader reader(data, size);
164 // Skip vps_video_parameter_set_id
165 reader.skipBits(4);
166 // Skip vps_base_layer_internal_flag
167 reader.skipBits(1);
168 // Skip vps_base_layer_available_flag
169 reader.skipBits(1);
170 // Skip vps_max_layers_minus_1
171 reader.skipBits(6);
172 // Skip vps_max_sub_layers_minus1
173 reader.skipBits(3);
174 // Skip vps_temporal_id_nesting_flags
175 reader.skipBits(1);
176 // Skip reserved
177 reader.skipBits(16);
178
179 if (reader.atLeastNumBitsLeft(96)) {
180 mParams.add(kGeneralProfileSpace, reader.getBits(2));
181 mParams.add(kGeneralTierFlag, reader.getBits(1));
182 mParams.add(kGeneralProfileIdc, reader.getBits(5));
183 mParams.add(kGeneralProfileCompatibilityFlags, reader.getBits(32));
184 mParams.add(
185 kGeneralConstraintIndicatorFlags,
186 ((uint64_t)reader.getBits(16) << 32) | reader.getBits(32));
187 mParams.add(kGeneralLevelIdc, reader.getBits(8));
188 // 96 bits total for general profile.
189 } else {
190 reader.skipBits(96);
191 }
192
193 return reader.overRead() ? ERROR_MALFORMED : OK;
194 }
195
parseSps(const uint8_t * data,size_t size)196 status_t HevcParameterSets::parseSps(const uint8_t* data, size_t size) {
197 // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.2 for reference
198 NALBitReader reader(data, size);
199 // Skip sps_video_parameter_set_id
200 reader.skipBits(4);
201 uint8_t maxSubLayersMinus1 = reader.getBitsWithFallback(3, 0);
202 // Skip sps_temporal_id_nesting_flag;
203 reader.skipBits(1);
204 // Skip general profile
205 reader.skipBits(96);
206 if (maxSubLayersMinus1 > 0) {
207 bool subLayerProfilePresentFlag[8];
208 bool subLayerLevelPresentFlag[8];
209 for (int i = 0; i < maxSubLayersMinus1; ++i) {
210 subLayerProfilePresentFlag[i] = reader.getBitsWithFallback(1, 0);
211 subLayerLevelPresentFlag[i] = reader.getBitsWithFallback(1, 0);
212 }
213 // Skip reserved
214 reader.skipBits(2 * (8 - maxSubLayersMinus1));
215 for (int i = 0; i < maxSubLayersMinus1; ++i) {
216 if (subLayerProfilePresentFlag[i]) {
217 // Skip profile
218 reader.skipBits(88);
219 }
220 if (subLayerLevelPresentFlag[i]) {
221 // Skip sub_layer_level_idc[i]
222 reader.skipBits(8);
223 }
224 }
225 }
226 // Skip sps_seq_parameter_set_id
227 skipUE(&reader);
228 uint8_t chromaFormatIdc = parseUEWithFallback(&reader, 0);
229 mParams.add(kChromaFormatIdc, chromaFormatIdc);
230 if (chromaFormatIdc == 3) {
231 // Skip separate_colour_plane_flag
232 reader.skipBits(1);
233 }
234 // Skip pic_width_in_luma_samples
235 skipUE(&reader);
236 // Skip pic_height_in_luma_samples
237 skipUE(&reader);
238 if (reader.getBitsWithFallback(1, 0) /* i.e. conformance_window_flag */) {
239 // Skip conf_win_left_offset
240 skipUE(&reader);
241 // Skip conf_win_right_offset
242 skipUE(&reader);
243 // Skip conf_win_top_offset
244 skipUE(&reader);
245 // Skip conf_win_bottom_offset
246 skipUE(&reader);
247 }
248 mParams.add(kBitDepthLumaMinus8, parseUEWithFallback(&reader, 0));
249 mParams.add(kBitDepthChromaMinus8, parseUEWithFallback(&reader, 0));
250
251 // log2_max_pic_order_cnt_lsb_minus4
252 size_t log2MaxPicOrderCntLsb = parseUEWithFallback(&reader, 0) + (size_t)4;
253 bool spsSubLayerOrderingInfoPresentFlag = reader.getBitsWithFallback(1, 0);
254 for (uint32_t i = spsSubLayerOrderingInfoPresentFlag ? 0 : maxSubLayersMinus1;
255 i <= maxSubLayersMinus1; ++i) {
256 skipUE(&reader); // sps_max_dec_pic_buffering_minus1[i]
257 skipUE(&reader); // sps_max_num_reorder_pics[i]
258 skipUE(&reader); // sps_max_latency_increase_plus1[i]
259 }
260
261 skipUE(&reader); // log2_min_luma_coding_block_size_minus3
262 skipUE(&reader); // log2_diff_max_min_luma_coding_block_size
263 skipUE(&reader); // log2_min_luma_transform_block_size_minus2
264 skipUE(&reader); // log2_diff_max_min_luma_transform_block_size
265 skipUE(&reader); // max_transform_hierarchy_depth_inter
266 skipUE(&reader); // max_transform_hierarchy_depth_intra
267 if (reader.getBitsWithFallback(1, 0)) { // scaling_list_enabled_flag u(1)
268 // scaling_list_data
269 if (reader.getBitsWithFallback(1, 0)) { // sps_scaling_list_data_present_flag
270 for (uint32_t sizeId = 0; sizeId < 4; ++sizeId) {
271 for (uint32_t matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
272 if (!reader.getBitsWithFallback(1, 1)) {
273 // scaling_list_pred_mode_flag[sizeId][matrixId]
274 skipUE(&reader); // scaling_list_pred_matrix_id_delta[sizeId][matrixId]
275 } else {
276 uint32_t coefNum = std::min(64, (1 << (4 + (sizeId << 1))));
277 if (sizeId > 1) {
278 skipSE(&reader); // scaling_list_dc_coef_minus8[sizeId − 2][matrixId]
279 }
280 for (uint32_t i = 0; i < coefNum; ++i) {
281 skipSE(&reader); // scaling_list_delta_coef
282 }
283 }
284 }
285 }
286 }
287 }
288 reader.skipBits(1); // amp_enabled_flag
289 reader.skipBits(1); // sample_adaptive_offset_enabled_flag u(1)
290 if (reader.getBitsWithFallback(1, 0)) { // pcm_enabled_flag
291 reader.skipBits(4); // pcm_sample_bit_depth_luma_minus1
292 reader.skipBits(4); // pcm_sample_bit_depth_chroma_minus1 u(4)
293 skipUE(&reader); // log2_min_pcm_luma_coding_block_size_minus3
294 skipUE(&reader); // log2_diff_max_min_pcm_luma_coding_block_size
295 reader.skipBits(1); // pcm_loop_filter_disabled_flag
296 }
297 uint32_t numShortTermRefPicSets = parseUEWithFallback(&reader, 0);
298 uint32_t numPics = 0;
299 for (uint32_t i = 0; i < numShortTermRefPicSets; ++i) {
300 // st_ref_pic_set(i)
301 if (i != 0 && reader.getBitsWithFallback(1, 0)) { // inter_ref_pic_set_prediction_flag
302 reader.skipBits(1); // delta_rps_sign
303 skipUE(&reader); // abs_delta_rps_minus1
304 uint32_t nextNumPics = 0;
305 for (uint32_t j = 0; j <= numPics; ++j) {
306 if (reader.getBitsWithFallback(1, 0) // used_by_curr_pic_flag[j]
307 || reader.getBitsWithFallback(1, 0)) { // use_delta_flag[j]
308 ++nextNumPics;
309 }
310 }
311 numPics = nextNumPics;
312 } else {
313 uint32_t numNegativePics = parseUEWithFallback(&reader, 0);
314 uint32_t numPositivePics = parseUEWithFallback(&reader, 0);
315 if (numNegativePics > UINT32_MAX - numPositivePics) {
316 return ERROR_MALFORMED;
317 }
318 numPics = numNegativePics + numPositivePics;
319 for (uint32_t j = 0; j < numPics; ++j) {
320 skipUE(&reader); // delta_poc_s0|1_minus1[i]
321 reader.skipBits(1); // used_by_curr_pic_s0|1_flag[i]
322 if (reader.overRead()) {
323 return ERROR_MALFORMED;
324 }
325 }
326 }
327 if (reader.overRead()) {
328 return ERROR_MALFORMED;
329 }
330 }
331 if (reader.getBitsWithFallback(1, 0)) { // long_term_ref_pics_present_flag
332 uint32_t numLongTermRefPicSps = parseUEWithFallback(&reader, 0);
333 for (uint32_t i = 0; i < numLongTermRefPicSps; ++i) {
334 reader.skipBits(log2MaxPicOrderCntLsb); // lt_ref_pic_poc_lsb_sps[i]
335 reader.skipBits(1); // used_by_curr_pic_lt_sps_flag[i]
336 if (reader.overRead()) {
337 return ERROR_MALFORMED;
338 }
339 }
340 }
341 reader.skipBits(1); // sps_temporal_mvp_enabled_flag
342 reader.skipBits(1); // strong_intra_smoothing_enabled_flag
343 if (reader.getBitsWithFallback(1, 0)) { // vui_parameters_present_flag
344 if (reader.getBitsWithFallback(1, 0)) { // aspect_ratio_info_present_flag
345 uint32_t aspectRatioIdc = reader.getBitsWithFallback(8, 0);
346 if (aspectRatioIdc == 0xFF /* EXTENDED_SAR */) {
347 reader.skipBits(16); // sar_width
348 reader.skipBits(16); // sar_height
349 }
350 }
351 if (reader.getBitsWithFallback(1, 0)) { // overscan_info_present_flag
352 reader.skipBits(1); // overscan_appropriate_flag
353 }
354 if (reader.getBitsWithFallback(1, 0)) { // video_signal_type_present_flag
355 reader.skipBits(3); // video_format
356 uint32_t videoFullRangeFlag;
357 if (reader.getBitsGraceful(1, &videoFullRangeFlag)) {
358 mParams.add(kVideoFullRangeFlag, videoFullRangeFlag);
359 }
360 if (reader.getBitsWithFallback(1, 0)) { // colour_description_present_flag
361 mInfo = (Info)(mInfo | kInfoHasColorDescription);
362 uint32_t colourPrimaries, transferCharacteristics, matrixCoeffs;
363 if (reader.getBitsGraceful(8, &colourPrimaries)) {
364 mParams.add(kColourPrimaries, colourPrimaries);
365 }
366 if (reader.getBitsGraceful(8, &transferCharacteristics)) {
367 mParams.add(kTransferCharacteristics, transferCharacteristics);
368 if (transferCharacteristics == 16 /* ST 2084 */
369 || transferCharacteristics == 18 /* ARIB STD-B67 HLG */) {
370 mInfo = (Info)(mInfo | kInfoIsHdr);
371 }
372 }
373 if (reader.getBitsGraceful(8, &matrixCoeffs)) {
374 mParams.add(kMatrixCoeffs, matrixCoeffs);
375 }
376 }
377 // skip rest of VUI
378 }
379 }
380
381 return reader.overRead() ? ERROR_MALFORMED : OK;
382 }
383
FindHEVCDimensions(const sp<ABuffer> & SpsBuffer,int32_t * width,int32_t * height)384 void HevcParameterSets::FindHEVCDimensions(const sp<ABuffer> &SpsBuffer, int32_t *width, int32_t *height)
385 {
386 ALOGD("FindHEVCDimensions");
387 // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.2 for reference
388 ABitReader reader(SpsBuffer->data() + 1, SpsBuffer->size() - 1);
389 // Skip sps_video_parameter_set_id
390 reader.skipBits(4);
391 uint8_t maxSubLayersMinus1 = reader.getBitsWithFallback(3, 0);
392 // Skip sps_temporal_id_nesting_flag;
393 reader.skipBits(1);
394 // Skip general profile
395 reader.skipBits(96);
396 if (maxSubLayersMinus1 > 0) {
397 bool subLayerProfilePresentFlag[8];
398 bool subLayerLevelPresentFlag[8];
399 for (int i = 0; i < maxSubLayersMinus1; ++i) {
400 subLayerProfilePresentFlag[i] = reader.getBitsWithFallback(1, 0);
401 subLayerLevelPresentFlag[i] = reader.getBitsWithFallback(1, 0);
402 }
403 // Skip reserved
404 reader.skipBits(2 * (8 - maxSubLayersMinus1));
405 for (int i = 0; i < maxSubLayersMinus1; ++i) {
406 if (subLayerProfilePresentFlag[i]) {
407 // Skip profile
408 reader.skipBits(88);
409 }
410 if (subLayerLevelPresentFlag[i]) {
411 // Skip sub_layer_level_idc[i]
412 reader.skipBits(8);
413 }
414 }
415 }
416 // Skip sps_seq_parameter_set_id
417 skipUE(&reader);
418 uint8_t chromaFormatIdc = parseUEWithFallback(&reader, 0);
419 if (chromaFormatIdc == 3) {
420 // Skip separate_colour_plane_flag
421 reader.skipBits(1);
422 }
423 skipUE(&reader);
424 skipUE(&reader);
425
426 // pic_width_in_luma_samples
427 *width = parseUEWithFallback(&reader, 0);
428 // pic_height_in_luma_samples
429 *height = parseUEWithFallback(&reader, 0);
430 }
431
parsePps(const uint8_t * data UNUSED_PARAM,size_t size UNUSED_PARAM)432 status_t HevcParameterSets::parsePps(
433 const uint8_t* data UNUSED_PARAM, size_t size UNUSED_PARAM) {
434 return OK;
435 }
436
makeHvcc(uint8_t * hvcc,size_t * hvccSize,size_t nalSizeLength)437 status_t HevcParameterSets::makeHvcc(uint8_t *hvcc, size_t *hvccSize,
438 size_t nalSizeLength) {
439 if (hvcc == NULL || hvccSize == NULL
440 || (nalSizeLength != 4 && nalSizeLength != 2)) {
441 return BAD_VALUE;
442 }
443 // ISO 14496-15: HEVC file format
444 size_t size = 23; // 23 bytes in the header
445 size_t numOfArrays = 0;
446 const size_t numNalUnits = getNumNalUnits();
447 for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
448 uint8_t type = kHevcNalUnitTypes[i];
449 size_t numNalus = getNumNalUnitsOfType(type);
450 if (numNalus == 0) {
451 continue;
452 }
453 ++numOfArrays;
454 size += 3;
455 for (size_t j = 0; j < numNalUnits; ++j) {
456 if (getType(j) != type) {
457 continue;
458 }
459 size += 2 + getSize(j);
460 }
461 }
462 uint8_t generalProfileSpace, generalTierFlag, generalProfileIdc;
463 if (!findParam8(kGeneralProfileSpace, &generalProfileSpace)
464 || !findParam8(kGeneralTierFlag, &generalTierFlag)
465 || !findParam8(kGeneralProfileIdc, &generalProfileIdc)) {
466 return ERROR_MALFORMED;
467 }
468 uint32_t compatibilityFlags;
469 uint64_t constraintIdcFlags;
470 if (!findParam32(kGeneralProfileCompatibilityFlags, &compatibilityFlags)
471 || !findParam64(kGeneralConstraintIndicatorFlags, &constraintIdcFlags)) {
472 return ERROR_MALFORMED;
473 }
474 uint8_t generalLevelIdc;
475 if (!findParam8(kGeneralLevelIdc, &generalLevelIdc)) {
476 return ERROR_MALFORMED;
477 }
478 uint8_t chromaFormatIdc, bitDepthLumaMinus8, bitDepthChromaMinus8;
479 if (!findParam8(kChromaFormatIdc, &chromaFormatIdc)
480 || !findParam8(kBitDepthLumaMinus8, &bitDepthLumaMinus8)
481 || !findParam8(kBitDepthChromaMinus8, &bitDepthChromaMinus8)) {
482 return ERROR_MALFORMED;
483 }
484 if (size > *hvccSize) {
485 return NO_MEMORY;
486 }
487 *hvccSize = size;
488
489 uint8_t *header = hvcc;
490 header[0] = 1;
491 header[1] = (generalProfileSpace << 6) | (generalTierFlag << 5) | generalProfileIdc;
492 header[2] = (compatibilityFlags >> 24) & 0xff;
493 header[3] = (compatibilityFlags >> 16) & 0xff;
494 header[4] = (compatibilityFlags >> 8) & 0xff;
495 header[5] = compatibilityFlags & 0xff;
496 header[6] = (constraintIdcFlags >> 40) & 0xff;
497 header[7] = (constraintIdcFlags >> 32) & 0xff;
498 header[8] = (constraintIdcFlags >> 24) & 0xff;
499 header[9] = (constraintIdcFlags >> 16) & 0xff;
500 header[10] = (constraintIdcFlags >> 8) & 0xff;
501 header[11] = constraintIdcFlags & 0xff;
502 header[12] = generalLevelIdc;
503 // FIXME: parse min_spatial_segmentation_idc.
504 header[13] = 0xf0;
505 header[14] = 0;
506 // FIXME: derive parallelismType properly.
507 header[15] = 0xfc;
508 header[16] = 0xfc | chromaFormatIdc;
509 header[17] = 0xf8 | bitDepthLumaMinus8;
510 header[18] = 0xf8 | bitDepthChromaMinus8;
511 // FIXME: derive avgFrameRate
512 header[19] = 0;
513 header[20] = 0;
514 // constantFrameRate, numTemporalLayers, temporalIdNested all set to 0.
515 header[21] = nalSizeLength - 1;
516 header[22] = numOfArrays;
517 header += 23;
518 for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
519 uint8_t type = kHevcNalUnitTypes[i];
520 size_t numNalus = getNumNalUnitsOfType(type);
521 if (numNalus == 0) {
522 continue;
523 }
524 // array_completeness set to 1.
525 header[0] = type | 0x80;
526 header[1] = (numNalus >> 8) & 0xff;
527 header[2] = numNalus & 0xff;
528 header += 3;
529 for (size_t j = 0; j < numNalUnits; ++j) {
530 if (getType(j) != type) {
531 continue;
532 }
533 header[0] = (getSize(j) >> 8) & 0xff;
534 header[1] = getSize(j) & 0xff;
535 if (!write(j, header + 2, size - (header - (uint8_t *)hvcc))) {
536 return NO_MEMORY;
537 }
538 header += (2 + getSize(j));
539 }
540 }
541 CHECK_EQ(header - size, hvcc);
542
543 return OK;
544 }
545
IsHevcIDR(const uint8_t * data,size_t size)546 bool HevcParameterSets::IsHevcIDR(const uint8_t *data, size_t size) {
547 bool foundIDR = false;
548 const uint8_t *nalStart;
549 size_t nalSize;
550 while (!foundIDR && getNextNALUnit(&data, &size, &nalStart, &nalSize, true) == OK) {
551 if (nalSize == 0) {
552 ALOGE("Encountered zero-length HEVC NAL");
553 return false;
554 }
555
556 uint8_t nalType = (nalStart[0] & 0x7E) >> 1;
557 switch(nalType) {
558 case kHevcNalUnitTypeCodedSliceIdr:
559 case kHevcNalUnitTypeCodedSliceIdrNoLP:
560 case kHevcNalUnitTypeCodedSliceCra:
561 foundIDR = true;
562 break;
563 }
564 }
565
566 return foundIDR;
567 }
568 } // namespace android
569