blob: b82fa2b60bd8ccb1b1204fd3ee93098367c27c4f [file] [log] [blame]
// 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.
#include "media/capture/video/chromeos/request_builder.h"
#include <utility>
#include "media/capture/video/chromeos/camera_device_context.h"
#include "mojo/public/cpp/platform/platform_handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
namespace media {
RequestBuilder::RequestBuilder(CameraDeviceContext* device_context,
RequestBufferCallback request_buffer_callback)
: device_context_(device_context),
frame_number_(0),
request_buffer_callback_(std::move(request_buffer_callback)) {}
RequestBuilder::~RequestBuilder() = default;
cros::mojom::Camera3CaptureRequestPtr RequestBuilder::BuildRequest(
std::set<StreamType> stream_types,
cros::mojom::CameraMetadataPtr settings,
absl::optional<uint64_t> input_buffer_id) {
auto capture_request = cros::mojom::Camera3CaptureRequest::New();
for (StreamType stream_type : stream_types) {
absl::optional<BufferInfo> buffer_info;
if (IsInputStream(stream_type)) {
DCHECK(input_buffer_id.has_value());
buffer_info = request_buffer_callback_.Run(stream_type, input_buffer_id);
} else {
buffer_info = request_buffer_callback_.Run(stream_type, {});
}
if (!buffer_info) {
return capture_request;
}
const uint64_t buffer_ipc_id = buffer_info->ipc_id;
auto buffer_handle =
CreateCameraBufferHandle(stream_type, std::move(*buffer_info));
auto stream_buffer = CreateStreamBuffer(stream_type, buffer_ipc_id,
std::move(buffer_handle));
if (IsInputStream(stream_type)) {
capture_request->input_buffer = std::move(stream_buffer);
} else {
capture_request->output_buffers.push_back(std::move(stream_buffer));
}
}
capture_request->settings = std::move(settings);
capture_request->frame_number = frame_number_++;
return capture_request;
}
cros::mojom::CameraBufferHandlePtr RequestBuilder::CreateCameraBufferHandle(
StreamType stream_type,
BufferInfo buffer_info) {
auto buffer_handle = cros::mojom::CameraBufferHandle::New();
buffer_handle->buffer_id = buffer_info.ipc_id;
buffer_handle->drm_format = buffer_info.drm_format;
buffer_handle->hal_pixel_format = buffer_info.hal_pixel_format;
buffer_handle->width = buffer_info.dimension.width();
buffer_handle->height = buffer_info.dimension.height();
gfx::NativePixmapHandle& native_pixmap_handle =
buffer_info.gpu_memory_buffer_handle.native_pixmap_handle;
size_t num_planes = native_pixmap_handle.planes.size();
std::vector<StreamCaptureInterface::Plane> planes(num_planes);
for (size_t i = 0; i < num_planes; ++i) {
mojo::ScopedHandle mojo_fd = mojo::WrapPlatformHandle(
mojo::PlatformHandle(std::move(native_pixmap_handle.planes[i].fd)));
if (!mojo_fd.is_valid()) {
device_context_->SetErrorState(
media::VideoCaptureError::
kCrosHalV3BufferManagerFailedToWrapGpuMemoryHandle,
FROM_HERE, "Failed to wrap gpu memory handle");
return nullptr;
}
buffer_handle->fds.push_back(std::move(mojo_fd));
buffer_handle->strides.push_back(native_pixmap_handle.planes[i].stride);
buffer_handle->offsets.push_back(native_pixmap_handle.planes[i].offset);
}
return buffer_handle;
}
cros::mojom::Camera3StreamBufferPtr RequestBuilder::CreateStreamBuffer(
StreamType stream_type,
uint64_t buffer_ipc_id,
cros::mojom::CameraBufferHandlePtr buffer_handle) {
cros::mojom::Camera3StreamBufferPtr buffer =
cros::mojom::Camera3StreamBuffer::New();
buffer->stream_id = static_cast<uint64_t>(stream_type);
buffer->buffer_id = buffer_ipc_id;
buffer->status = cros::mojom::Camera3BufferStatus::CAMERA3_BUFFER_STATUS_OK;
buffer->buffer_handle = std::move(buffer_handle);
return buffer;
}
} // namespace media