调整画质

This commit is contained in:
cxh 2026-01-06 16:29:40 +08:00
parent 430e44d9fa
commit 5675440974

View File

@ -63,114 +63,41 @@ void RTMPManager::init()
std::string RTMPManager::make_key(const std::string& name) { return name + "_main"; }
// ========== 创建推流管线 ==========
GstElement* RTMPManager::create_pipeline(const Camera& cam)
{
const int width = cam.width;
const int height = cam.height;
const int fps = cam.fps;
const int bitrate = cam.bitrate;
// MediaMTX 中的 stream key
const std::string stream_name = cam.name;
// RTMP 推送到 MediaMTX
// mediamtx.yml 中 paths 会自动创建
const std::string rtmp_url = "rtmp://127.0.0.1:1935/" + stream_name;
/*
* Pipeline
* v4l2src -> mpph264enc -> h264parse -> flvmux -> rtmpsink
*
* - 使 tee
* - MediaMTX
* - RTMP TCP
*/
std::string pipeline_str = "v4l2src name=src device=" + cam.device +
" ! video/x-raw,format=NV12,width=" + std::to_string(width) +
",height=" + std::to_string(height) + ",framerate=" + std::to_string(fps) +
"/1 "
" ! mpph264enc bps=" +
std::to_string(bitrate) + " gop=" + std::to_string(fps) +
" rc-mode=cbr "
" ! h264parse name=parse "
" ! flvmux streamable=true "
" ! rtmpsink location=\"" +
rtmp_url +
"\" "
" sync=false async=false";
GError* error = nullptr;
GstElement* pipeline = gst_parse_launch(pipeline_str.c_str(), &error);
if (error)
{
LOG_ERROR(std::string("[RTMP] Pipeline creation failed: ") + error->message);
g_error_free(error);
return nullptr;
}
return pipeline;
}
// GstElement* RTMPManager::create_pipeline(const Camera& cam)
// {
// const int out_width = cam.width; // 推流分辨率(如 1280 / 960 / 720
// const int out_height = cam.height;
// const int width = cam.width;
// const int height = cam.height;
// const int fps = cam.fps;
// const int bitrate = cam.bitrate;
// // MediaMTX stream key
// // MediaMTX 中的 stream key
// const std::string stream_name = cam.name;
// // RTMP 推送到 MediaMTX
// // mediamtx.yml 中 paths 会自动创建
// const std::string rtmp_url = "rtmp://127.0.0.1:1935/" + stream_name;
// /*
// * A 方案 Pipeline
// * Pipeline 说明:
// * v4l2src -> mpph264enc -> h264parse -> flvmux -> rtmpsink
// *
// * v4l2src (原生 1280x960)
// * -> videoscale + caps编码前缩放
// * -> queue低延迟
// * -> mpph264encCBR
// * -> h264parse
// * -> flvmux
// * -> rtmpsink
// * - 不使用 tee降低死锁概率
// * - 不引入音频MediaMTX 不强制要求)
// * - 纯视频、纯 RTMP、纯 TCP
// */
// std::string pipeline_str = "v4l2src name=src device=" + cam.device +
// " io-mode=dmabuf "
// // ⭐ 相机真实输出:原生 1280x960
// "! video/x-raw,format=NV12,"
// "width=1280,height=960,"
// "framerate=" +
// std::to_string(fps) +
// " ! video/x-raw,format=NV12,width=" + std::to_string(width) +
// ",height=" + std::to_string(height) + ",framerate=" + std::to_string(fps) +
// "/1 "
// // ⭐ 编码前缩放(关键)
// "! videoscale "
// "! video/x-raw,"
// "width=" +
// std::to_string(out_width) + ",height=" + std::to_string(out_height) +
// " "
// // ⭐ 低延迟队列,防止下游阻塞反噬 v4l2
// "! queue max-size-buffers=2 max-size-time=0 leaky=downstream "
// // ⭐ 硬件编码SIM 卡友好
// "! mpph264enc "
// "rc-mode=cbr "
// "bps=" +
// std::to_string(bitrate) +
// " "
// "gop=" +
// std::to_string(fps) +
// " "
// "header-mode=each-idr "
// "profile=baseline "
// "! h264parse config-interval=1 "
// "! flvmux streamable=true "
// "! rtmpsink location=\"" +
// " ! mpph264enc bps=" +
// std::to_string(bitrate) + " gop=" + std::to_string(fps) +
// " rc-mode=cbr "
// " ! h264parse name=parse "
// " ! flvmux streamable=true "
// " ! rtmpsink location=\"" +
// rtmp_url +
// "\" "
// "sync=false async=false";
// " sync=false async=false";
// GError* error = nullptr;
// GstElement* pipeline = gst_parse_launch(pipeline_str.c_str(), &error);
@ -184,6 +111,65 @@ GstElement* RTMPManager::create_pipeline(const Camera& cam)
// return pipeline;
// }
GstElement* RTMPManager::create_pipeline(const Camera& cam)
{
const int out_width = cam.width;
const int out_height = cam.height;
const int fps = 30; // ⭐ 强制 30
const int bitrate = cam.bitrate; // 建议 3.5M~4.0M
const int gop = 15; // ⭐ 半秒 I 帧
const std::string stream_name = cam.name;
const std::string rtmp_url = "rtmp://127.0.0.1:1935/" + stream_name;
std::string pipeline_str = "v4l2src name=src device=" + cam.device +
" io-mode=dmabuf "
"! video/x-raw,format=NV12,"
"width=1280,height=960,"
"framerate=30/1 "
"! videoscale "
"! video/x-raw,"
"width=" +
std::to_string(out_width) + ",height=" + std::to_string(out_height) +
" "
"! queue max-size-buffers=2 max-size-time=0 leaky=downstream "
"! mpph264enc "
"rc-mode=cbr "
"bps=" +
std::to_string(bitrate) +
" "
"gop=" +
std::to_string(gop) +
" "
"header-mode=each-idr "
"profile=main " // ⭐ 关键改动
"! h264parse config-interval=1 "
"! video/x-h264,stream-format=avc,alignment=au "
"! flvmux streamable=true "
"! rtmpsink location=\"" +
rtmp_url +
"\" "
"sync=false async=false";
GError* error = nullptr;
GstElement* pipeline = gst_parse_launch(pipeline_str.c_str(), &error);
if (error)
{
LOG_ERROR(std::string("[RTMP] Pipeline creation failed: ") + error->message);
g_error_free(error);
return nullptr;
}
return pipeline;
}
// ========== 主推流循环 ==========
void RTMPManager::stream_loop(Camera cam, StreamContext* ctx)
{