AMPEG4AudioAssembler.cpp revision fc9ac988e08a8b4c42e58999300265989f26f24c
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#include "AMPEG4AudioAssembler.h"
18
19#include "ARTPSource.h"
20
21#include <media/stagefright/foundation/hexdump.h>
22#include <media/stagefright/foundation/ABitReader.h>
23#include <media/stagefright/foundation/ABuffer.h>
24#include <media/stagefright/foundation/ADebug.h>
25#include <media/stagefright/foundation/AMessage.h>
26#include <media/stagefright/MediaErrors.h>
27
28#include <ctype.h>
29
30namespace android {
31
32static bool GetAttribute(const char *s, const char *key, AString *value) {
33    value->clear();
34
35    size_t keyLen = strlen(key);
36
37    for (;;) {
38        while (isspace(*s)) {
39            ++s;
40        }
41
42        const char *colonPos = strchr(s, ';');
43
44        size_t len =
45            (colonPos == NULL) ? strlen(s) : colonPos - s;
46
47        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
48            value->setTo(&s[keyLen + 1], len - keyLen - 1);
49            return true;
50        }
51
52        if (colonPos == NULL) {
53            return false;
54        }
55
56        s = colonPos + 1;
57    }
58}
59
60static sp<ABuffer> decodeHex(const AString &s) {
61    if ((s.size() % 2) != 0) {
62        return NULL;
63    }
64
65    size_t outLen = s.size() / 2;
66    sp<ABuffer> buffer = new ABuffer(outLen);
67    uint8_t *out = buffer->data();
68
69    uint8_t accum = 0;
70    for (size_t i = 0; i < s.size(); ++i) {
71        char c = s.c_str()[i];
72        unsigned value;
73        if (c >= '0' && c <= '9') {
74            value = c - '0';
75        } else if (c >= 'a' && c <= 'f') {
76            value = c - 'a' + 10;
77        } else if (c >= 'A' && c <= 'F') {
78            value = c - 'A' + 10;
79        } else {
80            return NULL;
81        }
82
83        accum = (accum << 4) | value;
84
85        if (i & 1) {
86            *out++ = accum;
87
88            accum = 0;
89        }
90    }
91
92    return buffer;
93}
94
95static status_t parseAudioObjectType(
96        ABitReader *bits, unsigned *audioObjectType) {
97    *audioObjectType = bits->getBits(5);
98    if ((*audioObjectType) == 31) {
99        *audioObjectType = 32 + bits->getBits(6);
100    }
101
102    return OK;
103}
104
105static status_t parseGASpecificConfig(
106        ABitReader *bits,
107        unsigned audioObjectType, unsigned channelConfiguration) {
108    unsigned frameLengthFlag = bits->getBits(1);
109    unsigned dependsOnCoreCoder = bits->getBits(1);
110    if (dependsOnCoreCoder) {
111        /* unsigned coreCoderDelay = */bits->getBits(1);
112    }
113    unsigned extensionFlag = bits->getBits(1);
114
115    if (!channelConfiguration) {
116        // program_config_element
117        return ERROR_UNSUPPORTED;  // XXX to be implemented
118    }
119
120    if (audioObjectType == 6 || audioObjectType == 20) {
121        /* unsigned layerNr = */bits->getBits(3);
122    }
123
124    if (extensionFlag) {
125        if (audioObjectType == 22) {
126            /* unsigned numOfSubFrame = */bits->getBits(5);
127            /* unsigned layerLength = */bits->getBits(11);
128        } else if (audioObjectType == 17 || audioObjectType == 19
129                || audioObjectType == 20 || audioObjectType == 23) {
130            /* unsigned aacSectionDataResilienceFlag = */bits->getBits(1);
131            /* unsigned aacScalefactorDataResilienceFlag = */bits->getBits(1);
132            /* unsigned aacSpectralDataResilienceFlag = */bits->getBits(1);
133        }
134
135        unsigned extensionFlag3 = bits->getBits(1);
136        CHECK_EQ(extensionFlag3, 0u);  // TBD in version 3
137    }
138
139    return OK;
140}
141
142static status_t parseAudioSpecificConfig(ABitReader *bits) {
143    unsigned audioObjectType;
144    CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
145
146    unsigned samplingFreqIndex = bits->getBits(4);
147    if (samplingFreqIndex == 0x0f) {
148        /* unsigned samplingFrequency = */bits->getBits(24);
149    }
150
151    unsigned channelConfiguration = bits->getBits(4);
152
153    unsigned extensionAudioObjectType = 0;
154    unsigned sbrPresent = 0;
155
156    if (audioObjectType == 5) {
157        extensionAudioObjectType = audioObjectType;
158        sbrPresent = 1;
159        unsigned extensionSamplingFreqIndex = bits->getBits(4);
160        if (extensionSamplingFreqIndex == 0x0f) {
161            /* unsigned extensionSamplingFrequency = */bits->getBits(24);
162        }
163        CHECK_EQ(parseAudioObjectType(bits, &audioObjectType), (status_t)OK);
164    }
165
166    CHECK((audioObjectType >= 1 && audioObjectType <= 4)
167        || (audioObjectType >= 6 && audioObjectType <= 7)
168        || audioObjectType == 17
169        || (audioObjectType >= 19 && audioObjectType <= 23));
170
171    CHECK_EQ(parseGASpecificConfig(
172                bits, audioObjectType, channelConfiguration), (status_t)OK);
173
174    if (audioObjectType == 17
175            || (audioObjectType >= 19 && audioObjectType <= 27)) {
176        unsigned epConfig = bits->getBits(2);
177        if (epConfig == 2 || epConfig == 3) {
178            // ErrorProtectionSpecificConfig
179            return ERROR_UNSUPPORTED;  // XXX to be implemented
180
181            if (epConfig == 3) {
182                unsigned directMapping = bits->getBits(1);
183                CHECK_EQ(directMapping, 1u);
184            }
185        }
186    }
187
188#if 0
189    // This is not supported here as the upper layers did not explicitly
190    // signal the length of AudioSpecificConfig.
191
192    if (extensionAudioObjectType != 5 && bits->numBitsLeft() >= 16) {
193        unsigned syncExtensionType = bits->getBits(11);
194        if (syncExtensionType == 0x2b7) {
195            CHECK_EQ(parseAudioObjectType(bits, &extensionAudioObjectType),
196                     (status_t)OK);
197
198            sbrPresent = bits->getBits(1);
199
200            if (sbrPresent == 1) {
201                unsigned extensionSamplingFreqIndex = bits->getBits(4);
202                if (extensionSamplingFreqIndex == 0x0f) {
203                    /* unsigned extensionSamplingFrequency = */bits->getBits(24);
204                }
205            }
206        }
207    }
208#endif
209
210    return OK;
211}
212
213static status_t parseStreamMuxConfig(
214        ABitReader *bits,
215        unsigned *numSubFrames,
216        unsigned *frameLengthType,
217        bool *otherDataPresent,
218        unsigned *otherDataLenBits) {
219    unsigned audioMuxVersion = bits->getBits(1);
220
221    unsigned audioMuxVersionA = 0;
222    if (audioMuxVersion == 1) {
223        audioMuxVersionA = bits->getBits(1);
224    }
225
226    CHECK_EQ(audioMuxVersionA, 0u);  // otherwise future spec
227
228    if (audioMuxVersion != 0) {
229        return ERROR_UNSUPPORTED;  // XXX to be implemented;
230    }
231    CHECK_EQ(audioMuxVersion, 0u);  // XXX to be implemented
232
233    unsigned allStreamsSameTimeFraming = bits->getBits(1);
234    CHECK_EQ(allStreamsSameTimeFraming, 1u);  // There's only one stream.
235
236    *numSubFrames = bits->getBits(6);
237    unsigned numProgram = bits->getBits(4);
238    CHECK_EQ(numProgram, 0u);  // disabled in RTP LATM
239
240    unsigned numLayer = bits->getBits(3);
241    CHECK_EQ(numLayer, 0u);  // disabled in RTP LATM
242
243    if (audioMuxVersion == 0) {
244        // AudioSpecificConfig
245        CHECK_EQ(parseAudioSpecificConfig(bits), (status_t)OK);
246    } else {
247        TRESPASS();  // XXX to be implemented
248    }
249
250    *frameLengthType = bits->getBits(3);
251    switch (*frameLengthType) {
252        case 0:
253        {
254            /* unsigned bufferFullness = */bits->getBits(8);
255
256            // The "coreFrameOffset" does not apply since there's only
257            // a single layer.
258            break;
259        }
260
261        case 1:
262        {
263            /* unsigned frameLength = */bits->getBits(9);
264            break;
265        }
266
267        case 3:
268        case 4:
269        case 5:
270        {
271            /* unsigned CELPframeLengthTableIndex = */bits->getBits(6);
272            break;
273        }
274
275        case 6:
276        case 7:
277        {
278            /* unsigned HVXCframeLengthTableIndex = */bits->getBits(1);
279            break;
280        }
281
282        default:
283            break;
284    }
285
286    *otherDataPresent = bits->getBits(1);
287    *otherDataLenBits = 0;
288    if (*otherDataPresent) {
289        if (audioMuxVersion == 1) {
290            TRESPASS();  // XXX to be implemented
291        } else {
292            *otherDataLenBits = 0;
293
294            unsigned otherDataLenEsc;
295            do {
296                (*otherDataLenBits) <<= 8;
297                otherDataLenEsc = bits->getBits(1);
298                unsigned otherDataLenTmp = bits->getBits(8);
299                (*otherDataLenBits) += otherDataLenTmp;
300            } while (otherDataLenEsc);
301        }
302    }
303
304    unsigned crcCheckPresent = bits->getBits(1);
305    if (crcCheckPresent) {
306        /* unsigned crcCheckSum = */bits->getBits(8);
307    }
308
309    return OK;
310}
311
312sp<ABuffer> AMPEG4AudioAssembler::removeLATMFraming(const sp<ABuffer> &buffer) {
313    CHECK(!mMuxConfigPresent);  // XXX to be implemented
314
315    sp<ABuffer> out = new ABuffer(buffer->size());
316    out->setRange(0, 0);
317
318    size_t offset = 0;
319    uint8_t *ptr = buffer->data();
320
321    for (size_t i = 0; i <= mNumSubFrames; ++i) {
322        // parse PayloadLengthInfo
323
324        unsigned payloadLength = 0;
325
326        switch (mFrameLengthType) {
327            case 0:
328            {
329                unsigned muxSlotLengthBytes = 0;
330                unsigned tmp;
331                do {
332                    CHECK_LT(offset, buffer->size());
333                    tmp = ptr[offset++];
334                    muxSlotLengthBytes += tmp;
335                } while (tmp == 0xff);
336
337                payloadLength = muxSlotLengthBytes;
338                break;
339            }
340
341            default:
342                TRESPASS();  // XXX to be implemented
343                break;
344        }
345
346        CHECK_LE(offset + payloadLength, buffer->size());
347
348        memcpy(out->data() + out->size(), &ptr[offset], payloadLength);
349        out->setRange(0, out->size() + payloadLength);
350
351        offset += payloadLength;
352
353        if (mOtherDataPresent) {
354            // We want to stay byte-aligned.
355
356            CHECK((mOtherDataLenBits % 8) == 0);
357            CHECK_LE(offset + (mOtherDataLenBits / 8), buffer->size());
358            offset += mOtherDataLenBits / 8;
359        }
360    }
361
362    CHECK_EQ(offset, buffer->size());
363
364    return out;
365}
366
367AMPEG4AudioAssembler::AMPEG4AudioAssembler(
368        const sp<AMessage> &notify, const AString &params)
369    : mNotifyMsg(notify),
370      mMuxConfigPresent(false),
371      mAccessUnitRTPTime(0),
372      mNextExpectedSeqNoValid(false),
373      mNextExpectedSeqNo(0),
374      mAccessUnitDamaged(false) {
375    AString val;
376    if (!GetAttribute(params.c_str(), "cpresent", &val)) {
377        mMuxConfigPresent = true;
378    } else if (val == "0") {
379        mMuxConfigPresent = false;
380    } else {
381        CHECK(val == "1");
382        mMuxConfigPresent = true;
383    }
384
385    CHECK(GetAttribute(params.c_str(), "config", &val));
386
387    sp<ABuffer> config = decodeHex(val);
388    CHECK(config != NULL);
389
390    ABitReader bits(config->data(), config->size());
391    status_t err = parseStreamMuxConfig(
392            &bits, &mNumSubFrames, &mFrameLengthType,
393            &mOtherDataPresent, &mOtherDataLenBits);
394
395    CHECK_EQ(err, (status_t)NO_ERROR);
396}
397
398AMPEG4AudioAssembler::~AMPEG4AudioAssembler() {
399}
400
401ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::assembleMore(
402        const sp<ARTPSource> &source) {
403    AssemblyStatus status = addPacket(source);
404    if (status == MALFORMED_PACKET) {
405        mAccessUnitDamaged = true;
406    }
407    return status;
408}
409
410ARTPAssembler::AssemblyStatus AMPEG4AudioAssembler::addPacket(
411        const sp<ARTPSource> &source) {
412    List<sp<ABuffer> > *queue = source->queue();
413
414    if (queue->empty()) {
415        return NOT_ENOUGH_DATA;
416    }
417
418    if (mNextExpectedSeqNoValid) {
419        List<sp<ABuffer> >::iterator it = queue->begin();
420        while (it != queue->end()) {
421            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
422                break;
423            }
424
425            it = queue->erase(it);
426        }
427
428        if (queue->empty()) {
429            return NOT_ENOUGH_DATA;
430        }
431    }
432
433    sp<ABuffer> buffer = *queue->begin();
434
435    if (!mNextExpectedSeqNoValid) {
436        mNextExpectedSeqNoValid = true;
437        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
438    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
439#if VERBOSE
440        LOG(VERBOSE) << "Not the sequence number I expected";
441#endif
442
443        return WRONG_SEQUENCE_NUMBER;
444    }
445
446    uint32_t rtpTime;
447    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
448
449    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
450        submitAccessUnit();
451    }
452    mAccessUnitRTPTime = rtpTime;
453
454    mPackets.push_back(buffer);
455
456    queue->erase(queue->begin());
457    ++mNextExpectedSeqNo;
458
459    return OK;
460}
461
462void AMPEG4AudioAssembler::submitAccessUnit() {
463    CHECK(!mPackets.empty());
464
465#if VERBOSE
466    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
467#endif
468
469    size_t totalSize = 0;
470    List<sp<ABuffer> >::iterator it = mPackets.begin();
471    while (it != mPackets.end()) {
472        const sp<ABuffer> &unit = *it;
473
474        totalSize += unit->size();
475        ++it;
476    }
477
478    sp<ABuffer> accessUnit = new ABuffer(totalSize);
479    size_t offset = 0;
480    it = mPackets.begin();
481    while (it != mPackets.end()) {
482        const sp<ABuffer> &unit = *it;
483
484        memcpy((uint8_t *)accessUnit->data() + offset,
485               unit->data(), unit->size());
486
487        ++it;
488    }
489
490    accessUnit = removeLATMFraming(accessUnit);
491    CopyTimes(accessUnit, *mPackets.begin());
492
493#if 0
494    printf(mAccessUnitDamaged ? "X" : ".");
495    fflush(stdout);
496#endif
497
498    if (mAccessUnitDamaged) {
499        accessUnit->meta()->setInt32("damaged", true);
500    }
501
502    mPackets.clear();
503    mAccessUnitDamaged = false;
504
505    sp<AMessage> msg = mNotifyMsg->dup();
506    msg->setObject("access-unit", accessUnit);
507    msg->post();
508}
509
510void AMPEG4AudioAssembler::packetLost() {
511    CHECK(mNextExpectedSeqNoValid);
512    ++mNextExpectedSeqNo;
513
514    mAccessUnitDamaged = true;
515}
516
517void AMPEG4AudioAssembler::onByeReceived() {
518    sp<AMessage> msg = mNotifyMsg->dup();
519    msg->setInt32("eos", true);
520    msg->post();
521}
522
523}  // namespace android
524