Bug 1218311 - Port the fix of bug 1193614 to VideoSink. r=cpearce.

This commit is contained in:
JW Wang 2015-11-25 15:15:05 +08:00
Родитель 9e2043a953
Коммит 22151cf459
4 изменённых файлов: 23 добавлений и 30 удалений

Просмотреть файл

@ -392,7 +392,7 @@ MediaDecoderStateMachine::CreateMediaSink(bool aAudioCaptured)
RefPtr<media::MediaSink> mediaSink =
new VideoSink(mTaskQueue, audioSink, mVideoQueue,
mDecoder->GetVideoFrameContainer(), mRealTime,
mDecoder->GetFrameStatistics(), AUDIO_DURATION_USECS,
mDecoder->GetFrameStatistics(),
sVideoQueueSendToCompositorSize);
return mediaSink.forget();
}
@ -894,19 +894,6 @@ MediaDecoderStateMachine::OnVideoDecoded(MediaData* aVideoSample)
StopPrerollingVideo();
}
// Schedule the state machine to send stream data as soon as possible if
// the VideoQueue() is empty or contains one frame before the Push().
//
// The state machine threads requires a frame in VideoQueue() that is `in
// the future` to gather precise timing information. The head of
// VideoQueue() is always `in the past`.
//
// Schedule the state machine as soon as possible to render the video
// frame or delay the state machine thread accurately.
if (VideoQueue().GetSize() <= 2) {
ScheduleStateMachine();
}
// For non async readers, if the requested video sample was slow to
// arrive, increase the amount of audio we buffer to ensure that we
// don't run out of audio. This is unnecessary for async readers,

Просмотреть файл

@ -46,7 +46,7 @@ public:
MOZ_ASSERT(aItem);
NS_ADDREF(aItem);
nsDeque::Push(aItem);
mPushEvent.Notify();
mPushEvent.Notify(RefPtr<T>(aItem));
}
inline void PushFront(T* aItem) {
@ -54,7 +54,7 @@ public:
MOZ_ASSERT(aItem);
NS_ADDREF(aItem);
nsDeque::PushFront(aItem);
mPushEvent.Notify();
mPushEvent.Notify(RefPtr<T>(aItem));
}
inline already_AddRefed<T> PopFront() {
@ -161,7 +161,7 @@ public:
return mPopEvent;
}
MediaEventSource<void>& PushEvent() {
MediaEventSource<RefPtr<T>>& PushEvent() {
return mPushEvent;
}
@ -172,7 +172,7 @@ public:
private:
mutable ReentrantMonitor mReentrantMonitor;
MediaEventProducer<RefPtr<T>> mPopEvent;
MediaEventProducer<void> mPushEvent;
MediaEventProducer<RefPtr<T>> mPushEvent;
MediaEventProducer<void> mFinishEvent;
// True when we've decoded the last frame of data in the
// bitstream for which we're queueing frame data.

Просмотреть файл

@ -26,7 +26,6 @@ VideoSink::VideoSink(AbstractThread* aThread,
VideoFrameContainer* aContainer,
bool aRealTime,
FrameStatistics& aFrameStats,
int aDelayDuration,
uint32_t aVQueueSentToCompositerSize)
: mOwnerThread(aThread)
, mAudioSink(aAudioSink)
@ -38,7 +37,6 @@ VideoSink::VideoSink(AbstractThread* aThread,
, mVideoFrameEndTime(-1)
, mHasVideo(false)
, mUpdateScheduler(aThread)
, mDelayDuration(aDelayDuration)
, mVideoQueueSendToCompositorSize(aVQueueSentToCompositerSize)
{
MOZ_ASSERT(mAudioSink, "AudioSink should exist.");
@ -218,12 +216,18 @@ VideoSink::Shutdown()
}
void
VideoSink::OnVideoQueueEvent()
VideoSink::OnVideoQueueEvent(RefPtr<MediaData>&& aSample)
{
AssertOwnerThread();
// Listen to push event, VideoSink should try rendering ASAP if first frame
// arrives but update scheduler is not triggered yet.
TryUpdateRenderedVideoFrames();
VideoData* v = aSample->As<VideoData>();
if (!v->mSentToCompositor) {
// Since we push rendered frames back to the queue, we will receive
// push events for them. We only need to trigger render loop
// when this frame is not rendered yet.
TryUpdateRenderedVideoFrames();
}
}
void
@ -338,7 +342,7 @@ VideoSink::UpdateRenderedVideoFrames()
// the current frame.
NS_ASSERTION(clockTime >= 0, "Should have positive clock time.");
int64_t remainingTime = mDelayDuration;
int64_t remainingTime = -1;
if (VideoQueue().GetSize() > 0) {
RefPtr<MediaData> currentFrame = VideoQueue().PopFront();
int32_t framesRemoved = 0;
@ -365,7 +369,14 @@ VideoSink::UpdateRenderedVideoFrames()
RenderVideoFrames(mVideoQueueSendToCompositorSize, clockTime, nowTime);
TimeStamp target = nowTime + TimeDuration::FromMicroseconds(remainingTime);
// No next fame to render. There is no need to schedule next render
// loop. We will run render loops again upon incoming frames.
if (remainingTime < 0) {
return;
}
TimeStamp target = nowTime + TimeDuration::FromMicroseconds(
remainingTime / mAudioSink->GetPlaybackParams().mPlaybackRate);
RefPtr<VideoSink> self = this;
mUpdateScheduler.Ensure(target, [self] () {

Просмотреть файл

@ -35,7 +35,6 @@ public:
VideoFrameContainer* aContainer,
bool aRealTime,
FrameStatistics& aFrameStats,
int aDelayDuration,
uint32_t aVQueueSentToCompositerSize);
const PlaybackParams& GetPlaybackParams() const override;
@ -74,7 +73,7 @@ private:
virtual ~VideoSink();
// VideoQueue listener related.
void OnVideoQueueEvent();
void OnVideoQueueEvent(RefPtr<MediaData>&& aSample);
void ConnectListener();
void DisconnectListener();
@ -139,10 +138,6 @@ private:
// Used to trigger another update of rendered frames in next round.
DelayedScheduler mUpdateScheduler;
// A delay duration to trigger next time UpdateRenderedVideoFrames().
// Based on the default value in MDSM.
const int mDelayDuration;
// Max frame number sent to compositor at a time.
// Based on the pref value obtained in MDSM.
const uint32_t mVideoQueueSendToCompositorSize;