本文共 14441 字,大约阅读时间需要 48 分钟。
rtmpdump 是一个可以通过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/