OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/common/gpu/media/vaapi_video_encode_accelerator.h" | 5 #include "content/common/gpu/media/vaapi_video_encode_accelerator.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/callback.h" | 8 #include "base/callback.h" |
| 9 #include "base/message_loop/message_loop_proxy.h" |
9 #include "base/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
10 #include "base/numerics/safe_conversions.h" | 11 #include "base/numerics/safe_conversions.h" |
11 #include "content/common/gpu/media/h264_dpb.h" | 12 #include "content/common/gpu/media/h264_dpb.h" |
12 #include "media/base/bind_to_current_loop.h" | 13 #include "media/base/bind_to_current_loop.h" |
13 #include "third_party/libva/va/va_enc_h264.h" | 14 #include "third_party/libva/va/va_enc_h264.h" |
14 | 15 |
15 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " | 16 #define DVLOGF(level) DVLOG(level) << __FUNCTION__ << "(): " |
16 | 17 |
17 #define NOTIFY_ERROR(error, msg) \ | 18 #define NOTIFY_ERROR(error, msg) \ |
18 do { \ | 19 do { \ |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
125 mb_height_(0), | 126 mb_height_(0), |
126 output_buffer_byte_size_(0), | 127 output_buffer_byte_size_(0), |
127 state_(kUninitialized), | 128 state_(kUninitialized), |
128 frame_num_(0), | 129 frame_num_(0), |
129 idr_pic_id_(0), | 130 idr_pic_id_(0), |
130 bitrate_(0), | 131 bitrate_(0), |
131 framerate_(0), | 132 framerate_(0), |
132 cpb_size_(0), | 133 cpb_size_(0), |
133 encoding_parameters_changed_(false), | 134 encoding_parameters_changed_(false), |
134 encoder_thread_("VAVEAEncoderThread"), | 135 encoder_thread_("VAVEAEncoderThread"), |
135 child_task_runner_(base::ThreadTaskRunnerHandle::Get()), | 136 child_message_loop_proxy_(base::MessageLoopProxy::current()), |
136 weak_this_ptr_factory_(this) { | 137 weak_this_ptr_factory_(this) { |
137 DVLOGF(4); | 138 DVLOGF(4); |
138 weak_this_ = weak_this_ptr_factory_.GetWeakPtr(); | 139 weak_this_ = weak_this_ptr_factory_.GetWeakPtr(); |
139 | 140 |
140 max_ref_idx_l0_size_ = kMaxNumReferenceFrames; | 141 max_ref_idx_l0_size_ = kMaxNumReferenceFrames; |
141 qp_ = kDefaultQP; | 142 qp_ = kDefaultQP; |
142 idr_period_ = kIDRPeriod; | 143 idr_period_ = kIDRPeriod; |
143 i_period_ = kIPeriod; | 144 i_period_ = kIPeriod; |
144 ip_period_ = kIPPeriod; | 145 ip_period_ = kIPPeriod; |
145 } | 146 } |
146 | 147 |
147 VaapiVideoEncodeAccelerator::~VaapiVideoEncodeAccelerator() { | 148 VaapiVideoEncodeAccelerator::~VaapiVideoEncodeAccelerator() { |
148 DVLOGF(4); | 149 DVLOGF(4); |
149 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 150 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
150 DCHECK(!encoder_thread_.IsRunning()); | 151 DCHECK(!encoder_thread_.IsRunning()); |
151 } | 152 } |
152 | 153 |
153 bool VaapiVideoEncodeAccelerator::Initialize( | 154 bool VaapiVideoEncodeAccelerator::Initialize( |
154 media::VideoFrame::Format format, | 155 media::VideoFrame::Format format, |
155 const gfx::Size& input_visible_size, | 156 const gfx::Size& input_visible_size, |
156 media::VideoCodecProfile output_profile, | 157 media::VideoCodecProfile output_profile, |
157 uint32 initial_bitrate, | 158 uint32 initial_bitrate, |
158 Client* client) { | 159 Client* client) { |
159 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 160 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
160 DCHECK(!encoder_thread_.IsRunning()); | 161 DCHECK(!encoder_thread_.IsRunning()); |
161 DCHECK_EQ(state_, kUninitialized); | 162 DCHECK_EQ(state_, kUninitialized); |
162 | 163 |
163 DVLOGF(1) << "Initializing VAVEA, input_format: " | 164 DVLOGF(1) << "Initializing VAVEA, input_format: " |
164 << media::VideoFrame::FormatToString(format) | 165 << media::VideoFrame::FormatToString(format) |
165 << ", input_visible_size: " << input_visible_size.ToString() | 166 << ", input_visible_size: " << input_visible_size.ToString() |
166 << ", output_profile: " << output_profile | 167 << ", output_profile: " << output_profile |
167 << ", initial_bitrate: " << initial_bitrate; | 168 << ", initial_bitrate: " << initial_bitrate; |
168 | 169 |
169 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); | 170 client_ptr_factory_.reset(new base::WeakPtrFactory<Client>(client)); |
(...skipping 29 matching lines...) Expand all Loading... |
199 base::Bind(&ReportToUMA, VAAPI_ERROR)); | 200 base::Bind(&ReportToUMA, VAAPI_ERROR)); |
200 if (!vaapi_wrapper_.get()) { | 201 if (!vaapi_wrapper_.get()) { |
201 DVLOGF(1) << "Failed initializing VAAPI for profile " << output_profile; | 202 DVLOGF(1) << "Failed initializing VAAPI for profile " << output_profile; |
202 return false; | 203 return false; |
203 } | 204 } |
204 | 205 |
205 if (!encoder_thread_.Start()) { | 206 if (!encoder_thread_.Start()) { |
206 LOG(ERROR) << "Failed to start encoder thread"; | 207 LOG(ERROR) << "Failed to start encoder thread"; |
207 return false; | 208 return false; |
208 } | 209 } |
209 encoder_thread_task_runner_ = encoder_thread_.task_runner(); | 210 encoder_thread_proxy_ = encoder_thread_.message_loop_proxy(); |
210 | 211 |
211 // Finish the remaining initialization on the encoder thread. | 212 // Finish the remaining initialization on the encoder thread. |
212 encoder_thread_task_runner_->PostTask( | 213 encoder_thread_proxy_->PostTask( |
213 FROM_HERE, base::Bind(&VaapiVideoEncodeAccelerator::InitializeTask, | 214 FROM_HERE, |
214 base::Unretained(this))); | 215 base::Bind(&VaapiVideoEncodeAccelerator::InitializeTask, |
| 216 base::Unretained(this))); |
215 | 217 |
216 return true; | 218 return true; |
217 } | 219 } |
218 | 220 |
219 void VaapiVideoEncodeAccelerator::InitializeTask() { | 221 void VaapiVideoEncodeAccelerator::InitializeTask() { |
220 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 222 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
221 DCHECK_EQ(state_, kUninitialized); | 223 DCHECK_EQ(state_, kUninitialized); |
222 DVLOGF(4); | 224 DVLOGF(4); |
223 | 225 |
224 va_surface_release_cb_ = media::BindToCurrentLoop( | 226 va_surface_release_cb_ = media::BindToCurrentLoop( |
225 base::Bind(&VaapiVideoEncodeAccelerator::RecycleVASurfaceID, | 227 base::Bind(&VaapiVideoEncodeAccelerator::RecycleVASurfaceID, |
226 base::Unretained(this))); | 228 base::Unretained(this))); |
227 | 229 |
228 if (!vaapi_wrapper_->CreateSurfaces( | 230 if (!vaapi_wrapper_->CreateSurfaces( |
229 coded_size_, kNumSurfaces, &available_va_surface_ids_)) { | 231 coded_size_, kNumSurfaces, &available_va_surface_ids_)) { |
230 NOTIFY_ERROR(kPlatformFailureError, "Failed creating VASurfaces"); | 232 NOTIFY_ERROR(kPlatformFailureError, "Failed creating VASurfaces"); |
231 return; | 233 return; |
232 } | 234 } |
233 | 235 |
234 UpdateSPS(); | 236 UpdateSPS(); |
235 GeneratePackedSPS(); | 237 GeneratePackedSPS(); |
236 | 238 |
237 UpdatePPS(); | 239 UpdatePPS(); |
238 GeneratePackedPPS(); | 240 GeneratePackedPPS(); |
239 | 241 |
240 child_task_runner_->PostTask( | 242 child_message_loop_proxy_->PostTask( |
241 FROM_HERE, | 243 FROM_HERE, |
242 base::Bind(&Client::RequireBitstreamBuffers, client_, kNumInputBuffers, | 244 base::Bind(&Client::RequireBitstreamBuffers, |
243 coded_size_, output_buffer_byte_size_)); | 245 client_, |
| 246 kNumInputBuffers, |
| 247 coded_size_, |
| 248 output_buffer_byte_size_)); |
244 | 249 |
245 SetState(kEncoding); | 250 SetState(kEncoding); |
246 } | 251 } |
247 | 252 |
248 void VaapiVideoEncodeAccelerator::RecycleVASurfaceID( | 253 void VaapiVideoEncodeAccelerator::RecycleVASurfaceID( |
249 VASurfaceID va_surface_id) { | 254 VASurfaceID va_surface_id) { |
250 DVLOGF(4) << "va_surface_id: " << va_surface_id; | 255 DVLOGF(4) << "va_surface_id: " << va_surface_id; |
251 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 256 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
252 | 257 |
253 available_va_surface_ids_.push_back(va_surface_id); | 258 available_va_surface_ids_.push_back(va_surface_id); |
254 EncodeFrameTask(); | 259 EncodeFrameTask(); |
255 } | 260 } |
256 | 261 |
257 void VaapiVideoEncodeAccelerator::BeginFrame(bool force_keyframe) { | 262 void VaapiVideoEncodeAccelerator::BeginFrame(bool force_keyframe) { |
258 current_pic_ = new H264Picture(); | 263 current_pic_ = new H264Picture(); |
259 | 264 |
260 // If the current picture is an IDR picture, frame_num shall be equal to 0. | 265 // If the current picture is an IDR picture, frame_num shall be equal to 0. |
261 if (force_keyframe) | 266 if (force_keyframe) |
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
513 current_encode_job_->input_surface->id()); | 518 current_encode_job_->input_surface->id()); |
514 } | 519 } |
515 | 520 |
516 bool VaapiVideoEncodeAccelerator::UploadFrame( | 521 bool VaapiVideoEncodeAccelerator::UploadFrame( |
517 const scoped_refptr<media::VideoFrame>& frame) { | 522 const scoped_refptr<media::VideoFrame>& frame) { |
518 return vaapi_wrapper_->UploadVideoFrameToSurface( | 523 return vaapi_wrapper_->UploadVideoFrameToSurface( |
519 frame, current_encode_job_->input_surface->id()); | 524 frame, current_encode_job_->input_surface->id()); |
520 } | 525 } |
521 | 526 |
522 void VaapiVideoEncodeAccelerator::TryToReturnBitstreamBuffer() { | 527 void VaapiVideoEncodeAccelerator::TryToReturnBitstreamBuffer() { |
523 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 528 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
524 | 529 |
525 if (state_ != kEncoding) | 530 if (state_ != kEncoding) |
526 return; | 531 return; |
527 | 532 |
528 if (submitted_encode_jobs_.empty() || available_bitstream_buffers_.empty()) | 533 if (submitted_encode_jobs_.empty() || available_bitstream_buffers_.empty()) |
529 return; | 534 return; |
530 | 535 |
531 linked_ptr<BitstreamBufferRef> buffer = available_bitstream_buffers_.front(); | 536 linked_ptr<BitstreamBufferRef> buffer = available_bitstream_buffers_.front(); |
532 available_bitstream_buffers_.pop(); | 537 available_bitstream_buffers_.pop(); |
533 | 538 |
(...skipping 10 matching lines...) Expand all Loading... |
544 buffer->size, | 549 buffer->size, |
545 &data_size)) { | 550 &data_size)) { |
546 NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer"); | 551 NOTIFY_ERROR(kPlatformFailureError, "Failed downloading coded buffer"); |
547 return; | 552 return; |
548 } | 553 } |
549 | 554 |
550 DVLOGF(3) << "Returning bitstream buffer " | 555 DVLOGF(3) << "Returning bitstream buffer " |
551 << (encode_job->keyframe ? "(keyframe)" : "") | 556 << (encode_job->keyframe ? "(keyframe)" : "") |
552 << " id: " << buffer->id << " size: " << data_size; | 557 << " id: " << buffer->id << " size: " << data_size; |
553 | 558 |
554 child_task_runner_->PostTask( | 559 child_message_loop_proxy_->PostTask(FROM_HERE, |
555 FROM_HERE, base::Bind(&Client::BitstreamBufferReady, client_, buffer->id, | 560 base::Bind(&Client::BitstreamBufferReady, |
556 data_size, encode_job->keyframe)); | 561 client_, |
| 562 buffer->id, |
| 563 data_size, |
| 564 encode_job->keyframe)); |
557 } | 565 } |
558 | 566 |
559 void VaapiVideoEncodeAccelerator::Encode( | 567 void VaapiVideoEncodeAccelerator::Encode( |
560 const scoped_refptr<media::VideoFrame>& frame, | 568 const scoped_refptr<media::VideoFrame>& frame, |
561 bool force_keyframe) { | 569 bool force_keyframe) { |
562 DVLOGF(3) << "Frame timestamp: " << frame->timestamp().InMilliseconds() | 570 DVLOGF(3) << "Frame timestamp: " << frame->timestamp().InMilliseconds() |
563 << " force_keyframe: " << force_keyframe; | 571 << " force_keyframe: " << force_keyframe; |
564 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 572 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
565 | 573 |
566 encoder_thread_task_runner_->PostTask( | 574 encoder_thread_proxy_->PostTask( |
567 FROM_HERE, base::Bind(&VaapiVideoEncodeAccelerator::EncodeTask, | 575 FROM_HERE, |
568 base::Unretained(this), frame, force_keyframe)); | 576 base::Bind(&VaapiVideoEncodeAccelerator::EncodeTask, |
| 577 base::Unretained(this), |
| 578 frame, |
| 579 force_keyframe)); |
569 } | 580 } |
570 | 581 |
571 bool VaapiVideoEncodeAccelerator::PrepareNextJob() { | 582 bool VaapiVideoEncodeAccelerator::PrepareNextJob() { |
572 if (available_va_surface_ids_.size() < kMinSurfacesToEncode) | 583 if (available_va_surface_ids_.size() < kMinSurfacesToEncode) |
573 return false; | 584 return false; |
574 | 585 |
575 DCHECK(!current_encode_job_); | 586 DCHECK(!current_encode_job_); |
576 current_encode_job_.reset(new EncodeJob()); | 587 current_encode_job_.reset(new EncodeJob()); |
577 | 588 |
578 if (!vaapi_wrapper_->CreateCodedBuffer(output_buffer_byte_size_, | 589 if (!vaapi_wrapper_->CreateCodedBuffer(output_buffer_byte_size_, |
(...skipping 14 matching lines...) Expand all Loading... |
593 // removed from ref_pic_list0_ when it's full at the end of job submission. | 604 // removed from ref_pic_list0_ when it's full at the end of job submission. |
594 // Keep refs to them along with the job and only release after sync. | 605 // Keep refs to them along with the job and only release after sync. |
595 current_encode_job_->reference_surfaces = ref_pic_list0_; | 606 current_encode_job_->reference_surfaces = ref_pic_list0_; |
596 | 607 |
597 return true; | 608 return true; |
598 } | 609 } |
599 | 610 |
600 void VaapiVideoEncodeAccelerator::EncodeTask( | 611 void VaapiVideoEncodeAccelerator::EncodeTask( |
601 const scoped_refptr<media::VideoFrame>& frame, | 612 const scoped_refptr<media::VideoFrame>& frame, |
602 bool force_keyframe) { | 613 bool force_keyframe) { |
603 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 614 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
604 DCHECK_NE(state_, kUninitialized); | 615 DCHECK_NE(state_, kUninitialized); |
605 | 616 |
606 encoder_input_queue_.push( | 617 encoder_input_queue_.push( |
607 make_linked_ptr(new InputFrameRef(frame, force_keyframe))); | 618 make_linked_ptr(new InputFrameRef(frame, force_keyframe))); |
608 EncodeFrameTask(); | 619 EncodeFrameTask(); |
609 } | 620 } |
610 | 621 |
611 void VaapiVideoEncodeAccelerator::EncodeFrameTask() { | 622 void VaapiVideoEncodeAccelerator::EncodeFrameTask() { |
612 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 623 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
613 | 624 |
614 if (state_ != kEncoding || encoder_input_queue_.empty()) | 625 if (state_ != kEncoding || encoder_input_queue_.empty()) |
615 return; | 626 return; |
616 | 627 |
617 if (!PrepareNextJob()) { | 628 if (!PrepareNextJob()) { |
618 DVLOGF(4) << "Not ready for next frame yet"; | 629 DVLOGF(4) << "Not ready for next frame yet"; |
619 return; | 630 return; |
620 } | 631 } |
621 | 632 |
622 linked_ptr<InputFrameRef> frame_ref = encoder_input_queue_.front(); | 633 linked_ptr<InputFrameRef> frame_ref = encoder_input_queue_.front(); |
(...skipping 22 matching lines...) Expand all Loading... |
645 return; | 656 return; |
646 } | 657 } |
647 | 658 |
648 EndFrame(); | 659 EndFrame(); |
649 TryToReturnBitstreamBuffer(); | 660 TryToReturnBitstreamBuffer(); |
650 } | 661 } |
651 | 662 |
652 void VaapiVideoEncodeAccelerator::UseOutputBitstreamBuffer( | 663 void VaapiVideoEncodeAccelerator::UseOutputBitstreamBuffer( |
653 const media::BitstreamBuffer& buffer) { | 664 const media::BitstreamBuffer& buffer) { |
654 DVLOGF(4) << "id: " << buffer.id(); | 665 DVLOGF(4) << "id: " << buffer.id(); |
655 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 666 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
656 | 667 |
657 if (buffer.size() < output_buffer_byte_size_) { | 668 if (buffer.size() < output_buffer_byte_size_) { |
658 NOTIFY_ERROR(kInvalidArgumentError, "Provided bitstream buffer too small"); | 669 NOTIFY_ERROR(kInvalidArgumentError, "Provided bitstream buffer too small"); |
659 return; | 670 return; |
660 } | 671 } |
661 | 672 |
662 scoped_ptr<base::SharedMemory> shm( | 673 scoped_ptr<base::SharedMemory> shm( |
663 new base::SharedMemory(buffer.handle(), false)); | 674 new base::SharedMemory(buffer.handle(), false)); |
664 if (!shm->Map(buffer.size())) { | 675 if (!shm->Map(buffer.size())) { |
665 NOTIFY_ERROR(kPlatformFailureError, "Failed mapping shared memory."); | 676 NOTIFY_ERROR(kPlatformFailureError, "Failed mapping shared memory."); |
666 return; | 677 return; |
667 } | 678 } |
668 | 679 |
669 scoped_ptr<BitstreamBufferRef> buffer_ref( | 680 scoped_ptr<BitstreamBufferRef> buffer_ref( |
670 new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size())); | 681 new BitstreamBufferRef(buffer.id(), shm.Pass(), buffer.size())); |
671 | 682 |
672 encoder_thread_task_runner_->PostTask( | 683 encoder_thread_proxy_->PostTask( |
673 FROM_HERE, | 684 FROM_HERE, |
674 base::Bind(&VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask, | 685 base::Bind(&VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask, |
675 base::Unretained(this), base::Passed(&buffer_ref))); | 686 base::Unretained(this), |
| 687 base::Passed(&buffer_ref))); |
676 } | 688 } |
677 | 689 |
678 void VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask( | 690 void VaapiVideoEncodeAccelerator::UseOutputBitstreamBufferTask( |
679 scoped_ptr<BitstreamBufferRef> buffer_ref) { | 691 scoped_ptr<BitstreamBufferRef> buffer_ref) { |
680 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 692 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
681 DCHECK_NE(state_, kUninitialized); | 693 DCHECK_NE(state_, kUninitialized); |
682 | 694 |
683 available_bitstream_buffers_.push(make_linked_ptr(buffer_ref.release())); | 695 available_bitstream_buffers_.push(make_linked_ptr(buffer_ref.release())); |
684 TryToReturnBitstreamBuffer(); | 696 TryToReturnBitstreamBuffer(); |
685 } | 697 } |
686 | 698 |
687 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange( | 699 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChange( |
688 uint32 bitrate, | 700 uint32 bitrate, |
689 uint32 framerate) { | 701 uint32 framerate) { |
690 DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate; | 702 DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate; |
691 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 703 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
692 | 704 |
693 encoder_thread_task_runner_->PostTask( | 705 encoder_thread_proxy_->PostTask( |
694 FROM_HERE, | 706 FROM_HERE, |
695 base::Bind( | 707 base::Bind( |
696 &VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask, | 708 &VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask, |
697 base::Unretained(this), bitrate, framerate)); | 709 base::Unretained(this), |
| 710 bitrate, |
| 711 framerate)); |
698 } | 712 } |
699 | 713 |
700 void VaapiVideoEncodeAccelerator::UpdateRates(uint32 bitrate, | 714 void VaapiVideoEncodeAccelerator::UpdateRates(uint32 bitrate, |
701 uint32 framerate) { | 715 uint32 framerate) { |
702 if (encoder_thread_.IsRunning()) | 716 if (encoder_thread_.IsRunning()) |
703 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 717 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
704 DCHECK_NE(bitrate, 0u); | 718 DCHECK_NE(bitrate, 0u); |
705 DCHECK_NE(framerate, 0u); | 719 DCHECK_NE(framerate, 0u); |
706 bitrate_ = bitrate; | 720 bitrate_ = bitrate; |
707 framerate_ = framerate; | 721 framerate_ = framerate; |
708 cpb_size_ = bitrate_ * kCPBWindowSizeMs / 1000; | 722 cpb_size_ = bitrate_ * kCPBWindowSizeMs / 1000; |
709 } | 723 } |
710 | 724 |
711 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask( | 725 void VaapiVideoEncodeAccelerator::RequestEncodingParametersChangeTask( |
712 uint32 bitrate, | 726 uint32 bitrate, |
713 uint32 framerate) { | 727 uint32 framerate) { |
714 DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate; | 728 DVLOGF(2) << "bitrate: " << bitrate << " framerate: " << framerate; |
715 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 729 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
716 DCHECK_NE(state_, kUninitialized); | 730 DCHECK_NE(state_, kUninitialized); |
717 | 731 |
718 // This is a workaround to zero being temporarily, as part of the initial | 732 // This is a workaround to zero being temporarily, as part of the initial |
719 // setup, provided by the webrtc video encode and a zero bitrate and | 733 // setup, provided by the webrtc video encode and a zero bitrate and |
720 // framerate not being accepted by VAAPI | 734 // framerate not being accepted by VAAPI |
721 // TODO: This code is common with v4l2_video_encode_accelerator.cc, perhaps | 735 // TODO: This code is common with v4l2_video_encode_accelerator.cc, perhaps |
722 // it could be pulled up to RTCVideoEncoder | 736 // it could be pulled up to RTCVideoEncoder |
723 if (bitrate < 1) | 737 if (bitrate < 1) |
724 bitrate = 1; | 738 bitrate = 1; |
725 if (framerate < 1) | 739 if (framerate < 1) |
726 framerate = 1; | 740 framerate = 1; |
727 | 741 |
728 if (bitrate_ == bitrate && framerate_ == framerate) | 742 if (bitrate_ == bitrate && framerate_ == framerate) |
729 return; | 743 return; |
730 | 744 |
731 UpdateRates(bitrate, framerate); | 745 UpdateRates(bitrate, framerate); |
732 | 746 |
733 UpdateSPS(); | 747 UpdateSPS(); |
734 GeneratePackedSPS(); | 748 GeneratePackedSPS(); |
735 | 749 |
736 // Submit new parameters along with next frame that will be processed. | 750 // Submit new parameters along with next frame that will be processed. |
737 encoding_parameters_changed_ = true; | 751 encoding_parameters_changed_ = true; |
738 } | 752 } |
739 | 753 |
740 void VaapiVideoEncodeAccelerator::Destroy() { | 754 void VaapiVideoEncodeAccelerator::Destroy() { |
741 DCHECK(child_task_runner_->BelongsToCurrentThread()); | 755 DCHECK(child_message_loop_proxy_->BelongsToCurrentThread()); |
742 | 756 |
743 // Can't call client anymore after Destroy() returns. | 757 // Can't call client anymore after Destroy() returns. |
744 client_ptr_factory_.reset(); | 758 client_ptr_factory_.reset(); |
745 weak_this_ptr_factory_.InvalidateWeakPtrs(); | 759 weak_this_ptr_factory_.InvalidateWeakPtrs(); |
746 | 760 |
747 // Early-exit encoder tasks if they are running and join the thread. | 761 // Early-exit encoder tasks if they are running and join the thread. |
748 if (encoder_thread_.IsRunning()) { | 762 if (encoder_thread_.IsRunning()) { |
749 encoder_thread_.message_loop()->PostTask( | 763 encoder_thread_.message_loop()->PostTask( |
750 FROM_HERE, | 764 FROM_HERE, |
751 base::Bind(&VaapiVideoEncodeAccelerator::DestroyTask, | 765 base::Bind(&VaapiVideoEncodeAccelerator::DestroyTask, |
752 base::Unretained(this))); | 766 base::Unretained(this))); |
753 encoder_thread_.Stop(); | 767 encoder_thread_.Stop(); |
754 } | 768 } |
755 | 769 |
756 delete this; | 770 delete this; |
757 } | 771 } |
758 | 772 |
759 void VaapiVideoEncodeAccelerator::DestroyTask() { | 773 void VaapiVideoEncodeAccelerator::DestroyTask() { |
760 DVLOGF(2); | 774 DVLOGF(2); |
761 DCHECK(encoder_thread_task_runner_->BelongsToCurrentThread()); | 775 DCHECK(encoder_thread_proxy_->BelongsToCurrentThread()); |
762 SetState(kError); | 776 SetState(kError); |
763 } | 777 } |
764 | 778 |
765 void VaapiVideoEncodeAccelerator::UpdateSPS() { | 779 void VaapiVideoEncodeAccelerator::UpdateSPS() { |
766 memset(¤t_sps_, 0, sizeof(media::H264SPS)); | 780 memset(¤t_sps_, 0, sizeof(media::H264SPS)); |
767 | 781 |
768 // Spec A.2 and A.3. | 782 // Spec A.2 and A.3. |
769 switch (profile_) { | 783 switch (profile_) { |
770 case media::H264PROFILE_BASELINE: | 784 case media::H264PROFILE_BASELINE: |
771 // Due to crbug.com/345569, we don't distinguish between constrained | 785 // Due to crbug.com/345569, we don't distinguish between constrained |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1015 packed_pps_.AppendBool(current_pps_.pic_scaling_matrix_present_flag); | 1029 packed_pps_.AppendBool(current_pps_.pic_scaling_matrix_present_flag); |
1016 DCHECK(!current_pps_.pic_scaling_matrix_present_flag); | 1030 DCHECK(!current_pps_.pic_scaling_matrix_present_flag); |
1017 packed_pps_.AppendSE(current_pps_.second_chroma_qp_index_offset); | 1031 packed_pps_.AppendSE(current_pps_.second_chroma_qp_index_offset); |
1018 | 1032 |
1019 packed_pps_.FinishNALU(); | 1033 packed_pps_.FinishNALU(); |
1020 } | 1034 } |
1021 | 1035 |
1022 void VaapiVideoEncodeAccelerator::SetState(State state) { | 1036 void VaapiVideoEncodeAccelerator::SetState(State state) { |
1023 // Only touch state on encoder thread, unless it's not running. | 1037 // Only touch state on encoder thread, unless it's not running. |
1024 if (encoder_thread_.IsRunning() && | 1038 if (encoder_thread_.IsRunning() && |
1025 !encoder_thread_task_runner_->BelongsToCurrentThread()) { | 1039 !encoder_thread_proxy_->BelongsToCurrentThread()) { |
1026 encoder_thread_task_runner_->PostTask( | 1040 encoder_thread_proxy_->PostTask( |
1027 FROM_HERE, base::Bind(&VaapiVideoEncodeAccelerator::SetState, | 1041 FROM_HERE, |
1028 base::Unretained(this), state)); | 1042 base::Bind(&VaapiVideoEncodeAccelerator::SetState, |
| 1043 base::Unretained(this), |
| 1044 state)); |
1029 return; | 1045 return; |
1030 } | 1046 } |
1031 | 1047 |
1032 DVLOGF(1) << "setting state to: " << state; | 1048 DVLOGF(1) << "setting state to: " << state; |
1033 state_ = state; | 1049 state_ = state; |
1034 } | 1050 } |
1035 | 1051 |
1036 void VaapiVideoEncodeAccelerator::NotifyError(Error error) { | 1052 void VaapiVideoEncodeAccelerator::NotifyError(Error error) { |
1037 if (!child_task_runner_->BelongsToCurrentThread()) { | 1053 if (!child_message_loop_proxy_->BelongsToCurrentThread()) { |
1038 child_task_runner_->PostTask( | 1054 child_message_loop_proxy_->PostTask( |
1039 FROM_HERE, base::Bind(&VaapiVideoEncodeAccelerator::NotifyError, | 1055 FROM_HERE, |
1040 weak_this_, error)); | 1056 base::Bind( |
| 1057 &VaapiVideoEncodeAccelerator::NotifyError, weak_this_, error)); |
1041 return; | 1058 return; |
1042 } | 1059 } |
1043 | 1060 |
1044 if (client_) { | 1061 if (client_) { |
1045 client_->NotifyError(error); | 1062 client_->NotifyError(error); |
1046 client_ptr_factory_.reset(); | 1063 client_ptr_factory_.reset(); |
1047 } | 1064 } |
1048 } | 1065 } |
1049 | 1066 |
1050 VaapiVideoEncodeAccelerator::EncodeJob::EncodeJob() | 1067 VaapiVideoEncodeAccelerator::EncodeJob::EncodeJob() |
1051 : coded_buffer(VA_INVALID_ID), keyframe(false) { | 1068 : coded_buffer(VA_INVALID_ID), keyframe(false) { |
1052 } | 1069 } |
1053 | 1070 |
1054 VaapiVideoEncodeAccelerator::EncodeJob::~EncodeJob() { | 1071 VaapiVideoEncodeAccelerator::EncodeJob::~EncodeJob() { |
1055 } | 1072 } |
1056 | 1073 |
1057 } // namespace content | 1074 } // namespace content |
OLD | NEW |