123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- #include "video_stream_encoder.h"
- #include <algorithm>
- #include <limits>
- #include <numeric>
- #include <utility>
- #include "video_encoder.h"
- #include "stdint.h"
- #include "base/rate_statistics.h"
- #include "base/video_coding_clock.h"
- #include "base/video_coding_type_defines.h"
- #include "base/video_coding_log.h"
- #include "base/video_frame_type.h"
- #include "../video_statics/video_stats.h"
- namespace video_coding {
- // Time interval for logging frame counts.
- static const int64_t kFrameLogIntervalMs = 60000;
- static const int kMinFramerateFps = 2;
- // Averaging window spanning 90 frames at default 30fps, matching old media
- // optimization module defaults.
- static const int64_t kFrameRateAvergingWindowSizeMs = (1000 / 30) * 90;
- static const size_t kDefaultPayloadSize = 1440;
- static const size_t kDefaultProcessIntervalMs = 1000;
- bool RequiresEncoderReset(const VideoEncoderConfig *previous_send_codec,
- const VideoEncoderConfig *new_send_codec) {
- // Does not check startBitrate or maxFramerate.
- if (new_send_codec->encode_id != previous_send_codec->encode_id ||
- new_send_codec->width != previous_send_codec->width ||
- new_send_codec->height != previous_send_codec->height ||
- new_send_codec->max_bitrate != previous_send_codec->max_bitrate ||
- new_send_codec->min_bitrate != previous_send_codec->min_bitrate ||
- new_send_codec->max_qp != previous_send_codec->max_qp) {
- return true;
- }
- return false;
- }
- typedef struct _VideoFrameInfo {
- int width;
- int height;
- }VideoFrameInfo;
- int video_frame_info_pixel_count(VideoFrameInfo * obj) {
- return obj->width * obj->height;
- }
- typedef struct _EncoderRateSettings {
- // Target bitrate, per spatial/temporal layer.
- // A target bitrate of 0bps indicates a layer should not be encoded at all.
- //单位:bps
- int bitrate;
- // Target framerate, in fps. A value <= 0.0 is invalid and should be
- // interpreted as framerate target not available. In this case the encoder
- // should fall back to the max framerate specified in |codec_settings| of
- // the last InitEncode() call.
- double framerate_fps;
- }EncoderRateSettings;
- // Used to signal the encoder about reason a frame is dropped.
- // kDroppedByMediaOptimizations - dropped by MediaOptimizations (for rate
- // limiting purposes).
- // kDroppedByEncoder - dropped by encoder's internal rate limiter.
- enum DropReason {
- kDroppedByMediaOptimizations,
- kDroppedByEncoder
- };
- typedef struct _VideoStreamEncoder {
- //func object
- FrameDropper *frame_dropper_;
- VideoEncoder *encoder_;
- RateStatistics *input_framerate_;
- //输入根据分配fps丢帧累计值
- int64_t input_accumulator_;
- int64_t last_input_frame_ms_;
- //config
- VideoEncoderObserver encoder_stats_observer_;
- //其中target bitrate为encoder初始化设置带宽
- VideoEncoderConfig encoder_config_;
- //带宽探测,动态设置编码带宽
- EncoderRateSettings last_encoder_rate_settings_;
- EncoderRateSettings allocation_encoder_rate_settings_;
- int continue_bitrate_inc_count;
- int continue_bitrate_dec_count;
- VideoFrameInfo last_frame_info_;
- int64_t last_parameters_update_ms_;
- int64_t last_encode_info_ms_;
- size_t max_data_payload_length_;
- bool encoder_initialized_;
- // Set when configuration must create a new encoder object, e.g.,
- // because of a codec change.
- bool pending_encoder_creation_;
- int64_t last_frame_log_ms_;
- int captured_frame_count_;
- // TODO(sprang): Change actually support keyframe per simulcast stream, or
- // turn this into a simple bool |pending_keyframe_request_|.
- VideoFrameType next_frame_type_;
- }VideoStreamEncoder;
- VideoStreamEncoder *video_stream_encoder_new(
- VideoEncoderObserver* encoder_stats_observer)
- {
- video_coding_debug(VIDEO_CODING_DEBUG_ENABLE, "video_stream_encoder_new.");
- VideoStreamEncoder *obj = (VideoStreamEncoder *)malloc(sizeof(VideoStreamEncoder));
- memset(obj, 0, sizeof(VideoStreamEncoder));
- if (encoder_stats_observer != NULL) {
- memcpy(&obj->encoder_stats_observer_, encoder_stats_observer, sizeof(VideoEncoderObserver));
- }
- obj->encoder_initialized_ = false;
- obj->max_data_payload_length_ = 0;
- obj->last_frame_log_ms_ = TimeInMilliseconds();
- obj->captured_frame_count_ = 0;
- obj->input_framerate_ = rate_statistics_new(kFrameRateAvergingWindowSizeMs, 1000);
- obj->next_frame_type_ = kVideoFrameDelta;
- //reset value
- obj->last_encoder_rate_settings_.bitrate = -1;
- obj->last_encoder_rate_settings_.framerate_fps = -1;
- obj->allocation_encoder_rate_settings_.bitrate = -1;
- obj->allocation_encoder_rate_settings_.framerate_fps = -1;
- obj->frame_dropper_ = frame_dropper_new();
- return obj;
- }
- void video_stream_encoder_destroy(VideoStreamEncoder *obj) {
- if (obj != NULL) {
- frame_dropper_destroy(obj->frame_dropper_);
- obj->frame_dropper_ = NULL;
- rate_statistics_destroy(obj->input_framerate_);
- obj->input_framerate_ = NULL;
- video_encoder_destroy(obj->encoder_);
- obj->encoder_ = NULL;
- free(obj);
- video_coding_debug(VIDEO_CODING_DEBUG_ENABLE, "video_stream_encoder_destroy.");
- }
- }
- void video_stream_encoder_release_encoder(VideoStreamEncoder *obj) {
- if ((obj->encoder_ == NULL) || !obj->encoder_initialized_) {
- return;
- }
- video_encoder_destroy(obj->encoder_);
- obj->encoder_ = NULL;
- obj->encoder_initialized_ = false;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_release_encoder.");
- }
- void video_stream_encoder_stop(VideoStreamEncoder *obj) {
- video_stream_encoder_release_encoder(obj);
- //reset value
- obj->last_encoder_rate_settings_.bitrate = -1;
- obj->last_encoder_rate_settings_.framerate_fps = -1;
- obj->allocation_encoder_rate_settings_.bitrate = -1;
- obj->allocation_encoder_rate_settings_.framerate_fps = -1;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_stop.");
- }
- static uint32_t video_stream_encoder_get_input_framerate_fps(VideoStreamEncoder *obj) {
- const uint32_t default_fps = 30;
- uint32_t input_fps = rate_statistics_rate(obj->input_framerate_, TimeInMilliseconds());
- if (input_fps == absl_nullopt_uint32) {
- return default_fps;
- }
- return input_fps;
- }
- void video_stream_encoder_set_encoder_rates(VideoStreamEncoder *obj,
- const EncoderRateSettings *rate_settings) {
- const bool settings_changes = ((obj->last_encoder_rate_settings_.bitrate == -1) ||
- (obj->last_encoder_rate_settings_.framerate_fps == -1) ||
- (rate_settings->bitrate != obj->last_encoder_rate_settings_.bitrate) ||
- (rate_settings->framerate_fps != obj->last_encoder_rate_settings_.framerate_fps));
- if (settings_changes) {
- memcpy(&obj->last_encoder_rate_settings_, rate_settings, sizeof(EncoderRateSettings));
- }
- if (!obj->encoder_) {
- return;
- }
- // |bitrate_allocation| is 0 it means that the network is down or the send
- // pacer is full. We currently only report this if the encoder has an internal
- // source. If the encoder does not have an internal source, higher levels
- // are expected to not call AddVideoFrame. We do this since its unclear
- // how current encoder implementations behave when given a zero target
- // bitrate.
- // TODO(perkj): Make sure all known encoder implementations handle zero
- // target bitrate and remove this check.
- if (rate_settings->bitrate == 0) {
- return;
- }
- if (settings_changes) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_set_encoder_rates, new encoder setting bitrate: %d, framerate_fps: %lf.",
- rate_settings->bitrate, rate_settings->framerate_fps);
- video_stats_sender_on_encoder_rate_changed((int)rate_settings->framerate_fps, rate_settings->bitrate);
- video_encoder_set_rates(obj->encoder_, rate_settings->bitrate / 1000, rate_settings->framerate_fps);
- }
- }
- // TODO(bugs.webrtc.org/8807): Currently this always does a hard
- // reconfiguration, but this isn't always necessary. Add in logic to only update
- // the VideoBitrateAllocator and call OnEncoderConfigurationChanged with a
- // "soft" reconfiguration.
- static void video_stream_encoder_reconfigure_encoder(VideoStreamEncoder *obj) {
- // Keep the same encoder, as long as the video_format is unchanged.
- // Encoder creation block is split in two since EncoderInfo needed to start
- // CPU adaptation with the correct settings should be polled after
- // encoder_->InitEncode().
- bool success = true;
- if (obj->pending_encoder_creation_) {
- video_stream_encoder_release_encoder(obj);
- obj->encoder_ = video_encoder_new();
- if (video_encoder_init_encode(obj->encoder_, &obj->encoder_config_, obj->max_data_payload_length_ > 0
- ? obj->max_data_payload_length_
- : kDefaultPayloadSize) != 0) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_reconfigure_encoder Failed to initialize the encoder associated with codec type: %d",
- obj->encoder_config_.encode_id);
- video_stream_encoder_release_encoder(obj);
- success = false;
- }
- else {
- obj->encoder_initialized_ = true;
- }
- obj->last_encode_info_ms_ = absl_nullopt_int64;
- }
- if (success) {
- obj->next_frame_type_ = kVideoFrameKey;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_reconfigure_encoder max bitrate: %ukbps start bitrate: %ukbps max frame rate: %u max payload size: %d",
- obj->encoder_config_.max_bitrate, obj->encoder_config_.target_bitrate,
- obj->encoder_config_.max_framerate, obj->max_data_payload_length_);
- }
- else {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_reconfigure_encoder Failed to configure encoder.");
- }
- if (obj->pending_encoder_creation_) {
- obj->pending_encoder_creation_ = false;
- }
- frame_dropper_reset(obj->frame_dropper_);
- frame_dropper_set_rates(obj->frame_dropper_, obj->encoder_config_.target_bitrate, obj->encoder_config_.max_framerate);
- // Get the current target framerate, ie the maximum framerate as specified by
- // the current codec configuration, or any limit imposed by cpu adaption in
- // maintain-resolution or balanced mode. This is used to make sure overuse
- // detection doesn't needlessly trigger in low and/or variable framerate
- // scenarios.
- int target_framerate = std::min<int>(
- obj->encoder_config_.max_framerate, obj->last_encoder_rate_settings_.framerate_fps);
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_reconfigure_encoder target_framerate: %d.", target_framerate);
- }
- void video_stream_encoder_configure_encoder(VideoStreamEncoder *obj, VideoEncoderConfig *config,
- size_t max_data_payload_length) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_configure_encoder.");
- obj->pending_encoder_creation_ = !obj->encoder_ || RequiresEncoderReset(&obj->encoder_config_, config);
- memcpy(&obj->encoder_config_, config, sizeof(VideoEncoderConfig));
- obj->max_data_payload_length_ = max_data_payload_length;
- if (obj->pending_encoder_creation_) {
- video_stream_encoder_reconfigure_encoder(obj);
- }
- }
- void video_stream_encoder_on_dropped_frame(VideoStreamEncoder *obj, DropReason reason) {
- switch (reason) {
- case kDroppedByMediaOptimizations: {
- if (obj->encoder_stats_observer_.OnFrameDropped != NULL) {
- obj->encoder_stats_observer_.OnFrameDropped(kMediaOptimization, obj->encoder_stats_observer_.userdata);
- }
- break;
- }
- case kDroppedByEncoder: {
- if (obj->encoder_stats_observer_.OnFrameDropped != NULL) {
- obj->encoder_stats_observer_.OnFrameDropped(kEncoder, obj->encoder_stats_observer_.userdata);
- }
- break;
- }
- }
- }
- void video_stream_encoder_on_discarded_frame(VideoStreamEncoder *obj) {
- if (obj->encoder_stats_observer_.OnFrameDropped != NULL) {
- obj->encoder_stats_observer_.OnFrameDropped(kSource, obj->encoder_stats_observer_.userdata);
- }
- }
- void video_stream_encoder_run_post_encode(VideoStreamEncoder *obj, const EncodedImage *encoded_image,
- int64_t time_sent_us) {
- int encode_duration_us;
- encode_duration_us =
- // TODO(nisse): Maybe use capture_time_ms_ rather than encode_start_ms_?
- kNumMicrosecsPerMillisec *
- (encoded_image->encode_finish_ms -
- encoded_image->encode_start_ms);
- // Run post encode tasks, such as overuse detection and frame rate/drop
- // stats for internal encoders.
- const size_t frame_size = encoded_image->size_;
- const bool keyframe = encoded_image->key_frame;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_run_post_encode encode_duration_us: %d frame_size: %d keyframe: %d qp_: %d.",
- encode_duration_us, frame_size, keyframe, encoded_image->qp_);
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_run_post_encode time_sent_us: %I64d.",
- time_sent_us);
- if (frame_size > 0) {
- frame_dropper_fill(obj->frame_dropper_, frame_size, !keyframe);
- }
- }
- static void video_stream_encoder_on_encoded_image(VideoStreamEncoder *obj,
- const EncodedImage *encoded_image) {
- //TRACE_EVENT_INSTANT1("webrtc", "VCMEncodedFrameCallback::Encoded",
- // "timestamp", encoded_image.Timestamp());
- // Encoded is called on whatever thread the real encoder implementation run
- // on. In the case of hardware encoders, there might be several encoders
- // running in parallel on different threads.
- if (obj->encoder_stats_observer_.OnEncodedImage != NULL) {
- obj->encoder_stats_observer_.OnEncodedImage(encoded_image, obj->encoder_stats_observer_.userdata);
- }
- video_stream_encoder_run_post_encode(obj, encoded_image, TimeInMicroseconds());
- }
- static void video_stream_encoder_encode_video_frame(VideoStreamEncoder *obj, unsigned pt, const video_frame *video_frame,
- int64_t time_when_posted_us) {
- //TRACE_EVENT_ASYNC_STEP0("webrtc", "Video", video_frame.render_time_ms(),
- // "Encode");
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_encode_video_frame time_when_posted_us: %I64d.",
- time_when_posted_us);
- obj->last_encode_info_ms_ = TimeInMilliseconds();
- if (!obj->encoder_initialized_) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_encode_video_frame encoder not initialized.");
- return;
- }
- EncodedImage *image = video_encoder_encode(obj->encoder_, pt, video_frame, obj->next_frame_type_ == kVideoFrameKey);
- if (image == NULL) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_encode_video_frame Failed to encode frame.");
- return;
- }
- video_stream_encoder_on_encoded_image(obj, image);
- obj->next_frame_type_ = kVideoFrameDelta;
- }
- /* 编码前,判断是否丢帧:一种是在输入丢帧,一种是frame_dropper判断要丢帧 */
- static void video_stream_encoder_maybe_encode_video_frame(VideoStreamEncoder *obj, unsigned pt, const video_frame *frame,
- int64_t time_when_posted_us) {
- int64_t now_ms = TimeInMilliseconds();
- //do source cap framerate drop
- int target_framerate = std::min<int>(
- obj->encoder_config_.max_framerate, obj->allocation_encoder_rate_settings_.framerate_fps);
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_maybe_encode_video_frame, target_framerate: %d now_ms: %I64d.", target_framerate, now_ms);
- if (obj->last_input_frame_ms_ != 0 && target_framerate != -1) {
- int64_t avg_frame_ms = 1000 / target_framerate;
- int64_t elapse_ms = now_ms - obj->last_input_frame_ms_;
- obj->input_accumulator_ += avg_frame_ms - elapse_ms;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_maybe_encode_video_frame, avg_frame_ms: %I64d elapse_ms: %I64d input_accumulator: %I64d.", avg_frame_ms, elapse_ms, obj->input_accumulator_);
- if (obj->input_accumulator_ > avg_frame_ms) {
- video_stream_encoder_on_discarded_frame(obj);
- video_stats_sender_on_frame_dropped(1, 0);
- obj->input_accumulator_ -= avg_frame_ms;
- obj->last_input_frame_ms_ = now_ms;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_maybe_encode_video_frame, do source cap framerate drop with input_accumulator_: %I64d.",
- obj->input_accumulator_);
- return;
- }
- }
- obj->last_input_frame_ms_ = now_ms;
- if (frame->width != obj->last_frame_info_.width ||
- frame->height != obj->last_frame_info_.height) {
- obj->last_frame_info_.height = frame->height;
- obj->last_frame_info_.width = frame->width;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER, "video_stream_encoder_maybe_encode_video_frame Video frame parameters changed: dimensions= %d x %d.",
- obj->last_frame_info_.width, obj->last_frame_info_.height);
- }
- //updata encoder framerate with input
- // Update input frame rate before we start using it. If we update it after
- // any potential frame drop we are going to artificially increase frame sizes.
- // Poll the rate before updating, otherwise we risk the rate being estimated
- // a little too high at the start of the call when then window is small.
- uint32_t framerate_fps = video_stream_encoder_get_input_framerate_fps(obj);
- rate_statistics_update(obj->input_framerate_, 1u, TimeInMilliseconds());
- if (now_ms - obj->last_parameters_update_ms_ >= kDefaultProcessIntervalMs) {
- // Clone rate settings before update, so that SetEncoderRates() will
- // actually detect the change between the input and
- // |last_encoder_rate_setings_|, triggering the call to SetRate() on the
- // encoder.
- if ((obj->last_encoder_rate_settings_.bitrate != -1) && (obj->last_encoder_rate_settings_.framerate_fps != -1)) {
- EncoderRateSettings *new_rate_settings = &obj->last_encoder_rate_settings_;
- new_rate_settings->framerate_fps = static_cast<double>(framerate_fps);
- video_stream_encoder_set_encoder_rates(obj, new_rate_settings);
- }
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_maybe_encode_video_frame, update framerate_setting:%u.", framerate_fps);
- obj->last_parameters_update_ms_ = now_ms;
- }
- //do MediaOptimization framerate drop
- frame_dropper_leak(obj->frame_dropper_, framerate_fps);
- // Frame dropping is enabled if frame dropping is not force-disabled, and
- // rate controller is not trusted.
- const bool frame_dropping_enabled = true;
- frame_dropper_enable(obj->frame_dropper_, frame_dropping_enabled);
- if (frame_dropping_enabled && frame_dropper_drop_frame(obj->frame_dropper_)) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_maybe_encode_video_frame Drop Frame: target bitrate %d, input frame rate :%u.",
- obj->last_encoder_rate_settings_.bitrate, framerate_fps);
- video_stream_encoder_on_dropped_frame(obj, kDroppedByMediaOptimizations);
- video_stats_sender_on_frame_dropped(0, 1);
- return;
- }
- video_stream_encoder_encode_video_frame(obj, pt, frame, time_when_posted_us);
- }
- void video_stream_encoder_on_frame(VideoStreamEncoder *obj, unsigned pt, const video_frame *video_frame) {
- int64_t current_time_us = TimeInMicroseconds();
- int64_t current_time_ms = current_time_us / kNumMicrosecsPerMillisec;
- bool log_stats = false;
- if (current_time_ms - obj->last_frame_log_ms_ > kFrameLogIntervalMs) {
- obj->last_frame_log_ms_ = current_time_ms;
- log_stats = true;
- }
- int64_t post_time_us = TimeInMicroseconds();
- if (obj->encoder_stats_observer_.OnIncomingFrame != NULL) {
- obj->encoder_stats_observer_.OnIncomingFrame(video_frame->width,
- video_frame->height, obj->encoder_stats_observer_.userdata);
- }
- ++obj->captured_frame_count_;
- video_stream_encoder_maybe_encode_video_frame(obj, pt, video_frame, post_time_us);
- if (log_stats) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_frame Number of frames: captured %d.",
- obj->captured_frame_count_);
- obj->captured_frame_count_ = 0;
- }
- }
- void video_stream_encoder_send_key_frame(VideoStreamEncoder *obj) {
- //TRACE_EVENT0("webrtc", "OnKeyFrameRequest");
- obj->next_frame_type_ = kVideoFrameKey;
- }
- //动态更新编码参数,适应网络状态
- void video_stream_encoder_on_bitrate_updated(VideoStreamEncoder *obj, uint32_t target_bitrate,
- uint32_t link_allocation,
- uint8_t fraction_lost,
- int64_t round_trip_time_ms) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. bitrate %u, packet loss %u, rtt %I64d.",
- target_bitrate, fraction_lost, round_trip_time_ms);
- if (obj->allocation_encoder_rate_settings_.bitrate != -1 && obj->allocation_encoder_rate_settings_.framerate_fps != -1) {
- uint32_t framerate_fps = video_stream_encoder_get_input_framerate_fps(obj);
- float cur_fps_ratio = framerate_fps / (float)obj->encoder_config_.max_framerate;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. input_framerate_fps %u cur_fps_ratio:%f.",
- framerate_fps, cur_fps_ratio);
- if (target_bitrate > obj->allocation_encoder_rate_settings_.bitrate) {
- obj->continue_bitrate_inc_count++;
- obj->continue_bitrate_dec_count = 0;
- }
- else if (target_bitrate < obj->allocation_encoder_rate_settings_.bitrate) {
- obj->continue_bitrate_inc_count = 0;
- obj->continue_bitrate_dec_count++;
- }
- //调整策略:
- //带宽分配已经达到最大值90%(反馈的值与max因为header有一定偏差),此时需要提升fps
- if (target_bitrate >= obj->encoder_config_.max_bitrate * 1000 * 0.9) {
- obj->allocation_encoder_rate_settings_.framerate_fps = obj->encoder_config_.max_framerate;
- obj->allocation_encoder_rate_settings_.bitrate = obj->encoder_config_.max_bitrate * 1000;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. bitrate %u >= max_bitrate %u' 90%, use max send.",
- target_bitrate, obj->encoder_config_.max_bitrate * 1000);
- }
- else {
- //高带宽,升码率直到max_bitrate
- if (obj->continue_bitrate_inc_count >= 2 && target_bitrate >= 70000) {
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. continue_bitrate_inc_count >= 2, bitrate %u, last_bitrate %f, use new bitrate send.",
- target_bitrate, (float)obj->allocation_encoder_rate_settings_.bitrate*cur_fps_ratio);
- obj->allocation_encoder_rate_settings_.bitrate = target_bitrate;
- obj->allocation_encoder_rate_settings_.framerate_fps = obj->encoder_config_.max_framerate;
- }
- //低带宽:先降帧率,帧率降到最低仍不够,降低码率
- else if (obj->continue_bitrate_dec_count >= 3 || target_bitrate < 70000) {
- float fps_ratio = (float)obj->encoder_config_.min_framerate / (float)obj->encoder_config_.max_framerate;
- float ratio_bitrate = (float)obj->allocation_encoder_rate_settings_.bitrate*fps_ratio;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. continue_bitrate_dec_count >= 3, bitrate %d ,last_bitrate %f.",
- target_bitrate, (float)obj->allocation_encoder_rate_settings_.bitrate*cur_fps_ratio);
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. continue_bitrate_dec_count >= 3, fps_ratio %f ratio_bitrate %f.",
- fps_ratio, ratio_bitrate);
- obj->allocation_encoder_rate_settings_.framerate_fps = obj->encoder_config_.min_framerate;
- //obj->allocation_encoder_rate_settings_.bitrate = target_bitrate/fps_ratio;
- obj->allocation_encoder_rate_settings_.bitrate =
- target_bitrate > obj->encoder_config_.min_bitrate * 1000 ? target_bitrate : obj->encoder_config_.min_bitrate * 1000;
- video_coding_debug(VIDEO_CODING_DEBUG_STREAM_ENCODER,
- "video_stream_encoder_on_bitrate_updated. continue_bitrate_dec_count >= 3, new bitrate %d, new framerate_fps %lf.",
- obj->allocation_encoder_rate_settings_.bitrate, obj->allocation_encoder_rate_settings_.framerate_fps);
- }
- else {
- obj->allocation_encoder_rate_settings_.bitrate = target_bitrate;
- }
- }
- }
- else {
- obj->allocation_encoder_rate_settings_.framerate_fps = obj->encoder_config_.max_framerate;
- obj->allocation_encoder_rate_settings_.bitrate = target_bitrate;
- }
- /*if (target_bitrate < obj->encoder_config_.min_bitrate){
- obj->allocation_encoder_rate_settings_.framerate_fps = obj->encoder_config_.min_framerate;
- obj->allocation_encoder_rate_settings_.bitrate = obj->encoder_config_.min_bitrate;
- } else {
- obj->allocation_encoder_rate_settings_.framerate_fps = obj->encoder_config_.max_framerate;
- obj->allocation_encoder_rate_settings_.bitrate = target_bitrate;
- }*/
- frame_dropper_set_rates(obj->frame_dropper_, (obj->allocation_encoder_rate_settings_.bitrate + 500) / 1000,
- obj->allocation_encoder_rate_settings_.framerate_fps);
- EncoderRateSettings new_rate_settings = { obj->allocation_encoder_rate_settings_.bitrate, obj->allocation_encoder_rate_settings_.framerate_fps };
- video_stream_encoder_set_encoder_rates(obj, &new_rate_settings);
- }
- }
|