Chromium Code Reviews| 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 |