需求：仔细审核和分析【】内提供的源代码，运行后出现""""   """"所示问题，怎么修改？请最后请给出修改后的完整代码。其代码的核心功能如下：
【】内的代码，其实现功能是根据配置文件camera_config.ini的接入两路相机，实现的是2路视频流正常接入，然后2路视频每隔5秒抽帧图片数据形成一张图片，
然后发送给算法服务分析。目前的思路：整体的代码，为了降低CPU的使用率，在解码器之前就丢弃不必要的帧，从而减少解码器的工作量。为此，我们可以在解码器之前添加一个Pad Probe，在该Probe中根据时间间隔来丢弃帧。
【
1.video_capture.h文件
#pragma once

#include <string>
#include <memory>
#include <chrono>
#include <gst/gst.h>
#include <gst/video/video.h>
#include <opencv2/opencv.hpp>
#include "config_manager.h"
#include "frame_processor.h"
#include <mutex>

class VideoCapture {
public:
    VideoCapture(const CameraConfig& config);
    ~VideoCapture();

    bool start();
    bool stop();

    bool isRunning() const;

    void setFrameProcessor(std::shared_ptr<FrameProcessor> processor);

private:
    static GstFlowReturn onNewSample(GstElement* sink, gpointer data);
    static gboolean onBusMessage(GstBus* bus, GstMessage* msg, gpointer data);

    void reconnect();

    std::chrono::steady_clock::time_point last_frame_time_;

    bool is_running_;
    GstElement* pipeline_;
    std::shared_ptr<FrameProcessor> frame_processor_;
    CameraConfig config_;

    std::mutex reconnect_mutex_;
    int reconnect_attempts_;
    std::vector<int> reconnect_intervals_;
};
2.video_capture.cpp文件
#include "video_capture.h"
#include "logger.h"
#include <gst/app/gstappsink.h>
#include <gst/video/video.h>
#include <iomanip>

VideoCapture::VideoCapture(const CameraConfig &config)
    : config_(config), pipeline_(nullptr),
      is_running_(false),
      reconnect_attempts_(0),
      last_frame_time_(std::chrono::steady_clock::now())
{
    if (!gst_is_initialized())
    {
        gst_init(NULL, NULL); // Initialize GStreamer if not already initialized
    }

    reconnect_intervals_ = {5, 10, 30, 180}; // 秒
}

VideoCapture::~VideoCapture()
{
    stop();
}

void VideoCapture::setFrameProcessor(std::shared_ptr<FrameProcessor> processor)
{
    frame_processor_ = processor;
}

