Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /* | 1 /* |
| 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. | 2 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
| 5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
| 6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
| 7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
| 8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
| 9 */ | 9 */ |
| 10 | 10 |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 31 #include "webrtc/video/overuse_frame_detector.h" | 31 #include "webrtc/video/overuse_frame_detector.h" |
| 32 #include "webrtc/video/payload_router.h" | 32 #include "webrtc/video/payload_router.h" |
| 33 #include "webrtc/video/send_statistics_proxy.h" | 33 #include "webrtc/video/send_statistics_proxy.h" |
| 34 #include "webrtc/video_frame.h" | 34 #include "webrtc/video_frame.h" |
| 35 | 35 |
| 36 namespace webrtc { | 36 namespace webrtc { |
| 37 | 37 |
| 38 static const float kStopPaddingThresholdMs = 2000; | 38 static const float kStopPaddingThresholdMs = 2000; |
| 39 static const int kMinKeyFrameRequestIntervalMs = 300; | 39 static const int kMinKeyFrameRequestIntervalMs = 300; |
| 40 | 40 |
| 41 std::vector<uint32_t> AllocateStreamBitrates( | |
| 42 uint32_t total_bitrate, | |
| 43 const SimulcastStream* stream_configs, | |
| 44 size_t number_of_streams) { | |
| 45 if (number_of_streams == 0) { | |
| 46 std::vector<uint32_t> stream_bitrates(1, 0); | |
| 47 stream_bitrates[0] = total_bitrate; | |
| 48 return stream_bitrates; | |
| 49 } | |
| 50 std::vector<uint32_t> stream_bitrates(number_of_streams, 0); | |
| 51 uint32_t bitrate_remainder = total_bitrate; | |
| 52 for (size_t i = 0; i < stream_bitrates.size() && bitrate_remainder > 0; ++i) { | |
| 53 if (stream_configs[i].maxBitrate * 1000 > bitrate_remainder) { | |
| 54 stream_bitrates[i] = bitrate_remainder; | |
| 55 } else { | |
| 56 stream_bitrates[i] = stream_configs[i].maxBitrate * 1000; | |
| 57 } | |
| 58 bitrate_remainder -= stream_bitrates[i]; | |
| 59 } | |
| 60 return stream_bitrates; | |
| 61 } | |
| 62 | |
| 63 class QMVideoSettingsCallback : public VCMQMSettingsCallback { | 41 class QMVideoSettingsCallback : public VCMQMSettingsCallback { |
| 64 public: | 42 public: |
| 65 explicit QMVideoSettingsCallback(VideoProcessing* vpm); | 43 explicit QMVideoSettingsCallback(VideoProcessing* vpm); |
| 66 | 44 |
| 67 ~QMVideoSettingsCallback(); | 45 ~QMVideoSettingsCallback(); |
| 68 | 46 |
| 69 // Update VPM with QM (quality modes: frame size & frame rate) settings. | 47 // Update VPM with QM (quality modes: frame size & frame rate) settings. |
| 70 int32_t SetVideoQMSettings(const uint32_t frame_rate, | 48 int32_t SetVideoQMSettings(const uint32_t frame_rate, |
| 71 const uint32_t width, | 49 const uint32_t width, |
| 72 const uint32_t height); | 50 const uint32_t height); |
| 73 | 51 |
| 74 // Update target frame rate. | 52 // Update target frame rate. |
| 75 void SetTargetFramerate(int frame_rate); | 53 void SetTargetFramerate(int frame_rate); |
| 76 | 54 |
| 77 private: | 55 private: |
| 78 VideoProcessing* vp_; | 56 VideoProcessing* vp_; |
| 79 }; | 57 }; |
| 80 | 58 |
| 81 ViEEncoder::ViEEncoder(uint32_t number_of_cores, | 59 ViEEncoder::ViEEncoder(uint32_t number_of_cores, |
| 82 const std::vector<uint32_t>& ssrcs, | 60 const std::vector<uint32_t>& ssrcs, |
| 83 ProcessThread* module_process_thread, | 61 ProcessThread* module_process_thread, |
| 84 SendStatisticsProxy* stats_proxy, | 62 SendStatisticsProxy* stats_proxy, |
| 85 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, | 63 rtc::VideoSinkInterface<VideoFrame>* pre_encode_callback, |
| 86 OveruseFrameDetector* overuse_detector, | 64 OveruseFrameDetector* overuse_detector, |
| 87 PacedSender* pacer, | 65 PacedSender* pacer) |
| 88 PayloadRouter* payload_router, | |
| 89 EncodedImageCallback* post_encode_callback) | |
| 90 : number_of_cores_(number_of_cores), | 66 : number_of_cores_(number_of_cores), |
| 91 ssrcs_(ssrcs), | 67 ssrcs_(ssrcs), |
| 92 vp_(VideoProcessing::Create()), | 68 vp_(VideoProcessing::Create()), |
| 93 qm_callback_(new QMVideoSettingsCallback(vp_.get())), | 69 qm_callback_(new QMVideoSettingsCallback(vp_.get())), |
| 94 vcm_(VideoCodingModule::Create(Clock::GetRealTimeClock(), | 70 vcm_(VideoCodingModule::Create(Clock::GetRealTimeClock(), |
| 95 this, | 71 this, |
| 96 qm_callback_.get())), | 72 qm_callback_.get())), |
| 97 stats_proxy_(stats_proxy), | 73 stats_proxy_(stats_proxy), |
| 98 pre_encode_callback_(pre_encode_callback), | 74 pre_encode_callback_(pre_encode_callback), |
| 99 overuse_detector_(overuse_detector), | 75 overuse_detector_(overuse_detector), |
| 100 pacer_(pacer), | 76 pacer_(pacer), |
| 101 send_payload_router_(payload_router), | |
| 102 post_encode_callback_(post_encode_callback), | |
| 103 time_of_last_frame_activity_ms_(0), | 77 time_of_last_frame_activity_ms_(0), |
| 104 encoder_config_(), | 78 encoder_config_(), |
| 105 min_transmit_bitrate_bps_(0), | 79 min_transmit_bitrate_bps_(0), |
| 106 last_observed_bitrate_bps_(0), | 80 last_observed_bitrate_bps_(0), |
| 107 network_is_transmitting_(true), | 81 network_is_transmitting_(true), |
| 108 encoder_paused_(false), | 82 encoder_paused_(true), |
| 109 encoder_paused_and_dropped_frame_(false), | 83 encoder_paused_and_dropped_frame_(false), |
| 110 time_last_intra_request_ms_(ssrcs.size(), -1), | 84 time_last_intra_request_ms_(ssrcs.size(), -1), |
| 111 module_process_thread_(module_process_thread), | 85 module_process_thread_(module_process_thread), |
| 112 has_received_sli_(false), | 86 has_received_sli_(false), |
| 113 picture_id_sli_(0), | 87 picture_id_sli_(0), |
| 114 has_received_rpsi_(false), | 88 has_received_rpsi_(false), |
| 115 picture_id_rpsi_(0), | 89 picture_id_rpsi_(0), |
| 116 video_suspended_(false) { | 90 video_suspended_(false) { |
| 117 module_process_thread_->RegisterModule(vcm_.get()); | 91 module_process_thread_->RegisterModule(vcm_.get()); |
| 118 } | 92 } |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 149 rtc::CritScope lock(&data_cs_); | 123 rtc::CritScope lock(&data_cs_); |
| 150 network_is_transmitting_ = is_transmitting; | 124 network_is_transmitting_ = is_transmitting; |
| 151 } | 125 } |
| 152 } | 126 } |
| 153 | 127 |
| 154 void ViEEncoder::Pause() { | 128 void ViEEncoder::Pause() { |
| 155 rtc::CritScope lock(&data_cs_); | 129 rtc::CritScope lock(&data_cs_); |
| 156 encoder_paused_ = true; | 130 encoder_paused_ = true; |
| 157 } | 131 } |
| 158 | 132 |
| 159 void ViEEncoder::Restart() { | 133 void ViEEncoder::Start() { |
| 160 rtc::CritScope lock(&data_cs_); | 134 rtc::CritScope lock(&data_cs_); |
| 161 encoder_paused_ = false; | 135 encoder_paused_ = false; |
| 162 } | 136 } |
| 163 | 137 |
| 164 int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder, | 138 int32_t ViEEncoder::RegisterExternalEncoder(webrtc::VideoEncoder* encoder, |
| 165 uint8_t pl_type, | 139 uint8_t pl_type, |
| 166 bool internal_source) { | 140 bool internal_source) { |
| 167 if (vcm_->RegisterExternalEncoder(encoder, pl_type, internal_source) != | 141 if (vcm_->RegisterExternalEncoder(encoder, pl_type, internal_source) != |
| 168 VCM_OK) { | 142 VCM_OK) { |
| 169 return -1; | 143 return -1; |
| 170 } | 144 } |
| 171 return 0; | 145 return 0; |
| 172 } | 146 } |
| 173 | 147 |
| 174 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { | 148 int32_t ViEEncoder::DeRegisterExternalEncoder(uint8_t pl_type) { |
| 175 if (vcm_->RegisterExternalEncoder(nullptr, pl_type) != VCM_OK) { | 149 if (vcm_->RegisterExternalEncoder(nullptr, pl_type) != VCM_OK) { |
| 176 return -1; | 150 return -1; |
| 177 } | 151 } |
| 178 return 0; | 152 return 0; |
| 179 } | 153 } |
| 180 void ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec, | 154 void ViEEncoder::SetEncoder(const webrtc::VideoCodec& video_codec, |
| 181 int min_transmit_bitrate_bps) { | 155 int min_transmit_bitrate_bps, |
| 182 RTC_DCHECK(send_payload_router_); | 156 size_t max_data_payload_length, |
| 157 EncodedImageCallback* sink) { | |
| 183 // Setting target width and height for VPM. | 158 // Setting target width and height for VPM. |
| 184 RTC_CHECK_EQ(VPM_OK, | 159 RTC_CHECK_EQ(VPM_OK, |
| 185 vp_->SetTargetResolution(video_codec.width, video_codec.height, | 160 vp_->SetTargetResolution(video_codec.width, video_codec.height, |
| 186 video_codec.maxFramerate)); | 161 video_codec.maxFramerate)); |
| 187 | 162 |
| 188 // Cache codec before calling AddBitrateObserver (which calls OnBitrateUpdated | 163 // Cache codec before calling AddBitrateObserver (which calls OnBitrateUpdated |
| 189 // that makes use of the number of simulcast streams configured). | 164 // that makes use of the number of simulcast streams configured). |
| 190 { | 165 { |
| 191 rtc::CritScope lock(&data_cs_); | 166 rtc::CritScope lock(&data_cs_); |
| 192 encoder_config_ = video_codec; | 167 encoder_config_ = video_codec; |
| 193 encoder_paused_ = true; | |
| 194 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps; | 168 min_transmit_bitrate_bps_ = min_transmit_bitrate_bps; |
| 195 } | 169 } |
| 170 { | |
| 171 rtc::CritScope lock(&sink_cs_); | |
| 172 sink_ = sink; | |
| 173 } | |
| 196 | 174 |
| 197 size_t max_data_payload_length = send_payload_router_->MaxPayloadLength(); | |
| 198 bool success = vcm_->RegisterSendCodec( | 175 bool success = vcm_->RegisterSendCodec( |
| 199 &video_codec, number_of_cores_, | 176 &video_codec, number_of_cores_, |
| 200 static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; | 177 static_cast<uint32_t>(max_data_payload_length)) == VCM_OK; |
| 201 if (!success) { | 178 if (!success) { |
| 202 LOG(LS_ERROR) << "Failed to configure encoder."; | 179 LOG(LS_ERROR) << "Failed to configure encoder."; |
| 203 RTC_DCHECK(success); | 180 RTC_DCHECK(success); |
| 204 } | 181 } |
| 205 | 182 |
| 206 send_payload_router_->SetSendingRtpModules( | |
| 207 video_codec.numberOfSimulcastStreams); | |
| 208 | |
| 209 // Restart the media flow | |
| 210 Restart(); | |
| 211 if (stats_proxy_) { | 183 if (stats_proxy_) { |
| 212 // Clear stats for disabled layers. | 184 // Clear stats for disabled layers. |
| 213 for (size_t i = video_codec.numberOfSimulcastStreams; i < ssrcs_.size(); | 185 for (size_t i = video_codec.numberOfSimulcastStreams; i < ssrcs_.size(); |
| 214 ++i) { | 186 ++i) { |
| 215 stats_proxy_->OnInactiveSsrc(ssrcs_[i]); | 187 stats_proxy_->OnInactiveSsrc(ssrcs_[i]); |
| 216 } | 188 } |
| 217 VideoEncoderConfig::ContentType content_type = | 189 VideoEncoderConfig::ContentType content_type = |
| 218 VideoEncoderConfig::ContentType::kRealtimeVideo; | 190 VideoEncoderConfig::ContentType::kRealtimeVideo; |
| 219 switch (video_codec.mode) { | 191 switch (video_codec.mode) { |
| 220 case kRealtimeVideo: | 192 case kRealtimeVideo: |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 312 | 284 |
| 313 void ViEEncoder::TraceFrameDropEnd() { | 285 void ViEEncoder::TraceFrameDropEnd() { |
| 314 // End trace event on first frame after encoder resumes, if frame was dropped. | 286 // End trace event on first frame after encoder resumes, if frame was dropped. |
| 315 if (encoder_paused_and_dropped_frame_) { | 287 if (encoder_paused_and_dropped_frame_) { |
| 316 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); | 288 TRACE_EVENT_ASYNC_END0("webrtc", "EncoderPaused", this); |
| 317 } | 289 } |
| 318 encoder_paused_and_dropped_frame_ = false; | 290 encoder_paused_and_dropped_frame_ = false; |
| 319 } | 291 } |
| 320 | 292 |
| 321 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame) { | 293 void ViEEncoder::EncodeVideoFrame(const VideoFrame& video_frame) { |
| 322 if (!send_payload_router_->active()) { | |
| 323 // We've paused or we have no channels attached, don't waste resources on | |
| 324 // encoding. | |
| 325 return; | |
| 326 } | |
| 327 VideoCodecType codec_type; | 294 VideoCodecType codec_type; |
| 328 { | 295 { |
| 329 rtc::CritScope lock(&data_cs_); | 296 rtc::CritScope lock(&data_cs_); |
| 330 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); | 297 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); |
| 331 if (EncoderPaused()) { | 298 if (EncoderPaused()) { |
| 332 TraceFrameDropStart(); | 299 TraceFrameDropStart(); |
| 333 return; | 300 return; |
| 334 } | 301 } |
| 335 TraceFrameDropEnd(); | 302 TraceFrameDropEnd(); |
| 336 codec_type = encoder_config_.codecType; | 303 codec_type = encoder_config_.codecType; |
| (...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 410 } | 377 } |
| 411 | 378 |
| 412 void ViEEncoder::OnEncoderImplementationName(const char* implementation_name) { | 379 void ViEEncoder::OnEncoderImplementationName(const char* implementation_name) { |
| 413 if (stats_proxy_) | 380 if (stats_proxy_) |
| 414 stats_proxy_->OnEncoderImplementationName(implementation_name); | 381 stats_proxy_->OnEncoderImplementationName(implementation_name); |
| 415 } | 382 } |
| 416 | 383 |
| 417 int32_t ViEEncoder::Encoded(const EncodedImage& encoded_image, | 384 int32_t ViEEncoder::Encoded(const EncodedImage& encoded_image, |
| 418 const CodecSpecificInfo* codec_specific_info, | 385 const CodecSpecificInfo* codec_specific_info, |
| 419 const RTPFragmentationHeader* fragmentation) { | 386 const RTPFragmentationHeader* fragmentation) { |
| 420 RTC_DCHECK(send_payload_router_); | |
| 421 | |
| 422 { | 387 { |
| 423 rtc::CritScope lock(&data_cs_); | 388 rtc::CritScope lock(&data_cs_); |
| 424 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); | 389 time_of_last_frame_activity_ms_ = TickTime::MillisecondTimestamp(); |
| 425 } | 390 } |
| 426 | |
| 427 if (post_encode_callback_) { | |
| 428 post_encode_callback_->Encoded(encoded_image, codec_specific_info, | |
| 429 fragmentation); | |
| 430 } | |
| 431 | |
| 432 if (stats_proxy_) { | 391 if (stats_proxy_) { |
| 433 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); | 392 stats_proxy_->OnSendEncodedImage(encoded_image, codec_specific_info); |
| 434 } | 393 } |
| 435 int success = send_payload_router_->Encoded( | 394 |
| 436 encoded_image, codec_specific_info, fragmentation); | 395 int success = 0; |
| 396 { | |
| 397 rtc::CritScope lock(&sink_cs_); | |
| 398 sink_->Encoded(encoded_image, codec_specific_info, fragmentation); | |
|
sprang_webrtc
2016/04/22 11:38:20
succeess = sink_->Encoded() ?
Or remove success if
perkj_webrtc
2016/04/27 08:00:57
oops. I think it one day should be removed.
| |
| 399 } | |
| 400 | |
| 437 overuse_detector_->FrameSent(encoded_image._timeStamp); | 401 overuse_detector_->FrameSent(encoded_image._timeStamp); |
| 438 | |
| 439 if (kEnableFrameRecording) { | 402 if (kEnableFrameRecording) { |
| 440 int layer = codec_specific_info->codecType == kVideoCodecVP8 | 403 int layer = codec_specific_info->codecType == kVideoCodecVP8 |
| 441 ? codec_specific_info->codecSpecific.VP8.simulcastIdx | 404 ? codec_specific_info->codecSpecific.VP8.simulcastIdx |
| 442 : 0; | 405 : 0; |
| 443 IvfFileWriter* file_writer; | 406 IvfFileWriter* file_writer; |
| 444 { | 407 { |
| 445 rtc::CritScope lock(&data_cs_); | 408 rtc::CritScope lock(&data_cs_); |
| 446 if (file_writers_[layer] == nullptr) { | 409 if (file_writers_[layer] == nullptr) { |
| 447 std::ostringstream oss; | 410 std::ostringstream oss; |
| 448 oss << "send_bitstream_ssrc"; | 411 oss << "send_bitstream_ssrc"; |
| (...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 505 } | 468 } |
| 506 RTC_NOTREACHED() << "Should not receive keyframe requests on unknown SSRCs."; | 469 RTC_NOTREACHED() << "Should not receive keyframe requests on unknown SSRCs."; |
| 507 } | 470 } |
| 508 | 471 |
| 509 void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps, | 472 void ViEEncoder::OnBitrateUpdated(uint32_t bitrate_bps, |
| 510 uint8_t fraction_lost, | 473 uint8_t fraction_lost, |
| 511 int64_t round_trip_time_ms) { | 474 int64_t round_trip_time_ms) { |
| 512 LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate" << bitrate_bps | 475 LOG(LS_VERBOSE) << "OnBitrateUpdated, bitrate" << bitrate_bps |
| 513 << " packet loss " << static_cast<int>(fraction_lost) | 476 << " packet loss " << static_cast<int>(fraction_lost) |
| 514 << " rtt " << round_trip_time_ms; | 477 << " rtt " << round_trip_time_ms; |
| 515 RTC_DCHECK(send_payload_router_); | |
| 516 vcm_->SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms); | 478 vcm_->SetChannelParameters(bitrate_bps, fraction_lost, round_trip_time_ms); |
| 517 bool video_is_suspended = vcm_->VideoSuspended(); | 479 bool video_is_suspended = vcm_->VideoSuspended(); |
| 518 bool video_suspension_changed; | 480 bool video_suspension_changed; |
| 519 VideoCodec send_codec; | |
| 520 { | 481 { |
| 521 rtc::CritScope lock(&data_cs_); | 482 rtc::CritScope lock(&data_cs_); |
| 522 last_observed_bitrate_bps_ = bitrate_bps; | 483 last_observed_bitrate_bps_ = bitrate_bps; |
| 523 video_suspension_changed = video_suspended_ != video_is_suspended; | 484 video_suspension_changed = video_suspended_ != video_is_suspended; |
| 524 video_suspended_ = video_is_suspended; | 485 video_suspended_ = video_is_suspended; |
| 525 send_codec = encoder_config_; | |
| 526 } | 486 } |
| 527 | 487 |
| 528 SimulcastStream* stream_configs = send_codec.simulcastStream; | |
| 529 // Allocate the bandwidth between the streams. | |
| 530 std::vector<uint32_t> stream_bitrates = AllocateStreamBitrates( | |
| 531 bitrate_bps, stream_configs, send_codec.numberOfSimulcastStreams); | |
| 532 send_payload_router_->SetTargetSendBitrates(stream_bitrates); | |
| 533 | |
| 534 if (!video_suspension_changed) | 488 if (!video_suspension_changed) |
| 535 return; | 489 return; |
| 536 // Video suspend-state changed, inform codec observer. | 490 // Video suspend-state changed, inform codec observer. |
| 537 LOG(LS_INFO) << "Video suspend state changed " << video_is_suspended | 491 LOG(LS_INFO) << "Video suspend state changed " << video_is_suspended |
| 538 << " for ssrc " << ssrcs_[0]; | 492 << " for ssrc " << ssrcs_[0]; |
| 539 if (stats_proxy_) | 493 if (stats_proxy_) |
| 540 stats_proxy_->OnSuspendChange(video_is_suspended); | 494 stats_proxy_->OnSuspendChange(video_is_suspended); |
| 541 } | 495 } |
| 542 | 496 |
| 543 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessing* vpm) | 497 QMVideoSettingsCallback::QMVideoSettingsCallback(VideoProcessing* vpm) |
| 544 : vp_(vpm) { | 498 : vp_(vpm) { |
| 545 } | 499 } |
| 546 | 500 |
| 547 QMVideoSettingsCallback::~QMVideoSettingsCallback() { | 501 QMVideoSettingsCallback::~QMVideoSettingsCallback() { |
| 548 } | 502 } |
| 549 | 503 |
| 550 int32_t QMVideoSettingsCallback::SetVideoQMSettings( | 504 int32_t QMVideoSettingsCallback::SetVideoQMSettings( |
| 551 const uint32_t frame_rate, | 505 const uint32_t frame_rate, |
| 552 const uint32_t width, | 506 const uint32_t width, |
| 553 const uint32_t height) { | 507 const uint32_t height) { |
| 554 return vp_->SetTargetResolution(width, height, frame_rate); | 508 return vp_->SetTargetResolution(width, height, frame_rate); |
| 555 } | 509 } |
| 556 | 510 |
| 557 void QMVideoSettingsCallback::SetTargetFramerate(int frame_rate) { | 511 void QMVideoSettingsCallback::SetTargetFramerate(int frame_rate) { |
| 558 vp_->SetTargetFramerate(frame_rate); | 512 vp_->SetTargetFramerate(frame_rate); |
| 559 } | 513 } |
| 560 | 514 |
| 561 } // namespace webrtc | 515 } // namespace webrtc |
| OLD | NEW |