LCOV - code coverage report
Current view: top level - dom/media/ipc - VideoDecoderChild.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 151 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 27 0.0 %
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 "VideoDecoderChild.h"
       7             : #include "VideoDecoderManagerChild.h"
       8             : #include "mozilla/layers/TextureClient.h"
       9             : #include "base/thread.h"
      10             : #include "MediaInfo.h"
      11             : #include "ImageContainer.h"
      12             : #include "GPUVideoImage.h"
      13             : 
      14             : namespace mozilla {
      15             : namespace dom {
      16             : 
      17             : using base::Thread;
      18             : using namespace ipc;
      19             : using namespace layers;
      20             : using namespace gfx;
      21             : 
      22           0 : VideoDecoderChild::VideoDecoderChild()
      23             :   : mThread(VideoDecoderManagerChild::GetManagerThread())
      24             :   , mCanSend(false)
      25             :   , mInitialized(false)
      26             :   , mIsHardwareAccelerated(false)
      27             :   , mConversion(MediaDataDecoder::ConversionRequired::kNeedNone)
      28           0 :   , mNeedNewDecoder(false)
      29             : {
      30           0 : }
      31             : 
      32           0 : VideoDecoderChild::~VideoDecoderChild()
      33             : {
      34           0 :   AssertOnManagerThread();
      35           0 :   mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
      36           0 : }
      37             : 
      38             : mozilla::ipc::IPCResult
      39           0 : VideoDecoderChild::RecvOutput(const VideoDataIPDL& aData)
      40             : {
      41           0 :   AssertOnManagerThread();
      42             : 
      43             :   // The Image here creates a TextureData object that takes ownership
      44             :   // of the SurfaceDescriptor, and is responsible for making sure that
      45             :   // it gets deallocated.
      46           0 :   RefPtr<Image> image = new GPUVideoImage(GetManager(), aData.sd(), aData.frameSize());
      47             : 
      48           0 :   RefPtr<VideoData> video = VideoData::CreateFromImage(
      49           0 :     aData.display(),
      50           0 :     aData.base().offset(),
      51           0 :     media::TimeUnit::FromMicroseconds(aData.base().time()),
      52           0 :     media::TimeUnit::FromMicroseconds(aData.base().duration()),
      53             :     image,
      54           0 :     aData.base().keyframe(),
      55           0 :     media::TimeUnit::FromMicroseconds(aData.base().timecode()));
      56             : 
      57           0 :   mDecodedData.AppendElement(Move(video));
      58           0 :   return IPC_OK();
      59             : }
      60             : 
      61             : mozilla::ipc::IPCResult
      62           0 : VideoDecoderChild::RecvInputExhausted()
      63             : {
      64           0 :   AssertOnManagerThread();
      65           0 :   mDecodePromise.ResolveIfExists(mDecodedData, __func__);
      66           0 :   mDecodedData.Clear();
      67           0 :   return IPC_OK();
      68             : }
      69             : 
      70             : mozilla::ipc::IPCResult
      71           0 : VideoDecoderChild::RecvDrainComplete()
      72             : {
      73           0 :   AssertOnManagerThread();
      74           0 :   mDrainPromise.ResolveIfExists(mDecodedData, __func__);
      75           0 :   mDecodedData.Clear();
      76           0 :   return IPC_OK();
      77             : }
      78             : 
      79             : mozilla::ipc::IPCResult
      80           0 : VideoDecoderChild::RecvError(const nsresult& aError)
      81             : {
      82           0 :   AssertOnManagerThread();
      83           0 :   mDecodedData.Clear();
      84           0 :   mDecodePromise.RejectIfExists(aError, __func__);
      85           0 :   mDrainPromise.RejectIfExists(aError, __func__);
      86           0 :   mFlushPromise.RejectIfExists(aError, __func__);
      87           0 :   return IPC_OK();
      88             : }
      89             : 
      90             : mozilla::ipc::IPCResult
      91           0 : VideoDecoderChild::RecvInitComplete(const bool& aHardware,
      92             :                                     const nsCString& aHardwareReason,
      93             :                                     const uint32_t& aConversion)
      94             : {
      95           0 :   AssertOnManagerThread();
      96           0 :   mInitPromise.ResolveIfExists(TrackInfo::kVideoTrack, __func__);
      97           0 :   mInitialized = true;
      98           0 :   mIsHardwareAccelerated = aHardware;
      99           0 :   mHardwareAcceleratedReason = aHardwareReason;
     100           0 :   mConversion = static_cast<MediaDataDecoder::ConversionRequired>(aConversion);
     101           0 :   return IPC_OK();
     102             : }
     103             : 
     104             : mozilla::ipc::IPCResult
     105           0 : VideoDecoderChild::RecvInitFailed(const nsresult& aReason)
     106             : {
     107           0 :   AssertOnManagerThread();
     108           0 :   mInitPromise.RejectIfExists(aReason, __func__);
     109           0 :   return IPC_OK();
     110             : }
     111             : 
     112             : mozilla::ipc::IPCResult
     113           0 : VideoDecoderChild::RecvFlushComplete()
     114             : {
     115           0 :   AssertOnManagerThread();
     116           0 :   mFlushPromise.ResolveIfExists(true, __func__);
     117           0 :   return IPC_OK();
     118             : }
     119             : 
     120             : void
     121           0 : VideoDecoderChild::ActorDestroy(ActorDestroyReason aWhy)
     122             : {
     123           0 :   if (aWhy == AbnormalShutdown) {
     124             :     // Defer reporting an error until we've recreated the manager so that
     125             :     // it'll be safe for MediaFormatReader to recreate decoders
     126           0 :     RefPtr<VideoDecoderChild> ref = this;
     127           0 :     GetManager()->RunWhenRecreated(
     128           0 :       NS_NewRunnableFunction("dom::VideoDecoderChild::ActorDestroy", [=]() {
     129           0 :         if (ref->mInitialized) {
     130           0 :           mDecodedData.Clear();
     131           0 :           mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER,
     132           0 :                                         __func__);
     133           0 :           mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER,
     134           0 :                                        __func__);
     135           0 :           mFlushPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER,
     136           0 :                                        __func__);
     137             :           // Make sure the next request will be rejected accordingly if ever
     138             :           // called.
     139           0 :           mNeedNewDecoder = true;
     140             :         } else {
     141           0 :           ref->mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER,
     142           0 :                                            __func__);
     143             :         }
     144           0 :       }));
     145             :   }
     146           0 :   mCanSend = false;
     147           0 : }
     148             : 
     149             : bool
     150           0 : VideoDecoderChild::InitIPDL(const VideoInfo& aVideoInfo,
     151             :                             const layers::TextureFactoryIdentifier& aIdentifier)
     152             : {
     153             :   RefPtr<VideoDecoderManagerChild> manager =
     154           0 :     VideoDecoderManagerChild::GetSingleton();
     155             :   // If the manager isn't available, then don't initialize mIPDLSelfRef and
     156             :   // leave us in an error state. We'll then immediately reject the promise when
     157             :   // Init() is called and the caller can try again. Hopefully by then the new
     158             :   // manager is ready, or we've notified the caller of it being no longer
     159             :   // available. If not, then the cycle repeats until we're ready.
     160           0 :   if (!manager || !manager->CanSend()) {
     161           0 :     return true;
     162             :   }
     163             : 
     164           0 :   mIPDLSelfRef = this;
     165           0 :   bool success = false;
     166           0 :   if (manager->SendPVideoDecoderConstructor(this, aVideoInfo, aIdentifier,
     167             :                                             &success)) {
     168           0 :     mCanSend = true;
     169             :   }
     170           0 :   return success;
     171             : }
     172             : 
     173             : void
     174           0 : VideoDecoderChild::DestroyIPDL()
     175             : {
     176           0 :   if (mCanSend) {
     177           0 :     PVideoDecoderChild::Send__delete__(this);
     178             :   }
     179           0 : }
     180             : 
     181             : void
     182           0 : VideoDecoderChild::IPDLActorDestroyed()
     183             : {
     184           0 :   mIPDLSelfRef = nullptr;
     185           0 : }
     186             : 
     187             : // MediaDataDecoder methods
     188             : 
     189             : RefPtr<MediaDataDecoder::InitPromise>
     190           0 : VideoDecoderChild::Init()
     191             : {
     192           0 :   AssertOnManagerThread();
     193             : 
     194           0 :   if (!mIPDLSelfRef) {
     195             :     return MediaDataDecoder::InitPromise::CreateAndReject(
     196           0 :       NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
     197             :   }
     198             :   // If we failed to send this, then we'll still resolve the Init promise
     199             :   // as ActorDestroy handles it.
     200           0 :   if (mCanSend) {
     201           0 :     SendInit();
     202             :   }
     203           0 :   return mInitPromise.Ensure(__func__);
     204             : }
     205             : 
     206             : RefPtr<MediaDataDecoder::DecodePromise>
     207           0 : VideoDecoderChild::Decode(MediaRawData* aSample)
     208             : {
     209           0 :   AssertOnManagerThread();
     210             : 
     211           0 :   if (mNeedNewDecoder) {
     212             :     return MediaDataDecoder::DecodePromise::CreateAndReject(
     213           0 :       NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER, __func__);
     214             :   }
     215           0 :   if (!mCanSend) {
     216             :     // We're here if the IPC channel has died but we're still waiting for the
     217             :     // RunWhenRecreated task to complete. The decode promise will be rejected
     218             :     // when that task is run.
     219           0 :     return mDecodePromise.Ensure(__func__);
     220             :   }
     221             : 
     222             :   // TODO: It would be nice to add an allocator method to
     223             :   // MediaDataDecoder so that the demuxer could write directly
     224             :   // into shmem rather than requiring a copy here.
     225           0 :   Shmem buffer;
     226           0 :   if (!AllocShmem(aSample->Size(), Shmem::SharedMemory::TYPE_BASIC, &buffer)) {
     227             :     return MediaDataDecoder::DecodePromise::CreateAndReject(
     228           0 :       NS_ERROR_DOM_MEDIA_DECODE_ERR, __func__);
     229             :   }
     230             : 
     231           0 :   memcpy(buffer.get<uint8_t>(), aSample->Data(), aSample->Size());
     232             : 
     233           0 :   MediaRawDataIPDL sample(MediaDataIPDL(aSample->mOffset,
     234           0 :                                         aSample->mTime.ToMicroseconds(),
     235           0 :                                         aSample->mTimecode.ToMicroseconds(),
     236           0 :                                         aSample->mDuration.ToMicroseconds(),
     237             :                                         aSample->mFrames,
     238             :                                         aSample->mKeyframe),
     239           0 :                           buffer);
     240           0 :   SendInput(sample);
     241           0 :   return mDecodePromise.Ensure(__func__);
     242             : }
     243             : 
     244             : RefPtr<MediaDataDecoder::FlushPromise>
     245           0 : VideoDecoderChild::Flush()
     246             : {
     247           0 :   AssertOnManagerThread();
     248           0 :   mDecodePromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
     249           0 :   mDrainPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
     250           0 :   if (mNeedNewDecoder) {
     251             :     return MediaDataDecoder::FlushPromise::CreateAndReject(
     252           0 :       NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER, __func__);
     253             :   }
     254           0 :   if (mCanSend) {
     255           0 :     SendFlush();
     256             :   }
     257           0 :   return mFlushPromise.Ensure(__func__);
     258             : }
     259             : 
     260             : RefPtr<MediaDataDecoder::DecodePromise>
     261           0 : VideoDecoderChild::Drain()
     262             : {
     263           0 :   AssertOnManagerThread();
     264           0 :   if (mNeedNewDecoder) {
     265             :     return MediaDataDecoder::DecodePromise::CreateAndReject(
     266           0 :       NS_ERROR_DOM_MEDIA_NEED_NEW_DECODER, __func__);
     267             :   }
     268           0 :   if (mCanSend) {
     269           0 :     SendDrain();
     270             :   }
     271           0 :   return mDrainPromise.Ensure(__func__);
     272             : }
     273             : 
     274             : void
     275           0 : VideoDecoderChild::Shutdown()
     276             : {
     277           0 :   AssertOnManagerThread();
     278           0 :   mInitPromise.RejectIfExists(NS_ERROR_DOM_MEDIA_CANCELED, __func__);
     279           0 :   if (mCanSend) {
     280           0 :     SendShutdown();
     281             :   }
     282           0 :   mInitialized = false;
     283           0 : }
     284             : 
     285             : bool
     286           0 : VideoDecoderChild::IsHardwareAccelerated(nsACString& aFailureReason) const
     287             : {
     288           0 :   aFailureReason = mHardwareAcceleratedReason;
     289           0 :   return mIsHardwareAccelerated;
     290             : }
     291             : 
     292             : void
     293           0 : VideoDecoderChild::SetSeekThreshold(const media::TimeUnit& aTime)
     294             : {
     295           0 :   AssertOnManagerThread();
     296           0 :   if (mCanSend) {
     297           0 :     SendSetSeekThreshold(aTime.ToMicroseconds());
     298             :   }
     299           0 : }
     300             : 
     301             : MediaDataDecoder::ConversionRequired
     302           0 : VideoDecoderChild::NeedsConversion() const
     303             : {
     304           0 :   return mConversion;
     305             : }
     306             : 
     307             : void
     308           0 : VideoDecoderChild::AssertOnManagerThread() const
     309             : {
     310           0 :   MOZ_ASSERT(NS_GetCurrentThread() == mThread);
     311           0 : }
     312             : 
     313             : VideoDecoderManagerChild*
     314           0 : VideoDecoderChild::GetManager()
     315             : {
     316           0 :   if (!mCanSend) {
     317           0 :     return nullptr;
     318             :   }
     319           0 :   return static_cast<VideoDecoderManagerChild*>(Manager());
     320             : }
     321             : 
     322             : } // namespace dom
     323             : } // namespace mozilla

Generated by: LCOV version 1.13