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