• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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> &params) {
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