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/vp8_encoder.h" | 5 #include "media/cast/sender/vp8_encoder.h" |
6 | 6 |
7 #include "base/logging.h" | 7 #include "base/logging.h" |
8 #include "media/base/video_frame.h" | 8 #include "media/base/video_frame.h" |
9 #include "media/cast/cast_defines.h" | 9 #include "media/cast/cast_defines.h" |
| 10 #include "media/cast/net/cast_transport_config.h" |
10 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" | 11 #include "third_party/libvpx/source/libvpx/vpx/vp8cx.h" |
11 | 12 |
12 namespace media { | 13 namespace media { |
13 namespace cast { | 14 namespace cast { |
14 | 15 |
15 namespace { | 16 namespace { |
16 | 17 |
17 // After a pause in the video stream, what is the maximum duration amount to | 18 // After a pause in the video stream, what is the maximum duration amount to |
18 // pass to the encoder for the next frame (in terms of 1/max_fps sized periods)? | 19 // pass to the encoder for the next frame (in terms of 1/max_fps sized periods)? |
19 // This essentially controls the encoded size of the first frame that follows a | 20 // This essentially controls the encoded size of the first frame that follows a |
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
156 // Improve quality by enabling sets of codec features that utilize more CPU. | 157 // Improve quality by enabling sets of codec features that utilize more CPU. |
157 // The default is zero, with increasingly more CPU to be used as the value is | 158 // The default is zero, with increasingly more CPU to be used as the value is |
158 // more negative. | 159 // more negative. |
159 // TODO(miu): Document why this value was chosen and expected behaviors. | 160 // TODO(miu): Document why this value was chosen and expected behaviors. |
160 // Should this be dynamic w.r.t. hardware performance? | 161 // Should this be dynamic w.r.t. hardware performance? |
161 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, -6), VPX_CODEC_OK); | 162 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_SET_CPUUSED, -6), VPX_CODEC_OK); |
162 } | 163 } |
163 | 164 |
164 void Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, | 165 void Vp8Encoder::Encode(const scoped_refptr<media::VideoFrame>& video_frame, |
165 const base::TimeTicks& reference_time, | 166 const base::TimeTicks& reference_time, |
166 SenderEncodedFrame* encoded_frame) { | 167 EncodedFrame* encoded_frame) { |
167 DCHECK(thread_checker_.CalledOnValidThread()); | 168 DCHECK(thread_checker_.CalledOnValidThread()); |
168 DCHECK(encoded_frame); | 169 DCHECK(encoded_frame); |
169 | 170 |
170 // Note: This is used to compute the |deadline_utilization| and so it uses the | |
171 // real-world clock instead of the CastEnvironment clock, the latter of which | |
172 // might be simulated. | |
173 const base::TimeTicks start_time = base::TimeTicks::Now(); | |
174 | |
175 // Initialize on-demand. Later, if the video frame size has changed, update | 171 // Initialize on-demand. Later, if the video frame size has changed, update |
176 // the encoder configuration. | 172 // the encoder configuration. |
177 const gfx::Size frame_size = video_frame->visible_rect().size(); | 173 const gfx::Size frame_size = video_frame->visible_rect().size(); |
178 if (!is_initialized() || gfx::Size(config_.g_w, config_.g_h) != frame_size) | 174 if (!is_initialized() || gfx::Size(config_.g_w, config_.g_h) != frame_size) |
179 ConfigureForNewFrameSize(frame_size); | 175 ConfigureForNewFrameSize(frame_size); |
180 | 176 |
181 uint32 latest_frame_id_to_reference; | 177 uint32 latest_frame_id_to_reference; |
182 Vp8Buffers buffer_to_update; | 178 Vp8Buffers buffer_to_update; |
183 vpx_codec_flags_t flags = 0; | 179 vpx_codec_flags_t flags = 0; |
184 if (key_frame_requested_) { | 180 if (key_frame_requested_) { |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
276 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency); | 272 TimeDeltaToRtpDelta(video_frame->timestamp(), kVideoFrequency); |
277 encoded_frame->reference_time = reference_time; | 273 encoded_frame->reference_time = reference_time; |
278 encoded_frame->data.assign( | 274 encoded_frame->data.assign( |
279 static_cast<const uint8*>(pkt->data.frame.buf), | 275 static_cast<const uint8*>(pkt->data.frame.buf), |
280 static_cast<const uint8*>(pkt->data.frame.buf) + pkt->data.frame.sz); | 276 static_cast<const uint8*>(pkt->data.frame.buf) + pkt->data.frame.sz); |
281 break; // Done, since all data is provided in one CX_FRAME_PKT packet. | 277 break; // Done, since all data is provided in one CX_FRAME_PKT packet. |
282 } | 278 } |
283 DCHECK(!encoded_frame->data.empty()) | 279 DCHECK(!encoded_frame->data.empty()) |
284 << "BUG: Encoder must provide data since lagged encoding is disabled."; | 280 << "BUG: Encoder must provide data since lagged encoding is disabled."; |
285 | 281 |
286 // Compute deadline utilization as the real-world time elapsed divided by the | |
287 // frame duration. | |
288 const base::TimeDelta processing_time = base::TimeTicks::Now() - start_time; | |
289 encoded_frame->deadline_utilization = | |
290 processing_time.InSecondsF() / predicted_frame_duration.InSecondsF(); | |
291 | |
292 // Compute lossy utilization. The VP8 encoder took an estimated guess at what | |
293 // quantizer value would produce an encoded frame size as close to the target | |
294 // as possible. Now that the frame has been encoded and the number of bytes | |
295 // is known, the perfect quantizer value (i.e., the one that should have been | |
296 // used) can be determined. This perfect quantizer is then normalized and | |
297 // used as the lossy utilization. | |
298 const double actual_bitrate = | |
299 encoded_frame->data.size() * 8.0 / predicted_frame_duration.InSecondsF(); | |
300 const double target_bitrate = 1000.0 * config_.rc_target_bitrate; | |
301 DCHECK_GT(target_bitrate, 0.0); | |
302 const double bitrate_utilization = actual_bitrate / target_bitrate; | |
303 int quantizer = -1; | |
304 CHECK_EQ(vpx_codec_control(&encoder_, VP8E_GET_LAST_QUANTIZER_64, &quantizer), | |
305 VPX_CODEC_OK); | |
306 const double perfect_quantizer = bitrate_utilization * std::max(0, quantizer); | |
307 // Side note: If it was possible for the encoder to encode within the target | |
308 // number of bytes, the |perfect_quantizer| will be in the range [0.0,63.0]. | |
309 // If it was never possible, the value will be greater than 63.0. | |
310 encoded_frame->lossy_utilization = perfect_quantizer / 63.0; | |
311 | |
312 DVLOG(2) << "VP8 encoded frame_id " << encoded_frame->frame_id | 282 DVLOG(2) << "VP8 encoded frame_id " << encoded_frame->frame_id |
313 << ", sized: " << encoded_frame->data.size() | 283 << ", sized:" << encoded_frame->data.size(); |
314 << ", deadline_utilization: " << encoded_frame->deadline_utilization | |
315 << ", lossy_utilization: " << encoded_frame->lossy_utilization | |
316 << " (quantizer chosen by the encoder was " << quantizer << ')'; | |
317 | 284 |
318 if (encoded_frame->dependency == EncodedFrame::KEY) { | 285 if (encoded_frame->dependency == EncodedFrame::KEY) { |
319 key_frame_requested_ = false; | 286 key_frame_requested_ = false; |
320 | 287 |
321 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { | 288 for (int i = 0; i < kNumberOfVp8VideoBuffers; ++i) { |
322 buffer_state_[i].state = kBufferSent; | 289 buffer_state_[i].state = kBufferSent; |
323 buffer_state_[i].frame_id = encoded_frame->frame_id; | 290 buffer_state_[i].frame_id = encoded_frame->frame_id; |
324 } | 291 } |
325 } else { | 292 } else { |
326 if (buffer_to_update != kNoBuffer) { | 293 if (buffer_to_update != kNoBuffer) { |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
509 } | 476 } |
510 } | 477 } |
511 | 478 |
512 void Vp8Encoder::GenerateKeyFrame() { | 479 void Vp8Encoder::GenerateKeyFrame() { |
513 DCHECK(thread_checker_.CalledOnValidThread()); | 480 DCHECK(thread_checker_.CalledOnValidThread()); |
514 key_frame_requested_ = true; | 481 key_frame_requested_ = true; |
515 } | 482 } |
516 | 483 |
517 } // namespace cast | 484 } // namespace cast |
518 } // namespace media | 485 } // namespace media |
OLD | NEW |