LCOV - code coverage report
Current view: top level - dom/media/ipc - VideoDecoderManagerParent.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 4 127 3.1 %
Date: 2017-07-14 16:53:18 Functions: 2 33 6.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2             : /* vim: set ts=8 sts=2 et sw=2 tw=99: */
       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
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : #include "VideoDecoderManagerParent.h"
       7             : #include "VideoDecoderParent.h"
       8             : #include "base/thread.h"
       9             : #include "mozilla/UniquePtr.h"
      10             : #include "mozilla/Services.h"
      11             : #include "mozilla/Observer.h"
      12             : #include "nsIObserverService.h"
      13             : #include "nsIObserver.h"
      14             : #include "nsIEventTarget.h"
      15             : #include "nsThreadUtils.h"
      16             : #include "ImageContainer.h"
      17             : #include "mozilla/layers/VideoBridgeChild.h"
      18             : #include "mozilla/SharedThreadPool.h"
      19             : #include "mozilla/layers/ImageDataSerializer.h"
      20             : #include "mozilla/SyncRunnable.h"
      21             : 
      22             : #if XP_WIN
      23             : #include <objbase.h>
      24             : #endif
      25             : 
      26             : namespace mozilla {
      27             : namespace dom {
      28             : 
      29             : using namespace ipc;
      30             : using namespace layers;
      31             : using namespace gfx;
      32             : 
      33             : SurfaceDescriptorGPUVideo
      34           0 : VideoDecoderManagerParent::StoreImage(Image* aImage, TextureClient* aTexture)
      35             : {
      36           0 :   mImageMap[aTexture->GetSerial()] = aImage;
      37           0 :   mTextureMap[aTexture->GetSerial()] = aTexture;
      38           0 :   return SurfaceDescriptorGPUVideo(aTexture->GetSerial());
      39             : }
      40             : 
      41           3 : StaticRefPtr<nsIThread> sVideoDecoderManagerThread;
      42           3 : StaticRefPtr<TaskQueue> sManagerTaskQueue;
      43             : 
      44             : class VideoDecoderManagerThreadHolder
      45             : {
      46           0 :   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(VideoDecoderManagerThreadHolder)
      47             : 
      48             : public:
      49           0 :   VideoDecoderManagerThreadHolder() {}
      50             : 
      51             : private:
      52           0 :   ~VideoDecoderManagerThreadHolder() {
      53           0 :     NS_DispatchToMainThread(NS_NewRunnableFunction(
      54             :       "dom::VideoDecoderManagerThreadHolder::~VideoDecoderManagerThreadHolder",
      55           0 :       []() -> void {
      56           0 :         sVideoDecoderManagerThread->Shutdown();
      57           0 :         sVideoDecoderManagerThread = nullptr;
      58           0 :       }));
      59           0 :   }
      60             : };
      61           3 : StaticRefPtr<VideoDecoderManagerThreadHolder> sVideoDecoderManagerThreadHolder;
      62             : 
      63             : class ManagerThreadShutdownObserver : public nsIObserver
      64             : {
      65           0 :   virtual ~ManagerThreadShutdownObserver() = default;
      66             : public:
      67           0 :   ManagerThreadShutdownObserver() {}
      68             : 
      69             :   NS_DECL_ISUPPORTS
      70             : 
      71           0 :   NS_IMETHOD Observe(nsISupports* aSubject, const char* aTopic,
      72             :                      const char16_t* aData) override
      73             :   {
      74           0 :     MOZ_ASSERT(strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID) == 0);
      75             : 
      76           0 :     VideoDecoderManagerParent::ShutdownThreads();
      77           0 :     return NS_OK;
      78             :   }
      79             : };
      80           0 : NS_IMPL_ISUPPORTS(ManagerThreadShutdownObserver, nsIObserver);
      81             : 
      82             : void
      83           0 : VideoDecoderManagerParent::StartupThreads()
      84             : {
      85           0 :   MOZ_ASSERT(NS_IsMainThread());
      86             : 
      87           0 :   if (sVideoDecoderManagerThread) {
      88           0 :     return;
      89             :   }
      90             : 
      91           0 :   nsCOMPtr<nsIObserverService> observerService = services::GetObserverService();
      92           0 :   if (!observerService) {
      93           0 :     return;
      94             :   }
      95             : 
      96           0 :   RefPtr<nsIThread> managerThread;
      97           0 :   nsresult rv = NS_NewNamedThread("VideoParent", getter_AddRefs(managerThread));
      98           0 :   if (NS_FAILED(rv)) {
      99           0 :     return;
     100             :   }
     101           0 :   sVideoDecoderManagerThread = managerThread;
     102           0 :   sVideoDecoderManagerThreadHolder = new VideoDecoderManagerThreadHolder();
     103             : #if XP_WIN
     104             :   sVideoDecoderManagerThread->Dispatch(NS_NewRunnableFunction("VideoDecoderManagerParent::StartupThreads",
     105             :   []() {
     106             :     HRESULT hr = CoInitializeEx(0, COINIT_MULTITHREADED);
     107             :     MOZ_ASSERT(hr == S_OK);
     108             :   }), NS_DISPATCH_NORMAL);
     109             : #endif
     110           0 :   sVideoDecoderManagerThread->Dispatch(
     111           0 :     NS_NewRunnableFunction("dom::VideoDecoderManagerParent::StartupThreads",
     112           0 :                            []() { layers::VideoBridgeChild::Startup(); }),
     113           0 :     NS_DISPATCH_NORMAL);
     114             : 
     115             :   sManagerTaskQueue = new TaskQueue(
     116           0 :     managerThread.forget(), "VideoDecoderManagerParent::sManagerTaskQueue");
     117             : 
     118           0 :   auto* obs = new ManagerThreadShutdownObserver();
     119           0 :   observerService->AddObserver(obs, NS_XPCOM_SHUTDOWN_OBSERVER_ID, false);
     120             : }
     121             : 
     122             : void
     123           0 : VideoDecoderManagerParent::ShutdownThreads()
     124             : {
     125           0 :   sManagerTaskQueue->BeginShutdown();
     126           0 :   sManagerTaskQueue->AwaitShutdownAndIdle();
     127           0 :   sManagerTaskQueue = nullptr;
     128             : 
     129           0 :   sVideoDecoderManagerThreadHolder = nullptr;
     130           0 :   while (sVideoDecoderManagerThread) {
     131           0 :     NS_ProcessNextEvent(nullptr, true);
     132             :   }
     133           0 : }
     134             : 
     135             : void
     136           0 : VideoDecoderManagerParent::ShutdownVideoBridge()
     137             : {
     138           0 :   if (sVideoDecoderManagerThread) {
     139           0 :     RefPtr<Runnable> task = NS_NewRunnableFunction(
     140             :       "dom::VideoDecoderManagerParent::ShutdownVideoBridge",
     141           0 :       []() { VideoBridgeChild::Shutdown(); });
     142           0 :     SyncRunnable::DispatchToThread(sVideoDecoderManagerThread, task);
     143             :   }
     144           0 : }
     145             : 
     146             : bool
     147           0 : VideoDecoderManagerParent::OnManagerThread()
     148             : {
     149           0 :   return NS_GetCurrentThread() == sVideoDecoderManagerThread;
     150             : }
     151             : 
     152             : bool
     153           0 : VideoDecoderManagerParent::CreateForContent(Endpoint<PVideoDecoderManagerParent>&& aEndpoint)
     154             : {
     155           0 :   MOZ_ASSERT(XRE_GetProcessType() == GeckoProcessType_GPU);
     156           0 :   MOZ_ASSERT(NS_IsMainThread());
     157             : 
     158           0 :   StartupThreads();
     159           0 :   if (!sVideoDecoderManagerThread) {
     160           0 :     return false;
     161             :   }
     162             : 
     163             :   RefPtr<VideoDecoderManagerParent> parent =
     164           0 :     new VideoDecoderManagerParent(sVideoDecoderManagerThreadHolder);
     165             : 
     166             :   RefPtr<Runnable> task =
     167           0 :     NewRunnableMethod<Endpoint<PVideoDecoderManagerParent>&&>(
     168             :       "dom::VideoDecoderManagerParent::Open",
     169             :       parent,
     170             :       &VideoDecoderManagerParent::Open,
     171           0 :       Move(aEndpoint));
     172           0 :   sVideoDecoderManagerThread->Dispatch(task.forget(), NS_DISPATCH_NORMAL);
     173           0 :   return true;
     174             : }
     175             : 
     176           0 : VideoDecoderManagerParent::VideoDecoderManagerParent(VideoDecoderManagerThreadHolder* aHolder)
     177           0 :  : mThreadHolder(aHolder)
     178             : {
     179           0 :   MOZ_COUNT_CTOR(VideoDecoderManagerParent);
     180           0 : }
     181             : 
     182           0 : VideoDecoderManagerParent::~VideoDecoderManagerParent()
     183             : {
     184           0 :   MOZ_COUNT_DTOR(VideoDecoderManagerParent);
     185           0 : }
     186             : 
     187             : void
     188           0 : VideoDecoderManagerParent::ActorDestroy(mozilla::ipc::IProtocol::ActorDestroyReason)
     189             : {
     190           0 :   mThreadHolder = nullptr;
     191           0 : }
     192             : 
     193             : PVideoDecoderParent*
     194           0 : VideoDecoderManagerParent::AllocPVideoDecoderParent(const VideoInfo& aVideoInfo,
     195             :                                                     const layers::TextureFactoryIdentifier& aIdentifier,
     196             :                                                     bool* aSuccess)
     197             : {
     198             :   RefPtr<TaskQueue> decodeTaskQueue = new TaskQueue(
     199           0 :     SharedThreadPool::Get(NS_LITERAL_CSTRING("VideoDecoderParent"), 4),
     200           0 :     "VideoDecoderParent::mDecodeTaskQueue");
     201             : 
     202             :   return new VideoDecoderParent(
     203             :     this, aVideoInfo, aIdentifier,
     204           0 :     sManagerTaskQueue, decodeTaskQueue, aSuccess);
     205             : }
     206             : 
     207             : bool
     208           0 : VideoDecoderManagerParent::DeallocPVideoDecoderParent(PVideoDecoderParent* actor)
     209             : {
     210           0 :   VideoDecoderParent* parent = static_cast<VideoDecoderParent*>(actor);
     211           0 :   parent->Destroy();
     212           0 :   return true;
     213             : }
     214             : 
     215             : void
     216           0 : VideoDecoderManagerParent::Open(Endpoint<PVideoDecoderManagerParent>&& aEndpoint)
     217             : {
     218           0 :   if (!aEndpoint.Bind(this)) {
     219             :     // We can't recover from this.
     220           0 :     MOZ_CRASH("Failed to bind VideoDecoderManagerParent to endpoint");
     221             :   }
     222           0 :   AddRef();
     223           0 : }
     224             : 
     225             : void
     226           0 : VideoDecoderManagerParent::DeallocPVideoDecoderManagerParent()
     227             : {
     228           0 :   Release();
     229           0 : }
     230             : 
     231             : mozilla::ipc::IPCResult
     232           0 : VideoDecoderManagerParent::RecvReadback(const SurfaceDescriptorGPUVideo& aSD, SurfaceDescriptor* aResult)
     233             : {
     234           0 :   RefPtr<Image> image = mImageMap[aSD.handle()];
     235           0 :   if (!image) {
     236           0 :     *aResult = null_t();
     237           0 :     return IPC_OK();
     238             :   }
     239             : 
     240           0 :   RefPtr<SourceSurface> source = image->GetAsSourceSurface();
     241           0 :   if (!source) {
     242           0 :     *aResult = null_t();
     243           0 :     return IPC_OK();
     244             :   }
     245             : 
     246           0 :   SurfaceFormat format = source->GetFormat();
     247           0 :   IntSize size = source->GetSize();
     248           0 :   size_t length = ImageDataSerializer::ComputeRGBBufferSize(size, format);
     249             : 
     250           0 :   Shmem buffer;
     251           0 :   if (!length || !AllocShmem(length, Shmem::SharedMemory::TYPE_BASIC, &buffer)) {
     252           0 :     *aResult = null_t();
     253           0 :     return IPC_OK();
     254             :   }
     255             : 
     256           0 :   RefPtr<DrawTarget> dt = Factory::CreateDrawTargetForData(gfx::BackendType::CAIRO,
     257             :                                                            buffer.get<uint8_t>(), size,
     258             :                                                            ImageDataSerializer::ComputeRGBStride(format, size.width),
     259           0 :                                                            format);
     260           0 :   if (!dt) {
     261           0 :     DeallocShmem(buffer);
     262           0 :     *aResult = null_t();
     263           0 :     return IPC_OK();
     264             :   }
     265             : 
     266           0 :   dt->CopySurface(source, IntRect(0, 0, size.width, size.height), IntPoint());
     267           0 :   dt->Flush();
     268             : 
     269           0 :   *aResult = SurfaceDescriptorBuffer(RGBDescriptor(size, format, true), MemoryOrShmem(buffer));
     270           0 :   return IPC_OK();
     271             : }
     272             : 
     273             : mozilla::ipc::IPCResult
     274           0 : VideoDecoderManagerParent::RecvDeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD)
     275             : {
     276           0 :   mImageMap.erase(aSD.handle());
     277           0 :   mTextureMap.erase(aSD.handle());
     278           0 :   return IPC_OK();
     279             : }
     280             : 
     281             : } // namespace dom
     282           9 : } // namespace mozilla

Generated by: LCOV version 1.13