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('H', '2', '6', '4'):
581        case FOURCC('v', 's', 's', 'h'):
582            return MEDIA_MIMETYPE_VIDEO_AVC;
583
584        default:
585            return NULL;
586    }
587}
588
589status_t AVIExtractor::parseStreamHeader(off64_t offset, size_t size) {
590    if (size != 56) {
591        return ERROR_MALFORMED;
592    }
593
594    if (mTracks.size() > 99) {
595        return -ERANGE;
596    }
597
598    sp<ABuffer> buffer = new ABuffer(size);
599    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
600
601    if (n < (ssize_t)size) {
602        return n < 0 ? (status_t)n : ERROR_MALFORMED;
603    }
604
605    const uint8_t *data = buffer->data();
606
607    uint32_t type = U32_AT(data);
608    uint32_t handler = U32_AT(&data[4]);
609    uint32_t flags = U32LE_AT(&data[8]);
610
611    sp<MetaData> meta = new MetaData;
612
613    uint32_t rate = U32LE_AT(&data[20]);
614    uint32_t scale = U32LE_AT(&data[24]);
615
616    uint32_t sampleSize = U32LE_AT(&data[44]);
617
618    const char *mime = NULL;
619    Track::Kind kind = Track::OTHER;
620
621    if (type == FOURCC('v', 'i', 'd', 's')) {
622        mime = GetMIMETypeForHandler(handler);
623
624        if (mime && strncasecmp(mime, "video/", 6)) {
625            return ERROR_MALFORMED;
626        }
627
628        if (mime == NULL) {
629            ALOGW("Unsupported video format '%c%c%c%c'",
630                 (char)(handler >> 24),
631                 (char)((handler >> 16) & 0xff),
632                 (char)((handler >> 8) & 0xff),
633                 (char)(handler & 0xff));
634        }
635
636        kind = Track::VIDEO;
637    } else if (type == FOURCC('a', 'u', 'd', 's')) {
638        if (mime && strncasecmp(mime, "audio/", 6)) {
639            return ERROR_MALFORMED;
640        }
641
642        kind = Track::AUDIO;
643    }
644
645    if (!mime) {
646        mime = "application/octet-stream";
647    }
648
649    meta->setCString(kKeyMIMEType, mime);
650
651    mTracks.push();
652    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
653
654    track->mMeta = meta;
655    track->mRate = rate;
656    track->mScale = scale;
657    track->mBytesPerSample = sampleSize;
658    track->mKind = kind;
659    track->mNumSyncSamples = 0;
660    track->mThumbnailSampleSize = 0;
661    track->mThumbnailSampleIndex = -1;
662    track->mMaxSampleSize = 0;
663    track->mAvgChunkSize = 1.0;
664    track->mFirstChunkSize = 0;
665
666    return OK;
667}
668
669status_t AVIExtractor::parseStreamFormat(off64_t offset, size_t size) {
670    if (mTracks.isEmpty()) {
671        return ERROR_MALFORMED;
672    }
673
674    Track *track = &mTracks.editItemAt(mTracks.size() - 1);
675
676    if (track->mKind == Track::OTHER) {
677        // We don't support this content, but that's not a parsing error.
678        return OK;
679    }
680
681    bool isVideo = (track->mKind == Track::VIDEO);
682
683    if ((isVideo && size < 40) || (!isVideo && size < 16)) {
684        // Expected a BITMAPINFO or WAVEFORMAT(EX) structure, respectively.
685        return ERROR_MALFORMED;
686    }
687
688    sp<ABuffer> buffer = new ABuffer(size);
689    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
690
691    if (n < (ssize_t)size) {
692        return n < 0 ? (status_t)n : ERROR_MALFORMED;
693    }
694
695    const uint8_t *data = buffer->data();
696
697    if (isVideo) {
698        uint32_t width = U32LE_AT(&data[4]);
699        uint32_t height = U32LE_AT(&data[8]);
700
701        track->mMeta->setInt32(kKeyWidth, width);
702        track->mMeta->setInt32(kKeyHeight, height);
703    } else {
704        uint32_t format = U16LE_AT(data);
705
706        if (format == 0x55) {
707            track->mMeta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_AUDIO_MPEG);
708        } else {
709            ALOGW("Unsupported audio format = 0x%04x", format);
710        }
711
712        uint32_t numChannels = U16LE_AT(&data[2]);
713        uint32_t sampleRate = U32LE_AT(&data[4]);
714
715        track->mMeta->setInt32(kKeyChannelCount, numChannels);
716        track->mMeta->setInt32(kKeySampleRate, sampleRate);
717    }
718
719    return OK;
720}
721
722// static
723bool AVIExtractor::IsCorrectChunkType(
724        ssize_t trackIndex, Track::Kind kind, uint32_t chunkType) {
725    uint32_t chunkBase = chunkType & 0xffff;
726
727    switch (kind) {
728        case Track::VIDEO:
729        {
730            if (chunkBase != FOURCC(0, 0, 'd', 'c')
731                    && chunkBase != FOURCC(0, 0, 'd', 'b')) {
732                return false;
733            }
734            break;
735        }
736
737        case Track::AUDIO:
738        {
739            if (chunkBase != FOURCC(0, 0, 'w', 'b')) {
740                return false;
741            }
742            break;
743        }
744
745        default:
746            break;
747    }
748
749    if (trackIndex < 0) {
750        return true;
751    }
752
753    uint8_t hi = chunkType >> 24;
754    uint8_t lo = (chunkType >> 16) & 0xff;
755
756    if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
757        return false;
758    }
759
760    if (trackIndex != (10 * (hi - '0') + (lo - '0'))) {
761        return false;
762    }
763
764    return true;
765}
766
767status_t AVIExtractor::parseIndex(off64_t offset, size_t size) {
768    if ((size % 16) != 0) {
769        return ERROR_MALFORMED;
770    }
771
772    sp<ABuffer> buffer = new ABuffer(size);
773    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
774
775    if (n < (ssize_t)size) {
776        return n < 0 ? (status_t)n : ERROR_MALFORMED;
777    }
778
779    const uint8_t *data = buffer->data();
780
781    while (size > 0) {
782        uint32_t chunkType = U32_AT(data);
783
784        uint8_t hi = chunkType >> 24;
785        uint8_t lo = (chunkType >> 16) & 0xff;
786
787        if (hi < '0' || hi > '9' || lo < '0' || lo > '9') {
788            return ERROR_MALFORMED;
789        }
790
791        size_t trackIndex = 10 * (hi - '0') + (lo - '0');
792
793        if (trackIndex >= mTracks.size()) {
794            return ERROR_MALFORMED;
795        }
796
797        Track *track = &mTracks.editItemAt(trackIndex);
798
799        if (!IsCorrectChunkType(-1, track->mKind, chunkType)) {
800            return ERROR_MALFORMED;
801        }
802
803        if (track->mKind == Track::OTHER) {
804            data += 16;
805            size -= 16;
806            continue;
807        }
808
809        uint32_t flags = U32LE_AT(&data[4]);
810        uint32_t offset = U32LE_AT(&data[8]);
811        uint32_t chunkSize = U32LE_AT(&data[12]);
812
813        if (chunkSize > track->mMaxSampleSize) {
814            track->mMaxSampleSize = chunkSize;
815        }
816
817        track->mSamples.push();
818
819        SampleInfo *info =
820            &track->mSamples.editItemAt(track->mSamples.size() - 1);
821
822        info->mOffset = offset;
823        info->mIsKey = (flags & 0x10) != 0;
824
825        if (info->mIsKey) {
826            static const size_t kMaxNumSyncSamplesToScan = 20;
827
828            if (track->mNumSyncSamples < kMaxNumSyncSamplesToScan) {
829                if (chunkSize > track->mThumbnailSampleSize) {
830                    track->mThumbnailSampleSize = chunkSize;
831
832                    track->mThumbnailSampleIndex =
833                        track->mSamples.size() - 1;
834                }
835            }
836
837            ++track->mNumSyncSamples;
838        }
839
840        data += 16;
841        size -= 16;
842    }
843
844    if (!mTracks.isEmpty()) {
845        off64_t offset;
846        size_t size;
847        bool isKey;
848        int64_t timeUs;
849        status_t err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
850
851        if (err != OK) {
852            mOffsetsAreAbsolute = !mOffsetsAreAbsolute;
853            err = getSampleInfo(0, 0, &offset, &size, &isKey, &timeUs);
854
855            if (err != OK) {
856                return err;
857            }
858        }
859
860        ALOGV("Chunk offsets are %s",
861             mOffsetsAreAbsolute ? "absolute" : "movie-chunk relative");
862    }
863
864    for (size_t i = 0; i < mTracks.size(); ++i) {
865        Track *track = &mTracks.editItemAt(i);
866
867        if (track->mBytesPerSample > 0) {
868            // Assume all chunks are roughly the same size for now.
869
870            // Compute the avg. size of the first 128 chunks (if there are
871            // that many), but exclude the size of the first one, since
872            // it may be an outlier.
873            size_t numSamplesToAverage = track->mSamples.size();
874            if (numSamplesToAverage > 256) {
875                numSamplesToAverage = 256;
876            }
877
878            double avgChunkSize = 0;
879            size_t j;
880            for (j = 0; j <= numSamplesToAverage; ++j) {
881                off64_t offset;
882                size_t size;
883                bool isKey;
884                int64_t dummy;
885
886                status_t err =
887                    getSampleInfo(
888                            i, j,
889                            &offset, &size, &isKey, &dummy);
890
891                if (err != OK) {
892                    return err;
893                }
894
895                if (j == 0) {
896                    track->mFirstChunkSize = size;
897                    continue;
898                }
899
900                avgChunkSize += size;
901            }
902
903            avgChunkSize /= numSamplesToAverage;
904
905            track->mAvgChunkSize = avgChunkSize;
906        }
907
908        int64_t durationUs;
909        CHECK_EQ((status_t)OK,
910                 getSampleTime(i, track->mSamples.size() - 1, &durationUs));
911
912        ALOGV("track %d duration = %.2f secs", i, durationUs / 1E6);
913
914        track->mMeta->setInt64(kKeyDuration, durationUs);
915        track->mMeta->setInt32(kKeyMaxInputSize, track->mMaxSampleSize);
916
917        const char *tmp;
918        CHECK(track->mMeta->findCString(kKeyMIMEType, &tmp));
919
920        AString mime = tmp;
921
922        if (!strncasecmp("video/", mime.c_str(), 6)) {
923            if (track->mThumbnailSampleIndex >= 0) {
924                int64_t thumbnailTimeUs;
925                CHECK_EQ((status_t)OK,
926                         getSampleTime(i, track->mThumbnailSampleIndex,
927                                       &thumbnailTimeUs));
928
929                track->mMeta->setInt64(kKeyThumbnailTime, thumbnailTimeUs);
930            }
931
932            status_t err = OK;
933
934            if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_MPEG4)) {
935                err = addMPEG4CodecSpecificData(i);
936            } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_VIDEO_AVC)) {
937                err = addH264CodecSpecificData(i);
938            }
939
940            if (err != OK) {
941                return err;
942            }
943        }
944    }
945
946    mFoundIndex = true;
947
948    return OK;
949}
950
951static size_t GetSizeWidth(size_t x) {
952    size_t n = 1;
953    while (x > 127) {
954        ++n;
955        x >>= 7;
956    }
957    return n;
958}
959
960static uint8_t *EncodeSize(uint8_t *dst, size_t x) {
961    while (x > 127) {
962        *dst++ = (x & 0x7f) | 0x80;
963        x >>= 7;
964    }
965    *dst++ = x;
966    return dst;
967}
968
969sp<ABuffer> MakeMPEG4VideoCodecSpecificData(const sp<ABuffer> &config) {
970    size_t len1 = config->size() + GetSizeWidth(config->size()) + 1;
971    size_t len2 = len1 + GetSizeWidth(len1) + 1 + 13;
972    size_t len3 = len2 + GetSizeWidth(len2) + 1 + 3;
973
974    sp<ABuffer> csd = new ABuffer(len3);
975    uint8_t *dst = csd->data();
976    *dst++ = 0x03;
977    dst = EncodeSize(dst, len2 + 3);
978    *dst++ = 0x00;  // ES_ID
979    *dst++ = 0x00;
980    *dst++ = 0x00;  // streamDependenceFlag, URL_Flag, OCRstreamFlag
981
982    *dst++ = 0x04;
983    dst = EncodeSize(dst, len1 + 13);
984    *dst++ = 0x01;  // Video ISO/IEC 14496-2 Simple Profile
985    for (size_t i = 0; i < 12; ++i) {
986        *dst++ = 0x00;
987    }
988
989    *dst++ = 0x05;
990    dst = EncodeSize(dst, config->size());
991    memcpy(dst, config->data(), config->size());
992    dst += config->size();
993
994    // hexdump(csd->data(), csd->size());
995
996    return csd;
997}
998
999status_t AVIExtractor::addMPEG4CodecSpecificData(size_t trackIndex) {
1000    Track *track = &mTracks.editItemAt(trackIndex);
1001
1002    off64_t offset;
1003    size_t size;
1004    bool isKey;
1005    int64_t timeUs;
1006    status_t err =
1007        getSampleInfo(trackIndex, 0, &offset, &size, &isKey, &timeUs);
1008
1009    if (err != OK) {
1010        return err;
1011    }
1012
1013    sp<ABuffer> buffer = new ABuffer(size);
1014    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1015
1016    if (n < (ssize_t)size) {
1017        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1018    }
1019
1020    // Extract everything up to the first VOP start code from the first
1021    // frame's encoded data and use it to construct an ESDS with the
1022    // codec specific data.
1023
1024    size_t i = 0;
1025    bool found = false;
1026    while (i + 3 < buffer->size()) {
1027        if (!memcmp("\x00\x00\x01\xb6", &buffer->data()[i], 4)) {
1028            found = true;
1029            break;
1030        }
1031
1032        ++i;
1033    }
1034
1035    if (!found) {
1036        return ERROR_MALFORMED;
1037    }
1038
1039    buffer->setRange(0, i);
1040
1041    sp<ABuffer> csd = MakeMPEG4VideoCodecSpecificData(buffer);
1042    track->mMeta->setData(kKeyESDS, kTypeESDS, csd->data(), csd->size());
1043
1044    return OK;
1045}
1046
1047status_t AVIExtractor::addH264CodecSpecificData(size_t trackIndex) {
1048    Track *track = &mTracks.editItemAt(trackIndex);
1049
1050    off64_t offset;
1051    size_t size;
1052    bool isKey;
1053    int64_t timeUs;
1054
1055    // Extract codec specific data from the first non-empty sample.
1056
1057    size_t sampleIndex = 0;
1058    for (;;) {
1059        status_t err =
1060            getSampleInfo(
1061                    trackIndex, sampleIndex, &offset, &size, &isKey, &timeUs);
1062
1063        if (err != OK) {
1064            return err;
1065        }
1066
1067        if (size > 0) {
1068            break;
1069        }
1070
1071        ++sampleIndex;
1072    }
1073
1074    sp<ABuffer> buffer = new ABuffer(size);
1075    ssize_t n = mDataSource->readAt(offset, buffer->data(), buffer->size());
1076
1077    if (n < (ssize_t)size) {
1078        return n < 0 ? (status_t)n : ERROR_MALFORMED;
1079    }
1080
1081    sp<MetaData> meta = MakeAVCCodecSpecificData(buffer);
1082
1083    if (meta == NULL) {
1084        ALOGE("Unable to extract AVC codec specific data");
1085        return ERROR_MALFORMED;
1086    }
1087
1088    int32_t width, height;
1089    CHECK(meta->findInt32(kKeyWidth, &width));
1090    CHECK(meta->findInt32(kKeyHeight, &height));
1091
1092    uint32_t type;
1093    const void *csd;
1094    size_t csdSize;
1095    CHECK(meta->findData(kKeyAVCC, &type, &csd, &csdSize));
1096
1097    track->mMeta->setInt32(kKeyWidth, width);
1098    track->mMeta->setInt32(kKeyHeight, height);
1099    track->mMeta->setData(kKeyAVCC, type, csd, csdSize);
1100
1101    return OK;
1102}
1103
1104status_t AVIExtractor::getSampleInfo(
1105        size_t trackIndex, size_t sampleIndex,
1106        off64_t *offset, size_t *size, bool *isKey,
1107        int64_t *sampleTimeUs) {
1108    if (trackIndex >= mTracks.size()) {
1109        return -ERANGE;
1110    }
1111
1112    const Track &track = mTracks.itemAt(trackIndex);
1113
1114    if (sampleIndex >= track.mSamples.size()) {
1115        return -ERANGE;
1116    }
1117
1118    const SampleInfo &info = track.mSamples.itemAt(sampleIndex);
1119
1120    if (!mOffsetsAreAbsolute) {
1121        *offset = info.mOffset + mMovieOffset + 8;
1122    } else {
1123        *offset = info.mOffset;
1124    }
1125
1126    *size = 0;
1127
1128    uint8_t tmp[8];
1129    ssize_t n = mDataSource->readAt(*offset, tmp, 8);
1130
1131    if (n < 8) {
1132        return n < 0 ? (status_t)n : (status_t)ERROR_MALFORMED;
1133    }
1134
1135    uint32_t chunkType = U32_AT(tmp);
1136
1137    if (!IsCorrectChunkType(trackIndex, track.mKind, chunkType)) {
1138        return ERROR_MALFORMED;
1139    }
1140
1141    *offset += 8;
1142    *size = U32LE_AT(&tmp[4]);
1143
1144    *isKey = info.mIsKey;
1145
1146    if (track.mBytesPerSample > 0) {
1147        size_t sampleStartInBytes;
1148        if (sampleIndex == 0) {
1149            sampleStartInBytes = 0;
1150        } else {
1151            sampleStartInBytes =
1152                track.mFirstChunkSize + track.mAvgChunkSize * (sampleIndex - 1);
1153        }
1154
1155        sampleIndex = sampleStartInBytes / track.mBytesPerSample;
1156    }
1157
1158    *sampleTimeUs = (sampleIndex * 1000000ll * track.mRate) / track.mScale;
1159
1160    return OK;
1161}
1162
1163status_t AVIExtractor::getSampleTime(
1164        size_t trackIndex, size_t sampleIndex, int64_t *sampleTimeUs) {
1165    off64_t offset;
1166    size_t size;
1167    bool isKey;
1168    return getSampleInfo(
1169            trackIndex, sampleIndex, &offset, &size, &isKey, sampleTimeUs);
1170}
1171
1172status_t AVIExtractor::getSampleIndexAtTime(
1173        size_t trackIndex,
1174        int64_t timeUs, MediaSource::ReadOptions::SeekMode mode,
1175        size_t *sampleIndex) const {
1176    if (trackIndex >= mTracks.size()) {
1177        return -ERANGE;
1178    }
1179
1180    const Track &track = mTracks.itemAt(trackIndex);
1181
1182    ssize_t closestSampleIndex;
1183
1184    if (track.mBytesPerSample > 0) {
1185        size_t closestByteOffset =
1186            (timeUs * track.mBytesPerSample)
1187                / track.mRate * track.mScale / 1000000ll;
1188
1189        if (closestByteOffset <= track.mFirstChunkSize) {
1190            closestSampleIndex = 0;
1191        } else {
1192            closestSampleIndex =
1193                (closestByteOffset - track.mFirstChunkSize)
1194                    / track.mAvgChunkSize;
1195        }
1196    } else {
1197        // Each chunk contains a single sample.
1198        closestSampleIndex = timeUs / track.mRate * track.mScale / 1000000ll;
1199    }
1200
1201    ssize_t numSamples = track.mSamples.size();
1202
1203    if (closestSampleIndex < 0) {
1204        closestSampleIndex = 0;
1205    } else if (closestSampleIndex >= numSamples) {
1206        closestSampleIndex = numSamples - 1;
1207    }
1208
1209    if (mode == MediaSource::ReadOptions::SEEK_CLOSEST) {
1210        *sampleIndex = closestSampleIndex;
1211
1212        return OK;
1213    }
1214
1215    ssize_t prevSyncSampleIndex = closestSampleIndex;
1216    while (prevSyncSampleIndex >= 0) {
1217        const SampleInfo &info =
1218            track.mSamples.itemAt(prevSyncSampleIndex);
1219
1220        if (info.mIsKey) {
1221            break;
1222        }
1223
1224        --prevSyncSampleIndex;
1225    }
1226
1227    ssize_t nextSyncSampleIndex = closestSampleIndex;
1228    while (nextSyncSampleIndex < numSamples) {
1229        const SampleInfo &info =
1230            track.mSamples.itemAt(nextSyncSampleIndex);
1231
1232        if (info.mIsKey) {
1233            break;
1234        }
1235
1236        ++nextSyncSampleIndex;
1237    }
1238
1239    switch (mode) {
1240        case MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC:
1241        {
1242            *sampleIndex = prevSyncSampleIndex;
1243
1244            return prevSyncSampleIndex >= 0 ? OK : UNKNOWN_ERROR;
1245        }
1246
1247        case MediaSource::ReadOptions::SEEK_NEXT_SYNC:
1248        {
1249            *sampleIndex = nextSyncSampleIndex;
1250
1251            return nextSyncSampleIndex < numSamples ? OK : UNKNOWN_ERROR;
1252        }
1253
1254        case MediaSource::ReadOptions::SEEK_CLOSEST_SYNC:
1255        {
1256            if (prevSyncSampleIndex < 0 && nextSyncSampleIndex >= numSamples) {
1257                return UNKNOWN_ERROR;
1258            }
1259
1260            if (prevSyncSampleIndex < 0) {
1261                *sampleIndex = nextSyncSampleIndex;
1262                return OK;
1263            }
1264
1265            if (nextSyncSampleIndex >= numSamples) {
1266                *sampleIndex = prevSyncSampleIndex;
1267                return OK;
1268            }
1269
1270            size_t dist1 = closestSampleIndex - prevSyncSampleIndex;
1271            size_t dist2 = nextSyncSampleIndex - closestSampleIndex;
1272
1273            *sampleIndex =
1274                (dist1 < dist2) ? prevSyncSampleIndex : nextSyncSampleIndex;
1275
1276            return OK;
1277        }
1278
1279        default:
1280            TRESPASS();
1281            break;
1282    }
1283}
1284
1285bool SniffAVI(
1286        const sp<DataSource> &source, String8 *mimeType, float *confidence,
1287        sp<AMessage> *) {
1288    char tmp[12];
1289    if (source->readAt(0, tmp, 12) < 12) {
1290        return false;
1291    }
1292
1293    if (!memcmp(tmp, "RIFF", 4) && !memcmp(&tmp[8], "AVI ", 4)) {
1294        mimeType->setTo(MEDIA_MIMETYPE_CONTAINER_AVI);
1295
1296        // Just a tad over the mp3 extractor's confidence, since
1297        // these .avi files may contain .mp3 content that otherwise would
1298        // mistakenly lead to us identifying the entire file as a .mp3 file.
1299        *confidence = 0.21;
1300
1301        return true;
1302    }
1303
1304    return false;
1305}
1306
1307}  // namespace android
1308