zoukankan      html  css  js  c++  java
  • 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 	Len:%d 	tm:%u.%u 	%u
    ",_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 	Len:%d 	tm:%u.%u 	%u
    ", _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 ...
    ", ConfigRTSPURL);
            }
            else if (NULL!=_frameInfo && _frameInfo->type==0xF1)
            {
                printf("Lose Packet:%s ...
    ", ConfigRTSPURL);
            }
        }
    
        return 0;
    }
    void PrintUsage()
    {
        printf("Usage:
    ");
        printf("------------------------------------------------------
    ");
        printf("%s [-c <PlayListCapacity> -C <AllowCache> -v <M3U8Version> -t <TargetDuration> -d <HLSRootDir> -n <HLSessionName> -u <RTSPURL> -U <HttpRootUrl>]
    ", ProgName);
        printf("Help Mode:   %s -h 
    ", 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/
    ", ProgName); 
        printf("------------------------------------------------------
    ");
    }
    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!
    ");
            break;
        case EASY_ACTIVATE_TIME_ERR:
            printf("EasyHLS_KEY is EASY_ACTIVATE_TIME_ERR!
    ");
            break;
        case EASY_ACTIVATE_PROCESS_NAME_LEN_ERR:
            printf("EasyHLS_KEY is EASY_ACTIVATE_PROCESS_NAME_LEN_ERR!
    ");
            break;
        case EASY_ACTIVATE_PROCESS_NAME_ERR:
            printf("EasyHLS_KEY is EASY_ACTIVATE_PROCESS_NAME_ERR!
    ");
            break;
        case EASY_ACTIVATE_VALIDITY_PERIOD_ERR:
            printf("EasyHLS_KEY is EASY_ACTIVATE_VALIDITY_PERIOD_ERR!
    ");
            break;
        case EASY_ACTIVATE_SUCCESS:
            printf("EasyHLS_KEY is EASY_ACTIVATE_SUCCESS!
    ");
            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
    ", ConfigHLSRootDir, ConfigHLSessionName, ConfigHLSessionName);
    
        printf("Press Enter exit...
    ");
        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

  • 相关阅读:
    一个爬虫的练习(妹子图)
    安装模块出现的编译问题(解决)
    基于套接字通信的简单练习(FTP)
    Python3 之选课系统
    数据爬取后台(PHP+Python)联合作战
    让pip 使用国内镜像源
    为啥学蛇和python10年后的变化
    模拟登陆百度以及Selenium 的基本用法
    冒泡排序及其效率分析(无聊搞来玩玩)
    LLVM编译器
  • 原文地址:https://www.cnblogs.com/babosa/p/7348806.html
Copyright © 2011-2022 走看看