int QRtmp::download()
{
    qint32 now, lastUpdate;
    int bufferSize = 64 * 1024;
    char *buffer = (char *) malloc(bufferSize);
    int nRead = 0;
    off_t size = 0;

    m_rtmp->m_read.timestamp = dSeek;
    m_percent = 0.0;

    if(m_rtmp->m_read.timestamp)
        RTMP_Log(RTMP_LOGDEBUG, "Continuing at TS: %d ms\n", m_rtmp->m_read.timestamp);

    if(m_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(m_duration > 0)
        {
            if((double) m_rtmp->m_read.timestamp >= (double) m_duration * 999.0)
            {
                RTMP_LogPrintf("Already Completed at: %.3f sec Duration=%.3f sec\n",
                               (double) m_rtmp->m_read.timestamp / 1000.0,
                               (double) m_duration / 1000.0);
                return RD_SUCCESS;
            }
            else
            {
                m_percent = ((double) m_rtmp->m_read.timestamp) / (m_duration * 1000.0) * 100.0;
                m_percent = ((double) (int) (m_percent * 10.0)) / 10.0;
                RTMP_LogPrintf("%s download at: %.3f kB / %.3f sec (%.1f%%)\n",
                               m_bResume ? "Resuming" : "Starting",
                               (double) size / 1024.0, (double) m_rtmp->m_read.timestamp / 1000.0,
                               m_percent);
            }
        }
        else
        {
            RTMP_LogPrintf("%s download at: %.3f kB\n",
                           m_bResume ? "Resuming" : "Starting",
                           (double) size / 1024.0);
        }
    }

    if(dStopOffset > 0)
        RTMP_LogPrintf("For duration: %.3f sec\n", (double) (dStopOffset - dSeek) / 1000.0);

    m_rtmp->m_read.nResumeTS = dSeek;

    now = RTMP_GetTime();
    lastUpdate = now - 1000;
    do
    {
        nRead = RTMP_Read(m_rtmp, buffer, bufferSize);
        //RTMP_LogPrintf("nRead: %d\n", nRead);
        if(nRead > 0)
        {
            if(m_destFile.isOpen())
            {
                if(m_destFile.write(buffer, nRead) != nRead)
                {
                    setError(QString("Can't write to %1 - %2").arg(m_destFile.fileName()).arg(m_destFile.errorString()));
                    m_stop = true;
                }
            }
            else
                emit readData(QByteArray(buffer, nRead));
            m_destFile.flush();
            size += nRead;
            setStreamIsRunning(true);

            //RTMP_LogPrintf("write %dbytes (%.1f kB)\n", nRead, nRead/1024.0);
            if(m_duration <= 0)	// if duration unknown try to get it from the stream (onMetaData)
                m_duration = RTMP_GetDuration(m_rtmp);

            if(m_duration > 0)
            {
                // make sure we claim to have enough buffer time!
                if(!m_bOverrideBufferTime && m_bufferTime < (m_duration * 1000.0))
                {
                    m_bufferTime = (quint32) (m_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", m_bufferTime);
                    RTMP_SetBufferMS(m_rtmp, m_bufferTime);
                    RTMP_UpdateBufferMS(m_rtmp);
                }
                m_percent = ((double) m_rtmp->m_read.timestamp) / (m_duration * 1000.0) * 100.0;
                m_percent = ((double) (int) (m_percent * 10.0)) / 10.0;
                now = RTMP_GetTime();
                if(abs(now - lastUpdate) > 200)
                {
                    RTMP_LogStatus("\r%.3f kB / %.2f sec (%.1f%%)",
                                   (double) size / 1024.0,
                                   (double) (m_rtmp->m_read.timestamp) / 1000.0, m_percent);
                    lastUpdate = now;
                }
            }
            else
            {
                now = RTMP_GetTime();
                if(abs(now - lastUpdate) > 200)
                {
                    RTMP_LogStatus("\r%.3f kB / %.2f sec", (double) size / 1024.0,
                                   (double) (m_rtmp->m_read.timestamp) / 1000.0);
                    lastUpdate = now;
                }
            }
        }
    }while (!m_stop && nRead > -1 && RTMP_IsConnected(m_rtmp) && !RTMP_IsTimedout(m_rtmp));
    free(buffer);
    if (nRead < 0)
        nRead = m_rtmp->m_read.status;

    /* Final status update */
    if(m_duration > 0)
    {
        m_percent = ((double) m_rtmp->m_read.timestamp) / (m_duration * 1000.0) * 100.0;
        m_percent = ((double) (int) (m_percent * 10.0)) / 10.0;
        RTMP_LogStatus("\r%.3f kB / %.2f sec (%.1f%%)",
                       (double) size / 1024.0,
                       (double) (m_rtmp->m_read.timestamp) / 1000.0, m_percent);
    }
    else
    {
        RTMP_LogStatus("\r%.3f kB / %.2f sec", (double) size / 1024.0,
                       (double) (m_rtmp->m_read.timestamp) / 1000.0);
    }

    RTMP_Log(RTMP_LOGDEBUG, "RTMP_Read returned: %d", nRead);

    if(m_bResume && nRead == -2)
    {
        RTMP_LogPrintf("Couldn't resume FLV file, try --skip %d\n\n",
                       m_nSkipKeyFrames + 1);
        return RD_FAILED;
    }

    if(nRead == -3)
        return RD_SUCCESS;

    if((m_duration > 0 && m_percent < 99.9) || m_stop || nRead < 0
            || RTMP_IsTimedout(m_rtmp))
    {
        return RD_INCOMPLETE;
    }

    return RD_SUCCESS;
}
Esempio n. 2
0
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 = (char *) malloc(bufferSize);
	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)
		{
			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;
}