最简单的基于librtmp的示例:发布(FLV通过RTMP发布)(发送数据)

2024-02-05 10:08

本文主要是介绍最简单的基于librtmp的示例:发布(FLV通过RTMP发布)(发送数据),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!


http://blog.csdn.net/leixiaohua1020/article/details/42104945




本文记录一个基于libRTMP的发布流媒体的程序:Simplest libRTMP Send FLV。该程序可以将本地FLV文件发布到RTMP流媒体服务器。是最简单的基于libRTMP的流媒体发布示例。

流程图


使用librtmp发布RTMP流的可以使用两种API:RTMP_SendPacket()和RTMP_Write()。使用RTMP_SendPacket()发布流的时候的函数执行流程图如下图所示。使用RTMP_Write()发布流的时候的函数执行流程图相差不大。
 

流程图中关键函数的作用如下所列:

InitSockets():初始化Socket
RTMP_Alloc():为结构体“RTMP”分配内存。
RTMP_Init():初始化结构体“RTMP”中的成员变量。
RTMP_SetupURL():设置输入的RTMP连接的URL。
RTMP_EnableWrite():发布流的时候必须要使用。如果不使用则代表接收流。
RTMP_Connect():建立RTMP连接,创建一个RTMP协议规范中的NetConnection。
RTMP_ConnectStream():创建一个RTMP协议规范中的NetStream。
Delay:发布流过程中的延时,保证按正常播放速度发送数据。
RTMP_SendPacket():发送一个RTMP数据RTMPPacket。
RTMP_Close():关闭RTMP连接。
RTMP_Free():释放结构体“RTMP”。
CleanupSockets():关闭Socket。
 

源代码

