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//#define LOG_NDEBUG 0
17#define LOG_TAG "AH263Assembler"
18#include <utils/Log.h>
19
20#include "AH263Assembler.h"
21
22#include "ARTPSource.h"
23
24#include <media/stagefright/foundation/ABuffer.h>
25#include <media/stagefright/foundation/ADebug.h>
26#include <media/stagefright/foundation/AMessage.h>
27#include <media/stagefright/foundation/hexdump.h>
28#include <media/stagefright/Utils.h>
29
30namespace android {
31
32AH263Assembler::AH263Assembler(const sp<AMessage> &notify)
33    : mNotifyMsg(notify),
34      mAccessUnitRTPTime(0),
35      mNextExpectedSeqNoValid(false),
36      mNextExpectedSeqNo(0),
37      mAccessUnitDamaged(false) {
38}
39
40AH263Assembler::~AH263Assembler() {
41}
42
43ARTPAssembler::AssemblyStatus AH263Assembler::assembleMore(
44        const sp<ARTPSource> &source) {
45    AssemblyStatus status = addPacket(source);
46    if (status == MALFORMED_PACKET) {
47        mAccessUnitDamaged = true;
48    }
49    return status;
50}
51
52ARTPAssembler::AssemblyStatus AH263Assembler::addPacket(
53        const sp<ARTPSource> &source) {
54    List<sp<ABuffer> > *queue = source->queue();
55
56    if (queue->empty()) {
57        return NOT_ENOUGH_DATA;
58    }
59
60    if (mNextExpectedSeqNoValid) {
61        List<sp<ABuffer> >::iterator it = queue->begin();
62        while (it != queue->end()) {
63            if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
64                break;
65            }
66
67            it = queue->erase(it);
68        }
69
70        if (queue->empty()) {
71            return NOT_ENOUGH_DATA;
72        }
73    }
74
75    sp<ABuffer> buffer = *queue->begin();
76
77    if (!mNextExpectedSeqNoValid) {
78        mNextExpectedSeqNoValid = true;
79        mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
80    } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
81#if VERBOSE
82        LOG(VERBOSE) << "Not the sequence number I expected";
83#endif
84
85        return WRONG_SEQUENCE_NUMBER;
86    }
87
88    uint32_t rtpTime;
89    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
90
91    if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
92        submitAccessUnit();
93    }
94    mAccessUnitRTPTime = rtpTime;
95
96    // hexdump(buffer->data(), buffer->size());
97
98    if (buffer->size() < 2) {
99        queue->erase(queue->begin());
100        ++mNextExpectedSeqNo;
101
102        return MALFORMED_PACKET;
103    }
104
105    unsigned payloadHeader = U16_AT(buffer->data());
106    unsigned P = (payloadHeader >> 10) & 1;
107    unsigned V = (payloadHeader >> 9) & 1;
108    unsigned PLEN = (payloadHeader >> 3) & 0x3f;
109    unsigned PEBIT = payloadHeader & 7;
110
111    // V=0
112    if (V != 0u) {
113        queue->erase(queue->begin());
114        ++mNextExpectedSeqNo;
115        ALOGW("Packet discarded due to VRC (V != 0)");
116        return MALFORMED_PACKET;
117    }
118
119    // PLEN=0
120    if (PLEN != 0u) {
121        queue->erase(queue->begin());
122        ++mNextExpectedSeqNo;
123        ALOGW("Packet discarded (PLEN != 0)");
124        return MALFORMED_PACKET;
125    }
126
127    // PEBIT=0
128    if (PEBIT != 0u) {
129        queue->erase(queue->begin());
130        ++mNextExpectedSeqNo;
131        ALOGW("Packet discarded (PEBIT != 0)");
132        return MALFORMED_PACKET;
133    }
134
135    size_t skip = V + PLEN + (P ? 0 : 2);
136
137    buffer->setRange(buffer->offset() + skip, buffer->size() - skip);
138
139    if (P) {
140        buffer->data()[0] = 0x00;
141        buffer->data()[1] = 0x00;
142    }
143
144    mPackets.push_back(buffer);
145
146    queue->erase(queue->begin());
147    ++mNextExpectedSeqNo;
148
149    return OK;
150}
151
152void AH263Assembler::submitAccessUnit() {
153    CHECK(!mPackets.empty());
154
155#if VERBOSE
156    LOG(VERBOSE) << "Access unit complete (" << mPackets.size() << " packets)";
157#endif
158
159    size_t totalSize = 0;
160    List<sp<ABuffer> >::iterator it = mPackets.begin();
161    while (it != mPackets.end()) {
162        const sp<ABuffer> &unit = *it;
163
164        totalSize += unit->size();
165        ++it;
166    }
167
168    sp<ABuffer> accessUnit = new ABuffer(totalSize);
169    size_t offset = 0;
170    it = mPackets.begin();
171    while (it != mPackets.end()) {
172        const sp<ABuffer> &unit = *it;
173
174        memcpy((uint8_t *)accessUnit->data() + offset,
175               unit->data(), unit->size());
176
177        offset += unit->size();
178
179        ++it;
180    }
181
182    CopyTimes(accessUnit, *mPackets.begin());
183
184#if 0
185    printf(mAccessUnitDamaged ? "X" : ".");
186    fflush(stdout);
187#endif
188
189    if (mAccessUnitDamaged) {
190        accessUnit->meta()->setInt32("damaged", true);
191    }
192
193    mPackets.clear();
194    mAccessUnitDamaged = false;
195
196    sp<AMessage> msg = mNotifyMsg->dup();
197    msg->setBuffer("access-unit", accessUnit);
198    msg->post();
199}
200
201void AH263Assembler::packetLost() {
202    CHECK(mNextExpectedSeqNoValid);
203    ++mNextExpectedSeqNo;
204
205    mAccessUnitDamaged = true;
206}
207
208void AH263Assembler::onByeReceived() {
209    sp<AMessage> msg = mNotifyMsg->dup();
210    msg->setInt32("eos", true);
211    msg->post();
212}
213
214}  // namespace android
215
216