bool VideoCapture::start()
{
    std::lock_guard<std::mutex> lock(reconnect_mutex_);

    if (!frame_processor_)
    {
        LOG_ERROR("No frame processor set for camera " + config_.name);
        return false;
    }

    if (is_running_)
    {
        LOG_WARNING("Camera " + config_.name + " is already running");
        return true;
    }

    // 确保清理之前的pipeline
    if (pipeline_)
    {
        gst_element_set_state(pipeline_, GST_STATE_NULL);
        gst_object_unref(pipeline_);
        pipeline_ = nullptr;
    }

    GError *error = nullptr;
    std::string sink_name = "sink_" + config_.name; // 为每个摄像头的appsink设置唯一名称

    // 使用skip-frame设置为nonkey的解码器
    std::string decoder = "avdec_h264"; // 根据您的系统调整硬件解码器

    // **构建GStreamer管道，并在解码器中设置skip-frame属性**
    std::ostringstream pipeline_ss;
    pipeline_ss << "rtspsrc location=\"" << config_.rtsp_url << "\" protocols=tcp latency=300 ! "
                << "rtph264depay ! h264parse ! "
                << decoder << " skip-frame=nonkey ! "
                << "videoconvert ! appsink name=" << sink_name << " max-buffers=1 drop=true";

    std::string pipeline_str = pipeline_ss.str();

    pipeline_ = gst_parse_launch(pipeline_str.c_str(), &error);
    if (error)
    {
        LOG_ERROR("Failed to create pipeline for camera " + config_.name + ": " + error->message);
        g_error_free(error);
        return false;
    }

    GstElement *sink = gst_bin_get_by_name(GST_BIN(pipeline_), sink_name.c_str());
    if (!sink)
    {
        LOG_ERROR("Failed to get sink element for camera " + config_.name);
        gst_object_unref(pipeline_);
        pipeline_ = nullptr;
        return false;
    }

    g_object_set(G_OBJECT(sink),
                 "emit-signals", TRUE,
                 "sync", FALSE,
                 "max-buffers", 1,
                 "drop", TRUE,
                 NULL);

    g_signal_connect(sink, "new-sample", G_CALLBACK(onNewSample), this);
    gst_object_unref(sink);

    // 处理GStreamer的bus消息，监听错误和EOS
    GstBus *bus = gst_element_get_bus(pipeline_);
    gst_bus_add_watch(bus, (GstBusFunc)onBusMessage, this);
    gst_object_unref(bus);

    // 等待pipeline完全启动
    GstStateChangeReturn ret = gst_element_set_state(pipeline_, GST_STATE_PLAYING);
    if (ret == GST_STATE_CHANGE_FAILURE)
    {
        LOG_ERROR("Failed to start pipeline for camera " + config_.name);
        gst_object_unref(pipeline_);
        pipeline_ = nullptr;
        return false;
    }

    // 验证pipeline是否真正启动
    GstState state;
    ret = gst_element_get_state(pipeline_, &state, nullptr, 5 * GST_SECOND);
    if (ret != GST_STATE_CHANGE_SUCCESS || state != GST_STATE_PLAYING)
    {
        LOG_ERROR("Pipeline failed to reach PLAYING state for camera " + config_.name);
        gst_element_set_state(pipeline_, GST_STATE_NULL);
        gst_object_unref(pipeline_);
        pipeline_ = nullptr;
        return false;
    }

    is_running_ = true;
    LOG_INFO("Started video capture for camera " + config_.name);
    return true;
}

bool VideoCapture::stop()
{
    std::lock_guard<std::mutex> lock(reconnect_mutex_);
    if (!is_running_)
        return true;

    if (pipeline_)
    {
        gst_element_set_state(pipeline_, GST_STATE_NULL);
        gst_object_unref(pipeline_);
        pipeline_ = nullptr;
    }

    is_running_ = false;
    return true;
}

bool VideoCapture::isRunning() const
{
    return is_running_;
}

