LCOV - code coverage report
Current view: top level - dom/media/ipc - VideoDecoderManagerChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 24 137 17.5 %
Date: 2017-07-14 16:53:18 Functions: 5 31 16.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 "VideoDecoderManagerChild.h"
       7             : #include "VideoDecoderChild.h"
       8             : #include "mozilla/dom/ContentChild.h"
       9             : #include "MediaPrefs.h"
      10             : #include "nsThreadUtils.h"
      11             : #include "mozilla/gfx/2D.h"
      12             : #include "mozilla/ipc/ProtocolUtils.h"
      13             : #include "mozilla/layers/SynchronousTask.h"
      14             : #include "mozilla/gfx/DataSurfaceHelpers.h"
      15             : #include "mozilla/layers/ISurfaceAllocator.h"
      16             : #include "base/task.h"
      17             : 
      18             : namespace mozilla {
      19             : namespace dom {
      20             : 
      21             : using namespace ipc;
      22             : using namespace layers;
      23             : using namespace gfx;
      24             : 
      25             : // Only modified on the main-thread
      26           3 : StaticRefPtr<nsIThread> sVideoDecoderChildThread;
      27           3 : StaticRefPtr<AbstractThread> sVideoDecoderChildAbstractThread;
      28             : 
      29             : // Only accessed from sVideoDecoderChildThread
      30           3 : static StaticRefPtr<VideoDecoderManagerChild> sDecoderManager;
      31           3 : static UniquePtr<nsTArray<RefPtr<Runnable>>> sRecreateTasks;
      32             : 
      33             : /* static */ void
      34           2 : VideoDecoderManagerChild::InitializeThread()
      35             : {
      36           2 :   MOZ_ASSERT(NS_IsMainThread());
      37             : 
      38           2 :   if (!sVideoDecoderChildThread) {
      39           4 :     RefPtr<nsIThread> childThread;
      40           2 :     nsresult rv = NS_NewNamedThread("VideoChild", getter_AddRefs(childThread));
      41           2 :     NS_ENSURE_SUCCESS_VOID(rv);
      42           2 :     sVideoDecoderChildThread = childThread;
      43             : 
      44             :     sVideoDecoderChildAbstractThread =
      45           2 :       AbstractThread::CreateXPCOMThreadWrapper(childThread, false);
      46             : 
      47           2 :     sRecreateTasks = MakeUnique<nsTArray<RefPtr<Runnable>>>();
      48             :   }
      49             : }
      50             : 
      51             : /* static */ void
      52           2 : VideoDecoderManagerChild::InitForContent(Endpoint<PVideoDecoderManagerChild>&& aVideoManager)
      53             : {
      54           2 :   InitializeThread();
      55           2 :   sVideoDecoderChildThread->Dispatch(NewRunnableFunction(&Open, Move(aVideoManager)), NS_DISPATCH_NORMAL);
      56           2 : }
      57             : 
      58             : /* static */ void
      59           0 : VideoDecoderManagerChild::Shutdown()
      60             : {
      61           0 :   MOZ_ASSERT(NS_IsMainThread());
      62             : 
      63           0 :   if (sVideoDecoderChildThread) {
      64           0 :     sVideoDecoderChildThread->Dispatch(
      65           0 :       NS_NewRunnableFunction("dom::VideoDecoderManagerChild::Shutdown",
      66           0 :                              []() {
      67           0 :                                if (sDecoderManager &&
      68           0 :                                    sDecoderManager->CanSend()) {
      69           0 :                                  sDecoderManager->Close();
      70           0 :                                  sDecoderManager = nullptr;
      71             :                                }
      72           0 :                              }),
      73           0 :       NS_DISPATCH_NORMAL);
      74             : 
      75           0 :     sVideoDecoderChildAbstractThread = nullptr;
      76           0 :     sVideoDecoderChildThread->Shutdown();
      77           0 :     sVideoDecoderChildThread = nullptr;
      78             : 
      79           0 :     sRecreateTasks = nullptr;
      80             :   }
      81           0 : }
      82             : 
      83             : void
      84           0 : VideoDecoderManagerChild::RunWhenRecreated(already_AddRefed<Runnable> aTask)
      85             : {
      86           0 :   MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
      87             : 
      88             :   // If we've already been recreated, then run the task immediately.
      89           0 :   if (sDecoderManager && sDecoderManager != this && sDecoderManager->CanSend()) {
      90           0 :     RefPtr<Runnable> task = aTask;
      91           0 :     task->Run();
      92             :   } else {
      93           0 :     sRecreateTasks->AppendElement(aTask);
      94             :   }
      95           0 : }
      96             : 
      97             : 
      98             : /* static */ VideoDecoderManagerChild*
      99           0 : VideoDecoderManagerChild::GetSingleton()
     100             : {
     101           0 :   MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
     102           0 :   return sDecoderManager;
     103             : }
     104             : 
     105             : /* static */ nsIThread*
     106           0 : VideoDecoderManagerChild::GetManagerThread()
     107             : {
     108           0 :   return sVideoDecoderChildThread;
     109             : }
     110             : 
     111             : /* static */ AbstractThread*
     112           0 : VideoDecoderManagerChild::GetManagerAbstractThread()
     113             : {
     114           0 :   return sVideoDecoderChildAbstractThread;
     115             : }
     116             : 
     117             : PVideoDecoderChild*
     118           0 : VideoDecoderManagerChild::AllocPVideoDecoderChild(const VideoInfo& aVideoInfo,
     119             :                                                   const layers::TextureFactoryIdentifier& aIdentifier,
     120             :                                                   bool* aSuccess)
     121             : {
     122           0 :   return new VideoDecoderChild();
     123             : }
     124             : 
     125             : bool
     126           0 : VideoDecoderManagerChild::DeallocPVideoDecoderChild(PVideoDecoderChild* actor)
     127             : {
     128           0 :   VideoDecoderChild* child = static_cast<VideoDecoderChild*>(actor);
     129           0 :   child->IPDLActorDestroyed();
     130           0 :   return true;
     131             : }
     132             : 
     133             : void
     134           2 : VideoDecoderManagerChild::Open(Endpoint<PVideoDecoderManagerChild>&& aEndpoint)
     135             : {
     136             :   // Make sure we always dispatch everything in sRecreateTasks, even if we
     137             :   // fail since this is as close to being recreated as we will ever be.
     138           2 :   sDecoderManager = nullptr;
     139           2 :   if (aEndpoint.IsValid()) {
     140           0 :     RefPtr<VideoDecoderManagerChild> manager = new VideoDecoderManagerChild();
     141           0 :     if (aEndpoint.Bind(manager)) {
     142           0 :       sDecoderManager = manager;
     143           0 :       manager->InitIPDL();
     144             :     }
     145             :   }
     146           2 :   for (Runnable* task : *sRecreateTasks) {
     147           0 :     task->Run();
     148             :   }
     149           2 :   sRecreateTasks->Clear();
     150           2 : }
     151             : 
     152             : void
     153           0 : VideoDecoderManagerChild::InitIPDL()
     154             : {
     155           0 :   mCanSend = true;
     156           0 :   mIPDLSelfRef = this;
     157           0 : }
     158             : 
     159             : void
     160           0 : VideoDecoderManagerChild::ActorDestroy(ActorDestroyReason aWhy)
     161             : {
     162           0 :   mCanSend = false;
     163           0 : }
     164             : 
     165             : void
     166           0 : VideoDecoderManagerChild::DeallocPVideoDecoderManagerChild()
     167             : {
     168           0 :   mIPDLSelfRef = nullptr;
     169           0 : }
     170             : 
     171             : bool
     172           0 : VideoDecoderManagerChild::CanSend()
     173             : {
     174           0 :   MOZ_ASSERT(NS_GetCurrentThread() == GetManagerThread());
     175           0 :   return mCanSend;
     176             : }
     177             : 
     178             : bool
     179           0 : VideoDecoderManagerChild::DeallocShmem(mozilla::ipc::Shmem& aShmem)
     180             : {
     181           0 :   if (NS_GetCurrentThread() != sVideoDecoderChildThread) {
     182           0 :     RefPtr<VideoDecoderManagerChild> self = this;
     183           0 :     mozilla::ipc::Shmem shmem = aShmem;
     184           0 :     sVideoDecoderChildThread->Dispatch(
     185           0 :       NS_NewRunnableFunction("dom::VideoDecoderManagerChild::DeallocShmem",
     186           0 :                              [self, shmem]() {
     187           0 :                                if (self->CanSend()) {
     188           0 :                                  mozilla::ipc::Shmem shmemCopy = shmem;
     189           0 :                                  self->DeallocShmem(shmemCopy);
     190             :                                }
     191           0 :                              }),
     192           0 :       NS_DISPATCH_NORMAL);
     193           0 :     return true;
     194             :   }
     195           0 :   return PVideoDecoderManagerChild::DeallocShmem(aShmem);
     196             : }
     197             : 
     198             : struct SurfaceDescriptorUserData
     199             : {
     200           0 :   SurfaceDescriptorUserData(VideoDecoderManagerChild* aAllocator, SurfaceDescriptor& aSD)
     201           0 :     : mAllocator(aAllocator)
     202           0 :     , mSD(aSD)
     203           0 :   {}
     204           0 :   ~SurfaceDescriptorUserData()
     205           0 :   {
     206           0 :     DestroySurfaceDescriptor(mAllocator, &mSD);
     207           0 :   }
     208             : 
     209             :   RefPtr<VideoDecoderManagerChild> mAllocator;
     210             :   SurfaceDescriptor mSD;
     211             : };
     212             : 
     213           0 : void DeleteSurfaceDescriptorUserData(void* aClosure)
     214             : {
     215           0 :   SurfaceDescriptorUserData* sd = reinterpret_cast<SurfaceDescriptorUserData*>(aClosure);
     216           0 :   delete sd;
     217           0 : }
     218             : 
     219             : already_AddRefed<SourceSurface>
     220           0 : VideoDecoderManagerChild::Readback(const SurfaceDescriptorGPUVideo& aSD)
     221             : {
     222             :   // We can't use NS_DISPATCH_SYNC here since that can spin the event
     223             :   // loop while it waits. This function can be called from JS and we
     224             :   // don't want that to happen.
     225           0 :   SynchronousTask task("Readback sync");
     226             : 
     227           0 :   RefPtr<VideoDecoderManagerChild> ref = this;
     228           0 :   SurfaceDescriptor sd;
     229           0 :   if (NS_FAILED(sVideoDecoderChildThread->Dispatch(NS_NewRunnableFunction("VideoDecoderManagerChild::Readback",
     230             :                                                                           [&]() {
     231             :     AutoCompleteTask complete(&task);
     232             :     if (ref->CanSend()) {
     233             :       ref->SendReadback(aSD, &sd);
     234             :     }
     235             :   }), NS_DISPATCH_NORMAL))) {
     236           0 :     return nullptr;
     237             :   }
     238             : 
     239           0 :   task.Wait();
     240             : 
     241           0 :   if (!IsSurfaceDescriptorValid(sd)) {
     242           0 :     return nullptr;
     243             :   }
     244             : 
     245           0 :   RefPtr<DataSourceSurface> source = GetSurfaceForDescriptor(sd);
     246           0 :   if (!source) {
     247           0 :     DestroySurfaceDescriptor(this, &sd);
     248           0 :     NS_WARNING("Failed to map SurfaceDescriptor in Readback");
     249           0 :     return nullptr;
     250             :   }
     251             : 
     252             :   static UserDataKey sSurfaceDescriptor;
     253           0 :   source->AddUserData(&sSurfaceDescriptor,
     254           0 :                       new SurfaceDescriptorUserData(this, sd),
     255           0 :                       DeleteSurfaceDescriptorUserData);
     256             : 
     257           0 :   return source.forget();
     258             : }
     259             : 
     260             : void
     261           0 : VideoDecoderManagerChild::DeallocateSurfaceDescriptorGPUVideo(const SurfaceDescriptorGPUVideo& aSD)
     262             : {
     263           0 :   RefPtr<VideoDecoderManagerChild> ref = this;
     264           0 :   SurfaceDescriptorGPUVideo sd = Move(aSD);
     265           0 :   sVideoDecoderChildThread->Dispatch(
     266           0 :     NS_NewRunnableFunction(
     267             :       "dom::VideoDecoderManagerChild::DeallocateSurfaceDescriptorGPUVideo",
     268           0 :       [ref, sd]() {
     269           0 :         if (ref->CanSend()) {
     270           0 :           ref->SendDeallocateSurfaceDescriptorGPUVideo(sd);
     271             :         }
     272           0 :       }),
     273           0 :     NS_DISPATCH_NORMAL);
     274           0 : }
     275             : 
     276             : void
     277           0 : VideoDecoderManagerChild::HandleFatalError(const char* aName, const char* aMsg) const
     278             : {
     279           0 :   dom::ContentChild::FatalErrorIfNotUsingGPUProcess(aName, aMsg, OtherPid());
     280           0 : }
     281             : 
     282             : } // namespace dom
     283           9 : } // namespace mozilla

Generated by: LCOV version 1.13