RTMP协议相干:
【流媒体】RTMP协议概述
【流媒体】RTMP协议的数据格式
【流媒体】RTMP协议的消息类型
【流媒体】RTMPDump—主流程简单分析
【流媒体】RTMPDump—RTMP_Connect函数(握手、网络连接)
【流媒体】RTMPDump—RTMP_ConnectStream(创建流连接)
参考雷博的系列文章(可以从一篇链接到其他文章):
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;
- }
复制代码 免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |