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