LCOV - code coverage report
Current view: top level - media/webrtc/trunk/webrtc/video_engine - desktop_capture_impl.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 0 350 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 56 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
       3             :  *
       4             :  *  Use of this source code is governed by a BSD-style license
       5             :  *  that can be found in the LICENSE file in the root of the source
       6             :  *  tree. An additional intellectual property rights grant can be found
       7             :  *  in the file PATENTS.  All contributing project authors may
       8             :  *  be found in the AUTHORS file in the root of the source tree.
       9             :  */
      10             : 
      11             : #include "webrtc/modules/video_capture/video_capture_impl.h"
      12             : 
      13             : #include <stdlib.h>
      14             : #include <string>
      15             : 
      16             : #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h"
      17             : #include "webrtc/modules/include/module_common_types.h"
      18             : #include "webrtc/modules/video_capture/video_capture_config.h"
      19             : #include "webrtc/system_wrappers/include/clock.h"
      20             : #include "webrtc/system_wrappers/include/critical_section_wrapper.h"
      21             : #include "webrtc/system_wrappers/include/trace.h"
      22             : #include "webrtc/base/trace_event.h"
      23             : #include "webrtc/video_engine/desktop_capture_impl.h"
      24             : #include "webrtc/modules/desktop_capture/desktop_frame.h"
      25             : #include "webrtc/modules/desktop_capture/desktop_device_info.h"
      26             : #include "webrtc/modules/desktop_capture/app_capturer.h"
      27             : #include "webrtc/modules/desktop_capture/desktop_capture_options.h"
      28             : #include "webrtc/modules/video_capture/video_capture.h"
      29             : 
      30             : namespace webrtc {
      31             : 
      32           0 : ScreenDeviceInfoImpl::ScreenDeviceInfoImpl(const int32_t id) : _id(id) {
      33           0 : }
      34             : 
      35           0 : ScreenDeviceInfoImpl::~ScreenDeviceInfoImpl(void) {
      36           0 : }
      37             : 
      38           0 : int32_t ScreenDeviceInfoImpl::Init() {
      39           0 :   desktop_device_info_ = std::unique_ptr<DesktopDeviceInfo>(DesktopDeviceInfoImpl::Create());
      40           0 :   return 0;
      41             : }
      42             : 
      43           0 : int32_t ScreenDeviceInfoImpl::Refresh() {
      44           0 :   desktop_device_info_->Refresh();
      45           0 :   return 0;
      46             : }
      47             : 
      48           0 : uint32_t ScreenDeviceInfoImpl::NumberOfDevices() {
      49           0 :   return desktop_device_info_->getDisplayDeviceCount();
      50             : }
      51             : 
      52           0 : int32_t ScreenDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
      53             :                                             char* deviceNameUTF8,
      54             :                                             uint32_t deviceNameUTF8Length,
      55             :                                             char* deviceUniqueIdUTF8,
      56             :                                             uint32_t deviceUniqueIdUTF8Length,
      57             :                                             char* productUniqueIdUTF8,
      58             :                                             uint32_t productUniqueIdUTF8Length,
      59             :                                             pid_t* pid) {
      60             : 
      61           0 :   DesktopDisplayDevice desktopDisplayDevice;
      62             : 
      63             :   // always initialize output
      64           0 :   if (deviceNameUTF8 && deviceNameUTF8Length > 0) {
      65           0 :     memset(deviceNameUTF8, 0, deviceNameUTF8Length);
      66             :   }
      67             : 
      68           0 :   if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
      69           0 :     memset(deviceUniqueIdUTF8, 0, deviceUniqueIdUTF8Length);
      70             :   }
      71           0 :   if (productUniqueIdUTF8 && productUniqueIdUTF8Length > 0) {
      72           0 :     memset(productUniqueIdUTF8, 0, productUniqueIdUTF8Length);
      73             :   }
      74             : 
      75           0 :   if (desktop_device_info_->getDesktopDisplayDeviceInfo(deviceNumber,
      76           0 :                                                        desktopDisplayDevice) == 0) {
      77             :     size_t len;
      78             : 
      79           0 :     const char *deviceName = desktopDisplayDevice.getDeviceName();
      80           0 :     len = deviceName ? strlen(deviceName) : 0;
      81           0 :     if (len && deviceNameUTF8 && len <= deviceNameUTF8Length) {
      82             :       memcpy(deviceNameUTF8,
      83             :              deviceName,
      84           0 :              len);
      85             :     }
      86             : 
      87           0 :     const char *deviceUniqueId = desktopDisplayDevice.getUniqueIdName();
      88           0 :     len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
      89           0 :     if (len && deviceUniqueIdUTF8 && len <= deviceUniqueIdUTF8Length) {
      90             :       memcpy(deviceUniqueIdUTF8,
      91             :              deviceUniqueId,
      92           0 :              len);
      93             :     }
      94             :   }
      95             : 
      96           0 :   return 0;
      97             : }
      98             : 
      99           0 : int32_t ScreenDeviceInfoImpl::DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
     100             :                                                               const char* dialogTitleUTF8,
     101             :                                                               void* parentWindow,
     102             :                                                               uint32_t positionX,
     103             :                                                               uint32_t positionY) {
     104             :   // no device properties to change
     105           0 :   return 0;
     106             : }
     107             : 
     108           0 : int32_t ScreenDeviceInfoImpl::NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
     109           0 :   return 0;
     110             : }
     111             : 
     112           0 : int32_t ScreenDeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
     113             :                                             const uint32_t deviceCapabilityNumber,
     114             :                                             VideoCaptureCapability& capability) {
     115           0 :   return 0;
     116             : }
     117             : 
     118           0 : int32_t ScreenDeviceInfoImpl::GetBestMatchedCapability(const char* deviceUniqueIdUTF8,
     119             :                                                        const VideoCaptureCapability& requested,
     120             :                                                        VideoCaptureCapability& resulting) {
     121           0 :   return 0;
     122             : }
     123             : 
     124           0 : int32_t ScreenDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
     125             :                                              VideoRotation& orientation) {
     126           0 :   return 0;
     127             : }
     128             : 
     129           0 : AppDeviceInfoImpl::AppDeviceInfoImpl(const int32_t id) {
     130           0 : }
     131             : 
     132           0 : AppDeviceInfoImpl::~AppDeviceInfoImpl(void) {
     133           0 : }
     134             : 
     135           0 : int32_t AppDeviceInfoImpl::Init() {
     136           0 :   desktop_device_info_ = std::unique_ptr<DesktopDeviceInfo>(DesktopDeviceInfoImpl::Create());
     137           0 :   return 0;
     138             : }
     139             : 
     140           0 : int32_t AppDeviceInfoImpl::Refresh() {
     141           0 :   desktop_device_info_->Refresh();
     142           0 :   return 0;
     143             : }
     144             : 
     145           0 : uint32_t AppDeviceInfoImpl::NumberOfDevices() {
     146           0 :   return desktop_device_info_->getApplicationCount();
     147             : }
     148             : 
     149           0 : int32_t AppDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
     150             :                                          char* deviceNameUTF8,
     151             :                                          uint32_t deviceNameUTF8Length,
     152             :                                          char* deviceUniqueIdUTF8,
     153             :                                          uint32_t deviceUniqueIdUTF8Length,
     154             :                                          char* productUniqueIdUTF8,
     155             :                                          uint32_t productUniqueIdUTF8Length,
     156             :                                          pid_t* pid) {
     157             : 
     158           0 :   DesktopApplication desktopApplication;
     159             : 
     160             :   // always initialize output
     161           0 :   if (deviceNameUTF8Length && deviceNameUTF8Length > 0) {
     162           0 :     memset(deviceNameUTF8, 0, deviceNameUTF8Length);
     163             :   }
     164           0 :   if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
     165           0 :     memset(deviceUniqueIdUTF8, 0, deviceUniqueIdUTF8Length);
     166             :   }
     167           0 :   if (productUniqueIdUTF8 && productUniqueIdUTF8Length > 0) {
     168           0 :     memset(productUniqueIdUTF8, 0, productUniqueIdUTF8Length);
     169             :   }
     170             : 
     171           0 :   if (desktop_device_info_->getApplicationInfo(deviceNumber,desktopApplication) == 0) {
     172             :     size_t len;
     173             : 
     174           0 :     const char *deviceName = desktopApplication.getProcessAppName();
     175           0 :     len = deviceName ? strlen(deviceName) : 0;
     176           0 :     if (len && len <= deviceNameUTF8Length) {
     177           0 :       memcpy(deviceNameUTF8, deviceName, len);
     178             :     }
     179             : 
     180           0 :     const char *deviceUniqueId = desktopApplication.getUniqueIdName();
     181           0 :     len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
     182           0 :     if (len && deviceUniqueIdUTF8 && len <= deviceUniqueIdUTF8Length) {
     183             :       memcpy(deviceUniqueIdUTF8,
     184             :              deviceUniqueId,
     185           0 :              len);
     186             :     }
     187           0 :     if (pid) {
     188           0 :       *pid = desktopApplication.getProcessId();
     189             :     }
     190             :   }
     191           0 :   return 0;
     192             : }
     193             : 
     194           0 : int32_t AppDeviceInfoImpl::DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
     195             :                                                            const char* dialogTitleUTF8,
     196             :                                                            void* parentWindow,
     197             :                                                            uint32_t positionX,
     198             :                                                            uint32_t positionY) {
     199           0 :   return 0;
     200             : }
     201             : 
     202           0 : int32_t AppDeviceInfoImpl::NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
     203           0 :   return 0;
     204             : }
     205             : 
     206           0 : int32_t AppDeviceInfoImpl::GetCapability(
     207             :                                          const char* deviceUniqueIdUTF8,
     208             :                                          const uint32_t deviceCapabilityNumber,
     209             :                                          VideoCaptureCapability& capability) {
     210           0 :   return 0;
     211             : }
     212             : 
     213           0 : int32_t AppDeviceInfoImpl::GetBestMatchedCapability(
     214             :                                                     const char* deviceUniqueIdUTF8,
     215             :                                                     const VideoCaptureCapability& requested,
     216             :                                                     VideoCaptureCapability& resulting) {
     217           0 :   return 0;
     218             : }
     219             : 
     220           0 : int32_t AppDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
     221             :                                           VideoRotation& orientation) {
     222           0 :   return 0;
     223             : }
     224             : 
     225           0 : VideoCaptureModule* DesktopCaptureImpl::Create(const int32_t id,
     226             :                                                const char* uniqueId,
     227             :                                                const CaptureDeviceType type) {
     228             : 
     229           0 :   rtc::RefCountedObject<DesktopCaptureImpl>* capture = new rtc::RefCountedObject<DesktopCaptureImpl>(id);
     230             : 
     231             :   //create real screen capturer.
     232           0 :   if (capture->Init(uniqueId, type)) {
     233           0 :     capture->Release();
     234           0 :     return nullptr;
     235             :   }
     236             : 
     237           0 :   return capture;
     238             : }
     239             : 
     240           0 : int32_t WindowDeviceInfoImpl::Init() {
     241           0 :   desktop_device_info_ = std::unique_ptr<DesktopDeviceInfo>(DesktopDeviceInfoImpl::Create());
     242           0 :   return 0;
     243             : }
     244             : 
     245           0 : int32_t DesktopCaptureImpl::AddRef() const {
     246           0 :   return ++mRefCount;
     247             : }
     248           0 : int32_t DesktopCaptureImpl::Release() const {
     249           0 :   assert(mRefCount > 0);
     250           0 :   auto count = --mRefCount;
     251           0 :   if (!count) {
     252             :     WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideoCapture, -1,
     253             :                  "DesktopCapture self deleting (desktopCapture=0x%p)", this);
     254             : 
     255             :     // Clear any pointers before starting destruction. Otherwise worker-
     256             :     // threads will still have pointers to a partially destructed object.
     257             :     // Example: AudioDeviceBuffer::RequestPlayoutData() can access a
     258             :     // partially deconstructed |_ptrCbAudioTransport| during destruction
     259             :     // if we don't call Terminate here.
     260             :     //-> NG TODO Terminate();
     261           0 :     delete this;
     262           0 :     return count;
     263             :   }
     264           0 :   return mRefCount;
     265             : }
     266             : 
     267           0 : int32_t WindowDeviceInfoImpl::Refresh() {
     268           0 :   desktop_device_info_->Refresh();
     269           0 :   return 0;
     270             : }
     271             : 
     272           0 : uint32_t WindowDeviceInfoImpl::NumberOfDevices() {
     273           0 :   return desktop_device_info_->getWindowCount();
     274             : }
     275             : 
     276           0 : int32_t WindowDeviceInfoImpl::GetDeviceName(uint32_t deviceNumber,
     277             :                                             char* deviceNameUTF8,
     278             :                                             uint32_t deviceNameUTF8Length,
     279             :                                             char* deviceUniqueIdUTF8,
     280             :                                             uint32_t deviceUniqueIdUTF8Length,
     281             :                                             char* productUniqueIdUTF8,
     282             :                                             uint32_t productUniqueIdUTF8Length,
     283             :                                             pid_t* pid) {
     284             : 
     285           0 :   DesktopDisplayDevice desktopDisplayDevice;
     286             : 
     287             :   // always initialize output
     288           0 :   if (deviceNameUTF8 && deviceNameUTF8Length > 0) {
     289           0 :     memset(deviceNameUTF8, 0, deviceNameUTF8Length);
     290             :   }
     291           0 :   if (deviceUniqueIdUTF8 && deviceUniqueIdUTF8Length > 0) {
     292           0 :     memset(deviceUniqueIdUTF8, 0, deviceUniqueIdUTF8Length);
     293             :   }
     294           0 :   if (productUniqueIdUTF8 && productUniqueIdUTF8Length > 0) {
     295           0 :     memset(productUniqueIdUTF8, 0, productUniqueIdUTF8Length);
     296             :   }
     297             : 
     298           0 :   if (desktop_device_info_->getWindowInfo(deviceNumber,
     299           0 :                                           desktopDisplayDevice) == 0) {
     300             : 
     301             :     size_t len;
     302             : 
     303           0 :     const char *deviceName = desktopDisplayDevice.getDeviceName();
     304           0 :     len = deviceName ? strlen(deviceName) : 0;
     305           0 :     if (len && deviceNameUTF8 && len <= deviceNameUTF8Length) {
     306             :       memcpy(deviceNameUTF8,
     307             :              deviceName,
     308           0 :              len);
     309             :     }
     310             : 
     311           0 :     const char *deviceUniqueId = desktopDisplayDevice.getUniqueIdName();
     312           0 :     len = deviceUniqueId ? strlen(deviceUniqueId) : 0;
     313           0 :     if (len && deviceUniqueIdUTF8 && len <= deviceUniqueIdUTF8Length) {
     314             :       memcpy(deviceUniqueIdUTF8,
     315             :              deviceUniqueId,
     316           0 :              len);
     317             :     }
     318           0 :     if (pid) {
     319           0 :       *pid = desktopDisplayDevice.getPid();
     320             :     }
     321             :   }
     322             : 
     323           0 :   return 0;
     324             : }
     325             : 
     326           0 : int32_t WindowDeviceInfoImpl::DisplayCaptureSettingsDialogBox(const char* deviceUniqueIdUTF8,
     327             :                                                               const char* dialogTitleUTF8,
     328             :                                                               void* parentWindow,
     329             :                                                               uint32_t positionX,
     330             :                                                               uint32_t positionY) {
     331             :   // no device properties to change
     332           0 :   return 0;
     333             : }
     334             : 
     335           0 : int32_t WindowDeviceInfoImpl::NumberOfCapabilities(const char* deviceUniqueIdUTF8) {
     336           0 :   return 0;
     337             : }
     338             : 
     339           0 : int32_t WindowDeviceInfoImpl::GetCapability(const char* deviceUniqueIdUTF8,
     340             :                                             const uint32_t deviceCapabilityNumber,
     341             :                                             VideoCaptureCapability& capability) {
     342           0 :   return 0;
     343             : }
     344             : 
     345           0 : int32_t WindowDeviceInfoImpl::GetBestMatchedCapability(const char* deviceUniqueIdUTF8,
     346             :                                                        const VideoCaptureCapability& requested,
     347             :                                                        VideoCaptureCapability& resulting) {
     348           0 :   return 0;
     349             : }
     350             : 
     351           0 : int32_t WindowDeviceInfoImpl::GetOrientation(const char* deviceUniqueIdUTF8,
     352             :                                              VideoRotation& orientation) {
     353           0 :   return 0;
     354             : }
     355             : 
     356           0 : VideoCaptureModule::DeviceInfo* DesktopCaptureImpl::CreateDeviceInfo(const int32_t id,
     357             :                                                                      const CaptureDeviceType type) {
     358           0 :   if (type == CaptureDeviceType::Application) {
     359           0 :     AppDeviceInfoImpl * pAppDeviceInfoImpl = new AppDeviceInfoImpl(id);
     360           0 :     if (!pAppDeviceInfoImpl || pAppDeviceInfoImpl->Init()) {
     361           0 :       delete pAppDeviceInfoImpl;
     362           0 :       pAppDeviceInfoImpl = NULL;
     363             :     }
     364           0 :     return pAppDeviceInfoImpl;
     365           0 :   } else if (type == CaptureDeviceType::Screen) {
     366           0 :     ScreenDeviceInfoImpl * pScreenDeviceInfoImpl = new ScreenDeviceInfoImpl(id);
     367           0 :     if (!pScreenDeviceInfoImpl || pScreenDeviceInfoImpl->Init()) {
     368           0 :       delete pScreenDeviceInfoImpl;
     369           0 :       pScreenDeviceInfoImpl = NULL;
     370             :     }
     371           0 :     return pScreenDeviceInfoImpl;
     372           0 :   } else if (type == CaptureDeviceType::Window) {
     373           0 :     WindowDeviceInfoImpl * pWindowDeviceInfoImpl = new WindowDeviceInfoImpl(id);
     374           0 :     if (!pWindowDeviceInfoImpl || pWindowDeviceInfoImpl->Init()) {
     375           0 :       delete pWindowDeviceInfoImpl;
     376           0 :       pWindowDeviceInfoImpl = NULL;
     377             :     }
     378           0 :     return pWindowDeviceInfoImpl;
     379             :   }
     380           0 :   return NULL;
     381             : }
     382             : 
     383           0 : const char* DesktopCaptureImpl::CurrentDeviceName() const {
     384           0 :   return _deviceUniqueId.c_str();
     385             : }
     386             : 
     387           0 : int32_t DesktopCaptureImpl::Init(const char* uniqueId,
     388             :                                  const CaptureDeviceType type) {
     389           0 :   DesktopCaptureOptions options = DesktopCaptureOptions::CreateDefault();
     390             :   // Leave desktop effects enabled during WebRTC captures.
     391           0 :   options.set_disable_effects(false);
     392             : 
     393           0 :   if (type == CaptureDeviceType::Application) {
     394           0 :     std::unique_ptr<DesktopCapturer> pAppCapturer = DesktopCapturer::CreateAppCapturer(options);
     395           0 :     if (!pAppCapturer) {
     396           0 :       return -1;
     397             :     }
     398             : 
     399           0 :     DesktopCapturer::SourceId sourceId = atoi(uniqueId);
     400           0 :     pAppCapturer->SelectSource(sourceId);
     401             : 
     402           0 :     MouseCursorMonitor *pMouseCursorMonitor = MouseCursorMonitor::CreateForScreen(options, webrtc::kFullDesktopScreenId);
     403           0 :     desktop_capturer_cursor_composer_ = std::unique_ptr<DesktopAndCursorComposer>(new DesktopAndCursorComposer(pAppCapturer.release(), pMouseCursorMonitor));
     404           0 :   } else if (type == CaptureDeviceType::Screen) {
     405           0 :     std::unique_ptr<DesktopCapturer> pScreenCapturer = DesktopCapturer::CreateScreenCapturer(options);
     406           0 :     if (!pScreenCapturer.get()) {
     407           0 :       return -1;
     408             :     }
     409             : 
     410           0 :     DesktopCapturer::SourceId sourceId = atoi(uniqueId);
     411           0 :     pScreenCapturer->SelectSource(sourceId);
     412             : 
     413             :     // Upstream removed the ShapeObserver
     414             :     //pScreenCapturer->SetMouseShapeObserver(this);
     415             : 
     416           0 :     MouseCursorMonitor *pMouseCursorMonitor = MouseCursorMonitor::CreateForScreen(options, sourceId);
     417           0 :     desktop_capturer_cursor_composer_ = std::unique_ptr<DesktopAndCursorComposer>(new DesktopAndCursorComposer(pScreenCapturer.release(), pMouseCursorMonitor));
     418           0 :   } else if (type == CaptureDeviceType::Window) {
     419           0 :     std::unique_ptr<DesktopCapturer> pWindowCapturer = DesktopCapturer::CreateWindowCapturer(options);
     420           0 :     if (!pWindowCapturer.get()) {
     421           0 :       return -1;
     422             :     }
     423             : 
     424           0 :     DesktopCapturer::SourceId sourceId = atoi(uniqueId);
     425           0 :     pWindowCapturer->SelectSource(sourceId);
     426             : 
     427           0 :     MouseCursorMonitor *pMouseCursorMonitor = MouseCursorMonitor::CreateForWindow(webrtc::DesktopCaptureOptions::CreateDefault(), sourceId);
     428           0 :     desktop_capturer_cursor_composer_ = std::unique_ptr<DesktopAndCursorComposer>(new DesktopAndCursorComposer(pWindowCapturer.release(), pMouseCursorMonitor));
     429             :   }
     430           0 :   _deviceUniqueId = uniqueId;
     431             : 
     432           0 :   return 0;
     433             : }
     434             : 
     435           0 : DesktopCaptureImpl::DesktopCaptureImpl(const int32_t id)
     436             :   : _id(id),
     437             :     _deviceUniqueId(""),
     438           0 :     _apiCs(*CriticalSectionWrapper::CreateCriticalSection()),
     439             :     _requestedCapability(),
     440           0 :     _callBackCs(*CriticalSectionWrapper::CreateCriticalSection()),
     441             :     _dataCallBack(NULL),
     442             :     _rotateFrame(kVideoRotation_0),
     443           0 :     last_capture_time_(rtc::TimeNanos()/rtc::kNumNanosecsPerMillisec),
     444             :     // XXX Note that this won't capture drift!
     445           0 :     delta_ntp_internal_ms_(Clock::GetRealTimeClock()->CurrentNtpInMilliseconds() -
     446           0 :                            last_capture_time_),
     447             :     time_event_(EventWrapper::Create()),
     448             :     mRefCount(0),
     449             : #if defined(_WIN32)
     450             :     capturer_thread_(new rtc::PlatformUIThread(Run, this, "ScreenCaptureThread")),
     451             : #else
     452           0 :     capturer_thread_(new rtc::PlatformThread(Run, this, "ScreenCaptureThread")),
     453             : #endif
     454           0 :     started_(false) {
     455             :   //-> TODO @@NG why is this crashing (seen on Linux)
     456             :   //-> capturer_thread_->SetPriority(rtc::kHighPriority);
     457           0 :   _requestedCapability.width = kDefaultWidth;
     458           0 :   _requestedCapability.height = kDefaultHeight;
     459           0 :   _requestedCapability.maxFPS = 30;
     460           0 :   _requestedCapability.rawType = kVideoI420;
     461           0 :   _requestedCapability.codecType = kVideoCodecUnknown;
     462           0 :   memset(_incomingFrameTimesNanos, 0, sizeof(_incomingFrameTimesNanos));
     463           0 : }
     464             : 
     465           0 : DesktopCaptureImpl::~DesktopCaptureImpl() {
     466           0 :   time_event_->Set();
     467           0 :   capturer_thread_->Stop();
     468             : 
     469           0 :   DeRegisterCaptureDataCallback();
     470           0 :   delete &_callBackCs;
     471           0 :   delete &_apiCs;
     472           0 : }
     473             : 
     474           0 : void DesktopCaptureImpl::RegisterCaptureDataCallback(rtc::VideoSinkInterface<VideoFrame> *dataCallback)
     475             : {
     476           0 :   CriticalSectionScoped cs(&_apiCs);
     477           0 :   CriticalSectionScoped cs2(&_callBackCs);
     478           0 :   _dataCallBack = dataCallback;
     479           0 : }
     480             : 
     481           0 : void DesktopCaptureImpl::DeRegisterCaptureDataCallback()
     482             : {
     483           0 :   CriticalSectionScoped cs(&_apiCs);
     484           0 :   CriticalSectionScoped cs2(&_callBackCs);
     485           0 :   _dataCallBack = nullptr;
     486           0 : }
     487             : 
     488           0 : int32_t DesktopCaptureImpl::DeliverCapturedFrame(webrtc::VideoFrame& captureFrame,
     489             :                                                  int64_t capture_time) {
     490           0 :   UpdateFrameCount();  // frame count used for local frame rate callback.
     491             : 
     492             :   // Set the capture time
     493           0 :   if (capture_time != 0) {
     494           0 :     captureFrame.set_render_time_ms(capture_time - delta_ntp_internal_ms_);
     495             :   } else {
     496           0 :     captureFrame.set_render_time_ms(rtc::TimeNanos()/rtc::kNumNanosecsPerMillisec);
     497             :   }
     498             : 
     499           0 :   if (captureFrame.render_time_ms() == last_capture_time_) {
     500             :     // We don't allow the same capture time for two frames, drop this one.
     501           0 :     return -1;
     502             :   }
     503           0 :   last_capture_time_ = captureFrame.render_time_ms();
     504             : 
     505           0 :   if (_dataCallBack) {
     506           0 :     _dataCallBack->OnFrame(captureFrame);
     507             :   }
     508             : 
     509           0 :   return 0;
     510             : }
     511             : 
     512             : // Copied from VideoCaptureImpl::IncomingFrame. See Bug 1038324
     513           0 : int32_t DesktopCaptureImpl::IncomingFrame(uint8_t* videoFrame,
     514             :                                           size_t videoFrameLength,
     515             :                                           const VideoCaptureCapability& frameInfo,
     516             :                                           int64_t captureTime/*=0*/)
     517             : {
     518             :   WEBRTC_TRACE(webrtc::kTraceStream, webrtc::kTraceVideoCapture, _id,
     519             :                "IncomingFrame width %d, height %d", (int) frameInfo.width,
     520             :                (int) frameInfo.height);
     521             : 
     522           0 :   int64_t startProcessTime = rtc::TimeNanos();
     523             : 
     524           0 :   CriticalSectionScoped cs(&_callBackCs);
     525             : 
     526           0 :   const int32_t width = frameInfo.width;
     527           0 :   const int32_t height = frameInfo.height;
     528             : 
     529           0 :   TRACE_EVENT1("webrtc", "VC::IncomingFrame", "capture_time", captureTime);
     530             : 
     531           0 :   if (frameInfo.codecType == kVideoCodecUnknown) {
     532             :     // Not encoded, convert to I420.
     533             :     const VideoType commonVideoType =
     534           0 :       RawVideoTypeToCommonVideoVideoType(frameInfo.rawType);
     535             : 
     536           0 :     if (frameInfo.rawType != kVideoMJPEG &&
     537           0 :         CalcBufferSize(commonVideoType, width,
     538             :                        abs(height)) != videoFrameLength) {
     539             :       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
     540             :                    "Wrong incoming frame length.");
     541           0 :       return -1;
     542             :     }
     543             : 
     544           0 :     int stride_y = width;
     545           0 :     int stride_uv = (width + 1) / 2;
     546           0 :     int target_width = width;
     547           0 :     int target_height = abs(height);
     548             :     // Rotating resolution when for 90/270 degree rotations.
     549           0 :     if (_rotateFrame == kVideoRotation_90 || _rotateFrame == kVideoRotation_270)  {
     550           0 :       target_height = width;
     551           0 :       target_width = abs(height);
     552             :     }
     553             : 
     554             :     // Setting absolute height (in case it was negative).
     555             :     // In Windows, the image starts bottom left, instead of top left.
     556             :     // Setting a negative source height, inverts the image (within LibYuv).
     557           0 :     rtc::scoped_refptr<webrtc::I420Buffer> buffer;
     558           0 :     buffer = I420Buffer::Create(target_width, target_height, stride_y,
     559           0 :                                 stride_uv, stride_uv);
     560           0 :     const int conversionResult = ConvertToI420(commonVideoType,
     561             :                                                videoFrame,
     562             :                                                0, 0,  // No cropping
     563             :                                                width, height,
     564             :                                                videoFrameLength,
     565             :                                                _rotateFrame,
     566           0 :                                                buffer.get());
     567           0 :     webrtc::VideoFrame captureFrame(buffer, 0, 0, kVideoRotation_0);
     568           0 :     if (conversionResult < 0) {
     569             :       WEBRTC_TRACE(webrtc::kTraceError, webrtc::kTraceVideoCapture, _id,
     570             :                    "Failed to convert capture frame from type %d to I420",
     571             :                    frameInfo.rawType);
     572           0 :       return -1;
     573             :     }
     574             : 
     575           0 :     int32_t req_max_width = _requestedCapability.width & 0xffff;
     576           0 :     int32_t req_max_height = _requestedCapability.height & 0xffff;
     577           0 :     int32_t req_ideal_width = (_requestedCapability.width >> 16) & 0xffff;
     578           0 :     int32_t req_ideal_height = (_requestedCapability.height >> 16) & 0xffff;
     579             : 
     580           0 :     int32_t dest_max_width = std::min(req_max_width, target_width);
     581           0 :     int32_t dest_max_height = std::min(req_max_height, target_height);
     582           0 :     int32_t dst_width = std::min(req_ideal_width > 0 ? req_ideal_width : target_width, dest_max_width);
     583           0 :     int32_t dst_height = std::min(req_ideal_height > 0 ? req_ideal_height : target_height, dest_max_height);
     584             : 
     585             :     // scale to average of portrait and landscape
     586           0 :     float scale_width = (float)dst_width / (float)target_width;
     587           0 :     float scale_height = (float)dst_height / (float)target_height;
     588           0 :     float scale = (scale_width + scale_height) / 2;
     589           0 :     dst_width = (int)(scale * target_width);
     590           0 :     dst_height = (int)(scale * target_height);
     591             : 
     592             :     // if scaled rectangle exceeds max rectangle, scale to minimum of portrait and landscape
     593           0 :     if (dst_width > dest_max_width || dst_height > dest_max_height) {
     594           0 :       scale_width = (float)dest_max_width / (float)dst_width;
     595           0 :       scale_height = (float)dest_max_height / (float)dst_height;
     596           0 :       scale = std::min(scale_width, scale_height);
     597           0 :       dst_width = (int)(scale * dst_width);
     598           0 :       dst_height = (int)(scale * dst_height);
     599             :     }
     600             : 
     601           0 :     if (dst_width == target_width && dst_height == target_height) {
     602           0 :       DeliverCapturedFrame(captureFrame, captureTime);
     603             :     } else {
     604           0 :       rtc::scoped_refptr<webrtc::I420Buffer> buffer;
     605           0 :       buffer = I420Buffer::Create(dst_width, dst_height, stride_y,
     606           0 :                                   stride_uv, stride_uv);
     607             : 
     608           0 :       buffer->ScaleFrom(*captureFrame.video_frame_buffer().get());
     609           0 :       webrtc::VideoFrame scaledFrame(buffer, 0, 0, kVideoRotation_0);
     610           0 :       DeliverCapturedFrame(scaledFrame, captureTime);
     611             :     }
     612             :   } else {
     613           0 :     assert(false);
     614             :     return -1;
     615             :   }
     616             : 
     617             :   const int64_t processTime =
     618           0 :     (rtc::TimeNanos() - startProcessTime)/rtc::kNumNanosecsPerMillisec;
     619             : 
     620             :   if (processTime > 10) {
     621             :     WEBRTC_TRACE(webrtc::kTraceWarning, webrtc::kTraceVideoCapture, _id,
     622             :                  "Too long processing time of Incoming frame: %ums",
     623             :                  (unsigned int) processTime);
     624             :   }
     625             : 
     626           0 :   return 0;
     627             : }
     628             : 
     629           0 : int32_t DesktopCaptureImpl::SetCaptureRotation(VideoRotation rotation) {
     630           0 :   CriticalSectionScoped cs(&_apiCs);
     631           0 :   CriticalSectionScoped cs2(&_callBackCs);
     632           0 :   _rotateFrame = rotation;
     633           0 :   return 0;
     634             : }
     635             : 
     636           0 : bool DesktopCaptureImpl::SetApplyRotation(bool enable) {
     637           0 :   return true;
     638             : }
     639             : 
     640           0 : void DesktopCaptureImpl::UpdateFrameCount() {
     641           0 :   if (_incomingFrameTimesNanos[0] == 0) {
     642             :     // first no shift
     643             :   } else {
     644             :     // shift
     645           0 :     for (int i = (kFrameRateCountHistorySize - 2); i >= 0; i--) {
     646           0 :       _incomingFrameTimesNanos[i + 1] = _incomingFrameTimesNanos[i];
     647             :     }
     648             :   }
     649           0 :   _incomingFrameTimesNanos[0] = rtc::TimeNanos();
     650           0 : }
     651             : 
     652           0 : uint32_t DesktopCaptureImpl::CalculateFrameRate(int64_t now_ns)
     653             : {
     654           0 :     int32_t num = 0;
     655           0 :     int32_t nrOfFrames = 0;
     656           0 :     for (num = 1; num < (kFrameRateCountHistorySize - 1); num++)
     657             :     {
     658           0 :         if (_incomingFrameTimesNanos[num] <= 0 ||
     659           0 :             (now_ns - _incomingFrameTimesNanos[num]) /
     660             :             rtc::kNumNanosecsPerMillisec >
     661             :                 kFrameRateHistoryWindowMs) // don't use data older than 2sec
     662             :         {
     663             :             break;
     664             :         }
     665             :         else
     666             :         {
     667           0 :             nrOfFrames++;
     668             :         }
     669             :     }
     670           0 :     if (num > 1)
     671             :     {
     672           0 :         int64_t diff = (now_ns - _incomingFrameTimesNanos[num - 1]) /
     673           0 :                        rtc::kNumNanosecsPerMillisec;
     674           0 :         if (diff > 0)
     675             :         {
     676           0 :             return uint32_t((nrOfFrames * 1000.0f / diff) + 0.5f);
     677             :         }
     678             :     }
     679             : 
     680           0 :     return nrOfFrames;
     681             : }
     682             : 
     683           0 : int32_t DesktopCaptureImpl::StartCapture(const VideoCaptureCapability& capability) {
     684           0 :   _requestedCapability = capability;
     685             : #if defined(_WIN32)
     686             :   uint32_t maxFPSNeeded = 1000/_requestedCapability.maxFPS;
     687             :   capturer_thread_->RequestCallbackTimer(maxFPSNeeded);
     688             : #endif
     689             : 
     690           0 :   desktop_capturer_cursor_composer_->Start(this);
     691           0 :   capturer_thread_->Start();
     692           0 :   started_ = true;
     693             : 
     694           0 :   return 0;
     695             : }
     696             : 
     697           0 : int32_t DesktopCaptureImpl::StopCapture() {
     698           0 :   if (started_) {
     699           0 :     capturer_thread_->Stop(); // thread is guaranteed stopped before this returns
     700           0 :     desktop_capturer_cursor_composer_->Stop();
     701           0 :     started_ = false;
     702           0 :     return 0;
     703             :   }
     704           0 :   return -1;
     705             : }
     706             : 
     707           0 : bool DesktopCaptureImpl::CaptureStarted() {
     708           0 :   return started_;
     709             : }
     710             : 
     711           0 : int32_t DesktopCaptureImpl::CaptureSettings(VideoCaptureCapability& settings) {
     712           0 :   return -1;
     713             : }
     714             : 
     715           0 : void DesktopCaptureImpl::OnCaptureResult(DesktopCapturer::Result result,
     716             :                                          std::unique_ptr<DesktopFrame> frame) {
     717           0 :   if (frame.get() == nullptr) return;
     718           0 :   uint8_t * videoFrame = frame->data();
     719           0 :   VideoCaptureCapability frameInfo;
     720           0 :   frameInfo.width = frame->size().width();
     721           0 :   frameInfo.height = frame->size().height();
     722           0 :   frameInfo.rawType = kVideoARGB;
     723             : 
     724             :   // combine cursor in frame
     725             :   // Latest WebRTC already support it by DesktopFrameWithCursor/DesktopAndCursorComposer.
     726             : 
     727           0 :   size_t videoFrameLength = frameInfo.width * frameInfo.height * DesktopFrame::kBytesPerPixel;
     728           0 :   IncomingFrame(videoFrame, videoFrameLength, frameInfo);
     729             : }
     730             : 
     731           0 : void DesktopCaptureImpl::process() {
     732           0 :   DesktopRect desktop_rect;
     733           0 :   DesktopRegion desktop_region;
     734             : 
     735             : #if !defined(_WIN32)
     736           0 :   int64_t startProcessTime = rtc::TimeNanos();
     737             : #endif
     738             : 
     739           0 :   desktop_capturer_cursor_composer_->CaptureFrame();
     740             : 
     741             : #if !defined(_WIN32)
     742             :   const uint32_t processTime =
     743           0 :     ((uint32_t)(rtc::TimeNanos() - startProcessTime))/rtc::kNumNanosecsPerMillisec;
     744             :   // Use at most x% CPU or limit framerate
     745           0 :   const uint32_t maxFPSNeeded = 1000/_requestedCapability.maxFPS;
     746           0 :   const float sleepTimeFactor = (100.0f / kMaxDesktopCaptureCpuUsage) - 1.0f;
     747           0 :   const uint32_t sleepTime = sleepTimeFactor * processTime;
     748           0 :   time_event_->Wait(std::max<uint32_t>(maxFPSNeeded, sleepTime));
     749             : #endif
     750           0 : }
     751             : 
     752             : }  // namespace webrtc

Generated by: LCOV version 1.13