源代码中包含了使用两种API函数RTMP_SendPacket()和RTMP_Write()发布流媒体的源代码,如下所示。
[cpp]  view plain copy
  1. /** 
  2.  * Simplest Librtmp Send FLV 
  3.  * 
  4.  * 雷霄骅,张晖 
  5.  * leixiaohua1020@126.com 
  6.  * zhanghuicuc@gmail.com 
  7.  * 中国传媒大学/数字电视技术 
  8.  * Communication University of China / Digital TV Technology 
  9.  * http://blog.csdn.net/leixiaohua1020 
  10.  * 
  11.  * 本程序用于将FLV格式的视音频文件使用RTMP推送至RTMP流媒体服务器。 
  12.  * This program can send local flv file to net server as a rtmp live stream. 
  13.  */  
  14.    
  15. #include <stdio.h>  
  16. #include <stdlib.h>  
  17. #include <string.h>  
  18. #include <stdint.h>  
  19. #ifndef WIN32  
  20. #include <unistd.h>  
  21. #endif  
  22.    
  23.    
  24. #include "librtmp/rtmp_sys.h"  
  25. #include "librtmp/log.h"  
  26.    
  27. #define HTON16(x)  ((x>>8&0xff)|(x<<8&0xff00))  
  28. #define HTON24(x)  ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00))  
  29. #define HTON32(x)  ((x>>24&0xff)|(x>>8&0xff00)|\  
  30.          (x<<8&0xff0000)|(x<<24&0xff000000))  
  31. #define HTONTIME(x) ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00)|(x&0xff000000))  
  32.    
  33. /*read 1 byte*/  
  34. int ReadU8(uint32_t *u8,FILE*fp){  
  35.          if(fread(u8,1,1,fp)!=1)  
  36.                    return 0;  
  37.          return 1;  
  38. }  
  39. /*read 2 byte*/  
  40. int ReadU16(uint32_t *u16,FILE*fp){  
  41.          if(fread(u16,2,1,fp)!=1)  
  42.                    return 0;  
  43.          *u16=HTON16(*u16);  
  44.          return 1;  
  45. }  
  46. /*read 3 byte*/  
  47. int ReadU24(uint32_t *u24,FILE*fp){  
  48.          if(fread(u24,3,1,fp)!=1)  
  49.                    return 0;  
  50.          *u24=HTON24(*u24);  
  51.          return 1;  
  52. }  
  53. /*read 4 byte*/  
  54. int ReadU32(uint32_t *u32,FILE*fp){  
  55.          if(fread(u32,4,1,fp)!=1)  
  56.                    return 0;  
  57.          *u32=HTON32(*u32);  
  58.          return 1;  
  59. }  
  60. /*read 1 byte,and loopback 1 byte at once*/  
  61. int PeekU8(uint32_t *u8,FILE*fp){  
  62.          if(fread(u8,1,1,fp)!=1)  
  63.                    return 0;  
  64.          fseek(fp,-1,SEEK_CUR);  
  65.          return 1;  
  66. }  
  67. /*read 4 byte and convert to time format*/  
  68. int ReadTime(uint32_t *utime,FILE*fp){  
  69.          if(fread(utime,4,1,fp)!=1)  
  70.                    return 0;  
  71.          *utime=HTONTIME(*utime);  
  72.          return 1;  
  73. }  
  74.    
  75. int InitSockets()  
  76. {  
  77.          WORD version;  
  78.          WSADATA wsaData;  
  79.          version=MAKEWORD(2,2);  
  80.          return (WSAStartup(version, &wsaData) == 0);  
  81. }  
  82.    
  83. void CleanupSockets()  
  84. {  
  85.          WSACleanup();  
  86. }  
  87.    
  88. //Publish using RTMP_SendPacket()  
  89. int publish_using_packet(){  
  90.          RTMP *rtmp=NULL;                             
  91.          RTMPPacket *packet=NULL;  
  92.          uint32_t start_time=0;  
  93.          uint32_t now_time=0;  
  94.          //the timestamp of the previous frame  
  95.          long pre_frame_time=0;  
  96.          long lasttime=0;  
  97.          int bNextIsKey=1;  
  98.          uint32_t preTagsize=0;  
  99.           
  100.          //packet attributes  
  101.          uint32_t type=0;                          
  102.          uint32_t datalength=0;             
  103.          uint32_t timestamp=0;             
  104.          uint32_t streamid=0;                          
  105.    
  106.          FILE*fp=NULL;  
  107.          fp=fopen("cuc_ieschool.flv","rb");  
  108.          if (!fp){  
  109.                    RTMP_LogPrintf("Open File Error.\n");  
  110.                    CleanupSockets();  
  111.                    return -1;  
  112.          }  
  113.    
  114.          /* set log level */  
  115.          //RTMP_LogLevel loglvl=RTMP_LOGDEBUG;  
  116.          //RTMP_LogSetLevel(loglvl);  
  117.                     
  118.          if (!InitSockets()){  
  119.                    RTMP_LogPrintf("Init Socket Err\n");  
  120.                    return -1;  
  121.          }  
  122.    
  123.          rtmp=RTMP_Alloc();  
  124.          RTMP_Init(rtmp);  
  125.          //set connection timeout,default 30s  
  126.          rtmp->Link.timeout=5;                        
  127.          if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))  
  128.          {  
  129.                    RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");  
  130.                    RTMP_Free(rtmp);  
  131.                    CleanupSockets();  
  132.                    return -1;  
  133.          }  
  134.           
  135.          //if unable,the AMF command would be 'play' instead of 'publish'  
  136.          RTMP_EnableWrite(rtmp);       
  137.           
  138.          if (!RTMP_Connect(rtmp,NULL)){  
  139.                    RTMP_Log(RTMP_LOGERROR,"Connect Err\n");  
  140.                    RTMP_Free(rtmp);  
  141.                    CleanupSockets();  
  142.                    return -1;  
  143.          }  
  144.           
  145.          if (!RTMP_ConnectStream(rtmp,0)){  
  146.                    RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");  
  147.                    RTMP_Close(rtmp);  
  148.                    RTMP_Free(rtmp);  
  149.                    CleanupSockets();  
  150.                    return -1;  
  151.          }  
  152.    
  153.          packet=(RTMPPacket*)malloc(sizeof(RTMPPacket));  
  154.          RTMPPacket_Alloc(packet,1024*64);  
  155.          RTMPPacket_Reset(packet);  
  156.    
  157.          packet->m_hasAbsTimestamp = 0;          
  158.          packet->m_nChannel = 0x04;  
  159.          packet->m_nInfoField2 = rtmp->m_stream_id;  
  160.    
  161.          RTMP_LogPrintf("Start to send data ...\n");  
  162.           
  163.          //jump over FLV Header  
  164.          fseek(fp,9,SEEK_SET);       
  165.          //jump over previousTagSizen  
  166.          fseek(fp,4,SEEK_CUR);     
  167.          start_time=RTMP_GetTime();  
  168.          while(1)  
  169.          {  
  170.                    if((((now_time=RTMP_GetTime())-start_time)  
  171.                               <(pre_frame_time)) && bNextIsKey){          
  172.                             //wait for 1 sec if the send process is too fast  
  173.                             //this mechanism is not very good,need some improvement  
  174.                             if(pre_frame_time>lasttime){  
  175.                                      RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time);  
  176.                                      lasttime=pre_frame_time;  
  177.                             }  
  178.                             Sleep(1000);  
  179.                             continue;  
  180.                    }  
  181.                     
  182.                    //not quite the same as FLV spec  
  183.                    if(!ReadU8(&type,fp))       
  184.                             break;  
  185.                    if(!ReadU24(&datalength,fp))  
  186.                             break;  
  187.                    if(!ReadTime(×tamp,fp))  
  188.                             break;  
  189.                    if(!ReadU24(&streamid,fp))  
  190.                             break;  
  191.    
  192.                    if (type!=0x08&&type!=0x09){  
  193.                             //jump over non_audio and non_video frame,  
  194.                             //jump over next previousTagSizen at the same time  
  195.                             fseek(fp,datalength+4,SEEK_CUR);  
  196.                             continue;  
  197.                    }  
  198.                     
  199.                    if(fread(packet->m_body,1,datalength,fp)!=datalength)  
  200.                             break;  
  201.    
  202.                    packet->m_headerType = RTMP_PACKET_SIZE_LARGE;  
  203.                    packet->m_nTimeStamp = timestamp;  
  204.                    packet->m_packetType = type;  
  205.                    packet->m_nBodySize  = datalength;  
  206.                    pre_frame_time=timestamp;  
  207.    
  208.                    if (!RTMP_IsConnected(rtmp)){  
  209.                             RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");  
  210.                             break;  
  211.                    }  
  212.                    if (!RTMP_SendPacket(rtmp,packet,0)){  
  213.                             RTMP_Log(RTMP_LOGERROR,"Send Error\n");  
  214.                             break;  
  215.                    }  
  216.    
  217.                    if(!ReadU32(&preTagsize,fp))  
  218.                             break;  
  219.                              
  220.                    if(!PeekU8(&type,fp))  
  221.                             break;  
  222.                    if(type==0x09){  
  223.                             if(fseek(fp,11,SEEK_CUR)!=0)  
  224.                                      break;  
  225.                             if(!PeekU8(&type,fp)){  
  226.                                      break;  
  227.                             }  
  228.                             if(type==0x17)  
  229.                                      bNextIsKey=1;  
  230.                             else  
  231.                                      bNextIsKey=0;  
  232.    
  233.                             fseek(fp,-11,SEEK_CUR);  
  234.                    }  
  235.          }                 
  236.    
  237.          RTMP_LogPrintf("\nSend Data Over\n");  
  238.           
  239.          if(fp)  
  240.                    fclose(fp);  
  241.    
  242.          if (rtmp!=NULL){  
  243.                    RTMP_Close(rtmp);          
  244.                    RTMP_Free(rtmp);   
  245.                    rtmp=NULL;  
  246.          }  
  247.          if (packet!=NULL){  
  248.                    RTMPPacket_Free(packet);      
  249.                    free(packet);  
  250.                    packet=NULL;  
  251.          }  
  252.    
  253.          CleanupSockets();  
  254.          return 0;  
  255. }  
  256.    
  257. //Publish using RTMP_Write()  
  258. int publish_using_write(){  
  259.          uint32_t start_time=0;  
  260.          uint32_t now_time=0;  
  261.          uint32_t pre_frame_time=0;  
  262.          uint32_t lasttime=0;  
  263.          int bNextIsKey=0;  
  264.          char* pFileBuf=NULL;  
  265.    
  266.          //read from tag header  
  267.          uint32_t type=0;  
  268.          uint32_t datalength=0;  
  269.          uint32_t timestamp=0;  
  270.    
  271.          RTMP *rtmp=NULL;                             
  272.           
  273.          FILE*fp=NULL;  
  274.          fp=fopen("cuc_ieschool.flv","rb");  
  275.          if (!fp){  
  276.                    RTMP_LogPrintf("Open File Error.\n");  
  277.                    CleanupSockets();  
  278.                    return -1;  
  279.          }  
  280.    
  281.          /* set log level */  
  282.          //RTMP_LogLevel loglvl=RTMP_LOGDEBUG;  
  283.          //RTMP_LogSetLevel(loglvl);  
  284.                     
  285.          if (!InitSockets()){  
  286.                   RTMP_LogPrintf("Init Socket Err\n");  
  287.                    return -1;  
  288.          }  
  289.    
  290.          rtmp=RTMP_Alloc();  
  291.          RTMP_Init(rtmp);  
  292.          //set connection timeout,default 30s  
  293.          rtmp->Link.timeout=5;                        
  294.          if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))  
  295.          {  
  296.                    RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");  
  297.                    RTMP_Free(rtmp);  
  298.                    CleanupSockets();  
  299.                    return -1;  
  300.          }  
  301.    
  302.          RTMP_EnableWrite(rtmp);  
  303.          //1hour  
  304.          RTMP_SetBufferMS(rtmp, 3600*1000);           
  305.          if (!RTMP_Connect(rtmp,NULL)){  
  306.                    RTMP_Log(RTMP_LOGERROR,"Connect Err\n");  
  307.                    RTMP_Free(rtmp);  
  308.                    CleanupSockets();  
  309.                    return -1;  
  310.          }  
  311.           
  312.          if (!RTMP_ConnectStream(rtmp,0)){  
  313.                    RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");  
  314.                    RTMP_Close(rtmp);  
  315.                    RTMP_Free(rtmp);  
  316.                    CleanupSockets();  
  317.                    return -1;  
  318.          }  
  319.    
  320.          printf("Start to send data ...\n");  
  321.           
  322.          //jump over FLV Header  
  323.          fseek(fp,9,SEEK_SET);       
  324.          //jump over previousTagSizen  
  325.          fseek(fp,4,SEEK_CUR);     
  326.          start_time=RTMP_GetTime();  
  327.          while(1)  
  328.          {  
  329.                    if((((now_time=RTMP_GetTime())-start_time)  
  330.                               <(pre_frame_time)) && bNextIsKey){          
  331.                             //wait for 1 sec if the send process is too fast  
  332.                             //this mechanism is not very good,need some improvement  
  333.                             if(pre_frame_time>lasttime){  
  334.                                      RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time);  
  335.                                      lasttime=pre_frame_time;  
  336.                             }  
  337.                             Sleep(1000);  
  338.                             continue;  
  339.                    }  
  340.                     
  341.                    //jump over type  
  342.                    fseek(fp,1,SEEK_CUR);     
  343.                    if(!ReadU24(&datalength,fp))  
  344.                             break;  
  345.                    if(!ReadTime(×tamp,fp))  
  346.                             break;  
  347.                    //jump back  
  348.                    fseek(fp,-8,SEEK_CUR);    
  349.                     
  350.                    pFileBuf=(char*)malloc(11+datalength+4);  
  351.                    memset(pFileBuf,0,11+datalength+4);  
  352.                    if(fread(pFileBuf,1,11+datalength+4,fp)!=(11+datalength+4))  
  353.                             break;  
  354.                     
  355.                    pre_frame_time=timestamp;  
  356.                     
  357.                    if (!RTMP_IsConnected(rtmp)){  
  358.                             RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");  
  359.                             break;  
  360.                    }  
  361.                    if (!RTMP_Write(rtmp,pFileBuf,11+datalength+4)){  
  362.                             RTMP_Log(RTMP_LOGERROR,"Rtmp Write Error\n");  
  363.                             break;  
  364.                    }  
  365.                     
  366.                    free(pFileBuf);  
  367.                    pFileBuf=NULL;  
  368.    
  369.                    if(!PeekU8(&type,fp))  
  370.                             break;  
  371.                    if(type==0x09){  
  372.                             if(fseek(fp,11,SEEK_CUR)!=0)  
  373.                                      break;  
  374.                             if(!PeekU8(&type,fp)){  
  375.                                      break;  
  376.                             }  
  377.                             if(type==0x17)  
  378.                                      bNextIsKey=1;  
  379.                             else  
  380.                                      bNextIsKey=0;  
  381.                             fseek(fp,-11,SEEK_CUR);  
  382.                    }  
  383.          }  
  384.    
  385.          RTMP_LogPrintf("\nSend Data Over\n");  
  386.           
  387.          if(fp)  
  388.                    fclose(fp);  
  389.    
  390.          if (rtmp!=NULL){  
  391.                    RTMP_Close(rtmp);          
  392.                    RTMP_Free(rtmp);  
  393.                    rtmp=NULL;  
  394.          }  
  395.    
  396.          if(pFileBuf){  
  397.                    free(pFileBuf);  
  398.                    pFileBuf=NULL;  
  399.          }  
  400.    
  401.          CleanupSockets();  
  402.          return 0;  
  403. }  
  404.    
  405. int main(int argc, char* argv[]){  
  406.          //2 Methods:  
  407.          publish_using_packet();  
  408.          //publish_using_write();  
  409.          return 0;  
  410. }  


