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