转:H264通过RTMP发布(Red5 wowza测试通过)

转:H264通过RTMP发布(Red5 wowza测试通过) - 加菲 - .

 

 

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值