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     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