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 {
110        ALOGV("Ignoring unsupported buffer (nalType=%d)", 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    ALOGV("addSingleNALUnit of size %d", buffer->size());
121#if !LOG_NDEBUG
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        ALOGV("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            ALOGV("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        ALOGV("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        ALOGV("Ignoring malformed FU buffer (size = %d)", 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        ALOGV("Start bit not set on first buffer");
198
199        queue->erase(queue->begin());
200        ++mNextExpectedSeqNo;
201        return MALFORMED_PACKET;
202    }
203
204    uint32_t nalType = data[1] & 0x1f;
205    uint32_t nri = (data[0] >> 5) & 3;
206
207    uint32_t expectedSeqNo = (uint32_t)buffer->int32Data() + 1;
208    size_t totalSize = size - 2;
209    size_t totalCount = 1;
210    bool complete = false;
211
212    if (data[1] & 0x40) {
213        // Huh? End bit also set on the first buffer.
214
215        ALOGV("Grrr. This isn't fragmented at all.");
216
217        complete = true;
218    } else {
219        List<sp<ABuffer> >::iterator it = ++queue->begin();
220        while (it != queue->end()) {
221            ALOGV("sequence length %d", totalCount);
222
223            const sp<ABuffer> &buffer = *it;
224
225            const uint8_t *data = buffer->data();
226            size_t size = buffer->size();
227
228            if ((uint32_t)buffer->int32Data() != expectedSeqNo) {
229                ALOGV("sequence not complete, expected seqNo %d, got %d",
230                     expectedSeqNo, (uint32_t)buffer->int32Data());
231
232                return WRONG_SEQUENCE_NUMBER;
233            }
234
235            if (size < 2
236                    || data[0] != indicator
237                    || (data[1] & 0x1f) != nalType
238                    || (data[1] & 0x80)) {
239                ALOGV("Ignoring malformed FU buffer.");
240
241                // Delete the whole start of the FU.
242
243                it = queue->begin();
244                for (size_t i = 0; i <= totalCount; ++i) {
245                    it = queue->erase(it);
246                }
247
248                mNextExpectedSeqNo = expectedSeqNo + 1;
249
250                return MALFORMED_PACKET;
251            }
252
253            totalSize += size - 2;
254            ++totalCount;
255
256            expectedSeqNo = expectedSeqNo + 1;
257
258            if (data[1] & 0x40) {
259                // This is the last fragment.
260                complete = true;
261                break;
262            }
263
264            ++it;
265        }
266    }
267
268    if (!complete) {
269        return NOT_ENOUGH_DATA;
270    }
271
272    mNextExpectedSeqNo = expectedSeqNo;
273
274    // We found all the fragments that make up the complete NAL unit.
275
276    // Leave room for the header. So far totalSize did not include the
277    // header byte.
278    ++totalSize;
279
280    sp<ABuffer> unit = new ABuffer(totalSize);
281    CopyTimes(unit, *queue->begin());
282
283    unit->data()[0] = (nri << 5) | nalType;
284
285    size_t offset = 1;
286    List<sp<ABuffer> >::iterator it = queue->begin();
287    for (size_t i = 0; i < totalCount; ++i) {
288        const sp<ABuffer> &buffer = *it;
289
290        ALOGV("piece #%d/%d", i + 1, totalCount);
291#if !LOG_NDEBUG
292        hexdump(buffer->data(), buffer->size());
293#endif
294
295        memcpy(unit->data() + offset, buffer->data() + 2, buffer->size() - 2);
296        offset += buffer->size() - 2;
297
298        it = queue->erase(it);
299    }
300
301    unit->setRange(0, totalSize);
302
303    addSingleNALUnit(unit);
304
305    ALOGV("successfully assembled a NAL unit from fragments.");
306
307    return OK;
308}
309
310void AAVCAssembler::submitAccessUnit() {
311    CHECK(!mNALUnits.empty());
312
313    ALOGV("Access unit complete (%d nal units)", mNALUnits.size());
314
315    size_t totalSize = 0;
316    for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
317         it != mNALUnits.end(); ++it) {
318        totalSize += 4 + (*it)->size();
319    }
320
321    sp<ABuffer> accessUnit = new ABuffer(totalSize);
322    size_t offset = 0;
323    for (List<sp<ABuffer> >::iterator it = mNALUnits.begin();
324         it != mNALUnits.end(); ++it) {
325        memcpy(accessUnit->data() + offset, "\x00\x00\x00\x01", 4);
326        offset += 4;
327
328        sp<ABuffer> nal = *it;
329        memcpy(accessUnit->data() + offset, nal->data(), nal->size());
330        offset += nal->size();
331    }
332
333    CopyTimes(accessUnit, *mNALUnits.begin());
334
335#if 0
336    printf(mAccessUnitDamaged ? "X" : ".");
337    fflush(stdout);
338#endif
339
340    if (mAccessUnitDamaged) {
341        accessUnit->meta()->setInt32("damaged", true);
342    }
343
344    mNALUnits.clear();
345    mAccessUnitDamaged = false;
346
347    sp<AMessage> msg = mNotifyMsg->dup();
348    msg->setBuffer("access-unit", accessUnit);
349    msg->post();
350}
351
352ARTPAssembler::AssemblyStatus AAVCAssembler::assembleMore(
353        const sp<ARTPSource> &source) {
354    AssemblyStatus status = addNALUnit(source);
355    if (status == MALFORMED_PACKET) {
356        mAccessUnitDamaged = true;
357    }
358    return status;
359}
360
361void AAVCAssembler::packetLost() {
362    CHECK(mNextExpectedSeqNoValid);
363    ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
364
365    ++mNextExpectedSeqNo;
366
367    mAccessUnitDamaged = true;
368}
369
370void AAVCAssembler::onByeReceived() {
371    sp<AMessage> msg = mNotifyMsg->dup();
372    msg->setInt32("eos", true);
373    msg->post();
374}
375
376}  // namespace android
377