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