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