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" |
11 #include "base/debug/crash_logging.h" | 11 #include "base/debug/crash_logging.h" |
12 #include "base/debug/dump_without_crashing.h" | 12 #include "base/debug/dump_without_crashing.h" |
13 #include "base/format_macros.h" | 13 #include "base/format_macros.h" |
14 #include "base/logging.h" | 14 #include "base/logging.h" |
15 #include "base/macros.h" | 15 #include "base/macros.h" |
16 #include "base/memory/scoped_vector.h" | |
17 #include "base/memory/shared_memory.h" | 16 #include "base/memory/shared_memory.h" |
18 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
19 #include "base/metrics/histogram.h" | 18 #include "base/metrics/histogram.h" |
20 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
21 #include "build/build_config.h" | 20 #include "build/build_config.h" |
| 21 #include "media/base/bind_to_current_loop.h" |
22 #include "media/base/video_frame.h" | 22 #include "media/base/video_frame.h" |
23 #include "media/base/video_types.h" | 23 #include "media/base/video_types.h" |
24 #include "media/base/video_util.h" | 24 #include "media/base/video_util.h" |
25 #include "media/cast/cast_config.h" | 25 #include "media/cast/cast_config.h" |
26 #include "media/cast/common/rtp_time.h" | 26 #include "media/cast/common/rtp_time.h" |
27 #include "media/cast/logging/logging_defines.h" | 27 #include "media/cast/logging/logging_defines.h" |
28 #include "media/cast/net/cast_transport_config.h" | 28 #include "media/cast/net/cast_transport_config.h" |
29 #include "media/cast/sender/vp8_quantizer_parser.h" | 29 #include "media/cast/sender/vp8_quantizer_parser.h" |
30 #include "media/filters/h264_parser.h" | 30 #include "media/filters/h264_parser.h" |
31 | 31 |
32 namespace { | 32 namespace { |
33 | 33 |
34 enum { MAX_H264_QUANTIZER = 51 }; | 34 enum { MAX_H264_QUANTIZER = 51 }; |
35 static const size_t kOutputBufferCount = 3; | 35 |
| 36 // Number of buffers for encoded bit stream. |
| 37 constexpr size_t kOutputBufferCount = 3; |
| 38 |
| 39 // Maximum number of extra input buffers for encoder. The input buffers are only |
| 40 // used when copy is needed to match the required coded size. |
| 41 constexpr size_t kExtraInputBufferCount = 2; |
36 | 42 |
37 } // namespace | 43 } // namespace |
38 | 44 |
39 namespace media { | 45 namespace media { |
40 namespace cast { | 46 namespace cast { |
41 | 47 |
42 // Container for the associated data of a video frame being processed. | 48 // Container for the associated data of a video frame being processed. |
43 struct InProgressFrameEncode { | 49 struct InProgressFrameEncode { |
44 // The source content to encode. | 50 // The source content to encode. |
45 const scoped_refptr<VideoFrame> video_frame; | 51 const scoped_refptr<VideoFrame> video_frame; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
89 max_frame_rate_(max_frame_rate), | 95 max_frame_rate_(max_frame_rate), |
90 status_change_cb_(status_change_cb), | 96 status_change_cb_(status_change_cb), |
91 create_video_encode_memory_cb_(create_video_encode_memory_cb), | 97 create_video_encode_memory_cb_(create_video_encode_memory_cb), |
92 video_encode_accelerator_(std::move(vea)), | 98 video_encode_accelerator_(std::move(vea)), |
93 encoder_active_(false), | 99 encoder_active_(false), |
94 next_frame_id_(FrameId::first()), | 100 next_frame_id_(FrameId::first()), |
95 key_frame_encountered_(false), | 101 key_frame_encountered_(false), |
96 codec_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), | 102 codec_profile_(media::VIDEO_CODEC_PROFILE_UNKNOWN), |
97 key_frame_quantizer_parsable_(false), | 103 key_frame_quantizer_parsable_(false), |
98 requested_bit_rate_(-1), | 104 requested_bit_rate_(-1), |
99 has_seen_zero_length_encoded_frame_(false) {} | 105 has_seen_zero_length_encoded_frame_(false), |
| 106 max_allowed_input_buffers_(0), |
| 107 allocate_input_buffer_in_progress_(false) {} |
100 | 108 |
101 base::SingleThreadTaskRunner* task_runner() const { | 109 base::SingleThreadTaskRunner* task_runner() const { |
102 return task_runner_.get(); | 110 return task_runner_.get(); |
103 } | 111 } |
104 | 112 |
105 void Initialize(const gfx::Size& frame_size, | 113 void Initialize(const gfx::Size& frame_size, |
106 VideoCodecProfile codec_profile, | 114 VideoCodecProfile codec_profile, |
107 int start_bit_rate, | 115 int start_bit_rate, |
108 FrameId first_frame_id) { | 116 FrameId first_frame_id) { |
109 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 117 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
(...skipping 17 matching lines...) Expand all Loading... |
127 } | 135 } |
128 | 136 |
129 void SetBitRate(int bit_rate) { | 137 void SetBitRate(int bit_rate) { |
130 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 138 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
131 | 139 |
132 requested_bit_rate_ = bit_rate; | 140 requested_bit_rate_ = bit_rate; |
133 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, | 141 video_encode_accelerator_->RequestEncodingParametersChange(bit_rate, |
134 max_frame_rate_); | 142 max_frame_rate_); |
135 } | 143 } |
136 | 144 |
| 145 // The destruction call back of the copied video frame to free its use of |
| 146 // the input buffer. |
| 147 void ReturnInputBufferToPool(int index) { |
| 148 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 149 DCHECK_GE(index, 0); |
| 150 DCHECK_LT(index, static_cast<int>(input_buffers_.size())); |
| 151 free_input_buffer_index_.push_back(index); |
| 152 } |
| 153 |
137 void EncodeVideoFrame( | 154 void EncodeVideoFrame( |
138 const scoped_refptr<media::VideoFrame>& video_frame, | 155 const scoped_refptr<media::VideoFrame>& video_frame, |
139 const base::TimeTicks& reference_time, | 156 const base::TimeTicks& reference_time, |
140 bool key_frame_requested, | 157 bool key_frame_requested, |
141 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { | 158 const VideoEncoder::FrameEncodedCallback& frame_encoded_callback) { |
142 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 159 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
143 | 160 |
144 if (!encoder_active_) | 161 if (!encoder_active_) |
145 return; | 162 return; |
146 | 163 |
147 in_progress_frame_encodes_.push_back(InProgressFrameEncode( | 164 in_progress_frame_encodes_.push_back(InProgressFrameEncode( |
148 video_frame, reference_time, frame_encoded_callback, | 165 video_frame, reference_time, frame_encoded_callback, |
149 requested_bit_rate_)); | 166 requested_bit_rate_)); |
150 | 167 |
| 168 scoped_refptr<media::VideoFrame> frame = video_frame; |
| 169 if (video_frame->coded_size() != frame_coded_size_) { |
| 170 DCHECK_GE(frame_coded_size_.width(), video_frame->visible_rect().width()); |
| 171 DCHECK_GE(frame_coded_size_.height(), |
| 172 video_frame->visible_rect().height()); |
| 173 |
| 174 if (free_input_buffer_index_.empty()) { |
| 175 if (!allocate_input_buffer_in_progress_ && |
| 176 input_buffers_.size() < max_allowed_input_buffers_) { |
| 177 allocate_input_buffer_in_progress_ = true; |
| 178 create_video_encode_memory_cb_.Run( |
| 179 media::VideoFrame::AllocationSize(media::PIXEL_FORMAT_I420, |
| 180 frame_coded_size_), |
| 181 base::Bind(&VEAClientImpl::OnCreateInputSharedMemory, this)); |
| 182 } |
| 183 ExitEncodingWithErrors(); |
| 184 return; |
| 185 } |
| 186 |
| 187 int index = free_input_buffer_index_.back(); |
| 188 base::SharedMemory* input_buffer = input_buffers_[index].get(); |
| 189 frame = VideoFrame::WrapExternalSharedMemory( |
| 190 video_frame->format(), frame_coded_size_, video_frame->visible_rect(), |
| 191 video_frame->visible_rect().size(), |
| 192 static_cast<uint8_t*>(input_buffer->memory()), |
| 193 input_buffer->mapped_size(), input_buffer->handle(), 0, |
| 194 video_frame->timestamp()); |
| 195 if (!frame || !media::I420CopyWithPadding(*video_frame, frame.get())) { |
| 196 LOG(DFATAL) << "Error: ExternalVideoEncoder: copy failed."; |
| 197 ExitEncodingWithErrors(); |
| 198 return; |
| 199 } |
| 200 |
| 201 frame->AddDestructionObserver(media::BindToCurrentLoop(base::Bind( |
| 202 &ExternalVideoEncoder::VEAClientImpl::ReturnInputBufferToPool, this, |
| 203 index))); |
| 204 free_input_buffer_index_.pop_back(); |
| 205 } |
| 206 |
151 // BitstreamBufferReady will be called once the encoder is done. | 207 // BitstreamBufferReady will be called once the encoder is done. |
152 video_encode_accelerator_->Encode(video_frame, key_frame_requested); | 208 video_encode_accelerator_->Encode(frame, key_frame_requested); |
153 } | 209 } |
154 | 210 |
155 protected: | 211 protected: |
156 void NotifyError(VideoEncodeAccelerator::Error error) final { | 212 void NotifyError(VideoEncodeAccelerator::Error error) final { |
157 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 213 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
158 | 214 |
159 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && | 215 DCHECK(error != VideoEncodeAccelerator::kInvalidArgumentError && |
160 error != VideoEncodeAccelerator::kIllegalStateError); | 216 error != VideoEncodeAccelerator::kIllegalStateError); |
161 | 217 |
162 encoder_active_ = false; | 218 encoder_active_ = false; |
163 | 219 |
164 cast_environment_->PostTask( | 220 cast_environment_->PostTask( |
165 CastEnvironment::MAIN, | 221 CastEnvironment::MAIN, |
166 FROM_HERE, | 222 FROM_HERE, |
167 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); | 223 base::Bind(status_change_cb_, STATUS_CODEC_RUNTIME_ERROR)); |
168 | 224 |
169 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so | 225 // TODO(miu): Force-flush all |in_progress_frame_encodes_| immediately so |
170 // pending frames do not become stuck, freezing VideoSender. | 226 // pending frames do not become stuck, freezing VideoSender. |
171 } | 227 } |
172 | 228 |
173 // Called to allocate the input and output buffers. | 229 // Called to allocate the input and output buffers. |
174 void RequireBitstreamBuffers(unsigned int input_count, | 230 void RequireBitstreamBuffers(unsigned int input_count, |
175 const gfx::Size& input_coded_size, | 231 const gfx::Size& input_coded_size, |
176 size_t output_buffer_size) final { | 232 size_t output_buffer_size) final { |
177 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 233 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
178 | 234 |
179 // TODO(miu): Investigate why we are ignoring |input_count| (4) and instead | 235 frame_coded_size_ = input_coded_size; |
180 // using |kOutputBufferCount| (3) here. | 236 |
| 237 max_allowed_input_buffers_ = input_count + kExtraInputBufferCount; |
| 238 |
181 for (size_t j = 0; j < kOutputBufferCount; ++j) { | 239 for (size_t j = 0; j < kOutputBufferCount; ++j) { |
182 create_video_encode_memory_cb_.Run( | 240 create_video_encode_memory_cb_.Run( |
183 output_buffer_size, | 241 output_buffer_size, |
184 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); | 242 base::Bind(&VEAClientImpl::OnCreateSharedMemory, this)); |
185 } | 243 } |
186 } | 244 } |
187 | 245 |
188 // Encoder has encoded a frame and it's available in one of the output | 246 // Encoder has encoded a frame and it's available in one of the output |
189 // buffers. Package the result in a media::cast::EncodedFrame and post it | 247 // buffers. Package the result in a media::cast::EncodedFrame and post it |
190 // to the Cast MAIN thread via the supplied callback. | 248 // to the Cast MAIN thread via the supplied callback. |
191 void BitstreamBufferReady(int32_t bitstream_buffer_id, | 249 void BitstreamBufferReady(int32_t bitstream_buffer_id, |
192 size_t payload_size, | 250 size_t payload_size, |
193 bool key_frame) final { | 251 bool key_frame) final { |
194 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 252 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
195 if (bitstream_buffer_id < 0 || | 253 if (bitstream_buffer_id < 0 || |
196 bitstream_buffer_id >= static_cast<int32_t>(output_buffers_.size())) { | 254 bitstream_buffer_id >= static_cast<int32_t>(output_buffers_.size())) { |
197 NOTREACHED(); | 255 NOTREACHED(); |
198 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" | 256 VLOG(1) << "BitstreamBufferReady(): invalid bitstream_buffer_id=" |
199 << bitstream_buffer_id; | 257 << bitstream_buffer_id; |
200 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 258 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
201 return; | 259 return; |
202 } | 260 } |
203 base::SharedMemory* output_buffer = output_buffers_[bitstream_buffer_id]; | 261 base::SharedMemory* output_buffer = |
| 262 output_buffers_[bitstream_buffer_id].get(); |
204 if (payload_size > output_buffer->mapped_size()) { | 263 if (payload_size > output_buffer->mapped_size()) { |
205 NOTREACHED(); | 264 NOTREACHED(); |
206 VLOG(1) << "BitstreamBufferReady(): invalid payload_size = " | 265 VLOG(1) << "BitstreamBufferReady(): invalid payload_size = " |
207 << payload_size; | 266 << payload_size; |
208 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); | 267 NotifyError(media::VideoEncodeAccelerator::kPlatformFailureError); |
209 return; | 268 return; |
210 } | 269 } |
211 if (key_frame) | 270 if (key_frame) |
212 key_frame_encountered_ = true; | 271 key_frame_encountered_ = true; |
213 if (!key_frame_encountered_) { | 272 if (!key_frame_encountered_) { |
(...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
361 } | 420 } |
362 | 421 |
363 // Note: This method can be called on any thread. | 422 // Note: This method can be called on any thread. |
364 void OnCreateSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | 423 void OnCreateSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
365 task_runner_->PostTask(FROM_HERE, | 424 task_runner_->PostTask(FROM_HERE, |
366 base::Bind(&VEAClientImpl::OnReceivedSharedMemory, | 425 base::Bind(&VEAClientImpl::OnReceivedSharedMemory, |
367 this, | 426 this, |
368 base::Passed(&memory))); | 427 base::Passed(&memory))); |
369 } | 428 } |
370 | 429 |
| 430 void OnCreateInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
| 431 task_runner_->PostTask( |
| 432 FROM_HERE, base::Bind(&VEAClientImpl::OnReceivedInputSharedMemory, this, |
| 433 base::Passed(&memory))); |
| 434 } |
| 435 |
371 void OnReceivedSharedMemory(std::unique_ptr<base::SharedMemory> memory) { | 436 void OnReceivedSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
372 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 437 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
373 | 438 |
374 output_buffers_.push_back(std::move(memory)); | 439 output_buffers_.push_back(std::move(memory)); |
375 | 440 |
376 // Wait until all requested buffers are received. | 441 // Wait until all requested buffers are received. |
377 if (output_buffers_.size() < kOutputBufferCount) | 442 if (output_buffers_.size() < kOutputBufferCount) |
378 return; | 443 return; |
379 | 444 |
380 // Immediately provide all output buffers to the VEA. | 445 // Immediately provide all output buffers to the VEA. |
381 for (size_t i = 0; i < output_buffers_.size(); ++i) { | 446 for (size_t i = 0; i < output_buffers_.size(); ++i) { |
382 video_encode_accelerator_->UseOutputBitstreamBuffer( | 447 video_encode_accelerator_->UseOutputBitstreamBuffer( |
383 media::BitstreamBuffer(static_cast<int32_t>(i), | 448 media::BitstreamBuffer(static_cast<int32_t>(i), |
384 output_buffers_[i]->handle(), | 449 output_buffers_[i]->handle(), |
385 output_buffers_[i]->mapped_size())); | 450 output_buffers_[i]->mapped_size())); |
386 } | 451 } |
387 } | 452 } |
388 | 453 |
| 454 void OnReceivedInputSharedMemory(std::unique_ptr<base::SharedMemory> memory) { |
| 455 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 456 |
| 457 if (memory.get()) { |
| 458 input_buffers_.push_back(std::move(memory)); |
| 459 free_input_buffer_index_.push_back(input_buffers_.size() - 1); |
| 460 } |
| 461 allocate_input_buffer_in_progress_ = false; |
| 462 } |
| 463 |
| 464 // This is called when copy errors occur in encoding process when there is |
| 465 // need to copy the VideoFrames to match the required coded size for encoder. |
| 466 void ExitEncodingWithErrors() { |
| 467 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 468 |
| 469 std::unique_ptr<SenderEncodedFrame> no_result(nullptr); |
| 470 cast_environment_->PostTask( |
| 471 CastEnvironment::MAIN, FROM_HERE, |
| 472 base::Bind(in_progress_frame_encodes_.back().frame_encoded_callback, |
| 473 base::Passed(&no_result))); |
| 474 in_progress_frame_encodes_.pop_back(); |
| 475 } |
| 476 |
389 // Parse H264 SPS, PPS, and Slice header, and return the averaged frame | 477 // Parse H264 SPS, PPS, and Slice header, and return the averaged frame |
390 // quantizer in the range of [0, 51], or -1 on parse error. | 478 // quantizer in the range of [0, 51], or -1 on parse error. |
391 double GetH264FrameQuantizer(const uint8_t* encoded_data, off_t size) { | 479 double GetH264FrameQuantizer(const uint8_t* encoded_data, off_t size) { |
392 DCHECK(encoded_data); | 480 DCHECK(encoded_data); |
393 if (!size) | 481 if (!size) |
394 return -1; | 482 return -1; |
395 h264_parser_.SetStream(encoded_data, size); | 483 h264_parser_.SetStream(encoded_data, size); |
396 double total_quantizer = 0; | 484 double total_quantizer = 0; |
397 int num_slices = 0; | 485 int num_slices = 0; |
398 | 486 |
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
453 std::unique_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; | 541 std::unique_ptr<media::VideoEncodeAccelerator> video_encode_accelerator_; |
454 bool encoder_active_; | 542 bool encoder_active_; |
455 FrameId next_frame_id_; | 543 FrameId next_frame_id_; |
456 bool key_frame_encountered_; | 544 bool key_frame_encountered_; |
457 std::string stream_header_; | 545 std::string stream_header_; |
458 VideoCodecProfile codec_profile_; | 546 VideoCodecProfile codec_profile_; |
459 bool key_frame_quantizer_parsable_; | 547 bool key_frame_quantizer_parsable_; |
460 H264Parser h264_parser_; | 548 H264Parser h264_parser_; |
461 | 549 |
462 // Shared memory buffers for output with the VideoAccelerator. | 550 // Shared memory buffers for output with the VideoAccelerator. |
463 ScopedVector<base::SharedMemory> output_buffers_; | 551 std::vector<std::unique_ptr<base::SharedMemory>> output_buffers_; |
| 552 |
| 553 // Shared memory buffers for input video frames with the VideoAccelerator. |
| 554 // These buffers will be allocated only when copy is needed to match the |
| 555 // required coded size for encoder. They are allocated on-demand, up to |
| 556 // |max_allowed_input_buffers_|. |
| 557 std::vector<std::unique_ptr<base::SharedMemory>> input_buffers_; |
| 558 |
| 559 // Available input buffer index. These buffers are used in FILO order. |
| 560 std::vector<int> free_input_buffer_index_; |
464 | 561 |
465 // FIFO list. | 562 // FIFO list. |
466 std::list<InProgressFrameEncode> in_progress_frame_encodes_; | 563 std::list<InProgressFrameEncode> in_progress_frame_encodes_; |
467 | 564 |
468 // The requested encode bit rate for the next frame. | 565 // The requested encode bit rate for the next frame. |
469 int requested_bit_rate_; | 566 int requested_bit_rate_; |
470 | 567 |
471 // Used to compute utilization metrics for each frame. | 568 // Used to compute utilization metrics for each frame. |
472 QuantizerEstimator quantizer_estimator_; | 569 QuantizerEstimator quantizer_estimator_; |
473 | 570 |
474 // Set to true once a frame with zero-length encoded data has been | 571 // Set to true once a frame with zero-length encoded data has been |
475 // encountered. | 572 // encountered. |
476 // TODO(miu): Remove after discovering cause. http://crbug.com/519022 | 573 // TODO(miu): Remove after discovering cause. http://crbug.com/519022 |
477 bool has_seen_zero_length_encoded_frame_; | 574 bool has_seen_zero_length_encoded_frame_; |
478 | 575 |
| 576 // The coded size of the video frame required by Encoder. This size is |
| 577 // obtained from VEA through |RequireBitstreamBuffers()|. |
| 578 gfx::Size frame_coded_size_; |
| 579 |
| 580 // The maximum number of input buffers. These buffers are used to copy |
| 581 // VideoFrames in order to match the required coded size for encoder. |
| 582 size_t max_allowed_input_buffers_; |
| 583 |
| 584 // Set to true when the allocation of an input buffer is in progress, and |
| 585 // reset to false after the allocated buffer is received. |
| 586 bool allocate_input_buffer_in_progress_; |
| 587 |
479 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); | 588 DISALLOW_COPY_AND_ASSIGN(VEAClientImpl); |
480 }; | 589 }; |
481 | 590 |
482 // static | 591 // static |
483 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { | 592 bool ExternalVideoEncoder::IsSupported(const VideoSenderConfig& video_config) { |
484 if (video_config.codec != CODEC_VIDEO_VP8 && | 593 if (video_config.codec != CODEC_VIDEO_VP8 && |
485 video_config.codec != CODEC_VIDEO_H264) | 594 video_config.codec != CODEC_VIDEO_H264) |
486 return false; | 595 return false; |
487 | 596 |
488 // TODO(miu): "Layering hooks" are needed to be able to query outside of | 597 // TODO(miu): "Layering hooks" are needed to be able to query outside of |
(...skipping 295 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
784 const double kEntropyAtMaxQuantizer = 7.5; | 893 const double kEntropyAtMaxQuantizer = 7.5; |
785 const double slope = | 894 const double slope = |
786 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; | 895 (MAX_VP8_QUANTIZER - MIN_VP8_QUANTIZER) / kEntropyAtMaxQuantizer; |
787 const double quantizer = std::min<double>( | 896 const double quantizer = std::min<double>( |
788 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); | 897 MAX_VP8_QUANTIZER, MIN_VP8_QUANTIZER + slope * shannon_entropy); |
789 return quantizer; | 898 return quantizer; |
790 } | 899 } |
791 | 900 |
792 } // namespace cast | 901 } // namespace cast |
793 } // namespace media | 902 } // namespace media |
OLD | NEW |