From e503e9789c2b91aa1aff7e308a50adcdacac4c48 Mon Sep 17 00:00:00 2001
From: Thulinma <jaron@vietors.com>
Date: Sun, 21 Aug 2011 20:49:42 +0200
Subject: [PATCH] Attempts at fixing timestamp issues, improved FLV/RTMP
 cooperatibility, fixed several bugs

---
 Connector_RTMP/main.cpp |  8 +++++---
 util/flv_tag.cpp        |  1 +
 util/flv_tag.h          |  6 +++++-
 util/rtmpchunks.cpp     | 40 ++++++++++++++++++++++++++++------------
 util/rtmpchunks.h       |  6 ++++++
 5 files changed, 45 insertions(+), 16 deletions(-)

diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp
index e07b7d29..754a43dc 100644
--- a/Connector_RTMP/main.cpp
+++ b/Connector_RTMP/main.cpp
@@ -121,13 +121,15 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){
             }
             if (viddone && auddone && justdone){
               if (viddata.len != 0){
-                Socket.write(RTMPStream::SendMedia((unsigned char)viddata.data[0], (unsigned char *)viddata.data+11, viddata.len-15, 0));
+                viddata.tagTime(RTMPStream::getNowMS());
+                Socket.write(RTMPStream::SendMedia(viddata));
                 #if DEBUG >= 8
                 fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), viddata.tagTime(), viddata.tagType().c_str());
                 #endif
               }
               if (auddata.len != 0){
-                Socket.write(RTMPStream::SendMedia((unsigned char)auddata.data[0], (unsigned char *)auddata.data+11, auddata.len-15, 0));
+                auddata.tagTime(RTMPStream::getNowMS());
+                Socket.write(RTMPStream::SendMedia(auddata));
                 #if DEBUG >= 8
                 fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), auddata.tagTime(), auddata.tagType().c_str());
                 #endif
@@ -137,7 +139,7 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){
             //not gotten init yet? cancel this tag
             if (viddata.len == 0 || auddata.len == 0){break;}
             //send tag normally
-            Socket.write(RTMPStream::SendMedia((unsigned char)tag.data[0], (unsigned char *)tag.data+11, tag.len-15, tag.tagTime()));
+            Socket.write(RTMPStream::SendMedia(tag));
             #if DEBUG >= 8
             fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), tag.tagTime(), tag.tagType().c_str());
             #endif
diff --git a/util/flv_tag.cpp b/util/flv_tag.cpp
index cc44c24d..526de7d0 100644
--- a/util/flv_tag.cpp
+++ b/util/flv_tag.cpp
@@ -2,6 +2,7 @@
 /// Holds all code for the FLV namespace.
 
 #include "flv_tag.h"
+#include "rtmpchunks.h"
 #include <stdio.h> //for Tag::FileLoader
 #include <unistd.h> //for Tag::FileLoader
 #include <fcntl.h> //for Tag::FileLoader
diff --git a/util/flv_tag.h b/util/flv_tag.h
index 862cdd68..1350c870 100644
--- a/util/flv_tag.h
+++ b/util/flv_tag.h
@@ -4,7 +4,11 @@
 #pragma once
 #include "socket.h"
 #include <string>
