EasyHLS实现将IPCamera摄像机的RTSP流转成HLS(ts+m3u8)直播输出

本文转自:http://www.cnblogs.com/babosa/p/6033039.html

EasyHLS

EasyHLS是EasyDarwin开源流媒体团队开发的一款HLS打包库,接口非常简单,只需要传入打包的文件名、切片存放的目录、单个切片时长以及切片数等参数,EasyHLS库就能轻松将H264+AAC的流媒体切片成m3u8+ts,提供给WEB服务器进行HLS流媒体发布;

调用流程

EasyHLS RTSP

/* 打包H264视频 */
EasyHLS_API int Easy_APICALL EasyHLS_VideoMux(Easy_HLS_Handle handle, unsigned int uiFrameType, unsigned char *data, int dataLength, unsigned long long pcr, unsigned long long pts, unsigned long long dts);

其中pcr、dts、pts等参数都是unsigned long long型,通常情况下为时间戳(ms毫秒)\*90以后的结果,所以我们通常需要定义:
unsigned long long pcr,dts,pts = timestamp\*90; 千万不要定义unsigned int型接收数据输入!具体过程参考上面的几个示例;

EasyHLS_RTSP

EasyHLS_RTSP程序可以通过RTSPClient将RTSP摄像机IPCamera的流媒体音视频数据流获取到本地,再进行ts的音视频封装打包,并不断更新m3u8列表,以提供HLS直播功能:

Easy_HLS_Handle     fHLSHandle  = 0;
Easy_RTSP_Handle    fRTSPHandle = 0;

