博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
rtmpdump 实现flv视频数据的rtmp推流功能
阅读量:4200 次
发布时间:2019-05-26

本文共 14441 字,大约阅读时间需要 48 分钟。

rtmpdump 是一个可以通过RTMP协议上推和下载流媒体的工具.

1、rtmpdump的编译

下载rtmpdump
(请不要再使用v2.3的版本,建议使用rtmpdump2.4的版本,v2.3版本中有几个bug在里面)
编译
解压后直接make
(编译之前需要先安装openssl,apt-get install openssl;apt-get install libssl-dev)
应用
如:./rtmpdump -r rtmp://172.16.1.65:1935/vod/mp4:sample.mp4 -v -o test.flv
    ./rtmpdump -r "rtmp://live.hkstv.hk.lxdns.com/live/hks" -o test1.flv -q
   
      -r url参数
      -v 是否为直播 
      -o 保存的文件

2、rtmpdump 实现 flv视频数据的rtmp推流功能

Makefle

#!/bin/shINCLUDE = /ternence/test/rtmpdump/LIB_DIR = /ternence/test/rtmpdump/librtmp/LDFLAGS = -lrtmpSRC=rtmp_send.call:$(SRC)	gcc -g -Wall $(SRC) -o target -I $(INCLUDE) -L $(LIB_DIR)  $(LDFLAGS)

rtmp_send.c

