blob: 3aee9e46ec3c00ab3136e3f436ebfd50985c8a51 [file] [log] [blame]
/*
* 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 <media/stagefright/foundation/AHandler.h>
#include <media/stagefright/foundation/ALooper.h>
#include <media/stagefright/foundation/AMessage.h>
//--------------------------------------------------------------------------------------------------
/**
* 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 = 'prep',
kEventHasVideoSize = 'vsiz',
kEventPrefetchStatusChange = 'pfsc',
kEventPrefetchFillLevelUpdate = 'pflu',
kEventEndOfStream = 'eos',
kEventChannelCount = 'ccnt',
kEventPlay = 'play', // SL_PLAYEVENT_*
kEventErrorAfterPrepare = 'easp', // error after successful prepare
};
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<IGraphicBufferProducer> &bufferProducer) {}
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 = 'prep', // start preparation
kWhatNotif = 'noti', // send a notification to client
kWhatPlay = 'play', // start player
kWhatPause = 'paus', // pause or stop player
kWhatSeek = 'seek', // request a seek to specified position
kWhatSeekComplete = 'skcp', // seek request has completed
kWhatLoop = 'loop', // set the player's looping status
kWhatVolumeUpdate = 'volu', // set the channel gains to specified values
kWhatBufferingUpdate = 'bufu',
kWhatBuffUpdateThres = 'buut',
kWhatAttachAuxEffect = 'aaux',
kWhatSetAuxEffectSendLevel = 'saux',
kWhatSetPlayEvents = 'spev', // process new IPlay settings related to SL_PLAYEVENT_*
kWhatOneShot = 'ones', // 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<AMessage> &msg);
// Async event handlers (called from GenericPlayer's event loop)
virtual void onPrepare();
virtual void onNotify(const sp<AMessage> &msg);
virtual void onPlay();
virtual void onPause();
virtual void onSeek(const sp<AMessage> &msg);
virtual void onLoop(const sp<AMessage> &msg);
virtual void onVolumeUpdate();
virtual void onSeekComplete();
virtual void onBufferingUpdate(const sp<AMessage> &msg);
virtual void onSetBufferingUpdateThreshold(const sp<AMessage> &msg);
virtual void onAttachAuxEffect(const sp<AMessage> &msg);
virtual void onSetAuxEffectSendLevel(const sp<AMessage> &msg);
void onSetPlayEvents(const sp<AMessage> &msg);
void onOneShot(const sp<AMessage> &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<ALooper> 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__ */