Easypusher接口推送RTP数据

来源:互联网 发布:淘宝找优惠券怎么赚钱 编辑:程序博客网 时间:2024/05/22 03:43

最近在整合asterisk系统的视频通话录像功能,开始使用mp4v2库直接在asterisk系统中进行mp4视频文件的生成,测试发现性能上存在瓶颈,只能做到50路(双向即100mp4文件)左右的并发通话的mp4文件生成,初步分析问题主要在写文件上,鉴于此,希望能把RTP流送出到别的服务中进行录制。在网上查找了相关的流媒体服务,发现easydarwin比较适合我们当前的应用场景,准备使用其作为我们的流媒体服务器使用,把对接过程所遇到的问题进行记录,希望对有这方面应用的XDJM有一定的帮助。

 

一、环境说明:

1、EasyDarwin版本:Server: EasyDarwin/7.0.5 (Build/16.0518; Platform/Win32; Release/EasyDarwin; State/Development; )

 

下载地址:https://github.com/EasyDarwin/EasyDarwin/releases

2、Easypusher静态库版本:v1.2.16.1105

静态库下载地址:https://github.com/EasyDarwin/EasyPusher

3、Asterisk版本:Asterisk 1.8.20.1 built   (自行到官网下载一个能用的版本应该都行)

4、

 

二、源码:

 

isActivated = EasyPusher_Activate(KEY);/* 目前用到.a库的话,需要临时授权*/

switch(isActivated)

{

case EASY_ACTIVATE_INVALID_KEY:

ast_log(LOG_DEBUG, "KEY is EASY_ACTIVATE_INVALID_KEY!\n");

break;

case EASY_ACTIVATE_TIME_ERR:

ast_log(LOG_DEBUG, "KEY is EASY_ACTIVATE_TIME_ERR!\n");

break;

case EASY_ACTIVATE_PROCESS_NAME_LEN_ERR:

ast_log(LOG_DEBUG, "KEY is EASY_ACTIVATE_PROCESS_NAME_LEN_ERR!\n");

break;

case EASY_ACTIVATE_PROCESS_NAME_ERR:

ast_log(LOG_DEBUG, "KEY is EASY_ACTIVATE_PROCESS_NAME_ERR!\n");

break;

case EASY_ACTIVATE_VALIDITY_PERIOD_ERR:

ast_log(LOG_DEBUG, "KEY is EASY_ACTIVATE_VALIDITY_PERIOD_ERR!\n");

break;

case EASY_ACTIVATE_SUCCESS:

ast_log(LOG_DEBUG, "KEY is EASY_ACTIVATE_SUCCESS!\n");

break;

}

 

if(EASY_ACTIVATE_SUCCESS != isActivated)

{

ast_log(LOG_ERROR, "EasyPusher_Activate : NOT EASY_ACTIVATE_SUCCESS\n");

//return -1;

}

 

 memset(&fSourceMediaInfo, 0x00, sizeof(EASY_MEDIA_INFO_T));

fSourceMediaInfo.u32VideoCodec = EASY_SDK_VIDEO_CODEC_H264;// fSourceMediaInfo.u32VideoFps = 25; //

 

/*711语音处理*/

fSourceMediaInfo.u32AudioCodec = 0x10007;//EASY_SDK_AUDIO_CODEC_G711A;

fSourceMediaInfo.u32AudioSamplerate = 8000;

fSourceMediaInfo.u32AudioChannel = 1;

 

fPusherHandle = EasyPusher_Create();

fPusherBuff = malloc(2048*1024);

If (NULL == fPusherBuff )

    Return -1;

memset(fPusherBuff, 0, 2048*1024);

EasyPusher_SetEventCallback(fPusherHandle, __EasyPusher_Callback, 0, NULL);

EasyPusher_StartStream(fPusherHandle, ConfigIP, atoi(ConfigPort), ConfigName, "admin", "admin", &fSourceMediaInfo, 2048, 0);//2M缓冲区

ast_log(LOG_WARNING, "*** live streaming url:rtsp://%s:%d/%s ***\n", ConfigIP, atoi(ConfigPort), ConfigName);

bfile=fopen("/Data/h264test.264", "at+");/*调试用,写h264裸文件*/

 

 

