Commit 055aa314 authored by 957dd's avatar 957dd

c语言推流基本完成

parent 3585cc8c
No preview for this file type
......@@ -28,6 +28,14 @@
#define CAR0107_BACK_US_RUN_MIN 1440 /* val=53 起步即动(须低于死区 1450) */
#define CAR0107_BACK_US_RUN_MAX 1300 /* 后退最大速度再降20%:val=200 -> 1300us */
/* idle 唤醒动作:5分钟无控制后 低速后退 -> 低速前进 -> 前进刹车停止 */
#define CAR0107_IDLE_REVERSE_US CAR0107_BACK_US_RUN_MIN /* 1440us 刚过死区,最低速后退 */
#define CAR0107_IDLE_FORWARD_US CAR0107_FWD_US_RUN_MIN /* 1560us 最低前进行走脉宽 */
#define CAR0107_IDLE_REVERSE_MS 600 /* 后退保持时长 */
#define CAR0107_IDLE_NEUTRAL_MS 150 /* 后退切前进前中位稳定时长 */
#define CAR0107_IDLE_FORWARD_MS 600 /* 前进保持时长 */
#define CAR0107_IDLE_BRAKE_WAIT_MS 250 /* 等待刹车保持+中位解锁收尾到 NEUTRAL */
typedef enum {
CAR0107_ESC_DIR_FORWARD = 1, /* App mode1 前进:高脉宽(与 0101 相反) */
CAR0107_ESC_DIR_BACK = 2, /* App mode2 后退:低脉宽(与 0101 相反) */
......@@ -1392,3 +1400,92 @@ void car0107_esc_thread_close(void)
pthread_mutex_unlock(&s_esc_start_mutex);
my_zlog_info("car0107 esc thread closed");
}
/*
* 0107 idle 唤醒动作:5分钟无控制命令时由 idle 线程调用。
* 顺序:低速后退一点 -> 中位 -> 低速前进一点 -> 前进刹车停止。
* 前进停止遵守电调刹车动作 BRAKE_THEN_NEUTRAL -> NEUTRAL_UNLOCK -> NEUTRAL,
* 由电调专用线程 tick 自动完成刹车保持与中位解锁收尾。
* 动作期间若有真实控制命令介入(control_source 被改为非 NONE)则立即让位。
*/
void car0107_idle_wakeup_maneuver(void)
{
/* 必须保证电调线程在运行,否则刹车序列无法由 tick 自动收尾到 NEUTRAL */
car0107_esc_thread_start();
/* 方向盘回正,后退/前进均走直线 */
pthread_mutex_lock(&s_car0107_hw_mutex);
s_control_source = CTRL_NONE; /* 阻止 speed_smooth_process 串扰速度 */
s_target_angle = 90;
s_current_angle = 90;
car0107_calculate_L_R(90);
/* 1) 低速后退:从中位直接跳到刚过死区的后退脉宽 */
car0107_esc_clear_pending_stop();
s_esc.cmd_dir = CAR0107_ESC_DIR_BACK;
s_esc.last_drive_dir = CAR0107_ESC_DIR_BACK;
s_esc.last_nonzero_mode = CAR0107_ESC_DIR_BACK;
s_esc.target_us = CAR0107_IDLE_REVERSE_US;
s_esc.current_us = CAR0107_IDLE_REVERSE_US;
s_esc.state = CAR0107_ESC_REVERSE;
s_esc.trans_phase = CAR0107_TRANS_RAMP_RUN;
car0107_esc_output_us(s_esc.current_us, 0);
pthread_mutex_unlock(&s_car0107_hw_mutex);
car0107_esc_thread_wake();
my_zlog_info("car0107 idle maneuver: reverse %dus for %dms",
CAR0107_IDLE_REVERSE_US, CAR0107_IDLE_REVERSE_MS);
delay_ms(CAR0107_IDLE_REVERSE_MS);
/* 2) 停止后退:后退松手不刹车,直接回中 */
pthread_mutex_lock(&s_car0107_hw_mutex);
if (s_control_source != CTRL_NONE) {
pthread_mutex_unlock(&s_car0107_hw_mutex);
my_zlog_info("car0107 idle maneuver: yield at neutral (control taken)");
return;
}
car0107_esc_begin_neutral_stop();
car0107_esc_output_us(CAR0107_ESC_US_NEUTRAL, 0);
pthread_mutex_unlock(&s_car0107_hw_mutex);
car0107_esc_thread_wake();
delay_ms(CAR0107_IDLE_NEUTRAL_MS);
/* 3) 低速前进:从中位直接跳到最低前进行走脉宽 */
pthread_mutex_lock(&s_car0107_hw_mutex);
if (s_control_source != CTRL_NONE) {
pthread_mutex_unlock(&s_car0107_hw_mutex);
my_zlog_info("car0107 idle maneuver: yield before forward (control taken)");
return;
}
car0107_esc_clear_pending_stop();
s_esc.cmd_dir = CAR0107_ESC_DIR_FORWARD;
s_esc.last_drive_dir = CAR0107_ESC_DIR_FORWARD;
s_esc.last_nonzero_mode = CAR0107_ESC_DIR_FORWARD;
s_esc.target_us = CAR0107_IDLE_FORWARD_US;
s_esc.current_us = CAR0107_IDLE_FORWARD_US;
s_esc.state = CAR0107_ESC_FORWARD;
s_esc.trans_phase = CAR0107_TRANS_RAMP_RUN;
car0107_esc_output_us(s_esc.current_us, 0);
pthread_mutex_unlock(&s_car0107_hw_mutex);
car0107_esc_thread_wake();
my_zlog_info("car0107 idle maneuver: forward %dus for %dms",
CAR0107_IDLE_FORWARD_US, CAR0107_IDLE_FORWARD_MS);
delay_ms(CAR0107_IDLE_FORWARD_MS);
/* 4) 停止前进:遵守刹车动作,由电调线程 tick 自动收尾 */
pthread_mutex_lock(&s_car0107_hw_mutex);
if (s_control_source != CTRL_NONE) {
pthread_mutex_unlock(&s_car0107_hw_mutex);
my_zlog_info("car0107 idle maneuver: yield before brake (control taken)");
return;
}
car0107_esc_begin_forward_brake();
pthread_mutex_unlock(&s_car0107_hw_mutex);
car0107_esc_thread_wake();
my_zlog_info("car0107 idle maneuver: forward brake %dus for %dms",
car0107_forward_brake_us(), CAR0107_ESC_BRAKE_HOLD_MS);
delay_ms(CAR0107_IDLE_BRAKE_WAIT_MS);
}
......@@ -14,4 +14,7 @@ void car0107_esc_thread_start(void);
void car0107_esc_thread_wake(void);
void car0107_esc_thread_close(void);
/* idle 唤醒动作:低速后退 -> 低速前进 -> 前进刹车停止 */
void car0107_idle_wakeup_maneuver(void);
#endif
......@@ -6,16 +6,12 @@
#define CAR0107_IDLE_CHECK_MS 10000
#define CAR0107_IDLE_TIMEOUT_MS (5 * 60 * 1000)
#define CAR0107_IDLE_STEER_HOLD_MS 450
#define CAR0107_IDLE_STEER_LEFT 115
#define CAR0107_IDLE_STEER_RIGHT 65
typedef struct {
pthread_mutex_t mutex;
ThreadPool_t *pool;
bool shutdown;
bool pool_ready;
int next_left;
} car0107_idle_ctx_t;
static car0107_idle_ctx_t s_idle_ctx = {
......@@ -23,7 +19,6 @@ static car0107_idle_ctx_t s_idle_ctx = {
.pool = NULL,
.shutdown = false,
.pool_ready = false,
.next_left = 1,
};
static void car0107_idle_lock(void)
......@@ -67,16 +62,6 @@ static int car0107_idle_pool_init(void)
return 0;
}
static void car0107_idle_nudge_steering(int turn_left)
{
int angle = turn_left ? CAR0107_IDLE_STEER_LEFT : CAR0107_IDLE_STEER_RIGHT;
/* 速度 PWM 只由持有0107硬件锁的控制路径写,idle线程不直接碰速度。 */
car0107_steering_set_angle_sync(angle);
delay_ms(CAR0107_IDLE_STEER_HOLD_MS);
car0107_steering_set_angle_sync(90);
}
static void car0107_idle_monitor_task(void *arg)
{
(void)arg;
......@@ -85,7 +70,6 @@ static void car0107_idle_monitor_task(void *arg)
while (!car0107_idle_shutdown_get()) {
long long now;
long long last;
int turn_left;
delay_ms(CAR0107_IDLE_CHECK_MS);
if (car0107_idle_shutdown_get() || g_device_type != DEVICE_CAR0107) {
......@@ -101,15 +85,10 @@ static void car0107_idle_monitor_task(void *arg)
continue;
}
car0107_idle_lock();
turn_left = s_idle_ctx.next_left;
s_idle_ctx.next_left = !s_idle_ctx.next_left;
car0107_idle_unlock();
my_zlog_info("car0107 idle %dmin: nudge steer %s",
CAR0107_IDLE_TIMEOUT_MS / 60000,
turn_left ? "left" : "right");
car0107_idle_nudge_steering(turn_left);
my_zlog_info("car0107 idle %dmin: wakeup maneuver (reverse->forward->brake)",
CAR0107_IDLE_TIMEOUT_MS / 60000);
/* 低速后退一点 -> 低速前进一点 -> 前进刹车停止(遵守刹车动作)*/
car0107_idle_wakeup_maneuver();
car0107_notify_control_activity();
}
......@@ -133,7 +112,7 @@ void car0107_idle_startup(int device_id)
car0107_idle_unlock();
car0107_notify_control_activity();
my_zlog_info("car0107 idle monitor enabled: steer nudge every %dmin when idle",
my_zlog_info("car0107 idle monitor enabled: wakeup maneuver every %dmin when idle",
CAR0107_IDLE_TIMEOUT_MS / 60000);
}
......
This diff is collapsed.
......@@ -73,6 +73,8 @@ struct MppH264Source {
guint8 *jpeg_tmp_v;
size_t jpeg_tmp_capacity;
guint keyframe_req;
gint pending_bitrate_bps;
guint applied_bitrate_bps;
volatile gboolean pending_idr;
gboolean pending_idr_event_sent;
gint64 last_keyframe_event_us;
......@@ -104,6 +106,7 @@ static gboolean pull_sample(MppH264Source *src, gboolean require_idr,
size_t *size, gboolean *is_idr,
guint64 *pts_ns);
static gboolean send_force_key_unit(MppH264Source *src);
static void apply_pending_bitrate(MppH264Source *src);
static gpointer mjpeg_decode_thread(gpointer user_data);
static void timing_mark_encoder_in(MppH264Source *src, guint64 pts_ns,
gint64 enc_in_us);
......@@ -1648,6 +1651,9 @@ gboolean mpp_h264_source_pull(MppH264Source *src, gboolean force_idr,
if (!src || !src->appsink || !data || !size)
return FALSE;
/* 编码帧之间应用动态码率,避免从 REMB/RTP 回调线程直接重配编码器。 */
apply_pending_bitrate(src);
/* bus 报 ERROR 后 pipeline 卡死,这里及时恢复避免长期黑屏 */
if (src->pending_recover && mpp_h264_source_recover(src)) {
src->pending_idr = TRUE;
......@@ -1676,7 +1682,7 @@ gboolean mpp_h264_source_pull(MppH264Source *src, gboolean force_idr,
return pull_sample(src, FALSE, timeout_ms, data, size, is_idr, pts_ns);
}
void mpp_h264_source_set_bitrate(MppH264Source *src, guint bitrate_bps)
static void apply_bitrate_now(MppH264Source *src, guint bitrate_bps)
{
GstElementFactory *f;
const gchar *name;
......@@ -1710,6 +1716,36 @@ void mpp_h264_source_set_bitrate(MppH264Source *src, guint bitrate_bps)
} else if (name && g_str_has_prefix(name, "x264enc")) {
g_object_set(src->enc, "bitrate", bitrate_bps / 1000, NULL);
}
src->applied_bitrate_bps = bitrate_bps;
my_zlog_info("mpp_h264_source: bitrate applied at frame boundary %u kbps",
bitrate_bps / 1000);
}
static void apply_pending_bitrate(MppH264Source *src)
{
gint pending;
if (!src)
return;
pending = g_atomic_int_get(&src->pending_bitrate_bps);
if (pending <= 0 ||
!g_atomic_int_compare_and_exchange(&src->pending_bitrate_bps,
pending, 0))
return;
if ((guint)pending == src->applied_bitrate_bps)
return;
apply_bitrate_now(src, (guint)pending);
}
void mpp_h264_source_set_bitrate(MppH264Source *src, guint bitrate_bps)
{
if (!src || !bitrate_bps)
return;
if (bitrate_bps < MPP_VIDEO_MIN_BPS)
bitrate_bps = MPP_VIDEO_MIN_BPS;
if (bitrate_bps > MPP_VIDEO_MAX_BPS)
bitrate_bps = MPP_VIDEO_MAX_BPS;
g_atomic_int_set(&src->pending_bitrate_bps, (gint)bitrate_bps);
}
gboolean mpp_h264_source_recover(MppH264Source *src)
......
......@@ -88,6 +88,8 @@ typedef struct {
guint last_remb_bitrate;
guint remb_filtered;
guint remb_down_samples;
gboolean initial_probe_complete;
gint64 probe_target_reached_us;
gint64 last_bitrate_ramp_us;
gint64 last_mpp_bitrate_apply_us;
gint64 last_idr_request_us;
......@@ -1021,6 +1023,7 @@ static void apply_bitrate(RtcClient *client, int track, guint bitrate)
guint b;
guint old_b;
guint old_mpp_b;
guint mpp_apply_b = 0;
guint mpp_delta;
gint64 now_us;
gint64 last_mpp_apply_us;
......@@ -1039,11 +1042,25 @@ static void apply_bitrate(RtcClient *client, int track, guint bitrate)
old_mpp_b = old_b ? old_b : b;
client->target_bitrate = b;
mpp_delta = bitrate_delta(old_mpp_b, b);
if (mpp_delta >= WEBRTCPUSH_MPP_RECONFIG_MIN_DELTA_BPS &&
if ((guint64)mpp_delta * 100U >=
(guint64)old_mpp_b * WEBRTCPUSH_MPP_RECONFIG_MIN_DELTA_PERCENT &&
now_us - last_mpp_apply_us >=
(gint64)WEBRTCPUSH_MPP_RECONFIG_MIN_INTERVAL_MS * 1000) {
apply_mpp = TRUE;
client->applied_mpp_bitrate = b;
mpp_apply_b = b;
if (b > old_mpp_b) {
guint max_up = (guint)(((guint64)old_mpp_b *
(100U + WEBRTCPUSH_MPP_RECONFIG_MAX_STEP_PERCENT)) / 100U);
if (mpp_apply_b > max_up)
mpp_apply_b = max_up;
} else {
guint min_down = (guint)(((guint64)old_mpp_b *
(100U - WEBRTCPUSH_MPP_RECONFIG_MAX_STEP_PERCENT)) / 100U);
if (mpp_apply_b < min_down)
mpp_apply_b = min_down;
}
mpp_apply_b = clamp_bitrate(mpp_apply_b);
client->applied_mpp_bitrate = mpp_apply_b;
client->last_mpp_bitrate_apply_us = now_us;
}
g_mutex_unlock(&client->lock);
......@@ -1058,12 +1075,13 @@ static void apply_bitrate(RtcClient *client, int track, guint bitrate)
g_mutex_unlock(&client->send_lock);
}
if (apply_mpp) {
mpp_h264_source_set_bitrate(client->h264_source, b);
my_zlog_info("libdatachannel: RTCP bitrate control -> target=%u->%u kbps, MPP=%u->%u kbps pacing=%u kbps",
old_b / 1000, b / 1000, old_mpp_b / 1000, b / 1000,
/* 这里只投递原子目标;真正的 mpph264enc 属性更新在拉帧边界执行。 */
mpp_h264_source_set_bitrate(client->h264_source, mpp_apply_b);
my_zlog_info("libdatachannel: bitrate control -> target=%u->%u kbps, MPP queued=%u->%u kbps pacing=%u kbps",
old_b / 1000, b / 1000, old_mpp_b / 1000, mpp_apply_b / 1000,
pacing_bitrate_for_encoder(b) / 1000);
} else {
my_zlog_info("libdatachannel: RTCP bitrate control -> target=%u->%u kbps, MPP hold=%u kbps pacing=%u kbps",
my_zlog_info("libdatachannel: bitrate control -> target=%u->%u kbps, MPP hold=%u kbps pacing=%u kbps",
old_b / 1000, b / 1000, old_mpp_b / 1000,
pacing_bitrate_for_encoder(b) / 1000);
}
......@@ -1093,11 +1111,11 @@ static void ramp_bitrate_toward_ceiling(RtcClient *client, int track)
return; /* confirmed decreases are applied by on_remb() */
diff = tgt - cur;
step = (guint)(((guint64)cur * 12U) / 100U);
if (step < 50000U)
step = 50000U;
if (step > 250000U)
step = 250000U;
step = (guint)(((guint64)cur * WEBRTCPUSH_BITRATE_RAMP_UP_PERCENT) / 100U);
if (step < WEBRTCPUSH_BITRATE_RAMP_UP_STEP_MIN_BPS)
step = WEBRTCPUSH_BITRATE_RAMP_UP_STEP_MIN_BPS;
if (step > WEBRTCPUSH_BITRATE_RAMP_UP_STEP_MAX_BPS)
step = WEBRTCPUSH_BITRATE_RAMP_UP_STEP_MAX_BPS;
if (step > diff)
step = diff;
next = cur + step;
......@@ -1144,8 +1162,10 @@ static void RTC_API on_remb(int track, unsigned int bitrate, void *ptr)
gboolean can_step_down = FALSE;
gboolean have_pacing;
gboolean first_frame_sent;
gboolean recent_idr = FALSE;
gboolean remb_sane_floor = FALSE;
gboolean log_remb_sane_floor = FALSE;
gboolean probe_completed_now = FALSE;
guint pacing_packets = 0;
guint pacing_bytes = 0;
guint pacing_delay_ms = 0;
......@@ -1161,13 +1181,34 @@ static void RTC_API on_remb(int track, unsigned int bitrate, void *ptr)
g_mutex_lock(&client->lock);
current = client->target_bitrate;
first_frame_sent = client->first_frame_sent;
recent_idr = client->last_idr_sent_us > 0 &&
now_us - client->last_idr_sent_us <
(gint64)WEBRTCPUSH_REMB_IDR_GRACE_MS * 1000;
client->last_remb_bitrate = bitrate;
can_step_down = now_us - client->last_bitrate_ramp_us >=
(gint64)WEBRTCPUSH_BITRATE_RAMP_DOWN_MS * 1000;
/*
* REMB 在低发送量时容易形成“低码率 -> 低估计 -> 永远无法探测”的闭环。
* 初次连接主动爬到健康探测目标并保持一段时间,让接收端用真实流量重新估计。
* 探测完成后仍保留“发送端受限”保护:pacing 健康时,低 REMB 只能阻止
* 继续上升,不能把发送量越压越低。只有持续积压且不在 IDR 窗口才允许下降。
*/
if (!client->initial_probe_complete) {
if (current + WEBRTCPUSH_REMB_DOWN_MIN_STEP >=
WEBRTCPUSH_HEALTHY_PROBE_TARGET_BPS) {
if (client->probe_target_reached_us == 0)
client->probe_target_reached_us = now_us;
else if (now_us - client->probe_target_reached_us >=
(gint64)WEBRTCPUSH_INITIAL_PROBE_HOLD_MS * 1000) {
client->initial_probe_complete = TRUE;
probe_completed_now = TRUE;
}
}
}
estimate_bitrate = bitrate;
if (first_frame_sent && have_pacing &&
bitrate < WEBRTCPUSH_REMB_SANE_RAW_MAX_BPS &&
pacing_delay_ms <= WEBRTCPUSH_REMB_SANE_PACING_MAX_MS) {
(pacing_delay_ms <= WEBRTCPUSH_REMB_SANE_PACING_MAX_MS || recent_idr)) {
estimate_bitrate = WEBRTCPUSH_REMB_SANE_FLOOR_BPS;
remb_sane_floor = TRUE;
if (client->last_remb_sane_log_us == 0 ||
......@@ -1234,10 +1275,16 @@ static void RTC_API on_remb(int track, unsigned int bitrate, void *ptr)
}
g_mutex_unlock(&client->lock);
if (probe_completed_now) {
my_zlog_info("libdatachannel: initial bandwidth probe complete at %u kbps; steady sender-limited REMB guard enabled",
current / 1000);
}
if (log_remb_sane_floor) {
my_zlog_info("libdatachannel: RTCP REMB suspicious low raw=%u kbps, use=%u kbps (pacing=%u pkt/%u bytes/%ums)",
my_zlog_info("libdatachannel: RTCP REMB sender-limited raw=%u kbps, use=%u kbps (pacing=%u pkt/%u bytes/%ums idr_grace=%d)",
bitrate / 1000, estimate_bitrate / 1000,
pacing_packets, pacing_bytes, pacing_delay_ms);
pacing_packets, pacing_bytes, pacing_delay_ms,
recent_idr ? 1 : 0);
}
if (next) {
......@@ -1492,13 +1539,14 @@ static gpointer send_thread_main(gpointer data)
actual_fps_x10 = (guint)(((guint64)sent_window_frames * 10U * 1000000U) /
elapsed_us);
}
my_zlog_info("libdatachannel: stats encoder=%u actual_h264=%u kbps sent_fps=%u.%u raw_remb=%u filtered_remb=%u ceiling=%u kbps pacing=%u pkt/%u bytes/%ums queue_dropped=%u",
my_zlog_info("libdatachannel: stats encoder=%u actual_h264=%u kbps sent_fps=%u.%u raw_remb=%u filtered_remb=%u ceiling=%u kbps pacing=%u pkt/%u bytes/%ums queue_dropped=%u probe=%s",
target_bps / 1000, actual_kbps,
actual_fps_x10 / 10, actual_fps_x10 % 10,
raw_remb_bps / 1000, filtered_remb_bps / 1000,
remb_bps / 1000,
pacing_packets, pacing_bytes, pacing_delay_ms,
queue_dropped);
queue_dropped,
client->initial_probe_complete ? "done" : "active");
send_datachannel_mbps(client, actual_kbps);
/* 修复: MPP CBR失控时actual>>target, pacing必须跟actual否则永远堆积 */
if (actual_kbps > 0) {
......@@ -1975,6 +2023,8 @@ int rtc_client_start(AppState *app)
client->target_bitrate = WEBRTCPUSH_INITIAL_BITRATE;
client->applied_mpp_bitrate = WEBRTCPUSH_INITIAL_BITRATE;
client->remb_ceiling = WEBRTCPUSH_INITIAL_BITRATE;
client->initial_probe_complete = FALSE;
client->probe_target_reached_us = 0;
client->last_remb_bitrate = 0;
client->remb_filtered = 0;
client->remb_down_samples = 0;
......@@ -2201,6 +2251,8 @@ int rtc_client_handle_offer(AppState *app, const char *sdp)
client->target_bitrate = WEBRTCPUSH_INITIAL_BITRATE;
client->applied_mpp_bitrate = WEBRTCPUSH_INITIAL_BITRATE;
client->remb_ceiling = WEBRTCPUSH_INITIAL_BITRATE;
client->initial_probe_complete = FALSE;
client->probe_target_reached_us = 0;
client->last_remb_bitrate = 0;
client->remb_filtered = 0;
client->remb_down_samples = 0;
......
......@@ -8,7 +8,7 @@
*
* 原生分支:v4l2 采集 → mpph264enc(或 x264enc 回退)→ libdatachannel 发送。
*/
#define WEBRTCPUSH_USE_MPP 0
#define WEBRTCPUSH_USE_MPP 1
/* 正常固定 24fps;弱网以降码率为主,后续若启用动态帧率也不得低于 22fps。 */
#define WEBRTCPUSH_H264_FPS 24
......@@ -22,24 +22,33 @@
*/
#define WEBRTCPUSH_INITIAL_BITRATE 900000U
#define WEBRTCPUSH_MIN_BITRATE 800000U
#define WEBRTCPUSH_MAX_BITRATE 2600000U
#define WEBRTCPUSH_MAX_BITRATE 3000000U
#define WEBRTCPUSH_REMB_UTIL_PERCENT 80U
#define WEBRTCPUSH_REMB_DOWN_MIN_STEP 100000U
#define WEBRTCPUSH_REMB_DOWN_CONFIRMATIONS 8U
#define WEBRTCPUSH_REMB_SEVERE_CONFIRMATIONS 2U
#define WEBRTCPUSH_REMB_SEVERE_PERCENT 65U
#define WEBRTCPUSH_BITRATE_RAMP_UP_MS 1800U
#define WEBRTCPUSH_BITRATE_RAMP_UP_MS 1200U
#define WEBRTCPUSH_BITRATE_RAMP_DOWN_MS 2000U
#define WEBRTCPUSH_BITRATE_RAMP_UP_PERCENT 12U
#define WEBRTCPUSH_BITRATE_RAMP_UP_STEP_MIN_BPS 70000U
#define WEBRTCPUSH_BITRATE_RAMP_UP_STEP_MAX_BPS 250000U
#define WEBRTCPUSH_REMB_DOWN_STEP_PERCENT 10U
#define WEBRTCPUSH_REMB_DOWN_STEP_MIN_BPS 60000U
#define WEBRTCPUSH_REMB_DOWN_STEP_MAX_BPS 120000U
/* REMB 低估保护:pacing 不堵时,过低浏览器估计不直接压糊 720p。 */
#define WEBRTCPUSH_REMB_SANE_FLOOR_BPS 2200000U
#define WEBRTCPUSH_REMB_SANE_RAW_MAX_BPS 1200000U
#define WEBRTCPUSH_HEALTHY_PROBE_TARGET_BPS 2700000U
/* 3.375Mbps * 80% = 2.7Mbps. 这是 REMB 原始估计的探测地板,不是编码码率。 */
#define WEBRTCPUSH_REMB_SANE_FLOOR_BPS 3375000U
#define WEBRTCPUSH_REMB_SANE_RAW_MAX_BPS WEBRTCPUSH_REMB_SANE_FLOOR_BPS
#define WEBRTCPUSH_REMB_SANE_PACING_MAX_MS 100U
#define WEBRTCPUSH_PACING_HEADROOM_PERCENT 180U
/* IDR 会产生短时大包,不能在这个窗口内把瞬时 pacing 峰值误判成网络拥塞。 */
#define WEBRTCPUSH_REMB_IDR_GRACE_MS 1000U
/* 达到 2.3Mbps 后继续发送一段时间,让浏览器有真实流量可重新估计带宽。 */
#define WEBRTCPUSH_INITIAL_PROBE_HOLD_MS 6000U
#define WEBRTCPUSH_PACING_HEADROOM_PERCENT 135U
#define WEBRTCPUSH_PACING_INTERVAL_MS 5U
#define WEBRTCPUSH_PACING_MAX_BITRATE 4000000U
#define WEBRTCPUSH_PACING_MAX_BITRATE 4200000U
#define WEBRTCPUSH_PACING_MAX_QUEUE_MS 260U
#define WEBRTCPUSH_PACING_GUARD_COOLDOWN_MS 1000U
/* 首个/刚恢复的 IDR 允许短暂排队,避免首屏关键帧刚发出就被清队列 */
......@@ -48,8 +57,9 @@
#define WEBRTCPUSH_PACING_RESYNC_IDR_MS 5000U
/* RK MPP 运行中小幅改 bps 容易顿一下;小变化只调 pacing,少重配硬编。 */
#define WEBRTCPUSH_MPP_RECONFIG_MIN_DELTA_BPS 200000U
#define WEBRTCPUSH_MPP_RECONFIG_MIN_INTERVAL_MS 5000U
#define WEBRTCPUSH_MPP_RECONFIG_MIN_DELTA_PERCENT 20U
#define WEBRTCPUSH_MPP_RECONFIG_MAX_STEP_PERCENT 25U
#define WEBRTCPUSH_MPP_RECONFIG_MIN_INTERVAL_MS 1000U
/* RTP 分片与 NACK(MTU=1200,留 SRTP/DTLS/FU 余量) */
#define WEBRTCPUSH_RTP_MAX_FRAGMENT 1050U
......
......@@ -9,4 +9,4 @@ file perms = 600
millisecond = "%d(%Y-%m-%d %H:%M:%S).%ms [%V] %m%n"
[rules]
my_log.* "/home/orangepi/car/master/log/log_2026-07-10.log"; millisecond
my_log.* "/home/orangepi/car/master/log/log_2026-07-11.log"; millisecond
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment