Commit fc5da42b authored by Andres Calderon Jaramillo's avatar Andres Calderon Jaramillo Committed by Commit Bot

Make the JDA unit tests save decoded output as .png instead of .yuv.

This CL changes the JpegClient::SaveToFile method in
jpeg_decode_accelerator_unittest.cc so that it saves the decode result
as a PNG file for easy visualization. Previously, the output was a .yuv
file which couldn't be readily visualized.

This makes the problem with odd-sized images more evident. Here are
examples of the PNG output for three images (compared to a reference
output which is the result of opening the original JPEG image in GIMP):

- 80x46 JPEG (even-sized):
  Reference:
  https://drive.google.com/open?id=15hv1c4d2Iy1SPXxTk6575JPGhkGMEYnr
  Unit test:
  https://drive.google.com/open?id=1ZQtNkZzwvfIwp9kBsbwf301aIjY7zSmY

- 81x46 JPEG (odd-sized):
  Reference:
  https://drive.google.com/open?id=1WB2gW0H4XB9T4-fkRIBygXvfpKkX1rxY
  Unit test:
  https://drive.google.com/open?id=1Zprc8UaPyVoYw7IWGngSmwXNEsyy__jQ

- 80x45 JPEG (odd-sized):
  Reference:
  https://drive.google.com/open?id=1tnOQU4cvbtgIH5036pbb2qmaOLPBLOmK
  Unit test:
  https://drive.google.com/open?id=1XWXYnStEqTtLQPqDxZidaPIH4ShzDSaq

The issue with odd-sized images will be corrected in follow-up CLs.

