Commit 94dbd9af authored by Wei Lee's avatar Wei Lee Committed by Commit Bot

Enable encoding through DMA-buf on VAAPI JEA

This CL enables DMA-buf encoding on VAAPI JEA to optimize the
performance and reduce the CPU consumption.

Bug: 944705, b/123057886
Test: Manually
Test: ./jpeg_encode_accelerator_unittest

Change-Id: I05d80c8bb649b0c09ad26d3545377c77e3d385bc
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1532135
Commit-Queue: Wei Lee <wtlee@chromium.org>
Reviewed-by: default avatarRicky Liang <jcliang@chromium.org>
Reviewed-by: default avatarRobert Sesek <rsesek@chromium.org>
Reviewed-by: default avatarTommi <tommi@chromium.org>
Reviewed-by: default avatarSheng-hao Tsao <shenghao@chromium.org>
Cr-Commit-Position: refs/heads/master@{#662964}
parent f5b5ef85
...@@ -142,6 +142,7 @@ if (use_v4l2_codec || use_vaapi) { ...@@ -142,6 +142,7 @@ if (use_v4l2_codec || use_vaapi) {
"//base", "//base",
"//base/test:test_support", "//base/test:test_support",
"//media:test_support", "//media:test_support",
"//media/capture:chromeos_test_utils",
"//media/gpu:buildflags", "//media/gpu:buildflags",
"//media/gpu/test:helpers", "//media/gpu/test:helpers",
"//media/parsers", "//media/parsers",
......
...@@ -36,40 +36,37 @@ interface JpegEncodeAccelerator { ...@@ -36,40 +36,37 @@ interface JpegEncodeAccelerator {
// Encodes the given buffer that contains one I420 image. // Encodes the given buffer that contains one I420 image.
// |input_fd| and |output_fd| are file descriptors of shared memory. // |input_fd| and |output_fd| are file descriptors of shared memory.
// The image is encoded from memory of |input_fd| // The image is encoded from memory of |input_fd|
// with size |input_buffer_size|. The output buffer is associated with // with size |input_buffer_size|. |task_id| is used to distinguish different
// |buffer_id| and the dimension of I420 image is |coded_size_width| and // tasks. The dimension of I420 image is |coded_size_width| and
// |coded_size_height|. // |coded_size_height|.
// |exif_fd| is the shared memory buffer, with |exif_buffer_size| as size, // |exif_fd| is the shared memory buffer, with |exif_buffer_size| as size,
// containing Exif data which will be put onto APP1 segment in the output // containing Exif data which will be put onto APP1 segment in the output
// JPEG image. // JPEG image.
// Encoded JPEG image will be put onto memory associated with |output_fd| // Encoded JPEG image will be put onto memory associated with |output_fd|
// with allocated size |output_buffer_size|. // with allocated size |output_buffer_size|.
// Returns |buffer_id| and |error| in a callback to notify the // Returns |task_id| and |error| in a callback to notify the
// encode status. |buffer_id| is the id of |output_buffer| and |status| is the // encode status. |status| is the status code. |encoded_buffer_size| is the
// status code. |encoded_buffer_size| is the actual size of the encoded JPEG. // actual size of the encoded JPEG.
EncodeWithFD(int32 buffer_id, handle input_fd, uint32 input_buffer_size, EncodeWithFD(int32 task_id, handle input_fd, uint32 input_buffer_size,
int32 coded_size_width, int32 coded_size_height, int32 coded_size_width, int32 coded_size_height,
handle exif_fd, uint32 exif_buffer_size, handle exif_fd, uint32 exif_buffer_size,
handle output_fd, uint32 output_buffer_size) handle output_fd, uint32 output_buffer_size)
=> (int32 buffer_id, uint32 encoded_buffer_size, EncodeStatus status); => (int32 task_id, uint32 encoded_buffer_size, EncodeStatus status);
// Encodes the given DMA-buf. The buffer id of output is |buffer_id|. The // Encodes the given DMA-buf. |task_id| is used to distinguish different
// size of input image defined in |coded_size_width| and |coded_size_height| // tasks. The size of input image defined in |coded_size_width| and
// and the format |input_format| represents by its fourcc value. The plane // |coded_size_height| and the format |input_format| represents by its fourcc
// information of input DMA-buf and output DMA-buf is stored in |input_planes| // value. The plane information of input DMA-buf and output DMA-buf is stored
// and |output_planes| respectively. Although the actual amount of buffers // in |input_planes| and |output_planes| respectively. Although the actual
// could be equal to or less than the number of planes, the amount of plane // amount of buffers could be equal to or less than the number of planes, the
// information |input_planes| and |output_planes| should be same as the number // amount of plane information |input_planes| and |output_planes| should be
// of planes. |exif_handle| is the shared memory buffer, with // same as the number of planes. |exif_handle| is the shared memory buffer,
// |exif_buffer_size| as size, containing Exif data which will be put onto // with |exif_buffer_size| as size, containing Exif data which will be put
// APP1 segment in the output JPEG image. When the task ends, it returns // onto APP1 segment in the output JPEG image. When the task ends, it returns
// |status| as the status code and |encoded_buffer_size| is the actual size of // |status| as the status code and |encoded_buffer_size| is the actual size of
// the encoded JPEG. // the encoded JPEG.
//
// TODO(crbug.com/957469): Consider passing more unique identifier rather than
// |buffer_id| for JpegEocdeAccelerator
EncodeWithDmaBuf( EncodeWithDmaBuf(
int32 buffer_id, int32 task_id,
uint32 input_format, uint32 input_format,
array<DmaBufPlane> input_planes, array<DmaBufPlane> input_planes,
array<DmaBufPlane> output_planes, array<DmaBufPlane> output_planes,
......
...@@ -105,21 +105,22 @@ class JpegEncodeAccelerator { ...@@ -105,21 +105,22 @@ class JpegEncodeAccelerator {
media::BitstreamBuffer output_buffer) = 0; media::BitstreamBuffer output_buffer) = 0;
// Encodes the given |video_frame| that contains a YUV image. Client will // Encodes the given |video_frame| that contains a YUV image. Client will
// receive the encoded result in Client::VideoFrameReady() callback with the // receive the encoded result in Client::VideoFrameReady() callback, or
// corresponding |output_buffer.id()|, or receive // receive Client::NotifyError() callback.
// Client::NotifyError() callback.
// Parameters: // Parameters:
// |input_frame| contains the YUV image to be encoded. // |input_frame| contains the YUV image to be encoded.
// |output_frame| is used to represent the output Dma-buf layout. // |output_frame| is used to represent the output Dma-buf layout.
// |quality| of JPEG image. The range is from 1~100. High value means high // |quality| of JPEG image. The range is from 1~100. High value means high
// quality. // quality.
// |task_id| is an identifier started from zero that passed from the client
// side. Could be used to identify different encode tasks.
// |exif_buffer| contains Exif data to be inserted into JPEG image. If it's // |exif_buffer| contains Exif data to be inserted into JPEG image. If it's
// nullptr, the JFIF APP0 segment will be inserted. // nullptr, the JFIF APP0 segment will be inserted.
virtual void EncodeWithDmaBuf(scoped_refptr<media::VideoFrame> input_frame, virtual void EncodeWithDmaBuf(scoped_refptr<media::VideoFrame> input_frame,
scoped_refptr<media::VideoFrame> output_frame, scoped_refptr<media::VideoFrame> output_frame,
int quality, int quality,
int32_t buffer_id, int32_t task_id,
const media::BitstreamBuffer* exif_buffer) = 0; media::BitstreamBuffer* exif_buffer) = 0;
}; };
} // namespace chromeos_camera } // namespace chromeos_camera
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "components/chromeos_camera/gpu_jpeg_encode_accelerator_factory.h" #include "components/chromeos_camera/gpu_jpeg_encode_accelerator_factory.h"
#include "components/chromeos_camera/jpeg_encode_accelerator.h" #include "components/chromeos_camera/jpeg_encode_accelerator.h"
#include "media/base/test_data_util.h" #include "media/base/test_data_util.h"
#include "media/capture/video/chromeos/local_gpu_memory_buffer_manager.h"
#include "media/gpu/buildflags.h" #include "media/gpu/buildflags.h"
#include "media/gpu/test/video_accelerator_unittest_helpers.h" #include "media/gpu/test/video_accelerator_unittest_helpers.h"
#include "media/parsers/jpeg_parser.h" #include "media/parsers/jpeg_parser.h"
...@@ -81,6 +82,31 @@ enum class ClientState { ...@@ -81,6 +82,31 @@ enum class ClientState {
ERROR, ERROR,
}; };
scoped_refptr<media::VideoFrame> GetVideoFrameFromGpuMemoryBuffer(
gfx::GpuMemoryBuffer* buffer,
gfx::Size size,
media::VideoPixelFormat format) {
auto buffer_handle = buffer->CloneHandle().native_pixmap_handle;
size_t num_planes = media::VideoFrame::NumPlanes(format);
std::vector<media::VideoFrameLayout::Plane> planes(num_planes);
std::vector<size_t> buffer_sizes(num_planes);
std::vector<base::ScopedFD> fds(num_planes);
for (size_t i = 0; i < num_planes; i++) {
auto& plane = buffer_handle.planes[i];
fds[i] = std::move(plane.fd);
planes[i].stride = plane.stride;
planes[i].offset = plane.offset;
buffer_sizes[i] = plane.size;
}
gfx::Rect visible_rect(size);
auto layout = media::VideoFrameLayout::CreateWithPlanes(
format, size, std::move(planes), std::move(buffer_sizes));
return media::VideoFrame::WrapExternalDmabufs(
*layout, visible_rect, size, std::move(fds), base::TimeDelta());
}
class JpegEncodeAcceleratorTestEnvironment : public ::testing::Environment { class JpegEncodeAcceleratorTestEnvironment : public ::testing::Environment {
public: public:
JpegEncodeAcceleratorTestEnvironment( JpegEncodeAcceleratorTestEnvironment(
...@@ -247,6 +273,7 @@ class JpegClient : public JpegEncodeAccelerator::Client { ...@@ -247,6 +273,7 @@ class JpegClient : public JpegEncodeAccelerator::Client {
void CreateJpegEncoder(); void CreateJpegEncoder();
void DestroyJpegEncoder(); void DestroyJpegEncoder();
void StartEncode(int32_t bitstream_buffer_id); void StartEncode(int32_t bitstream_buffer_id);
void StartEncodeDmaBuf(int32_t bitstream_buffer_id);
// JpegEncodeAccelerator::Client implementation. // JpegEncodeAccelerator::Client implementation.
void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size) override; void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size) override;
...@@ -305,6 +332,9 @@ class JpegClient : public JpegEncodeAccelerator::Client { ...@@ -305,6 +332,9 @@ class JpegClient : public JpegEncodeAccelerator::Client {
// Mapped memory of output buffer from software encoder. // Mapped memory of output buffer from software encoder.
std::unique_ptr<base::SharedMemory> sw_out_shm_; std::unique_ptr<base::SharedMemory> sw_out_shm_;
// Used to create Gpu memory buffer for DMA-buf encoding tests.
std::unique_ptr<gpu::GpuMemoryBufferManager> gpu_memory_buffer_manager_;
DISALLOW_COPY_AND_ASSIGN(JpegClient); DISALLOW_COPY_AND_ASSIGN(JpegClient);
}; };
...@@ -314,7 +344,8 @@ JpegClient::JpegClient(const std::vector<TestImage*>& test_aligned_images, ...@@ -314,7 +344,8 @@ JpegClient::JpegClient(const std::vector<TestImage*>& test_aligned_images,
: test_aligned_images_(test_aligned_images), : test_aligned_images_(test_aligned_images),
test_images_(test_images), test_images_(test_images),
state_(ClientState::CREATED), state_(ClientState::CREATED),
note_(note) {} note_(note),
gpu_memory_buffer_manager_(new media::LocalGpuMemoryBufferManager()) {}
JpegClient::~JpegClient() {} JpegClient::~JpegClient() {}
...@@ -576,6 +607,34 @@ void JpegClient::StartEncode(int32_t bitstream_buffer_id) { ...@@ -576,6 +607,34 @@ void JpegClient::StartEncode(int32_t bitstream_buffer_id) {
std::move(encoded_buffer_)); std::move(encoded_buffer_));
} }
void JpegClient::StartEncodeDmaBuf(int32_t bitstream_buffer_id) {
TestImage* test_image = GetTestImage(bitstream_buffer_id);
test_image->output_size =
encoder_->GetMaxCodedBufferSize(test_image->visible_size);
auto input_buffer = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
test_image->visible_size, gfx::BufferFormat::YUV_420_BIPLANAR,
gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE, gpu::kNullSurfaceHandle);
ASSERT_EQ(input_buffer->Map(), true);
memcpy(input_buffer->memory(0), test_image->image_data.data(),
test_image->image_data.size());
auto input_frame = GetVideoFrameFromGpuMemoryBuffer(
input_buffer.get(), test_image->visible_size, media::PIXEL_FORMAT_NV12);
LOG_ASSERT(input_frame.get());
auto output_buffer = gpu_memory_buffer_manager_->CreateGpuMemoryBuffer(
test_image->visible_size, gfx::BufferFormat::R_8,
gfx::BufferUsage::CAMERA_AND_CPU_READ_WRITE, gpu::kNullSurfaceHandle);
ASSERT_EQ(output_buffer->Map(), true);
auto output_frame = GetVideoFrameFromGpuMemoryBuffer(
output_buffer.get(), test_image->visible_size, media::PIXEL_FORMAT_MJPEG);
LOG_ASSERT(output_frame.get());
buffer_id_to_start_time_[bitstream_buffer_id] = base::TimeTicks::Now();
encoder_->EncodeWithDmaBuf(input_frame, output_frame, kJpegDefaultQuality,
bitstream_buffer_id, nullptr);
}
class JpegEncodeAcceleratorTest : public ::testing::Test { class JpegEncodeAcceleratorTest : public ::testing::Test {
protected: protected:
JpegEncodeAcceleratorTest() {} JpegEncodeAcceleratorTest() {}
...@@ -628,6 +687,14 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders) { ...@@ -628,6 +687,14 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders) {
for (size_t i = 0; i < num_concurrent_encoders; i++) { for (size_t i = 0; i < num_concurrent_encoders; i++) {
ASSERT_EQ(notes[i]->Wait(), ClientState::ENCODE_PASS); ASSERT_EQ(notes[i]->Wait(), ClientState::ENCODE_PASS);
} }
for (size_t i = 0; i < num_concurrent_encoders; i++) {
encoder_thread.task_runner()->PostTask(
FROM_HERE, base::BindOnce(&JpegClient::StartEncodeDmaBuf,
base::Unretained(clients[i].get()), index));
}
for (size_t i = 0; i < num_concurrent_encoders; i++) {
ASSERT_EQ(notes[i]->Wait(), ClientState::ENCODE_PASS);
}
} }
for (size_t index = 0; index < test_images_.size(); index++) { for (size_t index = 0; index < test_images_.size(); index++) {
...@@ -645,6 +712,24 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders) { ...@@ -645,6 +712,24 @@ void JpegEncodeAcceleratorTest::TestEncode(size_t num_concurrent_encoders) {
for (size_t i = 0; i < num_concurrent_encoders; i++) { for (size_t i = 0; i < num_concurrent_encoders; i++) {
// For unaligned images, V4L2 may not be able to encode them. // For unaligned images, V4L2 may not be able to encode them.
#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
ClientState status = notes[i]->Wait();
ASSERT_TRUE(status == ClientState::ENCODE_PASS ||
status == ClientState::ERROR);
#else
ASSERT_EQ(notes[i]->Wait(), ClientState::ENCODE_PASS);
#endif
}
for (size_t i = 0; i < num_concurrent_encoders; i++) {
encoder_thread.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&JpegClient::StartEncode,
base::Unretained(clients[i].get()), buffer_id));
}
for (size_t i = 0; i < num_concurrent_encoders; i++) {
// For unaligned images, V4L2 may not be able to encode them.
#if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY) #if BUILDFLAG(USE_V4L2_CODEC) && defined(ARCH_CPU_ARM_FAMILY)
ClientState status = notes[i]->Wait(); ClientState status = notes[i]->Wait();
ASSERT_TRUE(status == ClientState::ENCODE_PASS || ASSERT_TRUE(status == ClientState::ENCODE_PASS ||
......
...@@ -107,19 +107,19 @@ MojoJpegEncodeAcceleratorService::~MojoJpegEncodeAcceleratorService() { ...@@ -107,19 +107,19 @@ MojoJpegEncodeAcceleratorService::~MojoJpegEncodeAcceleratorService() {
} }
void MojoJpegEncodeAcceleratorService::VideoFrameReady( void MojoJpegEncodeAcceleratorService::VideoFrameReady(
int32_t bitstream_buffer_id, int32_t task_id,
size_t encoded_picture_size) { size_t encoded_picture_size) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
NotifyEncodeStatus( NotifyEncodeStatus(
bitstream_buffer_id, encoded_picture_size, task_id, encoded_picture_size,
::chromeos_camera::JpegEncodeAccelerator::Status::ENCODE_OK); ::chromeos_camera::JpegEncodeAccelerator::Status::ENCODE_OK);
} }
void MojoJpegEncodeAcceleratorService::NotifyError( void MojoJpegEncodeAcceleratorService::NotifyError(
int32_t bitstream_buffer_id, int32_t task_id,
::chromeos_camera::JpegEncodeAccelerator::Status error) { ::chromeos_camera::JpegEncodeAccelerator::Status error) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
NotifyEncodeStatus(bitstream_buffer_id, 0, error); NotifyEncodeStatus(task_id, 0, error);
} }
void MojoJpegEncodeAcceleratorService::Initialize(InitializeCallback callback) { void MojoJpegEncodeAcceleratorService::Initialize(InitializeCallback callback) {
...@@ -151,7 +151,7 @@ void MojoJpegEncodeAcceleratorService::Initialize(InitializeCallback callback) { ...@@ -151,7 +151,7 @@ void MojoJpegEncodeAcceleratorService::Initialize(InitializeCallback callback) {
} }
void MojoJpegEncodeAcceleratorService::EncodeWithFD( void MojoJpegEncodeAcceleratorService::EncodeWithFD(
int32_t buffer_id, int32_t task_id,
mojo::ScopedHandle input_handle, mojo::ScopedHandle input_handle,
uint32_t input_buffer_size, uint32_t input_buffer_size,
int32_t coded_size_width, int32_t coded_size_width,
...@@ -169,7 +169,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -169,7 +169,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
if (coded_size_width <= 0 || coded_size_height <= 0) { if (coded_size_width <= 0 || coded_size_height <= 0) {
std::move(callback).Run( std::move(callback).Run(
buffer_id, 0, task_id, 0,
::chromeos_camera::JpegEncodeAccelerator::Status::INVALID_ARGUMENT); ::chromeos_camera::JpegEncodeAccelerator::Status::INVALID_ARGUMENT);
return; return;
} }
...@@ -177,7 +177,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -177,7 +177,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
result = mojo::UnwrapPlatformFile(std::move(input_handle), &input_fd); result = mojo::UnwrapPlatformFile(std::move(input_handle), &input_fd);
if (result != MOJO_RESULT_OK) { if (result != MOJO_RESULT_OK) {
std::move(callback).Run( std::move(callback).Run(
buffer_id, 0, task_id, 0,
::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE); ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return; return;
} }
...@@ -185,7 +185,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -185,7 +185,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
result = mojo::UnwrapPlatformFile(std::move(exif_handle), &exif_fd); result = mojo::UnwrapPlatformFile(std::move(exif_handle), &exif_fd);
if (result != MOJO_RESULT_OK) { if (result != MOJO_RESULT_OK) {
std::move(callback).Run( std::move(callback).Run(
buffer_id, 0, task_id, 0,
::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE); ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return; return;
} }
...@@ -193,7 +193,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -193,7 +193,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
result = mojo::UnwrapPlatformFile(std::move(output_handle), &output_fd); result = mojo::UnwrapPlatformFile(std::move(output_handle), &output_fd);
if (result != MOJO_RESULT_OK) { if (result != MOJO_RESULT_OK) {
std::move(callback).Run( std::move(callback).Run(
buffer_id, 0, task_id, 0,
::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE); ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return; return;
} }
...@@ -209,33 +209,33 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -209,33 +209,33 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
base::FileDescriptor(output_fd, true), output_buffer_size, output_guid); base::FileDescriptor(output_fd, true), output_buffer_size, output_guid);
media::BitstreamBuffer output_buffer( media::BitstreamBuffer output_buffer(
buffer_id, output_shm_handle, false /* read_only */, output_buffer_size); task_id, output_shm_handle, false /* read_only */, output_buffer_size);
std::unique_ptr<media::BitstreamBuffer> exif_buffer; std::unique_ptr<media::BitstreamBuffer> exif_buffer;
if (exif_buffer_size > 0) { if (exif_buffer_size > 0) {
exif_buffer = std::make_unique<media::BitstreamBuffer>( exif_buffer = std::make_unique<media::BitstreamBuffer>(
buffer_id, exif_shm_handle, false /* read_only */, exif_buffer_size); task_id, exif_shm_handle, false /* read_only */, exif_buffer_size);
} }
gfx::Size coded_size(coded_size_width, coded_size_height); gfx::Size coded_size(coded_size_width, coded_size_height);
if (encode_cb_map_.find(buffer_id) != encode_cb_map_.end()) { if (encode_cb_map_.find(task_id) != encode_cb_map_.end()) {
mojo::ReportBadMessage("buffer_id is already registered in encode_cb_map_"); mojo::ReportBadMessage("task_id is already registered in encode_cb_map_");
return; return;
} }
auto wrapped_callback = base::BindOnce( auto wrapped_callback = base::BindOnce(
[](int32_t buffer_id, EncodeWithFDCallback callback, [](int32_t task_id, EncodeWithFDCallback callback,
uint32_t encoded_picture_size, uint32_t encoded_picture_size,
::chromeos_camera::JpegEncodeAccelerator::Status error) { ::chromeos_camera::JpegEncodeAccelerator::Status error) {
std::move(callback).Run(buffer_id, encoded_picture_size, error); std::move(callback).Run(task_id, encoded_picture_size, error);
}, },
buffer_id, std::move(callback)); task_id, std::move(callback));
encode_cb_map_.emplace(buffer_id, std::move(wrapped_callback)); encode_cb_map_.emplace(task_id, std::move(wrapped_callback));
auto input_shm = std::make_unique<base::SharedMemory>(input_shm_handle, true); auto input_shm = std::make_unique<base::SharedMemory>(input_shm_handle, true);
if (!input_shm->Map(input_buffer_size)) { if (!input_shm->Map(input_buffer_size)) {
DLOG(ERROR) << "Could not map input shared memory for buffer id " DLOG(ERROR) << "Could not map input shared memory for buffer id "
<< buffer_id; << task_id;
NotifyEncodeStatus( NotifyEncodeStatus(
buffer_id, 0, task_id, 0,
::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE); ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return; return;
} }
...@@ -253,9 +253,9 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -253,9 +253,9 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
0, // data_offset 0, // data_offset
base::TimeDelta()); // timestamp base::TimeDelta()); // timestamp
if (!frame.get()) { if (!frame.get()) {
LOG(ERROR) << "Could not create VideoFrame for buffer id " << buffer_id; LOG(ERROR) << "Could not create VideoFrame for buffer id " << task_id;
NotifyEncodeStatus( NotifyEncodeStatus(
buffer_id, 0, task_id, 0,
::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE); ::chromeos_camera::JpegEncodeAccelerator::Status::PLATFORM_FAILURE);
return; return;
} }
...@@ -270,7 +270,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD( ...@@ -270,7 +270,7 @@ void MojoJpegEncodeAcceleratorService::EncodeWithFD(
} }
void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf( void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf(
int32_t buffer_id, int32_t task_id,
uint32_t input_format, uint32_t input_format,
std::vector<chromeos_camera::mojom::DmaBufPlanePtr> input_planes, std::vector<chromeos_camera::mojom::DmaBufPlanePtr> input_planes,
std::vector<chromeos_camera::mojom::DmaBufPlanePtr> output_planes, std::vector<chromeos_camera::mojom::DmaBufPlanePtr> output_planes,
...@@ -285,8 +285,8 @@ void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf( ...@@ -285,8 +285,8 @@ void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf(
0, ::chromeos_camera::JpegEncodeAccelerator::Status::INVALID_ARGUMENT); 0, ::chromeos_camera::JpegEncodeAccelerator::Status::INVALID_ARGUMENT);
return; return;
} }
if (encode_cb_map_.find(buffer_id) != encode_cb_map_.end()) { if (encode_cb_map_.find(task_id) != encode_cb_map_.end()) {
mojo::ReportBadMessage("buffer_id is already registered in encode_cb_map_"); mojo::ReportBadMessage("task_id is already registered in encode_cb_map_");
return; return;
} }
...@@ -319,23 +319,25 @@ void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf( ...@@ -319,23 +319,25 @@ void MojoJpegEncodeAcceleratorService::EncodeWithDmaBuf(
exif_buffer_size, exif_guid); exif_buffer_size, exif_guid);
std::unique_ptr<media::BitstreamBuffer> exif_buffer; std::unique_ptr<media::BitstreamBuffer> exif_buffer;
if (exif_buffer_size > 0) { if (exif_buffer_size > 0) {
// Currently we use our zero-based |task_id| as id of |exif_buffer| to track
// the encode task process from both Chrome OS and Chrome side.
exif_buffer = std::make_unique<media::BitstreamBuffer>( exif_buffer = std::make_unique<media::BitstreamBuffer>(
buffer_id, exif_shm_handle, false /* read_only */, exif_buffer_size); task_id, exif_shm_handle, false /* read_only */, exif_buffer_size);
} }
encode_cb_map_.emplace(buffer_id, std::move(callback)); encode_cb_map_.emplace(task_id, std::move(callback));
DCHECK(accelerator_); DCHECK(accelerator_);
accelerator_->EncodeWithDmaBuf(input_video_frame, output_video_frame, accelerator_->EncodeWithDmaBuf(input_video_frame, output_video_frame,
kJpegQuality, buffer_id, exif_buffer.get()); kJpegQuality, task_id, exif_buffer.get());
} }
void MojoJpegEncodeAcceleratorService::NotifyEncodeStatus( void MojoJpegEncodeAcceleratorService::NotifyEncodeStatus(
int32_t bitstream_buffer_id, int32_t task_id,
size_t encoded_picture_size, size_t encoded_picture_size,
::chromeos_camera::JpegEncodeAccelerator::Status error) { ::chromeos_camera::JpegEncodeAccelerator::Status error) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
auto iter = encode_cb_map_.find(bitstream_buffer_id); auto iter = encode_cb_map_.find(task_id);
DCHECK(iter != encode_cb_map_.end()); DCHECK(iter != encode_cb_map_.end());
EncodeWithDmaBufCallback encode_cb = std::move(iter->second); EncodeWithDmaBufCallback encode_cb = std::move(iter->second);
encode_cb_map_.erase(iter); encode_cb_map_.erase(iter);
......
...@@ -30,9 +30,9 @@ class MojoJpegEncodeAcceleratorService ...@@ -30,9 +30,9 @@ class MojoJpegEncodeAcceleratorService
~MojoJpegEncodeAcceleratorService() override; ~MojoJpegEncodeAcceleratorService() override;
// JpegEncodeAccelerator::Client implementation. // JpegEncodeAccelerator::Client implementation.
void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size) override; void VideoFrameReady(int32_t task_id, size_t encoded_picture_size) override;
void NotifyError( void NotifyError(
int32_t buffer_id, int32_t task_id,
::chromeos_camera::JpegEncodeAccelerator::Status status) override; ::chromeos_camera::JpegEncodeAccelerator::Status status) override;
private: private:
...@@ -48,7 +48,7 @@ class MojoJpegEncodeAcceleratorService ...@@ -48,7 +48,7 @@ class MojoJpegEncodeAcceleratorService
void Initialize(InitializeCallback callback) override; void Initialize(InitializeCallback callback) override;
// TODO(wtlee): To be deprecated. (crbug.com/944705) // TODO(wtlee): To be deprecated. (crbug.com/944705)
void EncodeWithFD(int32_t buffer_id, void EncodeWithFD(int32_t task_id,
mojo::ScopedHandle input_fd, mojo::ScopedHandle input_fd,
uint32_t input_buffer_size, uint32_t input_buffer_size,
int32_t coded_size_width, int32_t coded_size_width,
...@@ -60,7 +60,7 @@ class MojoJpegEncodeAcceleratorService ...@@ -60,7 +60,7 @@ class MojoJpegEncodeAcceleratorService
EncodeWithFDCallback callback) override; EncodeWithFDCallback callback) override;
void EncodeWithDmaBuf( void EncodeWithDmaBuf(
int32_t buffer_id, int32_t task_id,
uint32_t input_format, uint32_t input_format,
std::vector<chromeos_camera::mojom::DmaBufPlanePtr> input_planes, std::vector<chromeos_camera::mojom::DmaBufPlanePtr> input_planes,
std::vector<chromeos_camera::mojom::DmaBufPlanePtr> output_planes, std::vector<chromeos_camera::mojom::DmaBufPlanePtr> output_planes,
...@@ -71,14 +71,14 @@ class MojoJpegEncodeAcceleratorService ...@@ -71,14 +71,14 @@ class MojoJpegEncodeAcceleratorService
EncodeWithDmaBufCallback callback) override; EncodeWithDmaBufCallback callback) override;
void NotifyEncodeStatus( void NotifyEncodeStatus(
int32_t bitstream_buffer_id, int32_t task_id,
size_t encoded_picture_size, size_t encoded_picture_size,
::chromeos_camera::JpegEncodeAccelerator::Status status); ::chromeos_camera::JpegEncodeAccelerator::Status status);
const std::vector<GpuJpegEncodeAcceleratorFactory::CreateAcceleratorCB> const std::vector<GpuJpegEncodeAcceleratorFactory::CreateAcceleratorCB>
accelerator_factory_functions_; accelerator_factory_functions_;
// A map from bitstream_buffer_id to EncodeCallback. // A map from task_id to EncodeCallback.
EncodeCallbackMap encode_cb_map_; EncodeCallbackMap encode_cb_map_;
std::unique_ptr<::chromeos_camera::JpegEncodeAccelerator> accelerator_; std::unique_ptr<::chromeos_camera::JpegEncodeAccelerator> accelerator_;
......
...@@ -328,6 +328,20 @@ source_set("test_support") { ...@@ -328,6 +328,20 @@ source_set("test_support") {
testonly = true testonly = true
} }
if (is_chromeos) {
source_set("chromeos_test_utils") {
sources = [
"video/chromeos/local_gpu_memory_buffer_manager.cc",
]
deps = [
"//base",
"//build/config/linux/libdrm",
"//third_party/minigbm",
]
}
}
test("capture_unittests") { test("capture_unittests") {
sources = [ sources = [
"content/animated_content_sampler_unittest.cc", "content/animated_content_sampler_unittest.cc",
...@@ -403,7 +417,6 @@ test("capture_unittests") { ...@@ -403,7 +417,6 @@ test("capture_unittests") {
"video/chromeos/camera_device_delegate_unittest.cc", "video/chromeos/camera_device_delegate_unittest.cc",
"video/chromeos/camera_hal_delegate_unittest.cc", "video/chromeos/camera_hal_delegate_unittest.cc",
"video/chromeos/camera_hal_dispatcher_impl_unittest.cc", "video/chromeos/camera_hal_dispatcher_impl_unittest.cc",
"video/chromeos/local_gpu_memory_buffer_manager.cc",
"video/chromeos/mock_camera_module.cc", "video/chromeos/mock_camera_module.cc",
"video/chromeos/mock_camera_module.h", "video/chromeos/mock_camera_module.h",
"video/chromeos/mock_vendor_tag_ops.cc", "video/chromeos/mock_vendor_tag_ops.cc",
...@@ -413,6 +426,7 @@ test("capture_unittests") { ...@@ -413,6 +426,7 @@ test("capture_unittests") {
"video/chromeos/request_manager_unittest.cc", "video/chromeos/request_manager_unittest.cc",
] ]
deps += [ deps += [
":chromeos_test_utils",
"//build/config/linux/libdrm", "//build/config/linux/libdrm",
"//chromeos/dbus/power", "//chromeos/dbus/power",
"//media/capture/video/chromeos/mojo:cros_camera", "//media/capture/video/chromeos/mojo:cros_camera",
......
...@@ -1039,8 +1039,8 @@ void V4L2JpegEncodeAccelerator::EncodeWithDmaBuf( ...@@ -1039,8 +1039,8 @@ void V4L2JpegEncodeAccelerator::EncodeWithDmaBuf(
scoped_refptr<VideoFrame> input_frame, scoped_refptr<VideoFrame> input_frame,
scoped_refptr<VideoFrame> output_frame, scoped_refptr<VideoFrame> output_frame,
int quality, int quality,
int32_t buffer_id, int32_t task_id,
const BitstreamBuffer* exif_buffer) { BitstreamBuffer* exif_buffer) {
NOTIMPLEMENTED(); NOTIMPLEMENTED();
} }
......
...@@ -64,8 +64,8 @@ class MEDIA_GPU_EXPORT V4L2JpegEncodeAccelerator ...@@ -64,8 +64,8 @@ class MEDIA_GPU_EXPORT V4L2JpegEncodeAccelerator
void EncodeWithDmaBuf(scoped_refptr<VideoFrame> input_frame, void EncodeWithDmaBuf(scoped_refptr<VideoFrame> input_frame,
scoped_refptr<VideoFrame> output_frame, scoped_refptr<VideoFrame> output_frame,
int quality, int quality,
int32_t buffer_id, int32_t task_id,
const BitstreamBuffer* exif_buffer) override; BitstreamBuffer* exif_buffer) override;
private: private:
// Record for input buffers. // Record for input buffers.
......
...@@ -74,12 +74,15 @@ source_set("vaapi") { ...@@ -74,12 +74,15 @@ source_set("vaapi") {
deps = [ deps = [
":libva_stubs", ":libva_stubs",
"//base", "//base",
"//gpu/ipc/common",
"//gpu/ipc/service", "//gpu/ipc/service",
"//media", "//media",
"//media/gpu:common", "//media/gpu:common",
"//media/gpu:video_frame_mapper_common", "//media/gpu:video_frame_mapper_common",
"//media/gpu/linux",
"//mojo/public/cpp/bindings", "//mojo/public/cpp/bindings",
"//third_party/libyuv", "//third_party/libyuv",
"//ui/gfx",
"//ui/gfx/geometry", "//ui/gfx/geometry",
] ]
......
...@@ -48,21 +48,21 @@ class MEDIA_GPU_EXPORT VaapiJpegEncodeAccelerator ...@@ -48,21 +48,21 @@ class MEDIA_GPU_EXPORT VaapiJpegEncodeAccelerator
void EncodeWithDmaBuf(scoped_refptr<VideoFrame> input_frame, void EncodeWithDmaBuf(scoped_refptr<VideoFrame> input_frame,
scoped_refptr<VideoFrame> output_frame, scoped_refptr<VideoFrame> output_frame,
int quality, int quality,
int32_t buffer_id, int32_t task_id,
const BitstreamBuffer* exif_buffer) override; BitstreamBuffer* exif_buffer) override;
private: private:
// An input video frame and the corresponding output buffer awaiting // An input video frame and the corresponding output buffer awaiting
// consumption, provided by the client. // consumption, provided by the client.
struct EncodeRequest { struct EncodeRequest {
EncodeRequest(int32_t buffer_id, EncodeRequest(int32_t task_id,
scoped_refptr<VideoFrame> video_frame, scoped_refptr<VideoFrame> video_frame,
std::unique_ptr<UnalignedSharedMemory> exif_shm, std::unique_ptr<UnalignedSharedMemory> exif_shm,
std::unique_ptr<UnalignedSharedMemory> output_shm, std::unique_ptr<UnalignedSharedMemory> output_shm,
int quality); int quality);
~EncodeRequest(); ~EncodeRequest();
int32_t buffer_id; int32_t task_id;
scoped_refptr<VideoFrame> video_frame; scoped_refptr<VideoFrame> video_frame;
std::unique_ptr<UnalignedSharedMemory> exif_shm; std::unique_ptr<UnalignedSharedMemory> exif_shm;
std::unique_ptr<UnalignedSharedMemory> output_shm; std::unique_ptr<UnalignedSharedMemory> output_shm;
...@@ -77,9 +77,9 @@ class MEDIA_GPU_EXPORT VaapiJpegEncodeAccelerator ...@@ -77,9 +77,9 @@ class MEDIA_GPU_EXPORT VaapiJpegEncodeAccelerator
// Notifies the client that an error has occurred and encoding cannot // Notifies the client that an error has occurred and encoding cannot
// continue. // continue.
void NotifyError(int32_t buffer_id, Status status); void NotifyError(int32_t task_id, Status status);
void VideoFrameReady(int32_t buffer_id, size_t encoded_picture_size); void VideoFrameReady(int32_t task_id, size_t encoded_picture_size);
// ChildThread's task runner. // ChildThread's task runner.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_; scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
......
...@@ -110,23 +110,6 @@ uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) { ...@@ -110,23 +110,6 @@ uint32_t BufferFormatToVAFourCC(gfx::BufferFormat fmt) {
} }
} }
uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt) {
switch (fmt) {
case gfx::BufferFormat::UYVY_422:
return VA_RT_FORMAT_YUV422;
case gfx::BufferFormat::BGRX_8888:
case gfx::BufferFormat::BGRA_8888:
case gfx::BufferFormat::RGBX_8888:
return VA_RT_FORMAT_RGB32;
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
return VA_RT_FORMAT_YUV420;
default:
NOTREACHED();
return 0;
}
}
} // namespace } // namespace
namespace media { namespace media {
...@@ -1207,6 +1190,24 @@ VaapiWrapper::GetSupportedImageFormatsForTesting() { ...@@ -1207,6 +1190,24 @@ VaapiWrapper::GetSupportedImageFormatsForTesting() {
return VASupportedImageFormats::Get().GetSupportedImageFormats(); return VASupportedImageFormats::Get().GetSupportedImageFormats();
} }
// static
uint32_t VaapiWrapper::BufferFormatToVARTFormat(gfx::BufferFormat fmt) {
switch (fmt) {
case gfx::BufferFormat::UYVY_422:
return VA_RT_FORMAT_YUV422;
case gfx::BufferFormat::BGRX_8888:
case gfx::BufferFormat::BGRA_8888:
case gfx::BufferFormat::RGBX_8888:
return VA_RT_FORMAT_RGB32;
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
return VA_RT_FORMAT_YUV420;
default:
NOTREACHED();
return 0;
}
}
bool VaapiWrapper::CreateContextAndSurfaces( bool VaapiWrapper::CreateContextAndSurfaces(
unsigned int va_format, unsigned int va_format,
const gfx::Size& size, const gfx::Size& size,
......
...@@ -140,6 +140,8 @@ class MEDIA_GPU_EXPORT VaapiWrapper ...@@ -140,6 +140,8 @@ class MEDIA_GPU_EXPORT VaapiWrapper
// Returns the list of VAImageFormats supported by the driver. // Returns the list of VAImageFormats supported by the driver.
static const std::vector<VAImageFormat>& GetSupportedImageFormatsForTesting(); static const std::vector<VAImageFormat>& GetSupportedImageFormatsForTesting();
static uint32_t BufferFormatToVARTFormat(gfx::BufferFormat fmt);
// Creates |num_surfaces| backing surfaces in driver for VASurfaces of // Creates |num_surfaces| backing surfaces in driver for VASurfaces of
// |va_format|, each of size |size| and initializes |va_context_id_| with // |va_format|, each of size |size| and initializes |va_context_id_| with
// |format| and |size|. Returns true when successful, with the created IDs in // |format| and |size|. Returns true when successful, with the created IDs in
......
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