| 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..44b3d4cda742305848f232a9ad381b50e696163d 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,
|
| @@ -856,6 +860,10 @@ class VEAClient : public VideoEncodeAccelerator::Client {
|
| void NotifyError(VideoEncodeAccelerator::Error error) override;
|
|
|
| private:
|
| + void BitstreamBufferReadyOnMainThread(int32_t bitstream_buffer_id,
|
| + size_t payload_size,
|
| + bool key_frame,
|
| + base::TimeDelta timestamp);
|
| bool has_encoder() { return encoder_.get(); }
|
|
|
| // Return the number of encoded frames per second.
|
| @@ -1046,6 +1054,24 @@ class VEAClient : public VideoEncodeAccelerator::Client {
|
|
|
| // The last timestamp popped from |frame_timestamps_|.
|
| base::TimeDelta previous_timestamp_;
|
| +
|
| + // Dummy thread used to redirect encode tasks, represents GPU IO thread.
|
| + base::Thread io_thread_;
|
| +
|
| + // Task runner on which |encoder_| is created.
|
| + scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
|
| +
|
| + // Task runner used for posting encode tasks. If
|
| + // TryToSetupEncodeOnSeperateThread() is true, |io_thread|'s task runner is
|
| + // used, otherwise |main_thread_task_runner_|.
|
| + scoped_refptr<base::SingleThreadTaskRunner> encode_task_runner_;
|
| +
|
| + // Weak factory used for posting tasks on |encode_task_runner_|.
|
| + std::unique_ptr<base::WeakPtrFactory<VideoEncodeAccelerator>>
|
| + encoder_weak_factory_;
|
| +
|
| + // Weak factory used for TryToSetupEncodeOnSeperateThread().
|
| + base::WeakPtrFactory<VEAClient> client_weak_factory_for_io_;
|
| };
|
|
|
| VEAClient::VEAClient(TestStream* test_stream,
|
| @@ -1084,7 +1110,9 @@ VEAClient::VEAClient(TestStream* test_stream,
|
| requested_bitrate_(0),
|
| requested_framerate_(0),
|
| requested_subsequent_bitrate_(0),
|
| - requested_subsequent_framerate_(0) {
|
| + requested_subsequent_framerate_(0),
|
| + io_thread_("IOThread"),
|
| + client_weak_factory_for_io_(this) {
|
| if (keyframe_period_)
|
| LOG_ASSERT(kMaxKeyframeDelay < keyframe_period_);
|
|
|
| @@ -1167,6 +1195,9 @@ void VEAClient::CreateEncoder() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| LOG_ASSERT(!has_encoder());
|
|
|
| + main_thread_task_runner_ = base::ThreadTaskRunnerHandle::Get();
|
| + encode_task_runner_ = main_thread_task_runner_;
|
| +
|
| std::unique_ptr<VideoEncodeAccelerator> encoders[] = {
|
| CreateFakeVEA(), CreateV4L2VEA(), CreateVaapiVEA(), CreateVTVEA(),
|
| CreateMFVEA()};
|
| @@ -1182,6 +1213,9 @@ void VEAClient::CreateEncoder() {
|
| if (encoder_->Initialize(kInputFormat, test_stream_->visible_size,
|
| test_stream_->requested_profile,
|
| requested_bitrate_, this)) {
|
| + encoder_weak_factory_.reset(
|
| + new base::WeakPtrFactory<VideoEncodeAccelerator>(encoder_.get()));
|
| + TryToSetupEncodeOnSeperateThread();
|
| SetStreamParameters(requested_bitrate_, requested_framerate_);
|
| SetState(CS_INITIALIZED);
|
|
|
| @@ -1202,6 +1236,20 @@ void VEAClient::DecodeCompleted() {
|
| SetState(CS_VALIDATED);
|
| }
|
|
|
| +void VEAClient::TryToSetupEncodeOnSeperateThread() {
|
| + // Start dummy thread if not started already.
|
| + if (!io_thread_.IsRunning())
|
| + ASSERT_TRUE(io_thread_.Start());
|
| +
|
| + if (!encoder_->TryToSetupEncodeOnSeparateThread(
|
| + client_weak_factory_for_io_.GetWeakPtr(), io_thread_.task_runner())) {
|
| + io_thread_.Stop();
|
| + return;
|
| + }
|
| +
|
| + encode_task_runner_ = io_thread_.task_runner();
|
| +}
|
| +
|
| void VEAClient::DecodeFailed() {
|
| SetState(CS_ERROR);
|
| }
|
| @@ -1210,12 +1258,33 @@ void VEAClient::DestroyEncoder() {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| if (!has_encoder())
|
| return;
|
| +
|
| + if (io_thread_.IsRunning()) {
|
| + encode_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&VEAClient::DestroyEncodeOnSeperateThread,
|
| + client_weak_factory_for_io_.GetWeakPtr()));
|
| + io_thread_.Stop();
|
| + } else {
|
| + DestroyEncodeOnSeperateThread();
|
| + }
|
| +
|
| // Clear the objects that should be destroyed on the same thread as creation.
|
| encoder_.reset();
|
| input_timer_.reset();
|
| quality_validator_.reset();
|
| }
|
|
|
| +void VEAClient::DestroyEncodeOnSeperateThread() {
|
| + encoder_weak_factory_->InvalidateWeakPtrs();
|
| + // |client_weak_factory_for_io_| is used only when
|
| + // TryToSetupEncodeOnSeperateThread() returns true, in order to have weak
|
| + // pointers to use when posting tasks on |io_thread_|. It is safe to
|
| + // invalidate here because |encode_task_runner_| points to |io_thread_| in
|
| + // this case. If not, it is safe to invalidate it on
|
| + // |main_thread_task_runner_| as no weak pointers are used.
|
| + client_weak_factory_for_io_.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 +1405,24 @@ void VEAClient::BitstreamBufferReady(int32_t bitstream_buffer_id,
|
| size_t payload_size,
|
| bool key_frame,
|
| base::TimeDelta timestamp) {
|
| + ASSERT_TRUE(encode_task_runner_->BelongsToCurrentThread());
|
| + main_thread_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&VEAClient::BitstreamBufferReadyOnMainThread,
|
| + base::Unretained(this), bitstream_buffer_id,
|
| + payload_size, key_frame, timestamp));
|
| +}
|
| +
|
| +void VEAClient::NotifyError(VideoEncodeAccelerator::Error error) {
|
| + DCHECK(thread_checker_.CalledOnValidThread());
|
| + SetState(CS_ERROR);
|
| +}
|
| +
|
| +void VEAClient::BitstreamBufferReadyOnMainThread(int32_t bitstream_buffer_id,
|
| + size_t payload_size,
|
| + bool key_frame,
|
| + base::TimeDelta timestamp) {
|
| DCHECK(thread_checker_.CalledOnValidThread());
|
| +
|
| ASSERT_LE(payload_size, output_buffer_size_);
|
|
|
| IdToSHM::iterator it = output_buffers_at_client_.find(bitstream_buffer_id);
|
| @@ -1388,11 +1474,6 @@ void VEAClient::BitstreamBufferReady(int32_t bitstream_buffer_id,
|
| FeedEncoderWithOutput(shm);
|
| }
|
|
|
| -void VEAClient::NotifyError(VideoEncodeAccelerator::Error error) {
|
| - DCHECK(thread_checker_.CalledOnValidThread());
|
| - SetState(CS_ERROR);
|
| -}
|
| -
|
| void VEAClient::SetState(ClientState new_state) {
|
| DVLOG(4) << "Changing state " << state_ << "->" << new_state;
|
| note_->Notify(new_state);
|
| @@ -1405,8 +1486,10 @@ 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_);
|
| + encode_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&VideoEncodeAccelerator::RequestEncodingParametersChange,
|
| + encoder_weak_factory_->GetWeakPtr(), bitrate, framerate));
|
| DVLOG(1) << "Switched parameters to " << current_requested_bitrate_
|
| << " bps @ " << current_framerate_ << " FPS";
|
| }
|
| @@ -1505,7 +1588,11 @@ 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);
|
| +
|
| + encode_task_runner_->PostTask(
|
| + FROM_HERE, base::Bind(&VideoEncodeAccelerator::Encode,
|
| + encoder_weak_factory_->GetWeakPtr(), video_frame,
|
| + force_keyframe));
|
| }
|
|
|
| void VEAClient::FeedEncoderWithOutput(base::SharedMemory* shm) {
|
| @@ -1523,7 +1610,11 @@ 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);
|
| +
|
| + encode_task_runner_->PostTask(
|
| + FROM_HERE,
|
| + base::Bind(&VideoEncodeAccelerator::UseOutputBitstreamBuffer,
|
| + encoder_weak_factory_->GetWeakPtr(), bitstream_buffer));
|
| }
|
|
|
| bool VEAClient::HandleEncodedFrame(bool keyframe) {
|
|
|