| 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 |