使用librtmp推流/拉流

准备工作

#include "librtmp/rtmp_sys.h"
#include "librtmp/log.h"

#pragma comment(lib, "librtmp.lib")
#pragma comment(lib, "WS2_32.lib")

WORD version;
WSADATA wsaData;
version = MAKEWORD(1, 1);
WSAStartup(version, &wsaData);

int res = 0;
RTMP* rtmp =  RTMP_Alloc();
RTMP_Init(rtmp);

推流

    res = RTMP_SetupURL(rtmp, "rtmp://192.168.34.40/live/test");//推流
    PRINTERROR(res, 1, "RTMP_SetupURL error.\n");
    //if unable,the AMF command would be 'play' instead of 'publish'
    RTMP_EnableWrite(rtmp);//推流要设置写
    res = RTMP_Connect(rtmp, NULL);
    PRINTERROR(res, 1, "RTMP_Connect error.\n");
    res = RTMP_ConnectStream(rtmp,0);
    PRINTERROR(res, 1, "RTMP_ConnectStream error.\n");

    //推流
    FILE *fp_push=fopen("save.flv","rb");
    FlvHeader flvheader;
    fread(&flvheader, sizeof(flvheader), 1, fp_push);
    int32_t preTagLen = 0;//前一个Tag长度
    fread(&preTagLen, 4, 1, fp_push);
    TagHeader tagHeader;
    uint32_t begintime=RTMP_GetTime(),nowtime,pretimetamp = 0;

    while (true)
    {
        fread(&tagHeader, sizeof(tagHeader), 1, fp_push);
        if(tagHeader.type != 0x09)
        {
            int num = FINT24TOINT(tagHeader.datalen);
            fseek(fp_push, FINT24TOINT(tagHeader.datalen)+4, SEEK_CUR);
            continue;
        }
        fseek(fp_push, -sizeof(tagHeader), SEEK_CUR);
        if((nowtime=RTMP_GetTime()-begintime)<pretimetamp)
        {
            printf("%d - %d\n", pretimetamp, nowtime);
            Sleep(pretimetamp-nowtime);
            continue;
        }

        char* pFileBuf=(char*)malloc(11+FINT24TOINT(tagHeader.datalen)+4);
        memset(pFileBuf,0,11+FINT24TOINT(tagHeader.datalen)+4);
        if(fread(pFileBuf,1,11+FINT24TOINT(tagHeader.datalen)+4,fp_push)!=11+FINT24TOINT(tagHeader.datalen)+4)
            break;

        if ((res = RTMP_Write(rtmp,pFileBuf,11+FINT24TOINT(tagHeader.datalen)+4)) <= 0)
        {
            printf("RTMP_Write end.\n");
            break;
        }
        pretimetamp = FINT24TOINT(tagHeader.timestamp);

        free(pFileBuf);
        pFileBuf=NULL;
    }
    //推流结束

拉流

    res = RTMP_SetupURL(rtmp, "rtmp://live.hkstv.hk.lxdns.com/live//hks");//拉流
    PRINTERROR(res, 1, "RTMP_SetupURL error.\n");
    //if unable,the AMF command would be 'play' instead of 'publish'
    //RTMP_EnableWrite(rtmp);//推流要设置写
    res = RTMP_Connect(rtmp, NULL);
    PRINTERROR(res, 1, "RTMP_Connect error.\n");
    res = RTMP_ConnectStream(rtmp,0);
    PRINTERROR(res, 1, "RTMP_ConnectStream error.\n");

    //拉流
    int nRead = 0, NRead = 0;
    int bufsize = 1024*1024;
    char* buf = (char*)malloc(bufsize);
    FILE* fp_save = fopen("save.flv", "wb");
    while(nRead=RTMP_Read(rtmp,buf,bufsize))
    {
        fwrite(buf,1,nRead,fp_save);
        NRead += nRead;
        RTMP_LogPrintf("Receive: %5dByte, Total: %5.2fkB\n",nRead,NRead*1.0/1024);
    }
    //拉流结束

清理资源

    RTMP_Close(rtmp);
    RTMP_Free(rtmp);
    WSACleanup();

Github

https://github.com/gongluck/testLibRtmp.git

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术小黑屋

Quickly Find Content in Files

Although Eclipse does provide a lot of facilities for Finding content is Workspa...

571
来自专栏智能计算时代

Capturing Packets in Linux at a Speed of Millions of PPS

My article will tell you how to accept 10 million packets per second without usi...

3157
来自专栏智能计算时代

Microservices Ecosystem Transit Map

…we assembled a map of the ecosystem to help guide practitioners, vendors, inves...

3014
来自专栏C语言及其他语言

【程序源码】用纯C语言实现坦克大战

程序源码 今天笔者又给大家带来一个好玩的东西——纯C语言实现坦克大战源码! TC的环境下,运行效果截图如下: ? 上...

2665
来自专栏函数式编程语言及工具

FunDA(9)- Stream Source:reactive data streams

    上篇我们讨论了静态数据源(Static Source, snapshot)。这种方式只能在预知数据规模有限的情况下使用,对于超大型的数据库表也可以说是不...

18810
来自专栏我和未来有约会

silverlight beta 2 将在本周末发布.

太开心了,刚刚收到微软silverlight.net的邮件.  确定了 将在本周末发布beta2. 以下是部分邮件内容 引用: There are some...

1846
来自专栏岑志军的专栏

AFN挂代理访问

1064
来自专栏跟着阿笨一起玩NET

LINQ to XML 从逗号分隔值 (CSV) 文件生成 XML 文件

参考:http://msdn.microsoft.com/zh-cn/library/bb387090.aspx

351
来自专栏Golang语言社区

Golang国际化(i18n)和本地化(l10n)指南

Go is a statically compiled language that gained a lot of popularity lately due ...

1443
来自专栏张善友的专栏

Quartz.net官方开发指南 第二课:Jobs And Triggers

正如前面所提到的那样,通过实现IJob接口来使你的.NET组件可以很简单地被scheduler执行。下面是IJob接口: namespace Quartz ...

1968

扫描关注云+社区