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

Unified Diff: media/gpu/ipc/service/gpu_video_encode_accelerator.cc

Issue 2427053002: Move video encode accelerator IPC messages to GPU IO thread (Closed)
Patch Set: Fix log order. Created 4 years, 2 months 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
Index: media/gpu/ipc/service/gpu_video_encode_accelerator.cc
diff --git a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
index 26d2aaa55d5f2c2dea38d33181dd7e3f5944d6dc..fb44364c7f0a085db590cec3ff351fb053780e69 100644
--- a/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
+++ b/media/gpu/ipc/service/gpu_video_encode_accelerator.cc
@@ -99,13 +99,68 @@ std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() {
} // anonymous namespace
+class GpuVideoEncodeAccelerator::MessageFilter : public IPC::MessageFilter {
+ public:
+ MessageFilter(GpuVideoEncodeAccelerator* owner, int32_t host_route_id)
+ : owner_(owner), host_route_id_(host_route_id) {}
+
+ void OnChannelError() override { sender_ = NULL; }
Pawel Osciak 2016/10/25 01:44:04 sender_ = nullptr; and similarly below please.
emircan 2016/10/25 21:57:51 Done.
+
+ void OnChannelClosing() override { sender_ = NULL; }
+
+ void OnFilterAdded(IPC::Channel* channel) override { sender_ = channel; }
+
+ void OnFilterRemoved() override { owner_->OnFilterRemoved(); }
+
+ bool OnMessageReceived(const IPC::Message& msg) override {
+ if (msg.routing_id() != host_route_id_)
+ return false;
+
+ IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
+ IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_Encode, owner_,
+ GpuVideoEncodeAccelerator::OnEncode)
+ IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
+ owner_,
+ GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer)
+ IPC_MESSAGE_FORWARD(
+ AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, owner_,
+ GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange)
+ IPC_MESSAGE_UNHANDLED(return false)
+ IPC_END_MESSAGE_MAP()
+ return true;
+ }
+
+ bool SendOnIOThread(IPC::Message* message) {
+ CHECK(!message->is_sync());
Pawel Osciak 2016/10/25 01:44:05 Perhaps DCHECK and return false to avoid crashing
emircan 2016/10/25 21:57:50 I merged this error case with l.135 and made it a
+ if (!sender_) {
+ delete message;
+ return false;
+ }
+ return sender_->Send(message);
+ }
+
+ protected:
+ ~MessageFilter() override {}
+
+ private:
+ GpuVideoEncodeAccelerator* const owner_;
+ const int32_t host_route_id_;
+ // The sender to which this filter was added.
+ IPC::Sender* sender_;
Pawel Osciak 2016/10/25 01:44:04 = nullptr ?
emircan 2016/10/25 21:57:50 Added to the initializer list.
+};
Pawel Osciak 2016/10/25 01:44:04 Should we also have some DISALLOW_COPY_AND_ASSIGN
emircan 2016/10/25 21:57:50 Done.
+
GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(
int32_t host_route_id,
- gpu::GpuCommandBufferStub* stub)
+ gpu::GpuCommandBufferStub* stub,
+ const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
: host_route_id_(host_route_id),
stub_(stub),
input_format_(PIXEL_FORMAT_UNKNOWN),
output_buffer_size_(0),
+ filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL,
+ base::WaitableEvent::InitialState::NOT_SIGNALED),
+ main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
+ io_task_runner_(io_task_runner),
weak_this_factory_(this) {
stub_->AddDestructionObserver(this);
make_context_current_ =
@@ -122,7 +177,8 @@ bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format,
const gfx::Size& input_visible_size,
VideoCodecProfile output_profile,
uint32_t initial_bitrate) {
- DVLOG(1) << __FUNCTION__
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ DVLOG(1) << __func__
<< " input_format=" << VideoPixelFormatToString(input_format)
<< ", input_visible_size=" << input_visible_size.ToString()
<< ", output_profile=" << GetProfileName(output_profile)
@@ -130,14 +186,14 @@ bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format,
DCHECK(!encoder_);
if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) {
- DLOG(ERROR) << __FUNCTION__ << " failed to add route";
+ DLOG(ERROR) << __func__ << " failed to add route";
return false;
}
if (input_visible_size.width() > limits::kMaxDimension ||
input_visible_size.height() > limits::kMaxDimension ||
input_visible_size.GetArea() > limits::kMaxCanvas) {
- DLOG(ERROR) << __FUNCTION__ << "too large input_visible_size "
+ DLOG(ERROR) << __func__ << "too large input_visible_size "
<< input_visible_size.ToString();
return false;
}
@@ -153,11 +209,18 @@ bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format,
initial_bitrate, this)) {
input_format_ = input_format;
input_visible_size_ = input_visible_size;
+ // Attempt to set up performing encoding tasks on IO thread, if supported
+ // by the VEA.
+ if (encoder_->TryToSetupEncodeOnSeparateThread(
+ weak_this_factory_.GetWeakPtr(), io_task_runner_)) {
+ filter_ = new MessageFilter(this, host_route_id_);
+ stub_->channel()->AddFilter(filter_.get());
+ }
return true;
}
}
encoder_.reset();
- DLOG(ERROR) << __FUNCTION__ << " VEA initialization failed";
+ DLOG(ERROR) << __func__ << " VEA initialization failed";
return false;
}
@@ -180,8 +243,10 @@ void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
unsigned int input_count,
const gfx::Size& input_coded_size,
size_t output_buffer_size) {
- Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
- host_route_id_, input_count, input_coded_size, output_buffer_size));
+ if (!Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
Pawel Osciak 2016/10/25 01:44:04 DCHECK(CheckCalledOnMessageFilterThread()) if we e
emircan 2016/10/25 21:57:50 I moved it to main thread after your comment and a
+ host_route_id_, input_count, input_coded_size, output_buffer_size))) {
+ DLOG(ERROR) << __func__ << " failed.";
+ }
input_coded_size_ = input_coded_size;
output_buffer_size_ = output_buffer_size;
}
@@ -191,17 +256,33 @@ void GpuVideoEncodeAccelerator::BitstreamBufferReady(
size_t payload_size,
bool key_frame,
base::TimeDelta timestamp) {
- Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
- host_route_id_, bitstream_buffer_id, payload_size, key_frame, timestamp));
+ DCHECK(CheckCalledOnMessageFilterThread());
+ if (!Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
+ host_route_id_, bitstream_buffer_id, payload_size, key_frame,
+ timestamp))) {
+ DLOG(ERROR) << __func__ << " failed.";
+ }
}
void GpuVideoEncodeAccelerator::NotifyError(
VideoEncodeAccelerator::Error error) {
- Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_, error));
+ DCHECK(CheckCalledOnMessageFilterThread());
+ if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_,
+ error))) {
+ DLOG(ERROR) << __func__ << " failed.";
+ }
}
void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
+ DVLOG(2) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
DCHECK(stub_);
+
+ if (filter_) {
+ stub_->channel()->RemoveFilter(filter_.get());
+ filter_removed_.Wait();
Pawel Osciak 2016/10/25 01:44:04 Please add a comment similar to the one in gvda.cc
emircan 2016/10/25 21:57:51 Done.
+ }
+
stub_->channel()->RemoveRoute(host_route_id_);
stub_->RemoveDestructionObserver(this);
encoder_.reset();
@@ -226,6 +307,14 @@ GpuVideoEncodeAccelerator::GetSupportedProfiles(
return GpuVideoAcceleratorUtil::ConvertMediaToGpuEncodeProfiles(profiles);
}
+void GpuVideoEncodeAccelerator::OnFilterRemoved() {
+ DVLOG(2) << __func__;
+
+ // We're destroying; cancel all callbacks.
+ weak_this_factory_.InvalidateWeakPtrs();
+ filter_removed_.Signal();
+}
+
// static
std::vector<GpuVideoEncodeAccelerator::VEAFactoryFunction>
GpuVideoEncodeAccelerator::GetVEAFactoryFunctions(
@@ -254,9 +343,10 @@ GpuVideoEncodeAccelerator::GetVEAFactoryFunctions(
void GpuVideoEncodeAccelerator::OnEncode(
const AcceleratedVideoEncoderMsg_Encode_Params& params) {
- DVLOG(3) << __FUNCTION__ << " frame_id = " << params.frame_id
+ DVLOG(3) << __func__ << " frame_id = " << params.frame_id
<< ", buffer_size=" << params.buffer_size
<< ", force_keyframe=" << params.force_keyframe;
+ DCHECK(CheckCalledOnMessageFilterThread());
DCHECK_EQ(PIXEL_FORMAT_I420, input_format_);
// Wrap into a SharedMemory in the beginning, so that |params.buffer_handle|
Pawel Osciak 2016/10/25 01:44:04 Could we move the reminder of this method off of t
emircan 2016/10/25 21:57:50 I added a trace to measure how long it takes here.
Pawel Osciak 2016/10/27 01:45:19 From my understanding, the rule of thumb is that n
emircan 2016/10/27 17:53:30 I like the idea of letting VideoFrame lazy evaluat
Pawel Osciak 2016/10/31 07:40:21 From our experience with this, the main performanc
emircan 2016/10/31 19:45:08 Sorry if my statement earlier wasn't clear. I am n
Pawel Osciak 2016/11/01 04:59:58 SGTM, thanks! That would be in this CL, right?
@@ -268,7 +358,7 @@ void GpuVideoEncodeAccelerator::OnEncode(
return;
if (params.frame_id < 0) {
- DLOG(ERROR) << __FUNCTION__ << " invalid frame_id=" << params.frame_id;
+ DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id;
NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
return;
}
@@ -281,14 +371,13 @@ void GpuVideoEncodeAccelerator::OnEncode(
map_size += aligned_offset;
if (!map_offset.IsValid() || !map_size.IsValid()) {
- DLOG(ERROR) << __FUNCTION__ << " invalid map_offset or map_size";
+ DLOG(ERROR) << __func__ << " invalid map_offset or map_size";
NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
return;
}
if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
- DLOG(ERROR) << __FUNCTION__
- << " could not map frame_id=" << params.frame_id;
+ DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id;
NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
return;
}
@@ -300,7 +389,7 @@ void GpuVideoEncodeAccelerator::OnEncode(
input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle,
params.buffer_offset, params.timestamp);
if (!frame) {
- DLOG(ERROR) << __FUNCTION__ << " could not create a frame";
+ DLOG(ERROR) << __func__ << " could not create a frame";
NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
return;
}
@@ -314,18 +403,18 @@ void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
int32_t buffer_id,
base::SharedMemoryHandle buffer_handle,
uint32_t buffer_size) {
- DVLOG(3) << __FUNCTION__ << " buffer_id=" << buffer_id
+ DVLOG(3) << __func__ << " buffer_id=" << buffer_id
<< ", buffer_size=" << buffer_size;
+ DCHECK(CheckCalledOnMessageFilterThread());
if (!encoder_)
return;
if (buffer_id < 0) {
- DLOG(ERROR) << __FUNCTION__ << " invalid buffer_id=" << buffer_id;
+ DLOG(ERROR) << __func__ << " invalid buffer_id=" << buffer_id;
NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
return;
}
if (buffer_size < output_buffer_size_) {
- DLOG(ERROR) << __FUNCTION__
- << " buffer too small for buffer_id=" << buffer_id;
+ DLOG(ERROR) << __func__ << " buffer too small for buffer_id=" << buffer_id;
NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
return;
}
@@ -334,15 +423,16 @@ void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
}
void GpuVideoEncodeAccelerator::OnDestroy() {
- DVLOG(2) << __FUNCTION__;
+ DVLOG(2) << __func__;
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
OnWillDestroyStub();
}
void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
uint32_t bitrate,
uint32_t framerate) {
- DVLOG(2) << __FUNCTION__ << " bitrate=" << bitrate
- << ", framerate=" << framerate;
+ DVLOG(2) << __func__ << " bitrate=" << bitrate << ", framerate=" << framerate;
+ DCHECK(CheckCalledOnMessageFilterThread());
if (!encoder_)
return;
encoder_->RequestEncodingParametersChange(bitrate, framerate);
@@ -351,13 +441,25 @@ void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
void GpuVideoEncodeAccelerator::EncodeFrameFinished(
int32_t frame_id,
std::unique_ptr<base::SharedMemory> shm) {
- Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
- frame_id));
+ DCHECK(CheckCalledOnMessageFilterThread());
+ if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
+ frame_id))) {
+ DLOG(ERROR) << __func__ << " failed.";
+ }
// Just let |shm| fall out of scope.
}
-void GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
- stub_->channel()->Send(message);
+bool GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
+ if (filter_ && io_task_runner_->BelongsToCurrentThread()) {
+ return filter_->SendOnIOThread(message);
+ }
+ DCHECK(main_task_runner_->BelongsToCurrentThread());
+ return stub_->channel()->Send(message);
+}
+
+bool GpuVideoEncodeAccelerator::CheckCalledOnMessageFilterThread() {
+ return (filter_ && io_task_runner_->BelongsToCurrentThread()) ||
+ (!filter_ && main_task_runner_->BelongsToCurrentThread());
}
} // namespace media

Powered by Google App Engine
This is Rietveld 408576698