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