mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
Bug 820588 - Aggregate and forward statistics in DASH decoder classes r=cpearce
This commit is contained in:
parent
daabc3d610
commit
a60e66b6fb
@ -925,6 +925,10 @@ void MediaDecoder::NotifySuspendedStatusChanged()
|
||||
void MediaDecoder::NotifyBytesDownloaded()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread());
|
||||
{
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
UpdatePlaybackRate();
|
||||
}
|
||||
UpdateReadyStateForData();
|
||||
Progress(false);
|
||||
}
|
||||
|
@ -618,10 +618,24 @@ public:
|
||||
|
||||
// Something has changed that could affect the computed playback rate,
|
||||
// so recompute it. The monitor must be held.
|
||||
void UpdatePlaybackRate();
|
||||
virtual void UpdatePlaybackRate();
|
||||
|
||||
// Used to estimate rates of data passing through the decoder's channel.
|
||||
// Records activity stopping on the channel. The monitor must be held.
|
||||
virtual void NotifyPlaybackStarted() {
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
mPlaybackStatistics.Start();
|
||||
}
|
||||
|
||||
// Used to estimate rates of data passing through the decoder's channel.
|
||||
// Records activity stopping on the channel. The monitor must be held.
|
||||
virtual void NotifyPlaybackStopped() {
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
mPlaybackStatistics.Stop();
|
||||
}
|
||||
|
||||
// The actual playback rate computation. The monitor must be held.
|
||||
double ComputePlaybackRate(bool* aReliable);
|
||||
virtual double ComputePlaybackRate(bool* aReliable);
|
||||
|
||||
// Returns true if we can play the entire media through without stopping
|
||||
// to buffer, given the current download and playback rates.
|
||||
@ -787,7 +801,7 @@ public:
|
||||
// This can be called from any thread. It's only a snapshot of the
|
||||
// current state, since other threads might be changing the state
|
||||
// at any time.
|
||||
Statistics GetStatistics();
|
||||
virtual Statistics GetStatistics();
|
||||
|
||||
// Frame decoding/painting related performance counters.
|
||||
// Threadsafe.
|
||||
@ -862,7 +876,7 @@ public:
|
||||
|
||||
// Increments the parsed and decoded frame counters by the passed in counts.
|
||||
// Can be called on any thread.
|
||||
virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_FINAL MOZ_OVERRIDE
|
||||
virtual void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE
|
||||
{
|
||||
GetFrameStatistics().NotifyDecodedFrames(aParsed, aDecoded);
|
||||
}
|
||||
@ -881,10 +895,6 @@ public:
|
||||
// during decoder seek operations, but it's updated at the end when we
|
||||
// start playing back again.
|
||||
int64_t mPlaybackPosition;
|
||||
// Data needed to estimate playback data rate. The timeline used for
|
||||
// this estimate is "decode time" (where the "current time" is the
|
||||
// time of the last decoded video frame).
|
||||
MediaChannelStatistics mPlaybackStatistics;
|
||||
|
||||
// The current playback position of the media resource in units of
|
||||
// seconds. This is updated approximately at the framerate of the
|
||||
@ -1050,6 +1060,11 @@ protected:
|
||||
// more data is received. Read/Write from the main thread only.
|
||||
TimeStamp mDataTime;
|
||||
|
||||
// Data needed to estimate playback data rate. The timeline used for
|
||||
// this estimate is "decode time" (where the "current time" is the
|
||||
// time of the last decoded video frame).
|
||||
MediaChannelStatistics mPlaybackStatistics;
|
||||
|
||||
// The framebuffer size to use for audioavailable events.
|
||||
uint32_t mFrameBufferLength;
|
||||
|
||||
|
@ -1222,7 +1222,7 @@ void MediaDecoderStateMachine::StopPlayback()
|
||||
"Should be on state machine thread or the decoder thread.");
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
|
||||
mDecoder->mPlaybackStatistics.Stop(TimeStamp::Now());
|
||||
mDecoder->NotifyPlaybackStopped();
|
||||
|
||||
if (IsPlaying()) {
|
||||
mPlayDuration += DurationToUsecs(TimeStamp::Now() - mPlayStartTime);
|
||||
@ -1241,7 +1241,7 @@ void MediaDecoderStateMachine::StartPlayback()
|
||||
NS_ASSERTION(!IsPlaying(), "Shouldn't be playing when StartPlayback() is called");
|
||||
mDecoder->GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
LOG(PR_LOG_DEBUG, ("%p StartPlayback", mDecoder.get()));
|
||||
mDecoder->mPlaybackStatistics.Start(TimeStamp::Now());
|
||||
mDecoder->NotifyPlaybackStarted();
|
||||
mPlayStartTime = TimeStamp::Now();
|
||||
|
||||
NS_ASSERTION(IsPlaying(), "Should report playing by end of StartPlayback()");
|
||||
|
@ -325,7 +325,7 @@ ChannelMediaResource::OnStartRequest(nsIRequest* aRequest)
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mChannelStatistics.Start(TimeStamp::Now());
|
||||
mChannelStatistics->Start();
|
||||
}
|
||||
|
||||
mReopenOnError = false;
|
||||
@ -406,7 +406,7 @@ ChannelMediaResource::OnStopRequest(nsIRequest* aRequest, nsresult aStatus)
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
mChannelStatistics->Stop();
|
||||
}
|
||||
|
||||
// If we were loading a byte range, notify decoder and return.
|
||||
@ -512,7 +512,7 @@ ChannelMediaResource::OnDataAvailable(nsIRequest* aRequest,
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mChannelStatistics.AddBytes(aCount);
|
||||
mChannelStatistics->AddBytes(aCount);
|
||||
}
|
||||
|
||||
CopySegmentClosure closure;
|
||||
@ -583,6 +583,10 @@ nsresult ChannelMediaResource::Open(nsIStreamListener **aStreamListener)
|
||||
{
|
||||
NS_ASSERTION(NS_IsMainThread(), "Only call on main thread");
|
||||
|
||||
if (!mChannelStatistics) {
|
||||
mChannelStatistics = new MediaChannelStatistics();
|
||||
}
|
||||
|
||||
nsresult rv = mCacheStream.Init();
|
||||
if (NS_FAILED(rv))
|
||||
return rv;
|
||||
@ -731,7 +735,7 @@ MediaResource* ChannelMediaResource::CloneData(MediaDecoder* aDecoder)
|
||||
resource->mSuspendCount = 1;
|
||||
resource->mCacheStream.InitAsClone(&mCacheStream);
|
||||
resource->mChannelStatistics = mChannelStatistics;
|
||||
resource->mChannelStatistics.Stop(TimeStamp::Now());
|
||||
resource->mChannelStatistics->Stop();
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
@ -742,7 +746,7 @@ void ChannelMediaResource::CloseChannel()
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
mChannelStatistics->Stop();
|
||||
}
|
||||
|
||||
if (mListener) {
|
||||
@ -844,7 +848,7 @@ void ChannelMediaResource::Suspend(bool aCloseImmediately)
|
||||
} else if (mSuspendCount == 0) {
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mChannelStatistics.Stop(TimeStamp::Now());
|
||||
mChannelStatistics->Stop();
|
||||
}
|
||||
PossiblySuspend();
|
||||
element->DownloadSuspended();
|
||||
@ -877,7 +881,7 @@ void ChannelMediaResource::Resume()
|
||||
// Just wake up our existing channel
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
mChannelStatistics.Start(TimeStamp::Now());
|
||||
mChannelStatistics->Start();
|
||||
}
|
||||
// if an error occurs after Resume, assume it's because the server
|
||||
// timed out the connection and we should reopen it.
|
||||
@ -1219,7 +1223,7 @@ double
|
||||
ChannelMediaResource::GetDownloadRate(bool* aIsReliable)
|
||||
{
|
||||
MutexAutoLock lock(mLock);
|
||||
return mChannelStatistics.GetRate(TimeStamp::Now(), aIsReliable);
|
||||
return mChannelStatistics->GetRate(aIsReliable);
|
||||
}
|
||||
|
||||
int64_t
|
||||
|
@ -46,22 +46,25 @@ class MediaDecoder;
|
||||
class MediaChannelStatistics {
|
||||
public:
|
||||
MediaChannelStatistics() { Reset(); }
|
||||
|
||||
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaChannelStatistics)
|
||||
|
||||
void Reset() {
|
||||
mLastStartTime = TimeStamp();
|
||||
mAccumulatedTime = TimeDuration(0);
|
||||
mAccumulatedBytes = 0;
|
||||
mIsStarted = false;
|
||||
}
|
||||
void Start(TimeStamp aNow) {
|
||||
void Start() {
|
||||
if (mIsStarted)
|
||||
return;
|
||||
mLastStartTime = aNow;
|
||||
mLastStartTime = TimeStamp::Now();
|
||||
mIsStarted = true;
|
||||
}
|
||||
void Stop(TimeStamp aNow) {
|
||||
void Stop() {
|
||||
if (!mIsStarted)
|
||||
return;
|
||||
mAccumulatedTime += aNow - mLastStartTime;
|
||||
mAccumulatedTime += TimeStamp::Now() - mLastStartTime;
|
||||
mIsStarted = false;
|
||||
}
|
||||
void AddBytes(int64_t aBytes) {
|
||||
@ -79,10 +82,10 @@ public:
|
||||
return 0.0;
|
||||
return static_cast<double>(mAccumulatedBytes)/seconds;
|
||||
}
|
||||
double GetRate(TimeStamp aNow, bool* aReliable) {
|
||||
double GetRate(bool* aReliable) {
|
||||
TimeDuration time = mAccumulatedTime;
|
||||
if (mIsStarted) {
|
||||
time += aNow - mLastStartTime;
|
||||
time += TimeStamp::Now() - mLastStartTime;
|
||||
}
|
||||
double seconds = time.ToSeconds();
|
||||
*aReliable = seconds >= 3.0;
|
||||
@ -213,6 +216,8 @@ public:
|
||||
// with a new channel. Any cached data associated with the original
|
||||
// stream should be accessible in the new stream too.
|
||||
virtual MediaResource* CloneData(MediaDecoder* aDecoder) = 0;
|
||||
// Set statistics to be recorded to the object passed in.
|
||||
virtual void RecordStatisticsTo(MediaChannelStatistics *aStatistics) { }
|
||||
|
||||
// These methods are called off the main thread.
|
||||
// The mode is initially MODE_PLAYBACK.
|
||||
@ -459,6 +464,15 @@ public:
|
||||
bool IsClosed() const { return mCacheStream.IsClosed(); }
|
||||
virtual bool CanClone();
|
||||
virtual MediaResource* CloneData(MediaDecoder* aDecoder);
|
||||
// Set statistics to be recorded to the object passed in. If not called,
|
||||
// |ChannelMediaResource| will create it's own statistics objects in |Open|.
|
||||
void RecordStatisticsTo(MediaChannelStatistics *aStatistics) MOZ_OVERRIDE {
|
||||
NS_ASSERTION(aStatistics, "Statistics param cannot be null!");
|
||||
MutexAutoLock lock(mLock);
|
||||
if (!mChannelStatistics) {
|
||||
mChannelStatistics = aStatistics;
|
||||
}
|
||||
}
|
||||
virtual nsresult ReadFromCache(char* aBuffer, int64_t aOffset, uint32_t aCount);
|
||||
virtual void EnsureCacheUpToDate();
|
||||
|
||||
@ -567,7 +581,7 @@ protected:
|
||||
|
||||
// This lock protects mChannelStatistics
|
||||
Mutex mLock;
|
||||
MediaChannelStatistics mChannelStatistics;
|
||||
nsRefPtr<MediaChannelStatistics> mChannelStatistics;
|
||||
|
||||
// True if we couldn't suspend the stream and we therefore don't want
|
||||
// to resume later. This is usually due to the channel not being in the
|
||||
|
@ -156,9 +156,12 @@ DASHDecoder::DASHDecoder() :
|
||||
mVideoSubsegmentIdx(0),
|
||||
mAudioMetadataReadCount(0),
|
||||
mVideoMetadataReadCount(0),
|
||||
mSeeking(false)
|
||||
mSeeking(false),
|
||||
mStatisticsLock("DASHDecoder.mStatisticsLock")
|
||||
{
|
||||
MOZ_COUNT_CTOR(DASHDecoder);
|
||||
mAudioStatistics = new MediaChannelStatistics();
|
||||
mVideoStatistics = new MediaChannelStatistics();
|
||||
}
|
||||
|
||||
DASHDecoder::~DASHDecoder()
|
||||
@ -536,6 +539,7 @@ DASHDecoder::CreateAudioSubResource(nsIURI* aUrl,
|
||||
= MediaResource::Create(aAudioDecoder, channel);
|
||||
NS_ENSURE_TRUE(audioResource, nullptr);
|
||||
|
||||
audioResource->RecordStatisticsTo(mAudioStatistics);
|
||||
return audioResource;
|
||||
}
|
||||
|
||||
@ -557,6 +561,7 @@ DASHDecoder::CreateVideoSubResource(nsIURI* aUrl,
|
||||
= MediaResource::Create(aVideoDecoder, channel);
|
||||
NS_ENSURE_TRUE(videoResource, nullptr);
|
||||
|
||||
videoResource->RecordStatisticsTo(mVideoStatistics);
|
||||
return videoResource;
|
||||
}
|
||||
|
||||
@ -910,19 +915,23 @@ DASHDecoder::PossiblySwitchDecoder(DASHRepDecoder* aRepDecoder)
|
||||
|
||||
// Now, determine if and which decoder to switch to.
|
||||
// XXX This download rate is averaged over time, and only refers to the bytes
|
||||
// downloaded for the given decoder. A running average would be better, and
|
||||
// downloaded for the video decoder. A running average would be better, and
|
||||
// something that includes all downloads. But this will do for now.
|
||||
NS_ASSERTION(VideoRepDecoder(), "Video decoder should not be null.");
|
||||
NS_ASSERTION(VideoRepDecoder()->GetResource(),
|
||||
"Video resource should not be null");
|
||||
bool reliable = false;
|
||||
double downloadRate = VideoRepDecoder()->GetResource()->GetDownloadRate(&reliable);
|
||||
double downloadRate = 0;
|
||||
{
|
||||
MutexAutoLock lock(mStatisticsLock);
|
||||
downloadRate = mVideoStatistics->GetRate(&reliable);
|
||||
}
|
||||
uint32_t bestRepIdx = UINT32_MAX;
|
||||
bool noRepAvailable = !mMPDManager->GetBestRepForBandwidth(mVideoAdaptSetIdx,
|
||||
downloadRate,
|
||||
bestRepIdx);
|
||||
LOG("downloadRate [%f] reliable [%s] bestRepIdx [%d] noRepAvailable",
|
||||
downloadRate, (reliable ? "yes" : "no"), bestRepIdx,
|
||||
LOG("downloadRate [%0.2f kbps] reliable [%s] bestRepIdx [%d] noRepAvailable [%s]",
|
||||
downloadRate/1000.0, (reliable ? "yes" : "no"), bestRepIdx,
|
||||
(noRepAvailable ? "yes" : "no"));
|
||||
|
||||
// If there is a higher bitrate stream that can be downloaded with the
|
||||
@ -1119,5 +1128,124 @@ DASHDecoder::SetSubsegmentIndex(DASHRepDecoder* aRepDecoder,
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
double
|
||||
DASHDecoder::ComputePlaybackRate(bool* aReliable)
|
||||
{
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
|
||||
NS_ASSERTION(aReliable, "Bool pointer aRelible should not be null!");
|
||||
|
||||
// While downloading the MPD, return 0; do not count manifest as media data.
|
||||
if (mResource && !mMPDManager) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Once MPD is downloaded, use the rate from the video decoder.
|
||||
// XXX Not ideal, but since playback rate is used to estimate if we have
|
||||
// enough data to continue playing, this should be sufficient.
|
||||
double videoRate = 0;
|
||||
if (VideoRepDecoder()) {
|
||||
videoRate = VideoRepDecoder()->ComputePlaybackRate(aReliable);
|
||||
}
|
||||
return videoRate;
|
||||
}
|
||||
|
||||
void
|
||||
DASHDecoder::UpdatePlaybackRate()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
// While downloading the MPD, return silently; playback rate has no meaning
|
||||
// for the manifest.
|
||||
if (mResource && !mMPDManager) {
|
||||
return;
|
||||
}
|
||||
// Once MPD is downloaded and audio/video decoder(s) are loading, forward to
|
||||
// active rep decoders.
|
||||
if (AudioRepDecoder()) {
|
||||
AudioRepDecoder()->UpdatePlaybackRate();
|
||||
}
|
||||
if (VideoRepDecoder()) {
|
||||
VideoRepDecoder()->UpdatePlaybackRate();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DASHDecoder::NotifyPlaybackStarted()
|
||||
{
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
// While downloading the MPD, return silently; playback rate has no meaning
|
||||
// for the manifest.
|
||||
if (mResource && !mMPDManager) {
|
||||
return;
|
||||
}
|
||||
// Once MPD is downloaded and audio/video decoder(s) are loading, forward to
|
||||
// active rep decoders.
|
||||
if (AudioRepDecoder()) {
|
||||
AudioRepDecoder()->NotifyPlaybackStarted();
|
||||
}
|
||||
if (VideoRepDecoder()) {
|
||||
VideoRepDecoder()->NotifyPlaybackStarted();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DASHDecoder::NotifyPlaybackStopped()
|
||||
{
|
||||
GetReentrantMonitor().AssertCurrentThreadIn();
|
||||
// While downloading the MPD, return silently; playback rate has no meaning
|
||||
// for the manifest.
|
||||
if (mResource && !mMPDManager) {
|
||||
return;
|
||||
}
|
||||
// Once // Once MPD is downloaded and audio/video decoder(s) are loading, forward to
|
||||
// active rep decoders.
|
||||
if (AudioRepDecoder()) {
|
||||
AudioRepDecoder()->NotifyPlaybackStopped();
|
||||
}
|
||||
if (VideoRepDecoder()) {
|
||||
VideoRepDecoder()->NotifyPlaybackStopped();
|
||||
}
|
||||
}
|
||||
|
||||
MediaDecoder::Statistics
|
||||
DASHDecoder::GetStatistics()
|
||||
{
|
||||
MOZ_ASSERT(NS_IsMainThread() || OnStateMachineThread());
|
||||
Statistics result;
|
||||
|
||||
ReentrantMonitorAutoEnter mon(GetReentrantMonitor());
|
||||
if (mResource && !mMPDManager) {
|
||||
return MediaDecoder::GetStatistics();
|
||||
}
|
||||
|
||||
// XXX Use video decoder and its media resource to get stats.
|
||||
// This assumes that the following getter functions are getting relevant
|
||||
// video data only.
|
||||
if (VideoRepDecoder() && VideoRepDecoder()->GetResource()) {
|
||||
MediaResource *resource = VideoRepDecoder()->GetResource();
|
||||
// Note: this rate reflects the rate observed for all video downloads.
|
||||
result.mDownloadRate =
|
||||
resource->GetDownloadRate(&result.mDownloadRateReliable);
|
||||
result.mDownloadPosition =
|
||||
resource->GetCachedDataEnd(VideoRepDecoder()->mDecoderPosition);
|
||||
result.mTotalBytes = resource->GetLength();
|
||||
result.mPlaybackRate = ComputePlaybackRate(&result.mPlaybackRateReliable);
|
||||
result.mDecoderPosition = VideoRepDecoder()->mDecoderPosition;
|
||||
result.mPlaybackPosition = VideoRepDecoder()->mPlaybackPosition;
|
||||
}
|
||||
else {
|
||||
result.mDownloadRate = 0;
|
||||
result.mDownloadRateReliable = true;
|
||||
result.mPlaybackRate = 0;
|
||||
result.mPlaybackRateReliable = true;
|
||||
result.mDecoderPosition = 0;
|
||||
result.mPlaybackPosition = 0;
|
||||
result.mDownloadPosition = 0;
|
||||
result.mTotalBytes = 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -179,6 +179,31 @@ public:
|
||||
return switchCount;
|
||||
}
|
||||
|
||||
// The actual playback rate computation. The monitor must be held.
|
||||
// XXX Computes playback for the current video rep decoder only.
|
||||
double ComputePlaybackRate(bool* aReliable) MOZ_OVERRIDE;
|
||||
|
||||
// Something has changed that could affect the computed playback rate,
|
||||
// so recompute it. The monitor must be held. Will be forwarded to current
|
||||
// audio and video rep decoders.
|
||||
void UpdatePlaybackRate() MOZ_OVERRIDE;
|
||||
|
||||
// Used to estimate rates of data passing through the decoder's channel.
|
||||
// Records activity starting on the channel. The monitor must be held.
|
||||
virtual void NotifyPlaybackStarted() MOZ_OVERRIDE;
|
||||
|
||||
// Used to estimate rates of data passing through the decoder's channel.
|
||||
// Records activity stopping on the channel. The monitor must be held.
|
||||
virtual void NotifyPlaybackStopped() MOZ_OVERRIDE;
|
||||
|
||||
// Return statistics. This is used for progress events and other things.
|
||||
// This can be called from any thread. It's only a snapshot of the
|
||||
// current state, since other threads might be changing the state
|
||||
// at any time.
|
||||
// XXX Stats are calculated based on the current video rep decoder, with the
|
||||
// exception of download rate, which is based on all video downloads.
|
||||
virtual Statistics GetStatistics() MOZ_OVERRIDE;
|
||||
|
||||
// Drop reference to state machine and tell sub-decoders to do the same.
|
||||
// Only called during shutdown dance, on main thread only.
|
||||
void ReleaseStateMachine();
|
||||
@ -320,6 +345,13 @@ private:
|
||||
// |NotifySeekInSubsegment| is called, which will set it to false, and will
|
||||
// start a new series of downloads from the seeked subsegment.
|
||||
bool mSeeking;
|
||||
|
||||
// Mutex for statistics.
|
||||
Mutex mStatisticsLock;
|
||||
// Stores snapshot statistics, such as download rate, for the audio|video
|
||||
// data streams. |mStatisticsLock| must be locked for access.
|
||||
nsRefPtr<MediaChannelStatistics> mAudioStatistics;
|
||||
nsRefPtr<MediaChannelStatistics> mVideoStatistics;
|
||||
};
|
||||
|
||||
} // namespace mozilla
|
||||
|
@ -136,6 +136,12 @@ public:
|
||||
// start consuming data, if possible, because the cache is full.
|
||||
void NotifySuspendedStatusChanged();
|
||||
|
||||
// Increments the parsed and decoded frame counters by the passed in counts.
|
||||
// Can be called on any thread.
|
||||
void NotifyDecodedFrames(uint32_t aParsed, uint32_t aDecoded) MOZ_OVERRIDE {
|
||||
if (mMainDecoder) {mMainDecoder->NotifyDecodedFrames(aParsed, aDecoded); }
|
||||
}
|
||||
|
||||
// Gets a byte range containing the byte offset. Call on main thread only.
|
||||
nsresult GetByteRangeForSeek(int64_t const aOffset,
|
||||
MediaByteRange& aByteRange);
|
||||
|
Loading…
Reference in New Issue
Block a user