AMPEG4ElementaryAssembler.cpp revision 80804f4e953d6c5f6ed0c3c8e004c4cce280f5c1
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/hexdump.h>
31#include <media/stagefright/Utils.h>
32
33#include <ctype.h>
34#include <stdint.h>
35
36namespace android {
37
38static 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
67static 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
89static 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
109AMPEG4ElementaryAssembler::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
198AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
199}
200
201struct AUHeader {
202    unsigned mSize;
203    unsigned mSerial;
204};
205
206ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
207        const sp<ARTPSource> &source) {
208    List<sp<ABuffer> > *queue = source->queue();
209
210    if (queue->empty()) {
211        return NOT_ENOUGH_DATA;
212    }
213
214    if (mNextExpectedSeqNoValid) {
215        List<sp<ABuffer> >::iterator it = queue->begin();
216        while (it != queue->end()) {
217            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
218                break;
219            }
220
221            it = queue->erase(it);
222        }
223
224        if (queue->empty()) {
225            return NOT_ENOUGH_DATA;
226        }
227    }
228
229    sp<ABuffer> buffer = *queue->begin();
230
231    if (!mNextExpectedSeqNoValid) {
232        mNextExpectedSeqNoValid = true;
233        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
234    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
235        ALOGV("Not the sequence number I expected");
236
237        return WRONG_SEQUENCE_NUMBER;
238    }
239
240    uint32_t rtpTime;
241    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
242
243    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
244        submitAccessUnit();
245    }
246    mAccessUnitRTPTime = rtpTime;
247
248    if (!mIsGeneric) {
249        mPackets.push_back(buffer);
250    } else {
251        // hexdump(buffer->data(), buffer->size());
252        if (buffer->size() < 2) {
253            return MALFORMED_PACKET;
254        }
255
256        unsigned AU_headers_length = U16_AT(buffer->data());  // in bits
257
258        if (buffer->size() < 2 + (AU_headers_length + 7) / 8) {
259            return MALFORMED_PACKET;
260        }
261
262        List<AUHeader> headers;
263
264        ABitReader bits(buffer->data() + 2, buffer->size() - 2);
265        unsigned numBitsLeft = AU_headers_length;
266
267        unsigned AU_serial = 0;
268        for (;;) {
269            if (numBitsLeft < mSizeLength) { break; }
270
271            unsigned AU_size = bits.getBits(mSizeLength);
272            numBitsLeft -= mSizeLength;
273
274            size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
275            if (numBitsLeft < n) { break; }
276
277            unsigned AU_index = bits.getBits(n);
278            numBitsLeft -= n;
279
280            if (headers.empty()) {
281                AU_serial = AU_index;
282            } else {
283                AU_serial += 1 + AU_index;
284            }
285
286            if (mCTSDeltaLength > 0) {
287                if (numBitsLeft < 1) {
288                    break;
289                }
290                --numBitsLeft;
291                if (bits.getBits(1)) {
292                    if (numBitsLeft < mCTSDeltaLength) {
293                        break;
294                    }
295                    bits.skipBits(mCTSDeltaLength);
296                    numBitsLeft -= mCTSDeltaLength;
297                }
298            }
299
300            if (mDTSDeltaLength > 0) {
301                if (numBitsLeft < 1) {
302                    break;
303                }
304                --numBitsLeft;
305                if (bits.getBits(1)) {
306                    if (numBitsLeft < mDTSDeltaLength) {
307                        break;
308                    }
309                    bits.skipBits(mDTSDeltaLength);
310                    numBitsLeft -= mDTSDeltaLength;
311                }
312            }
313
314            if (mRandomAccessIndication) {
315                if (numBitsLeft < 1) {
316                    break;
317                }
318                bits.skipBits(1);
319                --numBitsLeft;
320            }
321
322            if (mStreamStateIndication > 0) {
323                if (numBitsLeft < mStreamStateIndication) {
324                    break;
325                }
326                bits.skipBits(mStreamStateIndication);
327            }
328
329            AUHeader header;
330            header.mSize = AU_size;
331            header.mSerial = AU_serial;
332            headers.push_back(header);
333        }
334
335        size_t offset = 2 + (AU_headers_length + 7) / 8;
336
337        if (mAuxiliaryDataSizeLength > 0) {
338            ABitReader bits(buffer->data() + offset, buffer->size() - offset);
339
340            unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
341
342            offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
343        }
344
345        for (List<AUHeader>::iterator it = headers.begin();
346             it != headers.end(); ++it) {
347            const AUHeader &header = *it;
348
349            if (buffer->size() < offset + header.mSize) {
350                return MALFORMED_PACKET;
351            }
352
353            sp<ABuffer> accessUnit = new ABuffer(header.mSize);
354            memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
355
356            offset += header.mSize;
357
358            CopyTimes(accessUnit, buffer);
359            mPackets.push_back(accessUnit);
360        }
361
362        if (offset != buffer->size()) {
363            ALOGW("potentially malformed packet (offset %d, size %d)",
364                    offset, buffer->size());
365        }
366    }
367
368    queue->erase(queue->begin());
369    ++mNextExpectedSeqNo;
370
371    return OK;
372}
373
374void AMPEG4ElementaryAssembler::submitAccessUnit() {
375    CHECK(!mPackets.empty());
376
377    ALOGV("Access unit complete (%zu nal units)", mPackets.size());
378
379    sp<ABuffer> accessUnit;
380
381    if (mIsGeneric) {
382        accessUnit = MakeADTSCompoundFromAACFrames(
383                OMX_AUDIO_AACObjectLC - 1,
384                mSampleRateIndex,
385                mChannelConfig,
386                mPackets);
387    } else {
388        accessUnit = MakeCompoundFromPackets(mPackets);
389    }
390
391#if 0
392    printf(mAccessUnitDamaged ? "X" : ".");
393    fflush(stdout);
394#endif
395
396    if (mAccessUnitDamaged) {
397        accessUnit->meta()->setInt32("damaged", true);
398    }
399
400    mPackets.clear();
401    mAccessUnitDamaged = false;
402
403    sp<AMessage> msg = mNotifyMsg->dup();
404    msg->setBuffer("access-unit", accessUnit);
405    msg->post();
406}
407
408ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
409        const sp<ARTPSource> &source) {
410    AssemblyStatus status = addPacket(source);
411    if (status == MALFORMED_PACKET) {
412        ALOGI("access unit is damaged");
413        mAccessUnitDamaged = true;
414    }
415    return status;
416}
417
418void AMPEG4ElementaryAssembler::packetLost() {
419    CHECK(mNextExpectedSeqNoValid);
420    ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
421
422    ++mNextExpectedSeqNo;
423
424    mAccessUnitDamaged = true;
425}
426
427void AMPEG4ElementaryAssembler::onByeReceived() {
428    sp<AMessage> msg = mNotifyMsg->dup();
429    msg->setInt32("eos", true);
430    msg->post();
431}
432
433}  // namespace android
434