EasyPusher应用

转自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...
");
    else if (_state == EASY_PUSH_STATE_CONNECTED)           printf("Connected
");
    else if (_state == EASY_PUSH_STATE_CONNECT_FAILED)      printf("Connect failed
");
    else if (_state == EASY_PUSH_STATE_CONNECT_ABORT)       printf("Connect abort
");
    else if (_state == EASY_PUSH_STATE_PUSHING)             printf("P->");
    else if (_state == EASY_PUSH_STATE_DISCONNECTED)        printf("Disconnect.
");

    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 ***
");

    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...
");
    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 
", 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 
", 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...
");
    else if (_state == EASY_PUSH_STATE_CONNECTED)           printf("Connected
");
    else if (_state == EASY_PUSH_STATE_CONNECT_FAILED)      printf("Connect failed
");
    else if (_state == EASY_PUSH_STATE_CONNECT_ABORT)       printf("Connect abort
");
    //else if (_state == EASY_PUSH_STATE_PUSHING)             printf("P->");
    else if (_state == EASY_PUSH_STATE_DISCONNECTED)        printf("Disconnect.
");

    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 ***
", 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

原文地址:https://www.cnblogs.com/dong1/p/6014572.html