运行结果

程序运行后,会将“cuc_ieschool.flv”文件以直播流的形式发布到“rtmp://localhost/publishlive/livestream”的URL。修改文件名称和RTMP的URL可以实现将任意flv文件发布到任意RTMP的URL。


下载 

Simplest LibRTMP Example
 

项目主页

SourceForge:https://sourceforge.net/projects/simplestlibrtmpexample/

Github:https://github.com/leixiaohua1020/simplest_librtmp_example

开源中国:http://git.oschina.net/leixiaohua1020/simplest_librtmp_example


CSDN下载: http://download.csdn.net/detail/leixiaohua1020/8291757
 




本文记录一个基于libRTMP的发布流媒体的程序:Simplest libRTMP Send FLV。该程序可以将本地FLV文件发布到RTMP流媒体服务器。是最简单的基于libRTMP的流媒体发布示例。

流程图


使用librtmp发布RTMP流的可以使用两种API:RTMP_SendPacket()和RTMP_Write()。使用RTMP_SendPacket()发布流的时候的函数执行流程图如下图所示。使用RTMP_Write()发布流的时候的函数执行流程图相差不大。
 

流程图中关键函数的作用如下所列:

InitSockets():初始化Socket
RTMP_Alloc():为结构体“RTMP”分配内存。
RTMP_Init():初始化结构体“RTMP”中的成员变量。
RTMP_SetupURL():设置输入的RTMP连接的URL。
RTMP_EnableWrite():发布流的时候必须要使用。如果不使用则代表接收流。
RTMP_Connect():建立RTMP连接,创建一个RTMP协议规范中的NetConnection。
RTMP_ConnectStream():创建一个RTMP协议规范中的NetStream。
Delay:发布流过程中的延时,保证按正常播放速度发送数据。
RTMP_SendPacket():发送一个RTMP数据RTMPPacket。
RTMP_Close():关闭RTMP连接。
RTMP_Free():释放结构体“RTMP”。
CleanupSockets():关闭Socket。
 

