添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
int Open(); int SendData(char * data,int dataLength, unsigned int timeStamp,int debug = -1); int IsConnect(); int Close(); private: int InitSockets(); void CleanupSockets(); int pushSPSPPS(char *sps, int spsLen, char *pps, int ppsLen, int m_stream_id,unsigned int timeStamp); int pushVideoData(char *data, int dataLen, bool keyFrame, int m_stream_id,unsigned int timeStamp); int GetStartPrixLen(char *Pack, int offest); char * rtmpUrl = NULL; RTMP * m_pRtmp = NULL; NALU * CopyNALU(NALU * src); void FreeNALU(NALU * nalu);

Wrapper_RtmpLib对外提供RTMP推流接口。

基本使用步骤:

  1. 定义一个Wrapper_RtmpLib对象test
  2. Test.open(),与服务器建立rtmp信令相关连接
  3. int SendData(char * data,int dataLength, unsigned int timeStamp,int debug = -1);发送RTMP数据

注意data,必须是一个完整的NAL单元。所以应用程序调该接口前必须解析出NAL单元。

下面是一个h264裸文件推送RTMP过程。

#include <cstdio>
#include"Wrapper_RtmpLib.hpp"
#include <unistd.h>
#include<string.h>
#include <signal.h>
#include<time.h>
#define LEN_R 1400
//检测启动码,并获取启动码的长度
int GetStartCode(char *Pack, int offest)
    int iStartPrexLen = 0;
    if (Pack[offest] == 'x00' && Pack[offest + 1] == 'x00'&&Pack[offest + 2] == 'x00'&&Pack[offest + 3] == 'x01')
        iStartPrexLen = 4;
        return iStartPrexLen;
    else if (Pack[offest] == 'x00' && Pack[offest + 1] == 'x00'&&Pack[offest + 2] == 'x01')
        iStartPrexLen = 3;
        return iStartPrexLen;
        return iStartPrexLen;
#include <time.h>
void delaytime(int ms)
//    return;
    struct timespec tvUec;
    clock_gettime(CLOCK_MONOTONIC, &tvUec);
    long long pretime = tvUec.tv_nsec / 1000000 + tvUec.tv_sec * 1000;
    long long nowtime = tvUec.tv_nsec / 1000000 + tvUec.tv_sec * 1000;
    while (1)
        clock_gettime(CLOCK_MONOTONIC, &tvUec);
        nowtime = tvUec.tv_nsec / 1000000 + tvUec.tv_sec * 1000;
        if (nowtime - pretime > ms-10) //程序自身耗时,预估耗时10ms。实际网络流不要延时,仅供测试
            return;
void help(char *p)
    printf("Use:");
    printf("%s h264_File RTMP_URL FRate  1111n",p);
