CURLOPT_INTERLEAVEFUNCTION回调函数始终将nullptr用作用户数据指针

问题描述 投票:0回答:1

我一直在尝试通过CURL库从rtsp流中获取数据(我以前尝试过使用libvlc,但也失败了)。出于某种原因,我传递给应通过函数获取数据的回调的user_data始终为null。以下是一些代码段:这是应该运行并提取数据包的部分

void CRTSPStream::Run() {
    curl_socket_t socket;
    CURLcode res = curl_easy_getinfo(m_CurrentCURL, CURLINFO_ACTIVESOCKET, &socket);
    Data streamData;
    if(res != CURLE_OK) {
        throw Camera::InputException("RTSP Receive data socket error.", 4003);
    }
    while(m_ShouldRun) {
        m_CURLResults = curl_easy_setopt(m_CurrentCURL, CURLOPT_INTERLEAVEFUNCTION, &CRTSPStream::WriteCallback);
        if (m_CURLResults != CURLE_OK) throw Camera::InputException("RTSP unable to set INTERLEAVE buffer.", 4004);
        m_CURLResults = curl_easy_setopt(m_CurrentCURL, CURLOPT_INTERLEAVEDATA, &streamData);
        if (m_CURLResults != CURLE_OK) throw Camera::InputException("RTSP unable to set INTERLEAVEDATA buffer.", 4005);
        m_CURLResults = curl_easy_setopt(m_CurrentCURL, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_RECEIVE);
        if (m_CURLResults != CURLE_OK) throw Camera::InputException("RTSP unable to send RTSP REQUEST.", 4006);
        m_CURLResults = curl_easy_perform(m_CurrentCURL);
        if (m_CURLResults != CURLE_OK) throw Camera::InputException("RTSP unable to receive new data.", 4007);
        //Do something with the data

        m_Logger.Info("New Packet arrived");
    }
}

这是具有Run函数实现的类

class CRTSPStream : public Utility::Runnable {
public:
    static const std::string DEFAULT_LOGER_LEVEL;

    CRTSPStream() : m_Logger("RTSP", DEFAULT_LOGER_LEVEL) {
        m_Terminated = true;
        m_ShouldRun = false;
    }
    virtual ~CRTSPStream() { Deinit(); }
    void Init(const std::string& _url, const std::string& _transport, const std::string& _range, const std::string& _outFilename);
    void Deinit();
    void SendDescribe();
    void Setup();
    void Play();
    void SendTeardown();
    void GetMediaControlAttribude();
    void StartReceiving();
    void StopReceiving();
    virtual void Run();
private:
    size_t WriteCallback(void *_ptr, size_t _size, size_t _nmemb, void *_userdata);
    int WaitForRecvPacket(curl_socket_t _sockfd, unsigned long _miliseconds);

    Example::Logger m_Logger;
    Utility::Thread m_RecvThread;
    bool m_Terminated;
    bool m_ShouldRun;

    struct Data {
        size_t m_Size;
        char* m_Data;
    };

    Data* m_Data;
    CURL* m_CurrentCURL;
    CURLcode m_CURLResults;
    curl_version_info_data* m_CurlVersionInfo;
    std::string m_StreamURL;
    std::string m_OutStreamPath;
    std::string m_Transport;
    std::string m_Range;
    char m_Control[256];
    FILE* m_OutStream;
};

初始化,或更确切地说,RTSP描述和其他设置通过此方法发送

void CRTSPStream::Init(const std::string& _url, const std::string &_transport, const std::string &_range, const std::string& _outFilename) {
    std::stringstream ss;
    if((m_CURLResults = curl_global_init(CURL_GLOBAL_ALL)) != CURLE_OK) {
        throw Camera::InputException("RTSP failed curl_global_init", m_CURLResults);
    }
    m_CurlVersionInfo = curl_version_info(CURLVERSION_NOW);
    ss << "RTSP initialization loaded CURL version: " << m_CurlVersionInfo->version;
    m_Logger.Debug(ss.str());
    if((m_CurrentCURL = curl_easy_init()) == nullptr) {
        throw Camera::InputException("RTSP failed curl_easy_init", 5001);
    }
    //This part of the code always succeedes
    curl_easy_setopt(m_CurrentCURL, CURLOPT_VERBOSE, 0L);
    curl_easy_setopt(m_CurrentCURL, CURLOPT_NOPROGRESS, 1L);
    curl_easy_setopt(m_CurrentCURL, CURLOPT_HEADERDATA, stdout);
    curl_easy_setopt(m_CurrentCURL, CURLOPT_URL, _url.c_str());

    if((m_CURLResults = curl_easy_setopt(m_CurrentCURL, CURLOPT_RTSP_STREAM_URI, _url.c_str())) != CURLE_OK)
        throw Camera::InputException("RTSP failed to set an option to CURLOPT_RTSP_STREAM_URI", m_CURLResults);
    if((m_CURLResults = curl_easy_setopt(m_CurrentCURL, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS)) != CURLE_OK)
        throw Camera::InputException("RTSP failed to set an option to CURLOPT_RTSP_REQUEST", m_CURLResults);
    if((m_CURLResults = curl_easy_perform(m_CurrentCURL)) != CURLE_OK)
        throw Camera::InputException("RTSP failed to execute PERFORM on url: " + _url, m_CURLResults);
    m_OutStreamPath = _outFilename;

    if((m_OutStream = fopen(m_OutStreamPath.c_str(), "wb")) == NULL) {
        m_Logger.Error("RTSP Output failed to open: " + _outFilename);
    } else {
        m_Logger.Info("Writing to " + _outFilename);
    }
    m_Data = new Data();
    m_Transport = _transport;
    m_Range = _range;
    m_StreamURL = _url;
}

最后,这是回调函数:

size_t CRTSPStream::WriteCallback(void* _ptr, size_t _size, size_t _nmemb, void* _userdata) {
    Data* data = (Data*)_userdata;
    data->m_Data = new char[_nmemb*_size];
    memcpy(data->m_Data, _ptr, _size*_nmemb);
    m_Logger.Debug("Memory copied.");
    return m_Data->m_Size = _size * _nmemb;
}
通过启动启动一个新线程的StartReceiving在

Init函数之后调用Run函数,该线程调用前面提到的Run] >

我一直在尝试通过CURL库从rtsp流中获取数据(我以前尝试过使用libvlc,但也失败了)。由于某种原因,我传递给回调的user_data应该获取...
c++ curl stream segmentation-fault rtsp
1个回答
0
投票
您正在尝试将

非静态类方法

© www.soinside.com 2019 - 2024. All rights reserved.