APacketSource.cpp revision dc468c5f9d72ce54de0070493e9a23efb8907e06
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 "ASessionDescription.h"
24
25#include "avc_utils.h"
26
27#include <ctype.h>
28
29#include <media/stagefright/foundation/ABitReader.h>
30#include <media/stagefright/foundation/ABuffer.h>
31#include <media/stagefright/foundation/ADebug.h>
32#include <media/stagefright/foundation/AMessage.h>
33#include <media/stagefright/foundation/AString.h>
34#include <media/stagefright/foundation/base64.h>
35#include <media/stagefright/foundation/hexdump.h>
36#include <media/stagefright/MediaBuffer.h>
37#include <media/stagefright/MediaDefs.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    if (!GetAttribute(params, "profile-level-id", &val)) {
113        return NULL;
114    }
115
116    sp<ABuffer> profileLevelID = decodeHex(val);
117    CHECK(profileLevelID != NULL);
118    CHECK_EQ(profileLevelID->size(), 3u);
119
120    Vector<sp<ABuffer> > paramSets;
121
122    size_t numSeqParameterSets = 0;
123    size_t totalSeqParameterSetSize = 0;
124    size_t numPicParameterSets = 0;
125    size_t totalPicParameterSetSize = 0;
126
127    if (!GetAttribute(params, "sprop-parameter-sets", &val)) {
128        return NULL;
129    }
130
131    size_t start = 0;
132    for (;;) {
133        ssize_t commaPos = val.find(",", start);
134        size_t end = (commaPos < 0) ? val.size() : commaPos;
135
136        AString nalString(val, start, end - start);
137        sp<ABuffer> nal = decodeBase64(nalString);
138        CHECK(nal != NULL);
139        CHECK_GT(nal->size(), 0u);
140        CHECK_LE(nal->size(), 65535u);
141
142        uint8_t nalType = nal->data()[0] & 0x1f;
143        if (numSeqParameterSets == 0) {
144            CHECK_EQ((unsigned)nalType, 7u);
145        } else if (numPicParameterSets > 0) {
146            CHECK_EQ((unsigned)nalType, 8u);
147        }
148        if (nalType == 7) {
149            ++numSeqParameterSets;
150            totalSeqParameterSetSize += nal->size();
151        } else  {
152            CHECK_EQ((unsigned)nalType, 8u);
153            ++numPicParameterSets;
154            totalPicParameterSetSize += nal->size();
155        }
156
157        paramSets.push(nal);
158
159        if (commaPos < 0) {
160            break;
161        }
162
163        start = commaPos + 1;
164    }
165
166    CHECK_LT(numSeqParameterSets, 32u);
167    CHECK_LE(numPicParameterSets, 255u);
168
169    size_t csdSize =
170        1 + 3 + 1 + 1
171        + 2 * numSeqParameterSets + totalSeqParameterSetSize
172        + 1 + 2 * numPicParameterSets + totalPicParameterSetSize;
173
174    sp<ABuffer> csd = new ABuffer(csdSize);
175    uint8_t *out = csd->data();
176
177    *out++ = 0x01;  // configurationVersion
178    memcpy(out, profileLevelID->data(), 3);
179    out += 3;
180    *out++ = (0x3f << 2) | 1;  // lengthSize == 2 bytes
181    *out++ = 0xe0 | numSeqParameterSets;
182
183    for (size_t i = 0; i < numSeqParameterSets; ++i) {
184        sp<ABuffer> nal = paramSets.editItemAt(i);
185
186        *out++ = nal->size() >> 8;
187        *out++ = nal->size() & 0xff;
188
189        memcpy(out, nal->data(), nal->size());
190
191        out += nal->size();
192
193        if (i == 0) {
194            FindAVCDimensions(nal, width, height);
195            LOGI("dimensions %dx%d", *width, *height);
196        }
197    }
198
199    *out++ = numPicParameterSets;
200
201    for (size_t i = 0; i < numPicParameterSets; ++i) {
202        sp<ABuffer> nal = paramSets.editItemAt(i + numSeqParameterSets);
203
204        *out++ = nal->size() >> 8;
205        *out++ = nal->size() & 0xff;
206
207        memcpy(out, nal->data(), nal->size());
208
209        out += nal->size();
210    }
211
212    // hexdump(csd->data(), csd->size());
213
214    return csd;
215}
216
217sp<ABuffer> MakeAACCodecSpecificData(const char *params) {
218    AString val;
219    CHECK(GetAttribute(params, "config", &val));
220
221    sp<ABuffer> config = decodeHex(val);
222    CHECK(config != NULL);
223    CHECK_GE(config->size(), 4u);
224
225    const uint8_t *data = config->data();
226    uint32_t x = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
227    x = (x >> 1) & 0xffff;
228
229    static const uint8_t kStaticESDS[] = {
230        0x03, 22,
231        0x00, 0x00,     // ES_ID
232        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
233
234        0x04, 17,
235        0x40,                       // Audio ISO/IEC 14496-3
236        0x00, 0x00, 0x00, 0x00,
237        0x00, 0x00, 0x00, 0x00,
238        0x00, 0x00, 0x00, 0x00,
239
240        0x05, 2,
241        // AudioSpecificInfo follows
242    };
243
244    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + 2);
245    memcpy(csd->data(), kStaticESDS, sizeof(kStaticESDS));
246    csd->data()[sizeof(kStaticESDS)] = (x >> 8) & 0xff;
247    csd->data()[sizeof(kStaticESDS) + 1] = x & 0xff;
248
249    // hexdump(csd->data(), csd->size());
250
251    return csd;
252}
253
254// From mpeg4-generic configuration data.
255sp<ABuffer> MakeAACCodecSpecificData2(const char *params) {
256    AString val;
257    unsigned long objectType;
258    if (GetAttribute(params, "objectType", &val)) {
259        const char *s = val.c_str();
260        char *end;
261        objectType = strtoul(s, &end, 10);
262        CHECK(end > s && *end == '\0');
263    } else {
264        objectType = 0x40;  // Audio ISO/IEC 14496-3
265    }
266
267    CHECK(GetAttribute(params, "config", &val));
268
269    sp<ABuffer> config = decodeHex(val);
270    CHECK(config != NULL);
271
272    // Make sure size fits into a single byte and doesn't have to
273    // be encoded.
274    CHECK_LT(20 + config->size(), 128u);
275
276    const uint8_t *data = config->data();
277
278    static const uint8_t kStaticESDS[] = {
279        0x03, 22,
280        0x00, 0x00,     // ES_ID
281        0x00,           // streamDependenceFlag, URL_Flag, OCRstreamFlag
282
283        0x04, 17,
284        0x40,                       // Audio ISO/IEC 14496-3
285        0x00, 0x00, 0x00, 0x00,
286        0x00, 0x00, 0x00, 0x00,
287        0x00, 0x00, 0x00, 0x00,
288
289        0x05, 2,
290        // AudioSpecificInfo follows
291    };
292
293    sp<ABuffer> csd = new ABuffer(sizeof(kStaticESDS) + config->size());
294    uint8_t *dst = csd->data();
295    *dst++ = 0x03;
296    *dst++ = 20 + config->size();
297    *dst++ = 0x00;  // ES_ID
298    *dst++ = 0x00;
299    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
300    *dst++ = 0x04;
301    *dst++ = 15 + config->size();
302    *dst++ = objectType;
303    for (int i = 0; i < 12; ++i) { *dst++ = 0x00; }
304    *dst++ = 0x05;
305    *dst++ = config->size();
306    memcpy(dst, config->data(), config->size());
307
308    // hexdump(csd->data(), csd->size());
309
310    return csd;
311}
312
313static size_t GetSizeWidth(size_t x) {
314    size_t n = 1;
315    while (x > 127) {
316        ++n;
317        x >>= 7;
318    }
319    return n;
320}
321
322static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
323    while (x > 127) {
324        *dst++ = (x & 0x7f) | 0x80;
325        x >>= 7;
326    }
327    *dst++ = x;
328    return dst;
329}
330
331static bool ExtractDimensionsFromVOLHeader(
332        const sp<ABuffer> &config, int32_t *width, int32_t *height) {
333    *width = 0;
334    *height = 0;
335
336    const uint8_t *ptr = config->data();
337    size_t offset = 0;
338    bool foundVOL = false;
339    while (offset + 3 < config->size()) {
340        if (memcmp("\x00\x00\x01", &ptr[offset], 3)
341                || (ptr[offset + 3] & 0xf0) != 0x20) {
342            ++offset;
343            continue;
344        }
345
346        foundVOL = true;
347        break;
348    }
349
350    if (!foundVOL) {
351        return false;
352    }
353
354    ABitReader br(&ptr[offset + 4], config->size() - offset - 4);
355    br.skipBits(1);  // random_accessible_vol
356    unsigned video_object_type_indication = br.getBits(8);
357
358    CHECK_NE(video_object_type_indication,
359             0x21u /* Fine Granularity Scalable */);
360
361    unsigned video_object_layer_verid;
362    unsigned video_object_layer_priority;
363    if (br.getBits(1)) {
364        video_object_layer_verid = br.getBits(4);
365        video_object_layer_priority = br.getBits(3);
366    }
367    unsigned aspect_ratio_info = br.getBits(4);
368    if (aspect_ratio_info == 0x0f /* extended PAR */) {
369        br.skipBits(8);  // par_width
370        br.skipBits(8);  // par_height
371    }
372    if (br.getBits(1)) {  // vol_control_parameters
373        br.skipBits(2);  // chroma_format
374        br.skipBits(1);  // low_delay
375        if (br.getBits(1)) {  // vbv_parameters
376            br.skipBits(15);  // first_half_bit_rate
377            CHECK(br.getBits(1));  // marker_bit
378            br.skipBits(15);  // latter_half_bit_rate
379            CHECK(br.getBits(1));  // marker_bit
380            br.skipBits(15);  // first_half_vbv_buffer_size
381            CHECK(br.getBits(1));  // marker_bit
382            br.skipBits(3);  // latter_half_vbv_buffer_size
383            br.skipBits(11);  // first_half_vbv_occupancy
384            CHECK(br.getBits(1));  // marker_bit
385            br.skipBits(15);  // latter_half_vbv_occupancy
386            CHECK(br.getBits(1));  // marker_bit
387        }
388    }
389    unsigned video_object_layer_shape = br.getBits(2);
390    CHECK_EQ(video_object_layer_shape, 0x00u /* rectangular */);
391
392    CHECK(br.getBits(1));  // marker_bit
393    unsigned vop_time_increment_resolution = br.getBits(16);
394    CHECK(br.getBits(1));  // marker_bit
395
396    if (br.getBits(1)) {  // fixed_vop_rate
397        // range [0..vop_time_increment_resolution)
398
399        // vop_time_increment_resolution
400        // 2 => 0..1, 1 bit
401        // 3 => 0..2, 2 bits
402        // 4 => 0..3, 2 bits
403        // 5 => 0..4, 3 bits
404        // ...
405
406        CHECK_GT(vop_time_increment_resolution, 0u);
407        --vop_time_increment_resolution;
408
409        unsigned numBits = 0;
410        while (vop_time_increment_resolution > 0) {
411            ++numBits;
412            vop_time_increment_resolution >>= 1;
413        }
414
415        br.skipBits(numBits);  // fixed_vop_time_increment
416    }
417
418    CHECK(br.getBits(1));  // marker_bit
419    unsigned video_object_layer_width = br.getBits(13);
420    CHECK(br.getBits(1));  // marker_bit
421    unsigned video_object_layer_height = br.getBits(13);
422    CHECK(br.getBits(1));  // marker_bit
423
424    unsigned interlaced = br.getBits(1);
425
426    *width = video_object_layer_width;
427    *height = video_object_layer_height;
428
429    LOGI("VOL dimensions = %dx%d", *width, *height);
430
431    return true;
432}
433
434sp<ABuffer> MakeMPEG4VideoCodecSpecificData(
435        const char *params, int32_t *width, int32_t *height) {
436    *width = 0;
437    *height = 0;
438
439    AString val;
440    CHECK(GetAttribute(params, "config", &val));
441
442    sp<ABuffer> config = decodeHex(val);
443    CHECK(config != NULL);
444
445    if (!ExtractDimensionsFromVOLHeader(config, width, height)) {
446        return NULL;
447    }
448
449    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
450    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
451    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
452
453    sp<ABuffer> csd = new ABuffer(len3);
454    uint8_t *dst = csd->data();
455    *dst++ = 0x03;
456    dst = EncodeSize(dst, len2 + 3);
457    *dst++ = 0x00;  // ES_ID
458    *dst++ = 0x00;
459    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
460
461    *dst++ = 0x04;
462    dst = EncodeSize(dst, len1 + 13);
463    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
464    for (size_t i = 0; i < 12; ++i) {
465        *dst++ = 0x00;
466    }
467
468    *dst++ = 0x05;
469    dst = EncodeSize(dst, config->size());
470    memcpy(dst, config->data(), config->size());
471    dst += config->size();
472
473    // hexdump(csd->data(), csd->size());
474
475    return csd;
476}
477
478static bool GetClockRate(const AString &desc, uint32_t *clockRate) {
479    ssize_t slashPos = desc.find("/");
480    if (slashPos < 0) {
481        return false;
482    }
483
484    const char *s = desc.c_str() + slashPos + 1;
485
486    char *end;
487    unsigned long x = strtoul(s, &end, 10);
488
489    if (end == s || (*end != '\0' && *end != '/')) {
490        return false;
491    }
492
493    *clockRate = x;
494
495    return true;
496}
497
498APacketSource::APacketSource(
499        const sp<ASessionDescription> &sessionDesc, size_t index)
500    : mInitCheck(NO_INIT),
501      mFormat(new MetaData),
502      mEOSResult(OK),
503      mIsAVC(false),
504      mScanForIDR(true),
505      mRTPTimeBase(0),
506      mNormalPlayTimeBaseUs(0),
507      mLastNormalPlayTimeUs(0) {
508    unsigned long PT;
509    AString desc;
510    AString params;
511    sessionDesc->getFormatType(index, &PT, &desc, &params);
512
513    CHECK(GetClockRate(desc, &mClockRate));
514
515    int64_t durationUs;
516    if (sessionDesc->getDurationUs(&durationUs)) {
517        mFormat->setInt64(kKeyDuration, durationUs);
518    } else {
519        mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
520    }
521
522    mInitCheck = OK;
523    if (!strncmp(desc.c_str(), "H264/", 5)) {
524        mIsAVC = true;
525
526        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
527
528        int32_t width, height;
529        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
530            width = -1;
531            height = -1;
532        }
533
534        int32_t encWidth, encHeight;
535        sp<ABuffer> codecSpecificData =
536            MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
537
538        if (codecSpecificData != NULL) {
539            if (width < 0) {
540                // If no explicit width/height given in the sdp, use the dimensions
541                // extracted from the first sequence parameter set.
542                width = encWidth;
543                height = encHeight;
544            }
545
546            mFormat->setData(
547                    kKeyAVCC, 0,
548                    codecSpecificData->data(), codecSpecificData->size());
549        } else if (width < 0) {
550            mInitCheck = ERROR_UNSUPPORTED;
551            return;
552        }
553
554        mFormat->setInt32(kKeyWidth, width);
555        mFormat->setInt32(kKeyHeight, height);
556    } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
557            || !strncmp(desc.c_str(), "H263-1998/", 10)) {
558        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
559
560        int32_t width, height;
561        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
562            mInitCheck = ERROR_UNSUPPORTED;
563            return;
564        }
565
566        mFormat->setInt32(kKeyWidth, width);
567        mFormat->setInt32(kKeyHeight, height);
568    } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
569        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
570
571        int32_t sampleRate, numChannels;
572        ASessionDescription::ParseFormatDesc(
573                desc.c_str(), &sampleRate, &numChannels);
574
575        mFormat->setInt32(kKeySampleRate, sampleRate);
576        mFormat->setInt32(kKeyChannelCount, numChannels);
577
578        sp<ABuffer> codecSpecificData =
579            MakeAACCodecSpecificData(params.c_str());
580
581        mFormat->setData(
582                kKeyESDS, 0,
583                codecSpecificData->data(), codecSpecificData->size());
584    } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
585        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
586
587        int32_t sampleRate, numChannels;
588        ASessionDescription::ParseFormatDesc(
589                desc.c_str(), &sampleRate, &numChannels);
590
591        mFormat->setInt32(kKeySampleRate, sampleRate);
592        mFormat->setInt32(kKeyChannelCount, numChannels);
593
594        if (sampleRate != 8000 || numChannels != 1) {
595            mInitCheck = ERROR_UNSUPPORTED;
596        }
597    } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
598        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
599
600        int32_t sampleRate, numChannels;
601        ASessionDescription::ParseFormatDesc(
602                desc.c_str(), &sampleRate, &numChannels);
603
604        mFormat->setInt32(kKeySampleRate, sampleRate);
605        mFormat->setInt32(kKeyChannelCount, numChannels);
606
607        if (sampleRate != 16000 || numChannels != 1) {
608            mInitCheck = ERROR_UNSUPPORTED;
609        }
610    } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
611        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
612
613        int32_t width, height;
614        if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
615            width = -1;
616            height = -1;
617        }
618
619        int32_t encWidth, encHeight;
620        sp<ABuffer> codecSpecificData =
621            MakeMPEG4VideoCodecSpecificData(
622                    params.c_str(), &encWidth, &encHeight);
623
624        if (codecSpecificData != NULL) {
625            mFormat->setData(
626                    kKeyESDS, 0,
627                    codecSpecificData->data(), codecSpecificData->size());
628
629            if (width < 0) {
630                width = encWidth;
631                height = encHeight;
632            }
633        } else if (width < 0) {
634            mInitCheck = ERROR_UNSUPPORTED;
635            return;
636        }
637
638        mFormat->setInt32(kKeyWidth, width);
639        mFormat->setInt32(kKeyHeight, height);
640    } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
641        AString val;
642        if (!GetAttribute(params.c_str(), "mode", &val)
643                || (strcasecmp(val.c_str(), "AAC-lbr")
644                    && strcasecmp(val.c_str(), "AAC-hbr"))) {
645            mInitCheck = ERROR_UNSUPPORTED;
646            return;
647        }
648
649        mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
650
651        int32_t sampleRate, numChannels;
652        ASessionDescription::ParseFormatDesc(
653                desc.c_str(), &sampleRate, &numChannels);
654
655        mFormat->setInt32(kKeySampleRate, sampleRate);
656        mFormat->setInt32(kKeyChannelCount, numChannels);
657
658        sp<ABuffer> codecSpecificData =
659            MakeAACCodecSpecificData2(params.c_str());
660
661        mFormat->setData(
662                kKeyESDS, 0,
663                codecSpecificData->data(), codecSpecificData->size());
664    } else {
665        mInitCheck = ERROR_UNSUPPORTED;
666    }
667}
668
669APacketSource::~APacketSource() {
670}
671
672status_t APacketSource::initCheck() const {
673    return mInitCheck;
674}
675
676status_t APacketSource::start(MetaData *params) {
677    return OK;
678}
679
680status_t APacketSource::stop() {
681    return OK;
682}
683
684sp<MetaData> APacketSource::getFormat() {
685    return mFormat;
686}
687
688status_t APacketSource::read(
689        MediaBuffer **out, const ReadOptions *) {
690    *out = NULL;
691
692    Mutex::Autolock autoLock(mLock);
693    while (mEOSResult == OK && mBuffers.empty()) {
694        mCondition.wait(mLock);
695    }
696
697    if (!mBuffers.empty()) {
698        const sp<ABuffer> buffer = *mBuffers.begin();
699
700        updateNormalPlayTime_l(buffer);
701
702        MediaBuffer *mediaBuffer = new MediaBuffer(buffer->size());
703
704        int64_t timeUs;
705        CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
706
707        mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
708
709        memcpy(mediaBuffer->data(), buffer->data(), buffer->size());
710        *out = mediaBuffer;
711
712        mBuffers.erase(mBuffers.begin());
713        return OK;
714    }
715
716    return mEOSResult;
717}
718
719void APacketSource::updateNormalPlayTime_l(const sp<ABuffer> &buffer) {
720    uint32_t rtpTime;
721    CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
722
723    mLastNormalPlayTimeUs =
724        (((double)rtpTime - (double)mRTPTimeBase) / mClockRate)
725            * 1000000ll
726            + mNormalPlayTimeBaseUs;
727}
728
729void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
730    int32_t damaged;
731    if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
732        LOGV("discarding damaged AU");
733        return;
734    }
735
736    if (mScanForIDR && mIsAVC) {
737        // This pretty piece of code ensures that the first access unit
738        // fed to the decoder after stream-start or seek is guaranteed to
739        // be an IDR frame. This is to workaround limitations of a certain
740        // hardware h.264 decoder that requires this to be the case.
741
742        if (!IsIDR(buffer)) {
743            LOGV("skipping AU while scanning for next IDR frame.");
744            return;
745        }
746
747        mScanForIDR = false;
748    }
749
750    Mutex::Autolock autoLock(mLock);
751    mBuffers.push_back(buffer);
752    mCondition.signal();
753}
754
755void APacketSource::signalEOS(status_t result) {
756    CHECK(result != OK);
757
758    Mutex::Autolock autoLock(mLock);
759    mEOSResult = result;
760    mCondition.signal();
761}
762
763void APacketSource::flushQueue() {
764    Mutex::Autolock autoLock(mLock);
765    mBuffers.clear();
766
767    mScanForIDR = true;
768}
769
770int64_t APacketSource::getNormalPlayTimeUs() {
771    Mutex::Autolock autoLock(mLock);
772    return mLastNormalPlayTimeUs;
773}
774
775void APacketSource::setNormalPlayTimeMapping(
776        uint32_t rtpTime, int64_t normalPlayTimeUs) {
777    Mutex::Autolock autoLock(mLock);
778
779    mRTPTimeBase = rtpTime;
780    mNormalPlayTimeBaseUs = normalPlayTimeUs;
781}
782
783int64_t APacketSource::getQueueDurationUs(bool *eos) {
784    Mutex::Autolock autoLock(mLock);
785
786    *eos = (mEOSResult != OK);
787
788    if (mBuffers.size() < 2) {
789        return 0;
790    }
791
792    const sp<ABuffer> first = *mBuffers.begin();
793    const sp<ABuffer> last = *--mBuffers.end();
794
795    int64_t firstTimeUs;
796    CHECK(first->meta()->findInt64("timeUs", &firstTimeUs));
797
798    int64_t lastTimeUs;
799    CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
800
801    if (lastTimeUs < firstTimeUs) {
802        LOGE("Huh? Time moving backwards? %lld > %lld",
803             firstTimeUs, lastTimeUs);
804
805        return 0;
806    }
807
808    return lastTimeUs - firstTimeUs;
809}
810
811}  // namespace android
812