转自https://github.com/EasyDarwin/EasyPusher
easydarwin今年开始发力了, 不过有商业价值的模块都不开源,他们也得吃饭,可以理解。
本文仅实际体验一下demo,review一下示例代码,分析一下如何应用。
1)EasyPusher框图预览
2) EasyPusher应用实现
a. 推送h264文件
/*
Copyright (c) 2013-2014 EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.EasyDarwin.org
*/
#include "EasyPusherAPI.h"
#include "trace.h" int __EasyPusher_Callback(int _id, EASY_PUSH_STATE_T _state, EASY_AV_Frame *_frame, void *_userptr)
{
if (_state == EASY_PUSH_STATE_CONNECTING) printf("Connecting...\n");
else if (_state == EASY_PUSH_STATE_CONNECTED) printf("Connected\n");
else if (_state == EASY_PUSH_STATE_CONNECT_FAILED) printf("Connect failed\n");
else if (_state == EASY_PUSH_STATE_CONNECT_ABORT) printf("Connect abort\n");
else if (_state == EASY_PUSH_STATE_PUSHING) printf("P->");
else if (_state == EASY_PUSH_STATE_DISCONNECTED) printf("Disconnect.\n"); return ;
} int main()
{
char szIP[] = {};
Easy_Pusher_Handle pusherId = ;
EASY_MEDIA_INFO_T mediainfo; int buf_size = *;
char *pbuf = (char *) malloc(buf_size);
FILE *fES = NULL;
int position = ;
int iFrameNo = ; WSADATA wsaData;
WSAStartup(MAKEWORD(,), &wsaData); memset(&mediainfo, 0x00, sizeof(EASY_MEDIA_INFO_T));
mediainfo.u32VideoCodec = 0x1C; fES = fopen("./EasyDarwin.264", "rb");
if (NULL == fES) return ; pusherId = EasyPusher_Create(); EasyPusher_SetEventCallback(pusherId, __EasyPusher_Callback, , NULL); EasyPusher_StartStream(pusherId, "127.0.0.1", , "live.sdp", "admin", "admin", &mediainfo, );
//printf("*** live streaming url:rtsp://115.29.139.20:554/live.sdp ***\n"); while ()
{
int nReadBytes = fread(pbuf+position, , , fES);
if (nReadBytes < )
{
if (feof(fES))
{
position = ;
fseek(fES, , SEEK_SET);
continue;
}
break;
} position ++; if (position > )
{
unsigned char naltype = ( (unsigned char)pbuf[position-] & 0x1F); if ( (unsigned char)pbuf[position-]== 0x00 &&
(unsigned char)pbuf[position-]== 0x00 &&
(unsigned char)pbuf[position-] == 0x00 &&
(unsigned char)pbuf[position-] == 0x01 &&
//(((unsigned char)pbuf[position-1] == 0x61) ||
//((unsigned char)pbuf[position-1] == 0x67) ) )
(naltype==0x07||naltype==0x01) )
{
int framesize = position - ;
EASY_AV_Frame avFrame; naltype = (unsigned char)pbuf[] & 0x1F; memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
avFrame.u32AVFrameLen = framesize;
avFrame.pBuffer = (unsigned char*)pbuf;
avFrame.u32VFrameType = (naltype==0x07)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;
EasyPusher_PushFrame(pusherId, &avFrame); Sleep(); memmove(pbuf, pbuf+position-, );
position = ; iFrameNo ++; //if (iFrameNo > 100000) break;
//break;
}
}
} _TRACE("Press Enter exit...\n");
getchar();
EasyPusher_StopStream(pusherId);
EasyPusher_Release(pusherId); WSACleanup();
return ;
}
b. 推送Camera SDK回调的音视频数据,示例中的SDK是EasyDarwin开源摄像机的配套库,EasyCamera SDK及配套源码可在 http://www.easydarwin.org 或者 https://github.com/EasyDarwin/EasyCamera 获取到,也可以用自己项目中用到的SDK获取音视频数据进行推送;
/*
Copyright (c) 2013-2014 EasyDarwin.ORG. All rights reserved.
Github: https://github.com/EasyDarwin
WEChat: EasyDarwin
Website: http://www.EasyDarwin.org
*/
#define _CRTDBG_MAP_ALLOC
#include <stdio.h>
#include "EasyPusherAPI.h"
#include <winsock2.h>
#include "hi_type.h"
#include "hi_net_dev_sdk.h"
#include "hi_net_dev_errors.h"
#include "trace.h" #define UNAME "admin"
#define PWORD "admin"
#define DHOST "192.168.66.189" //EasyCamera摄像机IP地址
#define DPORT 80 //EasyCamera摄像机端口 #define SHOST "115.29.139.20" //EasyDarwin流媒体服务器地址
#define SPORT 554 //EasyDarwin流媒体服务器端口 HI_U32 u32Handle = ;
Easy_Pusher_Handle pusherHandle = ; HI_S32 OnEventCallback(HI_U32 u32Handle, /* 句柄 */
HI_U32 u32Event, /* 事件 */
HI_VOID* pUserData /* 用户数据*/
)
{
return HI_SUCCESS;
} HI_S32 NETSDK_APICALL OnStreamCallback(HI_U32 u32Handle, /* 句柄 */
HI_U32 u32DataType, /* 数据类型,视频或音频数据或音视频复合数据 */
HI_U8* pu8Buffer, /* 数据包含帧头 */
HI_U32 u32Length, /* 数据长度 */
HI_VOID* pUserData /* 用户数据*/
)
{ HI_S_AVFrame* pstruAV = HI_NULL;
HI_S_SysHeader* pstruSys = HI_NULL; if (u32DataType == HI_NET_DEV_AV_DATA)
{
pstruAV = (HI_S_AVFrame*)pu8Buffer; if (pstruAV->u32AVFrameFlag == HI_NET_DEV_VIDEO_FRAME_FLAG)
{
if(pusherHandle == )
return ; if(pstruAV->u32AVFrameLen > )
{
unsigned char* pbuf = (unsigned char*)(pu8Buffer+sizeof(HI_S_AVFrame));
unsigned char naltype = ( (unsigned char)pbuf[] & 0x1F); if ( (unsigned char)pbuf[]== 0x00 &&
(unsigned char)pbuf[]== 0x00 &&
(unsigned char)pbuf[] == 0x00 &&
(unsigned char)pbuf[] == 0x01 &&
(naltype==0x07 || naltype==0x01) )
{
EASY_AV_Frame avFrame; naltype = (unsigned char)pbuf[] & 0x1F;
memset(&avFrame, 0x00, sizeof(EASY_AV_Frame));
avFrame.u32AVFrameLen = pstruAV->u32AVFrameLen;
avFrame.pBuffer = (unsigned char*)pbuf;
avFrame.u32VFrameType = (naltype==0x07)?EASY_SDK_VIDEO_FRAME_I:EASY_SDK_VIDEO_FRAME_P;
EasyPusher_PushFrame(pusherHandle, &avFrame);
}
}
}
else
if (pstruAV->u32AVFrameFlag == HI_NET_DEV_AUDIO_FRAME_FLAG)
{
//printf("Audio %u PTS: %u \n", pstruAV->u32AVFrameLen, pstruAV->u32AVFramePTS);
//SaveRecordFile("Video.hx", pu8Buffer, u32Length);
}
}
else
if (u32DataType == HI_NET_DEV_SYS_DATA)
{
pstruSys = (HI_S_SysHeader*)pu8Buffer;
printf("Video W:%u H:%u Audio: %u \n", pstruSys->struVHeader.u32Width, pstruSys->struVHeader.u32Height, pstruSys->struAHeader.u32Format);
} return HI_SUCCESS;
} HI_S32 OnDataCallback(HI_U32 u32Handle, /* 句柄 */
HI_U32 u32DataType, /* 数据类型*/
HI_U8* pu8Buffer, /* 数据 */
HI_U32 u32Length, /* 数据长度 */
HI_VOID* pUserData /* 用户数据*/
)
{
return HI_SUCCESS;
} int __EasyPusher_Callback(int _id, EASY_PUSH_STATE_T _state, EASY_AV_Frame *_frame, void *_userptr)
{
if (_state == EASY_PUSH_STATE_CONNECTING) printf("Connecting...\n");
else if (_state == EASY_PUSH_STATE_CONNECTED) printf("Connected\n");
else if (_state == EASY_PUSH_STATE_CONNECT_FAILED) printf("Connect failed\n");
else if (_state == EASY_PUSH_STATE_CONNECT_ABORT) printf("Connect abort\n");
//else if (_state == EASY_PUSH_STATE_PUSHING) printf("P->");
else if (_state == EASY_PUSH_STATE_DISCONNECTED) printf("Disconnect.\n"); return ;
} int main()
{
HI_S32 s32Ret = HI_SUCCESS;
HI_S_STREAM_INFO struStreamInfo;
HI_U32 a; HI_NET_DEV_Init(); s32Ret = HI_NET_DEV_Login(&u32Handle, UNAME, PWORD, DHOST, DPORT);
if (s32Ret != HI_SUCCESS)
{
HI_NET_DEV_DeInit();
return -;
} //HI_NET_DEV_SetEventCallBack(u32Handle, OnEventCallback, &a);
HI_NET_DEV_SetStreamCallBack(u32Handle, (HI_ON_STREAM_CALLBACK)OnStreamCallback, &a);
//HI_NET_DEV_SetDataCallBack(u32Handle, OnDataCallback, &a); struStreamInfo.u32Channel = HI_NET_DEV_CHANNEL_1;
struStreamInfo.blFlag = HI_FALSE;//HI_FALSE;
struStreamInfo.u32Mode = HI_NET_DEV_STREAM_MODE_TCP;
struStreamInfo.u8Type = HI_NET_DEV_STREAM_ALL;
s32Ret = HI_NET_DEV_StartStream(u32Handle, &struStreamInfo);
if (s32Ret != HI_SUCCESS)
{
HI_NET_DEV_Logout(u32Handle);
u32Handle = ;
return -;
} WSADATA wsaData;
WSAStartup(MAKEWORD(,), &wsaData); EASY_MEDIA_INFO_T mediainfo; memset(&mediainfo, 0x00, sizeof(EASY_MEDIA_INFO_T));
mediainfo.u32VideoCodec = 0x1C; pusherHandle = EasyPusher_Create(); EasyPusher_SetEventCallback(pusherHandle, __EasyPusher_Callback, , NULL); EasyPusher_StartStream(pusherHandle, SHOST, SPORT, "live.sdp", "admin", "admin", &mediainfo, );
printf("*** live streaming url:rtsp://%s:%d/live.sdp ***\n", SHOST, SPORT); while()
{
Sleep();
}; EasyPusher_StopStream(pusherHandle);
EasyPusher_Release(pusherHandle);
pusherHandle = ; HI_NET_DEV_StopStream(u32Handle);
HI_NET_DEV_Logout(u32Handle); HI_NET_DEV_DeInit(); return ;
}
3) demo运行
先启动EasyDarwin服务器,然后启动EasyPusher,这里推送H264文件做测试
4)总结
重点:获取数据帧,发送数据帧,查找数据帧帧头。
end