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 "APacketSource"
19 #include <utils/Log.h>
20
21 #include "APacketSource.h"
22
23 #include "ARawAudioAssembler.h"
24 #include "ASessionDescription.h"
25
26 #include <ctype.h>
27
28 #include <media/stagefright/foundation/ABitReader.h>
29 #include <media/stagefright/foundation/ABuffer.h>
30 #include <media/stagefright/foundation/ADebug.h>
31 #include <media/stagefright/foundation/AMessage.h>
32 #include <media/stagefright/foundation/AString.h>
33 #include <media/stagefright/foundation/avc_utils.h>
34 #include <media/stagefright/foundation/base64.h>
35 #include <media/stagefright/foundation/hexdump.h>
36 #include <media/stagefright/MediaDefs.h>
37 #include <media/stagefright/MediaErrors.h>
38 #include <media/stagefright/MetaData.h>
39 #include <utils/Vector.h>
40
41 namespace android {
42
GetAttribute(const char * s,const char * key,AString * value)43 static bool GetAttribute(const char *s, const char *key, AString *value) {
44 value->clear();
45
46 size_t keyLen = strlen(key);
47
48 for (;;) {
49 while (isspace(*s)) {
50 ++s;
51 }
52
53 const char *colonPos = strchr(s, ';');
54
55 size_t len =
56 (colonPos == NULL) ? strlen(s) : colonPos - s;
57
58 if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
59 value->setTo(&s[keyLen + 1], len - keyLen - 1);
60 return true;
61 }
62
63 if (colonPos == NULL) {
64 return false;
65 }
66
67 s = colonPos + 1;
68 }
69 }
70
decodeHex(const AString & s)71 static sp<ABuffer> decodeHex(const AString &s) {
72 if ((s.size() % 2) != 0) {
73 return NULL;
74 }
75
76 size_t outLen = s.size() / 2;
77 sp<ABuffer> buffer = new ABuffer(outLen);
78 uint8_t *out = buffer->data();
79
80 uint8_t accum = 0;
81 for (size_t i = 0; i < s.size(); ++i) {
82 char c = s.c_str()[i];
83 unsigned value;
84 if (c >= '0' && c <= '9') {
85 value = c - '0';
86 } else if (c >= 'a' && c <= 'f') {
87 value = c - 'a' + 10;
88 } else if (c >= 'A' && c <= 'F') {
89 value = c - 'A' + 10;
90 } else {
91 return NULL;
92 }
93
94 accum = (accum << 4) | value;
95
96 if (i & 1) {
97 *out++ = accum;
98
99 accum = 0;
100 }
101 }
102
103 return buffer;
104 }
105
MakeAVCCodecSpecificData(const char * params,int32_t * width,int32_t * height)106 static sp<ABuffer> MakeAVCCodecSpecificData(
107 const char *params, int32_t *width, int32_t *height) {
108 *width = 0;
109 *height = 0;
110
111 AString val;
112 sp<ABuffer> profileLevelID = NULL;
113 if (GetAttribute(params, "profile-level-id", &val)) {
114 profileLevelID = decodeHex(val);
115 if (profileLevelID != NULL && profileLevelID->size() != 3u) {
116 profileLevelID = NULL;
117 }
118 }
119
120 Vector<sp<ABuffer> > paramSets;
121
122 size_t numSeqParameterSets = 0;
123 size_t totalSeqParameterSetSize = 0;
124 size_t numPicParameterSets = 0;
125 size_t totalPicParameterSetSize = 0;
126
127 if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
128 return NULL;
129 }
130
131 size_t start = 0;
132 for (;;) {
133 ssize_t commaPos = val.find(",", start);
134 size_t end = (commaPos < 0) ? val.size() : commaPos;
135
136 AString nalString(val, start, end - start);
137 sp<ABuffer> nal = decodeBase64(nalString);
138 CHECK(nal != NULL);
139 CHECK_GT(nal->size(), 0u);
140 CHECK_LE(nal->size(), 65535u);
141
142 uint8_t nalType = nal->data()[0] & 0x1f;
143 if (numSeqParameterSets == 0) {
144 CHECK_EQ((unsigned)nalType, 7u);
145 } else if (numPicParameterSets > 0) {
146 CHECK_EQ((unsigned)nalType, 8u);
147 }
148 if (nalType == 7) {
149 ++numSeqParameterSets;
150 totalSeqParameterSetSize += nal->size();
151 } else {
152 CHECK_EQ((unsigned)nalType, 8u);
153 ++numPicParameterSets;
154 totalPicParameterSetSize += nal->size();
155 }
156
157 paramSets.push(nal);
158
159 if (commaPos < 0) {
160 break;
161 }
162
163 start = commaPos + 1;
164 }
165
166 CHECK_LT(numSeqParameterSets, 32u);
167 CHECK_LE(numPicParameterSets, 255u);
168
169 size_t csdSize =
170 1 + 3 + 1 + 1
171 + 2 * numSeqParameterSets + totalSeqParameterSetSize
172 + 1 + 2 * numPicParameterSets + totalPicParameterSetSize;
173
174 sp<ABuffer> csd = new ABuffer(csdSize);
175 uint8_t *out = csd->data();
176
177 *out++ = 0x01; // configurationVersion
178 if (profileLevelID != NULL) {
179 memcpy(out, profileLevelID->data(), 3);
180 out += 3;
181 } else {
182 *out++ = 0x42; // Baseline profile
183 *out++ = 0xE0; // Common subset for all profiles
184 *out++ = 0x0A; // Level 1
185 }
186
187 *out++ = (0x3f << 2) | 1; // lengthSize == 2 bytes
188 *out++ = 0xe0 | numSeqParameterSets;
189
190 for (size_t i = 0; i < numSeqParameterSets; ++i) {
191 sp<ABuffer> nal = paramSets.editItemAt(i);
192
193 *out++ = nal->size() >> 8;
194 *out++ = nal->size() & 0xff;
195
196 memcpy(out, nal->data(), nal->size());
197
198 out += nal->size();
199
200 if (i == 0) {
201 FindAVCDimensions(nal, width, height);
202 ALOGI("dimensions %dx%d", *width, *height);
203 }
204 }
205
206 *out++ = numPicParameterSets;
207
208 for (size_t i = 0; i < numPicParameterSets; ++i) {
209 sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets);
210
211 *out++ = nal->size() >> 8;
212 *out++ = nal->size() & 0xff;
213
214 memcpy(out, nal->data(), nal->size());
215
216 out += nal->size();
217 }
218
219 // hexdump(csd->data(), csd->size());
220
221 return csd;
222 }
223
MakeAACCodecSpecificData(const char * params)224 static sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
225 AString val;
226 CHECK(GetAttribute(params, "config", &val));
227
228 sp<ABuffer> config = decodeHex(val);
229 CHECK(config != NULL);
230 CHECK_GE(config->size(), 4u);
231
232 const uint8_t *data = config->data();
233 uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
234 x = (x >> 1) & 0xffff;
235
236 static const uint8_t kStaticESDS[] = {
237 0x03, 22,
238 0x00, 0x00, // ES_ID
239 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
240
241 0x04, 17,
242 0x40, // Audio ISO/IEC 14496-3
243 0x00, 0x00, 0x00, 0x00,
244 0x00, 0x00, 0x00, 0x00,
245 0x00, 0x00, 0x00, 0x00,
246
247 0x05, 2,
248 // AudioSpecificInfo follows
249 };
250
251 sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
252 memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
253 csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
254 csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
255
256 // hexdump(csd->data(), csd->size());
257
258 return csd;
259 }
260
261 // From mpeg4-generic configuration data.
MakeAACCodecSpecificData2(const char * params)262 static sp<ABuffer> MakeAACCodecSpecificData2(const char *params) {
263 AString val;
264 unsigned long objectType;
265 if (GetAttribute(params, "objectType", &val)) {
266 const char *s = val.c_str();
267 char *end;
268 objectType = strtoul(s, &end, 10);
269 CHECK(end > s && *end == '\0');
270 } else {
271 objectType = 0x40; // Audio ISO/IEC 14496-3
272 }
273
274 CHECK(GetAttribute(params, "config", &val));
275
276 sp<ABuffer> config = decodeHex(val);
277 CHECK(config != NULL);
278
279 // Make sure size fits into a single byte and doesn't have to
280 // be encoded.
281 CHECK_LT(20 + config->size(), 128u);
282
283 static const uint8_t kStaticESDS[] = {
284 0x03, 22,
285 0x00, 0x00, // ES_ID
286 0x00, // streamDependenceFlag, URL_Flag, OCRstreamFlag
287
288 0x04, 17,
289 0x40, // Audio ISO/IEC 14496-3
290 0x00, 0x00, 0x00, 0x00,
291 0x00, 0x00, 0x00, 0x00,
292 0x00, 0x00, 0x00, 0x00,
293
294 0x05, 2,
295 // AudioSpecificInfo follows
296 };
297
298 sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + config->size());
299 uint8_t *dst = csd->data();
300 *dst++ = 0x03;
301 *dst++ = 20 + config->size();
302 *dst++ = 0x00; // ES_ID
303 *dst++ = 0x00;
304 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
305 *dst++ = 0x04;
306 *dst++ = 15 + config->size();
307 *dst++ = objectType;
308 for (int i = 0; i < 12; ++i) { *dst++ = 0x00; }
309 *dst++ = 0x05;
310 *dst++ = config->size();
311 memcpy(dst, config->data(), config->size());
312
313 // hexdump(csd->data(), csd->size());
314
315 return csd;
316 }
317
GetSizeWidth(size_t x)318 static size_t GetSizeWidth(size_t x) {
319 size_t n = 1;
320 while (x > 127) {
321 ++n;
322 x >>= 7;
323 }
324 return n;
325 }
326
EncodeSize(uint8_t * dst,size_t x)327 static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
328 while (x > 127) {
329 *dst++ = (x & 0x7f) | 0x80;
330 x >>= 7;
331 }
332 *dst++ = x;
333 return dst;
334 }
335
ExtractDimensionsMPEG4Config(const sp<ABuffer> & config,int32_t * width,int32_t * height)336 static bool ExtractDimensionsMPEG4Config(
337 const sp<ABuffer> &config, int32_t *width, int32_t *height) {
338 *width = 0;
339 *height = 0;
340
341 const uint8_t *ptr = config->data();
342 size_t offset = 0;
343 bool foundVOL = false;
344 while (offset + 3 < config->size()) {
345 if (memcmp("\x00\x00\x01", &ptr[offset], 3)
346 || (ptr[offset + 3] & 0xf0) != 0x20) {
347 ++offset;
348 continue;
349 }
350
351 foundVOL = true;
352 break;
353 }
354
355 if (!foundVOL) {
356 return false;
357 }
358
359 return ExtractDimensionsFromVOLHeader(
360 &ptr[offset], config->size() - offset, width, height);
361 }
362
MakeMPEG4VideoCodecSpecificData(const char * params,int32_t * width,int32_t * height)363 static sp<ABuffer> MakeMPEG4VideoCodecSpecificData(
364 const char *params, int32_t *width, int32_t *height) {
365 *width = 0;
366 *height = 0;
367
368 AString val;
369 CHECK(GetAttribute(params, "config", &val));
370
371 sp<ABuffer> config = decodeHex(val);
372 CHECK(config != NULL);
373
374 if (!ExtractDimensionsMPEG4Config(config, width, height)) {
375 return NULL;
376 }
377
378 ALOGI("VOL dimensions = %dx%d", *width, *height);
379
380 size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
381 size_t len2 = len1 + GetSizeWidth(len1 + 13) + 1 + 13;
382 size_t len3 = len2 + GetSizeWidth(len2 + 3) + 1 + 3;
383
384 sp<ABuffer> csd = new ABuffer(len3);
385 uint8_t *dst = csd->data();
386 *dst++ = 0x03;
387 dst = EncodeSize(dst, len2 + 3);
388 *dst++ = 0x00; // ES_ID
389 *dst++ = 0x00;
390 *dst++ = 0x00; // streamDependenceFlag, URL_Flag, OCRstreamFlag
391
392 *dst++ = 0x04;
393 dst = EncodeSize(dst, len1 + 13);
394 *dst++ = 0x01; // Video ISO/IEC 14496-2 Simple Profile
395 for (size_t i = 0; i < 12; ++i) {
396 *dst++ = 0x00;
397 }
398
399 *dst++ = 0x05;
400 dst = EncodeSize(dst, config->size());
401 memcpy(dst, config->data(), config->size());
402 dst += config->size();
403
404 // hexdump(csd->data(), csd->size());
405
406 return csd;
407 }
408
APacketSource(const sp<ASessionDescription> & sessionDesc,size_t index)409 APacketSource::APacketSource(
410 const sp<ASessionDescription> &sessionDesc, size_t index)
411 : mInitCheck(NO_INIT),
412 mFormat(new MetaData) {
413 unsigned long PT;
414 AString desc;
415 AString params;
416 sessionDesc->getFormatType(index, &PT, &desc, ¶ms);
417
418 int64_t durationUs;
419 if (sessionDesc->getDurationUs(&durationUs)) {
420 mFormat->setInt64(kKeyDuration, durationUs);
421 } else {
422 mFormat->setInt64(kKeyDuration, -1LL);
423 }
424
425 mInitCheck = OK;
426 if (!strncmp(desc.c_str(), "H264/", 5)) {
427 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
428
429 int32_t width, height;
430 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
431 width = -1;
432 height = -1;
433 }
434
435 int32_t encWidth, encHeight;
436 sp<ABuffer> codecSpecificData =
437 MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
438
439 if (codecSpecificData != NULL) {
440 if (width < 0) {
441 // If no explicit width/height given in the sdp, use the dimensions
442 // extracted from the first sequence parameter set.
443 width = encWidth;
444 height = encHeight;
445 }
446
447 mFormat->setData(
448 kKeyAVCC, 0,
449 codecSpecificData->data(), codecSpecificData->size());
450 } else if (width < 0) {
451 mInitCheck = ERROR_UNSUPPORTED;
452 return;
453 }
454
455 mFormat->setInt32(kKeyWidth, width);
456 mFormat->setInt32(kKeyHeight, height);
457 } else if (!strncmp(desc.c_str(), "H265/", 5)) {
458 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_HEVC);
459
460 int32_t width, height;
461 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
462 width = -1;
463 height = -1;
464 }
465
466 mFormat->setInt32(kKeyWidth, width);
467 mFormat->setInt32(kKeyHeight, height);
468 } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
469 || !strncmp(desc.c_str(), "H263-1998/", 10)) {
470 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
471
472 int32_t width, height;
473 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
474 mInitCheck = ERROR_UNSUPPORTED;
475 return;
476 }
477
478 mFormat->setInt32(kKeyWidth, width);
479 mFormat->setInt32(kKeyHeight, height);
480 } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
481 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
482
483 int32_t sampleRate, numChannels;
484 ASessionDescription::ParseFormatDesc(
485 desc.c_str(), &sampleRate, &numChannels);
486
487 mFormat->setInt32(kKeySampleRate, sampleRate);
488 mFormat->setInt32(kKeyChannelCount, numChannels);
489
490 sp<ABuffer> codecSpecificData =
491 MakeAACCodecSpecificData(params.c_str());
492
493 mFormat->setData(
494 kKeyESDS, 0,
495 codecSpecificData->data(), codecSpecificData->size());
496 } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
497 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
498
499 int32_t sampleRate, numChannels;
500 ASessionDescription::ParseFormatDesc(
501 desc.c_str(), &sampleRate, &numChannels);
502
503 mFormat->setInt32(kKeySampleRate, sampleRate);
504 mFormat->setInt32(kKeyChannelCount, numChannels);
505
506 if (sampleRate != 8000 || numChannels != 1) {
507 mInitCheck = ERROR_UNSUPPORTED;
508 }
509 } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
510 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
511
512 int32_t sampleRate, numChannels;
513 ASessionDescription::ParseFormatDesc(
514 desc.c_str(), &sampleRate, &numChannels);
515
516 mFormat->setInt32(kKeySampleRate, sampleRate);
517 mFormat->setInt32(kKeyChannelCount, numChannels);
518
519 if (sampleRate != 16000 || numChannels != 1) {
520 mInitCheck = ERROR_UNSUPPORTED;
521 }
522 } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
523 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
524
525 int32_t width, height;
526 if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
527 width = -1;
528 height = -1;
529 }
530
531 int32_t encWidth, encHeight;
532 sp<ABuffer> codecSpecificData =
533 MakeMPEG4VideoCodecSpecificData(
534 params.c_str(), &encWidth, &encHeight);
535
536 if (codecSpecificData != NULL) {
537 mFormat->setData(
538 kKeyESDS, 0,
539 codecSpecificData->data(), codecSpecificData->size());
540
541 if (width < 0) {
542 width = encWidth;
543 height = encHeight;
544 }
545 } else if (width < 0) {
546 mInitCheck = ERROR_UNSUPPORTED;
547 return;
548 }
549
550 mFormat->setInt32(kKeyWidth, width);
551 mFormat->setInt32(kKeyHeight, height);
552 } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
553 AString val;
554 if (!GetAttribute(params.c_str(), "mode", &val)
555 || (strcasecmp(val.c_str(), "AAC-lbr")
556 && strcasecmp(val.c_str(), "AAC-hbr"))) {
557 mInitCheck = ERROR_UNSUPPORTED;
558 return;
559 }
560
561 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
562
563 int32_t sampleRate, numChannels;
564 ASessionDescription::ParseFormatDesc(
565 desc.c_str(), &sampleRate, &numChannels);
566
567 mFormat->setInt32(kKeySampleRate, sampleRate);
568 mFormat->setInt32(kKeyChannelCount, numChannels);
569 mFormat->setInt32(kKeyIsADTS, true);
570
571 sp<ABuffer> codecSpecificData =
572 MakeAACCodecSpecificData2(params.c_str());
573
574 mFormat->setData(
575 kKeyESDS, 0,
576 codecSpecificData->data(), codecSpecificData->size());
577 } else if (ARawAudioAssembler::Supports(desc.c_str())) {
578 ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
579 } else if (!strncasecmp("MP2T/", desc.c_str(), 5)) {
580 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG2TS);
581 } else {
582 mInitCheck = ERROR_UNSUPPORTED;
583 }
584 }
585
~APacketSource()586 APacketSource::~APacketSource() {
587 }
588
initCheck() const589 status_t APacketSource::initCheck() const {
590 return mInitCheck;
591 }
592
getFormat()593 sp<MetaData> APacketSource::getFormat() {
594 return mFormat;
595 }
596
isVideo()597 bool APacketSource::isVideo() {
598 bool isVideo = false;
599
600 const char *mime;
601 if (mFormat->findCString(kKeyMIMEType, &mime)) {
602 isVideo = !strncasecmp(mime, "video/", 6);
603 }
604
605 return isVideo;
606 }
607
608 } // namespace android
609