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/Utils.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