michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* vim:set ts=2 sw=2 sts=2 et cindent: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #if !defined(MP4Reader_h_) michael@0: #define MP4Reader_h_ michael@0: michael@0: #include "MediaDecoderReader.h" michael@0: #include "nsAutoPtr.h" michael@0: #include "PlatformDecoderModule.h" michael@0: #include "mp4_demuxer/mp4_demuxer.h" michael@0: #include "mp4_demuxer/box_definitions.h" michael@0: #include "MediaTaskQueue.h" michael@0: michael@0: #include michael@0: #include "mozilla/Monitor.h" michael@0: michael@0: namespace mozilla { michael@0: michael@0: namespace dom { michael@0: class TimeRanges; michael@0: } michael@0: michael@0: typedef std::deque MP4SampleQueue; michael@0: michael@0: class MP4Stream; michael@0: michael@0: class MP4Reader : public MediaDecoderReader michael@0: { michael@0: public: michael@0: MP4Reader(AbstractMediaDecoder* aDecoder); michael@0: michael@0: virtual ~MP4Reader(); michael@0: michael@0: virtual nsresult Init(MediaDecoderReader* aCloneDonor) MOZ_OVERRIDE; michael@0: michael@0: virtual bool DecodeAudioData() MOZ_OVERRIDE; michael@0: virtual bool DecodeVideoFrame(bool &aKeyframeSkip, michael@0: int64_t aTimeThreshold) MOZ_OVERRIDE; michael@0: michael@0: virtual bool HasAudio() MOZ_OVERRIDE; michael@0: virtual bool HasVideo() MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult ReadMetadata(MediaInfo* aInfo, michael@0: MetadataTags** aTags) MOZ_OVERRIDE; michael@0: michael@0: virtual nsresult Seek(int64_t aTime, michael@0: int64_t aStartTime, michael@0: int64_t aEndTime, michael@0: int64_t aCurrentTime) MOZ_OVERRIDE; michael@0: private: michael@0: michael@0: // Destroys all decoder resources. michael@0: void Shutdown(); michael@0: michael@0: // Initializes mLayersBackendType if possible. michael@0: void InitLayersBackendType(); michael@0: michael@0: // Blocks until the demuxer produces an sample of specified type. michael@0: // Returns nullptr on error on EOS. Caller must delete sample. michael@0: mp4_demuxer::MP4Sample* PopSample(mp4_demuxer::TrackType aTrack); michael@0: michael@0: bool SkipVideoDemuxToNextKeyFrame(int64_t aTimeThreshold, uint32_t& parsed); michael@0: michael@0: void Output(mp4_demuxer::TrackType aType, MediaData* aSample); michael@0: void InputExhausted(mp4_demuxer::TrackType aTrack); michael@0: void Error(mp4_demuxer::TrackType aTrack); michael@0: bool Decode(mp4_demuxer::TrackType aTrack); michael@0: void Flush(mp4_demuxer::TrackType aTrack); michael@0: michael@0: nsAutoPtr mDemuxer; michael@0: nsAutoPtr mMP4Stream; michael@0: nsAutoPtr mPlatform; michael@0: michael@0: class DecoderCallback : public MediaDataDecoderCallback { michael@0: public: michael@0: DecoderCallback(MP4Reader* aReader, michael@0: mp4_demuxer::TrackType aType) michael@0: : mReader(aReader) michael@0: , mType(aType) michael@0: { michael@0: } michael@0: virtual void Output(MediaData* aSample) MOZ_OVERRIDE { michael@0: mReader->Output(mType, aSample); michael@0: } michael@0: virtual void InputExhausted() MOZ_OVERRIDE { michael@0: mReader->InputExhausted(mType); michael@0: } michael@0: virtual void Error() MOZ_OVERRIDE { michael@0: mReader->Error(mType); michael@0: } michael@0: private: michael@0: MP4Reader* mReader; michael@0: mp4_demuxer::TrackType mType; michael@0: }; michael@0: michael@0: struct DecoderData { michael@0: DecoderData(const char* aMonitorName, michael@0: uint32_t aDecodeAhead) michael@0: : mMonitor(aMonitorName) michael@0: , mNumSamplesInput(0) michael@0: , mNumSamplesOutput(0) michael@0: , mDecodeAhead(aDecodeAhead) michael@0: , mActive(false) michael@0: , mInputExhausted(false) michael@0: , mError(false) michael@0: , mIsFlushing(false) michael@0: { michael@0: } michael@0: michael@0: // The platform decoder. michael@0: RefPtr mDecoder; michael@0: // Queue of input extracted by the demuxer, but not yet sent to the michael@0: // platform decoder. michael@0: MP4SampleQueue mDemuxedSamples; michael@0: // TaskQueue on which decoder can choose to decode. michael@0: // Only non-null up until the decoder is created. michael@0: RefPtr mTaskQueue; michael@0: // Callback that receives output and error notifications from the decoder. michael@0: nsAutoPtr mCallback; michael@0: // Monitor that protects all non-threadsafe state; the primitives michael@0: // that follow. michael@0: Monitor mMonitor; michael@0: uint64_t mNumSamplesInput; michael@0: uint64_t mNumSamplesOutput; michael@0: uint32_t mDecodeAhead; michael@0: // Whether this stream exists in the media. michael@0: bool mActive; michael@0: bool mInputExhausted; michael@0: bool mError; michael@0: bool mIsFlushing; michael@0: }; michael@0: DecoderData mAudio; michael@0: DecoderData mVideo; michael@0: michael@0: // The last number of decoded output frames that we've reported to michael@0: // MediaDecoder::NotifyDecoded(). We diff the number of output video michael@0: // frames every time that DecodeVideoData() is called, and report the michael@0: // delta there. michael@0: uint64_t mLastReportedNumDecodedFrames; michael@0: michael@0: DecoderData& GetDecoderData(mp4_demuxer::TrackType aTrack); michael@0: MP4SampleQueue& SampleQueue(mp4_demuxer::TrackType aTrack); michael@0: MediaDataDecoder* Decoder(mp4_demuxer::TrackType aTrack); michael@0: michael@0: layers::LayersBackend mLayersBackendType; michael@0: michael@0: }; michael@0: michael@0: } // namespace mozilla michael@0: michael@0: #endif