blob: 9f6bd29eecab38f8cbd8dc520b5d8d1859d63168 [file] [log] [blame]
Andreas Hubera979ad62010-08-19 10:56:15 -07001/*
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
Andreas Huber6e3fa442010-09-21 13:13:15 -070017//#define LOG_NDEBUG 0
18#define LOG_TAG "AMPEG4ElementaryAssembler"
19#include <utils/Log.h>
20
Andreas Hubera979ad62010-08-19 10:56:15 -070021#include "AMPEG4ElementaryAssembler.h"
22
23#include "ARTPSource.h"
24
Andreas Hubere536f802010-08-31 14:25:36 -070025#include <media/stagefright/foundation/ABitReader.h>
Andreas Hubera979ad62010-08-19 10:56:15 -070026#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
29#include <media/stagefright/foundation/hexdump.h>
Andreas Hubere536f802010-08-31 14:25:36 -070030#include <media/stagefright/Utils.h>
Andreas Hubera979ad62010-08-19 10:56:15 -070031
Andreas Hubere536f802010-08-31 14:25:36 -070032#include <ctype.h>
Andreas Hubera979ad62010-08-19 10:56:15 -070033#include <stdint.h>
34
Andreas Hubera979ad62010-08-19 10:56:15 -070035namespace android {
36
Andreas Hubere536f802010-08-31 14:25:36 -070037static bool GetAttribute(const char *s, const char *key, AString *value) {
38 value->clear();
39
40 size_t keyLen = strlen(key);
41
42 for (;;) {
43 while (isspace(*s)) {
44 ++s;
45 }
46
47 const char *colonPos = strchr(s, ';');
48
49 size_t len =
50 (colonPos == NULL) ? strlen(s) : colonPos - s;
51
52 if (len >= keyLen + 1 && s[keyLen] == '='
53 && !strncasecmp(s, key, keyLen)) {
54 value->setTo(&s[keyLen + 1], len - keyLen - 1);
55 return true;
56 }
57
58 if (colonPos == NULL) {
59 return false;
60 }
61
62 s = colonPos + 1;
63 }
64}
65
66static bool GetIntegerAttribute(
67 const char *s, const char *key, unsigned *x) {
68 *x = 0;
69
70 AString val;
71 if (!GetAttribute(s, key, &val)) {
72 return false;
73 }
74
75 s = val.c_str();
76 char *end;
77 unsigned y = strtoul(s, &end, 10);
78
79 if (end == s || *end != '\0') {
80 return false;
81 }
82
83 *x = y;
84
85 return true;
86}
87
Andreas Hubera979ad62010-08-19 10:56:15 -070088// static
Andreas Hubere536f802010-08-31 14:25:36 -070089AMPEG4ElementaryAssembler::AMPEG4ElementaryAssembler(
90 const sp<AMessage> &notify, const AString &desc, const AString &params)
Andreas Hubera979ad62010-08-19 10:56:15 -070091 : mNotifyMsg(notify),
Andreas Hubere536f802010-08-31 14:25:36 -070092 mIsGeneric(false),
93 mParams(params),
94 mSizeLength(0),
95 mIndexLength(0),
96 mIndexDeltaLength(0),
97 mCTSDeltaLength(0),
98 mDTSDeltaLength(0),
99 mRandomAccessIndication(false),
100 mStreamStateIndication(0),
101 mAuxiliaryDataSizeLength(0),
102 mHasAUHeader(false),
Andreas Hubera979ad62010-08-19 10:56:15 -0700103 mAccessUnitRTPTime(0),
104 mNextExpectedSeqNoValid(false),
105 mNextExpectedSeqNo(0),
106 mAccessUnitDamaged(false) {
Andreas Huber04072692011-02-15 10:39:48 -0800107 mIsGeneric = !strncasecmp(desc.c_str(),"mpeg4-generic/", 14);
Andreas Hubere536f802010-08-31 14:25:36 -0700108
109 if (mIsGeneric) {
110 AString value;
111 CHECK(GetAttribute(params.c_str(), "mode", &value));
112
113 if (!GetIntegerAttribute(params.c_str(), "sizeLength", &mSizeLength)) {
114 mSizeLength = 0;
115 }
116
117 if (!GetIntegerAttribute(
118 params.c_str(), "indexLength", &mIndexLength)) {
119 mIndexLength = 0;
120 }
121
122 if (!GetIntegerAttribute(
123 params.c_str(), "indexDeltaLength", &mIndexDeltaLength)) {
124 mIndexDeltaLength = 0;
125 }
126
127 if (!GetIntegerAttribute(
128 params.c_str(), "CTSDeltaLength", &mCTSDeltaLength)) {
129 mCTSDeltaLength = 0;
130 }
131
132 if (!GetIntegerAttribute(
133 params.c_str(), "DTSDeltaLength", &mDTSDeltaLength)) {
134 mDTSDeltaLength = 0;
135 }
136
137 unsigned x;
138 if (!GetIntegerAttribute(
139 params.c_str(), "randomAccessIndication", &x)) {
140 mRandomAccessIndication = false;
141 } else {
142 CHECK(x == 0 || x == 1);
143 mRandomAccessIndication = (x != 0);
144 }
145
146 if (!GetIntegerAttribute(
147 params.c_str(), "streamStateIndication",
148 &mStreamStateIndication)) {
149 mStreamStateIndication = 0;
150 }
151
152 if (!GetIntegerAttribute(
153 params.c_str(), "auxiliaryDataSizeLength",
154 &mAuxiliaryDataSizeLength)) {
155 mAuxiliaryDataSizeLength = 0;
156 }
157
158 mHasAUHeader =
159 mSizeLength > 0
160 || mIndexLength > 0
161 || mIndexDeltaLength > 0
162 || mCTSDeltaLength > 0
163 || mDTSDeltaLength > 0
164 || mRandomAccessIndication
165 || mStreamStateIndication > 0;
166 }
Andreas Hubera979ad62010-08-19 10:56:15 -0700167}
168
169AMPEG4ElementaryAssembler::~AMPEG4ElementaryAssembler() {
170}
171
Andreas Hubere536f802010-08-31 14:25:36 -0700172struct AUHeader {
173 unsigned mSize;
174 unsigned mSerial;
175};
176
Andreas Hubera979ad62010-08-19 10:56:15 -0700177ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::addPacket(
178 const sp<ARTPSource> &source) {
179 List<sp<ABuffer> > *queue = source->queue();
180
181 if (queue->empty()) {
182 return NOT_ENOUGH_DATA;
183 }
184
185 if (mNextExpectedSeqNoValid) {
186 List<sp<ABuffer> >::iterator it = queue->begin();
187 while (it != queue->end()) {
188 if ((uint32_t)(*it)->int32Data() >= mNextExpectedSeqNo) {
189 break;
190 }
191
192 it = queue->erase(it);
193 }
194
195 if (queue->empty()) {
196 return NOT_ENOUGH_DATA;
197 }
198 }
199
200 sp<ABuffer> buffer = *queue->begin();
201
202 if (!mNextExpectedSeqNoValid) {
203 mNextExpectedSeqNoValid = true;
204 mNextExpectedSeqNo = (uint32_t)buffer->int32Data();
205 } else if ((uint32_t)buffer->int32Data() != mNextExpectedSeqNo) {
Andreas Huber6e3fa442010-09-21 13:13:15 -0700206 LOGV("Not the sequence number I expected");
Andreas Hubera979ad62010-08-19 10:56:15 -0700207
208 return WRONG_SEQUENCE_NUMBER;
209 }
210
211 uint32_t rtpTime;
212 CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
213
214 if (mPackets.size() > 0 && rtpTime != mAccessUnitRTPTime) {
215 submitAccessUnit();
216 }
217 mAccessUnitRTPTime = rtpTime;
218
Andreas Hubere536f802010-08-31 14:25:36 -0700219 if (!mIsGeneric) {
220 mPackets.push_back(buffer);
221 } else {
222 // hexdump(buffer->data(), buffer->size());
223
224 CHECK_GE(buffer->size(), 2u);
225 unsigned AU_headers_length = U16_AT(buffer->data()); // in bits
226
227 CHECK_GE(buffer->size(), 2 + (AU_headers_length + 7) / 8);
228
229 List<AUHeader> headers;
230
231 ABitReader bits(buffer->data() + 2, buffer->size() - 2);
232 unsigned numBitsLeft = AU_headers_length;
233
234 unsigned AU_serial = 0;
235 for (;;) {
236 if (numBitsLeft < mSizeLength) { break; }
237
238 unsigned AU_size = bits.getBits(mSizeLength);
239 numBitsLeft -= mSizeLength;
240
241 size_t n = headers.empty() ? mIndexLength : mIndexDeltaLength;
242 if (numBitsLeft < n) { break; }
243
244 unsigned AU_index = bits.getBits(n);
245 numBitsLeft -= n;
246
247 if (headers.empty()) {
248 AU_serial = AU_index;
249 } else {
250 AU_serial += 1 + AU_index;
251 }
252
253 if (mCTSDeltaLength > 0) {
254 if (numBitsLeft < 1) {
255 break;
256 }
257 --numBitsLeft;
258 if (bits.getBits(1)) {
259 if (numBitsLeft < mCTSDeltaLength) {
260 break;
261 }
262 bits.skipBits(mCTSDeltaLength);
263 numBitsLeft -= mCTSDeltaLength;
264 }
265 }
266
267 if (mDTSDeltaLength > 0) {
268 if (numBitsLeft < 1) {
269 break;
270 }
271 --numBitsLeft;
272 if (bits.getBits(1)) {
273 if (numBitsLeft < mDTSDeltaLength) {
274 break;
275 }
276 bits.skipBits(mDTSDeltaLength);
277 numBitsLeft -= mDTSDeltaLength;
278 }
279 }
280
281 if (mRandomAccessIndication) {
282 if (numBitsLeft < 1) {
283 break;
284 }
285 bits.skipBits(1);
286 --numBitsLeft;
287 }
288
289 if (mStreamStateIndication > 0) {
290 if (numBitsLeft < mStreamStateIndication) {
291 break;
292 }
293 bits.skipBits(mStreamStateIndication);
294 }
295
296 AUHeader header;
297 header.mSize = AU_size;
298 header.mSerial = AU_serial;
299 headers.push_back(header);
300 }
301
302 size_t offset = 2 + (AU_headers_length + 7) / 8;
303
304 if (mAuxiliaryDataSizeLength > 0) {
305 ABitReader bits(buffer->data() + offset, buffer->size() - offset);
306
307 unsigned auxSize = bits.getBits(mAuxiliaryDataSizeLength);
308
309 offset += (mAuxiliaryDataSizeLength + auxSize + 7) / 8;
310 }
311
312 for (List<AUHeader>::iterator it = headers.begin();
313 it != headers.end(); ++it) {
314 const AUHeader &header = *it;
315
316 CHECK_LE(offset + header.mSize, buffer->size());
317
318 sp<ABuffer> accessUnit = new ABuffer(header.mSize);
319 memcpy(accessUnit->data(), buffer->data() + offset, header.mSize);
320
321 offset += header.mSize;
322
323 CopyTimes(accessUnit, buffer);
324 mPackets.push_back(accessUnit);
325 }
326
327 CHECK_EQ(offset, buffer->size());
328 }
Andreas Hubera979ad62010-08-19 10:56:15 -0700329
330 queue->erase(queue->begin());
331 ++mNextExpectedSeqNo;
332
333 return OK;
334}
335
336void AMPEG4ElementaryAssembler::submitAccessUnit() {
337 CHECK(!mPackets.empty());
338
Andreas Huber6e3fa442010-09-21 13:13:15 -0700339 LOGV("Access unit complete (%d nal units)", mPackets.size());
Andreas Hubera979ad62010-08-19 10:56:15 -0700340
Andreas Hubera979ad62010-08-19 10:56:15 -0700341 size_t totalSize = 0;
342 for (List<sp<ABuffer> >::iterator it = mPackets.begin();
343 it != mPackets.end(); ++it) {
344 totalSize += (*it)->size();
345 }
346
347 sp<ABuffer> accessUnit = new ABuffer(totalSize);
348 size_t offset = 0;
349 for (List<sp<ABuffer> >::iterator it = mPackets.begin();
350 it != mPackets.end(); ++it) {
351 sp<ABuffer> nal = *it;
352 memcpy(accessUnit->data() + offset, nal->data(), nal->size());
353 offset += nal->size();
354 }
355
Andreas Hubereeb97d92010-08-27 13:29:08 -0700356 CopyTimes(accessUnit, *mPackets.begin());
Andreas Hubera979ad62010-08-19 10:56:15 -0700357
358#if 0
359 printf(mAccessUnitDamaged ? "X" : ".");
360 fflush(stdout);
361#endif
362
363 if (mAccessUnitDamaged) {
364 accessUnit->meta()->setInt32("damaged", true);
365 }
366
367 mPackets.clear();
368 mAccessUnitDamaged = false;
369
370 sp<AMessage> msg = mNotifyMsg->dup();
371 msg->setObject("access-unit", accessUnit);
372 msg->post();
373}
374
375ARTPAssembler::AssemblyStatus AMPEG4ElementaryAssembler::assembleMore(
376 const sp<ARTPSource> &source) {
377 AssemblyStatus status = addPacket(source);
378 if (status == MALFORMED_PACKET) {
379 mAccessUnitDamaged = true;
380 }
381 return status;
382}
383
384void AMPEG4ElementaryAssembler::packetLost() {
385 CHECK(mNextExpectedSeqNoValid);
Andreas Huber6e3fa442010-09-21 13:13:15 -0700386 LOGV("packetLost (expected %d)", mNextExpectedSeqNo);
Andreas Hubera979ad62010-08-19 10:56:15 -0700387
388 ++mNextExpectedSeqNo;
389
390 mAccessUnitDamaged = true;
391}
392
393void AMPEG4ElementaryAssembler::onByeReceived() {
394 sp<AMessage> msg = mNotifyMsg->dup();
395 msg->setInt32("eos", true);
396 msg->post();
397}
398
399} // namespace android