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