OLD | NEW |
---|---|
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 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
164 : host_route_id_(host_route_id), | 164 : host_route_id_(host_route_id), |
165 stub_(stub), | 165 stub_(stub), |
166 input_format_(PIXEL_FORMAT_UNKNOWN), | 166 input_format_(PIXEL_FORMAT_UNKNOWN), |
167 output_buffer_size_(0), | 167 output_buffer_size_(0), |
168 filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL, | 168 filter_removed_(base::WaitableEvent::ResetPolicy::MANUAL, |
169 base::WaitableEvent::InitialState::NOT_SIGNALED), | 169 base::WaitableEvent::InitialState::NOT_SIGNALED), |
170 encoder_worker_thread_("EncoderWorkerThread"), | 170 encoder_worker_thread_("EncoderWorkerThread"), |
171 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 171 main_task_runner_(base::ThreadTaskRunnerHandle::Get()), |
172 io_task_runner_(io_task_runner), | 172 io_task_runner_(io_task_runner), |
173 encode_task_runner_(main_task_runner_), | 173 encode_task_runner_(main_task_runner_), |
174 weak_this_factory_for_encoder_worker_(this), | 174 weak weak_this_factory_for_encoder_worker_(this), |
sandersd (OOO until July 31)
2017/04/28 18:22:44
Presumably does not compile.
emircan
2017/04/29 00:10:46
Done.
| |
175 weak_this_factory_(this) { | 175 weak_this_factory_(this) { |
176 weak_this_for_encoder_worker_ = | |
177 weak_this_factory_for_encoder_worker_.GetWeakPtr(); | |
178 weak_this_ = weak_this_factory_.GetWeakPtr(); | |
176 stub_->AddDestructionObserver(this); | 179 stub_->AddDestructionObserver(this); |
177 make_context_current_ = | 180 make_context_current_ = |
178 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); | 181 base::Bind(&MakeDecoderContextCurrent, stub_->AsWeakPtr()); |
179 } | 182 } |
180 | 183 |
181 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() { | 184 GpuVideoEncodeAccelerator::~GpuVideoEncodeAccelerator() { |
182 // This class can only be self-deleted from OnWillDestroyStub(), which means | 185 // This class can only be self-deleted from OnWillDestroyStub(), which means |
183 // the VEA has already been destroyed in there. | 186 // the VEA has already been destroyed in there. |
184 DCHECK(!encoder_); | 187 DCHECK(!encoder_); |
185 if (encoder_worker_thread_.IsRunning()) { | 188 DCHECK(!encoder_worker_thread_.IsRunning()); |
186 encoder_worker_task_runner_->PostTask( | |
187 FROM_HERE, | |
188 base::Bind(&GpuVideoEncodeAccelerator::DestroyOnEncoderWorker, | |
189 weak_this_factory_for_encoder_worker_.GetWeakPtr())); | |
190 encoder_worker_thread_.Stop(); | |
191 } | |
192 } | 189 } |
193 | 190 |
194 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format, | 191 bool GpuVideoEncodeAccelerator::Initialize(VideoPixelFormat input_format, |
195 const gfx::Size& input_visible_size, | 192 const gfx::Size& input_visible_size, |
196 VideoCodecProfile output_profile, | 193 VideoCodecProfile output_profile, |
197 uint32_t initial_bitrate) { | 194 uint32_t initial_bitrate) { |
198 DCHECK(main_task_runner_->BelongsToCurrentThread()); | 195 DCHECK(main_task_runner_->BelongsToCurrentThread()); |
199 DVLOG(1) << __func__ | 196 DVLOG(1) << __func__ |
200 << " input_format=" << VideoPixelFormatToString(input_format) | 197 << " input_format=" << VideoPixelFormatToString(input_format) |
201 << ", input_visible_size=" << input_visible_size.ToString() | 198 << ", input_visible_size=" << input_visible_size.ToString() |
(...skipping 20 matching lines...) Expand all Loading... | |
222 // Try all possible encoders and use the first successful encoder. | 219 // Try all possible encoders and use the first successful encoder. |
223 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { | 220 for (const auto& factory_function : GetVEAFactoryFunctions(gpu_preferences)) { |
224 encoder_ = factory_function.Run(); | 221 encoder_ = factory_function.Run(); |
225 if (encoder_ && | 222 if (encoder_ && |
226 encoder_->Initialize(input_format, input_visible_size, output_profile, | 223 encoder_->Initialize(input_format, input_visible_size, output_profile, |
227 initial_bitrate, this)) { | 224 initial_bitrate, this)) { |
228 input_format_ = input_format; | 225 input_format_ = input_format; |
229 input_visible_size_ = input_visible_size; | 226 input_visible_size_ = input_visible_size; |
230 // Attempt to set up performing encoding tasks on IO thread, if supported | 227 // Attempt to set up performing encoding tasks on IO thread, if supported |
231 // by the VEA. | 228 // by the VEA. |
232 if (encoder_->TryToSetupEncodeOnSeparateThread( | 229 if (encoder_->TryToSetupEncodeOnSeparateThread(weak_this_, |
233 weak_this_factory_.GetWeakPtr(), io_task_runner_)) { | 230 io_task_runner_)) { |
234 filter_ = new MessageFilter(this, host_route_id_); | 231 filter_ = new MessageFilter(this, host_route_id_); |
235 stub_->channel()->AddFilter(filter_.get()); | 232 stub_->channel()->AddFilter(filter_.get()); |
236 encode_task_runner_ = io_task_runner_; | 233 encode_task_runner_ = io_task_runner_; |
237 } | 234 } |
238 | 235 |
239 if (!encoder_worker_thread_.Start()) { | 236 if (!encoder_worker_thread_.Start()) { |
240 DLOG(ERROR) << "Failed spawning encoder worker thread."; | 237 DLOG(ERROR) << "Failed spawning encoder worker thread."; |
241 return false; | 238 return false; |
242 } | 239 } |
243 encoder_worker_task_runner_ = encoder_worker_thread_.task_runner(); | 240 encoder_worker_task_runner_ = encoder_worker_thread_.task_runner(); |
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
318 // removed however, since we cannot service incoming messages with VEA gone. | 315 // removed however, since we cannot service incoming messages with VEA gone. |
319 // We cannot simply check for existence of VEA on IO thread though, because | 316 // We cannot simply check for existence of VEA on IO thread though, because |
320 // we don't want to synchronize the IO thread with the ChildThread. | 317 // we don't want to synchronize the IO thread with the ChildThread. |
321 // So we have to wait for the RemoveFilter callback here instead and remove | 318 // So we have to wait for the RemoveFilter callback here instead and remove |
322 // the VEA after it arrives and before returning. | 319 // the VEA after it arrives and before returning. |
323 if (filter_) { | 320 if (filter_) { |
324 stub_->channel()->RemoveFilter(filter_.get()); | 321 stub_->channel()->RemoveFilter(filter_.get()); |
325 filter_removed_.Wait(); | 322 filter_removed_.Wait(); |
326 } | 323 } |
327 | 324 |
325 // We should stop |encoder_worker_thread_| before releasing |encoder_|, see | |
326 // crbug.com/715759. | |
327 if (encoder_worker_thread_.IsRunning()) { | |
328 encoder_worker_task_runner_->PostTask( | |
329 FROM_HERE, | |
330 base::Bind(&GpuVideoEncodeAccelerator::DestroyOnEncoderWorker, | |
331 weak_this_for_encoder_worker_)); | |
332 encoder_worker_thread_.Stop(); | |
333 } | |
334 | |
328 stub_->channel()->RemoveRoute(host_route_id_); | 335 stub_->channel()->RemoveRoute(host_route_id_); |
329 stub_->RemoveDestructionObserver(this); | 336 stub_->RemoveDestructionObserver(this); |
330 encoder_.reset(); | 337 encoder_.reset(); |
331 delete this; | 338 delete this; |
332 } | 339 } |
333 | 340 |
334 // static | 341 // static |
335 gpu::VideoEncodeAcceleratorSupportedProfiles | 342 gpu::VideoEncodeAcceleratorSupportedProfiles |
336 GpuVideoEncodeAccelerator::GetSupportedProfiles( | 343 GpuVideoEncodeAccelerator::GetSupportedProfiles( |
337 const gpu::GpuPreferences& gpu_preferences) { | 344 const gpu::GpuPreferences& gpu_preferences) { |
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
397 | 404 |
398 if (params.frame_id < 0) { | 405 if (params.frame_id < 0) { |
399 DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id; | 406 DLOG(ERROR) << __func__ << " invalid frame_id=" << params.frame_id; |
400 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 407 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
401 return; | 408 return; |
402 } | 409 } |
403 | 410 |
404 encoder_worker_task_runner_->PostTask( | 411 encoder_worker_task_runner_->PostTask( |
405 FROM_HERE, | 412 FROM_HERE, |
406 base::Bind(&GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker, | 413 base::Bind(&GpuVideoEncodeAccelerator::CreateEncodeFrameOnEncoderWorker, |
407 weak_this_factory_for_encoder_worker_.GetWeakPtr(), params)); | 414 weak_this_for_encoder_worker_, params)); |
408 } | 415 } |
409 | 416 |
410 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( | 417 void GpuVideoEncodeAccelerator::OnUseOutputBitstreamBuffer( |
411 int32_t buffer_id, | 418 int32_t buffer_id, |
412 base::SharedMemoryHandle buffer_handle, | 419 base::SharedMemoryHandle buffer_handle, |
413 uint32_t buffer_size) { | 420 uint32_t buffer_size) { |
414 DVLOG(3) << __func__ << " buffer_id=" << buffer_id | 421 DVLOG(3) << __func__ << " buffer_id=" << buffer_id |
415 << ", buffer_size=" << buffer_size; | 422 << ", buffer_size=" << buffer_size; |
416 DCHECK(CheckIfCalledOnCorrectThread()); | 423 DCHECK(CheckIfCalledOnCorrectThread()); |
417 if (!encoder_) | 424 if (!encoder_) |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
458 const uint32_t aligned_offset = | 465 const uint32_t aligned_offset = |
459 params.buffer_offset % base::SysInfo::VMAllocationGranularity(); | 466 params.buffer_offset % base::SysInfo::VMAllocationGranularity(); |
460 base::CheckedNumeric<off_t> map_offset = params.buffer_offset; | 467 base::CheckedNumeric<off_t> map_offset = params.buffer_offset; |
461 map_offset -= aligned_offset; | 468 map_offset -= aligned_offset; |
462 base::CheckedNumeric<size_t> map_size = params.buffer_size; | 469 base::CheckedNumeric<size_t> map_size = params.buffer_size; |
463 map_size += aligned_offset; | 470 map_size += aligned_offset; |
464 | 471 |
465 if (!map_offset.IsValid() || !map_size.IsValid()) { | 472 if (!map_offset.IsValid() || !map_size.IsValid()) { |
466 DLOG(ERROR) << __func__ << " invalid map_offset or map_size"; | 473 DLOG(ERROR) << __func__ << " invalid map_offset or map_size"; |
467 encode_task_runner_->PostTask( | 474 encode_task_runner_->PostTask( |
468 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError, | 475 FROM_HERE, |
469 weak_this_factory_.GetWeakPtr(), | 476 base::Bind(&GpuVideoEncodeAccelerator::NotifyError, weak_this_, |
470 VideoEncodeAccelerator::kPlatformFailureError)); | 477 VideoEncodeAccelerator::kPlatformFailureError)); |
471 return; | 478 return; |
472 } | 479 } |
473 | 480 |
474 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) { | 481 if (!shm->MapAt(map_offset.ValueOrDie(), map_size.ValueOrDie())) { |
475 DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id; | 482 DLOG(ERROR) << __func__ << " could not map frame_id=" << params.frame_id; |
476 encode_task_runner_->PostTask( | 483 encode_task_runner_->PostTask( |
477 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError, | 484 FROM_HERE, |
478 weak_this_factory_.GetWeakPtr(), | 485 base::Bind(&GpuVideoEncodeAccelerator::NotifyError, weak_this_, |
479 VideoEncodeAccelerator::kPlatformFailureError)); | 486 VideoEncodeAccelerator::kPlatformFailureError)); |
480 return; | 487 return; |
481 } | 488 } |
482 | 489 |
483 uint8_t* shm_memory = | 490 uint8_t* shm_memory = |
484 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset; | 491 reinterpret_cast<uint8_t*>(shm->memory()) + aligned_offset; |
485 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory( | 492 scoped_refptr<VideoFrame> frame = VideoFrame::WrapExternalSharedMemory( |
486 input_format_, input_coded_size_, gfx::Rect(input_visible_size_), | 493 input_format_, input_coded_size_, gfx::Rect(input_visible_size_), |
487 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle, | 494 input_visible_size_, shm_memory, params.buffer_size, params.buffer_handle, |
488 params.buffer_offset, params.timestamp); | 495 params.buffer_offset, params.timestamp); |
489 if (!frame) { | 496 if (!frame) { |
490 DLOG(ERROR) << __func__ << " could not create a frame"; | 497 DLOG(ERROR) << __func__ << " could not create a frame"; |
491 encode_task_runner_->PostTask( | 498 encode_task_runner_->PostTask( |
492 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::NotifyError, | 499 FROM_HERE, |
493 weak_this_factory_.GetWeakPtr(), | 500 base::Bind(&GpuVideoEncodeAccelerator::NotifyError, weak_this_, |
494 VideoEncodeAccelerator::kPlatformFailureError)); | 501 VideoEncodeAccelerator::kPlatformFailureError)); |
495 return; | 502 return; |
496 } | 503 } |
497 | 504 |
498 // We wrap |shm| in a callback and add it as a destruction observer, so it | 505 // We wrap |shm| in a callback and add it as a destruction observer, so it |
499 // stays alive and mapped until |frame| goes out of scope. | 506 // stays alive and mapped until |frame| goes out of scope. |
500 frame->AddDestructionObserver( | 507 frame->AddDestructionObserver( |
501 base::Bind(&DropSharedMemory, base::Passed(&shm))); | 508 base::Bind(&DropSharedMemory, base::Passed(&shm))); |
502 encode_task_runner_->PostTask( | 509 encode_task_runner_->PostTask( |
503 FROM_HERE, base::Bind(&GpuVideoEncodeAccelerator::OnEncodeFrameCreated, | 510 FROM_HERE, |
504 weak_this_factory_.GetWeakPtr(), params.frame_id, | 511 base::Bind(&GpuVideoEncodeAccelerator::OnEncodeFrameCreated, weak_this_, |
505 params.force_keyframe, frame)); | 512 params.frame_id, params.force_keyframe, frame)); |
506 } | 513 } |
507 | 514 |
508 void GpuVideoEncodeAccelerator::DestroyOnEncoderWorker() { | 515 void GpuVideoEncodeAccelerator::DestroyOnEncoderWorker() { |
509 DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread()); | 516 DCHECK(encoder_worker_task_runner_->BelongsToCurrentThread()); |
510 weak_this_factory_for_encoder_worker_.InvalidateWeakPtrs(); | 517 weak_this_factory_for_encoder_worker_.InvalidateWeakPtrs(); |
511 } | 518 } |
512 | 519 |
513 void GpuVideoEncodeAccelerator::OnEncodeFrameCreated( | 520 void GpuVideoEncodeAccelerator::OnEncodeFrameCreated( |
514 int32_t frame_id, | 521 int32_t frame_id, |
515 bool force_keyframe, | 522 bool force_keyframe, |
516 const scoped_refptr<media::VideoFrame>& frame) { | 523 const scoped_refptr<media::VideoFrame>& frame) { |
517 DVLOG(3) << __func__; | 524 DVLOG(3) << __func__; |
518 DCHECK(CheckIfCalledOnCorrectThread()); | 525 DCHECK(CheckIfCalledOnCorrectThread()); |
519 | 526 |
527 if (filter_removed_.IsSignaled()) | |
528 return; | |
529 | |
520 if (!frame) { | 530 if (!frame) { |
521 DLOG(ERROR) << __func__ << " could not create a frame"; | 531 DLOG(ERROR) << __func__ << " could not create a frame"; |
522 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); | 532 NotifyError(VideoEncodeAccelerator::kPlatformFailureError); |
523 return; | 533 return; |
524 } | 534 } |
525 | 535 |
526 frame->AddDestructionObserver(BindToCurrentLoop( | 536 frame->AddDestructionObserver(BindToCurrentLoop( |
527 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished, | 537 base::Bind(&GpuVideoEncodeAccelerator::EncodeFrameFinished, |
528 weak_this_factory_.GetWeakPtr(), frame_id))); | 538 weak_this_factory_.GetWeakPtr(), frame_id))); |
529 encoder_->Encode(frame, force_keyframe); | 539 encoder_->Encode(frame, force_keyframe); |
530 } | 540 } |
531 | 541 |
532 void GpuVideoEncodeAccelerator::EncodeFrameFinished(int32_t frame_id) { | 542 void GpuVideoEncodeAccelerator::EncodeFrameFinished(int32_t frame_id) { |
533 DCHECK(CheckIfCalledOnCorrectThread()); | 543 DCHECK(CheckIfCalledOnCorrectThread()); |
534 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_, | 544 if (!Send(new AcceleratedVideoEncoderHostMsg_NotifyInputDone(host_route_id_, |
535 frame_id))) { | 545 frame_id))) { |
536 DLOG(ERROR) << __func__ << " failed."; | 546 DLOG(ERROR) << __func__ << " failed."; |
537 } | 547 } |
538 } | 548 } |
539 | 549 |
540 bool GpuVideoEncodeAccelerator::CheckIfCalledOnCorrectThread() { | 550 bool GpuVideoEncodeAccelerator::CheckIfCalledOnCorrectThread() { |
541 return (filter_ && io_task_runner_->BelongsToCurrentThread()) || | 551 return (filter_ && io_task_runner_->BelongsToCurrentThread()) || |
542 (!filter_ && main_task_runner_->BelongsToCurrentThread()); | 552 (!filter_ && main_task_runner_->BelongsToCurrentThread()); |
543 } | 553 } |
544 | 554 |
545 } // namespace media | 555 } // namespace media |
OLD | NEW |