1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker * Copyright (C) 2009 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker *
4*ec779b8eSAndroid Build Coastguard Worker * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker *
8*ec779b8eSAndroid Build Coastguard Worker * http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker *
10*ec779b8eSAndroid Build Coastguard Worker * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker */
16*ec779b8eSAndroid Build Coastguard Worker
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ESDS"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker
21*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ByteUtils.h>
22*ec779b8eSAndroid Build Coastguard Worker
23*ec779b8eSAndroid Build Coastguard Worker #include <media/esds/ESDS.h>
24*ec779b8eSAndroid Build Coastguard Worker
25*ec779b8eSAndroid Build Coastguard Worker #include <string.h>
26*ec779b8eSAndroid Build Coastguard Worker
27*ec779b8eSAndroid Build Coastguard Worker namespace android {
28*ec779b8eSAndroid Build Coastguard Worker
ESDS(const void * data,size_t size)29*ec779b8eSAndroid Build Coastguard Worker ESDS::ESDS(const void *data, size_t size)
30*ec779b8eSAndroid Build Coastguard Worker : mData(new uint8_t[size]),
31*ec779b8eSAndroid Build Coastguard Worker mSize(size),
32*ec779b8eSAndroid Build Coastguard Worker mInitCheck(NO_INIT),
33*ec779b8eSAndroid Build Coastguard Worker mDecoderSpecificOffset(0),
34*ec779b8eSAndroid Build Coastguard Worker mDecoderSpecificLength(0),
35*ec779b8eSAndroid Build Coastguard Worker mObjectTypeIndication(0) {
36*ec779b8eSAndroid Build Coastguard Worker memcpy(mData, data, size);
37*ec779b8eSAndroid Build Coastguard Worker
38*ec779b8eSAndroid Build Coastguard Worker mInitCheck = parse();
39*ec779b8eSAndroid Build Coastguard Worker }
40*ec779b8eSAndroid Build Coastguard Worker
~ESDS()41*ec779b8eSAndroid Build Coastguard Worker ESDS::~ESDS() {
42*ec779b8eSAndroid Build Coastguard Worker delete[] mData;
43*ec779b8eSAndroid Build Coastguard Worker mData = NULL;
44*ec779b8eSAndroid Build Coastguard Worker }
45*ec779b8eSAndroid Build Coastguard Worker
InitCheck() const46*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::InitCheck() const {
47*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
48*ec779b8eSAndroid Build Coastguard Worker }
49*ec779b8eSAndroid Build Coastguard Worker
getObjectTypeIndication(uint8_t * objectTypeIndication) const50*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::getObjectTypeIndication(uint8_t *objectTypeIndication) const {
51*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
52*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
53*ec779b8eSAndroid Build Coastguard Worker }
54*ec779b8eSAndroid Build Coastguard Worker
55*ec779b8eSAndroid Build Coastguard Worker *objectTypeIndication = mObjectTypeIndication;
56*ec779b8eSAndroid Build Coastguard Worker
57*ec779b8eSAndroid Build Coastguard Worker return OK;
58*ec779b8eSAndroid Build Coastguard Worker }
59*ec779b8eSAndroid Build Coastguard Worker
getCodecSpecificInfo(const void ** data,size_t * size) const60*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::getCodecSpecificInfo(const void **data, size_t *size) const {
61*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
62*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
63*ec779b8eSAndroid Build Coastguard Worker }
64*ec779b8eSAndroid Build Coastguard Worker
65*ec779b8eSAndroid Build Coastguard Worker *data = &mData[mDecoderSpecificOffset];
66*ec779b8eSAndroid Build Coastguard Worker *size = mDecoderSpecificLength;
67*ec779b8eSAndroid Build Coastguard Worker
68*ec779b8eSAndroid Build Coastguard Worker return OK;
69*ec779b8eSAndroid Build Coastguard Worker }
70*ec779b8eSAndroid Build Coastguard Worker
skipDescriptorHeader(size_t offset,size_t size,uint8_t * tag,size_t * data_offset,size_t * data_size) const71*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::skipDescriptorHeader(
72*ec779b8eSAndroid Build Coastguard Worker size_t offset, size_t size,
73*ec779b8eSAndroid Build Coastguard Worker uint8_t *tag, size_t *data_offset, size_t *data_size) const {
74*ec779b8eSAndroid Build Coastguard Worker if (size == 0) {
75*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
76*ec779b8eSAndroid Build Coastguard Worker }
77*ec779b8eSAndroid Build Coastguard Worker
78*ec779b8eSAndroid Build Coastguard Worker *tag = mData[offset++];
79*ec779b8eSAndroid Build Coastguard Worker --size;
80*ec779b8eSAndroid Build Coastguard Worker
81*ec779b8eSAndroid Build Coastguard Worker *data_size = 0;
82*ec779b8eSAndroid Build Coastguard Worker bool more;
83*ec779b8eSAndroid Build Coastguard Worker do {
84*ec779b8eSAndroid Build Coastguard Worker if (size == 0) {
85*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
86*ec779b8eSAndroid Build Coastguard Worker }
87*ec779b8eSAndroid Build Coastguard Worker
88*ec779b8eSAndroid Build Coastguard Worker uint8_t x = mData[offset++];
89*ec779b8eSAndroid Build Coastguard Worker --size;
90*ec779b8eSAndroid Build Coastguard Worker
91*ec779b8eSAndroid Build Coastguard Worker *data_size = (*data_size << 7) | (x & 0x7f);
92*ec779b8eSAndroid Build Coastguard Worker more = (x & 0x80) != 0;
93*ec779b8eSAndroid Build Coastguard Worker }
94*ec779b8eSAndroid Build Coastguard Worker while (more);
95*ec779b8eSAndroid Build Coastguard Worker
96*ec779b8eSAndroid Build Coastguard Worker ALOGV("tag=0x%02x data_size=%zu", *tag, *data_size);
97*ec779b8eSAndroid Build Coastguard Worker
98*ec779b8eSAndroid Build Coastguard Worker if (*data_size > size) {
99*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
100*ec779b8eSAndroid Build Coastguard Worker }
101*ec779b8eSAndroid Build Coastguard Worker
102*ec779b8eSAndroid Build Coastguard Worker *data_offset = offset;
103*ec779b8eSAndroid Build Coastguard Worker
104*ec779b8eSAndroid Build Coastguard Worker return OK;
105*ec779b8eSAndroid Build Coastguard Worker }
106*ec779b8eSAndroid Build Coastguard Worker
parse()107*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::parse() {
108*ec779b8eSAndroid Build Coastguard Worker uint8_t tag;
109*ec779b8eSAndroid Build Coastguard Worker size_t data_offset;
110*ec779b8eSAndroid Build Coastguard Worker size_t data_size;
111*ec779b8eSAndroid Build Coastguard Worker status_t err =
112*ec779b8eSAndroid Build Coastguard Worker skipDescriptorHeader(0, mSize, &tag, &data_offset, &data_size);
113*ec779b8eSAndroid Build Coastguard Worker
114*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
115*ec779b8eSAndroid Build Coastguard Worker return err;
116*ec779b8eSAndroid Build Coastguard Worker }
117*ec779b8eSAndroid Build Coastguard Worker
118*ec779b8eSAndroid Build Coastguard Worker if (tag != kTag_ESDescriptor) {
119*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
120*ec779b8eSAndroid Build Coastguard Worker }
121*ec779b8eSAndroid Build Coastguard Worker
122*ec779b8eSAndroid Build Coastguard Worker return parseESDescriptor(data_offset, data_size);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker
parseESDescriptor(size_t offset,size_t size)125*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
126*ec779b8eSAndroid Build Coastguard Worker if (size < 3) {
127*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
128*ec779b8eSAndroid Build Coastguard Worker }
129*ec779b8eSAndroid Build Coastguard Worker
130*ec779b8eSAndroid Build Coastguard Worker offset += 2; // skip ES_ID
131*ec779b8eSAndroid Build Coastguard Worker size -= 2;
132*ec779b8eSAndroid Build Coastguard Worker
133*ec779b8eSAndroid Build Coastguard Worker unsigned streamDependenceFlag = mData[offset] & 0x80;
134*ec779b8eSAndroid Build Coastguard Worker unsigned URL_Flag = mData[offset] & 0x40;
135*ec779b8eSAndroid Build Coastguard Worker unsigned OCRstreamFlag = mData[offset] & 0x20;
136*ec779b8eSAndroid Build Coastguard Worker
137*ec779b8eSAndroid Build Coastguard Worker ++offset;
138*ec779b8eSAndroid Build Coastguard Worker --size;
139*ec779b8eSAndroid Build Coastguard Worker
140*ec779b8eSAndroid Build Coastguard Worker if (streamDependenceFlag) {
141*ec779b8eSAndroid Build Coastguard Worker if (size < 2)
142*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
143*ec779b8eSAndroid Build Coastguard Worker offset += 2;
144*ec779b8eSAndroid Build Coastguard Worker size -= 2;
145*ec779b8eSAndroid Build Coastguard Worker }
146*ec779b8eSAndroid Build Coastguard Worker
147*ec779b8eSAndroid Build Coastguard Worker if (URL_Flag) {
148*ec779b8eSAndroid Build Coastguard Worker if (offset >= size) {
149*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
150*ec779b8eSAndroid Build Coastguard Worker }
151*ec779b8eSAndroid Build Coastguard Worker unsigned URLlength = mData[offset];
152*ec779b8eSAndroid Build Coastguard Worker if (URLlength >= size)
153*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
154*ec779b8eSAndroid Build Coastguard Worker offset += URLlength + 1;
155*ec779b8eSAndroid Build Coastguard Worker size -= URLlength + 1;
156*ec779b8eSAndroid Build Coastguard Worker }
157*ec779b8eSAndroid Build Coastguard Worker
158*ec779b8eSAndroid Build Coastguard Worker if (OCRstreamFlag) {
159*ec779b8eSAndroid Build Coastguard Worker if (size < 2)
160*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
161*ec779b8eSAndroid Build Coastguard Worker offset += 2;
162*ec779b8eSAndroid Build Coastguard Worker size -= 2;
163*ec779b8eSAndroid Build Coastguard Worker
164*ec779b8eSAndroid Build Coastguard Worker if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
165*ec779b8eSAndroid Build Coastguard Worker && offset - 2 < size
166*ec779b8eSAndroid Build Coastguard Worker && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
167*ec779b8eSAndroid Build Coastguard Worker // Content found "in the wild" had OCRstreamFlag set but was
168*ec779b8eSAndroid Build Coastguard Worker // missing OCR_ES_Id, the decoder config descriptor immediately
169*ec779b8eSAndroid Build Coastguard Worker // followed instead.
170*ec779b8eSAndroid Build Coastguard Worker offset -= 2;
171*ec779b8eSAndroid Build Coastguard Worker size += 2;
172*ec779b8eSAndroid Build Coastguard Worker
173*ec779b8eSAndroid Build Coastguard Worker ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
174*ec779b8eSAndroid Build Coastguard Worker }
175*ec779b8eSAndroid Build Coastguard Worker }
176*ec779b8eSAndroid Build Coastguard Worker
177*ec779b8eSAndroid Build Coastguard Worker if (offset >= size) {
178*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
179*ec779b8eSAndroid Build Coastguard Worker }
180*ec779b8eSAndroid Build Coastguard Worker
181*ec779b8eSAndroid Build Coastguard Worker uint8_t tag;
182*ec779b8eSAndroid Build Coastguard Worker size_t sub_offset, sub_size;
183*ec779b8eSAndroid Build Coastguard Worker status_t err = skipDescriptorHeader(
184*ec779b8eSAndroid Build Coastguard Worker offset, size, &tag, &sub_offset, &sub_size);
185*ec779b8eSAndroid Build Coastguard Worker
186*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
187*ec779b8eSAndroid Build Coastguard Worker return err;
188*ec779b8eSAndroid Build Coastguard Worker }
189*ec779b8eSAndroid Build Coastguard Worker
190*ec779b8eSAndroid Build Coastguard Worker if (tag != kTag_DecoderConfigDescriptor) {
191*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
192*ec779b8eSAndroid Build Coastguard Worker }
193*ec779b8eSAndroid Build Coastguard Worker
194*ec779b8eSAndroid Build Coastguard Worker err = parseDecoderConfigDescriptor(sub_offset, sub_size);
195*ec779b8eSAndroid Build Coastguard Worker
196*ec779b8eSAndroid Build Coastguard Worker return err;
197*ec779b8eSAndroid Build Coastguard Worker }
198*ec779b8eSAndroid Build Coastguard Worker
getBitRate(uint32_t * brateMax,uint32_t * brateAvg) const199*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::getBitRate(uint32_t *brateMax, uint32_t *brateAvg) const {
200*ec779b8eSAndroid Build Coastguard Worker if (mInitCheck != OK) {
201*ec779b8eSAndroid Build Coastguard Worker return mInitCheck;
202*ec779b8eSAndroid Build Coastguard Worker }
203*ec779b8eSAndroid Build Coastguard Worker
204*ec779b8eSAndroid Build Coastguard Worker *brateMax = mBitRateMax;
205*ec779b8eSAndroid Build Coastguard Worker *brateAvg = mBitRateAvg;
206*ec779b8eSAndroid Build Coastguard Worker
207*ec779b8eSAndroid Build Coastguard Worker return OK;
208*ec779b8eSAndroid Build Coastguard Worker };
209*ec779b8eSAndroid Build Coastguard Worker
parseDecoderConfigDescriptor(size_t offset,size_t size)210*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
211*ec779b8eSAndroid Build Coastguard Worker if (size < 13) {
212*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
213*ec779b8eSAndroid Build Coastguard Worker }
214*ec779b8eSAndroid Build Coastguard Worker
215*ec779b8eSAndroid Build Coastguard Worker mObjectTypeIndication = mData[offset];
216*ec779b8eSAndroid Build Coastguard Worker mBitRateMax = U32_AT(mData + offset + 5);
217*ec779b8eSAndroid Build Coastguard Worker mBitRateAvg = U32_AT(mData + offset + 9);
218*ec779b8eSAndroid Build Coastguard Worker
219*ec779b8eSAndroid Build Coastguard Worker offset += 13;
220*ec779b8eSAndroid Build Coastguard Worker size -= 13;
221*ec779b8eSAndroid Build Coastguard Worker
222*ec779b8eSAndroid Build Coastguard Worker if (size == 0) {
223*ec779b8eSAndroid Build Coastguard Worker mDecoderSpecificOffset = 0;
224*ec779b8eSAndroid Build Coastguard Worker mDecoderSpecificLength = 0;
225*ec779b8eSAndroid Build Coastguard Worker return OK;
226*ec779b8eSAndroid Build Coastguard Worker }
227*ec779b8eSAndroid Build Coastguard Worker
228*ec779b8eSAndroid Build Coastguard Worker uint8_t tag;
229*ec779b8eSAndroid Build Coastguard Worker size_t sub_offset, sub_size;
230*ec779b8eSAndroid Build Coastguard Worker status_t err = skipDescriptorHeader(
231*ec779b8eSAndroid Build Coastguard Worker offset, size, &tag, &sub_offset, &sub_size);
232*ec779b8eSAndroid Build Coastguard Worker
233*ec779b8eSAndroid Build Coastguard Worker if (err != OK) {
234*ec779b8eSAndroid Build Coastguard Worker return err;
235*ec779b8eSAndroid Build Coastguard Worker }
236*ec779b8eSAndroid Build Coastguard Worker
237*ec779b8eSAndroid Build Coastguard Worker if (tag != kTag_DecoderSpecificInfo) {
238*ec779b8eSAndroid Build Coastguard Worker return ERROR_MALFORMED;
239*ec779b8eSAndroid Build Coastguard Worker }
240*ec779b8eSAndroid Build Coastguard Worker
241*ec779b8eSAndroid Build Coastguard Worker mDecoderSpecificOffset = sub_offset;
242*ec779b8eSAndroid Build Coastguard Worker mDecoderSpecificLength = sub_size;
243*ec779b8eSAndroid Build Coastguard Worker
244*ec779b8eSAndroid Build Coastguard Worker return OK;
245*ec779b8eSAndroid Build Coastguard Worker }
246*ec779b8eSAndroid Build Coastguard Worker
247*ec779b8eSAndroid Build Coastguard Worker } // namespace android
248*ec779b8eSAndroid Build Coastguard Worker
249