| OLD | NEW |
| 1 /* | 1 /* |
| 2 * libjingle | 2 * libjingle |
| 3 * Copyright 2010 Google Inc. | 3 * Copyright 2010 Google Inc. |
| 4 * | 4 * |
| 5 * Redistribution and use in source and binary forms, with or without | 5 * Redistribution and use in source and binary forms, with or without |
| 6 * modification, are permitted provided that the following conditions are met: | 6 * modification, are permitted provided that the following conditions are met: |
| 7 * | 7 * |
| 8 * 1. Redistributions of source code must retain the above copyright notice, | 8 * 1. Redistributions of source code must retain the above copyright notice, |
| 9 * this list of conditions and the following disclaimer. | 9 * this list of conditions and the following disclaimer. |
| 10 * 2. Redistributions in binary form must reproduce the above copyright notice, | 10 * 2. Redistributions in binary form must reproduce the above copyright notice, |
| (...skipping 15 matching lines...) Expand all Loading... |
| 26 */ | 26 */ |
| 27 | 27 |
| 28 // Implementation file of class VideoCapturer. | 28 // Implementation file of class VideoCapturer. |
| 29 | 29 |
| 30 #include "talk/media/base/videocapturer.h" | 30 #include "talk/media/base/videocapturer.h" |
| 31 | 31 |
| 32 #include <algorithm> | 32 #include <algorithm> |
| 33 | 33 |
| 34 #include "libyuv/scale_argb.h" | 34 #include "libyuv/scale_argb.h" |
| 35 #include "talk/media/base/videoframefactory.h" | 35 #include "talk/media/base/videoframefactory.h" |
| 36 #include "talk/media/base/videoprocessor.h" | |
| 37 #include "webrtc/base/common.h" | 36 #include "webrtc/base/common.h" |
| 38 #include "webrtc/base/logging.h" | 37 #include "webrtc/base/logging.h" |
| 39 #include "webrtc/base/systeminfo.h" | 38 #include "webrtc/base/systeminfo.h" |
| 40 | 39 |
| 41 #if defined(HAVE_WEBRTC_VIDEO) | 40 #if defined(HAVE_WEBRTC_VIDEO) |
| 42 #include "talk/media/webrtc/webrtcvideoframe.h" | 41 #include "talk/media/webrtc/webrtcvideoframe.h" |
| 43 #include "talk/media/webrtc/webrtcvideoframefactory.h" | 42 #include "talk/media/webrtc/webrtcvideoframefactory.h" |
| 44 #endif // HAVE_WEBRTC_VIDEO | 43 #endif // HAVE_WEBRTC_VIDEO |
| 45 | 44 |
| 46 namespace cricket { | 45 namespace cricket { |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 100 ASSERT(rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270); | 99 ASSERT(rotation == 0 || rotation == 90 || rotation == 180 || rotation == 270); |
| 101 return static_cast<webrtc::VideoRotation>(rotation); | 100 return static_cast<webrtc::VideoRotation>(rotation); |
| 102 } | 101 } |
| 103 | 102 |
| 104 ///////////////////////////////////////////////////////////////////// | 103 ///////////////////////////////////////////////////////////////////// |
| 105 // Implementation of class VideoCapturer | 104 // Implementation of class VideoCapturer |
| 106 ///////////////////////////////////////////////////////////////////// | 105 ///////////////////////////////////////////////////////////////////// |
| 107 VideoCapturer::VideoCapturer() | 106 VideoCapturer::VideoCapturer() |
| 108 : thread_(rtc::Thread::Current()), | 107 : thread_(rtc::Thread::Current()), |
| 109 adapt_frame_drops_data_(kMaxAccumulatorSize), | 108 adapt_frame_drops_data_(kMaxAccumulatorSize), |
| 110 effect_frame_drops_data_(kMaxAccumulatorSize), | |
| 111 frame_time_data_(kMaxAccumulatorSize), | 109 frame_time_data_(kMaxAccumulatorSize), |
| 112 apply_rotation_(true) { | 110 apply_rotation_(true) { |
| 113 Construct(); | 111 Construct(); |
| 114 } | 112 } |
| 115 | 113 |
| 116 VideoCapturer::VideoCapturer(rtc::Thread* thread) | 114 VideoCapturer::VideoCapturer(rtc::Thread* thread) |
| 117 : thread_(thread), | 115 : thread_(thread), |
| 118 adapt_frame_drops_data_(kMaxAccumulatorSize), | 116 adapt_frame_drops_data_(kMaxAccumulatorSize), |
| 119 effect_frame_drops_data_(kMaxAccumulatorSize), | |
| 120 frame_time_data_(kMaxAccumulatorSize), | 117 frame_time_data_(kMaxAccumulatorSize), |
| 121 apply_rotation_(true) { | 118 apply_rotation_(true) { |
| 122 Construct(); | 119 Construct(); |
| 123 } | 120 } |
| 124 | 121 |
| 125 void VideoCapturer::Construct() { | 122 void VideoCapturer::Construct() { |
| 126 ClearAspectRatio(); | 123 ClearAspectRatio(); |
| 127 enable_camera_list_ = false; | 124 enable_camera_list_ = false; |
| 128 square_pixel_aspect_ratio_ = false; | 125 square_pixel_aspect_ratio_ = false; |
| 129 capture_state_ = CS_STOPPED; | 126 capture_state_ = CS_STOPPED; |
| 130 SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured); | 127 SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured); |
| 131 scaled_width_ = 0; | 128 scaled_width_ = 0; |
| 132 scaled_height_ = 0; | 129 scaled_height_ = 0; |
| 133 screencast_max_pixels_ = 0; | 130 screencast_max_pixels_ = 0; |
| 134 muted_ = false; | 131 muted_ = false; |
| 135 black_frame_count_down_ = kNumBlackFramesOnMute; | 132 black_frame_count_down_ = kNumBlackFramesOnMute; |
| 136 enable_video_adapter_ = true; | 133 enable_video_adapter_ = true; |
| 137 adapt_frame_drops_ = 0; | 134 adapt_frame_drops_ = 0; |
| 138 effect_frame_drops_ = 0; | |
| 139 previous_frame_time_ = 0.0; | 135 previous_frame_time_ = 0.0; |
| 140 #ifdef HAVE_WEBRTC_VIDEO | 136 #ifdef HAVE_WEBRTC_VIDEO |
| 141 // There are lots of video capturers out there that don't call | 137 // There are lots of video capturers out there that don't call |
| 142 // set_frame_factory. We can either go change all of them, or we | 138 // set_frame_factory. We can either go change all of them, or we |
| 143 // can set this default. | 139 // can set this default. |
| 144 // TODO(pthatcher): Remove this hack and require the frame factory | 140 // TODO(pthatcher): Remove this hack and require the frame factory |
| 145 // to be passed in the constructor. | 141 // to be passed in the constructor. |
| 146 set_frame_factory(new WebRtcVideoFrameFactory()); | 142 set_frame_factory(new WebRtcVideoFrameFactory()); |
| 147 #endif | 143 #endif |
| 148 } | 144 } |
| (...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 302 best_format->width = best->width; | 298 best_format->width = best->width; |
| 303 best_format->height = best->height; | 299 best_format->height = best->height; |
| 304 best_format->fourcc = best->fourcc; | 300 best_format->fourcc = best->fourcc; |
| 305 best_format->interval = best->interval; | 301 best_format->interval = best->interval; |
| 306 LOG(LS_INFO) << " Best " << best_format->ToString() << " Interval " | 302 LOG(LS_INFO) << " Best " << best_format->ToString() << " Interval " |
| 307 << best_format->interval << " distance " << best_distance; | 303 << best_format->interval << " distance " << best_distance; |
| 308 } | 304 } |
| 309 return true; | 305 return true; |
| 310 } | 306 } |
| 311 | 307 |
| 312 void VideoCapturer::AddVideoProcessor(VideoProcessor* video_processor) { | |
| 313 rtc::CritScope cs(&crit_); | |
| 314 ASSERT(std::find(video_processors_.begin(), video_processors_.end(), | |
| 315 video_processor) == video_processors_.end()); | |
| 316 video_processors_.push_back(video_processor); | |
| 317 } | |
| 318 | |
| 319 bool VideoCapturer::RemoveVideoProcessor(VideoProcessor* video_processor) { | |
| 320 rtc::CritScope cs(&crit_); | |
| 321 VideoProcessors::iterator found = std::find( | |
| 322 video_processors_.begin(), video_processors_.end(), video_processor); | |
| 323 if (found == video_processors_.end()) { | |
| 324 return false; | |
| 325 } | |
| 326 video_processors_.erase(found); | |
| 327 return true; | |
| 328 } | |
| 329 | |
| 330 void VideoCapturer::ConstrainSupportedFormats(const VideoFormat& max_format) { | 308 void VideoCapturer::ConstrainSupportedFormats(const VideoFormat& max_format) { |
| 331 max_format_.reset(new VideoFormat(max_format)); | 309 max_format_.reset(new VideoFormat(max_format)); |
| 332 LOG(LS_VERBOSE) << " ConstrainSupportedFormats " << max_format.ToString(); | 310 LOG(LS_VERBOSE) << " ConstrainSupportedFormats " << max_format.ToString(); |
| 333 UpdateFilteredSupportedFormats(); | 311 UpdateFilteredSupportedFormats(); |
| 334 } | 312 } |
| 335 | 313 |
| 336 std::string VideoCapturer::ToString(const CapturedFrame* captured_frame) const { | 314 std::string VideoCapturer::ToString(const CapturedFrame* captured_frame) const { |
| 337 std::string fourcc_name = GetFourccName(captured_frame->fourcc) + " "; | 315 std::string fourcc_name = GetFourccName(captured_frame->fourcc) + " "; |
| 338 for (std::string::const_iterator i = fourcc_name.begin(); | 316 for (std::string::const_iterator i = fourcc_name.begin(); |
| 339 i < fourcc_name.end(); ++i) { | 317 i < fourcc_name.end(); ++i) { |
| (...skipping 16 matching lines...) Expand all Loading... |
| 356 frame_factory->SetApplyRotation(apply_rotation_); | 334 frame_factory->SetApplyRotation(apply_rotation_); |
| 357 } | 335 } |
| 358 } | 336 } |
| 359 | 337 |
| 360 void VideoCapturer::GetStats(VariableInfo<int>* adapt_drops_stats, | 338 void VideoCapturer::GetStats(VariableInfo<int>* adapt_drops_stats, |
| 361 VariableInfo<int>* effect_drops_stats, | 339 VariableInfo<int>* effect_drops_stats, |
| 362 VariableInfo<double>* frame_time_stats, | 340 VariableInfo<double>* frame_time_stats, |
| 363 VideoFormat* last_captured_frame_format) { | 341 VideoFormat* last_captured_frame_format) { |
| 364 rtc::CritScope cs(&frame_stats_crit_); | 342 rtc::CritScope cs(&frame_stats_crit_); |
| 365 GetVariableSnapshot(adapt_frame_drops_data_, adapt_drops_stats); | 343 GetVariableSnapshot(adapt_frame_drops_data_, adapt_drops_stats); |
| 366 GetVariableSnapshot(effect_frame_drops_data_, effect_drops_stats); | |
| 367 GetVariableSnapshot(frame_time_data_, frame_time_stats); | 344 GetVariableSnapshot(frame_time_data_, frame_time_stats); |
| 368 *last_captured_frame_format = last_captured_frame_format_; | 345 *last_captured_frame_format = last_captured_frame_format_; |
| 369 | 346 |
| 370 adapt_frame_drops_data_.Reset(); | 347 adapt_frame_drops_data_.Reset(); |
| 371 effect_frame_drops_data_.Reset(); | |
| 372 frame_time_data_.Reset(); | 348 frame_time_data_.Reset(); |
| 373 } | 349 } |
| 374 | 350 |
| 375 void VideoCapturer::OnFrameCaptured(VideoCapturer*, | 351 void VideoCapturer::OnFrameCaptured(VideoCapturer*, |
| 376 const CapturedFrame* captured_frame) { | 352 const CapturedFrame* captured_frame) { |
| 377 if (muted_) { | 353 if (muted_) { |
| 378 if (black_frame_count_down_ == 0) { | 354 if (black_frame_count_down_ == 0) { |
| 379 thread_->Post(this, MSG_DO_PAUSE, NULL); | 355 thread_->Post(this, MSG_DO_PAUSE, NULL); |
| 380 } else { | 356 } else { |
| 381 --black_frame_count_down_; | 357 --black_frame_count_down_; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 560 adapted_width, adapted_height)); | 536 adapted_width, adapted_height)); |
| 561 | 537 |
| 562 if (!adapted_frame) { | 538 if (!adapted_frame) { |
| 563 // TODO(fbarchard): LOG more information about captured frame attributes. | 539 // TODO(fbarchard): LOG more information about captured frame attributes. |
| 564 LOG(LS_ERROR) << "Couldn't convert to I420! " | 540 LOG(LS_ERROR) << "Couldn't convert to I420! " |
| 565 << "From " << ToString(captured_frame) << " To " | 541 << "From " << ToString(captured_frame) << " To " |
| 566 << cropped_width << " x " << cropped_height; | 542 << cropped_width << " x " << cropped_height; |
| 567 return; | 543 return; |
| 568 } | 544 } |
| 569 | 545 |
| 570 if (!muted_ && !ApplyProcessors(adapted_frame.get())) { | |
| 571 // Processor dropped the frame. | |
| 572 ++effect_frame_drops_; | |
| 573 return; | |
| 574 } | |
| 575 if (muted_) { | 546 if (muted_) { |
| 576 // TODO(pthatcher): Use frame_factory_->CreateBlackFrame() instead. | 547 // TODO(pthatcher): Use frame_factory_->CreateBlackFrame() instead. |
| 577 adapted_frame->SetToBlack(); | 548 adapted_frame->SetToBlack(); |
| 578 } | 549 } |
| 579 SignalVideoFrame(this, adapted_frame.get()); | 550 SignalVideoFrame(this, adapted_frame.get()); |
| 580 | 551 |
| 581 UpdateStats(captured_frame); | 552 UpdateStats(captured_frame); |
| 582 } | 553 } |
| 583 | 554 |
| 584 void VideoCapturer::SetCaptureState(CaptureState state) { | 555 void VideoCapturer::SetCaptureState(CaptureState state) { |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 702 } | 673 } |
| 703 int64 idelta_fps = static_cast<int>(delta_fps); | 674 int64 idelta_fps = static_cast<int>(delta_fps); |
| 704 | 675 |
| 705 // 12 bits for width and height and 8 bits for fps and fourcc. | 676 // 12 bits for width and height and 8 bits for fps and fourcc. |
| 706 distance |= | 677 distance |= |
| 707 (delta_w << 28) | (delta_h << 16) | (idelta_fps << 8) | delta_fourcc; | 678 (delta_w << 28) | (delta_h << 16) | (idelta_fps << 8) | delta_fourcc; |
| 708 | 679 |
| 709 return distance; | 680 return distance; |
| 710 } | 681 } |
| 711 | 682 |
| 712 bool VideoCapturer::ApplyProcessors(VideoFrame* video_frame) { | |
| 713 bool drop_frame = false; | |
| 714 rtc::CritScope cs(&crit_); | |
| 715 for (VideoProcessors::iterator iter = video_processors_.begin(); | |
| 716 iter != video_processors_.end(); ++iter) { | |
| 717 (*iter)->OnFrame(kDummyVideoSsrc, video_frame, &drop_frame); | |
| 718 if (drop_frame) { | |
| 719 return false; | |
| 720 } | |
| 721 } | |
| 722 return true; | |
| 723 } | |
| 724 | |
| 725 void VideoCapturer::UpdateFilteredSupportedFormats() { | 683 void VideoCapturer::UpdateFilteredSupportedFormats() { |
| 726 filtered_supported_formats_.clear(); | 684 filtered_supported_formats_.clear(); |
| 727 filtered_supported_formats_ = supported_formats_; | 685 filtered_supported_formats_ = supported_formats_; |
| 728 if (!max_format_) { | 686 if (!max_format_) { |
| 729 return; | 687 return; |
| 730 } | 688 } |
| 731 std::vector<VideoFormat>::iterator iter = filtered_supported_formats_.begin(); | 689 std::vector<VideoFormat>::iterator iter = filtered_supported_formats_.begin(); |
| 732 while (iter != filtered_supported_formats_.end()) { | 690 while (iter != filtered_supported_formats_.end()) { |
| 733 if (ShouldFilterFormat(*iter)) { | 691 if (ShouldFilterFormat(*iter)) { |
| 734 iter = filtered_supported_formats_.erase(iter); | 692 iter = filtered_supported_formats_.erase(iter); |
| (...skipping 23 matching lines...) Expand all Loading... |
| 758 | 716 |
| 759 last_captured_frame_format_.width = captured_frame->width; | 717 last_captured_frame_format_.width = captured_frame->width; |
| 760 last_captured_frame_format_.height = captured_frame->height; | 718 last_captured_frame_format_.height = captured_frame->height; |
| 761 // TODO(ronghuawu): Useful to report interval as well? | 719 // TODO(ronghuawu): Useful to report interval as well? |
| 762 last_captured_frame_format_.interval = 0; | 720 last_captured_frame_format_.interval = 0; |
| 763 last_captured_frame_format_.fourcc = captured_frame->fourcc; | 721 last_captured_frame_format_.fourcc = captured_frame->fourcc; |
| 764 | 722 |
| 765 double time_now = frame_length_time_reporter_.TimerNow(); | 723 double time_now = frame_length_time_reporter_.TimerNow(); |
| 766 if (previous_frame_time_ != 0.0) { | 724 if (previous_frame_time_ != 0.0) { |
| 767 adapt_frame_drops_data_.AddSample(adapt_frame_drops_); | 725 adapt_frame_drops_data_.AddSample(adapt_frame_drops_); |
| 768 effect_frame_drops_data_.AddSample(effect_frame_drops_); | |
| 769 frame_time_data_.AddSample(time_now - previous_frame_time_); | 726 frame_time_data_.AddSample(time_now - previous_frame_time_); |
| 770 } | 727 } |
| 771 previous_frame_time_ = time_now; | 728 previous_frame_time_ = time_now; |
| 772 effect_frame_drops_ = 0; | |
| 773 adapt_frame_drops_ = 0; | 729 adapt_frame_drops_ = 0; |
| 774 } | 730 } |
| 775 | 731 |
| 776 template<class T> | 732 template<class T> |
| 777 void VideoCapturer::GetVariableSnapshot( | 733 void VideoCapturer::GetVariableSnapshot( |
| 778 const rtc::RollingAccumulator<T>& data, | 734 const rtc::RollingAccumulator<T>& data, |
| 779 VariableInfo<T>* stats) { | 735 VariableInfo<T>* stats) { |
| 780 stats->max_val = data.ComputeMax(); | 736 stats->max_val = data.ComputeMax(); |
| 781 stats->mean = data.ComputeMean(); | 737 stats->mean = data.ComputeMean(); |
| 782 stats->min_val = data.ComputeMin(); | 738 stats->min_val = data.ComputeMin(); |
| 783 stats->variance = data.ComputeVariance(); | 739 stats->variance = data.ComputeVariance(); |
| 784 } | 740 } |
| 785 | 741 |
| 786 } // namespace cricket | 742 } // namespace cricket |
| OLD | NEW |