直接上代码
// demo.cpp : 定义控制台应用程序的入口点。 // #include "stdafx.h" #include <MqOaI.h> extern "C" { #include "../../common/common.h" #include "../../common/cpu.h"" #include "../../x264.h" #include "../../encoder/set.h" } #include "librtmp/rtmp_sys.h" #include "librtmp/log.h" #include "librtmp/amf.h" #include "CameraDS.h" void ConvertYCbCr2BGR(unsigned char *pYUV,unsigned char *pBGR,int iWidth,int iHeight); void ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned char *yuv); int InitSockets() { #ifdef WIN32 WORD version; WSADATA wsaData; version = MAKEWORD(1, 1); return (WSAStartup(version, &wsaData) == 0); #else return TRUE; #endif } inline void CleanupSockets() { #ifdef WIN32 WSACleanup(); #endif } #define HEX2BIN(a) (((a)&0x40)?((a)&0xf)+9:((a)&0xf)) int hex2bin(char *str, char **hex) { char *ptr; int i, l = strlen(str); if (l & 1) return 0; *hex = (char *)malloc(l/2); ptr = *hex; if (!ptr) return 0; for (i=0; i<l; i+=2) *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i+1]); return l/2; } char * put_byte( char *output, uint8_t nVal ) { output[0] = nVal; return output+1; } char * put_be16(char *output, uint16_t nVal ) { output[1] = nVal & 0xff; output[0] = nVal >> 8; return output+2; } char * put_be24(char *output,uint32_t nVal ) { output[2] = nVal & 0xff; output[1] = nVal >> 8; output[0] = nVal >> 16; return output+3; } char * put_be32(char *output, uint32_t nVal ) { output[3] = nVal & 0xff; output[2] = nVal >> 8; output[1] = nVal >> 16; output[0] = nVal >> 24; return output+4; } char * put_be64( char *output, uint64_t nVal ) { output=put_be32( output, nVal >> 32 ); output=put_be32( output, nVal ); return output; } char * put_amf_string( char *c, const char *str ) { uint16_t len = strlen( str ); c=put_be16( c, len ); memcpy(c,str,len); return c+len; } char * put_amf_double( char *c, double d ) { *c++ = AMF_NUMBER; /* type: Number */ { unsigned char *ci, *co; ci = (unsigned char *)&d; co = (unsigned char *)c; co[0] = ci[7]; co[1] = ci[6]; co[2] = ci[5]; co[3] = ci[4]; co[4] = ci[3]; co[5] = ci[2]; co[6] = ci[1]; co[7] = ci[0]; } return c+8; } int main(int argc, char * argv[]) { if (argc<2) { RTMP_LogPrintf("RTMP_URL IS NULL!!!/n"); //return -1; } if (!InitSockets()) { RTMP_LogPrintf("InitSockets Error!/n"); return -1; } RTMP_LogPrintf("InitSockets!/n"); CoInitialize(NULL); CCameraDS camera; if (!camera.OpenCamera(0,320,240,false)) { RTMP_LogPrintf("Open Camera Error/n"); return -1; } int nHeight=camera.GetHeight(); int nWidth=camera.GetWidth(); unsigned char * szRGBBuffer=new unsigned char[nHeight*nWidth * 3]; RTMP_LogPrintf("Camera Open Scuess! Picture Size[%2dx%d]/n",nWidth,nHeight); RTMP_debuglevel = RTMP_LOGINFO; RTMP *r; //char uri[]="rtmp://127.0.0.1/live/test"; //char uri[]="rtmp://192.199.15.223/live/test"; //char uri[]="rtmp://221.9.244.4/live/jltv"; //char uri[]="rtmp://192.199.15.223/oflaDemo/red5StreamDemo"; //char uri[]="rtmp://192.199.15.151/live/test"; char uri[]="rtmp://127.0.0.1/live/zzj"; r= RTMP_Alloc(); RTMP_Init(r); RTMP_SetupURL(r, (char*)uri); RTMP_EnableWrite(r); RTMP_Connect(r, NULL); RTMP_ConnectStream(r,0); unsigned char szNalBuffer[1024*32]; unsigned char szBodyBuffer[1024*32]; x264_nal_t *p264Nal; int i264Nal; x264_param_t * p264Param; x264_picture_t * p264Pic; x264_t *p264Handle; p264Param = new x264_param_t(); p264Pic = new x264_picture_t(); memset(p264Pic,0,sizeof(x264_picture_t)); x264_param_default(p264Param); //set default param p264Param->i_threads=2; p264Param->i_width = nWidth; //set frame width p264Param->i_height = nHeight; //set frame height /*baseline level 1.1*/ p264Param->b_cabac =0; p264Param->i_bframe =0; p264Param->b_interlaced=0; p264Param->rc.i_rc_method=X264_RC_ABR;//X264_RC_CQP p264Param->i_level_idc=21; p264Param->rc.i_bitrate=200; p264Param->i_fps_num=30; p264Param->i_keyint_max=p264Param->i_fps_num*3; if((p264Handle = x264_encoder_open(p264Param)) == NULL) { fprintf( stderr, "x264_encoder_open failed/n" ); return -2; } bs_t bs={0}; x264_picture_alloc(p264Pic, X264_CSP_YV12, p264Param->i_width, p264Param->i_height); p264Pic->i_type = X264_TYPE_AUTO; x264_picture_t pic_out; RTMPPacket packet={0}; memset(&packet,0,sizeof(RTMPPacket)); packet.m_nChannel = 0x04; packet.m_headerType = RTMP_PACKET_SIZE_LARGE; packet.m_nTimeStamp = 0; packet.m_nInfoField2 = r->m_stream_id; packet.m_hasAbsTimestamp = 0; packet.m_body =(char *) szBodyBuffer; char * szTmp=(char *)szBodyBuffer; packet.m_packetType = RTMP_PACKET_TYPE_INFO; szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string(szTmp, "@setDataFrame" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string(szTmp, "onMetaData" ); szTmp=put_byte(szTmp, AMF_OBJECT ); szTmp=put_amf_string( szTmp, "author" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "" ); szTmp=put_amf_string( szTmp, "copyright" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "" ); szTmp=put_amf_string( szTmp, "description" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "" ); szTmp=put_amf_string( szTmp, "keywords" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "" ); szTmp=put_amf_string( szTmp, "rating" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "" ); szTmp=put_amf_string( szTmp, "presetname" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "Custom" ); szTmp=put_amf_string( szTmp, "width" ); szTmp=put_amf_double( szTmp, p264Param->i_width ); szTmp=put_amf_string( szTmp, "width" ); szTmp=put_amf_double( szTmp, p264Param->i_width ); szTmp=put_amf_string( szTmp, "height" ); szTmp=put_amf_double( szTmp, p264Param->i_height ); szTmp=put_amf_string( szTmp, "framerate" ); szTmp=put_amf_double( szTmp, (double)p264Param->i_fps_num / p264Param->i_fps_den ); szTmp=put_amf_string( szTmp, "videocodecid" ); szTmp=put_byte(szTmp, AMF_STRING ); szTmp=put_amf_string( szTmp, "avc1" ); szTmp=put_amf_string( szTmp, "videodatarate" ); szTmp=put_amf_double( szTmp, p264Param->rc.i_bitrate ); szTmp=put_amf_string( szTmp, "avclevel" ); szTmp=put_amf_double( szTmp, p264Param->i_level_idc ); szTmp=put_amf_string( szTmp, "avcprofile" ); szTmp=put_amf_double( szTmp, 0x42 ); szTmp=put_amf_string( szTmp, "videokeyframe_frequency" ); szTmp=put_amf_double( szTmp, 3 ); szTmp=put_amf_string( szTmp, "" ); szTmp=put_byte( szTmp, AMF_OBJECT_END ); packet.m_nBodySize=szTmp-(char *)szBodyBuffer; RTMP_SendPacket(r,&packet,1); packet.m_packetType = RTMP_PACKET_TYPE_VIDEO; /* VIDEO */ szBodyBuffer[ 0]=0x17; szBodyBuffer[ 1]=0x00; szBodyBuffer[ 2]=0x00; szBodyBuffer[ 3]=0x00; szBodyBuffer[ 4]=0x00; szBodyBuffer[ 5]=0x01; szBodyBuffer[ 6]=0x42; szBodyBuffer[ 7]=0xC0; szBodyBuffer[ 8]=0x15; szBodyBuffer[ 9]=0x03; szBodyBuffer[10]=0x01; szTmp=(char *)szBodyBuffer+11; short slen=0; bs_init(&bs,szNalBuffer,16);//初始话bs x264_sps_write(&bs, p264Handle->sps);//读取编码器的SPS slen=bs.p-bs.p_start+1;//spslen(short) slen=htons(slen); memcpy(szTmp,&slen,sizeof(short)); szTmp+=sizeof(short); *szTmp=0x67; szTmp+=1; memcpy(szTmp,bs.p_start,bs.p-bs.p_start); szTmp+=bs.p-bs.p_start; *szTmp=0x01; szTmp+=1; bs_init(&bs,szNalBuffer,16);//初始话bs x264_pps_write(&bs, p264Handle->pps);//读取编码器的PPS slen=bs.p-bs.p_start+1;//spslen(short) slen=htons(slen); memcpy(szTmp,&slen,sizeof(short)); szTmp+=sizeof(short); *szTmp=0x68; szTmp+=1; memcpy(szTmp,bs.p_start,bs.p-bs.p_start); szTmp+=bs.p-bs.p_start; packet.m_nBodySize=szTmp-(char *)szBodyBuffer; RTMP_SendPacket(r,&packet,0); unsigned int nTimes=0; unsigned int oldTick=GetTickCount(); unsigned int newTick=0; packet.m_nTimeStamp=0; while(true) { szBodyBuffer[ 0]=0x17; szBodyBuffer[ 1]=0x01; szBodyBuffer[ 2]=0x00; szBodyBuffer[ 3]=0x00; szBodyBuffer[ 4]=0x42; unsigned char * szTmp=szBodyBuffer+5; unsigned char * pNal=szNalBuffer; nTimes++; int nFramsInPack=0; while(true) { nFramsInPack++; unsigned char * pCameraBuf = camera.QueryFrame(); if (!pCameraBuf) { return -1; } for(int ii=0;ii<nHeight;ii++) { memcpy(szRGBBuffer+(nWidth*3)*(nHeight-ii-1),pCameraBuf+(nWidth*3)*ii,nWidth*3); //memcpy(pCameraBuf+nWidth*(nHeight-ii-1),pCameraBuf+nWidth*ii,nWidth*3); //memcpy(szLineBuffer,pCameraBuf+nWidth*(nHeight-ii-1),nWidth*3); } ConvertRGB2YUV(nWidth,nHeight,szRGBBuffer,p264Pic->img.plane[0]); //memcpy(p264Pic->img.plane[0],szNalBuffer,nWidth*nHeight); //memcpy(p264Pic->img.plane[1],szNalBuffer+nWidth*nHeight,nWidth*nHeight/4); //memcpy(p264Pic->img.plane[2],szNalBuffer+nWidth*nHeight*5/4,nWidth*nHeight/4); /* int nCount; nCount=fread(p264Pic->img.plane[0],1,176*144,yuv); if (nCount<176*144) { fseek(yuv,SEEK_SET,0); continue; } nCount=fread(p264Pic->img.plane[1],1,176*144/4,yuv); if (nCount<176*144/4) { fseek(yuv,SEEK_SET,0); continue; } nCount=fread(p264Pic->img.plane[2],1,176*144/4,yuv); if (nCount<176*144/4) { fseek(yuv,SEEK_SET,0); continue; } */ if( x264_encoder_encode( p264Handle, &p264Nal, &i264Nal, p264Pic ,&pic_out) < 0 ) { fprintf( stderr, "x264_encoder_encode failed/n" ); } for( int i = 0; i < i264Nal; i++ ) { int i_size; int i_data; i_data = 1024*32; if( ( i_size = x264_nal_encode( pNal, &i_data, 1, &p264Nal[i] ) ) > 0 ) { if ((pNal[4]&0x60)==0) { continue; } if (pNal[4]==0x67) { continue; } if (pNal[4]==0x68) { continue; } memmove(pNal,pNal+4,i_size-4); pNal+=i_size-4; } else if( i_size < 0 ) { fprintf( stderr,"need to increase buffer size (size=%d)/n", -i_size ); } } unsigned int nSize=pNal-szNalBuffer; packet.m_nBodySize=nSize+9; if (i264Nal>1) { szBodyBuffer[ 0]=0x17; } else { szBodyBuffer[ 0]=0x27; } put_be32((char *)szBodyBuffer+5,nSize); memcpy(szBodyBuffer+9,szNalBuffer,pNal-szNalBuffer); RTMP_SendPacket(r,&packet,0); Sleep(20); newTick=GetTickCount(); //RTMP_LogStatus("/rInfo NAUL Type:0x%02x size: %5d Tick:%03d %03d",szNalBuffer[0], nSize,33-nSleep,GetTickCount()-oldTick+nSleep); packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM; packet.m_nTimeStamp+=newTick-oldTick; oldTick=newTick; break; } } return 0; }
您还没有登录,请您登录后再发表评论
在网上找到的将h264通过rtmp发布到flash media server。Red5 Wowza 测试通过。该代码使用到了x264和librtmp。如果要编译该源码,请先配置好x264和librtmp。
将h264裸流封装成flv格式后,通过rtmp协议发布到rtmp流服务器
将H264视频流打包成rtmp格式并发送,可以支持多路同时发送。该程序为dll
1、本视频流为h264编码,流来源为海康摄像头。 2、本视频播放时长为3分03秒,几乎可以满足所有测试需要。 3、本视频以原有电影为素材进行剪辑加工而成。 4、本视频分辨率为:1920*1080,帧率为25。 5、本视频下载...
内存中H264数据加原始PCM音频数据封装FLV格式发布出rtmp
h264裸流,可用于rtmp和rtsp推流测试,分辨率800*,608,绝对可用
1)、拉取RTSP流转推RTMP,支持H265转H264。 2)、可选择使用javaCV推流、ffmpeg推流两种方式。 3)、javaCV仅支持拉去或推送H264压缩方式的流。 4)、ffmpeg采用命令的方式拉流和推流,支持H265和H264。 5)、...
h264测试文件,通过rtmpdump库推送到red5服务器
H264 FAAC音视频采集编码,并经由Rtmp发布测试代码 1. 采用DirectShow实现摄像头视频数据和音频数据的采集 2. 采用x264/faac实现音视频的编码 3. 采用librtmp实现编码后音视频数据到Rtmp流媒体服务器的发布 4. 实际...
本文档记录了利用ffmpeg将摄像机采集的rtsp视频流转换为rtmp视频流,并推送到rtmp服务器red5的详细步骤。最终可以供VLC、web页面访问并展示rtmp视频。
基于rtmpdump的rtmp包转解码打包ts(h264+aac),通过rtmpdump收流,调用系统接口,转码音视频数据包成h264视频和aac的音频。供封转ts使用
测试rtmp流或者Adobe Media Server,red5等流媒体服务器是否部署成功
RTMP协议封 包 由一个...包体最大长度默认为128字节,通过chunkSize可改变包体最大长 度,通常当一段AFM数据超过128字节后,超过128的部分就放到了其他的RTMP封包中,包头为一个字节. 完整的12字节RTMP包头每个字节的含义:
纯C++代码,读取H264文件到内存推流到RTMP流媒体服务器,关键使用libRTMP库封装成RTMP协议格式!方便初学者
H264 to FLV and RTMP
1:通过DirectShow和DirectSound捕获指定摄像头和麦克风的数据,并使用x264和aac编码后通过librtmp发布到指定的RTMP服务端(red5/fms等)。 2:支持将摄像头和麦克风数据录制到本地FLV文件中(h.264/aac)。 3:可自定义...
支持h264和h265视频流封装成mp4文件和推流到rtmp服务器,资源是一个完整的VS工程,VS版本为2015,可直接运行。主要代码文件为zhf_h264_to_mp4_file.h和zhf_pushstream_rtmp.h
里面包含了如何把x264与rtmpdump集成到android studio中
rtmp 播放工具,支持H264 H265, 参考FFmpeg完成rtmp H265推流后,使用此工具测试OK. 工具同时支持将rtsp转码rtmp推送测试平台,比Wowza Streaming用着更方便,rtmp开发者值得拥有,具体开发问题也可留言讨论。谢谢
RTMP播放器测试程序
相关推荐
在网上找到的将h264通过rtmp发布到flash media server。Red5 Wowza 测试通过。该代码使用到了x264和librtmp。如果要编译该源码,请先配置好x264和librtmp。
将h264裸流封装成flv格式后,通过rtmp协议发布到rtmp流服务器
将H264视频流打包成rtmp格式并发送,可以支持多路同时发送。该程序为dll
1、本视频流为h264编码,流来源为海康摄像头。 2、本视频播放时长为3分03秒,几乎可以满足所有测试需要。 3、本视频以原有电影为素材进行剪辑加工而成。 4、本视频分辨率为:1920*1080,帧率为25。 5、本视频下载...
内存中H264数据加原始PCM音频数据封装FLV格式发布出rtmp
h264裸流,可用于rtmp和rtsp推流测试,分辨率800*,608,绝对可用
1)、拉取RTSP流转推RTMP,支持H265转H264。 2)、可选择使用javaCV推流、ffmpeg推流两种方式。 3)、javaCV仅支持拉去或推送H264压缩方式的流。 4)、ffmpeg采用命令的方式拉流和推流,支持H265和H264。 5)、...
h264测试文件,通过rtmpdump库推送到red5服务器
H264 FAAC音视频采集编码,并经由Rtmp发布测试代码 1. 采用DirectShow实现摄像头视频数据和音频数据的采集 2. 采用x264/faac实现音视频的编码 3. 采用librtmp实现编码后音视频数据到Rtmp流媒体服务器的发布 4. 实际...
本文档记录了利用ffmpeg将摄像机采集的rtsp视频流转换为rtmp视频流,并推送到rtmp服务器red5的详细步骤。最终可以供VLC、web页面访问并展示rtmp视频。
基于rtmpdump的rtmp包转解码打包ts(h264+aac),通过rtmpdump收流,调用系统接口,转码音视频数据包成h264视频和aac的音频。供封转ts使用
测试rtmp流或者Adobe Media Server,red5等流媒体服务器是否部署成功
RTMP协议封 包 由一个...包体最大长度默认为128字节,通过chunkSize可改变包体最大长 度,通常当一段AFM数据超过128字节后,超过128的部分就放到了其他的RTMP封包中,包头为一个字节. 完整的12字节RTMP包头每个字节的含义:
纯C++代码,读取H264文件到内存推流到RTMP流媒体服务器,关键使用libRTMP库封装成RTMP协议格式!方便初学者
H264 to FLV and RTMP
1:通过DirectShow和DirectSound捕获指定摄像头和麦克风的数据,并使用x264和aac编码后通过librtmp发布到指定的RTMP服务端(red5/fms等)。 2:支持将摄像头和麦克风数据录制到本地FLV文件中(h.264/aac)。 3:可自定义...
支持h264和h265视频流封装成mp4文件和推流到rtmp服务器,资源是一个完整的VS工程,VS版本为2015,可直接运行。主要代码文件为zhf_h264_to_mp4_file.h和zhf_pushstream_rtmp.h
里面包含了如何把x264与rtmpdump集成到android studio中
rtmp 播放工具,支持H264 H265, 参考FFmpeg完成rtmp H265推流后,使用此工具测试OK. 工具同时支持将rtsp转码rtmp推送测试平台,比Wowza Streaming用着更方便,rtmp开发者值得拥有,具体开发问题也可留言讨论。谢谢
RTMP播放器测试程序