tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

commit 5f30f72c4a2b57a6a830a82d292a9c440df60458
parent 1c7baf74eeb18f584cae392e5bc7ab19310f256c
Author: Andreas Pehrson <apehrson@mozilla.com>
Date:   Tue, 11 Nov 2025 08:20:26 +0000

Bug 1771789 - Extend webrtc::VideoFrame lifetime a bit to avoid an extra allocation and copy in some cases. r=jib

This is safe as the image buffer backing webrtc::VideoFrame is refcounted.

Differential Revision: https://phabricator.services.mozilla.com/D266406

Diffstat:
Mdom/media/systemservices/CamerasParent.cpp | 48+++++++++++++++++-------------------------------
Mdom/media/systemservices/CamerasParent.h | 4++--
2 files changed, 19 insertions(+), 33 deletions(-)

diff --git a/dom/media/systemservices/CamerasParent.cpp b/dom/media/systemservices/CamerasParent.cpp @@ -258,6 +258,8 @@ void CamerasParent::OnDeviceChange() { class DeliverFrameRunnable : public mozilla::Runnable { public: + // Constructor for when no ShmemBuffer (of the right size) was available, so + // keep the frame around until we can allocate one on PBackground (in Run). DeliverFrameRunnable(CamerasParent* aParent, CaptureEngine aEngine, int aCaptureId, nsTArray<int>&& aStreamIds, const TrackingId& aTrackingId, @@ -269,21 +271,8 @@ class DeliverFrameRunnable : public mozilla::Runnable { mCaptureId(aCaptureId), mStreamIds(std::move(aStreamIds)), mTrackingId(aTrackingId), - mProperties(aProperties) { - // No ShmemBuffer (of the right size) was available, so make an - // extra buffer here. We have no idea when we are going to run and - // it will be potentially long after the webrtc frame callback has - // returned, so the copy needs to be no later than here. - // We will need to copy this back into a Shmem later on so we prefer - // using ShmemBuffers to avoid the extra copy. - PerformanceRecorder<CopyVideoStage> rec( - "CamerasParent::VideoFrameToAltBuffer"_ns, aTrackingId, aFrame.width(), - aFrame.height()); - mAlternateBuffer.reset(new unsigned char[aProperties.bufferSize()]); - VideoFrameUtils::CopyVideoFrameBuffers(mAlternateBuffer.get(), - aProperties.bufferSize(), aFrame); - rec.Record(); - } + mBuffer(aFrame), + mProperties(aProperties) {} DeliverFrameRunnable(CamerasParent* aParent, CaptureEngine aEngine, int aCaptureId, nsTArray<int>&& aStreamIds, @@ -307,8 +296,7 @@ class DeliverFrameRunnable : public mozilla::Runnable { return NS_OK; } mParent->DeliverFrameOverIPC(mCapEngine, mCaptureId, mStreamIds, - mTrackingId, std::move(mBuffer), - mAlternateBuffer.get(), mProperties); + mTrackingId, std::move(mBuffer), mProperties); return NS_OK; } @@ -318,22 +306,20 @@ class DeliverFrameRunnable : public mozilla::Runnable { const int mCaptureId; const nsTArray<int> mStreamIds; const TrackingId mTrackingId; - ShmemBuffer mBuffer; - UniquePtr<unsigned char[]> mAlternateBuffer; + Variant<ShmemBuffer, webrtc::VideoFrame> mBuffer; const VideoFrameProperties mProperties; }; -int CamerasParent::DeliverFrameOverIPC(CaptureEngine aCapEngine, int aCaptureId, - const Span<const int>& aStreamIds, - const TrackingId& aTrackingId, - ShmemBuffer aBuffer, - unsigned char* aAltBuffer, - const VideoFrameProperties& aProps) { +int CamerasParent::DeliverFrameOverIPC( + CaptureEngine aCapEngine, int aCaptureId, const Span<const int>& aStreamIds, + const TrackingId& aTrackingId, + Variant<ShmemBuffer, webrtc::VideoFrame>&& aBuffer, + const VideoFrameProperties& aProps) { // No ShmemBuffers were available, so construct one now of the right size // and copy into it. That is an extra copy, but we expect this to be // the exceptional case, because we just assured the next call *will* have a // buffer of the right size. - if (aAltBuffer != nullptr) { + if (!aBuffer.is<ShmemBuffer>()) { // Get a shared memory buffer from the pool, at least size big ShmemBuffer shMemBuff; { @@ -354,8 +340,8 @@ int CamerasParent::DeliverFrameOverIPC(CaptureEngine aCapEngine, int aCaptureId, PerformanceRecorder<CopyVideoStage> rec( "CamerasParent::AltBufferToShmem"_ns, aTrackingId, aProps.width(), aProps.height()); - // get() and Size() check for proper alignment of the segment - memcpy(shMemBuff.GetBytes(), aAltBuffer, aProps.bufferSize()); + VideoFrameUtils::CopyVideoFrameBuffers(shMemBuff, + aBuffer.as<webrtc::VideoFrame>()); rec.Record(); if (!SendDeliverFrame(aCaptureId, aStreamIds, std::move(shMemBuff.Get()), @@ -363,11 +349,11 @@ int CamerasParent::DeliverFrameOverIPC(CaptureEngine aCapEngine, int aCaptureId, return -1; } } else { - MOZ_ASSERT(aBuffer.Valid()); + MOZ_ASSERT(aBuffer.as<ShmemBuffer>().Valid()); // ShmemBuffer was available, we're all good. A single copy happened // in the original webrtc callback. - if (!SendDeliverFrame(aCaptureId, aStreamIds, std::move(aBuffer.Get()), - aProps)) { + if (!SendDeliverFrame(aCaptureId, aStreamIds, + std::move(aBuffer.as<ShmemBuffer>().Get()), aProps)) { return -1; } } diff --git a/dom/media/systemservices/CamerasParent.h b/dom/media/systemservices/CamerasParent.h @@ -212,8 +212,8 @@ class CamerasParent final : public PCamerasParent { // helper to forward to the PBackground thread int DeliverFrameOverIPC(CaptureEngine aCapEngine, int aCaptureId, const Span<const int>& aStreamId, - const TrackingId& aTrackingId, ShmemBuffer aBuffer, - unsigned char* aAltBuffer, + const TrackingId& aTrackingId, + Variant<ShmemBuffer, webrtc::VideoFrame>&& aBuffer, const VideoFrameProperties& aProps); CamerasParent();