char NALBuff[1080 * 1920 * 8]={0};
int NALLen = 0;
int lastPos = 0;
int pretime = 0;
int NALCount = 0;
int main(int argc,char*argv[])
    if(argc<4)
        help(argv[0]);
        return 1;
    signal(SIGPIPE, SIG_IGN);
    Wrapper_RtmpLib test(argv[2]);
    if (test.Open() < 0)
        printf("open is failedn");
        return 0;
    if (test.IsConnect() < 0)
        printf("connect is failedn");
        return 0;
        printf("connect is okn");
    char Pack[1500] = { 0 };
    int ret = 0;
    char *pStart = NULL;
    char *pEnd = NULL;
    char *pNALbuff = NALBuff;
    unsigned int timestamp = 0;
    int ioffset = 1000 /atoi(argv[3]);
    char *pPack = Pack;
    int iCurrentStartLen = 0;
    int iPreStartLen = 0;
    FILE *fp = NULL;
    fp = fopen(argv[1], "rb+");
    if (fp == NULL)
        printf("open file is failedn");
        return -1;
    while (1)
        pStart = NULL;
        pEnd = NULL;
        ret = fread(Pack, LEN_R, 1, fp);
        if (ret == 1)
            //如果头4个字节恰好为 00 00 00 01  或者00 00 01
            iCurrentStartLen = GetStartCode(Pack, 0);
            if(iCurrentStartLen>0)
                iPreStartLen = iCurrentStartLen;
                pStart=&Pack[0];
                pEnd = &Pack[0];
                for (int i = 2; i < LEN_R; i++)
                    iCurrentStartLen = GetStartCode(Pack, i);
                    if (iCurrentStartLen > 0)
                        printf("##find nal start1n");
                        pEnd = &Pack[i];
                        memmove(NALBuff+ NALLen, pStart, pEnd - pStart);//分离NAL拷贝到buffer
                        NALLen += pEnd - pStart;
                        NALCount++;
                    if (NALLen != 0)
                            int StartCodeLen = GetStartCode(NALBuff, 0);
                            if (StartCodeLen <= 0)
                                printf("NAL buffer data errorn");
                            if ((NALBuff[StartCodeLen] & 0x1F) == 7) //sps需要等pps一起发
                                if (NALCount == 1)
                                    iPreStartLen = iCurrentStartLen;
                                    pStart = pEnd;
                                    continue;
                            else if (( NALBuff[StartCodeLen] & 0x1F)== 5|| (NALBuff[StartCodeLen] & 0x1F) == 1)
                                timestamp = timestamp + ioffset;
                                //不是我所关注的NAL类型,可以不往下送
                                NALLen = 0;
                                NALCount = 0;
                                memset(NALBuff, 0, sizeof(NALBuff));
                                iPreStartLen = iCurrentStartLen;
                                pStart = pEnd;
                                continue;
                            ret =test.SendData(NALBuff, NALLen, timestamp, -1);
                            if (ret < 0)
                                printf("send is failedn");
                            NALLen = 0;
                            NALCount = 0;
                            memset(NALBuff, 0, sizeof(NALBuff));
                            iPreStartLen = iCurrentStartLen;
                            delaytime(ioffset);
                    pStart = pEnd;
                //一个包中遗留半个NAL单元,找不到下一个头
                //剩余的不完整NAL单元拷贝到临时buffer,后面凑齐一个NAL单元再发
                    memmove(NALBuff + NALLen, pStart, (&Pack[LEN_R - 1] - pStart) + 1);//sps pps idr non-idr,拷贝到buffer
                    NALLen += (&Pack[LEN_R - 1] - pStart + 1);
            else  //如果头4个字节不是启动码
                for (int i = 1; i < LEN_R; i++) //必须从2开始,因为可能存在00 00 01或00 00 00 01相邻出现
                    //  pStart = &Pack[0];
                    iCurrentStartLen = GetStartCode(Pack, i);
                    if (iCurrentStartLen > 0)
                        printf("##find nal start2n");
                        pEnd = &Pack[i];
                        if (pStart == NULL)
                            pStart = &Pack[0];
                        memmove(NALBuff + NALLen, pStart, pEnd - pStart);//sps pps idr non-idr,拷贝到buffer
                        NALLen += pEnd - pStart;
                        NALCount++;
                        if (NALLen != 0)
                            int StartCodeLen = GetStartCode(NALBuff, 0);
                            if (StartCodeLen <= 0)
                                printf("NAL buffer data errorn");
                            if ((NALBuff[StartCodeLen] & 0x1F) == 7) //sps需要等pps一起发
                                if (NALCount == 1)
                                    iPreStartLen = iCurrentStartLen;
                                    pStart = pEnd;
                                    continue;
                            else if ((NALBuff[StartCodeLen] & 0x1F) == 5 || (NALBuff[StartCodeLen] & 0x1F) == 1)
                                timestamp = timestamp + ioffset;
                                //不是我所关注的NAL类型,可以不往下送
                                NALLen = 0;
                                NALCount = 0;
                                memset(NALBuff, 0, sizeof(NALBuff));
                                iPreStartLen = iCurrentStartLen;
                                pStart = pEnd;
                                continue;
                                ret = test.SendData(NALBuff, NALLen, timestamp, -1);
                                if (ret < 0)
                                    printf("send data is failedn");
                                NALLen = 0;
                                NALCount = 0;
                                memset(NALBuff, 0, sizeof(NALBuff));
                                delaytime(ioffset);
                        iPreStartLen = iCurrentStartLen;
                    pStart = pEnd;
                //整个包都不足一个NAL单元
                if (pStart == pEnd)
                    if (pStart == NULL)
                        pStart = &Pack[0];
                    pEnd = &Pack[LEN_R - 1];
                    memmove(NALBuff + NALLen, pStart, pEnd - pStart + 1); //
                        //lastPos = NALLen;
                    NALLen += (pEnd - pStart + 1);
            printf("read is failed endof streamn");
            break;
    getchar();
    printf("hello from rtmp!n");
    return 0;

基本思路如下:

读文件—-解析NAL单元—利用 SendData发送一个完成的NAL单元完成推流

编译main.cpp Wrapper_RtmpLib.cpp 并链接librtmp.so生成可执行文件h2642rtmp.

版权声明:本文内容转自互联网,本文观点仅代表作者本人。本站仅提供信息存储空间服务,所有权归原作者所有。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至[email protected] 举报,一经查实,本站将立刻删除。

(0)
  • 视频直播高延迟怎么解决(视频直播高延迟的原因)
  • M6+ 发布由 Bedrock 开发的 Apple Vision Pro 应用程序
  • Microsoft Clipchamp 将很快利用 AI 改善图像和音频
  • 如何利用实时互动性提升视频流媒体
  •