#include 
#include
#include
#include
#ifndef WIN32#include
#endif#include "librtmp/rtmp_sys.h"#include "librtmp/log.h" #define HTON16(x) ((x>>8&0xff)|(x<<8&0xff00))#define HTON24(x) ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00))#define HTON32(x) ((x>>24&0xff)|(x>>8&0xff00)|\ (x<<8&0xff0000)|(x<<24&0xff000000))#define HTONTIME(x) ((x>>16&0xff)|(x<<16&0xff0000)|(x&0xff00)|(x&0xff000000))#define RTMP_SERVER_URL "rtmp://172.16.1.65:1935/test1/myStream"#define LOCAL_FILE "test.flv"/*read 1 byte*/int ReadU8(uint32_t *u8,FILE*fp){ if(fread(u8,1,1,fp)!=1) return 0; return 1;}/*read 2 byte*/int ReadU16(uint32_t *u16,FILE*fp){ if(fread(u16,2,1,fp)!=1) return 0; *u16=HTON16(*u16); return 1;}/*read 3 byte*/int ReadU24(uint32_t *u24,FILE*fp){ if(fread(u24,3,1,fp)!=1) return 0; *u24=HTON24(*u24); return 1;}/*read 4 byte*/int ReadU32(uint32_t *u32,FILE*fp){ if(fread(u32,4,1,fp)!=1) return 0; *u32=HTON32(*u32); return 1;}/*read 1 byte,and loopback 1 byte at once*/int PeekU8(uint32_t *u8,FILE*fp){ if(fread(u8,1,1,fp)!=1) return 0; fseek(fp,-1,SEEK_CUR); return 1;}/*read 4 byte and convert to time format*/int ReadTime(uint32_t *utime,FILE*fp){ if(fread(utime,4,1,fp)!=1) return 0; *utime=HTONTIME(*utime); return 1;} int InitSockets(){ /* WORD version; WSADATA wsaData; version=MAKEWORD(2,2); return (WSAStartup(version, &wsaData) == 0); */ return 1;} void CleanupSockets(){ // WSACleanup(); return;} //Publish using RTMP_SendPacket()int publish_using_packet(){ RTMP *rtmp=NULL; RTMPPacket *packet=NULL; uint32_t start_time=0; uint32_t now_time=0; uint32_t add_time_times=0; //the timestamp of the previous frame long pre_frame_time=0; long lasttime=0; //int bNextIsKey=1; uint32_t preTagsize=0; //packet attributes uint32_t type=0; uint32_t datalength=0; uint32_t timestamp=0; uint32_t streamid=0; FILE*fp=NULL; fp=fopen(LOCAL_FILE,"rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); CleanupSockets(); return -1; } /* set log level */ //RTMP_LogLevel loglvl=RTMP_LOGDEBUG; //RTMP_LogSetLevel(loglvl); if (!InitSockets()){ RTMP_LogPrintf("Init Socket Err\n"); return -1; } rtmp=RTMP_Alloc(); RTMP_Init(rtmp); //set connection timeout,default 30s rtmp->Link.timeout=5; if(!RTMP_SetupURL(rtmp,RTMP_SERVER_URL)) { RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n"); RTMP_Free(rtmp); CleanupSockets(); return -1; } //if unable,the AMF command would be 'play' instead of 'publish' RTMP_EnableWrite(rtmp); if (!RTMP_Connect(rtmp,NULL)){ RTMP_Log(RTMP_LOGERROR,"Connect Err\n"); RTMP_Free(rtmp); CleanupSockets(); return -1; } if (!RTMP_ConnectStream(rtmp,0)){ RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n"); RTMP_Close(rtmp); RTMP_Free(rtmp); CleanupSockets(); return -1; } packet=(RTMPPacket*)malloc(sizeof(RTMPPacket)); RTMPPacket_Alloc(packet,1024*1500); RTMPPacket_Reset(packet); packet->m_hasAbsTimestamp = 0; packet->m_nChannel = 0x04; packet->m_nInfoField2 = rtmp->m_stream_id; while(1) { RTMP_LogPrintf("Start to send data ...\n"); fp=fopen(LOCAL_FILE,"rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); CleanupSockets(); return -1; } //jump over FLV Header fseek(fp,9,SEEK_SET); //jump over previousTagSizen fseek(fp,4,SEEK_CUR); start_time=RTMP_GetTime(); lasttime = 0; pre_frame_time = 0; RTMP_LogPrintf("add_time_times:%8u ms\n",add_time_times); while(1) { //if((((now_time=RTMP_GetTime())-start_time) < (pre_frame_time)) && bNextIsKey){ if(((now_time=RTMP_GetTime())-start_time) < (pre_frame_time)){ //wait for 1 sec if the send process is too fast //this mechanism is not very good,need some improvement if(pre_frame_time>lasttime){ RTMP_LogPrintf("TimeStamp:%8lu ms\n",pre_frame_time); lasttime=pre_frame_time; } usleep(10000); // 10ms continue; } //not quite the same as FLV spec if(!ReadU8(&type,fp)) { break; printf("line:%d\n",__LINE__); } if(!ReadU24(&datalength,fp)) { break; printf("line:%d\n",__LINE__); } if(!ReadTime(×tamp,fp)) { break; printf("line:%d\n",__LINE__); } if(!ReadU24(&streamid,fp)) { break; printf("line:%d\n",__LINE__); } if (type!=0x08&&type!=0x09){ //jump over non_audio and non_video frame, //jump over next previousTagSizen at the same time fseek(fp,datalength+4,SEEK_CUR); continue; } if(fread(packet->m_body,1,datalength,fp)!=datalength) { break; printf("line:%d\n",__LINE__); } packet->m_headerType = RTMP_PACKET_SIZE_LARGE; packet->m_nTimeStamp = timestamp + add_time_times; packet->m_packetType = type; packet->m_nBodySize = datalength; pre_frame_time=timestamp; if (!RTMP_IsConnected(rtmp)){ RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n"); printf("line:%d\n",__LINE__); break; } if (!RTMP_SendPacket(rtmp,packet,0)){ RTMP_Log(RTMP_LOGERROR,"Send Error\n"); printf("line:%d\n",__LINE__); break; } if(!ReadU32(&preTagsize,fp)) { break; printf("line:%d\n",__LINE__); } if(!PeekU8(&type,fp)) { break; printf("line:%d\n",__LINE__); } if(type==0x09){ if(fseek(fp,11,SEEK_CUR)!=0) break; if(!PeekU8(&type,fp)){ break; } /* if(type==0x17) bNextIsKey=1; else bNextIsKey=0; */ fseek(fp,-11,SEEK_CUR); } } RTMP_LogPrintf("\nSend Data Over\n"); add_time_times += 237080; if(fp) fclose(fp); } if (rtmp!=NULL){ RTMP_Close(rtmp); RTMP_Free(rtmp); rtmp=NULL; } if (packet!=NULL){ RTMPPacket_Free(packet); free(packet); packet=NULL; } CleanupSockets(); return 0;} //Publish using RTMP_Write()int publish_using_write(){ uint32_t start_time=0; uint32_t now_time=0; uint32_t pre_frame_time=0; uint32_t lasttime=0; int bNextIsKey=0; char* pFileBuf=NULL; //read from tag header uint32_t type=0; uint32_t datalength=0; uint32_t timestamp=0; RTMP *rtmp=NULL; FILE*fp=NULL; fp=fopen(LOCAL_FILE,"rb"); if (!fp){ RTMP_LogPrintf("Open File Error.\n"); CleanupSockets(); return -1; } /* set log level */ //RTMP_LogLevel loglvl=RTMP_LOGDEBUG; //RTMP_LogSetLevel(loglvl); if (!InitSockets()){ RTMP_LogPrintf("Init Socket Err\n"); return -1; } rtmp=RTMP_Alloc(); RTMP_Init(rtmp); //set connection timeout,default 30s rtmp->Link.timeout=5; if(!RTMP_SetupURL(rtmp,RTMP_SERVER_URL)) { RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n"); RTMP_Free(rtmp); CleanupSockets(); return -1; } RTMP_EnableWrite(rtmp); //1hour RTMP_SetBufferMS(rtmp, 3600*1000); if (!RTMP_Connect(rtmp,NULL)){ RTMP_Log(RTMP_LOGERROR,"Connect Err\n"); RTMP_Free(rtmp); CleanupSockets(); return -1; } if (!RTMP_ConnectStream(rtmp,0)){ RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n"); RTMP_Close(rtmp); RTMP_Free(rtmp); CleanupSockets(); return -1; } printf("Start to send data ...\n"); //jump over FLV Header fseek(fp,9,SEEK_SET); //jump over previousTagSizen fseek(fp,4,SEEK_CUR); start_time=RTMP_GetTime(); while(1) { if((((now_time=RTMP_GetTime())-start_time) <(pre_frame_time)) && bNextIsKey){ //wait for 1 sec if the send process is too fast //this mechanism is not very good,need some improvement if(pre_frame_time>lasttime){ RTMP_LogPrintf("TimeStamp:%8u ms\n",pre_frame_time); lasttime=pre_frame_time; } sleep(1); continue; } //jump over type fseek(fp,1,SEEK_CUR); if(!ReadU24(&datalength,fp)) break; if(!ReadTime(×tamp,fp)) break; //jump back fseek(fp,-8,SEEK_CUR); pFileBuf=(char*)malloc(11+datalength+4); memset(pFileBuf,0,11+datalength+4); if(fread(pFileBuf,1,11+datalength+4,fp)!=(11+datalength+4)) break; pre_frame_time=timestamp; if (!RTMP_IsConnected(rtmp)){ RTMP_Log(RTMP_LOGERROR,"rtmp is not connect\n"); break; } if (!RTMP_Write(rtmp,pFileBuf,11+datalength+4)){ RTMP_Log(RTMP_LOGERROR,"Rtmp Write Error\n"); break; } free(pFileBuf); pFileBuf=NULL; if(!PeekU8(&type,fp)) break; if(type==0x09){ if(fseek(fp,11,SEEK_CUR)!=0) break; if(!PeekU8(&type,fp)){ break; } if(type==0x17) bNextIsKey=1; else bNextIsKey=0; fseek(fp,-11,SEEK_CUR); } } RTMP_LogPrintf("\nSend Data Over\n"); if(fp) fclose(fp); if (rtmp!=NULL){ RTMP_Close(rtmp); RTMP_Free(rtmp); rtmp=NULL; } if(pFileBuf){ free(pFileBuf); pFileBuf=NULL; } CleanupSockets(); return 0;} int main(int argc, char* argv[]){ //2 Methods: publish_using_packet(); //publish_using_write(); return 0;}

源码的下载地址:

转载地址:http://fefli.baihongyu.com/

你可能感兴趣的文章
RPT8.1新特性
查看>>
LoadRunner测试AJAX
查看>>
LoadRunner测试GWT
查看>>
负载测试项目成功的5个关键要素
查看>>
LoadRunner性能测试培训大纲
查看>>
LoadRunner测试J2ME的Socket程序
查看>>
《QTP自动化测试实践》要出第二版了!
查看>>
用LoadRunner开发开心网外挂
查看>>
QTP测试.NET控件CheckedListBox
查看>>
使用QTP的.NET插件扩展技术测试ComponentOne的ToolBar控件
查看>>
用上帝之眼进行自动化测试
查看>>
为LoadRunner写一个lr_save_float函数
查看>>
PrefTest工作室全新力作-《性能测试与调优实战》课程视频即将上线
查看>>
质量度量分析与测试技术 培训大纲
查看>>
欢迎加入【亿能测试快讯】邮件列表!
查看>>
为什么我们的自动化测试“要”这么难
查看>>
LoadRunner性能脚本开发实战训练
查看>>
测试之途,前途?钱途?图何?
查看>>
测试设计与测试项目实战训练
查看>>
HP Sprinter:敏捷加速器
查看>>