diff --git a/dom/media/MediaRecorder.cpp b/dom/media/MediaRecorder.cpp index 1df252aee8b4..8a49b70f1ba1 100644 --- a/dom/media/MediaRecorder.cpp +++ b/dom/media/MediaRecorder.cpp @@ -592,7 +592,7 @@ class MediaRecorder::Session : public PrincipalChangeObserver, return NS_ERROR_FAILURE; } - mEncoder->Suspend(TimeStamp::Now()); + mEncoder->Suspend(); NS_DispatchToMainThread( new DispatchEventRunnable(this, NS_LITERAL_STRING("pause"))); return NS_OK; @@ -606,7 +606,7 @@ class MediaRecorder::Session : public PrincipalChangeObserver, return NS_ERROR_FAILURE; } - mEncoder->Resume(TimeStamp::Now()); + mEncoder->Resume(); NS_DispatchToMainThread( new DispatchEventRunnable(this, NS_LITERAL_STRING("resume"))); return NS_OK; diff --git a/dom/media/encoder/MediaEncoder.cpp b/dom/media/encoder/MediaEncoder.cpp index 4e65c06f5f52..b9f0341afa10 100644 --- a/dom/media/encoder/MediaEncoder.cpp +++ b/dom/media/encoder/MediaEncoder.cpp @@ -11,6 +11,7 @@ #include "DriftCompensation.h" #include "GeckoProfiler.h" #include "MediaDecoder.h" +#include "MediaStreamGraphImpl.h" #include "MediaStreamListener.h" #include "mozilla/dom/AudioNode.h" #include "mozilla/dom/AudioStreamTrack.h" @@ -26,6 +27,7 @@ #include "mozilla/Unused.h" #include "nsIPrincipal.h" #include "nsMimeTypes.h" +#include "nsThreadUtils.h" #include "OggWriter.h" #include "OpusTrackEncoder.h" #include "TimeUnits.h" @@ -434,36 +436,66 @@ MediaEncoder::MediaEncoder(TaskQueue* aEncoderThread, MediaEncoder::~MediaEncoder() { MOZ_ASSERT(mListeners.IsEmpty()); } -void MediaEncoder::Suspend(TimeStamp aTime) { - auto& ae = mAudioEncoder; - auto& ve = mVideoEncoder; - nsresult rv = mEncoderThread->Dispatch(NewRunnableFrom([ae, ve, aTime]() { - if (ae) { - ae->Suspend(aTime); - } - if (ve) { - ve->Suspend(aTime); - } - return NS_OK; - })); - MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); - Unused << rv; +void MediaEncoder::RunOnGraph(already_AddRefed aRunnable) { + MediaStreamGraphImpl* graph; + if (mAudioTrack) { + graph = mAudioTrack->GraphImpl(); + } else if (mVideoTrack) { + graph = mVideoTrack->GraphImpl(); + } else if (mPipeStream) { + graph = mPipeStream->GraphImpl(); + } else { + MOZ_CRASH("No graph"); + } + class Message : public ControlMessage { + public: + explicit Message(already_AddRefed aRunnable) + : ControlMessage(nullptr), mRunnable(aRunnable) {} + void Run() override { mRunnable->Run(); } + const RefPtr mRunnable; + }; + graph->AppendMessage(MakeUnique(std::move(aRunnable))); } -void MediaEncoder::Resume(TimeStamp aTime) { - auto& ae = mAudioEncoder; - auto& ve = mVideoEncoder; - nsresult rv = mEncoderThread->Dispatch(NewRunnableFrom([ae, ve, aTime]() { - if (ae) { - ae->Resume(aTime); - } - if (ve) { - ve->Resume(aTime); - } - return NS_OK; - })); - MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); - Unused << rv; +void MediaEncoder::Suspend() { + RunOnGraph(NS_NewRunnableFunction( + "MediaEncoder::Suspend", + [thread = mEncoderThread, audio = mAudioEncoder, video = mVideoEncoder] { + if (audio) { + nsresult rv = thread->Dispatch( + NewRunnableMethod("AudioTrackEncoder::Suspend", audio, + &AudioTrackEncoder::Suspend)); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + Unused << rv; + } + if (video) { + nsresult rv = thread->Dispatch(NewRunnableMethod( + "VideoTrackEncoder::Suspend", video, &VideoTrackEncoder::Suspend, + TimeStamp::Now())); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + Unused << rv; + } + })); +} + +void MediaEncoder::Resume() { + RunOnGraph(NS_NewRunnableFunction( + "MediaEncoder::Resume", + [thread = mEncoderThread, audio = mAudioEncoder, video = mVideoEncoder] { + if (audio) { + nsresult rv = thread->Dispatch(NewRunnableMethod( + "AudioTrackEncoder::Resume", audio, &AudioTrackEncoder::Resume)); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + Unused << rv; + } + if (video) { + nsresult rv = thread->Dispatch(NewRunnableMethod( + "VideoTrackEncoder::Resume", video, &VideoTrackEncoder::Resume, + TimeStamp::Now())); + MOZ_DIAGNOSTIC_ASSERT(NS_SUCCEEDED(rv)); + Unused << rv; + } + })); } void MediaEncoder::ConnectAudioNode(AudioNode* aNode, uint32_t aOutput) { diff --git a/dom/media/encoder/MediaEncoder.h b/dom/media/encoder/MediaEncoder.h index d454f90bc998..ccbd3fc923e5 100644 --- a/dom/media/encoder/MediaEncoder.h +++ b/dom/media/encoder/MediaEncoder.h @@ -19,6 +19,7 @@ namespace mozilla { class DriftCompensator; +class Runnable; class TaskQueue; namespace dom { @@ -115,13 +116,15 @@ class MediaEncoder { VideoTrackEncoder* aVideoEncoder, TrackRate aTrackRate, const nsAString& aMIMEType); - /* Note - called from control code, not on MSG threads. */ - void Suspend(TimeStamp aTime); + /** + * Called on main thread from MediaRecorder::Pause. + */ + void Suspend(); /** - * Note - called from control code, not on MSG threads. - * Calculates time spent paused in order to offset frames. */ - void Resume(TimeStamp aTime); + * Called on main thread from MediaRecorder::Resume. + */ + void Resume(); /** * Stops the current encoding, and disconnects the input tracks. @@ -231,6 +234,12 @@ class MediaEncoder { ~MediaEncoder(); private: + /** + * Takes a regular runnable and dispatches it to the graph wrapped in a + * ControlMessage. + */ + void RunOnGraph(already_AddRefed aRunnable); + /** * Shuts down the MediaEncoder and cleans up track encoders. * Listeners will be notified of the shutdown unless we were Cancel()ed first. diff --git a/dom/media/encoder/TrackEncoder.cpp b/dom/media/encoder/TrackEncoder.cpp index e3f1c4d83dbb..81f0a5f42f36 100644 --- a/dom/media/encoder/TrackEncoder.cpp +++ b/dom/media/encoder/TrackEncoder.cpp @@ -102,7 +102,7 @@ void TrackEncoder::SetWorkerThread(AbstractThread* aWorkerThread) { mWorkerThread = aWorkerThread; } -void AudioTrackEncoder::Suspend(TimeStamp) { +void AudioTrackEncoder::Suspend() { MOZ_ASSERT(!mWorkerThread || mWorkerThread->IsCurrentThreadIn()); TRACK_LOG(LogLevel::Info, ("[AudioTrackEncoder %p]: Suspend(), was %s", this, mSuspended ? "suspended" : "live")); @@ -114,7 +114,7 @@ void AudioTrackEncoder::Suspend(TimeStamp) { mSuspended = true; } -void AudioTrackEncoder::Resume(TimeStamp) { +void AudioTrackEncoder::Resume() { MOZ_ASSERT(!mWorkerThread || mWorkerThread->IsCurrentThreadIn()); TRACK_LOG(LogLevel::Info, ("[AudioTrackEncoder %p]: Resume(), was %s", this, mSuspended ? "suspended" : "live")); diff --git a/dom/media/encoder/TrackEncoder.h b/dom/media/encoder/TrackEncoder.h index 18dae50682da..280ca1d161a1 100644 --- a/dom/media/encoder/TrackEncoder.h +++ b/dom/media/encoder/TrackEncoder.h @@ -61,10 +61,6 @@ class TrackEncoder { public: explicit TrackEncoder(TrackRate aTrackRate); - virtual void Suspend(TimeStamp aTime) = 0; - - virtual void Resume(TimeStamp aTime) = 0; - /** * Called by MediaEncoder to cancel the encoding. */ @@ -200,13 +196,13 @@ class AudioTrackEncoder : public TrackEncoder { * Suspends encoding from now, i.e., all future audio data received through * AppendAudioSegment() until the next Resume() will be dropped. */ - void Suspend(TimeStamp aTime) override; + void Suspend(); /** * Resumes encoding starting now, i.e., data from the next * AppendAudioSegment() will get encoded. */ - void Resume(TimeStamp aTime) override; + void Resume(); /** * Appends and consumes track data from aSegment. @@ -340,12 +336,12 @@ class VideoTrackEncoder : public TrackEncoder { * Suspends encoding from aTime, i.e., all video frame with a timestamp * between aTime and the timestamp of the next Resume() will be dropped. */ - void Suspend(TimeStamp aTime) override; + void Suspend(TimeStamp aTime); /** * Resumes encoding starting at aTime. */ - void Resume(TimeStamp aTime) override; + void Resume(TimeStamp aTime); /** * Appends source video frames to mIncomingBuffer. We only append the source diff --git a/dom/media/encoder/moz.build b/dom/media/encoder/moz.build index 76381c7d6910..9fe2c9459f40 100644 --- a/dom/media/encoder/moz.build +++ b/dom/media/encoder/moz.build @@ -33,8 +33,10 @@ DEFINES['TRACING'] = True FINAL_LIBRARY = 'xul' -# These includes are from Android JB, for use of MediaCodec. -LOCAL_INCLUDES += ['/ipc/chromium/src'] +LOCAL_INCLUDES += [ + '/dom/media', + '/ipc/chromium/src', +] include('/ipc/chromium/chromium-config.mozbuild')