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

时间: 2024-10-25 12:49:09

EasyPusher应用的相关文章

EasyDarwin组件:EasyPusher

EasyPusher目前支持如下三种推送方式: - **EasyPusher_File**:推送本地文件到EasyDarwin流媒体服务器: - **EasyPusher_RTSP**:通过EasyRTSPClient库,将RTSP/RTP数据获取到本地,再推送到EasyDarwin: - **EasyPusher_SDK**:通过调用私有SDK回调的音视频数据,进行RTSP/RTP直播推送,

EasyPusher推流服务接口的.NET导出

本文是在使用由 EasyDarwin 团队开发的EasyPusher时导出的C++接口的.NET实现 public class EasyPushSDK { public EasyPushSDK() { } [StructLayoutAttribute(LayoutKind.Sequential)] public struct EASY_AV_Frame { public uint u32AVFrameFlag; /* 帧标志 视频 or 音频 */ public uint u32AVFrameL

easyDarwin--开源流媒体实现

EasyDarwin 是由国内开源流媒体团队开发和维护的一款开源流媒体平台框架,从2012年12月创建并发展至今,从原有的单服务的流媒体服务器形式,扩展成现在的云平台架构的开源项目,更好地帮助广大流媒体开发者和创业型企业快速构建流媒体服务平台,更快.更简单地实现最新的移动互联网(安卓.IOS.微信)流媒体直播与点播的需求,尤其是安防行业与互联网行业的衔接: 云平台结构 目前EasyDarwin流媒体平台整套解决方案包括有:EasyCMS(中心管理服务),EasyDarwin(流媒体服务),Eas

EasyDarwin开源流媒体服务器支持basic基本认证和digest摘要自定义认证

本文转自EasyDarwin开源团队成员的博客:http://blog.csdn.net/ss00_2012/article/details/52330838 在前面<EasyDarwin拉流支持基本认证和摘要认证>一文中讲述了如何通过修改qtaccess.qtusers来让EasyDarwin对我们创建的用户支持基本认证和摘要认证,之后在与群主的沟通中感觉这种方式的体验性太差,用户的需求是多方面的,可能有的想在配置文件中配置.有的想从数据库中读取.有的想在程序中写死--,我们需要提供一种便于

EasyDarwin

 1.EasyDarwin多媒体点播实现 新版本EasyDarwin都加入了中心管理服务EasyCMS, 点播系统不是必须的. MP4点播,需要将mp4文件hint之后才行,MP4Box这个工具用得较多 EasyCMS and EasyDarwin vod 3 EasyCMS and EasyDarwin vod 4  2.EasyDarwin组件:EasyPusher的rtsp码流推送  EasyPusher目前支持如下三种推送方式: - **EasyPusher_File**:推送本地文件到