AAVCAssembler.cpp revision 8d342970108926c4ea355c90d26a2a353ec0fd47
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 "AAVCAssembler.h"
18
19#include "ARTPSource.h"
20
21#include <media/stagefright/foundation/ABuffer.h>
22#include <media/stagefright/foundation/ADebug.h>
23#include <media/stagefright/foundation/AMessage.h>
24#include <media/stagefright/foundation/hexdump.h>
25
26#include <stdint.h>
27
28#define BE_VERBOSE      0
29
30namespace android {
31
32// static
33AAVCAssembler::AAVCAssembler(const sp<AMessage> &notify)
34    : mNotifyMsg(notify),
35      mAccessUnitRTPTime(0),
36      mNextExpectedSeqNoValid(false),
37      mNextExpectedSeqNo(0),
38      mAccessUnitDamaged(false) {
39}
40
41AAVCAssembler::~AAVCAssembler() {
42}
43
44ARTPAssembler::AssemblyStatus AAVCAssembler::addNALUnit(
45        const sp<ARTPSource> &source) {
46    List<sp<ABuffer> > *queue = source->queue();
47
48    if (queue->empty()) {
49        return NOT_ENOUGH_DATA;
50    }
51
52    if (mNextExpectedSeqNoValid) {
53        List<sp<ABuffer> >::iterator it = queue->begin();
54        while (it != queue->end()) {
55            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
56                break;
57            }
58
59            it = queue->erase(it);
60        }
61
62        if (queue->empty()) {
63            return NOT_ENOUGH_DATA;
64        }
65    }
66
67    sp<ABuffer> buffer = *queue->begin();
68
69    if (!mNextExpectedSeqNoValid) {
70        mNextExpectedSeqNoValid = true;
71        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
72    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
73#if BE_VERBOSE
74        LOG(VERBOSE) << "Not the sequence number I expected";
75#endif
76
77        return WRONG_SEQUENCE_NUMBER;
78    }
79
80    const uint8_t *data = buffer->data();
81    size_t size = buffer->size();
82
83    if (size < 1 || (data[0] & 0x80)) {
84        // Corrupt.
85
86        LOG(ERROR) << "Ignoring corrupt buffer.";
87        queue->erase(queue->begin());
88
89        ++mNextExpectedSeqNo;
90        return MALFORMED_PACKET;
91    }
92
93    unsigned nalType = data[0] & 0x1f;
94    if (nalType >= 1 && nalType <= 23) {
95        addSingleNALUnit(buffer);
96        queue->erase(queue->begin());
97        ++mNextExpectedSeqNo;
98        return OK;
99    } else if (nalType == 28) {
100        // FU-A
101        return addFragmentedNALUnit(queue);
102    } else if (nalType == 24) {
103        // STAP-A
104        bool success = addSingleTimeAggregationPacket(buffer);
105        queue->erase(queue->begin());
106        ++mNextExpectedSeqNo;
107
108        return success ? OK : MALFORMED_PACKET;
109    } else {
110        LOG(ERROR) << "Ignoring unsupported buffer (nalType=" << nalType << ")";
111
112        queue->erase(queue->begin());
113        ++mNextExpectedSeqNo;
114
115        return MALFORMED_PACKET;
116    }
117}
118
119void AAVCAssembler::addSingleNALUnit(const sp<ABuffer> &buffer) {
120#if BE_VERBOSE
121    LOG(VERBOSE) << "addSingleNALUnit of size " << buffer->size();
122    hexdump(buffer->data(), buffer->size());
123#endif
124
125    uint32_t rtpTime;
126    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
127
128    if (!mNALUnits.empty() && rtpTime != mAccessUnitRTPTime) {
129        submitAccessUnit();
130    }
131    mAccessUnitRTPTime = rtpTime;
132
133    mNALUnits.push_back(buffer);
134}
135
136bool AAVCAssembler::addSingleTimeAggregationPacket(const sp<ABuffer> &buffer) {
137    const uint8_t *data = buffer->data();
138    size_t size = buffer->size();
139
140    if (size < 3) {
141        LOG(ERROR) << "Discarding too small STAP-A packet.";
142        return false;
143    }
144
145    ++data;
146    --size;
147    while (size >= 2) {
148        size_t nalSize = (data[0] << 8) | data[1];
149
150        if (size < nalSize + 2) {
151            LOG(ERROR) << "Discarding malformed STAP-A packet.";
152            return false;
153        }
154
155        sp<ABuffer> unit = new ABuffer(nalSize);
156        memcpy(unit->data(), &data[2], nalSize);
157
158        CopyTimes(unit, buffer);
159
160        addSingleNALUnit(unit);
161
162        data += 2 + nalSize;
163        size -= 2 + nalSize;
164    }
165
166    if (size != 0) {
167        LOG(WARNING) << "Unexpected padding at end of STAP-A packet.";
168    }
169
170    return true;
171}
172
173ARTPAssembler::AssemblyStatus AAVCAssembler::addFragmentedNALUnit(
174        List<sp<ABuffer> > *queue) {
175    CHECK(!queue->empty());
176
177    sp<ABuffer> buffer = *queue->begin();
178    const uint8_t *data = buffer->data();
179    size_t size = buffer->size();
180
181    CHECK(size > 0);
182    unsigned indicator = data[0];
183
184    CHECK((indicator & 0x1f) == 28);
185
186    if (size < 2) {
187        LOG(ERROR) << "Ignoring malformed FU buffer (size = " << size << ")";
188
189        queue->erase(queue->begin());
190        ++mNextExpectedSeqNo;
191        return MALFORMED_PACKET;
192    }
193
194    if (!(data[1] & 0x80)) {
195        // Start bit not set on the first buffer.
196
197#if BE_VERBOSE
198        LOG(ERROR) << "Start bit not set on first buffer";
199#endif
200
201        queue->erase(queue->begin());
202        ++mNextExpectedSeqNo;
203        return MALFORMED_PACKET;
204    }
205
206    uint32_t nalType = data[1] & 0x1f;
207    uint32_t nri = (data[0] >> 5) & 3;
208
209    uint32_t expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
210    size_t totalSize = size - 2;
211    size_t totalCount = 1;
212    bool complete = false;
213
214    if (data[1] & 0x40) {
215        // Huh? End bit also set on the first buffer.
216
217#if BE_VERBOSE
218        LOG(WARNING) << "Grrr. This isn't fragmented at all.";
219#endif
220
221        complete = true;
222    } else {
223        List<sp<ABuffer> >::iterator it = ++queue->begin();
224        while (it != queue->end()) {
225#if BE_VERBOSE
226            LOG(VERBOSE) << "sequence length " << totalCount;
227#endif
228
229            const sp<ABuffer> &buffer = *it;
230
231            const uint8_t *data = buffer->data();
232            size_t size = buffer->size();
233
234            if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
235#if BE_VERBOSE
236                LOG(VERBOSE) << "sequence not complete, expected seqNo "
237                     << expectedSeqNo << ", got "
238                     << (uint32_t)buffer->int32Data();
239#endif
240
241                return WRONG_SEQUENCE_NUMBER;
242            }
243
244            if (size < 2
245                    || data[0] != indicator
246                    || (data[1] & 0x1f) != nalType
247                    || (data[1] & 0x80)) {
248                LOG(ERROR) << "Ignoring malformed FU buffer.\n";
249
250                // Delete the whole start of the FU.
251
252                it = queue->begin();
253                for (size_t i = 0; i <= totalCount; ++i) {
254                    it = queue->erase(it);
255                }
256
257                mNextExpectedSeqNo = expectedSeqNo + 1;
258
259                return MALFORMED_PACKET;
260            }
261
262            totalSize += size - 2;
263            ++totalCount;
264
265            expectedSeqNo = expectedSeqNo + 1;
266
267            if (data[1] & 0x40) {
268                // This is the last fragment.
269                complete = true;
270                break;
271            }
272
273            ++it;
274        }
275    }
276
277    if (!complete) {
278        return NOT_ENOUGH_DATA;
279    }
280
281    mNextExpectedSeqNo = expectedSeqNo;
282
283    // We found all the fragments that make up the complete NAL unit.
284
285    // Leave room for the header. So far totalSize did not include the
286    // header byte.
287    ++totalSize;
288
289    sp<ABuffer> unit = new ABuffer(totalSize);
290    CopyTimes(unit, *queue->begin());
291
292    unit->data()[0] = (nri << 5) | nalType;
293
294    size_t offset = 1;
295    List<sp<ABuffer> >::iterator it = queue->begin();
296    for (size_t i = 0; i < totalCount; ++i) {
297        const sp<ABuffer> &buffer = *it;
298
299#if BE_VERBOSE
300        LOG(VERBOSE) << "piece #" << (i + 1) << "/" << totalCount;
301        hexdump(buffer->data(), buffer->size());
302#endif
303
304        memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
305        offset += buffer->size() - 2;
306
307        it = queue->erase(it);
308    }
309
310    unit->setRange(0, totalSize);
311
312    addSingleNALUnit(unit);
313
314#if BE_VERBOSE
315    LOG(VERBOSE) << "successfully assembled a NAL unit from fragments.";
316#endif
317
318    return OK;
319}
320
321void AAVCAssembler::submitAccessUnit() {
322    CHECK(!mNALUnits.empty());
323
324#if BE_VERBOSE
325    LOG(VERBOSE) << "Access unit complete (" << mNALUnits.size() << " nal units)";
326#endif
327
328    size_t totalSize = 0;
329    for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
330         it != mNALUnits.end(); ++it) {
331        totalSize += 4 + (*it)->size();
332    }
333
334    sp<ABuffer> accessUnit = new ABuffer(totalSize);
335    size_t offset = 0;
336    for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
337         it != mNALUnits.end(); ++it) {
338        memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
339        offset += 4;
340
341        sp<ABuffer> nal = *it;
342        memcpy(accessUnit->data() + offset, nal->data(), nal->size());
343        offset += nal->size();
344    }
345
346    CopyTimes(accessUnit, *mNALUnits.begin());
347
348#if 0
349    printf(mAccessUnitDamaged ? "X" : ".");
350    fflush(stdout);
351#endif
352
353    if (mAccessUnitDamaged) {
354        accessUnit->meta()->setInt32("damaged", true);
355    }
356
357    mNALUnits.clear();
358    mAccessUnitDamaged = false;
359
360    sp<AMessage> msg = mNotifyMsg->dup();
361    msg->setObject("access-unit", accessUnit);
362    msg->post();
363}
364
365ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
366        const sp<ARTPSource> &source) {
367    AssemblyStatus status = addNALUnit(source);
368    if (status == MALFORMED_PACKET) {
369        mAccessUnitDamaged = true;
370    }
371    return status;
372}
373
374void AAVCAssembler::packetLost() {
375    CHECK(mNextExpectedSeqNoValid);
376    LOG(VERBOSE) << "packetLost (expected " << mNextExpectedSeqNo << ")";
377
378    ++mNextExpectedSeqNo;
379
380    mAccessUnitDamaged = true;
381}
382
383void AAVCAssembler::onByeReceived() {
384    sp<AMessage> msg = mNotifyMsg->dup();
385    msg->setInt32("eos", true);
386    msg->post();
387}
388
389}  // namespace android
390