LCOV - code coverage report
Current view: top level - dom/media/systemservices - CamerasChild.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 19 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 21 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* vim: set sw=2 ts=8 et ft=cpp : */
       3             : /* This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef mozilla_CamerasChild_h
       8             : #define mozilla_CamerasChild_h
       9             : 
      10             : #include "mozilla/Move.h"
      11             : #include "mozilla/Pair.h"
      12             : #include "mozilla/dom/ContentChild.h"
      13             : #include "mozilla/camera/PCamerasChild.h"
      14             : #include "mozilla/camera/PCamerasParent.h"
      15             : #include "mozilla/media/DeviceChangeCallback.h"
      16             : #include "mozilla/Mutex.h"
      17             : #include "base/singleton.h"
      18             : #include "nsCOMPtr.h"
      19             : 
      20             : // conflicts with #include of scoped_ptr.h
      21             : #undef FF
      22             : #include "webrtc/modules/video_capture/video_capture_defines.h"
      23             : 
      24             : namespace mozilla {
      25             : 
      26             : namespace ipc {
      27             : class BackgroundChildImpl;
      28             : class PrincipalInfo;
      29             : }
      30             : 
      31             : namespace camera {
      32             : 
      33           0 : class FrameRelay {
      34             : public:
      35             :   virtual int DeliverFrame(uint8_t* buffer,
      36             :     const mozilla::camera::VideoFrameProperties& props) = 0;
      37             :   virtual void FrameSizeChange(unsigned int w, unsigned int h) = 0;
      38             : };
      39             : 
      40             : struct CapturerElement {
      41             :   CaptureEngine engine;
      42             :   int id;
      43             :   FrameRelay* callback;
      44             : };
      45             : 
      46             : // Forward declaration so we can work with pointers to it.
      47             : class CamerasChild;
      48             : // Helper class in impl that we friend.
      49             : template <class T> class LockAndDispatch;
      50             : 
      51             : // We emulate the sync webrtc.org API with the help of singleton
      52             : // CamerasSingleton, which manages a pointer to an IPC object, a thread
      53             : // where IPC operations should run on, and a mutex.
      54             : // The static function Cameras() will use that Singleton to set up,
      55             : // if needed, both the thread and the associated IPC objects and return
      56             : // a pointer to the IPC object. Users can then do IPC calls on that object
      57             : // after dispatching them to aforementioned thread.
      58             : 
      59             : // 2 Threads are involved in this code:
      60             : // - the MediaManager thread, which will call the (static, sync API) functions
      61             : //   through MediaEngineRemoteVideoSource
      62             : // - the Cameras IPC thread, which will be doing our IPC to the parent process
      63             : //   via PBackground
      64             : 
      65             : // Our main complication is that we emulate a sync API while (having to do)
      66             : // async messaging. We dispatch the messages to another thread to send them
      67             : // async and hold a Monitor to wait for the result to be asynchronously received
      68             : // again. The requirement for async messaging originates on the parent side:
      69             : // it's not reasonable to block all PBackground IPC there while waiting for
      70             : // something like device enumeration to complete.
      71             : 
      72             : class CamerasSingleton {
      73             : public:
      74             :   CamerasSingleton();
      75             :   ~CamerasSingleton();
      76             : 
      77           0 :   static OffTheBooksMutex& Mutex() {
      78           0 :     return gTheInstance.get()->mCamerasMutex;
      79             :   }
      80             : 
      81           0 :   static CamerasChild*& Child() {
      82           0 :     Mutex().AssertCurrentThreadOwns();
      83           0 :     return gTheInstance.get()->mCameras;
      84             :   }
      85             : 
      86           0 :   static nsCOMPtr<nsIThread>& Thread() {
      87           0 :     Mutex().AssertCurrentThreadOwns();
      88           0 :     return gTheInstance.get()->mCamerasChildThread;
      89             :   }
      90             : 
      91           0 :   static nsCOMPtr<nsIThread>& FakeDeviceChangeEventThread() {
      92           0 :     Mutex().AssertCurrentThreadOwns();
      93           0 :     return gTheInstance.get()->mFakeDeviceChangeEventThread;
      94             :   }
      95             : 
      96             : private:
      97             :   static Singleton<CamerasSingleton> gTheInstance;
      98             : 
      99             :   // Reinitializing CamerasChild will change the pointers below.
     100             :   // We don't want this to happen in the middle of preparing IPC.
     101             :   // We will be alive on destruction, so this needs to be off the books.
     102             :   mozilla::OffTheBooksMutex mCamerasMutex;
     103             : 
     104             :   // This is owned by the IPC code, and the same code controls the lifetime.
     105             :   // It will set and clear this pointer as appropriate in setup/teardown.
     106             :   // We'd normally make this a WeakPtr but unfortunately the IPC code already
     107             :   // uses the WeakPtr mixin in a protected base class of CamerasChild, and in
     108             :   // any case the object becomes unusable as soon as IPC is tearing down, which
     109             :   // will be before actual destruction.
     110             :   CamerasChild* mCameras;
     111             :   nsCOMPtr<nsIThread> mCamerasChildThread;
     112             :   nsCOMPtr<nsIThread> mFakeDeviceChangeEventThread;
     113             : };
     114             : 
     115             : // Get a pointer to a CamerasChild object we can use to do IPC with.
     116             : // This does everything needed to set up, including starting the IPC
     117             : // channel with PBackground, blocking until thats done, and starting the
     118             : // thread to do IPC on. This will fail if we're in shutdown. On success
     119             : // it will set up the CamerasSingleton.
     120             : CamerasChild* GetCamerasChild();
     121             : 
     122             : CamerasChild* GetCamerasChildIfExists();
     123             : 
     124             : // Shut down the IPC channel and everything associated, like WebRTC.
     125             : // This is a static call because the CamerasChild object may not even
     126             : // be alive when we're called.
     127             : void Shutdown(void);
     128             : 
     129             : // Obtain the CamerasChild object (if possible, i.e. not shutting down),
     130             : // and maintain a grip on the object for the duration of the call.
     131             : template <class MEM_FUN, class... ARGS>
     132           0 : int GetChildAndCall(MEM_FUN&& f, ARGS&&... args)
     133             : {
     134           0 :   OffTheBooksMutexAutoLock lock(CamerasSingleton::Mutex());
     135           0 :   CamerasChild* child = GetCamerasChild();
     136           0 :   if (child) {
     137           0 :     return (child->*f)(mozilla::Forward<ARGS>(args)...);
     138             :   } else {
     139           0 :     return -1;
     140             :   }
     141             : }
     142             : 
     143             : class CamerasChild final : public PCamerasChild
     144             :                           ,public DeviceChangeCallback
     145             : {
     146             :   friend class mozilla::ipc::BackgroundChildImpl;
     147             :   template <class T> friend class mozilla::camera::LockAndDispatch;
     148             : 
     149             : public:
     150             :   // We are owned by the PBackground thread only. CamerasSingleton
     151             :   // takes a non-owning reference.
     152           0 :   NS_INLINE_DECL_REFCOUNTING(CamerasChild)
     153             : 
     154             :   // IPC messages recevied, received on the PBackground thread
     155             :   // these are the actual callbacks with data
     156             :   virtual mozilla::ipc::IPCResult RecvDeliverFrame(const CaptureEngine&, const int&,
     157             :                                                    mozilla::ipc::Shmem&&,
     158             :                                                    const VideoFrameProperties & prop) override;
     159             :   virtual mozilla::ipc::IPCResult RecvFrameSizeChange(const CaptureEngine&, const int&,
     160             :                                                       const int& w, const int& h) override;
     161             : 
     162             :   virtual mozilla::ipc::IPCResult RecvDeviceChange() override;
     163             :   virtual int AddDeviceChangeCallback(DeviceChangeCallback* aCallback) override;
     164             :   int SetFakeDeviceChangeEvents();
     165             : 
     166             :   // these are response messages to our outgoing requests
     167             :   virtual mozilla::ipc::IPCResult RecvReplyNumberOfCaptureDevices(const int&) override;
     168             :   virtual mozilla::ipc::IPCResult RecvReplyNumberOfCapabilities(const int&) override;
     169             :   virtual mozilla::ipc::IPCResult RecvReplyAllocateCaptureDevice(const int&) override;
     170             :   virtual mozilla::ipc::IPCResult RecvReplyGetCaptureCapability(const VideoCaptureCapability& capability) override;
     171             :   virtual mozilla::ipc::IPCResult RecvReplyGetCaptureDevice(const nsCString& device_name,
     172             :                                                             const nsCString& device_id,
     173             :                                                             const bool& scary) override;
     174             :   virtual mozilla::ipc::IPCResult RecvReplyFailure(void) override;
     175             :   virtual mozilla::ipc::IPCResult RecvReplySuccess(void) override;
     176             :   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
     177             : 
     178             :   // the webrtc.org ViECapture calls are mirrored here, but with access
     179             :   // to a specific PCameras instance to communicate over. These also
     180             :   // run on the MediaManager thread
     181             :   int NumberOfCaptureDevices(CaptureEngine aCapEngine);
     182             :   int NumberOfCapabilities(CaptureEngine aCapEngine,
     183             :                            const char* deviceUniqueIdUTF8);
     184             :   int ReleaseCaptureDevice(CaptureEngine aCapEngine,
     185             :                            const int capture_id);
     186             :   int StartCapture(CaptureEngine aCapEngine,
     187             :                    const int capture_id, webrtc::VideoCaptureCapability& capability,
     188             :                    FrameRelay* func);
     189             :   int StopCapture(CaptureEngine aCapEngine, const int capture_id);
     190             :   int AllocateCaptureDevice(CaptureEngine aCapEngine,
     191             :                             const char* unique_idUTF8,
     192             :                             const unsigned int unique_idUTF8Length,
     193             :                             int& capture_id,
     194             :                             const mozilla::ipc::PrincipalInfo& aPrincipalInfo);
     195             :   int GetCaptureCapability(CaptureEngine aCapEngine,
     196             :                            const char* unique_idUTF8,
     197             :                            const unsigned int capability_number,
     198             :                            webrtc::VideoCaptureCapability& capability);
     199             :   int GetCaptureDevice(CaptureEngine aCapEngine,
     200             :                        unsigned int list_number, char* device_nameUTF8,
     201             :                        const unsigned int device_nameUTF8Length,
     202             :                        char* unique_idUTF8,
     203             :                        const unsigned int unique_idUTF8Length,
     204             :                        bool* scary = nullptr);
     205             :   void ShutdownAll();
     206             :   int EnsureInitialized(CaptureEngine aCapEngine);
     207             : 
     208             :   FrameRelay* Callback(CaptureEngine aCapEngine, int capture_id);
     209             : 
     210             : private:
     211             :   CamerasChild();
     212             :   ~CamerasChild();
     213             :   // Dispatch a Runnable to the PCamerasParent, by executing it on the
     214             :   // decidecated Cameras IPC/PBackground thread.
     215             :   bool DispatchToParent(nsIRunnable* aRunnable,
     216             :                         MonitorAutoLock& aMonitor);
     217             :   void AddCallback(const CaptureEngine aCapEngine, const int capture_id,
     218             :                    FrameRelay* render);
     219             :   void RemoveCallback(const CaptureEngine aCapEngine, const int capture_id);
     220             :   void ShutdownParent();
     221             :   void ShutdownChild();
     222             : 
     223             :   nsTArray<CapturerElement> mCallbacks;
     224             :   // Protects the callback arrays
     225             :   Mutex mCallbackMutex;
     226             : 
     227             :   bool mIPCIsAlive;
     228             : 
     229             :   // Hold to prevent multiple outstanding requests. We don't use
     230             :   // request IDs so we only support one at a time. Don't want try
     231             :   // to use the webrtc.org API from multiple threads simultanously.
     232             :   // The monitor below isn't sufficient for this, as it will drop
     233             :   // the lock when Wait-ing for a response, allowing us to send a new
     234             :   // request. The Notify on receiving the response will then unblock
     235             :   // both waiters and one will be guaranteed to get the wrong result.
     236             :   // Take this one before taking mReplyMonitor.
     237             :   Mutex mRequestMutex;
     238             :   // Hold to wait for an async response to our calls
     239             :   Monitor mReplyMonitor;
     240             :   // Async response valid?
     241             :   bool mReceivedReply;
     242             :   // Async responses data contents;
     243             :   bool mReplySuccess;
     244             :   int mReplyInteger;
     245             :   webrtc::VideoCaptureCapability mReplyCapability;
     246             :   nsCString mReplyDeviceName;
     247             :   nsCString mReplyDeviceID;
     248             :   bool mReplyScary;
     249             : };
     250             : 
     251             : } // namespace camera
     252             : } // namespace mozilla
     253             : 
     254             : #endif  // mozilla_CamerasChild_h

Generated by: LCOV version 1.13