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