blob: 6819fefd30cce096647e13c2e2b90f624263f9fd [file] [log] [blame]
Andreas Huber7a747b82010-06-07 15:19:40 -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 "APacketSource"
19#include <utils/Log.h>
20
Andreas Huber7a747b82010-06-07 15:19:40 -070021#include "APacketSource.h"
22
Andreas Huberb6723732011-02-22 16:25:00 -080023#include "ARawAudioAssembler.h"
Andreas Huber7a747b82010-06-07 15:19:40 -070024#include "ASessionDescription.h"
25
Andreas Hubereef3c332010-08-19 10:39:47 -070026#include "avc_utils.h"
27
Andreas Huberaf063a62010-08-18 10:17:18 -070028#include <ctype.h>
29
Andreas Hubera979ad62010-08-19 10:56:15 -070030#include <media/stagefright/foundation/ABitReader.h>
Andreas Huber7a747b82010-06-07 15:19:40 -070031#include <media/stagefright/foundation/ABuffer.h>
32#include <media/stagefright/foundation/ADebug.h>
33#include <media/stagefright/foundation/AMessage.h>
34#include <media/stagefright/foundation/AString.h>
35#include <media/stagefright/foundation/base64.h>
36#include <media/stagefright/foundation/hexdump.h>
37#include <media/stagefright/MediaBuffer.h>
38#include <media/stagefright/MediaDefs.h>
39#include <media/stagefright/MetaData.h>
40#include <utils/Vector.h>
41
42namespace android {
43
44static bool GetAttribute(const char *s, const char *key, AString *value) {
45 value->clear();
46
47 size_t keyLen = strlen(key);
48
49 for (;;) {
Andreas Huberaf063a62010-08-18 10:17:18 -070050 while (isspace(*s)) {
51 ++s;
52 }
53
Andreas Huber7a747b82010-06-07 15:19:40 -070054 const char *colonPos = strchr(s, ';');
55
56 size_t len =
57 (colonPos == NULL) ? strlen(s) : colonPos - s;
58
59 if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
60 value->setTo(&s[keyLen + 1], len - keyLen - 1);
61 return true;
62 }
63
64 if (colonPos == NULL) {
65 return false;
66 }
67
68 s = colonPos + 1;
69 }
70}
71
72static sp<ABuffer> decodeHex(const AString &s) {
73 if ((s.size() % 2) != 0) {
74 return NULL;
75 }
76
77 size_t outLen = s.size() / 2;
78 sp<ABuffer> buffer = new ABuffer(outLen);
79 uint8_t *out = buffer->data();
80
81 uint8_t accum = 0;
82 for (size_t i = 0; i < s.size(); ++i) {
83 char c = s.c_str()[i];
84 unsigned value;
85 if (c >= '0' && c <= '9') {
86 value = c - '0';
87 } else if (c >= 'a' && c <= 'f') {
88 value = c - 'a' + 10;
89 } else if (c >= 'A' && c <= 'F') {
90 value = c - 'A' + 10;
91 } else {
92 return NULL;
93 }
94
95 accum = (accum << 4) | value;
96
97 if (i & 1) {
98 *out++ = accum;
99
100 accum = 0;
101 }
102 }
103
104 return buffer;
105}
106
Andreas Hubereef3c332010-08-19 10:39:47 -0700107static sp<ABuffer> MakeAVCCodecSpecificData(
108 const char *params, int32_t *width, int32_t *height) {
109 *width = 0;
110 *height = 0;
111
Andreas Huber7a747b82010-06-07 15:19:40 -0700112 AString val;
Andreas Huber426b6502010-08-04 14:04:31 -0700113 if (!GetAttribute(params, "profile-level-id", &val)) {
114 return NULL;
115 }
Andreas Huber7a747b82010-06-07 15:19:40 -0700116
117 sp<ABuffer> profileLevelID = decodeHex(val);
118 CHECK(profileLevelID != NULL);
119 CHECK_EQ(profileLevelID->size(), 3u);
120
121 Vector<sp<ABuffer> > paramSets;
122
123 size_t numSeqParameterSets = 0;
124 size_t totalSeqParameterSetSize = 0;
125 size_t numPicParameterSets = 0;
126 size_t totalPicParameterSetSize = 0;
127
Andreas Huber426b6502010-08-04 14:04:31 -0700128 if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
129 return NULL;
130 }
131
Andreas Huber7a747b82010-06-07 15:19:40 -0700132 size_t start = 0;
133 for (;;) {
134 ssize_t commaPos = val.find(",", start);
135 size_t end = (commaPos < 0) ? val.size() : commaPos;
136
137 AString nalString(val, start, end - start);
138 sp<ABuffer> nal = decodeBase64(nalString);
139 CHECK(nal != NULL);
140 CHECK_GT(nal->size(), 0u);
141 CHECK_LE(nal->size(), 65535u);
142
143 uint8_t nalType = nal->data()[0] & 0x1f;
144 if (numSeqParameterSets == 0) {
145 CHECK_EQ((unsigned)nalType, 7u);
146 } else if (numPicParameterSets > 0) {
147 CHECK_EQ((unsigned)nalType, 8u);
148 }
149 if (nalType == 7) {
150 ++numSeqParameterSets;
151 totalSeqParameterSetSize += nal->size();
152 } else {
153 CHECK_EQ((unsigned)nalType, 8u);
154 ++numPicParameterSets;
155 totalPicParameterSetSize += nal->size();
156 }
157
158 paramSets.push(nal);
159
160 if (commaPos < 0) {
161 break;
162 }
163
164 start = commaPos + 1;
165 }
166
167 CHECK_LT(numSeqParameterSets, 32u);
168 CHECK_LE(numPicParameterSets, 255u);
169
170 size_t csdSize =
171 1 + 3 + 1 + 1
172 + 2 * numSeqParameterSets + totalSeqParameterSetSize
173 + 1 + 2 * numPicParameterSets + totalPicParameterSetSize;
174
175 sp<ABuffer> csd = new ABuffer(csdSize);
176 uint8_t *out = csd->data();
177
178 *out++ = 0x01; // configurationVersion
179 memcpy(out, profileLevelID->data(), 3);
180 out += 3;
181 *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes
182 *out++ = 0xe0 | numSeqParameterSets;
183
184 for (size_t i = 0; i < numSeqParameterSets; ++i) {
185 sp<ABuffer> nal = paramSets.editItemAt(i);
186
187 *out++ = nal->size() >> 8;
188 *out++ = nal->size() & 0xff;
189
190 memcpy(out, nal->data(), nal->size());
191
192 out += nal->size();
Andreas Hubereef3c332010-08-19 10:39:47 -0700193
194 if (i == 0) {
195 FindAVCDimensions(nal, width, height);
Andreas Huber6e3fa442010-09-21 13:13:15 -0700196 LOGI("dimensions %dx%d", *width, *height);
Andreas Hubereef3c332010-08-19 10:39:47 -0700197 }
Andreas Huber7a747b82010-06-07 15:19:40 -0700198 }
199
200 *out++ = numPicParameterSets;
201
202 for (size_t i = 0; i < numPicParameterSets; ++i) {
203 sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets);
204
205 *out++ = nal->size() >> 8;
206 *out++ = nal->size() & 0xff;
207
208 memcpy(out, nal->data(), nal->size());
209
210 out += nal->size();
211 }
212
Andreas Hubereef3c332010-08-19 10:39:47 -0700213 // hexdump(csd->data(), csd->size());
Andreas Huber7a747b82010-06-07 15:19:40 -0700214
215 return csd;
216}
217
218sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
219 AString val;
220 CHECK(GetAttribute(params, "config", &val));
221
222 sp<ABuffer> config = decodeHex(val);
223 CHECK(config != NULL);
224 CHECK_GE(config->size(), 4u);
225
226 const uint8_t *data = config->data();
227 uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
228 x = (x >> 1) & 0xffff;
229
230 static const uint8_t kStaticESDS[] = {
231 0x03, 22,
232 0x00, 0x00, // ES_ID
233 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
234
235 0x04, 17,
236 0x40, // Audio ISO/IEC 14496-3
237 0x00, 0x00, 0x00, 0x00,
238 0x00, 0x00, 0x00, 0x00,
239 0x00, 0x00, 0x00, 0x00,
240
241 0x05, 2,
242 // AudioSpecificInfo follows
243 };
244
245 sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
246 memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
247 csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
248 csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
249
Andreas Hubereef3c332010-08-19 10:39:47 -0700250 // hexdump(csd->data(), csd->size());
Andreas Huber7a747b82010-06-07 15:19:40 -0700251
252 return csd;
253}
254
Andreas Hubere536f802010-08-31 14:25:36 -0700255// From mpeg4-generic configuration data.
256sp<ABuffer> MakeAACCodecSpecificData2(const char *params) {
257 AString val;
258 unsigned long objectType;
259 if (GetAttribute(params, "objectType", &val)) {
260 const char *s = val.c_str();
261 char *end;
262 objectType = strtoul(s, &end, 10);
263 CHECK(end > s && *end == '\0');
264 } else {
265 objectType = 0x40; // Audio ISO/IEC 14496-3
266 }
267
268 CHECK(GetAttribute(params, "config", &val));
269
270 sp<ABuffer> config = decodeHex(val);
271 CHECK(config != NULL);
272
273 // Make sure size fits into a single byte and doesn't have to
274 // be encoded.
275 CHECK_LT(20 + config->size(), 128u);
276
277 const uint8_t *data = config->data();
278
279 static const uint8_t kStaticESDS[] = {
280 0x03, 22,
281 0x00, 0x00, // ES_ID
282 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
283
284 0x04, 17,
285 0x40, // Audio ISO/IEC 14496-3
286 0x00, 0x00, 0x00, 0x00,
287 0x00, 0x00, 0x00, 0x00,
288 0x00, 0x00, 0x00, 0x00,
289
290 0x05, 2,
291 // AudioSpecificInfo follows
292 };
293
294 sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + config->size());
295 uint8_t *dst = csd->data();
296 *dst++ = 0x03;
297 *dst++ = 20 + config->size();
298 *dst++ = 0x00; // ES_ID
299 *dst++ = 0x00;
300 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
301 *dst++ = 0x04;
302 *dst++ = 15 + config->size();
303 *dst++ = objectType;
304 for (int i = 0; i < 12; ++i) { *dst++ = 0x00; }
305 *dst++ = 0x05;
306 *dst++ = config->size();
307 memcpy(dst, config->data(), config->size());
308
309 // hexdump(csd->data(), csd->size());
310
311 return csd;
312}
313
Andreas Hubera979ad62010-08-19 10:56:15 -0700314static size_t GetSizeWidth(size_t x) {
315 size_t n = 1;
316 while (x > 127) {
317 ++n;
318 x >>= 7;
319 }
320 return n;
321}
322
323static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
324 while (x > 127) {
325 *dst++ = (x & 0x7f) | 0x80;
326 x >>= 7;
327 }
328 *dst++ = x;
329 return dst;
330}
331
332static bool ExtractDimensionsFromVOLHeader(
333 const sp<ABuffer> &config, int32_t *width, int32_t *height) {
334 *width = 0;
335 *height = 0;
336
337 const uint8_t *ptr = config->data();
338 size_t offset = 0;
339 bool foundVOL = false;
340 while (offset + 3 < config->size()) {
341 if (memcmp("\x00\x00\x01", &ptr[offset], 3)
342 || (ptr[offset + 3] & 0xf0) != 0x20) {
343 ++offset;
344 continue;
345 }
346
347 foundVOL = true;
348 break;
349 }
350
351 if (!foundVOL) {
352 return false;
353 }
354
355 ABitReader br(&ptr[offset + 4], config->size() - offset - 4);
356 br.skipBits(1); // random_accessible_vol
357 unsigned video_object_type_indication = br.getBits(8);
358
359 CHECK_NE(video_object_type_indication,
360 0x21u /* Fine Granularity Scalable */);
361
362 unsigned video_object_layer_verid;
363 unsigned video_object_layer_priority;
364 if (br.getBits(1)) {
365 video_object_layer_verid = br.getBits(4);
366 video_object_layer_priority = br.getBits(3);
367 }
368 unsigned aspect_ratio_info = br.getBits(4);
369 if (aspect_ratio_info == 0x0f /* extended PAR */) {
370 br.skipBits(8); // par_width
371 br.skipBits(8); // par_height
372 }
373 if (br.getBits(1)) { // vol_control_parameters
374 br.skipBits(2); // chroma_format
375 br.skipBits(1); // low_delay
376 if (br.getBits(1)) { // vbv_parameters
Andreas Huber77034e62011-01-18 11:19:13 -0800377 br.skipBits(15); // first_half_bit_rate
378 CHECK(br.getBits(1)); // marker_bit
379 br.skipBits(15); // latter_half_bit_rate
380 CHECK(br.getBits(1)); // marker_bit
381 br.skipBits(15); // first_half_vbv_buffer_size
382 CHECK(br.getBits(1)); // marker_bit
383 br.skipBits(3); // latter_half_vbv_buffer_size
384 br.skipBits(11); // first_half_vbv_occupancy
385 CHECK(br.getBits(1)); // marker_bit
386 br.skipBits(15); // latter_half_vbv_occupancy
387 CHECK(br.getBits(1)); // marker_bit
Andreas Hubera979ad62010-08-19 10:56:15 -0700388 }
389 }
390 unsigned video_object_layer_shape = br.getBits(2);
391 CHECK_EQ(video_object_layer_shape, 0x00u /* rectangular */);
392
393 CHECK(br.getBits(1)); // marker_bit
394 unsigned vop_time_increment_resolution = br.getBits(16);
395 CHECK(br.getBits(1)); // marker_bit
396
397 if (br.getBits(1)) { // fixed_vop_rate
398 // range [0..vop_time_increment_resolution)
399
400 // vop_time_increment_resolution
401 // 2 => 0..1, 1 bit
402 // 3 => 0..2, 2 bits
403 // 4 => 0..3, 2 bits
404 // 5 => 0..4, 3 bits
405 // ...
406
407 CHECK_GT(vop_time_increment_resolution, 0u);
408 --vop_time_increment_resolution;
409
410 unsigned numBits = 0;
411 while (vop_time_increment_resolution > 0) {
412 ++numBits;
413 vop_time_increment_resolution >>= 1;
414 }
415
416 br.skipBits(numBits); // fixed_vop_time_increment
417 }
418
419 CHECK(br.getBits(1)); // marker_bit
420 unsigned video_object_layer_width = br.getBits(13);
421 CHECK(br.getBits(1)); // marker_bit
422 unsigned video_object_layer_height = br.getBits(13);
423 CHECK(br.getBits(1)); // marker_bit
424
425 unsigned interlaced = br.getBits(1);
426
427 *width = video_object_layer_width;
428 *height = video_object_layer_height;
429
Andreas Huber6e3fa442010-09-21 13:13:15 -0700430 LOGI("VOL dimensions = %dx%d", *width, *height);
Andreas Hubera979ad62010-08-19 10:56:15 -0700431
432 return true;
433}
434
435sp<ABuffer> MakeMPEG4VideoCodecSpecificData(
436 const char *params, int32_t *width, int32_t *height) {
437 *width = 0;
438 *height = 0;
439
440 AString val;
441 CHECK(GetAttribute(params, "config", &val));
442
443 sp<ABuffer> config = decodeHex(val);
444 CHECK(config != NULL);
445
446 if (!ExtractDimensionsFromVOLHeader(config, width, height)) {
447 return NULL;
448 }
449
450 size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
451 size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
452 size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
453
454 sp<ABuffer> csd = new ABuffer(len3);
455 uint8_t *dst = csd->data();
456 *dst++ = 0x03;
457 dst = EncodeSize(dst, len2 + 3);
458 *dst++ = 0x00; // ES_ID
459 *dst++ = 0x00;
460 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
461
462 *dst++ = 0x04;
463 dst = EncodeSize(dst, len1 + 13);
464 *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile
465 for (size_t i = 0; i < 12; ++i) {
466 *dst++ = 0x00;
467 }
468
469 *dst++ = 0x05;
470 dst = EncodeSize(dst, config->size());
471 memcpy(dst, config->data(), config->size());
472 dst += config->size();
473
474 // hexdump(csd->data(), csd->size());
475
476 return csd;
477}
478
Andreas Hubereeb97d92010-08-27 13:29:08 -0700479static bool GetClockRate(const AString &desc, uint32_t *clockRate) {
480 ssize_t slashPos = desc.find("/");
481 if (slashPos < 0) {
482 return false;
483 }
484
485 const char *s = desc.c_str() + slashPos + 1;
486
487 char *end;
488 unsigned long x = strtoul(s, &end, 10);
489
490 if (end == s || (*end != '\0' && *end != '/')) {
491 return false;
492 }
493
494 *clockRate = x;
495
496 return true;
497}
498
Andreas Huber7a747b82010-06-07 15:19:40 -0700499APacketSource::APacketSource(
500 const sp<ASessionDescription> &sessionDesc, size_t index)
Andreas Huber57648e42010-08-04 10:14:30 -0700501 : mInitCheck(NO_INIT),
502 mFormat(new MetaData),
Andreas Hubereeb97d92010-08-27 13:29:08 -0700503 mEOSResult(OK),
Andreas Huber38285db2010-10-08 12:06:27 -0700504 mIsAVC(false),
505 mScanForIDR(true),
Andreas Hubereeb97d92010-08-27 13:29:08 -0700506 mRTPTimeBase(0),
507 mNormalPlayTimeBaseUs(0),
508 mLastNormalPlayTimeUs(0) {
Andreas Huber7a747b82010-06-07 15:19:40 -0700509 unsigned long PT;
510 AString desc;
511 AString params;
512 sessionDesc->getFormatType(index, &PT, &desc, &params);
513
Andreas Hubereeb97d92010-08-27 13:29:08 -0700514 CHECK(GetClockRate(desc, &mClockRate));
515
Andreas Huber7a747b82010-06-07 15:19:40 -0700516 int64_t durationUs;
517 if (sessionDesc->getDurationUs(&durationUs)) {
518 mFormat->setInt64(kKeyDuration, durationUs);
519 } else {
520 mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
521 }
522
Andreas Huber57648e42010-08-04 10:14:30 -0700523 mInitCheck = OK;
Andreas Huber7a747b82010-06-07 15:19:40 -0700524 if (!strncmp(desc.c_str(), "H264/", 5)) {
Andreas Huber38285db2010-10-08 12:06:27 -0700525 mIsAVC = true;
526
Andreas Huber7a747b82010-06-07 15:19:40 -0700527 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
528
529 int32_t width, height;
Andreas Huberaf063a62010-08-18 10:17:18 -0700530 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
Andreas Hubereef3c332010-08-19 10:39:47 -0700531 width = -1;
532 height = -1;
533 }
534
535 int32_t encWidth, encHeight;
536 sp<ABuffer> codecSpecificData =
537 MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
538
539 if (codecSpecificData != NULL) {
540 if (width < 0) {
541 // If no explicit width/height given in the sdp, use the dimensions
542 // extracted from the first sequence parameter set.
543 width = encWidth;
544 height = encHeight;
545 }
546
547 mFormat->setData(
548 kKeyAVCC, 0,
549 codecSpecificData->data(), codecSpecificData->size());
550 } else if (width < 0) {
Andreas Huberaf063a62010-08-18 10:17:18 -0700551 mInitCheck = ERROR_UNSUPPORTED;
552 return;
553 }
Andreas Huber7a747b82010-06-07 15:19:40 -0700554
555 mFormat->setInt32(kKeyWidth, width);
556 mFormat->setInt32(kKeyHeight, height);
Andreas Huber57648e42010-08-04 10:14:30 -0700557 } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
558 || !strncmp(desc.c_str(), "H263-1998/", 10)) {
559 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
Andreas Huber7a747b82010-06-07 15:19:40 -0700560
Andreas Huber57648e42010-08-04 10:14:30 -0700561 int32_t width, height;
Andreas Huberaf063a62010-08-18 10:17:18 -0700562 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
563 mInitCheck = ERROR_UNSUPPORTED;
564 return;
565 }
Andreas Huber57648e42010-08-04 10:14:30 -0700566
567 mFormat->setInt32(kKeyWidth, width);
568 mFormat->setInt32(kKeyHeight, height);
569 } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
Andreas Huber7a747b82010-06-07 15:19:40 -0700570 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
571
572 int32_t sampleRate, numChannels;
573 ASessionDescription::ParseFormatDesc(
574 desc.c_str(), &sampleRate, &numChannels);
575
576 mFormat->setInt32(kKeySampleRate, sampleRate);
577 mFormat->setInt32(kKeyChannelCount, numChannels);
578
579 sp<ABuffer> codecSpecificData =
580 MakeAACCodecSpecificData(params.c_str());
581
582 mFormat->setData(
583 kKeyESDS, 0,
584 codecSpecificData->data(), codecSpecificData->size());
Andreas Huber57648e42010-08-04 10:14:30 -0700585 } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
586 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
587
588 int32_t sampleRate, numChannels;
589 ASessionDescription::ParseFormatDesc(
590 desc.c_str(), &sampleRate, &numChannels);
591
592 mFormat->setInt32(kKeySampleRate, sampleRate);
593 mFormat->setInt32(kKeyChannelCount, numChannels);
594
595 if (sampleRate != 8000 || numChannels != 1) {
596 mInitCheck = ERROR_UNSUPPORTED;
597 }
598 } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
599 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
600
601 int32_t sampleRate, numChannels;
602 ASessionDescription::ParseFormatDesc(
603 desc.c_str(), &sampleRate, &numChannels);
604
605 mFormat->setInt32(kKeySampleRate, sampleRate);
606 mFormat->setInt32(kKeyChannelCount, numChannels);
607
608 if (sampleRate != 16000 || numChannels != 1) {
609 mInitCheck = ERROR_UNSUPPORTED;
610 }
Andreas Hubera979ad62010-08-19 10:56:15 -0700611 } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
612 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
613
614 int32_t width, height;
615 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
616 width = -1;
617 height = -1;
618 }
619
620 int32_t encWidth, encHeight;
621 sp<ABuffer> codecSpecificData =
622 MakeMPEG4VideoCodecSpecificData(
623 params.c_str(), &encWidth, &encHeight);
624
625 if (codecSpecificData != NULL) {
626 mFormat->setData(
627 kKeyESDS, 0,
628 codecSpecificData->data(), codecSpecificData->size());
629
630 if (width < 0) {
631 width = encWidth;
632 height = encHeight;
633 }
634 } else if (width < 0) {
635 mInitCheck = ERROR_UNSUPPORTED;
636 return;
637 }
638
639 mFormat->setInt32(kKeyWidth, width);
640 mFormat->setInt32(kKeyHeight, height);
Andreas Huber04072692011-02-15 10:39:48 -0800641 } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
Andreas Hubere536f802010-08-31 14:25:36 -0700642 AString val;
643 if (!GetAttribute(params.c_str(), "mode", &val)
644 || (strcasecmp(val.c_str(), "AAC-lbr")
645 && strcasecmp(val.c_str(), "AAC-hbr"))) {
646 mInitCheck = ERROR_UNSUPPORTED;
647 return;
648 }
649
650 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
651
652 int32_t sampleRate, numChannels;
653 ASessionDescription::ParseFormatDesc(
654 desc.c_str(), &sampleRate, &numChannels);
655
656 mFormat->setInt32(kKeySampleRate, sampleRate);
657 mFormat->setInt32(kKeyChannelCount, numChannels);
658
659 sp<ABuffer> codecSpecificData =
660 MakeAACCodecSpecificData2(params.c_str());
661
662 mFormat->setData(
663 kKeyESDS, 0,
664 codecSpecificData->data(), codecSpecificData->size());
Andreas Huberb6723732011-02-22 16:25:00 -0800665 } else if (ARawAudioAssembler::Supports(desc.c_str())) {
666 ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
Andreas Huber7a747b82010-06-07 15:19:40 -0700667 } else {
Andreas Huber57648e42010-08-04 10:14:30 -0700668 mInitCheck = ERROR_UNSUPPORTED;
Andreas Huber7a747b82010-06-07 15:19:40 -0700669 }
670}
671
672APacketSource::~APacketSource() {
673}
674
Andreas Huber57648e42010-08-04 10:14:30 -0700675status_t APacketSource::initCheck() const {
676 return mInitCheck;
677}
678
Andreas Huber7a747b82010-06-07 15:19:40 -0700679status_t APacketSource::start(MetaData *params) {
680 return OK;
681}
682
683status_t APacketSource::stop() {
684 return OK;
685}
686
687sp<MetaData> APacketSource::getFormat() {
688 return mFormat;
689}
690
691status_t APacketSource::read(
692 MediaBuffer **out, const ReadOptions *) {
693 *out = NULL;
694
695 Mutex::Autolock autoLock(mLock);
696 while (mEOSResult == OK && mBuffers.empty()) {
697 mCondition.wait(mLock);
698 }
699
700 if (!mBuffers.empty()) {
701 const sp<ABuffer> buffer = *mBuffers.begin();
702
Andreas Hubereeb97d92010-08-27 13:29:08 -0700703 updateNormalPlayTime_l(buffer);
704
Andreas Huber57648e42010-08-04 10:14:30 -0700705 MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
Andreas Huber57648e42010-08-04 10:14:30 -0700706
Andreas Huberf88f8442010-08-10 11:18:36 -0700707 int64_t timeUs;
708 CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
Andreas Huber7a747b82010-06-07 15:19:40 -0700709
Andreas Huber7a747b82010-06-07 15:19:40 -0700710 mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
Andreas Huber57648e42010-08-04 10:14:30 -0700711
Andreas Huber7a747b82010-06-07 15:19:40 -0700712 memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
713 *out = mediaBuffer;
714
715 mBuffers.erase(mBuffers.begin());
716 return OK;
717 }
718
719 return mEOSResult;
720}
721
Andreas Hubereeb97d92010-08-27 13:29:08 -0700722void APacketSource::updateNormalPlayTime_l(const sp<ABuffer> &buffer) {
723 uint32_t rtpTime;
724 CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
725
726 mLastNormalPlayTimeUs =
727 (((double)rtpTime - (double)mRTPTimeBase) / mClockRate)
728 * 1000000ll
729 + mNormalPlayTimeBaseUs;
730}
731
Andreas Huber7a747b82010-06-07 15:19:40 -0700732void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
733 int32_t damaged;
734 if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
Andreas Huber6e3fa442010-09-21 13:13:15 -0700735 LOGV("discarding damaged AU");
Andreas Huber7a747b82010-06-07 15:19:40 -0700736 return;
737 }
738
Andreas Huber38285db2010-10-08 12:06:27 -0700739 if (mScanForIDR && mIsAVC) {
740 // This pretty piece of code ensures that the first access unit
741 // fed to the decoder after stream-start or seek is guaranteed to
742 // be an IDR frame. This is to workaround limitations of a certain
743 // hardware h.264 decoder that requires this to be the case.
744
745 if (!IsIDR(buffer)) {
746 LOGV("skipping AU while scanning for next IDR frame.");
747 return;
748 }
749
750 mScanForIDR = false;
751 }
752
Andreas Huber7a747b82010-06-07 15:19:40 -0700753 Mutex::Autolock autoLock(mLock);
754 mBuffers.push_back(buffer);
755 mCondition.signal();
756}
757
758void APacketSource::signalEOS(status_t result) {
759 CHECK(result != OK);
760
761 Mutex::Autolock autoLock(mLock);
762 mEOSResult = result;
763 mCondition.signal();
764}
765
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700766void APacketSource::flushQueue() {
Andreas Huber57648e42010-08-04 10:14:30 -0700767 Mutex::Autolock autoLock(mLock);
Andreas Hubere0dd7d32010-08-24 14:33:58 -0700768 mBuffers.clear();
Andreas Huber38285db2010-10-08 12:06:27 -0700769
770 mScanForIDR = true;
Andreas Huber57648e42010-08-04 10:14:30 -0700771}
772
Andreas Hubereeb97d92010-08-27 13:29:08 -0700773int64_t APacketSource::getNormalPlayTimeUs() {
774 Mutex::Autolock autoLock(mLock);
775 return mLastNormalPlayTimeUs;
776}
777
778void APacketSource::setNormalPlayTimeMapping(
779 uint32_t rtpTime, int64_t normalPlayTimeUs) {
780 Mutex::Autolock autoLock(mLock);
781
782 mRTPTimeBase = rtpTime;
783 mNormalPlayTimeBaseUs = normalPlayTimeUs;
784}
785
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700786int64_t APacketSource::getQueueDurationUs(bool *eos) {
787 Mutex::Autolock autoLock(mLock);
788
789 *eos = (mEOSResult != OK);
790
791 if (mBuffers.size() < 2) {
792 return 0;
793 }
794
795 const sp<ABuffer> first = *mBuffers.begin();
796 const sp<ABuffer> last = *--mBuffers.end();
797
798 int64_t firstTimeUs;
799 CHECK(first->meta()->findInt64("timeUs", &firstTimeUs));
800
801 int64_t lastTimeUs;
802 CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
803
Andreas Huberf3d2bdf2010-09-15 11:18:13 -0700804 if (lastTimeUs < firstTimeUs) {
Andreas Huber6e3fa442010-09-21 13:13:15 -0700805 LOGE("Huh? Time moving backwards? %lld > %lld",
806 firstTimeUs, lastTimeUs);
807
Andreas Huberf3d2bdf2010-09-15 11:18:13 -0700808 return 0;
809 }
Andreas Huber4d8f66b2010-09-01 15:05:28 -0700810
811 return lastTimeUs - firstTimeUs;
812}
813
Andreas Huber7a747b82010-06-07 15:19:40 -0700814} // namespace android