APacketSource.cpp revision 8647bbe4420ca487467318404127f52c567e346b
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    if (!GetAttribute(params, "profile-level-id", &val)) {
114        return NULL;
115    }
116
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
128    if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
129        return NULL;
130    }
131
132    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();
193
194        if (i == 0) {
195            FindAVCDimensions(nal, width, height);
196            ALOGI("dimensions %dx%d", *width, *height);
197        }
198    }
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
213    // hexdump(csd->data(), csd->size());
214
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
250    // hexdump(csd->data(), csd->size());
251
252    return csd;
253}
254
255// 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
314static 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 ExtractDimensionsMPEG4Config(
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    return ExtractDimensionsFromVOLHeader(
356            &ptr[offset], config->size() - offset, width, height);
357}
358
359static sp<ABuffer> MakeMPEG4VideoCodecSpecificData(
360        const char *params, int32_t *width, int32_t *height) {
361    *width = 0;
362    *height = 0;
363
364    AString val;
365    CHECK(GetAttribute(params, "config", &val));
366
367    sp<ABuffer> config = decodeHex(val);
368    CHECK(config != NULL);
369
370    if (!ExtractDimensionsMPEG4Config(config, width, height)) {
371        return NULL;
372    }
373
374    ALOGI("VOL dimensions = %dx%d", *width, *height);
375
376    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
377    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
378    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
379
380    sp<ABuffer> csd = new ABuffer(len3);
381    uint8_t *dst = csd->data();
382    *dst++ = 0x03;
383    dst = EncodeSize(dst, len2 + 3);
384    *dst++ = 0x00;  // ES_ID
385    *dst++ = 0x00;
386    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
387
388    *dst++ = 0x04;
389    dst = EncodeSize(dst, len1 + 13);
390    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
391    for (size_t i = 0; i < 12; ++i) {
392        *dst++ = 0x00;
393    }
394
395    *dst++ = 0x05;
396    dst = EncodeSize(dst, config->size());
397    memcpy(dst, config->data(), config->size());
398    dst += config->size();
399
400    // hexdump(csd->data(), csd->size());
401
402    return csd;
403}
404
405APacketSource::APacketSource(
406        const sp<ASessionDescription> &sessionDesc, size_t index)
407    : mInitCheck(NO_INIT),
408      mFormat(new MetaData) {
409    unsigned long PT;
410    AString desc;
411    AString params;
412    sessionDesc->getFormatType(index, &PT, &desc, &params);
413
414    int64_t durationUs;
415    if (sessionDesc->getDurationUs(&durationUs)) {
416        mFormat->setInt64(kKeyDuration, durationUs);
417    } else {
418        mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
419    }
420
421    mInitCheck = OK;
422    if (!strncmp(desc.c_str(), "H264/", 5)) {
423        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
424
425        int32_t width, height;
426        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
427            width = -1;
428            height = -1;
429        }
430
431        int32_t encWidth, encHeight;
432        sp<ABuffer> codecSpecificData =
433            MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
434
435        if (codecSpecificData != NULL) {
436            if (width < 0) {
437                // If no explicit width/height given in the sdp, use the dimensions
438                // extracted from the first sequence parameter set.
439                width = encWidth;
440                height = encHeight;
441            }
442
443            mFormat->setData(
444                    kKeyAVCC, 0,
445                    codecSpecificData->data(), codecSpecificData->size());
446        } else if (width < 0) {
447            mInitCheck = ERROR_UNSUPPORTED;
448            return;
449        }
450
451        mFormat->setInt32(kKeyWidth, width);
452        mFormat->setInt32(kKeyHeight, height);
453    } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
454            || !strncmp(desc.c_str(), "H263-1998/", 10)) {
455        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
456
457        int32_t width, height;
458        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
459            mInitCheck = ERROR_UNSUPPORTED;
460            return;
461        }
462
463        mFormat->setInt32(kKeyWidth, width);
464        mFormat->setInt32(kKeyHeight, height);
465    } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
466        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
467
468        int32_t sampleRate, numChannels;
469        ASessionDescription::ParseFormatDesc(
470                desc.c_str(), &sampleRate, &numChannels);
471
472        mFormat->setInt32(kKeySampleRate, sampleRate);
473        mFormat->setInt32(kKeyChannelCount, numChannels);
474
475        sp<ABuffer> codecSpecificData =
476            MakeAACCodecSpecificData(params.c_str());
477
478        mFormat->setData(
479                kKeyESDS, 0,
480                codecSpecificData->data(), codecSpecificData->size());
481    } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
482        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
483
484        int32_t sampleRate, numChannels;
485        ASessionDescription::ParseFormatDesc(
486                desc.c_str(), &sampleRate, &numChannels);
487
488        mFormat->setInt32(kKeySampleRate, sampleRate);
489        mFormat->setInt32(kKeyChannelCount, numChannels);
490
491        if (sampleRate != 8000 || numChannels != 1) {
492            mInitCheck = ERROR_UNSUPPORTED;
493        }
494    } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
495        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
496
497        int32_t sampleRate, numChannels;
498        ASessionDescription::ParseFormatDesc(
499                desc.c_str(), &sampleRate, &numChannels);
500
501        mFormat->setInt32(kKeySampleRate, sampleRate);
502        mFormat->setInt32(kKeyChannelCount, numChannels);
503
504        if (sampleRate != 16000 || numChannels != 1) {
505            mInitCheck = ERROR_UNSUPPORTED;
506        }
507    } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
508        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
509
510        int32_t width, height;
511        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
512            width = -1;
513            height = -1;
514        }
515
516        int32_t encWidth, encHeight;
517        sp<ABuffer> codecSpecificData =
518            MakeMPEG4VideoCodecSpecificData(
519                    params.c_str(), &encWidth, &encHeight);
520
521        if (codecSpecificData != NULL) {
522            mFormat->setData(
523                    kKeyESDS, 0,
524                    codecSpecificData->data(), codecSpecificData->size());
525
526            if (width < 0) {
527                width = encWidth;
528                height = encHeight;
529            }
530        } else if (width < 0) {
531            mInitCheck = ERROR_UNSUPPORTED;
532            return;
533        }
534
535        mFormat->setInt32(kKeyWidth, width);
536        mFormat->setInt32(kKeyHeight, height);
537    } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
538        AString val;
539        if (!GetAttribute(params.c_str(), "mode", &val)
540                || (strcasecmp(val.c_str(), "AAC-lbr")
541                    && strcasecmp(val.c_str(), "AAC-hbr"))) {
542            mInitCheck = ERROR_UNSUPPORTED;
543            return;
544        }
545
546        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
547
548        int32_t sampleRate, numChannels;
549        ASessionDescription::ParseFormatDesc(
550                desc.c_str(), &sampleRate, &numChannels);
551
552        mFormat->setInt32(kKeySampleRate, sampleRate);
553        mFormat->setInt32(kKeyChannelCount, numChannels);
554        mFormat->setInt32(kKeyIsADTS, true);
555
556        sp<ABuffer> codecSpecificData =
557            MakeAACCodecSpecificData2(params.c_str());
558
559        mFormat->setData(
560                kKeyESDS, 0,
561                codecSpecificData->data(), codecSpecificData->size());
562    } else if (ARawAudioAssembler::Supports(desc.c_str())) {
563        ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
564    } else {
565        mInitCheck = ERROR_UNSUPPORTED;
566    }
567}
568
569APacketSource::~APacketSource() {
570}
571
572status_t APacketSource::initCheck() const {
573    return mInitCheck;
574}
575
576sp<MetaData> APacketSource::getFormat() {
577    return mFormat;
578}
579
580}  // namespace android
581