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