源代码

源代码中包含了使用两种API函数RTMP_SendPacket()和RTMP_Write()发布流媒体的源代码,如下所示。
[cpp]  view plain copy
  1. /** 
  2.  * Simplest Librtmp Send FLV 
  3.  * 
  4.  * 雷霄骅,张晖 
  5.  * leixiaohua1020@126.com 
  6.  * zhanghuicuc@gmail.com 
  7.  * 中国传媒大学/数字电视技术 
  8.  * Communication University of China / Digital TV Technology 
  9.  * http://blog.csdn.net/leixiaohua1020 
  10.  * 
  11.  * 本程序用于将FLV格式的视音频文件使用RTMP推送至RTMP流媒体服务器。 
  12.  * This program can send local flv file to net server as a rtmp live stream. 
  13.  */  
  14.    
  15. #include <stdio.h>  
  16. #include <stdlib.h>  
  17. #include <string.h>  
  18. #include <stdint.h>  
  19. #ifndef WIN32  
  20. #include <unistd.h>  
  21. #endif  
  22.    
  23.    
  24. #include "librtmp/rtmp_sys.h"  
  25. #include "librtmp/log.h"  
  26.    
  27. #define HTON16(x)  ((x>>8&0xff)|(x<<8&0xff00))  
  28. #define HTON24(x)  ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00))  
  29. #define HTON32(x)  ((x>>24&0xff)|(x>>8&0xff00)|\  
  30.          (x<<8&0xff0000)|(x<<24&0xff000000))  
  31. #define HTONTIME(x) ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00)|(x&0xff000000))  
  32.    
  33. /*read 1 byte*/  
  34. int ReadU8(uint32_t *u8,FILE*fp){  
  35.          if(fread(u8,1,1,fp)!=1)  
  36.                    return 0;  
  37.          return 1;  
  38. }  
  39. /*read 2 byte*/  
  40. int ReadU16(uint32_t *u16,FILE*fp){  
  41.          if(fread(u16,2,1,fp)!=1)  
  42.                    return 0;  
  43.          *u16=HTON16(*u16);  
  44.          return 1;  
  45. }  
  46. /*read 3 byte*/  
  47. int ReadU24(uint32_t *u24,FILE*fp){  
  48.          if(fread(u24,3,1,fp)!=1)  
  49.                    return 0;  
  50.          *u24=HTON24(*u24);  
  51.          return 1;  
  52. }  
  53. /*read 4 byte*/  
  54. int ReadU32(uint32_t *u32,FILE*fp){  
  55.          if(fread(u32,4,1,fp)!=1)  
  56.                    return 0;  
  57.          *u32=HTON32(*u32);  
  58.          return 1;  
  59. }  
  60. /*read 1 byte,and loopback 1 byte at once*/  
  61. int PeekU8(uint32_t *u8,FILE*fp){  
  62.          if(fread(u8,1,1,fp)!=1)  
  63.                    return 0;  
  64.          fseek(fp,-1,SEEK_CUR);  
  65.          return 1;  
  66. }  
  67. /*read 4 byte and convert to time format*/  
  68. int ReadTime(uint32_t *utime,FILE*fp){  
  69.          if(fread(utime,4,1,fp)!=1)  
  70.                    return 0;  
  71.          *utime=HTONTIME(*utime);  
  72.          return 1;  
  73. }  
  74.    
  75. int InitSockets()  
  76. {  
  77.          WORD version;  
  78.          WSADATA wsaData;  
  79.          version=MAKEWORD(2,2);  
  80.          return (WSAStartup(version, &wsaData) == 0);  
  81. }  
  82.    
  83. void CleanupSockets()  
  84. {  
  85.          WSACleanup();  
  86. }  
  87.    
  88. //Publish using RTMP_SendPacket()  
  89. int publish_using_packet(){  
  90.          RTMP *rtmp=NULL;                             
  91.          RTMPPacket *packet=NULL;  
  92.          uint32_t start_time=0;  
  93.          uint32_t now_time=0;  
  94.          //the timestamp of the previous frame  
  95.          long pre_frame_time=0;  
  96.          long lasttime=0;  
  97.          int bNextIsKey=1;  
  98.          uint32_t preTagsize=0;  
  99.           
  100.          //packet attributes  
  101.          uint32_t type=0;                          
  102.          uint32_t datalength=0;             
  103.          uint32_t timestamp=0;             
  104.          uint32_t streamid=0;                          
  105.    
  106.          FILE*fp=NULL;  
  107.          fp=fopen("cuc_ieschool.flv","rb");  
  108.          if (!fp){  
  109.                    RTMP_LogPrintf("Open File Error.\n");  
  110.                    CleanupSockets();  
  111.                    return -1;  
  112.          }  
  113.    
  114.          /* set log level */  
  115.          //RTMP_LogLevel loglvl=RTMP_LOGDEBUG;  
  116.          //RTMP_LogSetLevel(loglvl);  
  117.                     
  118.          if (!InitSockets()){  
  119.                    RTMP_LogPrintf("Init Socket Err\n");  
  120.                    return -1;  
  121.          }  
  122.    
  123.          rtmp=RTMP_Alloc();  
  124.          RTMP_Init(rtmp);  
  125.          //set connection timeout,default 30s  
  126.          rtmp->Link.timeout=5;                        
  127.          if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))  
  128.          {  
  129.                    RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");  
  130.                    RTMP_Free(rtmp);  
  131.                    CleanupSockets();  
  132.                    return -1;  
  133.          }  
  134.           
  135.          //if unable,the AMF command would be 'play' instead of 'publish'  
  136.          RTMP_EnableWrite(rtmp);       
  137.           
  138.          if (!RTMP_Connect(rtmp,NULL)){  
  139.                    RTMP_Log(RTMP_LOGERROR,"Connect Err\n");  
  140.                    RTMP_Free(rtmp);  
  141.                    CleanupSockets();  
  142.                    return -1;  
  143.          }  
  144.           
  145.          if (!RTMP_ConnectStream(rtmp,0)){  
  146.                    RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");  
  147.                    RTMP_Close(rtmp);  
  148.                    RTMP_Free(rtmp);  
  149.                    CleanupSockets();  
  150.                    return -1;  
  151.          }  
  152.    
  153.          packet=(RTMPPacket*)malloc(sizeof(RTMPPacket));  
  154.          RTMPPacket_Alloc(packet,1024*64);  
  155.          RTMPPacket_Reset(packet);  
  156.    
  157.          packet->m_hasAbsTimestamp = 0;          
  158.          packet->m_nChannel = 0x04;  
  159.          packet->m_nInfoField2 = rtmp->m_stream_id;  
  160.    
  161.          RTMP_LogPrintf("Start to send data ...\n");  
  162.           
  163.          //jump over FLV Header  
  164.          fseek(fp,9,SEEK_SET);       
  165.          //jump over previousTagSizen  
  166.          fseek(fp,4,SEEK_CUR);     
  167.          start_time=RTMP_GetTime();  
  168.          while(1)  
  169.          {  
  170.                    if((((now_time=RTMP_GetTime())-start_time)  
  171.                               <(pre_frame_time)) && bNextIsKey){          
  172.                             //wait for 1 sec if the send process is too fast  
  173.                             //this mechanism is not very good,need some improvement  
  174.                             if(pre_frame_time>lasttime){  
  175.                                      RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time);  
  176.                                      lasttime=pre_frame_time;  
  177.                             }  
  178.                             Sleep(1000);  
  179.                             continue;  
  180.                    }  
  181.                     
  182.                    //not quite the same as FLV spec  
  183.                    if(!ReadU8(&type,fp))       
  184.                             break;  
  185.                    if(!ReadU24(&datalength,fp))  
  186.                             break;  
  187.                    if(!ReadTime(×tamp,fp))  
  188.                             break;  
  189.                    if(!ReadU24(&streamid,fp))  
  190.                             break;  
  191.    
  192.                    if (type!=0x08&&type!=0x09){  
  193.                             //jump over non_audio and non_video frame,  
  194.                             //jump over next previousTagSizen at the same time  
  195.                             fseek(fp,datalength+4,SEEK_CUR);  
  196.                             continue;  
  197.                    }  
  198.                     
  199.                    if(fread(packet->m_body,1,datalength,fp)!=datalength)  
  200.                             break;  
  201.    
  202.                    packet->m_headerType = RTMP_PACKET_SIZE_LARGE;  
  203.                    packet->m_nTimeStamp = timestamp;  
  204.                    packet->m_packetType = type;  
  205.                    packet->m_nBodySize  = datalength;  
  206.                    pre_frame_time=timestamp;  
  207.    
  208.                    if (!RTMP_IsConnected(rtmp)){  
  209.                             RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");  
  210.                             break;  
  211.                    }  
  212.                    if (!RTMP_SendPacket(rtmp,packet,0)){  
  213.                             RTMP_Log(RTMP_LOGERROR,"Send Error\n");  
  214.                             break;  
  215.                    }  
  216.    
  217.                    if(!ReadU32(&preTagsize,fp))  
  218.                             break;  
  219.                              
  220.                    if(!PeekU8(&type,fp))  
  221.                             break;  
  222.                    if(type==0x09){  
  223.                             if(fseek(fp,11,SEEK_CUR)!=0)  
  224.                                      break;  
  225.                             if(!PeekU8(&type,fp)){  
  226.                                      break;  
  227.                             }  
  228.                             if(type==0x17)  
  229.                                      bNextIsKey=1;  
  230.                             else  
  231.                                      bNextIsKey=0;  
  232.    
  233.                             fseek(fp,-11,SEEK_CUR);  
  234.                    }  
  235.          }                 
  236.    
  237.          RTMP_LogPrintf("\nSend Data Over\n");  
  238.           
  239.          if(fp)  
  240.                    fclose(fp);  
  241.    
  242.          if (rtmp!=NULL){  
  243.                    RTMP_Close(rtmp);          
  244.                    RTMP_Free(rtmp);   
  245.                    rtmp=NULL;  
  246.          }  
  247.          if (packet!=NULL){  
  248.                    RTMPPacket_Free(packet);      
  249.                    free(packet);  
  250.                    packet=NULL;  
  251.          }  
  252.    
  253.          CleanupSockets();  
  254.          return 0;  
  255. }  
  256.    
  257. //Publish using RTMP_Write()  
  258. int publish_using_write(){  
  259.          uint32_t start_time=0;  
  260.          uint32_t now_time=0;  
  261.          uint32_t pre_frame_time=0;  
  262.          uint32_t lasttime=0;  
  263.          int bNextIsKey=0;  
  264.          char* pFileBuf=NULL;  
  265.    
  266.          //read from tag header  
  267.          uint32_t type=0;  
  268.          uint32_t datalength=0;  
  269.          uint32_t timestamp=0;  
  270.    
  271.          RTMP *rtmp=NULL;                             
  272.           
  273.          FILE*fp=NULL;  
  274.          fp=fopen("cuc_ieschool.flv","rb");  
  275.          if (!fp){  
  276.                    RTMP_LogPrintf("Open File Error.\n");  
  277.                    CleanupSockets();  
  278.                    return -1;  
  279.          }  
  280.    
  281.          /* set log level */  
  282.          //RTMP_LogLevel loglvl=RTMP_LOGDEBUG;  
  283.          //RTMP_LogSetLevel(loglvl);  
  284.                     
  285.          if (!InitSockets()){  
  286.                   RTMP_LogPrintf("Init Socket Err\n");  
  287.                    return -1;  
  288.          }  
  289.    
  290.          rtmp=RTMP_Alloc();  
  291.          RTMP_Init(rtmp);  
  292.          //set connection timeout,default 30s  
  293.          rtmp->Link.timeout=5;                        
  294.          if(!RTMP_SetupURL(rtmp,"rtmp://localhost/publishlive/livestream"))  
  295.          {  
  296.                    RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");  
  297.                    RTMP_Free(rtmp);  
  298.                    CleanupSockets();  
  299.                    return -1;  
  300.          }  
  301.    
  302.          RTMP_EnableWrite(rtmp);  
  303.          //1hour  
  304.          RTMP_SetBufferMS(rtmp, 3600*1000);           
  305.          if (!RTMP_Connect(rtmp,NULL)){  
  306.                    RTMP_Log(RTMP_LOGERROR,"Connect Err\n");  
  307.                    RTMP_Free(rtmp);  
  308.                    CleanupSockets();  
  309.                    return -1;  
  310.          }  
  311.           
  312.          if (!RTMP_ConnectStream(rtmp,0)){  
  313.                    RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");  
  314.                    RTMP_Close(rtmp);  
  315.                    RTMP_Free(rtmp);  
  316.                    CleanupSockets();  
  317.                    return -1;  
  318.          }  
  319.    
  320.          printf("Start to send data ...\n");  
  321.           
  322.          //jump over FLV Header  
  323.          fseek(fp,9,SEEK_SET);       
  324.          //jump over previousTagSizen  
  325.          fseek(fp,4,SEEK_CUR);     
  326.          start_time=RTMP_GetTime();  
  327.          while(1)  
  328.          {  
  329.                    if((((now_time=RTMP_GetTime())-start_time)  
  330.                               <(pre_frame_time)) && bNextIsKey){          
  331.                             //wait for 1 sec if the send process is too fast  
  332.                             //this mechanism is not very good,need some improvement  
  333.                             if(pre_frame_time>lasttime){  
  334.                                      RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time);  
  335.                                      lasttime=pre_frame_time;  
  336.                             }  
  337.                             Sleep(1000);  
  338.                             continue;  
  339.                    }  
  340.                     
  341.                    //jump over type  
  342.                    fseek(fp,1,SEEK_CUR);     
  343.                    if(!ReadU24(&datalength,fp))  
  344.                             break;  
  345.                    if(!ReadTime(×tamp,fp))  
  346.                             break;  
  347.                    //jump back  
  348.                    fseek(fp,-8,SEEK_CUR);    
  349.                     
  350.                    pFileBuf=(char*)malloc(11+datalength+4);  
  351.                    memset(pFileBuf,0,11+datalength+4);  
  352.                    if(fread(pFileBuf,1,11+datalength+4,fp)!=(11+datalength+4))  
  353.                             break;  
  354.                     
  355.                    pre_frame_time=timestamp;  
  356.                     
  357.                    if (!RTMP_IsConnected(rtmp)){  
  358.                             RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n");  
  359.                             break;  
  360.                    }  
  361.                    if (!RTMP_Write(rtmp,pFileBuf,11+datalength+4)){  
  362.                             RTMP_Log(RTMP_LOGERROR,"Rtmp Write Error\n");  
  363.                             break;  
  364.                    }  
  365.                     
  366.                    free(pFileBuf);  
  367.                    pFileBuf=NULL;  
  368.    
  369.                    if(!PeekU8(&type,fp))  
  370.                             break;  
  371.                    if(type==0x09){  
  372.                             if(fseek(fp,11,SEEK_CUR)!=0)  
  373.                                      break;  
  374.                             if(!PeekU8(&type,fp)){  
  375.                                      break;  
  376.                             }  
  377.                             if(type==0x17)  
  378.                                      bNextIsKey=1;  
  379.                             else  
  380.                                      bNextIsKey=0;  
  381.                             fseek(fp,-11,SEEK_CUR);  
  382.                    }  
  383.          }  
  384.    
  385.          RTMP_LogPrintf("\nSend Data Over\n");  
  386.           
  387.          if(fp)  
  388.                    fclose(fp);  
  389.    
  390.          if (rtmp!=NULL){  
  391.                    RTMP_Close(rtmp);          
  392.                    RTMP_Free(rtmp);  
  393.                    rtmp=NULL;  
  394.          }  
  395.    
  396.          if(pFileBuf){  
  397.                    free(pFileBuf);  
  398.                    pFileBuf=NULL;  
  399.          }  
  400.    
  401.          CleanupSockets();  
  402.          return 0;  
  403. }  
  404.    
  405. int main(int argc, char* argv[]){  
  406.          //2 Methods:  
  407.          publish_using_packet();  
  408.          //publish_using_write();  
  409.          return 0;  
  410. }  


