summaryrefslogtreecommitdiffstats
path: root/dom/media/systemservices/CamerasParent.h
blob: 97e7ea0bd4672c919055af7a2454ae7608fbaddb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/* -*- 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 "VideoEngine.h"
#include "mozilla/Atomics.h"
#include "mozilla/camera/PCamerasParent.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 nsIThread;

namespace mozilla::camera {

class CamerasParent;

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 OnFrame(const webrtc::VideoFrame& aVideoFrame) override;

  friend CamerasParent;

 private:
  const CaptureEngine mCapEngine;
  const uint32_t mStreamId;
  const TrackingId mTrackingId;
  CamerasParent* const mParent;
};

class DeliverFrameRunnable;

class CamerasParent final : public PCamerasParent,
                            private webrtc::VideoInputFeedBack {
  using ShutdownMozPromise = media::ShutdownBlockingTicket::ShutdownMozPromise;

  NS_INLINE_DECL_THREADSAFE_REFCOUNTING_WITH_DELETE_ON_EVENT_TARGET(
      CamerasParent, mPBackgroundEventTarget)

 public:
  class VideoEngineArray;
  friend DeliverFrameRunnable;

  static already_AddRefed<CamerasParent> Create();

  // 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;

  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;

  // 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;
};

}  // namespace mozilla::camera

#endif  // mozilla_CameraParent_h