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) { |