browser(firefox): wait for file write to finish in stopVideoRecording (#3020)

This commit is contained in:
Yury Semikhatsky 2020-07-17 17:34:09 -07:00 committed by GitHub
parent c45b5797fa
commit 562e1e6460
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 39 additions and 6 deletions

View File

@ -1,2 +1,2 @@
1130 1131
Changed: yurys@chromium.org Thu Jul 16 15:31:21 PDT 2020 Changed: yurys@chromium.org Fri Jul 17 17:30:24 PDT 2020

View File

@ -300,13 +300,23 @@ class PageHandler {
this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, devicePixelRatio * rect.top); this._videoSessionId = screencast.startVideoRecording(docShell, file, width, height, scale || 0, devicePixelRatio * rect.top);
} }
stopVideoRecording() { async stopVideoRecording() {
if (this._videoSessionId === -1) if (this._videoSessionId === -1)
throw new Error('No video recording in progress'); throw new Error('No video recording in progress');
const videoSessionId = this._videoSessionId; const videoSessionId = this._videoSessionId;
this._videoSessionId = -1; this._videoSessionId = -1;
const screencast = Cc['@mozilla.org/juggler/screencast;1'].getService(Ci.nsIScreencastService); 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); screencast.stopVideoRecording(videoSessionId);
return result;
} }
} }

View File

@ -13,5 +13,9 @@ interface nsIDocShell;
interface nsIScreencastService : nsISupports 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); 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); void stopVideoRecording(in long sessionId);
}; };

View File

@ -11,6 +11,8 @@
#include "mozilla/PresShell.h" #include "mozilla/PresShell.h"
#include "mozilla/StaticPtr.h" #include "mozilla/StaticPtr.h"
#include "nsIDocShell.h" #include "nsIDocShell.h"
#include "nsIObserverService.h"
#include "nsISupportsPrimitives.h"
#include "nsThreadManager.h" #include "nsThreadManager.h"
#include "nsView.h" #include "nsView.h"
#include "nsViewManager.h" #include "nsViewManager.h"
@ -46,6 +48,18 @@ rtc::scoped_refptr<webrtc::VideoCaptureModule> CreateWindowCapturer(nsIWidget* w
windowId.AppendPrintf("%" PRIuPTR, rawWindowId); windowId.AppendPrintf("%" PRIuPTR, rawWindowId);
return webrtc::DesktopCaptureImpl::Create(sessionId, windowId.get(), webrtc::CaptureDeviceType::Window); return webrtc::DesktopCaptureImpl::Create(sessionId, windowId.get(), webrtc::CaptureDeviceType::Window);
} }
void NotifyScreencastStopped(int32_t sessionId) {
nsCOMPtr<nsIObserverService> 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<webrtc::VideoFrame> { class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
@ -72,13 +86,13 @@ class nsScreencastService::Session : public rtc::VideoSinkInterface<webrtc::Vide
return true; return true;
} }
void Stop() { void Stop(std::function<void()>&& callback) {
mCaptureModule->DeRegisterCaptureDataCallback(this); mCaptureModule->DeRegisterCaptureDataCallback(this);
int error = mCaptureModule->StopCapture(); int error = mCaptureModule->StopCapture();
if (error) { if (error) {
fprintf(stderr, "StopCapture error %d\n", error); fprintf(stderr, "StopCapture error %d\n", error);
return;
} }
mEncoder->finish(std::move(callback));
} }
// These callbacks end up running on the VideoCapture thread. // These callbacks end up running on the VideoCapture thread.
@ -150,7 +164,12 @@ nsresult nsScreencastService::StopVideoRecording(int32_t sessionId) {
auto it = mIdToSession.find(sessionId); auto it = mIdToSession.find(sessionId);
if (it == mIdToSession.end()) if (it == mIdToSession.end())
return NS_ERROR_INVALID_ARG; return NS_ERROR_INVALID_ARG;
it->second->Stop(); it->second->Stop([sessionId] {
NS_DispatchToMainThread(NS_NewRunnableFunction(
"NotifyScreencastStopped", [sessionId]() -> void {
NotifyScreencastStopped(sessionId);
}));
});
mIdToSession.erase(it); mIdToSession.erase(it);
return NS_OK; return NS_OK;
} }