1 /* 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. 3 * 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 6 * tree. An additional intellectual property rights grant can be found 7 * in the file PATENTS. All contributing project authors may 8 * be found in the AUTHORS file in the root of the source tree. 9 */ 10 11 #include "webrtc/video_engine/vie_capturer.h" 12 13 #include "webrtc/common_video/interface/texture_video_frame.h" 14 #include "webrtc/common_video/libyuv/include/webrtc_libyuv.h" 15 #include "webrtc/modules/interface/module_common_types.h" 16 #include "webrtc/modules/utility/interface/process_thread.h" 17 #include "webrtc/modules/video_capture/include/video_capture_factory.h" 18 #include "webrtc/modules/video_processing/main/interface/video_processing.h" 19 #include "webrtc/modules/video_render/include/video_render_defines.h" 20 #include "webrtc/system_wrappers/interface/clock.h" 21 #include "webrtc/system_wrappers/interface/critical_section_wrapper.h" 22 #include "webrtc/system_wrappers/interface/event_wrapper.h" 23 #include "webrtc/system_wrappers/interface/logging.h" 24 #include "webrtc/system_wrappers/interface/thread_wrapper.h" 25 #include "webrtc/system_wrappers/interface/trace_event.h" 26 #include "webrtc/video_engine/include/vie_image_process.h" 27 #include "webrtc/video_engine/overuse_frame_detector.h" 28 #include "webrtc/video_engine/vie_defines.h" 29 #include "webrtc/video_engine/vie_encoder.h" 30 31 namespace webrtc { 32 33 const int kThreadWaitTimeMs = 100; 34 35 ViECapturer::ViECapturer(int capture_id, 36 int engine_id, 37 const Config& config, 38 ProcessThread& module_process_thread) 39 : ViEFrameProviderBase(capture_id, engine_id), 40 capture_cs_(CriticalSectionWrapper::CreateCriticalSection()), 41 deliver_cs_(CriticalSectionWrapper::CreateCriticalSection()), 42 capture_module_(NULL), 43 external_capture_module_(NULL), 44 module_process_thread_(module_process_thread), 45 capture_id_(capture_id), 46 incoming_frame_cs_(CriticalSectionWrapper::CreateCriticalSection()), 47 capture_thread_(*ThreadWrapper::CreateThread(ViECaptureThreadFunction, 48 this, kHighPriority, 49 "ViECaptureThread")), 50 capture_event_(*EventWrapper::Create()), 51 deliver_event_(*EventWrapper::Create()), 52 effect_filter_(NULL), 53 image_proc_module_(NULL), 54 image_proc_module_ref_counter_(0), 55 deflicker_frame_stats_(NULL), 56 brightness_frame_stats_(NULL), 57 current_brightness_level_(Normal), 58 reported_brightness_level_(Normal), 59 observer_cs_(CriticalSectionWrapper::CreateCriticalSection()), 60 observer_(NULL), 61 overuse_detector_(new OveruseFrameDetector(Clock::GetRealTimeClock())) { 62 unsigned int t_id = 0; 63 if (!capture_thread_.Start(t_id)) { 64 assert(false); 65 } 66 module_process_thread_.RegisterModule(overuse_detector_.get()); 67 } 68 69 ViECapturer::~ViECapturer() { 70 module_process_thread_.DeRegisterModule(overuse_detector_.get()); 71 72 // Stop the thread. 73 deliver_cs_->Enter(); 74 capture_cs_->Enter(); 75 capture_thread_.SetNotAlive(); 76 capture_event_.Set(); 77 capture_cs_->Leave(); 78 deliver_cs_->Leave(); 79 80 // Stop the camera input. 81 if (capture_module_) { 82 module_process_thread_.DeRegisterModule(capture_module_); 83 capture_module_->DeRegisterCaptureDataCallback(); 84 capture_module_->Release(); 85 capture_module_ = NULL; 86 } 87 if (capture_thread_.Stop()) { 88 // Thread stopped. 89 delete &capture_thread_; 90 delete &capture_event_; 91 delete &deliver_event_; 92 } else { 93 assert(false); 94 } 95 96 if (image_proc_module_) { 97 VideoProcessingModule::Destroy(image_proc_module_); 98 } 99 if (deflicker_frame_stats_) { 100 delete deflicker_frame_stats_; 101 deflicker_frame_stats_ = NULL; 102 } 103 delete brightness_frame_stats_; 104 } 105 106 ViECapturer* ViECapturer::CreateViECapture( 107 int capture_id, 108 int engine_id, 109 const Config& config, 110 VideoCaptureModule* capture_module, 111 ProcessThread& module_process_thread) { 112 ViECapturer* capture = new ViECapturer(capture_id, engine_id, config, 113 module_process_thread); 114 if (!capture || capture->Init(capture_module) != 0) { 115 delete capture; 116 capture = NULL; 117 } 118 return capture; 119 } 120 121 int32_t ViECapturer::Init(VideoCaptureModule* capture_module) { 122 assert(capture_module_ == NULL); 123 capture_module_ = capture_module; 124 capture_module_->RegisterCaptureDataCallback(*this); 125 capture_module_->AddRef(); 126 if (module_process_thread_.RegisterModule(capture_module_) != 0) { 127 return -1; 128 } 129 130 return 0; 131 } 132 133 ViECapturer* ViECapturer::CreateViECapture( 134 int capture_id, 135 int engine_id, 136 const Config& config, 137 const char* device_unique_idUTF8, 138 const uint32_t device_unique_idUTF8Length, 139 ProcessThread& module_process_thread) { 140 ViECapturer* capture = new ViECapturer(capture_id, engine_id, config, 141 module_process_thread); 142 if (!capture || 143 capture->Init(device_unique_idUTF8, device_unique_idUTF8Length) != 0) { 144 delete capture; 145 capture = NULL; 146 } 147 return capture; 148 } 149 150 int32_t ViECapturer::Init(const char* device_unique_idUTF8, 151 uint32_t device_unique_idUTF8Length) { 152 assert(capture_module_ == NULL); 153 if (device_unique_idUTF8 == NULL) { 154 capture_module_ = VideoCaptureFactory::Create( 155 ViEModuleId(engine_id_, capture_id_), external_capture_module_); 156 } else { 157 capture_module_ = VideoCaptureFactory::Create( 158 ViEModuleId(engine_id_, capture_id_), device_unique_idUTF8); 159 } 160 if (!capture_module_) { 161 return -1; 162 } 163 capture_module_->AddRef(); 164 capture_module_->RegisterCaptureDataCallback(*this); 165 if (module_process_thread_.RegisterModule(capture_module_) != 0) { 166 return -1; 167 } 168 169 return 0; 170 } 171 172 int ViECapturer::FrameCallbackChanged() { 173 if (Started() && !CaptureCapabilityFixed()) { 174 // Reconfigure the camera if a new size is required and the capture device 175 // does not provide encoded frames. 176 int best_width; 177 int best_height; 178 int best_frame_rate; 179 VideoCaptureCapability capture_settings; 180 capture_module_->CaptureSettings(capture_settings); 181 GetBestFormat(&best_width, &best_height, &best_frame_rate); 182 if (best_width != 0 && best_height != 0 && best_frame_rate != 0) { 183 if (best_width != capture_settings.width || 184 best_height != capture_settings.height || 185 best_frame_rate != capture_settings.maxFPS || 186 capture_settings.codecType != kVideoCodecUnknown) { 187 Stop(); 188 Start(requested_capability_); 189 } 190 } 191 } 192 return 0; 193 } 194 195 int32_t ViECapturer::Start(const CaptureCapability& capture_capability) { 196 int width; 197 int height; 198 int frame_rate; 199 VideoCaptureCapability capability; 200 requested_capability_ = capture_capability; 201 202 if (!CaptureCapabilityFixed()) { 203 // Ask the observers for best size. 204 GetBestFormat(&width, &height, &frame_rate); 205 if (width == 0) { 206 width = kViECaptureDefaultWidth; 207 } 208 if (height == 0) { 209 height = kViECaptureDefaultHeight; 210 } 211 if (frame_rate == 0) { 212 frame_rate = kViECaptureDefaultFramerate; 213 } 214 capability.height = height; 215 capability.width = width; 216 capability.maxFPS = frame_rate; 217 capability.rawType = kVideoI420; 218 capability.codecType = kVideoCodecUnknown; 219 } else { 220 // Width, height and type specified with call to Start, not set by 221 // observers. 222 capability.width = requested_capability_.width; 223 capability.height = requested_capability_.height; 224 capability.maxFPS = requested_capability_.maxFPS; 225 capability.rawType = requested_capability_.rawType; 226 capability.interlaced = requested_capability_.interlaced; 227 } 228 return capture_module_->StartCapture(capability); 229 } 230 231 int32_t ViECapturer::Stop() { 232 requested_capability_ = CaptureCapability(); 233 return capture_module_->StopCapture(); 234 } 235 236 bool ViECapturer::Started() { 237 return capture_module_->CaptureStarted(); 238 } 239 240 const char* ViECapturer::CurrentDeviceName() const { 241 return capture_module_->CurrentDeviceName(); 242 } 243 244 void ViECapturer::RegisterCpuOveruseObserver(CpuOveruseObserver* observer) { 245 overuse_detector_->SetObserver(observer); 246 } 247 248 void ViECapturer::SetCpuOveruseOptions(const CpuOveruseOptions& options) { 249 overuse_detector_->SetOptions(options); 250 } 251 252 void ViECapturer::GetCpuOveruseMetrics(CpuOveruseMetrics* metrics) const { 253 overuse_detector_->GetCpuOveruseMetrics(metrics); 254 } 255 256 int32_t ViECapturer::SetCaptureDelay(int32_t delay_ms) { 257 capture_module_->SetCaptureDelay(delay_ms); 258 return 0; 259 } 260 261 int32_t ViECapturer::SetRotateCapturedFrames( 262 const RotateCapturedFrame rotation) { 263 VideoCaptureRotation converted_rotation = kCameraRotate0; 264 switch (rotation) { 265 case RotateCapturedFrame_0: 266 converted_rotation = kCameraRotate0; 267 break; 268 case RotateCapturedFrame_90: 269 converted_rotation = kCameraRotate90; 270 break; 271 case RotateCapturedFrame_180: 272 converted_rotation = kCameraRotate180; 273 break; 274 case RotateCapturedFrame_270: 275 converted_rotation = kCameraRotate270; 276 break; 277 } 278 return capture_module_->SetCaptureRotation(converted_rotation); 279 } 280 281 int ViECapturer::IncomingFrame(unsigned char* video_frame, 282 unsigned int video_frame_length, 283 uint16_t width, 284 uint16_t height, 285 RawVideoType video_type, 286 unsigned long long capture_time) { // NOLINT 287 if (!external_capture_module_) { 288 return -1; 289 } 290 VideoCaptureCapability capability; 291 capability.width = width; 292 capability.height = height; 293 capability.rawType = video_type; 294 return external_capture_module_->IncomingFrame(video_frame, 295 video_frame_length, 296 capability, capture_time); 297 } 298 299 int ViECapturer::IncomingFrameI420(const ViEVideoFrameI420& video_frame, 300 unsigned long long capture_time) { // NOLINT 301 if (!external_capture_module_) { 302 return -1; 303 } 304 305 int size_y = video_frame.height * video_frame.y_pitch; 306 int size_u = video_frame.u_pitch * ((video_frame.height + 1) / 2); 307 int size_v = video_frame.v_pitch * ((video_frame.height + 1) / 2); 308 CriticalSectionScoped cs(incoming_frame_cs_.get()); 309 int ret = incoming_frame_.CreateFrame(size_y, 310 video_frame.y_plane, 311 size_u, 312 video_frame.u_plane, 313 size_v, 314 video_frame.v_plane, 315 video_frame.width, 316 video_frame.height, 317 video_frame.y_pitch, 318 video_frame.u_pitch, 319 video_frame.v_pitch); 320 321 if (ret < 0) { 322 LOG_F(LS_ERROR) << "Could not create I420Frame."; 323 return -1; 324 } 325 326 return external_capture_module_->IncomingI420VideoFrame(&incoming_frame_, 327 capture_time); 328 } 329 330 void ViECapturer::SwapFrame(I420VideoFrame* frame) { 331 external_capture_module_->IncomingI420VideoFrame(frame, 332 frame->render_time_ms()); 333 frame->set_timestamp(0); 334 frame->set_ntp_time_ms(0); 335 frame->set_render_time_ms(0); 336 } 337 338 void ViECapturer::OnIncomingCapturedFrame(const int32_t capture_id, 339 I420VideoFrame& video_frame) { 340 CriticalSectionScoped cs(capture_cs_.get()); 341 // Make sure we render this frame earlier since we know the render time set 342 // is slightly off since it's being set when the frame has been received from 343 // the camera, and not when the camera actually captured the frame. 344 video_frame.set_render_time_ms(video_frame.render_time_ms() - FrameDelay()); 345 346 TRACE_EVENT_ASYNC_BEGIN1("webrtc", "Video", video_frame.render_time_ms(), 347 "render_time", video_frame.render_time_ms()); 348 349 if (video_frame.native_handle() != NULL) { 350 captured_frame_.reset(video_frame.CloneFrame()); 351 } else { 352 if (captured_frame_ == NULL || captured_frame_->native_handle() != NULL) 353 captured_frame_.reset(new I420VideoFrame()); 354 captured_frame_->SwapFrame(&video_frame); 355 } 356 capture_event_.Set(); 357 overuse_detector_->FrameCaptured(captured_frame_->width(), 358 captured_frame_->height()); 359 } 360 361 void ViECapturer::OnCaptureDelayChanged(const int32_t id, 362 const int32_t delay) { 363 LOG(LS_INFO) << "Capture delayed change to " << delay 364 << " for device " << id; 365 366 // Deliver the network delay to all registered callbacks. 367 ViEFrameProviderBase::SetFrameDelay(delay); 368 } 369 370 int32_t ViECapturer::RegisterEffectFilter( 371 ViEEffectFilter* effect_filter) { 372 CriticalSectionScoped cs(deliver_cs_.get()); 373 374 if (effect_filter != NULL && effect_filter_ != NULL) { 375 LOG_F(LS_ERROR) << "Effect filter already registered."; 376 return -1; 377 } 378 effect_filter_ = effect_filter; 379 return 0; 380 } 381 382 int32_t ViECapturer::IncImageProcRefCount() { 383 if (!image_proc_module_) { 384 assert(image_proc_module_ref_counter_ == 0); 385 image_proc_module_ = VideoProcessingModule::Create( 386 ViEModuleId(engine_id_, capture_id_)); 387 if (!image_proc_module_) { 388 LOG_F(LS_ERROR) << "Could not create video processing module."; 389 return -1; 390 } 391 } 392 image_proc_module_ref_counter_++; 393 return 0; 394 } 395 396 int32_t ViECapturer::DecImageProcRefCount() { 397 image_proc_module_ref_counter_--; 398 if (image_proc_module_ref_counter_ == 0) { 399 // Destroy module. 400 VideoProcessingModule::Destroy(image_proc_module_); 401 image_proc_module_ = NULL; 402 } 403 return 0; 404 } 405 406 int32_t ViECapturer::EnableDeflickering(bool enable) { 407 CriticalSectionScoped cs(deliver_cs_.get()); 408 if (enable) { 409 if (deflicker_frame_stats_) { 410 return -1; 411 } 412 if (IncImageProcRefCount() != 0) { 413 return -1; 414 } 415 deflicker_frame_stats_ = new VideoProcessingModule::FrameStats(); 416 } else { 417 if (deflicker_frame_stats_ == NULL) { 418 return -1; 419 } 420 DecImageProcRefCount(); 421 delete deflicker_frame_stats_; 422 deflicker_frame_stats_ = NULL; 423 } 424 return 0; 425 } 426 427 int32_t ViECapturer::EnableBrightnessAlarm(bool enable) { 428 CriticalSectionScoped cs(deliver_cs_.get()); 429 if (enable) { 430 if (brightness_frame_stats_) { 431 return -1; 432 } 433 if (IncImageProcRefCount() != 0) { 434 return -1; 435 } 436 brightness_frame_stats_ = new VideoProcessingModule::FrameStats(); 437 } else { 438 DecImageProcRefCount(); 439 if (brightness_frame_stats_ == NULL) { 440 return -1; 441 } 442 delete brightness_frame_stats_; 443 brightness_frame_stats_ = NULL; 444 } 445 return 0; 446 } 447 448 bool ViECapturer::ViECaptureThreadFunction(void* obj) { 449 return static_cast<ViECapturer*>(obj)->ViECaptureProcess(); 450 } 451 452 bool ViECapturer::ViECaptureProcess() { 453 if (capture_event_.Wait(kThreadWaitTimeMs) == kEventSignaled) { 454 overuse_detector_->FrameProcessingStarted(); 455 int64_t encode_start_time = -1; 456 deliver_cs_->Enter(); 457 if (SwapCapturedAndDeliverFrameIfAvailable()) { 458 encode_start_time = Clock::GetRealTimeClock()->TimeInMilliseconds(); 459 DeliverI420Frame(deliver_frame_.get()); 460 if (deliver_frame_->native_handle() != NULL) 461 deliver_frame_.reset(); // Release the texture so it can be reused. 462 } 463 deliver_cs_->Leave(); 464 if (current_brightness_level_ != reported_brightness_level_) { 465 CriticalSectionScoped cs(observer_cs_.get()); 466 if (observer_) { 467 observer_->BrightnessAlarm(id_, current_brightness_level_); 468 reported_brightness_level_ = current_brightness_level_; 469 } 470 } 471 // Update the overuse detector with the duration. 472 if (encode_start_time != -1) { 473 overuse_detector_->FrameEncoded( 474 Clock::GetRealTimeClock()->TimeInMilliseconds() - encode_start_time); 475 } 476 } 477 // We're done! 478 return true; 479 } 480 481 void ViECapturer::DeliverI420Frame(I420VideoFrame* video_frame) { 482 if (video_frame->native_handle() != NULL) { 483 ViEFrameProviderBase::DeliverFrame(video_frame); 484 return; 485 } 486 487 // Apply image enhancement and effect filter. 488 if (deflicker_frame_stats_) { 489 if (image_proc_module_->GetFrameStats(deflicker_frame_stats_, 490 *video_frame) == 0) { 491 image_proc_module_->Deflickering(video_frame, deflicker_frame_stats_); 492 } else { 493 LOG_F(LS_ERROR) << "Could not get frame stats."; 494 } 495 } 496 if (brightness_frame_stats_) { 497 if (image_proc_module_->GetFrameStats(brightness_frame_stats_, 498 *video_frame) == 0) { 499 int32_t brightness = image_proc_module_->BrightnessDetection( 500 *video_frame, *brightness_frame_stats_); 501 502 switch (brightness) { 503 case VideoProcessingModule::kNoWarning: 504 current_brightness_level_ = Normal; 505 break; 506 case VideoProcessingModule::kDarkWarning: 507 current_brightness_level_ = Dark; 508 break; 509 case VideoProcessingModule::kBrightWarning: 510 current_brightness_level_ = Bright; 511 break; 512 default: 513 break; 514 } 515 } 516 } 517 if (effect_filter_) { 518 unsigned int length = CalcBufferSize(kI420, 519 video_frame->width(), 520 video_frame->height()); 521 scoped_ptr<uint8_t[]> video_buffer(new uint8_t[length]); 522 ExtractBuffer(*video_frame, length, video_buffer.get()); 523 effect_filter_->Transform(length, 524 video_buffer.get(), 525 video_frame->ntp_time_ms(), 526 video_frame->timestamp(), 527 video_frame->width(), 528 video_frame->height()); 529 } 530 // Deliver the captured frame to all observers (channels, renderer or file). 531 ViEFrameProviderBase::DeliverFrame(video_frame); 532 } 533 534 int ViECapturer::DeregisterFrameCallback( 535 const ViEFrameCallback* callbackObject) { 536 return ViEFrameProviderBase::DeregisterFrameCallback(callbackObject); 537 } 538 539 bool ViECapturer::IsFrameCallbackRegistered( 540 const ViEFrameCallback* callbackObject) { 541 CriticalSectionScoped cs(provider_cs_.get()); 542 return ViEFrameProviderBase::IsFrameCallbackRegistered(callbackObject); 543 } 544 545 bool ViECapturer::CaptureCapabilityFixed() { 546 return requested_capability_.width != 0 && 547 requested_capability_.height != 0 && 548 requested_capability_.maxFPS != 0; 549 } 550 551 int32_t ViECapturer::RegisterObserver(ViECaptureObserver* observer) { 552 { 553 CriticalSectionScoped cs(observer_cs_.get()); 554 if (observer_) { 555 LOG_F(LS_ERROR) << "Observer already registered."; 556 return -1; 557 } 558 observer_ = observer; 559 } 560 capture_module_->RegisterCaptureCallback(*this); 561 capture_module_->EnableFrameRateCallback(true); 562 capture_module_->EnableNoPictureAlarm(true); 563 return 0; 564 } 565 566 int32_t ViECapturer::DeRegisterObserver() { 567 capture_module_->EnableFrameRateCallback(false); 568 capture_module_->EnableNoPictureAlarm(false); 569 capture_module_->DeRegisterCaptureCallback(); 570 571 CriticalSectionScoped cs(observer_cs_.get()); 572 observer_ = NULL; 573 return 0; 574 } 575 576 bool ViECapturer::IsObserverRegistered() { 577 CriticalSectionScoped cs(observer_cs_.get()); 578 return observer_ != NULL; 579 } 580 581 void ViECapturer::OnCaptureFrameRate(const int32_t id, 582 const uint32_t frame_rate) { 583 CriticalSectionScoped cs(observer_cs_.get()); 584 observer_->CapturedFrameRate(id_, static_cast<uint8_t>(frame_rate)); 585 } 586 587 void ViECapturer::OnNoPictureAlarm(const int32_t id, 588 const VideoCaptureAlarm alarm) { 589 LOG(LS_WARNING) << "OnNoPictureAlarm " << id; 590 591 CriticalSectionScoped cs(observer_cs_.get()); 592 CaptureAlarm vie_alarm = (alarm == Raised) ? AlarmRaised : AlarmCleared; 593 observer_->NoPictureAlarm(id, vie_alarm); 594 } 595 596 bool ViECapturer::SwapCapturedAndDeliverFrameIfAvailable() { 597 CriticalSectionScoped cs(capture_cs_.get()); 598 if (captured_frame_ == NULL) 599 return false; 600 601 if (captured_frame_->native_handle() != NULL) { 602 deliver_frame_.reset(captured_frame_.release()); 603 return true; 604 } 605 606 if (captured_frame_->IsZeroSize()) 607 return false; 608 609 if (deliver_frame_ == NULL) 610 deliver_frame_.reset(new I420VideoFrame()); 611 deliver_frame_->SwapFrame(captured_frame_.get()); 612 captured_frame_->ResetSize(); 613 return true; 614 } 615 616 } // namespace webrtc 617