APacketSource.cpp revision fcea8f7a7d178e5426aa06586cff54726e18d1f6
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/MediaBuffer.h>
38#include <media/stagefright/MediaDefs.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            LOGI("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 ExtractDimensionsFromVOLHeader(
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    ABitReader br(&ptr[offset + 4], config->size() - offset - 4);
356    br.skipBits(1);  // random_accessible_vol
357    unsigned video_object_type_indication = br.getBits(8);
358
359    CHECK_NE(video_object_type_indication,
360             0x21u /* Fine Granularity Scalable */);
361
362    unsigned video_object_layer_verid;
363    unsigned video_object_layer_priority;
364    if (br.getBits(1)) {
365        video_object_layer_verid = br.getBits(4);
366        video_object_layer_priority = br.getBits(3);
367    }
368    unsigned aspect_ratio_info = br.getBits(4);
369    if (aspect_ratio_info == 0x0f /* extended PAR */) {
370        br.skipBits(8);  // par_width
371        br.skipBits(8);  // par_height
372    }
373    if (br.getBits(1)) {  // vol_control_parameters
374        br.skipBits(2);  // chroma_format
375        br.skipBits(1);  // low_delay
376        if (br.getBits(1)) {  // vbv_parameters
377            br.skipBits(15);  // first_half_bit_rate
378            CHECK(br.getBits(1));  // marker_bit
379            br.skipBits(15);  // latter_half_bit_rate
380            CHECK(br.getBits(1));  // marker_bit
381            br.skipBits(15);  // first_half_vbv_buffer_size
382            CHECK(br.getBits(1));  // marker_bit
383            br.skipBits(3);  // latter_half_vbv_buffer_size
384            br.skipBits(11);  // first_half_vbv_occupancy
385            CHECK(br.getBits(1));  // marker_bit
386            br.skipBits(15);  // latter_half_vbv_occupancy
387            CHECK(br.getBits(1));  // marker_bit
388        }
389    }
390    unsigned video_object_layer_shape = br.getBits(2);
391    CHECK_EQ(video_object_layer_shape, 0x00u /* rectangular */);
392
393    CHECK(br.getBits(1));  // marker_bit
394    unsigned vop_time_increment_resolution = br.getBits(16);
395    CHECK(br.getBits(1));  // marker_bit
396
397    if (br.getBits(1)) {  // fixed_vop_rate
398        // range [0..vop_time_increment_resolution)
399
400        // vop_time_increment_resolution
401        // 2 => 0..1, 1 bit
402        // 3 => 0..2, 2 bits
403        // 4 => 0..3, 2 bits
404        // 5 => 0..4, 3 bits
405        // ...
406
407        CHECK_GT(vop_time_increment_resolution, 0u);
408        --vop_time_increment_resolution;
409
410        unsigned numBits = 0;
411        while (vop_time_increment_resolution > 0) {
412            ++numBits;
413            vop_time_increment_resolution >>= 1;
414        }
415
416        br.skipBits(numBits);  // fixed_vop_time_increment
417    }
418
419    CHECK(br.getBits(1));  // marker_bit
420    unsigned video_object_layer_width = br.getBits(13);
421    CHECK(br.getBits(1));  // marker_bit
422    unsigned video_object_layer_height = br.getBits(13);
423    CHECK(br.getBits(1));  // marker_bit
424
425    unsigned interlaced = br.getBits(1);
426
427    *width = video_object_layer_width;
428    *height = video_object_layer_height;
429
430    LOGI("VOL dimensions = %dx%d", *width, *height);
431
432    return true;
433}
434
435sp<ABuffer> MakeMPEG4VideoCodecSpecificData(
436        const char *params, int32_t *width, int32_t *height) {
437    *width = 0;
438    *height = 0;
439
440    AString val;
441    CHECK(GetAttribute(params, "config", &val));
442
443    sp<ABuffer> config = decodeHex(val);
444    CHECK(config != NULL);
445
446    if (!ExtractDimensionsFromVOLHeader(config, width, height)) {
447        return NULL;
448    }
449
450    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
451    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
452    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
453
454    sp<ABuffer> csd = new ABuffer(len3);
455    uint8_t *dst = csd->data();
456    *dst++ = 0x03;
457    dst = EncodeSize(dst, len2 + 3);
458    *dst++ = 0x00;  // ES_ID
459    *dst++ = 0x00;
460    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
461
462    *dst++ = 0x04;
463    dst = EncodeSize(dst, len1 + 13);
464    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
465    for (size_t i = 0; i < 12; ++i) {
466        *dst++ = 0x00;
467    }
468
469    *dst++ = 0x05;
470    dst = EncodeSize(dst, config->size());
471    memcpy(dst, config->data(), config->size());
472    dst += config->size();
473
474    // hexdump(csd->data(), csd->size());
475
476    return csd;
477}
478
479static bool GetClockRate(const AString &desc, uint32_t *clockRate) {
480    ssize_t slashPos = desc.find("/");
481    if (slashPos < 0) {
482        return false;
483    }
484
485    const char *s = desc.c_str() + slashPos + 1;
486
487    char *end;
488    unsigned long x = strtoul(s, &end, 10);
489
490    if (end == s || (*end != '\0' && *end != '/')) {
491        return false;
492    }
493
494    *clockRate = x;
495
496    return true;
497}
498
499APacketSource::APacketSource(
500        const sp<ASessionDescription> &sessionDesc, size_t index)
501    : mInitCheck(NO_INIT),
502      mFormat(new MetaData),
503      mEOSResult(OK),
504      mIsAVC(false),
505      mScanForIDR(true),
506      mRTPTimeBase(0),
507      mNormalPlayTimeBaseUs(0),
508      mLastNormalPlayTimeUs(0) {
509    unsigned long PT;
510    AString desc;
511    AString params;
512    sessionDesc->getFormatType(index, &PT, &desc, &params);
513
514    CHECK(GetClockRate(desc, &mClockRate));
515
516    int64_t durationUs;
517    if (sessionDesc->getDurationUs(&durationUs)) {
518        mFormat->setInt64(kKeyDuration, durationUs);
519    } else {
520        mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
521    }
522
523    mInitCheck = OK;
524    if (!strncmp(desc.c_str(), "H264/", 5)) {
525        mIsAVC = true;
526
527        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
528
529        int32_t width, height;
530        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
531            width = -1;
532            height = -1;
533        }
534
535        int32_t encWidth, encHeight;
536        sp<ABuffer> codecSpecificData =
537            MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
538
539        if (codecSpecificData != NULL) {
540            if (width < 0) {
541                // If no explicit width/height given in the sdp, use the dimensions
542                // extracted from the first sequence parameter set.
543                width = encWidth;
544                height = encHeight;
545            }
546
547            mFormat->setData(
548                    kKeyAVCC, 0,
549                    codecSpecificData->data(), codecSpecificData->size());
550        } else if (width < 0) {
551            mInitCheck = ERROR_UNSUPPORTED;
552            return;
553        }
554
555        mFormat->setInt32(kKeyWidth, width);
556        mFormat->setInt32(kKeyHeight, height);
557    } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
558            || !strncmp(desc.c_str(), "H263-1998/", 10)) {
559        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
560
561        int32_t width, height;
562        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
563            mInitCheck = ERROR_UNSUPPORTED;
564            return;
565        }
566
567        mFormat->setInt32(kKeyWidth, width);
568        mFormat->setInt32(kKeyHeight, height);
569    } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
570        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
571
572        int32_t sampleRate, numChannels;
573        ASessionDescription::ParseFormatDesc(
574                desc.c_str(), &sampleRate, &numChannels);
575
576        mFormat->setInt32(kKeySampleRate, sampleRate);
577        mFormat->setInt32(kKeyChannelCount, numChannels);
578
579        sp<ABuffer> codecSpecificData =
580            MakeAACCodecSpecificData(params.c_str());
581
582        mFormat->setData(
583                kKeyESDS, 0,
584                codecSpecificData->data(), codecSpecificData->size());
585    } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
586        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
587
588        int32_t sampleRate, numChannels;
589        ASessionDescription::ParseFormatDesc(
590                desc.c_str(), &sampleRate, &numChannels);
591
592        mFormat->setInt32(kKeySampleRate, sampleRate);
593        mFormat->setInt32(kKeyChannelCount, numChannels);
594
595        if (sampleRate != 8000 || numChannels != 1) {
596            mInitCheck = ERROR_UNSUPPORTED;
597        }
598    } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
599        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
600
601        int32_t sampleRate, numChannels;
602        ASessionDescription::ParseFormatDesc(
603                desc.c_str(), &sampleRate, &numChannels);
604
605        mFormat->setInt32(kKeySampleRate, sampleRate);
606        mFormat->setInt32(kKeyChannelCount, numChannels);
607
608        if (sampleRate != 16000 || numChannels != 1) {
609            mInitCheck = ERROR_UNSUPPORTED;
610        }
611    } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
612        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
613
614        int32_t width, height;
615        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
616            width = -1;
617            height = -1;
618        }
619
620        int32_t encWidth, encHeight;
621        sp<ABuffer> codecSpecificData =
622            MakeMPEG4VideoCodecSpecificData(
623                    params.c_str(), &encWidth, &encHeight);
624
625        if (codecSpecificData != NULL) {
626            mFormat->setData(
627                    kKeyESDS, 0,
628                    codecSpecificData->data(), codecSpecificData->size());
629
630            if (width < 0) {
631                width = encWidth;
632                height = encHeight;
633            }
634        } else if (width < 0) {
635            mInitCheck = ERROR_UNSUPPORTED;
636            return;
637        }
638
639        mFormat->setInt32(kKeyWidth, width);
640        mFormat->setInt32(kKeyHeight, height);
641    } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
642        AString val;
643        if (!GetAttribute(params.c_str(), "mode", &val)
644                || (strcasecmp(val.c_str(), "AAC-lbr")
645                    && strcasecmp(val.c_str(), "AAC-hbr"))) {
646            mInitCheck = ERROR_UNSUPPORTED;
647            return;
648        }
649
650        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
651
652        int32_t sampleRate, numChannels;
653        ASessionDescription::ParseFormatDesc(
654                desc.c_str(), &sampleRate, &numChannels);
655
656        mFormat->setInt32(kKeySampleRate, sampleRate);
657        mFormat->setInt32(kKeyChannelCount, numChannels);
658
659        sp<ABuffer> codecSpecificData =
660            MakeAACCodecSpecificData2(params.c_str());
661
662        mFormat->setData(
663                kKeyESDS, 0,
664                codecSpecificData->data(), codecSpecificData->size());
665    } else if (ARawAudioAssembler::Supports(desc.c_str())) {
666        ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
667    } else {
668        mInitCheck = ERROR_UNSUPPORTED;
669    }
670}
671
672APacketSource::~APacketSource() {
673}
674
675status_t APacketSource::initCheck() const {
676    return mInitCheck;
677}
678
679status_t APacketSource::start(MetaData *params) {
680    return OK;
681}
682
683status_t APacketSource::stop() {
684    return OK;
685}
686
687sp<MetaData> APacketSource::getFormat() {
688    return mFormat;
689}
690
691status_t APacketSource::read(
692        MediaBuffer **out, const ReadOptions *) {
693    *out = NULL;
694
695    Mutex::Autolock autoLock(mLock);
696    while (mEOSResult == OK && mBuffers.empty()) {
697        mCondition.wait(mLock);
698    }
699
700    if (!mBuffers.empty()) {
701        const sp<ABuffer> buffer = *mBuffers.begin();
702
703        updateNormalPlayTime_l(buffer);
704
705        MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
706
707        int64_t timeUs;
708        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
709
710        mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
711
712        memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
713        *out = mediaBuffer;
714
715        mBuffers.erase(mBuffers.begin());
716        return OK;
717    }
718
719    return mEOSResult;
720}
721
722void APacketSource::updateNormalPlayTime_l(const sp<ABuffer> &buffer) {
723    uint32_t rtpTime;
724    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
725
726    mLastNormalPlayTimeUs =
727        (((double)rtpTime - (double)mRTPTimeBase) / mClockRate)
728            * 1000000ll
729            + mNormalPlayTimeBaseUs;
730}
731
732void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
733    int32_t damaged;
734    if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
735        LOGV("discarding damaged AU");
736        return;
737    }
738
739    if (mScanForIDR && mIsAVC) {
740        // This pretty piece of code ensures that the first access unit
741        // fed to the decoder after stream-start or seek is guaranteed to
742        // be an IDR frame. This is to workaround limitations of a certain
743        // hardware h.264 decoder that requires this to be the case.
744
745        if (!IsIDR(buffer)) {
746            LOGV("skipping AU while scanning for next IDR frame.");
747            return;
748        }
749
750        mScanForIDR = false;
751    }
752
753    Mutex::Autolock autoLock(mLock);
754    mBuffers.push_back(buffer);
755    mCondition.signal();
756}
757
758void APacketSource::signalEOS(status_t result) {
759    CHECK(result != OK);
760
761    Mutex::Autolock autoLock(mLock);
762    mEOSResult = result;
763    mCondition.signal();
764}
765
766void APacketSource::flushQueue() {
767    Mutex::Autolock autoLock(mLock);
768    mBuffers.clear();
769
770    mScanForIDR = true;
771}
772
773int64_t APacketSource::getNormalPlayTimeUs() {
774    Mutex::Autolock autoLock(mLock);
775    return mLastNormalPlayTimeUs;
776}
777
778void APacketSource::setNormalPlayTimeMapping(
779        uint32_t rtpTime, int64_t normalPlayTimeUs) {
780    Mutex::Autolock autoLock(mLock);
781
782    mRTPTimeBase = rtpTime;
783    mNormalPlayTimeBaseUs = normalPlayTimeUs;
784}
785
786int64_t APacketSource::getQueueDurationUs(bool *eos) {
787    Mutex::Autolock autoLock(mLock);
788
789    *eos = (mEOSResult != OK);
790
791    if (mBuffers.size() < 2) {
792        return 0;
793    }
794
795    const sp<ABuffer> first = *mBuffers.begin();
796    const sp<ABuffer> last = *--mBuffers.end();
797
798    int64_t firstTimeUs;
799    CHECK(first->meta()->findInt64("timeUs", &firstTimeUs));
800
801    int64_t lastTimeUs;
802    CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
803
804    if (lastTimeUs < firstTimeUs) {
805        LOGE("Huh? Time moving backwards? %lld > %lld",
806             firstTimeUs, lastTimeUs);
807
808        return 0;
809    }
810
811    return lastTimeUs - firstTimeUs;
812}
813
814}  // namespace android
815