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