[rtmpdump] r30 - rtmpdump.cpp
hyc
subversion at mplayerhq.hu
Sat Nov 7 08:56:32 CET 2009
Author: hyc
Date: Sat Nov 7 08:56:32 2009
New Revision: 30
Log:
sync with flvstreamer 1.9, with additional cleanups
Modified:
rtmpdump.cpp
Modified: rtmpdump.cpp
==============================================================================
--- rtmpdump.cpp Sat Nov 7 08:20:40 2009 (r29)
+++ rtmpdump.cpp Sat Nov 7 08:56:32 2009 (r30)
@@ -50,7 +50,7 @@ int debuglevel = 1;
using namespace RTMP_LIB;
-#define RTMPDUMP_VERSION "v1.8"
+#define RTMPDUMP_VERSION "v1.9"
#define RD_SUCCESS 0
#define RD_FAILED 1
@@ -128,12 +128,14 @@ int WriteHeader(
return size;
}
+// Returns -3 if Play.Close/Stop, -2 if fatal error, -1 if no more media packets, 0 if ignorable error, >0 if there is a media packet
int WriteStream(
CRTMP* rtmp,
char **buf, // target pointer, maybe preallocated
unsigned int len, // length of buffer if preallocated
uint32_t *tsm, // pointer to timestamp, will contain timestamp of last video packet returned
bool bResume, // resuming mode, will not write FLV header and compare metaHeader and first kexframe
+ bool bLiveStream, // live mode, will not report absolute timestamps
uint32_t nResumeTS, // resume keyframe timestamp
char *metaHeader, // pointer to meta header (if bResume == TRUE)
uint32_t nMetaHeaderSize, // length of meta header, if zero meta header check omitted (if bResume == TRUE)
@@ -425,13 +427,16 @@ stopKeyframeSearch:
//ptr += 4;
}
+ // In non-live this nTimeStamp can contain an absolute TS.
+ // Update ext timestamp with this absolute offset in non-live mode otherwise report the relative one
+ // LogPrintf("\nDEBUG: type: %02X, size: %d, pktTS: %dms, TS: %dms, bLiveStream: %d", packet.m_packetType, nPacketLen, packet.m_nTimeStamp, nTimeStamp, bLiveStream);
if(tsm)
- *tsm = nTimeStamp;
+ *tsm = bLiveStream ? packet.m_nTimeStamp : nTimeStamp;
- // Return 0 if this was completed nicely with invoke message Play.Stop or Play.Complete
+ // Return -3 if this was completed nicely with invoke message Play.Stop or Play.Complete
if (rtnGetNextMediaPacket == 2) {
Log(LOGDEBUG, "Got Play.Complete or Play.Stop from server. Assuming stream is complete");
- return 0;
+ return -3;
}
return size;
@@ -716,6 +721,7 @@ int Download(CRTMP *rtmp,
int nSkipKeyFrames,
bool bStdoutMode,
bool bLiveStream,
+ bool bHashes,
bool bOverrideBufferTime,
uint32_t bufferTime,
double *percent) // percentage downloaded [out]
@@ -727,29 +733,36 @@ int Download(CRTMP *rtmp,
char *buffer = (char *)malloc(bufferSize);
int nRead = 0;
off_t size = ftello(file);
+ unsigned long lastPercent = 0;
memset(buffer, 0, bufferSize);
*percent = 0.0;
- if(timestamp != 0) {
- LogPrintf("Continuing at TS: %d ms\n", timestamp);
+ if(timestamp) {
+ Log(LOGDEBUG, "Continuing at TS: %d ms\n", timestamp);
}
- // print initial status
- // 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;
+ if(bLiveStream) {
+ 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)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("%s download at: %.3f kB / %.3f sec (%.1f%%)\n",
+ bResume ? "Resuming":"Starting",
+ (double)size/1024.0, (double)timestamp/1000.0, *percent);
+ }
} 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);
+ LogPrintf("%s download at: %.3f kB\n", bResume ? "Resuming":"Starting",(double)size/1024.0);
}
- } else {
- LogPrintf("Starting download at: %.3f kB\n", (double)size/1024.0);
- }
+ }
if (dLength > 0)
LogPrintf("For duration: %.3f sec\n", (double)dLength/1000.0);
@@ -775,7 +788,7 @@ int Download(CRTMP *rtmp,
lastUpdate = now-1000;
do
{
- nRead = WriteStream(rtmp, &buffer, bufferSize, ×tamp, bResume, dSeek, metaHeader, nMetaHeaderSize, initialFrame, initialFrameType, nInitialFrameSize, &dataType);
+ nRead = WriteStream(rtmp, &buffer, bufferSize, ×tamp, bResume, bLiveStream, dSeek, metaHeader, nMetaHeaderSize, initialFrame, initialFrameType, nInitialFrameSize, &dataType);
//LogPrintf("nRead: %d\n", nRead);
if(nRead > 0) {
@@ -801,15 +814,25 @@ int Download(CRTMP *rtmp,
}
*percent = ((double)timestamp) / (duration*1000.0)*100.0;
*percent = round(*percent*10.0)/10.0;
- now = GetTime();
- if (abs(now - lastUpdate) > 200) {
- LogStatus("\r%.3f kB / %.2f sec (%.1f%%)", (double)size/1024.0, (double)(timestamp)/1000.0, *percent);
- lastUpdate = now;
+ if (bHashes) {
+ if ( lastPercent + 1 <= *percent ) {
+ LogPrintf("#");
+ lastPercent = (unsigned long)*percent;
+ }
+ } else {
+ now = GetTime();
+ if (abs(now - lastUpdate) > 200) {
+ 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 / %.2f sec", (double)size/1024.0, (double)(timestamp)/1000.0);
+ if (bHashes)
+ LogPrintf("#");
+ else
+ LogStatus("\r%.3f kB / %.2f sec", (double)size/1024.0, (double)(timestamp)/1000.0);
lastUpdate = now;
}
}
@@ -821,6 +844,8 @@ int Download(CRTMP *rtmp,
} while(!bCtrlC && nRead > -1 && rtmp->IsConnected());
free(buffer);
+ Log(LOGDEBUG, "WriteStream returned: %d", nRead);
+
if(bResume && nRead == -2) {
LogPrintf("Couldn't resume FLV file, try --skip %d\n\n", nSkipKeyFrames+1);
return RD_FAILED;
@@ -832,6 +857,10 @@ int Download(CRTMP *rtmp,
fseek(file, 4, SEEK_SET);
fwrite(&dataType, sizeof(unsigned char), 1, file);
}
+
+ if(nRead == -3)
+ return RD_SUCCESS;
+
if((duration > 0 && *percent < 99.9) || bCtrlC || nRead < 0 || rtmp->IsTimedout()) {
return RD_INCOMPLETE;
}
@@ -877,6 +906,7 @@ int main(int argc, char **argv)
int port = -1;
int protocol = RTMP_PROTOCOL_UNDEFINED;
bool bLiveStream = false; // is it a live stream? then we can't seek/resume
+ bool bHashes = false; // display byte counters not hashes by default
long int timeout = 120; // timeout connection after 120 seconds
uint32_t dStartOffset = 0; // seek position in non-live mode
@@ -932,8 +962,10 @@ int main(int argc, char **argv)
{"pageUrl", 1, NULL, 'p'},
{"app", 1, NULL, 'a'},
{"auth", 1, NULL, 'u'},
+#ifdef CRYPTO
{"swfhash", 1, NULL, 'w'},
{"swfsize", 1, NULL, 'x'},
+#endif
{"flashVer",1, NULL, 'f'},
{"live" ,0, NULL, 'v'},
{"flv", 1, NULL, 'o'},
@@ -944,6 +976,7 @@ int main(int argc, char **argv)
{"subscribe",1,NULL, 'd'},
{"start", 1, NULL, 'A'},
{"stop", 1, NULL, 'B'},
+ {"hashes", 0, NULL, '#'},
{"debug", 0, NULL, 'z'},
{"quiet", 0, NULL, 'q'},
{"verbose", 0, NULL, 'V'},
@@ -965,8 +998,10 @@ int main(int argc, char **argv)
LogPrintf("--tcUrl|-t url URL to played stream (default: \"rtmp://host[:port]/app\")\n");
LogPrintf("--pageUrl|-p url Web URL of played programme\n");
LogPrintf("--app|-a app Name of player used\n");
+#ifdef CRYPTO
LogPrintf("--swfhash|-w hexstring SHA256 hash of the decompressed SWF file (32 bytes)\n");
LogPrintf("--swfsize|-x num Size of the decompressed SWF file, required for SWFVerification\n");
+#endif
LogPrintf("--auth|-u string Authentication string to be appended to the connect string\n");
LogPrintf("--flashVer|-f string Flash version string (default: \"%s\")\n", DEFAULT_FLASH_VER);
LogPrintf("--live|-v Save a live stream, no --resume (seeking) of live streams possible\n");
@@ -976,6 +1011,7 @@ int main(int argc, char **argv)
LogPrintf("--timeout|-m num Timeout connection num seconds (default: %lu)\n", timeout);
LogPrintf("--start|-A num Start at num seconds into stream (not valid when using --live)\n");
LogPrintf("--stop|-B num Stop at num seconds into stream\n");
+ LogPrintf("--hashes|-# Display progress with hashes, not with the byte counter\n");
LogPrintf("--buffer|-b Buffer time in milliseconds (default: %lu), this option makes only sense in stdout mode (-o -)\n",
bufferTime);
LogPrintf("--skip|-k num Skip num keyframes when looking for last keyframe to resume from. Useful if resume fails (default: %d)\n\n",
@@ -986,6 +1022,7 @@ int main(int argc, char **argv)
LogPrintf("If you don't pass parameters for swfUrl, pageUrl, app or auth these propertiews will not be included in the connect ");
LogPrintf("packet.\n\n");
return RD_SUCCESS;
+#ifdef CRYPTO
case 'w':
{
int res = hex2bin(optarg, &swfHash);
@@ -1005,6 +1042,7 @@ int main(int argc, char **argv)
}
break;
}
+#endif
case 'k':
nSkipKeyFrames = atoi(optarg);
if(nSkipKeyFrames < 0) {
@@ -1109,6 +1147,9 @@ int main(int argc, char **argv)
case 'B':
dStopOffset = int(atof(optarg)*1000.0);
break;
+ case '#':
+ bHashes = true;
+ break;
case 'q':
debuglevel = LOGCRIT;
break;
@@ -1284,7 +1325,7 @@ int main(int argc, char **argv)
timestamp = dSeek;
if(dSeek != 0) {
- LogPrintf("Continuing at TS: %d ms\n", timestamp);
+ Log(LOGDEBUG, "Continuing at TS: %d ms\n", timestamp);
}
// User defined seek offset
@@ -1320,7 +1361,7 @@ int main(int argc, char **argv)
nStatus = Download(rtmp, file, dSeek, dLength, duration, bResume,
metaHeader, nMetaHeaderSize, initialFrame,
initialFrameType, nInitialFrameSize,
- nSkipKeyFrames, bStdoutMode, bLiveStream,
+ nSkipKeyFrames, bStdoutMode, bLiveStream, bHashes,
bOverrideBufferTime, bufferTime, &percent);
free(initialFrame);
initialFrame = NULL;
@@ -1369,11 +1410,11 @@ int main(int argc, char **argv)
if (nStatus == RD_SUCCESS) {
LogPrintf("Download complete\n");
} else if (nStatus == RD_INCOMPLETE) {
- LogPrintf("Download may be incomplete (downloaded about %.2f%%), try --resume\n", percent);
+ LogPrintf("Download may be incomplete (downloaded about %.2f%%), try resuming\n", percent);
}
clean:
- LogPrintf("\rClosing connection.\n");
+ Log(LOGDEBUG, "Closing connection.\n");
rtmp->Close();
//LogPrintf("done!\n\n");
More information about the rtmpdump
mailing list