Chromium Code Reviews| Index: media/video/capture/fake_video_capture_device.cc |
| diff --git a/media/video/capture/fake_video_capture_device.cc b/media/video/capture/fake_video_capture_device.cc |
| index 34f8f20d701d8b3e2accd3b433db342a2b5b8ebe..82735df0680df919e8c857e91768ee86c04b5521 100644 |
| --- a/media/video/capture/fake_video_capture_device.cc |
| +++ b/media/video/capture/fake_video_capture_device.cc |
| @@ -10,31 +10,41 @@ |
| #include "base/memory/scoped_ptr.h" |
| #include "base/strings/stringprintf.h" |
| #include "media/audio/fake_audio_input_stream.h" |
| +#include "media/base/encoded_bitstream_buffer.h" |
| #include "third_party/skia/include/core/SkBitmap.h" |
| #include "third_party/skia/include/core/SkCanvas.h" |
| #include "third_party/skia/include/core/SkPaint.h" |
| namespace media { |
| -static const int kFakeCaptureTimeoutMs = 50; |
| -static const int kFakeCaptureBeepCycle = 20; // Visual beep every 1s. |
| +namespace { |
|
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
not adding value
sheu
2013/08/22 22:40:31
Fine :-P
|
| + |
| +const int kFakeCaptureTimeoutMs = 50; |
| +const int kFakeCaptureBeepCycle = 20; // Visual beep every 1s. |
| enum { kNumberOfFakeDevices = 2 }; |
| +} // anonymous namespace |
| + |
| bool FakeVideoCaptureDevice::fail_next_create_ = false; |
| -void FakeVideoCaptureDevice::GetDeviceNames(Names* const device_names) { |
| +void FakeVideoCaptureDevice::GetDeviceNames(Names* const device_names, |
| + bool encoded_capture) { |
| // Empty the name list. |
| device_names->erase(device_names->begin(), device_names->end()); |
| for (int n = 0; n < kNumberOfFakeDevices; n++) { |
| Name name; |
| name.unique_id = base::StringPrintf("/dev/video%d", n); |
| - name.device_name = base::StringPrintf("fake_device_%d", n); |
| + name.device_name = base::StringPrintf( |
| + "fake_%sdevice_%d", |
| + (encoded_capture ? "encoded_" : ""), |
| + n); |
| device_names->push_back(name); |
| } |
| } |
| -VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name) { |
| +VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name, |
| + bool encoded_capture) { |
| if (fail_next_create_) { |
| fail_next_create_ = false; |
| return NULL; |
| @@ -42,7 +52,7 @@ VideoCaptureDevice* FakeVideoCaptureDevice::Create(const Name& device_name) { |
| for (int n = 0; n < kNumberOfFakeDevices; ++n) { |
| std::string possible_id = base::StringPrintf("/dev/video%d", n); |
| if (device_name.unique_id.compare(possible_id) == 0) { |
| - return new FakeVideoCaptureDevice(device_name); |
| + return new FakeVideoCaptureDevice(device_name, encoded_capture); |
| } |
| } |
| return NULL; |
| @@ -52,8 +62,10 @@ void FakeVideoCaptureDevice::SetFailNextCreate() { |
| fail_next_create_ = true; |
| } |
| -FakeVideoCaptureDevice::FakeVideoCaptureDevice(const Name& device_name) |
| +FakeVideoCaptureDevice::FakeVideoCaptureDevice(const Name& device_name, |
| + bool encoded_capture) |
| : device_name_(device_name), |
| + encoded_capture_(encoded_capture), |
| observer_(NULL), |
| state_(kIdle), |
| capture_thread_("CaptureThread"), |
| @@ -69,39 +81,71 @@ FakeVideoCaptureDevice::~FakeVideoCaptureDevice() { |
| DCHECK(!capture_thread_.IsRunning()); |
| } |
| +VideoEncodingCapabilities FakeVideoCaptureDevice::GetEncodingCapabilities() { |
| + media::VideoEncodingCapabilities capabilities; |
| + if (encoded_capture_) { |
| + media::VideoEncodingConfig config; |
| + config.codec_type = kCodecVP8; |
| + config.codec_name = "VP8"; |
| + config.max_resolution.SetSize(640, 480); |
| + config.max_frames_per_second = 30; |
| + config.max_bitrate = 1024 * 1024; |
| + capabilities.push_back(config); |
| + } |
| + return capabilities; |
| +} |
| + |
| +void FakeVideoCaptureDevice::TryConfigureEncodedBitstream( |
| + const RuntimeVideoEncodingParameters& params) { |
| + DCHECK(encoded_capture_); |
| + DCHECK(observer_); |
| + observer_->OnBitstreamConfigChanged(params); |
| +} |
| + |
| void FakeVideoCaptureDevice::Allocate(int width, |
| - int height, |
| - int frame_rate, |
| - EventHandler* observer) { |
| + int height, |
| + int frame_rate, |
| + EventHandler* observer) { |
| if (state_ != kIdle) { |
| return; // Wrong state. |
| } |
| + DCHECK(!observer_); |
| observer_ = observer; |
| - VideoCaptureCapability current_settings; |
| - current_settings.color = VideoCaptureCapability::kI420; |
| - current_settings.expected_capture_delay = 0; |
| - current_settings.interlaced = false; |
| - if (width > 320) { // VGA |
| - current_settings.width = 640; |
| - current_settings.height = 480; |
| - current_settings.frame_rate = 30; |
| - } else { // QVGA |
| - current_settings.width = 320; |
| - current_settings.height = 240; |
| - current_settings.frame_rate = 30; |
| - } |
| + state_ = kAllocated; |
| - size_t fake_frame_size = |
| - current_settings.width * current_settings.height * 3 / 2; |
| - fake_frame_.reset(new uint8[fake_frame_size]); |
| - memset(fake_frame_.get(), 0, fake_frame_size); |
| - frame_size_ = fake_frame_size; |
| - frame_width_ = current_settings.width; |
| - frame_height_ = current_settings.height; |
| + if (encoded_capture_) { |
| + media::VideoEncodingParameters params; |
| + params.codec_name = std::string("VP8"); |
| + params.resolution.SetSize(640, 480); |
| + params.runtime_params.target_bitrate = 512; |
| + params.runtime_params.max_bitrate = 1024; |
| + params.runtime_params.frames_per_second = 30; |
| + observer_->OnEncodedFrameInfo(params); |
| + } else { |
| + VideoCaptureCapability current_settings; |
| + current_settings.color = VideoCaptureCapability::kI420; |
| + current_settings.expected_capture_delay = 0; |
| + current_settings.interlaced = false; |
| + if (width > 320) { // VGA |
| + current_settings.width = 640; |
| + current_settings.height = 480; |
| + current_settings.frame_rate = 30; |
| + } else { // QVGA |
| + current_settings.width = 320; |
| + current_settings.height = 240; |
| + current_settings.frame_rate = 30; |
| + } |
| - state_ = kAllocated; |
| - observer_->OnFrameInfo(current_settings); |
| + size_t fake_frame_size = |
| + current_settings.width * current_settings.height * 3 / 2; |
| + fake_frame_.reset(new uint8[fake_frame_size]); |
| + memset(fake_frame_.get(), 0, fake_frame_size); |
| + frame_size_ = fake_frame_size; |
| + frame_width_ = current_settings.width; |
| + frame_height_ = current_settings.height; |
| + observer_->OnFrameInfo(current_settings); |
| + } |
| } |
| void FakeVideoCaptureDevice::Start() { |
| @@ -130,6 +174,7 @@ void FakeVideoCaptureDevice::DeAllocate() { |
| } |
| capture_thread_.Stop(); |
| state_ = kIdle; |
| + observer_ = NULL; |
| } |
| const VideoCaptureDevice::Name& FakeVideoCaptureDevice::device_name() { |
| @@ -143,57 +188,70 @@ void FakeVideoCaptureDevice::OnCaptureTask() { |
| memset(fake_frame_.get(), 0, frame_size_); |
|
Ami GONE FROM CHROMIUM
2013/06/18 18:35:55
only used in the not-encoding case
sheu
2013/08/22 22:40:31
Also used for encoding. Changed up a bit here.
|
| - SkBitmap bitmap; |
| - bitmap.setConfig(SkBitmap::kA8_Config, frame_width_, frame_height_, |
| - frame_width_); |
| - bitmap.setPixels(fake_frame_.get()); |
| - |
| - SkCanvas canvas(bitmap); |
| - |
| - // Draw a sweeping circle to show an animation. |
| - int radius = std::min(frame_width_, frame_height_) / 4; |
| - SkRect rect = SkRect::MakeXYWH( |
| - frame_width_ / 2 - radius, frame_height_ / 2 - radius, |
| - 2 * radius, 2 * radius); |
| - |
| - SkPaint paint; |
| - paint.setStyle(SkPaint::kFill_Style); |
| - |
| - // Only Y plane is being drawn and this gives 50% grey on the Y |
| - // plane. The result is a light green color in RGB space. |
| - paint.setAlpha(128); |
| - |
| - int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) / |
| - kFakeCaptureBeepCycle; |
| - if (!end_angle) |
| - end_angle = 360; |
| - canvas.drawArc(rect, 0, end_angle, true, paint); |
| - |
| - // Draw current time. |
| - int elapsed_ms = kFakeCaptureTimeoutMs * frame_count_; |
| - int milliseconds = elapsed_ms % 1000; |
| - int seconds = (elapsed_ms / 1000) % 60; |
| - int minutes = (elapsed_ms / 1000 / 60) % 60; |
| - int hours = (elapsed_ms / 1000 / 60 / 60) % 60; |
| - |
| - std::string time_string = |
| - base::StringPrintf("%d:%02d:%02d:%03d %d", hours, minutes, |
| - seconds, milliseconds, frame_count_); |
| - canvas.scale(3, 3); |
| - canvas.drawText(time_string.data(), time_string.length(), 30, 20, |
| - paint); |
| - |
| - if (frame_count_ % kFakeCaptureBeepCycle == 0) { |
| - // Generate a synchronized beep sound if there is one audio input |
| - // stream created. |
| - FakeAudioInputStream::BeepOnce(); |
| - } |
| - |
| - frame_count_++; |
| - |
| - // Give the captured frame to the observer. |
| - observer_->OnIncomingCapturedFrame( |
| - fake_frame_.get(), frame_size_, base::Time::Now(), 0, false, false); |
| + if (encoded_capture_) { |
| + // Just return empty frames. |
| + scoped_refptr<media::EncodedBitstreamBuffer> buffer = |
| + observer_->ReserveOutputEncodedBitstreamBuffer(); |
| + if (buffer) { |
| + observer_->OnIncomingCapturedEncodedBitstreamBuffer( |
| + buffer, |
| + 0, |
| + base::Time::Now()); |
| + } |
| + } else { |
| + SkBitmap bitmap; |
| + bitmap.setConfig(SkBitmap::kA8_Config, frame_width_, frame_height_, |
| + frame_width_); |
| + bitmap.setPixels(fake_frame_.get()); |
| + |
| + SkCanvas canvas(bitmap); |
| + |
| + // Draw a sweeping circle to show an animation. |
| + int radius = std::min(frame_width_, frame_height_) / 4; |
| + SkRect rect = SkRect::MakeXYWH( |
| + frame_width_ / 2 - radius, frame_height_ / 2 - radius, |
| + 2 * radius, 2 * radius); |
| + |
| + SkPaint paint; |
| + paint.setStyle(SkPaint::kFill_Style); |
| + |
| + // Only Y plane is being drawn and this gives 50% grey on the Y |
| + // plane. The result is a light green color in RGB space. |
| + paint.setAlpha(128); |
| + |
| + int end_angle = (frame_count_ % kFakeCaptureBeepCycle * 360) / |
| + kFakeCaptureBeepCycle; |
| + if (!end_angle) |
| + end_angle = 360; |
| + canvas.drawArc(rect, 0, end_angle, true, paint); |
| + |
| + // Draw current time. |
| + int elapsed_ms = kFakeCaptureTimeoutMs * frame_count_; |
| + int milliseconds = elapsed_ms % 1000; |
| + int seconds = (elapsed_ms / 1000) % 60; |
| + int minutes = (elapsed_ms / 1000 / 60) % 60; |
| + int hours = (elapsed_ms / 1000 / 60 / 60) % 60; |
| + |
| + std::string time_string = |
| + base::StringPrintf("%d:%02d:%02d:%03d %d", hours, minutes, |
| + seconds, milliseconds, frame_count_); |
| + canvas.scale(3, 3); |
| + canvas.drawText(time_string.data(), time_string.length(), 30, 20, |
| + paint); |
| + |
| + if (frame_count_ % kFakeCaptureBeepCycle == 0) { |
| + // Generate a synchronized beep sound if there is one audio input |
| + // stream created. |
| + FakeAudioInputStream::BeepOnce(); |
| + } |
| + |
| + frame_count_++; |
| + |
| + // Give the captured frame to the observer. |
| + observer_->OnIncomingCapturedFrame( |
| + fake_frame_.get(), frame_size_, base::Time::Now(), 0, false, false); |
| + } |
| + |
| // Reschedule next CaptureTask. |
| capture_thread_.message_loop()->PostDelayedTask( |
| FROM_HERE, |