| OLD | NEW | 
|---|
| 1 /* | 1 /* | 
| 2  *  Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. | 2  *  Copyright (c) 2010 The WebRTC project authors. All Rights Reserved. | 
| 3  * | 3  * | 
| 4  *  Use of this source code is governed by a BSD-style license | 4  *  Use of this source code is governed by a BSD-style license | 
| 5  *  that can be found in the LICENSE file in the root of the source | 5  *  that can be found in the LICENSE file in the root of the source | 
| 6  *  tree. An additional intellectual property rights grant can be found | 6  *  tree. An additional intellectual property rights grant can be found | 
| 7  *  in the file PATENTS.  All contributing project authors may | 7  *  in the file PATENTS.  All contributing project authors may | 
| 8  *  be found in the AUTHORS file in the root of the source tree. | 8  *  be found in the AUTHORS file in the root of the source tree. | 
| 9  */ | 9  */ | 
| 10 | 10 | 
| 11 // Implementation file of class VideoCapturer. | 11 // Implementation file of class VideoCapturer. | 
| 12 | 12 | 
| 13 #include "webrtc/media/base/videocapturer.h" | 13 #include "webrtc/media/base/videocapturer.h" | 
| 14 | 14 | 
| 15 #include <algorithm> | 15 #include <algorithm> | 
| 16 | 16 | 
| 17 #include "libyuv/scale_argb.h" | 17 #include "libyuv/scale_argb.h" | 
| 18 #include "webrtc/base/common.h" | 18 #include "webrtc/base/common.h" | 
| 19 #include "webrtc/base/logging.h" | 19 #include "webrtc/base/logging.h" | 
| 20 #include "webrtc/base/systeminfo.h" | 20 #include "webrtc/base/systeminfo.h" | 
|  | 21 #include "webrtc/media/base/videoframefactory.h" | 
| 21 #include "webrtc/media/engine/webrtcvideoframe.h" | 22 #include "webrtc/media/engine/webrtcvideoframe.h" | 
|  | 23 #include "webrtc/media/engine/webrtcvideoframefactory.h" | 
| 22 | 24 | 
| 23 namespace cricket { | 25 namespace cricket { | 
| 24 | 26 | 
| 25 namespace { | 27 namespace { | 
| 26 | 28 | 
| 27 static const int64_t kMaxDistance = ~(static_cast<int64_t>(1) << 63); | 29 static const int64_t kMaxDistance = ~(static_cast<int64_t>(1) << 63); | 
| 28 #ifdef WEBRTC_LINUX | 30 #ifdef WEBRTC_LINUX | 
| 29 static const int kYU12Penalty = 16;  // Needs to be higher than MJPG index. | 31 static const int kYU12Penalty = 16;  // Needs to be higher than MJPG index. | 
| 30 #endif | 32 #endif | 
| 31 | 33 | 
| 32 }  // namespace | 34 }  // namespace | 
| 33 | 35 | 
| 34 ///////////////////////////////////////////////////////////////////// | 36 ///////////////////////////////////////////////////////////////////// | 
|  | 37 // Implementation of struct CapturedFrame | 
|  | 38 ///////////////////////////////////////////////////////////////////// | 
|  | 39 CapturedFrame::CapturedFrame() | 
|  | 40     : width(0), | 
|  | 41       height(0), | 
|  | 42       fourcc(0), | 
|  | 43       pixel_width(0), | 
|  | 44       pixel_height(0), | 
|  | 45       time_stamp(0), | 
|  | 46       data_size(0), | 
|  | 47       rotation(webrtc::kVideoRotation_0), | 
|  | 48       data(NULL) {} | 
|  | 49 | 
|  | 50 // TODO(fbarchard): Remove this function once lmimediaengine stops using it. | 
|  | 51 bool CapturedFrame::GetDataSize(uint32_t* size) const { | 
|  | 52   if (!size || data_size == CapturedFrame::kUnknownDataSize) { | 
|  | 53     return false; | 
|  | 54   } | 
|  | 55   *size = data_size; | 
|  | 56   return true; | 
|  | 57 } | 
|  | 58 | 
|  | 59 ///////////////////////////////////////////////////////////////////// | 
| 35 // Implementation of class VideoCapturer | 60 // Implementation of class VideoCapturer | 
| 36 ///////////////////////////////////////////////////////////////////// | 61 ///////////////////////////////////////////////////////////////////// | 
| 37 VideoCapturer::VideoCapturer() : apply_rotation_(false) { | 62 VideoCapturer::VideoCapturer() : apply_rotation_(false) { | 
| 38   thread_checker_.DetachFromThread(); | 63   thread_checker_.DetachFromThread(); | 
| 39   Construct(); | 64   Construct(); | 
| 40 } | 65 } | 
| 41 | 66 | 
| 42 void VideoCapturer::Construct() { | 67 void VideoCapturer::Construct() { | 
| 43   enable_camera_list_ = false; | 68   enable_camera_list_ = false; | 
| 44   capture_state_ = CS_STOPPED; | 69   capture_state_ = CS_STOPPED; | 
|  | 70   SignalFrameCaptured.connect(this, &VideoCapturer::OnFrameCaptured); | 
| 45   scaled_width_ = 0; | 71   scaled_width_ = 0; | 
| 46   scaled_height_ = 0; | 72   scaled_height_ = 0; | 
| 47   enable_video_adapter_ = true; | 73   enable_video_adapter_ = true; | 
|  | 74   // There are lots of video capturers out there that don't call | 
|  | 75   // set_frame_factory.  We can either go change all of them, or we | 
|  | 76   // can set this default. | 
|  | 77   // TODO(pthatcher): Remove this hack and require the frame factory | 
|  | 78   // to be passed in the constructor. | 
|  | 79   set_frame_factory(new WebRtcVideoFrameFactory()); | 
| 48 } | 80 } | 
| 49 | 81 | 
| 50 const std::vector<VideoFormat>* VideoCapturer::GetSupportedFormats() const { | 82 const std::vector<VideoFormat>* VideoCapturer::GetSupportedFormats() const { | 
| 51   return &filtered_supported_formats_; | 83   return &filtered_supported_formats_; | 
| 52 } | 84 } | 
| 53 | 85 | 
| 54 bool VideoCapturer::StartCapturing(const VideoFormat& capture_format) { | 86 bool VideoCapturer::StartCapturing(const VideoFormat& capture_format) { | 
| 55   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 87   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 56   CaptureState result = Start(capture_format); | 88   CaptureState result = Start(capture_format); | 
| 57   const bool success = (result == CS_RUNNING) || (result == CS_STARTING); | 89   const bool success = (result == CS_RUNNING) || (result == CS_STARTING); | 
| (...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 113   return true; | 145   return true; | 
| 114 } | 146 } | 
| 115 | 147 | 
| 116 void VideoCapturer::ConstrainSupportedFormats(const VideoFormat& max_format) { | 148 void VideoCapturer::ConstrainSupportedFormats(const VideoFormat& max_format) { | 
| 117   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 149   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 118   max_format_.reset(new VideoFormat(max_format)); | 150   max_format_.reset(new VideoFormat(max_format)); | 
| 119   LOG(LS_VERBOSE) << " ConstrainSupportedFormats " << max_format.ToString(); | 151   LOG(LS_VERBOSE) << " ConstrainSupportedFormats " << max_format.ToString(); | 
| 120   UpdateFilteredSupportedFormats(); | 152   UpdateFilteredSupportedFormats(); | 
| 121 } | 153 } | 
| 122 | 154 | 
|  | 155 std::string VideoCapturer::ToString(const CapturedFrame* captured_frame) const { | 
|  | 156   std::string fourcc_name = GetFourccName(captured_frame->fourcc) + " "; | 
|  | 157   for (std::string::const_iterator i = fourcc_name.begin(); | 
|  | 158        i < fourcc_name.end(); ++i) { | 
|  | 159     // Test character is printable; Avoid isprint() which asserts on negatives. | 
|  | 160     if (*i < 32 || *i >= 127) { | 
|  | 161       fourcc_name = ""; | 
|  | 162       break; | 
|  | 163     } | 
|  | 164   } | 
|  | 165 | 
|  | 166   std::ostringstream ss; | 
|  | 167   ss << fourcc_name << captured_frame->width << "x" << captured_frame->height; | 
|  | 168   return ss.str(); | 
|  | 169 } | 
|  | 170 | 
|  | 171 void VideoCapturer::set_frame_factory(VideoFrameFactory* frame_factory) { | 
|  | 172   frame_factory_.reset(frame_factory); | 
|  | 173   if (frame_factory) { | 
|  | 174     frame_factory->SetApplyRotation(apply_rotation_); | 
|  | 175   } | 
|  | 176 } | 
|  | 177 | 
| 123 bool VideoCapturer::GetInputSize(int* width, int* height) { | 178 bool VideoCapturer::GetInputSize(int* width, int* height) { | 
| 124   rtc::CritScope cs(&frame_stats_crit_); | 179   rtc::CritScope cs(&frame_stats_crit_); | 
| 125   if (!input_size_valid_) { | 180   if (!input_size_valid_) { | 
| 126     return false; | 181     return false; | 
| 127   } | 182   } | 
| 128   *width = input_width_; | 183   *width = input_width_; | 
| 129   *height = input_height_; | 184   *height = input_height_; | 
| 130 | 185 | 
| 131   return true; | 186   return true; | 
| 132 } | 187 } | 
| 133 | 188 | 
| 134 void VideoCapturer::RemoveSink( | 189 void VideoCapturer::RemoveSink( | 
| 135     rtc::VideoSinkInterface<cricket::VideoFrame>* sink) { | 190     rtc::VideoSinkInterface<cricket::VideoFrame>* sink) { | 
| 136   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 191   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 137   broadcaster_.RemoveSink(sink); | 192   broadcaster_.RemoveSink(sink); | 
| 138   OnSinkWantsChanged(broadcaster_.wants()); | 193   OnSinkWantsChanged(broadcaster_.wants()); | 
| 139 } | 194 } | 
| 140 | 195 | 
| 141 void VideoCapturer::AddOrUpdateSink( | 196 void VideoCapturer::AddOrUpdateSink( | 
| 142     rtc::VideoSinkInterface<cricket::VideoFrame>* sink, | 197     rtc::VideoSinkInterface<cricket::VideoFrame>* sink, | 
| 143     const rtc::VideoSinkWants& wants) { | 198     const rtc::VideoSinkWants& wants) { | 
| 144   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 199   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 145   broadcaster_.AddOrUpdateSink(sink, wants); | 200   broadcaster_.AddOrUpdateSink(sink, wants); | 
| 146   OnSinkWantsChanged(broadcaster_.wants()); | 201   OnSinkWantsChanged(broadcaster_.wants()); | 
| 147 } | 202 } | 
| 148 | 203 | 
| 149 void VideoCapturer::OnSinkWantsChanged(const rtc::VideoSinkWants& wants) { | 204 void VideoCapturer::OnSinkWantsChanged(const rtc::VideoSinkWants& wants) { | 
| 150   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 205   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 151   apply_rotation_ = wants.rotation_applied; | 206   apply_rotation_ = wants.rotation_applied; | 
|  | 207   if (frame_factory_) { | 
|  | 208     frame_factory_->SetApplyRotation(apply_rotation_); | 
|  | 209   } | 
| 152 | 210 | 
| 153   if (video_adapter()) { | 211   if (video_adapter()) { | 
| 154     video_adapter()->OnResolutionRequest(wants.max_pixel_count, | 212     video_adapter()->OnResolutionRequest(wants.max_pixel_count, | 
| 155                                          wants.max_pixel_count_step_up); | 213                                          wants.max_pixel_count_step_up); | 
| 156   } | 214   } | 
| 157 } | 215 } | 
| 158 | 216 | 
| 159 bool VideoCapturer::AdaptFrame(int width, | 217 bool VideoCapturer::AdaptFrame(int width, | 
| 160                                int height, | 218                                int height, | 
| 161                                int64_t camera_time_us, | 219                                int64_t camera_time_us, | 
| (...skipping 27 matching lines...) Expand all  Loading... | 
| 189     *out_height = height; | 247     *out_height = height; | 
| 190     *crop_width = width; | 248     *crop_width = width; | 
| 191     *crop_height = height; | 249     *crop_height = height; | 
| 192     *crop_x = 0; | 250     *crop_x = 0; | 
| 193     *crop_y = 0; | 251     *crop_y = 0; | 
| 194   } | 252   } | 
| 195 | 253 | 
| 196   return true; | 254   return true; | 
| 197 } | 255 } | 
| 198 | 256 | 
|  | 257 void VideoCapturer::OnFrameCaptured(VideoCapturer*, | 
|  | 258                                     const CapturedFrame* captured_frame) { | 
|  | 259   int out_width; | 
|  | 260   int out_height; | 
|  | 261   int crop_width; | 
|  | 262   int crop_height; | 
|  | 263   int crop_x; | 
|  | 264   int crop_y; | 
|  | 265 | 
|  | 266   // TODO(nisse): We don't do timestamp translation on this input | 
|  | 267   // path. It seems straight-forward to enable translation, but that | 
|  | 268   // breaks the WebRtcVideoEngine2Test.PropagatesInputFrameTimestamp | 
|  | 269   // test. Probably not worth the effort to fix, instead, try to | 
|  | 270   // delete or refactor all code using VideoFrameFactory and | 
|  | 271   // SignalCapturedFrame. | 
|  | 272   if (!AdaptFrame(captured_frame->width, captured_frame->height, | 
|  | 273                   captured_frame->time_stamp / rtc::kNumNanosecsPerMicrosec, | 
|  | 274                   0, | 
|  | 275                   &out_width, &out_height, | 
|  | 276                   &crop_width, &crop_height, &crop_x, &crop_y, nullptr)) { | 
|  | 277     return; | 
|  | 278   } | 
|  | 279 | 
|  | 280   if (!frame_factory_) { | 
|  | 281     LOG(LS_ERROR) << "No video frame factory."; | 
|  | 282     return; | 
|  | 283   } | 
|  | 284 | 
|  | 285   // TODO(nisse): Reorganize frame factory methods. crop_x and crop_y | 
|  | 286   // are ignored for now. | 
|  | 287   std::unique_ptr<VideoFrame> adapted_frame(frame_factory_->CreateAliasedFrame( | 
|  | 288       captured_frame, crop_width, crop_height, out_width, out_height)); | 
|  | 289 | 
|  | 290   if (!adapted_frame) { | 
|  | 291     // TODO(fbarchard): LOG more information about captured frame attributes. | 
|  | 292     LOG(LS_ERROR) << "Couldn't convert to I420! " | 
|  | 293                   << "From " << ToString(captured_frame) << " To " | 
|  | 294                   << out_width << " x " << out_height; | 
|  | 295     return; | 
|  | 296   } | 
|  | 297 | 
|  | 298   OnFrame(*adapted_frame, captured_frame->width, captured_frame->height); | 
|  | 299 } | 
|  | 300 | 
| 199 void VideoCapturer::OnFrame(const VideoFrame& frame, | 301 void VideoCapturer::OnFrame(const VideoFrame& frame, | 
| 200                             int orig_width, | 302                             int orig_width, | 
| 201                             int orig_height) { | 303                             int orig_height) { | 
| 202   // For a child class which implements rotation itself, we should | 304   broadcaster_.OnFrame(frame); | 
| 203   // always have apply_rotation_ == false or frame.rotation() == 0. |  | 
| 204   // Except possibly during races where apply_rotation_ is changed |  | 
| 205   // mid-stream. |  | 
| 206   if (apply_rotation_ && frame.rotation() != webrtc::kVideoRotation_0) { |  | 
| 207     rtc::scoped_refptr<webrtc::VideoFrameBuffer> buffer( |  | 
| 208         frame.video_frame_buffer()); |  | 
| 209     if (buffer->native_handle()) { |  | 
| 210       // Sources producing native frames must handle apply_rotation |  | 
| 211       // themselves. But even if they do, we may occasionally end up |  | 
| 212       // in this case, for frames in flight at the time |  | 
| 213       // applied_rotation is set to true. In that case, we just drop |  | 
| 214       // the frame. |  | 
| 215       LOG(LS_WARNING) << "Native frame requiring rotation. Discarding."; |  | 
| 216       return; |  | 
| 217     } |  | 
| 218     broadcaster_.OnFrame(WebRtcVideoFrame( |  | 
| 219         webrtc::I420Buffer::Rotate(buffer, frame.rotation()), |  | 
| 220         webrtc::kVideoRotation_0, frame.timestamp_us())); |  | 
| 221   } else { |  | 
| 222     broadcaster_.OnFrame(frame); |  | 
| 223   } |  | 
| 224   UpdateInputSize(orig_width, orig_height); | 305   UpdateInputSize(orig_width, orig_height); | 
| 225 } | 306 } | 
| 226 | 307 | 
| 227 void VideoCapturer::SetCaptureState(CaptureState state) { | 308 void VideoCapturer::SetCaptureState(CaptureState state) { | 
| 228   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 309   RTC_DCHECK(thread_checker_.CalledOnValidThread()); | 
| 229   if (state == capture_state_) { | 310   if (state == capture_state_) { | 
| 230     // Don't trigger a state changed callback if the state hasn't changed. | 311     // Don't trigger a state changed callback if the state hasn't changed. | 
| 231     return; | 312     return; | 
| 232   } | 313   } | 
| 233   capture_state_ = state; | 314   capture_state_ = state; | 
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
| 365 void VideoCapturer::UpdateInputSize(int width, int height) { | 446 void VideoCapturer::UpdateInputSize(int width, int height) { | 
| 366   // Update stats protected from fetches from different thread. | 447   // Update stats protected from fetches from different thread. | 
| 367   rtc::CritScope cs(&frame_stats_crit_); | 448   rtc::CritScope cs(&frame_stats_crit_); | 
| 368 | 449 | 
| 369   input_size_valid_ = true; | 450   input_size_valid_ = true; | 
| 370   input_width_ = width; | 451   input_width_ = width; | 
| 371   input_height_ = height; | 452   input_height_ = height; | 
| 372 } | 453 } | 
| 373 | 454 | 
| 374 }  // namespace cricket | 455 }  // namespace cricket | 
| OLD | NEW | 
|---|