Bug: 849776
Cq-Include-Trybots: luci.chromium.try:android_optional_gpu_tests_rel;luci.chromium.try:linux_optional_gpu_tests_rel;luci.chromium.try:mac_optional_gpu_tests_rel;luci.chromium.try:win_optional_gpu_tests_rel
Change-Id: I50a8662544b014c6d26ed8017c1a20f2fdca329f
Reviewed-on: https://chromium-review.googlesource.com/1087727
Commit-Queue: Andres Calderon Jaramillo <andrescj@chromium.org>
Reviewed-by: default avatarDaniele Castagna <dcastagna@chromium.org>
Cr-Commit-Position: refs/heads/master@{#565000}
parent b63841ff
...@@ -18,6 +18,7 @@ ...@@ -18,6 +18,7 @@
#include "base/files/file_util.h" #include "base/files/file_util.h"
#include "base/logging.h" #include "base/logging.h"
#include "base/macros.h" #include "base/macros.h"
#include "base/numerics/safe_conversions.h"
#include "base/path_service.h" #include "base/path_service.h"
#include "base/strings/string_piece.h" #include "base/strings/string_piece.h"
#include "base/strings/string_split.h" #include "base/strings/string_split.h"
...@@ -32,6 +33,7 @@ ...@@ -32,6 +33,7 @@
#include "media/video/jpeg_decode_accelerator.h" #include "media/video/jpeg_decode_accelerator.h"
#include "third_party/libyuv/include/libyuv.h" #include "third_party/libyuv/include/libyuv.h"
#include "ui/gfx/codec/jpeg_codec.h" #include "ui/gfx/codec/jpeg_codec.h"
#include "ui/gfx/codec/png_codec.h"
#if BUILDFLAG(USE_VAAPI) #if BUILDFLAG(USE_VAAPI)
#include "media/gpu/vaapi/vaapi_wrapper.h" #include "media/gpu/vaapi/vaapi_wrapper.h"
...@@ -97,7 +99,11 @@ class JpegClient : public JpegDecodeAccelerator::Client { ...@@ -97,7 +99,11 @@ class JpegClient : public JpegDecodeAccelerator::Client {
private: private:
void SetState(ClientState new_state); void SetState(ClientState new_state);
void SaveToFile(int32_t bitstream_buffer_id);
// Save a video frame that contains a decoded JPEG. The output is a PNG file.
// The suffix will be added before the .png extension.
void SaveToFile(int32_t bitstream_buffer_id,
const scoped_refptr<VideoFrame>& in_frame);
// Calculate mean absolute difference of hardware and software decode results // Calculate mean absolute difference of hardware and software decode results
// to check the similarity. // to check the similarity.
...@@ -120,6 +126,8 @@ class JpegClient : public JpegDecodeAccelerator::Client { ...@@ -120,6 +126,8 @@ class JpegClient : public JpegDecodeAccelerator::Client {
std::unique_ptr<base::SharedMemory> in_shm_; std::unique_ptr<base::SharedMemory> in_shm_;
// Mapped memory of output buffer from hardware decoder. // Mapped memory of output buffer from hardware decoder.
std::unique_ptr<base::SharedMemory> hw_out_shm_; std::unique_ptr<base::SharedMemory> hw_out_shm_;
// Video frame corresponding to the output of the hardware decoder.
scoped_refptr<VideoFrame> hw_out_frame_;
// Mapped memory of output buffer from software decoder. // Mapped memory of output buffer from software decoder.
std::unique_ptr<base::SharedMemory> sw_out_shm_; std::unique_ptr<base::SharedMemory> sw_out_shm_;
...@@ -181,7 +189,7 @@ void JpegClient::VideoFrameReady(int32_t bitstream_buffer_id) { ...@@ -181,7 +189,7 @@ void JpegClient::VideoFrameReady(int32_t bitstream_buffer_id) {
return; return;
} }
if (g_save_to_file) { if (g_save_to_file) {
SaveToFile(bitstream_buffer_id); SaveToFile(bitstream_buffer_id, hw_out_frame_);
} }
double difference = GetMeanAbsoluteDifference(bitstream_buffer_id); double difference = GetMeanAbsoluteDifference(bitstream_buffer_id);
...@@ -232,15 +240,50 @@ void JpegClient::SetState(ClientState new_state) { ...@@ -232,15 +240,50 @@ void JpegClient::SetState(ClientState new_state) {
state_ = new_state; state_ = new_state;
} }
void JpegClient::SaveToFile(int32_t bitstream_buffer_id) { void JpegClient::SaveToFile(int32_t bitstream_buffer_id,
const scoped_refptr<VideoFrame>& in_frame) {
LOG_ASSERT(in_frame.get());
TestImageFile* image_file = test_image_files_[bitstream_buffer_id]; TestImageFile* image_file = test_image_files_[bitstream_buffer_id];
base::FilePath in_filename(image_file->filename); // First convert to ARGB format. Note that in our case, the coded size and the
base::FilePath out_filename = in_filename.ReplaceExtension(".yuv"); // visible size will be the same.
int size = base::checked_cast<int>(image_file->output_size); scoped_refptr<VideoFrame> argb_out_frame = VideoFrame::CreateFrame(
ASSERT_EQ(size, VideoPixelFormat::PIXEL_FORMAT_ARGB, image_file->visible_size,
base::WriteFile(out_filename, gfx::Rect(image_file->visible_size), image_file->visible_size,
static_cast<char*>(hw_out_shm_->memory()), size)); base::TimeDelta());
LOG_ASSERT(argb_out_frame.get());
LOG_ASSERT(in_frame->visible_rect() == argb_out_frame->visible_rect());
// Note that we use J420ToARGB instead of I420ToARGB so that the
// kYuvJPEGConstants YUV-to-RGB conversion matrix is used.
const int conversion_status =
libyuv::J420ToARGB(in_frame->data(VideoFrame::kYPlane),
in_frame->stride(VideoFrame::kYPlane),
in_frame->data(VideoFrame::kUPlane),
in_frame->stride(VideoFrame::kUPlane),
in_frame->data(VideoFrame::kVPlane),
in_frame->stride(VideoFrame::kVPlane),
argb_out_frame->data(VideoFrame::kARGBPlane),
argb_out_frame->stride(VideoFrame::kARGBPlane),
argb_out_frame->visible_rect().width(),
argb_out_frame->visible_rect().height());
LOG_ASSERT(conversion_status == 0);
// Save as a PNG.
std::vector<uint8_t> png_output;
const bool png_encode_status = gfx::PNGCodec::Encode(
argb_out_frame->data(VideoFrame::kARGBPlane), gfx::PNGCodec::FORMAT_BGRA,
argb_out_frame->visible_rect().size(),
argb_out_frame->stride(VideoFrame::kARGBPlane),
true, /* discard_transparency */
std::vector<gfx::PNGCodec::Comment>(), &png_output);
LOG_ASSERT(png_encode_status);
const base::FilePath in_filename(image_file->filename);
const base::FilePath out_filename = in_filename.ReplaceExtension(".png");
const int size = base::checked_cast<int>(png_output.size());
const int file_written_bytes = base::WriteFile(
out_filename, reinterpret_cast<char*>(png_output.data()), size);
LOG_ASSERT(file_written_bytes == size);
} }
double JpegClient::GetMeanAbsoluteDifference(int32_t bitstream_buffer_id) { double JpegClient::GetMeanAbsoluteDifference(int32_t bitstream_buffer_id) {
...@@ -267,13 +310,13 @@ void JpegClient::StartDecode(int32_t bitstream_buffer_id, ...@@ -267,13 +310,13 @@ void JpegClient::StartDecode(int32_t bitstream_buffer_id,
dup_handle = base::SharedMemory::DuplicateHandle(in_shm_->handle()); dup_handle = base::SharedMemory::DuplicateHandle(in_shm_->handle());
BitstreamBuffer bitstream_buffer(bitstream_buffer_id, dup_handle, BitstreamBuffer bitstream_buffer(bitstream_buffer_id, dup_handle,
image_file->data_str.size()); image_file->data_str.size());
scoped_refptr<VideoFrame> out_frame_ = VideoFrame::WrapExternalSharedMemory( hw_out_frame_ = VideoFrame::WrapExternalSharedMemory(
PIXEL_FORMAT_I420, image_file->visible_size, PIXEL_FORMAT_I420, image_file->visible_size,
gfx::Rect(image_file->visible_size), image_file->visible_size, gfx::Rect(image_file->visible_size), image_file->visible_size,
static_cast<uint8_t*>(hw_out_shm_->memory()), image_file->output_size, static_cast<uint8_t*>(hw_out_shm_->memory()), image_file->output_size,
hw_out_shm_->handle(), 0, base::TimeDelta()); hw_out_shm_->handle(), 0, base::TimeDelta());
LOG_ASSERT(out_frame_.get()); LOG_ASSERT(hw_out_frame_.get());
decoder_->Decode(bitstream_buffer, out_frame_); decoder_->Decode(bitstream_buffer, hw_out_frame_);
} }
bool JpegClient::GetSoftwareDecodeResult(int32_t bitstream_buffer_id) { bool JpegClient::GetSoftwareDecodeResult(int32_t bitstream_buffer_id) {
......
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