首页 > 学院 > 开发设计 > 正文

RTMP学习(六)rtmpdump源码阅读(1)总体流程

2019-11-06 08:52:47
字体:
来源:转载
供稿:网友

rtmpdump总体流程

为了更加深入理解rtmp协议,下面分析一个开源的rtmp工具:rtmpdump。下载地址:https://github.com/aajanki/rtmpdump

rtmpdump实际就是一个下载工具,它会把URL中指定的资源下载下来

1、初始化

2、解析URL

3、打开文件(把URL资源保存到本地的文件)

4、建立连接

5、建立流

6、开始下载

7、下载完成,关闭连接,清理资源

下面是简化过的main函数,只保留核心的几个函数

intmain(int argc, char **argv){	// *** 只保留核心代码	// rtmp初始化	RTMP_Init(&rtmp);	// 参数解析	while ((opt =		getopt_long(argc, argv,		"hVveqzr:s:t:p:a:b:f:o:u:C:n:c:l:y:Ym:k:d:A:B:T:w:x:W:X:S:#j:J:",		longopts, NULL)) != -1)	{		switch (opt)		{		case 'h':			usage(argv[0]);			return RD_SUCCESS;		case 'r':		{			AVal parsedHost, parsedApp, parsedPlaypath;			unsigned int parsedPort = 0;			int parsedPRotocol = RTMP_PROTOCOL_UNDEFINED;			// URL解析			if (!RTMP_ParseURL				(optarg, &parsedProtocol, &parsedHost, &parsedPort,				&parsedPlaypath, &parsedApp))			{				RTMP_Log(RTMP_LOGWARNING, "Couldn't parse the specified url (%s)!",					optarg);			}			else			{				if (!hostname.av_len)					hostname = parsedHost;				if (port == -1)					port = parsedPort;				if (playpath.av_len == 0 && parsedPlaypath.av_len)				{					playpath = parsedPlaypath;				}				if (protocol == RTMP_PROTOCOL_UNDEFINED)					protocol = parsedProtocol;				if (app.av_len == 0 && parsedApp.av_len)				{					app = parsedApp;				}			}			break;		}				default:			RTMP_LogPrintf("unknown option: %c/n", opt);			usage(argv[0]);			return RD_FAILED;			break;		}	}	// 启动流	RTMP_SetupStream(&rtmp, protocol, &hostname, port, &sockshost, &playpath,		&tcUrl, &swfUrl, &pageUrl, &app, &auth, &swfHash, swfSize,		&FlashVer, &subscribepath, &usherToken, &WeebToken, dSeek, dStopOffset, bLiveStream, timeout);		if (!file)	{		if (bStdoutMode)		{			file = stdout;			SET_BINMODE(file);		}		else		{			file = fopen(flvFile, "w+b");			if (file == 0)			{				RTMP_LogPrintf("Failed to open file! %s/n", flvFile);				return RD_FAILED;			}		}	}	while (!RTMP_ctrlC)	{		RTMP_Log(RTMP_LOGDEBUG, "Setting buffer time to: %dms", bufferTime);		RTMP_SetBufferMS(&rtmp, bufferTime);		if (first)		{			first = 0;			RTMP_LogPrintf("Connecting .../n");			// 建立连接			if (!RTMP_Connect(&rtmp, NULL))			{				nStatus = RD_NO_CONNECT;				break;			}			RTMP_Log(RTMP_LOGINFO, "Connected...");			// User defined seek offset			if (dStartOffset > 0)			{				// Don't need the start offset if resuming an existing file				if (bResume)				{					RTMP_Log(RTMP_LOGWARNING,						"Can't seek a resumed stream, ignoring --start option");					dStartOffset = 0;				}				else				{					dSeek = dStartOffset;				}			}			// Calculate the length of the stream to still play			if (dStopOffset > 0)			{				// Quit if start seek is past required stop offset				if (dStopOffset <= dSeek)				{					RTMP_LogPrintf("Already Completed/n");					nStatus = RD_SUCCESS;					break;				}			}			// 建立流连接			if (!RTMP_ConnectStream(&rtmp, dSeek))			{				nStatus = RD_FAILED;				break;			}		}		else		{			nInitialFrameSize = 0;			if (retries)			{				RTMP_Log(RTMP_LOGERROR, "Failed to resume the stream/n/n");				if (!RTMP_IsTimedout(&rtmp))					nStatus = RD_FAILED;				else					nStatus = RD_INCOMPLETE;				break;			}			RTMP_Log(RTMP_LOGINFO, "Connection timed out, trying to resume./n/n");			/* Did we already try pausing, and it still didn't work? */			if (rtmp.m_pausing == 3)			{				/* Only one try at reconnecting... */				retries = 1;				dSeek = rtmp.m_pauseStamp;				if (dStopOffset > 0)				{					if (dStopOffset <= dSeek)					{						RTMP_LogPrintf("Already Completed/n");						nStatus = RD_SUCCESS;						break;					}				}				if (!RTMP_ReconnectStream(&rtmp, dSeek))				{					RTMP_Log(RTMP_LOGERROR, "Failed to resume the stream/n/n");					if (!RTMP_IsTimedout(&rtmp))						nStatus = RD_FAILED;					else						nStatus = RD_INCOMPLETE;					break;				}			}			else if (!RTMP_ToggleStream(&rtmp))			{				RTMP_Log(RTMP_LOGERROR, "Failed to resume the stream/n/n");				if (!RTMP_IsTimedout(&rtmp))					nStatus = RD_FAILED;				else					nStatus = RD_INCOMPLETE;				break;			}			bResume = TRUE;		}		// 下载		nStatus = Download(&rtmp, file, dSeek, dStopOffset, duration, bResume,			metaHeader, nMetaHeaderSize, initialFrame,			initialFrameType, nInitialFrameSize,			nSkipKeyFrames, bStdoutMode, bLiveStream, bHashes,			bOverrideBufferTime, bufferTime, &percent);		free(initialFrame);		initialFrame = NULL;		/* If we succeeded, we're done.		 */		if (nStatus != RD_INCOMPLETE || !RTMP_IsTimedout(&rtmp) || bLiveStream)			break;	}	if (nStatus == RD_SUCCESS)	{		RTMP_LogPrintf("Download complete/n");	}	else if (nStatus == RD_INCOMPLETE)	{		RTMP_LogPrintf			("Download may be incomplete (downloaded about %.2f%%), try resuming/n",			percent);	}clean:	// 关闭,清理	RTMP_Log(RTMP_LOGDEBUG, "Closing connection./n");	RTMP_Close(&rtmp);	if (file != 0)		fclose(file);	CleanupSockets();#ifdef _DEBUG	if (netstackdump != 0)		fclose(netstackdump);	if (netstackdump_read != 0)		fclose(netstackdump_read);#endif	return nStatus;}


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表