From df6ea8eb0dfa32ab2c2f28161f2803f51a512d6c Mon Sep 17 00:00:00 2001
From: Erik Zandvliet <erik.zandvliet@ddvtech.com>
Date: Tue, 23 Oct 2012 14:46:40 +0200
Subject: [PATCH] Working MP4 intro

---
 src/Makefile.am          |   3 +-
 src/conn_http.cpp        |   9 +-
 src/conn_http_smooth.cpp | 288 ++++++++++++++++-----------------------
 3 files changed, 127 insertions(+), 173 deletions(-)

diff --git a/src/Makefile.am b/src/Makefile.am
index 196c5ddf..fc0ad10f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -8,7 +8,7 @@ EXTRA_DIST=server.html server.html.h embed.js.h
 AM_CPPFLAGS = $(global_CFLAGS) $(MIST_CFLAGS)
 LDADD = $(MIST_LIBS)
 SUBDIRS=converters analysers
-bin_PROGRAMS=MistBuffer MistController MistConnRAW MistConnRTMP MistConnHTTP MistConnHTTPProgressive MistConnHTTPDynamic MistPlayer
+bin_PROGRAMS=MistBuffer MistController MistConnRAW MistConnRTMP MistConnHTTP MistConnHTTPProgressive MistConnHTTPDynamic MistConnHTTPSmooth MistPlayer
 MistBuffer_SOURCES=buffer.cpp buffer_user.h buffer_user.cpp buffer_stream.h buffer_stream.cpp tinythread.cpp tinythread.h ../VERSION
 MistBuffer_LDADD=$(MIST_LIBS) -lpthread
 MistController_SOURCES=controller.cpp ../VERSION ./server.html.h
@@ -18,6 +18,7 @@ MistConnHTTP_SOURCES=conn_http.cpp tinythread.cpp tinythread.h ../VERSION ./embe
 MistConnHTTP_LDADD=$(MIST_LIBS) -lpthread
 MistConnHTTPProgressive_SOURCES=conn_http_progressive.cpp ../VERSION
 MistConnHTTPDynamic_SOURCES=conn_http_dynamic.cpp ../VERSION
+MistConnHTTPSmooth_SOURCES=conn_http_smooth.cpp ../VERSION
 MistPlayer_SOURCES=player.cpp
 MistPlayer_LDADD=$(MIST_LIBS)
 
diff --git a/src/conn_http.cpp b/src/conn_http.cpp
index c56daa5a..ce00bdf1 100644
--- a/src/conn_http.cpp
+++ b/src/conn_http.cpp
@@ -318,6 +318,12 @@ namespace Connector_HTTP{
       H.SetVar("stream", streamname);
       return "dynamic";
     }
