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

Side by Side 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: posciak@ comments. 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 unified diff | Download patch
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h" 5 #include "media/gpu/ipc/service/gpu_video_encode_accelerator.h"
6 6
7 #include <memory> 7 #include <memory>
8 8
9 #include "base/callback.h" 9 #include "base/callback.h"
10 #include "base/command_line.h" 10 #include "base/command_line.h"
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
52 } 52 }
53 53
54 if (!stub->decoder()->MakeCurrent()) { 54 if (!stub->decoder()->MakeCurrent()) {
55 DLOG(ERROR) << "Failed to MakeCurrent()"; 55 DLOG(ERROR) << "Failed to MakeCurrent()";
56 return false; 56 return false;
57 } 57 }
58 58
59 return true; 59 return true;
60 } 60 }
61 61
62 void DropSharedMemory(std::unique_ptr<base::SharedMemory> shm) {
63 // Just let |shm| fall out of scope.
64 }
65
62 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC) 66 #if defined(OS_CHROMEOS) && defined(USE_V4L2_CODEC)
63 std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA() { 67 std::unique_ptr<VideoEncodeAccelerator> CreateV4L2VEA() {
64 scoped_refptr<V4L2Device> device = V4L2Device::Create(); 68 scoped_refptr<V4L2Device> device = V4L2Device::Create();
65 if (!device) 69 if (!device)
66 return nullptr; 70 return nullptr;
67 return base::WrapUnique<VideoEncodeAccelerator>( 71 return base::WrapUnique<VideoEncodeAccelerator>(
68 new V4L2VideoEncodeAccelerator(device)); 72 new V4L2VideoEncodeAccelerator(device));
69 } 73 }
70 #endif 74 #endif
71 75
(...skipping 20 matching lines...) Expand all
92 96
93 #if defined(OS_WIN) 97 #if defined(OS_WIN)
94 std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() { 98 std::unique_ptr<VideoEncodeAccelerator> CreateMediaFoundationVEA() {
95 return base::WrapUnique<media::VideoEncodeAccelerator>( 99 return base::WrapUnique<media::VideoEncodeAccelerator>(
96 new MediaFoundationVideoEncodeAccelerator()); 100 new MediaFoundationVideoEncodeAccelerator());
97 } 101 }
98 #endif 102 #endif
99 103
100 } // anonymous namespace 104 } // anonymous namespace
101 105
106 class GpuVideoEncodeAccelerator::MessageFilter : public IPC::MessageFilter {
107 public:
108 MessageFilter(GpuVideoEncodeAccelerator* owner, int32_t host_route_id)
109 : owner_(owner), host_route_id_(host_route_id) {}
110
111 void OnChannelError() override { sender_ = nullptr; }
112
113 void OnChannelClosing() override { sender_ = nullptr; }
114
115 void OnFilterAdded(IPC::Channel* channel) override { sender_ = channel; }
116
117 void OnFilterRemoved() override { owner_->OnFilterRemoved(); }
118
119 bool OnMessageReceived(const IPC::Message& msg) override {
120 if (msg.routing_id() != host_route_id_)
121 return false;
122
123 IPC_BEGIN_MESSAGE_MAP(MessageFilter, msg)
124 IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_Encode, owner_,
125 GpuVideoEncodeAccelerator::OnEncode)
126 IPC_MESSAGE_FORWARD(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
127 owner_,
128 GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer)
129 IPC_MESSAGE_FORWARD(
130 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, owner_,
131 GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange)
132 IPC_MESSAGE_UNHANDLED(return false)
133 IPC_END_MESSAGE_MAP()
134 return true;
135 }
136
137 bool SendOnIOThread(IPC::Message* message) {
138 if (!sender_ || message->is_sync()) {
139 DCHECK(!message->is_sync());
140 delete message;
141 return false;
142 }
143 return sender_->Send(message);
144 }
145
146 protected:
147 ~MessageFilter() override {}
148
149 private:
150 GpuVideoEncodeAccelerator* const owner_;
151 const int32_t host_route_id_;
152 // The sender to which this filter was added.
153 IPC::Sender* sender_ = nullptr;
154
155 DISALLOW_COPY_AND_ASSIGN(MessageFilter);
156 };
157
102 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator( 158 GpuVideoEncodeAccelerator::GpuVideoEncodeAccelerator(
103 int32_t host_route_id, 159 int32_t host_route_id,
104 gpu::GpuCommandBufferStub* stub) 160 gpu::GpuCommandBufferStub* stub,
161 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner)
105 : host_route_id_(host_route_id), 162 : host_route_id_(host_route_id),
106 stub_(stub), 163 stub_(stub),
107 input_format_(PIXEL_FORMAT_UNKNOWN), 164 input_format_(PIXEL_FORMAT_UNKNOWN),
108 output_buffer_size_(0), 165 output_buffer_size_(0),
166 filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL,
167 base::WaitableEvent::InitialState::NOT_SIGNALED),
168 encoder_worker_thread_("EncoderWorkerThread"),
169 main_task_runner_(base::ThreadTaskRunnerHandle::Get()),
170 io_task_runner_(io_task_runner),
171 encode_task_runner_(main_task_runner_),
172 weak_this_factory_for_encoder_worker_(this),
109 weak_this_factory_(this) { 173 weak_this_factory_(this) {
110 stub_->AddDestructionObserver(this); 174 stub_->AddDestructionObserver(this);
111 make_context_current_ = 175 make_context_current_ =
112 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); 176 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr());
113 } 177 }
114 178
115 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() { 179 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() {
116 // This class can only be self-deleted from OnWillDestroyStub(), which means 180 // This class can only be self-deleted from OnWillDestroyStub(), which means
117 // the VEA has already been destroyed in there. 181 // the VEA has already been destroyed in there.
118 DCHECK(!encoder_); 182 DCHECK(!encoder_);
183 if (encoder_worker_thread_.IsRunning()) {
184 encoder_worker_task_runner_->PostTask(
185 FROM_HERE,
186 base::Bind(&GpuVideoEncodeAccelerator::DestroyOnEncoderWorker,
187 weak_this_factory_for_encoder_worker_.GetWeakPtr()));
188 encoder_worker_thread_.Stop();
189 }
119 } 190 }
120 191
121 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format, 192 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format,
122 const gfx::Size& input_visible_size, 193 const gfx::Size& input_visible_size,
123 VideoCodecProfile output_profile, 194 VideoCodecProfile output_profile,
124 uint32_t initial_bitrate) { 195 uint32_t initial_bitrate) {
125 DVLOG(1) << __FUNCTION__ 196 DCHECK(main_task_runner_->BelongsToCurrentThread());
197 DVLOG(1) << __func__
126 << " input_format=" << VideoPixelFormatToString(input_format) 198 << " input_format=" << VideoPixelFormatToString(input_format)
127 << ", input_visible_size=" << input_visible_size.ToString() 199 << ", input_visible_size=" << input_visible_size.ToString()
128 << ", output_profile=" << GetProfileName(output_profile) 200 << ", output_profile=" << GetProfileName(output_profile)
129 << ", initial_bitrate=" << initial_bitrate; 201 << ", initial_bitrate=" << initial_bitrate;
130 DCHECK(!encoder_); 202 DCHECK(!encoder_);
131 203
132 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) { 204 if (!stub_->channel()->AddRoute(host_route_id_, stub_->stream_id(), this)) {
133 DLOG(ERROR) << __FUNCTION__ << " failed to add route"; 205 DLOG(ERROR) << __func__ << " failed to add route";
134 return false; 206 return false;
135 } 207 }
136 208
137 if (input_visible_size.width() > limits::kMaxDimension || 209 if (input_visible_size.width() > limits::kMaxDimension ||
138 input_visible_size.height() > limits::kMaxDimension || 210 input_visible_size.height() > limits::kMaxDimension ||
139 input_visible_size.GetArea() > limits::kMaxCanvas) { 211 input_visible_size.GetArea() > limits::kMaxCanvas) {
140 DLOG(ERROR) << __FUNCTION__ << "too large input_visible_size " 212 DLOG(ERROR) << __func__ << "too large input_visible_size "
141 << input_visible_size.ToString(); 213 << input_visible_size.ToString();
142 return false; 214 return false;
143 } 215 }
144 216
145 const gpu::GpuPreferences& gpu_preferences = 217 const gpu::GpuPreferences& gpu_preferences =
146 stub_->channel()->gpu_channel_manager()->gpu_preferences(); 218 stub_->channel()->gpu_channel_manager()->gpu_preferences();
147 219
148 // Try all possible encoders and use the first successful encoder. 220 // Try all possible encoders and use the first successful encoder.
149 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { 221 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) {
150 encoder_ = factory_function.Run(); 222 encoder_ = factory_function.Run();
151 if (encoder_ && 223 if (encoder_ &&
152 encoder_->Initialize(input_format, input_visible_size, output_profile, 224 encoder_->Initialize(input_format, input_visible_size, output_profile,
153 initial_bitrate, this)) { 225 initial_bitrate, this)) {
154 input_format_ = input_format; 226 input_format_ = input_format;
155 input_visible_size_ = input_visible_size; 227 input_visible_size_ = input_visible_size;
228 // Attempt to set up performing encoding tasks on IO thread, if supported
229 // by the VEA.
230 if (encoder_->TryToSetupEncodeOnSeparateThread(
231 weak_this_factory_.GetWeakPtr(), io_task_runner_)) {
232 filter_ = new MessageFilter(this, host_route_id_);
233 stub_->channel()->AddFilter(filter_.get());
234 encode_task_runner_ = io_task_runner_;
235 }
236
237 if (!encoder_worker_thread_.Start()) {
238 DLOG(ERROR) << "Failed spawning encoder worker thread.";
239 return false;
240 }
241 encoder_worker_task_runner_ = encoder_worker_thread_.task_runner();
242
156 return true; 243 return true;
157 } 244 }
158 } 245 }
159 encoder_.reset(); 246 encoder_.reset();
160 DLOG(ERROR) << __FUNCTION__ << " VEA initialization failed"; 247 DLOG(ERROR) << __func__ << " VEA initialization failed";
161 return false; 248 return false;
162 } 249 }
163 250
164 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) { 251 bool GpuVideoEncodeAccelerator::OnMessageReceived(const IPC::Message& message) {
165 bool handled = true; 252 bool handled = true;
166 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message) 253 IPC_BEGIN_MESSAGE_MAP(GpuVideoEncodeAccelerator, message)
167 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode) 254 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Encode, OnEncode)
168 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer, 255 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_UseOutputBitstreamBuffer,
169 OnUseOutputBitstreamBuffer) 256 OnUseOutputBitstreamBuffer)
170 IPC_MESSAGE_HANDLER( 257 IPC_MESSAGE_HANDLER(
171 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange, 258 AcceleratedVideoEncoderMsg_RequestEncodingParametersChange,
172 OnRequestEncodingParametersChange) 259 OnRequestEncodingParametersChange)
173 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy) 260 IPC_MESSAGE_HANDLER(AcceleratedVideoEncoderMsg_Destroy, OnDestroy)
174 IPC_MESSAGE_UNHANDLED(handled = false) 261 IPC_MESSAGE_UNHANDLED(handled = false)
175 IPC_END_MESSAGE_MAP() 262 IPC_END_MESSAGE_MAP()
176 return handled; 263 return handled;
177 } 264 }
178 265
266 bool GpuVideoEncodeAccelerator::Send(IPC::Message* message) {
267 if (filter_ && io_task_runner_->BelongsToCurrentThread()) {
268 return filter_->SendOnIOThread(message);
269 }
270 DCHECK(main_task_runner_->BelongsToCurrentThread());
271 return stub_->channel()->Send(message);
272 }
273
179 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers( 274 void GpuVideoEncodeAccelerator::RequireBitstreamBuffers(
180 unsigned int input_count, 275 unsigned int input_count,
181 const gfx::Size& input_coded_size, 276 const gfx::Size& input_coded_size,
182 size_t output_buffer_size) { 277 size_t output_buffer_size) {
183 Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers( 278 DCHECK(main_task_runner_->BelongsToCurrentThread());
184 host_route_id_, input_count, input_coded_size, output_buffer_size)); 279 if (!Send(new AcceleratedVideoEncoderHostMsg_RequireBitstreamBuffers(
280 host_route_id_, input_count, input_coded_size, output_buffer_size))) {
281 DLOG(ERROR) << __func__ << " failed.";
282 return;
283 }
185 input_coded_size_ = input_coded_size; 284 input_coded_size_ = input_coded_size;
186 output_buffer_size_ = output_buffer_size; 285 output_buffer_size_ = output_buffer_size;
187 } 286 }
188 287
189 void GpuVideoEncodeAccelerator::BitstreamBufferReady( 288 void GpuVideoEncodeAccelerator::BitstreamBufferReady(
190 int32_t bitstream_buffer_id, 289 int32_t bitstream_buffer_id,
191 size_t payload_size, 290 size_t payload_size,
192 bool key_frame, 291 bool key_frame,
193 base::TimeDelta timestamp) { 292 base::TimeDelta timestamp) {
194 Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady( 293 DCHECK(CheckIfCalledOnCorrectThread());
195 host_route_id_, bitstream_buffer_id, payload_size, key_frame, timestamp)); 294 if (!Send(new AcceleratedVideoEncoderHostMsg_BitstreamBufferReady(
295 host_route_id_, bitstream_buffer_id, payload_size, key_frame,
296 timestamp))) {
297 DLOG(ERROR) << __func__ << " failed.";
298 }
196 } 299 }
197 300
198 void GpuVideoEncodeAccelerator::NotifyError( 301 void GpuVideoEncodeAccelerator::NotifyError(
199 VideoEncodeAccelerator::Error error) { 302 VideoEncodeAccelerator::Error error) {
200 Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_, error)); 303 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyError(host_route_id_,
304 error))) {
305 DLOG(ERROR) << __func__ << " failed.";
306 }
201 } 307 }
202 308
203 void GpuVideoEncodeAccelerator::OnWillDestroyStub() { 309 void GpuVideoEncodeAccelerator::OnWillDestroyStub() {
310 DVLOG(2) << __func__;
311 DCHECK(main_task_runner_->BelongsToCurrentThread());
204 DCHECK(stub_); 312 DCHECK(stub_);
313
314 // The stub is going away, so we have to stop and destroy VEA here before
315 // returning. We cannot destroy the VEA before the IO thread message filter is
316 // removed however, since we cannot service incoming messages with VEA gone.
317 // We cannot simply check for existence of VEA on IO thread though, because
318 // we don't want to synchronize the IO thread with the ChildThread.
319 // So we have to wait for the RemoveFilter callback here instead and remove
320 // the VEA after it arrives and before returning.
321 if (filter_) {
322 stub_->channel()->RemoveFilter(filter_.get());
323 filter_removed_.Wait();
324 }
325
205 stub_->channel()->RemoveRoute(host_route_id_); 326 stub_->channel()->RemoveRoute(host_route_id_);
206 stub_->RemoveDestructionObserver(this); 327 stub_->RemoveDestructionObserver(this);
207 encoder_.reset(); 328 encoder_.reset();
208 delete this; 329 delete this;
209 } 330 }
210 331
211 // static 332 // static
212 gpu::VideoEncodeAcceleratorSupportedProfiles 333 gpu::VideoEncodeAcceleratorSupportedProfiles
213 GpuVideoEncodeAccelerator::GetSupportedProfiles( 334 GpuVideoEncodeAccelerator::GetSupportedProfiles(
214 const gpu::GpuPreferences& gpu_preferences) { 335 const gpu::GpuPreferences& gpu_preferences) {
(...skipping 30 matching lines...) Expand all
245 #if defined(OS_MACOSX) 366 #if defined(OS_MACOSX)
246 vea_factory_functions.push_back(base::Bind(&CreateVTVEA)); 367 vea_factory_functions.push_back(base::Bind(&CreateVTVEA));
247 #endif 368 #endif
248 #if defined(OS_WIN) 369 #if defined(OS_WIN)
249 if (base::FeatureList::IsEnabled(kMediaFoundationH264Encoding)) 370 if (base::FeatureList::IsEnabled(kMediaFoundationH264Encoding))
250 vea_factory_functions.push_back(base::Bind(&CreateMediaFoundationVEA)); 371 vea_factory_functions.push_back(base::Bind(&CreateMediaFoundationVEA));
251 #endif 372 #endif
252 return vea_factory_functions; 373 return vea_factory_functions;
253 } 374 }
254 375
376 void GpuVideoEncodeAccelerator::OnFilterRemoved() {
377 DVLOG(2) << __func__;
378 DCHECK(io_task_runner_->BelongsToCurrentThread());
379
380 // We're destroying; cancel all callbacks.
381 weak_this_factory_.InvalidateWeakPtrs();
382 filter_removed_.Signal();
383 }
384
255 void GpuVideoEncodeAccelerator::OnEncode( 385 void GpuVideoEncodeAccelerator::OnEncode(
256 const AcceleratedVideoEncoderMsg_Encode_Params& params) { 386 const AcceleratedVideoEncoderMsg_Encode_Params& params) {
257 DVLOG(3) << __FUNCTION__ << " frame_id = " << params.frame_id 387 DVLOG(3) << __func__ << " frame_id = " << params.frame_id
258 << ", buffer_size=" << params.buffer_size 388 << ", buffer_size=" << params.buffer_size
259 << ", force_keyframe=" << params.force_keyframe; 389 << ", force_keyframe=" << params.force_keyframe;
390 DCHECK(CheckIfCalledOnCorrectThread());
260 DCHECK_EQ(PIXEL_FORMAT_I420, input_format_); 391 DCHECK_EQ(PIXEL_FORMAT_I420, input_format_);
261 392
262 // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle|
263 // is cleaned properly in case of an early return.
264 std::unique_ptr<base::SharedMemory> shm(
265 new base::SharedMemory(params.buffer_handle, true));
266
267 if (!encoder_) 393 if (!encoder_)
268 return; 394 return;
269 395
270 if (params.frame_id < 0) { 396 if (params.frame_id < 0) {
271 DLOG(ERROR) << __FUNCTION__ << " invalid frame_id=" << params.frame_id; 397 DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id;
272 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); 398 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
273 return; 399 return;
274 } 400 }
275 401
276 const uint32_t aligned_offset = 402 encoder_worker_task_runner_->PostTask(
277 params.buffer_offset % base::SysInfo::VMAllocationGranularity(); 403 FROM_HERE,
278 base::CheckedNumeric<off_t> map_offset = params.buffer_offset; 404 base::Bind(&GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker,
279 map_offset -= aligned_offset; 405 weak_this_factory_for_encoder_worker_.GetWeakPtr(), params));
280 base::CheckedNumeric<size_t> map_size = params.buffer_size;
281 map_size += aligned_offset;
282
283 if (!map_offset.IsValid() || !map_size.IsValid()) {
284 DLOG(ERROR) << __FUNCTION__ << " invalid map_offset or map_size";
285 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
286 return;
287 }
288
289 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
290 DLOG(ERROR) << __FUNCTION__
291 << " could not map frame_id=" << params.frame_id;
292 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
293 return;
294 }
295
296 uint8_t* shm_memory =
297 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset;
298 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory(
299 input_format_, input_coded_size_, gfx::Rect(input_visible_size_),
300 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle,
301 params.buffer_offset, params.timestamp);
302 if (!frame) {
303 DLOG(ERROR) << __FUNCTION__ << " could not create a frame";
304 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
305 return;
306 }
307 frame->AddDestructionObserver(BindToCurrentLoop(base::Bind(
308 &GpuVideoEncodeAccelerator::EncodeFrameFinished,
309 weak_this_factory_.GetWeakPtr(), params.frame_id, base::Passed(&shm))));
310 encoder_->Encode(frame, params.force_keyframe);
311 } 406 }
312 407
313 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( 408 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer(
314 int32_t buffer_id, 409 int32_t buffer_id,
315 base::SharedMemoryHandle buffer_handle, 410 base::SharedMemoryHandle buffer_handle,
316 uint32_t buffer_size) { 411 uint32_t buffer_size) {
317 DVLOG(3) << __FUNCTION__ << " buffer_id=" << buffer_id 412 DVLOG(3) << __func__ << " buffer_id=" << buffer_id
318 << ", buffer_size=" << buffer_size; 413 << ", buffer_size=" << buffer_size;
414 DCHECK(CheckIfCalledOnCorrectThread());
319 if (!encoder_) 415 if (!encoder_)
320 return; 416 return;
321 if (buffer_id < 0) { 417 if (buffer_id < 0) {
322 DLOG(ERROR) << __FUNCTION__ << " invalid buffer_id=" << buffer_id; 418 DLOG(ERROR) << __func__ << " invalid buffer_id=" << buffer_id;
323 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); 419 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
324 return; 420 return;
325 } 421 }
326 if (buffer_size < output_buffer_size_) { 422 if (buffer_size < output_buffer_size_) {
327 DLOG(ERROR) << __FUNCTION__ 423 DLOG(ERROR) << __func__ << " buffer too small for buffer_id=" << buffer_id;
328 << " buffer too small for buffer_id=" << buffer_id;
329 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); 424 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
330 return; 425 return;
331 } 426 }
332 encoder_->UseOutputBitstreamBuffer( 427 encoder_->UseOutputBitstreamBuffer(
333 BitstreamBuffer(buffer_id, buffer_handle, buffer_size)); 428 BitstreamBuffer(buffer_id, buffer_handle, buffer_size));
334 } 429 }
335 430
336 void GpuVideoEncodeAccelerator::OnDestroy() { 431 void GpuVideoEncodeAccelerator::OnDestroy() {
337 DVLOG(2) << __FUNCTION__; 432 DVLOG(2) << __func__;
433 DCHECK(main_task_runner_->BelongsToCurrentThread());
338 OnWillDestroyStub(); 434 OnWillDestroyStub();
339 } 435 }
340 436
341 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange( 437 void GpuVideoEncodeAccelerator::OnRequestEncodingParametersChange(
342 uint32_t bitrate, 438 uint32_t bitrate,
343 uint32_t framerate) { 439 uint32_t framerate) {
344 DVLOG(2) << __FUNCTION__ << " bitrate=" << bitrate 440 DVLOG(2) << __func__ << " bitrate=" << bitrate << ", framerate=" << framerate;
345 << ", framerate=" << framerate; 441 DCHECK(CheckIfCalledOnCorrectThread());
346 if (!encoder_) 442 if (!encoder_)
347 return; 443 return;
348 encoder_->RequestEncodingParametersChange(bitrate, framerate); 444 encoder_->RequestEncodingParametersChange(bitrate, framerate);
349 } 445 }
350 446
351 void GpuVideoEncodeAccelerator::EncodeFrameFinished( 447 void GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker(
352 int32_t frame_id, 448 const AcceleratedVideoEncoderMsg_Encode_Params& params) {
353 std::unique_ptr<base::SharedMemory> shm) { 449 DVLOG(3) << __func__;
354 Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_, 450 DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread());
355 frame_id)); 451
356 // Just let |shm| fall out of scope. 452 // Wrap into a SharedMemory in the beginning, so that |params.buffer_handle|
453 // is cleaned properly in case of an early return.
454 std::unique_ptr<base::SharedMemory> shm(
455 new base::SharedMemory(params.buffer_handle, true));
456 const uint32_t aligned_offset =
457 params.buffer_offset % base::SysInfo::VMAllocationGranularity();
458 base::CheckedNumeric<off_t> map_offset = params.buffer_offset;
459 map_offset -= aligned_offset;
460 base::CheckedNumeric<size_t> map_size = params.buffer_size;
461 map_size += aligned_offset;
462
463 if (!map_offset.IsValid() || !map_size.IsValid()) {
464 DLOG(ERROR) << __func__ << " invalid map_offset or map_size";
465 encode_task_runner_->PostTask(
466 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError,
467 weak_this_factory_.GetWeakPtr(),
468 VideoEncodeAccelerator::kPlatformFailureError));
469 return;
470 }
471
472 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) {
473 DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id;
474 encode_task_runner_->PostTask(
475 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError,
476 weak_this_factory_.GetWeakPtr(),
477 VideoEncodeAccelerator::kPlatformFailureError));
478 return;
479 }
480
481 uint8_t* shm_memory =
482 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset;
483 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory(
484 input_format_, input_coded_size_, gfx::Rect(input_visible_size_),
485 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle,
486 params.buffer_offset, params.timestamp);
487 if (!frame) {
488 DLOG(ERROR) << __func__ << " could not create a frame";
489 encode_task_runner_->PostTask(
490 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError,
491 weak_this_factory_.GetWeakPtr(),
492 VideoEncodeAccelerator::kPlatformFailureError));
493 return;
494 }
495
496 // We wrap |shm| in a callback and add it as a destruction observer, so it
497 // stays alive and mapped until |frame| goes out of scope.
498 frame->AddDestructionObserver(
499 base::Bind(&DropSharedMemory, base::Passed(&shm)));
500 encode_task_runner_->PostTask(
501 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::OnEncodeFrameCreated,
502 weak_this_factory_.GetWeakPtr(), params.frame_id,
503 params.force_keyframe, frame));
357 } 504 }
358 505
359 void GpuVideoEncodeAccelerator::Send(IPC::Message* message) { 506 void GpuVideoEncodeAccelerator::DestroyOnEncoderWorker() {
360 stub_->channel()->Send(message); 507 DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread());
508 weak_this_factory_for_encoder_worker_.InvalidateWeakPtrs();
509 }
510
511 void GpuVideoEncodeAccelerator::OnEncodeFrameCreated(
512 int32_t frame_id,
513 bool force_keyframe,
514 const scoped_refptr<media::VideoFrame>& frame) {
515 DVLOG(3) << __func__;
516 DCHECK(CheckIfCalledOnCorrectThread());
517
518 if (!frame) {
519 DLOG(ERROR) << __func__ << " could not create a frame";
520 NotifyError(VideoEncodeAccelerator::kPlatformFailureError);
521 return;
522 }
523
524 frame->AddDestructionObserver(BindToCurrentLoop(
525 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished,
526 weak_this_factory_.GetWeakPtr(), frame_id)));
527 encoder_->Encode(frame, force_keyframe);
528 }
529
530 void GpuVideoEncodeAccelerator::EncodeFrameFinished(int32_t frame_id) {
531 DCHECK(CheckIfCalledOnCorrectThread());
532 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_,
533 frame_id))) {
534 DLOG(ERROR) << __func__ << " failed.";
535 }
536 }
537
538 bool GpuVideoEncodeAccelerator::CheckIfCalledOnCorrectThread() {
539 return (filter_ && io_task_runner_->BelongsToCurrentThread()) ||
540 (!filter_ && main_task_runner_->BelongsToCurrentThread());
361 } 541 }
362 542
363 } // namespace media 543 } // namespace media
OLDNEW
« no previous file with comments | « media/gpu/ipc/service/gpu_video_encode_accelerator.h ('k') | media/gpu/ipc/service/media_gpu_channel.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698