]> granicus.if.org Git - rtmpdump/commitdiff
Use RTMP_Read()
authorhyc <hyc@400ebc74-4327-4243-bc38-086b20814532>
Fri, 12 Mar 2010 05:04:10 +0000 (05:04 +0000)
committerhyc <hyc@400ebc74-4327-4243-bc38-086b20814532>
Fri, 12 Mar 2010 05:04:10 +0000 (05:04 +0000)
git-svn-id: svn://svn.mplayerhq.hu/rtmpdump/trunk@332 400ebc74-4327-4243-bc38-086b20814532

librtmp/rtmp.c
librtmp/rtmp.h
rtmpdump.c
rtmpgw.c

index ca29b0bb54a3d06e25ce042427470c7619a2e7d6..97d6011fcaed7a206d48f57a20102ee827aa6c7b 100644 (file)
@@ -3266,7 +3266,7 @@ Read_1_Packet(RTMP *r, char *buf, int buflen)
        * 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);
-      r->m_read.tsm = r->Link.bLiveStream ? packet.m_nTimeStamp : nTimeStamp;
+      r->m_read.timestamp = r->Link.bLiveStream ? packet.m_nTimeStamp : nTimeStamp;
 
       ret = size;
       break;
@@ -3313,7 +3313,7 @@ RTMP_Read(RTMP *r, char *buf, int size)
          r->m_read.buf += sizeof(flvHeader);
          r->m_read.buflen -= sizeof(flvHeader);
 
-         while (r->m_read.tsm == 0)
+         while (r->m_read.timestamp == 0)
            {
              nRead = Read_1_Packet(r, r->m_read.buf, r->m_read.buflen);
              if (nRead < 0)
index 179f37b11b2659b219e6ba0eec27020ac23479b5..628e37182a02da69ff2f19cc0e9a9382e2a4da5e 100644 (file)
@@ -183,7 +183,7 @@ extern "C"
     char *buf;
     char *bufpos;
     unsigned int buflen;
-    uint32_t tsm;
+    uint32_t timestamp;
     uint8_t dataType;
     uint8_t bResume;
     uint8_t bDidHeader;
index 73c504704ec637721763b279898113db1bba666c..f850b3086b4e4c2f2bd972797ea00980e4aeb149 100644 (file)
@@ -117,451 +117,9 @@ int hex2bin(char *str, char **hex)
   return l/2;
 }
 
-int
-WriteHeader(char **buf,                // target pointer, maybe preallocated
-           unsigned int len    // length of buffer if preallocated
-  )
-{
-  char flvHeader[] = { 'F', 'L', 'V', 0x01,
-    0x05,                      // video + audio, we finalize later if the value is different
-    0x00, 0x00, 0x00, 0x09,
-    0x00, 0x00, 0x00, 0x00     // first prevTagSize=0
-  };
-
-  unsigned int size = sizeof(flvHeader);
-
-  if (size > len)
-    {
-      *buf = (char *) realloc(*buf, size);
-      if (*buf == 0)
-       {
-         Log(LOGERROR, "Couldn't reallocate memory!");
-         return -1;            // fatal error
-       }
-    }
-  memcpy(*buf, flvHeader, sizeof(flvHeader));
-  return size;
-}
-
 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(WSargs *ws)