-#include "rtmpchunks.h"
+
+//forward declaration of RTMPStream::Chunk to avoid circular dependencies.
+namespace RTMPStream{
+  class Chunk;
+};
 
 /// This namespace holds all FLV-parsing related functionality.
 namespace FLV {
diff --git a/util/rtmpchunks.cpp b/util/rtmpchunks.cpp
index f6f11076..ad0e6c57 100644
--- a/util/rtmpchunks.cpp
+++ b/util/rtmpchunks.cpp
@@ -2,6 +2,7 @@
 /// Holds all code for the RTMPStream namespace.
 
 #include "rtmpchunks.h"
+#include "flv_tag.h"
 #include "crypto.h"
 
 char versionstring[] = "WWW.DDVTECH.COM "; ///< String that is repeated in the RTMP handshake
@@ -41,8 +42,8 @@ std::string RTMPStream::Chunk::Pack(){
   RTMPStream::Chunk prev = lastsend[cs_id];
   unsigned int tmpi;
   unsigned char chtype = 0x00;
-  timestamp -= firsttime;
-  if (timestamp < prev.timestamp){timestamp = prev.timestamp;}
+  //timestamp -= firsttime;
+  //if (timestamp < prev.timestamp){timestamp = prev.timestamp;}
   if ((prev.msg_type_id > 0) && (prev.cs_id == cs_id)){
     if (msg_stream_id == prev.msg_stream_id){
       chtype = 0x40;//do not send msg_stream_id
@@ -77,15 +78,15 @@ std::string RTMPStream::Chunk::Pack(){
       tmpi = timestamp - prev.timestamp;
     }
     if (tmpi >= 0x00ffffff){ntime = tmpi; tmpi = 0x00ffffff;}
-    output += (unsigned char)(tmpi / (256*256));
-    output += (unsigned char)(tmpi / 256);
-    output += (unsigned char)(tmpi % 256);
+    output += (unsigned char)((tmpi >> 16) & 0xff);
+    output += (unsigned char)((tmpi >> 8) & 0xff);
+    output += (unsigned char)(tmpi & 0xff);
     if (chtype != 0x80){
       //len
       tmpi = len;
-      output += (unsigned char)(tmpi / (256*256));
-      output += (unsigned char)(tmpi / 256);
-      output += (unsigned char)(tmpi % 256);
+      output += (unsigned char)((tmpi >> 16) & 0xff);
+      output += (unsigned char)((tmpi >> 8) & 0xff);
+      output += (unsigned char)(tmpi & 0xff);
       //msg type id
       output += (unsigned char)msg_type_id;
       if (chtype != 0x40){
@@ -99,10 +100,10 @@ std::string RTMPStream::Chunk::Pack(){
   }
   //support for 0x00ffffff timestamps
   if (ntime){
-    output += (unsigned char)(ntime % 256);
-    output += (unsigned char)(ntime / 256);
-    output += (unsigned char)(ntime / (256*256));
-    output += (unsigned char)(ntime / (256*256*256));
+    output += (unsigned char)(ntime & 0xff);
+    output += (unsigned char)((ntime >> 8) & 0xff);
+    output += (unsigned char)((ntime >> 16) & 0xff);
+    output += (unsigned char)((ntime >> 24) & 0xff);
   }
   len_left = 0;
   while (len_left < len){
@@ -174,6 +175,21 @@ std::string RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * dat
   return ch.Pack();
 }//SendMedia
 
+/// Packs up a chunk with media contents.
+/// \param tag FLV::Tag with media to send.
+std::string RTMPStream::SendMedia(FLV::Tag & tag){
+  RTMPStream::Chunk ch;
+  ch.cs_id = ((unsigned char)tag.data[0]);
+  ch.timestamp = tag.tagTime();
+  ch.len = tag.len-15;
+  ch.real_len = tag.len-15;
+  ch.len_left = 0;
+  ch.msg_type_id = (unsigned char)tag.data[0];
+  ch.msg_stream_id = 1;
+  ch.data.append(tag.data+11, (size_t)(tag.len-15));
+  return ch.Pack();
+}//SendMedia
+
 /// Packs up a chunk for a control message with 1 argument.
 std::string RTMPStream::SendCTL(unsigned char type, unsigned int data){
   RTMPStream::Chunk ch;
diff --git a/util/rtmpchunks.h b/util/rtmpchunks.h
index b114f440..ff4eee4a 100644
--- a/util/rtmpchunks.h
+++ b/util/rtmpchunks.h
@@ -9,6 +9,11 @@
 #include <string>
 #include <arpa/inet.h>
 
+//forward declaration of FLV::Tag to avoid circular dependencies.
+namespace FLV{
+  class Tag;
+};
+
 /// Contains all functions and classes needed for RTMP connections.
 namespace RTMPStream{
 
@@ -51,6 +56,7 @@ namespace RTMPStream{
 
   std::string SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data);
   std::string SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts);
+  std::string SendMedia(FLV::Tag & tag);
   std::string SendCTL(unsigned char type, unsigned int data);
   std::string SendCTL(unsigned char type, unsigned int data, unsigned char data2);
   std::string SendUSR(unsigned char type, unsigned int data);