【流媒体】RTMPDump—Download(接收流媒体信息)
创始人
2024-10-17 13:41:27
0

目录

RTMP协议相关:
【流媒体】RTMP协议概述
【流媒体】RTMP协议的数据格式
【流媒体】RTMP协议的消息类型
【流媒体】RTMPDump—主流程简单分析
【流媒体】RTMPDump—RTMP_Connect函数(握手、网络连接)
【流媒体】RTMPDump—RTMP_ConnectStream(创建流连接)
【流媒体】RTMPDump—Download(接收流媒体信息)
【流媒体】RTMPDump—AMF编码
【流媒体】基于libRTMP的H264推流器

参考雷博的系列文章(可以从一篇链接到其他文章):
RTMPdump 源代码分析 1: main()函数

在进行流连接之后,还可以进行传输过来数据的下载,执行这一功能的函数是Download(),其中使用RTMP_Read()读取数据,随后使用fwrite写入文件。写入文件通常是FLV格式,如果没有指定这个file,则会默认写到stdout

int Download(RTMP * rtmp,		// connected RTMP object 	FILE * file, uint32_t dSeek, uint32_t dStopOffset, double duration, int bResume, char* metaHeader, uint32_t nMetaHeaderSize, char* initialFrame, int initialFrameType, uint32_t nInitialFrameSize, int nSkipKeyFrames, int bStdoutMode, int bLiveStream, int bRealtimeStream, int bHashes, int bOverrideBufferTime, uint32_t bufferTime, double* percent)	// percentage downloaded [out] { 	int32_t now, lastUpdate; 	int bufferSize = 64 * 1024; 	char* buffer; 	int nRead = 0; 	off_t size = ftello(file); 	unsigned long lastPercent = 0;  	rtmp->m_read.timestamp = dSeek;  	*percent = 0.0;  	if (rtmp->m_read.timestamp) 	{ 		RTMP_Log(RTMP_LOGDEBUG, "Continuing at TS: %d ms\n", rtmp->m_read.timestamp); 	}  	if (bLiveStream) 	{ 		RTMP_LogPrintf("Starting Live Stream\n"); 	} 	else 	{ 		// print initial status 		// Workaround to exit with 0 if the file is fully (> 99.9%) downloaded 		if (duration > 0) 		{ 			if ((double)rtmp->m_read.timestamp >= (double)duration * 999.0) 			{ 				RTMP_LogPrintf("Already Completed at: %.3f sec Duration=%.3f sec\n", 					(double)rtmp->m_read.timestamp / 1000.0, 					(double)duration / 1000.0); 				return RD_SUCCESS; 			} 			else 			{ 				*percent = ((double)rtmp->m_read.timestamp) / (duration * 1000.0) * 100.0; 				*percent = ((double)(int)(*percent * 10.0)) / 10.0; 				RTMP_LogPrintf("%s download at: %.3f kB / %.3f sec (%.1f%%)\n", 					bResume ? "Resuming" : "Starting", 					(double)size / 1024.0, (double)rtmp->m_read.timestamp / 1000.0, 					*percent); 			} 		} 		else 		{ 			RTMP_LogPrintf("%s download at: %.3f kB\n", 				bResume ? "Resuming" : "Starting", 				(double)size / 1024.0); 		} 		if (bRealtimeStream) 			RTMP_LogPrintf("  in approximately realtime (disabled BUFX speedup hack)\n"); 	}  	if (dStopOffset > 0) 		RTMP_LogPrintf("For duration: %.3f sec\n", (double)(dStopOffset - dSeek) / 1000.0);  	if (bResume && nInitialFrameSize > 0) 		rtmp->m_read.flags |= RTMP_READ_RESUME; 	rtmp->m_read.initialFrameType = initialFrameType; 	rtmp->m_read.nResumeTS = dSeek; 	rtmp->m_read.metaHeader = metaHeader; 	rtmp->m_read.initialFrame = initialFrame; 	rtmp->m_read.nMetaHeaderSize = nMetaHeaderSize; 	rtmp->m_read.nInitialFrameSize = nInitialFrameSize;  	buffer = (char*)malloc(bufferSize);  	now = RTMP_GetTime(); 	lastUpdate = now - 1000; 	do 	{ 		// 读取信息 		nRead = RTMP_Read(rtmp, buffer, bufferSize); 		//RTMP_LogPrintf("nRead: %d\n", nRead); 		if (nRead > 0) 		{ 			// 将数据写入到file当中,FLV格式 			// 如果这个file没有指定,默认是stdout 			if (fwrite(buffer, sizeof(unsigned char), nRead, file) != 				(size_t)nRead) 			{ 				RTMP_Log(RTMP_LOGERROR, "%s: Failed writing, exiting!", __FUNCTION__); 				free(buffer); 				return RD_FAILED; 			} 			size += nRead;  			//RTMP_LogPrintf("write %dbytes (%.1f kB)\n", nRead, nRead/1024.0); 			if (duration <= 0)	// if duration unknown try to get it from the stream (onMetaData) 				duration = RTMP_GetDuration(rtmp);  			if (duration > 0) 			{ 				// make sure we claim to have enough buffer time! 				if (!bOverrideBufferTime && bufferTime < (duration * 1000.0)) 				{ 					bufferTime = (uint32_t)(duration * 1000.0) + 5000;	// extra 5sec to make sure we've got enough  					RTMP_Log(RTMP_LOGDEBUG, 						"Detected that buffer time is less than duration, resetting to: %dms", 						bufferTime); 					RTMP_SetBufferMS(rtmp, bufferTime); 					RTMP_UpdateBufferMS(rtmp); 				} 				*percent = ((double)rtmp->m_read.timestamp) / (duration * 1000.0) * 100.0; 				*percent = ((double)(int)(*percent * 10.0)) / 10.0; 				if (bHashes) 				{ 					if (lastPercent + 1 <= *percent) 					{ 						RTMP_LogStatus("#"); 						lastPercent = (unsigned long)* percent; 					} 				} 				else 				{ 					now = RTMP_GetTime(); 					if (abs(now - lastUpdate) > 200) 					{ 						RTMP_LogStatus("\r%.3f kB / %.2f sec (%.1f%%)", 							(double)size / 1024.0, 							(double)(rtmp->m_read.timestamp) / 1000.0, *percent); 						lastUpdate = now; 					} 				} 			} 			else 			{ 				now = RTMP_GetTime(); 				if (abs(now - lastUpdate) > 200) 				{ 					if (bHashes) 						RTMP_LogStatus("#"); 					else 						RTMP_LogStatus("\r%.3f kB / %.2f sec", (double)size / 1024.0, 						(double)(rtmp->m_read.timestamp) / 1000.0); 					lastUpdate = now; 				} 			} 		} 		else 		{ #ifdef _DEBUG 			RTMP_Log(RTMP_LOGDEBUG, "zero read!"); #endif 			if (rtmp->m_read.status == RTMP_READ_EOF) 				break; 		}  	} while (!RTMP_ctrlC && nRead > -1 && RTMP_IsConnected(rtmp) && !RTMP_IsTimedout(rtmp)); 	free(buffer); 	if (nRead < 0) 		nRead = rtmp->m_read.status;  	/* Final status update */ 	if (!bHashes) 	{ 		if (duration > 0) 		{ 			*percent = ((double)rtmp->m_read.timestamp) / (duration * 1000.0) * 100.0; 			*percent = ((double)(int)(*percent * 10.0)) / 10.0; 			RTMP_LogStatus("\r%.3f kB / %.2f sec (%.1f%%)", 				(double)size / 1024.0, 				(double)(rtmp->m_read.timestamp) / 1000.0, *percent); 		} 		else 		{ 			RTMP_LogStatus("\r%.3f kB / %.2f sec", (double)size / 1024.0, 				(double)(rtmp->m_read.timestamp) / 1000.0); 		} 	}  	RTMP_Log(RTMP_LOGDEBUG, "RTMP_Read returned: %d", nRead);  	if (bResume && nRead == -2) 	{ 		RTMP_LogPrintf("Couldn't resume FLV file, try --skip %d\n\n", 			nSkipKeyFrames + 1); 		return RD_FAILED; 	}  	if (nRead == -3) 		return RD_SUCCESS;  	if ((duration > 0 && *percent < 99.9) || RTMP_ctrlC || nRead < 0 		|| RTMP_IsTimedout(rtmp)) 	{ 		return RD_INCOMPLETE; 	}  	return RD_SUCCESS; } 

相关内容

热门资讯

分享经验”九神联盟房卡到哪里买... 分享经验”九神联盟房卡到哪里买“详细房卡使用教程游戏中心打开微信,添加客服【113857776】,进...
秒懂教程“微信斗牛房卡怎么获得... 新蜜瓜牛牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
一秒了解”天道联盟房卡详细充值... 一秒了解”天道联盟房卡详细充值“金花牛牛房卡充值 微信牛牛房卡客服微信号微信游戏中心打开微信,添加客...
ia实测“金花客服代理房卡获取... 天酷大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房卡...
玩家攻略”中游联盟如何购买房卡... 玩家攻略”中游联盟如何购买房卡“新老夫子房卡充值 微信牛牛房卡客服微信号微信游戏中心打开微信,添加客...
安卓系统自带闹钟文件,揭秘系统... 你有没有发现,手机里的安卓系统自带闹钟功能,简直是个小助手,每天早上准时叫醒你,让你开始新的一天。不...
一分钟了解“购买斗牛金花房卡联... 斗牛是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来享受...
安卓系统大表盘在哪,安卓系统大... 你有没有发现,安卓手机上的大表盘功能超级实用,尤其是对于喜欢个性化设置的小伙伴来说,简直是个宝藏!但...
一分钟实测分享”详心联盟房卡领... 来教大家如何使用房卡领取码房卡充值 添加房卡批售商:微【113857775】复制到微信搜索、直接添加...
秒懂教程“有没有炸金花房卡买,... 新七喜是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:15984933许多玩家在游戏中会购买房卡来享...
秒懂百科”趣游联盟哪里有详细房... 哪里有详细房卡介绍是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:113857776许多玩家在游戏中...
房卡必备教程“微信炸金花房间怎... 微信炸金花是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:160470940许多玩家在游戏中会购买房...
玩家须知”天启联盟获取房卡教程... 玩家须知”天启联盟获取房卡教程“详细房卡使用教程游戏中心打开微信,添加客服【113857776】,进...
一分钟推荐“开牛牛群怎么买房卡... 天王大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来...
秒懂普及”全游联盟获取房卡教程... 来教大家如何使用获取房卡教程房卡充值 添加房卡批售商:微【113857775】复制到微信搜索、直接添...
秒懂教程“炸金花房卡链接建立步... 九酷大厅是一款非常受欢迎的棋牌游戏,咨询房/卡添加微信:86909166许多玩家在游戏中会购买房卡来...
秒懂百科”九哥联盟如何购买房卡... 秒懂百科”九哥联盟如何购买房卡“卡农大厅房卡充值游戏中心打开微信,添加客服【113857776】,进...
秒懂百科”九九联盟房卡到哪里买... 来教大家如何使用房卡到哪里买房卡充值 添加房卡批售商:微【113857775】复制到微信搜索、直接添...
安卓系统微信开小号,轻松开启小... 你是不是也有过这样的烦恼?想要在微信上保持多个身份,但又不想让朋友们发现你竟然有“双面人生”?别急,...
实测教程”天神联盟房卡到哪里买... 来教大家如何使用房卡到哪里买房卡充值 添加房卡批售商:微【113857775】复制到微信搜索、直接添...