C++实践(二)C++实现基于curl的RTSP通信

这篇记录我在2015年的时候写的一个从远程摄像头服务器读取视频流的工作。先介绍RTSP通信部分。

RTSP协议

RTSP(Real Time Streaming Protocol)是由Real Network和Netscape共同提出的如何有效地在IP网络上传输流媒体数据的应用层协议。RTSP对流媒体提供了诸如暂停,快进等控制,而它本身并不传输数据,RTSP的作用相当于流媒体服务器的远程控制。服务器端可以自行选择使用TCP或UDP来传送串流内容,它的语法和运作跟HTTP 1.1类似,但并不特别强调时间同步,所以比较能容忍网络延迟。

参考资料:
http://blog.csdn.net/lory17/article/details/60144734

libcurl

libcurl主要功能就是用不同的协议连接和沟通不同的服务器~也就是相当封装了的sockPHP 支持libcurl(允许你用不同的协议连接和沟通不同的服务器)。, libcurl当前支持http, https, ftp, gopher, telnet, dict, file, 和ldap 协议。libcurl同样支持HTTPS证书授权,HTTP POST, HTTP PUT, FTP 上传(当然你也可以使用PHP的ftp扩展), HTTP基本表单上传,代理,cookies,和用户认证。
https://baike.baidu.com/item/libcurl/5256898?fr=aladdin

基于libcurl实现RTSP

#pragma once
#include <string>

struct curl_slist;
typedef void CURL;

class RTSPClient
{
public:
    RTSPClient(std::string url);
    ~RTSPClient();
    void options(const char *uri);
    std::string describe(const char *uri);
    void setup(const char *uri,const char *transport);
    void play(const char *uri,const char *range);
    void teardown(const char *uri);
private:
    CURL *mCurl = NULL;
    std::string mUrl;


};

//回调函数
static size_t onWriteData(void *buffer, size_t size, size_t nmemb, void *lpvoid);
static size_t onHeader(char *buffer, size_t size, size_t nitems, void *userdata);

需要实现几个基本的操作,比如:setup,play,teardown等。回调函数定义成静态函数。

#include "RTSPClient.h"
#include <curl/curl.h>
#include <string>

using std::string;


RTSPClient::RTSPClient(std::string url)
{
    CURLcode res;
    //In windows, this will init the winsock stuff
    res = curl_global_init(CURL_GLOBAL_ALL);
    if (res == CURLE_OK) {
        curl_version_info_data *data = curl_version_info(CURLVERSION_NOW);
        fprintf(stderr, "    cURL V%s loaded\n", data->version);
        /* get a curl handle */
        mCurl = curl_easy_init();
        if (mCurl != NULL) {
            curl_easy_setopt(mCurl, CURLOPT_URL, url.c_str());
            curl_easy_setopt(mCurl, CURLOPT_PROTOCOLS, (long)CURLPROTO_RTSP);
            mUrl = url;
        }
        else {
            fprintf(stderr, "curl_easy_init() failed\n");
        }
    }
    else {
        fprintf(stderr, "curl_global_init(%s) failed: %d\n",
            "CURL_GLOBAL_ALL", res);
    }
}


RTSPClient::~RTSPClient()
{
    curl_global_cleanup();
}

void RTSPClient::options(const char *uri)
{
    string responseHeader;
    curl_easy_setopt(mCurl, CURLOPT_RTSP_STREAM_URI, uri);
    curl_easy_setopt(mCurl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_OPTIONS);
    //应答消息头部
    curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, onHeader);
    //打印到字符串
    curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, (void *)&responseHeader);
    CURLcode res=curl_easy_perform(mCurl);
}

string RTSPClient::describe(const char *uri)
{
    string responseStr;
    string responseHeader;
    curl_easy_setopt(mCurl, CURLOPT_RTSP_STREAM_URI, uri);
    curl_easy_setopt(mCurl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_DESCRIBE);
    //应答消息主体
    curl_easy_setopt(mCurl, CURLOPT_WRITEFUNCTION, onWriteData);
    //打印到字符串
    curl_easy_setopt(mCurl, CURLOPT_WRITEDATA, (void *)&responseStr);
    //应答消息头部
    curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, onHeader);
    //打印到字符串
    curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, (void *)&responseHeader);

    curl_easy_perform(mCurl);

    return responseStr;
}

void RTSPClient::setup(const char *uri,const char *transport)
{
    string responseHeader;
    curl_easy_setopt(mCurl, CURLOPT_RTSP_STREAM_URI, uri);
    curl_easy_setopt(mCurl, CURLOPT_RTSP_TRANSPORT, transport);
    curl_easy_setopt(mCurl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_SETUP);
    //应答消息头部
    curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, onHeader);
    //打印到字符串
    curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, (void *)&responseHeader);
    curl_easy_perform(mCurl);
}

void RTSPClient::play(const char *uri,const char *range)
{
    string responseHeader;
    curl_easy_setopt(mCurl, CURLOPT_RTSP_STREAM_URI, uri);
    curl_easy_setopt(mCurl, CURLOPT_RANGE, range);
    curl_easy_setopt(mCurl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_PLAY);
    //应答消息头部
    curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, onHeader);
    //打印到字符串
    curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, (void *)&responseHeader);
    curl_easy_perform(mCurl);
}

void RTSPClient::teardown(const char * uri)
{
    string responseHeader;
    curl_easy_setopt(mCurl, CURLOPT_RTSP_REQUEST, (long)CURL_RTSPREQ_TEARDOWN);
    //应答消息头部
    curl_easy_setopt(mCurl, CURLOPT_HEADERFUNCTION, onHeader);
    //打印到字符串
    curl_easy_setopt(mCurl, CURLOPT_HEADERDATA, (void *)&responseHeader);
    curl_easy_perform(mCurl);
}



static size_t onWriteData(void *buffer, size_t size, size_t nmemb, void *lpvoid) {
    string *str = dynamic_cast<string *>((string *)lpvoid);
    if (str == NULL || buffer == NULL) {
        return -1;
    }
    char *data = (char *)buffer;
    str->append(data, size*nmemb);
    return nmemb;
}

static size_t onHeader(char *buffer, size_t size,
    size_t nitems, void *userdata)
{
    /* received header is nitems * size long in 'buffer' NOT ZERO TERMINATED */
    /* 'userdata' is set with CURLOPT_HEADERDATA */
    string *str = (string *)userdata;
    if (str == NULL || buffer == NULL) {
        return -1;
    }
    str->append(buffer, size*nitems);
    return nitems * size;
}

完成!

评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值