运行结果

程序运行后,会将“cuc_ieschool.flv”文件以直播流的形式发布到“rtmp://localhost/publishlive/livestream”的URL。修改文件名称和RTMP的URL可以实现将任意flv文件发布到任意RTMP的URL。


下载 

Simplest LibRTMP Example
 

项目主页

SourceForge:https://sourceforge.net/projects/simplestlibrtmpexample/

Github:https://github.com/leixiaohua1020/simplest_librtmp_example

开源中国:http://git.oschina.net/leixiaohua1020/simplest_librtmp_example


CSDN下载: http://download.csdn.net/detail/leixiaohua1020/8291757
 

这篇关于最简单的基于librtmp的示例:发布(FLV通过RTMP发布)(发送数据)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/680566

相关文章

高效+灵活,万博智云全球发布AWS无代理跨云容灾方案!

摘要 近日,万博智云推出了基于AWS的无代理跨云容灾解决方案,并与拉丁美洲,中东,亚洲的合作伙伴面向全球开展了联合发布。这一方案以AWS应用环境为基础,将HyperBDR平台的高效、灵活和成本效益优势与无代理功能相结合,为全球企业带来实现了更便捷、经济的数据保护。 一、全球联合发布 9月2日,万博智云CEO Michael Wong在线上平台发布AWS无代理跨云容灾解决方案的阐述视频,介绍了

