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
32 namespace android {
33
34 // static
AAVCAssembler(const sp<AMessage> & notify)35 AAVCAssembler::AAVCAssembler(const sp<AMessage> ¬ify)
36 : mNotifyMsg(notify),
37 mAccessUnitRTPTime(0),
38 mNextExpectedSeqNoValid(false),
39 mNextExpectedSeqNo(0),
40 mAccessUnitDamaged(false) {
41 }
42
~AAVCAssembler()43 AAVCAssembler::~AAVCAssembler() {
44 }
45
addNALUnit(const sp<ARTPSource> & source)46 ARTPAssembler::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
addSingleNALUnit(const sp<ABuffer> & buffer)126 void 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
addSingleTimeAggregationPacket(const sp<ABuffer> & buffer)143 bool 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
addFragmentedNALUnit(List<sp<ABuffer>> * queue)180 ARTPAssembler::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
submitAccessUnit()317 void 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
assembleMore(const sp<ARTPSource> & source)359 ARTPAssembler::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
packetLost()368 void AAVCAssembler::packetLost() {
369 CHECK(mNextExpectedSeqNoValid);
370 ALOGV("packetLost (expected %d)", mNextExpectedSeqNo);
371
372 ++mNextExpectedSeqNo;
373
374 mAccessUnitDamaged = true;
375 }
376
onByeReceived()377 void AAVCAssembler::onByeReceived() {
378 sp<AMessage> msg = mNotifyMsg->dup();
379 msg->setInt32("eos", true);
380 msg->post();
381 }
382
383 } // namespace android
384