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