csu 1446 Problem J Modified LCS (扩展欧几里得算法的简单应用)

这是一道扩展欧几里得算法的简单应用题,这题是在湖南多校训练赛中队友ac的一道题,在比赛之后请教了队友,然后自己把它a掉 这也是自己独自做扩展欧几里得算法的题目 题意:把题意转变下就变成了:求d1*x - d2*y = f2 - f1的解,很明显用exgcd来解 下面介绍一下exgcd的一些知识点:求ax + by = c的解 一、首先求ax + by = gcd(a,b)的解 这个

hdu2289(简单二分)

虽说是简单二分,但是我还是wa死了  题意:已知圆台的体积,求高度 首先要知道圆台体积怎么求:设上下底的半径分别为r1,r2,高为h,V = PI*(r1*r1+r1*r2+r2*r2)*h/3 然后以h进行二分 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#includ

usaco 1.3 Prime Cryptarithm(简单哈希表暴搜剪枝)

思路: 1. 用一个 hash[ ] 数组存放输入的数字,令 hash[ tmp ]=1 。 2. 一个自定义函数 check( ) ,检查各位是否为输入的数字。 3. 暴搜。第一行数从 100到999,第二行数从 10到99。 4. 剪枝。 代码: /*ID: who jayLANG: C++TASK: crypt1*/#include<stdio.h>bool h

