19aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim/*
29aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * Copyright (C) 2015 The Android Open Source Project
39aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim *
49aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * Licensed under the Apache License, Version 2.0 (the "License");
59aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * you may not use this file except in compliance with the License.
69aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * You may obtain a copy of the License at
79aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim *
89aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim *      http://www.apache.org/licenses/LICENSE-2.0
99aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim *
109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * Unless required by applicable law or agreed to in writing, software
119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * distributed under the License is distributed on an "AS IS" BASIS,
129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * See the License for the specific language governing permissions and
149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim * limitations under the License.
159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim */
169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim//#define LOG_NDEBUG 0
189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#define LOG_TAG "HevcUtils"
199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <cstring>
2172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar#include <utility>
229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include "include/HevcUtils.h"
249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <media/stagefright/foundation/ABitReader.h>
269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <media/stagefright/foundation/ABuffer.h>
279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <media/stagefright/foundation/ADebug.h>
289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <media/stagefright/foundation/AMessage.h>
29d91dc5a0602f54fc0d4d2187f37b5b8169bb62c3Dongwon Kang#include <media/stagefright/foundation/avc_utils.h>
309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <media/stagefright/MediaErrors.h>
319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim#include <media/stagefright/Utils.h>
329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimnamespace android {
349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic const uint8_t kHevcNalUnitTypes[5] = {
369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeVps,
379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSps,
389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePps,
399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypePrefixSei,
409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    kHevcNalUnitTypeSuffixSei,
419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim};
429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
4372061e5ab52d12c17054aeffbb2299a002b6b53aLajos MolnarHevcParameterSets::HevcParameterSets()
4472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    : mInfo(kInfoNone) {
459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t HevcParameterSets::addNalUnit(const uint8_t* data, size_t size) {
48e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick    if (size < 1) {
49e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick        ALOGE("empty NAL b/35467107");
50e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick        return ERROR_MALFORMED;
51e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick    }
529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t nalUnitType = (data[0] >> 1) & 0x3f;
539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    status_t err = OK;
549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    switch (nalUnitType) {
559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case 32:  // VPS
56e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick            if (size < 2) {
57e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick                ALOGE("invalid NAL/VPS size b/35467107");
58e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick                return ERROR_MALFORMED;
59e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick            }
609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            err = parseVps(data + 2, size - 2);
619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            break;
629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case 33:  // SPS
63e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick            if (size < 2) {
64e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick                ALOGE("invalid NAL/SPS size b/35467107");
65e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick                return ERROR_MALFORMED;
66e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick            }
679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            err = parseSps(data + 2, size - 2);
689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            break;
699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case 34:  // PPS
70e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick            if (size < 2) {
71e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick                ALOGE("invalid NAL/PPS size b/35467107");
72e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick                return ERROR_MALFORMED;
73e0dcf097cc029d056926029a29419e1650cbdf1bRay Essick            }
749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            err = parsePps(data + 2, size - 2);
759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            break;
769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case 39:  // Prefix SEI
779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        case 40:  // Suffix SEI
789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            // Ignore
799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            break;
809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        default:
819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ALOGE("Unrecognized NAL unit type.");
829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            return ERROR_MALFORMED;
839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (err != OK) {
869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return err;
879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    buffer->setInt32Data(nalUnitType);
919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mNalUnits.push(buffer);
929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimtemplate <typename T>
969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatic bool findParam(uint32_t key, T *param,
979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        KeyedVector<uint32_t, uint64_t> &params) {
989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK(param);
999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (params.indexOfKey(key) < 0) {
1009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return false;
1019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
1029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    *param = (T) params[key];
1039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return true;
1049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimbool HevcParameterSets::findParam8(uint32_t key, uint8_t *param) {
1079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return findParam(key, param, mParams);
1089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimbool HevcParameterSets::findParam16(uint32_t key, uint16_t *param) {
1119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return findParam(key, param, mParams);
1129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimbool HevcParameterSets::findParam32(uint32_t key, uint32_t *param) {
1159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return findParam(key, param, mParams);
1169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimbool HevcParameterSets::findParam64(uint32_t key, uint64_t *param) {
1199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return findParam(key, param, mParams);
1209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimsize_t HevcParameterSets::getNumNalUnitsOfType(uint8_t type) {
1239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t num = 0;
1249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < mNalUnits.size(); ++i) {
1259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (getType(i) == type) {
1269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            ++num;
1279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
1289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
1299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return num;
1309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimuint8_t HevcParameterSets::getType(size_t index) {
1339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_LT(index, mNalUnits.size());
1349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return mNalUnits[index]->int32Data();
1359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimsize_t HevcParameterSets::getSize(size_t index) {
1389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_LT(index, mNalUnits.size());
1399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return mNalUnits[index]->size();
1409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimbool HevcParameterSets::write(size_t index, uint8_t* dest, size_t size) {
1439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_LT(index, mNalUnits.size());
1449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const sp<ABuffer>& nalUnit = mNalUnits[index];
1459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size < nalUnit->size()) {
1469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ALOGE("dest buffer size too small: %zu vs. %zu to be written",
1479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                size, nalUnit->size());
1489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return false;
1499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
1509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    memcpy(dest, nalUnit->data(), nalUnit->size());
1519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return true;
1529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t HevcParameterSets::parseVps(const uint8_t* data, size_t size) {
1559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.1 for reference
1569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    NALBitReader reader(data, size);
1579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip vps_video_parameter_set_id
1589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(4);
1599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip vps_base_layer_internal_flag
1609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(1);
1619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip vps_base_layer_available_flag
1629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(1);
1639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip vps_max_layers_minus_1
1649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(6);
165c7771064eb299127815eeb01d7b1fd9dc3097e85Chong Zhang    // Skip vps_max_sub_layers_minus1
166c7771064eb299127815eeb01d7b1fd9dc3097e85Chong Zhang    reader.skipBits(3);
1679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip vps_temporal_id_nesting_flags
1689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(1);
1699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip reserved
1709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(16);
1719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
17205b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    if (reader.atLeastNumBitsLeft(96)) {
17305b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        mParams.add(kGeneralProfileSpace, reader.getBits(2));
17405b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        mParams.add(kGeneralTierFlag, reader.getBits(1));
17505b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        mParams.add(kGeneralProfileIdc, reader.getBits(5));
17605b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        mParams.add(kGeneralProfileCompatibilityFlags, reader.getBits(32));
17705b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        mParams.add(
17805b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar                kGeneralConstraintIndicatorFlags,
17905b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar                ((uint64_t)reader.getBits(16) << 32) | reader.getBits(32));
18005b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        mParams.add(kGeneralLevelIdc, reader.getBits(8));
18105b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        // 96 bits total for general profile.
18205b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    } else {
18305b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        reader.skipBits(96);
18405b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    }
1859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
18605b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    return reader.overRead() ? ERROR_MALFORMED : OK;
1879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
1889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
1899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t HevcParameterSets::parseSps(const uint8_t* data, size_t size) {
1909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // See Rec. ITU-T H.265 v3 (04/2015) Chapter 7.3.2.2 for reference
1919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    NALBitReader reader(data, size);
1929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip sps_video_parameter_set_id
1939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(4);
19405b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    uint8_t maxSubLayersMinus1 = reader.getBitsWithFallback(3, 0);
1959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip sps_temporal_id_nesting_flag;
1969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(1);
1979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip general profile
1989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    reader.skipBits(96);
1999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (maxSubLayersMinus1 > 0) {
2009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bool subLayerProfilePresentFlag[8];
2019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        bool subLayerLevelPresentFlag[8];
2029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (int i = 0; i < maxSubLayersMinus1; ++i) {
20305b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar            subLayerProfilePresentFlag[i] = reader.getBitsWithFallback(1, 0);
20405b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar            subLayerLevelPresentFlag[i] = reader.getBitsWithFallback(1, 0);
2059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
2069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Skip reserved
2079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        reader.skipBits(2 * (8 - maxSubLayersMinus1));
2089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (int i = 0; i < maxSubLayersMinus1; ++i) {
2099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (subLayerProfilePresentFlag[i]) {
2109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                // Skip profile
2119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                reader.skipBits(88);
2129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
2139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (subLayerLevelPresentFlag[i]) {
2149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                // Skip sub_layer_level_idc[i]
2159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                reader.skipBits(8);
2169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
2179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
2189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
2199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip sps_seq_parameter_set_id
22005b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    skipUE(&reader);
22105b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    uint8_t chromaFormatIdc = parseUEWithFallback(&reader, 0);
2229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    mParams.add(kChromaFormatIdc, chromaFormatIdc);
2239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (chromaFormatIdc == 3) {
2249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Skip separate_colour_plane_flag
2259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        reader.skipBits(1);
2269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
2279aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip pic_width_in_luma_samples
22805b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    skipUE(&reader);
2299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // Skip pic_height_in_luma_samples
23005b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    skipUE(&reader);
23105b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    if (reader.getBitsWithFallback(1, 0) /* i.e. conformance_window_flag */) {
2329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Skip conf_win_left_offset
23305b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        skipUE(&reader);
2349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Skip conf_win_right_offset
23505b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        skipUE(&reader);
2369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Skip conf_win_top_offset
23705b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        skipUE(&reader);
2389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // Skip conf_win_bottom_offset
23905b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar        skipUE(&reader);
2409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
24105b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    mParams.add(kBitDepthLumaMinus8, parseUEWithFallback(&reader, 0));
24205b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    mParams.add(kBitDepthChromaMinus8, parseUEWithFallback(&reader, 0));
2439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
24472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    // log2_max_pic_order_cnt_lsb_minus4
24572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    size_t log2MaxPicOrderCntLsb = parseUEWithFallback(&reader, 0) + (size_t)4;
24672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    bool spsSubLayerOrderingInfoPresentFlag = reader.getBitsWithFallback(1, 0);
24772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    for (uint32_t i = spsSubLayerOrderingInfoPresentFlag ? 0 : maxSubLayersMinus1;
24872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            i <= maxSubLayersMinus1; ++i) {
24972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        skipUE(&reader); // sps_max_dec_pic_buffering_minus1[i]
25072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        skipUE(&reader); // sps_max_num_reorder_pics[i]
25172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        skipUE(&reader); // sps_max_latency_increase_plus1[i]
25272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    }
25372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar
25472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    skipUE(&reader); // log2_min_luma_coding_block_size_minus3
25572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    skipUE(&reader); // log2_diff_max_min_luma_coding_block_size
25672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    skipUE(&reader); // log2_min_luma_transform_block_size_minus2
25772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    skipUE(&reader); // log2_diff_max_min_luma_transform_block_size
25872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    skipUE(&reader); // max_transform_hierarchy_depth_inter
25972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    skipUE(&reader); // max_transform_hierarchy_depth_intra
26072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    if (reader.getBitsWithFallback(1, 0)) { // scaling_list_enabled_flag u(1)
26172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        // scaling_list_data
26272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        if (reader.getBitsWithFallback(1, 0)) { // sps_scaling_list_data_present_flag
26372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            for (uint32_t sizeId = 0; sizeId < 4; ++sizeId) {
26472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                for (uint32_t matrixId = 0; matrixId < 6; matrixId += (sizeId == 3) ? 3 : 1) {
26572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    if (!reader.getBitsWithFallback(1, 1)) {
26672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        // scaling_list_pred_mode_flag[sizeId][matrixId]
26772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        skipUE(&reader); // scaling_list_pred_matrix_id_delta[sizeId][matrixId]
26872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    } else {
26972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        uint32_t coefNum = std::min(64, (1 << (4 + (sizeId << 1))));
27072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        if (sizeId > 1) {
27172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                            skipSE(&reader); // scaling_list_dc_coef_minus8[sizeId − 2][matrixId]
27272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        }
27372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        for (uint32_t i = 0; i < coefNum; ++i) {
27472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                            skipSE(&reader); // scaling_list_delta_coef
27572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        }
27672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    }
27772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                }
27872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
27972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        }
28072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    }
28172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    reader.skipBits(1); // amp_enabled_flag
28272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    reader.skipBits(1); // sample_adaptive_offset_enabled_flag u(1)
28372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    if (reader.getBitsWithFallback(1, 0)) { // pcm_enabled_flag
28472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        reader.skipBits(4); // pcm_sample_bit_depth_luma_minus1
28572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        reader.skipBits(4); // pcm_sample_bit_depth_chroma_minus1 u(4)
28672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        skipUE(&reader); // log2_min_pcm_luma_coding_block_size_minus3
28772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        skipUE(&reader); // log2_diff_max_min_pcm_luma_coding_block_size
28872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        reader.skipBits(1); // pcm_loop_filter_disabled_flag
28972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    }
29072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    uint32_t numShortTermRefPicSets = parseUEWithFallback(&reader, 0);
29172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    uint32_t numPics = 0;
29272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    for (uint32_t i = 0; i < numShortTermRefPicSets; ++i) {
29372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        // st_ref_pic_set(i)
29472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        if (i != 0 && reader.getBitsWithFallback(1, 0)) { // inter_ref_pic_set_prediction_flag
29572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            reader.skipBits(1); // delta_rps_sign
29672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            skipUE(&reader); // abs_delta_rps_minus1
29772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            uint32_t nextNumPics = 0;
29872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            for (uint32_t j = 0; j <= numPics; ++j) {
29972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                if (reader.getBitsWithFallback(1, 0) // used_by_curr_pic_flag[j]
30072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        || reader.getBitsWithFallback(1, 0)) { // use_delta_flag[j]
30172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    ++nextNumPics;
30272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                }
30372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
30472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            numPics = nextNumPics;
30572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        } else {
30672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            uint32_t numNegativePics = parseUEWithFallback(&reader, 0);
30772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            uint32_t numPositivePics = parseUEWithFallback(&reader, 0);
30872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            if (numNegativePics > UINT32_MAX - numPositivePics) {
30972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                return ERROR_MALFORMED;
31072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
31172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            numPics = numNegativePics + numPositivePics;
31272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            for (uint32_t j = 0; j < numPics; ++j) {
31372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                skipUE(&reader); // delta_poc_s0|1_minus1[i]
31472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                reader.skipBits(1); // used_by_curr_pic_s0|1_flag[i]
31572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
31672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        }
31772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    }
31872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    if (reader.getBitsWithFallback(1, 0)) { // long_term_ref_pics_present_flag
31972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        uint32_t numLongTermRefPicSps = parseUEWithFallback(&reader, 0);
32072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        for (uint32_t i = 0; i < numLongTermRefPicSps; ++i) {
32172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            reader.skipBits(log2MaxPicOrderCntLsb); // lt_ref_pic_poc_lsb_sps[i]
32272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            reader.skipBits(1); // used_by_curr_pic_lt_sps_flag[i]
32372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        }
32472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    }
32572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    reader.skipBits(1); // sps_temporal_mvp_enabled_flag
32672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    reader.skipBits(1); // strong_intra_smoothing_enabled_flag
32772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    if (reader.getBitsWithFallback(1, 0)) { // vui_parameters_present_flag
32872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        if (reader.getBitsWithFallback(1, 0)) { // aspect_ratio_info_present_flag
32972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            uint32_t aspectRatioIdc = reader.getBitsWithFallback(8, 0);
33072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            if (aspectRatioIdc == 0xFF /* EXTENDED_SAR */) {
33172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                reader.skipBits(16); // sar_width
33272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                reader.skipBits(16); // sar_height
33372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
33472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        }
33572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        if (reader.getBitsWithFallback(1, 0)) { // overscan_info_present_flag
33672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            reader.skipBits(1); // overscan_appropriate_flag
33772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        }
33872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        if (reader.getBitsWithFallback(1, 0)) { // video_signal_type_present_flag
33972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            reader.skipBits(3); // video_format
34072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            uint32_t videoFullRangeFlag;
34172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            if (reader.getBitsGraceful(1, &videoFullRangeFlag)) {
34272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                mParams.add(kVideoFullRangeFlag, videoFullRangeFlag);
34372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
34472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            if (reader.getBitsWithFallback(1, 0)) { // colour_description_present_flag
34572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                mInfo = (Info)(mInfo | kInfoHasColorDescription);
34672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                uint32_t colourPrimaries, transferCharacteristics, matrixCoeffs;
34772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                if (reader.getBitsGraceful(8, &colourPrimaries)) {
34872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    mParams.add(kColourPrimaries, colourPrimaries);
34972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                }
35072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                if (reader.getBitsGraceful(8, &transferCharacteristics)) {
35172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    mParams.add(kTransferCharacteristics, transferCharacteristics);
35272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    if (transferCharacteristics == 16 /* ST 2084 */
35372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                            || transferCharacteristics == 18 /* ARIB STD-B67 HLG */) {
35472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                        mInfo = (Info)(mInfo | kInfoIsHdr);
35572061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    }
35672061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                }
35772061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                if (reader.getBitsGraceful(8, &matrixCoeffs)) {
35872061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                    mParams.add(kMatrixCoeffs, matrixCoeffs);
35972061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar                }
36072061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            }
36172061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar            // skip rest of VUI
36272061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar        }
36372061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar    }
36472061e5ab52d12c17054aeffbb2299a002b6b53aLajos Molnar
36505b849ec0b585412aa0c23a5dad9ca5d9fb28888Lajos Molnar    return reader.overRead() ? ERROR_MALFORMED : OK;
3669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
3679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t HevcParameterSets::parsePps(
3699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        const uint8_t* data __unused, size_t size __unused) {
3709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
3719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
3729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
3739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kimstatus_t HevcParameterSets::makeHvcc(uint8_t *hvcc, size_t *hvccSize,
3749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t nalSizeLength) {
3759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (hvcc == NULL || hvccSize == NULL
3769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            || (nalSizeLength != 4 && nalSizeLength != 2)) {
3779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return BAD_VALUE;
3789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
3799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // ISO 14496-15: HEVC file format
3809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t size = 23;  // 23 bytes in the header
3819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    size_t numOfArrays = 0;
3829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    const size_t numNalUnits = getNumNalUnits();
3839aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
3849aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        uint8_t type = kHevcNalUnitTypes[i];
3859aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numNalus = getNumNalUnitsOfType(type);
3869aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numNalus == 0) {
3879aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            continue;
3889aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
3899aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        ++numOfArrays;
3909aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size += 3;
3919aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
3929aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (getType(j) != type) {
3939aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
3949aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
3959aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            size += 2 + getSize(j);
3969aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
3979aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
3989aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t generalProfileSpace, generalTierFlag, generalProfileIdc;
3999aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (!findParam8(kGeneralProfileSpace, &generalProfileSpace)
4009aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            || !findParam8(kGeneralTierFlag, &generalTierFlag)
4019aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            || !findParam8(kGeneralProfileIdc, &generalProfileIdc)) {
4029aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
4039aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
4049aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint32_t compatibilityFlags;
4059aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint64_t constraintIdcFlags;
4069aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (!findParam32(kGeneralProfileCompatibilityFlags, &compatibilityFlags)
4079aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            || !findParam64(kGeneralConstraintIndicatorFlags, &constraintIdcFlags)) {
4089aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
4099aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
4109aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t generalLevelIdc;
4119aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (!findParam8(kGeneralLevelIdc, &generalLevelIdc)) {
4129aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
4139aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
4149aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t chromaFormatIdc, bitDepthLumaMinus8, bitDepthChromaMinus8;
4159aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (!findParam8(kChromaFormatIdc, &chromaFormatIdc)
4169aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            || !findParam8(kBitDepthLumaMinus8, &bitDepthLumaMinus8)
4179aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            || !findParam8(kBitDepthChromaMinus8, &bitDepthChromaMinus8)) {
4189aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return ERROR_MALFORMED;
4199aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
4209aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    if (size > *hvccSize) {
4219aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        return NO_MEMORY;
4229aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
4239aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    *hvccSize = size;
4249aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
4259aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    uint8_t *header = hvcc;
4269aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[0] = 1;
427c7771064eb299127815eeb01d7b1fd9dc3097e85Chong Zhang    header[1] = (generalProfileSpace << 6) | (generalTierFlag << 5) | generalProfileIdc;
4289aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[2] = (compatibilityFlags >> 24) & 0xff;
4299aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[3] = (compatibilityFlags >> 16) & 0xff;
4309aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[4] = (compatibilityFlags >> 8) & 0xff;
4319aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[5] = compatibilityFlags & 0xff;
4329aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[6] = (constraintIdcFlags >> 40) & 0xff;
4339aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[7] = (constraintIdcFlags >> 32) & 0xff;
4349aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[8] = (constraintIdcFlags >> 24) & 0xff;
4359aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[9] = (constraintIdcFlags >> 16) & 0xff;
4369aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[10] = (constraintIdcFlags >> 8) & 0xff;
4379aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[11] = constraintIdcFlags & 0xff;
4389aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[12] = generalLevelIdc;
4399aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // FIXME: parse min_spatial_segmentation_idc.
4409aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[13] = 0xf0;
4419aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[14] = 0;
4429aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // FIXME: derive parallelismType properly.
4439aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[15] = 0xfc;
4449aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[16] = 0xfc | chromaFormatIdc;
4459aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[17] = 0xf8 | bitDepthLumaMinus8;
4469aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[18] = 0xf8 | bitDepthChromaMinus8;
4479aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // FIXME: derive avgFrameRate
4489aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[19] = 0;
4499aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[20] = 0;
4509aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    // constantFrameRate, numTemporalLayers, temporalIdNested all set to 0.
4519aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[21] = nalSizeLength - 1;
4529aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header[22] = numOfArrays;
4539aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    header += 23;
4549aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    for (size_t i = 0; i < ARRAY_SIZE(kHevcNalUnitTypes); ++i) {
4559aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        uint8_t type = kHevcNalUnitTypes[i];
4569aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        size_t numNalus = getNumNalUnitsOfType(type);
4579aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        if (numNalus == 0) {
4589aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            continue;
4599aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
4609aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        // array_completeness set to 0.
4619aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        header[0] = type;
4629aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        header[1] = (numNalus >> 8) & 0xff;
4639aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        header[2] = numNalus & 0xff;
4649aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        header += 3;
4659aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        for (size_t j = 0; j < numNalUnits; ++j) {
4669aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (getType(j) != type) {
4679aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                continue;
4689aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
4699aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            header[0] = (getSize(j) >> 8) & 0xff;
4709aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            header[1] = getSize(j) & 0xff;
4719aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            if (!write(j, header + 2, size - (header - (uint8_t *)hvcc))) {
4729aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim                return NO_MEMORY;
4739aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            }
4749aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim            header += (2 + getSize(j));
4759aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim        }
4769aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    }
4779aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    CHECK_EQ(header - size, hvcc);
4789aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
4799aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim    return OK;
4809aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}
4819aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim
4829aa87d4ef502c9700a31fe46dc6e1d6f99cf4e5eWonsik Kim}  // namespace android
483