MPEG4Extractor.cpp revision e46b7be812d68e49710b34048662cbf18e2a6550
1/*
2 * Copyright (C) 2009 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_TAG "MPEG4Extractor"
18#include <utils/Log.h>
19
20#include <arpa/inet.h>
21
22#undef NDEBUG
23#include <assert.h>
24
25#include <ctype.h>
26#include <stdint.h>
27#include <stdlib.h>
28#include <string.h>
29
30#include <media/stagefright/DataSource.h>
31#include <media/stagefright/MPEG4Extractor.h>
32#include <media/stagefright/MediaBuffer.h>
33#include <media/stagefright/MediaBufferGroup.h>
34#include <media/stagefright/MediaSource.h>
35#include <media/stagefright/MetaData.h>
36#include <media/stagefright/SampleTable.h>
37#include <media/stagefright/Utils.h>
38#include <utils/String8.h>
39
40namespace android {
41
42class MPEG4Source : public MediaSource {
43public:
44    // Caller retains ownership of both "dataSource" and "sampleTable".
45    MPEG4Source(const sp<MetaData> &format, DataSource *dataSource,
46                SampleTable *sampleTable);
47
48    virtual ~MPEG4Source();
49
50    virtual status_t start(MetaData *params = NULL);
51    virtual status_t stop();
52
53    virtual sp<MetaData> getFormat();
54
55    virtual status_t read(
56            MediaBuffer **buffer, const ReadOptions *options = NULL);
57
58private:
59    sp<MetaData> mFormat;
60    DataSource *mDataSource;
61    int32_t mTimescale;
62    SampleTable *mSampleTable;
63    uint32_t mCurrentSampleIndex;
64
65    bool mIsAVC;
66    bool mStarted;
67
68    MediaBufferGroup *mGroup;
69
70    MediaBuffer *mBuffer;
71    size_t mBufferOffset;
72    size_t mBufferSizeRemaining;
73
74    bool mNeedsNALFraming;
75
76    MPEG4Source(const MPEG4Source &);
77    MPEG4Source &operator=(const MPEG4Source &);
78};
79
80static void hexdump(const void *_data, size_t size) {
81    const uint8_t *data = (const uint8_t *)_data;
82    size_t offset = 0;
83    while (offset < size) {
84        printf("0x%04x  ", offset);
85
86        size_t n = size - offset;
87        if (n > 16) {
88            n = 16;
89        }
90
91        for (size_t i = 0; i < 16; ++i) {
92            if (i == 8) {
93                printf(" ");
94            }
95
96            if (offset + i < size) {
97                printf("%02x ", data[offset + i]);
98            } else {
99                printf("   ");
100            }
101        }
102
103        printf(" ");
104
105        for (size_t i = 0; i < n; ++i) {
106            if (isprint(data[offset + i])) {
107                printf("%c", data[offset + i]);
108            } else {
109                printf(".");
110            }
111        }
112
113        printf("\n");
114
115        offset += 16;
116    }
117}
118
119static const char *const FourCC2MIME(uint32_t fourcc) {
120    switch (fourcc) {
121        case FOURCC('m', 'p', '4', 'a'):
122            return "audio/mp4a-latm";
123
124        case FOURCC('s', 'a', 'm', 'r'):
125            return "audio/3gpp";
126
127        case FOURCC('m', 'p', '4', 'v'):
128            return "video/mp4v-es";
129
130        case FOURCC('s', '2', '6', '3'):
131            return "video/3gpp";
132
133        case FOURCC('a', 'v', 'c', '1'):
134            return "video/avc";
135
136        default:
137            assert(!"should not be here.");
138            return NULL;
139    }
140}
141
142MPEG4Extractor::MPEG4Extractor(DataSource *source)
143    : mDataSource(source),
144      mHaveMetadata(false),
145      mFirstTrack(NULL),
146      mLastTrack(NULL) {
147}
148
149MPEG4Extractor::~MPEG4Extractor() {
150    Track *track = mFirstTrack;
151    while (track) {
152        Track *next = track->next;
153
154        delete track->sampleTable;
155        track->sampleTable = NULL;
156
157        delete track;
158        track = next;
159    }
160    mFirstTrack = mLastTrack = NULL;
161
162    delete mDataSource;
163    mDataSource = NULL;
164}
165
166status_t MPEG4Extractor::countTracks(int *num_tracks) {
167    status_t err;
168    if ((err = readMetaData()) != OK) {
169        return err;
170    }
171
172    *num_tracks = 0;
173    Track *track = mFirstTrack;
174    while (track) {
175        ++*num_tracks;
176        track = track->next;
177    }
178
179    return OK;
180}
181
182sp<MetaData> MPEG4Extractor::getTrackMetaData(int index) {
183    if (index < 0) {
184        return NULL;
185    }
186
187    status_t err;
188    if ((err = readMetaData()) != OK) {
189        return NULL;
190    }
191
192    Track *track = mFirstTrack;
193    while (index > 0) {
194        if (track == NULL) {
195            return NULL;
196        }
197
198        track = track->next;
199        --index;
200    }
201
202    return track->meta;
203}
204
205status_t MPEG4Extractor::readMetaData() {
206    if (mHaveMetadata) {
207        return OK;
208    }
209
210    off_t offset = 0;
211    status_t err;
212    while ((err = parseChunk(&offset, 0)) == OK) {
213    }
214
215    if (mHaveMetadata) {
216        return OK;
217    }
218
219    return err;
220}
221
222static void MakeFourCCString(uint32_t x, char *s) {
223    s[0] = x >> 24;
224    s[1] = (x >> 16) & 0xff;
225    s[2] = (x >> 8) & 0xff;
226    s[3] = x & 0xff;
227    s[4] = '\0';
228}
229
230status_t MPEG4Extractor::parseChunk(off_t *offset, int depth) {
231    uint32_t hdr[2];
232    if (mDataSource->read_at(*offset, hdr, 8) < 8) {
233        return ERROR_IO;
234    }
235    uint64_t chunk_size = ntohl(hdr[0]);
236    uint32_t chunk_type = ntohl(hdr[1]);
237    off_t data_offset = *offset + 8;
238
239    if (chunk_size == 1) {
240        if (mDataSource->read_at(*offset + 8, &chunk_size, 8) < 8) {
241            return ERROR_IO;
242        }
243        chunk_size = ntoh64(chunk_size);
244        data_offset += 8;
245    }
246
247    char chunk[5];
248    MakeFourCCString(chunk_type, chunk);
249
250#if 0
251    static const char kWhitespace[] = "                                        ";
252    const char *indent = &kWhitespace[sizeof(kWhitespace) - 1 - 2 * depth];
253    printf("%sfound chunk '%s' of size %lld\n", indent, chunk, chunk_size);
254
255    char buffer[256];
256    if (chunk_size <= sizeof(buffer)) {
257        if (mDataSource->read_at(*offset, buffer, chunk_size) < chunk_size) {
258            return ERROR_IO;
259        }
260
261        hexdump(buffer, chunk_size);
262    }
263#endif
264
265    off_t chunk_data_size = *offset + chunk_size - data_offset;
266
267    switch(chunk_type) {
268        case FOURCC('m', 'o', 'o', 'v'):
269        case FOURCC('t', 'r', 'a', 'k'):
270        case FOURCC('m', 'd', 'i', 'a'):
271        case FOURCC('m', 'i', 'n', 'f'):
272        case FOURCC('d', 'i', 'n', 'f'):
273        case FOURCC('s', 't', 'b', 'l'):
274        case FOURCC('m', 'v', 'e', 'x'):
275        case FOURCC('m', 'o', 'o', 'f'):
276        case FOURCC('t', 'r', 'a', 'f'):
277        case FOURCC('m', 'f', 'r', 'a'):
278        case FOURCC('s', 'k', 'i' ,'p'):
279        {
280            off_t stop_offset = *offset + chunk_size;
281            *offset = data_offset;
282            while (*offset < stop_offset) {
283                status_t err = parseChunk(offset, depth + 1);
284                if (err != OK) {
285                    return err;
286                }
287            }
288            assert(*offset == stop_offset);
289
290            if (chunk_type == FOURCC('m', 'o', 'o', 'v')) {
291                mHaveMetadata = true;
292
293                return UNKNOWN_ERROR;  // Return a dummy error.
294            }
295            break;
296        }
297
298        case FOURCC('t', 'k', 'h', 'd'):
299        {
300            assert(chunk_data_size >= 4);
301
302            uint8_t version;
303            if (mDataSource->read_at(data_offset, &version, 1) < 1) {
304                return ERROR_IO;
305            }
306
307            uint64_t ctime, mtime, duration;
308            int32_t id;
309            uint32_t width, height;
310
311            if (version == 1) {
312                if (chunk_data_size != 36 + 60) {
313                    return ERROR_MALFORMED;
314                }
315
316                uint8_t buffer[36 + 60];
317                if (mDataSource->read_at(
318                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
319                    return ERROR_IO;
320                }
321
322                ctime = U64_AT(&buffer[4]);
323                mtime = U64_AT(&buffer[12]);
324                id = U32_AT(&buffer[20]);
325                duration = U64_AT(&buffer[28]);
326                width = U32_AT(&buffer[88]);
327                height = U32_AT(&buffer[92]);
328            } else if (version == 0) {
329                if (chunk_data_size != 24 + 60) {
330                    return ERROR_MALFORMED;
331                }
332
333                uint8_t buffer[24 + 60];
334                if (mDataSource->read_at(
335                            data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
336                    return ERROR_IO;
337                }
338                ctime = U32_AT(&buffer[4]);
339                mtime = U32_AT(&buffer[8]);
340                id = U32_AT(&buffer[12]);
341                duration = U32_AT(&buffer[20]);
342                width = U32_AT(&buffer[76]);
343                height = U32_AT(&buffer[80]);
344            }
345
346            Track *track = new Track;
347            track->next = NULL;
348            if (mLastTrack) {
349                mLastTrack->next = track;
350            } else {
351                mFirstTrack = track;
352            }
353            mLastTrack = track;
354
355            track->meta = new MetaData;
356            track->timescale = 0;
357            track->sampleTable = new SampleTable(mDataSource);
358            track->meta->setCString(kKeyMIMEType, "application/octet-stream");
359
360            *offset += chunk_size;
361            break;
362        }
363
364        case FOURCC('m', 'd', 'h', 'd'):
365        {
366            if (chunk_data_size < 4) {
367                return ERROR_MALFORMED;
368            }
369
370            uint8_t version;
371            if (mDataSource->read_at(
372                        data_offset, &version, sizeof(version))
373                    < (ssize_t)sizeof(version)) {
374                return ERROR_IO;
375            }
376
377            off_t timescale_offset;
378
379            if (version == 1) {
380                timescale_offset = data_offset + 4 + 16;
381            } else if (version == 0) {
382                timescale_offset = data_offset + 4 + 8;
383            } else {
384                return ERROR_IO;
385            }
386
387            uint32_t timescale;
388            if (mDataSource->read_at(
389                        timescale_offset, &timescale, sizeof(timescale))
390                    < (ssize_t)sizeof(timescale)) {
391                return ERROR_IO;
392            }
393
394            mLastTrack->timescale = ntohl(timescale);
395            mLastTrack->meta->setInt32(kKeyTimeScale, mLastTrack->timescale);
396
397            int64_t duration;
398            if (version == 1) {
399                if (mDataSource->read_at(
400                            timescale_offset + 4, &duration, sizeof(duration))
401                        < (ssize_t)sizeof(duration)) {
402                    return ERROR_IO;
403                }
404                duration = ntoh64(duration);
405            } else {
406                int32_t duration32;
407                if (mDataSource->read_at(
408                            timescale_offset + 4, &duration32, sizeof(duration32))
409                        < (ssize_t)sizeof(duration32)) {
410                    return ERROR_IO;
411                }
412                duration = ntohl(duration32);
413            }
414            mLastTrack->meta->setInt32(kKeyDuration, duration);
415
416            *offset += chunk_size;
417            break;
418        }
419
420        case FOURCC('h', 'd', 'l', 'r'):
421        {
422            if (chunk_data_size < 25) {
423                return ERROR_MALFORMED;
424            }
425
426            uint8_t buffer[24];
427            if (mDataSource->read_at(data_offset, buffer, 24) < 24) {
428                return ERROR_IO;
429            }
430
431            if (U32_AT(buffer) != 0) {
432                // Should be version 0, flags 0.
433                return ERROR_MALFORMED;
434            }
435
436            if (U32_AT(&buffer[4]) != 0) {
437                // pre_defined should be 0.
438                return ERROR_MALFORMED;
439            }
440
441            mHandlerType = U32_AT(&buffer[8]);
442            *offset += chunk_size;
443            break;
444        }
445
446        case FOURCC('s', 't', 's', 'd'):
447        {
448            if (chunk_data_size < 8) {
449                return ERROR_MALFORMED;
450            }
451
452            uint8_t buffer[8];
453            assert(chunk_data_size >= (off_t)sizeof(buffer));
454            if (mDataSource->read_at(
455                        data_offset, buffer, 8) < 8) {
456                return ERROR_IO;
457            }
458
459            if (U32_AT(buffer) != 0) {
460                // Should be version 0, flags 0.
461                return ERROR_MALFORMED;
462            }
463
464            uint32_t entry_count = U32_AT(&buffer[4]);
465
466            if (entry_count > 1) {
467                // For now we only support a single type of media per track.
468                return ERROR_UNSUPPORTED;
469            }
470
471            off_t stop_offset = *offset + chunk_size;
472            *offset = data_offset + 8;
473            for (uint32_t i = 0; i < entry_count; ++i) {
474                status_t err = parseChunk(offset, depth + 1);
475                if (err != OK) {
476                    return err;
477                }
478            }
479            assert(*offset == stop_offset);
480            break;
481        }
482
483        case FOURCC('m', 'p', '4', 'a'):
484        case FOURCC('s', 'a', 'm', 'r'):
485        {
486            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
487                return ERROR_MALFORMED;
488            }
489
490            uint8_t buffer[8 + 20];
491            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
492                // Basic AudioSampleEntry size.
493                return ERROR_MALFORMED;
494            }
495
496            if (mDataSource->read_at(
497                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
498                return ERROR_IO;
499            }
500
501            uint16_t data_ref_index = U16_AT(&buffer[6]);
502            uint16_t num_channels = U16_AT(&buffer[16]);
503
504            if (!strcasecmp("audio/3gpp", FourCC2MIME(chunk_type))) {
505                // AMR audio is always mono.
506                num_channels = 1;
507            }
508
509            uint16_t sample_size = U16_AT(&buffer[18]);
510            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
511
512            printf("*** coding='%s' %d channels, size %d, rate %d\n",
513                   chunk, num_channels, sample_size, sample_rate);
514
515            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
516            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
517            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
518
519            off_t stop_offset = *offset + chunk_size;
520            *offset = data_offset + sizeof(buffer);
521            while (*offset < stop_offset) {
522                status_t err = parseChunk(offset, depth + 1);
523                if (err != OK) {
524                    return err;
525                }
526            }
527            assert(*offset == stop_offset);
528            break;
529        }
530
531        case FOURCC('m', 'p', '4', 'v'):
532        case FOURCC('s', '2', '6', '3'):
533        case FOURCC('a', 'v', 'c', '1'):
534        {
535            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
536                return ERROR_MALFORMED;
537            }
538
539            uint8_t buffer[78];
540            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
541                // Basic VideoSampleEntry size.
542                return ERROR_MALFORMED;
543            }
544
545            if (mDataSource->read_at(
546                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
547                return ERROR_IO;
548            }
549
550            uint16_t data_ref_index = U16_AT(&buffer[6]);
551            uint16_t width = U16_AT(&buffer[6 + 18]);
552            uint16_t height = U16_AT(&buffer[6 + 20]);
553
554            printf("*** coding='%s' width=%d height=%d\n",
555                   chunk, width, height);
556
557            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
558            mLastTrack->meta->setInt32(kKeyWidth, width);
559            mLastTrack->meta->setInt32(kKeyHeight, height);
560
561            off_t stop_offset = *offset + chunk_size;
562            *offset = data_offset + sizeof(buffer);
563            while (*offset < stop_offset) {
564                status_t err = parseChunk(offset, depth + 1);
565                if (err != OK) {
566                    return err;
567                }
568            }
569            assert(*offset == stop_offset);
570            break;
571        }
572
573        case FOURCC('s', 't', 'c', 'o'):
574        case FOURCC('c', 'o', '6', '4'):
575        {
576            status_t err =
577                mLastTrack->sampleTable->setChunkOffsetParams(
578                        chunk_type, data_offset, chunk_data_size);
579
580            if (err != OK) {
581                return err;
582            }
583
584            *offset += chunk_size;
585            break;
586        }
587
588        case FOURCC('s', 't', 's', 'c'):
589        {
590            status_t err =
591                mLastTrack->sampleTable->setSampleToChunkParams(
592                        data_offset, chunk_data_size);
593
594            if (err != OK) {
595                return err;
596            }
597
598            *offset += chunk_size;
599            break;
600        }
601
602        case FOURCC('s', 't', 's', 'z'):
603        case FOURCC('s', 't', 'z', '2'):
604        {
605            status_t err =
606                mLastTrack->sampleTable->setSampleSizeParams(
607                        chunk_type, data_offset, chunk_data_size);
608
609            if (err != OK) {
610                return err;
611            }
612
613            *offset += chunk_size;
614            break;
615        }
616
617        case FOURCC('s', 't', 't', 's'):
618        {
619            status_t err =
620                mLastTrack->sampleTable->setTimeToSampleParams(
621                        data_offset, chunk_data_size);
622
623            if (err != OK) {
624                return err;
625            }
626
627            *offset += chunk_size;
628            break;
629        }
630
631        case FOURCC('s', 't', 's', 's'):
632        {
633            status_t err =
634                mLastTrack->sampleTable->setSyncSampleParams(
635                        data_offset, chunk_data_size);
636
637            if (err != OK) {
638                return err;
639            }
640
641            *offset += chunk_size;
642            break;
643        }
644
645        case FOURCC('e', 's', 'd', 's'):
646        {
647            if (chunk_data_size < 4) {
648                return ERROR_MALFORMED;
649            }
650
651            uint8_t buffer[256];
652            if (chunk_data_size > (off_t)sizeof(buffer)) {
653                return ERROR_BUFFER_TOO_SMALL;
654            }
655
656            if (mDataSource->read_at(
657                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
658                return ERROR_IO;
659            }
660
661            if (U32_AT(buffer) != 0) {
662                // Should be version 0, flags 0.
663                return ERROR_MALFORMED;
664            }
665
666            mLastTrack->meta->setData(
667                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
668
669            *offset += chunk_size;
670            break;
671        }
672
673        case FOURCC('a', 'v', 'c', 'C'):
674        {
675            char buffer[256];
676            if (chunk_data_size > (off_t)sizeof(buffer)) {
677                return ERROR_BUFFER_TOO_SMALL;
678            }
679
680            if (mDataSource->read_at(
681                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
682                return ERROR_IO;
683            }
684
685            mLastTrack->meta->setData(
686                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
687
688            *offset += chunk_size;
689            break;
690        }
691
692        default:
693        {
694            *offset += chunk_size;
695            break;
696        }
697    }
698
699    return OK;
700}
701
702status_t MPEG4Extractor::getTrack(int index, MediaSource **source) {
703    *source = NULL;
704
705    if (index < 0) {
706        return ERROR_OUT_OF_RANGE;
707    }
708
709    status_t err;
710    if ((err = readMetaData()) != OK) {
711        return err;
712    }
713
714    Track *track = mFirstTrack;
715    while (index > 0) {
716        if (track == NULL) {
717            return ERROR_OUT_OF_RANGE;
718        }
719
720        track = track->next;
721        --index;
722    }
723
724    *source = new MPEG4Source(
725            track->meta, mDataSource, track->sampleTable);
726
727    return OK;
728}
729
730////////////////////////////////////////////////////////////////////////////////
731
732MPEG4Source::MPEG4Source(
733        const sp<MetaData> &format,
734        DataSource *dataSource, SampleTable *sampleTable)
735    : mFormat(format),
736      mDataSource(dataSource),
737      mTimescale(0),
738      mSampleTable(sampleTable),
739      mCurrentSampleIndex(0),
740      mIsAVC(false),
741      mStarted(false),
742      mGroup(NULL),
743      mBuffer(NULL),
744      mBufferOffset(0),
745      mBufferSizeRemaining(0),
746      mNeedsNALFraming(false) {
747    const char *mime;
748    bool success = mFormat->findCString(kKeyMIMEType, &mime);
749    assert(success);
750
751    success = mFormat->findInt32(kKeyTimeScale, &mTimescale);
752    assert(success);
753
754    mIsAVC = !strcasecmp(mime, "video/avc");
755}
756
757MPEG4Source::~MPEG4Source() {
758    if (mStarted) {
759        stop();
760    }
761}
762
763status_t MPEG4Source::start(MetaData *params) {
764    assert(!mStarted);
765
766    int32_t val;
767    if (mIsAVC && params && params->findInt32(kKeyNeedsNALFraming, &val)
768        && val != 0) {
769        mNeedsNALFraming = true;
770    } else {
771        mNeedsNALFraming = false;
772    }
773
774    mGroup = new MediaBufferGroup;
775
776    size_t max_size;
777    status_t err = mSampleTable->getMaxSampleSize(&max_size);
778    assert(err == OK);
779
780    // Add padding for de-framing of AVC content just in case.
781    mGroup->add_buffer(new MediaBuffer(max_size + 2));
782
783    mStarted = true;
784
785    return OK;
786}
787
788status_t MPEG4Source::stop() {
789    assert(mStarted);
790
791    if (mBuffer != NULL) {
792        mBuffer->release();
793        mBuffer = NULL;
794    }
795
796    delete mGroup;
797    mGroup = NULL;
798
799    mStarted = false;
800    mCurrentSampleIndex = 0;
801
802    return OK;
803}
804
805sp<MetaData> MPEG4Source::getFormat() {
806    return mFormat;
807}
808
809status_t MPEG4Source::read(
810        MediaBuffer **out, const ReadOptions *options) {
811    assert(mStarted);
812
813    *out = NULL;
814
815    int64_t seekTimeUs;
816    if (options && options->getSeekTo(&seekTimeUs)) {
817        uint32_t sampleIndex;
818        status_t err = mSampleTable->findClosestSample(
819                seekTimeUs * mTimescale / 1000000,
820                &sampleIndex, SampleTable::kSyncSample_Flag);
821
822        if (err != OK) {
823            return err;
824        }
825
826        mCurrentSampleIndex = sampleIndex;
827        if (mBuffer != NULL) {
828            mBuffer->release();
829            mBuffer = NULL;
830        }
831
832        // fall through
833    }
834
835    if (mBuffer == NULL) {
836        off_t offset;
837        size_t size;
838        status_t err = mSampleTable->getSampleOffsetAndSize(
839                mCurrentSampleIndex, &offset, &size);
840
841        if (err != OK) {
842            return err;
843        }
844
845        uint32_t dts;
846        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
847
848        if (err != OK) {
849            return err;
850        }
851
852        err = mGroup->acquire_buffer(&mBuffer);
853        if (err != OK) {
854            assert(mBuffer == NULL);
855            return err;
856        }
857
858        assert(mBuffer->size() + 2 >= size);
859
860        ssize_t num_bytes_read =
861            mDataSource->read_at(offset, (uint8_t *)mBuffer->data() + 2, size);
862
863        if (num_bytes_read < (ssize_t)size) {
864            mBuffer->release();
865            mBuffer = NULL;
866
867            return err;
868        }
869
870        mBuffer->set_range(2, size);
871        mBuffer->meta_data()->clear();
872        mBuffer->meta_data()->setInt32(kKeyTimeUnits, dts);
873        mBuffer->meta_data()->setInt32(kKeyTimeScale, mTimescale);
874
875        ++mCurrentSampleIndex;
876
877        mBufferOffset = 2;
878        mBufferSizeRemaining = size;
879    }
880
881    if (!mIsAVC) {
882        *out = mBuffer;
883        mBuffer = NULL;
884
885        return OK;
886    }
887
888    uint8_t *data = (uint8_t *)mBuffer->data() + mBufferOffset;
889    assert(mBufferSizeRemaining >= 2);
890
891    size_t nal_length = (data[0] << 8) | data[1];
892    assert(mBufferSizeRemaining >= 2 + nal_length);
893
894    if (mNeedsNALFraming) {
895        // Insert marker.
896        data[-2] = data[-1] = data[0] = 0;
897        data[1] = 1;
898
899        mBuffer->set_range(mBufferOffset - 2, nal_length + 4);
900    } else {
901        mBuffer->set_range(mBufferOffset + 2, nal_length);
902    }
903
904    mBufferOffset += nal_length + 2;
905    mBufferSizeRemaining -= nal_length + 2;
906
907    if (mBufferSizeRemaining > 0) {
908        *out = mBuffer->clone();
909    } else {
910        *out = mBuffer;
911        mBuffer = NULL;
912    }
913
914    return OK;
915}
916
917bool SniffMPEG4(DataSource *source, String8 *mimeType, float *confidence) {
918    uint8_t header[8];
919
920    ssize_t n = source->read_at(4, header, sizeof(header));
921    if (n < (ssize_t)sizeof(header)) {
922        return false;
923    }
924
925    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
926        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) {
927        *mimeType = "video/mp4";
928        *confidence = 0.1;
929
930        return true;
931    }
932
933    return false;
934}
935
936}  // namespace android
937
938