诗林 发表于 2024-8-19 18:37:57

【流媒体】RTMPDump—Download(接收流媒体信息)

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
{
        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企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 【流媒体】RTMPDump—Download(接收流媒体信息)