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 |