1 /*
2  * Copyright (C) 2010 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 "AMPEG4ElementaryAssembler"
19 #include <utils/Log.h>
20 
21 #include "AMPEG4ElementaryAssembler.h"
22 
23 #include "ARTPSource.h"
24 #include "ASessionDescription.h"
25 
26 #include <media/stagefright/foundation/ABitReader.h>
27 #include <media/stagefright/foundation/ABuffer.h>
28 #include <media/stagefright/foundation/ADebug.h>
29 #include <media/stagefright/foundation/AMessage.h>
30 #include <media/stagefright/foundation/ByteUtils.h>
31 #include <media/stagefright/foundation/hexdump.h>
32 
33 #include <ctype.h>
34 #include <stdint.h>
35 
36 namespace android {
37 
GetAttribute(const char * s,const char * key,AString * value)38 static bool GetAttribute(const char *s, const char *key, AString *value) {
39     value->clear();
40 
41     size_t keyLen = strlen(key);
42 
43     for (;;) {
44         while (isspace(*s)) {
45             ++s;
46         }
47 
48         const char *colonPos = strchr(s, ';');
49 
50         size_t len =
51             (colonPos == NULL) ? strlen(s) : colonPos - s;
52 
53         if (len >= keyLen + 1 && s[keyLen] == '='
54                 && !strncasecmp(s, key, keyLen)) {
55             value->setTo(&s[keyLen + 1], len - keyLen - 1);
56             return true;
57         }
58 
59         if (colonPos == NULL) {
60             return false;
61         }
62 
63         s = colonPos + 1;
64     }
65 }
66 
GetIntegerAttribute(const char * s,const char * key,unsigned * x)67 static bool GetIntegerAttribute(
68         const char *s, const char *key, unsigned *x) {
69     *x = 0;
70 
71     AString val;
72     if (!GetAttribute(s, key, &val)) {
73         return false;
74     }
75 
76     s = val.c_str();
77     char *end;
78     unsigned y = strtoul(s, &end, 10);
79 
80     if (end == s || *end != '\0') {
81         return false;
82     }
83 
84     *x = y;
85 
86     return true;
87 }
88 
GetSampleRateIndex(int32_t sampleRate,size_t * tableIndex)89 static bool GetSampleRateIndex(int32_t sampleRate, size_t *tableIndex) {
90     static const int32_t kSampleRateTable[] = {
91         96000, 88200, 64000, 48000, 44100, 32000,
92         24000, 22050, 16000, 12000, 11025, 8000
93     };
94     const size_t kNumSampleRates =
95         sizeof(kSampleRateTable) / sizeof(kSampleRateTable[0]);
96 
97     *tableIndex = 0;
98     for (size_t index = 0; index < kNumSampleRates; ++index) {
99         if (sampleRate == kSampleRateTable[index]) {
100             *tableIndex = index;
101             return true;
102         }
103     }
104 
105     return false;
106 }
107 
108 // static
AMPEG4ElementaryAssembler(const sp<AMessage> & notify,const AString & desc,const AString & params)109 AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
110         const sp<AMessage> &notify, const AString &desc, const AString &params)
111     : mNotifyMsg(notify),
112       mIsGeneric(false),
113       mParams(params),
114       mSizeLength(0),
115       mIndexLength(0),
116       mIndexDeltaLength(0),
117       mCTSDeltaLength(0),
118       mDTSDeltaLength(0),
119       mRandomAccessIndication(false),
120       mStreamStateIndication(0),
121       mAuxiliaryDataSizeLength(0),
122       mHasAUHeader(false),
123       mChannelConfig(0),
124       mSampleRateIndex(0),
125       mAccessUnitRTPTime(0),
126       mNextExpectedSeqNoValid(false),
127       mNextExpectedSeqNo(0),
128       mAccessUnitDamaged(false) {
129     mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
130 
131     if (mIsGeneric) {
132         AString value;
133         CHECK(GetAttribute(params.c_str(), "mode", &value));
134 
135         if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) {
136             mSizeLength = 0;
137         }
138 
139         if (!GetIntegerAttribute(
140                     params.c_str(), "indexLength", &mIndexLength)) {
141             mIndexLength = 0;
142         }
143 
144         if (!GetIntegerAttribute(
145                     params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) {
146             mIndexDeltaLength = 0;
147         }
148 
149         if (!GetIntegerAttribute(
150                     params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) {
151             mCTSDeltaLength = 0;
152         }
153 
154         if (!GetIntegerAttribute(
155                     params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) {
156             mDTSDeltaLength = 0;
157         }
158 
159         unsigned x;
160         if (!GetIntegerAttribute(
161                     params.c_str(), "randomAccessIndication", &x)) {
162             mRandomAccessIndication = false;
163         } else {
164             CHECK(x == 0 || x == 1);
165             mRandomAccessIndication = (x != 0);
166         }
167 
168         if (!GetIntegerAttribute(
169                     params.c_str(), "streamStateIndication",
170                     &mStreamStateIndication)) {
171             mStreamStateIndication = 0;
172         }
173 
174         if (!GetIntegerAttribute(
175                     params.c_str(), "auxiliaryDataSizeLength",
176                     &mAuxiliaryDataSizeLength)) {
177             mAuxiliaryDataSizeLength = 0;
178         }
179 
180         mHasAUHeader =
181             mSizeLength > 0
182             || mIndexLength > 0
183             || mIndexDeltaLength > 0
184             || mCTSDeltaLength > 0
185             || mDTSDeltaLength > 0
186             || mRandomAccessIndication
187             || mStreamStateIndication > 0;
188 
189         int32_t sampleRate, numChannels;
190         ASessionDescription::ParseFormatDesc(
191                 desc.c_str(), &sampleRate, &numChannels);
192 
193         mChannelConfig = numChannels;
194         CHECK(GetSampleRateIndex(sampleRate, &mSampleRateIndex));
195     }
196 }
197 
~AMPEG4ElementaryAssembler()198 AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
199 }
200 
201 struct AUHeader {
202     unsigned mSize;
203     unsigned mSerial;
204 };
205 
initCheck()206 bool AMPEG4ElementaryAssembler::initCheck() {
207     if(mSizeLength == 0 || mIndexLength == 0 || mIndexDeltaLength == 0) {
208         android_errorWriteLog(0x534e4554, "124777537");
209         return false;
210     }
211     return true;
212 }
213 
addPacket(const sp<ARTPSource> & source)214 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
215         const sp<ARTPSource> &source) {
216     List<sp<ABuffer> > *queue = source->queue();
217 
218     if (queue->empty()) {
219         return NOT_ENOUGH_DATA;
220     }
221 
222     if (mNextExpectedSeqNoValid) {
223         List<sp<ABuffer> >::iterator it = queue->begin();
224         while (it != queue->end()) {
225             if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
226                 break;
227             }
228 
229             it = queue->erase(it);
230         }
231 
232         if (queue->empty()) {
233             return NOT_ENOUGH_DATA;
234         }
235     }
236 
237     sp<ABuffer> buffer = *queue->begin();
238 
239     if (!mNextExpectedSeqNoValid) {
240         mNextExpectedSeqNoValid = true;
241         mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
242     } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
243         ALOGV("Not the sequence number I expected");
244 
245         return WRONG_SEQUENCE_NUMBER;
246     }
247 
248     uint32_t rtpTime;
249     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
250 
251     if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
252         submitAccessUnit();
253     }
254     mAccessUnitRTPTime = rtpTime;
255 
256     if (!mIsGeneric) {
257         mPackets.push_back(buffer);
258     } else {
259         // hexdump(buffer->data(), buffer->size());
260         if (buffer->size() < 2) {
261             android_errorWriteLog(0x534e4554, "124783982");
262             queue->erase(queue->begin());
263             return MALFORMED_PACKET;
264         }
265 
266         unsigned AU_headers_length = U16_AT(buffer->data());  // in bits
267 
268         if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
269             android_errorWriteLog(0x534e4554, "124783982");
270             queue->erase(queue->begin());
271             return MALFORMED_PACKET;
272         }
273 
274         List<AUHeader> headers;
275 
276         ABitReader bits(buffer->data() + 2, buffer->size() - 2);
277         unsigned numBitsLeft = AU_headers_length;
278 
279         unsigned AU_serial = 0;
280         for (;;) {
281             if (numBitsLeft < mSizeLength) { break; }
282 
283             unsigned AU_size = bits.getBits(mSizeLength);
284             numBitsLeft -= mSizeLength;
285 
286             size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
287             if (numBitsLeft < n) { break; }
288 
289             unsigned AU_index = bits.getBits(n);
290             numBitsLeft -= n;
291 
292             if (headers.empty()) {
293                 AU_serial = AU_index;
294             } else {
295                 AU_serial += 1 + AU_index;
296             }
297 
298             if (mCTSDeltaLength > 0) {
299                 if (numBitsLeft < 1) {
300                     break;
301                 }
302                 --numBitsLeft;
303                 if (bits.getBits(1)) {
304                     if (numBitsLeft < mCTSDeltaLength) {
305                         break;
306                     }
307                     bits.skipBits(mCTSDeltaLength);
308                     numBitsLeft -= mCTSDeltaLength;
309                 }
310             }
311 
312             if (mDTSDeltaLength > 0) {
313                 if (numBitsLeft < 1) {
314                     break;
315                 }
316                 --numBitsLeft;
317                 if (bits.getBits(1)) {
318                     if (numBitsLeft < mDTSDeltaLength) {
319                         break;
320                     }
321                     bits.skipBits(mDTSDeltaLength);
322                     numBitsLeft -= mDTSDeltaLength;
323                 }
324             }
325 
326             if (mRandomAccessIndication) {
327                 if (numBitsLeft < 1) {
328                     break;
329                 }
330                 bits.skipBits(1);
331                 --numBitsLeft;
332             }
333 
334             if (mStreamStateIndication > 0) {
335                 if (numBitsLeft < mStreamStateIndication) {
336                     break;
337                 }
338                 bits.skipBits(mStreamStateIndication);
339             }
340 
341             AUHeader header;
342             header.mSize = AU_size;
343             header.mSerial = AU_serial;
344             headers.push_back(header);
345         }
346 
347         size_t offset = 2 + (AU_headers_length + 7) / 8;
348 
349         if (mAuxiliaryDataSizeLength > 0) {
350             ABitReader bits(buffer->data() + offset, buffer->size() - offset);
351 
352             unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
353             if (buffer->size() < auxSize) {
354                 ALOGE("b/123940919 auxSize %u", auxSize);
355                 android_errorWriteLog(0x534e4554, "123940919");
356                 queue->erase(queue->begin());
357                 return MALFORMED_PACKET;
358             }
359 
360             offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
361         }
362 
363         for (List<AUHeader>::iterator it = headers.begin();
364              it != headers.end(); ++it) {
365             const AUHeader &header = *it;
366 
367             if (buffer->size() < header.mSize) {
368                 ALOGE("b/123940919 AU_size %u", header.mSize);
369                 android_errorWriteLog(0x534e4554, "123940919");
370                 queue->erase(queue->begin());
371                 return MALFORMED_PACKET;
372             }
373             if (buffer->size() < offset + header.mSize) {
374                 android_errorWriteLog(0x534e4554, "124783982");
375                 queue->erase(queue->begin());
376                 return MALFORMED_PACKET;
377             }
378 
379             sp<ABuffer> accessUnit = new ABuffer(header.mSize);
380             memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
381 
382             offset += header.mSize;
383 
384             CopyTimes(accessUnit, buffer);
385             mPackets.push_back(accessUnit);
386         }
387 
388         if (offset != buffer->size()) {
389             ALOGW("potentially malformed packet (offset %zu, size %zu)",
390                     offset, buffer->size());
391         }
392     }
393 
394     queue->erase(queue->begin());
395     ++mNextExpectedSeqNo;
396 
397     return OK;
398 }
399 
submitAccessUnit()400 void AMPEG4ElementaryAssembler::submitAccessUnit() {
401     CHECK(!mPackets.empty());
402 
403     ALOGV("Access unit complete (%zu nal units)", mPackets.size());
404 
405     sp<ABuffer> accessUnit;
406 
407     if (mIsGeneric) {
408         accessUnit = MakeADTSCompoundFromAACFrames(
409                 OMX_AUDIO_AACObjectLC - 1,
410                 mSampleRateIndex,
411                 mChannelConfig,
412                 mPackets);
413     } else {
414         accessUnit = MakeCompoundFromPackets(mPackets);
415     }
416 
417 #if 0
418     printf(mAccessUnitDamaged ? "X" : ".");
419     fflush(stdout);
420 #endif
421 
422     if (mAccessUnitDamaged) {
423         accessUnit->meta()->setInt32("damaged", true);
424     }
425 
426     mPackets.clear();
427     mAccessUnitDamaged = false;
428 
429     sp<AMessage> msg = mNotifyMsg->dup();
430     msg->setBuffer("access-unit", accessUnit);
431     msg->post();
432 }
433 
assembleMore(const sp<ARTPSource> & source)434 ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
435         const sp<ARTPSource> &source) {
436     AssemblyStatus status = addPacket(source);
437     if (status == MALFORMED_PACKET) {
438         ALOGI("access unit is damaged");
439         mAccessUnitDamaged = true;
440     }
441     return status;
442 }
443 
packetLost()444 void AMPEG4ElementaryAssembler::packetLost() {
445     CHECK(mNextExpectedSeqNoValid);
446     ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
447 
448     ++mNextExpectedSeqNo;
449 
450     mAccessUnitDamaged = true;
451 }
452 
onByeReceived()453 void AMPEG4ElementaryAssembler::onByeReceived() {
454     sp<AMessage> msg = mNotifyMsg->dup();
455     msg->setInt32("eos", true);
456     msg->post();
457 }
458 
459 }  // namespace android
460