您的位置:首页 > 其它

H264通过RTMP发布 V2.0 (Red5 Wowza 测试通过)

2013-03-18 16:45 344 查看
直接上代码

[cpp] view
plaincopy

// 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;

}

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: