/* * Copyright (C) 2011 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. */ #ifndef __ANDROID_GENERICPLAYER_H__ #define __ANDROID_GENERICPLAYER_H__ #include #include #include //-------------------------------------------------------------------------------------------------- /** * Message parameters for AHandler messages, see list in GenericPlayer::kWhatxxx */ #define WHATPARAM_SEEK_SEEKTIME_MS "seekTimeMs" #define WHATPARAM_LOOP_LOOPING "looping" #define WHATPARAM_BUFFERING_UPDATE "bufferingUpdate" #define WHATPARAM_BUFFERING_UPDATETHRESHOLD_PERCENT "buffUpdateThreshold" #define WHATPARAM_ATTACHAUXEFFECT "attachAuxEffect" #define WHATPARAM_SETAUXEFFECTSENDLEVEL "setAuxEffectSendLevel" // Parameters for kWhatSetPlayEvents #define WHATPARAM_SETPLAYEVENTS_FLAGS "setPlayEventsFlags" #define WHATPARAM_SETPLAYEVENTS_MARKER "setPlayEventsMarker" #define WHATPARAM_SETPLAYEVENTS_UPDATE "setPlayEventsUpdate" // Parameters for kWhatOneShot (see explanation at definition of kWhatOneShot below) #define WHATPARAM_ONESHOT_GENERATION "oneShotGeneration" namespace android { // abstract base class class GenericPlayer : public AHandler { public: enum { kEventPrepared = 0, kEventHasVideoSize = 1, kEventPrefetchStatusChange = 2, kEventPrefetchFillLevelUpdate = 3, kEventEndOfStream = 4, kEventChannelCount = 5, kEventPlay = 6, // SL_PLAYEVENT_* kEventErrorAfterPrepare = 7, // error after successful prepare }; explicit GenericPlayer(const AudioPlayback_Parameters* params); virtual ~GenericPlayer(); void init(const notif_cbf_t cbf, void* notifUser); virtual void preDestroy(); void setDataSource(const char *uri); void setDataSource(int fd, int64_t offset, int64_t length, bool closeAfterUse = false); void prepare(); virtual void play(); void pause(); void stop(); // timeMsec must be >= 0 or == ANDROID_UNKNOWN_TIME (used by StreamPlayer after discontinuity) void seek(int64_t timeMsec); void loop(bool loop); void setBufferingUpdateThreshold(int16_t thresholdPercent); void getDurationMsec(int* msec); //msec != NULL, ANDROID_UNKNOWN_TIME if unknown virtual void getPositionMsec(int* msec) = 0; //msec != NULL, ANDROID_UNKNOWN_TIME if unknown virtual void setVideoSurfaceTexture(const sp &bufferProducer __unused) { } void setVolume(float leftVol, float rightVol); void attachAuxEffect(int32_t effectId); void setAuxEffectSendLevel(float level); virtual void setPlaybackRate(int32_t ratePermille); // Call after changing any of the IPlay settings related to SL_PLAYEVENT_* void setPlayEvents(int32_t eventFlags, int32_t markerPosition, int32_t positionUpdatePeriod); protected: // mutex used for set vs use of volume, duration, and cache (fill, threshold) settings Mutex mSettingsLock; void resetDataLocator(); DataLocator2 mDataLocator; int mDataLocatorType; // Constants used to identify the messages in this player's AHandler message loop // in onMessageReceived() enum { kWhatPrepare = 0, // start preparation kWhatNotif = 1, // send a notification to client kWhatPlay = 2, // start player kWhatPause = 3, // pause or stop player kWhatSeek = 4, // request a seek to specified position kWhatSeekComplete = 5, // seek request has completed kWhatLoop = 6, // set the player's looping status kWhatVolumeUpdate = 7, // set the channel gains to specified values kWhatBufferingUpdate = 8, kWhatBuffUpdateThres = 9, kWhatAttachAuxEffect = 10, kWhatSetAuxEffectSendLevel = 11, kWhatSetPlayEvents = 12, // process new IPlay settings related to SL_PLAYEVENT_* kWhatOneShot = 13, // deferred (non-0 timeout) handler for SL_PLAYEVENT_* // As used here, "one-shot" is the software equivalent of a "retriggerable monostable // multivibrator" from electronics. Briefly, a one-shot is a timer that can be triggered // to fire at some point in the future. It is "retriggerable" because while the timer // is active, it is possible to replace the current timeout value by a new value. // This is done by cancelling the current timer (using a generation count), // and then posting another timer with the new desired value. }; // Send a notification to one of the event listeners virtual void notify(const char* event, int data1, bool async); virtual void notify(const char* event, int data1, int data2, bool async); // AHandler implementation virtual void onMessageReceived(const sp &msg); // Async event handlers (called from GenericPlayer's event loop) virtual void onPrepare(); virtual void onNotify(const sp &msg); virtual void onPlay(); virtual void onPause(); virtual void onSeek(const sp &msg); virtual void onLoop(const sp &msg); virtual void onVolumeUpdate(); virtual void onSeekComplete(); virtual void onBufferingUpdate(const sp &msg); virtual void onSetBufferingUpdateThreshold(const sp &msg); virtual void onAttachAuxEffect(const sp &msg); virtual void onSetAuxEffectSendLevel(const sp &msg); void onSetPlayEvents(const sp &msg); void onOneShot(const sp &msg); // Convenience methods // for async notifications of prefetch status and cache fill level, needs to be called // with mSettingsLock locked void notifyStatus(); void notifyCacheFill(); // for internal async notification to update state that the player is no longer seeking void seekComplete(); void bufferingUpdate(int16_t fillLevelPerMille); // Event notification from GenericPlayer to OpenSL ES / OpenMAX AL framework notif_cbf_t mNotifyClient; void* mNotifyUser; // lock to protect mNotifyClient and mNotifyUser updates Mutex mNotifyClientLock; // Bits for mStateFlags enum { kFlagPrepared = 1 << 0, // use only for successful preparation kFlagPreparing = 1 << 1, kFlagPlaying = 1 << 2, kFlagBuffering = 1 << 3, kFlagSeeking = 1 << 4, // set if we (not Stagefright) initiated a seek kFlagLooping = 1 << 5, // set if looping is enabled kFlagPreparedUnsuccessfully = 1 << 6, }; // Only accessed from event loop, does not need a mutex uint32_t mStateFlags; sp mLooper; const AudioPlayback_Parameters mPlaybackParams; // protected by mSettingsLock after construction AndroidAudioLevels mAndroidAudioLevels; // protected by mSettingsLock int32_t mDurationMsec; int16_t mPlaybackRatePermille; CacheStatus_t mCacheStatus; int16_t mCacheFill; // cache fill level + played back 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 // Call any time any of the IPlay copies, current position, or play state changes, and // supply the latest known position or ANDROID_UNKNOWN_TIME if position is unknown to caller. void updateOneShot(int positionMs = ANDROID_UNKNOWN_TIME); // players that "render" data to present it to the user (a music player, a video player), // should return true, while players that only decode (hopefully faster than "real time") // should return false. virtual bool advancesPositionInRealTime() const { return true; } private: // Our copy of some important IPlay member variables, except in Android units int32_t mEventFlags; int32_t mMarkerPositionMs; int32_t mPositionUpdatePeriodMs; // We need to be able to cancel any pending one-shot event(s) prior to posting // a new one-shot. As AMessage does not currently support cancellation by // "what" category, we simulate this by keeping a generation counter for // one-shots. When a one-shot event is delivered, it checks to see if it is // still the current one-shot. If not, it returns immediately, thus // effectively cancelling itself. Note that counter wrap-around is possible // but unlikely and benign. int32_t mOneShotGeneration; // Play position at time of the most recently delivered SL_PLAYEVENT_HEADATNEWPOS, // or ANDROID_UNKNOWN_TIME if a SL_PLAYEVENT_HEADATNEWPOS has never been delivered. int32_t mDeliveredNewPosMs; // Play position most recently observed by updateOneShot, or ANDROID_UNKNOWN_TIME // if the play position has never been observed. int32_t mObservedPositionMs; DISALLOW_EVIL_CONSTRUCTORS(GenericPlayer); }; } // namespace android extern void android_player_volumeUpdate(float *pVolumes /*[2]*/, const IVolume *volumeItf, unsigned channelCount, float amplFromDirectLevel, const bool *audibilityFactors /*[2]*/); #endif /* __ANDROID_GENERICPLAYER_H__ */