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
ESDS(const void * data,size_t size)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
~ESDS()41 ESDS::~ESDS() {
42 delete[] mData;
43 mData = NULL;
44 }
45
InitCheck() const46 status_t ESDS::InitCheck() const {
47 return mInitCheck;
48 }
49
getObjectTypeIndication(uint8_t * objectTypeIndication) const50 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
getCodecSpecificInfo(const void ** data,size_t * size) const60 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
skipDescriptorHeader(size_t offset,size_t size,uint8_t * tag,size_t * data_offset,size_t * data_size) const71 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
parse()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
parseESDescriptor(size_t offset,size_t size)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
getBitRate(uint32_t * brateMax,uint32_t * brateAvg) const199 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
parseDecoderConfigDescriptor(size_t offset,size_t size)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