зеркало из https://github.com/mozilla/gecko-dev.git
183 строки
7.3 KiB
C++
183 строки
7.3 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
|
|
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
#if !defined(MediaDecoderReader_h_)
|
|
#define MediaDecoderReader_h_
|
|
|
|
#include "AbstractMediaDecoder.h"
|
|
#include "MediaInfo.h"
|
|
#include "MediaData.h"
|
|
#include "MediaQueue.h"
|
|
#include "AudioCompactor.h"
|
|
|
|
namespace mozilla {
|
|
|
|
namespace dom {
|
|
class TimeRanges;
|
|
}
|
|
|
|
// Encapsulates the decoding and reading of media data. Reading can only be
|
|
// done on the decode thread. Never hold the decoder monitor when
|
|
// calling into this class. Unless otherwise specified, methods and fields of
|
|
// this class can only be accessed on the decode thread.
|
|
class MediaDecoderReader {
|
|
public:
|
|
MediaDecoderReader(AbstractMediaDecoder* aDecoder);
|
|
virtual ~MediaDecoderReader();
|
|
|
|
// Initializes the reader, returns NS_OK on success, or NS_ERROR_FAILURE
|
|
// on failure.
|
|
virtual nsresult Init(MediaDecoderReader* aCloneDonor) = 0;
|
|
|
|
// True if this reader is waiting media resource allocation
|
|
virtual bool IsWaitingMediaResources() { return false; }
|
|
// True when this reader need to become dormant state
|
|
virtual bool IsDormantNeeded() { return false; }
|
|
// Release media resources they should be released in dormant state
|
|
virtual void ReleaseMediaResources() {};
|
|
// Release the decoder during shutdown
|
|
virtual void ReleaseDecoder() {};
|
|
|
|
// Resets all state related to decoding, emptying all buffers etc.
|
|
virtual nsresult ResetDecode();
|
|
|
|
// Decodes an unspecified amount of audio data, enqueuing the audio data
|
|
// in mAudioQueue. Returns true when there's more audio to decode,
|
|
// false if the audio is finished, end of file has been reached,
|
|
// or an un-recoverable read error has occured.
|
|
virtual bool DecodeAudioData() = 0;
|
|
|
|
// Reads and decodes one video frame. Packets with a timestamp less
|
|
// than aTimeThreshold will be decoded (unless they're not keyframes
|
|
// and aKeyframeSkip is true), but will not be added to the queue.
|
|
virtual bool DecodeVideoFrame(bool &aKeyframeSkip,
|
|
int64_t aTimeThreshold) = 0;
|
|
|
|
virtual bool HasAudio() = 0;
|
|
virtual bool HasVideo() = 0;
|
|
|
|
// Read header data for all bitstreams in the file. Fills aInfo with
|
|
// the data required to present the media, and optionally fills *aTags
|
|
// with tag metadata from the file.
|
|
// Returns NS_OK on success, or NS_ERROR_FAILURE on failure.
|
|
virtual nsresult ReadMetadata(MediaInfo* aInfo,
|
|
MetadataTags** aTags) = 0;
|
|
|
|
// Stores the presentation time of the first frame we'd be able to play if
|
|
// we started playback at the current position. Returns the first video
|
|
// frame, if we have video.
|
|
virtual VideoData* FindStartTime(int64_t& aOutStartTime);
|
|
|
|
// Moves the decode head to aTime microseconds. aStartTime and aEndTime
|
|
// denote the start and end times of the media in usecs, and aCurrentTime
|
|
// is the current playback position in microseconds.
|
|
virtual nsresult Seek(int64_t aTime,
|
|
int64_t aStartTime,
|
|
int64_t aEndTime,
|
|
int64_t aCurrentTime) = 0;
|
|
|
|
// Called to move the reader into idle state. When the reader is
|
|
// created it is assumed to be active (i.e. not idle). When the media
|
|
// element is paused and we don't need to decode any more data, the state
|
|
// machine calls SetIdle() to inform the reader that its decoder won't be
|
|
// needed for a while. The reader can use these notifications to enter
|
|
// a low power state when the decoder isn't needed, if desired.
|
|
// This is most useful on mobile.
|
|
// Note: DecodeVideoFrame, DecodeAudioData, ReadMetadata and Seek should
|
|
// activate the decoder if necessary. The state machine only needs to know
|
|
// when to call SetIdle().
|
|
virtual void SetIdle() { }
|
|
|
|
// Tell the reader that the data decoded are not for direct playback, so it
|
|
// can accept more files, in particular those which have more channels than
|
|
// available in the audio output.
|
|
void SetIgnoreAudioOutputFormat()
|
|
{
|
|
mIgnoreAudioOutputFormat = true;
|
|
}
|
|
|
|
protected:
|
|
// Queue of audio frames. This queue is threadsafe, and is accessed from
|
|
// the audio, decoder, state machine, and main threads.
|
|
MediaQueue<AudioData> mAudioQueue;
|
|
|
|
// Queue of video frames. This queue is threadsafe, and is accessed from
|
|
// the decoder, state machine, and main threads.
|
|
MediaQueue<VideoData> mVideoQueue;
|
|
|
|
// An adapter to the audio queue which first copies data to buffers with
|
|
// minimal allocation slop and then pushes them to the queue. This is
|
|
// useful for decoders working with formats that give awkward numbers of
|
|
// frames such as mp3.
|
|
AudioCompactor mAudioCompactor;
|
|
|
|
public:
|
|
// Populates aBuffered with the time ranges which are buffered. aStartTime
|
|
// must be the presentation time of the first frame in the media, e.g.
|
|
// the media time corresponding to playback time/position 0. This function
|
|
// is called on the main, decode, and state machine threads.
|
|
//
|
|
// This base implementation in MediaDecoderReader estimates the time ranges
|
|
// buffered by interpolating the cached byte ranges with the duration
|
|
// of the media. Reader subclasses should override this method if they
|
|
// can quickly calculate the buffered ranges more accurately.
|
|
//
|
|
// The primary advantage of this implementation in the reader base class
|
|
// is that it's a fast approximation, which does not perform any I/O.
|
|
//
|
|
// The OggReader relies on this base implementation not performing I/O,
|
|
// since in FirefoxOS we can't do I/O on the main thread, where this is
|
|
// called.
|
|
virtual nsresult GetBuffered(dom::TimeRanges* aBuffered,
|
|
int64_t aStartTime);
|
|
|
|
// Returns the number of bytes of memory allocated by structures/frames in
|
|
// the video queue.
|
|
size_t SizeOfVideoQueueInBytes() const;
|
|
|
|
// Returns the number of bytes of memory allocated by structures/frames in
|
|
// the audio queue.
|
|
size_t SizeOfAudioQueueInBytes() const;
|
|
|
|
// Only used by WebMReader and MediaOmxReader for now, so stub here rather
|
|
// than in every reader than inherits from MediaDecoderReader.
|
|
virtual void NotifyDataArrived(const char* aBuffer, uint32_t aLength, int64_t aOffset) {}
|
|
|
|
virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
|
|
virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
|
|
|
|
// Returns a pointer to the decoder.
|
|
AbstractMediaDecoder* GetDecoder() {
|
|
return mDecoder;
|
|
}
|
|
|
|
AudioData* DecodeToFirstAudioData();
|
|
VideoData* DecodeToFirstVideoData();
|
|
|
|
// Decodes samples until we reach frames required to play at time aTarget
|
|
// (usecs). This also trims the samples to start exactly at aTarget,
|
|
// by discarding audio samples and adjusting start times of video frames.
|
|
nsresult DecodeToTarget(int64_t aTarget);
|
|
|
|
MediaInfo GetMediaInfo() { return mInfo; }
|
|
|
|
protected:
|
|
|
|
// Reference to the owning decoder object.
|
|
AbstractMediaDecoder* mDecoder;
|
|
|
|
// Stores presentation info required for playback.
|
|
MediaInfo mInfo;
|
|
|
|
// Whether we should accept media that we know we can't play
|
|
// directly, because they have a number of channel higher than
|
|
// what we support.
|
|
bool mIgnoreAudioOutputFormat;
|
|
};
|
|
|
|
} // namespace mozilla
|
|
|
|
#endif
|