diff -r 000000000000 -r 6474c204b198 content/media/omx/OmxDecoder.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/content/media/omx/OmxDecoder.h Wed Dec 31 06:09:35 2014 +0100 @@ -0,0 +1,254 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "GonkNativeWindow.h" +#include "GonkNativeWindowClient.h" +#include "mozilla/layers/FenceUtils.h" +#include "MP3FrameParser.h" +#include "MPAPI.h" +#include "MediaResource.h" +#include "AbstractMediaDecoder.h" +#include "OMXCodecProxy.h" + +namespace android { +class OmxDecoder; +}; + +namespace android { + +// MediaStreamSource is a DataSource that reads from a MPAPI media stream. +class MediaStreamSource : public DataSource { + typedef mozilla::MediaResource MediaResource; + typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder; + + Mutex mLock; + nsRefPtr mResource; + AbstractMediaDecoder *mDecoder; +public: + MediaStreamSource(MediaResource* aResource, + AbstractMediaDecoder *aDecoder); + + virtual status_t initCheck() const; + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual ssize_t readAt(off_t offset, void *data, size_t size) { + return readAt(static_cast(offset), data, size); + } + virtual status_t getSize(off_t *size) { + off64_t size64; + status_t status = getSize(&size64); + *size = size64; + return status; + } + virtual status_t getSize(off64_t *size); + virtual uint32_t flags() { + return kWantsPrefetching; + } + + virtual ~MediaStreamSource(); + +private: + MediaStreamSource(const MediaStreamSource &); + MediaStreamSource &operator=(const MediaStreamSource &); +}; + +class OmxDecoder : public OMXCodecProxy::EventListener { + typedef MPAPI::AudioFrame AudioFrame; + typedef MPAPI::VideoFrame VideoFrame; + typedef mozilla::MP3FrameParser MP3FrameParser; + typedef mozilla::MediaResource MediaResource; + typedef mozilla::AbstractMediaDecoder AbstractMediaDecoder; + typedef mozilla::layers::FenceHandle FenceHandle; + typedef mozilla::layers::TextureClient TextureClient; + + enum { + kPreferSoftwareCodecs = 1, + kSoftwareCodecsOnly = 8, + kHardwareCodecsOnly = 16, + }; + + enum { + kNotifyPostReleaseVideoBuffer = 'noti', + kNotifyStatusChanged = 'stat' + }; + + AbstractMediaDecoder *mDecoder; + nsRefPtr mResource; + sp mNativeWindow; + sp mNativeWindowClient; + sp mVideoTrack; + sp mVideoSource; + sp mAudioOffloadTrack; + sp mAudioTrack; + sp mAudioSource; + int32_t mDisplayWidth; + int32_t mDisplayHeight; + int32_t mVideoWidth; + int32_t mVideoHeight; + int32_t mVideoColorFormat; + int32_t mVideoStride; + int32_t mVideoSliceHeight; + int32_t mVideoRotation; + int32_t mAudioChannels; + int32_t mAudioSampleRate; + int64_t mDurationUs; + VideoFrame mVideoFrame; + AudioFrame mAudioFrame; + MP3FrameParser mMP3FrameParser; + bool mIsMp3; + + // Lifetime of these should be handled by OMXCodec, as long as we release + // them after use: see ReleaseVideoBuffer(), ReleaseAudioBuffer() + MediaBuffer *mVideoBuffer; + MediaBuffer *mAudioBuffer; + + struct BufferItem { + BufferItem() + : mMediaBuffer(nullptr) + { + } + BufferItem(MediaBuffer* aMediaBuffer, const FenceHandle& aReleaseFenceHandle) + : mMediaBuffer(aMediaBuffer) + , mReleaseFenceHandle(aReleaseFenceHandle) { + } + + MediaBuffer* mMediaBuffer; + // a fence will signal when the current buffer is no longer being read. + FenceHandle mReleaseFenceHandle; + }; + + // Hold video's MediaBuffers that are released during video seeking. + // The holded MediaBuffers are released soon after seek completion. + // OMXCodec does not accept MediaBuffer during seeking. If MediaBuffer is + // returned to OMXCodec during seeking, OMXCodec calls assert. + Vector mPendingVideoBuffers; + // The lock protects mPendingVideoBuffers. + Mutex mPendingVideoBuffersLock; + + // Show if OMXCodec is seeking. + bool mIsVideoSeeking; + // The lock protects video MediaBuffer release()'s pending operations called + // from multiple threads. The pending operations happen only during video + // seeking. Holding mSeekLock long time could affect to video rendering. + // Holding time should be minimum. + Mutex mSeekLock; + + // ALooper is a message loop used in stagefright. + // It creates a thread for messages and handles messages in the thread. + // ALooper is a clone of Looper in android Java. + // http://developer.android.com/reference/android/os/Looper.html + sp mLooper; + // deliver a message to a wrapped object(OmxDecoder). + // AHandlerReflector is similar to Handler in android Java. + // http://developer.android.com/reference/android/os/Handler.html + sp > mReflector; + + // 'true' if a read from the audio stream was done while reading the metadata + bool mAudioMetadataRead; + + void ReleaseVideoBuffer(); + void ReleaseAudioBuffer(); + // Call with mSeekLock held. + void ReleaseAllPendingVideoBuffersLocked(); + + void PlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame); + void CbYCrYFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame); + void SemiPlanarYUV420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame); + void SemiPlanarYVU420Frame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame); + bool ToVideoFrame(VideoFrame *aFrame, int64_t aTimeUs, void *aData, size_t aSize, bool aKeyFrame); + bool ToAudioFrame(AudioFrame *aFrame, int64_t aTimeUs, void *aData, size_t aDataOffset, size_t aSize, + int32_t aAudioChannels, int32_t aAudioSampleRate); + + //True if decoder is in a paused state + bool mAudioPaused; + bool mVideoPaused; + +public: + OmxDecoder(MediaResource *aResource, AbstractMediaDecoder *aDecoder); + ~OmxDecoder(); + + // MediaResourceManagerClient::EventListener + virtual void statusChanged(); + + // The MediaExtractor provides essential information for creating OMXCodec + // instance. Such as video/audio codec, we can retrieve them through the + // MediaExtractor::getTrackMetaData(). + // In general cases, the extractor is created by a sp which + // connect to a MediaResource like ChannelMediaResource. + // Data is read from the MediaResource to create a suitable extractor which + // extracts data from a container. + // Note: RTSP requires a custom extractor because it doesn't have a container. + bool Init(sp& extractor); + + bool TryLoad(); + bool IsDormantNeeded(); + bool IsWaitingMediaResources(); + bool AllocateMediaResources(); + void ReleaseMediaResources(); + bool SetVideoFormat(); + bool SetAudioFormat(); + + void ReleaseDecoder(); + + bool NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset); + + void GetDuration(int64_t *durationUs) { + *durationUs = mDurationUs; + } + + void GetVideoParameters(int32_t* aDisplayWidth, int32_t* aDisplayHeight, + int32_t* aWidth, int32_t* aHeight) { + *aDisplayWidth = mDisplayWidth; + *aDisplayHeight = mDisplayHeight; + *aWidth = mVideoWidth; + *aHeight = mVideoHeight; + } + + void GetAudioParameters(int32_t *numChannels, int32_t *sampleRate) { + *numChannels = mAudioChannels; + *sampleRate = mAudioSampleRate; + } + + bool HasVideo() { + return mVideoSource != nullptr; + } + + bool HasAudio() { + return mAudioSource != nullptr; + } + + bool ReadVideo(VideoFrame *aFrame, int64_t aSeekTimeUs, + bool aKeyframeSkip = false, + bool aDoSeek = false); + bool ReadAudio(AudioFrame *aFrame, int64_t aSeekTimeUs); + + MediaResource *GetResource() { + return mResource; + } + + //Change decoder into a playing state + nsresult Play(); + + //Change decoder into a paused state + void Pause(); + + // Post kNotifyPostReleaseVideoBuffer message to OmxDecoder via ALooper. + void PostReleaseVideoBuffer(MediaBuffer *aBuffer, const FenceHandle& aReleaseFenceHandle); + // Receive a message from AHandlerReflector. + // Called on ALooper thread. + void onMessageReceived(const sp &msg); + + int64_t ProcessCachedData(int64_t aOffset, bool aWaitForCompletion); + + sp GetAudioOffloadTrack() { return mAudioOffloadTrack; } + + static void RecycleCallback(TextureClient* aClient, void* aClosure); +}; + +} +