blob: 3dff35dcda483fd24120b4b16f25bb9249ff7b41 [file] [log] [blame]
// Copyright 2018 The Chromium OS 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_perception/producer_impl.h"
#include <stdlib.h>
#include <algorithm>
#include <cstring>
#include <utility>
#include <base/bind.h>
#include <base/check.h>
#include <base/logging.h>
#include <mojo/public/cpp/system/handle.h>
#include <mojo/public/cpp/system/platform_handle.h>
#include "mojom/constants.mojom.h"
#include "mojom/video_capture_types.mojom.h"
namespace mri {
mojo::PendingRemote<video_capture::mojom::Producer>
ProducerImpl::CreateInterfacePendingRemote() {
mojo::PendingRemote<video_capture::mojom::Producer> producer;
receiver_.Bind(producer.InitWithNewPipeAndPassReceiver());
return producer;
}
void ProducerImpl::RegisterVirtualDevice(
mojo::Remote<video_capture::mojom::VideoSourceProvider>* provider,
media::mojom::VideoCaptureDeviceInfoPtr info) {
(*provider)->AddSharedMemoryVirtualDevice(
std::move(info), CreateInterfacePendingRemote(), true,
mojo::MakeRequest(&virtual_device_));
}
void ProducerImpl::OnNewBuffer(int32_t buffer_id,
media::mojom::VideoBufferHandlePtr buffer_handle,
OnNewBufferCallback callback) {
CHECK(buffer_handle->is_shared_memory_via_raw_file_descriptor());
base::ScopedPlatformFile platform_file;
MojoResult mojo_result = mojo::UnwrapPlatformFile(
std::move(buffer_handle->get_shared_memory_via_raw_file_descriptor()
->file_descriptor_handle),
&platform_file);
if (mojo_result != MOJO_RESULT_OK) {
LOG(ERROR) << "Failed to unwrap handle: " << mojo_result;
return;
}
base::UnsafeSharedMemoryRegion shm_region =
base::UnsafeSharedMemoryRegion::Deserialize(
base::subtle::PlatformSharedMemoryRegion::Take(
base::ScopedFD(std::move(platform_file)),
base::subtle::PlatformSharedMemoryRegion::Mode::kUnsafe,
buffer_handle->get_shared_memory_via_raw_file_descriptor()
->shared_memory_size_in_bytes,
base::UnguessableToken::Create()));
if (!shm_region.IsValid()) {
LOG(ERROR) << "Failed to take shared memory region.";
return;
}
base::WritableSharedMemoryMapping shm_mapping = shm_region.Map();
if (!shm_mapping.IsValid()) {
LOG(ERROR) << "Failed to map shared memory region.";
return;
}
outgoing_buffer_id_to_buffer_map_.insert(
std::make_pair(buffer_id, std::move(shm_mapping)));
std::move(callback).Run();
}
void ProducerImpl::OnBufferRetired(int32_t buffer_id) {
outgoing_buffer_id_to_buffer_map_.erase(buffer_id);
}
void ProducerImpl::PushNextFrame(
std::shared_ptr<ProducerImpl> producer_impl,
base::TimeDelta timestamp,
std::unique_ptr<const uint8_t[]> data,
int data_size,
media::mojom::VideoCapturePixelFormat pixel_format,
int width,
int height) {
gfx::mojom::SizePtr size = gfx::mojom::Size::New();
size->width = width;
size->height = height;
virtual_device_->RequestFrameBuffer(
std::move(size), pixel_format, nullptr,
base::Bind(&ProducerImpl::OnFrameBufferReceived, base::Unretained(this),
producer_impl, timestamp, base::Passed(&data), data_size,
pixel_format, width, height));
}
void ProducerImpl::OnFrameBufferReceived(
std::shared_ptr<ProducerImpl> producer_impl,
base::TimeDelta timestamp,
std::unique_ptr<const uint8_t[]> data,
int data_size,
media::mojom::VideoCapturePixelFormat pixel_format,
int width,
int height,
int32_t buffer_id) {
if (buffer_id == video_capture::mojom::kInvalidBufferId) {
LOG(ERROR) << "Got invalid buffer id.";
return;
}
media::mojom::VideoFrameInfoPtr info = media::mojom::VideoFrameInfo::New();
info->timestamp = mojo_base::mojom::TimeDelta::New();
info->timestamp->microseconds = timestamp.InMicroseconds();
info->pixel_format = pixel_format;
gfx::mojom::SizePtr size = gfx::mojom::Size::New();
size->width = width;
size->height = height;
info->coded_size = std::move(size);
gfx::mojom::RectPtr rect = gfx::mojom::Rect::New();
rect->width = width;
rect->height = height;
info->visible_rect = std::move(rect);
info->metadata = media::mojom::VideoFrameMetadata::New();
info->metadata->reference_time = mojo_base::mojom::TimeTicks::New();
info->metadata->reference_time->internal_value = timestamp.InMicroseconds();
base::WritableSharedMemoryMapping* outgoing_buffer =
&outgoing_buffer_id_to_buffer_map_.at(buffer_id);
std::memcpy(
outgoing_buffer->GetMemoryAs<uint8_t>(), data.get(),
std::min(outgoing_buffer->mapped_size(), static_cast<size_t>(data_size)));
virtual_device_->OnFrameReadyInBuffer(buffer_id, std::move(info));
}
} // namespace mri