AVIExtractor.cpp revision 3856b090cd04ba5dd4a59a12430ed724d5995909
1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17//#define LOG_NDEBUG 0
18#define LOG_TAG "AVIExtractor"
19#include <utils/Log.h>
20
21#include "include/avc_utils.h"
22#include "include/AVIExtractor.h"
23
24#include <binder/ProcessState.h>
25#include <media/stagefright/foundation/hexdump.h>
26#include <media/stagefright/foundation/ABuffer.h>
27#include <media/stagefright/foundation/ADebug.h>
28#include <media/stagefright/DataSource.h>
29#include <media/stagefright/MediaBuffer.h>
30#include <media/stagefright/MediaBufferGroup.h>
31#include <media/stagefright/MediaDefs.h>
32#include <media/stagefright/MediaErrors.h>
33#include <media/stagefright/MetaData.h>
34#include <media/stagefright/Utils.h>
35
36namespace android {
37
38struct AVIExtractor::AVISource : public MediaSource {
39    AVISource(const sp<AVIExtractor> &extractor, size_t trackIndex);
40
41    virtual status_t start(MetaData *params);
42    virtual status_t stop();
43
44    virtual sp<MetaData> getFormat();
45
46    virtual status_t read(
47            MediaBuffer **buffer, const ReadOptions *options);
48
49protected:
50    virtual ~AVISource();
51
52private:
53    sp<AVIExtractor> mExtractor;
54    size_t mTrackIndex;
55    const AVIExtractor::Track &mTrack;
56    MediaBufferGroup *mBufferGroup;
57    size_t mSampleIndex;
58
59    sp<MP3Splitter> mSplitter;
60
61    DISALLOW_EVIL_CONSTRUCTORS(AVISource);
62};
63
64////////////////////////////////////////////////////////////////////////////////
65
66struct AVIExtractor::MP3Splitter : public RefBase {
67    MP3Splitter();
68
69    void clear();
70    void append(MediaBuffer *buffer);
71    status_t read(MediaBuffer **buffer);
72
73protected:
74    virtual ~MP3Splitter();
75
76private:
77    bool mFindSync;
78    int64_t mBaseTimeUs;
79    int64_t mNumSamplesRead;
80    sp<ABuffer> mBuffer;
81
82    bool resync();
83
84    DISALLOW_EVIL_CONSTRUCTORS(MP3Splitter);
85};
86
87////////////////////////////////////////////////////////////////////////////////
88
89AVIExtractor::AVISource::AVISource(
90        const sp<AVIExtractor> &extractor, size_t trackIndex)
91    : mExtractor(extractor),
92      mTrackIndex(trackIndex),
93      mTrack(mExtractor->mTracks.itemAt(trackIndex)),
94      mBufferGroup(NULL) {
95}
96
97AVIExtractor::AVISource::~AVISource() {
98    if (mBufferGroup) {
99        stop();
100    }
101}
102
103status_t AVIExtractor::AVISource::start(MetaData *params) {
104    CHECK(!mBufferGroup);
105
106    mBufferGroup = new MediaBufferGroup;
107
108    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
109    mBufferGroup->add_buffer(new MediaBuffer(mTrack.mMaxSampleSize));
110    mSampleIndex = 0;
111
112    const char *mime;
113    CHECK(mTrack.mMeta->findCString(kKeyMIMEType, &mime));
114
115    if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
116        mSplitter = new MP3Splitter;
117    } else {
118        mSplitter.clear();
119    }
120
121    return OK;
122}
123
124status_t AVIExtractor::AVISource::stop() {
125    CHECK(mBufferGroup);
126
127    delete mBufferGroup;
128    mBufferGroup = NULL;
129
130    mSplitter.clear();
131
132    return OK;
133}
134
135sp<MetaData> AVIExtractor::AVISource::getFormat() {
136    return mTrack.mMeta;
137}
138
139status_t AVIExtractor::AVISource::read(
140        MediaBuffer **buffer, const ReadOptions *options) {
141    CHECK(mBufferGroup);
142
143    *buffer = NULL;
144
145    int64_t seekTimeUs;
146    ReadOptions::SeekMode seekMode;
147    if (options && options->getSeekTo(&seekTimeUs, &seekMode)) {
148        status_t err =
149            mExtractor->getSampleIndexAtTime(
150                    mTrackIndex, seekTimeUs, seekMode, &mSampleIndex);
151
152        if (err != OK) {
153            return ERROR_END_OF_STREAM;
154        }
155
156        if (mSplitter != NULL) {
157            mSplitter->clear();
158        }
159    }
160
161    for (;;) {
162        if (mSplitter != NULL) {
163            status_t err = mSplitter->read(buffer);
164
165            if (err == OK) {
166                break;
167            } else if (err != -EAGAIN) {
168                return err;
169            }
170        }
171
172        off64_t offset;
173        size_t size;
174        bool isKey;
175        int64_t timeUs;
176        status_t err = mExtractor->getSampleInfo(
177                mTrackIndex, mSampleIndex, &offset, &size, &isKey, &timeUs);
178
179        ++mSampleIndex;
180
181        if (err != OK) {
182            return ERROR_END_OF_STREAM;
183        }
184
185        MediaBuffer *out;
186        CHECK_EQ(mBufferGroup->acquire_buffer(&out), (status_t)OK);
187
188        ssize_t n = mExtractor->mDataSource->readAt(offset, out->data(), size);
189
190        if (n < (ssize_t)size) {
191            return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
192        }
193
194        out->set_range(0, size);
195
196        out->meta_data()->setInt64(kKeyTime, timeUs);
197
198        if (isKey) {
199            out->meta_data()->setInt32(kKeyIsSyncFrame, 1);
200        }
201
202        if (mSplitter == NULL) {
203            *buffer = out;
204            break;
205        }
206
207        mSplitter->append(out);
208        out->release();
209        out = NULL;
210    }
211
212    return OK;
213}
214
215////////////////////////////////////////////////////////////////////////////////
216
217AVIExtractor::MP3Splitter::MP3Splitter()
218    : mFindSync(true),
219      mBaseTimeUs(-1ll),
220      mNumSamplesRead(0) {
221}
222
223AVIExtractor::MP3Splitter::~MP3Splitter() {
224}
225
226void AVIExtractor::MP3Splitter::clear() {
227    mFindSync = true;
228    mBaseTimeUs = -1ll;
229    mNumSamplesRead = 0;
230
231    if (mBuffer != NULL) {
232        mBuffer->setRange(0, 0);
233    }
234}
235
236void AVIExtractor::MP3Splitter::append(MediaBuffer *buffer) {
237    size_t prevCapacity = (mBuffer != NULL) ? mBuffer->capacity() : 0;
238
239    if (mBaseTimeUs < 0) {
240        CHECK(mBuffer == NULL || mBuffer->size() == 0);
241        CHECK(buffer->meta_data()->findInt64(kKeyTime, &mBaseTimeUs));
242        mNumSamplesRead = 0;
243    }
244
245    if (mBuffer != NULL && mBuffer->offset() > 0) {
246        memmove(mBuffer->base(), mBuffer->data(), mBuffer->size());
247        mBuffer->setRange(0, mBuffer->size());
248    }
249
250    if (mBuffer == NULL
251            || mBuffer->size() + buffer->range_length() > prevCapacity) {
252        size_t newCapacity =
253            (prevCapacity + buffer->range_length() + 1023) & ~1023;
254
255        sp<ABuffer> newBuffer = new ABuffer(newCapacity);
256        if (mBuffer != NULL) {
257            memcpy(newBuffer->data(), mBuffer->data(), mBuffer->size());
258            newBuffer->setRange(0, mBuffer->size());
259        } else {
260            newBuffer->setRange(0, 0);
261        }
262        mBuffer = newBuffer;
263    }
264
265    memcpy(mBuffer->data() + mBuffer->size(),
266           (const uint8_t *)buffer->data() + buffer->range_offset(),
267           buffer->range_length());
268
269    mBuffer->setRange(0, mBuffer->size() + buffer->range_length());
270}
271
272bool AVIExtractor::MP3Splitter::resync() {
273    if (mBuffer == NULL) {
274        return false;
275    }
276
277    bool foundSync = false;
278    for (size_t offset = 0; offset + 3 < mBuffer->size(); ++offset) {
279        uint32_t firstHeader = U32_AT(mBuffer->data() + offset);
280
281        size_t frameSize;
282        if (!GetMPEGAudioFrameSize(firstHeader, &frameSize)) {
283            continue;
284        }
285
286        size_t subsequentOffset = offset + frameSize;
287        size_t i = 3;
288        while (i > 0) {
289            if (subsequentOffset + 3 >= mBuffer->size()) {
290                break;
291            }
292
293            static const uint32_t kMask = 0xfffe0c00;
294
295            uint32_t header = U32_AT(mBuffer->data() + subsequentOffset);
296            if ((header & kMask) != (firstHeader & kMask)) {
297                break;
298            }
299
300            if (!GetMPEGAudioFrameSize(header, &frameSize)) {
301                break;
302            }
303
304            subsequentOffset += frameSize;
305            --i;
306        }
307
308        if (i == 0) {
309            foundSync = true;
310            memmove(mBuffer->data(),
311                    mBuffer->data() + offset,
312                    mBuffer->size() - offset);
313
314            mBuffer->setRange(0, mBuffer->size() - offset);
315            break;
316        }
317    }
318
319    return foundSync;
320}
321
322status_t AVIExtractor::MP3Splitter::read(MediaBuffer **out) {
323    *out = NULL;
324
325    if (mFindSync) {
326        if (!resync()) {
327            return -EAGAIN;
328        }
329
330        mFindSync = false;
331    }
332
333    if (mBuffer->size() < 4) {
334        return -EAGAIN;
335    }
336
337    uint32_t header = U32_AT(mBuffer->data());
338    size_t frameSize;
339    int sampleRate;
340    int numSamples;
341    if (!GetMPEGAudioFrameSize(
342                header, &frameSize, &sampleRate, NULL, NULL, &numSamples)) {
343        return ERROR_MALFORMED;
344    }
345
346    if (mBuffer->size() < frameSize) {
347        return -EAGAIN;
348    }
349
350    MediaBuffer *mbuf = new MediaBuffer(frameSize);
351    memcpy(mbuf->data(), mBuffer->data(), frameSize);
352
353    int64_t timeUs = mBaseTimeUs + (mNumSamplesRead * 1000000ll) / sampleRate;
354    mNumSamplesRead += numSamples;
355
356    mbuf->meta_data()->setInt64(kKeyTime, timeUs);
357
358    mBuffer->setRange(
359            mBuffer->offset() + frameSize, mBuffer->size() - frameSize);
360
361    *out = mbuf;
362
363    return OK;
364}
365
366////////////////////////////////////////////////////////////////////////////////
367
368AVIExtractor::AVIExtractor(const sp<DataSource> &dataSource)
369    : mDataSource(dataSource) {
370    mInitCheck = parseHeaders();
371
372    if (mInitCheck != OK) {
373        mTracks.clear();
374    }
375}
376
377AVIExtractor::~AVIExtractor() {
378}
379
380size_t AVIExtractor::countTracks() {
381    return mTracks.size();
382}
383
384sp<MediaSource> AVIExtractor::getTrack(size_t index) {
385    return index < mTracks.size() ? new AVISource(this, index) : NULL;
386}
387
388sp<MetaData> AVIExtractor::getTrackMetaData(
389        size_t index, uint32_t flags) {
390    return index < mTracks.size() ? mTracks.editItemAt(index).mMeta : NULL;
391}
392
393sp<MetaData> AVIExtractor::getMetaData() {
394    sp<MetaData> meta = new MetaData;
395
396    if (mInitCheck == OK) {
397        meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_AVI);
398    }
399
400    return meta;
401}
402
403status_t AVIExtractor::parseHeaders() {
404    mTracks.clear();
405    mMovieOffset = 0;
406    mFoundIndex = false;
407    mOffsetsAreAbsolute = false;
408
409    ssize_t res = parseChunk(0ll, -1ll);
410
411    if (res < 0) {
412        return (status_t)res;
413    }
414
415    if (mMovieOffset == 0ll || !mFoundIndex) {
416        return ERROR_MALFORMED;
417    }
418
419    return OK;
420}
421
422ssize_t AVIExtractor::parseChunk(off64_t offset, off64_t size, int depth) {
423    if (size >= 0 && size < 8) {
424        return ERROR_MALFORMED;
425    }
426
427    uint8_t tmp[12];
428    ssize_t n = mDataSource->readAt(offset, tmp, 8);
429
430    if (n < 8) {
431        return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
432    }
433
434    uint32_t fourcc = U32_AT(tmp);
435    uint32_t chunkSize = U32LE_AT(&tmp[4]);
436
437    if (size >= 0 && chunkSize + 8 > size) {
438        return ERROR_MALFORMED;
439    }
440
441    static const char kPrefix[] = "                              ";
442    const char *prefix = &kPrefix[strlen(kPrefix) - 2 * depth];
443
444    if (fourcc == FOURCC('L', 'I', 'S', 'T')
445            || fourcc == FOURCC('R', 'I', 'F', 'F')) {
446        // It's a list of chunks
447
448        if (size >= 0 && size < 12) {
449            return ERROR_MALFORMED;
450        }
451
452        n = mDataSource->readAt(offset + 8, &tmp[8], 4);
453
454        if (n < 4) {
455            return (n < 0) ? n : (ssize_t)ERROR_MALFORMED;
456        }
457
458        uint32_t subFourcc = U32_AT(&tmp[8]);
459
460        ALOGV("%s offset 0x%08llx LIST of '%c%c%c%c', size %d",
461             prefix,
462             offset,
463             (char)(subFourcc >> 24),
464             (char)((subFourcc >> 16) & 0xff),
465             (char)((subFourcc >> 8) & 0xff),
466             (char)(subFourcc & 0xff),
467             chunkSize - 4);
468
469        if (subFourcc == FOURCC('m', 'o', 'v', 'i')) {
470            // We're not going to parse this, but will take note of the
471            // offset.
472
473            mMovieOffset = offset;
474        } else {
475            off64_t subOffset = offset + 12;
476            off64_t subOffsetLimit = subOffset + chunkSize - 4;
477            while (subOffset < subOffsetLimit) {
478                ssize_t res =
479                    parseChunk(subOffset, subOffsetLimit - subOffset, depth + 1);
480
481                if (res < 0) {
482                    return res;
483                }
484
485                subOffset += res;
486            }
487        }
488    } else {
489        ALOGV("%s offset 0x%08llx CHUNK '%c%c%c%c'",
490             prefix,
491             offset,
492             (char)(fourcc >> 24),
493             (char)((fourcc >> 16) & 0xff),
494             (char)((fourcc >> 8) & 0xff),
495             (char)(fourcc & 0xff));
496
497        status_t err = OK;
498
499        switch (fourcc) {
500            case FOURCC('s', 't', 'r', 'h'):
501            {
502                err = parseStreamHeader(offset + 8, chunkSize);
503                break;
504            }
505
506            case FOURCC('s', 't', 'r', 'f'):
507            {
508                err = parseStreamFormat(offset + 8, chunkSize);
509                break;
510            }
511
512            case FOURCC('i', 'd', 'x', '1'):
513            {
514                err = parseIndex(offset + 8, chunkSize);
515                break;
516            }
517
518            default:
519                break;
520        }
521
522        if (err != OK) {
523            return err;
524        }
525    }
526
527    if (chunkSize & 1) {
528        ++chunkSize;
529    }
530
531    return chunkSize + 8;
532}
533
534static const char *GetMIMETypeForHandler(uint32_t handler) {
535    switch (handler) {
536        // Wow... shamelessly copied from
537        // http://wiki.multimedia.cx/index.php?title=ISO_MPEG-4
538
539        case FOURCC('3', 'I', 'V', '2'):
540        case FOURCC('3', 'i', 'v', '2'):
541        case FOURCC('B', 'L', 'Z', '0'):
542        case FOURCC('D', 'I', 'G', 'I'):
543        case FOURCC('D', 'I', 'V', '1'):
544        case FOURCC('d', 'i', 'v', '1'):
545        case FOURCC('D', 'I', 'V', 'X'):
546        case FOURCC('d', 'i', 'v', 'x'):
547        case FOURCC('D', 'X', '5', '0'):
548        case FOURCC('d', 'x', '5', '0'):
549        case FOURCC('D', 'X', 'G', 'M'):
550        case FOURCC('E', 'M', '4', 'A'):
551        case FOURCC('E', 'P', 'H', 'V'):
552        case FOURCC('F', 'M', 'P', '4'):
553        case FOURCC('f', 'm', 'p', '4'):
554        case FOURCC('F', 'V', 'F', 'W'):
555        case FOURCC('H', 'D', 'X', '4'):
556        case FOURCC('h', 'd', 'x', '4'):
557        case FOURCC('M', '4', 'C', 'C'):
558        case FOURCC('M', '4', 'S', '2'):
559        case FOURCC('m', '4', 's', '2'):
560        case FOURCC('M', 'P', '4', 'S'):
561        case FOURCC('m', 'p', '4', 's'):
562        case FOURCC('M', 'P', '4', 'V'):
563        case FOURCC('m', 'p', '4', 'v'):
564        case FOURCC('M', 'V', 'X', 'M'):
565        case FOURCC('R', 'M', 'P', '4'):
566        case FOURCC('S', 'E', 'D', 'G'):
567        case FOURCC('S', 'M', 'P', '4'):
568        case FOURCC('U', 'M', 'P', '4'):
569        case FOURCC('W', 'V', '1', 'F'):
570        case FOURCC('X', 'V', 'I', 'D'):
571        case FOURCC('X', 'v', 'i', 'D'):
572        case FOURCC('x', 'v', 'i', 'd'):
573        case FOURCC('X', 'V', 'I', 'X'):
574            return MEDIA_MIMETYPE_VIDEO_MPEG4;
575
576        // from http://wiki.multimedia.cx/index.php?title=H264
577        case FOURCC('a', 'v', 'c', '1'):
578        case FOURCC('d', 'a', 'v', 'c'):
579        case FOURCC('x', '2', '6', '4'):
580        case FOURCC('v', 's', 's', 'h'):
581            return MEDIA_MIMETYPE_VIDEO_AVC;
582
583        default:
584            return NULL;
585    }
586}
587
588status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
589    if (size != 56) {
590        return ERROR_MALFORMED;
591    }
592
593    if (mTracks.size() > 99) {
594        return -ERANGE;
595    }
596
597    sp<ABuffer> buffer = new ABuffer(size);
598    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
599
600    if (n < (ssize_t)size) {
601        return n < 0 ? (status_t)n : ERROR_MALFORMED;
602    }
603
604    const uint8_t *data = buffer->data();
605
606    uint32_t type = U32_AT(data);
607    uint32_t handler = U32_AT(&data[4]);
608    uint32_t flags = U32LE_AT(&data[8]);
609
610    sp<MetaData> meta = new MetaData;
611
612    uint32_t rate = U32LE_AT(&data[20]);
613    uint32_t scale = U32LE_AT(&data[24]);
614
615    uint32_t sampleSize = U32LE_AT(&data[44]);
616
617    const char *mime = NULL;
618    Track::Kind kind = Track::OTHER;
619
620    if (type == FOURCC('v', 'i', 'd', 's')) {
621        mime = GetMIMETypeForHandler(handler);
622
623        if (mime && strncasecmp(mime, "video/", 6)) {
624            return ERROR_MALFORMED;
625        }
626
627        if (mime == NULL) {
628            LOGW("Unsupported video format '%c%c%c%c'",
629                 (char)(handler >> 24),
630                 (char)((handler >> 16) & 0xff),
631                 (char)((handler >> 8) & 0xff),
632                 (char)(handler & 0xff));
633        }
634
635        kind = Track::VIDEO;
636    } else if (type == FOURCC('a', 'u', 'd', 's')) {
637        if (mime && strncasecmp(mime, "audio/", 6)) {
638            return ERROR_MALFORMED;
639        }
640
641        kind = Track::AUDIO;
642    }
643
644    if (!mime) {
645        mime = "application/octet-stream";
646    }
647
648    meta->setCString(kKeyMIMEType, mime);
649
650    mTracks.push();
651    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
652
653    track->mMeta = meta;
654    track->mRate = rate;
655    track->mScale = scale;
656    track->mBytesPerSample = sampleSize;
657    track->mKind = kind;
658    track->mNumSyncSamples = 0;
659    track->mThumbnailSampleSize = 0;
660    track->mThumbnailSampleIndex = -1;
661    track->mMaxSampleSize = 0;
662    track->mAvgChunkSize = 1.0;
663    track->mFirstChunkSize = 0;
664
665    return OK;
666}
667
668status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
669    if (mTracks.isEmpty()) {
670        return ERROR_MALFORMED;
671    }
672
673    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
674
675    if (track->mKind == Track::OTHER) {
676        // We don't support this content, but that's not a parsing error.
677        return OK;
678    }
679
680    bool isVideo = (track->mKind == Track::VIDEO);
681
682    if ((isVideo && size < 40) || (!isVideo && size < 16)) {
683        // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively.
684        return ERROR_MALFORMED;
685    }
686
687    sp<ABuffer> buffer = new ABuffer(size);
688    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
689
690    if (n < (ssize_t)size) {
691        return n < 0 ? (status_t)n : ERROR_MALFORMED;
692    }
693
694    const uint8_t *data = buffer->data();
695
696    if (isVideo) {
697        uint32_t width = U32LE_AT(&data[4]);
698        uint32_t height = U32LE_AT(&data[8]);
699
700        track->mMeta->setInt32(kKeyWidth, width);
701        track->mMeta->setInt32(kKeyHeight, height);
702    } else {
703        uint32_t format = U16LE_AT(data);
704
705        if (format == 0x55) {
706            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
707        } else {
708            LOGW("Unsupported audio format = 0x%04x", format);
709        }
710
711        uint32_t numChannels = U16LE_AT(&data[2]);
712        uint32_t sampleRate = U32LE_AT(&data[4]);
713
714        track->mMeta->setInt32(kKeyChannelCount, numChannels);
715        track->mMeta->setInt32(kKeySampleRate, sampleRate);
716    }
717
718    return OK;
719}
720
721// static
722bool AVIExtractor::IsCorrectChunkType(
723        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
724    uint32_t chunkBase = chunkType & 0xffff;
725
726    switch (kind) {
727        case Track::VIDEO:
728        {
729            if (chunkBase != FOURCC(0, 0, 'd', 'c')
730                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
731                return false;
732            }
733            break;
734        }
735
736        case Track::AUDIO:
737        {
738            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
739                return false;
740            }
741            break;
742        }
743
744        default:
745            break;
746    }
747
748    if (trackIndex < 0) {
749        return true;
750    }
751
752    uint8_t hi = chunkType >> 24;
753    uint8_t lo = (chunkType >> 16) & 0xff;
754
755    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
756        return false;
757    }
758
759    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
760        return false;
761    }
762
763    return true;
764}
765
766status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
767    if ((size % 16) != 0) {
768        return ERROR_MALFORMED;
769    }
770
771    sp<ABuffer> buffer = new ABuffer(size);
772    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
773
774    if (n < (ssize_t)size) {
775        return n < 0 ? (status_t)n : ERROR_MALFORMED;
776    }
777
778    const uint8_t *data = buffer->data();
779
780    while (size > 0) {
781        uint32_t chunkType = U32_AT(data);
782
783        uint8_t hi = chunkType >> 24;
784        uint8_t lo = (chunkType >> 16) & 0xff;
785
786        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
787            return ERROR_MALFORMED;
788        }
789
790        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
791
792        if (trackIndex >= mTracks.size()) {
793            return ERROR_MALFORMED;
794        }
795
796        Track *track = &mTracks.editItemAt(trackIndex);
797
798        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
799            return ERROR_MALFORMED;
800        }
801
802        if (track->mKind == Track::OTHER) {
803            data += 16;
804            size -= 16;
805            continue;
806        }
807
808        uint32_t flags = U32LE_AT(&data[4]);
809        uint32_t offset = U32LE_AT(&data[8]);
810        uint32_t chunkSize = U32LE_AT(&data[12]);
811
812        if (chunkSize > track->mMaxSampleSize) {
813            track->mMaxSampleSize = chunkSize;
814        }
815
816        track->mSamples.push();
817
818        SampleInfo *info =
819            &track->mSamples.editItemAt(track->mSamples.size() - 1);
820
821        info->mOffset = offset;
822        info->mIsKey = (flags & 0x10) != 0;
823
824        if (info->mIsKey) {
825            static const size_t kMaxNumSyncSamplesToScan = 20;
826
827            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
828                if (chunkSize > track->mThumbnailSampleSize) {
829                    track->mThumbnailSampleSize = chunkSize;
830
831                    track->mThumbnailSampleIndex =
832                        track->mSamples.size() - 1;
833                }
834            }
835
836            ++track->mNumSyncSamples;
837        }
838
839        data += 16;
840        size -= 16;
841    }
842
843    if (!mTracks.isEmpty()) {
844        off64_t offset;
845        size_t size;
846        bool isKey;
847        int64_t timeUs;
848        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
849
850        if (err != OK) {
851            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
852            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
853
854            if (err != OK) {
855                return err;
856            }
857        }
858
859        ALOGV("Chunk offsets are %s",
860             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
861    }
862
863    for (size_t i = 0; i < mTracks.size(); ++i) {
864        Track *track = &mTracks.editItemAt(i);
865
866        if (track->mBytesPerSample > 0) {
867            // Assume all chunks are roughly the same size for now.
868
869            // Compute the avg. size of the first 128 chunks (if there are
870            // that many), but exclude the size of the first one, since
871            // it may be an outlier.
872            size_t numSamplesToAverage = track->mSamples.size();
873            if (numSamplesToAverage > 256) {
874                numSamplesToAverage = 256;
875            }
876
877            double avgChunkSize = 0;
878            size_t j;
879            for (j = 0; j <= numSamplesToAverage; ++j) {
880                off64_t offset;
881                size_t size;
882                bool isKey;
883                int64_t dummy;
884
885                status_t err =
886                    getSampleInfo(
887                            i, j,
888                            &offset, &size, &isKey, &dummy);
889
890                if (err != OK) {
891                    return err;
892                }
893
894                if (j == 0) {
895                    track->mFirstChunkSize = size;
896                    continue;
897                }
898
899                avgChunkSize += size;
900            }
901
902            avgChunkSize /= numSamplesToAverage;
903
904            track->mAvgChunkSize = avgChunkSize;
905        }
906
907        int64_t durationUs;
908        CHECK_EQ((status_t)OK,
909                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
910
911        ALOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
912
913        track->mMeta->setInt64(kKeyDuration, durationUs);
914        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
915
916        const char *tmp;
917        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
918
919        AString mime = tmp;
920
921        if (!strncasecmp("video/", mime.c_str(), 6)) {
922            if (track->mThumbnailSampleIndex >= 0) {
923                int64_t thumbnailTimeUs;
924                CHECK_EQ((status_t)OK,
925                         getSampleTime(i, track->mThumbnailSampleIndex,
926                                       &thumbnailTimeUs));
927
928                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
929            }
930
931            status_t err = OK;
932
933            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
934                err = addMPEG4CodecSpecificData(i);
935            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
936                err = addH264CodecSpecificData(i);
937            }
938
939            if (err != OK) {
940                return err;
941            }
942        }
943    }
944
945    mFoundIndex = true;
946
947    return OK;
948}
949
950static size_t GetSizeWidth(size_t x) {
951    size_t n = 1;
952    while (x > 127) {
953        ++n;
954        x >>= 7;
955    }
956    return n;
957}
958
959static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
960    while (x > 127) {
961        *dst++ = (x & 0x7f) | 0x80;
962        x >>= 7;
963    }
964    *dst++ = x;
965    return dst;
966}
967
968sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
969    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
970    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
971    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
972
973    sp<ABuffer> csd = new ABuffer(len3);
974    uint8_t *dst = csd->data();
975    *dst++ = 0x03;
976    dst = EncodeSize(dst, len2 + 3);
977    *dst++ = 0x00;  // ES_ID
978    *dst++ = 0x00;
979    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
980
981    *dst++ = 0x04;
982    dst = EncodeSize(dst, len1 + 13);
983    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
984    for (size_t i = 0; i < 12; ++i) {
985        *dst++ = 0x00;
986    }
987
988    *dst++ = 0x05;
989    dst = EncodeSize(dst, config->size());
990    memcpy(dst, config->data(), config->size());
991    dst += config->size();
992
993    // hexdump(csd->data(), csd->size());
994
995    return csd;
996}
997
998status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
999    Track *track = &mTracks.editItemAt(trackIndex);
1000
1001    off64_t offset;
1002    size_t size;
1003    bool isKey;
1004    int64_t timeUs;
1005    status_t err =
1006        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
1007
1008    if (err != OK) {
1009        return err;
1010    }
1011
1012    sp<ABuffer> buffer = new ABuffer(size);
1013    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1014
1015    if (n < (ssize_t)size) {
1016        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1017    }
1018
1019    // Extract everything up to the first VOP start code from the first
1020    // frame's encoded data and use it to construct an ESDS with the
1021    // codec specific data.
1022
1023    size_t i = 0;
1024    bool found = false;
1025    while (i + 3 < buffer->size()) {
1026        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
1027            found = true;
1028            break;
1029        }
1030
1031        ++i;
1032    }
1033
1034    if (!found) {
1035        return ERROR_MALFORMED;
1036    }
1037
1038    buffer->setRange(0, i);
1039
1040    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
1041    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
1042
1043    return OK;
1044}
1045
1046status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
1047    Track *track = &mTracks.editItemAt(trackIndex);
1048
1049    off64_t offset;
1050    size_t size;
1051    bool isKey;
1052    int64_t timeUs;
1053
1054    // Extract codec specific data from the first non-empty sample.
1055
1056    size_t sampleIndex = 0;
1057    for (;;) {
1058        status_t err =
1059            getSampleInfo(
1060                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
1061
1062        if (err != OK) {
1063            return err;
1064        }
1065
1066        if (size > 0) {
1067            break;
1068        }
1069
1070        ++sampleIndex;
1071    }
1072
1073    sp<ABuffer> buffer = new ABuffer(size);
1074    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1075
1076    if (n < (ssize_t)size) {
1077        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1078    }
1079
1080    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
1081
1082    if (meta == NULL) {
1083        LOGE("Unable to extract AVC codec specific data");
1084        return ERROR_MALFORMED;
1085    }
1086
1087    int32_t width, height;
1088    CHECK(meta->findInt32(kKeyWidth, &width));
1089    CHECK(meta->findInt32(kKeyHeight, &height));
1090
1091    uint32_t type;
1092    const void *csd;
1093    size_t csdSize;
1094    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
1095
1096    track->mMeta->setInt32(kKeyWidth, width);
1097    track->mMeta->setInt32(kKeyHeight, width);
1098    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
1099
1100    return OK;
1101}
1102
1103status_t AVIExtractor::getSampleInfo(
1104        size_t trackIndex, size_t sampleIndex,
1105        off64_t *offset, size_t *size, bool *isKey,
1106        int64_t *sampleTimeUs) {
1107    if (trackIndex >= mTracks.size()) {
1108        return -ERANGE;
1109    }
1110
1111    const Track &track = mTracks.itemAt(trackIndex);
1112
1113    if (sampleIndex >= track.mSamples.size()) {
1114        return -ERANGE;
1115    }
1116
1117    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
1118
1119    if (!mOffsetsAreAbsolute) {
1120        *offset = info.mOffset + mMovieOffset + 8;
1121    } else {
1122        *offset = info.mOffset;
1123    }
1124
1125    *size = 0;
1126
1127    uint8_t tmp[8];
1128    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
1129
1130    if (n < 8) {
1131        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
1132    }
1133
1134    uint32_t chunkType = U32_AT(tmp);
1135
1136    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
1137        return ERROR_MALFORMED;
1138    }
1139
1140    *offset += 8;
1141    *size = U32LE_AT(&tmp[4]);
1142
1143    *isKey = info.mIsKey;
1144
1145    if (track.mBytesPerSample > 0) {
1146        size_t sampleStartInBytes;
1147        if (sampleIndex == 0) {
1148            sampleStartInBytes = 0;
1149        } else {
1150            sampleStartInBytes =
1151                track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1);
1152        }
1153
1154        sampleIndex = sampleStartInBytes / track.mBytesPerSample;
1155    }
1156
1157    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
1158
1159    return OK;
1160}
1161
1162status_t AVIExtractor::getSampleTime(
1163        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
1164    off64_t offset;
1165    size_t size;
1166    bool isKey;
1167    return getSampleInfo(
1168            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
1169}
1170
1171status_t AVIExtractor::getSampleIndexAtTime(
1172        size_t trackIndex,
1173        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
1174        size_t *sampleIndex) const {
1175    if (trackIndex >= mTracks.size()) {
1176        return -ERANGE;
1177    }
1178
1179    const Track &track = mTracks.itemAt(trackIndex);
1180
1181    ssize_t closestSampleIndex;
1182
1183    if (track.mBytesPerSample > 0) {
1184        size_t closestByteOffset =
1185            (timeUs * track.mBytesPerSample)
1186                / track.mRate * track.mScale / 1000000ll;
1187
1188        if (closestByteOffset <= track.mFirstChunkSize) {
1189            closestSampleIndex = 0;
1190        } else {
1191            closestSampleIndex =
1192                (closestByteOffset - track.mFirstChunkSize)
1193                    / track.mAvgChunkSize;
1194        }
1195    } else {
1196        // Each chunk contains a single sample.
1197        closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll;
1198    }
1199
1200    ssize_t numSamples = track.mSamples.size();
1201
1202    if (closestSampleIndex < 0) {
1203        closestSampleIndex = 0;
1204    } else if (closestSampleIndex >= numSamples) {
1205        closestSampleIndex = numSamples - 1;
1206    }
1207
1208    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
1209        *sampleIndex = closestSampleIndex;
1210
1211        return OK;
1212    }
1213
1214    ssize_t prevSyncSampleIndex = closestSampleIndex;
1215    while (prevSyncSampleIndex >= 0) {
1216        const SampleInfo &info =
1217            track.mSamples.itemAt(prevSyncSampleIndex);
1218
1219        if (info.mIsKey) {
1220            break;
1221        }
1222
1223        --prevSyncSampleIndex;
1224    }
1225
1226    ssize_t nextSyncSampleIndex = closestSampleIndex;
1227    while (nextSyncSampleIndex < numSamples) {
1228        const SampleInfo &info =
1229            track.mSamples.itemAt(nextSyncSampleIndex);
1230
1231        if (info.mIsKey) {
1232            break;
1233        }
1234
1235        ++nextSyncSampleIndex;
1236    }
1237
1238    switch (mode) {
1239        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
1240        {
1241            *sampleIndex = prevSyncSampleIndex;
1242
1243            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
1244        }
1245
1246        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
1247        {
1248            *sampleIndex = nextSyncSampleIndex;
1249
1250            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
1251        }
1252
1253        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
1254        {
1255            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
1256                return UNKNOWN_ERROR;
1257            }
1258
1259            if (prevSyncSampleIndex < 0) {
1260                *sampleIndex = nextSyncSampleIndex;
1261                return OK;
1262            }
1263
1264            if (nextSyncSampleIndex >= numSamples) {
1265                *sampleIndex = prevSyncSampleIndex;
1266                return OK;
1267            }
1268
1269            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
1270            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
1271
1272            *sampleIndex =
1273                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
1274
1275            return OK;
1276        }
1277
1278        default:
1279            TRESPASS();
1280            break;
1281    }
1282}
1283
1284bool SniffAVI(
1285        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1286        sp<AMessage> *) {
1287    char tmp[12];
1288    if (source->readAt(0, tmp, 12) < 12) {
1289        return false;
1290    }
1291
1292    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
1293        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
1294
1295        // Just a tad over the mp3 extractor's confidence, since
1296        // these .avi files may contain .mp3 content that otherwise would
1297        // mistakenly lead to us identifying the entire file as a .mp3 file.
1298        *confidence = 0.21;
1299
1300        return true;
1301    }
1302
1303    return false;
1304}
1305
1306}  // namespace android
1307