Skip to content

Commit 562e1e6

Browse files
authored
browser(firefox): wait for file write to finish in stopVideoRecording (#3020)
1 parent c45b579 commit 562e1e6

File tree

4 files changed

+39
-6
lines changed

4 files changed

+39
-6
lines changed

browser_patches/firefox/BUILD_NUMBER

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
1-
1130
2-
Changed: [email protected] Thu Jul 16 15:31:21 PDT 2020
1+
1131
2+
Changed: [email protected] Fri Jul 17 17:30:24 PDT 2020

browser_patches/firefox/juggler/protocol/PageHandler.js

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,13 +300,23 @@ class PageHandler {
300300
this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, devicePixelRatio * rect.top);
301301
}
302302

303-
stopVideoRecording() {
303+
async stopVideoRecording() {
304304
if (this._videoSessionId === -1)
305305
throw new Error('No video recording in progress');
306306
const videoSessionId = this._videoSessionId;
307307
this._videoSessionId = -1;
308308
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService);
309+
const result = new Promise(resolve =>
310+
Services.obs.addObserver(function onStopped(subject, topic, data) {
311+
if (videoSessionId != data)
312+
return;
313+
314+
Services.obs.removeObserver(onStopped, 'juggler-screencast-stopped');
315+
resolve();
316+
}, 'juggler-screencast-stopped')
317+
);
309318
screencast.stopVideoRecording(videoSessionId);
319+
return result;
310320
}
311321
}
312322

browser_patches/firefox/juggler/screencast/nsIScreencastService.idl

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,5 +13,9 @@ interface nsIDocShell;
1313
interface nsIScreencastService : nsISupports
1414
{
1515
long startVideoRecording(in nsIDocShell docShell, in ACString fileName, in uint32_t width, in uint32_t height, in double scale, in int32_t offset_top);
16+
17+
/**
18+
* Will emit 'juggler-screencast-stopped' when the video file is saved.
19+
*/
1620
void stopVideoRecording(in long sessionId);
1721
};

browser_patches/firefox/juggler/screencast/nsScreencastService.cpp

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
#include "mozilla/PresShell.h"
1212
#include "mozilla/StaticPtr.h"
1313
#include "nsIDocShell.h"
14+
#include "nsIObserverService.h"
15+
#include "nsISupportsPrimitives.h"
1416
#include "nsThreadManager.h"
1517
#include "nsView.h"
1618
#include "nsViewManager.h"
@@ -46,6 +48,18 @@ rtc::scoped_refptr<webrtc::VideoCaptureModule> CreateWindowCapturer(nsIWidget* w
4648
windowId.AppendPrintf("%" PRIuPTR, rawWindowId);
4749
return webrtc::DesktopCaptureImpl::Create(sessionId, windowId.get(), webrtc::CaptureDeviceType::Window);
4850
}
51+
52+
void NotifyScreencastStopped(int32_t sessionId) {
53+
nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService();
54+
if (!observerService) {
55+
fprintf(stderr, "NotifyScreencastStopped error: no observer service\n");
56+
return;
57+
}
58+
59+
nsString id;
60+
id.AppendPrintf("%" PRIi32, sessionId);
61+
observerService->NotifyObservers(nullptr, "juggler-screencast-stopped", id.get());
62+
}
4963
}
5064

5165
class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
@@ -72,13 +86,13 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
7286
return true;
7387
}
7488

75-
void Stop() {
89+
void Stop(std::function<void()>&& callback) {
7690
mCaptureModule->DeRegisterCaptureDataCallback(this);
7791
int error = mCaptureModule->StopCapture();
7892
if (error) {
7993
fprintf(stderr, "StopCapture error %d\n", error);
80-
return;
8194
}
95+
mEncoder->finish(std::move(callback));
8296
}
8397

8498
// These callbacks end up running on the VideoCapture thread.
@@ -150,7 +164,12 @@ nsresult nsScreencastService::StopVideoRecording(int32_t sessionId) {
150164
auto it = mIdToSession.find(sessionId);
151165
if (it == mIdToSession.end())
152166
return NS_ERROR_INVALID_ARG;
153-
it->second->Stop();
167+
it->second->Stop([sessionId] {
168+
NS_DispatchToMainThread(NS_NewRunnableFunction(
169+
"NotifyScreencastStopped", [sessionId]() -> void {
170+
NotifyScreencastStopped(sessionId);
171+
}));
172+
});
154173
mIdToSession.erase(it);
155174
return NS_OK;
156175
}

0 commit comments

Comments
 (0)