uva 10387 Billiard(简单几何)

题意是一个球从矩形的中点出发,告诉你小球与矩形两条边的碰撞次数与小球回到原点的时间,求小球出发时的角度和小球的速度。 简单的几何问题,小球每与竖边碰撞一次,向右扩展一个相同的矩形;每与横边碰撞一次,向上扩展一个相同的矩形。 可以发现,扩展矩形的路径和在当前矩形中的每一段路径相同,当小球回到出发点时,一条直线的路径刚好经过最后一个扩展矩形的中心点。 最后扩展的路径和横边竖边恰好组成一个直

poj 1113 凸包+简单几何计算

题意: 给N个平面上的点,现在要在离点外L米处建城墙,使得城墙把所有点都包含进去且城墙的长度最短。 解析: 韬哥出的某次训练赛上A出的第一道计算几何,算是大水题吧。 用convexhull算法把凸包求出来,然后加加减减就A了。 计算见下图: 好久没玩画图了啊好开心。 代码: #include <iostream>#include <cstdio>#inclu

uva 10130 简单背包

题意: 背包和 代码: #include <iostream>#include <cstdio>#include <cstdlib>#include <algorithm>#include <cstring>#include <cmath>#include <stack>#include <vector>#include <queue>#include <map>

Vue3项目开发——新闻发布管理系统(六)