GstFlowReturn VideoCapture::onNewSample(GstElement *sink, gpointer data)
{
    VideoCapture *self = static_cast<VideoCapture *>(data);
    if (!self)
    {
        g_print("Error: Invalid VideoCapture instance\n");
        return GST_FLOW_ERROR;
    }

    // 获取示例
    GstSample *sample_ptr = nullptr;
    g_signal_emit_by_name(sink, "pull-sample", &sample_ptr);
    if (!sample_ptr)
    {
        g_print("Error: Failed to pull sample for camera %s\n", self->config_.name.c_str());
        return GST_FLOW_ERROR;
    }

    // 使用智能指针管理 GstSample
    std::unique_ptr<GstSample, decltype(&gst_sample_unref)> sample(sample_ptr, gst_sample_unref);

    // 获取缓冲区
    GstBuffer *buffer = gst_sample_get_buffer(sample.get());
    if (!buffer)
    {
        g_print("Error: Failed to get buffer from sample for camera %s\n", self->config_.name.c_str());
        return GST_FLOW_ERROR;
    }

    try
    {
        // 获取 caps 和视频格式信息
        GstCaps *caps = gst_sample_get_caps(sample.get());
        if (!caps)
        {
            g_print("Error: No caps in sample for camera %s\n", self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        GstStructure *structure = gst_caps_get_structure(caps, 0);
        if (!structure)
        {
            g_print("Error: No structure in caps for camera %s\n", self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        // 获取视频格式
        const gchar *format = gst_structure_get_string(structure, "format");
        if (!format)
        {
            g_print("Error: No format in caps for camera %s\n", self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        // 获取视频尺寸
        int width = 0, height = 0;
        if (!gst_structure_get_int(structure, "width", &width) ||
            !gst_structure_get_int(structure, "height", &height) ||
            width <= 0 || height <= 0)
        {
            g_print("Error: Invalid dimensions (%dx%d) for camera %s\n",
                    width, height, self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        // Map buffer
        GstMapInfo map;
        if (!gst_buffer_map(buffer, &map, GST_MAP_READ))
        {
            g_print("Error: Failed to map buffer for camera %s\n", self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        // 使用RAII确保buffer被正确unmap
        struct MapGuard
        {
            GstBuffer *buffer;
            GstMapInfo *map;
            ~MapGuard()
            {
                if (buffer && map)
                    gst_buffer_unmap(buffer, map);
            }
        } mapGuard{buffer, &map};

        // 确定正确的 Mat 类型
        int cv_type;
        if (g_str_equal(format, "RGB"))
        {
            cv_type = CV_8UC3;
        }
        else if (g_str_equal(format, "RGBA"))
        {
            cv_type = CV_8UC4;
        }
        else if (g_str_equal(format, "GRAY8"))
        {
            cv_type = CV_8UC1;
        }
        else if (g_str_equal(format, "BGR"))
        {
            cv_type = CV_8UC3;
        }
        else if (g_str_equal(format, "I420"))
        {
            cv_type = CV_8UC1;
        }
        else
        {
            g_print("Error: Unsupported format %s for camera %s\n", format, self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        // 安全地创建 Mat
        cv::Mat frame;
        {
            cv::Mat temp(height, width, cv_type, (void *)map.data);
            if (temp.empty())
            {
                g_print("Error: Failed to create temp frame for camera %s\n", self->config_.name.c_str());
                return GST_FLOW_ERROR;
            }

            // 确保数据被完全复制
            frame = temp.clone();
        }

        if (frame.empty())
        {
            g_print("Error: Failed to clone frame for camera %s\n", self->config_.name.c_str());
            return GST_FLOW_ERROR;
        }

        // 如果需要，转换为 BGR 格式
        if (!g_str_equal(format, "BGR"))
        {
            cv::Mat bgr_frame;
            if (g_str_equal(format, "RGB"))
            {
                cv::cvtColor(frame, bgr_frame, cv::COLOR_RGB2BGR);
            }
            else if (g_str_equal(format, "RGBA"))
            {
                cv::cvtColor(frame, bgr_frame, cv::COLOR_RGBA2BGR);
            }
            else if (g_str_equal(format, "GRAY8"))
            {
                cv::cvtColor(frame, bgr_frame, cv::COLOR_GRAY2BGR);
            }
            else if (g_str_equal(format, "I420"))
            {
                cv::cvtColor(frame, bgr_frame, cv::COLOR_YUV2BGR_I420);
            }
            frame = bgr_frame;
        }

        // 处理帧
        if (self->frame_processor_)
        {
            try
            {
                self->frame_processor_->processFrame(frame);
            }
            catch (const std::exception &e)
            {
                g_print("Error: Frame processing exception for camera %s: %s\n",
                        self->config_.name.c_str(), e.what());
                return GST_FLOW_ERROR;
            }
        }

        return GST_FLOW_OK;
    }
    catch (const cv::Exception &e)
    {
        g_print("OpenCV Error in onNewSample for camera %s: %s\n",
                self->config_.name.c_str(), e.what());
        return GST_FLOW_ERROR;
    }
    catch (const std::exception &e)
    {
        g_print("Fatal: Unhandled exception in onNewSample for camera %s: %s\n",
                self->config_.name.c_str(), e.what());
        return GST_FLOW_ERROR;
    }
    catch (...)
    {
        g_print("Fatal: Unknown exception in onNewSample for camera %s\n",
                self->config_.name.c_str());
        return GST_FLOW_ERROR;
    }
}

gboolean VideoCapture::onBusMessage(GstBus *bus, GstMessage *msg, gpointer data)
{
    VideoCapture *self = static_cast<VideoCapture *>(data);

    switch (GST_MESSAGE_TYPE(msg))
    {
    case GST_MESSAGE_EOS:
        LOG_WARNING("Stream reached EOS for camera " + self->config_.name);
        self->reconnect();
        break;
    case GST_MESSAGE_ERROR:
    {
        GError *err;
        gchar *debug_info;
        gst_message_parse_error(msg, &err, &debug_info);
        LOG_ERROR("GStreamer error for camera " + self->config_.name + ": " + err->message);
        self->reconnect();
        g_clear_error(&err);
        g_free(debug_info);
        break;
    }
    default:
        break;
    }
    return TRUE;
}

void VideoCapture::reconnect()
{
    std::lock_guard<std::mutex> lock(reconnect_mutex_);
    if (is_running_)
    {
        gst_element_set_state(pipeline_, GST_STATE_NULL);
        gst_object_unref(pipeline_);
        pipeline_ = nullptr;
        is_running_ = false;
    }

    int wait_time = reconnect_attempts_ < reconnect_intervals_.size() ? reconnect_intervals_[reconnect_attempts_] : reconnect_intervals_.back();
    LOG_INFO("Attempting to reconnect camera " + config_.name + " in " + std::to_string(wait_time) + " seconds");
    std::this_thread::sleep_for(std::chrono::seconds(wait_time));

    reconnect_attempts_++;
    start();
}
】
""""
(triton) (base) chen@chen-Precision-3660:~/data/algorithm_analysis_service/build$ export GST_DEBUG=3
(triton) (base) chen@chen-Precision-3660:~/data/algorithm_analysis_service/build$ ./algorithm_analysis_service
2024-11-18 09:25:42 [INFO] Starting Video Analysis Service...
2024-11-18 09:25:42 [INFO] Configuration loaded successfully
2024-11-18 09:25:42 [INFO] Loaded camera config:
2024-11-18 09:25:42 [INFO]   Camera Name: room1
2024-11-18 09:25:42 [INFO]   RTSP URL: rtsp://117.71.99.41:5544/live/43130100001320000006_43130100001320000006?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVSUQiOjAsIlVzZXJuYW1lIjoiNDMxMzAxMDAwMDEzMjAwMDAwMDZfNDMxMzAxMDAwMDEzMjAwMDAwMDYiLCJHcm91cElEIjowLCJpc3MiOiJ4eEBnb2xhbmcuc3BhY2UiLCJleHAiOjE3Mzc3MTI5MDMsImlhdCI6MTczMTQ5MjEwM30.NT9CkDrZVLRZGjxX_DJiCXH0yvCN64D01gr1eXDJHbI&expired=20250124180143
constuct FrameProcessor: triton_client_
0:00:00.022393559 794128 0x5610a218be00 ERROR           GST_PIPELINE grammar.y:453:gst_parse_element_set: could not set property "skip-frame" in element "avdec_h264-0" to "nonkey"
2024-11-18 09:25:42 [ERROR] Failed to create pipeline for camera room1: could not set property "skip-frame" in element "avdec_h264-0" to "nonkey"
2024-11-18 09:25:42 [ERROR] Failed to start video capture for camera: room1
2024-11-18 09:25:42 [INFO] Loaded camera config:
2024-11-18 09:25:42 [INFO]   Camera Name: room2
2024-11-18 09:25:42 [INFO]   RTSP URL: rtsp://117.71.99.41:5544/live/43130100001320000002_43130100001320000002?token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVSUQiOjAsIlVzZXJuYW1lIjoiNDMxMzAxMDAwMDEzMjAwMDAwMDJfNDMxMzAxMDAwMDEzMjAwMDAwMDIiLCJHcm91cElEIjowLCJpc3MiOiJ4eEBnb2xhbmcuc3BhY2UiLCJleHAiOjE3Mzc3MTI5NDIsImlhdCI6MTczMTQ5MjE0Mn0.VuU_FjJZ0JqevQt3PJjKMhsJjOn4-WU75xf5XYut5as&expired=20250124180222
constuct FrameProcessor: triton_client_
0:00:00.023935663 794128 0x5610a218be00 ERROR           GST_PIPELINE grammar.y:453:gst_parse_element_set: could not set property "skip-frame" in element "avdec_h264-1" to "nonkey"
2024-11-18 09:25:42 [ERROR] Failed to create pipeline for camera room2: could not set property "skip-frame" in element "avdec_h264-1" to "nonkey"
2024-11-18 09:25:42 [ERROR] Failed to start video capture for camera: room2
""""