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