文章目录 八、首页设计开发1、页面设计2、登录访问拦截实现3、用户基本信息显示①封装用户基本信息获取接口②用户基本信息存储③用户基本信息调用④用户基本信息动态渲染 4、退出功能实现①注册点击事件②添加退出功能③数据清理 5、代码下载 八、首页设计开发 登录成功后,系统就进入了首页。接下来,也就进行首页的开发了。 1、页面设计 系统页面主要分为三部分,左侧为系统的菜单栏,右侧

zeroclipboard 粘贴板的应用示例, 兼容 Chrome、IE等多浏览器

zeroclipboard单个复制按钮和多个复制按钮的实现方法 最近网站改版想让复制代码功能在多个浏览器上都可以实现,最近看网上不少说我们的代码复制功能不好用的,我们最近将会增加代码高亮等功能,希望大家多多支持我们 zeroclipboard是一个跨浏览器的库类 它利用 Flash 进行复制,所以只要浏览器装有 Flash 就可以运行,而且比 IE 的

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令

maven发布项目到私服-snapshot快照库和release发布库的区别和作用及maven常用命令 在日常的工作中由于各种原因,会出现这样一种情况,某些项目并没有打包至mvnrepository。如果采用原始直接打包放到lib目录的方式进行处理,便对项目的管理带来一些不必要的麻烦。例如版本升级后需要重新打包并,替换原有jar包等等一些额外的工作量和麻烦。为了避免这些不必要的麻烦,通常我们