blob: 4a0c35c6784148ec29e91aa3fa863855df39c941 [file] [log] [blame]
Andreas Huber20111aa2009-07-14 16:56:47 -07001/*
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
Andreas Huberf3dadf22011-07-19 16:05:50 -070017//#define LOG_NDEBUG 0
18#define LOG_TAG "ESDS"
19#include <utils/Log.h>
20
Andreas Huber89e69da2009-10-13 10:22:55 -070021#include "include/ESDS.h"
Andreas Huber20111aa2009-07-14 16:56:47 -070022
23#include <string.h>
24
25namespace android {
26
27ESDS::ESDS(const void *data, size_t size)
28 : mData(new uint8_t[size]),
29 mSize(size),
30 mInitCheck(NO_INIT),
31 mDecoderSpecificOffset(0),
Andreas Huber81f82c32010-04-12 16:05:57 -070032 mDecoderSpecificLength(0),
33 mObjectTypeIndication(0) {
Andreas Huber20111aa2009-07-14 16:56:47 -070034 memcpy(mData, data, size);
35
36 mInitCheck = parse();
37}
38
39ESDS::~ESDS() {
40 delete[] mData;
41 mData = NULL;
42}
43
44status_t ESDS::InitCheck() const {
45 return mInitCheck;
46}
47
Andreas Huber81f82c32010-04-12 16:05:57 -070048status_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
Andreas Huber20111aa2009-07-14 16:56:47 -070058status_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
69status_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
Steve Block3856b092011-10-20 11:56:00 +010094 ALOGV("tag=0x%02x data_size=%d", *tag, *data_size);
Andreas Huberf3dadf22011-07-19 16:05:50 -070095
Andreas Huber20111aa2009-07-14 16:56:47 -070096 if (*data_size > size) {
97 return ERROR_MALFORMED;
98 }
99
100 *data_offset = offset;
101
102 return OK;
103}
104
105status_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
123status_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;
Andreas Huberf3dadf22011-07-19 16:05:50 -0700155
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
Steve Block5ff1dd52012-01-05 23:22:43 +0000165 ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
Andreas Huberf3dadf22011-07-19 16:05:50 -0700166 }
Andreas Huber20111aa2009-07-14 16:56:47 -0700167 }
Andreas Huberf3dadf22011-07-19 16:05:50 -0700168
Andreas Huber20111aa2009-07-14 16:56:47 -0700169 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
191status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
192 if (size < 13) {
193 return ERROR_MALFORMED;
194 }
195
Andreas Huber81f82c32010-04-12 16:05:57 -0700196 mObjectTypeIndication = mData[offset];
197
Andreas Huber20111aa2009-07-14 16:56:47 -0700198 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