Home | History | Annotate | Download | only in libstagefright
      1 /*
      2  * Copyright (C) 2009 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 "ESDS"
     19 #include <utils/Log.h>
     20 
     21 #include <media/stagefright/foundation/ByteUtils.h>
     22 
     23 #include "include/ESDS.h"
     24 
     25 #include <string.h>
     26 
     27 namespace android {
     28 
     29 ESDS::ESDS(const void *data, size_t size)
     30     : mData(new uint8_t[size]),
     31       mSize(size),
     32       mInitCheck(NO_INIT),
     33       mDecoderSpecificOffset(0),
     34       mDecoderSpecificLength(0),
     35       mObjectTypeIndication(0) {
     36     memcpy(mData, data, size);
     37 
     38     mInitCheck = parse();
     39 }
     40 
     41 ESDS::~ESDS() {
     42     delete[] mData;
     43     mData = NULL;
     44 }
     45 
     46 status_t ESDS::InitCheck() const {
     47     return mInitCheck;
     48 }
     49 
     50 status_t ESDS::getObjectTypeIndication(uint8_t *objectTypeIndication) const {
     51     if (mInitCheck != OK) {
     52         return mInitCheck;
     53     }
     54 
     55     *objectTypeIndication = mObjectTypeIndication;
     56 
     57     return OK;
     58 }
     59 
     60 status_t ESDS::getCodecSpecificInfo(const void **data, size_t *size) const {
     61     if (mInitCheck != OK) {
     62         return mInitCheck;
     63     }
     64 
     65     *data = &mData[mDecoderSpecificOffset];
     66     *size = mDecoderSpecificLength;
     67 
     68     return OK;
     69 }
     70 
     71 status_t ESDS::skipDescriptorHeader(
     72         size_t offset, size_t size,
     73         uint8_t *tag, size_t *data_offset, size_t *data_size) const {
     74     if (size == 0) {
     75         return ERROR_MALFORMED;
     76     }
     77 
     78     *tag = mData[offset++];
     79     --size;
     80 
     81     *data_size = 0;
     82     bool more;
     83     do {
     84         if (size == 0) {
     85             return ERROR_MALFORMED;
     86         }
     87 
     88         uint8_t x = mData[offset++];
     89         --size;
     90 
     91         *data_size = (*data_size << 7) | (x & 0x7f);
     92         more = (x & 0x80) != 0;
     93     }
     94     while (more);
     95 
     96     ALOGV("tag=0x%02x data_size=%zu", *tag, *data_size);
     97 
     98     if (*data_size > size) {
     99         return ERROR_MALFORMED;
    100     }
    101 
    102     *data_offset = offset;
    103 
    104     return OK;
    105 }
    106 
    107 status_t ESDS::parse() {
    108     uint8_t tag;
    109     size_t data_offset;
    110     size_t data_size;
    111     status_t err =
    112         skipDescriptorHeader(0, mSize, &tag, &data_offset, &data_size);
    113 
    114     if (err != OK) {
    115         return err;
    116     }
    117 
    118     if (tag != kTag_ESDescriptor) {
    119         return ERROR_MALFORMED;
    120     }
    121 
    122     return parseESDescriptor(data_offset, data_size);
    123 }
    124 
    125 status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
    126     if (size < 3) {
    127         return ERROR_MALFORMED;
    128     }
    129 
    130     offset += 2;  // skip ES_ID
    131     size -= 2;
    132 
    133     unsigned streamDependenceFlag = mData[offset] & 0x80;
    134     unsigned URL_Flag = mData[offset] & 0x40;
    135     unsigned OCRstreamFlag = mData[offset] & 0x20;
    136 
    137     ++offset;
    138     --size;
    139 
    140     if (streamDependenceFlag) {
    141         if (size < 2)
    142             return ERROR_MALFORMED;
    143         offset += 2;
    144         size -= 2;
    145     }
    146 
    147     if (URL_Flag) {
    148         if (offset >= size) {
    149             return ERROR_MALFORMED;
    150         }
    151         unsigned URLlength = mData[offset];
    152         if (URLlength >= size)
    153             return ERROR_MALFORMED;
    154         offset += URLlength + 1;
    155         size -= URLlength + 1;
    156     }
    157 
    158     if (OCRstreamFlag) {
    159         if (size < 2)
    160             return ERROR_MALFORMED;
    161         offset += 2;
    162         size -= 2;
    163 
    164         if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
    165                 && offset - 2 < size
    166                 && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
    167             // Content found "in the wild" had OCRstreamFlag set but was
    168             // missing OCR_ES_Id, the decoder config descriptor immediately
    169             // followed instead.
    170             offset -= 2;
    171             size += 2;
    172 
    173             ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
    174         }
    175     }
    176 
    177     if (offset >= size) {
    178         return ERROR_MALFORMED;
    179     }
    180 
    181     uint8_t tag;
    182     size_t sub_offset, sub_size;
    183     status_t err = skipDescriptorHeader(
    184             offset, size, &tag, &sub_offset, &sub_size);
    185 
    186     if (err != OK) {
    187         return err;
    188     }
    189 
    190     if (tag != kTag_DecoderConfigDescriptor) {
    191         return ERROR_MALFORMED;
    192     }
    193 
    194     err = parseDecoderConfigDescriptor(sub_offset, sub_size);
    195 
    196     return err;
    197 }
    198 
    199 status_t ESDS::getBitRate(uint32_t *brateMax, uint32_t *brateAvg) const {
    200     if (mInitCheck != OK) {
    201         return mInitCheck;
    202     }
    203 
    204     *brateMax = mBitRateMax;
    205     *brateAvg = mBitRateAvg;
    206 
    207     return OK;
    208 };
    209 
    210 status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
    211     if (size < 13) {
    212         return ERROR_MALFORMED;
    213     }
    214 
    215     mObjectTypeIndication = mData[offset];
    216     mBitRateMax = U32_AT(mData + offset + 5);
    217     mBitRateAvg = U32_AT(mData + offset + 9);
    218 
    219     offset += 13;
    220     size -= 13;
    221 
    222     if (size == 0) {
    223         mDecoderSpecificOffset = 0;
    224         mDecoderSpecificLength = 0;
    225         return OK;
    226     }
    227 
    228     uint8_t tag;
    229     size_t sub_offset, sub_size;
    230     status_t err = skipDescriptorHeader(
    231             offset, size, &tag, &sub_offset, &sub_size);
    232 
    233     if (err != OK) {
    234         return err;
    235     }
    236 
    237     if (tag != kTag_DecoderSpecificInfo) {
    238         return ERROR_MALFORMED;
    239     }
    240 
    241     mDecoderSpecificOffset = sub_offset;
    242     mDecoderSpecificLength = sub_size;
    243 
    244     return OK;
    245 }
    246 
    247 }  // namespace android
    248 
    249