diff options
Diffstat (limited to 'media/libstagefright/ESDS.cpp')
-rw-r--r-- | media/libstagefright/ESDS.cpp | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/media/libstagefright/ESDS.cpp b/media/libstagefright/ESDS.cpp new file mode 100644 index 0000000..53b92a0 --- /dev/null +++ b/media/libstagefright/ESDS.cpp @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2009 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include <media/stagefright/ESDS.h> + +#include <string.h> + +namespace android { + +ESDS::ESDS(const void *data, size_t size) + : mData(new uint8_t[size]), + mSize(size), + mInitCheck(NO_INIT), + mDecoderSpecificOffset(0), + mDecoderSpecificLength(0) { + memcpy(mData, data, size); + + mInitCheck = parse(); +} + +ESDS::~ESDS() { + delete[] mData; + mData = NULL; +} + +status_t ESDS::InitCheck() const { + return mInitCheck; +} + +status_t ESDS::getCodecSpecificInfo(const void **data, size_t *size) const { + if (mInitCheck != OK) { + return mInitCheck; + } + + *data = &mData[mDecoderSpecificOffset]; + *size = mDecoderSpecificLength; + + return OK; +} + +status_t ESDS::skipDescriptorHeader( + size_t offset, size_t size, + uint8_t *tag, size_t *data_offset, size_t *data_size) const { + if (size == 0) { + return ERROR_MALFORMED; + } + + *tag = mData[offset++]; + --size; + + *data_size = 0; + bool more; + do { + if (size == 0) { + return ERROR_MALFORMED; + } + + uint8_t x = mData[offset++]; + --size; + + *data_size = (*data_size << 7) | (x & 0x7f); + more = (x & 0x80) != 0; + } + while (more); + + if (*data_size > size) { + return ERROR_MALFORMED; + } + + *data_offset = offset; + + return OK; +} + +status_t ESDS::parse() { + uint8_t tag; + size_t data_offset; + size_t data_size; + status_t err = + skipDescriptorHeader(0, mSize, &tag, &data_offset, &data_size); + + if (err != OK) { + return err; + } + + if (tag != kTag_ESDescriptor) { + return ERROR_MALFORMED; + } + + return parseESDescriptor(data_offset, data_size); +} + +status_t ESDS::parseESDescriptor(size_t offset, size_t size) { + if (size < 3) { + return ERROR_MALFORMED; + } + + offset += 2; // skip ES_ID + size -= 2; + + unsigned streamDependenceFlag = mData[offset] & 0x80; + unsigned URL_Flag = mData[offset] & 0x40; + unsigned OCRstreamFlag = mData[offset] & 0x20; + + ++offset; + --size; + + if (streamDependenceFlag) { + offset += 2; + size -= 2; + } + + if (URL_Flag) { + if (offset >= size) { + return ERROR_MALFORMED; + } + unsigned URLlength = mData[offset]; + offset += URLlength + 1; + size -= URLlength + 1; + } + + if (OCRstreamFlag) { + offset += 2; + size -= 2; + } + + if (offset >= size) { + return ERROR_MALFORMED; + } + + uint8_t tag; + size_t sub_offset, sub_size; + status_t err = skipDescriptorHeader( + offset, size, &tag, &sub_offset, &sub_size); + + if (err != OK) { + return err; + } + + if (tag != kTag_DecoderConfigDescriptor) { + return ERROR_MALFORMED; + } + + err = parseDecoderConfigDescriptor(sub_offset, sub_size); + + return err; +} + +status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) { + if (size < 13) { + return ERROR_MALFORMED; + } + + offset += 13; + size -= 13; + + if (size == 0) { + mDecoderSpecificOffset = 0; + mDecoderSpecificLength = 0; + return OK; + } + + uint8_t tag; + size_t sub_offset, sub_size; + status_t err = skipDescriptorHeader( + offset, size, &tag, &sub_offset, &sub_size); + + if (err != OK) { + return err; + } + + if (tag != kTag_DecoderSpecificInfo) { + return ERROR_MALFORMED; + } + + mDecoderSpecificOffset = sub_offset; + mDecoderSpecificLength = sub_size; + + return OK; +} + +} // namespace android + |