Home | History | Annotate | Download | only in rtsp
      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 
     42 namespace android {
     43 
     44 static 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 
     72 static 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 
    107 static 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 
    218 sp<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.
    256 sp<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 
    314 static 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 
    323 static 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 
    332 static 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 
    359 static 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     LOGI("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 
    405 static bool GetClockRate(const AString &desc, uint32_t *clockRate) {
    406     ssize_t slashPos = desc.find("/");
    407     if (slashPos < 0) {
    408         return false;
    409     }
    410 
    411     const char *s = desc.c_str() + slashPos + 1;
    412 
    413     char *end;
    414     unsigned long x = strtoul(s, &end, 10);
    415 
    416     if (end == s || (*end != '\0' && *end != '/')) {
    417         return false;
    418     }
    419 
    420     *clockRate = x;
    421 
    422     return true;
    423 }
    424 
    425 APacketSource::APacketSource(
    426         const sp<ASessionDescription> &sessionDesc, size_t index)
    427     : mInitCheck(NO_INIT),
    428       mFormat(new MetaData),
    429       mEOSResult(OK),
    430       mIsAVC(false),
    431       mScanForIDR(true),
    432       mRTPTimeBase(0),
    433       mNormalPlayTimeBaseUs(0),
    434       mLastNormalPlayTimeUs(0) {
    435     unsigned long PT;
    436     AString desc;
    437     AString params;
    438     sessionDesc->getFormatType(index, &PT, &desc, &params);
    439 
    440     CHECK(GetClockRate(desc, &mClockRate));
    441 
    442     int64_t durationUs;
    443     if (sessionDesc->getDurationUs(&durationUs)) {
    444         mFormat->setInt64(kKeyDuration, durationUs);
    445     } else {
    446         mFormat->setInt64(kKeyDuration, 60 * 60 * 1000000ll);
    447     }
    448 
    449     mInitCheck = OK;
    450     if (!strncmp(desc.c_str(), "H264/", 5)) {
    451         mIsAVC = true;
    452 
    453         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC);
    454 
    455         int32_t width, height;
    456         if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
    457             width = -1;
    458             height = -1;
    459         }
    460 
    461         int32_t encWidth, encHeight;
    462         sp<ABuffer> codecSpecificData =
    463             MakeAVCCodecSpecificData(params.c_str(), &encWidth, &encHeight);
    464 
    465         if (codecSpecificData != NULL) {
    466             if (width < 0) {
    467                 // If no explicit width/height given in the sdp, use the dimensions
    468                 // extracted from the first sequence parameter set.
    469                 width = encWidth;
    470                 height = encHeight;
    471             }
    472 
    473             mFormat->setData(
    474                     kKeyAVCC, 0,
    475                     codecSpecificData->data(), codecSpecificData->size());
    476         } else if (width < 0) {
    477             mInitCheck = ERROR_UNSUPPORTED;
    478             return;
    479         }
    480 
    481         mFormat->setInt32(kKeyWidth, width);
    482         mFormat->setInt32(kKeyHeight, height);
    483     } else if (!strncmp(desc.c_str(), "H263-2000/", 10)
    484             || !strncmp(desc.c_str(), "H263-1998/", 10)) {
    485         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263);
    486 
    487         int32_t width, height;
    488         if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
    489             mInitCheck = ERROR_UNSUPPORTED;
    490             return;
    491         }
    492 
    493         mFormat->setInt32(kKeyWidth, width);
    494         mFormat->setInt32(kKeyHeight, height);
    495     } else if (!strncmp(desc.c_str(), "MP4A-LATM/", 10)) {
    496         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    497 
    498         int32_t sampleRate, numChannels;
    499         ASessionDescription::ParseFormatDesc(
    500                 desc.c_str(), &sampleRate, &numChannels);
    501 
    502         mFormat->setInt32(kKeySampleRate, sampleRate);
    503         mFormat->setInt32(kKeyChannelCount, numChannels);
    504 
    505         sp<ABuffer> codecSpecificData =
    506             MakeAACCodecSpecificData(params.c_str());
    507 
    508         mFormat->setData(
    509                 kKeyESDS, 0,
    510                 codecSpecificData->data(), codecSpecificData->size());
    511     } else if (!strncmp(desc.c_str(), "AMR/", 4)) {
    512         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_NB);
    513 
    514         int32_t sampleRate, numChannels;
    515         ASessionDescription::ParseFormatDesc(
    516                 desc.c_str(), &sampleRate, &numChannels);
    517 
    518         mFormat->setInt32(kKeySampleRate, sampleRate);
    519         mFormat->setInt32(kKeyChannelCount, numChannels);
    520 
    521         if (sampleRate != 8000 || numChannels != 1) {
    522             mInitCheck = ERROR_UNSUPPORTED;
    523         }
    524     } else if (!strncmp(desc.c_str(), "AMR-WB/", 7)) {
    525         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AMR_WB);
    526 
    527         int32_t sampleRate, numChannels;
    528         ASessionDescription::ParseFormatDesc(
    529                 desc.c_str(), &sampleRate, &numChannels);
    530 
    531         mFormat->setInt32(kKeySampleRate, sampleRate);
    532         mFormat->setInt32(kKeyChannelCount, numChannels);
    533 
    534         if (sampleRate != 16000 || numChannels != 1) {
    535             mInitCheck = ERROR_UNSUPPORTED;
    536         }
    537     } else if (!strncmp(desc.c_str(), "MP4V-ES/", 8)) {
    538         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
    539 
    540         int32_t width, height;
    541         if (!sessionDesc->getDimensions(index, PT, &width, &height)) {
    542             width = -1;
    543             height = -1;
    544         }
    545 
    546         int32_t encWidth, encHeight;
    547         sp<ABuffer> codecSpecificData =
    548             MakeMPEG4VideoCodecSpecificData(
    549                     params.c_str(), &encWidth, &encHeight);
    550 
    551         if (codecSpecificData != NULL) {
    552             mFormat->setData(
    553                     kKeyESDS, 0,
    554                     codecSpecificData->data(), codecSpecificData->size());
    555 
    556             if (width < 0) {
    557                 width = encWidth;
    558                 height = encHeight;
    559             }
    560         } else if (width < 0) {
    561             mInitCheck = ERROR_UNSUPPORTED;
    562             return;
    563         }
    564 
    565         mFormat->setInt32(kKeyWidth, width);
    566         mFormat->setInt32(kKeyHeight, height);
    567     } else if (!strncasecmp(desc.c_str(), "mpeg4-generic/", 14)) {
    568         AString val;
    569         if (!GetAttribute(params.c_str(), "mode", &val)
    570                 || (strcasecmp(val.c_str(), "AAC-lbr")
    571                     && strcasecmp(val.c_str(), "AAC-hbr"))) {
    572             mInitCheck = ERROR_UNSUPPORTED;
    573             return;
    574         }
    575 
    576         mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_AAC);
    577 
    578         int32_t sampleRate, numChannels;
    579         ASessionDescription::ParseFormatDesc(
    580                 desc.c_str(), &sampleRate, &numChannels);
    581 
    582         mFormat->setInt32(kKeySampleRate, sampleRate);
    583         mFormat->setInt32(kKeyChannelCount, numChannels);
    584 
    585         sp<ABuffer> codecSpecificData =
    586             MakeAACCodecSpecificData2(params.c_str());
    587 
    588         mFormat->setData(
    589                 kKeyESDS, 0,
    590                 codecSpecificData->data(), codecSpecificData->size());
    591     } else if (ARawAudioAssembler::Supports(desc.c_str())) {
    592         ARawAudioAssembler::MakeFormat(desc.c_str(), mFormat);
    593     } else {
    594         mInitCheck = ERROR_UNSUPPORTED;
    595     }
    596 }
    597 
    598 APacketSource::~APacketSource() {
    599 }
    600 
    601 status_t APacketSource::initCheck() const {
    602     return mInitCheck;
    603 }
    604 
    605 status_t APacketSource::start(MetaData *params) {
    606     return OK;
    607 }
    608 
    609 status_t APacketSource::stop() {
    610     return OK;
    611 }
    612 
    613 sp<MetaData> APacketSource::getFormat() {
    614     return mFormat;
    615 }
    616 
    617 status_t APacketSource::read(
    618         MediaBuffer **out, const ReadOptions *) {
    619     *out = NULL;
    620 
    621     Mutex::Autolock autoLock(mLock);
    622     while (mEOSResult == OK && mBuffers.empty()) {
    623         mCondition.wait(mLock);
    624     }
    625 
    626     if (!mBuffers.empty()) {
    627         const sp<ABuffer> buffer = *mBuffers.begin();
    628 
    629         updateNormalPlayTime_l(buffer);
    630 
    631         int64_t timeUs;
    632         CHECK(buffer->meta()->findInt64("timeUs", &timeUs));
    633 
    634         MediaBuffer *mediaBuffer = new MediaBuffer(buffer);
    635         mediaBuffer->meta_data()->setInt64(kKeyTime, timeUs);
    636 
    637         *out = mediaBuffer;
    638 
    639         mBuffers.erase(mBuffers.begin());
    640         return OK;
    641     }
    642 
    643     return mEOSResult;
    644 }
    645 
    646 void APacketSource::updateNormalPlayTime_l(const sp<ABuffer> &buffer) {
    647     uint32_t rtpTime;
    648     CHECK(buffer->meta()->findInt32("rtp-time", (int32_t *)&rtpTime));
    649 
    650     mLastNormalPlayTimeUs =
    651         (((double)rtpTime - (double)mRTPTimeBase) / mClockRate)
    652             * 1000000ll
    653             + mNormalPlayTimeBaseUs;
    654 }
    655 
    656 void APacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
    657     int32_t damaged;
    658     if (buffer->meta()->findInt32("damaged", &damaged) && damaged) {
    659         LOGV("discarding damaged AU");
    660         return;
    661     }
    662 
    663     if (mScanForIDR && mIsAVC) {
    664         // This pretty piece of code ensures that the first access unit
    665         // fed to the decoder after stream-start or seek is guaranteed to
    666         // be an IDR frame. This is to workaround limitations of a certain
    667         // hardware h.264 decoder that requires this to be the case.
    668 
    669         if (!IsIDR(buffer)) {
    670             LOGV("skipping AU while scanning for next IDR frame.");
    671             return;
    672         }
    673 
    674         mScanForIDR = false;
    675     }
    676 
    677     Mutex::Autolock autoLock(mLock);
    678     mBuffers.push_back(buffer);
    679     mCondition.signal();
    680 }
    681 
    682 void APacketSource::signalEOS(status_t result) {
    683     CHECK(result != OK);
    684 
    685     Mutex::Autolock autoLock(mLock);
    686     mEOSResult = result;
    687     mCondition.signal();
    688 }
    689 
    690 void APacketSource::flushQueue() {
    691     Mutex::Autolock autoLock(mLock);
    692     mBuffers.clear();
    693 
    694     mScanForIDR = true;
    695 }
    696 
    697 int64_t APacketSource::getNormalPlayTimeUs() {
    698     Mutex::Autolock autoLock(mLock);
    699     return mLastNormalPlayTimeUs;
    700 }
    701 
    702 void APacketSource::setNormalPlayTimeMapping(
    703         uint32_t rtpTime, int64_t normalPlayTimeUs) {
    704     Mutex::Autolock autoLock(mLock);
    705 
    706     mRTPTimeBase = rtpTime;
    707     mNormalPlayTimeBaseUs = normalPlayTimeUs;
    708 }
    709 
    710 int64_t APacketSource::getQueueDurationUs(bool *eos) {
    711     Mutex::Autolock autoLock(mLock);
    712 
    713     *eos = (mEOSResult != OK);
    714 
    715     if (mBuffers.size() < 2) {
    716         return 0;
    717     }
    718 
    719     const sp<ABuffer> first = *mBuffers.begin();
    720     const sp<ABuffer> last = *--mBuffers.end();
    721 
    722     int64_t firstTimeUs;
    723     CHECK(first->meta()->findInt64("timeUs", &firstTimeUs));
    724 
    725     int64_t lastTimeUs;
    726     CHECK(last->meta()->findInt64("timeUs", &lastTimeUs));
    727 
    728     if (lastTimeUs < firstTimeUs) {
    729         LOGE("Huh? Time moving backwards? %lld > %lld",
    730              firstTimeUs, lastTimeUs);
    731 
    732         return 0;
    733     }
    734 
    735     return lastTimeUs - firstTimeUs;
    736 }
    737 
    738 }  // namespace android
    739