[rtmpdump] r326 - trunk/rtmpdump.c
hyc
subversion at mplayerhq.hu
Wed Mar 10 19:31:47 CET 2010
Author: hyc
Date: Wed Mar 10 19:31:45 2010
New Revision: 326
Log:
Rework WriteStream arguments
Modified:
trunk/rtmpdump.c
Modified: trunk/rtmpdump.c
==============================================================================
--- trunk/rtmpdump.c Wed Mar 10 12:58:34 2010 (r325)
+++ trunk/rtmpdump.c Wed Mar 10 19:31:45 2010 (r326)
@@ -146,21 +146,27 @@ WriteHeader(char **buf, // target point
static const AVal av_onMetaData = AVC("onMetaData");
static const AVal av_duration = AVC("duration");
+typedef struct WSargs {
+ RTMP *rtmp;
+ char *buf; // target pointer, maybe preallocated
+ unsigned int buflen; // length of buffer if preallocated
+ uint32_t tsm; // contain timestamp of last packet returned
+ uint8_t dataType; // whenever we get a video/audio packet we set an appropriate flag here, this will be later written to the FLV header
+ uint8_t bLiveStream; // live mode, will not report absolute timestamps
+ uint8_t bResume; // resuming mode, will not write FLV header and compare metaHeader and first kexframe
+ uint8_t initialFrameType; // initial frame type (audio or video)
+
+ /* if bResume == TRUE */
+ uint32_t nResumeTS; // resume keyframe timestamp
+ char *metaHeader; // pointer to meta header
+ char *initialFrame; // pointer to initial keyframe (no FLV header or tagSize, raw data)
+ uint32_t nMetaHeaderSize; // length of meta header, if zero meta header check omitted
+ uint32_t nInitialFrameSize; // length of initial frame in bytes, if zero initial frame check omitted
+} WSargs;
+
// 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(RTMP * 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)
- char *initialFrame, // pointer to initial keyframe (no FLV header or tagSize, raw data) (if bResume == TRUE)
- uint8_t initialFrameType, // initial frame type (audio or video)
- uint32_t nInitialFrameSize, // length of initial frame in bytes, if zero initial frame check omitted (if bResume == TRUE)
- uint8_t * dataType // whenever we get a video/audio packet we set an appropriate flag here, this will be later written to the FLV header
- )
+WriteStream(WSargs *ws)
{
static bool bStopIgnoring = false;
static bool bFoundKeyframe = false;
@@ -170,7 +176,7 @@ WriteStream(RTMP * rtmp, char **buf, //
int rtnGetNextMediaPacket = 0, ret = -1;
RTMPPacket packet = { 0 };
- rtnGetNextMediaPacket = RTMP_GetNextMediaPacket(rtmp, &packet);
+ rtnGetNextMediaPacket = RTMP_GetNextMediaPacket(ws->rtmp, &packet);
while (rtnGetNextMediaPacket)
{
char *packetBody = packet.m_body;
@@ -185,6 +191,9 @@ WriteStream(RTMP * rtmp, char **buf, //
break;
}
+ ws->dataType |= (((packet.m_packetType == 0x08) << 2) |
+ (packet.m_packetType == 0x09));
+
// skip video info/command packets
if (packet.m_packetType == 0x09 &&
nPacketLen == 2 && ((*packetBody & 0xf0) == 0x50))
@@ -207,7 +216,7 @@ WriteStream(RTMP * rtmp, char **buf, //
ret = 0;
break;
}
-#ifdef _DEBUG
+#if 1 /* def _DEBUG */
Log(LOGDEBUG, "type: %02X, size: %d, TS: %d ms, abs TS: %d",
packet.m_packetType, nPacketLen, packet.m_nTimeStamp,
packet.m_hasAbsTimestamp);
@@ -216,9 +225,9 @@ WriteStream(RTMP * rtmp, char **buf, //
#endif
// check the header if we get one
- if (bResume && packet.m_nTimeStamp == 0)
+ if (ws->bResume && packet.m_nTimeStamp == 0)
{
- if (nMetaHeaderSize > 0 && packet.m_packetType == 0x12)
+ if (ws->nMetaHeaderSize > 0 && packet.m_packetType == 0x12)
{
AMFObject metaObj;
@@ -232,8 +241,8 @@ WriteStream(RTMP * rtmp, char **buf, //
if (AVMATCH(&metastring, &av_onMetaData))
{
// compare
- if ((nMetaHeaderSize != nPacketLen) ||
- (memcmp(metaHeader, packetBody, nMetaHeaderSize) !=
+ if ((ws->nMetaHeaderSize != nPacketLen) ||
+ (memcmp(ws->metaHeader, packetBody, ws->nMetaHeaderSize) !=
0))
{
ret = -2;
@@ -247,16 +256,16 @@ WriteStream(RTMP * rtmp, char **buf, //
// check first keyframe to make sure we got the right position in the stream!
// (the first non ignored frame)
- if (nInitialFrameSize > 0)
+ if (ws->nInitialFrameSize > 0)
{
// video or audio data
- if (packet.m_packetType == initialFrameType
- && nInitialFrameSize == nPacketLen)
+ if (packet.m_packetType == ws->initialFrameType
+ && ws->nInitialFrameSize == nPacketLen)
{
// we don't compare the sizes since the packet can contain several FLV packets, just make
// sure the first frame is our keyframe (which we are going to rewrite)
- if (memcmp(initialFrame, packetBody, nInitialFrameSize) ==
+ if (memcmp(ws->initialFrame, packetBody, ws->nInitialFrameSize) ==
0)
{
Log(LOGDEBUG, "Checked keyframe successfully!");
@@ -289,17 +298,17 @@ WriteStream(RTMP * rtmp, char **buf, //
#endif
// ok, is it a keyframe!!!: well doesn't work for audio!
if (packetBody[pos /*6928, test 0 */ ] ==
- initialFrameType
+ ws->initialFrameType
/* && (packetBody[11]&0xf0) == 0x10 */ )
{
- if (ts == nResumeTS)
+ if (ts == ws->nResumeTS)
{
Log(LOGDEBUG,
"Found keyframe with resume-keyframe timestamp!");
- if (nInitialFrameSize != dataSize
- || memcmp(initialFrame,
+ if (ws->nInitialFrameSize != dataSize
+ || memcmp(ws->initialFrame,
packetBody + pos + 11,
- nInitialFrameSize) != 0)
+ ws->nInitialFrameSize) != 0)
{
Log(LOGERROR,
"FLV Stream: Keyframe doesn't match!");
@@ -323,14 +332,14 @@ WriteStream(RTMP * rtmp, char **buf, //
goto stopKeyframeSearch;
}
- else if (nResumeTS < ts)
+ else if (ws->nResumeTS < ts)
{
goto stopKeyframeSearch; // the timestamp ts will only increase with further packets, wait for seek
}
}
pos += (11 + dataSize + 4);
}
- if (ts < nResumeTS)
+ if (ts < ws->nResumeTS)
{
Log(LOGERROR,
"First packet does not contain keyframe, all timestamps are smaller than the keyframe timestamp, so probably the resume seek failed?");
@@ -348,7 +357,7 @@ WriteStream(RTMP * rtmp, char **buf, //
}
}
- if (bResume && packet.m_nTimeStamp > 0
+ if (ws->bResume && packet.m_nTimeStamp > 0
&& (bFoundFlvKeyframe || bFoundKeyframe))
{
// another problem is that the server can actually change from 09/08 video/audio packets to an FLV stream
@@ -363,7 +372,7 @@ WriteStream(RTMP * rtmp, char **buf, //
}
// skip till we find out keyframe (seeking might put us somewhere before it)
- if (bResume && !bFoundKeyframe && packet.m_packetType != 0x16)
+ if (ws->bResume && !bFoundKeyframe && packet.m_packetType != 0x16)
{
Log(LOGWARNING,
"Stream does not start with requested frame, ignoring data... ");
@@ -375,7 +384,7 @@ WriteStream(RTMP * rtmp, char **buf, //
break;
}
// ok, do the same for FLV streams
- if (bResume && !bFoundFlvKeyframe && packet.m_packetType == 0x16)
+ if (ws->bResume && !bFoundFlvKeyframe && packet.m_packetType == 0x16)
{
Log(LOGWARNING,
"Stream does not start with requested FLV frame, ignoring data... ");
@@ -390,7 +399,7 @@ WriteStream(RTMP * rtmp, char **buf, //
// if bResume, we continue a stream, we have to ignore the 0ms frames since these are the first keyframes, we've got these
// so don't mess around with multiple copies sent by the server to us! (if the keyframe is found at a later position
// there is only one copy and it will be ignored by the preceding if clause)
- if (!bStopIgnoring && bResume && packet.m_packetType != 0x16)
+ if (!bStopIgnoring && ws->bResume && packet.m_packetType != 0x16)
{ // exclude type 0x16 (FLV) since it can conatin several FLV packets
if (packet.m_nTimeStamp == 0)
{
@@ -410,17 +419,18 @@ WriteStream(RTMP * rtmp, char **buf, //
|| packet.m_packetType ==
0x12) ? 11 : 0) + (packet.m_packetType != 0x16 ? 4 : 0);
- if (size + 4 > len)
+ if (size + 4 > ws->buflen)
{ // the extra 4 is for the case of an FLV stream without a last prevTagSize (we need extra 4 bytes to append it)
- *buf = (char *) realloc(*buf, size + 4);
- if (*buf == 0)
+ ws->buf = realloc(ws->buf, size + 4);
+ if (ws->buf == 0)
{
Log(LOGERROR, "Couldn't reallocate memory!");
ret = -1; // fatal error
break;
}
+ ws->buflen = size + 4;
}
- char *ptr = *buf, *pend = ptr+size+4;
+ char *ptr = ws->buf, *pend = ptr+size+4;
uint32_t nTimeStamp = 0; // use to return timestamp of last processed packet
@@ -429,12 +439,7 @@ WriteStream(RTMP * rtmp, char **buf, //
if (packet.m_packetType == 0x08 || packet.m_packetType == 0x09
|| packet.m_packetType == 0x12)
{
- // set data type
- *dataType |=
- (((packet.m_packetType == 0x08) << 2) | (packet.m_packetType ==
- 0x09));
-
- nTimeStamp = nResumeTS + packet.m_nTimeStamp;
+ nTimeStamp = ws->nResumeTS + packet.m_nTimeStamp;
prevTagSize = 11 + nPacketLen;
*ptr = packet.m_packetType;
@@ -485,7 +490,7 @@ WriteStream(RTMP * rtmp, char **buf, //
ptr[pos+7] = (nTimeStamp>>24)&0xff;// */
// set data type
- *dataType |=
+ ws->dataType |=
(((*(packetBody + pos) ==
0x08) << 2) | (*(packetBody + pos) == 0x09));
@@ -546,9 +551,7 @@ WriteStream(RTMP * rtmp, char **buf, //
// 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 = bLiveStream ? packet.m_nTimeStamp : nTimeStamp;
-
+ ws->tsm = ws->bLiveStream ? packet.m_nTimeStamp : nTimeStamp;
ret = size;
break;
@@ -872,22 +875,22 @@ int
Download(RTMP * rtmp, // connected RTMP object
FILE * file, uint32_t dSeek, uint32_t dLength, double duration, bool bResume, char *metaHeader, uint32_t nMetaHeaderSize, char *initialFrame, int initialFrameType, uint32_t nInitialFrameSize, int nSkipKeyFrames, bool bStdoutMode, bool bLiveStream, bool bHashes, bool bOverrideBufferTime, uint32_t bufferTime, double *percent) // percentage downloaded [out]
{
- uint32_t timestamp = dSeek;
int32_t now, lastUpdate;
- uint8_t dataType = 0; // will be written into the FLV header (position 4)
int bufferSize = 1024 * 1024;
char *buffer = (char *) malloc(bufferSize);
int nRead = 0;
off_t size = ftello(file);
unsigned long lastPercent = 0;
+ WSargs ws;
+ ws.tsm = dSeek;
memset(buffer, 0, bufferSize);
*percent = 0.0;
- if (timestamp)
+ if (ws.tsm)
{
- Log(LOGDEBUG, "Continuing at TS: %d ms\n", timestamp);
+ Log(LOGDEBUG, "Continuing at TS: %d ms\n", ws.tsm);
}
if (bLiveStream)
@@ -900,20 +903,20 @@ Download(RTMP * rtmp, // connected RTMP
// Workaround to exit with 0 if the file is fully (> 99.9%) downloaded
if (duration > 0)
{
- if ((double) timestamp >= (double) duration * 999.0)
+ if ((double) ws.tsm >= (double) duration * 999.0)
{
LogPrintf("Already Completed at: %.3f sec Duration=%.3f sec\n",
- (double) timestamp / 1000.0,
+ (double) ws.tsm / 1000.0,
(double) duration / 1000.0);
return RD_SUCCESS;
}
else
{
- *percent = ((double) timestamp) / (duration * 1000.0) * 100.0;
+ *percent = ((double) ws.tsm) / (duration * 1000.0) * 100.0;
*percent = ((double) (int) (*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,
+ (double) size / 1024.0, (double) ws.tsm / 1000.0,
*percent);
}
}
@@ -952,15 +955,24 @@ Download(RTMP * rtmp, // connected RTMP
}
}
+ ws.rtmp = rtmp;
+ ws.buf = buffer;
+ ws.buflen = bufferSize;
+ ws.dataType = 0;
+ ws.bLiveStream = bLiveStream;
+ ws.bResume = bResume;
+ ws.initialFrameType = initialFrameType;
+ ws.nResumeTS = dSeek;
+ ws.metaHeader = metaHeader;
+ ws.initialFrame = initialFrame;
+ ws.nMetaHeaderSize = nMetaHeaderSize;
+ ws.nInitialFrameSize = nInitialFrameSize;
+
now = RTMP_GetTime();
lastUpdate = now - 1000;
do
{
- nRead = WriteStream(rtmp, &buffer, bufferSize, ×tamp, bResume
- && nInitialFrameSize > 0, bLiveStream, dSeek,
- metaHeader, nMetaHeaderSize, initialFrame,
- initialFrameType, nInitialFrameSize, &dataType);
-
+ nRead = WriteStream(&ws);
//LogPrintf("nRead: %d\n", nRead);
if (nRead > 0)
{
@@ -990,7 +1002,7 @@ Download(RTMP * rtmp, // connected RTMP
RTMP_SetBufferMS(rtmp, bufferTime);
RTMP_UpdateBufferMS(rtmp);
}
- *percent = ((double) timestamp) / (duration * 1000.0) * 100.0;
+ *percent = ((double) ws.tsm) / (duration * 1000.0) * 100.0;
*percent = ((double) (int) (*percent * 10.0)) / 10.0;
if (bHashes)
{
@@ -1007,7 +1019,7 @@ Download(RTMP * rtmp, // connected RTMP
{
LogStatus("\r%.3f kB / %.2f sec (%.1f%%)",
(double) size / 1024.0,
- (double) (timestamp) / 1000.0, *percent);
+ (double) (ws.tsm) / 1000.0, *percent);
lastUpdate = now;
}
}
@@ -1021,7 +1033,7 @@ Download(RTMP * rtmp, // connected RTMP
LogStatus("#");
else
LogStatus("\r%.3f kB / %.2f sec", (double) size / 1024.0,
- (double) (timestamp) / 1000.0);
+ (double) (ws.tsm) / 1000.0);
lastUpdate = now;
}
}
@@ -1042,16 +1054,16 @@ Download(RTMP * rtmp, // connected RTMP
{
if (duration > 0)
{
- *percent = ((double) timestamp) / (duration * 1000.0) * 100.0;
+ *percent = ((double) ws.tsm) / (duration * 1000.0) * 100.0;
*percent = ((double) (int) (*percent * 10.0)) / 10.0;
LogStatus("\r%.3f kB / %.2f sec (%.1f%%)",
(double) size / 1024.0,
- (double) (timestamp) / 1000.0, *percent);
+ (double) (ws.tsm) / 1000.0, *percent);
}
else
{
LogStatus("\r%.3f kB / %.2f sec", (double) size / 1024.0,
- (double) (timestamp) / 1000.0);
+ (double) (ws.tsm) / 1000.0);
}
}
@@ -1065,11 +1077,11 @@ Download(RTMP * rtmp, // connected RTMP
}
// finalize header by writing the correct dataType (video, audio, video+audio)
- if (!bResume && dataType != 0x5 && !bStdoutMode)
+ if (!bResume && ws.dataType != 0x5 && !bStdoutMode)
{
//Log(LOGDEBUG, "Writing data type: %02X", dataType);
fseek(file, 4, SEEK_SET);
- fwrite(&dataType, sizeof(unsigned char), 1, file);
+ fwrite(&ws.dataType, sizeof(unsigned char), 1, file);
/* resume uses ftell to see where we left off */
fseek(file, 0, SEEK_END);
}
More information about the rtmpdump
mailing list