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