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