{

now = ast_tvnow();

if( (f->frametype == AST_FRAME_VOICE)  && spsflag )// spsflag: 先写入视频数据

{

EASY_AV_Frame  avoiceFrame;

if(f->subclass.codec & AST_FORMAT_ALAW)//  例子里只处理ALAW语音,实际看接口,还支持ULAWG726AAC

{

//ast_log(LOG_WARNING, "AST_FORMAT_ALAW    f->datalen[%d]\n", f->datalen);

memset(&avoiceFrame, 0x00, sizeof(EASY_AV_Frame));

avoiceFrame.u32AVFrameLen =  f->datalen ;

avoiceFrame.pBuffer =AST_FRAME_GET_BUFFER(f) ;/* RTP包中的771裸数据,即RTP包中的PAYLOAD数据*/

avoiceFrame.u32AVFrameFlag = EASY_SDK_AUDIO_FRAME_FLAG;

avoiceFrame.u32TimestampSec =now.tv_sec;

avoiceFrame.u32TimestampUsec = now.tv_usec;

EasyPusher_PushFrame(fPusherHandle, &avoiceFrame);

}

}

else if (f->frametype == AST_FRAME_VIDEO) //写入视频数据

{

if (f->subclass.codec & AST_FORMAT_H264)

{

EASY_AV_Frame   avideoFrame;

unsigned char *frame = NULL;

unsigned char ttype ;

unsigned char h264_hdr[4] = {0};

 

frame = AST_FRAME_GET_BUFFER(f);/* RTP包中的h264裸数据,即RTP包中的PAYLOAD数据*/

ttype = (unsigned char)frame[0] & 0x1F;

memset(&avideoFrame, 0x00, sizeof(EASY_AV_Frame));

avideoFrame.u32TimestampSec = now.tv_sec;

avideoFrame.u32TimestampUsec = now.tv_usec;

 

h264_hdr[3] |= 0x1;

  /* 只有是SPSP帧才去调用API发送;否则会出现easydarwin保存成文件后,播放不出来的问题(直播不存在问题),具体原因不明确*/

if ((0x7 == ttype) || (0x1 == ttype))

{

spsflag += 1;

if (spsflag >1)

{

            fwrite(h264_hdr, 4, 1, bfile);

            fwrite(AST_FRAME_GET_BUFFER(f), 1, f->datalen, bfile);

     ttype = (unsigned char)fPusherBuff[4] & 0x1F;

            avideoFrame.u32VFrameType = (ttype==0x07)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;

            avideoFrame.u32AVFrameFlag = EASY_SDK_VIDEO_FRAME_FLAG;

            avideoFrame.u32AVFrameLen   =   fPusherBuffOffset;

            avideoFrame.pBuffer = fPusherBuff;

     spsflag = 1;

     EasyPusher_PushFrame(fPusherHandle, &avideoFrame);

 

     fPusherBuffOffset = 0;

     memset(fPusherBuff, 0, 2048*1024);

 

 

     memcpy(fPusherBuff+fPusherBuffOffset, h264_hdr, 4);

     fPusherBuffOffset += 4;

     memcpy(fPusherBuff+fPusherBuffOffset , AST_FRAME_GET_BUFFER(f), f->datalen);

     fPusherBuffOffset += f->datalen;

 

}

else

{

/*调试用,写h264裸文件*/

            fwrite(h264_hdr, 4, 1, bfile);

            fwrite(AST_FRAME_GET_BUFFER(f), 1, f->datalen, bfile);

     memcpy(fPusherBuff+fPusherBuffOffset, h264_hdr, 4);

     fPusherBuffOffset += 4;

     memcpy(fPusherBuff+fPusherBuffOffset , AST_FRAME_GET_BUFFER(f), f->datalen);

     fPusherBuffOffset += f->datalen;

}

}

else

{

            fwrite(h264_hdr, 4, 1, bfile);/*调试用,写h264裸文件*/

            fwrite(AST_FRAME_GET_BUFFER(f), 1, f->datalen, bfile);

     memcpy(fPusherBuff+fPusherBuffOffset, h264_hdr, 4);

     fPusherBuffOffset += 4;

     memcpy(fPusherBuff+fPusherBuffOffset , AST_FRAME_GET_BUFFER(f), f->datalen);

     fPusherBuffOffset += f->datalen;

}

 

}

}

}

 

三、参考:

1、利用EasyRTSPClient工具检查摄像机RTSP流不能播放原因以及排查音视频数据无法播放问题:http://blog.csdn.net/xiejiashu/article/details/53105103

2、H264裸数据推送参考:https://github.com/EasyDarwin/EasyPusher  解压后的EasyPusher_File目录

 

四、感谢:

非常感谢在调测试过程中,Babosa大神给予的指点,具体问题可以在EasyDarwin开源流媒体服务器QQ群中提出:496258327()

 

五、后续:

后续会针对并发性能做个测试,有新进展的话贴出分享受给大家

0 0