/* RTSPClient获取数据后回调给上层 */
int Easy_APICALL __RTSPClientCallBack( int _chid, void *_chPtr, int _frameType, char *_pBuf, RTSP_FRAME_INFO *_frameInfo)
{
    if(NULL == fHLSHandle) return -1;

    if (_frameType == EASY_SDK_VIDEO_FRAME_FLAG)
    {
        unsigned long long llPTS = (_frameInfo->timestamp_sec%1000000)*1000 + _frameInfo->timestamp_usec/1000;  

        printf("Get %s Video \tLen:%d \ttm:%u.%u \t%u\n",_frameInfo->type==EASY_SDK_VIDEO_FRAME_I?"I":"P", _frameInfo->length, _frameInfo->timestamp_sec, _frameInfo->timestamp_usec, llPTS);

        unsigned int uiFrameType = 0;
        if (_frameInfo->type == EASY_SDK_VIDEO_FRAME_I)
        {
            uiFrameType = TS_TYPE_PES_VIDEO_I_FRAME;
        }
        else if (_frameInfo->type == EASY_SDK_VIDEO_FRAME_P)
        {
            uiFrameType = TS_TYPE_PES_VIDEO_P_FRAME;
        }

        EasyHLS_VideoMux(fHLSHandle, uiFrameType, (unsigned char*)_pBuf, _frameInfo->length, llPTS*90, llPTS*90, llPTS*90);
    }
    else if (_frameType == EASY_SDK_AUDIO_FRAME_FLAG)
    {

        unsigned long long llPTS = (_frameInfo->timestamp_sec%1000000)*1000 + _frameInfo->timestamp_usec/1000;  

        printf("Get Audio \tLen:%d \ttm:%u.%u \t%u\n", _frameInfo->length, _frameInfo->timestamp_sec, _frameInfo->timestamp_usec, llPTS);

        if (_frameInfo->codec == EASY_SDK_AUDIO_CODEC_AAC)
        {
            EasyHLS_AudioMux(fHLSHandle, (unsigned char*)_pBuf, _frameInfo->length, llPTS*90, llPTS*90);
        }
    }
    else if (_frameType == EASY_SDK_EVENT_FRAME_FLAG)
    {
        if (NULL == _pBuf && NULL == _frameInfo)
        {
            printf("Connecting:%s ...\n", ConfigRTSPURL);
        }
        else if (NULL!=_frameInfo && _frameInfo->type==0xF1)
        {
            printf("Lose Packet:%s ...\n", ConfigRTSPURL);
        }
    }

    return 0;
}
void PrintUsage()
{
    printf("Usage:\n");
    printf("------------------------------------------------------\n");
    printf("%s [-c <PlayListCapacity> -C <AllowCache> -v <M3U8Version> -t <TargetDuration> -d <HLSRootDir> -n <HLSessionName> -u <RTSPURL> -U <HttpRootUrl>]\n", ProgName);
    printf("Help Mode:   %s -h \n", ProgName );
    printf("For example: %s -c 4 -C 0 -v 3 -t 4 -d ./ -n easyhls_rtsp -u rtsp://admin:admin@anfengde.f3322.org/22 -U http://www.easydarwin.org/easyhls/\n", ProgName); 
    printf("------------------------------------------------------\n");
}
int main(int argc, char * argv[])
{
#ifdef _WIN32
    extern char* optarg;
#endif
    int ch;
    ProgName = argv[0];
    PrintUsage();
    while ((ch = getopt(argc,argv, "hc:C:v:t:d:n:u:U:")) != EOF) 
    {
        switch(ch)
        {
        case 'h':
            PrintUsage();
            return 0;
            break;
        case 'c':
            ConfigPlayListCapacity =atoi(optarg);
            break;
        case 'C':
            ConfigAllowCache =atoi(optarg);
            break;
        case 'v':
            ConfigM3U8Version =atoi(optarg);
            break;
        case 't':
            ConfigTargetDuration =atoi(optarg);
            break;
        case 'd':
            ConfigHLSRootDir =optarg;
            break;
        case 'n':
            ConfigHLSessionName =optarg;
            break;
        case 'u':
            ConfigRTSPURL =optarg;
            break;
        case 'U':
            ConfigHttpRootUrl =optarg;
            break;
        case '?':
            return 0;
            break;
        default:
            break;
        }
    }

    int isEasyHLSActivated = EasyHLS_Activate(KEY);
    switch(isEasyHLSActivated)
    {
    case EASY_ACTIVATE_INVALID_KEY:
        printf("EasyHLS_KEY is EASY_ACTIVATE_INVALID_KEY!\n");
        break;
    case EASY_ACTIVATE_TIME_ERR:
        printf("EasyHLS_KEY is EASY_ACTIVATE_TIME_ERR!\n");
        break;
    case EASY_ACTIVATE_PROCESS_NAME_LEN_ERR:
        printf("EasyHLS_KEY is EASY_ACTIVATE_PROCESS_NAME_LEN_ERR!\n");
        break;
    case EASY_ACTIVATE_PROCESS_NAME_ERR:
        printf("EasyHLS_KEY is EASY_ACTIVATE_PROCESS_NAME_ERR!\n");
        break;
    case EASY_ACTIVATE_VALIDITY_PERIOD_ERR:
        printf("EasyHLS_KEY is EASY_ACTIVATE_VALIDITY_PERIOD_ERR!\n");
        break;
    case EASY_ACTIVATE_SUCCESS:
        printf("EasyHLS_KEY is EASY_ACTIVATE_SUCCESS!\n");
        break;
    }

    if(EASY_ACTIVATE_SUCCESS != isEasyHLSActivated)
        return -1;

    if( EASY_ACTIVATE_SUCCESS != EasyRTSP_Activate(EasyRTSPClient_KEY))
        return -1;

    //创建EasyRTSPClient
    EasyRTSP_Init(&fRTSPHandle);
    if (NULL == fRTSPHandle) return 0;

    unsigned int mediaType = EASY_SDK_VIDEO_FRAME_FLAG | EASY_SDK_AUDIO_FRAME_FLAG;

    //设置数据回调处理
    EasyRTSP_SetCallback(fRTSPHandle, __RTSPClientCallBack);
    //打开RTSP流
    EasyRTSP_OpenStream(fRTSPHandle, 0, ConfigRTSPURL, EASY_RTP_OVER_TCP, mediaType, 0, 0, NULL, 1000, 0, 0x01, 1);

    //创建EasyHLS Session
    fHLSHandle = EasyHLS_Session_Create(ConfigPlayListCapacity, ConfigAllowCache, ConfigM3U8Version);

    char subDir[64] = { 0 };
    sprintf(subDir,"%s/",ConfigHLSessionName);
    EasyHLS_ResetStreamCache(fHLSHandle, ConfigHLSRootDir, subDir, ConfigHLSessionName, ConfigTargetDuration);

    printf("HLS URL:%s%s/%s.m3u8\n", ConfigHLSRootDir, ConfigHLSessionName, ConfigHLSessionName);

    printf("Press Enter exit...\n");
    getchar();

    EasyHLS_Session_Release(fHLSHandle);
    fHLSHandle = 0;

    EasyRTSP_CloseStream(fRTSPHandle);
    EasyRTSP_Deinit(&fRTSPHandle);
    fRTSPHandle = NULL;

    return 0;
}

详细代码下载:https://github.com/EasyDarwin/EasyHLS

获取更多信息

邮件:support@easydarwin.org

WEB:www.EasyDarwin.org

Author:Jason

QQ交流群:532837588

Copyright © EasyDarwin.org 2012-2016

EasyDarwin

posted @ 2016-11-05 14:07  Babosa  阅读(351)  评论(0编辑  收藏  举报