#include "liveMedia.hh"  
#include "BasicUsageEnvironment.hh"  
#include "GroupsockHelper.hh"  
UsageEnvironment* env;  
portNumBits tunnelOverHTTPPortNum = 0;  
const char * url="rtsp://127.0.0.1:1935/vod/Extremists.m4v";  
#if defined(__WIN32__) || defined(_WIN32)  
#define snprintf _snprintf  
#endif  
int main(int argc,const char ** argv)  
{  
    //创建BasicTaskScheduler对象  
    TaskScheduler* scheduler = BasicTaskScheduler::createNew();  
    //创建BisicUsageEnvironment对象  
    env = BasicUsageEnvironment::createNew(*scheduler);  
    //创建RTSPClient对象  
    RTSPClient * rtspClient= RTSPClient::createNew(*env);  
    //由RTSPClient对象向服务器发送OPTION消息并接受回应  
    char* optionsResponse=rtspClient->sendOptionsCmd(url);  
    delete [] optionsResponse;  
    //产生SDPDescription字符串(由RTSPClient对象向服务器发送DESCRIBE消息并接受回应,根据回应的信息产生SDPDescription字符串,其中包括视音频数据的协议和解码器类型)  
    char* sdpDescription =rtspClient->describeURL(url);  
    //创建MediaSession对象(根据SDPDescription在MediaSession中创建和初始化MediaSubSession子会话对象)  
    MediaSession* session = MediaSession::createNew(*env, sdpDescription);  
    delete[] sdpDescription;  
 
    MediaSubsessionIterator iter(*session);  
    MediaSubsession *subsession;  
    while ((subsession = iter.next()) != NULL) {  
        // Creates a "RTPSource" for this subsession. (Has no effect if it's  
        // already been created.)  Returns True iff this succeeds.  
        if (!subsession->initiate()) {  
            *env << "Unable to create receiver for "" << subsession->mediumName()  
                << "/" << subsession->codecName()  
                << "" subsession: " << env->getResultMsg() << "\n";  
        } else {  
            *env << "Created receiver for "" << subsession->mediumName()  
                << "/" << subsession->codecName()  
                << "" subsession (client ports " << subsession->clientPortNum()  
                << "-" << subsession->clientPortNum()+1 << ")\n";  
            if (subsession->rtpSource() != NULL) {  
                // Because we're saving the incoming data, rather than playing  
                // it in real time, allow an especially large time threshold  
                // (1 second) for reordering misordered incoming packets:  
                unsigned const thresh = 1000000; // 1 second  
                subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);  
                // Set the RTP source's OS socket buffer size as appropriate - either if we were explicitly asked (using -B),  
                // or if the desired FileSink buffer size happens to be larger than the current OS socket buffer size.  
                // (The latter case is a heuristic, on the assumption that if the user asked for a large FileSink buffer size,  
                // then the input data rate may be large enough to justify increasing the OS socket buffer size also.)  
                int socketNum = subsession->rtpSource()->RTPgs()->socketNum();  
                unsigned curBufferSize = getReceiveBufferSize(*env, socketNum);  
                unsigned newBufferSize = setReceiveBufferTo(*env, socketNum, 100000);  
 
            }  
        }  
    }  
    //由RTSPClient对象向服务器发送SETUP消息并接受回应  
    iter.reset();  
    while ((subsession = iter.next()) != NULL) {  
        if (subsession->clientPortNum() == 0) continue; // port # was not set  
        if (!rtspClient->setupMediaSubsession(*subsession)) {  
            *env << "Failed to setup "" << subsession->mediumName()  
                << "/" << subsession->codecName()  
                << "" subsession: " << env->getResultMsg() << "\n";  
        } else {  
            *env << "Setup "" << subsession->mediumName()  
                << "/" << subsession->codecName()  
                << "" subsession (client ports " << subsession->clientPortNum()  
                << "-" << subsession->clientPortNum()+1 << ")\n";  
        }  
        if (subsession->rtpSource() != NULL) {  
            // Because we're saving the incoming data, rather than playing  
            // it in real time, allow an especially large time threshold  
            // (1 second) for reordering misordered incoming packets:  
            unsigned const thresh = 1000000; // 1 second  
            subsession->rtpSource()->setPacketReorderingThresholdTime(thresh);  
        }  
    }  
    iter.reset();  
    while ((subsession = iter.next()) != NULL) {  
        if (subsession->readSource() == NULL) continue; // was not initiated  
        char outFileName[1000];  
        static unsigned streamCounter = 0;  
        snprintf(outFileName, sizeof outFileName, "%s-%s-%d",  
            subsession->mediumName(),  
            subsession->codecName(), ++streamCounter);  
        FileSink* fileSink;  
        if (strcmp(subsession->mediumName(), "audio") == 0 &&  
            (strcmp(subsession->codecName(), "AMR") == 0 ||  
            strcmp(subsession->codecName(), "AMR-WB") == 0)) {  
                // For AMR audio streams, we use a special sink that inserts AMR frame hdrs:  
                fileSink = AMRAudioFileSink::createNew(*env, outFileName);  
        } else if (strcmp(subsession->mediumName(), "video") == 0 &&  
            (strcmp(subsession->codecName(), "H264") == 0)) {  
                // For H.264 video stream, we use a special sink that insert start_codes:  
                unsigned int num=0;  
                SPropRecord * sps=parseSPropParameterSets(subsession->fmtp_spropparametersets(),num);  
                fileSink = H264VideoFileSink::createNew(*env, outFileName,100000);  
                struct timeval tv={0,0};  
                unsigned char start_code[4] = {0x00, 0x00, 0x00, 0x01};  
                fileSink->addData(start_code, 4, tv);  
                fileSink->addData(sps[0].sPropBytes,sps[0].sPropLength,tv);  
                fileSink->addData(start_code, 4, tv);  
                fileSink->addData(sps[1].sPropBytes,sps[1].sPropLength,tv);  
                delete[] sps;  
        } else {  
            // Normal case:  
            fileSink = FileSink::createNew(*env, outFileName);  
        }  
        subsession->sink = fileSink;  
        subsession->sink->startPlaying(*(subsession->readSource()),NULL,NULL);  
    }  
    rtspClient->playMediaSession(*session, 0.0f, 0.0f, (float)1.0);  
    env->taskScheduler().doEventLoop(); // does not return  
    return 0; // only to prevent compiler warning  
}

参照openRTSP写的一个RTSP client 加了一些注解的更多相关文章

  1. C语言写了一个socket client端,适合windows和linux,用GCC编译运行通过

    ////////////////////////////////////////////////////////////////////////////////* gcc -Wall -o c1 c1 ...

  2. [jQuery插件]手写一个图片懒加载实现

    教你做图片懒加载插件 那一年 那一年,我还年轻 刚接手一个ASP.NET MVC 的 web 项目, (C#/jQuery/Bootstrap) 并没有做 web 的经验,没有预留学习时间, (作为项 ...

  3. 用C3中的animation和transform写的一个模仿加载的时动画效果

    用用C3中的animation和transform写的一个模仿加载的时动画效果! 不多说直接上代码; html标签部分 <div class="wrap"> <h ...

  4. 输入一个数字n 如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数 写出一个函数

    题目: 输入一个数字n  如果n为偶数则除以2,若为奇数则加1或者减1,直到n为1,求最少次数  写出一个函数 首先,这道题肯定可以用动态规划来解, n为整数时,n的解为 n/2 的解加1 n为奇数时 ...

  5. 用c#写的一个局域网聊天客户端 类似小飞鸽

    用c#写的一个局域网聊天客户端 类似小飞鸽 摘自: http://www.cnblogs.com/yyl8781697/archive/2012/12/07/csharp-socket-udp.htm ...

  6. 搞了我一下午竟然是web.config少写了一个点

    Safari手机版居然有个这么愚蠢的bug,浪费了我整个下午,使尽浑身解数,国内国外网站搜索解决方案,每一行代码读了又想想了又读如此不知道多少遍,想破脑袋也想不通到底哪里出了问题,结果竟然是web.c ...

  7. C# 写的一个生成随机汉语名字的小程序

    最近因为要做数据库相关的测试,频繁使用到测试数据,手动添加太过于麻烦,而且复用性太差,因此干脆花了点时间写了一个生成随机姓名和相关数据的类,贴在这里,有需用的同志们可以参考一下.代码本身质量不好,也不 ...

  8. R入门-第一次写了一个完整的时间序列分析代码

    纪念一下,在心心念念想从会计本科转为数据分析师快两年后,近期终于迈出了使用R的第一步,在参考他人的例子前提下,成功写了几行代码.用成本的角度来说,省去了部门去买昂贵的数据分析软件的金钱和时间,而对自己 ...

  9. 升级WebService图形服务,将K10.2和K10.3写到一个类库,所有服务放在一个类库

    问题描述: 平时负责电子政务和图形调用部分,凡是牵涉到图形的都需要调用WebService服务,因此很多工程都需要添加web服务引用,现在WebForm的工程一个是10.2版本,一个是10.3版本,区 ...

随机推荐

  1. framework层和native层实现联网控制(iptable方式)

    最近工作中,需要开发一个功能----联网控制,这个功能其实用过root的安卓机应该都知道,禁止某个应用连接移动网络或者wifi. root后,通过su去执行iptable的命令就可以根据uid去控制应 ...

  2. HTML与CSS绘制简单DIV布局

    HTML代码<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF ...

  3. fatal error LNK1112: module machine type 'X86' conflicts with target machine type 'x64'

    xxxxxx.lib(xxxxxx.obj) : fatal error LNK1112: module machine type 'X86' conflicts with target machin ...

  4. B - 确定比赛名次

    B - 确定比赛名次 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Submit S ...

  5. (总结)Nginx/LVS/HAProxy负载均衡软件的优缺点详解

    PS:Nginx/LVS/HAProxy是目前使用最广泛的三种负载均衡软件,本人都在多个项目中实施过,参考了一些资料,结合自己的一些使用经验,总结一下. 一般对负载均衡的使用是随着网站规模的提升根据不 ...

  6. SSE && WebSockets

    SSE && WebSockets 参考 http://www.bitscn.com/school/HTMLCSS/201402/194940.html WebSockets 定义了一 ...

  7. PL/SQL database character set(AL32UTF8) and Client character set(ZHS16GBK) are different

    启动PL/SQL Developer 报字符编码不一致错误 Database character set (AL32UTF8) and Client character set (ZHS16GBK) ...

  8. Date对象需要注意的点

    var today=new Date(); Date对象取得了PC内部时钟的一个快照,并同时返回一个Date对象实例. 注意静态Date对象和Date对象实例的差别,后者包含一个实际的日期值.毫秒为单 ...

  9. 完美解决CTRL+空格不能切换中/英文输入法的问题

    首先任务栏上的输入法图标上点右键选择设置. 然后选择键设置,双击第一个“在不同的输入语言之间切换”先勾选“切换输入语言”下面选择左手ALT.取消右边“切换键盘布局”前的勾. 然后进入“中文(简体)输入 ...

  10. iOS开发笔记 基于wsdl2objc调用asp.net WebService

    1.准备 先下载待会要用到的工具 WSDL2ObjC-0.6.zip WSDL2ObjC-0.7-pre1.zip 我用的是WSDL2ObjC-0.6.zip 1.1搭建asp.net WebServ ...