/* * Copyright (C) 2010 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include <binder/ProcessState.h> #include <sys/stat.h> #include <media/AudioTrack.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AHandler.h> #include <media/stagefright/foundation/ALooper.h> #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/DataSource.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaExtractor.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> #include "NuCachedSource2.h" #include "NuHTTPDataSource.h" #include "ThrottledSource.h" #ifdef USERDEBUG_BUILD #define _DEBUG_AUDIO_TESTS 1 #endif #define DURATION_CACHED_HIGH_US 30000000 // 30s #define DURATION_CACHED_MED_US 10000000 // 10s #define DURATION_CACHED_LOW_US 2000000 // 2s /* * by how much time data is written to the AudioTrack ahead of the scheduled render time */ #define RENDER_SAFETY_DELAY_US 5000 // 5ms #define SIZE_CACHED_HIGH_BYTES 1000000 #define SIZE_CACHED_MED_BYTES 700000 #define SIZE_CACHED_LOW_BYTES 400000 /* * events sent to mNotifyClient during prepare, prefetch, and playback */ #define EVENT_PREPARED "prep" #define EVENT_PREFETCHSTATUSCHANGE "prsc" #define EVENT_PREFETCHFILLLEVELUPDATE "pflu" #define EVENT_ENDOFSTREAM "eos" #define EVENT_NEW_AUDIOTRACK "nwat" #define SFPLAYER_SUCCESS 1 #define SFPLAYER_FD_FIND_FILE_SIZE ((int64_t)0xFFFFFFFFFFFFFFFFll) #define NO_FILL_LEVEL_UPDATE -1 #define NO_STATUS_UPDATE kStatusUnknown typedef struct AudioPlayback_Parameters_struct { int streamType; int sessionId; android::AudioTrack::callback_t trackcb; void* trackcbUser; } AudioPlayback_Parameters; namespace android { typedef void (*notif_client_t)(int event, const int data1, void* notifUser); struct SfPlayer : public AHandler { SfPlayer(AudioPlayback_Parameters *app); enum CacheStatus { kStatusUnknown = -1, kStatusEmpty = 0, kStatusLow, kStatusIntermediate, kStatusEnough, kStatusHigh }; enum { kEventPrepared = 'prep', kEventPrefetchStatusChange = 'prsc', kEventPrefetchFillLevelUpdate = 'pflu', kEventEndOfStream = 'eos', kEventNewAudioTrack = 'nwat' }; void armLooper(); void setNotifListener(const notif_client_t cbf, void* notifUser); void setDataSource(const char *uri); void setDataSource(const int fd, const int64_t offset, const int64_t length); void setCacheFillUpdateThreshold(int16_t thr) { mCacheFillNotifThreshold = thr; } void prepare(); void play(); void pause(); void stop(); void seek(int64_t timeMsec); void loop(bool loop); bool wantPrefetch(); void startPrefetch_async(); /** * returns the duration in microseconds, -1 if unknown */ int64_t getDurationUsec() { return mDurationUsec; } int32_t getNumChannels() { return mNumChannels; } int32_t getSampleRateHz() { return mSampleRateHz; } AudioTrack* getAudioTrack() { return mAudioTrack; } uint32_t getPositionMsec(); protected: virtual ~SfPlayer(); virtual void onMessageReceived(const sp<AMessage> &msg); private: enum { kDataLocatorNone = 'none', kDataLocatorUri = 'uri', kDataLocatorFd = 'fd', }; enum { kWhatPrepare = 'prep', kWhatDecode = 'deco', kWhatRender = 'rend', kWhatCheckCache = 'cach', kWhatNotif = 'noti', kWhatPlay = 'play', kWhatPause = 'paus', kWhatSeek = 'seek', kWhatLoop = 'loop', }; enum { kFlagPlaying = 1, kFlagPreparing = 2, kFlagBuffering = 4, kFlagSeeking = 8, kFlagLooping = 16, }; struct FdInfo { int fd; int64_t offset; int64_t length; }; union DataLocator { char* uri; FdInfo fdi; }; #ifdef _DEBUG_AUDIO_TESTS FILE *mMonitorAudioFp; // Automated tests #endif // mutex used for seek flag and seek time read/write Mutex mSeekLock; AudioTrack *mAudioTrack; sp<ALooper> mRenderLooper; sp<DataSource> mDataSource; sp<MediaSource> mAudioSource; uint32_t mFlags; int64_t mBitrate; // in bits/sec int32_t mNumChannels; int32_t mSampleRateHz; int64_t mTimeDelta; int64_t mDurationUsec; CacheStatus mCacheStatus; int64_t mSeekTimeMsec; int64_t mLastDecodedPositionUs; int16_t mCacheFill; // cache fill level in permille int16_t mLastNotifiedCacheFill; // last cache fill level communicated to the listener int16_t mCacheFillNotifThreshold; // threshold in cache fill level for cache fill to be reported AudioPlayback_Parameters mPlaybackParams; DataLocator mDataLocator; int mDataLocatorType; notif_client_t mNotifyClient; void* mNotifyUser; // mutex used for protecting the decode buffer Mutex mDecodeBufferLock; // buffer passed from decoder to renderer MediaBuffer *mDecodeBuffer; // message handlers void onPrepare(const sp<AMessage> &msg); void onDecode(); void onRender(const sp<AMessage> &msg); void onCheckCache(const sp<AMessage> &msg); void onNotify(const sp<AMessage> &msg); void onPlay(); void onPause(); void onSeek(const sp<AMessage> &msg); void onLoop(const sp<AMessage> &msg); CacheStatus getCacheRemaining(bool *eos); int64_t getPositionUsec(); void reachedEndOfStream(); void updatePlaybackParamsFromSource(); void notifyStatus(); void notifyCacheFill(); void notifyPrepared(status_t prepareRes); void notify(const sp<AMessage> &msg, bool async); void resetDataLocator(); DISALLOW_EVIL_CONSTRUCTORS(SfPlayer); }; } // namespace android