Chromium Code Reviews| Index: content/browser/renderer_host/video_capture_controller.cc |
| =================================================================== |
| --- content/browser/renderer_host/video_capture_controller.cc (revision 0) |
| +++ content/browser/renderer_host/video_capture_controller.cc (revision 0) |
| @@ -0,0 +1,196 @@ |
| +// Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "content/browser/renderer_host/video_capture_controller.h" |
| + |
| +#include "base/logging.h" |
| +#include "base/stl_util-inl.h" |
| +#include "content/browser/browser_thread.h" |
| +#include "content/browser/media_stream/video_capture_manager.h" |
| +#include "media/base/yuv_convert.h" |
| + |
| +// The number of TransportDIBs VideoCaptureController allocate. |
| +static const unsigned int kNoOfDIBS = 3; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
size_t ?
Per K
2011/05/23 12:05:47
Done.
|
| + |
| +VideoCaptureController::VideoCaptureController( |
| + ControllerId id, |
| + VideoCaptureController::EventHandler* event_handler) |
| + : report_ready_to_delete_(false), |
| + event_handler_(*event_handler), |
| + id_(id) {} |
| + |
| +VideoCaptureController::~VideoCaptureController() { |
| + // Delete all TransportDIBs |
|
scherkus (not reviewing)
2011/05/23 05:05:09
comments end w/ periods
Per K
2011/05/23 12:05:47
Done.
|
| + STLDeleteContainerPairSecondPointers(owned_dibs_.begin(), |
| + owned_dibs_.end()); |
| +} |
| + |
| +void VideoCaptureController::StartCapture( |
| + const media::VideoCaptureParams& params) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + params_ = params; |
| + media_stream::VideoCaptureManager* manager = |
| + media_stream::VideoCaptureManager::Get(); |
| + // Order the manager to start the actual capture. |
| + manager->Start(params, this); |
| +} |
| + |
| +void VideoCaptureController::StopCapture(Task* stopped_task) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| + |
| + media_stream::VideoCaptureManager* manager = |
| + media_stream::VideoCaptureManager::Get(); |
| + manager->Stop(params_.session_id, |
| + NewRunnableMethod(this, |
| + &VideoCaptureController::OnDeviceStopped, |
| + stopped_task)); |
| +} |
| + |
| +void VideoCaptureController::ReturnTransportDIB(TransportDIB::Handle handle) { |
| + DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); |
| +// Check if we own this handle |
|
scherkus (not reviewing)
2011/05/23 05:05:09
indent
Per K
2011/05/23 12:05:47
Done.
|
| + CHECK(owned_dibs_.find(handle) != owned_dibs_.end()); |
| + |
| + bool ready_to_delete; |
| + lock_.Acquire(); |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: use AutoLock with a scope
{
AutoLock l(loc
Per K
2011/05/23 12:05:47
Done.
|
| + free_dibs_.push_back(handle); |
| + ready_to_delete = (free_dibs_.size() == owned_dibs_.size()); |
| + lock_.Release(); |
| + |
| + if (report_ready_to_delete_ && ready_to_delete) { |
| + event_handler_.OnReadyToDelete(id_); |
| + } |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| +// Implements VideoCaptureDevice::EventHandler. |
| +void VideoCaptureController::OnIncomingCapturedFrame(const uint8* data, |
|
scherkus (not reviewing)
2011/05/23 05:05:09
which thread is this executing on? we're doing co
Per K
2011/05/23 12:05:47
This will be done by the thread running the captur
|
| + int length, |
| + base::Time timestamp) { |
| + TransportDIB::Handle handle; |
| + // Check if there is a TransportDIB to fill. |
| + bool buffer_exist = false; |
| + lock_.Acquire(); |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: use AutoLock with a scope
{
AutoLock l(loc
Per K
2011/05/23 12:05:47
Done.
|
| + if (!report_ready_to_delete_ && free_dibs_.size() > 0) { |
| + handle = free_dibs_.back(); |
| + free_dibs_.pop_back(); |
| + buffer_exist = true; |
| + } |
| + lock_.Release(); |
| + |
| + if (!buffer_exist) { |
| + return; |
| + } |
| + |
| + TransportDIB* dib = TransportDIB::Map(handle); |
| + uint8* target = static_cast<uint8*> (dib->memory()); |
|
scherkus (not reviewing)
2011/05/23 05:05:09
no space between > and (
Per K
2011/05/23 12:05:47
Done.
|
| + CHECK(dib->size() >= (unsigned int) (frame_info_.width*frame_info_.height*3) / |
|
scherkus (not reviewing)
2011/05/23 05:05:09
static_cast<>
Per K
2011/05/23 12:05:47
Done.
|
| + 2); |
| + |
| + // Do color conversion from the camera format to I420. |
| + switch (frame_info_.color) { |
| + case media::VideoCaptureDevice::kColorUnknown: // Color format not set |
| + break; |
| + case media::VideoCaptureDevice::kI420: { |
| + memcpy(target, data, (frame_info_.width * frame_info_.height * 3) / 2); |
| + break; |
| + } |
| + case media::VideoCaptureDevice::kYUY2: { |
| + uint8* yplane = target; |
| + uint8* uplane = target + frame_info_.width * frame_info_.height; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: remove extra space after +
Per K
2011/05/23 12:05:47
Done.
|
| + uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: remove extra space after +
Per K
2011/05/23 12:05:47
Done.
|
| + media::ConvertYUY2ToYUV(data, yplane, uplane, vplane, frame_info_.width, |
| + frame_info_.height); |
| + break; |
| + } |
| + case media::VideoCaptureDevice::kRGB24: { |
| +#if defined(OS_WIN) // RGB on Windows start at the bottom line. |
| + uint8* yplane = target; |
| + uint8* uplane = target + frame_info_.width * frame_info_.height; |
| + uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; |
| + int ystride = frame_info_.width; |
| + int uvstride = frame_info_.width / 2; |
| + int rgb_stride = - 3 * frame_info_.width; |
| + const uint8* rgb_src = data + 3 * frame_info_.width * |
| + (frame_info_.height -1); |
| +#else |
| + uint8* yplane = target; |
| + uint8* uplane = target + frame_info_.width * frame_info_.height; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: remove extra space after +
Per K
2011/05/23 12:05:47
Done.
|
| + uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: remove extra space after +
Per K
2011/05/23 12:05:47
Done.
|
| + int ystride = frame_info_.width; |
| + int uvstride = frame_info_.width / 2; |
| + int rgb_stride = 3 * frame_info_.width; |
| + const uint8* rgb_src = data; |
| +#endif |
| + media::ConvertRGB24ToYUV(rgb_src, yplane, uplane, vplane, |
| + frame_info_.width, frame_info_.height, |
| + rgb_stride, ystride, uvstride); |
| + break; |
| + } |
| + case media::VideoCaptureDevice::kARGB: { |
| + uint8* yplane = target; |
| + uint8* uplane = target + frame_info_.width * frame_info_.height; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: remove extra space after +
Per K
2011/05/23 12:05:47
Done.
|
| + uint8* vplane = uplane + (frame_info_.width * frame_info_.height) / 4; |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: remove extra space after +
Per K
2011/05/23 12:05:47
Done.
|
| + media::ConvertRGB32ToYUV(data, yplane, uplane, vplane, frame_info_.width, |
| + frame_info_.height, frame_info_.width * 4, |
| + frame_info_.width, frame_info_.width / 2); |
| + break; |
| + } |
| + default: |
| + NOTREACHED(); |
| + } |
| + |
| + event_handler_.OnBufferReady(id_, handle, timestamp); |
| +} |
| + |
| +void VideoCaptureController::OnError() { |
| + event_handler_.OnError(id_); |
| +} |
| + |
| +void VideoCaptureController::OnFrameInfo( |
| + const media::VideoCaptureDevice::Capability& info) { |
| + DCHECK(owned_dibs_.empty()); |
| + const size_t needed_size = (info.width * info.height * 3) / 2; |
| + for (unsigned int i = 0; i < kNoOfDIBS; ++i) { |
| + TransportDIB* dib = TransportDIB::Create(needed_size, i); |
| + if (!dib) { |
| + break; |
| + } |
| + // Lock needed since the buffers are used in OnIncomingFrame |
| + // and we need to use it there in order to avoid memcpy of complete frames. |
| + lock_.Acquire(); |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: use AutoLock with a scope
{
AutoLock l(loc
Per K
2011/05/23 12:05:47
Done.
|
| + owned_dibs_.insert(std::make_pair(dib->handle(), dib)); |
| + free_dibs_.push_back(dib->handle()); |
| + lock_.Release(); |
| + } |
| + frame_info_= info; |
| + |
| + // Check that all Dibs where created. |
| + if (owned_dibs_.size() != kNoOfDIBS) { |
|
scherkus (not reviewing)
2011/05/23 05:05:09
warning: accessing owned_dibs_ outside of lock
Per K
2011/05/23 12:05:47
Done.
|
| + event_handler_.OnError(id_); |
| + } |
| + event_handler_.OnFrameInfo(id_, info.width, info.height, |
| + info.frame_rate); |
| +} |
| + |
| +/////////////////////////////////////////////////////////////////////////////// |
| +// Called by VideoCaptureManager when a device have been stopped. |
| +// This will report to the event handler that this object is ready to be deleted |
| +// if all DIBS have been returned. |
| +void VideoCaptureController::OnDeviceStopped(Task* stopped_task) { |
| + bool ready_to_delete_now; |
| + lock_.Acquire(); |
|
scherkus (not reviewing)
2011/05/23 05:05:09
nit: use AutoLock with a scope
{
AutoLock l(loc
Per K
2011/05/23 12:05:47
Done.
|
| + // Set flag to indicate we need to report when all DIBs have been returned. |
| + report_ready_to_delete_ = true; |
| + ready_to_delete_now = (free_dibs_.size() == owned_dibs_.size()); |
| + lock_.Release(); |
| + if (ready_to_delete_now) { |
| + event_handler_.OnReadyToDelete(id_); |
| + } |
| + if (stopped_task) { |
|
scherkus (not reviewing)
2011/05/23 05:05:09
who would call OnDeviceStopped() w/o a task?
it l
Per K
2011/05/23 12:05:47
VideoCaptureController::StopCapture called from
V
|
| + stopped_task->Run(); |
| + delete stopped_task; |
| + } |
| +} |