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