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


    直接上代码

     // demo.cpp : 定义控制台应用程序的入口点。
    //
    #include "stdafx.h"
    #include
    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
            *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;    
        {
            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[-x%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
        
        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;    
        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
                {
                    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);
                
                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:0xx size: ] Tick:d d",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;
    }

  • 相关阅读:
    Codeforces 963A Alternating Sum 【数论+数学】
    大数相加 a+b
    BFS(广度优先搜索) poj3278
    PHPExcel 学习笔记
    一个高在线(可以超过1024)多线程的socket echo server(pthreads 和 libevent扩展)
    php pthreads 多线程扩展的使用:一个较为稳定例子。
    PHP 长字符串替换操作性能(替换多换注释的代码)
    最简单的PHP socket echo server。
    PHP 多线程扩展(正儿八经的线程)pthreads安装
    定长度结构体数组、不定长度结构体指针初始化
  • 原文地址:https://www.cnblogs.com/zjoch/p/3286307.html
Copyright © 2020-2023  润新知