APacketSource.cpp revision 62cb04d23642a2ea7c005f050494c8ef3c370dd3
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#include "APacketSource.h"
18
19#include "ASessionDescription.h"
20
21#include "avc_utils.h"
22
23#include <ctype.h>
24
25#include <media/stagefright/foundation/ABitReader.h>
26#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/foundation/AMessage.h>
29#include <media/stagefright/foundation/AString.h>
30#include <media/stagefright/foundation/base64.h>
31#include <media/stagefright/foundation/hexdump.h>
32#include <media/stagefright/MediaBuffer.h>
33#include <media/stagefright/MediaDefs.h>
34#include <media/stagefright/MetaData.h>
35#include <utils/Vector.h>
36
37namespace android {
38
39static bool GetAttribute(const char *s, const char *key, AString *value) {
40    value->clear();
41
42    size_t keyLen = strlen(key);
43
44    for (;;) {
45        while (isspace(*s)) {
46            ++s;
47        }
48
49        const char *colonPos = strchr(s, ';');
50
51        size_t len =
52            (colonPos == NULL) ? strlen(s) : colonPos - s;
53
54        if (len >= keyLen + 1 && s[keyLen] == '=' && !strncmp(s, key, keyLen)) {
55            value->setTo(&s[keyLen + 1], len - keyLen - 1);
56            return true;
57        }
58
59        if (colonPos == NULL) {
60            return false;
61        }
62
63        s = colonPos + 1;
64    }
65}
66
67static sp<ABuffer> decodeHex(const AString &s) {
68    if ((s.size() % 2) != 0) {
69        return NULL;
70    }
71
72    size_t outLen = s.size() / 2;
73    sp<ABuffer> buffer = new ABuffer(outLen);
74    uint8_t *out = buffer->data();
75
76    uint8_t accum = 0;
77    for (size_t i = 0; i < s.size(); ++i) {
78        char c = s.c_str()[i];
79        unsigned value;
80        if (c >= '0' && c <= '9') {
81            value = c - '0';
82        } else if (c >= 'a' && c <= 'f') {
83            value = c - 'a' + 10;
84        } else if (c >= 'A' && c <= 'F') {
85            value = c - 'A' + 10;
86        } else {
87            return NULL;
88        }
89
90        accum = (accum << 4) | value;
91
92        if (i & 1) {
93            *out++ = accum;
94
95            accum = 0;
96        }
97    }
98
99    return buffer;
100}
101
102static sp<ABuffer> MakeAVCCodecSpecificData(
103        const char *params, int32_t *width, int32_t *height) {
104    *width = 0;
105    *height = 0;
106
107    AString val;
108    if (!GetAttribute(params, "profile-level-id", &val)) {
109        return NULL;
110    }
111
112    sp<ABuffer> profileLevelID = decodeHex(val);
113    CHECK(profileLevelID != NULL);
114    CHECK_EQ(profileLevelID->size(), 3u);
115
116    Vector<sp<ABuffer> > paramSets;
117
118    size_t numSeqParameterSets = 0;
119    size_t totalSeqParameterSetSize = 0;
120    size_t numPicParameterSets = 0;
121    size_t totalPicParameterSetSize = 0;
122
123    if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
124        return NULL;
125    }
126
127    size_t start = 0;
128    for (;;) {
129        ssize_t commaPos = val.find(",", start);
130        size_t end = (commaPos < 0) ? val.size() : commaPos;
131
132        AString nalString(val, start, end - start);
133        sp<ABuffer> nal = decodeBase64(nalString);
134        CHECK(nal != NULL);
135        CHECK_GT(nal->size(), 0u);
136        CHECK_LE(nal->size(), 65535u);
137
138        uint8_t nalType = nal->data()[0] & 0x1f;
139        if (numSeqParameterSets == 0) {
140            CHECK_EQ((unsigned)nalType, 7u);
141        } else if (numPicParameterSets > 0) {
142            CHECK_EQ((unsigned)nalType, 8u);
143        }
144        if (nalType == 7) {
145            ++numSeqParameterSets;
146            totalSeqParameterSetSize += nal->size();
147        } else  {
148            CHECK_EQ((unsigned)nalType, 8u);
149            ++numPicParameterSets;
150            totalPicParameterSetSize += nal->size();
151        }
152
153        paramSets.push(nal);
154
155        if (commaPos < 0) {
156            break;
157        }
158
159        start = commaPos + 1;
160    }
161
162    CHECK_LT(numSeqParameterSets, 32u);
163    CHECK_LE(numPicParameterSets, 255u);
164
165    size_t csdSize =
166        1 + 3 + 1 + 1
167        + 2 * numSeqParameterSets + totalSeqParameterSetSize
168        + 1 + 2 * numPicParameterSets + totalPicParameterSetSize;
169
170    sp<ABuffer> csd = new ABuffer(csdSize);
171    uint8_t *out = csd->data();
172
173    *out++ = 0x01;  // configurationVersion
174    memcpy(out, profileLevelID->data(), 3);
175    out += 3;
176    *out++ = (0x3f << 2) | 1;  // lengthSize == 2 bytes
177    *out++ = 0xe0 | numSeqParameterSets;
178
179    for (size_t i = 0; i < numSeqParameterSets; ++i) {
180        sp<ABuffer> nal = paramSets.editItemAt(i);
181
182        *out++ = nal->size() >> 8;
183        *out++ = nal->size() & 0xff;
184
185        memcpy(out, nal->data(), nal->size());
186
187        out += nal->size();
188
189        if (i == 0) {
190            FindAVCDimensions(nal, width, height);
191            LOG(INFO) << "dimensions " << *width << "x" << *height;
192        }
193    }
194
195    *out++ = numPicParameterSets;
196
197    for (size_t i = 0; i < numPicParameterSets; ++i) {
198        sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets);
199
200        *out++ = nal->size() >> 8;
201        *out++ = nal->size() & 0xff;
202
203        memcpy(out, nal->data(), nal->size());
204
205        out += nal->size();
206    }
207
208    // hexdump(csd->data(), csd->size());
209
210    return csd;
211}
212
213sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
214    AString val;
215    CHECK(GetAttribute(params, "config", &val));
216
217    sp<ABuffer> config = decodeHex(val);
218    CHECK(config != NULL);
219    CHECK_GE(config->size(), 4u);
220
221    const uint8_t *data = config->data();
222    uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
223    x = (x >> 1) & 0xffff;
224
225    static const uint8_t kStaticESDS[] = {
226        0x03, 22,
227        0x00, 0x00,     // ES_ID
228        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
229
230        0x04, 17,
231        0x40,                       // Audio ISO/IEC 14496-3
232        0x00, 0x00, 0x00, 0x00,
233        0x00, 0x00, 0x00, 0x00,
234        0x00, 0x00, 0x00, 0x00,
235
236        0x05, 2,
237        // AudioSpecificInfo follows
238    };
239
240    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
241    memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
242    csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
243    csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
244
245    // hexdump(csd->data(), csd->size());
246
247    return csd;
248}
249
250static size_t GetSizeWidth(size_t x) {
251    size_t n = 1;
252    while (x > 127) {
253        ++n;
254        x >>= 7;
255    }
256    return n;
257}
258
259static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
260    while (x > 127) {
261        *dst++ = (x & 0x7f) | 0x80;
262        x >>= 7;
263    }
264    *dst++ = x;
265    return dst;
266}
267
268static bool ExtractDimensionsFromVOLHeader(
269        const sp<ABuffer> &config, int32_t *width, int32_t *height) {
270    *width = 0;
271    *height = 0;
272
273    const uint8_t *ptr = config->data();
274    size_t offset = 0;
275    bool foundVOL = false;
276    while (offset + 3 < config->size()) {
277        if (memcmp("\x00\x00\x01", &ptr[offset], 3)
278                || (ptr[offset + 3] & 0xf0) != 0x20) {
279            ++offset;
280            continue;
281        }
282
283        foundVOL = true;
284        break;
285    }
286
287    if (!foundVOL) {
288        return false;
289    }
290
291    ABitReader br(&ptr[offset + 4], config->size() - offset - 4);
292    br.skipBits(1);  // random_accessible_vol
293    unsigned video_object_type_indication = br.getBits(8);
294
295    CHECK_NE(video_object_type_indication,
296             0x21u /* Fine Granularity Scalable */);
297
298    unsigned video_object_layer_verid;
299    unsigned video_object_layer_priority;
300    if (br.getBits(1)) {
301        video_object_layer_verid = br.getBits(4);
302        video_object_layer_priority = br.getBits(3);
303    }
304    unsigned aspect_ratio_info = br.getBits(4);
305    if (aspect_ratio_info == 0x0f /* extended PAR */) {
306        br.skipBits(8);  // par_width
307        br.skipBits(8);  // par_height
308    }
309    if (br.getBits(1)) {  // vol_control_parameters
310        br.skipBits(2);  // chroma_format
311        br.skipBits(1);  // low_delay
312        if (br.getBits(1)) {  // vbv_parameters
313            TRESPASS();
314        }
315    }
316    unsigned video_object_layer_shape = br.getBits(2);
317    CHECK_EQ(video_object_layer_shape, 0x00u /* rectangular */);
318
319    CHECK(br.getBits(1));  // marker_bit
320    unsigned vop_time_increment_resolution = br.getBits(16);
321    CHECK(br.getBits(1));  // marker_bit
322
323    if (br.getBits(1)) {  // fixed_vop_rate
324        // range [0..vop_time_increment_resolution)
325
326        // vop_time_increment_resolution
327        // 2 => 0..1, 1 bit
328        // 3 => 0..2, 2 bits
329        // 4 => 0..3, 2 bits
330        // 5 => 0..4, 3 bits
331        // ...
332
333        CHECK_GT(vop_time_increment_resolution, 0u);
334        --vop_time_increment_resolution;
335
336        unsigned numBits = 0;
337        while (vop_time_increment_resolution > 0) {
338            ++numBits;
339            vop_time_increment_resolution >>= 1;
340        }
341
342        br.skipBits(numBits);  // fixed_vop_time_increment
343    }
344
345    CHECK(br.getBits(1));  // marker_bit
346    unsigned video_object_layer_width = br.getBits(13);
347    CHECK(br.getBits(1));  // marker_bit
348    unsigned video_object_layer_height = br.getBits(13);
349    CHECK(br.getBits(1));  // marker_bit
350
351    unsigned interlaced = br.getBits(1);
352
353    *width = video_object_layer_width;
354    *height = video_object_layer_height;
355
356    LOG(INFO) << "VOL dimensions = " << *width << "x" << *height;
357
358    return true;
359}
360
361sp<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 (!ExtractDimensionsFromVOLHeader(config, width, height)) {
373        return NULL;
374    }
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      mEOSResult(OK),
410      mFirstAccessUnit(true),
411      mFirstAccessUnitNTP(0) {
412    unsigned long PT;
413    AString desc;
414    AString params;
415    sessionDesc->getFormatType(index, &PT, &desc, &params);
416
417    int64_t durationUs;
418    if (sessionDesc->getDurationUs(&durationUs)) {
419        mFormat->setInt64(kKeyDuration, durationUs);
420    } else {
421        mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
422    }
423
424    mInitCheck = OK;
425    if (!strncmp(desc.c_str(), "H264/", 5)) {
426        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
427
428        int32_t width, height;
429        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
430            width = -1;
431            height = -1;
432        }
433
434        int32_t encWidth, encHeight;
435        sp<ABuffer> codecSpecificData =
436            MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
437
438        if (codecSpecificData != NULL) {
439            if (width < 0) {
440                // If no explicit width/height given in the sdp, use the dimensions
441                // extracted from the first sequence parameter set.
442                width = encWidth;
443                height = encHeight;
444            }
445
446            mFormat->setData(
447                    kKeyAVCC, 0,
448                    codecSpecificData->data(), codecSpecificData->size());
449        } else if (width < 0) {
450            mInitCheck = ERROR_UNSUPPORTED;
451            return;
452        }
453
454        mFormat->setInt32(kKeyWidth, width);
455        mFormat->setInt32(kKeyHeight, height);
456    } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
457            || !strncmp(desc.c_str(), "H263-1998/", 10)) {
458        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
459
460        int32_t width, height;
461        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
462            mInitCheck = ERROR_UNSUPPORTED;
463            return;
464        }
465
466        mFormat->setInt32(kKeyWidth, width);
467        mFormat->setInt32(kKeyHeight, height);
468    } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
469        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
470
471        int32_t sampleRate, numChannels;
472        ASessionDescription::ParseFormatDesc(
473                desc.c_str(), &sampleRate, &numChannels);
474
475        mFormat->setInt32(kKeySampleRate, sampleRate);
476        mFormat->setInt32(kKeyChannelCount, numChannels);
477
478        sp<ABuffer> codecSpecificData =
479            MakeAACCodecSpecificData(params.c_str());
480
481        mFormat->setData(
482                kKeyESDS, 0,
483                codecSpecificData->data(), codecSpecificData->size());
484    } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
485        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
486
487        int32_t sampleRate, numChannels;
488        ASessionDescription::ParseFormatDesc(
489                desc.c_str(), &sampleRate, &numChannels);
490
491        mFormat->setInt32(kKeySampleRate, sampleRate);
492        mFormat->setInt32(kKeyChannelCount, numChannels);
493
494        if (sampleRate != 8000 || numChannels != 1) {
495            mInitCheck = ERROR_UNSUPPORTED;
496        }
497    } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
498        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
499
500        int32_t sampleRate, numChannels;
501        ASessionDescription::ParseFormatDesc(
502                desc.c_str(), &sampleRate, &numChannels);
503
504        mFormat->setInt32(kKeySampleRate, sampleRate);
505        mFormat->setInt32(kKeyChannelCount, numChannels);
506
507        if (sampleRate != 16000 || numChannels != 1) {
508            mInitCheck = ERROR_UNSUPPORTED;
509        }
510    } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
511        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
512
513        int32_t width, height;
514        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
515            width = -1;
516            height = -1;
517        }
518
519        int32_t encWidth, encHeight;
520        sp<ABuffer> codecSpecificData =
521            MakeMPEG4VideoCodecSpecificData(
522                    params.c_str(), &encWidth, &encHeight);
523
524        if (codecSpecificData != NULL) {
525            mFormat->setData(
526                    kKeyESDS, 0,
527                    codecSpecificData->data(), codecSpecificData->size());
528
529            if (width < 0) {
530                width = encWidth;
531                height = encHeight;
532            }
533        } else if (width < 0) {
534            mInitCheck = ERROR_UNSUPPORTED;
535            return;
536        }
537
538        mFormat->setInt32(kKeyWidth, width);
539        mFormat->setInt32(kKeyHeight, height);
540    } else {
541        mInitCheck = ERROR_UNSUPPORTED;
542    }
543}
544
545APacketSource::~APacketSource() {
546}
547
548status_t APacketSource::initCheck() const {
549    return mInitCheck;
550}
551
552status_t APacketSource::start(MetaData *params) {
553    mFirstAccessUnit = true;
554    mFirstAccessUnitNTP = 0;
555
556    return OK;
557}
558
559status_t APacketSource::stop() {
560    return OK;
561}
562
563sp<MetaData> APacketSource::getFormat() {
564    return mFormat;
565}
566
567status_t APacketSource::read(
568        MediaBuffer **out, const ReadOptions *) {
569    *out = NULL;
570
571    Mutex::Autolock autoLock(mLock);
572    while (mEOSResult == OK && mBuffers.empty()) {
573        mCondition.wait(mLock);
574    }
575
576    if (!mBuffers.empty()) {
577        const sp<ABuffer> buffer = *mBuffers.begin();
578
579        MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
580
581        int64_t timeUs;
582        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
583
584        mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
585
586        memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
587        *out = mediaBuffer;
588
589        mBuffers.erase(mBuffers.begin());
590        return OK;
591    }
592
593    return mEOSResult;
594}
595
596void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
597    int32_t damaged;
598    if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
599        LOG(VERBOSE) << "discarding damaged AU";
600        return;
601    }
602
603    uint64_t ntpTime;
604    CHECK(buffer->meta()->findInt64(
605                "ntp-time", (int64_t *)&ntpTime));
606
607    if (mFirstAccessUnit) {
608        mFirstAccessUnit = false;
609        mFirstAccessUnitNTP = ntpTime;
610    }
611
612    if (ntpTime > mFirstAccessUnitNTP) {
613        ntpTime -= mFirstAccessUnitNTP;
614    } else {
615        ntpTime = 0;
616    }
617
618    int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
619
620    buffer->meta()->setInt64("timeUs", timeUs);
621
622    Mutex::Autolock autoLock(mLock);
623    mBuffers.push_back(buffer);
624    mCondition.signal();
625}
626
627void APacketSource::signalEOS(status_t result) {
628    CHECK(result != OK);
629
630    Mutex::Autolock autoLock(mLock);
631    mEOSResult = result;
632    mCondition.signal();
633}
634
635int64_t APacketSource::getQueuedDuration(bool *eos) {
636    Mutex::Autolock autoLock(mLock);
637
638    *eos = (mEOSResult != OK);
639
640    if (mBuffers.empty()) {
641        return 0;
642    }
643
644    sp<ABuffer> buffer = *mBuffers.begin();
645
646    uint64_t ntpTime;
647    CHECK(buffer->meta()->findInt64(
648                "ntp-time", (int64_t *)&ntpTime));
649
650    int64_t firstTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
651
652    buffer = *--mBuffers.end();
653
654    CHECK(buffer->meta()->findInt64(
655                "ntp-time", (int64_t *)&ntpTime));
656
657    int64_t lastTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
658
659    return lastTimeUs - firstTimeUs;
660}
661
662}  // namespace android
663