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=%d", *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         offset += 2;
    140         size -= 2;
    141     }
    142 
    143     if (URL_Flag) {
    144         if (offset >= size) {
    145             return ERROR_MALFORMED;
    146         }
    147         unsigned URLlength = mData[offset];
    148         offset += URLlength + 1;
    149         size -= URLlength + 1;
    150     }
    151 
    152     if (OCRstreamFlag) {
    153         offset += 2;
    154         size -= 2;
    155 
    156         if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
    157                 && offset - 2 < size
    158                 && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
    159             // Content found "in the wild" had OCRstreamFlag set but was
    160             // missing OCR_ES_Id, the decoder config descriptor immediately
    161             // followed instead.
    162             offset -= 2;
    163             size += 2;
    164 
    165             ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
    166         }
    167     }
    168 
    169     if (offset >= size) {
    170         return ERROR_MALFORMED;
    171     }
    172 
    173     uint8_t tag;
    174     size_t sub_offset, sub_size;
    175     status_t err = skipDescriptorHeader(
    176             offset, size, &tag, &sub_offset, &sub_size);
    177 
    178     if (err != OK) {
    179         return err;
    180     }
    181 
    182     if (tag != kTag_DecoderConfigDescriptor) {
    183         return ERROR_MALFORMED;
    184     }
    185 
    186     err = parseDecoderConfigDescriptor(sub_offset, sub_size);
    187 
    188     return err;
    189 }
    190 
    191 status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
    192     if (size < 13) {
    193         return ERROR_MALFORMED;
    194     }
    195 
    196     mObjectTypeIndication = mData[offset];
    197 
    198     offset += 13;
    199     size -= 13;
    200 
    201     if (size == 0) {
    202         mDecoderSpecificOffset = 0;
    203         mDecoderSpecificLength = 0;
    204         return OK;
    205     }
    206 
    207     uint8_t tag;
    208     size_t sub_offset, sub_size;
    209     status_t err = skipDescriptorHeader(
    210             offset, size, &tag, &sub_offset, &sub_size);
    211 
    212     if (err != OK) {
    213         return err;
    214     }
    215 
    216     if (tag != kTag_DecoderSpecificInfo) {
    217         return ERROR_MALFORMED;
    218     }
    219 
    220     mDecoderSpecificOffset = sub_offset;
    221     mDecoderSpecificLength = sub_size;
    222 
    223     return OK;
    224 }
    225 
    226 }  // namespace android
    227 
    228