156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen/*
256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * Copyright (C) 2012 The Android Open Source Project
356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen *
456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * Licensed under the Apache License, Version 2.0 (the "License");
556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * you may not use this file except in compliance with the License.
656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * You may obtain a copy of the License at
756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen *
856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen *      http://www.apache.org/licenses/LICENSE-2.0
956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen *
1056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * Unless required by applicable law or agreed to in writing, software
1156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * distributed under the License is distributed on an "AS IS" BASIS,
1256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * See the License for the specific language governing permissions and
1456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen * limitations under the License.
1556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen */
1656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
1756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen//#define LOG_NDEBUG 0
1856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#define LOG_TAG "FragmentedMP4Extractor"
1956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <utils/Log.h>
2056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
2156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include "include/FragmentedMP4Extractor.h"
2256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include "include/SampleTable.h"
2356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include "include/ESDS.h"
2456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
2556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <arpa/inet.h>
2656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
2756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <ctype.h>
2856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <stdint.h>
2956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <stdlib.h>
3056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <string.h>
3156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
3256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <cutils/properties.h> // for property_get
3356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
3456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/foundation/ABitReader.h>
3556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/foundation/ABuffer.h>
3656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/foundation/ADebug.h>
3756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/foundation/AMessage.h>
3856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/DataSource.h>
3956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/MediaBuffer.h>
4056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/MediaBufferGroup.h>
4156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/MediaDefs.h>
4256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/MediaSource.h>
4356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/MetaData.h>
4456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <media/stagefright/Utils.h>
4556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen#include <utils/String8.h>
4656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
4756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissennamespace android {
4856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
4956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenclass FragmentedMPEG4Source : public MediaSource {
5056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenpublic:
5156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    // Caller retains ownership of the Parser
5256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    FragmentedMPEG4Source(bool audio,
5356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                const sp<MetaData> &format,
5456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                const sp<FragmentedMP4Parser> &parser,
5556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                const sp<FragmentedMP4Extractor> &extractor);
5656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
5756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual status_t start(MetaData *params = NULL);
5856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual status_t stop();
5956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
6056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual sp<MetaData> getFormat();
6156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
6256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual status_t read(
6356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            MediaBuffer **buffer, const ReadOptions *options = NULL);
6456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
6556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenprotected:
6656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    virtual ~FragmentedMPEG4Source();
6756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
6856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenprivate:
6956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    Mutex mLock;
7056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
7156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<MetaData> mFormat;
7256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<FragmentedMP4Parser> mParser;
7356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<FragmentedMP4Extractor> mExtractor;
7456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool mIsAudioTrack;
7556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint32_t mCurrentSampleIndex;
7656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
7756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool mIsAVC;
7856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    size_t mNALLengthSize;
7956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
8056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool mStarted;
8156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
8256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    MediaBufferGroup *mGroup;
8356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
8456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool mWantsNALFragments;
8556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
8656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    uint8_t *mSrcBuffer;
8756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
8856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    FragmentedMPEG4Source(const FragmentedMPEG4Source &);
8956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    FragmentedMPEG4Source &operator=(const FragmentedMPEG4Source &);
9056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen};
9156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
9256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
9356997121c5031598fbbba7b7c53980b7fd529c2dMarco NelissenFragmentedMP4Extractor::FragmentedMP4Extractor(const sp<DataSource> &source)
9456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    : mLooper(new ALooper),
9556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mParser(new FragmentedMP4Parser()),
9656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mDataSource(source),
9756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mInitCheck(NO_INIT),
9856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mFileMetaData(new MetaData) {
9956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("FragmentedMP4Extractor");
10056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mLooper->registerHandler(mParser);
10156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mLooper->start(false /* runOnCallingThread */);
10256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mParser->start(mDataSource);
10356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
10456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool hasVideo = mParser->getFormat(false /* audio */, true /* synchronous */) != NULL;
10556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool hasAudio = mParser->getFormat(true /* audio */, true /* synchronous */) != NULL;
10656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
10756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("number of tracks: %d", countTracks());
10856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
10956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (hasVideo) {
11056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mFileMetaData->setCString(
11156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                kKeyMIMEType, MEDIA_MIMETYPE_CONTAINER_MPEG4);
11256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else if (hasAudio) {
11356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mFileMetaData->setCString(kKeyMIMEType, "audio/mp4");
11456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else {
11556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGE("no audio and no video, no idea what file type this is");
11656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
11756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    // tracks are numbered such that video track is first, audio track is second
11856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (hasAudio && hasVideo) {
11956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mTrackCount = 2;
12056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mAudioTrackIndex = 1;
12156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else if (hasAudio) {
12256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mTrackCount = 1;
12356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mAudioTrackIndex = 0;
12456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else if (hasVideo) {
12556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mTrackCount = 1;
12656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mAudioTrackIndex = -1;
12756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else {
12856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mTrackCount = 0;
12956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mAudioTrackIndex = -1;
13056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
13156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
13256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
13356997121c5031598fbbba7b7c53980b7fd529c2dMarco NelissenFragmentedMP4Extractor::~FragmentedMP4Extractor() {
13456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("~FragmentedMP4Extractor");
13556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mLooper->stop();
13656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
13756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
13856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenuint32_t FragmentedMP4Extractor::flags() const {
13956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return CAN_PAUSE |
14056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            (mParser->isSeekable() ? (CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_SEEK) : 0);
14156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
14256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
14356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissensp<MetaData> FragmentedMP4Extractor::getMetaData() {
14456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return mFileMetaData;
14556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
14656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
14756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissensize_t FragmentedMP4Extractor::countTracks() {
14856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return mTrackCount;
14956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
15056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
15156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
15256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissensp<MetaData> FragmentedMP4Extractor::getTrackMetaData(
15356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        size_t index, uint32_t flags) {
15456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (index >= countTracks()) {
15556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return NULL;
15656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
15756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
15856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<AMessage> msg = mParser->getFormat(index == mAudioTrackIndex, true /* synchronous */);
15956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
16056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (msg == NULL) {
16156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV("got null format for track %d", index);
16256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return NULL;
16356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
16456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
16556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<MetaData> meta = new MetaData();
16656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    convertMessageToMetaData(msg, meta);
16756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return meta;
16856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
16956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
17056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic void MakeFourCCString(uint32_t x, char *s) {
17156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    s[0] = x >> 24;
17256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    s[1] = (x >> 16) & 0xff;
17356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    s[2] = (x >> 8) & 0xff;
17456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    s[3] = x & 0xff;
17556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    s[4] = '\0';
17656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
17756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
17856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissensp<MediaSource> FragmentedMP4Extractor::getTrack(size_t index) {
17956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (index >= countTracks()) {
18056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return NULL;
18156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
18256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return new FragmentedMPEG4Source(index == mAudioTrackIndex, getTrackMetaData(index, 0), mParser, this);
18356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
18456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
18556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
18656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen////////////////////////////////////////////////////////////////////////////////
18756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
18856997121c5031598fbbba7b7c53980b7fd529c2dMarco NelissenFragmentedMPEG4Source::FragmentedMPEG4Source(
18956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        bool audio,
19056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        const sp<MetaData> &format,
19156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        const sp<FragmentedMP4Parser> &parser,
19256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        const sp<FragmentedMP4Extractor> &extractor)
19356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    : mFormat(format),
19456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mParser(parser),
19556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mExtractor(extractor),
19656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mIsAudioTrack(audio),
19756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mStarted(false),
19856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mGroup(NULL),
19956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mWantsNALFragments(false),
20056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen      mSrcBuffer(NULL) {
20156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
20256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
20356997121c5031598fbbba7b7c53980b7fd529c2dMarco NelissenFragmentedMPEG4Source::~FragmentedMPEG4Source() {
20456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (mStarted) {
20556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        stop();
20656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
20756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
20856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
20956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMPEG4Source::start(MetaData *params) {
21056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    Mutex::Autolock autoLock(mLock);
21156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
21256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    CHECK(!mStarted);
21356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
21456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    int32_t val;
21556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (params && params->findInt32(kKeyWantsNALFragments, &val)
21656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        && val != 0) {
21756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mWantsNALFragments = true;
21856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    } else {
21956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mWantsNALFragments = false;
22056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
22156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("caller wants NAL fragments: %s", mWantsNALFragments ? "yes" : "no");
22256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
22356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mGroup = new MediaBufferGroup;
22456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
22556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    int32_t max_size = 65536;
22656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    // XXX CHECK(mFormat->findInt32(kKeyMaxInputSize, &max_size));
22756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
22856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mGroup->add_buffer(new MediaBuffer(max_size));
22956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
23056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mSrcBuffer = new uint8_t[max_size];
23156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
23256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mStarted = true;
23356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
23456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return OK;
23556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
23656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
23756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMPEG4Source::stop() {
23856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    Mutex::Autolock autoLock(mLock);
23956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
24056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    CHECK(mStarted);
24156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
24256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    delete[] mSrcBuffer;
24356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mSrcBuffer = NULL;
24456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
24556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    delete mGroup;
24656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mGroup = NULL;
24756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
24856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mStarted = false;
24956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mCurrentSampleIndex = 0;
25056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
25156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return OK;
25256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
25356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
25456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissensp<MetaData> FragmentedMPEG4Source::getFormat() {
25556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    Mutex::Autolock autoLock(mLock);
25656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
25756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return mFormat;
25856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
25956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
26056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
26156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatus_t FragmentedMPEG4Source::read(
26256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        MediaBuffer **out, const ReadOptions *options) {
26356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    int64_t seekTimeUs;
26456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ReadOptions::SeekMode mode;
26556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (options && options->getSeekTo(&seekTimeUs, &mode)) {
26656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        mParser->seekTo(mIsAudioTrack, seekTimeUs);
26756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
26856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    MediaBuffer *buffer = NULL;
26956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    mGroup->acquire_buffer(&buffer);
27056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<ABuffer> parseBuffer;
27156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
27256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    status_t ret = mParser->dequeueAccessUnit(mIsAudioTrack, &parseBuffer, true /* synchronous */);
27356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (ret != OK) {
27456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        buffer->release();
27556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV("returning %d", ret);
27656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return ret;
27756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
27856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    sp<AMessage> meta = parseBuffer->meta();
27956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    int64_t timeUs;
28056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    CHECK(meta->findInt64("timeUs", &timeUs));
28156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    buffer->meta_data()->setInt64(kKeyTime, timeUs);
28256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    buffer->set_range(0, parseBuffer->size());
28356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    memcpy(buffer->data(), parseBuffer->data(), parseBuffer->size());
28456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    *out = buffer;
28556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return OK;
28656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
28756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
28856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
28956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic bool isCompatibleBrand(uint32_t fourcc) {
29056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    static const uint32_t kCompatibleBrands[] = {
29156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('i', 's', 'o', 'm'),
29256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('i', 's', 'o', '2'),
29356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('a', 'v', 'c', '1'),
29456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('3', 'g', 'p', '4'),
29556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('m', 'p', '4', '1'),
29656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('m', 'p', '4', '2'),
29756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
29856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        // Won't promise that the following file types can be played.
29956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        // Just give these file types a chance.
30056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('q', 't', ' ', ' '),  // Apple's QuickTime
30156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('M', 'S', 'N', 'V'),  // Sony's PSP
30256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
30356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('3', 'g', '2', 'a'),  // 3GPP2
30456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        FOURCC('3', 'g', '2', 'b'),
30556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    };
30656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
30756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    for (size_t i = 0;
30856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen         i < sizeof(kCompatibleBrands) / sizeof(kCompatibleBrands[0]);
30956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen         ++i) {
31056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (kCompatibleBrands[i] == fourcc) {
31156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return true;
31256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
31356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
31456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
31556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return false;
31656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
31756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
31856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen// Attempt to actually parse the 'ftyp' atom and determine if a suitable
31956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen// compatible brand is present.
32056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen// Also try to identify where this file's metadata ends
32156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen// (end of the 'moov' atom) and report it to the caller as part of
32256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen// the metadata.
32356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenstatic bool Sniff(
32456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        const sp<DataSource> &source, String8 *mimeType, float *confidence,
32556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> *meta) {
32656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    // We scan up to 128k bytes to identify this file as an MP4.
32756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    static const off64_t kMaxScanOffset = 128ll * 1024ll;
32856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
32956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    off64_t offset = 0ll;
33056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool foundGoodFileType = false;
33156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool isFragmented = false;
33256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    off64_t moovAtomEndOffset = -1ll;
33356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    bool done = false;
33456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
33556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    while (!done && offset < kMaxScanOffset) {
33656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint32_t hdr[2];
33756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (source->readAt(offset, hdr, 8) < 8) {
33856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return false;
33956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
34056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
34156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint64_t chunkSize = ntohl(hdr[0]);
34256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        uint32_t chunkType = ntohl(hdr[1]);
34356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        off64_t chunkDataOffset = offset + 8;
34456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
34556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        if (chunkSize == 1) {
34656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (source->readAt(offset + 8, &chunkSize, 8) < 8) {
34756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                return false;
34856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
34956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
35056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            chunkSize = ntoh64(chunkSize);
35156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            chunkDataOffset += 8;
35256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
35356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            if (chunkSize < 16) {
35456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                // The smallest valid chunk is 16 bytes long in this case.
35556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                return false;
35656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
35756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        } else if (chunkSize < 8) {
35856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            // The smallest valid chunk is 8 bytes long.
35956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            return false;
36056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
36156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
36256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        off64_t chunkDataSize = offset + chunkSize - chunkDataOffset;
36356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
36456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        char chunkstring[5];
36556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        MakeFourCCString(chunkType, chunkstring);
36656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV("saw chunk type %s, size %lld @ %lld", chunkstring, chunkSize, offset);
36756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        switch (chunkType) {
36856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            case FOURCC('f', 't', 'y', 'p'):
36956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            {
37056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                if (chunkDataSize < 8) {
37156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    return false;
37256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                }
37356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
37456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                uint32_t numCompatibleBrands = (chunkDataSize - 8) / 4;
37556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                for (size_t i = 0; i < numCompatibleBrands + 2; ++i) {
37656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    if (i == 1) {
37756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        // Skip this index, it refers to the minorVersion,
37856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        // not a brand.
37956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        continue;
38056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    }
38156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
38256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    uint32_t brand;
38356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    if (source->readAt(
38456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                                chunkDataOffset + 4 * i, &brand, 4) < 4) {
38556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        return false;
38656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    }
38756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
38856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    brand = ntohl(brand);
38956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    char brandstring[5];
39056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    MakeFourCCString(brand, brandstring);
39156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    ALOGV("Brand: %s", brandstring);
39256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
39356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    if (isCompatibleBrand(brand)) {
39456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        foundGoodFileType = true;
39556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                        break;
39656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    }
39756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                }
39856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
39956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                if (!foundGoodFileType) {
40056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                    return false;
40156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                }
40256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
40356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                break;
40456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
40556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
40656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            case FOURCC('m', 'o', 'o', 'v'):
40756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            {
40856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                moovAtomEndOffset = offset + chunkSize;
40956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                break;
41056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
41156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
41256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            case FOURCC('m', 'o', 'o', 'f'):
41356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            {
41456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                // this is kind of broken, since we might not actually find a
41556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                // moof box in the first 128k.
41656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                isFragmented = true;
41756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                done = true;
41856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                break;
41956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            }
42056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
42156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            default:
42256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen                break;
42356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        }
42456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
42556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        offset += chunkSize;
42656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
42756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
42856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (!foundGoodFileType || !isFragmented) {
42956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return false;
43056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
43156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
43256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    *mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
43356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    *confidence = 0.5f; // slightly more than MPEG4Extractor
43456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
43556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (moovAtomEndOffset >= 0) {
43656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        *meta = new AMessage;
43756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        (*meta)->setInt64("meta-data-size", moovAtomEndOffset);
43856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        (*meta)->setInt32("fragmented", 1); // tell MediaExtractor what to instantiate
43956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
44056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        ALOGV("found metadata size: %lld", moovAtomEndOffset);
44156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
44256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
44356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return true;
44456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
44556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
44656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen// used by DataSource::RegisterDefaultSniffers
44756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissenbool SniffFragmentedMP4(
44856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        const sp<DataSource> &source, String8 *mimeType, float *confidence,
44956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        sp<AMessage> *meta) {
45056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    ALOGV("SniffFragmentedMP4");
45156997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    char prop[PROPERTY_VALUE_MAX];
45256997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    if (property_get("media.stagefright.use-fragmp4", prop, NULL)
45356997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen            && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) {
45456997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen        return Sniff(source, mimeType, confidence, meta);
45556997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    }
45656997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
45756997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen    return false;
45856997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}
45956997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen
46056997121c5031598fbbba7b7c53980b7fd529c2dMarco Nelissen}  // namespace android
461