首页 > 代码库 > EasyPusher应用

EasyPusher应用

转自https://github.com/EasyDarwin/EasyPusher

 

本文仅实际体验一下demo,分析一下如何应用。

1)EasyPusher框图预览

技术分享

 

2) EasyPusher应用实现

啃代码才是关键,看懂demo才好熟练应用。

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 0;}int main(){    char szIP[16] = {0};    Easy_Pusher_Handle pusherId = 0;    EASY_MEDIA_INFO_T   mediainfo;    int buf_size = 1024*512;    char *pbuf = (char *) malloc(buf_size);    FILE *fES = NULL;    int position = 0;    int iFrameNo = 0;    WSADATA wsaData;    WSAStartup(MAKEWORD(2,2), &wsaData);    memset(&mediainfo, 0x00, sizeof(EASY_MEDIA_INFO_T));    mediainfo.u32VideoCodec =   0x1C;    fES = fopen("./EasyDarwin.264", "rb");    if (NULL == fES)        return 0;    pusherId = EasyPusher_Create();    EasyPusher_SetEventCallback(pusherId, __EasyPusher_Callback, 0, NULL);    EasyPusher_StartStream(pusherId, "127.0.0.1", 554, "live.sdp", "admin", "admin", &mediainfo, 512);    //printf("*** live streaming url:rtsp://115.29.139.20:554/live.sdp ***\n");    while (1)    {        int nReadBytes = fread(pbuf+position, 1, 1, fES);        if (nReadBytes < 1)        {            if (feof(fES))            {                position = 0;                fseek(fES, 0, SEEK_SET);                continue;            }            break;        }        position ++;        if (position > 5)        {            unsigned char naltype = ( (unsigned char)pbuf[position-1] & 0x1F);            if ( (unsigned char)pbuf[position-5]== 0x00 &&                     (unsigned char)pbuf[position-4]== 0x00 &&                     (unsigned char)pbuf[position-3] == 0x00 &&                    (unsigned char)pbuf[position-2] == 0x01 &&                    //(((unsigned char)pbuf[position-1] == 0x61) ||                    //((unsigned char)pbuf[position-1] == 0x67) ) )                    (naltype==0x07||naltype==0x01) )            {                int framesize = position - 5;                EASY_AV_Frame   avFrame;                naltype = (unsigned char)pbuf[4] & 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(30);                memmove(pbuf, pbuf+position-5, 5);                position = 5;                iFrameNo ++;                //if (iFrameNo > 100000) break;                //break;            }        }    }    _TRACE("Press Enter exit...\n");    getchar();    EasyPusher_StopStream(pusherId);    EasyPusher_Release(pusherId);    WSACleanup();    return 0;}

 

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 = 0;Easy_Pusher_Handle pusherHandle = 0;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 == 0 )                return 0;            if(pstruAV->u32AVFrameLen > 5)            {                unsigned char* pbuf = (unsigned char*)(pu8Buffer+sizeof(HI_S_AVFrame));                unsigned char naltype = ( (unsigned char)pbuf[4] & 0x1F);                if ( (unsigned char)pbuf[0]== 0x00 &&                         (unsigned char)pbuf[1]== 0x00 &&                         (unsigned char)pbuf[2] == 0x00 &&                        (unsigned char)pbuf[3] == 0x01 &&                        (naltype==0x07 || naltype==0x01) )                {                    EASY_AV_Frame  avFrame;                    naltype = (unsigned char)pbuf[4] & 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 0;}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 -1;    }        //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 = 0;        return -1;    }            WSADATA wsaData;    WSAStartup(MAKEWORD(2,2), &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, 0, NULL);    EasyPusher_StartStream(pusherHandle, SHOST, SPORT, "live.sdp", "admin", "admin", &mediainfo, 512);    printf("*** live streaming url:rtsp://%s:%d/live.sdp ***\n", SHOST, SPORT);    while(1)    {        Sleep(10);        };    EasyPusher_StopStream(pusherHandle);    EasyPusher_Release(pusherHandle);    pusherHandle = 0;       HI_NET_DEV_StopStream(u32Handle);    HI_NET_DEV_Logout(u32Handle);        HI_NET_DEV_DeInit();    return 0;}

 

3) demo运行

先启动EasyDarwin服务器,然后启动EasyPusher,这里推送H264文件做测试

技术分享

 

4)总结

啃代码,重点:如何获取数据帧,如何发送数据帧,如何查找数据帧帧头?

 

end

 

EasyPusher应用