Chromium Code Reviews| 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 45da3ff52968fed7391297723afc9de12f694273..d69d4937a084c4f4fae0e4723a21f2f79b7b6203 100644 |
| --- a/media/gpu/video_encode_accelerator_unittest.cc |
| +++ b/media/gpu/video_encode_accelerator_unittest.cc |
| @@ -20,6 +20,7 @@ |
| #include "base/macros.h" |
| #include "base/memory/aligned_memory.h" |
| #include "base/memory/scoped_vector.h" |
| +#include "base/memory/weak_ptr.h" |
| #include "base/message_loop/message_loop.h" |
| #include "base/numerics/safe_conversions.h" |
| #include "base/process/process_handle.h" |
| @@ -845,6 +846,9 @@ class VEAClient : public VideoEncodeAccelerator::Client { |
| void CreateEncoder(); |
| void DestroyEncoder(); |
| + void TryToSetupEncodeOnSeperateThread(); |
| + void DestroyEncodeOnSeperateThread(); |
| + |
| // VideoDecodeAccelerator::Client implementation. |
| void RequireBitstreamBuffers(unsigned int input_count, |
| const gfx::Size& input_coded_size, |
| @@ -1046,6 +1050,24 @@ class VEAClient : public VideoEncodeAccelerator::Client { |
| // The last timestamp popped from |frame_timestamps_|. |
| base::TimeDelta previous_timestamp_; |
| + |
| + // Indicates if encode is setup on on |io_thread_|. |
| + bool encode_setup_on_io_thread_; |
| + |
| + // Dummy thread used to redirect encode tasks, represents GPU IO thread. |
| + base::Thread io_thread_; |
| + |
| + // Task runner used for TryToSetupEncodeOnSeperateThread(). |
| + scoped_refptr<base::SingleThreadTaskRunner> io_thread_task_runner_; |
| + |
| + // Task runner used for trampolining from |io_thread_|. |
| + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_; |
| + |
| + // Weak factories to use for TryToSetupEncodeOnSeperateThread() on |
| + // |io_thread_|. |
| + std::unique_ptr<base::WeakPtrFactory<VideoEncodeAccelerator>> |
| + encoder_weak_factory_; |
| + base::WeakPtrFactory<VEAClient> client_weak_factory_; |
| }; |
| VEAClient::VEAClient(TestStream* test_stream, |
| @@ -1084,7 +1106,10 @@ VEAClient::VEAClient(TestStream* test_stream, |
| requested_bitrate_(0), |
| requested_framerate_(0), |
| requested_subsequent_bitrate_(0), |
| - requested_subsequent_framerate_(0) { |
| + requested_subsequent_framerate_(0), |
| + encode_setup_on_io_thread_(false), |
| + io_thread_("IOThread"), |
| + client_weak_factory_(this) { |
| if (keyframe_period_) |
| LOG_ASSERT(kMaxKeyframeDelay < keyframe_period_); |
| @@ -1167,6 +1192,8 @@ void VEAClient::CreateEncoder() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| LOG_ASSERT(!has_encoder()); |
| + main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get(); |
| + |
| std::unique_ptr<VideoEncodeAccelerator> encoders[] = { |
| CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(), |
| CreateMFVEA()}; |
| @@ -1182,6 +1209,7 @@ void VEAClient::CreateEncoder() { |
| if (encoder_->Initialize(kInputFormat, test_stream_->visible_size, |
| test_stream_->requested_profile, |
| requested_bitrate_, this)) { |
| + TryToSetupEncodeOnSeperateThread(); |
| SetStreamParameters(requested_bitrate_, requested_framerate_); |
| SetState(CS_INITIALIZED); |
| @@ -1202,6 +1230,25 @@ void VEAClient::DecodeCompleted() { |
| SetState(CS_VALIDATED); |
| } |
| +void VEAClient::TryToSetupEncodeOnSeperateThread() { |
| + // Start dummy thread if not started. |
| + if (!io_thread_.IsRunning()) { |
| + ASSERT_TRUE(io_thread_.Start()); |
| + io_thread_task_runner_ = io_thread_.task_runner(); |
| + } |
| + |
| + if (!encoder_->TryToSetupEncodeOnSeparateThread( |
| + client_weak_factory_.GetWeakPtr(), io_thread_task_runner_)) { |
| + io_thread_.Stop(); |
| + encode_setup_on_io_thread_ = false; |
| + return; |
| + } |
| + |
| + encoder_weak_factory_.reset( |
| + new base::WeakPtrFactory<VideoEncodeAccelerator>(encoder_.get())); |
| + encode_setup_on_io_thread_ = true; |
| +} |
| + |
| void VEAClient::DecodeFailed() { |
| SetState(CS_ERROR); |
| } |
| @@ -1210,12 +1257,25 @@ void VEAClient::DestroyEncoder() { |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| if (!has_encoder()) |
| return; |
| + |
| + if (encode_setup_on_io_thread_) { |
| + io_thread_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&VEAClient::DestroyEncodeOnSeperateThread, |
| + client_weak_factory_.GetWeakPtr())); |
| + io_thread_.Stop(); |
| + } |
| + |
| // Clear the objects that should be destroyed on the same thread as creation. |
| encoder_.reset(); |
| input_timer_.reset(); |
| quality_validator_.reset(); |
| } |
| +void VEAClient::DestroyEncodeOnSeperateThread() { |
| + client_weak_factory_.InvalidateWeakPtrs(); |
| + encoder_weak_factory_->InvalidateWeakPtrs(); |
| +} |
| + |
| void VEAClient::UpdateTestStreamData(bool mid_stream_bitrate_switch, |
| bool mid_stream_framerate_switch) { |
| // Use defaults for bitrate/framerate if they are not provided. |
| @@ -1336,7 +1396,16 @@ void VEAClient::BitstreamBufferReady(int32_t bitstream_buffer_id, |
| size_t payload_size, |
| bool key_frame, |
| base::TimeDelta timestamp) { |
| + if (encode_setup_on_io_thread_ && |
|
Pawel Osciak
2016/10/31 07:40:22
If you'd accept my suggestion below, we could ASSE
emircan
2016/10/31 19:45:08
Done.
|
| + io_thread_task_runner_->BelongsToCurrentThread()) { |
| + main_thread_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&VEAClient::BitstreamBufferReady, base::Unretained(this), |
| + bitstream_buffer_id, payload_size, key_frame, timestamp)); |
| + return; |
| + } |
| DCHECK(thread_checker_.CalledOnValidThread()); |
| + |
| ASSERT_LE(payload_size, output_buffer_size_); |
| IdToSHM::iterator it = output_buffers_at_client_.find(bitstream_buffer_id); |
| @@ -1405,8 +1474,15 @@ void VEAClient::SetStreamParameters(unsigned int bitrate, |
| current_framerate_ = framerate; |
| LOG_ASSERT(current_requested_bitrate_ > 0UL); |
| LOG_ASSERT(current_framerate_ > 0UL); |
| - encoder_->RequestEncodingParametersChange(current_requested_bitrate_, |
| - current_framerate_); |
| + if (encode_setup_on_io_thread_) { |
| + io_thread_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&VideoEncodeAccelerator::RequestEncodingParametersChange, |
| + encoder_weak_factory_->GetWeakPtr(), bitrate, framerate)); |
| + } else { |
| + encoder_->RequestEncodingParametersChange(current_requested_bitrate_, |
| + current_framerate_); |
| + } |
| DVLOG(1) << "Switched parameters to " << current_requested_bitrate_ |
| << " bps @ " << current_framerate_ << " FPS"; |
| } |
| @@ -1505,7 +1581,15 @@ void VEAClient::FeedEncoderWithOneInput() { |
| LOG_ASSERT(input_id == static_cast<int32_t>(encode_start_time_.size())); |
| encode_start_time_.push_back(base::TimeTicks::Now()); |
| } |
| - encoder_->Encode(video_frame, force_keyframe); |
| + |
| + if (encode_setup_on_io_thread_) { |
|
Pawel Osciak
2016/10/31 07:40:21
Perhaps we could remove encode_setup_on_io_thread_
emircan
2016/10/31 19:45:08
Done.
|
| + io_thread_task_runner_->PostTask( |
| + FROM_HERE, base::Bind(&VideoEncodeAccelerator::Encode, |
| + encoder_weak_factory_->GetWeakPtr(), video_frame, |
| + force_keyframe)); |
| + } else { |
| + encoder_->Encode(video_frame, force_keyframe); |
| + } |
| } |
| void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { |
| @@ -1523,7 +1607,15 @@ void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) { |
| LOG_ASSERT(output_buffers_at_client_ |
| .insert(std::make_pair(bitstream_buffer.id(), shm)) |
| .second); |
| - encoder_->UseOutputBitstreamBuffer(bitstream_buffer); |
| + |
| + if (encode_setup_on_io_thread_) { |
| + io_thread_task_runner_->PostTask( |
| + FROM_HERE, |
| + base::Bind(&VideoEncodeAccelerator::UseOutputBitstreamBuffer, |
| + encoder_weak_factory_->GetWeakPtr(), bitstream_buffer)); |
| + } else { |
| + encoder_->UseOutputBitstreamBuffer(bitstream_buffer); |
| + } |
| } |
| bool VEAClient::HandleEncodedFrame(bool keyframe) { |