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