Home | History | Annotate | Download | only in mpeg2ts
      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 "ESQueue"
     19 #include <media/stagefright/foundation/ADebug.h>
     20 
     21 #include "ESQueue.h"
     22 
     23 #include <media/stagefright/foundation/hexdump.h>
     24 #include <media/stagefright/foundation/ABitReader.h>
     25 #include <media/stagefright/foundation/ABuffer.h>
     26 #include <media/stagefright/foundation/AMessage.h>
     27 #include <media/stagefright/MediaErrors.h>
     28 #include <media/stagefright/MediaDefs.h>
     29 #include <media/stagefright/MetaData.h>
     30 #include <media/stagefright/Utils.h>
     31 
     32 #include "include/avc_utils.h"
     33 
     34 namespace android {
     35 
     36 ElementaryStreamQueue::ElementaryStreamQueue(Mode mode)
     37     : mMode(mode) {
     38 }
     39 
     40 sp<MetaData> ElementaryStreamQueue::getFormat() {
     41     return mFormat;
     42 }
     43 
     44 void ElementaryStreamQueue::clear(bool clearFormat) {
     45     if (mBuffer != NULL) {
     46         mBuffer->setRange(0, 0);
     47     }
     48 
     49     mRangeInfos.clear();
     50 
     51     if (clearFormat) {
     52         mFormat.clear();
     53     }
     54 }
     55 
     56 static bool IsSeeminglyValidADTSHeader(const uint8_t *ptr, size_t size) {
     57     if (size < 3) {
     58         // Not enough data to verify header.
     59         return false;
     60     }
     61 
     62     if (ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
     63         return false;
     64     }
     65 
     66     unsigned layer = (ptr[1] >> 1) & 3;
     67 
     68     if (layer != 0) {
     69         return false;
     70     }
     71 
     72     unsigned ID = (ptr[1] >> 3) & 1;
     73     unsigned profile_ObjectType = ptr[2] >> 6;
     74 
     75     if (ID == 1 && profile_ObjectType == 3) {
     76         // MPEG-2 profile 3 is reserved.
     77         return false;
     78     }
     79 
     80     return true;
     81 }
     82 
     83 static bool IsSeeminglyValidMPEGAudioHeader(const uint8_t *ptr, size_t size) {
     84     if (size < 3) {
     85         // Not enough data to verify header.
     86         return false;
     87     }
     88 
     89     if (ptr[0] != 0xff || (ptr[1] >> 5) != 0x07) {
     90         return false;
     91     }
     92 
     93     unsigned ID = (ptr[1] >> 3) & 3;
     94 
     95     if (ID == 1) {
     96         return false;  // reserved
     97     }
     98 
     99     unsigned layer = (ptr[1] >> 1) & 3;
    100 
    101     if (layer == 0) {
    102         return false;  // reserved
    103     }
    104 
    105     unsigned bitrateIndex = (ptr[2] >> 4);
    106 
    107     if (bitrateIndex == 0x0f) {
    108         return false;  // reserved
    109     }
    110 
    111     unsigned samplingRateIndex = (ptr[2] >> 2) & 3;
    112 
    113     if (samplingRateIndex == 3) {
    114         return false;  // reserved
    115     }
    116 
    117     return true;
    118 }
    119 
    120 status_t ElementaryStreamQueue::appendData(
    121         const void *data, size_t size, int64_t timeUs) {
    122     if (mBuffer == NULL || mBuffer->size() == 0) {
    123         switch (mMode) {
    124             case H264:
    125             case MPEG_VIDEO:
    126             {
    127 #if 0
    128                 if (size < 4 || memcmp("\x00\x00\x00\x01", data, 4)) {
    129                     return ERROR_MALFORMED;
    130                 }
    131 #else
    132                 uint8_t *ptr = (uint8_t *)data;
    133 
    134                 ssize_t startOffset = -1;
    135                 for (size_t i = 0; i + 3 < size; ++i) {
    136                     if (!memcmp("\x00\x00\x00\x01", &ptr[i], 4)) {
    137                         startOffset = i;
    138                         break;
    139                     }
    140                 }
    141 
    142                 if (startOffset < 0) {
    143                     return ERROR_MALFORMED;
    144                 }
    145 
    146                 if (startOffset > 0) {
    147                     ALOGI("found something resembling an H.264/MPEG syncword at "
    148                          "offset %ld",
    149                          startOffset);
    150                 }
    151 
    152                 data = &ptr[startOffset];
    153                 size -= startOffset;
    154 #endif
    155                 break;
    156             }
    157 
    158             case MPEG4_VIDEO:
    159             {
    160 #if 0
    161                 if (size < 3 || memcmp("\x00\x00\x01", data, 3)) {
    162                     return ERROR_MALFORMED;
    163                 }
    164 #else
    165                 uint8_t *ptr = (uint8_t *)data;
    166 
    167                 ssize_t startOffset = -1;
    168                 for (size_t i = 0; i + 2 < size; ++i) {
    169                     if (!memcmp("\x00\x00\x01", &ptr[i], 3)) {
    170                         startOffset = i;
    171                         break;
    172                     }
    173                 }
    174 
    175                 if (startOffset < 0) {
    176                     return ERROR_MALFORMED;
    177                 }
    178 
    179                 if (startOffset > 0) {
    180                     ALOGI("found something resembling an H.264/MPEG syncword at "
    181                          "offset %ld",
    182                          startOffset);
    183                 }
    184 
    185                 data = &ptr[startOffset];
    186                 size -= startOffset;
    187 #endif
    188                 break;
    189             }
    190 
    191             case AAC:
    192             {
    193                 uint8_t *ptr = (uint8_t *)data;
    194 
    195 #if 0
    196                 if (size < 2 || ptr[0] != 0xff || (ptr[1] >> 4) != 0x0f) {
    197                     return ERROR_MALFORMED;
    198                 }
    199 #else
    200                 ssize_t startOffset = -1;
    201                 for (size_t i = 0; i < size; ++i) {
    202                     if (IsSeeminglyValidADTSHeader(&ptr[i], size - i)) {
    203                         startOffset = i;
    204                         break;
    205                     }
    206                 }
    207 
    208                 if (startOffset < 0) {
    209                     return ERROR_MALFORMED;
    210                 }
    211 
    212                 if (startOffset > 0) {
    213                     ALOGI("found something resembling an AAC syncword at offset %ld",
    214                          startOffset);
    215                 }
    216 
    217                 data = &ptr[startOffset];
    218                 size -= startOffset;
    219 #endif
    220                 break;
    221             }
    222 
    223             case MPEG_AUDIO:
    224             {
    225                 uint8_t *ptr = (uint8_t *)data;
    226 
    227                 ssize_t startOffset = -1;
    228                 for (size_t i = 0; i < size; ++i) {
    229                     if (IsSeeminglyValidMPEGAudioHeader(&ptr[i], size - i)) {
    230                         startOffset = i;
    231                         break;
    232                     }
    233                 }
    234 
    235                 if (startOffset < 0) {
    236                     return ERROR_MALFORMED;
    237                 }
    238 
    239                 if (startOffset > 0) {
    240                     ALOGI("found something resembling an MPEG audio "
    241                          "syncword at offset %ld",
    242                          startOffset);
    243                 }
    244 
    245                 data = &ptr[startOffset];
    246                 size -= startOffset;
    247                 break;
    248             }
    249 
    250             default:
    251                 TRESPASS();
    252                 break;
    253         }
    254     }
    255 
    256     size_t neededSize = (mBuffer == NULL ? 0 : mBuffer->size()) + size;
    257     if (mBuffer == NULL || neededSize > mBuffer->capacity()) {
    258         neededSize = (neededSize + 65535) & ~65535;
    259 
    260         ALOGV("resizing buffer to size %d", neededSize);
    261 
    262         sp<ABuffer> buffer = new ABuffer(neededSize);
    263         if (mBuffer != NULL) {
    264             memcpy(buffer->data(), mBuffer->data(), mBuffer->size());
    265             buffer->setRange(0, mBuffer->size());
    266         } else {
    267             buffer->setRange(0, 0);
    268         }
    269 
    270         mBuffer = buffer;
    271     }
    272 
    273     memcpy(mBuffer->data() + mBuffer->size(), data, size);
    274     mBuffer->setRange(0, mBuffer->size() + size);
    275 
    276     RangeInfo info;
    277     info.mLength = size;
    278     info.mTimestampUs = timeUs;
    279     mRangeInfos.push_back(info);
    280 
    281 #if 0
    282     if (mMode == AAC) {
    283         ALOGI("size = %d, timeUs = %.2f secs", size, timeUs / 1E6);
    284         hexdump(data, size);
    285     }
    286 #endif
    287 
    288     return OK;
    289 }
    290 
    291 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnit() {
    292     switch (mMode) {
    293         case H264:
    294             return dequeueAccessUnitH264();
    295         case AAC:
    296             return dequeueAccessUnitAAC();
    297         case MPEG_VIDEO:
    298             return dequeueAccessUnitMPEGVideo();
    299         case MPEG4_VIDEO:
    300             return dequeueAccessUnitMPEG4Video();
    301         default:
    302             CHECK_EQ((unsigned)mMode, (unsigned)MPEG_AUDIO);
    303             return dequeueAccessUnitMPEGAudio();
    304     }
    305 }
    306 
    307 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
    308     int64_t timeUs;
    309 
    310     size_t offset = 0;
    311     while (offset + 7 <= mBuffer->size()) {
    312         ABitReader bits(mBuffer->data() + offset, mBuffer->size() - offset);
    313 
    314         // adts_fixed_header
    315 
    316         CHECK_EQ(bits.getBits(12), 0xfffu);
    317         bits.skipBits(3);  // ID, layer
    318         bool protection_absent = bits.getBits(1) != 0;
    319 
    320         if (mFormat == NULL) {
    321             unsigned profile = bits.getBits(2);
    322             CHECK_NE(profile, 3u);
    323             unsigned sampling_freq_index = bits.getBits(4);
    324             bits.getBits(1);  // private_bit
    325             unsigned channel_configuration = bits.getBits(3);
    326             CHECK_NE(channel_configuration, 0u);
    327             bits.skipBits(2);  // original_copy, home
    328 
    329             mFormat = MakeAACCodecSpecificData(
    330                     profile, sampling_freq_index, channel_configuration);
    331 
    332             mFormat->setInt32(kKeyIsADTS, true);
    333 
    334             int32_t sampleRate;
    335             int32_t numChannels;
    336             CHECK(mFormat->findInt32(kKeySampleRate, &sampleRate));
    337             CHECK(mFormat->findInt32(kKeyChannelCount, &numChannels));
    338 
    339             ALOGI("found AAC codec config (%d Hz, %d channels)",
    340                  sampleRate, numChannels);
    341         } else {
    342             // profile_ObjectType, sampling_frequency_index, private_bits,
    343             // channel_configuration, original_copy, home
    344             bits.skipBits(12);
    345         }
    346 
    347         // adts_variable_header
    348 
    349         // copyright_identification_bit, copyright_identification_start
    350         bits.skipBits(2);
    351 
    352         unsigned aac_frame_length = bits.getBits(13);
    353 
    354         bits.skipBits(11);  // adts_buffer_fullness
    355 
    356         unsigned number_of_raw_data_blocks_in_frame = bits.getBits(2);
    357 
    358         if (number_of_raw_data_blocks_in_frame != 0) {
    359             // To be implemented.
    360             TRESPASS();
    361         }
    362 
    363         if (offset + aac_frame_length > mBuffer->size()) {
    364             break;
    365         }
    366 
    367         size_t headerSize = protection_absent ? 7 : 9;
    368 
    369         int64_t tmpUs = fetchTimestamp(aac_frame_length);
    370         CHECK_GE(tmpUs, 0ll);
    371 
    372         if (offset == 0) {
    373             timeUs = tmpUs;
    374         }
    375 
    376         offset += aac_frame_length;
    377     }
    378 
    379     if (offset == 0) {
    380         return NULL;
    381     }
    382 
    383     sp<ABuffer> accessUnit = new ABuffer(offset);
    384     memcpy(accessUnit->data(), mBuffer->data(), offset);
    385 
    386     memmove(mBuffer->data(), mBuffer->data() + offset,
    387             mBuffer->size() - offset);
    388     mBuffer->setRange(0, mBuffer->size() - offset);
    389 
    390     accessUnit->meta()->setInt64("timeUs", timeUs);
    391 
    392     return accessUnit;
    393 }
    394 
    395 int64_t ElementaryStreamQueue::fetchTimestamp(size_t size) {
    396     int64_t timeUs = -1;
    397     bool first = true;
    398 
    399     while (size > 0) {
    400         CHECK(!mRangeInfos.empty());
    401 
    402         RangeInfo *info = &*mRangeInfos.begin();
    403 
    404         if (first) {
    405             timeUs = info->mTimestampUs;
    406             first = false;
    407         }
    408 
    409         if (info->mLength > size) {
    410             info->mLength -= size;
    411 
    412             if (first) {
    413                 info->mTimestampUs = -1;
    414             }
    415 
    416             size = 0;
    417         } else {
    418             size -= info->mLength;
    419 
    420             mRangeInfos.erase(mRangeInfos.begin());
    421             info = NULL;
    422         }
    423     }
    424 
    425     if (timeUs == 0ll) {
    426         ALOGV("Returning 0 timestamp");
    427     }
    428 
    429     return timeUs;
    430 }
    431 
    432 struct NALPosition {
    433     size_t nalOffset;
    434     size_t nalSize;
    435 };
    436 
    437 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitH264() {
    438     const uint8_t *data = mBuffer->data();
    439     size_t size = mBuffer->size();
    440 
    441     Vector<NALPosition> nals;
    442 
    443     size_t totalSize = 0;
    444 
    445     status_t err;
    446     const uint8_t *nalStart;
    447     size_t nalSize;
    448     bool foundSlice = false;
    449     while ((err = getNextNALUnit(&data, &size, &nalStart, &nalSize)) == OK) {
    450         CHECK_GT(nalSize, 0u);
    451 
    452         unsigned nalType = nalStart[0] & 0x1f;
    453         bool flush = false;
    454 
    455         if (nalType == 1 || nalType == 5) {
    456             if (foundSlice) {
    457                 ABitReader br(nalStart + 1, nalSize);
    458                 unsigned first_mb_in_slice = parseUE(&br);
    459 
    460                 if (first_mb_in_slice == 0) {
    461                     // This slice starts a new frame.
    462 
    463                     flush = true;
    464                 }
    465             }
    466 
    467             foundSlice = true;
    468         } else if ((nalType == 9 || nalType == 7) && foundSlice) {
    469             // Access unit delimiter and SPS will be associated with the
    470             // next frame.
    471 
    472             flush = true;
    473         }
    474 
    475         if (flush) {
    476             // The access unit will contain all nal units up to, but excluding
    477             // the current one, separated by 0x00 0x00 0x00 0x01 startcodes.
    478 
    479             size_t auSize = 4 * nals.size() + totalSize;
    480             sp<ABuffer> accessUnit = new ABuffer(auSize);
    481 
    482 #if !LOG_NDEBUG
    483             AString out;
    484 #endif
    485 
    486             size_t dstOffset = 0;
    487             for (size_t i = 0; i < nals.size(); ++i) {
    488                 const NALPosition &pos = nals.itemAt(i);
    489 
    490                 unsigned nalType = mBuffer->data()[pos.nalOffset] & 0x1f;
    491 
    492 #if !LOG_NDEBUG
    493                 char tmp[128];
    494                 sprintf(tmp, "0x%02x", nalType);
    495                 if (i > 0) {
    496                     out.append(", ");
    497                 }
    498                 out.append(tmp);
    499 #endif
    500 
    501                 memcpy(accessUnit->data() + dstOffset, "\x00\x00\x00\x01", 4);
    502 
    503                 memcpy(accessUnit->data() + dstOffset + 4,
    504                        mBuffer->data() + pos.nalOffset,
    505                        pos.nalSize);
    506 
    507                 dstOffset += pos.nalSize + 4;
    508             }
    509 
    510             ALOGV("accessUnit contains nal types %s", out.c_str());
    511 
    512             const NALPosition &pos = nals.itemAt(nals.size() - 1);
    513             size_t nextScan = pos.nalOffset + pos.nalSize;
    514 
    515             memmove(mBuffer->data(),
    516                     mBuffer->data() + nextScan,
    517                     mBuffer->size() - nextScan);
    518 
    519             mBuffer->setRange(0, mBuffer->size() - nextScan);
    520 
    521             int64_t timeUs = fetchTimestamp(nextScan);
    522             CHECK_GE(timeUs, 0ll);
    523 
    524             accessUnit->meta()->setInt64("timeUs", timeUs);
    525 
    526             if (mFormat == NULL) {
    527                 mFormat = MakeAVCCodecSpecificData(accessUnit);
    528             }
    529 
    530             return accessUnit;
    531         }
    532 
    533         NALPosition pos;
    534         pos.nalOffset = nalStart - mBuffer->data();
    535         pos.nalSize = nalSize;
    536 
    537         nals.push(pos);
    538 
    539         totalSize += nalSize;
    540     }
    541     CHECK_EQ(err, (status_t)-EAGAIN);
    542 
    543     return NULL;
    544 }
    545 
    546 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGAudio() {
    547     const uint8_t *data = mBuffer->data();
    548     size_t size = mBuffer->size();
    549 
    550     if (size < 4) {
    551         return NULL;
    552     }
    553 
    554     uint32_t header = U32_AT(data);
    555 
    556     size_t frameSize;
    557     int samplingRate, numChannels, bitrate, numSamples;
    558     CHECK(GetMPEGAudioFrameSize(
    559                 header, &frameSize, &samplingRate, &numChannels,
    560                 &bitrate, &numSamples));
    561 
    562     if (size < frameSize) {
    563         return NULL;
    564     }
    565 
    566     unsigned layer = 4 - ((header >> 17) & 3);
    567 
    568     sp<ABuffer> accessUnit = new ABuffer(frameSize);
    569     memcpy(accessUnit->data(), data, frameSize);
    570 
    571     memmove(mBuffer->data(),
    572             mBuffer->data() + frameSize,
    573             mBuffer->size() - frameSize);
    574 
    575     mBuffer->setRange(0, mBuffer->size() - frameSize);
    576 
    577     int64_t timeUs = fetchTimestamp(frameSize);
    578     CHECK_GE(timeUs, 0ll);
    579 
    580     accessUnit->meta()->setInt64("timeUs", timeUs);
    581 
    582     if (mFormat == NULL) {
    583         mFormat = new MetaData;
    584 
    585         switch (layer) {
    586             case 1:
    587                 mFormat->setCString(
    588                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_I);
    589                 break;
    590             case 2:
    591                 mFormat->setCString(
    592                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG_LAYER_II);
    593                 break;
    594             case 3:
    595                 mFormat->setCString(
    596                         kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
    597                 break;
    598             default:
    599                 TRESPASS();
    600         }
    601 
    602         mFormat->setInt32(kKeySampleRate, samplingRate);
    603         mFormat->setInt32(kKeyChannelCount, numChannels);
    604     }
    605 
    606     return accessUnit;
    607 }
    608 
    609 static void EncodeSize14(uint8_t **_ptr, size_t size) {
    610     CHECK_LE(size, 0x3fff);
    611 
    612     uint8_t *ptr = *_ptr;
    613 
    614     *ptr++ = 0x80 | (size >> 7);
    615     *ptr++ = size & 0x7f;
    616 
    617     *_ptr = ptr;
    618 }
    619 
    620 static sp<ABuffer> MakeMPEGVideoESDS(const sp<ABuffer> &csd) {
    621     sp<ABuffer> esds = new ABuffer(csd->size() + 25);
    622 
    623     uint8_t *ptr = esds->data();
    624     *ptr++ = 0x03;
    625     EncodeSize14(&ptr, 22 + csd->size());
    626 
    627     *ptr++ = 0x00;  // ES_ID
    628     *ptr++ = 0x00;
    629 
    630     *ptr++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
    631 
    632     *ptr++ = 0x04;
    633     EncodeSize14(&ptr, 16 + csd->size());
    634 
    635     *ptr++ = 0x40;  // Audio ISO/IEC 14496-3
    636 
    637     for (size_t i = 0; i < 12; ++i) {
    638         *ptr++ = 0x00;
    639     }
    640 
    641     *ptr++ = 0x05;
    642     EncodeSize14(&ptr, csd->size());
    643 
    644     memcpy(ptr, csd->data(), csd->size());
    645 
    646     return esds;
    647 }
    648 
    649 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEGVideo() {
    650     const uint8_t *data = mBuffer->data();
    651     size_t size = mBuffer->size();
    652 
    653     bool sawPictureStart = false;
    654     int pprevStartCode = -1;
    655     int prevStartCode = -1;
    656     int currentStartCode = -1;
    657 
    658     size_t offset = 0;
    659     while (offset + 3 < size) {
    660         if (memcmp(&data[offset], "\x00\x00\x01", 3)) {
    661             ++offset;
    662             continue;
    663         }
    664 
    665         pprevStartCode = prevStartCode;
    666         prevStartCode = currentStartCode;
    667         currentStartCode = data[offset + 3];
    668 
    669         if (currentStartCode == 0xb3 && mFormat == NULL) {
    670             memmove(mBuffer->data(), mBuffer->data() + offset, size - offset);
    671             size -= offset;
    672             (void)fetchTimestamp(offset);
    673             offset = 0;
    674             mBuffer->setRange(0, size);
    675         }
    676 
    677         if ((prevStartCode == 0xb3 && currentStartCode != 0xb5)
    678                 || (pprevStartCode == 0xb3 && prevStartCode == 0xb5)) {
    679             // seqHeader without/with extension
    680 
    681             if (mFormat == NULL) {
    682                 CHECK_GE(size, 7u);
    683 
    684                 unsigned width =
    685                     (data[4] << 4) | data[5] >> 4;
    686 
    687                 unsigned height =
    688                     ((data[5] & 0x0f) << 8) | data[6];
    689 
    690                 mFormat = new MetaData;
    691                 mFormat->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG2);
    692                 mFormat->setInt32(kKeyWidth, width);
    693                 mFormat->setInt32(kKeyHeight, height);
    694 
    695                 ALOGI("found MPEG2 video codec config (%d x %d)", width, height);
    696 
    697                 sp<ABuffer> csd = new ABuffer(offset);
    698                 memcpy(csd->data(), data, offset);
    699 
    700                 memmove(mBuffer->data(),
    701                         mBuffer->data() + offset,
    702                         mBuffer->size() - offset);
    703 
    704                 mBuffer->setRange(0, mBuffer->size() - offset);
    705                 size -= offset;
    706                 (void)fetchTimestamp(offset);
    707                 offset = 0;
    708 
    709                 // hexdump(csd->data(), csd->size());
    710 
    711                 sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
    712                 mFormat->setData(
    713                         kKeyESDS, kTypeESDS, esds->data(), esds->size());
    714 
    715                 return NULL;
    716             }
    717         }
    718 
    719         if (mFormat != NULL && currentStartCode == 0x00) {
    720             // Picture start
    721 
    722             if (!sawPictureStart) {
    723                 sawPictureStart = true;
    724             } else {
    725                 sp<ABuffer> accessUnit = new ABuffer(offset);
    726                 memcpy(accessUnit->data(), data, offset);
    727 
    728                 memmove(mBuffer->data(),
    729                         mBuffer->data() + offset,
    730                         mBuffer->size() - offset);
    731 
    732                 mBuffer->setRange(0, mBuffer->size() - offset);
    733 
    734                 int64_t timeUs = fetchTimestamp(offset);
    735                 CHECK_GE(timeUs, 0ll);
    736 
    737                 offset = 0;
    738 
    739                 accessUnit->meta()->setInt64("timeUs", timeUs);
    740 
    741                 ALOGV("returning MPEG video access unit at time %lld us",
    742                       timeUs);
    743 
    744                 // hexdump(accessUnit->data(), accessUnit->size());
    745 
    746                 return accessUnit;
    747             }
    748         }
    749 
    750         ++offset;
    751     }
    752 
    753     return NULL;
    754 }
    755 
    756 static ssize_t getNextChunkSize(
    757         const uint8_t *data, size_t size) {
    758     static const char kStartCode[] = "\x00\x00\x01";
    759 
    760     if (size < 3) {
    761         return -EAGAIN;
    762     }
    763 
    764     if (memcmp(kStartCode, data, 3)) {
    765         TRESPASS();
    766     }
    767 
    768     size_t offset = 3;
    769     while (offset + 2 < size) {
    770         if (!memcmp(&data[offset], kStartCode, 3)) {
    771             return offset;
    772         }
    773 
    774         ++offset;
    775     }
    776 
    777     return -EAGAIN;
    778 }
    779 
    780 sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitMPEG4Video() {
    781     uint8_t *data = mBuffer->data();
    782     size_t size = mBuffer->size();
    783 
    784     enum {
    785         SKIP_TO_VISUAL_OBJECT_SEQ_START,
    786         EXPECT_VISUAL_OBJECT_START,
    787         EXPECT_VO_START,
    788         EXPECT_VOL_START,
    789         WAIT_FOR_VOP_START,
    790         SKIP_TO_VOP_START,
    791 
    792     } state;
    793 
    794     if (mFormat == NULL) {
    795         state = SKIP_TO_VISUAL_OBJECT_SEQ_START;
    796     } else {
    797         state = SKIP_TO_VOP_START;
    798     }
    799 
    800     int32_t width = -1, height = -1;
    801 
    802     size_t offset = 0;
    803     ssize_t chunkSize;
    804     while ((chunkSize = getNextChunkSize(
    805                     &data[offset], size - offset)) > 0) {
    806         bool discard = false;
    807 
    808         unsigned chunkType = data[offset + 3];
    809 
    810         switch (state) {
    811             case SKIP_TO_VISUAL_OBJECT_SEQ_START:
    812             {
    813                 if (chunkType == 0xb0) {
    814                     // Discard anything before this marker.
    815 
    816                     state = EXPECT_VISUAL_OBJECT_START;
    817                 } else {
    818                     discard = true;
    819                 }
    820                 break;
    821             }
    822 
    823             case EXPECT_VISUAL_OBJECT_START:
    824             {
    825                 CHECK_EQ(chunkType, 0xb5);
    826                 state = EXPECT_VO_START;
    827                 break;
    828             }
    829 
    830             case EXPECT_VO_START:
    831             {
    832                 CHECK_LE(chunkType, 0x1f);
    833                 state = EXPECT_VOL_START;
    834                 break;
    835             }
    836 
    837             case EXPECT_VOL_START:
    838             {
    839                 CHECK((chunkType & 0xf0) == 0x20);
    840 
    841                 CHECK(ExtractDimensionsFromVOLHeader(
    842                             &data[offset], chunkSize,
    843                             &width, &height));
    844 
    845                 state = WAIT_FOR_VOP_START;
    846                 break;
    847             }
    848 
    849             case WAIT_FOR_VOP_START:
    850             {
    851                 if (chunkType == 0xb3 || chunkType == 0xb6) {
    852                     // group of VOP or VOP start.
    853 
    854                     mFormat = new MetaData;
    855                     mFormat->setCString(
    856                             kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4);
    857 
    858                     mFormat->setInt32(kKeyWidth, width);
    859                     mFormat->setInt32(kKeyHeight, height);
    860 
    861                     ALOGI("found MPEG4 video codec config (%d x %d)",
    862                          width, height);
    863 
    864                     sp<ABuffer> csd = new ABuffer(offset);
    865                     memcpy(csd->data(), data, offset);
    866 
    867                     // hexdump(csd->data(), csd->size());
    868 
    869                     sp<ABuffer> esds = MakeMPEGVideoESDS(csd);
    870                     mFormat->setData(
    871                             kKeyESDS, kTypeESDS,
    872                             esds->data(), esds->size());
    873 
    874                     discard = true;
    875                     state = SKIP_TO_VOP_START;
    876                 }
    877 
    878                 break;
    879             }
    880 
    881             case SKIP_TO_VOP_START:
    882             {
    883                 if (chunkType == 0xb6) {
    884                     offset += chunkSize;
    885 
    886                     sp<ABuffer> accessUnit = new ABuffer(offset);
    887                     memcpy(accessUnit->data(), data, offset);
    888 
    889                     memmove(data, &data[offset], size - offset);
    890                     size -= offset;
    891                     mBuffer->setRange(0, size);
    892 
    893                     int64_t timeUs = fetchTimestamp(offset);
    894                     CHECK_GE(timeUs, 0ll);
    895 
    896                     offset = 0;
    897 
    898                     accessUnit->meta()->setInt64("timeUs", timeUs);
    899 
    900                     ALOGV("returning MPEG4 video access unit at time %lld us",
    901                          timeUs);
    902 
    903                     // hexdump(accessUnit->data(), accessUnit->size());
    904 
    905                     return accessUnit;
    906                 } else if (chunkType != 0xb3) {
    907                     offset += chunkSize;
    908                     discard = true;
    909                 }
    910 
    911                 break;
    912             }
    913 
    914             default:
    915                 TRESPASS();
    916         }
    917 
    918         if (discard) {
    919             (void)fetchTimestamp(offset);
    920             memmove(data, &data[offset], size - offset);
    921             size -= offset;
    922             offset = 0;
    923             mBuffer->setRange(0, size);
    924         } else {
    925             offset += chunkSize;
    926         }
    927     }
    928 
    929     return NULL;
    930 }
    931 
    932 }  // namespace android
    933