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


直接上代码

 

[cpp]  view plain copy
  1. // demo.cpp : 定义控制台应用程序的入口点。  
  2. //  
  3. #include "stdafx.h"  
  4. #include <MqOaI.h>  
  5. extern "C"   
  6. {  
  7. #include "../../common/common.h"  
  8. #include "../../common/cpu.h""  
  9. #include "../../x264.h"  
  10. #include "../../encoder/set.h"  
  11. }  
  12. #include "librtmp/rtmp_sys.h"  
  13. #include "librtmp/log.h"  
  14. #include "librtmp/amf.h"  
  15. #include "CameraDS.h"  
  16. void ConvertYCbCr2BGR(unsigned char *pYUV,unsigned char *pBGR,int iWidth,int iHeight);  
  17. void ConvertRGB2YUV(int w,int h,unsigned char *bmp,unsigned char *yuv);  
  18. int InitSockets()  
  19. {  
  20. #ifdef WIN32  
  21.     WORD version;  
  22.     WSADATA wsaData;  
  23.     version = MAKEWORD(1, 1);  
  24.     return (WSAStartup(version, &wsaData) == 0);  
  25. #else  
  26.     return TRUE;  
  27. #endif  
  28. }  
  29. inline void CleanupSockets()  
  30. {  
  31. #ifdef WIN32  
  32.     WSACleanup();  
  33. #endif  
  34. }  
  35. #define HEX2BIN(a)      (((a)&0x40)?((a)&0xf)+9:((a)&0xf))  
  36. int hex2bin(char *str, char **hex)  
  37. {  
  38.     char *ptr;  
  39.     int i, l = strlen(str);  
  40.     if (l & 1)  
  41.         return 0;  
  42.     *hex = (char *)malloc(l/2);  
  43.     ptr = *hex;  
  44.     if (!ptr)  
  45.         return 0;  
  46.     for (i=0; i<l; i+=2)  
  47.         *ptr++ = (HEX2BIN(str[i]) << 4) | HEX2BIN(str[i+1]);  
  48.     return l/2;  
  49. }  
  50. char * put_byte( char *output, uint8_t nVal )  
  51. {  
  52.     output[0] = nVal;  
  53.     return output+1;  
  54. }  
  55. char * put_be16(char *output, uint16_t nVal )  
  56. {  
  57.     output[1] = nVal & 0xff;  
  58.     output[0] = nVal >> 8;  
  59.     return output+2;  
  60. }  
  61. char * put_be24(char *output,uint32_t nVal )  
  62. {  
  63.     output[2] = nVal & 0xff;  
  64.     output[1] = nVal >> 8;  
  65.     output[0] = nVal >> 16;  
  66.     return output+3;  
  67. }  
  68. char * put_be32(char *output, uint32_t nVal )  
  69. {  
  70.     output[3] = nVal & 0xff;  
  71.     output[2] = nVal >> 8;  
  72.     output[1] = nVal >> 16;  
  73.     output[0] = nVal >> 24;  
  74.     return output+4;  
  75. }  
  76. char *  put_be64( char *output, uint64_t nVal )  
  77. {  
  78.     output=put_be32( output, nVal >> 32 );  
  79.     output=put_be32( output, nVal );  
  80.     return output;  
  81. }  
  82. char * put_amf_string( char *c, const char *str )  
  83. {  
  84.     uint16_t len = strlen( str );  
  85.     c=put_be16( c, len );  
  86.     memcpy(c,str,len);  
  87.     return c+len;  
  88. }  
  89. char * put_amf_double( char *c, double d )  
  90. {  
  91.     *c++ = AMF_NUMBER;  /* type: Number */  
  92.     {  
  93.         unsigned char *ci, *co;  
  94.         ci = (unsigned char *)&d;  
  95.         co = (unsigned char *)c;  
  96.         co[0] = ci[7];  
  97.         co[1] = ci[6];  
  98.         co[2] = ci[5];  
  99.         co[3] = ci[4];  
  100.         co[4] = ci[3];  
  101.         co[5] = ci[2];  
  102.         co[6] = ci[1];  
  103.         co[7] = ci[0];  
  104.     }  
  105.     return c+8;  
  106. }  
  107. int main(int argc, char * argv[])  
  108. {  
  109.     if (argc<2)   
  110.     {  
  111.         RTMP_LogPrintf("RTMP_URL IS NULL!!!/n");  
  112.         //return -1;  
  113.     }  
  114.     if (!InitSockets())  
  115.     {  
  116.         RTMP_LogPrintf("InitSockets Error!/n");  
  117.         return -1;  
  118.     }  
  119.     RTMP_LogPrintf("InitSockets!/n");  
  120.     CoInitialize(NULL);  
  121.     CCameraDS camera;  
  122.     if (!camera.OpenCamera(0,320,240,false))  
  123.     {  
  124.         RTMP_LogPrintf("Open Camera Error/n");  
  125.         return -1;  
  126.     }  
  127.     int nHeight=camera.GetHeight();  
  128.     int nWidth=camera.GetWidth();  
  129.     unsigned char * szRGBBuffer=new unsigned char[nHeight*nWidth * 3];  
  130.     RTMP_LogPrintf("Camera Open Scuess!  Picture Size[%2dx%d]/n",nWidth,nHeight);  
  131.     RTMP_debuglevel = RTMP_LOGINFO;  
  132.     RTMP *r;  
  133.     //char uri[]="rtmp://127.0.0.1/live/test";  
  134.     //char uri[]="rtmp://192.199.15.223/live/test";  
  135.     //char uri[]="rtmp://221.9.244.4/live/jltv";  
  136.     //char uri[]="rtmp://192.199.15.223/oflaDemo/red5StreamDemo";  
  137.     //char uri[]="rtmp://192.199.15.151/live/test";  
  138.     char uri[]="rtmp://127.0.0.1/live/zzj";  
  139.     r= RTMP_Alloc();  
  140.     RTMP_Init(r);  
  141.     RTMP_SetupURL(r, (char*)uri);  
  142.     RTMP_EnableWrite(r);  
  143.     RTMP_Connect(r, NULL);  
  144.     RTMP_ConnectStream(r,0);  
  145.     unsigned char szNalBuffer[1024*32];  
  146.     unsigned char szBodyBuffer[1024*32];  
  147.     x264_nal_t  *p264Nal;  
  148.     int         i264Nal;  
  149.     x264_param_t * p264Param;  
  150.     x264_picture_t * p264Pic;  
  151.     x264_t *p264Handle;   
  152.     p264Param = new x264_param_t();  
  153.     p264Pic  = new x264_picture_t();  
  154.     memset(p264Pic,0,sizeof(x264_picture_t));  
  155.     x264_param_default(p264Param);  //set default param  
  156.     p264Param->i_threads=2;  
  157.     p264Param->i_width   = nWidth;   //set frame width  
  158.     p264Param->i_height  = nHeight;  //set frame height  
  159.     /*baseline level 1.1*/  
  160.     p264Param->b_cabac =0;   
  161.     p264Param->i_bframe =0;  
  162.     p264Param->b_interlaced=0;  
  163.     p264Param->rc.i_rc_method=X264_RC_ABR;//X264_RC_CQP  
  164.     p264Param->i_level_idc=21;  
  165.     p264Param->rc.i_bitrate=200;  
  166.     p264Param->i_fps_num=30;  
  167.     p264Param->i_keyint_max=p264Param->i_fps_num*3;  
  168.     if((p264Handle = x264_encoder_open(p264Param)) == NULL)  
  169.     {  
  170.         fprintf( stderr, "x264_encoder_open failed/n" );  
  171.         return -2;  
  172.     }  
  173.     bs_t bs={0};  
  174.     x264_picture_alloc(p264Pic, X264_CSP_YV12, p264Param->i_width, p264Param->i_height);  
  175.     p264Pic->i_type = X264_TYPE_AUTO;  
  176.     x264_picture_t pic_out;  
  177.     RTMPPacket packet={0};  
  178.     memset(&packet,0,sizeof(RTMPPacket));  
  179.     packet.m_nChannel = 0x04;  
  180.     packet.m_headerType = RTMP_PACKET_SIZE_LARGE;  
  181.     packet.m_nTimeStamp = 0;  
  182.     packet.m_nInfoField2 = r->m_stream_id;  
  183.     packet.m_hasAbsTimestamp = 0;  
  184.     packet.m_body =(char *) szBodyBuffer;  
  185.     char * szTmp=(char *)szBodyBuffer;  
  186.     packet.m_packetType = RTMP_PACKET_TYPE_INFO;  
  187.     szTmp=put_byte(szTmp, AMF_STRING );  
  188.     szTmp=put_amf_string(szTmp, "@setDataFrame" );  
  189.     szTmp=put_byte(szTmp, AMF_STRING );  
  190.     szTmp=put_amf_string(szTmp, "onMetaData" );  
  191.     szTmp=put_byte(szTmp, AMF_OBJECT );  
  192.     szTmp=put_amf_string( szTmp, "author" );  
  193.     szTmp=put_byte(szTmp, AMF_STRING );  
  194.     szTmp=put_amf_string( szTmp, "" );  
  195.     szTmp=put_amf_string( szTmp, "copyright" );  
  196.     szTmp=put_byte(szTmp, AMF_STRING );  
  197.     szTmp=put_amf_string( szTmp, "" );  
  198.     szTmp=put_amf_string( szTmp, "description" );  
  199.     szTmp=put_byte(szTmp, AMF_STRING );  
  200.     szTmp=put_amf_string( szTmp, "" );  
  201.     szTmp=put_amf_string( szTmp, "keywords" );  
  202.     szTmp=put_byte(szTmp, AMF_STRING );  
  203.     szTmp=put_amf_string( szTmp, "" );  
  204.     szTmp=put_amf_string( szTmp, "rating" );  
  205.     szTmp=put_byte(szTmp, AMF_STRING );  
  206.     szTmp=put_amf_string( szTmp, "" );  
  207.     szTmp=put_amf_string( szTmp, "presetname" );  
  208.     szTmp=put_byte(szTmp, AMF_STRING );  
  209.     szTmp=put_amf_string( szTmp, "Custom" );  
  210.     szTmp=put_amf_string( szTmp, "width" );  
  211.     szTmp=put_amf_double( szTmp, p264Param->i_width );  
  212.     szTmp=put_amf_string( szTmp, "width" );  
  213.     szTmp=put_amf_double( szTmp, p264Param->i_width );  
  214.     szTmp=put_amf_string( szTmp, "height" );  
  215.     szTmp=put_amf_double( szTmp, p264Param->i_height );  
  216.     szTmp=put_amf_string( szTmp, "framerate" );  
  217.     szTmp=put_amf_double( szTmp, (double)p264Param->i_fps_num / p264Param->i_fps_den );  
  218.     szTmp=put_amf_string( szTmp, "videocodecid" );  
  219.     szTmp=put_byte(szTmp, AMF_STRING );  
  220.     szTmp=put_amf_string( szTmp, "avc1" );  
  221.     szTmp=put_amf_string( szTmp, "videodatarate" );  
  222.     szTmp=put_amf_double( szTmp, p264Param->rc.i_bitrate );   
  223.     szTmp=put_amf_string( szTmp, "avclevel" );  
  224.     szTmp=put_amf_double( szTmp, p264Param->i_level_idc );   
  225.     szTmp=put_amf_string( szTmp, "avcprofile" );  
  226.     szTmp=put_amf_double( szTmp, 0x42 );   
  227.     szTmp=put_amf_string( szTmp, "videokeyframe_frequency" );  
  228.     szTmp=put_amf_double( szTmp, 3 );   
  229.     szTmp=put_amf_string( szTmp, "" );  
  230.     szTmp=put_byte( szTmp, AMF_OBJECT_END );  
  231.     packet.m_nBodySize=szTmp-(char *)szBodyBuffer;  
  232.     RTMP_SendPacket(r,&packet,1);  
  233.     packet.m_packetType = RTMP_PACKET_TYPE_VIDEO;   /* VIDEO */  
  234.     szBodyBuffer[ 0]=0x17;  
  235.     szBodyBuffer[ 1]=0x00;  
  236.     szBodyBuffer[ 2]=0x00;  
  237.     szBodyBuffer[ 3]=0x00;  
  238.     szBodyBuffer[ 4]=0x00;  
  239.     szBodyBuffer[ 5]=0x01;  
  240.     szBodyBuffer[ 6]=0x42;  
  241.     szBodyBuffer[ 7]=0xC0;  
  242.     szBodyBuffer[ 8]=0x15;  
  243.     szBodyBuffer[ 9]=0x03;  
  244.     szBodyBuffer[10]=0x01;  
  245.     szTmp=(char *)szBodyBuffer+11;  
  246.     short slen=0;  
  247.     bs_init(&bs,szNalBuffer,16);//初始话bs  
  248.     x264_sps_write(&bs, p264Handle->sps);//读取编码器的SPS  
  249.     slen=bs.p-bs.p_start+1;//spslen(short)  
  250.     slen=htons(slen);  
  251.     memcpy(szTmp,&slen,sizeof(short));  
  252.     szTmp+=sizeof(short);  
  253.     *szTmp=0x67;  
  254.     szTmp+=1;  
  255.     memcpy(szTmp,bs.p_start,bs.p-bs.p_start);  
  256.     szTmp+=bs.p-bs.p_start;  
  257.     *szTmp=0x01;  
  258.     szTmp+=1;  
  259.     bs_init(&bs,szNalBuffer,16);//初始话bs  
  260.     x264_pps_write(&bs, p264Handle->pps);//读取编码器的PPS  
  261.     slen=bs.p-bs.p_start+1;//spslen(short)  
  262.     slen=htons(slen);  
  263.     memcpy(szTmp,&slen,sizeof(short));  
  264.     szTmp+=sizeof(short);  
  265.     *szTmp=0x68;  
  266.     szTmp+=1;  
  267.     memcpy(szTmp,bs.p_start,bs.p-bs.p_start);  
  268.     szTmp+=bs.p-bs.p_start;  
  269.     packet.m_nBodySize=szTmp-(char *)szBodyBuffer;  
  270.     RTMP_SendPacket(r,&packet,0);  
  271.     unsigned int nTimes=0;  
  272.     unsigned int oldTick=GetTickCount();  
  273.     unsigned int newTick=0;  
  274.     packet.m_nTimeStamp=0;  
  275.       
  276.     while(true)  
  277.     {  
  278.         szBodyBuffer[ 0]=0x17;  
  279.         szBodyBuffer[ 1]=0x01;  
  280.         szBodyBuffer[ 2]=0x00;  
  281.         szBodyBuffer[ 3]=0x00;  
  282.         szBodyBuffer[ 4]=0x42;  
  283.         unsigned char * szTmp=szBodyBuffer+5;  
  284.         unsigned  char * pNal=szNalBuffer;  
  285.         nTimes++;  
  286.         int nFramsInPack=0;  
  287.         while(true)  
  288.         {  
  289.             nFramsInPack++;  
  290.             unsigned char * pCameraBuf = camera.QueryFrame();  
  291.             if (!pCameraBuf)  
  292.             {  
  293.                 return -1;  
  294.             }  
  295.             for(int ii=0;ii<nHeight;ii++)  
  296.             {  
  297.                 memcpy(szRGBBuffer+(nWidth*3)*(nHeight-ii-1),pCameraBuf+(nWidth*3)*ii,nWidth*3);  
  298.                 //memcpy(pCameraBuf+nWidth*(nHeight-ii-1),pCameraBuf+nWidth*ii,nWidth*3);  
  299.                 //memcpy(szLineBuffer,pCameraBuf+nWidth*(nHeight-ii-1),nWidth*3);  
  300.             }  
  301.             ConvertRGB2YUV(nWidth,nHeight,szRGBBuffer,p264Pic->img.plane[0]);  
  302.             //memcpy(p264Pic->img.plane[0],szNalBuffer,nWidth*nHeight);  
  303.             //memcpy(p264Pic->img.plane[1],szNalBuffer+nWidth*nHeight,nWidth*nHeight/4);  
  304.             //memcpy(p264Pic->img.plane[2],szNalBuffer+nWidth*nHeight*5/4,nWidth*nHeight/4);  
  305.             /* 
  306.             int nCount; 
  307.             nCount=fread(p264Pic->img.plane[0],1,176*144,yuv); 
  308.             if (nCount<176*144) 
  309.             { 
  310.             fseek(yuv,SEEK_SET,0); 
  311.             continue; 
  312.             } 
  313.             nCount=fread(p264Pic->img.plane[1],1,176*144/4,yuv); 
  314.             if (nCount<176*144/4) 
  315.             { 
  316.             fseek(yuv,SEEK_SET,0); 
  317.             continue; 
  318.             } 
  319.             nCount=fread(p264Pic->img.plane[2],1,176*144/4,yuv); 
  320.             if (nCount<176*144/4) 
  321.             { 
  322.             fseek(yuv,SEEK_SET,0); 
  323.             continue; 
  324.             } 
  325.             */  
  326.             if( x264_encoder_encode( p264Handle, &p264Nal, &i264Nal, p264Pic ,&pic_out) < 0 )  
  327.             {  
  328.                 fprintf( stderr, "x264_encoder_encode failed/n" );  
  329.             }  
  330.             forint i = 0; i < i264Nal; i++ )  
  331.             {  
  332.                 int i_size;  
  333.                 int i_data;  
  334.                 i_data = 1024*32;  
  335.                 if( ( i_size = x264_nal_encode( pNal, &i_data, 1, &p264Nal[i] ) ) > 0 )  
  336.                 {  
  337.                     if ((pNal[4]&0x60)==0)  
  338.                     {  
  339.                         continue;  
  340.                     }  
  341.                     if (pNal[4]==0x67)  
  342.                     {  
  343.                         continue;  
  344.                     }  
  345.                     if (pNal[4]==0x68)  
  346.                     {  
  347.                         continue;  
  348.                     }  
  349.                     memmove(pNal,pNal+4,i_size-4);  
  350.                     pNal+=i_size-4;  
  351.                 }  
  352.                 else if( i_size < 0 )  
  353.                 {  
  354.                     fprintf( stderr,"need to increase buffer size (size=%d)/n", -i_size );  
  355.                 }  
  356.             }  
  357.             unsigned int nSize=pNal-szNalBuffer;  
  358.             packet.m_nBodySize=nSize+9;  
  359.             if (i264Nal>1)  
  360.             {  
  361.                 szBodyBuffer[ 0]=0x17;  
  362.             }  
  363.             else  
  364.             {  
  365.                 szBodyBuffer[ 0]=0x27;  
  366.             }  
  367.             put_be32((char *)szBodyBuffer+5,nSize);  
  368.             memcpy(szBodyBuffer+9,szNalBuffer,pNal-szNalBuffer);  
  369.             RTMP_SendPacket(r,&packet,0);  
  370.             Sleep(20);  
  371.             newTick=GetTickCount();  
  372.             //RTMP_LogStatus("/rInfo NAUL Type:0x%02x size: %5d Tick:%03d %03d",szNalBuffer[0], nSize,33-nSleep,GetTickCount()-oldTick+nSleep);  
  373.             packet.m_headerType = RTMP_PACKET_SIZE_MEDIUM;  
  374.             packet.m_nTimeStamp+=newTick-oldTick;  
  375.             oldTick=newTick;  
  376.             break;  
  377.         }  
  378.     }  
  379.     return 0;  
  380. }  
 

 

H264通过RTMP发布 V2.0 (Red5 Wowza 测试通过)_第1张图片


转自 http://blog.csdn.net/zblue78/article/details/6406707

你可能感兴趣的:(H264通过RTMP发布 V2.0 (Red5 Wowza 测试通过))