| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright 2012 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 #include "webrtc/api/videosource.h" | 11 #include "webrtc/api/videosource.h" |
| 12 | 12 |
| 13 #include <cstdlib> | 13 #include <cstdlib> |
| 14 #include <string> | 14 #include <string> |
| 15 #include <vector> | 15 #include <vector> |
| 16 | 16 |
| 17 #include "webrtc/api/mediaconstraintsinterface.h" | 17 #include "webrtc/api/mediaconstraintsinterface.h" |
| 18 #include "webrtc/base/arraysize.h" | 18 #include "webrtc/base/arraysize.h" |
| 19 #include "webrtc/pc/channelmanager.h" | |
| 20 | 19 |
| 21 using cricket::CaptureState; | 20 using cricket::CaptureState; |
| 22 using webrtc::MediaConstraintsInterface; | 21 using webrtc::MediaConstraintsInterface; |
| 23 using webrtc::MediaSourceInterface; | 22 using webrtc::MediaSourceInterface; |
| 24 | 23 |
| 25 namespace { | 24 namespace { |
| 26 | 25 |
| 27 const double kRoundingTruncation = 0.0005; | 26 const double kRoundingTruncation = 0.0005; |
| 28 | 27 |
| 29 enum { | |
| 30 MSG_VIDEOCAPTURESTATECONNECT, | |
| 31 MSG_VIDEOCAPTURESTATEDISCONNECT, | |
| 32 MSG_VIDEOCAPTURESTATECHANGE, | |
| 33 }; | |
| 34 | |
| 35 // Default resolution. If no constraint is specified, this is the resolution we | 28 // Default resolution. If no constraint is specified, this is the resolution we |
| 36 // will use. | 29 // will use. |
| 37 static const cricket::VideoFormatPod kDefaultFormat = | 30 static const cricket::VideoFormatPod kDefaultFormat = |
| 38 {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}; | 31 {640, 480, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}; |
| 39 | 32 |
| 40 // List of formats used if the camera doesn't support capability enumeration. | 33 // List of formats used if the camera doesn't support capability enumeration. |
| 41 static const cricket::VideoFormatPod kVideoFormats[] = { | 34 static const cricket::VideoFormatPod kVideoFormats[] = { |
| 42 {1920, 1080, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, | 35 {1920, 1080, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, |
| 43 {1280, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, | 36 {1280, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, |
| 44 {960, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, | 37 {960, 720, FPS_TO_INTERVAL(30), cricket::FOURCC_ANY}, |
| (...skipping 230 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 &(options->video_noise_reduction)); | 268 &(options->video_noise_reduction)); |
| 276 | 269 |
| 277 return all_valid; | 270 return all_valid; |
| 278 } | 271 } |
| 279 | 272 |
| 280 } // anonymous namespace | 273 } // anonymous namespace |
| 281 | 274 |
| 282 namespace webrtc { | 275 namespace webrtc { |
| 283 | 276 |
| 284 rtc::scoped_refptr<VideoSource> VideoSource::Create( | 277 rtc::scoped_refptr<VideoSource> VideoSource::Create( |
| 285 cricket::ChannelManager* channel_manager, | 278 rtc::Thread* worker_thread, |
| 286 cricket::VideoCapturer* capturer, | 279 cricket::VideoCapturer* capturer, |
| 287 const webrtc::MediaConstraintsInterface* constraints, | 280 const webrtc::MediaConstraintsInterface* constraints, |
| 288 bool remote) { | 281 bool remote) { |
| 289 ASSERT(channel_manager != NULL); | 282 RTC_DCHECK(worker_thread != NULL); |
| 290 ASSERT(capturer != NULL); | 283 RTC_DCHECK(capturer != NULL); |
| 291 rtc::scoped_refptr<VideoSource> source(new rtc::RefCountedObject<VideoSource>( | 284 rtc::scoped_refptr<VideoSource> source(new rtc::RefCountedObject<VideoSource>( |
| 292 channel_manager, capturer, remote)); | 285 worker_thread, capturer, remote)); |
| 293 source->Initialize(constraints); | 286 source->Initialize(constraints); |
| 294 return source; | 287 return source; |
| 295 } | 288 } |
| 296 | 289 |
| 297 VideoSource::VideoSource(cricket::ChannelManager* channel_manager, | 290 VideoSource::VideoSource(rtc::Thread* worker_thread, |
| 298 cricket::VideoCapturer* capturer, | 291 cricket::VideoCapturer* capturer, |
| 299 bool remote) | 292 bool remote) |
| 300 : channel_manager_(channel_manager), | 293 : signaling_thread_(rtc::Thread::Current()), |
| 294 worker_thread_(worker_thread), |
| 301 video_capturer_(capturer), | 295 video_capturer_(capturer), |
| 296 started_(false), |
| 302 state_(kInitializing), | 297 state_(kInitializing), |
| 303 remote_(remote) { | 298 remote_(remote) { |
| 304 channel_manager_->SignalVideoCaptureStateChange.connect( | 299 video_capturer_->SignalStateChange.connect( |
| 305 this, &VideoSource::OnStateChange); | 300 this, &VideoSource::OnStateChange); |
| 306 } | 301 } |
| 307 | 302 |
| 308 VideoSource::~VideoSource() { | 303 VideoSource::~VideoSource() { |
| 309 channel_manager_->StopVideoCapture(video_capturer_.get(), format_); | 304 video_capturer_->SignalStateChange.disconnect(this); |
| 310 channel_manager_->SignalVideoCaptureStateChange.disconnect(this); | 305 Stop(); |
| 311 } | 306 } |
| 312 | 307 |
| 313 void VideoSource::Initialize( | 308 void VideoSource::Initialize( |
| 314 const webrtc::MediaConstraintsInterface* constraints) { | 309 const webrtc::MediaConstraintsInterface* constraints) { |
| 315 | |
| 316 std::vector<cricket::VideoFormat> formats = | 310 std::vector<cricket::VideoFormat> formats = |
| 317 channel_manager_->GetSupportedFormats(video_capturer_.get()); | 311 *video_capturer_->GetSupportedFormats(); |
| 318 if (formats.empty()) { | 312 if (formats.empty()) { |
| 319 if (video_capturer_->IsScreencast()) { | 313 if (video_capturer_->IsScreencast()) { |
| 320 // The screen capturer can accept any resolution and we will derive the | 314 // The screen capturer can accept any resolution and we will derive the |
| 321 // format from the constraints if any. | 315 // format from the constraints if any. |
| 322 // Note that this only affects tab capturing, not desktop capturing, | 316 // Note that this only affects tab capturing, not desktop capturing, |
| 323 // since the desktop capturer does not respect the VideoFormat passed in. | 317 // since the desktop capturer does not respect the VideoFormat passed in. |
| 324 formats.push_back(cricket::VideoFormat(kDefaultFormat)); | 318 formats.push_back(cricket::VideoFormat(kDefaultFormat)); |
| 325 } else { | 319 } else { |
| 326 // The VideoCapturer implementation doesn't support capability | 320 // The VideoCapturer implementation doesn't support capability |
| 327 // enumeration. We need to guess what the camera supports. | 321 // enumeration. We need to guess what the camera supports. |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 354 } |
| 361 options_.SetAll(options); | 355 options_.SetAll(options); |
| 362 options_.is_screencast = rtc::Optional<bool>(video_capturer_->IsScreencast()); | 356 options_.is_screencast = rtc::Optional<bool>(video_capturer_->IsScreencast()); |
| 363 | 357 |
| 364 format_ = GetBestCaptureFormat(formats); | 358 format_ = GetBestCaptureFormat(formats); |
| 365 // Start the camera with our best guess. | 359 // Start the camera with our best guess. |
| 366 // TODO(perkj): Should we try again with another format it it turns out that | 360 // TODO(perkj): Should we try again with another format it it turns out that |
| 367 // the camera doesn't produce frames with the correct format? Or will | 361 // the camera doesn't produce frames with the correct format? Or will |
| 368 // cricket::VideCapturer be able to re-scale / crop to the requested | 362 // cricket::VideCapturer be able to re-scale / crop to the requested |
| 369 // resolution? | 363 // resolution? |
| 370 if (!channel_manager_->StartVideoCapture(video_capturer_.get(), format_)) { | 364 if (!worker_thread_->Invoke<bool>( |
| 365 rtc::Bind(&cricket::VideoCapturer::StartCapturing, |
| 366 video_capturer_.get(), format_))) { |
| 371 SetState(kEnded); | 367 SetState(kEnded); |
| 372 return; | 368 return; |
| 373 } | 369 } |
| 370 started_ = true; |
| 374 // Initialize hasn't succeeded until a successful state change has occurred. | 371 // Initialize hasn't succeeded until a successful state change has occurred. |
| 375 } | 372 } |
| 376 | 373 |
| 377 void VideoSource::Stop() { | 374 void VideoSource::Stop() { |
| 378 channel_manager_->StopVideoCapture(video_capturer_.get(), format_); | 375 if (!started_) { |
| 376 return; |
| 377 } |
| 378 started_ = false; |
| 379 worker_thread_->Invoke<void>( |
| 380 rtc::Bind(&cricket::VideoCapturer::Stop, |
| 381 video_capturer_.get())); |
| 379 } | 382 } |
| 380 | 383 |
| 381 void VideoSource::Restart() { | 384 void VideoSource::Restart() { |
| 382 if (!channel_manager_->StartVideoCapture(video_capturer_.get(), format_)) { | 385 if (started_) { |
| 386 return; |
| 387 } |
| 388 if (!worker_thread_->Invoke<bool>( |
| 389 rtc::Bind(&cricket::VideoCapturer::StartCapturing, |
| 390 video_capturer_.get(), format_))) { |
| 383 SetState(kEnded); | 391 SetState(kEnded); |
| 384 return; | 392 return; |
| 385 } | 393 } |
| 386 for (auto* sink : sinks_) { | 394 started_ = true; |
| 387 channel_manager_->AddVideoSink(video_capturer_.get(), sink); | |
| 388 } | |
| 389 } | 395 } |
| 390 | 396 |
| 391 void VideoSource::AddSink( | 397 void VideoSource::AddSink( |
| 392 rtc::VideoSinkInterface<cricket::VideoFrame>* output) { | 398 rtc::VideoSinkInterface<cricket::VideoFrame>* output) { |
| 393 sinks_.push_back(output); | 399 // TODO(perkj): Use fake rtc::VideoSinkWants for now. This will change once |
| 394 channel_manager_->AddVideoSink(video_capturer_.get(), output); | 400 // webrtc::VideoSourceInterface inherit rtc::VideoSourceInterface. |
| 401 worker_thread_->Invoke<void>( |
| 402 rtc::Bind(&cricket::VideoCapturer::AddOrUpdateSink, |
| 403 video_capturer_.get(), output, rtc::VideoSinkWants())); |
| 395 } | 404 } |
| 396 | 405 |
| 397 void VideoSource::RemoveSink( | 406 void VideoSource::RemoveSink( |
| 398 rtc::VideoSinkInterface<cricket::VideoFrame>* output) { | 407 rtc::VideoSinkInterface<cricket::VideoFrame>* output) { |
| 399 sinks_.remove(output); | 408 worker_thread_->Invoke<void>( |
| 400 channel_manager_->RemoveVideoSink(video_capturer_.get(), output); | 409 rtc::Bind(&cricket::VideoCapturer::RemoveSink, |
| 410 video_capturer_.get(), output)); |
| 401 } | 411 } |
| 402 | 412 |
| 403 // OnStateChange listens to the ChannelManager::SignalVideoCaptureStateChange. | 413 // OnStateChange listens to the cricket::VideoCapturer::SignalStateChange. |
| 404 // This signal is triggered for all video capturers. Not only the one we are | |
| 405 // interested in. | |
| 406 void VideoSource::OnStateChange(cricket::VideoCapturer* capturer, | 414 void VideoSource::OnStateChange(cricket::VideoCapturer* capturer, |
| 407 cricket::CaptureState capture_state) { | 415 cricket::CaptureState capture_state) { |
| 416 if (rtc::Thread::Current() != signaling_thread_) { |
| 417 invoker_.AsyncInvoke<void>( |
| 418 signaling_thread_, rtc::Bind(&VideoSource::OnStateChange, this, |
| 419 capturer, capture_state)); |
| 420 return; |
| 421 } |
| 422 |
| 408 if (capturer == video_capturer_.get()) { | 423 if (capturer == video_capturer_.get()) { |
| 409 SetState(GetReadyState(capture_state)); | 424 SetState(GetReadyState(capture_state)); |
| 410 } | 425 } |
| 411 } | 426 } |
| 412 | 427 |
| 413 void VideoSource::SetState(SourceState new_state) { | 428 void VideoSource::SetState(SourceState new_state) { |
| 414 // TODO(hbos): Temporarily disabled VERIFY due to webrtc:4776. | |
| 415 // if (VERIFY(state_ != new_state)) { | |
| 416 if (state_ != new_state) { | 429 if (state_ != new_state) { |
| 417 state_ = new_state; | 430 state_ = new_state; |
| 418 FireOnChanged(); | 431 FireOnChanged(); |
| 419 } | 432 } |
| 420 } | 433 } |
| 421 | 434 |
| 422 } // namespace webrtc | 435 } // namespace webrtc |
| OLD | NEW |