| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "content/browser/renderer_host/media/video_capture_controller.h" | 5 #include "content/browser/renderer_host/media/video_capture_controller.h" |
| 6 | 6 |
| 7 #include <set> | 7 #include <set> |
| 8 | 8 |
| 9 #include "base/bind.h" | 9 #include "base/bind.h" |
| 10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 // The memory created to be shared with renderer processes. | 60 // The memory created to be shared with renderer processes. |
| 61 scoped_ptr<base::SharedMemory> shared_memory; | 61 scoped_ptr<base::SharedMemory> shared_memory; |
| 62 | 62 |
| 63 // Number of renderer processes which hold this shared memory. | 63 // Number of renderer processes which hold this shared memory. |
| 64 // renderer process is represented by VidoeCaptureHost. | 64 // renderer process is represented by VidoeCaptureHost. |
| 65 int references; | 65 int references; |
| 66 }; | 66 }; |
| 67 | 67 |
| 68 VideoCaptureController::VideoCaptureController( | 68 VideoCaptureController::VideoCaptureController( |
| 69 media_stream::VideoCaptureManager* video_capture_manager) | 69 media_stream::VideoCaptureManager* video_capture_manager) |
| 70 : frame_info_available_(false), | 70 : chopped_width_(0), |
| 71 chopped_height_(0), |
| 72 frame_info_available_(false), |
| 71 video_capture_manager_(video_capture_manager), | 73 video_capture_manager_(video_capture_manager), |
| 72 device_in_use_(false), | 74 device_in_use_(false), |
| 73 state_(video_capture::kStopped) { | 75 state_(video_capture::kStopped) { |
| 74 memset(¤t_params_, 0, sizeof(current_params_)); | 76 memset(¤t_params_, 0, sizeof(current_params_)); |
| 75 } | 77 } |
| 76 | 78 |
| 77 void VideoCaptureController::StartCapture( | 79 void VideoCaptureController::StartCapture( |
| 78 const VideoCaptureControllerID& id, | 80 const VideoCaptureControllerID& id, |
| 79 VideoCaptureControllerEventHandler* event_handler, | 81 VideoCaptureControllerEventHandler* event_handler, |
| 80 base::ProcessHandle render_process, | 82 base::ProcessHandle render_process, |
| (...skipping 189 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 270 2); | 272 2); |
| 271 uint8* yplane = target; | 273 uint8* yplane = target; |
| 272 uint8* uplane = target + frame_info_.width * frame_info_.height; | 274 uint8* uplane = target + frame_info_.width * frame_info_.height; |
| 273 uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; | 275 uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; |
| 274 | 276 |
| 275 // Do color conversion from the camera format to I420. | 277 // Do color conversion from the camera format to I420. |
| 276 switch (frame_info_.color) { | 278 switch (frame_info_.color) { |
| 277 case media::VideoCaptureCapability::kColorUnknown: // Color format not set. | 279 case media::VideoCaptureCapability::kColorUnknown: // Color format not set. |
| 278 break; | 280 break; |
| 279 case media::VideoCaptureCapability::kI420: { | 281 case media::VideoCaptureCapability::kI420: { |
| 282 DCHECK(!chopped_width_ && !chopped_height_); |
| 280 memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2); | 283 memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2); |
| 281 break; | 284 break; |
| 282 } | 285 } |
| 283 case media::VideoCaptureCapability::kYV12: { | 286 case media::VideoCaptureCapability::kYV12: { |
| 287 DCHECK(!chopped_width_ && !chopped_height_); |
| 284 const uint8* ptr = data; | 288 const uint8* ptr = data; |
| 285 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height)); | 289 memcpy(yplane, ptr, (frame_info_.width * frame_info_.height)); |
| 286 ptr += frame_info_.width * frame_info_.height; | 290 ptr += frame_info_.width * frame_info_.height; |
| 287 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2); | 291 memcpy(vplane, ptr, (frame_info_.width * frame_info_.height) >> 2); |
| 288 ptr += (frame_info_.width * frame_info_.height) >> 2; | 292 ptr += (frame_info_.width * frame_info_.height) >> 2; |
| 289 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2); | 293 memcpy(uplane, ptr, (frame_info_.width * frame_info_.height) >> 2); |
| 290 break; | 294 break; |
| 291 } | 295 } |
| 292 case media::VideoCaptureCapability::kNV21: { | 296 case media::VideoCaptureCapability::kNV21: { |
| 297 DCHECK(!chopped_width_ && !chopped_height_); |
| 293 media::ConvertNV21ToYUV(data, yplane, uplane, vplane, frame_info_.width, | 298 media::ConvertNV21ToYUV(data, yplane, uplane, vplane, frame_info_.width, |
| 294 frame_info_.height); | 299 frame_info_.height); |
| 295 break; | 300 break; |
| 296 } | 301 } |
| 297 case media::VideoCaptureCapability::kYUY2: { | 302 case media::VideoCaptureCapability::kYUY2: { |
| 303 DCHECK(!chopped_width_ && !chopped_height_); |
| 298 media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width, | 304 media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width, |
| 299 frame_info_.height); | 305 frame_info_.height); |
| 300 break; | 306 break; |
| 301 } | 307 } |
| 302 case media::VideoCaptureCapability::kRGB24: { | 308 case media::VideoCaptureCapability::kRGB24: { |
| 303 int ystride = frame_info_.width; | 309 int ystride = frame_info_.width; |
| 304 int uvstride = frame_info_.width / 2; | 310 int uvstride = frame_info_.width / 2; |
| 305 #if defined(OS_WIN) // RGB on Windows start at the bottom line. | 311 #if defined(OS_WIN) // RGB on Windows start at the bottom line. |
| 306 int rgb_stride = -3 * frame_info_.width; | 312 int rgb_stride = -3 * (frame_info_.width + chopped_width_); |
| 307 const uint8* rgb_src = data + 3 * frame_info_.width * | 313 const uint8* rgb_src = data + 3 * (frame_info_.width + chopped_width_) * |
| 308 (frame_info_.height -1); | 314 (frame_info_.height -1 + chopped_height_); |
| 309 #else | 315 #else |
| 310 int rgb_stride = 3 * frame_info_.width; | 316 int rgb_stride = 3 * (frame_info_.width + chopped_width_); |
| 311 const uint8* rgb_src = data; | 317 const uint8* rgb_src = data; |
| 312 #endif | 318 #endif |
| 313 media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane, | 319 media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane, |
| 314 frame_info_.width, frame_info_.height, | 320 frame_info_.width, frame_info_.height, |
| 315 rgb_stride, ystride, uvstride); | 321 rgb_stride, ystride, uvstride); |
| 316 break; | 322 break; |
| 317 } | 323 } |
| 318 case media::VideoCaptureCapability::kARGB: { | 324 case media::VideoCaptureCapability::kARGB: { |
| 319 media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width, | 325 media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width, |
| 320 frame_info_.height, frame_info_.width * 4, | 326 frame_info_.height, |
| 327 (frame_info_.width + chopped_width_) * 4, |
| 321 frame_info_.width, frame_info_.width / 2); | 328 frame_info_.width, frame_info_.width / 2); |
| 322 break; | 329 break; |
| 323 } | 330 } |
| 324 default: | 331 default: |
| 325 NOTREACHED(); | 332 NOTREACHED(); |
| 326 } | 333 } |
| 327 | 334 |
| 328 BrowserThread::PostTask(BrowserThread::IO, | 335 BrowserThread::PostTask(BrowserThread::IO, |
| 329 FROM_HERE, | 336 FROM_HERE, |
| 330 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, | 337 base::Bind(&VideoCaptureController::DoIncomingCapturedFrameOnIOThread, |
| 331 this, buffer_id, timestamp)); | 338 this, buffer_id, timestamp)); |
| 332 } | 339 } |
| 333 | 340 |
| 334 void VideoCaptureController::OnError() { | 341 void VideoCaptureController::OnError() { |
| 335 video_capture_manager_->Error(current_params_.session_id); | 342 video_capture_manager_->Error(current_params_.session_id); |
| 336 BrowserThread::PostTask(BrowserThread::IO, | 343 BrowserThread::PostTask(BrowserThread::IO, |
| 337 FROM_HERE, | 344 FROM_HERE, |
| 338 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); | 345 base::Bind(&VideoCaptureController::DoErrorOnIOThread, this)); |
| 339 } | 346 } |
| 340 | 347 |
| 341 void VideoCaptureController::OnFrameInfo( | 348 void VideoCaptureController::OnFrameInfo( |
| 342 const media::VideoCaptureCapability& info) { | 349 const media::VideoCaptureCapability& info) { |
| 343 frame_info_= info; | 350 frame_info_= info; |
| 351 // Handle cases when |info| has odd numbers for width/height. |
| 352 if (info.width & 1) { |
| 353 --frame_info_.width; |
| 354 chopped_width_ = 1; |
| 355 } else { |
| 356 chopped_width_ = 0; |
| 357 } |
| 358 if (info.height & 1) { |
| 359 --frame_info_.height; |
| 360 chopped_height_ = 1; |
| 361 } else { |
| 362 chopped_height_ = 0; |
| 363 } |
| 344 BrowserThread::PostTask(BrowserThread::IO, | 364 BrowserThread::PostTask(BrowserThread::IO, |
| 345 FROM_HERE, | 365 FROM_HERE, |
| 346 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, | 366 base::Bind(&VideoCaptureController::DoFrameInfoOnIOThread, this)); |
| 347 this, info)); | |
| 348 } | 367 } |
| 349 | 368 |
| 350 VideoCaptureController::~VideoCaptureController() { | 369 VideoCaptureController::~VideoCaptureController() { |
| 351 // Delete all DIBs. | 370 // Delete all DIBs. |
| 352 STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), | 371 STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), |
| 353 owned_dibs_.end()); | 372 owned_dibs_.end()); |
| 354 STLDeleteContainerPointers(controller_clients_.begin(), | 373 STLDeleteContainerPointers(controller_clients_.begin(), |
| 355 controller_clients_.end()); | 374 controller_clients_.end()); |
| 356 STLDeleteContainerPointers(pending_clients_.begin(), | 375 STLDeleteContainerPointers(pending_clients_.begin(), |
| 357 pending_clients_.end()); | 376 pending_clients_.end()); |
| (...skipping 24 matching lines...) Expand all Loading... |
| 382 } | 401 } |
| 383 } | 402 } |
| 384 | 403 |
| 385 base::AutoLock lock(lock_); | 404 base::AutoLock lock(lock_); |
| 386 if (owned_dibs_.find(buffer_id) != owned_dibs_.end()) { | 405 if (owned_dibs_.find(buffer_id) != owned_dibs_.end()) { |
| 387 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); | 406 DCHECK_EQ(owned_dibs_[buffer_id]->references, -1); |
| 388 owned_dibs_[buffer_id]->references = count; | 407 owned_dibs_[buffer_id]->references = count; |
| 389 } | 408 } |
| 390 } | 409 } |
| 391 | 410 |
| 392 void VideoCaptureController::DoFrameInfoOnIOThread( | 411 void VideoCaptureController::DoFrameInfoOnIOThread() { |
| 393 const media::VideoCaptureCapability& info) { | |
| 394 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 412 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 395 DCHECK(owned_dibs_.empty()) | 413 DCHECK(owned_dibs_.empty()) |
| 396 << "Device is restarted without releasing shared memory."; | 414 << "Device is restarted without releasing shared memory."; |
| 397 | 415 |
| 416 // Allocate memory only when device has been started. |
| 417 if (state_ != video_capture::kStarted) |
| 418 return; |
| 419 |
| 398 bool frames_created = true; | 420 bool frames_created = true; |
| 399 const size_t needed_size = (info.width * info.height * 3) / 2; | 421 const size_t needed_size = (frame_info_.width * frame_info_.height * 3) / 2; |
| 400 { | 422 { |
| 401 base::AutoLock lock(lock_); | 423 base::AutoLock lock(lock_); |
| 402 for (size_t i = 1; i <= kNoOfDIBS; ++i) { | 424 for (size_t i = 1; i <= kNoOfDIBS; ++i) { |
| 403 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); | 425 scoped_ptr<base::SharedMemory> shared_memory(new base::SharedMemory()); |
| 404 if (!shared_memory->CreateAndMapAnonymous(needed_size)) { | 426 if (!shared_memory->CreateAndMapAnonymous(needed_size)) { |
| 405 frames_created = false; | 427 frames_created = false; |
| 406 break; | 428 break; |
| 407 } | 429 } |
| 408 SharedDIB* dib = new SharedDIB(shared_memory.release()); | 430 SharedDIB* dib = new SharedDIB(shared_memory.release()); |
| 409 owned_dibs_.insert(std::make_pair(i, dib)); | 431 owned_dibs_.insert(std::make_pair(i, dib)); |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 549 bool VideoCaptureController::ClientHasDIB() { | 571 bool VideoCaptureController::ClientHasDIB() { |
| 550 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | 572 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| 551 base::AutoLock lock(lock_); | 573 base::AutoLock lock(lock_); |
| 552 for (DIBMap::iterator dib_it = owned_dibs_.begin(); | 574 for (DIBMap::iterator dib_it = owned_dibs_.begin(); |
| 553 dib_it != owned_dibs_.end(); dib_it++) { | 575 dib_it != owned_dibs_.end(); dib_it++) { |
| 554 if (dib_it->second->references > 0) | 576 if (dib_it->second->references > 0) |
| 555 return true; | 577 return true; |
| 556 } | 578 } |
| 557 return false; | 579 return false; |
| 558 } | 580 } |
| OLD | NEW |