-{
-  static bool bStopIgnoring = false;
-  static bool bFoundKeyframe = false;
-  static bool bFoundFlvKeyframe = false;
-
-  uint32_t prevTagSize = 0;
-  int rtnGetNextMediaPacket = 0, ret = -1;
-  RTMPPacket packet = { 0 };
-
-  rtnGetNextMediaPacket = RTMP_GetNextMediaPacket(ws->rtmp, &packet);
-  while (rtnGetNextMediaPacket)
-    {
-      char *packetBody = packet.m_body;
-      unsigned int nPacketLen = packet.m_nBodySize;
-
-      // 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");
-         ret = -3;
-         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))
-       {
-         ret = 0;
-         break;
-       }
-
-      if (packet.m_packetType == 0x09 && nPacketLen <= 5)
-       {
-         Log(LOGWARNING, "ignoring too small video packet: size: %d",
-             nPacketLen);
-         ret = 0;
-         break;
-       }
-      if (packet.m_packetType == 0x08 && nPacketLen <= 1)
-       {
-         Log(LOGWARNING, "ignoring too small audio packet: size: %d",
-             nPacketLen);
-         ret = 0;
-         break;
-       }
-#ifdef _DEBUG
-      Log(LOGDEBUG, "type: %02X, size: %d, TS: %d ms, abs TS: %d",
-         packet.m_packetType, nPacketLen, packet.m_nTimeStamp,
-         packet.m_hasAbsTimestamp);
-      if (packet.m_packetType == 0x09)
-       Log(LOGDEBUG, "frametype: %02X", (*packetBody & 0xf0));
-#endif
-
-      // check the header if we get one
-      if (ws->bResume && packet.m_nTimeStamp == 0)
-       {
-         if (ws->nMetaHeaderSize > 0 && packet.m_packetType == 0x12)
-           {
-
-             AMFObject metaObj;
-             int nRes = AMF_Decode(&metaObj, packetBody, nPacketLen, false);
-             if (nRes >= 0)
-               {
-                 AVal metastring;
-                 AMFProp_GetString(AMF_GetProp(&metaObj, NULL, 0),
-                                   &metastring);
-
-                 if (AVMATCH(&metastring, &av_onMetaData))
-                   {
-                     // compare
-                     if ((ws->nMetaHeaderSize != nPacketLen) ||
-                         (memcmp(ws->metaHeader, packetBody, ws->nMetaHeaderSize) !=
-                          0))
-                       {
-                         ret = -2;
-                       }
-                   }
-                 AMF_Reset(&metaObj);
-                 if (ret == -2)
-                   break;
-               }
-           }
-
-         // check first keyframe to make sure we got the right position in the stream!
-         // (the first non ignored frame)
-         if (ws->nInitialFrameSize > 0)
-           {
-
-             // video or audio data
-             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(ws->initialFrame, packetBody, ws->nInitialFrameSize) ==
-                     0)
-                   {
-                     Log(LOGDEBUG, "Checked keyframe successfully!");
-                     bFoundKeyframe = true;
-                     ret = 0;  // ignore it! (what about audio data after it? it is handled by ignoring all 0ms frames, see below)
-                     break;
-                   }
-               }
-
-             // hande FLV streams, even though the server resends the keyframe as an extra video packet
-             // it is also included in the first FLV stream chunk and we have to compare it and
-             // filter it out !!
-             //
-             if (packet.m_packetType == 0x16)
-               {
-                 // basically we have to find the keyframe with the correct TS being nResumeTS
-                 unsigned int pos = 0;
-                 uint32_t ts = 0;
-
-                 while (pos + 11 < nPacketLen)
-                   {
-                     uint32_t dataSize = AMF_DecodeInt24(packetBody + pos + 1);        // size without header (11) and prevTagSize (4)
-                     ts = AMF_DecodeInt24(packetBody + pos + 4);
-                     ts |= (packetBody[pos + 7] << 24);
-
-#ifdef _DEBUG
-                     Log(LOGDEBUG,
-                         "keyframe search: FLV Packet: type %02X, dataSize: %d, timeStamp: %d ms",
-                         packetBody[pos], dataSize, ts);
-#endif
-                     // ok, is it a keyframe!!!: well doesn't work for audio!
-                     if (packetBody[pos /*6928, test 0 */ ] ==
-                         ws->initialFrameType
-                         /* && (packetBody[11]&0xf0) == 0x10 */ )
-                       {
-                         if (ts == ws->nResumeTS)
-                           {
-                             Log(LOGDEBUG,
-                                 "Found keyframe with resume-keyframe timestamp!");
-                             if (ws->nInitialFrameSize != dataSize
-                                 || memcmp(ws->initialFrame,
-                                           packetBody + pos + 11,
-                                           ws->nInitialFrameSize) != 0)
-                               {
-                                 Log(LOGERROR,
-                                     "FLV Stream: Keyframe doesn't match!");
-                                 ret = -2;
-                                 break;
-                               }
-                             bFoundFlvKeyframe = true;
-
-                             // ok, skip this packet
-                             // check whether skipable:
-                             if (pos + 11 + dataSize + 4 > nPacketLen)
-                               {
-                                 Log(LOGWARNING,
-                                     "Non skipable packet since it doesn't end with chunk, stream corrupt!");
-                                 ret = -2;
-                                 break;
-                               }
-                             packetBody += (pos + 11 + dataSize + 4);
-                             nPacketLen -= (pos + 11 + dataSize + 4);
-
-                             goto stopKeyframeSearch;
-
-                           }
-                         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 < ws->nResumeTS)
-                   {
-                     Log(LOGERROR,
-                         "First packet does not contain keyframe, all timestamps are smaller than the keyframe timestamp, so probably the resume seek failed?");
-                   }
-               stopKeyframeSearch:
-                 ;
-                 if (!bFoundFlvKeyframe)
-                   {
-                     Log(LOGERROR,
-                         "Couldn't find the seeked keyframe in this chunk!");
-                     ret = 0;
-                     break;
-                   }
-               }
-           }
-       }
-
-      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
-         // or vice versa and our keyframe check will prevent us from going along with the new stream if we resumed
-         //
-         // in this case set the 'found keyframe' variables to true
-         // We assume that if we found one keyframe somewhere and were already beyond TS > 0 we have written
-         // data to the output which means we can accept all forthcoming data inclusing the change between 08/09 <-> FLV
-         // packets
-         bFoundFlvKeyframe = true;
-         bFoundKeyframe = true;
-       }
-
-      // skip till we find out keyframe (seeking might put us somewhere before it)
-      if (ws->bResume && !bFoundKeyframe && packet.m_packetType != 0x16)
-       {
-         Log(LOGWARNING,
-             "Stream does not start with requested frame, ignoring data... ");
-         nIgnoredFrameCounter++;
-         if (nIgnoredFrameCounter > MAX_IGNORED_FRAMES)
-           ret = -2;           // fatal error, couldn't continue stream
-         else
-           ret = 0;
-         break;
-       }
-      // ok, do the same for FLV streams
-      if (ws->bResume && !bFoundFlvKeyframe && packet.m_packetType == 0x16)
-       {
-         Log(LOGWARNING,
-             "Stream does not start with requested FLV frame, ignoring data... ");
-         nIgnoredFlvFrameCounter++;
-         if (nIgnoredFlvFrameCounter > MAX_IGNORED_FRAMES)
-           ret = -2;
-         else
-           ret = 0;
-         break;
-       }
-
-      // 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 && ws->bResume && packet.m_packetType != 0x16)
-       {                       // exclude type 0x16 (FLV) since it can conatin several FLV packets
-         if (packet.m_nTimeStamp == 0)
-           {
-             ret = 0;
-             break;
-           }
-         else
-           {
-             bStopIgnoring = true;     // stop ignoring packets
-           }
-       }
-
-      // calculate packet size and reallocate buffer if necessary
-      unsigned int size = nPacketLen
-       +
-       ((packet.m_packetType == 0x08 || packet.m_packetType == 0x09
-         || packet.m_packetType ==
-         0x12) ? 11 : 0) + (packet.m_packetType != 0x16 ? 4 : 0);
-
-      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)
-         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 = ws->buf, *pend = ptr+size+4;
-
-      uint32_t nTimeStamp = 0; // use to return timestamp of last processed packet
-
-      // audio (0x08), video (0x09) or metadata (0x12) packets :
-      // construct 11 byte header then add rtmp packet's data
-      if (packet.m_packetType == 0x08 || packet.m_packetType == 0x09
-         || packet.m_packetType == 0x12)
-       {
-         nTimeStamp = ws->nResumeTS + packet.m_nTimeStamp;
-         prevTagSize = 11 + nPacketLen;
-
-         *ptr = packet.m_packetType;
-         ptr++;
-         ptr = AMF_EncodeInt24(ptr, pend, nPacketLen);
-
-         /*if(packet.m_packetType == 0x09) { // video
-
-            // H264 fix:
-            if((packetBody[0] & 0x0f) == 7) { // CodecId = H264
-            uint8_t packetType = *(packetBody+1);
-
-            uint32_t ts = AMF_DecodeInt24(packetBody+2); // composition time
-            int32_t cts = (ts+0xff800000)^0xff800000;
-            Log(LOGDEBUG, "cts  : %d\n", cts);
-
-            nTimeStamp -= cts;
-            // get rid of the composition time
-            CRTMP::EncodeInt24(packetBody+2, 0);
-            }
-            Log(LOGDEBUG, "VIDEO: nTimeStamp: 0x%08X (%d)\n", nTimeStamp, nTimeStamp);
-            } */
-
-         ptr = AMF_EncodeInt24(ptr, pend, nTimeStamp);
-         *ptr = (char) ((nTimeStamp & 0xFF000000) >> 24);
-         ptr++;
-
-         // stream id
-         ptr = AMF_EncodeInt24(ptr, pend, 0);
-       }
-
-      memcpy(ptr, packetBody, nPacketLen);
-      unsigned int len = nPacketLen;
-
-      // correct tagSize and obtain timestamp if we have an FLV stream
-      if (packet.m_packetType == 0x16)
-       {
-         unsigned int pos = 0;
-
-         while (pos + 11 < nPacketLen)
-           {
-             uint32_t dataSize = AMF_DecodeInt24(packetBody + pos + 1);        // size without header (11) and without prevTagSize (4)
-             nTimeStamp = AMF_DecodeInt24(packetBody + pos + 4);
-             nTimeStamp |= (packetBody[pos + 7] << 24);
-
-             /*
-                CRTMP::EncodeInt24(ptr+pos+4, nTimeStamp);
-                ptr[pos+7] = (nTimeStamp>>24)&0xff;// */
-
-             // set data type
-             ws->dataType |=
-               (((*(packetBody + pos) ==
-                  0x08) << 2) | (*(packetBody + pos) == 0x09));
-
-             if (pos + 11 + dataSize + 4 > nPacketLen)
-               {
-                 if (pos + 11 + dataSize > nPacketLen)
-                   {
-                     Log(LOGERROR,
-                         "Wrong data size (%lu), stream corrupted, aborting!",
-                         dataSize);
-                     ret = -2;
-                     break;
-                   }
-                 Log(LOGWARNING, "No tagSize found, appending!");
-
-                 // we have to append a last tagSize!
-                 prevTagSize = dataSize + 11;
-                 AMF_EncodeInt32(ptr + pos + 11 + dataSize, pend, prevTagSize);
-                 size += 4;
-                 len += 4;
-               }
-             else
-               {
-                 prevTagSize =
-                   AMF_DecodeInt32(packetBody + pos + 11 + dataSize);
-
-#ifdef _DEBUG
-                 Log(LOGDEBUG,
-                     "FLV Packet: type %02X, dataSize: %lu, tagSize: %lu, timeStamp: %lu ms",
-                     (unsigned char) packetBody[pos], dataSize, prevTagSize,
-                     nTimeStamp);
-#endif
-
-                 if (prevTagSize != (dataSize + 11))
-                   {
-#ifdef _DEBUG
-                     Log(LOGWARNING,
-                         "Tag and data size are not consitent, writing tag size according to dataSize+11: %d",
-                         dataSize + 11);
-#endif
-
-                     prevTagSize = dataSize + 11;
-                     AMF_EncodeInt32(ptr + pos + 11 + dataSize, pend, prevTagSize);
-                   }
-               }
-
-             pos += prevTagSize + 4;   //(11+dataSize+4);
-           }
-       }
-      ptr += len;
-
-      if (packet.m_packetType != 0x16)
-       {                       // FLV tag packets contain their own prevTagSize
-         AMF_EncodeInt32(ptr, pend, prevTagSize);
-         //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);
-      ws->tsm = ws->bLiveStream ? packet.m_nTimeStamp : nTimeStamp;
-
-      ret = size;
-      break;
-    }
-
-  if (rtnGetNextMediaPacket)
-    RTMPPacket_Free(&packet);
-  return ret;                  // no more media packets
-}
-
 int
 OpenResumeFile(const char *flvFile,    // file name [in]
               FILE ** file,    // opened file [out]
@@ -876,21 +434,19 @@ 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]
 {
   int32_t now, lastUpdate;
-  int bufferSize = 1024 * 1024;
+  int bufferSize = 64 * 1024;
   char *buffer = (char *) malloc(bufferSize);
-  int nRead = 0, doHeader = 0;
+  int nRead = 0;
   off_t size = ftello(file);
   unsigned long lastPercent = 0;
-  WSargs ws;
 
-  ws.tsm = dSeek;
-  memset(buffer, 0, bufferSize);
+  rtmp->m_read.timestamp = dSeek;
 
   *percent = 0.0;
 
-  if (ws.tsm)
+  if (rtmp->m_read.timestamp)
     {
-      Log(LOGDEBUG, "Continuing at TS: %d ms\n", ws.tsm);
+      Log(LOGDEBUG, "Continuing at TS: %d ms\n", rtmp->m_read.timestamp);
     }
 
   if (bLiveStream)
@@ -903,20 +459,20 @@ Download(RTMP * rtmp,             // connected RTMP object
       // Workaround to exit with 0 if the file is fully (> 99.9%) downloaded
       if (duration > 0)
        {
-         if ((double) ws.tsm >= (double) duration * 999.0)
+         if ((double) rtmp->m_read.timestamp >= (double) duration * 999.0)
            {
              LogPrintf("Already Completed at: %.3f sec Duration=%.3f sec\n",
-                       (double) ws.tsm / 1000.0,
+                       (double) rtmp->m_read.timestamp / 1000.0,
                        (double) duration / 1000.0);
              return RD_SUCCESS;
            }
          else
            {
-             *percent = ((double) ws.tsm) / (duration * 1000.0) * 100.0;
+             *percent = ((double) rtmp->m_read.timestamp) / (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) ws.tsm / 1000.0,
+                       (double) size / 1024.0, (double) rtmp->m_read.timestamp / 1000.0,
                        *percent);
            }
        }
@@ -931,68 +487,23 @@ Download(RTMP * rtmp,             // connected RTMP object
   if (dLength > 0)
     LogPrintf("For duration: %.3f sec\n", (double) dLength / 1000.0);
 
-  ws.buf = buffer;
-  ws.buflen = bufferSize;
-
-  // write FLV header if not resuming
-  if (!bResume)
-    {
-      nRead = WriteHeader(&buffer, bufferSize);
-      if (nRead > 0)
-       {
-         ws.buf += nRead;
-         ws.buflen -= nRead;
-         size += nRead;
-         doHeader = 1;
-       }
-      else
-       {
-         Log(LOGERROR, "Couldn't obtain FLV header, exiting!");
-         free(buffer);
-         return RD_FAILED;
-       }
-    }
-
-  ws.rtmp = rtmp;
-  ws.dataType = 0;
-  ws.bLiveStream = bLiveStream;
-  ws.bResume = bResume && nInitialFrameSize > 0;
-  ws.initialFrameType = initialFrameType;
-  ws.nResumeTS = dSeek;
-  ws.metaHeader = metaHeader;
-  ws.initialFrame = initialFrame;
-  ws.nMetaHeaderSize = nMetaHeaderSize;
-  ws.nInitialFrameSize = nInitialFrameSize;
+  rtmp->m_read.bResume = bResume && nInitialFrameSize > 0;
+  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;
 
   now = RTMP_GetTime();
   lastUpdate = now - 1000;
   do
     {
-      nRead = WriteStream(&ws);
+      nRead = RTMP_Read(rtmp, buffer, bufferSize);
       //LogPrintf("nRead: %d\n", nRead);
       if (nRead > 0)
        {
-         if (doHeader)
-           {
-             /* cache all the ts=0 pkts so we can get the dataType.
-              * then flush it all with the header when we get ts > 0
-              */
-             if (ws.tsm)
-               {
-                 doHeader = 0;
-                 nRead += size;
-                 size = 0;
-                 ws.buf = buffer;
-                 ws.buflen = bufferSize;
-                 buffer[4] = ws.dataType;
-               }
-             else
-               {
-                 ws.buf += nRead;
-                 ws.buflen -= nRead;
-               }
-           }
-         if (!doHeader && fwrite(buffer, sizeof(unsigned char), nRead, file) !=
+         if (fwrite(buffer, sizeof(unsigned char), nRead, file) !=
              (size_t) nRead)
            {
              Log(LOGERROR, "%s: Failed writing, exiting!", __FUNCTION__);
@@ -1018,7 +529,7 @@ Download(RTMP * rtmp,              // connected RTMP object
                  RTMP_SetBufferMS(rtmp, bufferTime);
                  RTMP_UpdateBufferMS(rtmp);
                }
-             *percent = ((double) ws.tsm) / (duration * 1000.0) * 100.0;
+             *percent = ((double) rtmp->m_read.timestamp) / (duration * 1000.0) * 100.0;
              *percent = ((double) (int) (*percent * 10.0)) / 10.0;
              if (bHashes)
                {
@@ -1035,7 +546,7 @@ Download(RTMP * rtmp,              // connected RTMP object
                    {
                      LogStatus("\r%.3f kB / %.2f sec (%.1f%%)",
                                (double) size / 1024.0,
-                               (double) (ws.tsm) / 1000.0, *percent);
+                               (double) (rtmp->m_read.timestamp) / 1000.0, *percent);
                      lastUpdate = now;
                    }
                }
@@ -1049,7 +560,7 @@ Download(RTMP * rtmp,              // connected RTMP object
                    LogStatus("#");
                  else
                    LogStatus("\r%.3f kB / %.2f sec", (double) size / 1024.0,
-                             (double) (ws.tsm) / 1000.0);
+                             (double) (rtmp->m_read.timestamp) / 1000.0);
                  lastUpdate = now;
                }
            }
@@ -1064,26 +575,28 @@ Download(RTMP * rtmp,            // connected RTMP object
     }
   while (!RTMP_ctrlC && nRead > -1 && RTMP_IsConnected(rtmp));
   free(buffer);
+  if (nRead < 0)
+    nRead = rtmp->m_read.status;
 
   /* Final status update */
   if (!bHashes)
     {
       if (duration > 0)
        {
-         *percent = ((double) ws.tsm) / (duration * 1000.0) * 100.0;
+         *percent = ((double) rtmp->m_read.timestamp) / (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) (ws.tsm) / 1000.0, *percent);
+           (double) (rtmp->m_read.timestamp) / 1000.0, *percent);
        }
       else
        {
          LogStatus("\r%.3f kB / %.2f sec", (double) size / 1024.0,
-           (double) (ws.tsm) / 1000.0);
+           (double) (rtmp->m_read.timestamp) / 1000.0);
        }
     }
 
-  Log(LOGDEBUG, "WriteStream returned: %d", nRead);
+  Log(LOGDEBUG, "RTMP_Read returned: %d", nRead);
 
   if (bResume && nRead == -2)
     {
index b41dff70c475b7a190fb0fc99c1a57962c7e5b1e..3b71d116d65a9441e6266326d3b67bb43ff38520 100644 (file)
--- a/rtmpgw.c
+++ b/rtmpgw.c
@@ -265,211 +265,6 @@ http_unescape(char *data)
   data[dst_x] = '\0';
 }
 
-int
-WriteHeader(char **buf,                // target pointer, maybe preallocated
-           unsigned int len    // length of buffer if preallocated
-  )
-{
-  char flvHeader[] = { 'F', 'L', 'V', 0x01,
-    0x05,                      // video + audio, we finalize later if the value is different
-    0x00, 0x00, 0x00, 0x09,
-    0x00, 0x00, 0x00, 0x00     // first prevTagSize=0
-  };
-
-  unsigned int size = sizeof(flvHeader);
-
-  if (size > len)
-    {
-      *buf = (char *) realloc(*buf, size);
-      if (*buf == 0)
-       {
-         Log(LOGERROR, "Couldn't reallocate memory!");
-         return -1;            // fatal error
-       }
-    }
-  memcpy(*buf, flvHeader, sizeof(flvHeader));
-  return size;
-}
-
-typedef struct WSargs {
-  RTMP *rtmp;
-  char *buf;                   // target pointer, maybe preallocated
-  unsigned int buflen;         // length of buffer if preallocated
-  uint32_t nTimeStamp;         // timestamp of last packet returned
-  uint8_t dataType;            // type of stream for FLV header
-} WSargs;
-
-int
-WriteStream(WSargs *ws)
-{
-  uint32_t prevTagSize = 0;
-  int rtnGetNextMediaPacket = 0, ret = -1;
-  RTMPPacket packet = { 0 };
-
-  rtnGetNextMediaPacket = RTMP_GetNextMediaPacket(ws->rtmp, &packet);
-  while (rtnGetNextMediaPacket)
-    {
-      char *packetBody = packet.m_body;
-      unsigned int nPacketLen = packet.m_nBodySize;
-
-      // set data type
-      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))
-       {
-         ret = 0;
-         break;
-       }
-
-      if (packet.m_packetType == 0x09 && nPacketLen <= 5)
-       {
-         Log(LOGWARNING, "ignoring too small video packet: size: %d",
-             nPacketLen);
-         ret = 0;
-         break;
-       }
-      if (packet.m_packetType == 0x08 && nPacketLen <= 1)
-       {
-         Log(LOGWARNING, "ignoring too small audio packet: size: %d",
-             nPacketLen);
-         ret = 0;
-         break;
-       }
-#ifdef _DEBUG
-      Log(LOGDEBUG, "type: %02X, size: %d, TS: %d ms", packet.m_packetType,
-         nPacketLen, packet.m_nTimeStamp);
-      if (packet.m_packetType == 0x09)
-       Log(LOGDEBUG, "frametype: %02X", (*packetBody & 0xf0));
-#endif
-
-      // calculate packet size and reallocate buffer if necessary
-      unsigned int size = nPacketLen
-       +
-       ((packet.m_packetType == 0x08 || packet.m_packetType == 0x09
-         || packet.m_packetType == 0x12) ? 11 : 0) + (packet.m_packetType !=
-                                                      0x16 ? 4 : 0);
-
-      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)
-         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 = ws->buf, *pend = ptr + size+4;
-
-      // audio (0x08), video (0x09) or metadata (0x12) packets :
-      // construct 11 byte header then add rtmp packet's data
-      if (packet.m_packetType == 0x08 || packet.m_packetType == 0x09
-         || packet.m_packetType == 0x12)
-       {
-         ws->nTimeStamp = packet.m_nTimeStamp;
-         prevTagSize = 11 + nPacketLen;
-
-         *ptr++ = packet.m_packetType;
-         ptr = AMF_EncodeInt24(ptr, pend, nPacketLen);
-         ptr = AMF_EncodeInt24(ptr, pend, ws->nTimeStamp);
-         *ptr = (char) (((ws->nTimeStamp) & 0xFF000000) >> 24);
-         ptr++;
-
-         // stream id
-         ptr = AMF_EncodeInt24(ptr, pend, 0);
-       }
-
-      memcpy(ptr, packetBody, nPacketLen);
-      unsigned int len = nPacketLen;
-
-      // correct tagSize and obtain timestamp if we have an FLV stream
-      if (packet.m_packetType == 0x16)
-       {
-         unsigned int pos = 0;
-
-         while (pos + 11 < nPacketLen)
-           {
-             uint32_t dataSize = AMF_DecodeInt24(packetBody + pos + 1);        // size without header (11) and without prevTagSize (4)
-             ws->nTimeStamp = AMF_DecodeInt24(packetBody + pos + 4);
-             ws->nTimeStamp |= (packetBody[pos + 7] << 24);
-
-             // set data type
-             ws->dataType |= (((*(packetBody+pos) == 0x08)<<2)|(*(packetBody+pos) == 0x09));
-
-             if (pos + 11 + dataSize + 4 > nPacketLen)
-               {
-                 if (pos + 11 + dataSize > nPacketLen)
-                   {
-                     Log(LOGERROR,
-                         "Wrong data size (%lu), stream corrupted, aborting!",
-                         dataSize);
-                     ret = -2;
-                     break;
-                   }
-                 Log(LOGWARNING, "No tagSize found, appending!");
-
-                 // we have to append a last tagSize!
-                 prevTagSize = dataSize + 11;
-                 AMF_EncodeInt32(ptr + pos + 11 + dataSize, pend, prevTagSize);
-                 size += 4;
-                 len += 4;
-               }
-             else
-               {
-                 prevTagSize =
-                   AMF_DecodeInt32(packetBody + pos + 11 + dataSize);
-
-#ifdef _DEBUG
-                 Log(LOGDEBUG,
-                     "FLV Packet: type %02X, dataSize: %lu, tagSize: %lu, timeStamp: %lu ms",
-                     (unsigned char) packetBody[pos], dataSize, prevTagSize,
-                     ws->nTimeStamp);
-#endif
-
-                 if (prevTagSize != (dataSize + 11))
-                   {
-#ifdef _DEBUG
-                     Log(LOGWARNING,
-                         "Tag and data size are not consitent, writing tag size according to dataSize+11: %d",
-                         dataSize + 11);
-#endif
-
-                     prevTagSize = dataSize + 11;
-                     AMF_EncodeInt32(ptr + pos + 11 + dataSize, pend, prevTagSize);
-                   }
-               }
-
-             pos += prevTagSize + 4;   //(11+dataSize+4);
-           }
-       }
-      ptr += len;
-
-      if (packet.m_packetType != 0x16)
-       {                       // FLV tag packets contain their own prevTagSize
-         AMF_EncodeInt32(ptr, pend, prevTagSize);
-         //ptr += 4;
-       }
-
-      // Return 0 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");
-         ret = 0;
-         break;
-       }
-
-      ret = size;
-      break;
-    }
-
-  RTMPPacket_Free(&packet);
-  return ret;                  // no more media packets
-}
-
 TFTYPE
 controlServerThread(void *unused)
 {
@@ -538,7 +333,6 @@ void processTCPrequest(STREAMING_SERVER * server,   // server socket and state (ou
   char *ptr = NULL;            // header pointer
 
   size_t nRead = 0;
-  int doHeader = 1;
 
   char srvhead[] =
     "\r\nServer:HTTP-RTMP Stream Server \r\nContent-Type: Video/MPEG \r\n\r\n";
@@ -547,7 +341,6 @@ void processTCPrequest(STREAMING_SERVER * server,   // server socket and state (ou
 
   RTMP rtmp = { 0 };
   uint32_t dSeek = 0;          // can be used to start from a later point in the stream
-  WSargs ws;
 
   // reset RTMP options to defaults specified upon invokation of streams
   RTMP_REQUEST req;
@@ -728,11 +521,6 @@ void processTCPrequest(STREAMING_SERVER * server,  // server socket and state (ou
 
   // send the packets
   buffer = (char *) calloc(PACKET_SIZE, 1);
-  ws.rtmp = &rtmp;
-  ws.buf = buffer;
-  ws.buflen = PACKET_SIZE;
-  ws.nTimeStamp = dSeek;
-  ws.dataType = 0;
 
   // User defined seek offset
   if (req.dStartOffset > 0)
@@ -746,7 +534,7 @@ void processTCPrequest(STREAMING_SERVER * server,   // server socket and state (ou
 
   if (dSeek != 0)
     {
-      LogPrintf("Starting at TS: %d ms\n", ws.nTimeStamp);
+      LogPrintf("Starting at TS: %d ms\n", dSeek);
     }
 
   Log(LOGDEBUG, "Setting buffer time to: %dms", req.bufferTime);
@@ -761,6 +549,7 @@ void processTCPrequest(STREAMING_SERVER * server,   // server socket and state (ou
 
   rtmp.Link.extras = req.extras;
   rtmp.Link.token = req.token;
+  rtmp.m_read.timestamp = dSeek;
 
   LogPrintf("Connecting ... port: %d, app: %s\n", req.rtmpport, req.app);
   if (!RTMP_Connect(&rtmp, NULL))
@@ -776,46 +565,13 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou
       int nWritten = 0;
       int nRead = 0;
 
-      // write FLV header first
-      nRead = WriteHeader(&buffer, PACKET_SIZE);
-      if (nRead > 0)
-       {
-         ws.buf += nRead;
-         ws.buflen -= nRead;
-         size += nRead;
-       }
-      else
-       {
-         Log(LOGERROR, "%s: Couldn't obtain FLV header, exiting!",
-             __FUNCTION__);
-         goto cleanup;
-       }
-
-      // get the rest of the stream
       do
        {
-         nRead = WriteStream(&ws);
+         nRead = RTMP_Read(&rtmp, buffer, PACKET_SIZE);
 
          if (nRead > 0)
            {
-             if (doHeader)
-               {
-                 if (ws.nTimeStamp > dSeek)
-                   {
-                     doHeader = 0;
-                     nRead += size;
-                     size = 0;
-                     ws.buf = buffer;
-                     ws.buflen = PACKET_SIZE;
-                     buffer[4] = ws.dataType;
-                   }
-                 else
-                   {
-                     ws.buf += nRead;
-                     ws.buflen -= nRead;
-                   }
-               }
-             if (!doHeader && (nWritten = send(sockfd, buffer, nRead, 0)) < 0)
+             if ((nWritten = send(sockfd, buffer, nRead, 0)) < 0)
                {
                  Log(LOGERROR, "%s, sending failed, error: %d", __FUNCTION__,
                      GetSockError());
@@ -831,17 +587,17 @@ void processTCPrequest(STREAMING_SERVER * server, // server socket and state (ou
              if (duration > 0)
                {
                  percent =
-                   ((double) (dSeek + ws.nTimeStamp)) / (duration *
+                   ((double) (dSeek + rtmp.m_read.timestamp)) / (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) (ws.nTimeStamp) / 1000.0, percent);
+                           (double) (rtmp.m_read.timestamp) / 1000.0, percent);
                }
              else
                {
                  LogStatus("\r%.3f KB / %.2f sec", (double) size / 1024.0,
-                           (double) (ws.nTimeStamp) / 1000.0);
+                           (double) (rtmp.m_read.timestamp) / 1000.0);
                }
            }
 #ifdef _DEBUG
@@ -852,7 +608,7 @@ void processTCPrequest(STREAMING_SERVER * server,   // server socket and state (ou
 #endif
 
          // Force clean close if a specified stop offset is reached
-         if (req.dStopOffset && ws.nTimeStamp >= req.dStopOffset)
+         if (req.dStopOffset && rtmp.m_read.timestamp >= req.dStopOffset)
            {
              LogPrintf("\nStop offset has been reached at %.2f seconds\n",
                        (double) req.dStopOffset / 1000.0);