Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(725)

Unified Diff: webrtc/modules/video_coding/generic_encoder.cc

Issue 2911193002: Implement timing frames. (Closed)
Patch Set: Implement Holmer@ comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/modules/video_coding/generic_encoder.cc
diff --git a/webrtc/modules/video_coding/generic_encoder.cc b/webrtc/modules/video_coding/generic_encoder.cc
index 50731c050aeec4548af668ea974191c516d47674..5faa193f9fa0acae393d5e7c3c02bb3ba8b796b8 100644
--- a/webrtc/modules/video_coding/generic_encoder.cc
+++ b/webrtc/modules/video_coding/generic_encoder.cc
@@ -15,6 +15,7 @@
#include "webrtc/api/video/i420_buffer.h"
#include "webrtc/base/checks.h"
#include "webrtc/base/logging.h"
+#include "webrtc/base/timeutils.h"
#include "webrtc/base/trace_event.h"
#include "webrtc/modules/video_coding/encoded_frame.h"
#include "webrtc/modules/video_coding/media_optimization.h"
@@ -29,7 +30,8 @@ VCMGenericEncoder::VCMGenericEncoder(
vcm_encoded_frame_callback_(encoded_frame_callback),
internal_source_(internal_source),
encoder_params_({BitrateAllocation(), 0, 0, 0}),
- is_screenshare_(false) {}
+ is_screenshare_(false),
+ streams_or_svc_num_(0) {}
VCMGenericEncoder::~VCMGenericEncoder() {}
@@ -45,6 +47,17 @@ int32_t VCMGenericEncoder::InitEncode(const VideoCodec* settings,
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
TRACE_EVENT0("webrtc", "VCMGenericEncoder::InitEncode");
is_screenshare_ = settings->mode == VideoCodecMode::kScreensharing;
+ streams_or_svc_num_ = settings->numberOfSimulcastStreams;
+ if (settings->codecType == kVideoCodecVP9) {
+ streams_or_svc_num_ = settings->VP9().numberOfSpatialLayers;
+ }
+ if (streams_or_svc_num_ == 0)
+ streams_or_svc_num_ = 1;
+
+ vcm_encoded_frame_callback_->SetTimingFramesThresholds(
+ settings->timing_frame_thresholds);
+ vcm_encoded_frame_callback_->OnFrameRateChanged(settings->maxFramerate);
+
if (encoder_->InitEncode(settings, number_of_cores, max_payload_size) != 0) {
LOG(LS_ERROR) << "Failed to initialize the encoder associated with "
"payload name: "
@@ -65,6 +78,8 @@ int32_t VCMGenericEncoder::Encode(const VideoFrame& frame,
for (FrameType frame_type : frame_types)
RTC_DCHECK(frame_type == kVideoFrameKey || frame_type == kVideoFrameDelta);
+ for (size_t i = 0; i < streams_or_svc_num_; ++i)
+ vcm_encoded_frame_callback_->OnEncodeStarted(frame.render_time_ms(), i);
int32_t result = encoder_->Encode(frame, codec_specific, &frame_types);
if (is_screenshare_ &&
@@ -107,6 +122,17 @@ void VCMGenericEncoder::SetEncoderParameters(const EncoderParameters& params) {
<< ", framerate = " << params.input_frame_rate
<< "): " << res;
}
+ vcm_encoded_frame_callback_->OnFrameRateChanged(params.input_frame_rate);
+ for (size_t i = 0; i < streams_or_svc_num_; ++i) {
+ size_t layer_bitrate_bytes_per_sec =
+ params.target_bitrate.GetSpatialLayerSum(i) / 8;
+ // VP9 rate control is not yet moved out of VP9Impl. Due to that rates
+ // are not split among spatial layers.
+ if (layer_bitrate_bytes_per_sec == 0)
+ layer_bitrate_bytes_per_sec = params.target_bitrate.get_sum_bps() / 8;
+ vcm_encoded_frame_callback_->OnTargetBitrateChanged(
+ layer_bitrate_bytes_per_sec, i);
+ }
}
}
@@ -124,6 +150,8 @@ int32_t VCMGenericEncoder::RequestFrame(
const std::vector<FrameType>& frame_types) {
RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
+ for (size_t i = 0; i < streams_or_svc_num_; ++i)
+ vcm_encoded_frame_callback_->OnEncodeStarted(0, i);
// TODO(nisse): Used only with internal source. Delete as soon as
// that feature is removed. The only implementation I've been able
// to find ignores what's in the frame. With one exception: It seems
@@ -151,16 +179,102 @@ VCMEncodedFrameCallback::VCMEncodedFrameCallback(
media_optimization::MediaOptimization* media_opt)
: internal_source_(false),
post_encode_callback_(post_encode_callback),
- media_opt_(media_opt) {}
+ media_opt_(media_opt),
+ framerate_(1),
+ last_timing_frame_time_ms_(-1),
+ timing_frames_thresholds_({-1, 0}) {}
VCMEncodedFrameCallback::~VCMEncodedFrameCallback() {}
+void VCMEncodedFrameCallback::OnTargetBitrateChanged(
+ size_t bitrate_bytes_per_second,
+ size_t simulcast_svc_idx) {
+ rtc::CritScope crit(&timing_params_lock_);
+ if (timing_frames_info_.size() < simulcast_svc_idx + 1)
+ timing_frames_info_.resize(simulcast_svc_idx + 1);
+ timing_frames_info_[simulcast_svc_idx].target_bitrate_bytes_per_sec =
+ bitrate_bytes_per_second;
+}
+
+void VCMEncodedFrameCallback::OnFrameRateChanged(size_t framerate) {
+ rtc::CritScope crit(&timing_params_lock_);
+ framerate_ = framerate;
+}
+
+void VCMEncodedFrameCallback::OnEncodeStarted(int64_t capture_time_ms,
+ size_t simulcast_svc_idx) {
+ rtc::CritScope crit(&timing_params_lock_);
+ if (timing_frames_info_.size() < simulcast_svc_idx + 1)
+ timing_frames_info_.resize(simulcast_svc_idx + 1);
+ timing_frames_info_[simulcast_svc_idx].encode_start_time_ms[capture_time_ms] =
+ rtc::TimeMillis();
+}
+
EncodedImageCallback::Result VCMEncodedFrameCallback::OnEncodedImage(
const EncodedImage& encoded_image,
const CodecSpecificInfo* codec_specific,
const RTPFragmentationHeader* fragmentation_header) {
TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded",
"timestamp", encoded_image._timeStamp);
+ bool is_timing_frame = false;
+ size_t outlier_frame_size = 0;
+ int64_t encode_start_ms = -1;
+ size_t simulcast_svc_idx = 0;
+ if (codec_specific->codecType == kVideoCodecVP9) {
+ if (codec_specific->codecSpecific.VP9.num_spatial_layers > 1)
+ simulcast_svc_idx = codec_specific->codecSpecific.VP9.spatial_idx;
+ } else if (codec_specific->codecType == kVideoCodecVP8) {
+ simulcast_svc_idx = codec_specific->codecSpecific.VP8.simulcastIdx;
+ } else if (codec_specific->codecType == kVideoCodecGeneric) {
+ simulcast_svc_idx = codec_specific->codecSpecific.generic.simulcast_idx;
+ } else if (codec_specific->codecType == kVideoCodecH264) {
+ // TODO(ilnik): When h264 simulcast is landed, extract simulcast idx here.
+ }
+
+ {
+ rtc::CritScope crit(&timing_params_lock_);
+ RTC_CHECK_LT(simulcast_svc_idx, timing_frames_info_.size());
+
+ auto encode_start_map =
+ &timing_frames_info_[simulcast_svc_idx].encode_start_time_ms;
+ auto it = encode_start_map->find(encoded_image.capture_time_ms_);
+ if (it != encode_start_map->end()) {
+ encode_start_ms = it->second;
+ // Assuming all encoders do not reorder frames within single stream,
+ // there may be some dropped frames with smaller timestamps. These should
+ // be purged.
+ encode_start_map->erase(encode_start_map->begin(), it);
+ encode_start_map->erase(it);
+ } else {
+ // Some chromium remoting unittests use generic encoder incorrectly
+ // If timestamps do not match, purge them all.
+ encode_start_map->erase(encode_start_map->begin(),
+ encode_start_map->end());
+ }
+
+ int64_t timing_frame_delay_ms =
+ encoded_image.capture_time_ms_ - last_timing_frame_time_ms_;
+ if (last_timing_frame_time_ms_ == -1 ||
+ timing_frame_delay_ms >= timing_frames_thresholds_.delay_ms ||
+ timing_frame_delay_ms == 0) {
+ is_timing_frame = true;
+ last_timing_frame_time_ms_ = encoded_image.capture_time_ms_;
+ }
+ RTC_CHECK_GT(framerate_, 0);
+ size_t average_frame_size =
+ timing_frames_info_[simulcast_svc_idx].target_bitrate_bytes_per_sec /
+ framerate_;
+ outlier_frame_size = average_frame_size *
+ timing_frames_thresholds_.outlier_ratio_percent / 100;
+ }
+
+ if (encoded_image._length >= outlier_frame_size) {
+ is_timing_frame = true;
+ }
+ if (encode_start_ms >= 0 && is_timing_frame) {
+ encoded_image.SetEncodeTime(encode_start_ms, rtc::TimeMillis());
+ }
+
Result result = post_encode_callback_->OnEncodedImage(
encoded_image, codec_specific, fragmentation_header);
if (result.error != Result::OK)
« no previous file with comments | « webrtc/modules/video_coding/generic_encoder.h ('k') | webrtc/modules/video_coding/generic_encoder_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698