/* * Copyright (C) 2009 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 AWESOME_PLAYER_H_ #define AWESOME_PLAYER_H_ #include "HTTPBase.h" #include "TimedEventQueue.h" #include #include #include #include #include #include #include namespace android { struct AudioPlayer; struct ClockEstimator; struct DataSource; struct MediaBuffer; struct MediaExtractor; struct MediaSource; struct NuCachedSource2; struct IGraphicBufferProducer; class DrmManagerClinet; class DecryptHandle; class TimedTextDriver; struct WVMExtractor; struct AwesomeRenderer : public RefBase { AwesomeRenderer() {} virtual void render(MediaBuffer *buffer) = 0; private: AwesomeRenderer(const AwesomeRenderer &); AwesomeRenderer &operator=(const AwesomeRenderer &); }; struct AwesomePlayer { AwesomePlayer(); ~AwesomePlayer(); void setListener(const wp &listener); void setUID(uid_t uid); status_t setDataSource( const char *uri, const KeyedVector *headers = NULL); status_t setDataSource(int fd, int64_t offset, int64_t length); status_t setDataSource(const sp &source); void reset(); status_t prepare(); status_t prepare_l(); status_t prepareAsync(); status_t prepareAsync_l(); status_t play(); status_t pause(); bool isPlaying() const; status_t setSurfaceTexture(const sp &bufferProducer); void setAudioSink(const sp &audioSink); status_t setLooping(bool shouldLoop); status_t getDuration(int64_t *durationUs); status_t getPosition(int64_t *positionUs); status_t setParameter(int key, const Parcel &request); status_t getParameter(int key, Parcel *reply); status_t invoke(const Parcel &request, Parcel *reply); status_t setCacheStatCollectFreq(const Parcel &request); status_t seekTo(int64_t timeUs); // This is a mask of MediaExtractor::Flags. uint32_t flags() const; void postAudioEOS(int64_t delayUs = 0ll); void postAudioSeekComplete(); void postAudioTearDown(); status_t dump(int fd, const Vector &args) const; private: friend struct AwesomeEvent; friend struct PreviewPlayer; enum { PLAYING = 0x01, LOOPING = 0x02, FIRST_FRAME = 0x04, PREPARING = 0x08, PREPARED = 0x10, AT_EOS = 0x20, PREPARE_CANCELLED = 0x40, CACHE_UNDERRUN = 0x80, AUDIO_AT_EOS = 0x0100, VIDEO_AT_EOS = 0x0200, AUTO_LOOPING = 0x0400, // We are basically done preparing but are currently buffering // sufficient data to begin playback and finish the preparation phase // for good. PREPARING_CONNECTED = 0x0800, // We're triggering a single video event to display the first frame // after the seekpoint. SEEK_PREVIEW = 0x1000, AUDIO_RUNNING = 0x2000, AUDIOPLAYER_STARTED = 0x4000, INCOGNITO = 0x8000, TEXT_RUNNING = 0x10000, TEXTPLAYER_INITIALIZED = 0x20000, SLOW_DECODER_HACK = 0x40000, }; mutable Mutex mLock; Mutex mMiscStateLock; mutable Mutex mStatsLock; Mutex mAudioLock; OMXClient mClient; TimedEventQueue mQueue; bool mQueueStarted; wp mListener; bool mUIDValid; uid_t mUID; sp mNativeWindow; sp mAudioSink; SystemTimeSource mSystemTimeSource; TimeSource *mTimeSource; String8 mUri; KeyedVector mUriHeaders; sp mFileSource; sp mVideoTrack; sp mVideoSource; sp mVideoRenderer; bool mVideoRenderingStarted; bool mVideoRendererIsPreview; int32_t mMediaRenderingStartGeneration; int32_t mStartGeneration; ssize_t mActiveAudioTrackIndex; sp mAudioTrack; sp mOmxSource; sp mAudioSource; AudioPlayer *mAudioPlayer; int64_t mDurationUs; int32_t mDisplayWidth; int32_t mDisplayHeight; int32_t mVideoScalingMode; uint32_t mFlags; uint32_t mExtractorFlags; uint32_t mSinceLastDropped; int64_t mTimeSourceDeltaUs; int64_t mVideoTimeUs; enum SeekType { NO_SEEK, SEEK, SEEK_VIDEO_ONLY }; SeekType mSeeking; bool mSeekNotificationSent; int64_t mSeekTimeUs; int64_t mBitrate; // total bitrate of the file (in bps) or -1 if unknown. bool mWatchForAudioSeekComplete; bool mWatchForAudioEOS; sp mVideoEvent; bool mVideoEventPending; sp mStreamDoneEvent; bool mStreamDoneEventPending; sp mBufferingEvent; bool mBufferingEventPending; sp mCheckAudioStatusEvent; bool mAudioStatusEventPending; sp mVideoLagEvent; bool mVideoLagEventPending; sp mAudioTearDownEvent; bool mAudioTearDownEventPending; sp mAsyncPrepareEvent; Condition mPreparedCondition; bool mIsAsyncPrepare; status_t mPrepareResult; status_t mStreamDoneStatus; void postVideoEvent_l(int64_t delayUs = -1); void postBufferingEvent_l(); void postStreamDoneEvent_l(status_t status); void postCheckAudioStatusEvent(int64_t delayUs); void postVideoLagEvent_l(); void postAudioTearDownEvent(int64_t delayUs); status_t play_l(); MediaBuffer *mVideoBuffer; sp mClockEstimator; sp mConnectingDataSource; sp mCachedSource; DrmManagerClient *mDrmManagerClient; sp mDecryptHandle; int64_t mLastVideoTimeUs; TimedTextDriver *mTextDriver; sp mWVMExtractor; sp mExtractor; status_t setDataSource_l( const char *uri, const KeyedVector *headers = NULL); status_t setDataSource_l(const sp &dataSource); status_t setDataSource_l(const sp &extractor); void reset_l(); status_t seekTo_l(int64_t timeUs); status_t pause_l(bool at_eos = false); void initRenderer_l(); void notifyVideoSize_l(); void seekAudioIfNecessary_l(); void cancelPlayerEvents(bool keepNotifications = false); void setAudioSource(sp source); status_t initAudioDecoder(); void setVideoSource(sp source); status_t initVideoDecoder(uint32_t flags = 0); void addTextSource_l(size_t trackIndex, const sp& source); void onStreamDone(); void notifyListener_l(int msg, int ext1 = 0, int ext2 = 0); void onVideoEvent(); void onBufferingUpdate(); void onCheckAudioStatus(); void onPrepareAsyncEvent(); void abortPrepare(status_t err); void finishAsyncPrepare_l(); void onVideoLagUpdate(); void onAudioTearDownEvent(); void beginPrepareAsync_l(); bool getCachedDuration_l(int64_t *durationUs, bool *eos); status_t finishSetDataSource_l(); static bool ContinuePreparation(void *cookie); bool getBitrate(int64_t *bitrate); int64_t estimateRealTimeUs(TimeSource *ts, int64_t systemTimeUs); void finishSeekIfNecessary(int64_t videoTimeUs); void ensureCacheIsFetching_l(); void notifyIfMediaStarted_l(); void createAudioPlayer_l(); status_t startAudioPlayer_l(bool sendErrorNotification = true); void shutdownVideoDecoder_l(); status_t setNativeWindow_l(const sp &native); bool isStreamingHTTP() const; void sendCacheStats(); void checkDrmStatus(const sp& dataSource); enum FlagMode { SET, CLEAR, ASSIGN }; void modifyFlags(unsigned value, FlagMode mode); struct TrackStat { String8 mMIME; String8 mDecoderName; }; // protected by mStatsLock struct Stats { int mFd; String8 mURI; int64_t mBitrate; // FIXME: // These two indices are just 0 or 1 for now // They are not representing the actual track // indices in the stream. ssize_t mAudioTrackIndex; ssize_t mVideoTrackIndex; int64_t mNumVideoFramesDecoded; int64_t mNumVideoFramesDropped; int32_t mVideoWidth; int32_t mVideoHeight; uint32_t mFlags; Vector mTracks; } mStats; bool mOffloadAudio; bool mAudioTearDown; bool mAudioTearDownWasPlaying; int64_t mAudioTearDownPosition; status_t setVideoScalingMode(int32_t mode); status_t setVideoScalingMode_l(int32_t mode); status_t getTrackInfo(Parcel* reply) const; status_t selectAudioTrack_l(const sp& source, size_t trackIndex); // when select is true, the given track is selected. // otherwise, the given track is unselected. status_t selectTrack(size_t trackIndex, bool select); size_t countTracks() const; AwesomePlayer(const AwesomePlayer &); AwesomePlayer &operator=(const AwesomePlayer &); }; } // namespace android #endif // AWESOME_PLAYER_H_