Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(592)

Unified Diff: media/gpu/video_encode_accelerator_unittest.cc

Issue 2525563005: VEA unittest: add a test case for cache line-alignment (Closed)
Patch Set: VEA unittest: add a test case for cache line-alignment Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: media/gpu/video_encode_accelerator_unittest.cc
diff --git a/media/gpu/video_encode_accelerator_unittest.cc b/media/gpu/video_encode_accelerator_unittest.cc
index 4e0dd6ad8ec14bcdf064266d6eb131e9d8a9b3d5..5d9e52bee69af436fea4a9dad9578cd56ed22aae 100644
--- a/media/gpu/video_encode_accelerator_unittest.cc
+++ b/media/gpu/video_encode_accelerator_unittest.cc
@@ -1762,9 +1762,161 @@ void VEAClient::WriteIvfFrameHeader(int frame_index, size_t frame_size) {
// This client is only used to make sure the encoder does not return an encoded
// frame before getting any input.
class VEANoInputClient : public VideoEncodeAccelerator::Client {
wuchengli 2016/11/23 14:43:33 There are some boilerplate code in every VEAXxxCli
hywu1 2016/11/24 06:01:29 Done.
+ public:
Owen Lin 2016/11/24 03:00:52 Did you change the code here on purpose? I think
hywu1 2016/11/24 06:01:29 Done.
+ explicit VEANoInputClient(ClientStateNotification<ClientState>* note);
+ ~VEANoInputClient() override;
+ void CreateEncoder();
+ void DestroyEncoder();
+
+ // VideoDecodeAccelerator::Client implementation.
+ void RequireBitstreamBuffers(unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_buffer_size) override;
+ void BitstreamBufferReady(int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) override;
+ void NotifyError(VideoEncodeAccelerator::Error error) override;
+
+ private:
+ bool has_encoder() { return encoder_.get(); }
+
+ void SetState(ClientState new_state);
+
+ // Provide the encoder with a new output buffer.
+ void FeedEncoderWithOutput(base::SharedMemory* shm, size_t output_size);
+
+ std::unique_ptr<VideoEncodeAccelerator> encoder_;
+
+ // Used to notify another thread about the state. VEAClient does not own this.
wuchengli 2016/11/23 14:43:33 Please run git cl format to check the style.
hywu1 2016/11/24 06:01:29 Done.
+ ClientStateNotification<ClientState>* note_;
+
+ // All methods of this class should be run on the same thread.
+ base::ThreadChecker thread_checker_;
+
+ // Ids for output BitstreamBuffers.
+ ScopedVector<base::SharedMemory> output_shms_;
+ int32_t next_output_buffer_id_;
+
+ // The timer used to monitor the encoder doesn't return an output buffer in
+ // a period of time.
+ std::unique_ptr<base::Timer> timer_;
+};
+
+VEANoInputClient::VEANoInputClient(ClientStateNotification<ClientState>* note)
+ : note_(note), next_output_buffer_id_(0) {
+ thread_checker_.DetachFromThread();
+ }
+
+VEANoInputClient::~VEANoInputClient() {
+ LOG_ASSERT(!has_encoder());
+}
+
+void VEANoInputClient::CreateEncoder() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ LOG_ASSERT(!has_encoder());
+ LOG_ASSERT(g_env->test_streams_.size());
+
+ const int kDefaultWidth = 320;
+ const int kDefaultHeight = 240;
+ const int kDefaultBitrate = 200000;
+ const int kDefaultFps = 30;
+
+ std::unique_ptr<VideoEncodeAccelerator> encoders[] = {
+ CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(),
+ CreateMFVEA()};
+
+ // The test case is no input. Use default visible size, bitrate, and fps.
+ gfx::Size visible_size(kDefaultWidth, kDefaultHeight);
+ for (auto& encoder : encoders) {
+ if (!encoder)
+ continue;
+ encoder_ = std::move(encoder);
+ if (encoder_->Initialize(kInputFormat, visible_size,
+ g_env->test_streams_[0]->requested_profile,
+ kDefaultBitrate, this)) {
+ encoder_->RequestEncodingParametersChange(kDefaultBitrate, kDefaultFps);
+ SetState(CS_INITIALIZED);
+ return;
+ }
+ }
+ encoder_.reset();
+ LOG(ERROR) << "VideoEncodeAccelerator::Initialize() failed";
+ SetState(CS_ERROR);
+}
+
+void VEANoInputClient::DestroyEncoder() {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ if (!has_encoder())
+ return;
+ // Clear the objects that should be destroyed on the same thread as creation.
+ encoder_.reset();
+ timer_.reset();
+}
+
+void VEANoInputClient::RequireBitstreamBuffers(
+ unsigned int input_count,
+ const gfx::Size& input_coded_size,
+ size_t output_size) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ SetState(CS_ENCODING);
+ ASSERT_GT(output_size, 0UL);
+
+ for (unsigned int i = 0; i < kNumOutputBuffers; ++i) {
+ base::SharedMemory* shm = new base::SharedMemory();
+ LOG_ASSERT(shm->CreateAndMapAnonymous(output_size));
+ output_shms_.push_back(shm);
+ FeedEncoderWithOutput(shm, output_size);
+ }
+ // Timer is used to make sure there is no output frame in 100ms.
+ timer_.reset(new base::Timer(FROM_HERE,
+ base::TimeDelta::FromMilliseconds(100),
+ base::Bind(&VEANoInputClient::SetState,
+ base::Unretained(this), CS_FINISHED),
+ false));
+ timer_->Reset();
+}
+
+void VEANoInputClient::BitstreamBufferReady(int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ SetState(CS_ERROR);
+}
+
+void VEANoInputClient::NotifyError(VideoEncodeAccelerator::Error error) {
+ DCHECK(thread_checker_.CalledOnValidThread());
+ SetState(CS_ERROR);
+}
+
+void VEANoInputClient::SetState(ClientState new_state) {
+ DVLOG(4) << "Changing state to " << new_state;
+ note_->Notify(new_state);
+}
+
+void VEANoInputClient::FeedEncoderWithOutput(base::SharedMemory* shm,
+ size_t output_size) {
+ if (!has_encoder())
+ return;
+
+ base::SharedMemoryHandle dup_handle;
+ LOG_ASSERT(shm->ShareToProcess(base::GetCurrentProcessHandle(), &dup_handle));
+
+ BitstreamBuffer bitstream_buffer(next_output_buffer_id_++, dup_handle,
+ output_size);
+ encoder_->UseOutputBitstreamBuffer(bitstream_buffer);
+}
+
+/* This client is only used to test input frame with the size of U and V planes
+ unaligned to cache line.
+ To have both width and height divisible by 16 but not 32 will make the size
+ of U/V plane (width * height / 4) unaligned to 128-byte cache line. */
+class VEACacheLineUnalignedInputClient : public VideoEncodeAccelerator::Client {
public:
- explicit VEANoInputClient(ClientStateNotification<ClientState>* note);
- ~VEANoInputClient() override;
+ explicit VEACacheLineUnalignedInputClient(
+ ClientStateNotification<ClientState>* note);
+ ~VEACacheLineUnalignedInputClient() override;
void CreateEncoder();
void DestroyEncoder();
@@ -1786,6 +1938,9 @@ class VEANoInputClient : public VideoEncodeAccelerator::Client {
// Provide the encoder with a new output buffer.
void FeedEncoderWithOutput(base::SharedMemory* shm, size_t output_size);
+ // Feed the encoder with one input frame.
+ void FeedEncoderWithOneInput(const gfx::Size& input_coded_size);
+
std::unique_ptr<VideoEncodeAccelerator> encoder_;
// Used to notify another thread about the state. VEAClient does not own this.
@@ -1798,44 +1953,44 @@ class VEANoInputClient : public VideoEncodeAccelerator::Client {
ScopedVector<base::SharedMemory> output_shms_;
int32_t next_output_buffer_id_;
- // The timer used to monitor the encoder doesn't return an output buffer in
- // a period of time.
- std::unique_ptr<base::Timer> timer_;
+ const int default_width_;
+ const int default_height_;
+ const int default_bitrate_;
+ const int default_fps_;
};
-VEANoInputClient::VEANoInputClient(ClientStateNotification<ClientState>* note)
- : note_(note), next_output_buffer_id_(0) {
+VEACacheLineUnalignedInputClient::VEACacheLineUnalignedInputClient(
+ ClientStateNotification<ClientState>* note)
+ : note_(note),
+ next_output_buffer_id_(0),
+ default_width_(368), // divisible by 16 but not 32
+ default_height_(368), // divisible by 16 but not 32
+ default_bitrate_(200000),
+ default_fps_(30) {
thread_checker_.DetachFromThread();
}
-VEANoInputClient::~VEANoInputClient() {
+VEACacheLineUnalignedInputClient::~VEACacheLineUnalignedInputClient() {
LOG_ASSERT(!has_encoder());
}
-void VEANoInputClient::CreateEncoder() {
+void VEACacheLineUnalignedInputClient::CreateEncoder() {
DCHECK(thread_checker_.CalledOnValidThread());
LOG_ASSERT(!has_encoder());
- LOG_ASSERT(g_env->test_streams_.size());
-
- const int kDefaultWidth = 320;
- const int kDefaultHeight = 240;
- const int kDefaultBitrate = 200000;
- const int kDefaultFps = 30;
std::unique_ptr<VideoEncodeAccelerator> encoders[] = {
CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(),
CreateMFVEA()};
- // The test case is no input. Use default visible size, bitrate, and fps.
- gfx::Size visible_size(kDefaultWidth, kDefaultHeight);
+ gfx::Size visible_size(default_width_, default_height_);
for (auto& encoder : encoders) {
if (!encoder)
continue;
encoder_ = std::move(encoder);
if (encoder_->Initialize(kInputFormat, visible_size,
g_env->test_streams_[0]->requested_profile,
- kDefaultBitrate, this)) {
- encoder_->RequestEncodingParametersChange(kDefaultBitrate, kDefaultFps);
+ default_bitrate_, this)) {
+ encoder_->RequestEncodingParametersChange(default_bitrate_, default_fps_);
SetState(CS_INITIALIZED);
return;
}
@@ -1845,16 +2000,15 @@ void VEANoInputClient::CreateEncoder() {
SetState(CS_ERROR);
}
-void VEANoInputClient::DestroyEncoder() {
+void VEACacheLineUnalignedInputClient::DestroyEncoder() {
DCHECK(thread_checker_.CalledOnValidThread());
if (!has_encoder())
return;
// Clear the objects that should be destroyed on the same thread as creation.
encoder_.reset();
- timer_.reset();
}
-void VEANoInputClient::RequireBitstreamBuffers(
+void VEACacheLineUnalignedInputClient::RequireBitstreamBuffers(
unsigned int input_count,
const gfx::Size& input_coded_size,
size_t output_size) {
@@ -1868,35 +2022,33 @@ void VEANoInputClient::RequireBitstreamBuffers(
output_shms_.push_back(shm);
FeedEncoderWithOutput(shm, output_size);
}
- // Timer is used to make sure there is no output frame in 100ms.
- timer_.reset(new base::Timer(FROM_HERE,
- base::TimeDelta::FromMilliseconds(100),
- base::Bind(&VEANoInputClient::SetState,
- base::Unretained(this), CS_FINISHED),
- false));
- timer_->Reset();
+ FeedEncoderWithOneInput(input_coded_size);
}
-void VEANoInputClient::BitstreamBufferReady(int32_t bitstream_buffer_id,
- size_t payload_size,
- bool key_frame,
- base::TimeDelta timestamp) {
+void VEACacheLineUnalignedInputClient::BitstreamBufferReady(
+ int32_t bitstream_buffer_id,
+ size_t payload_size,
+ bool key_frame,
+ base::TimeDelta timestamp) {
DCHECK(thread_checker_.CalledOnValidThread());
- SetState(CS_ERROR);
+ // It's enough to encode just one frame
+ SetState(CS_FINISHED);
}
-void VEANoInputClient::NotifyError(VideoEncodeAccelerator::Error error) {
+void VEACacheLineUnalignedInputClient::NotifyError(
+ VideoEncodeAccelerator::Error error) {
DCHECK(thread_checker_.CalledOnValidThread());
SetState(CS_ERROR);
}
-void VEANoInputClient::SetState(ClientState new_state) {
+void VEACacheLineUnalignedInputClient::SetState(ClientState new_state) {
DVLOG(4) << "Changing state to " << new_state;
note_->Notify(new_state);
}
-void VEANoInputClient::FeedEncoderWithOutput(base::SharedMemory* shm,
- size_t output_size) {
+void VEACacheLineUnalignedInputClient::FeedEncoderWithOutput(
+ base::SharedMemory* shm,
+ size_t output_size) {
if (!has_encoder())
return;
@@ -1908,6 +2060,32 @@ void VEANoInputClient::FeedEncoderWithOutput(base::SharedMemory* shm,
encoder_->UseOutputBitstreamBuffer(bitstream_buffer);
}
+void VEACacheLineUnalignedInputClient::FeedEncoderWithOneInput(
+ const gfx::Size& input_coded_size) {
+ if (!has_encoder())
+ return;
+
+ std::vector<char, AlignedAllocator<char, kPlatformBufferAlignment>>
+ aligned_in_file_data(VideoFrame::AllocationSize(PIXEL_FORMAT_I420,
+ input_coded_size));
+
+ uint8_t* frame_data_y = reinterpret_cast<uint8_t*>(&aligned_in_file_data[0]);
+ uint8_t* frame_data_u = frame_data_y +
+ VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 0, input_coded_size).GetArea();
+ uint8_t* frame_data_v = frame_data_u +
+ VideoFrame::PlaneSize(PIXEL_FORMAT_I420, 1, input_coded_size).GetArea();
+
+ scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapExternalYuvData(
+ PIXEL_FORMAT_I420, input_coded_size, gfx::Rect(input_coded_size),
+ input_coded_size, input_coded_size.width(),
+ input_coded_size.width() / 2, input_coded_size.width() / 2,
+ frame_data_y, frame_data_u, frame_data_v,
+ base::TimeDelta().FromMilliseconds(
+ base::Time::kMillisecondsPerSecond / default_fps_));
+
+ encoder_->Encode(video_frame, false);
+}
+
// Test parameters:
// - Number of concurrent encoders. The value takes effect when there is only
// one input stream; otherwise, one encoder per input stream will be
@@ -2076,6 +2254,41 @@ TEST(VEANoInputTest, CheckOutput) {
encoder_thread.Stop();
}
+TEST(VEACacheLineUnalignedInputTest, CheckOutput) {
+ std::unique_ptr<ClientStateNotification<ClientState>> note(
+ new ClientStateNotification<ClientState>());
+ std::unique_ptr<VEACacheLineUnalignedInputClient> client(
+ new VEACacheLineUnalignedInputClient(note.get()));
+ base::Thread encoder_thread("EncoderThread");
+ ASSERT_TRUE(encoder_thread.Start());
+
+ encoder_thread.task_runner()->PostTask(
+ FROM_HERE, base::Bind(&VEACacheLineUnalignedInputClient::CreateEncoder,
+ base::Unretained(client.get())));
+
+ // Encoder must pass through states in this order.
+ enum ClientState state_transitions[] = {CS_INITIALIZED, CS_ENCODING,
+ CS_FINISHED};
+
+ ClientState expected_state, wait_state;
+ for (const auto& state : state_transitions) {
+ expected_state = state;
+ wait_state = note->Wait();
+ if (expected_state != wait_state) {
+ break;
+ }
+ }
+
+ encoder_thread.task_runner()->PostTask(
+ FROM_HERE, base::Bind(&VEACacheLineUnalignedInputClient::DestroyEncoder,
+ base::Unretained(client.get())));
+
+ // This ensures all tasks have finished.
+ encoder_thread.Stop();
+
+ ASSERT_EQ(expected_state, wait_state);
+}
+
#elif defined(OS_MACOSX) || defined(OS_WIN)
INSTANTIATE_TEST_CASE_P(
SimpleEncode,
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698