10e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// libjingle 20e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Copyright 2010 Google Inc. 30e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 40e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Redistribution and use in source and binary forms, with or without 50e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// modification, are permitted provided that the following conditions are met: 60e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 70e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1. Redistributions of source code must retain the above copyright notice, 80e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// this list of conditions and the following disclaimer. 90e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 2. Redistributions in binary form must reproduce the above copyright notice, 100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// this list of conditions and the following disclaimer in the documentation 110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// and/or other materials provided with the distribution. 120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 3. The name of the author may not be used to endorse or promote products 130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// derived from this software without specific prior written permission. 140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO 180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; 210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF 240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementation file of class VideoCapturer. 270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/base/videocapturer.h" 290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include <algorithm> 310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_YUV) 330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "libyuv/scale_argb.h" 340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 35cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/videoframefactory.h" 36cf81adffe15fa8ea0f333432e41f6d504148f18abuildbot@webrtc.org#include "talk/media/base/videoprocessor.h" 372a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/common.h" 382a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/logging.h" 392a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org#include "webrtc/base/systeminfo.h" 400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if defined(HAVE_WEBRTC_VIDEO) 420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#include "talk/media/webrtc/webrtcvideoframe.h" 432a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org#include "talk/media/webrtc/webrtcvideoframefactory.h" 440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // HAVE_WEBRTC_VIDEO 450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace cricket { 470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgnamespace { 490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO(thorcarpenter): This is a BIG hack to flush the system with black 510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// frames. Frontends should coordinate to update the video state of a muted 520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// user. When all frontends to this consider removing the black frame business. 530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst int kNumBlackFramesOnMute = 30; 540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// MessageHandler constants. 560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgenum { 570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_DO_PAUSE = 0, 580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_DO_UNPAUSE, 590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org MSG_STATE_CHANGE 600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org}; 610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int64 kMaxDistance = ~(static_cast<int64>(1) << 63); 63c47d0d933f5c12781b4be695de79a709255bc8afhenrike@webrtc.org#ifdef LINUX 640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kYU12Penalty = 16; // Needs to be higher than MJPG index. 65c47d0d933f5c12781b4be695de79a709255bc8afhenrike@webrtc.org#endif 660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstatic const int kDefaultScreencastFps = 5; 672a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgtypedef rtc::TypedMessageData<CaptureState> StateChangeParams; 680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 697587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org// Limit stats data collections to ~20 seconds of 30fps data before dropping 707587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org// old data in case stats aren't reset for long periods of time. 717587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgstatic const size_t kMaxAccumulatorSize = 600; 727587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace 740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////// 760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementation of struct CapturedFrame 770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////// 780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgCapturedFrame::CapturedFrame() 790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : width(0), 800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org height(0), 810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org fourcc(0), 820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org pixel_width(0), 830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org pixel_height(0), 840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org elapsed_time(0), 850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org time_stamp(0), 860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data_size(0), 870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org rotation(0), 880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org data(NULL) {} 890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// TODO(fbarchard): Remove this function once lmimediaengine stops using it. 910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool CapturedFrame::GetDataSize(uint32* size) const { 920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!size || data_size == CapturedFrame::kUnknownDataSize) { 930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org *size = data_size; 960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////// 1000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Implementation of class VideoCapturer 1010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org///////////////////////////////////////////////////////////////////// 1027587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgVideoCapturer::VideoCapturer() 1032a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org : thread_(rtc::Thread::Current()), 1047587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org adapt_frame_drops_data_(kMaxAccumulatorSize), 1057587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org effect_frame_drops_data_(kMaxAccumulatorSize), 1067587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org frame_time_data_(kMaxAccumulatorSize) { 1070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Construct(); 1080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1102a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgVideoCapturer::VideoCapturer(rtc::Thread* thread) 1117587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org : thread_(thread), 1127587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org adapt_frame_drops_data_(kMaxAccumulatorSize), 1137587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org effect_frame_drops_data_(kMaxAccumulatorSize), 1147587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org frame_time_data_(kMaxAccumulatorSize) { 1150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Construct(); 1160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::Construct() { 1190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ClearAspectRatio(); 1200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org enable_camera_list_ = false; 1212007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org square_pixel_aspect_ratio_ = false; 1220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org capture_state_ = CS_STOPPED; 1230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured); 1240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org scaled_width_ = 0; 1250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org scaled_height_ = 0; 126952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org screencast_max_pixels_ = 0; 1270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org muted_ = false; 1280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org black_frame_count_down_ = kNumBlackFramesOnMute; 129e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org enable_video_adapter_ = true; 1307587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org adapt_frame_drops_ = 0; 1317587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org effect_frame_drops_ = 0; 1327587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org previous_frame_time_ = 0.0; 1333541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org#ifdef HAVE_WEBRTC_VIDEO 1343541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org // There are lots of video capturers out there that don't call 1353541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org // set_frame_factory. We can either go change all of them, or we 1363541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org // can set this default. 1373541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org // TODO(pthatcher): Remove this hack and require the frame factory 1383541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org // to be passed in the constructor. 1393541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org set_frame_factory(new WebRtcVideoFrameFactory()); 1403541181607ffe656d8db759a6095864d9f72248dbuildbot@webrtc.org#endif 1410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgconst std::vector<VideoFormat>* VideoCapturer::GetSupportedFormats() const { 1440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return &filtered_supported_formats_; 1450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::StartCapturing(const VideoFormat& capture_format) { 1487587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org previous_frame_time_ = frame_length_time_reporter_.TimerNow(); 1490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org CaptureState result = Start(capture_format); 1500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const bool success = (result == CS_RUNNING) || (result == CS_STARTING); 1510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!success) { 1520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (result == CS_RUNNING) { 1550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetCaptureState(result); 1560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::UpdateAspectRatio(int ratio_w, int ratio_h) { 1610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ratio_w == 0 || ratio_h == 0) { 1620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "UpdateAspectRatio ignored invalid ratio: " 1630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << ratio_w << "x" << ratio_h; 1640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 1650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ratio_w_ = ratio_w; 1670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ratio_h_ = ratio_h; 1680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::ClearAspectRatio() { 1710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ratio_w_ = 0; 1720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ratio_h_ = 0; 1730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 1740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 1750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Override this to have more control of how your device is started/stopped. 1760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::Pause(bool pause) { 1770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (pause) { 1780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (capture_state() == CS_PAUSED) { 1790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 1800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool is_running = capture_state() == CS_STARTING || 1820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org capture_state() == CS_RUNNING; 1830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!is_running) { 1840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Cannot pause a stopped camera."; 1850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 1870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Pausing a camera."; 1882a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<VideoFormat> capture_format_when_paused( 1890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org capture_format_ ? new VideoFormat(*capture_format_) : NULL); 1900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Stop(); 1910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetCaptureState(CS_PAUSED); 1920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // If you override this function be sure to restore the capture format 1930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // after calling Stop(). 1940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SetCaptureFormat(capture_format_when_paused.get()); 1950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { // Unpause. 1960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (capture_state() != CS_PAUSED) { 1970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Cannot unpause a camera that hasn't been paused."; 1980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 1990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!capture_format_) { 2010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Missing capture_format_, cannot unpause a camera."; 2020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (muted_) { 2050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_WARNING) << "Camera cannot be unpaused while muted."; 2060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << "Unpausing a camera."; 2090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!Start(*capture_format_)) { 2100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Camera failed to start when unpausing."; 2110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::Restart(const VideoFormat& capture_format) { 2180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!IsRunning()) { 2190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return StartCapturing(capture_format); 2200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (GetCaptureFormat() != NULL && *GetCaptureFormat() == capture_format) { 2230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The reqested format is the same; nothing to do. 2240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Stop(); 2280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return StartCapturing(capture_format); 2290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::MuteToBlackThenPause(bool muted) { 2320e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (muted == IsMuted()) { 2330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << (muted ? "Muting" : "Unmuting") << " this video capturer."; 2370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org muted_ = muted; // Do this before calling Pause(). 2380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (muted) { 2390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Reset black frame count down. 2400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org black_frame_count_down_ = kNumBlackFramesOnMute; 2410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Following frames will be overritten with black, then the camera will be 2420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // paused. 2430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Start the camera. 2460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org thread_->Clear(this, MSG_DO_PAUSE); 2470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return Pause(false); 2480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::SetSupportedFormats( 2510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<VideoFormat>& formats) { 2520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org supported_formats_ = formats; 2530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateFilteredSupportedFormats(); 2540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::GetBestCaptureFormat(const VideoFormat& format, 2570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoFormat* best_format) { 2580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(fbarchard): Directly support max_format. 2590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateFilteredSupportedFormats(); 2600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const std::vector<VideoFormat>* supported_formats = GetSupportedFormats(); 2610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (supported_formats->empty()) { 2630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << " Capture Requested " << format.ToString(); 2660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 best_distance = kMaxDistance; 2670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<VideoFormat>::const_iterator best = supported_formats->end(); 2680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<VideoFormat>::const_iterator i; 2690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (i = supported_formats->begin(); i != supported_formats->end(); ++i) { 2700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 distance = GetFormatDistance(format, *i); 2710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(fbarchard): Reduce to LS_VERBOSE if/when camera capture is 2720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // relatively bug free. 2730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << " Supported " << i->ToString() << " distance " << distance; 2740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (distance < best_distance) { 2750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org best_distance = distance; 2760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org best = i; 2770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (supported_formats->end() == best) { 2800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << " No acceptable camera format found"; 2810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 2820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (best_format) { 2850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org best_format->width = best->width; 2860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org best_format->height = best->height; 2870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org best_format->fourcc = best->fourcc; 288f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org best_format->interval = best->interval; 2890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_INFO) << " Best " << best_format->ToString() << " Interval " 2900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << best_format->interval << " distance " << best_distance; 2910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 2920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 2930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 2940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 2950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::AddVideoProcessor(VideoProcessor* video_processor) { 2962a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::CritScope cs(&crit_); 2970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(std::find(video_processors_.begin(), video_processors_.end(), 2980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_processor) == video_processors_.end()); 2990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_processors_.push_back(video_processor); 3000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::RemoveVideoProcessor(VideoProcessor* video_processor) { 3032a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::CritScope cs(&crit_); 3040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org VideoProcessors::iterator found = std::find( 3050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_processors_.begin(), video_processors_.end(), video_processor); 3060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (found == video_processors_.end()) { 3070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 3080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org video_processors_.erase(found); 3100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 3110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::ConstrainSupportedFormats(const VideoFormat& max_format) { 3140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org max_format_.reset(new VideoFormat(max_format)); 3150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_VERBOSE) << " ConstrainSupportedFormats " << max_format.ToString(); 3160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org UpdateFilteredSupportedFormats(); 3170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgstd::string VideoCapturer::ToString(const CapturedFrame* captured_frame) const { 3200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::string fourcc_name = GetFourccName(captured_frame->fourcc) + " "; 3210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (std::string::const_iterator i = fourcc_name.begin(); 3220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org i < fourcc_name.end(); ++i) { 3230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Test character is printable; Avoid isprint() which asserts on negatives. 3240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (*i < 32 || *i >= 127) { 3250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org fourcc_name = ""; 3260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 3270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::ostringstream ss; 3310e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ss << fourcc_name << captured_frame->width << "x" << captured_frame->height 332f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org << "x" << VideoFormat::IntervalToFpsFloat(captured_frame->elapsed_time); 3330e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return ss.str(); 3340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 3350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3367587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgvoid VideoCapturer::GetStats(VariableInfo<int>* adapt_drops_stats, 3377587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org VariableInfo<int>* effect_drops_stats, 3383657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org VariableInfo<double>* frame_time_stats, 3393657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org VideoFormat* last_captured_frame_format) { 3402a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::CritScope cs(&frame_stats_crit_); 3417587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org GetVariableSnapshot(adapt_frame_drops_data_, adapt_drops_stats); 3427587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org GetVariableSnapshot(effect_frame_drops_data_, effect_drops_stats); 3437587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org GetVariableSnapshot(frame_time_data_, frame_time_stats); 3443657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org *last_captured_frame_format = last_captured_frame_format_; 3457587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 3467587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org adapt_frame_drops_data_.Reset(); 3477587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org effect_frame_drops_data_.Reset(); 3487587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org frame_time_data_.Reset(); 3497587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org} 3507587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 3510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::OnFrameCaptured(VideoCapturer*, 3520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const CapturedFrame* captured_frame) { 3530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (muted_) { 3540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (black_frame_count_down_ == 0) { 3550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org thread_->Post(this, MSG_DO_PAUSE, NULL); 3560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 3570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org --black_frame_count_down_; 3580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3610e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (SignalVideoFrame.is_empty()) { 3620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 3630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 3640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#if !defined(DISABLE_YUV) 3650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (IsScreencast()) { 3660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int scaled_width, scaled_height; 367952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org if (screencast_max_pixels_ > 0) { 368952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org ComputeScaleMaxPixels(captured_frame->width, captured_frame->height, 369952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org screencast_max_pixels_, &scaled_width, &scaled_height); 370952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } else { 371952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org int desired_screencast_fps = capture_format_.get() ? 372952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org VideoFormat::IntervalToFps(capture_format_->interval) : 373952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org kDefaultScreencastFps; 374952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org ComputeScale(captured_frame->width, captured_frame->height, 375952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org desired_screencast_fps, &scaled_width, &scaled_height); 376952740e2dafeb2599d21778eb2e1b8f1c8f2bb07wu@webrtc.org } 3770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 3780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (FOURCC_ARGB == captured_frame->fourcc && 379a487db2aeda23ade81f0b2e5fd4d50f874d06a9csergeyu@chromium.org (scaled_width != captured_frame->width || 3802007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_height != captured_frame->height)) { 3812007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org if (scaled_width != scaled_width_ || scaled_height != scaled_height_) { 3822007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org LOG(LS_INFO) << "Scaling Screencast from " 3832007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << captured_frame->width << "x" 3842007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << captured_frame->height << " to " 3852007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << scaled_width << "x" << scaled_height; 3862007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_width_ = scaled_width; 3872007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_height_ = scaled_height; 3882007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org } 3892007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org CapturedFrame* modified_frame = 3902007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org const_cast<CapturedFrame*>(captured_frame); 3910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Compute new width such that width * height is less than maximum but 3920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // maintains original captured frame aspect ratio. 3930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Round down width to multiple of 4 so odd width won't round up beyond 3940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // maximum, and so chroma channel is even width to simplify spatial 3950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // resampling. 3960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org libyuv::ARGBScale(reinterpret_cast<const uint8*>(captured_frame->data), 3970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org captured_frame->width * 4, captured_frame->width, 3980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org captured_frame->height, 3992007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org reinterpret_cast<uint8*>(modified_frame->data), 4000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org scaled_width * 4, scaled_width, scaled_height, 4010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org libyuv::kFilterBilinear); 4022007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->width = scaled_width; 4032007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->height = scaled_height; 4042007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->data_size = scaled_width * 4 * scaled_height; 4052007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org } 4062007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org } 4072007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org 4082007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org const int kYuy2Bpp = 2; 4092007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org const int kArgbBpp = 4; 4102007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // TODO(fbarchard): Make a helper function to adjust pixels to square. 4112007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // TODO(fbarchard): Hook up experiment to scaling. 4122007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // TODO(fbarchard): Avoid scale and convert if muted. 4132007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // Temporary buffer is scoped here so it will persist until i420_frame.Init() 4142007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // makes a copy of the frame, converting to I420. 4152a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<uint8[]> temp_buffer; 4162007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // YUY2 can be scaled vertically using an ARGB scaler. Aspect ratio is only 4172007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // a problem on OSX. OSX always converts webcams to YUY2 or UYVY. 4182007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org bool can_scale = 4192007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org FOURCC_YUY2 == CanonicalFourCC(captured_frame->fourcc) || 4202007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org FOURCC_UYVY == CanonicalFourCC(captured_frame->fourcc); 4212007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org 4222007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // If pixels are not square, optionally use vertical scaling to make them 4232007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // square. Square pixels simplify the rest of the pipeline, including 4242007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // effects and rendering. 4252007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org if (can_scale && square_pixel_aspect_ratio_ && 4262007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org captured_frame->pixel_width != captured_frame->pixel_height) { 4272007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org int scaled_width, scaled_height; 4282007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // modified_frame points to the captured_frame but with const casted away 4292007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // so it can be modified. 4302007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org CapturedFrame* modified_frame = const_cast<CapturedFrame*>(captured_frame); 4312007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // Compute the frame size that makes pixels square pixel aspect ratio. 4322007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org ComputeScaleToSquarePixels(captured_frame->width, captured_frame->height, 4332007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org captured_frame->pixel_width, 4342007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org captured_frame->pixel_height, 4352007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org &scaled_width, &scaled_height); 4362007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org 4372007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org if (scaled_width != scaled_width_ || scaled_height != scaled_height_) { 4382007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org LOG(LS_INFO) << "Scaling WebCam from " 4392007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << captured_frame->width << "x" 4402007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << captured_frame->height << " to " 4412007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << scaled_width << "x" << scaled_height 4422007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << " for PAR " 4432007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << captured_frame->pixel_width << "x" 4442007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org << captured_frame->pixel_height; 4452007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_width_ = scaled_width; 4462007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_height_ = scaled_height; 4470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4482007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org const int modified_frame_size = scaled_width * scaled_height * kYuy2Bpp; 4492007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org uint8* temp_buffer_data; 4502007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // Pixels are wide and short; Increasing height. Requires temporary buffer. 4512007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org if (scaled_height > captured_frame->height) { 4522007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org temp_buffer.reset(new uint8[modified_frame_size]); 4532007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org temp_buffer_data = temp_buffer.get(); 4542007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org } else { 4552007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // Pixels are narrow and tall; Decreasing height. Scale will be done 4562007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // in place. 4572007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org temp_buffer_data = reinterpret_cast<uint8*>(captured_frame->data); 4582007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org } 4592007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org 4602007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // Use ARGBScaler to vertically scale the YUY2 image, adjusting for 16 bpp. 4612007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org libyuv::ARGBScale(reinterpret_cast<const uint8*>(captured_frame->data), 4622007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org captured_frame->width * kYuy2Bpp, // Stride for YUY2. 4632007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org captured_frame->width * kYuy2Bpp / kArgbBpp, // Width. 4642007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org abs(captured_frame->height), // Height. 4652007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org temp_buffer_data, 4662007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_width * kYuy2Bpp, // Stride for YUY2. 4672007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org scaled_width * kYuy2Bpp / kArgbBpp, // Width. 4682007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org abs(scaled_height), // New height. 4692007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org libyuv::kFilterBilinear); 4702007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->width = scaled_width; 4712007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->height = scaled_height; 4722007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->pixel_width = 1; 4732007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->pixel_height = 1; 4742007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->data_size = modified_frame_size; 4752007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org modified_frame->data = temp_buffer_data; 4760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 4770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif // !DISABLE_YUV 4782007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org 4792007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // Size to crop captured frame to. This adjusts the captured frames 4802007187dab65bb5d6f602355216534d6dd4ceaf2mallinath@webrtc.org // aspect ratio to match the final view aspect ratio, considering pixel 4810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // aspect ratio and rotation. The final size may be scaled down by video 4820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // adapter to better match ratio_w_ x ratio_h_. 4830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Note that abs() of frame height is passed in, because source may be 4840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // inverted, but output will be positive. 4850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int desired_width = captured_frame->width; 4860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int desired_height = captured_frame->height; 4870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 4880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(fbarchard): Improve logic to pad or crop. 4890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // MJPG can crop vertically, but not horizontally. This logic disables crop. 4900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Alternatively we could pad the image with black, or implement a 2 step 4910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // crop. 4920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool can_crop = true; 4930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (captured_frame->fourcc == FOURCC_MJPG) { 4940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org float cam_aspect = static_cast<float>(captured_frame->width) / 4950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<float>(captured_frame->height); 4960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org float view_aspect = static_cast<float>(ratio_w_) / 4970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<float>(ratio_h_); 4980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org can_crop = cam_aspect <= view_aspect; 4990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (can_crop && !IsScreencast()) { 5010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(ronghuawu): The capturer should always produce the native 5020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // resolution and the cropping should be done in downstream code. 5030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ComputeCrop(ratio_w_, ratio_h_, captured_frame->width, 5040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org abs(captured_frame->height), captured_frame->pixel_width, 5050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org captured_frame->pixel_height, captured_frame->rotation, 5060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org &desired_width, &desired_height); 5070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5092a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org if (!frame_factory_) { 5102a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org LOG(LS_ERROR) << "No video frame factory."; 5112a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org return; 5122a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org } 5132a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org 5142a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org rtc::scoped_ptr<VideoFrame> i420_frame( 5152a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org frame_factory_->CreateAliasedFrame( 5162a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org captured_frame, desired_width, desired_height)); 5172a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org if (!i420_frame) { 5180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(fbarchard): LOG more information about captured frame attributes. 5190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org LOG(LS_ERROR) << "Couldn't convert to I420! " 5200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << "From " << ToString(captured_frame) << " To " 5210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org << desired_width << " x " << desired_height; 5220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 5230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 524b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 5252a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org VideoFrame* adapted_frame = i420_frame.get(); 526e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org if (enable_video_adapter_ && !IsScreencast()) { 527b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org VideoFrame* out_frame = NULL; 528e8b0cc3bf706964d657fdb25f0c5791c5a7aa3d7henrike@webrtc.org video_adapter_.AdaptFrame(adapted_frame, &out_frame); 529b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!out_frame) { 5307587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org // VideoAdapter dropped the frame. 5317587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org ++adapt_frame_drops_; 5327587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org return; 533b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 534b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org adapted_frame = out_frame; 535b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org } 536b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org 537b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org if (!muted_ && !ApplyProcessors(adapted_frame)) { 5380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Processor dropped the frame. 5397587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org ++effect_frame_drops_; 5400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 5410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (muted_) { 5432a0553609b5b6d1d4dce0366b334dc9ef8aa4d65buildbot@webrtc.org // TODO(pthatcher): Use frame_factory_->CreateBlackFrame() instead. 544b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org adapted_frame->SetToBlack(); 5450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 546b881d27f23e9a8f52dc6a60fc66ebd75f9c2f15cmallinath@webrtc.org SignalVideoFrame(this, adapted_frame); 5477587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 5483657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org UpdateStats(captured_frame); 5490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::SetCaptureState(CaptureState state) { 5520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (state == capture_state_) { 5530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Don't trigger a state changed callback if the state hasn't changed. 5540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 5550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org StateChangeParams* state_params = new StateChangeParams(state); 5570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org capture_state_ = state; 5580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org thread_->Post(this, MSG_STATE_CHANGE, state_params); 5590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5600e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5612a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.orgvoid VideoCapturer::OnMessage(rtc::Message* message) { 5620e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org switch (message->message_id) { 5630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case MSG_STATE_CHANGE: { 5642a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::scoped_ptr<StateChangeParams> p( 5650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static_cast<StateChangeParams*>(message->pdata)); 5660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org SignalStateChange(this, p->data()); 5670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 5680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case MSG_DO_PAUSE: { 5700e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Pause(true); 5710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 5720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org case MSG_DO_UNPAUSE: { 5740e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org Pause(false); 5750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 5760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org default: { 5780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ASSERT(false); 5790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 5810e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 5820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Get the distance between the supported and desired formats. 5840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// Prioritization is done according to this algorithm: 5850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 1) Width closeness. If not same, we prefer wider. 5860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 2) Height closeness. If not same, we prefer higher. 5870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 3) Framerate closeness. If not same, we prefer faster. 5880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// 4) Compression. If desired format has a specific fourcc, we need exact match; 5890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org// otherwise, we use preference. 5900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgint64 VideoCapturer::GetFormatDistance(const VideoFormat& desired, 5910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org const VideoFormat& supported) { 5920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 distance = kMaxDistance; 5930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 5940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Check fourcc. 5950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org uint32 supported_fourcc = CanonicalFourCC(supported.fourcc); 5960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 delta_fourcc = kMaxDistance; 5970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (FOURCC_ANY == desired.fourcc) { 5980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Any fourcc is OK for the desired. Use preference to find best fourcc. 5990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<uint32> preferred_fourccs; 6000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!GetPreferredFourccs(&preferred_fourccs)) { 6010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return distance; 6020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (size_t i = 0; i < preferred_fourccs.size(); ++i) { 6050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (supported_fourcc == CanonicalFourCC(preferred_fourccs[i])) { 6060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delta_fourcc = i; 6070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#ifdef LINUX 6080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // For HD avoid YU12 which is a software conversion and has 2 bugs 6090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // b/7326348 b/6960899. Reenable when fixed. 6100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (supported.height >= 720 && (supported_fourcc == FOURCC_YU12 || 6110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org supported_fourcc == FOURCC_YV12)) { 6120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delta_fourcc += kYU12Penalty; 6130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org#endif 6150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org break; 6160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else if (supported_fourcc == CanonicalFourCC(desired.fourcc)) { 6190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delta_fourcc = 0; // Need exact match. 6200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6220e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (kMaxDistance == delta_fourcc) { 6230e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Failed to match fourcc. 6240e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return distance; 6250e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6260e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6270e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Check resolution and fps. 6280e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int desired_width = desired.width; 6290e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int desired_height = desired.height; 6300e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 delta_w = supported.width - desired_width; 631f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org float supported_fps = VideoFormat::IntervalToFpsFloat(supported.interval); 632f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org float delta_fps = 633f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org supported_fps - VideoFormat::IntervalToFpsFloat(desired.interval); 6340e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Check height of supported height compared to height we would like it to be. 6350e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 aspect_h = 6360e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org desired_width ? supported.width * desired_height / desired_width 6370e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org : desired_height; 6380e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org int64 delta_h = supported.height - aspect_h; 6390e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6400e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org distance = 0; 6410e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Set high penalty if the supported format is lower than the desired format. 6420e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // 3x means we would prefer down to down to 3/4, than up to double. 6430e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // But we'd prefer up to double than down to 1/2. This is conservative, 6440e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // strongly avoiding going down in resolution, similar to 6450e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // the old method, but not completely ruling it out in extreme situations. 6460e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // It also ignores framerate, which is often very low at high resolutions. 6470e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // TODO(fbarchard): Improve logic to use weighted factors. 6480e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org static const int kDownPenalty = -3; 6490e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (delta_w < 0) { 6500e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delta_w = delta_w * kDownPenalty; 6510e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6520e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (delta_h < 0) { 6530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delta_h = delta_h * kDownPenalty; 6540e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6550e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Require camera fps to be at least 80% of what is requested if resolution 6560e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // matches. 6570e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // Require camera fps to be at least 96% of what is requested, or higher, 6580e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // if resolution differs. 96% allows for slight variations in fps. e.g. 29.97 6590e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (delta_fps < 0) { 660f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org float min_desirable_fps = delta_w ? 661f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org VideoFormat::IntervalToFpsFloat(desired.interval) * 28.f / 30.f : 662f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org VideoFormat::IntervalToFpsFloat(desired.interval) * 23.f / 30.f; 6630e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org delta_fps = -delta_fps; 6640e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (supported_fps < min_desirable_fps) { 6650e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org distance |= static_cast<int64>(1) << 62; 6660e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 6670e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org distance |= static_cast<int64>(1) << 15; 6680e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6690e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 670f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org int64 idelta_fps = static_cast<int>(delta_fps); 6710e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6720e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // 12 bits for width and height and 8 bits for fps and fourcc. 6730e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org distance |= 674f32dd31e14521d7f845e7776af6d44d411573370sergeyu@chromium.org (delta_w << 28) | (delta_h << 16) | (idelta_fps << 8) | delta_fourcc; 6750e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6760e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return distance; 6770e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6780e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6790e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::ApplyProcessors(VideoFrame* video_frame) { 6800e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org bool drop_frame = false; 6812a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::CritScope cs(&crit_); 6820e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org for (VideoProcessors::iterator iter = video_processors_.begin(); 6830e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org iter != video_processors_.end(); ++iter) { 6840e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org (*iter)->OnFrame(kDummyVideoSsrc, video_frame, &drop_frame); 6850e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (drop_frame) { 6860e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 6870e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6880e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6890e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return true; 6900e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 6910e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 6920e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgvoid VideoCapturer::UpdateFilteredSupportedFormats() { 6930e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filtered_supported_formats_.clear(); 6940e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filtered_supported_formats_ = supported_formats_; 6950e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!max_format_) { 6960e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return; 6970e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 6980e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org std::vector<VideoFormat>::iterator iter = filtered_supported_formats_.begin(); 6990e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org while (iter != filtered_supported_formats_.end()) { 7000e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (ShouldFilterFormat(*iter)) { 7010e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org iter = filtered_supported_formats_.erase(iter); 7020e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } else { 7030e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org ++iter; 7040e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7050e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7060e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (filtered_supported_formats_.empty()) { 7070e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // The device only captures at resolutions higher than |max_format_| this 7080e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // indicates that |max_format_| should be ignored as it is better to capture 7090e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org // at too high a resolution than to not capture at all. 7100e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org filtered_supported_formats_ = supported_formats_; 7110e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7120e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7130e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7140e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.orgbool VideoCapturer::ShouldFilterFormat(const VideoFormat& format) const { 7150e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org if (!enable_camera_list_) { 7160e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return false; 7170e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org } 7180e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org return format.width > max_format_->width || 7190e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org format.height > max_format_->height; 7200e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} 7210e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org 7223657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.orgvoid VideoCapturer::UpdateStats(const CapturedFrame* captured_frame) { 7233657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org // Update stats protected from fetches from different thread. 7242a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org rtc::CritScope cs(&frame_stats_crit_); 7253657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org 7263657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org last_captured_frame_format_.width = captured_frame->width; 7273657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org last_captured_frame_format_.height = captured_frame->height; 7283657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org // TODO(ronghuawu): Useful to report interval as well? 7293657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org last_captured_frame_format_.interval = 0; 7303657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org last_captured_frame_format_.fourcc = captured_frame->fourcc; 7313657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org 7323657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org double time_now = frame_length_time_reporter_.TimerNow(); 7333657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org if (previous_frame_time_ != 0.0) { 7343657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org adapt_frame_drops_data_.AddSample(adapt_frame_drops_); 7353657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org effect_frame_drops_data_.AddSample(effect_frame_drops_); 7363657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org frame_time_data_.AddSample(time_now - previous_frame_time_); 7373657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org } 7383657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org previous_frame_time_ = time_now; 7393657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org effect_frame_drops_ = 0; 7403657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org adapt_frame_drops_ = 0; 7413657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org} 7423657d9107db9ffd3dfbe996b9a3af57e4818efb4buildbot@webrtc.org 7437587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgtemplate<class T> 7447587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.orgvoid VideoCapturer::GetVariableSnapshot( 7452a86ce22ccc387dfa6f8a98ce3eba5c1e6f9e538buildbot@webrtc.org const rtc::RollingAccumulator<T>& data, 7467587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org VariableInfo<T>* stats) { 7477587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org stats->max_val = data.ComputeMax(); 7487587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org stats->mean = data.ComputeMean(); 7497587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org stats->min_val = data.ComputeMin(); 7507587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org stats->variance = data.ComputeVariance(); 7517587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org} 7527587c5e0b2fb5100b52bf271370ee1369ba18690henrike@webrtc.org 7530e118e7129884fbea117e78d6f2068139a414dbhenrike@webrtc.org} // namespace cricket 754