/* * Copyright (c) 2013 The WebRTC project authors. All Rights Reserved. * * Use of this source code is governed by a BSD-style license * that can be found in the LICENSE file in the root of the source * tree. An additional intellectual property rights grant can be found * in the file PATENTS. All contributing project authors may * be found in the AUTHORS file in the root of the source tree.
*/
// mMainThreadWorker handles frame capture requests async. Since we're in the // dtor, no more frame capture requests can be made through CaptureFrame(). It // can be shut down now.
mMainThreadWorker->BeginShutdown();
// There may still be async frame capture requests in flight, waiting to be // reported to mCallback on mCallbackWorker. Disconnect them (must be done on // mCallbackWorker) and shut down mCallbackWorker to ensure nothing more can // get queued to it.
MOZ_ALWAYS_SUCCEEDS(
mCallbackWorker->Dispatch(NS_NewRunnableFunction(__func__, [this] {
RTC_DCHECK_RUN_ON(&mCallbackChecker); for (constauto& req : mRequests) {
DisconnectRequest(req);
}
mCallbackWorker->BeginShutdown();
})));
// Block until the workers have run all pending tasks. We must do this for two // reasons: // - All runnables dispatched to mMainThreadWorker and mCallbackWorker capture // the raw pointer `this` as they rely on `this` outliving the worker // TaskQueues. // - mCallback is only guaranteed to outlive `this`. No calls can be made to // it after the dtor is finished.
// Spin the underlying thread of mCallbackWorker, which we are currently on, // until it is empty. We have no other way of waiting for mCallbackWorker to // become empty while blocking the current call.
SpinEventLoopUntil<ProcessFailureBehavior::IgnoreAndContinue>( "~TabCapturerWebrtc"_ns, [&] { return mCallbackWorker->IsEmpty(); });
// No need to await shutdown since it was shut down synchronously above.
mMainThreadWorker->AwaitIdle();
}
bool TabCapturerWebrtc::SelectSource(webrtc::DesktopCapturer::SourceId) {
MOZ_ASSERT_UNREACHABLE("Source is passed through ctor for constness"); returntrue;
}
void TabCapturerWebrtc::CaptureFrame() {
RTC_DCHECK_RUN_ON(&mCallbackChecker);
LOG_FUNCV(); if (mRequests.GetSize() > 2) { // Allow two async capture requests in flight
OnCaptureFrameFailure(); return;
}
auto request = MakeRefPtr<CaptureFrameRequest>();
InvokeAsync(mMainThreadWorker, __func__, [this] { return CaptureFrameNow(); })
->Then(mCallbackWorker, __func__,
[this, request](CapturePromise::ResolveOrRejectValue&& aValue) { if (!CompleteRequest(request)) { // Request was disconnected or overrun. Failure has already // been reported to the callback elsewhere. return;
}
if (aValue.IsReject()) {
OnCaptureFrameFailure(); return;
}
bool TabCapturerWebrtc::CompleteRequest(CaptureFrameRequest* aRequest) {
RTC_DCHECK_RUN_ON(&mCallbackChecker); if (!aRequest->Exists()) { // Request was disconnected or overrun. mCallback has already been notified. returnfalse;
} while (CaptureFrameRequest* req = mRequests.Peek()) { if (req->mCaptureTime > aRequest->mCaptureTime) { break;
} // Pop the request before calling the callback, in case it could mutate // mRequests, now or in the future.
RefPtr<CaptureFrameRequest> dropMe = mRequests.Pop();
req->Complete(); if (req->mCaptureTime < aRequest->mCaptureTime) {
OnCaptureFrameFailure();
}
}
MOZ_DIAGNOSTIC_ASSERT(!aRequest->Exists()); returntrue;
}
auto TabCapturerWebrtc::CaptureFrameNow() -> RefPtr<CapturePromise> {
MOZ_ASSERT(mMainThreadWorker->IsOnCurrentThread());
LOG_FUNCV();
WindowGlobalParent* wgp = nullptr;
RefPtr<BrowsingContext> context =
BrowsingContext::GetCurrentTopByBrowserId(mBrowserId); if (context) {
wgp = context->Canonical()->GetCurrentWindowGlobal();
} if (!wgp) { // If we can't access the window, we just won't capture anything return CapturePromise::CreateAndReject(NS_ERROR_NOT_AVAILABLE, __func__);
}
// XXX This would be more efficient if we used CrossProcessPaint directly and // returned a surface.
RefPtr<Promise> promise =
wgp->DrawSnapshot(nullptr, 1.0, "white"_ns, false, IgnoreErrors()); if (!promise) { return CapturePromise::CreateAndReject(NS_ERROR_FAILURE, __func__);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.