MPEG4Extractor.cpp revision 89e69da4d86348409994c9dafbbb2634ccd7c196
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 "include/SampleTable.h"
21
22#include <arpa/inet.h>
23
24#include <ctype.h>
25#include <stdint.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <media/stagefright/DataSource.h>
30#include <media/stagefright/MPEG4Extractor.h>
31#include <media/stagefright/MediaBuffer.h>
32#include <media/stagefright/MediaBufferGroup.h>
33#include <media/stagefright/MediaDebug.h>
34#include <media/stagefright/MediaDefs.h>
35#include <media/stagefright/MediaSource.h>
36#include <media/stagefright/MetaData.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,
46                const sp<DataSource> &dataSource,
47                int32_t timeScale,
48                const sp<SampleTable> &sampleTable);
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
58protected:
59    virtual ~MPEG4Source();
60
61private:
62    sp<MetaData> mFormat;
63    sp<DataSource> mDataSource;
64    int32_t mTimescale;
65    sp<SampleTable> mSampleTable;
66    uint32_t mCurrentSampleIndex;
67
68    bool mIsAVC;
69    bool mStarted;
70
71    MediaBufferGroup *mGroup;
72
73    MediaBuffer *mBuffer;
74
75    bool mWantsNALFragments;
76
77    uint8_t *mSrcBuffer;
78
79    MPEG4Source(const MPEG4Source &);
80    MPEG4Source &operator=(const MPEG4Source &);
81};
82
83static void hexdump(const void *_data, size_t size) {
84    const uint8_t *data = (const uint8_t *)_data;
85    size_t offset = 0;
86    while (offset < size) {
87        printf("0x%04x  ", offset);
88
89        size_t n = size - offset;
90        if (n > 16) {
91            n = 16;
92        }
93
94        for (size_t i = 0; i < 16; ++i) {
95            if (i == 8) {
96                printf(" ");
97            }
98
99            if (offset + i < size) {
100                printf("%02x ", data[offset + i]);
101            } else {
102                printf("   ");
103            }
104        }
105
106        printf(" ");
107
108        for (size_t i = 0; i < n; ++i) {
109            if (isprint(data[offset + i])) {
110                printf("%c", data[offset + i]);
111            } else {
112                printf(".");
113            }
114        }
115
116        printf("\n");
117
118        offset += 16;
119    }
120}
121
122static const char *FourCC2MIME(uint32_t fourcc) {
123    switch (fourcc) {
124        case FOURCC('m', 'p', '4', 'a'):
125            return MEDIA_MIMETYPE_AUDIO_AAC;
126
127        case FOURCC('s', 'a', 'm', 'r'):
128            return MEDIA_MIMETYPE_AUDIO_AMR_NB;
129
130        case FOURCC('s', 'a', 'w', 'b'):
131            return MEDIA_MIMETYPE_AUDIO_AMR_WB;
132
133        case FOURCC('m', 'p', '4', 'v'):
134            return MEDIA_MIMETYPE_VIDEO_MPEG4;
135
136        case FOURCC('s', '2', '6', '3'):
137            return MEDIA_MIMETYPE_VIDEO_H263;
138
139        case FOURCC('a', 'v', 'c', '1'):
140            return MEDIA_MIMETYPE_VIDEO_AVC;
141
142        default:
143            CHECK(!"should not be here.");
144            return NULL;
145    }
146}
147
148MPEG4Extractor::MPEG4Extractor(const sp<DataSource> &source)
149    : mDataSource(source),
150      mHaveMetadata(false),
151      mFirstTrack(NULL),
152      mLastTrack(NULL) {
153}
154
155MPEG4Extractor::~MPEG4Extractor() {
156    Track *track = mFirstTrack;
157    while (track) {
158        Track *next = track->next;
159
160        delete track;
161        track = next;
162    }
163    mFirstTrack = mLastTrack = NULL;
164}
165
166size_t MPEG4Extractor::countTracks() {
167    status_t err;
168    if ((err = readMetaData()) != OK) {
169        return 0;
170    }
171
172    size_t n = 0;
173    Track *track = mFirstTrack;
174    while (track) {
175        ++n;
176        track = track->next;
177    }
178
179    return n;
180}
181
182sp<MetaData> MPEG4Extractor::getTrackMetaData(size_t index) {
183    status_t err;
184    if ((err = readMetaData()) != OK) {
185        return NULL;
186    }
187
188    Track *track = mFirstTrack;
189    while (index > 0) {
190        if (track == NULL) {
191            return NULL;
192        }
193
194        track = track->next;
195        --index;
196    }
197
198    if (track == NULL) {
199        return NULL;
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            CHECK_EQ(*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            CHECK(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
396            int64_t duration;
397            if (version == 1) {
398                if (mDataSource->read_at(
399                            timescale_offset + 4, &duration, sizeof(duration))
400                        < (ssize_t)sizeof(duration)) {
401                    return ERROR_IO;
402                }
403                duration = ntoh64(duration);
404            } else {
405                int32_t duration32;
406                if (mDataSource->read_at(
407                            timescale_offset + 4, &duration32, sizeof(duration32))
408                        < (ssize_t)sizeof(duration32)) {
409                    return ERROR_IO;
410                }
411                duration = ntohl(duration32);
412            }
413            mLastTrack->meta->setInt64(
414                    kKeyDuration, (duration * 1000000) / mLastTrack->timescale);
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            CHECK(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            CHECK_EQ(*offset, stop_offset);
480            break;
481        }
482
483        case FOURCC('m', 'p', '4', 'a'):
484        case FOURCC('s', 'a', 'm', 'r'):
485        case FOURCC('s', 'a', 'w', 'b'):
486        {
487            if (mHandlerType != FOURCC('s', 'o', 'u', 'n')) {
488                return ERROR_MALFORMED;
489            }
490
491            uint8_t buffer[8 + 20];
492            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
493                // Basic AudioSampleEntry size.
494                return ERROR_MALFORMED;
495            }
496
497            if (mDataSource->read_at(
498                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
499                return ERROR_IO;
500            }
501
502            uint16_t data_ref_index = U16_AT(&buffer[6]);
503            uint16_t num_channels = U16_AT(&buffer[16]);
504
505            if (!strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_NB,
506                            FourCC2MIME(chunk_type))
507                || !strcasecmp(MEDIA_MIMETYPE_AUDIO_AMR_WB,
508                               FourCC2MIME(chunk_type))) {
509                // AMR audio is always mono.
510                num_channels = 1;
511            }
512
513            uint16_t sample_size = U16_AT(&buffer[18]);
514            uint32_t sample_rate = U32_AT(&buffer[24]) >> 16;
515
516            printf("*** coding='%s' %d channels, size %d, rate %d\n",
517                   chunk, num_channels, sample_size, sample_rate);
518
519            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
520            mLastTrack->meta->setInt32(kKeyChannelCount, num_channels);
521            mLastTrack->meta->setInt32(kKeySampleRate, sample_rate);
522
523            off_t stop_offset = *offset + chunk_size;
524            *offset = data_offset + sizeof(buffer);
525            while (*offset < stop_offset) {
526                status_t err = parseChunk(offset, depth + 1);
527                if (err != OK) {
528                    return err;
529                }
530            }
531            CHECK_EQ(*offset, stop_offset);
532            break;
533        }
534
535        case FOURCC('m', 'p', '4', 'v'):
536        case FOURCC('s', '2', '6', '3'):
537        case FOURCC('a', 'v', 'c', '1'):
538        {
539            if (mHandlerType != FOURCC('v', 'i', 'd', 'e')) {
540                return ERROR_MALFORMED;
541            }
542
543            uint8_t buffer[78];
544            if (chunk_data_size < (ssize_t)sizeof(buffer)) {
545                // Basic VideoSampleEntry size.
546                return ERROR_MALFORMED;
547            }
548
549            if (mDataSource->read_at(
550                        data_offset, buffer, sizeof(buffer)) < (ssize_t)sizeof(buffer)) {
551                return ERROR_IO;
552            }
553
554            uint16_t data_ref_index = U16_AT(&buffer[6]);
555            uint16_t width = U16_AT(&buffer[6 + 18]);
556            uint16_t height = U16_AT(&buffer[6 + 20]);
557
558            printf("*** coding='%s' width=%d height=%d\n",
559                   chunk, width, height);
560
561            mLastTrack->meta->setCString(kKeyMIMEType, FourCC2MIME(chunk_type));
562            mLastTrack->meta->setInt32(kKeyWidth, width);
563            mLastTrack->meta->setInt32(kKeyHeight, height);
564
565            off_t stop_offset = *offset + chunk_size;
566            *offset = data_offset + sizeof(buffer);
567            while (*offset < stop_offset) {
568                status_t err = parseChunk(offset, depth + 1);
569                if (err != OK) {
570                    return err;
571                }
572            }
573            CHECK_EQ(*offset, stop_offset);
574            break;
575        }
576
577        case FOURCC('s', 't', 'c', 'o'):
578        case FOURCC('c', 'o', '6', '4'):
579        {
580            status_t err =
581                mLastTrack->sampleTable->setChunkOffsetParams(
582                        chunk_type, 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', 'c'):
593        {
594            status_t err =
595                mLastTrack->sampleTable->setSampleToChunkParams(
596                        data_offset, chunk_data_size);
597
598            if (err != OK) {
599                return err;
600            }
601
602            *offset += chunk_size;
603            break;
604        }
605
606        case FOURCC('s', 't', 's', 'z'):
607        case FOURCC('s', 't', 'z', '2'):
608        {
609            status_t err =
610                mLastTrack->sampleTable->setSampleSizeParams(
611                        chunk_type, 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', 't', 's'):
622        {
623            status_t err =
624                mLastTrack->sampleTable->setTimeToSampleParams(
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('s', 't', 's', 's'):
636        {
637            status_t err =
638                mLastTrack->sampleTable->setSyncSampleParams(
639                        data_offset, chunk_data_size);
640
641            if (err != OK) {
642                return err;
643            }
644
645            *offset += chunk_size;
646            break;
647        }
648
649        case FOURCC('e', 's', 'd', 's'):
650        {
651            if (chunk_data_size < 4) {
652                return ERROR_MALFORMED;
653            }
654
655            uint8_t buffer[256];
656            if (chunk_data_size > (off_t)sizeof(buffer)) {
657                return ERROR_BUFFER_TOO_SMALL;
658            }
659
660            if (mDataSource->read_at(
661                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
662                return ERROR_IO;
663            }
664
665            if (U32_AT(buffer) != 0) {
666                // Should be version 0, flags 0.
667                return ERROR_MALFORMED;
668            }
669
670            mLastTrack->meta->setData(
671                    kKeyESDS, kTypeESDS, &buffer[4], chunk_data_size - 4);
672
673            *offset += chunk_size;
674            break;
675        }
676
677        case FOURCC('a', 'v', 'c', 'C'):
678        {
679            char buffer[256];
680            if (chunk_data_size > (off_t)sizeof(buffer)) {
681                return ERROR_BUFFER_TOO_SMALL;
682            }
683
684            if (mDataSource->read_at(
685                        data_offset, buffer, chunk_data_size) < chunk_data_size) {
686                return ERROR_IO;
687            }
688
689            mLastTrack->meta->setData(
690                    kKeyAVCC, kTypeAVCC, buffer, chunk_data_size);
691
692            *offset += chunk_size;
693            break;
694        }
695
696        default:
697        {
698            *offset += chunk_size;
699            break;
700        }
701    }
702
703    return OK;
704}
705
706sp<MediaSource> MPEG4Extractor::getTrack(size_t index) {
707    status_t err;
708    if ((err = readMetaData()) != OK) {
709        return NULL;
710    }
711
712    Track *track = mFirstTrack;
713    while (index > 0) {
714        if (track == NULL) {
715            return NULL;
716        }
717
718        track = track->next;
719        --index;
720    }
721
722    if (track == NULL) {
723        return NULL;
724    }
725
726    return new MPEG4Source(
727            track->meta, mDataSource, track->timescale, track->sampleTable);
728}
729
730////////////////////////////////////////////////////////////////////////////////
731
732MPEG4Source::MPEG4Source(
733        const sp<MetaData> &format,
734        const sp<DataSource> &dataSource,
735        int32_t timeScale,
736        const sp<SampleTable> &sampleTable)
737    : mFormat(format),
738      mDataSource(dataSource),
739      mTimescale(timeScale),
740      mSampleTable(sampleTable),
741      mCurrentSampleIndex(0),
742      mIsAVC(false),
743      mStarted(false),
744      mGroup(NULL),
745      mBuffer(NULL),
746      mWantsNALFragments(false),
747      mSrcBuffer(NULL) {
748    const char *mime;
749    bool success = mFormat->findCString(kKeyMIMEType, &mime);
750    CHECK(success);
751
752    mIsAVC = !strcasecmp(mime, MEDIA_MIMETYPE_VIDEO_AVC);
753}
754
755MPEG4Source::~MPEG4Source() {
756    if (mStarted) {
757        stop();
758    }
759}
760
761status_t MPEG4Source::start(MetaData *params) {
762    CHECK(!mStarted);
763
764    int32_t val;
765    if (params && params->findInt32(kKeyWantsNALFragments, &val)
766        && val != 0) {
767        mWantsNALFragments = true;
768    } else {
769        mWantsNALFragments = false;
770    }
771
772    mGroup = new MediaBufferGroup;
773
774    size_t max_size;
775    status_t err = mSampleTable->getMaxSampleSize(&max_size);
776    CHECK_EQ(err, OK);
777
778    // Assume that a given buffer only contains at most 10 fragments,
779    // each fragment originally prefixed with a 2 byte length will
780    // have a 4 byte header (0x00 0x00 0x00 0x01) after conversion,
781    // and thus will grow by 2 bytes per fragment.
782    mGroup->add_buffer(new MediaBuffer(max_size + 10 * 2));
783
784    mSrcBuffer = new uint8_t[max_size];
785
786    mStarted = true;
787
788    return OK;
789}
790
791status_t MPEG4Source::stop() {
792    CHECK(mStarted);
793
794    if (mBuffer != NULL) {
795        mBuffer->release();
796        mBuffer = NULL;
797    }
798
799    delete[] mSrcBuffer;
800    mSrcBuffer = NULL;
801
802    delete mGroup;
803    mGroup = NULL;
804
805    mStarted = false;
806    mCurrentSampleIndex = 0;
807
808    return OK;
809}
810
811sp<MetaData> MPEG4Source::getFormat() {
812    return mFormat;
813}
814
815status_t MPEG4Source::read(
816        MediaBuffer **out, const ReadOptions *options) {
817    CHECK(mStarted);
818
819    *out = NULL;
820
821    int64_t seekTimeUs;
822    if (options && options->getSeekTo(&seekTimeUs)) {
823        uint32_t sampleIndex;
824        status_t err = mSampleTable->findClosestSample(
825                seekTimeUs * mTimescale / 1000000,
826                &sampleIndex, SampleTable::kSyncSample_Flag);
827
828        if (err != OK) {
829            return err;
830        }
831
832        mCurrentSampleIndex = sampleIndex;
833        if (mBuffer != NULL) {
834            mBuffer->release();
835            mBuffer = NULL;
836        }
837
838        // fall through
839    }
840
841    off_t offset;
842    size_t size;
843    uint32_t dts;
844    bool newBuffer = false;
845    if (mBuffer == NULL) {
846        newBuffer = true;
847
848        status_t err = mSampleTable->getSampleOffsetAndSize(
849                mCurrentSampleIndex, &offset, &size);
850
851        if (err != OK) {
852            return err;
853        }
854
855        err = mSampleTable->getDecodingTime(mCurrentSampleIndex, &dts);
856
857        if (err != OK) {
858            return err;
859        }
860
861        err = mGroup->acquire_buffer(&mBuffer);
862        if (err != OK) {
863            CHECK_EQ(mBuffer, NULL);
864            return err;
865        }
866    }
867
868    if (!mIsAVC || mWantsNALFragments) {
869        if (newBuffer) {
870            ssize_t num_bytes_read =
871                mDataSource->read_at(offset, (uint8_t *)mBuffer->data(), size);
872
873            if (num_bytes_read < (ssize_t)size) {
874                mBuffer->release();
875                mBuffer = NULL;
876
877                return ERROR_IO;
878            }
879
880            mBuffer->set_range(0, size);
881            mBuffer->meta_data()->clear();
882            mBuffer->meta_data()->setInt64(
883                    kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
884            ++mCurrentSampleIndex;
885        }
886
887        if (!mIsAVC) {
888            *out = mBuffer;
889            mBuffer = NULL;
890
891            return OK;
892        }
893
894        // Each NAL unit is split up into its constituent fragments and
895        // each one of them returned in its own buffer.
896
897        CHECK(mBuffer->range_length() >= 2);
898
899        const uint8_t *src =
900            (const uint8_t *)mBuffer->data() + mBuffer->range_offset();
901
902        size_t nal_size = U16_AT(src);
903
904        CHECK(mBuffer->range_length() >= 2 + nal_size);
905
906        MediaBuffer *clone = mBuffer->clone();
907        clone->set_range(mBuffer->range_offset() + 2, nal_size);
908
909        mBuffer->set_range(
910                mBuffer->range_offset() + 2 + nal_size,
911                mBuffer->range_length() - 2 - nal_size);
912
913        if (mBuffer->range_length() == 0) {
914            mBuffer->release();
915            mBuffer = NULL;
916        }
917
918        *out = clone;
919
920        return OK;
921    } else {
922        // Whole NAL units are returned but each fragment is prefixed by
923        // the start code (0x00 00 00 01).
924
925        ssize_t num_bytes_read =
926            mDataSource->read_at(offset, mSrcBuffer, size);
927
928        if (num_bytes_read < (ssize_t)size) {
929            mBuffer->release();
930            mBuffer = NULL;
931
932            return ERROR_IO;
933        }
934
935        uint8_t *dstData = (uint8_t *)mBuffer->data();
936        size_t srcOffset = 0;
937        size_t dstOffset = 0;
938        while (srcOffset < size) {
939            CHECK(srcOffset + 1 < size);
940            size_t nalLength =
941                (mSrcBuffer[srcOffset] << 8) | mSrcBuffer[srcOffset + 1];
942            CHECK(srcOffset + 1 + nalLength < size);
943            srcOffset += 2;
944
945            if (nalLength == 0) {
946                continue;
947            }
948
949            CHECK(dstOffset + 4 <= mBuffer->size());
950
951            dstData[dstOffset++] = 0;
952            dstData[dstOffset++] = 0;
953            dstData[dstOffset++] = 0;
954            dstData[dstOffset++] = 1;
955            memcpy(&dstData[dstOffset], &mSrcBuffer[srcOffset], nalLength);
956            srcOffset += nalLength;
957            dstOffset += nalLength;
958        }
959
960        mBuffer->set_range(0, dstOffset);
961        mBuffer->meta_data()->clear();
962        mBuffer->meta_data()->setInt64(
963                kKeyTime, ((int64_t)dts * 1000000) / mTimescale);
964        ++mCurrentSampleIndex;
965
966        *out = mBuffer;
967        mBuffer = NULL;
968
969        return OK;
970    }
971}
972
973bool SniffMPEG4(
974        const sp<DataSource> &source, String8 *mimeType, float *confidence) {
975    uint8_t header[8];
976
977    ssize_t n = source->read_at(4, header, sizeof(header));
978    if (n < (ssize_t)sizeof(header)) {
979        return false;
980    }
981
982    if (!memcmp(header, "ftyp3gp", 7) || !memcmp(header, "ftypmp42", 8)
983        || !memcmp(header, "ftypisom", 8) || !memcmp(header, "ftypM4V ", 8)) {
984        *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
985        *confidence = 0.1;
986
987        return true;
988    }
989
990    return false;
991}
992
993}  // namespace android
994
995