Commit 5cddb472 authored by David Staessens's avatar David Staessens Committed by Commit Bot

media/gpu/vaapi: Reuse surface if size doesn't change between jpeg encodes.

When decoding a jpeg the generated surface is reused when the video frame size
doesn't change. When encoding a jpeg a new surface is created every time. This
change enables reusing of surfaces for jpeg encoding.

This also fixes a bug that causes the jpeg_encode_accelerator_unittest to always
fail in debug, because surfaces are not properly destroyed before creating new
ones.

TEST=JPEG encode tests on nocturne

BUG=905502

Change-Id: I9a6b0b5703813e518a3e82687b289e94745e1c62
Reviewed-on: https://chromium-review.googlesource.com/c/1337130
Commit-Queue: David Staessens <dstaessens@chromium.org>
Reviewed-by: default avatarPawel Osciak <posciak@chromium.org>
Reviewed-by: default avatarHirokazu Honda <hiroh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#608683}
parent 2e8d4443
...@@ -81,6 +81,11 @@ class VaapiJpegEncodeAccelerator::Encoder { ...@@ -81,6 +81,11 @@ class VaapiJpegEncodeAccelerator::Encoder {
base::RepeatingCallback<void(int32_t, size_t)> video_frame_ready_cb_; base::RepeatingCallback<void(int32_t, size_t)> video_frame_ready_cb_;
base::RepeatingCallback<void(int32_t, Status)> notify_error_cb_; base::RepeatingCallback<void(int32_t, Status)> notify_error_cb_;
// The current VA surface used for encoding.
VASurfaceID va_surface_id_;
// The size of the surface associated with |va_surface_id_|.
gfx::Size surface_size_;
SEQUENCE_CHECKER(sequence_checker_); SEQUENCE_CHECKER(sequence_checker_);
DISALLOW_COPY_AND_ASSIGN(Encoder); DISALLOW_COPY_AND_ASSIGN(Encoder);
...@@ -94,7 +99,8 @@ VaapiJpegEncodeAccelerator::Encoder::Encoder( ...@@ -94,7 +99,8 @@ VaapiJpegEncodeAccelerator::Encoder::Encoder(
jpeg_encoder_(new VaapiJpegEncoder(vaapi_wrapper)), jpeg_encoder_(new VaapiJpegEncoder(vaapi_wrapper)),
vaapi_wrapper_(std::move(vaapi_wrapper)), vaapi_wrapper_(std::move(vaapi_wrapper)),
video_frame_ready_cb_(std::move(video_frame_ready_cb)), video_frame_ready_cb_(std::move(video_frame_ready_cb)),
notify_error_cb_(std::move(notify_error_cb)) { notify_error_cb_(std::move(notify_error_cb)),
va_surface_id_(VA_INVALID_SURFACE) {
DETACH_FROM_SEQUENCE(sequence_checker_); DETACH_FROM_SEQUENCE(sequence_checker_);
} }
...@@ -110,17 +116,26 @@ void VaapiJpegEncodeAccelerator::Encoder::EncodeTask( ...@@ -110,17 +116,26 @@ void VaapiJpegEncodeAccelerator::Encoder::EncodeTask(
const int buffer_id = request->buffer_id; const int buffer_id = request->buffer_id;
gfx::Size input_size = request->video_frame->coded_size(); gfx::Size input_size = request->video_frame->coded_size();
std::vector<VASurfaceID> va_surfaces;
if (!vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, input_size, 1, // Recreate VASurface if the video frame's size changed.
&va_surfaces)) { if (input_size != surface_size_ || va_surface_id_ == VA_INVALID_SURFACE) {
VLOGF(1) << "Failed to create VA surface"; vaapi_wrapper_->DestroySurfaces();
notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE); va_surface_id_ = VA_INVALID_SURFACE;
return; surface_size_ = gfx::Size();
std::vector<VASurfaceID> va_surfaces;
if (!vaapi_wrapper_->CreateSurfaces(VA_RT_FORMAT_YUV420, input_size, 1,
&va_surfaces)) {
VLOGF(1) << "Failed to create VA surface";
notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
return;
}
va_surface_id_ = va_surfaces[0];
surface_size_ = input_size;
} }
VASurfaceID va_surface_id = va_surfaces[0];
if (!vaapi_wrapper_->UploadVideoFrameToSurface(request->video_frame, if (!vaapi_wrapper_->UploadVideoFrameToSurface(request->video_frame,
va_surface_id)) { va_surface_id_)) {
VLOGF(1) << "Failed to upload video frame to VA surface"; VLOGF(1) << "Failed to upload video frame to VA surface";
notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE); notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
return; return;
...@@ -159,7 +174,7 @@ void VaapiJpegEncodeAccelerator::Encoder::EncodeTask( ...@@ -159,7 +174,7 @@ void VaapiJpegEncodeAccelerator::Encoder::EncodeTask(
std::vector<uint8_t> exif_buffer_dummy(exif_buffer_size, 0); std::vector<uint8_t> exif_buffer_dummy(exif_buffer_size, 0);
size_t exif_offset = 0; size_t exif_offset = 0;
if (!jpeg_encoder_->Encode(input_size, exif_buffer_dummy.data(), if (!jpeg_encoder_->Encode(input_size, exif_buffer_dummy.data(),
exif_buffer_size, request->quality, va_surface_id, exif_buffer_size, request->quality, va_surface_id_,
cached_output_buffer_id_, &exif_offset)) { cached_output_buffer_id_, &exif_offset)) {
VLOGF(1) << "Encode JPEG failed"; VLOGF(1) << "Encode JPEG failed";
notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE); notify_error_cb_.Run(buffer_id, PLATFORM_FAILURE);
...@@ -170,7 +185,7 @@ void VaapiJpegEncodeAccelerator::Encoder::EncodeTask( ...@@ -170,7 +185,7 @@ void VaapiJpegEncodeAccelerator::Encoder::EncodeTask(
// would wait until encoding is finished. // would wait until encoding is finished.
size_t encoded_size = 0; size_t encoded_size = 0;
if (!vaapi_wrapper_->DownloadFromCodedBuffer( if (!vaapi_wrapper_->DownloadFromCodedBuffer(
cached_output_buffer_id_, va_surface_id, cached_output_buffer_id_, va_surface_id_,
static_cast<uint8_t*>(request->output_shm->memory()), static_cast<uint8_t*>(request->output_shm->memory()),
request->output_shm->size(), &encoded_size)) { request->output_shm->size(), &encoded_size)) {
VLOGF(1) << "Failed to retrieve output image from VA coded buffer"; VLOGF(1) << "Failed to retrieve output image from VA coded buffer";
......
...@@ -888,13 +888,15 @@ bool VaapiWrapper::CreateSurfaces(unsigned int va_format, ...@@ -888,13 +888,15 @@ bool VaapiWrapper::CreateSurfaces(unsigned int va_format,
std::vector<VASurfaceID>* va_surfaces) { std::vector<VASurfaceID>* va_surfaces) {
base::AutoLock auto_lock(*va_lock_); base::AutoLock auto_lock(*va_lock_);
DVLOG(2) << "Creating " << num_surfaces << " surfaces"; DVLOG(2) << "Creating " << num_surfaces << " surfaces";
DCHECK(va_surfaces->empty()); DCHECK(va_surfaces->empty());
DCHECK(va_surface_ids_.empty());
DCHECK_EQ(va_surface_format_, 0u); if (!va_surface_ids_.empty() || va_surface_format_ != 0u) {
va_surface_ids_.resize(num_surfaces); LOG(ERROR) << "Surfaces should be destroyed before creating new surfaces";
return false;
}
// Allocate surfaces in driver. // Allocate surfaces in driver.
va_surface_ids_.resize(num_surfaces);
VAStatus va_res = VAStatus va_res =
vaCreateSurfaces(va_display_, va_format, size.width(), size.height(), vaCreateSurfaces(va_display_, va_format, size.width(), size.height(),
&va_surface_ids_[0], va_surface_ids_.size(), NULL, 0); &va_surface_ids_[0], va_surface_ids_.size(), NULL, 0);
......
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