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 <media/stagefright/rtsp/AH263Assembler.h>
21
22 #include <media/stagefright/rtsp/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/foundation/ByteUtils.h>
29
30 namespace android {
31
AH263Assembler(const sp<AMessage> & notify)32 AH263Assembler::AH263Assembler(const sp<AMessage> ¬ify)
33 : mNotifyMsg(notify),
34 mAccessUnitRTPTime(0),
35 mNextExpectedSeqNoValid(false),
36 mNextExpectedSeqNo(0),
37 mAccessUnitDamaged(false) {
38 }
39
~AH263Assembler()40 AH263Assembler::~AH263Assembler() {
41 }
42
assembleMore(const sp<ARTPSource> & source)43 ARTPAssembler::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
addPacket(const sp<ARTPSource> & source)52 ARTPAssembler::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
submitAccessUnit()152 void 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
packetLost()201 void AH263Assembler::packetLost() {
202 CHECK(mNextExpectedSeqNoValid);
203 ++mNextExpectedSeqNo;
204
205 mAccessUnitDamaged = true;
206 }
207
onByeReceived()208 void AH263Assembler::onByeReceived() {
209 sp<AMessage> msg = mNotifyMsg->dup();
210 msg->setInt32("eos", true);
211 msg->post();
212 }
213
214 } // namespace android
215
216