LCOV - code coverage report
Current view: top level - dom/media/imagecapture - CaptureTask.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 88 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 19 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             : /* vim:set ts=2 sw=2 sts=2 et cindent: */
       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             : 
       7             : #include "CaptureTask.h"
       8             : #include "mozilla/dom/ImageCapture.h"
       9             : #include "mozilla/dom/ImageCaptureError.h"
      10             : #include "mozilla/dom/ImageEncoder.h"
      11             : #include "mozilla/dom/MediaStreamTrack.h"
      12             : #include "mozilla/dom/VideoStreamTrack.h"
      13             : #include "gfxUtils.h"
      14             : #include "nsThreadUtils.h"
      15             : 
      16             : namespace mozilla {
      17             : 
      18           0 : class CaptureTask::MediaStreamEventListener : public MediaStreamTrackListener
      19             : {
      20             : public:
      21           0 :   explicit MediaStreamEventListener(CaptureTask* aCaptureTask)
      22           0 :     : mCaptureTask(aCaptureTask) {};
      23             : 
      24             :   // MediaStreamListener methods.
      25           0 :   void NotifyEnded() override
      26             :   {
      27           0 :     if(!mCaptureTask->mImageGrabbedOrTrackEnd) {
      28           0 :       mCaptureTask->PostTrackEndEvent();
      29             :     }
      30           0 :   }
      31             : 
      32             : private:
      33             :   CaptureTask* mCaptureTask;
      34             : };
      35             : 
      36           0 : CaptureTask::CaptureTask(dom::ImageCapture* aImageCapture)
      37             :   : mImageCapture(aImageCapture)
      38           0 :   , mEventListener(new MediaStreamEventListener(this))
      39             :   , mImageGrabbedOrTrackEnd(false)
      40           0 :   , mPrincipalChanged(false)
      41             : {
      42           0 : }
      43             : 
      44             : nsresult
      45           0 : CaptureTask::TaskComplete(already_AddRefed<dom::Blob> aBlob, nsresult aRv)
      46             : {
      47           0 :   MOZ_ASSERT(NS_IsMainThread());
      48             : 
      49           0 :   DetachTrack();
      50             : 
      51             :   nsresult rv;
      52           0 :   RefPtr<dom::Blob> blob(aBlob);
      53             : 
      54             :   // We have to set the parent because the blob has been generated with a valid one.
      55           0 :   if (blob) {
      56           0 :     blob = dom::Blob::Create(mImageCapture->GetParentObject(), blob->Impl());
      57             :   }
      58             : 
      59           0 :   if (mPrincipalChanged) {
      60           0 :     aRv = NS_ERROR_DOM_SECURITY_ERR;
      61           0 :     IC_LOG("MediaStream principal should not change during TakePhoto().");
      62             :   }
      63             : 
      64           0 :   if (NS_SUCCEEDED(aRv)) {
      65           0 :     rv = mImageCapture->PostBlobEvent(blob);
      66             :   } else {
      67           0 :     rv = mImageCapture->PostErrorEvent(dom::ImageCaptureError::PHOTO_ERROR, aRv);
      68             :   }
      69             : 
      70             :   // Ensure ImageCapture dereference on main thread here because the TakePhoto()
      71             :   // sequences stopped here.
      72           0 :   mImageCapture = nullptr;
      73             : 
      74           0 :   return rv;
      75             : }
      76             : 
      77             : void
      78           0 : CaptureTask::AttachTrack()
      79             : {
      80           0 :   MOZ_ASSERT(NS_IsMainThread());
      81             : 
      82           0 :   dom::VideoStreamTrack* track = mImageCapture->GetVideoStreamTrack();
      83           0 :   track->AddPrincipalChangeObserver(this);
      84           0 :   track->AddListener(mEventListener.get());
      85           0 :   track->AddDirectListener(this);
      86           0 : }
      87             : 
      88             : void
      89           0 : CaptureTask::DetachTrack()
      90             : {
      91           0 :   MOZ_ASSERT(NS_IsMainThread());
      92             : 
      93           0 :   dom::VideoStreamTrack* track = mImageCapture->GetVideoStreamTrack();
      94           0 :   track->RemovePrincipalChangeObserver(this);
      95           0 :   track->RemoveListener(mEventListener.get());
      96           0 :   track->RemoveDirectListener(this);
      97           0 : }
      98             : 
      99             : void
     100           0 : CaptureTask::PrincipalChanged(dom::MediaStreamTrack* aMediaStreamTrack)
     101             : {
     102           0 :   MOZ_ASSERT(NS_IsMainThread());
     103           0 :   mPrincipalChanged = true;
     104           0 : }
     105             : 
     106             : void
     107           0 : CaptureTask::SetCurrentFrames(const VideoSegment& aSegment)
     108             : {
     109           0 :   if (mImageGrabbedOrTrackEnd) {
     110           0 :     return;
     111             :   }
     112             : 
     113             :   // Callback for encoding complete, it calls on main thread.
     114           0 :   class EncodeComplete : public dom::EncodeCompleteCallback
     115             :   {
     116             :   public:
     117           0 :     explicit EncodeComplete(CaptureTask* aTask) : mTask(aTask) {}
     118             : 
     119           0 :     nsresult ReceiveBlob(already_AddRefed<dom::Blob> aBlob) override
     120             :     {
     121           0 :       RefPtr<dom::Blob> blob(aBlob);
     122           0 :       mTask->TaskComplete(blob.forget(), NS_OK);
     123           0 :       mTask = nullptr;
     124           0 :       return NS_OK;
     125             :     }
     126             : 
     127             :   protected:
     128             :     RefPtr<CaptureTask> mTask;
     129             :   };
     130             : 
     131           0 :   for (VideoSegment::ConstChunkIterator iter(aSegment);
     132           0 :        !iter.IsEnded(); iter.Next()) {
     133           0 :     VideoChunk chunk = *iter;
     134             : 
     135             :     // Extract the first valid video frame.
     136           0 :     VideoFrame frame;
     137           0 :     if (!chunk.IsNull()) {
     138           0 :       RefPtr<layers::Image> image;
     139           0 :       if (chunk.mFrame.GetForceBlack()) {
     140             :         // Create a black image.
     141           0 :         image = VideoFrame::CreateBlackImage(chunk.mFrame.GetIntrinsicSize());
     142             :       } else {
     143           0 :         image = chunk.mFrame.GetImage();
     144             :       }
     145           0 :       if (!image) {
     146           0 :         MOZ_ASSERT(image);
     147           0 :         continue;
     148             :       }
     149           0 :       mImageGrabbedOrTrackEnd = true;
     150             : 
     151             :       // Encode image.
     152             :       nsresult rv;
     153           0 :       nsAutoString type(NS_LITERAL_STRING("image/jpeg"));
     154           0 :       nsAutoString options;
     155           0 :       rv = dom::ImageEncoder::ExtractDataFromLayersImageAsync(
     156             :                                 type,
     157             :                                 options,
     158             :                                 false,
     159             :                                 image,
     160           0 :                                 new EncodeComplete(this));
     161           0 :       if (NS_FAILED(rv)) {
     162           0 :         PostTrackEndEvent();
     163             :       }
     164           0 :       return;
     165             :     }
     166             :   }
     167             : }
     168             : 
     169             : void
     170           0 : CaptureTask::PostTrackEndEvent()
     171             : {
     172           0 :   mImageGrabbedOrTrackEnd = true;
     173             : 
     174             :   // Got track end or finish event, stop the task.
     175           0 :   class TrackEndRunnable : public Runnable
     176             :   {
     177             :   public:
     178           0 :     explicit TrackEndRunnable(CaptureTask* aTask)
     179           0 :       : mozilla::Runnable("TrackEndRunnable")
     180           0 :       , mTask(aTask)
     181             :     {
     182           0 :     }
     183             : 
     184           0 :     NS_IMETHOD Run() override
     185             :     {
     186           0 :       mTask->TaskComplete(nullptr, NS_ERROR_FAILURE);
     187           0 :       mTask = nullptr;
     188           0 :       return NS_OK;
     189             :     }
     190             : 
     191             :   protected:
     192             :     RefPtr<CaptureTask> mTask;
     193             :   };
     194             : 
     195           0 :   IC_LOG("Got MediaStream track removed or finished event.");
     196           0 :   nsCOMPtr<nsIRunnable> event = new TrackEndRunnable(this);
     197             :   SystemGroup::Dispatch("CaptureTask::TaskComplete",
     198             :                         TaskCategory::Other,
     199           0 :                         event.forget());
     200           0 : }
     201             : 
     202             : } // namespace mozilla

Generated by: LCOV version 1.13