--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -180,21 +180,22 @@ class MediaDecoderStateMachine::StateObj
public:
virtual ~StateObject() { }
virtual void Exit() { } // Exit action.
virtual void Step() { } // Perform a 'cycle' of this state object.
virtual State GetState() const = 0;
// Event handlers for various events.
virtual void HandleAudioCaptured() { }
- virtual void HandleAudioDecoded(AudioData* aAudio)
+ virtual void HandleAudioDecoded(RefPtr<AudioData> aAudio)
{
Crash("Unexpected event!", __func__);
}
- virtual void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart)
+ virtual void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+ TimeStamp aDecodeStart)
{
Crash("Unexpected event!", __func__);
}
virtual void HandleAudioWaited(MediaData::Type aType)
{
Crash("Unexpected event!", __func__);
}
virtual void HandleVideoWaited(MediaData::Type aType)
@@ -447,18 +448,21 @@ public:
void HandleResumeVideoDecoding(const TimeUnit&) override
{
// Do nothing since we won't resume decoding until exiting dormant.
}
void HandlePlayStateChanged(MediaDecoder::PlayState aPlayState) override;
- void HandleAudioDecoded(AudioData*) override { MaybeReleaseResources(); }
- void HandleVideoDecoded(VideoData*, TimeStamp) override
+ void HandleAudioDecoded(RefPtr<AudioData>) override
+ {
+ MaybeReleaseResources();
+ }
+ void HandleVideoDecoded(RefPtr<VideoData>, TimeStamp) override
{
MaybeReleaseResources();
}
void HandleWaitingForAudio() override { MaybeReleaseResources(); }
void HandleWaitingForVideo() override { MaybeReleaseResources(); }
void HandleAudioCanceled() override { MaybeReleaseResources(); }
void HandleVideoCanceled() override { MaybeReleaseResources(); }
void HandleEndOfAudio() override { MaybeReleaseResources(); }
@@ -498,25 +502,26 @@ public:
{
// mPendingSeek is either moved in MaybeFinishDecodeFirstFrame()
// or should be rejected here before transition to SHUTDOWN.
mPendingSeek.RejectIfExists(__func__);
}
State GetState() const override { return DECODER_STATE_DECODING_FIRSTFRAME; }
- void HandleAudioDecoded(AudioData* aAudio) override
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
{
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
MaybeFinishDecodeFirstFrame();
}
- void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+ void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+ TimeStamp aDecodeStart) override
{
- mMaster->PushVideo(aVideo);
+ mMaster->PushVideo(aVideo.forget());
MaybeFinishDecodeFirstFrame();
}
void HandleWaitingForAudio() override
{
mMaster->WaitForData(MediaData::AUDIO_DATA);
}
@@ -624,26 +629,27 @@ public:
void Step() override;
State GetState() const override
{
return DECODER_STATE_DECODING;
}
- void HandleAudioDecoded(AudioData* aAudio) override
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
{
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
DispatchDecodeTasksIfNeeded();
MaybeStopPrerolling();
}
- void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+ void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+ TimeStamp aDecodeStart) override
{
- mMaster->PushVideo(aVideo);
+ mMaster->PushVideo(aVideo.forget());
DispatchDecodeTasksIfNeeded();
MaybeStopPrerolling();
}
void HandleAudioCanceled() override
{
mMaster->RequestAudioData();
}
@@ -865,18 +871,18 @@ public:
virtual void Exit() override = 0;
State GetState() const override
{
return DECODER_STATE_SEEKING;
}
- void HandleAudioDecoded(AudioData* aAudio) override = 0;
- void HandleVideoDecoded(VideoData* aVideo,
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override = 0;
+ void HandleVideoDecoded(RefPtr<VideoData> aVideo,
TimeStamp aDecodeStart) override = 0;
void HandleAudioWaited(MediaData::Type aType) override = 0;
void HandleVideoWaited(MediaData::Type aType) override = 0;
void HandleVideoSuspendTimeout() override
{
// Do nothing since we want a valid video frame to show when seek is done.
}
@@ -917,57 +923,58 @@ public:
mSeekJob.RejectIfExists(__func__);
// Disconnect ReaderProxy.
mSeekRequest.DisconnectIfExists();
mWaitRequest.DisconnectIfExists();
}
- void HandleAudioDecoded(AudioData* aAudio) override
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
{
MOZ_ASSERT(!mDoneAudioSeeking || !mDoneVideoSeeking,
"Seek shouldn't be finished");
MOZ_ASSERT(aAudio);
AdjustFastSeekIfNeeded(aAudio);
if (mSeekJob.mTarget->IsFast()) {
// Non-precise seek; we can stop the seek at the first sample.
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
mDoneAudioSeeking = true;
} else {
- nsresult rv = DropAudioUpToSeekTarget(aAudio);
+ nsresult rv = DropAudioUpToSeekTarget(aAudio.forget());
if (NS_FAILED(rv)) {
mMaster->DecodeError(rv);
return;
}
}
if (!mDoneAudioSeeking) {
RequestAudioData();
return;
}
MaybeFinishSeek();
}
- void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+ void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+ TimeStamp aDecodeStart) override
{
MOZ_ASSERT(!mDoneAudioSeeking || !mDoneVideoSeeking,
"Seek shouldn't be finished");
MOZ_ASSERT(aVideo);
AdjustFastSeekIfNeeded(aVideo);
if (mSeekJob.mTarget->IsFast()) {
// Non-precise seek. We can stop the seek at the first sample.
- mMaster->PushVideo(aVideo);
+ mMaster->PushVideo(aVideo.forget());
mDoneVideoSeeking = true;
} else {
- nsresult rv = DropVideoUpToSeekTarget(aVideo);
+ nsresult rv = DropVideoUpToSeekTarget(aVideo.forget());
if (NS_FAILED(rv)) {
mMaster->DecodeError(rv);
return;
}
}
if (!mDoneVideoSeeking) {
RequestVideoData();
@@ -1175,17 +1182,17 @@ protected:
// seek and decode to the seek target. This is not conformant to the
// spec, fastSeek should always be fast, but until we get the time to
// change all Readers to seek to the keyframe after the currentTime
// in this case, we'll just decode forward. Bug 1026330.
mSeekJob.mTarget->SetType(SeekTarget::Accurate);
}
}
- nsresult DropAudioUpToSeekTarget(AudioData* aAudio)
+ nsresult DropAudioUpToSeekTarget(RefPtr<AudioData> aAudio)
{
MOZ_ASSERT(aAudio && mSeekJob.mTarget->IsAccurate());
auto sampleDuration = FramesToTimeUnit(
aAudio->mFrames, Info().mAudio.mRate);
if (!sampleDuration.IsValid()) {
return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
}
@@ -1201,17 +1208,17 @@ protected:
// The seek target doesn't lie in the audio block just after the last
// audio frames we've seen which were before the seek target. This
// could have been the first audio data we've seen after seek, i.e. the
// seek terminated after the seek target in the audio stream. Just
// abort the audio decode-to-target, the state machine will play
// silence to cover the gap. Typically this happens in poorly muxed
// files.
SLOGW("Audio not synced after seek, maybe a poorly muxed file?");
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
mDoneAudioSeeking = true;
return NS_OK;
}
// The seek target lies somewhere in this AudioData's frames, strip off
// any frames which lie before the seek target, so we'll begin playback
// exactly at the seek target.
NS_ASSERTION(mSeekJob.mTarget->GetTime() >= audioTime,
@@ -1245,23 +1252,23 @@ protected:
return NS_ERROR_DOM_MEDIA_OVERFLOW_ERR;
}
RefPtr<AudioData> data(new AudioData(
aAudio->mOffset, mSeekJob.mTarget->GetTime(),
duration, frames, Move(audioData), channels,
aAudio->mRate));
MOZ_ASSERT(AudioQueue().GetSize() == 0,
"Should be the 1st sample after seeking");
- mMaster->PushAudio(data);
+ mMaster->PushAudio(data.forget());
mDoneAudioSeeking = true;
return NS_OK;
}
- nsresult DropVideoUpToSeekTarget(VideoData* aVideo)
+ nsresult DropVideoUpToSeekTarget(RefPtr<VideoData> aVideo)
{
MOZ_ASSERT(aVideo);
SLOG("DropVideoUpToSeekTarget() frame [%" PRId64 ", %" PRId64 "]",
aVideo->mTime.ToMicroseconds(), aVideo->GetEndTime().ToMicroseconds());
const auto target = GetSeekTarget();
// If the frame end time is less than the seek target, we won't want
// to display this frame after the seek, so discard it.
@@ -1284,17 +1291,17 @@ protected:
SLOG("DropVideoUpToSeekTarget() found video frame [%" PRId64 ", %" PRId64
"] containing target=%" PRId64,
aVideo->mTime.ToMicroseconds(),
aVideo->GetEndTime().ToMicroseconds(),
target.ToMicroseconds());
MOZ_ASSERT(VideoQueue().GetSize() == 0,
"Should be the 1st sample after seeking");
- mMaster->PushVideo(aVideo);
+ mMaster->PushVideo(aVideo.forget());
mDoneVideoSeeking = true;
}
return NS_OK;
}
void HandleEndOfAudioInternal()
{
@@ -1385,29 +1392,30 @@ public:
{
// Disconnect my async seek operation.
if (mAsyncSeekTask) { mAsyncSeekTask->Cancel(); }
// Disconnect MediaDecoder.
mSeekJob.RejectIfExists(__func__);
}
- void HandleAudioDecoded(AudioData* aAudio) override
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
{
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
}
- void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+ void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+ TimeStamp aDecodeStart) override
{
MOZ_ASSERT(aVideo);
MOZ_ASSERT(!mSeekJob.mPromise.IsEmpty(), "Seek shouldn't be finished");
MOZ_ASSERT(NeedMoreVideo());
if (aVideo->mTime > mCurrentTime) {
- mMaster->PushVideo(aVideo);
+ mMaster->PushVideo(aVideo.forget());
FinishSeek();
} else {
RequestVideoData();
}
}
void HandleWaitingForAudio() override
{
@@ -1658,27 +1666,27 @@ public:
// dispatch an event so that the UI can change in response to the end
// of video-only seek.
mMaster->mOnPlaybackEvent.Notify(
MediaPlaybackEvent::VideoOnlySeekCompleted);
AccurateSeekingState::Exit();
}
- void HandleAudioDecoded(AudioData* aAudio) override
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
{
MOZ_ASSERT(mDoneAudioSeeking && !mDoneVideoSeeking,
"Seek shouldn't be finished");
MOZ_ASSERT(aAudio);
// Video-only seek doesn't reset audio decoder. There might be pending audio
// requests when AccurateSeekTask::Seek() begins. We will just store the
// data without checking |mDiscontinuity| or calling
// DropAudioUpToSeekTarget().
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
}
void HandleWaitingForAudio() override { }
void HandleAudioCanceled() override { }
void HandleEndOfAudio() override { }
@@ -1799,30 +1807,31 @@ public:
mMaster->mOnNextFrameStatus.Notify(
MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE_BUFFERING);
}
void Step() override;
State GetState() const override { return DECODER_STATE_BUFFERING; }
- void HandleAudioDecoded(AudioData* aAudio) override
+ void HandleAudioDecoded(RefPtr<AudioData> aAudio) override
{
- mMaster->PushAudio(aAudio);
+ mMaster->PushAudio(aAudio.forget());
if (!mMaster->HaveEnoughDecodedAudio()) {
mMaster->RequestAudioData();
}
// This might be the sample we need to exit buffering.
// Schedule Step() to check it.
mMaster->ScheduleStateMachine();
}
- void HandleVideoDecoded(VideoData* aVideo, TimeStamp aDecodeStart) override
+ void HandleVideoDecoded(RefPtr<VideoData> aVideo,
+ TimeStamp aDecodeStart) override
{
- mMaster->PushVideo(aVideo);
+ mMaster->PushVideo(aVideo.forget());
if (!mMaster->HaveEnoughDecodedVideo()) {
mMaster->RequestVideoData(media::TimeUnit());
}
// This might be the sample we need to exit buffering.
// Schedule Step() to check it.
mMaster->ScheduleStateMachine();
}
@@ -2834,25 +2843,25 @@ MediaDecoderStateMachine::HaveEnoughDeco
bool MediaDecoderStateMachine::HaveEnoughDecodedVideo()
{
MOZ_ASSERT(OnTaskQueue());
return VideoQueue().GetSize() >= GetAmpleVideoFrames() * mPlaybackRate + 1;
}
void
-MediaDecoderStateMachine::PushAudio(AudioData* aSample)
+MediaDecoderStateMachine::PushAudio(RefPtr<AudioData> aSample)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aSample);
AudioQueue().Push(aSample);
}
void
-MediaDecoderStateMachine::PushVideo(VideoData* aSample)
+MediaDecoderStateMachine::PushVideo(RefPtr<VideoData> aSample)
{
MOZ_ASSERT(OnTaskQueue());
MOZ_ASSERT(aSample);
aSample->mFrameID = ++mCurrentFrameID;
VideoQueue().Push(aSample);
}
void
@@ -3222,17 +3231,17 @@ MediaDecoderStateMachine::RequestAudioDa
MOZ_ASSERT(aAudio);
mAudioDataRequest.Complete();
// audio->GetEndTime() is not always mono-increasing in chained ogg.
mDecodedAudioEndTime = std::max(
aAudio->GetEndTime(), mDecodedAudioEndTime);
LOGV("OnAudioDecoded [%" PRId64 ",%" PRId64 "]",
aAudio->mTime.ToMicroseconds(),
aAudio->GetEndTime().ToMicroseconds());
- mStateObj->HandleAudioDecoded(aAudio);
+ mStateObj->HandleAudioDecoded(aAudio.forget());
},
[this, self] (const MediaResult& aError) {
LOGV("OnAudioNotDecoded aError=%s", aError.ErrorName().get());
mAudioDataRequest.Complete();
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mStateObj->HandleWaitingForAudio();
break;
@@ -3268,17 +3277,17 @@ MediaDecoderStateMachine::RequestVideoDa
MOZ_ASSERT(aVideo);
mVideoDataRequest.Complete();
// Handle abnormal or negative timestamps.
mDecodedVideoEndTime = std::max(
mDecodedVideoEndTime, aVideo->GetEndTime());
LOGV("OnVideoDecoded [%" PRId64 ",%" PRId64 "]",
aVideo->mTime.ToMicroseconds(),
aVideo->GetEndTime().ToMicroseconds());
- mStateObj->HandleVideoDecoded(aVideo, videoDecodeStartTime);
+ mStateObj->HandleVideoDecoded(aVideo.forget(), videoDecodeStartTime);
},
[this, self] (const MediaResult& aError) {
LOGV("OnVideoNotDecoded aError=%s" , aError.ErrorName().get());
mVideoDataRequest.Complete();
switch (aError.Code()) {
case NS_ERROR_DOM_MEDIA_WAITING_FOR_DATA:
mStateObj->HandleWaitingForVideo();
break;