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