[rtmpdump] r26 - bytes.h rtmp.cpp rtmp.h rtmpdump.cpp streams.cpp
hyc
subversion at mplayerhq.hu
Fri Nov 6 06:38:22 CET 2009
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);
More information about the rtmpdump
mailing list