EasyHLS實現將IPCamera攝像機的RTSP轉HLS直播輸出


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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM