xref: /aosp_15_r20/frameworks/av/media/module/esds/ESDS.cpp (revision ec779b8e0859a360c3d303172224686826e6e0e1)
1*ec779b8eSAndroid Build Coastguard Worker /*
2*ec779b8eSAndroid Build Coastguard Worker  * Copyright (C) 2009 The Android Open Source Project
3*ec779b8eSAndroid Build Coastguard Worker  *
4*ec779b8eSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
5*ec779b8eSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
6*ec779b8eSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
7*ec779b8eSAndroid Build Coastguard Worker  *
8*ec779b8eSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
9*ec779b8eSAndroid Build Coastguard Worker  *
10*ec779b8eSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
11*ec779b8eSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
12*ec779b8eSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*ec779b8eSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
14*ec779b8eSAndroid Build Coastguard Worker  * limitations under the License.
15*ec779b8eSAndroid Build Coastguard Worker  */
16*ec779b8eSAndroid Build Coastguard Worker 
17*ec779b8eSAndroid Build Coastguard Worker //#define LOG_NDEBUG 0
18*ec779b8eSAndroid Build Coastguard Worker #define LOG_TAG "ESDS"
19*ec779b8eSAndroid Build Coastguard Worker #include <utils/Log.h>
20*ec779b8eSAndroid Build Coastguard Worker 
21*ec779b8eSAndroid Build Coastguard Worker #include <media/stagefright/foundation/ByteUtils.h>
22*ec779b8eSAndroid Build Coastguard Worker 
23*ec779b8eSAndroid Build Coastguard Worker #include <media/esds/ESDS.h>
24*ec779b8eSAndroid Build Coastguard Worker 
25*ec779b8eSAndroid Build Coastguard Worker #include <string.h>
26*ec779b8eSAndroid Build Coastguard Worker 
27*ec779b8eSAndroid Build Coastguard Worker namespace android {
28*ec779b8eSAndroid Build Coastguard Worker 
ESDS(const void * data,size_t size)29*ec779b8eSAndroid Build Coastguard Worker ESDS::ESDS(const void *data, size_t size)
30*ec779b8eSAndroid Build Coastguard Worker     : mData(new uint8_t[size]),
31*ec779b8eSAndroid Build Coastguard Worker       mSize(size),
32*ec779b8eSAndroid Build Coastguard Worker       mInitCheck(NO_INIT),
33*ec779b8eSAndroid Build Coastguard Worker       mDecoderSpecificOffset(0),
34*ec779b8eSAndroid Build Coastguard Worker       mDecoderSpecificLength(0),
35*ec779b8eSAndroid Build Coastguard Worker       mObjectTypeIndication(0) {
36*ec779b8eSAndroid Build Coastguard Worker     memcpy(mData, data, size);
37*ec779b8eSAndroid Build Coastguard Worker 
38*ec779b8eSAndroid Build Coastguard Worker     mInitCheck = parse();
39*ec779b8eSAndroid Build Coastguard Worker }
40*ec779b8eSAndroid Build Coastguard Worker 
~ESDS()41*ec779b8eSAndroid Build Coastguard Worker ESDS::~ESDS() {
42*ec779b8eSAndroid Build Coastguard Worker     delete[] mData;
43*ec779b8eSAndroid Build Coastguard Worker     mData = NULL;
44*ec779b8eSAndroid Build Coastguard Worker }
45*ec779b8eSAndroid Build Coastguard Worker 
InitCheck() const46*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::InitCheck() const {
47*ec779b8eSAndroid Build Coastguard Worker     return mInitCheck;
48*ec779b8eSAndroid Build Coastguard Worker }
49*ec779b8eSAndroid Build Coastguard Worker 
getObjectTypeIndication(uint8_t * objectTypeIndication) const50*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::getObjectTypeIndication(uint8_t *objectTypeIndication) const {
51*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
52*ec779b8eSAndroid Build Coastguard Worker         return mInitCheck;
53*ec779b8eSAndroid Build Coastguard Worker     }
54*ec779b8eSAndroid Build Coastguard Worker 
55*ec779b8eSAndroid Build Coastguard Worker     *objectTypeIndication = mObjectTypeIndication;
56*ec779b8eSAndroid Build Coastguard Worker 
57*ec779b8eSAndroid Build Coastguard Worker     return OK;
58*ec779b8eSAndroid Build Coastguard Worker }
59*ec779b8eSAndroid Build Coastguard Worker 
getCodecSpecificInfo(const void ** data,size_t * size) const60*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::getCodecSpecificInfo(const void **data, size_t *size) const {
61*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
62*ec779b8eSAndroid Build Coastguard Worker         return mInitCheck;
63*ec779b8eSAndroid Build Coastguard Worker     }
64*ec779b8eSAndroid Build Coastguard Worker 
65*ec779b8eSAndroid Build Coastguard Worker     *data = &mData[mDecoderSpecificOffset];
66*ec779b8eSAndroid Build Coastguard Worker     *size = mDecoderSpecificLength;
67*ec779b8eSAndroid Build Coastguard Worker 
68*ec779b8eSAndroid Build Coastguard Worker     return OK;
69*ec779b8eSAndroid Build Coastguard Worker }
70*ec779b8eSAndroid Build Coastguard Worker 
skipDescriptorHeader(size_t offset,size_t size,uint8_t * tag,size_t * data_offset,size_t * data_size) const71*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::skipDescriptorHeader(
72*ec779b8eSAndroid Build Coastguard Worker         size_t offset, size_t size,
73*ec779b8eSAndroid Build Coastguard Worker         uint8_t *tag, size_t *data_offset, size_t *data_size) const {
74*ec779b8eSAndroid Build Coastguard Worker     if (size == 0) {
75*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
76*ec779b8eSAndroid Build Coastguard Worker     }
77*ec779b8eSAndroid Build Coastguard Worker 
78*ec779b8eSAndroid Build Coastguard Worker     *tag = mData[offset++];
79*ec779b8eSAndroid Build Coastguard Worker     --size;
80*ec779b8eSAndroid Build Coastguard Worker 
81*ec779b8eSAndroid Build Coastguard Worker     *data_size = 0;
82*ec779b8eSAndroid Build Coastguard Worker     bool more;
83*ec779b8eSAndroid Build Coastguard Worker     do {
84*ec779b8eSAndroid Build Coastguard Worker         if (size == 0) {
85*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
86*ec779b8eSAndroid Build Coastguard Worker         }
87*ec779b8eSAndroid Build Coastguard Worker 
88*ec779b8eSAndroid Build Coastguard Worker         uint8_t x = mData[offset++];
89*ec779b8eSAndroid Build Coastguard Worker         --size;
90*ec779b8eSAndroid Build Coastguard Worker 
91*ec779b8eSAndroid Build Coastguard Worker         *data_size = (*data_size << 7) | (x & 0x7f);
92*ec779b8eSAndroid Build Coastguard Worker         more = (x & 0x80) != 0;
93*ec779b8eSAndroid Build Coastguard Worker     }
94*ec779b8eSAndroid Build Coastguard Worker     while (more);
95*ec779b8eSAndroid Build Coastguard Worker 
96*ec779b8eSAndroid Build Coastguard Worker     ALOGV("tag=0x%02x data_size=%zu", *tag, *data_size);
97*ec779b8eSAndroid Build Coastguard Worker 
98*ec779b8eSAndroid Build Coastguard Worker     if (*data_size > size) {
99*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
100*ec779b8eSAndroid Build Coastguard Worker     }
101*ec779b8eSAndroid Build Coastguard Worker 
102*ec779b8eSAndroid Build Coastguard Worker     *data_offset = offset;
103*ec779b8eSAndroid Build Coastguard Worker 
104*ec779b8eSAndroid Build Coastguard Worker     return OK;
105*ec779b8eSAndroid Build Coastguard Worker }
106*ec779b8eSAndroid Build Coastguard Worker 
parse()107*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::parse() {
108*ec779b8eSAndroid Build Coastguard Worker     uint8_t tag;
109*ec779b8eSAndroid Build Coastguard Worker     size_t data_offset;
110*ec779b8eSAndroid Build Coastguard Worker     size_t data_size;
111*ec779b8eSAndroid Build Coastguard Worker     status_t err =
112*ec779b8eSAndroid Build Coastguard Worker         skipDescriptorHeader(0, mSize, &tag, &data_offset, &data_size);
113*ec779b8eSAndroid Build Coastguard Worker 
114*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
115*ec779b8eSAndroid Build Coastguard Worker         return err;
116*ec779b8eSAndroid Build Coastguard Worker     }
117*ec779b8eSAndroid Build Coastguard Worker 
118*ec779b8eSAndroid Build Coastguard Worker     if (tag != kTag_ESDescriptor) {
119*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
120*ec779b8eSAndroid Build Coastguard Worker     }
121*ec779b8eSAndroid Build Coastguard Worker 
122*ec779b8eSAndroid Build Coastguard Worker     return parseESDescriptor(data_offset, data_size);
123*ec779b8eSAndroid Build Coastguard Worker }
124*ec779b8eSAndroid Build Coastguard Worker 
parseESDescriptor(size_t offset,size_t size)125*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::parseESDescriptor(size_t offset, size_t size) {
126*ec779b8eSAndroid Build Coastguard Worker     if (size < 3) {
127*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
128*ec779b8eSAndroid Build Coastguard Worker     }
129*ec779b8eSAndroid Build Coastguard Worker 
130*ec779b8eSAndroid Build Coastguard Worker     offset += 2;  // skip ES_ID
131*ec779b8eSAndroid Build Coastguard Worker     size -= 2;
132*ec779b8eSAndroid Build Coastguard Worker 
133*ec779b8eSAndroid Build Coastguard Worker     unsigned streamDependenceFlag = mData[offset] & 0x80;
134*ec779b8eSAndroid Build Coastguard Worker     unsigned URL_Flag = mData[offset] & 0x40;
135*ec779b8eSAndroid Build Coastguard Worker     unsigned OCRstreamFlag = mData[offset] & 0x20;
136*ec779b8eSAndroid Build Coastguard Worker 
137*ec779b8eSAndroid Build Coastguard Worker     ++offset;
138*ec779b8eSAndroid Build Coastguard Worker     --size;
139*ec779b8eSAndroid Build Coastguard Worker 
140*ec779b8eSAndroid Build Coastguard Worker     if (streamDependenceFlag) {
141*ec779b8eSAndroid Build Coastguard Worker         if (size < 2)
142*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
143*ec779b8eSAndroid Build Coastguard Worker         offset += 2;
144*ec779b8eSAndroid Build Coastguard Worker         size -= 2;
145*ec779b8eSAndroid Build Coastguard Worker     }
146*ec779b8eSAndroid Build Coastguard Worker 
147*ec779b8eSAndroid Build Coastguard Worker     if (URL_Flag) {
148*ec779b8eSAndroid Build Coastguard Worker         if (offset >= size) {
149*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
150*ec779b8eSAndroid Build Coastguard Worker         }
151*ec779b8eSAndroid Build Coastguard Worker         unsigned URLlength = mData[offset];
152*ec779b8eSAndroid Build Coastguard Worker         if (URLlength >= size)
153*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
154*ec779b8eSAndroid Build Coastguard Worker         offset += URLlength + 1;
155*ec779b8eSAndroid Build Coastguard Worker         size -= URLlength + 1;
156*ec779b8eSAndroid Build Coastguard Worker     }
157*ec779b8eSAndroid Build Coastguard Worker 
158*ec779b8eSAndroid Build Coastguard Worker     if (OCRstreamFlag) {
159*ec779b8eSAndroid Build Coastguard Worker         if (size < 2)
160*ec779b8eSAndroid Build Coastguard Worker             return ERROR_MALFORMED;
161*ec779b8eSAndroid Build Coastguard Worker         offset += 2;
162*ec779b8eSAndroid Build Coastguard Worker         size -= 2;
163*ec779b8eSAndroid Build Coastguard Worker 
164*ec779b8eSAndroid Build Coastguard Worker         if ((offset >= size || mData[offset] != kTag_DecoderConfigDescriptor)
165*ec779b8eSAndroid Build Coastguard Worker                 && offset - 2 < size
166*ec779b8eSAndroid Build Coastguard Worker                 && mData[offset - 2] == kTag_DecoderConfigDescriptor) {
167*ec779b8eSAndroid Build Coastguard Worker             // Content found "in the wild" had OCRstreamFlag set but was
168*ec779b8eSAndroid Build Coastguard Worker             // missing OCR_ES_Id, the decoder config descriptor immediately
169*ec779b8eSAndroid Build Coastguard Worker             // followed instead.
170*ec779b8eSAndroid Build Coastguard Worker             offset -= 2;
171*ec779b8eSAndroid Build Coastguard Worker             size += 2;
172*ec779b8eSAndroid Build Coastguard Worker 
173*ec779b8eSAndroid Build Coastguard Worker             ALOGW("Found malformed 'esds' atom, ignoring missing OCR_ES_Id.");
174*ec779b8eSAndroid Build Coastguard Worker         }
175*ec779b8eSAndroid Build Coastguard Worker     }
176*ec779b8eSAndroid Build Coastguard Worker 
177*ec779b8eSAndroid Build Coastguard Worker     if (offset >= size) {
178*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
179*ec779b8eSAndroid Build Coastguard Worker     }
180*ec779b8eSAndroid Build Coastguard Worker 
181*ec779b8eSAndroid Build Coastguard Worker     uint8_t tag;
182*ec779b8eSAndroid Build Coastguard Worker     size_t sub_offset, sub_size;
183*ec779b8eSAndroid Build Coastguard Worker     status_t err = skipDescriptorHeader(
184*ec779b8eSAndroid Build Coastguard Worker             offset, size, &tag, &sub_offset, &sub_size);
185*ec779b8eSAndroid Build Coastguard Worker 
186*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
187*ec779b8eSAndroid Build Coastguard Worker         return err;
188*ec779b8eSAndroid Build Coastguard Worker     }
189*ec779b8eSAndroid Build Coastguard Worker 
190*ec779b8eSAndroid Build Coastguard Worker     if (tag != kTag_DecoderConfigDescriptor) {
191*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
192*ec779b8eSAndroid Build Coastguard Worker     }
193*ec779b8eSAndroid Build Coastguard Worker 
194*ec779b8eSAndroid Build Coastguard Worker     err = parseDecoderConfigDescriptor(sub_offset, sub_size);
195*ec779b8eSAndroid Build Coastguard Worker 
196*ec779b8eSAndroid Build Coastguard Worker     return err;
197*ec779b8eSAndroid Build Coastguard Worker }
198*ec779b8eSAndroid Build Coastguard Worker 
getBitRate(uint32_t * brateMax,uint32_t * brateAvg) const199*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::getBitRate(uint32_t *brateMax, uint32_t *brateAvg) const {
200*ec779b8eSAndroid Build Coastguard Worker     if (mInitCheck != OK) {
201*ec779b8eSAndroid Build Coastguard Worker         return mInitCheck;
202*ec779b8eSAndroid Build Coastguard Worker     }
203*ec779b8eSAndroid Build Coastguard Worker 
204*ec779b8eSAndroid Build Coastguard Worker     *brateMax = mBitRateMax;
205*ec779b8eSAndroid Build Coastguard Worker     *brateAvg = mBitRateAvg;
206*ec779b8eSAndroid Build Coastguard Worker 
207*ec779b8eSAndroid Build Coastguard Worker     return OK;
208*ec779b8eSAndroid Build Coastguard Worker };
209*ec779b8eSAndroid Build Coastguard Worker 
parseDecoderConfigDescriptor(size_t offset,size_t size)210*ec779b8eSAndroid Build Coastguard Worker status_t ESDS::parseDecoderConfigDescriptor(size_t offset, size_t size) {
211*ec779b8eSAndroid Build Coastguard Worker     if (size < 13) {
212*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
213*ec779b8eSAndroid Build Coastguard Worker     }
214*ec779b8eSAndroid Build Coastguard Worker 
215*ec779b8eSAndroid Build Coastguard Worker     mObjectTypeIndication = mData[offset];
216*ec779b8eSAndroid Build Coastguard Worker     mBitRateMax = U32_AT(mData + offset + 5);
217*ec779b8eSAndroid Build Coastguard Worker     mBitRateAvg = U32_AT(mData + offset + 9);
218*ec779b8eSAndroid Build Coastguard Worker 
219*ec779b8eSAndroid Build Coastguard Worker     offset += 13;
220*ec779b8eSAndroid Build Coastguard Worker     size -= 13;
221*ec779b8eSAndroid Build Coastguard Worker 
222*ec779b8eSAndroid Build Coastguard Worker     if (size == 0) {
223*ec779b8eSAndroid Build Coastguard Worker         mDecoderSpecificOffset = 0;
224*ec779b8eSAndroid Build Coastguard Worker         mDecoderSpecificLength = 0;
225*ec779b8eSAndroid Build Coastguard Worker         return OK;
226*ec779b8eSAndroid Build Coastguard Worker     }
227*ec779b8eSAndroid Build Coastguard Worker 
228*ec779b8eSAndroid Build Coastguard Worker     uint8_t tag;
229*ec779b8eSAndroid Build Coastguard Worker     size_t sub_offset, sub_size;
230*ec779b8eSAndroid Build Coastguard Worker     status_t err = skipDescriptorHeader(
231*ec779b8eSAndroid Build Coastguard Worker             offset, size, &tag, &sub_offset, &sub_size);
232*ec779b8eSAndroid Build Coastguard Worker 
233*ec779b8eSAndroid Build Coastguard Worker     if (err != OK) {
234*ec779b8eSAndroid Build Coastguard Worker         return err;
235*ec779b8eSAndroid Build Coastguard Worker     }
236*ec779b8eSAndroid Build Coastguard Worker 
237*ec779b8eSAndroid Build Coastguard Worker     if (tag != kTag_DecoderSpecificInfo) {
238*ec779b8eSAndroid Build Coastguard Worker         return ERROR_MALFORMED;
239*ec779b8eSAndroid Build Coastguard Worker     }
240*ec779b8eSAndroid Build Coastguard Worker 
241*ec779b8eSAndroid Build Coastguard Worker     mDecoderSpecificOffset = sub_offset;
242*ec779b8eSAndroid Build Coastguard Worker     mDecoderSpecificLength = sub_size;
243*ec779b8eSAndroid Build Coastguard Worker 
244*ec779b8eSAndroid Build Coastguard Worker     return OK;
245*ec779b8eSAndroid Build Coastguard Worker }
246*ec779b8eSAndroid Build Coastguard Worker 
247*ec779b8eSAndroid Build Coastguard Worker }  // namespace android
248*ec779b8eSAndroid Build Coastguard Worker 
249