Files
tubestation/dom/media/systemservices/CamerasParent.h
Jan Grulich 7ef5f04eba Bug 1912778 - Always register video input feedback for newly created DeviceInfo r=pehrsons
Make sure to always register video input feedback when a new DeviceInfo
is created. We always destroy DeviceInfo once request to camera access
is resolved, making it to be created again, but this time skipping the
part where video input feedback is registered as we use already existing
VideoEngine. There is now just one place where DeviceInfo gets created
and the logic for video input feedback registration has been moved to
VideoEngine as it's the only place where we know when new DeviceInfo is
created.

Differential Revision: https://phabricator.services.mozilla.com/D219060
2024-09-03 07:56:39 +00:00

197 lines
7.3 KiB
C++

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set sw=2 ts=8 et ft=cpp : */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef mozilla_CamerasParent_h
#define mozilla_CamerasParent_h
#include "CamerasChild.h"
#include "mozilla/Atomics.h"
#include "mozilla/camera/PCamerasParent.h"
#include "mozilla/media/MediaUtils.h"
#include "mozilla/ipc/Shmem.h"
#include "mozilla/ShmemPool.h"
#include "api/video/video_sink_interface.h"
#include "modules/video_capture/video_capture.h"
#include "modules/video_capture/video_capture_defines.h"
#include "video/render/incoming_video_stream.h"
class WebrtcLogSinkHandle;
class nsIThread;
namespace mozilla {
class VideoCaptureFactory;
}
namespace mozilla::camera {
class CamerasParent;
class VideoEngine;
class CallbackHelper : public rtc::VideoSinkInterface<webrtc::VideoFrame> {
public:
CallbackHelper(CaptureEngine aCapEng, uint32_t aStreamId,
CamerasParent* aParent)
: mCapEngine(aCapEng),
mStreamId(aStreamId),
mTrackingId(CaptureEngineToTrackingSourceStr(aCapEng), aStreamId),
mParent(aParent) {};
// These callbacks end up running on the VideoCapture thread.
// From VideoCaptureCallback
void OnCaptureEnded();
void OnFrame(const webrtc::VideoFrame& aVideoFrame) override;
friend CamerasParent;
private:
const CaptureEngine mCapEngine;
const uint32_t mStreamId;
const TrackingId mTrackingId;
CamerasParent* const mParent;
MediaEventListener mCaptureEndedListener;
bool mConnectedToCaptureEnded = false;
};
class DeliverFrameRunnable;
class CamerasParent final : public PCamerasParent,
private webrtc::VideoInputFeedBack {
public:
using ShutdownMozPromise = media::ShutdownBlockingTicket::ShutdownMozPromise;
using CameraAccessRequestPromise = MozPromise<CamerasAccessStatus, void_t,
/* IsExclusive = */ false>;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET(
CamerasParent, mPBackgroundEventTarget)
class VideoEngineArray;
friend DeliverFrameRunnable;
static already_AddRefed<CamerasParent> Create();
/**
* Request camera access
* Currently only used on desktop. If @value
* aAllowPermissionRequest is true, a request for full camera access may be
* made and the returned promise may be blocked on user input on a modal
* dialog. If @value aAllowPermissionRequest is false, only a request to
* check camera device presence will be made. If any camera device is
* present, we will enumerate a single placeholder device until a successful
* RequestCameraAccess with a true aAllowPermissionRequest.
* The returned promise will never be rejected.
*/
static RefPtr<CameraAccessRequestPromise> RequestCameraAccess(
bool aAllowPermissionRequest);
// Messages received from the child. These run on the IPC/PBackground thread.
mozilla::ipc::IPCResult RecvPCamerasConstructor();
mozilla::ipc::IPCResult RecvAllocateCapture(
const CaptureEngine& aCapEngine, const nsACString& aUniqueIdUTF8,
const uint64_t& aWindowID) override;
mozilla::ipc::IPCResult RecvReleaseCapture(const CaptureEngine& aCapEngine,
const int& aCaptureId) override;
mozilla::ipc::IPCResult RecvNumberOfCaptureDevices(
const CaptureEngine& aCapEngine) override;
mozilla::ipc::IPCResult RecvNumberOfCapabilities(
const CaptureEngine& aCapEngine, const nsACString& aUniqueId) override;
mozilla::ipc::IPCResult RecvGetCaptureCapability(
const CaptureEngine& aCapEngine, const nsACString& aUniqueId,
const int& aIndex) override;
mozilla::ipc::IPCResult RecvGetCaptureDevice(
const CaptureEngine& aCapEngine, const int& aDeviceIndex) override;
mozilla::ipc::IPCResult RecvStartCapture(
const CaptureEngine& aCapEngine, const int& aCaptureId,
const VideoCaptureCapability& aIpcCaps) override;
mozilla::ipc::IPCResult RecvFocusOnSelectedSource(
const CaptureEngine& aCapEngine, const int& aCaptureId) override;
mozilla::ipc::IPCResult RecvStopCapture(const CaptureEngine& aCapEngine,
const int& aCaptureId) override;
mozilla::ipc::IPCResult RecvReleaseFrame(
mozilla::ipc::Shmem&& aShmem) override;
void ActorDestroy(ActorDestroyReason aWhy) override;
mozilla::ipc::IPCResult RecvEnsureInitialized(
const CaptureEngine& aCapEngine) override;
nsIEventTarget* GetBackgroundEventTarget() {
return mPBackgroundEventTarget;
};
bool IsShuttingDown() {
// the first 2 are pBackground only, the last is atomic
MOZ_ASSERT(mPBackgroundEventTarget->IsOnCurrentThread());
return mDestroyed;
};
ShmemBuffer GetBuffer(size_t aSize);
// helper to forward to the PBackground thread
int DeliverFrameOverIPC(CaptureEngine aCapEngine, uint32_t aStreamId,
const TrackingId& aTrackingId, ShmemBuffer aBuffer,
unsigned char* aAltBuffer,
const VideoFrameProperties& aProps);
CamerasParent();
private:
virtual ~CamerasParent();
// We use these helpers for shutdown and for the respective IPC commands.
void StopCapture(const CaptureEngine& aCapEngine, int aCaptureId);
int ReleaseCapture(const CaptureEngine& aCapEngine, int aCaptureId);
// VideoInputFeedBack
void OnDeviceChange() override;
// Creates a new DeviceInfo or returns an existing DeviceInfo for given
// capture engine. Returns a nullptr in case capture engine failed to be
// initialized. Video capture thread only.
std::shared_ptr<webrtc::VideoCaptureModule::DeviceInfo> GetDeviceInfo(
int aEngine);
VideoEngine* EnsureInitialized(int aEngine);
// Stops any ongoing capturing and releases resources. Called on
// mVideoCaptureThread. Idempotent.
void CloseEngines();
void OnShutdown();
nsTArray<CallbackHelper*> mCallbacks;
// If existent, blocks xpcom shutdown while alive.
// Note that this makes a reference cycle that gets broken in ActorDestroy().
const UniquePtr<media::ShutdownBlockingTicket> mShutdownBlocker;
// Tracks the mShutdownBlocker shutdown handler. mPBackgroundEventTarget only.
MozPromiseRequestHolder<ShutdownMozPromise> mShutdownRequest;
// Local copy of sVideoCaptureThread. Guaranteed alive if non-null.
const nsCOMPtr<nsISerialEventTarget> mVideoCaptureThread;
// Reference to same VideoEngineArray as sEngines. Video capture thread only.
const RefPtr<VideoEngineArray> mEngines;
// Reference to same VideoCaptureFactory as sVideoCaptureFactory. Video
// capture thread only.
const RefPtr<VideoCaptureFactory> mVideoCaptureFactory;
// image buffers
ShmemPool mShmemPool;
// PBackgroundParent thread
const nsCOMPtr<nsISerialEventTarget> mPBackgroundEventTarget;
// Set to true in ActorDestroy. PBackground only.
bool mDestroyed;
std::map<nsCString, std::map<uint32_t, webrtc::VideoCaptureCapability>>
mAllCandidateCapabilities;
// While alive, ensure webrtc logging is hooked up to MOZ_LOG. Main thread
// only.
nsMainThreadPtrHandle<WebrtcLogSinkHandle> mLogHandle;
};
} // namespace mozilla::camera
#endif // mozilla_CameraParent_h