当前位置:   article > 正文

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

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);
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

需要实现几个基本的操作,比如: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;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131

完成!

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/198367
推荐阅读
相关标签
  

闽ICP备14008679号