+    if (url.find("/smooth/") != std::string::npos ) {
+      std::string streamname = url.substr(8,url.find("/",8)-8);
+      Util::Stream::sanitizeName(streamname);
+      H.SetVar("stream", streamname);
+      return "smooth";
+    }
     if (url.length() > 4){
       std::string ext = url.substr(url.length() - 4, 4);
       if (ext == ".flv" || ext == ".mp3"){
@@ -404,7 +410,8 @@ int main(int argc, char ** argv){
   //start progressive and dynamic handlers from the same folder as this application
   Util::Procs::Start("progressive", Util::getMyPath() + "MistConnHTTPProgressive -n");
   Util::Procs::Start("dynamic", Util::getMyPath() + "MistConnHTTPDynamic -n");
-  
+  Util::Procs::Start("smooth", Util::getMyPath() + "MistConnHTTPSmooth -n");
+
   while (server_socket.connected() && conf.is_active){
     Socket::Connection S = server_socket.accept();
     if (S.connected()){//check if the new connection is valid
diff --git a/src/conn_http_smooth.cpp b/src/conn_http_smooth.cpp
index c92d15e8..2536da5f 100644
--- a/src/conn_http_smooth.cpp
+++ b/src/conn_http_smooth.cpp
@@ -25,136 +25,55 @@
 
 /// Holds everything unique to HTTP Dynamic Connector.
 namespace Connector_HTTP{
-
-  std::string GenerateBootstrap(std::string & MovieId, JSON::Value & metadata, int fragnum, int starttime, int endtime){
-    std::string empty;
-
-    MP4::ASRT asrt;
-    if (starttime == 0){
-      asrt.setUpdate(false);
-    }else{
-      asrt.setUpdate(true);
-    }
-    asrt.setVersion(1);
-    asrt.setQualityEntry(empty, 0);
-    if (!metadata.isMember("keytime") || metadata["keytime"].size() == 0){
-      asrt.setSegmentRun(1, 20000, 0);
-    }else{
-      asrt.setSegmentRun(1, metadata["keytime"].size(), 0);
-    }
-
-
-    MP4::AFRT afrt;
-    if (starttime == 0){
-      afrt.setUpdate(false);
-    }else{
-      afrt.setUpdate(true);
-    }
-    afrt.setVersion(1);
-    afrt.setTimeScale(1000);
-    afrt.setQualityEntry(empty, 0);
-    MP4::afrt_runtable afrtrun;
-    if (!metadata.isMember("keytime") || metadata["keytime"].size() == 0){
-      afrtrun.firstFragment = 1;
-      afrtrun.firstTimestamp = 0;
-      if (!metadata.isMember("video") || !metadata["video"].isMember("keyms") || metadata["video"]["keyms"].asInt() == 0){
-        afrtrun.duration = 2000;
-      }else{
-        afrtrun.duration = metadata["video"]["keyms"].asInt();
-      }
-      afrt.setFragmentRun(afrtrun, 0);
-    }else{
-      for (int i = 0; i < metadata["keytime"].size(); i++){
-        afrtrun.firstFragment = i+1;
-        afrtrun.firstTimestamp = metadata["keytime"][i].asInt();
-        if (i+1 < metadata["keytime"].size()){
-          afrtrun.duration = metadata["keytime"][i+1].asInt() - metadata["keytime"][i].asInt();
-        }else{
-          if (metadata["lastms"].asInt()){
-            afrtrun.duration = metadata["lastms"].asInt() - metadata["keytime"][i].asInt();
-          }else{
-            afrtrun.duration = 3000;//guess 3 seconds if unknown
-          }
-        }
-        afrt.setFragmentRun(afrtrun, i);
-      }
-    }
-    
-    MP4::ABST abst;
-    abst.setVersion(1);
-    abst.setBootstrapinfoVersion(1);
-    abst.setProfile(0);
-    if (starttime == 0){
-      abst.setUpdate(false);
-    }else{
-      abst.setUpdate(true);
-    }
-    abst.setTimeScale(1000);
-    if (metadata.isMember("length") && metadata["length"].asInt() > 0){
-      abst.setLive(false);
-      if (metadata["lastms"].asInt()){
-        abst.setCurrentMediaTime(metadata["lastms"].asInt());
-      }else{
-        abst.setCurrentMediaTime(1000*metadata["length"].asInt());
-      }
-    }else{
-      abst.setLive(true);
-      abst.setCurrentMediaTime(0xFFFFFFFF);
-    }
-    abst.setSmpteTimeCodeOffset(0);
-    abst.setMovieIdentifier(MovieId);
-    abst.setServerEntry(empty, 0);
-    abst.setQualityEntry(empty, 0);
-    abst.setDrmData(empty);
-    abst.setMetaData(empty);
-    abst.setSegmentRunTable(asrt, 0);
-    abst.setFragmentRunTable(afrt, 0);
-
-    #if DEBUG >= 8
-    std::cout << "Sending bootstrap:" << std::endl << abst.toPrettyString(0) << std::endl;
-    #endif
-    return std::string((char*)abst.asBox(), (int)abst.boxedSize());
-  }
-  
-
-  /// Returns a F4M-format manifest file
+  /// Returns a Smooth-format manifest file
   std::string BuildManifest(std::string & MovieId, JSON::Value & metadata){
-    std::string Result;
-    if (metadata.isMember("length") && metadata["length"].asInt() > 0){
-      Result="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-      "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n"
-      "<id>" + MovieId + "</id>\n"
-      "<width>" + metadata["video"]["width"].asString() + "</width>\n"
-      "<height>" + metadata["video"]["height"].asString() + "</height>\n"
-      "<duration>" + metadata["length"].asString() + ".000</duration>\n"
-      "<mimeType>video/mp4</mimeType>\n"
-      "<streamType>recorded</streamType>\n"
-      "<deliveryType>streaming</deliveryType>\n"
-      "<bootstrapInfo profile=\"named\" id=\"bootstrap1\">" + Base64::encode(GenerateBootstrap(MovieId, metadata, 1, 0, 0)) + "</bootstrapInfo>\n"
-      "<media streamId=\"1\" bootstrapInfoId=\"bootstrap1\" url=\"" + MovieId + "/\">\n"
-      "<metadata>AgAKb25NZXRhRGF0YQgAAAAAAAl0cmFja2luZm8KAAAAAgMACXRpbWVzY2FsZQBA+GoAAAAAAAAGbGVuZ3RoAEGMcHoQAAAAAAhsYW5ndWFnZQIAA2VuZwARc2FtcGxlZGVzY3JpcHRpb24KAAAAAQMACnNhbXBsZXR5cGUCAARhdmMxAAAJAAAJAwAJdGltZXNjYWxlAEDncAAAAAAAAAZsZW5ndGgAQXtNvTAAAAAACGxhbmd1YWdlAgADZW5nABFzYW1wbGVkZXNjcmlwdGlvbgoAAAABAwAKc2FtcGxldHlwZQIABG1wNGEAAAkAAAkADWF1ZGlvY2hhbm5lbHMAQAAAAAAAAAAAD2F1ZGlvc2FtcGxlcmF0ZQBA53AAAAAAAAAOdmlkZW9mcmFtZXJhdGUAQDf/gi5SciUABmFhY2FvdABAAAAAAAAAAAAIYXZjbGV2ZWwAQD8AAAAAAAAACmF2Y3Byb2ZpbGUAQFNAAAAAAAAADGF1ZGlvY29kZWNpZAIABG1wNGEADHZpZGVvY29kZWNpZAIABGF2YzEABXdpZHRoAECQ4AAAAAAAAAZoZWlnaHQAQIMAAAAAAAAACmZyYW1lV2lkdGgAQJDgAAAAAAAAC2ZyYW1lSGVpZ2h0AECDAAAAAAAAAAxkaXNwbGF5V2lkdGgAQJDgAAAAAAAADWRpc3BsYXlIZWlnaHQAQIMAAAAAAAAADG1vb3Zwb3NpdGlvbgBBmxq2uAAAAAAIZHVyYXRpb24AQIKjqW3oyhIAAAk=</metadata>\n"
-      "</media>\n"
-      "</manifest>\n";
-    }else{
-      Result="<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
-      "<manifest xmlns=\"http://ns.adobe.com/f4m/1.0\">\n"
-      "<id>" + MovieId + "</id>\n"
-      "<mimeType>video/mp4</mimeType>\n"
-      "<streamType>live</streamType>\n"
-      "<deliveryType>streaming</deliveryType>\n"
-      "<bootstrapInfo profile=\"named\" id=\"bootstrap1\">" + Base64::encode(GenerateBootstrap(MovieId, metadata, 1, 0, 0)) + "</bootstrapInfo>\n"
-      "<media streamId=\"1\" bootstrapInfoId=\"bootstrap1\" url=\"" + MovieId + "/\"></media>\n"
-      "</manifest>\n";
+    std::stringstream Result;
+    Result << "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n";
+    Result << "<SmoothStreamingMedia MajorVersion=\"2\" MinorVersion=\"0\" TimeScale=\"1000\" Duration=\"" << metadata["lastms"].asInt() << "\">\n";
+    if( metadata.isMember( "audio" ) ) {
+      Result << "  <StreamIndex Type=\"audio\" QualityLevels=\"1\" TimeScale=\"1000\" Name=\"audio\" Chunks=\"" << metadata["keytime"].size() << "\" Url=\"Q({bitrate})/A({start time})\">\n";
+      Result << "    <QualityLevel Index=\"0\" Bitrate=\"" << metadata["audio"]["bps"].asInt()*8 << "\" CodecPrivateData=\"";
+      Result << std::hex;
+      for( int i = 0; i < metadata["audio"]["init"].asString().size(); i++ ) {
+        Result << (int)metadata["audio"]["init"].asString()[i];
+      }
+      Result << std::dec;
+      Result << "\" SamplingRate=\"" << metadata["audio"]["rate"].asInt() << "\" Channels=\"2\" BitsPerSample=\"16\" PacketSize=\"4\" AudioTag=\"255\" FourCC=\"AACL\" />\n";
+      for( int i = 0; i < metadata["keytime"].size(); i++ ) {
+        Result << "      <c ";
+        if( i == 0 ) { Result << "t=\"0\" "; }
+        Result << "d=\"" << metadata["keytime"][i].asInt() << "\"/>\n";
+      }
+      Result << "   </StreamIndex>\n";
     }
+    if( metadata.isMember( "video" ) ) {
+      Result << "  <StreamIndex Type=\"video\" QualityLevels=\"1\" TimeScale=\"1000\" Name=\"video\" Chunks=\"" << metadata["keytime"].size() << "\" Url=\"Q({bitrate})/V({start time})\" MaxWidth=\"" << metadata["video"]["width"].asInt() << "\" MaxHeight=\"" << metadata["video"]["height"].asInt() << "\" DisplayWidth=\"" << metadata["video"]["width"].asInt() << "\" DisplayHeight=\"" << metadata["video"]["height"].asInt() << "\">\n";
+      Result << "    <QualityLevel Index=\"0\" Bitrate=\"" << metadata["video"]["bps"].asInt()*8 << "\" CodecPrivateData=\"";
+      Result << std::hex;
+      for( int i = 0; i < metadata["video"]["init"].asString().size(); i++ ) {
+        Result << (int)metadata["video"]["init"].asString()[i];
+      }
+      Result << std::dec;
+      Result << "\" MaxWidth=\"" << metadata["video"]["width"].asInt() << "\" MaxHeight=\"" << metadata["video"]["height"].asInt() << "\" FourCC=\"AVC1\"/>\n";
+      for( int i = 0; i < metadata["keytime"].size(); i++ ) {
+        Result << "      <c ";
+        if( i == 0 ) { Result << "t=\"0\" "; }
+        Result << "d=\"" << metadata["keytime"][i].asInt() << "\"/>\n";
+      }
+      Result << "   </StreamIndex>\n";
+    }
+    Result << "</SmoothStreamingMedia>\n";
+      
     #if DEBUG >= 8
     std::cerr << "Sending this manifest:" << std::endl << Result << std::endl;
     #endif
-    return Result;
+    return Result.str();
   }//BuildManifest
 
   /// Main function for Connector_HTTP_Dynamic
   int Connector_HTTP_Dynamic(Socket::Connection conn){
     std::deque<std::string> FlashBuf;
+    std::vector<int> Timestamps;
     int FlashBufSize = 0;
     long long int FlashBufTime = 0;
     FLV::Tag tmp;//temporary tag
@@ -170,10 +89,14 @@ namespace Connector_HTTP{
     std::string streamname;
     std::string recBuffer = "";
 
+    bool wantsVideo = false;
+    bool wantsAudio = false;
+    
     std::string Quality;
     int Segment = -1;
     int ReqFragment = -1;
     int temp;
+    std::string tempStr;
     int Flash_RequestPending = 0;
     unsigned int lastStats = 0;
     conn.setBlocking(false);//do not block on conn.spool() when no data is available
@@ -195,8 +118,8 @@ namespace Connector_HTTP{
           std::cout << "Received request: " << HTTP_R.getUrl() << std::endl;
           #endif
           conn.setHost(HTTP_R.GetHeader("X-Origin"));
-          if (HTTP_R.url.find("f4m") == std::string::npos){
-            streamname = HTTP_R.url.substr(1,HTTP_R.url.find("/",1)-1);
+          if (HTTP_R.url.find("Manifest") == std::string::npos){
+            streamname = HTTP_R.url.substr(8,HTTP_R.url.find("/",8)-8);
             if (!ss){
               ss = Util::Stream::getStream(streamname);
               if (!ss.connected()){
@@ -205,7 +128,7 @@ namespace Connector_HTTP{
                 #endif
                 ss.close();
                 HTTP_S.Clean();
-                HTTP_S.SetBody("No such stream is available on the system. Please try again.\n");
+                HTTP_S.SetBody("No such stream " + streamname + " is available on the system. Please try again.\n");
                 conn.SendNow(HTTP_S.BuildResponse("404", "Not found"));
                 ready4data = false;
                 continue;
@@ -213,21 +136,22 @@ namespace Connector_HTTP{
               ss.setBlocking(false);
               inited = true;
             }
-            Quality = HTTP_R.url.substr( HTTP_R.url.find("/",1)+1 );
-            Quality = Quality.substr(0, Quality.find("Seg"));
-            temp = HTTP_R.url.find("Seg") + 3;
-            Segment = atoi( HTTP_R.url.substr(temp,HTTP_R.url.find("-",temp)-temp).c_str());
-            temp = HTTP_R.url.find("Frag") + 4;
-            ReqFragment = atoi( HTTP_R.url.substr(temp).c_str() );
+            Quality = HTTP_R.url.substr( HTTP_R.url.find("/Q(",8)+3 );
+            Quality = Quality.substr(0, Quality.find(")"));
+            tempStr = HTTP_R.url.substr( HTTP_R.url.find(")/") + 2 );
+            if( tempStr[0] == 'A' ) { wantsAudio = true; }
+            if( tempStr[0] == 'V' ) { wantsVideo = true; }
+            tempStr = tempStr.find("(") + 1;
+            ReqFragment = atoi( tempStr.substr(0,tempStr.find(")")).c_str() );
             #if DEBUG >= 4
-            printf( "Quality: %s, Seg %d Frag %d\n", Quality.c_str(), Segment, ReqFragment);
+            printf( "Quality: %s, Frag %d\n", Quality.c_str(), ReqFragment);
             #endif
             std::stringstream sstream;
-            sstream << "f " << ReqFragment << "\no \n";
+            sstream << "s " << ReqFragment << "\no \n";
             ss.SendNow(sstream.str().c_str());
             Flash_RequestPending++;
           }else{
-            streamname = HTTP_R.url.substr(1,HTTP_R.url.find("/",1)-1);
+            streamname = HTTP_R.url.substr(8,HTTP_R.url.find("/",8)-8);
             if (!Strm.metadata.isNull()){
               HTTP_S.Clean();
               HTTP_S.SetHeader("Content-Type","text/xml");
@@ -264,7 +188,7 @@ namespace Connector_HTTP{
             #endif
             ss.close();
             HTTP_S.Clean();
-            HTTP_S.SetBody("No such stream is available on the system. Please try again.\n");
+            HTTP_S.SetBody("No such stream " + streamname + " is available on the system. Please try again.\n");
             conn.SendNow(HTTP_S.BuildResponse("404", "Not found"));
             ready4data = false;
             continue;
@@ -278,7 +202,7 @@ namespace Connector_HTTP{
         unsigned int now = Util::epoch();
         if (now != lastStats){
           lastStats = now;
-          ss.SendNow(conn.getStats("HTTP_Dynamic").c_str());
+          ss.SendNow(conn.getStats("HTTP_Smooth").c_str());
         }
         if (ss.spool()){
           while (Strm.parsePacket(ss.Received())){
@@ -306,6 +230,9 @@ namespace Connector_HTTP{
               pending_manifest = false;
             }
             if (!receive_marks && Strm.metadata.isMember("length")){receive_marks = true;}
+            if ( Strm.lastType() == DTSC::PAUSEMARK ) {
+              Timestamps.push_back( Strm.getPacket(0)["time"].asInt() );
+            }
             if ((Strm.getPacket(0).isMember("keyframe") && !receive_marks) || Strm.lastType() == DTSC::PAUSEMARK){
               #if DEBUG >= 4
               fprintf(stderr, "Received a %s fragment of %i bytes.\n", Strm.getPacket(0)["datatype"].asString().c_str(), FlashBufSize);
@@ -319,21 +246,51 @@ namespace Connector_HTTP{
                 HTTP_S.Clean();
                 HTTP_S.SetHeader("Content-Type", "video/mp4");
                 HTTP_S.SetBody("");
-                HTTP_S.SetHeader("Content-Length", FlashBufSize+8);//32+33+btstrp.size());
+                
+                MP4::MFHD mfhd_box;
+                mfhd_box.setSequenceNumber( 1 );
+                
+                MP4::TFHD tfhd_box;
+                tfhd_box.setFlags( MP4::tfhdSampleFlag );
+                tfhd_box.setTrackID( 1 );
+                tfhd_box.setDefaultSampleFlags( MP4::noIPicture | MP4::noDisposable | MP4::noKeySample );
+                
+                MP4::TRUN trun_box;
+                //maybe reinsert dataOffset
+                trun_box.setFlags( MP4::trunfirstSampleFlags | MP4::trunsampleDuration | MP4::trunsampleSize );
+                trun_box.setFirstSampleFlags( MP4::isIPicture | MP4::noDisposable | MP4::isKeySample );
+                std::deque< std::string >::iterator FlashBufIter = FlashBuf.begin();
+                for( int i = 0; i < FlashBuf.size(); i++ ) {
+                  MP4::trunSampleInformation trunSample;
+                  trunSample.sampleSize = (*FlashBufIter).size();
+                  trunSample.sampleDuration = Timestamps[i+1]-Timestamps[i];
+                  trun_box.setSampleInformation( trunSample, i );
+                  FlashBufIter ++;
+                }
+                
+                MP4::Box sdtp_box;
+                sdtp_box.setType( "sdtp" );
+                sdtp_box.setInt32( 0, 0 );
+                sdtp_box.setInt8( 0x24, 4 );
+                for( int i = 1; i < FlashBuf.size(); i++ ) {
+                  sdtp_box.setInt8( 0x14, i+4 );
+                }
+                
+                MP4::TRAF traf_box;
+                traf_box.setContent( tfhd_box, 0 );
+                traf_box.setContent( trun_box, 1 );
+                traf_box.setContent( sdtp_box, 2 );
+                
+                MP4::MOOF moof_box;
+                moof_box.setContent( mfhd_box, 0 );
+                moof_box.setContent( traf_box, 1 );
+                
+                HTTP_S.SetHeader("Content-Length", FlashBufSize+8+moof_box.boxedSize());//32+33+btstrp.size());
                 conn.SendNow(HTTP_S.BuildResponse("200", "OK"));
-                //conn.SendNow("\x00\x00\x00\x21" "afra\x00\x00\x00\x00\x00\x00\x00\x03\xE8\x00\x00\x00\x01", 21);
-                //unsigned long tmptime = htonl(FlashBufTime << 32);
-                //conn.SendNow((char*)&tmptime, 4);
-                //tmptime = htonl(FlashBufTime & 0xFFFFFFFF);
-                //conn.SendNow((char*)&tmptime, 4);
-                //tmptime = htonl(65);
-                //conn.SendNow((char*)&tmptime, 4);
+                
 
-                //conn.SendNow(btstrp);
-
-                //conn.SendNow("\x00\x00\x00\x18moof\x00\x00\x00\x10mfhd\x00\x00\x00\x00", 20);
-                //unsigned long fragno = htonl(ReqFragment);
-                //conn.SendNow((char*)&fragno, 4);
+                conn.SendNow( moof_box.asBox(), moof_box.boxedSize() );
+                
                 unsigned long size = htonl(FlashBufSize+8);
                 conn.SendNow((char*)&size, 4);
                 conn.SendNow("mdat", 4);
@@ -349,26 +306,15 @@ namespace Connector_HTTP{
               FlashBuf.clear();
               FlashBufSize = 0;
             }
-            if (Strm.lastType() == DTSC::VIDEO || Strm.lastType() == DTSC::AUDIO){
-              if (FlashBufSize == 0){
-                //fill buffer with init data, if needed.
-                if (Strm.metadata.isMember("audio") && Strm.metadata["audio"].isMember("init")){
-                  tmp.DTSCAudioInit(Strm);
-                  tmp.tagTime(Strm.getPacket(0)["time"].asInt());
-                  FlashBuf.push_back(std::string(tmp.data, tmp.len));
-                  FlashBufSize += tmp.len;
-                }
-                if (Strm.metadata.isMember("video") && Strm.metadata["video"].isMember("init")){
-                  tmp.DTSCVideoInit(Strm);
-                  tmp.tagTime(Strm.getPacket(0)["time"].asInt());
-                  FlashBuf.push_back(std::string(tmp.data, tmp.len));
-                  FlashBufSize += tmp.len;
-                }
-                FlashBufTime = Strm.getPacket(0)["time"].asInt();
-              }
-              tmp.DTSCLoader(Strm);
-              FlashBuf.push_back(std::string(tmp.data, tmp.len));
-              FlashBufSize += tmp.len;
+            if ( wantsVideo && Strm.lastType() == DTSC::VIDEO ) {
+              FlashBuf.push_back( Strm.lastData() );
+              FlashBufSize += Strm.lastData().size();
+              Timestamps.push_back( Strm.getPacket(0)["time"].asInt() );
+            }
+            if ( wantsAudio && Strm.lastType() == DTSC::AUDIO ) {
+              FlashBuf.push_back( Strm.lastData() );
+              FlashBufSize += Strm.lastData().size();
+              Timestamps.push_back( Strm.getPacket(0)["time"].asInt() );
             }
           }
           if (pending_manifest && !Strm.metadata.isNull()){
@@ -389,7 +335,7 @@ namespace Connector_HTTP{
       }
     }
     conn.close();
-    ss.SendNow(conn.getStats("HTTP_Dynamic").c_str());
+    ss.SendNow(conn.getStats("HTTP_Smooth").c_str());
     ss.close();
     #if DEBUG >= 1
     if (FLV::Parse_Error){fprintf(stderr, "FLV Parser Error: %s\n", FLV::Error_Str.c_str());}
@@ -405,15 +351,15 @@ namespace Connector_HTTP{
     }
     #endif
     return 0;
-  }//Connector_HTTP_Dynamic main function
+  }//Connector_HTTP_Smooth main function
 
-};//Connector_HTTP_Dynamic namespace
+};//Connector_HTTP_Smooth namespace
 
 int main(int argc, char ** argv){
   Util::Config conf(argv[0], PACKAGE_VERSION);
   conf.addConnectorOptions(1935);
   conf.parseArgs(argc, argv);
-  Socket::Server server_socket = Socket::Server("/tmp/mist/http_dynamic");
+  Socket::Server server_socket = Socket::Server("/tmp/mist/http_smooth");
   if (!server_socket.connected()){return 1;}
   conf.activate();