r26 - bytes.h rtmp.cpp rtmp.h rtmpdump.cpp streams.cpp
Author: hyc Date: Fri Nov 6 06:38:22 2009 New Revision: 26 Log: Sync again with flvstreamer 1.8: handle files >2GB, more for start/stop conditions Modified: bytes.h rtmp.cpp rtmp.h rtmpdump.cpp streams.cpp Modified: bytes.h ============================================================================== --- bytes.h Fri Nov 6 06:36:42 2009 (r25) +++ bytes.h Fri Nov 6 06:38:22 2009 (r26) @@ -65,8 +65,8 @@ typedef unsigned long long int uint64_t; #endif // define default endianness -#ifndef __LITTLE_EDNIAN -#define __LITTLE_EDNIAN 1234 +#ifndef __LITTLE_ENDIAN +#define __LITTLE_ENDIAN 1234 #endif #ifndef __BIG_ENDIAN Modified: rtmp.cpp ============================================================================== --- rtmp.cpp Fri Nov 6 06:36:42 2009 (r25) +++ rtmp.cpp Fri Nov 6 06:38:22 2009 (r26) @@ -141,6 +141,7 @@ void CRTMP::SetupStream( const char *flashVer, const char *subscribepath, double dTime, + uint32_t dLength, bool bLiveStream, long int timeout ) @@ -167,7 +168,9 @@ void CRTMP::SetupStream( if(flashVer) Log(LOGDEBUG, "flashVer : %s", flashVer); if(dTime > 0) - Log(LOGDEBUG, "SeekTime : %lf", dTime); + Log(LOGDEBUG, "SeekTime : %.3f sec", (double)dTime/1000.0); + if(dLength > 0) + Log(LOGDEBUG, "playLength : %.3f sec", (double)dLength/1000.0); Log(LOGDEBUG, "live : %s", bLiveStream ? "yes":"no"); Log(LOGDEBUG, "timeout : %d sec", timeout); @@ -208,6 +211,7 @@ void CRTMP::SetupStream( Link.flashVer = flashVer; Link.subscribepath = subscribepath; Link.seekTime = dTime; + Link.length = dLength; Link.bLiveStream = bLiveStream; Link.timeout = timeout; @@ -345,10 +349,13 @@ bool CRTMP::SocksNegotiate() { } } -bool CRTMP::ConnectStream(double seekTime) { +bool CRTMP::ConnectStream(double seekTime, uint32_t dLength) { if (seekTime >= -2.0) Link.seekTime = seekTime; + if (dLength >= 0) + Link.length = dLength; + RTMPPacket packet; while (!m_bPlaying && IsConnected() && ReadPacket(packet)) { if (!packet.IsReady()) @@ -371,14 +378,14 @@ bool CRTMP::ConnectStream(double seekTim return m_bPlaying; } -bool CRTMP::ReconnectStream(int bufferTime, double seekTime) { +bool CRTMP::ReconnectStream(int bufferTime, double seekTime, uint32_t dLength) { DeleteStream(); SendCreateStream(2.0); SetBufferMS(bufferTime); - return ConnectStream(seekTime); + return ConnectStream(seekTime, dLength); } void CRTMP::DeleteStream() { @@ -934,7 +941,7 @@ bool CRTMP::SendPlay() *enc = 0x05; // NULL enc++; - Log(LOGDEBUG, "%s, sending play: %s", __FUNCTION__, Link.playpath); + Log(LOGDEBUG, "%s, seekTime=%.2f, dLength=%d, sending play: %s", __FUNCTION__, Link.seekTime, Link.length, Link.playpath); enc += EncodeString(enc, Link.playpath); // Optional parameters start and len. @@ -943,14 +950,22 @@ bool CRTMP::SendPlay() // -2: looks for a live stream, then a recorded stream, if not found any open a live stream // -1: plays a live stream // >=0: plays a recorded streams from 'start' milliseconds + if(Link.bLiveStream) + enc += EncodeNumber(enc, -1000.0); + else { if(Link.seekTime > 0.0) enc += EncodeNumber(enc, Link.seekTime); // resume from here + else + enc += EncodeNumber(enc, 0.0);//-2000.0); // recorded as default, -2000.0 is not reliable since that freezes the player if the stream is not found + } // len: -1, 0, positive number // -1: plays live or recorded stream to the end (default) // 0: plays a frame 'start' ms away from the beginning // >0: plays a live or recoded stream for 'len' milliseconds //enc += EncodeNumber(enc, -1.0); // len + if(Link.length) + enc += EncodeNumber(enc, Link.length); // len packet.m_nBodySize = enc - packet.m_body; @@ -1009,6 +1024,7 @@ bool CRTMP::SendPing(short nType, unsign return SendRTMP(packet); } +// Returns 0 for OK/Failed/error, 1 for 'Stop or Complete' int CRTMP::HandleInvoke(const char *body, unsigned int nBodySize) { if (body[0] != 0x02) // make sure it is a string method name we start with Modified: rtmp.h ============================================================================== --- rtmp.h Fri Nov 6 06:36:42 2009 (r25) +++ rtmp.h Fri Nov 6 06:38:22 2009 (r26) @@ -88,6 +88,7 @@ typedef struct const char *subscribepath; double seekTime; + uint32_t length; bool bLiveStream; long int timeout; // number of seconds before connection times out @@ -131,6 +132,7 @@ class CRTMP const char *flashVer, const char *subscribepath, double dTime, + uint32_t dLength, bool bLiveStream, long int timeout=300); @@ -140,8 +142,8 @@ class CRTMP bool IsTimedout(); double GetDuration(); - bool ConnectStream(double seekTime=-10.0); - bool ReconnectStream(int bufferTime, double seekTime=-10.0); + bool ConnectStream(double seekTime=-10.0, uint32_t dLength=0); + bool ReconnectStream(int bufferTime, double seekTime=-10.0, uint32_t dLength=0); void DeleteStream(); int GetNextMediaPacket(RTMPPacket &packet); Modified: rtmpdump.cpp ============================================================================== --- rtmpdump.cpp Fri Nov 6 06:36:42 2009 (r25) +++ rtmpdump.cpp Fri Nov 6 06:38:22 2009 (r26) @@ -19,6 +19,8 @@ * */ +#define _FILE_OFFSET_BITS 64 + #include <stdlib.h> #include <string.h> #include <math.h> @@ -27,8 +29,12 @@ #include <getopt.h> #ifdef WIN32 +#define fseeko fseeko64 +#define ftello ftello64 #include <winsock.h> +#include <stdio.h> #include <io.h> +#include <fcntl.h> #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) #else #define SET_BINMODE(f) @@ -44,7 +50,7 @@ int debuglevel = 1; using namespace RTMP_LIB; -#define RTMPDUMP_VERSION "v1.7" +#define RTMPDUMP_VERSION "v1.8" #define RD_SUCCESS 0 #define RD_FAILED 1 @@ -90,7 +96,12 @@ bool bCtrlC = false; void sigIntHandler(int sig) { bCtrlC = true; LogPrintf("Caught signal: %d, cleaning up, just a second...\n", sig); - signal(SIGINT, SIG_DFL); + // ignore all these signals now and let the connection close + signal(SIGHUP, SIG_IGN); + signal(SIGINT, SIG_IGN); + signal(SIGPIPE, SIG_IGN); + signal(SIGTERM, SIG_IGN); + signal(SIGQUIT, SIG_IGN); } int WriteHeader( @@ -215,10 +226,10 @@ int WriteStream( ts = CRTMP::ReadInt24(packetBody+pos+4); ts |= (packetBody[pos+7]<<24); - #ifdef _DEBUG +#ifdef _DEBUG Log(LOGDEBUG, "keyframe search: FLV Packet: type %02X, dataSize: %d, timeStamp: %d ms", packetBody[pos], dataSize, ts); - #endif +#endif // ok, is it a keyframe!!!: well doesn't work for audio! if(packetBody[pos /*6928, test 0*/] == initialFrameType /* && (packetBody[11]&0xf0) == 0x10*/) { if(ts == nResumeTS) { @@ -389,15 +400,15 @@ stopKeyframeSearch: } else { prevTagSize = CRTMP::ReadInt32(packetBody+pos+11+dataSize); - #ifdef _DEBUG +#ifdef _DEBUG Log(LOGDEBUG, "FLV Packet: type %02X, dataSize: %lu, tagSize: %lu, timeStamp: %lu ms", (unsigned char)packetBody[pos], dataSize, prevTagSize, nTimeStamp); - #endif +#endif if(prevTagSize != (dataSize+11)) { - #ifdef _DEBUG +#ifdef _DEBUG Log(LOGWARNING, "Tag and data size are not consitent, writing tag size according to dataSize+11: %d", dataSize+11); - #endif +#endif prevTagSize = dataSize+11; CRTMP::EncodeInt32(ptr+pos+11+dataSize, prevTagSize); @@ -431,7 +442,7 @@ stopKeyframeSearch: int OpenResumeFile(const char *flvFile, // file name [in] FILE **file, // opened file [out] - unsigned long *size, // size of the file [out] + off_t *size, // size of the file [out] char **metaHeader, // meta data read from the file [out] uint32_t *nMetaHeaderSize, // length of metaHeader [out] double *duration) // duration of the stream in ms [out] @@ -447,7 +458,7 @@ int OpenResumeFile(const char *flvFile, return RD_SUCCESS; // RD_SUCCESS, because we go to fresh file mode instead of quiting fseek(*file, 0, SEEK_END); - *size = ftell(*file); + *size = ftello(*file); fseek(*file, 0, SEEK_SET); if(*size > 0) { @@ -482,11 +493,11 @@ int OpenResumeFile(const char *flvFile, } // go through the file to find the meta data! - uint32_t pos = dataOffset+4; + off_t pos = dataOffset+4; bool bFoundMetaHeader = false; while(pos < *size-4 && !bFoundMetaHeader) { - fseek(*file, pos, SEEK_SET); + fseeko(*file, pos, SEEK_SET); if(fread(buffer, 1, 4, *file)!=4) break; @@ -498,7 +509,7 @@ int OpenResumeFile(const char *flvFile, return RD_FAILED; } - fseek(*file, pos+11, SEEK_SET); + fseeko(*file, pos+11, SEEK_SET); if(fread(buffer, 1, dataSize, *file) != dataSize) break; @@ -553,23 +564,23 @@ int GetLastKeyframe(FILE *file, char buffer[bufferSize]; uint8_t dataType; bool bAudioOnly; - unsigned long size; + off_t size; fseek(file, 0, SEEK_END); - size = ftell(file); + size = ftello(file); fseek(file, 4, SEEK_SET); fread(&dataType, sizeof(uint8_t), 1, file); bAudioOnly = (dataType & 0x4) && !(dataType & 0x1); - Log(LOGDEBUG, "bAudioOnly: %d, size: %d", bAudioOnly, size); + Log(LOGDEBUG, "bAudioOnly: %d, size: %llu", bAudioOnly, (unsigned long long)size); // ok, we have to get the timestamp of the last keyframe (only keyframes are seekable) / last audio frame (audio only streams) //if(!bAudioOnly) // we have to handle video/video+audio different since we have non-seekable frames //{ // find the last seekable frame - uint32_t tsize = 0; + off_t tsize = 0; uint32_t prevTagSize = 0; // go through the file and find the last video keyframe @@ -580,7 +591,7 @@ skipkeyframe: Log(LOGERROR, "Unexpected start of file, error in tag sizes, couldn't arrive at prevTagSize=0"); return RD_FAILED; } - fseek(file, size-tsize-4, SEEK_SET); + fseeko(file, size-tsize-4, SEEK_SET); xread = fread(buffer, 1, 4, file); if(xread != 4) { Log(LOGERROR, "Couldn't read prevTagSize from file!"); @@ -602,17 +613,17 @@ skipkeyframe: tsize += prevTagSize+4; // read header - fseek(file, size-tsize, SEEK_SET); + fseeko(file, size-tsize, SEEK_SET); if(fread(buffer, 1, 12, file) != 12) { Log(LOGERROR, "Couldn't read header!"); return RD_FAILED; } //* - #ifdef _DEBUG +#ifdef _DEBUG uint32_t ts = RTMP_LIB::CRTMP::ReadInt24(buffer+4); ts |= (buffer[7]<<24); Log(LOGDEBUG, "%02X: TS: %d ms", buffer[0], ts); - #endif //*/ +#endif //*/ // this just continues the loop whenever the number of skipped frames is > 0, // so we look for the next keyframe to continue with @@ -638,7 +649,7 @@ skipkeyframe: *nInitialFrameSize = prevTagSize-11; *initialFrame = (char *)malloc(*nInitialFrameSize); - fseek(file, size-tsize+11, SEEK_SET); + fseeko(file, size-tsize+11, SEEK_SET); if(fread(*initialFrame, 1, *nInitialFrameSize, file) != *nInitialFrameSize) { Log(LOGERROR, "Couldn't read last keyframe, aborting!"); return RD_FAILED; @@ -659,13 +670,13 @@ skipkeyframe: /* // now read the timestamp of the frame before the seekable keyframe: - fseek(file, size-tsize-4, SEEK_SET); + fseeko(file, size-tsize-4, SEEK_SET); if(fread(buffer, 1, 4, file) != 4) { Log(LOGERROR, "Couldn't read prevTagSize from file!"); goto start; } uint32_t prevTagSize = RTMP_LIB::CRTMP::ReadInt32(buffer); - fseek(file, size-tsize-4-prevTagSize+4, SEEK_SET); + fseeko(file, size-tsize-4-prevTagSize+4, SEEK_SET); if(fread(buffer, 1, 4, file) != 4) { Log(LOGERROR, "Couldn't read previous timestamp!"); goto start; @@ -679,7 +690,7 @@ skipkeyframe: if(*dSeek != 0) { // seek to position after keyframe in our file (we will ignore the keyframes resent by the server // since they are sent a couple of times and handling this would be a mess) - fseek(file, size-tsize+prevTagSize+4, SEEK_SET); + fseeko(file, size-tsize+prevTagSize+4, SEEK_SET); // make sure the WriteStream doesn't write headers and ignores all the 0ms TS packets // (including several meta data headers and the keyframe we seeked to) @@ -694,6 +705,7 @@ skipkeyframe: int Download(CRTMP *rtmp, // connected CRTMP object FILE *file, uint32_t dSeek, + uint32_t dLength, uint32_t dStopOffset, double duration, bool bResume, @@ -715,7 +727,7 @@ int Download(CRTMP *rtmp, int bufferSize = 1024*1024; char *buffer = (char *)malloc(bufferSize); int nRead = 0; - unsigned long size = ftell(file); + off_t size = ftello(file); memset(buffer, 0, bufferSize); @@ -726,15 +738,23 @@ int Download(CRTMP *rtmp, } // print initial status - LogPrintf("Starting download at "); - if(duration > 0) { - *percent = ((double)timestamp) / (duration*1000.0)*100.0; - *percent = round(*percent*10.0)/10.0; - LogPrintf("%.3f kB (%.1f%%)\n", (double)size/1024.0, *percent); + // Workaround to exit with 0 if the file is fully (> 99.9%) downloaded + if( duration > 0 ) { + if ((double)timestamp >= (double)duration*999.0 ) { + LogPrintf("Already Completed at: %.3f sec Duration=%.3f sec\n", (double)timestamp/1000.0, (double)timestamp/1000.0); + return RD_SUCCESS; + } else { + *percent = ((double)timestamp) / (duration*1000.0)*100.0; + *percent = round(*percent*10.0)/10.0; + LogPrintf("Starting download at: %.3f kB / %.3f sec (%.1f%%)\n", (double)size/1024.0, (double)timestamp/1000.0, *percent); + } } else { - LogPrintf("%.3f kB\n", (double)size/1024.0); + LogPrintf("Starting download at: %.3f kB\n", (double)size/1024.0); } + if (dLength > 0) + LogPrintf("For duration: %.3f sec\n", (double)dLength/1000.0); + // write FLV header if not resuming if(!bResume) { nRead = WriteHeader(&buffer, bufferSize); @@ -784,24 +804,24 @@ int Download(CRTMP *rtmp, *percent = round(*percent*10.0)/10.0; now = GetTime(); if (abs(now - lastUpdate) > 200) { - LogStatus("\r%.3f kB (%.1f%%)", (double)size/1024.0, *percent); + LogStatus("\r%.3f kB / %.2f sec (%.1f%%)", (double)size/1024.0, (double)(timestamp)/1000.0, *percent); lastUpdate = now; } } else { now = GetTime(); if (abs(now - lastUpdate) > 200) { - LogStatus("\r%.3f kB", (double)size/1024.0); + LogStatus("\r%.3f kB / %.2f sec", (double)size/1024.0, (double)(timestamp)/1000.0); lastUpdate = now; } } } - #ifdef _DEBUG +#ifdef _DEBUG else { Log(LOGDEBUG, "zero read!"); } - #endif +#endif // Force clean close if a specified stop offset is reached if (dStopOffset && timestamp >= dStopOffset) { - LogPrintf("Stop offset has been reached at %.2f seconds\n", (double)dStopOffset/1000.0); + LogPrintf("Stop offset has been reached at %.2f seconds (ts=%d, so=%d)\n", (double)dStopOffset/1000.0, timestamp, dStopOffset); nRead = 0; rtmp->Close(); } @@ -820,7 +840,7 @@ int Download(CRTMP *rtmp, fseek(file, 4, SEEK_SET); fwrite(&dataType, sizeof(unsigned char), 1, file); } - if((duration > 0 && *percent < 99.9) || bCtrlC || nRead < 0 || rtmp->IsTimedout()) { + if((duration > 0 && *percent < 99.9 && dStopOffset <= 0) || bCtrlC || nRead < 0 || rtmp->IsTimedout()) { return RD_INCOMPLETE; } @@ -844,7 +864,7 @@ int main(int argc, char **argv) int nSkipKeyFrames = 0; // skip this number of keyframes when resuming bool bOverrideBufferTime = false; // if the user specifies a buffer time override this is true - bool bStdoutMode = false;// if true print the stream directly to stdout, messages go to stderr + bool bStdoutMode = true;// if true print the stream directly to stdout, messages go to stderr bool bResume = false; // true in resume mode uint32_t dSeek = 0; // seek position in resume mode, 0 otherwise uint32_t bufferTime = 10*60*60*1000; // 10 hours as default @@ -869,6 +889,7 @@ int main(int argc, char **argv) long int timeout = 120; // timeout connection after 120 seconds uint32_t dStartOffset = 0; // seek position in non-live mode uint32_t dStopOffset = 0; + uint32_t dLength = 0; // length to play from stream - calculated from seek position and dStopOffset char *rtmpurl = 0; char *swfUrl = 0; @@ -885,7 +906,11 @@ int main(int argc, char **argv) char DEFAULT_FLASH_VER[] = "LNX 10,0,22,87"; + signal(SIGHUP, sigIntHandler); signal(SIGINT, sigIntHandler); + signal(SIGPIPE, sigIntHandler); + signal(SIGTERM, sigIntHandler); + signal(SIGQUIT, sigIntHandler); /* sleep(30); */ @@ -899,7 +924,7 @@ int main(int argc, char **argv) } LogPrintf("RTMPDump %s\n", RTMPDUMP_VERSION); - LogPrintf("(c) 2009 Andrej Stepanchuk, Howard Chu; license: GPL\n\n"); + LogPrintf("(c) 2009 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL\n"); int opt; struct option longopts[] = { @@ -1073,8 +1098,8 @@ int main(int argc, char **argv) break; case 'o': flvFile = optarg; - if(strcmp(flvFile, "-")==0) - bStdoutMode = true; + if(strcmp(flvFile, "-")) + bStdoutMode = false; break; case 'e': @@ -1088,11 +1113,9 @@ int main(int argc, char **argv) break; case 'A': dStartOffset = int(atof(optarg)*1000.0); - //printf("dStartOffset = %d\n", dStartOffset); break; case 'B': dStopOffset = int(atof(optarg)*1000.0); - //printf("dStartOffset = %d\n", dStartOffset); break; case 'q': debuglevel = LOGCRIT; @@ -1133,8 +1156,8 @@ int main(int argc, char **argv) protocol = RTMP_PROTOCOL_RTMP; } if(flvFile == 0) { - Log(LOGERROR, "You must specify an output flv file (-o filename)"); - return RD_FAILED; + Log(LOGWARNING, "You haven't specified an output file (-o filename), using stdout"); + bStdoutMode = true; } if(bStdoutMode && bResume) { @@ -1187,12 +1210,21 @@ int main(int argc, char **argv) memset(buffer, 0, bufferSize); + // User defined seek offset + if (dStartOffset > 0) { + // Live stream + if (bLiveStream) { + Log(LOGWARNING, "Can't seek in a live stream, ignoring --start option"); + dStartOffset = 0; + } + } + CRTMP *rtmp = new CRTMP(); rtmp->SetupStream(protocol, hostname, port, sockshost, playpath, tcUrl, swfUrl, pageUrl, app, auth, swfHash, swfSize, flashVer, subscribepath, - dSeek, bLiveStream, timeout); + dSeek, 0, bLiveStream, timeout); - unsigned long size = 0; + off_t size = 0; uint32_t timestamp = 0; int tries = 2; /* 1 retry */ @@ -1236,85 +1268,117 @@ int main(int argc, char **argv) } } - #ifdef _DEBUG +#ifdef _DEBUG netstackdump = fopen("netstackdump", "wb"); netstackdump_read = fopen("netstackdump_read", "wb"); - #endif - - // User defined seek offset - if (dStartOffset > 0) { - if (bLiveStream) - Log(LOGWARNING, "Can't seek in a live stream, ignoring --seek option"); - // Don't need the offset if resuming an existing file - else if (bResume) - Log(LOGDEBUG, "Can't seek a resumed stream, ignoring --seek option"); - else - dSeek += dStartOffset; - } +#endif while (tries > 0 && !bCtrlC) { tries--; - Log(LOGDEBUG, "Setting buffer time to: %dms", bufferTime); - rtmp->SetBufferMS(bufferTime); + Log(LOGDEBUG, "Setting buffer time to: %dms", bufferTime); + rtmp->SetBufferMS(bufferTime); - if (first) { - first = 0; - LogPrintf("Connecting ...\n"); + if (first) { + first = 0; + LogPrintf("Connecting ...\n"); - if (!rtmp->Connect()) { - break; - } + if (!rtmp->Connect()) { + break; + } - Log(LOGINFO, "Connected..."); - - timestamp = dSeek; - if(dSeek != 0) { - LogPrintf("Continuing at TS: %d ms\n", timestamp); - } + Log(LOGINFO, "Connected..."); - if (!rtmp->ConnectStream(dSeek)) { - break; + timestamp = dSeek; + if(dSeek != 0) { + LogPrintf("Continuing at TS: %d ms\n", timestamp); + } + + // User defined seek offset + if (dStartOffset > 0) { + // Don't need the start offset if resuming an existing file + if (bResume) { + Log(LOGWARNING, "Can't seek a resumed stream, ignoring --start option"); + dStartOffset = 0; + } else { + // ??? we want to add not equals ??? + dSeek += dStartOffset; + } + } + + // Calculate the length of the stream to still play + if (dStopOffset > 0) { + dLength = dStopOffset - dSeek; + + // Quit if start seek is past required stop offset + if(dSeek >= dStopOffset) { + LogPrintf("Already Completed\n"); + return RD_SUCCESS; + } + } + + if (!rtmp->ConnectStream(dSeek, dLength)) { + break; + } } - } - nStatus = Download(rtmp, file, dSeek, dStopOffset, duration, bResume, + nStatus = Download(rtmp, file, dSeek, dLength, dStopOffset, duration, bResume, metaHeader, nMetaHeaderSize, initialFrame, initialFrameType, nInitialFrameSize, nSkipKeyFrames, bStdoutMode, bLiveStream, bOverrideBufferTime, bufferTime, &percent); free(initialFrame); - initialFrame = NULL; + initialFrame = NULL; - /* If we succeeded, we're done. If writing to stdout - * we can't seek and retry. - */ - if (nStatus != RD_INCOMPLETE || bStdoutMode || !rtmp->IsTimedout()) - break; - - nInitialFrameSize = 0; + /* If we succeeded, we're done. If writing to stdout + * we can't seek and retry. + */ + if (nStatus != RD_INCOMPLETE || bStdoutMode || !rtmp->IsTimedout()) + break; - Log(LOGINFO, "Connection timed out, trying to reconnect.\n\n"); + nInitialFrameSize = 0; + + Log(LOGINFO, "Connection timed out, trying to reconnect.\n\n"); - nStatus = GetLastKeyframe(file, nSkipKeyFrames, + nStatus = GetLastKeyframe(file, nSkipKeyFrames, &dSeek, &initialFrame, &initialFrameType, &nInitialFrameSize); - if (nStatus != RD_SUCCESS) { + if (nStatus != RD_SUCCESS) { Log(LOGDEBUG, "Failed to get last keyframe."); break; - } + } - if (!rtmp->ReconnectStream(bufferTime, dSeek)) { + // Calculate the length of the stream to still play + if (dStopOffset > 0) { + dLength = dStopOffset - dSeek; + + // Quit if start seek is past required stop offset + if(dLength <= 0) { + LogPrintf("Already Completed\n"); + nStatus = RD_SUCCESS; + break; + } + } + + if (!rtmp->ReconnectStream(bufferTime, dSeek, dLength)) { Log(LOGERROR, "Failed to resume the stream\n\n"); - if (!rtmp->IsTimedout()) { + if (!rtmp->IsTimedout()) { nStatus = RD_FAILED; break; - } - } + } + } bResume = true; } + // If duration is available then assume the download is complete if > 99.9% + if (bLiveStream == false && dStopOffset <= 0) { + if (duration > 0 && percent > 99.9) + nStatus = RD_SUCCESS; + else + nStatus = RD_INCOMPLETE; + } + if (nStatus == RD_SUCCESS) { LogPrintf("Download complete\n"); } else if (nStatus == RD_INCOMPLETE) { Modified: streams.cpp ============================================================================== --- streams.cpp Fri Nov 6 06:36:42 2009 (r25) +++ streams.cpp Fri Nov 6 06:38:22 2009 (r26) @@ -641,6 +641,7 @@ void processTCPrequest req.flashVer, req.subscribepath, dSeek, + -1, // length req.bLiveStream, req.timeout);
participants (1)
-
hyc