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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "GMPVideoEncoderParent.h"
       7             : #include "mozilla/Logging.h"
       8             : #include "GMPVideoi420FrameImpl.h"
       9             : #include "GMPVideoEncodedFrameImpl.h"
      10             : #include "mozilla/Unused.h"
      11             : #include "GMPMessageUtils.h"
      12             : #include "nsAutoRef.h"
      13             : #include "GMPContentParent.h"
      14             : #include "mozilla/gmp/GMPTypes.h"
      15             : #include "nsThread.h"
      16             : #include "nsThreadUtils.h"
      17             : #include "runnable_utils.h"
      18             : #include "GMPUtils.h"
      19             : #include "mozilla/SystemGroup.h"
      20             : #include "GMPCrashHelper.h"
      21             : 
      22             : namespace mozilla {
      23             : 
      24             : #ifdef LOG
      25             : #undef LOG
      26             : #endif
      27             : 
      28             : extern LogModule* GetGMPLog();
      29             : 
      30             : #define LOGD(msg) MOZ_LOG(GetGMPLog(), mozilla::LogLevel::Debug, msg)
      31             : #define LOG(level, msg) MOZ_LOG(GetGMPLog(), (level), msg)
      32             : 
      33             : #ifdef __CLASS__
      34             : #undef __CLASS__
      35             : #endif
      36             : #define __CLASS__ "GMPVideoEncoderParent"
      37             : 
      38             : namespace gmp {
      39             : 
      40             : // States:
      41             : // Initial: mIsOpen == false
      42             : //    on InitDecode success -> Open
      43             : //    on Shutdown -> Dead
      44             : // Open: mIsOpen == true
      45             : //    on Close -> Dead
      46             : //    on ActorDestroy -> Dead
      47             : //    on Shutdown -> Dead
      48             : // Dead: mIsOpen == false
      49             : 
      50           0 : GMPVideoEncoderParent::GMPVideoEncoderParent(GMPContentParent *aPlugin)
      51             : : GMPSharedMemManager(aPlugin),
      52             :   mIsOpen(false),
      53             :   mShuttingDown(false),
      54             :   mActorDestroyed(false),
      55             :   mPlugin(aPlugin),
      56             :   mCallback(nullptr),
      57             :   mVideoHost(this),
      58           0 :   mPluginId(aPlugin->GetPluginId())
      59             : {
      60           0 :   MOZ_ASSERT(mPlugin);
      61           0 : }
      62             : 
      63             : GMPVideoHostImpl&
      64           0 : GMPVideoEncoderParent::Host()
      65             : {
      66           0 :   return mVideoHost;
      67             : }
      68             : 
      69             : // Note: may be called via Terminated()
      70             : void
      71           0 : GMPVideoEncoderParent::Close()
      72             : {
      73           0 :   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
      74           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
      75             :   // Consumer is done with us; we can shut down.  No more callbacks should
      76             :   // be made to mCallback.  Note: do this before Shutdown()!
      77           0 :   mCallback = nullptr;
      78             : 
      79             :   // Let Shutdown mark us as dead so it knows if we had been alive
      80             : 
      81             :   // In case this is the last reference
      82           0 :   RefPtr<GMPVideoEncoderParent> kungfudeathgrip(this);
      83           0 :   Release();
      84           0 :   Shutdown();
      85           0 : }
      86             : 
      87             : GMPErr
      88           0 : GMPVideoEncoderParent::InitEncode(const GMPVideoCodec& aCodecSettings,
      89             :                                   const nsTArray<uint8_t>& aCodecSpecific,
      90             :                                   GMPVideoEncoderCallbackProxy* aCallback,
      91             :                                   int32_t aNumberOfCores,
      92             :                                   uint32_t aMaxPayloadSize)
      93             : {
      94           0 :   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
      95           0 :   if (mIsOpen) {
      96           0 :     NS_WARNING("Trying to re-init an in-use GMP video encoder!");
      97           0 :     return GMPGenericErr;;
      98             :   }
      99             : 
     100           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
     101           0 :   MOZ_ASSERT(!mCallback);
     102             : 
     103           0 :   if (!aCallback) {
     104           0 :     return GMPGenericErr;
     105             :   }
     106           0 :   mCallback = aCallback;
     107             : 
     108           0 :   if (!SendInitEncode(aCodecSettings, aCodecSpecific, aNumberOfCores, aMaxPayloadSize)) {
     109           0 :     return GMPGenericErr;
     110             :   }
     111           0 :   mIsOpen = true;
     112             : 
     113             :   // Async IPC, we don't have access to a return value.
     114           0 :   return GMPNoErr;
     115             : }
     116             : 
     117             : GMPErr
     118           0 : GMPVideoEncoderParent::Encode(GMPUniquePtr<GMPVideoi420Frame> aInputFrame,
     119             :                               const nsTArray<uint8_t>& aCodecSpecificInfo,
     120             :                               const nsTArray<GMPVideoFrameType>& aFrameTypes)
     121             : {
     122           0 :   if (!mIsOpen) {
     123           0 :     NS_WARNING("Trying to use an dead GMP video encoder");
     124           0 :     return GMPGenericErr;
     125             :   }
     126             : 
     127           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
     128             : 
     129             :   GMPUniquePtr<GMPVideoi420FrameImpl> inputFrameImpl(
     130           0 :     static_cast<GMPVideoi420FrameImpl*>(aInputFrame.release()));
     131             : 
     132             :   // Very rough kill-switch if the plugin stops processing.  If it's merely
     133             :   // hung and continues, we'll come back to life eventually.
     134             :   // 3* is because we're using 3 buffers per frame for i420 data for now.
     135           0 :   if ((NumInUse(GMPSharedMem::kGMPFrameData) > 3*GMPSharedMem::kGMPBufLimit) ||
     136           0 :       (NumInUse(GMPSharedMem::kGMPEncodedData) > GMPSharedMem::kGMPBufLimit)) {
     137           0 :     return GMPGenericErr;
     138             :   }
     139             : 
     140           0 :   GMPVideoi420FrameData frameData;
     141           0 :   inputFrameImpl->InitFrameData(frameData);
     142             : 
     143           0 :   if (!SendEncode(frameData,
     144             :                   aCodecSpecificInfo,
     145             :                   aFrameTypes)) {
     146           0 :     return GMPGenericErr;
     147             :   }
     148             : 
     149             :   // Async IPC, we don't have access to a return value.
     150           0 :   return GMPNoErr;
     151             : }
     152             : 
     153             : GMPErr
     154           0 : GMPVideoEncoderParent::SetChannelParameters(uint32_t aPacketLoss, uint32_t aRTT)
     155             : {
     156           0 :   if (!mIsOpen) {
     157           0 :     NS_WARNING("Trying to use an invalid GMP video encoder!");
     158           0 :     return GMPGenericErr;
     159             :   }
     160             : 
     161           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
     162             : 
     163           0 :   if (!SendSetChannelParameters(aPacketLoss, aRTT)) {
     164           0 :     return GMPGenericErr;
     165             :   }
     166             : 
     167             :   // Async IPC, we don't have access to a return value.
     168           0 :   return GMPNoErr;
     169             : }
     170             : 
     171             : GMPErr
     172           0 : GMPVideoEncoderParent::SetRates(uint32_t aNewBitRate, uint32_t aFrameRate)
     173             : {
     174           0 :   if (!mIsOpen) {
     175           0 :     NS_WARNING("Trying to use an dead GMP video decoder");
     176           0 :     return GMPGenericErr;
     177             :   }
     178             : 
     179           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
     180             : 
     181           0 :   if (!SendSetRates(aNewBitRate, aFrameRate)) {
     182           0 :     return GMPGenericErr;
     183             :   }
     184             : 
     185             :   // Async IPC, we don't have access to a return value.
     186           0 :   return GMPNoErr;
     187             : }
     188             : 
     189             : GMPErr
     190           0 : GMPVideoEncoderParent::SetPeriodicKeyFrames(bool aEnable)
     191             : {
     192           0 :   if (!mIsOpen) {
     193           0 :     NS_WARNING("Trying to use an invalid GMP video encoder!");
     194           0 :     return GMPGenericErr;
     195             :   }
     196             : 
     197           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
     198             : 
     199           0 :   if (!SendSetPeriodicKeyFrames(aEnable)) {
     200           0 :     return GMPGenericErr;
     201             :   }
     202             : 
     203             :   // Async IPC, we don't have access to a return value.
     204           0 :   return GMPNoErr;
     205             : }
     206             : 
     207             : // Note: Consider keeping ActorDestroy sync'd up when making changes here.
     208             : void
     209           0 : GMPVideoEncoderParent::Shutdown()
     210             : {
     211           0 :   LOGD(("%s::%s: %p", __CLASS__, __FUNCTION__, this));
     212           0 :   MOZ_ASSERT(mPlugin->GMPEventTarget()->IsOnCurrentThread());
     213             : 
     214           0 :   if (mShuttingDown) {
     215           0 :     return;
     216             :   }
     217           0 :   mShuttingDown = true;
     218             : 
     219             :   // Notify client we're gone!  Won't occur after Close()
     220           0 :   if (mCallback) {
     221           0 :     mCallback->Terminated();
     222           0 :     mCallback = nullptr;
     223             :   }
     224             : 
     225           0 :   mIsOpen = false;
     226           0 :   if (!mActorDestroyed) {
     227           0 :     Unused << SendEncodingComplete();
     228             :   }
     229             : }
     230             : 
     231             : // Note: Keep this sync'd up with Shutdown
     232             : void
     233           0 : GMPVideoEncoderParent::ActorDestroy(ActorDestroyReason aWhy)
     234             : {
     235           0 :   LOGD(("%s::%s: %p (%d)", __CLASS__, __FUNCTION__, this, (int) aWhy));
     236           0 :   mIsOpen = false;
     237           0 :   mActorDestroyed = true;
     238           0 :   if (mCallback) {
     239             :     // May call Close() (and Shutdown()) immediately or with a delay
     240           0 :     mCallback->Terminated();
     241           0 :     mCallback = nullptr;
     242             :   }
     243           0 :   if (mPlugin) {
     244             :     // Ignore any return code. It is OK for this to fail without killing the process.
     245           0 :     mPlugin->VideoEncoderDestroyed(this);
     246           0 :     mPlugin = nullptr;
     247             :   }
     248           0 :   mVideoHost.ActorDestroyed(); // same as DoneWithAPI
     249           0 :   MaybeDisconnect(aWhy == AbnormalShutdown);
     250           0 : }
     251             : 
     252             : mozilla::ipc::IPCResult
     253           0 : GMPVideoEncoderParent::RecvEncoded(const GMPVideoEncodedFrameData& aEncodedFrame,
     254             :                                    InfallibleTArray<uint8_t>&& aCodecSpecificInfo)
     255             : {
     256           0 :   if (!mCallback) {
     257           0 :     return IPC_FAIL_NO_REASON(this);
     258             :   }
     259             : 
     260           0 :   auto f = new GMPVideoEncodedFrameImpl(aEncodedFrame, &mVideoHost);
     261             :   // Ignore any return code. It is OK for this to fail without killing the process.
     262             :   // This can be called on any thread (or more than one)
     263           0 :   mCallback->Encoded(f, aCodecSpecificInfo);
     264           0 :   f->Destroy();
     265           0 :   return IPC_OK();
     266             : }
     267             : 
     268             : mozilla::ipc::IPCResult
     269           0 : GMPVideoEncoderParent::RecvError(const GMPErr& aError)
     270             : {
     271           0 :   if (!mCallback) {
     272           0 :     return IPC_FAIL_NO_REASON(this);
     273             :   }
     274             : 
     275             :   // Ignore any return code. It is OK for this to fail without killing the process.
     276           0 :   mCallback->Error(aError);
     277             : 
     278           0 :   return IPC_OK();
     279             : }
     280             : 
     281             : mozilla::ipc::IPCResult
     282           0 : GMPVideoEncoderParent::RecvShutdown()
     283             : {
     284           0 :   Shutdown();
     285           0 :   return IPC_OK();
     286             : }
     287             : 
     288             : mozilla::ipc::IPCResult
     289           0 : GMPVideoEncoderParent::RecvParentShmemForPool(Shmem&& aFrameBuffer)
     290             : {
     291           0 :   if (aFrameBuffer.IsWritable()) {
     292             :     // This test may be paranoia now that we don't shut down the VideoHost
     293             :     // in ::Shutdown, but doesn't hurt
     294           0 :     if (mVideoHost.SharedMemMgr()) {
     295           0 :       mVideoHost.SharedMemMgr()->MgrDeallocShmem(GMPSharedMem::kGMPFrameData,
     296           0 :                                                  aFrameBuffer);
     297             :     } else {
     298           0 :       LOGD(("%s::%s: %p Called in shutdown, ignoring and freeing directly", __CLASS__, __FUNCTION__, this));
     299           0 :       DeallocShmem(aFrameBuffer);
     300             :     }
     301             :   }
     302           0 :   return IPC_OK();
     303             : }
     304             : 
     305             : mozilla::ipc::IPCResult
     306           0 : GMPVideoEncoderParent::AnswerNeedShmem(const uint32_t& aEncodedBufferSize,
     307             :                                        Shmem* aMem)
     308             : {
     309           0 :   ipc::Shmem mem;
     310             : 
     311             :   // This test may be paranoia now that we don't shut down the VideoHost
     312             :   // in ::Shutdown, but doesn't hurt
     313           0 :   if (!mVideoHost.SharedMemMgr() ||
     314           0 :       !mVideoHost.SharedMemMgr()->MgrAllocShmem(GMPSharedMem::kGMPEncodedData,
     315           0 :                                                 aEncodedBufferSize,
     316           0 :                                                 ipc::SharedMemory::TYPE_BASIC, &mem))
     317             :   {
     318           0 :     LOG(LogLevel::Error, ("%s::%s: Failed to get a shared mem buffer for Child! size %u",
     319             :                        __CLASS__, __FUNCTION__, aEncodedBufferSize));
     320           0 :     return IPC_FAIL_NO_REASON(this);
     321             :   }
     322           0 :   *aMem = mem;
     323           0 :   mem = ipc::Shmem();
     324           0 :   return IPC_OK();
     325             : }
     326             : 
     327             : mozilla::ipc::IPCResult
     328           0 : GMPVideoEncoderParent::Recv__delete__()
     329             : {
     330           0 :   if (mPlugin) {
     331             :     // Ignore any return code. It is OK for this to fail without killing the process.
     332           0 :     mPlugin->VideoEncoderDestroyed(this);
     333           0 :     mPlugin = nullptr;
     334             :   }
     335             : 
     336           0 :   return IPC_OK();
     337             : }
     338             : 
     339             : } // namespace gmp
     340             : } // namespace mozilla

Generated by: LCOV version 1.13