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 "media/cast/sender/external_video_encoder.h" | 5 #include "media/cast/sender/external_video_encoder.h" |
6 | 6 |
7 #include <cmath> | 7 #include <cmath> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/bind.h" | 10 #include "base/bind.h" |
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 allocate_input_buffer_in_progress_(false) {} | 115 allocate_input_buffer_in_progress_(false) {} |
116 | 116 |
117 base::SingleThreadTaskRunner* task_runner() const { | 117 base::SingleThreadTaskRunner* task_runner() const { |
118 return task_runner_.get(); | 118 return task_runner_.get(); |
119 } | 119 } |
120 | 120 |
121 void Initialize(const gfx::Size& frame_size, | 121 void Initialize(const gfx::Size& frame_size, |
122 VideoCodecProfile codec_profile, | 122 VideoCodecProfile codec_profile, |
123 int start_bit_rate, | 123 int start_bit_rate, |
124 FrameId first_frame_id) { | 124 FrameId first_frame_id) { |
125 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 125 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
126 | 126 |
127 requested_bit_rate_ = start_bit_rate; | 127 requested_bit_rate_ = start_bit_rate; |
128 encoder_active_ = video_encode_accelerator_->Initialize( | 128 encoder_active_ = video_encode_accelerator_->Initialize( |
129 media::PIXEL_FORMAT_I420, frame_size, codec_profile, start_bit_rate, | 129 media::PIXEL_FORMAT_I420, frame_size, codec_profile, start_bit_rate, |
130 this); | 130 this); |
131 next_frame_id_ = first_frame_id; | 131 next_frame_id_ = first_frame_id; |
132 codec_profile_ = codec_profile; | 132 codec_profile_ = codec_profile; |
133 | 133 |
134 UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess", | 134 UMA_HISTOGRAM_BOOLEAN("Cast.Sender.VideoEncodeAcceleratorInitializeSuccess", |
135 encoder_active_); | 135 encoder_active_); |
136 | 136 |
137 cast_environment_->PostTask( | 137 cast_environment_->PostTask( |
138 CastEnvironment::MAIN, | 138 CastEnvironment::MAIN, |
139 FROM_HERE, | 139 FROM_HERE, |
140 base::Bind(status_change_cb_, | 140 base::Bind(status_change_cb_, |
141 encoder_active_ ? STATUS_INITIALIZED : | 141 encoder_active_ ? STATUS_INITIALIZED : |
142 STATUS_CODEC_INIT_FAILED)); | 142 STATUS_CODEC_INIT_FAILED)); |
143 } | 143 } |
144 | 144 |
145 void SetBitRate(int bit_rate) { | 145 void SetBitRate(int bit_rate) { |
146 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 146 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
147 | 147 |
148 requested_bit_rate_ = bit_rate; | 148 requested_bit_rate_ = bit_rate; |
149 video_encode_accelerator_->RequestEncodingParametersChange( | 149 video_encode_accelerator_->RequestEncodingParametersChange( |
150 bit_rate, static_cast<uint32_t>(max_frame_rate_ + 0.5)); | 150 bit_rate, static_cast<uint32_t>(max_frame_rate_ + 0.5)); |
151 } | 151 } |
152 | 152 |
153 // The destruction call back of the copied video frame to free its use of | 153 // The destruction call back of the copied video frame to free its use of |
154 // the input buffer. | 154 // the input buffer. |
155 void ReturnInputBufferToPool(int index) { | 155 void ReturnInputBufferToPool(int index) { |
156 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 156 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
157 DCHECK_GE(index, 0); | 157 DCHECK_GE(index, 0); |
158 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); | 158 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); |
159 free_input_buffer_index_.push_back(index); | 159 free_input_buffer_index_.push_back(index); |
160 } | 160 } |
161 | 161 |
162 void EncodeVideoFrame( | 162 void EncodeVideoFrame( |
163 const scoped_refptr<media::VideoFrame>& video_frame, | 163 const scoped_refptr<media::VideoFrame>& video_frame, |
164 const base::TimeTicks& reference_time, | 164 const base::TimeTicks& reference_time, |
165 bool key_frame_requested, | 165 bool key_frame_requested, |
166 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { | 166 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { |
167 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 167 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
168 | 168 |
169 if (!encoder_active_) | 169 if (!encoder_active_) |
170 return; | 170 return; |
171 | 171 |
172 in_progress_frame_encodes_.push_back(InProgressFrameEncode( | 172 in_progress_frame_encodes_.push_back(InProgressFrameEncode( |
173 video_frame, reference_time, frame_encoded_callback, | 173 video_frame, reference_time, frame_encoded_callback, |
174 requested_bit_rate_)); | 174 requested_bit_rate_)); |
175 | 175 |
176 scoped_refptr<media::VideoFrame> frame = video_frame; | 176 scoped_refptr<media::VideoFrame> frame = video_frame; |
177 if (video_frame->coded_size() != frame_coded_size_) { | 177 if (video_frame->coded_size() != frame_coded_size_) { |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
211 index))); | 211 index))); |
212 free_input_buffer_index_.pop_back(); | 212 free_input_buffer_index_.pop_back(); |
213 } | 213 } |
214 | 214 |
215 // BitstreamBufferReady will be called once the encoder is done. | 215 // BitstreamBufferReady will be called once the encoder is done. |
216 video_encode_accelerator_->Encode(frame, key_frame_requested); | 216 video_encode_accelerator_->Encode(frame, key_frame_requested); |
217 } | 217 } |
218 | 218 |
219 protected: | 219 protected: |
220 void NotifyError(VideoEncodeAccelerator::Error error) final { | 220 void NotifyError(VideoEncodeAccelerator::Error error) final { |
221 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 221 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
222 | 222 |
223 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && | 223 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && |
224 error != VideoEncodeAccelerator::kIllegalStateError); | 224 error != VideoEncodeAccelerator::kIllegalStateError); |
225 | 225 |
226 encoder_active_ = false; | 226 encoder_active_ = false; |
227 | 227 |
228 cast_environment_->PostTask( | 228 cast_environment_->PostTask( |
229 CastEnvironment::MAIN, | 229 CastEnvironment::MAIN, |
230 FROM_HERE, | 230 FROM_HERE, |
231 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); | 231 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); |
232 | 232 |
233 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so | 233 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so |
234 // pending frames do not become stuck, freezing VideoSender. | 234 // pending frames do not become stuck, freezing VideoSender. |
235 } | 235 } |
236 | 236 |
237 // Called to allocate the input and output buffers. | 237 // Called to allocate the input and output buffers. |
238 void RequireBitstreamBuffers(unsigned int input_count, | 238 void RequireBitstreamBuffers(unsigned int input_count, |
239 const gfx::Size& input_coded_size, | 239 const gfx::Size& input_coded_size, |
240 size_t output_buffer_size) final { | 240 size_t output_buffer_size) final { |
241 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 241 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
242 | 242 |
243 frame_coded_size_ = input_coded_size; | 243 frame_coded_size_ = input_coded_size; |
244 | 244 |
245 max_allowed_input_buffers_ = input_count + kExtraInputBufferCount; | 245 max_allowed_input_buffers_ = input_count + kExtraInputBufferCount; |
246 | 246 |
247 for (size_t j = 0; j < kOutputBufferCount; ++j) { | 247 for (size_t j = 0; j < kOutputBufferCount; ++j) { |
248 create_video_encode_memory_cb_.Run( | 248 create_video_encode_memory_cb_.Run( |
249 output_buffer_size, | 249 output_buffer_size, |
250 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); | 250 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); |
251 } | 251 } |
252 } | 252 } |
253 | 253 |
254 // Encoder has encoded a frame and it's available in one of the output | 254 // Encoder has encoded a frame and it's available in one of the output |
255 // buffers. Package the result in a media::cast::EncodedFrame and post it | 255 // buffers. Package the result in a media::cast::EncodedFrame and post it |
256 // to the Cast MAIN thread via the supplied callback. | 256 // to the Cast MAIN thread via the supplied callback. |
257 void BitstreamBufferReady(int32_t bitstream_buffer_id, | 257 void BitstreamBufferReady(int32_t bitstream_buffer_id, |
258 size_t payload_size, | 258 size_t payload_size, |
259 bool key_frame, | 259 bool key_frame, |
260 base::TimeDelta /* timestamp */) final { | 260 base::TimeDelta /* timestamp */) final { |
261 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 261 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
262 if (bitstream_buffer_id < 0 || | 262 if (bitstream_buffer_id < 0 || |
263 bitstream_buffer_id >= static_cast<int32_t>(output_buffers_.size())) { | 263 bitstream_buffer_id >= static_cast<int32_t>(output_buffers_.size())) { |
264 NOTREACHED(); | 264 NOTREACHED(); |
265 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" | 265 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" |
266 << bitstream_buffer_id; | 266 << bitstream_buffer_id; |
267 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 267 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
268 return; | 268 return; |
269 } | 269 } |
270 base::SharedMemory* output_buffer = | 270 base::SharedMemory* output_buffer = |
271 output_buffers_[bitstream_buffer_id].get(); | 271 output_buffers_[bitstream_buffer_id].get(); |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
445 base::Passed(&memory))); | 445 base::Passed(&memory))); |
446 } | 446 } |
447 | 447 |
448 void OnCreateInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | 448 void OnCreateInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
449 task_runner_->PostTask( | 449 task_runner_->PostTask( |
450 FROM_HERE, base::Bind(&VEAClientImpl::OnReceivedInputSharedMemory, this, | 450 FROM_HERE, base::Bind(&VEAClientImpl::OnReceivedInputSharedMemory, this, |
451 base::Passed(&memory))); | 451 base::Passed(&memory))); |
452 } | 452 } |
453 | 453 |
454 void OnReceivedSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | 454 void OnReceivedSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
455 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 455 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
456 | 456 |
457 output_buffers_.push_back(std::move(memory)); | 457 output_buffers_.push_back(std::move(memory)); |
458 | 458 |
459 // Wait until all requested buffers are received. | 459 // Wait until all requested buffers are received. |
460 if (output_buffers_.size() < kOutputBufferCount) | 460 if (output_buffers_.size() < kOutputBufferCount) |
461 return; | 461 return; |
462 | 462 |
463 // Immediately provide all output buffers to the VEA. | 463 // Immediately provide all output buffers to the VEA. |
464 for (size_t i = 0; i < output_buffers_.size(); ++i) { | 464 for (size_t i = 0; i < output_buffers_.size(); ++i) { |
465 video_encode_accelerator_->UseOutputBitstreamBuffer( | 465 video_encode_accelerator_->UseOutputBitstreamBuffer( |
466 media::BitstreamBuffer(static_cast<int32_t>(i), | 466 media::BitstreamBuffer(static_cast<int32_t>(i), |
467 output_buffers_[i]->handle(), | 467 output_buffers_[i]->handle(), |
468 output_buffers_[i]->mapped_size())); | 468 output_buffers_[i]->mapped_size())); |
469 } | 469 } |
470 } | 470 } |
471 | 471 |
472 void OnReceivedInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | 472 void OnReceivedInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
473 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 473 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
474 | 474 |
475 if (memory.get()) { | 475 if (memory.get()) { |
476 input_buffers_.push_back(std::move(memory)); | 476 input_buffers_.push_back(std::move(memory)); |
477 free_input_buffer_index_.push_back(input_buffers_.size() - 1); | 477 free_input_buffer_index_.push_back(input_buffers_.size() - 1); |
478 } | 478 } |
479 allocate_input_buffer_in_progress_ = false; | 479 allocate_input_buffer_in_progress_ = false; |
480 } | 480 } |
481 | 481 |
482 // This is called when copy errors occur in encoding process when there is | 482 // This is called when copy errors occur in encoding process when there is |
483 // need to copy the VideoFrames to match the required coded size for encoder. | 483 // need to copy the VideoFrames to match the required coded size for encoder. |
484 void ExitEncodingWithErrors() { | 484 void ExitEncodingWithErrors() { |
485 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 485 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
486 | 486 |
487 std::unique_ptr<SenderEncodedFrame> no_result(nullptr); | 487 std::unique_ptr<SenderEncodedFrame> no_result(nullptr); |
488 cast_environment_->PostTask( | 488 cast_environment_->PostTask( |
489 CastEnvironment::MAIN, FROM_HERE, | 489 CastEnvironment::MAIN, FROM_HERE, |
490 base::Bind(in_progress_frame_encodes_.back().frame_encoded_callback, | 490 base::Bind(in_progress_frame_encodes_.back().frame_encoded_callback, |
491 base::Passed(&no_result))); | 491 base::Passed(&no_result))); |
492 in_progress_frame_encodes_.pop_back(); | 492 in_progress_frame_encodes_.pop_back(); |
493 } | 493 } |
494 | 494 |
495 // Parse H264 SPS, PPS, and Slice header, and return the averaged frame | 495 // Parse H264 SPS, PPS, and Slice header, and return the averaged frame |
(...skipping 415 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
911 const double kEntropyAtMaxQuantizer = 7.5; | 911 const double kEntropyAtMaxQuantizer = 7.5; |
912 const double slope = | 912 const double slope = |
913 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; | 913 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; |
914 const double quantizer = std::min<double>( | 914 const double quantizer = std::min<double>( |
915 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); | 915 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); |
916 return quantizer; | 916 return quantizer; |
917 } | 917 } |
918 | 918 |
919 } // namespace cast | 919 } // namespace cast |
920 } // namespace media | 920 } // namespace media |
OLD | NEW |