Commit 1b3709ce authored by Ricky Liang's avatar Ricky Liang Committed by Commit Bot

RELAND: media: implement TakePhoto in Chrome OS camera HAL VideoCaptureDevice

Fix an out-of-bound memory access bug in unit tests.

Original change's description --------------------------------------------------

media: implement TakePhoto in Chrome OS camera HAL VideoCaptureDevice

This CL implements the TakePhoto() API for the Chrome OS camera HAL
VideoCaptureDevice, including the following features:

  - Full size still capture
  - Auto-focus, auto-exposure, and auto-white-balancing stabilization

BUG=chromium:832772
TEST=Run capture_unittests on DUT
TEST=Make sure TakePhoto() API works on
https://googlechrome.github.io/samples/image-capture/grab-frame-take-photo.html
TEST=Run capture_unittests on host with asan and lsan build
TBR=wuchengli@chromium.org,emircan@chromium.org

Change-Id: Ieafc98e07bbc39ac64347eea76baa3a496c0c775
Reviewed-on: https://chromium-review.googlesource.com/1059915Reviewed-by: default avatarRicky Liang <jcliang@chromium.org>
Commit-Queue: Ricky Liang <jcliang@chromium.org>
Cr-Commit-Position: refs/heads/master@{#558770}
parent a988115a
......@@ -223,6 +223,8 @@ component("capture_lib") {
if (is_chromeos) {
sources += [
"video/chromeos/camera_3a_controller.cc",
"video/chromeos/camera_3a_controller.h",
"video/chromeos/camera_buffer_factory.cc",
"video/chromeos/camera_buffer_factory.h",
"video/chromeos/camera_device_context.cc",
......@@ -342,6 +344,7 @@ test("capture_unittests") {
if (is_chromeos) {
sources += [
"video/chromeos/camera_3a_controller_unittest.cc",
"video/chromeos/camera_device_delegate_unittest.cc",
"video/chromeos/camera_hal_delegate_unittest.cc",
"video/chromeos/camera_hal_dispatcher_impl_unittest.cc",
......
This diff is collapsed.
// Copyright 2018 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.
#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_3A_CONTROLLER_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_3A_CONTROLLER_H_
#include <unordered_set>
#include "media/base/media_export.h"
#include "media/capture/video/chromeos/mojo/camera3.mojom.h"
#include "media/capture/video/chromeos/stream_buffer_manager.h"
namespace media {
// A class to control the auto-exposure, auto-focus, and auto-white-balancing
// operations and modes of the camera. For the detailed state transitions for
// auto-exposure, auto-focus, and auto-white-balancing, see
// https://source.android.com/devices/camera/camera3_3Amodes
class CAPTURE_EXPORT Camera3AController
: public CaptureMetadataDispatcher::ResultMetadataObserver {
public:
Camera3AController(const cros::mojom::CameraMetadataPtr& static_metadata,
CaptureMetadataDispatcher* capture_metadata_dispatcher,
scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~Camera3AController() final;
// Trigger the camera to start exposure, focus, and white-balance metering and
// lock them for still capture.
void Stabilize3AForStillCapture(base::OnceClosure on_3a_stabilized_callback);
// CaptureMetadataDispatcher::ResultMetadataObserver implementation.
void OnResultMetadataAvailable(
const cros::mojom::CameraMetadataPtr& result_metadata) final;
// Enable the auto-focus mode suitable for still capture.
void SetAutoFocusModeForStillCapture();
// Enable the auto-focus mode suitable for video recording.
void SetAutoFocusModeForVideoRecording();
base::WeakPtr<Camera3AController> GetWeakPtr();
private:
void Set3AMode(cros::mojom::CameraMetadataTag tag, uint8_t target_mode);
bool Is3AStabilized();
CaptureMetadataDispatcher* capture_metadata_dispatcher_;
const scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
std::unordered_set<cros::mojom::AndroidControlAfMode> available_af_modes_;
cros::mojom::AndroidControlAfMode af_mode_;
cros::mojom::AndroidControlAfState af_state_;
// |af_mode_set_| is set to true when the AF mode is synchronized between the
// HAL and the Camera3AController.
bool af_mode_set_;
std::unordered_set<cros::mojom::AndroidControlAeMode> available_ae_modes_;
cros::mojom::AndroidControlAeMode ae_mode_;
cros::mojom::AndroidControlAeState ae_state_;
// |ae_mode_set_| is set to true when the AE mode is synchronized between the
// HAL and the Camera3AController.
bool ae_mode_set_;
std::unordered_set<cros::mojom::AndroidControlAwbMode> available_awb_modes_;
cros::mojom::AndroidControlAwbMode awb_mode_;
cros::mojom::AndroidControlAwbState awb_state_;
// |awb_mode_set_| is set to true when the AWB mode is synchronized between
// the HAL and the Camera3AController.
bool awb_mode_set_;
base::OnceClosure on_3a_mode_set_callback_;
base::OnceClosure on_3a_stabilized_callback_;
base::WeakPtrFactory<Camera3AController> weak_ptr_factory_;
DISALLOW_IMPLICIT_CONSTRUCTORS(Camera3AController);
};
} // namespace media
#endif // MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_3A_CONTROLLER_H_
This diff is collapsed.
......@@ -21,9 +21,12 @@ CameraBufferFactory::CreateGpuMemoryBuffer(const gfx::Size& size,
LOG(ERROR) << "GpuMemoryBufferManager not set";
return std::unique_ptr<gfx::GpuMemoryBuffer>();
}
return buf_manager->CreateGpuMemoryBuffer(
size, format, gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
gpu::kNullSurfaceHandle);
gfx::BufferUsage buffer_usage = gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE;
if (format == gfx::BufferFormat::R_8) {
buffer_usage = gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE;
}
return buf_manager->CreateGpuMemoryBuffer(size, format, buffer_usage,
gpu::kNullSurfaceHandle);
}
// There's no good way to resolve the HAL pixel format to the platform-specific
......
......@@ -56,7 +56,7 @@ class CAPTURE_EXPORT CameraDeviceContext {
//
// ConstructDefaultRequestSettings() ->
// OnConstructedDefaultRequestSettings() ->
// |stream_buffer_manager_|->StartCapture()
// |stream_buffer_manager_|->StartPreview()
//
// In the kCapturing state the |stream_buffer_manager_| runs the capture
// loop to send capture requests and process capture results.
......
......@@ -17,10 +17,21 @@
namespace media {
class CameraHalDelegate;
class Camera3AController;
class CameraDeviceContext;
class CameraHalDelegate;
class StreamBufferManager;
enum class StreamType : int32_t {
kPreview = 0,
kStillCapture = 1,
kUnknown,
};
std::string StreamTypeToString(StreamType stream_type);
std::ostream& operator<<(std::ostream& os, StreamType stream_type);
// The interface to register buffer with and send capture request to the
// camera HAL.
class CAPTURE_EXPORT StreamCaptureInterface {
......@@ -122,10 +133,14 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
// settings of the stream in |stream_context_|.
// OnConstructedDefaultRequestSettings sets the request settings in
// |streams_context_|. If there's no error
// OnConstructedDefaultRequestSettings calls StartCapture to start the video
// capture loop.
void ConstructDefaultRequestSettings();
void OnConstructedDefaultRequestSettings(
// OnConstructedDefaultPreviewRequestSettings calls StartPreview to start the
// video capture loop.
// OnConstructDefaultStillCaptureRequestSettings triggers
// |stream_buffer_manager_| to request a still capture.
void ConstructDefaultRequestSettings(StreamType stream_type);
void OnConstructedDefaultPreviewRequestSettings(
cros::mojom::CameraMetadataPtr settings);
void OnConstructedDefaultStillCaptureRequestSettings(
cros::mojom::CameraMetadataPtr settings);
// StreamCaptureInterface implementations. These methods are called by
......@@ -151,8 +166,12 @@ class CAPTURE_EXPORT CameraDeviceDelegate final {
CameraDeviceContext* device_context_;
std::queue<VideoCaptureDevice::TakePhotoCallback> take_photo_callbacks_;
std::unique_ptr<StreamBufferManager> stream_buffer_manager_;
std::unique_ptr<Camera3AController> camera_3a_controller_;
// Stores the static camera characteristics of the camera device. E.g. the
// supported formats and resolution, various available exposure and apeture
// settings, etc.
......
......@@ -110,8 +110,11 @@ class MockCameraDevice : public cros::mojom::Camera3DeviceOps {
DISALLOW_COPY_AND_ASSIGN(MockCameraDevice);
};
constexpr int32_t kJpegMaxBufferSize = 1024;
constexpr size_t kDefaultWidth = 1280, kDefaultHeight = 720;
const VideoCaptureDeviceDescriptor kDefaultDescriptor("Fake device", "0");
const VideoCaptureFormat kDefaultCaptureFormat(gfx::Size(1280, 720),
const VideoCaptureFormat kDefaultCaptureFormat(gfx::Size(kDefaultWidth,
kDefaultHeight),
30.0,
PIXEL_FORMAT_I420);
......@@ -153,16 +156,60 @@ class CameraDeviceDelegateTest : public ::testing::Test {
cros::mojom::CameraInfoPtr camera_info = cros::mojom::CameraInfo::New();
cros::mojom::CameraMetadataPtr static_metadata =
cros::mojom::CameraMetadata::New();
static_metadata->entry_count = 3;
static_metadata->entry_capacity = 3;
static_metadata->entries =
std::vector<cros::mojom::CameraMetadataEntryPtr>();
cros::mojom::CameraMetadataEntryPtr entry =
cros::mojom::CameraMetadataEntry::New();
entry->index = 0;
entry->tag = cros::mojom::CameraMetadataTag::
ANDROID_SCALER_AVAILABLE_STREAM_CONFIGURATIONS;
entry->type = cros::mojom::EntryType::TYPE_INT32;
entry->count = 12;
std::vector<int32_t> stream_configurations(entry->count);
stream_configurations[0] = static_cast<int32_t>(
cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_IMPLEMENTATION_DEFINED);
stream_configurations[1] = kDefaultWidth;
stream_configurations[2] = kDefaultHeight;
stream_configurations[3] = static_cast<int32_t>(
cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT);
stream_configurations[4] = static_cast<int32_t>(
cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888);
stream_configurations[5] = kDefaultWidth;
stream_configurations[6] = kDefaultHeight;
stream_configurations[7] = static_cast<int32_t>(
cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT);
stream_configurations[8] = static_cast<int32_t>(
cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB);
stream_configurations[9] = kDefaultWidth;
stream_configurations[10] = kDefaultHeight;
stream_configurations[11] = static_cast<int32_t>(
cros::mojom::Camera3StreamType::CAMERA3_STREAM_OUTPUT);
uint8_t* as_int8 = reinterpret_cast<uint8_t*>(stream_configurations.data());
entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
static_metadata->entries->push_back(std::move(entry));
entry = cros::mojom::CameraMetadataEntry::New();
entry->index = 1;
entry->tag = cros::mojom::CameraMetadataTag::ANDROID_SENSOR_ORIENTATION;
entry->type = cros::mojom::EntryType::TYPE_INT32;
entry->count = 1;
entry->data = std::vector<uint8_t>(4, 0);
static_metadata->entries =
std::vector<cros::mojom::CameraMetadataEntryPtr>();
static_metadata->entries->push_back(std::move(entry));
entry = cros::mojom::CameraMetadataEntry::New();
entry->index = 2;
entry->tag = cros::mojom::CameraMetadataTag::ANDROID_JPEG_MAX_SIZE;
entry->type = cros::mojom::EntryType::TYPE_INT32;
entry->count = 1;
int32_t jpeg_max_size = kJpegMaxBufferSize;
as_int8 = reinterpret_cast<uint8_t*>(&jpeg_max_size);
entry->data.assign(as_int8, as_int8 + entry->count * sizeof(int32_t));
static_metadata->entries->push_back(std::move(entry));
switch (camera_id) {
case 0:
camera_info->facing = cros::mojom::CameraFacing::CAMERA_FACING_FRONT;
......@@ -195,23 +242,17 @@ class CameraDeviceDelegateTest : public ::testing::Test {
base::OnceCallback<void(int32_t,
cros::mojom::Camera3StreamConfigurationPtr)>&
callback) {
ASSERT_EQ(1u, config->streams.size());
ASSERT_EQ(static_cast<uint32_t>(kDefaultCaptureFormat.frame_size.width()),
config->streams[0]->width);
ASSERT_EQ(static_cast<uint32_t>(kDefaultCaptureFormat.frame_size.height()),
config->streams[0]->height);
ASSERT_EQ(cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888,
config->streams[0]->format);
config->streams[0]->usage = 0;
config->streams[0]->max_buffers = 1;
ASSERT_EQ(2u, config->streams.size());
for (size_t i = 0; i < config->streams.size(); ++i) {
config->streams[i]->usage = 0;
config->streams[i]->max_buffers = 1;
}
std::move(callback).Run(0, std::move(config));
}
void ConstructFakeRequestSettings(
cros::mojom::Camera3RequestTemplate type,
base::OnceCallback<void(cros::mojom::CameraMetadataPtr)>& callback) {
ASSERT_EQ(cros::mojom::Camera3RequestTemplate::CAMERA3_TEMPLATE_PREVIEW,
type);
cros::mojom::CameraMetadataPtr fake_settings =
cros::mojom::CameraMetadata::New();
fake_settings->entry_count = 1;
......@@ -291,10 +332,27 @@ class CameraDeviceDelegateTest : public ::testing::Test {
.Times(1)
.WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
CreateFakeGpuMemoryBuffer));
EXPECT_CALL(
mock_gpu_memory_buffer_manager_,
CreateGpuMemoryBuffer(_, gfx::BufferFormat::R_8,
gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE,
gpu::kNullSurfaceHandle))
.Times(1)
.WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
CreateFakeGpuMemoryBuffer));
EXPECT_CALL(
mock_gpu_memory_buffer_manager_,
CreateGpuMemoryBuffer(gfx::Size(kDefaultWidth, kDefaultHeight),
gfx::BufferFormat::YUV_420_BIPLANAR,
gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
gpu::kNullSurfaceHandle))
.Times(1)
.WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
CreateFakeGpuMemoryBuffer));
EXPECT_CALL(mock_gpu_memory_buffer_manager_,
CreateGpuMemoryBuffer(
gfx::Size(1280, 720), gfx::BufferFormat::YUV_420_BIPLANAR,
gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
gfx::Size(kJpegMaxBufferSize, 1), gfx::BufferFormat::R_8,
gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE,
gpu::kNullSurfaceHandle))
.Times(1)
.WillOnce(Invoke(&unittest_internal::MockGpuMemoryBufferManager::
......
......@@ -130,21 +130,25 @@ void CameraHalDelegate::GetSupportedFormats(
reinterpret_cast<int64_t*>((*min_frame_durations)->data.data());
for (size_t i = 0; i < (*min_frame_durations)->count;
i += kStreamDurationSize) {
int32_t format = base::checked_cast<int32_t>(iter[kStreamFormatOffset]);
auto hal_format =
static_cast<cros::mojom::HalPixelFormat>(iter[kStreamFormatOffset]);
int32_t width = base::checked_cast<int32_t>(iter[kStreamWidthOffset]);
int32_t height = base::checked_cast<int32_t>(iter[kStreamHeightOffset]);
int64_t duration = iter[kStreamDurationOffset];
iter += kStreamDurationSize;
if (hal_format == cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB) {
// Skip BLOB formats and use it only for TakePicture() since it's
// inefficient to stream JPEG frames for CrOS camera HAL.
continue;
}
if (duration <= 0) {
LOG(ERROR) << "Ignoring invalid frame duration: " << duration;
continue;
}
float max_fps = 1.0 * 1000000000LL / duration;
DVLOG(1) << "[" << std::hex << format << " " << std::dec << width << " "
<< height << " " << duration << "]";
auto hal_format = static_cast<cros::mojom::HalPixelFormat>(format);
const ChromiumPixelFormat cr_format =
camera_buffer_factory_->ResolveStreamBufferFormat(hal_format);
if (cr_format.video_format == PIXEL_FORMAT_UNKNOWN) {
......@@ -327,6 +331,7 @@ void CameraHalDelegate::OnGotCameraInfoOnIpcThread(
LOG(ERROR) << "Failed to get camera info. Camera id: " << camera_id;
}
// In case of error |camera_info| is empty.
SortCameraMetadata(&camera_info->static_camera_characteristics);
camera_info_[std::to_string(camera_id)] = std::move(camera_info);
if (camera_info_.size() == num_builtin_cameras_) {
builtin_camera_info_updated_.Signal();
......
......@@ -4,22 +4,43 @@
#include "media/capture/video/chromeos/camera_metadata_utils.h"
#include <set>
#include <algorithm>
#include <unordered_set>
namespace media {
const cros::mojom::CameraMetadataEntryPtr* GetMetadataEntry(
cros::mojom::CameraMetadataEntryPtr* GetMetadataEntry(
const cros::mojom::CameraMetadataPtr& camera_metadata,
cros::mojom::CameraMetadataTag tag) {
if (!camera_metadata->entries.has_value()) {
if (!camera_metadata || !camera_metadata->entries.has_value()) {
return nullptr;
}
for (const auto& entry : camera_metadata->entries.value()) {
if (entry->tag == tag) {
return &entry;
}
// We assume the metadata entries are sorted.
auto iter = std::find_if(camera_metadata->entries.value().begin(),
camera_metadata->entries.value().end(),
[tag](const cros::mojom::CameraMetadataEntryPtr& e) {
return e->tag == tag;
});
if (iter == camera_metadata->entries.value().end()) {
return nullptr;
}
return &(camera_metadata->entries.value()[(*iter)->index]);
}
void SortCameraMetadata(cros::mojom::CameraMetadataPtr* camera_metadata) {
if (!camera_metadata || !(*camera_metadata) ||
!(*camera_metadata)->entries.has_value()) {
return;
}
std::sort((*camera_metadata)->entries.value().begin(),
(*camera_metadata)->entries.value().end(),
[](const cros::mojom::CameraMetadataEntryPtr& a,
const cros::mojom::CameraMetadataEntryPtr& b) {
return a->tag < b->tag;
});
for (size_t i = 0; i < (*camera_metadata)->entries.value().size(); ++i) {
(*camera_metadata)->entries.value()[i]->index = i;
}
return nullptr;
}
void MergeMetadata(cros::mojom::CameraMetadataPtr* to,
......@@ -34,7 +55,7 @@ void MergeMetadata(cros::mojom::CameraMetadataPtr* to,
return;
}
std::set<cros::mojom::CameraMetadataTag> tags;
std::unordered_set<cros::mojom::CameraMetadataTag> tags;
if ((*to)->entries) {
for (const auto& entry : (*to)->entries.value()) {
tags.insert(entry->tag);
......
......@@ -5,16 +5,21 @@
#ifndef MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_METADATA_UTILS_H_
#define MEDIA_CAPTURE_VIDEO_CHROMEOS_CAMERA_METADATA_UTILS_H_
#include "media/capture/capture_export.h"
#include "media/capture/video/chromeos/mojo/camera_metadata.mojom.h"
namespace media {
const cros::mojom::CameraMetadataEntryPtr* GetMetadataEntry(
CAPTURE_EXPORT cros::mojom::CameraMetadataEntryPtr* GetMetadataEntry(
const cros::mojom::CameraMetadataPtr& camera_metadata,
cros::mojom::CameraMetadataTag tag);
void MergeMetadata(cros::mojom::CameraMetadataPtr* to,
const cros::mojom::CameraMetadataPtr& from);
// Sort the camera metadata entries using the metadata tags.
CAPTURE_EXPORT void SortCameraMetadata(
cros::mojom::CameraMetadataPtr* camera_metadata);
CAPTURE_EXPORT void MergeMetadata(cros::mojom::CameraMetadataPtr* to,
const cros::mojom::CameraMetadataPtr& from);
} // namespace media
......
......@@ -51,6 +51,8 @@ gbm_device* CreateGbmDevice() {
uint32_t GetDrmFormat(gfx::BufferFormat gfx_format) {
switch (gfx_format) {
case gfx::BufferFormat::R_8:
return DRM_FORMAT_R8;
case gfx::BufferFormat::YUV_420_BIPLANAR:
return DRM_FORMAT_NV12;
// Add more formats when needed.
......@@ -186,7 +188,8 @@ LocalGpuMemoryBufferManager::CreateGpuMemoryBuffer(
gfx::BufferFormat format,
gfx::BufferUsage usage,
gpu::SurfaceHandle surface_handle) {
if (usage != gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE) {
if (usage != gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE &&
usage != gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE) {
LOG(ERROR) << "Unsupported gfx::BufferUsage" << static_cast<int>(usage);
return std::unique_ptr<gfx::GpuMemoryBuffer>();
}
......
......@@ -31,6 +31,9 @@ struct SupportedFormat {
// support YUV flexbile format video streams.
{cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_YCbCr_420_888,
{PIXEL_FORMAT_NV12, gfx::BufferFormat::YUV_420_BIPLANAR}},
// FIXME(jcliang): MJPEG is not accurate; we should have BLOB or JPEG
{cros::mojom::HalPixelFormat::HAL_PIXEL_FORMAT_BLOB,
{PIXEL_FORMAT_MJPEG, gfx::BufferFormat::R_8}},
// Add more mappings when we have more devices.
};
......@@ -51,6 +54,8 @@ uint32_t PixFormatVideoToDrm(VideoPixelFormat from) {
switch (from) {
case PIXEL_FORMAT_NV12:
return DRM_FORMAT_NV12;
case PIXEL_FORMAT_MJPEG:
return DRM_FORMAT_R8;
default:
// Unsupported format.
return 0;
......
......@@ -6,6 +6,10 @@
#include <memory>
#if defined(OS_CHROMEOS)
#include "media/capture/video/chromeos/stream_buffer_manager.h"
#endif
using ::testing::Return;
namespace media {
......@@ -17,8 +21,9 @@ class FakeGpuMemoryBuffer : public gfx::GpuMemoryBuffer {
public:
FakeGpuMemoryBuffer(const gfx::Size& size, gfx::BufferFormat format)
: size_(size), format_(format) {
// We use only NV12 in unit tests.
EXPECT_EQ(gfx::BufferFormat::YUV_420_BIPLANAR, format);
// We use only NV12 or R8 in unit tests.
EXPECT_TRUE(format == gfx::BufferFormat::YUV_420_BIPLANAR ||
format == gfx::BufferFormat::R_8);
size_t y_plane_size = size_.width() * size_.height();
size_t uv_plane_size = size_.width() * size_.height() / 2;
......@@ -36,6 +41,15 @@ class FakeGpuMemoryBuffer : public gfx::GpuMemoryBuffer {
handle_.native_pixmap_handle.planes.push_back(gfx::NativePixmapPlane(
size_.width(), handle_.native_pixmap_handle.planes[0].size,
uv_plane_size));
// For faking a valid JPEG blob buffer.
if (base::checked_cast<size_t>(size_.width()) >= sizeof(Camera3JpegBlob)) {
Camera3JpegBlob* header = reinterpret_cast<Camera3JpegBlob*>(
reinterpret_cast<uintptr_t>(data_.data()) + size_.width() -
sizeof(Camera3JpegBlob));
header->jpeg_blob_id = kCamera3JpegBlobId;
header->jpeg_size = size_.width();
}
#endif
}
......
......@@ -664,13 +664,6 @@ WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_TakePhoto) {
if (!descriptor)
return;
#if defined(OS_CHROMEOS)
// TODO(jcliang): Remove this after we implement TakePhoto.
if (VideoCaptureDeviceFactoryChromeOS::ShouldEnable()) {
return;
}
#endif
#if defined(OS_ANDROID)
// TODO(mcasas): fails on Lollipop devices, reconnect https://crbug.com/646840
if (base::android::BuildInfo::GetInstance()->sdk_int() <
......@@ -713,13 +706,6 @@ WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_GetPhotoState) {
if (!descriptor)
return;
#if defined(OS_CHROMEOS)
// TODO(jcliang): Remove this after we implement GetPhotoCapabilities.
if (VideoCaptureDeviceFactoryChromeOS::ShouldEnable()) {
return;
}
#endif
#if defined(OS_ANDROID)
// TODO(mcasas): fails on Lollipop devices, reconnect https://crbug.com/646840
if (base::android::BuildInfo::GetInstance()->sdk_int() <
......@@ -745,6 +731,9 @@ WRAPPED_TEST_P(VideoCaptureDeviceTest, MAYBE_GetPhotoState) {
base::BindOnce(&MockImageCaptureClient::DoOnGetPhotoState,
image_capture_client_);
// On Chrome OS AllocateAndStart() is asynchronous, so wait until we get the
// first frame.
WaitForCapturedFrame();
base::RunLoop run_loop;
base::Closure quit_closure = BindToCurrentLoop(run_loop.QuitClosure());
EXPECT_CALL(*image_capture_client_.get(), OnCorrectGetPhotoState())
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment