From 562e1e6460676da28183be848ece90bc4696ecaf Mon Sep 17 00:00:00 2001 From: Yury Semikhatsky Date: Fri, 17 Jul 2020 17:34:09 -0700 Subject: [PATCH] browser(firefox): wait for file write to finish in stopVideoRecording (#3020) --- browser_patches/firefox/BUILD_NUMBER | 4 +-- .../firefox/juggler/protocol/PageHandler.js | 12 ++++++++- .../screencast/nsIScreencastService.idl | 4 +++ .../screencast/nsScreencastService.cpp | 25 ++++++++++++++++--- 4 files changed, 39 insertions(+), 6 deletions(-) diff --git a/browser_patches/firefox/BUILD_NUMBER b/browser_patches/firefox/BUILD_NUMBER index aaea94d989..0d541dc2d4 100644 --- a/browser_patches/firefox/BUILD_NUMBER +++ b/browser_patches/firefox/BUILD_NUMBER @@ -1,2 +1,2 @@ -1130 -Changed: yurys@chromium.org Thu Jul 16 15:31:21 PDT 2020 +1131 +Changed: yurys@chromium.org Fri Jul 17 17:30:24 PDT 2020 diff --git a/browser_patches/firefox/juggler/protocol/PageHandler.js b/browser_patches/firefox/juggler/protocol/PageHandler.js index 0ca7fa6f11..fc061dbc74 100644 --- a/browser_patches/firefox/juggler/protocol/PageHandler.js +++ b/browser_patches/firefox/juggler/protocol/PageHandler.js @@ -300,13 +300,23 @@ class PageHandler { this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, devicePixelRatio * rect.top); } - stopVideoRecording() { + async stopVideoRecording() { if (this._videoSessionId === -1) throw new Error('No video recording in progress'); const videoSessionId = this._videoSessionId; this._videoSessionId = -1; const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService); + const result = new Promise(resolve => + Services.obs.addObserver(function onStopped(subject, topic, data) { + if (videoSessionId != data) + return; + + Services.obs.removeObserver(onStopped, 'juggler-screencast-stopped'); + resolve(); + }, 'juggler-screencast-stopped') + ); screencast.stopVideoRecording(videoSessionId); + return result; } } diff --git a/browser_patches/firefox/juggler/screencast/nsIScreencastService.idl b/browser_patches/firefox/juggler/screencast/nsIScreencastService.idl index 7f896a6c46..acac1bd3bd 100644 --- a/browser_patches/firefox/juggler/screencast/nsIScreencastService.idl +++ b/browser_patches/firefox/juggler/screencast/nsIScreencastService.idl @@ -13,5 +13,9 @@ interface nsIDocShell; interface nsIScreencastService : nsISupports { long startVideoRecording(in nsIDocShell docShell, in ACString fileName, in uint32_t width, in uint32_t height, in double scale, in int32_t offset_top); + + /** + * Will emit 'juggler-screencast-stopped' when the video file is saved. + */ void stopVideoRecording(in long sessionId); }; diff --git a/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp b/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp index eb3b9d0153..6889d8b380 100644 --- a/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp +++ b/browser_patches/firefox/juggler/screencast/nsScreencastService.cpp @@ -11,6 +11,8 @@ #include "mozilla/PresShell.h" #include "mozilla/StaticPtr.h" #include "nsIDocShell.h" +#include "nsIObserverService.h" +#include "nsISupportsPrimitives.h" #include "nsThreadManager.h" #include "nsView.h" #include "nsViewManager.h" @@ -46,6 +48,18 @@ rtc::scoped_refptr CreateWindowCapturer(nsIWidget* w windowId.AppendPrintf("%" PRIuPTR, rawWindowId); return webrtc::DesktopCaptureImpl::Create(sessionId, windowId.get(), webrtc::CaptureDeviceType::Window); } + +void NotifyScreencastStopped(int32_t sessionId) { + nsCOMPtr observerService = mozilla::services::GetObserverService(); + if (!observerService) { + fprintf(stderr, "NotifyScreencastStopped error: no observer service\n"); + return; + } + + nsString id; + id.AppendPrintf("%" PRIi32, sessionId); + observerService->NotifyObservers(nullptr, "juggler-screencast-stopped", id.get()); +} } class nsScreencastService::Session : public rtc::VideoSinkInterface { @@ -72,13 +86,13 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface&& callback) { mCaptureModule->DeRegisterCaptureDataCallback(this); int error = mCaptureModule->StopCapture(); if (error) { fprintf(stderr, "StopCapture error %d\n", error); - return; } + mEncoder->finish(std::move(callback)); } // These callbacks end up running on the VideoCapture thread. @@ -150,7 +164,12 @@ nsresult nsScreencastService::StopVideoRecording(int32_t sessionId) { auto it = mIdToSession.find(sessionId); if (it == mIdToSession.end()) return NS_ERROR_INVALID_ARG; - it->second->Stop(); + it->second->Stop([sessionId] { + NS_DispatchToMainThread(NS_NewRunnableFunction( + "NotifyScreencastStopped", [sessionId]() -> void { + NotifyScreencastStopped(sessionId); + })); + }); mIdToSession.erase(it); return NS_OK; }