From 2a8ce23db0173ad090f36986bc37b57cb03bd3cd Mon Sep 17 00:00:00 2001 From: Thulinma Date: Tue, 17 Apr 2012 21:33:43 +0200 Subject: [PATCH 1/4] A few bugfixes and improvements in the FLV2DTSC code. Also, moved conversion logic to flv_tag.cpp/h instead of keeping it inside the conversion tool itself. --- tools/FLV2DTSC/main.cpp | 201 +--------------------------------------- util/dtsc.cpp | 14 ++- util/dtsc.h | 1 + util/flv_tag.cpp | 175 ++++++++++++++++++++++++++++++++++ util/flv_tag.h | 5 + 5 files changed, 198 insertions(+), 198 deletions(-) diff --git a/tools/FLV2DTSC/main.cpp b/tools/FLV2DTSC/main.cpp index 1d7156e0..6ae6516c 100644 --- a/tools/FLV2DTSC/main.cpp +++ b/tools/FLV2DTSC/main.cpp @@ -14,62 +14,12 @@ #include "../../util/dtsc.h" //DTSC support #include "../../util/amf.h" //AMF support -// String onMetaData -// ECMA Array -// Bool hasVideo 1 -// Number videocodecid 4 (2 = H263, 4 = VP6, 7 = H264) -// Number width 320 -// Number height 240 -// Number framerate 23.976 (/ 1000) -// Number videodatarate 500.349 (kbps) -// Bool hasAudio 1 -// Bool stereo 1 -// Number audiodelay 0 -// Number audiosamplerate 11025 -// Number audiosamplesize 16 -// Number audiocodecid 2 (2 = MP3, 10 = AAC) -// Number audiodatarate 64.3269 (kbps) - - /// Holds all code that converts filetypes to DTSC. namespace Converters{ - /// Inserts std::string type metadata into the passed DTMI object. - /// \arg meta The DTMI object to put the metadata into. - /// \arg cat Metadata category to insert into. - /// \arg elem Element name to put into the category. - /// \arg val Value to put into the element name. - void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, std::string val){ - if (meta.getContentP(cat) == 0){meta.addContent(DTSC::DTMI(cat));} - meta.getContentP(cat)->addContent(DTSC::DTMI(elem, val)); - std::cerr << "Metadata " << cat << "." << elem << " = " << val << std::endl; - } - - /// Inserts uint64_t type metadata into the passed DTMI object. - /// \arg meta The DTMI object to put the metadata into. - /// \arg cat Metadata category to insert into. - /// \arg elem Element name to put into the category. - /// \arg val Value to put into the element name. - void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, uint64_t val){ - if (meta.getContentP(cat) == 0){meta.addContent(DTSC::DTMI(cat));} - meta.getContentP(cat)->addContent(DTSC::DTMI(elem, val)); - std::cerr << "Metadata " << cat << "." << elem << " = " << val << std::endl; - } - - /// Returns true if the named category and elementname are available in the metadata. - /// \arg meta The DTMI object to check. - /// \arg cat Metadata category to check. - /// \arg elem Element name to check. - bool Meta_Has(DTSC::DTMI & meta, std::string cat, std::string elem){ - if (meta.getContentP(cat) == 0){return false;} - if (meta.getContentP(cat)->getContentP(elem) == 0){return false;} - return true; - } - /// Reads FLV from STDIN, outputs DTSC to STDOUT. int FLV2DTSC() { FLV::Tag FLV_in; // Temporary storage for incoming FLV data. - AMF::Object meta_in; // Temporary storage for incoming metadata. DTSC::DTMI meta_out; // Storage for outgoing DTMI header data. DTSC::DTMI pack_out; // Storage for outgoing DTMI data. std::stringstream prebuffer; // Temporary buffer before sending real data @@ -78,6 +28,8 @@ namespace Converters{ while (!feof(stdin)){ if (FLV_in.FileLoader(stdin)){ + pack_out = FLV_in.toDTSC(meta_out); + if (pack_out.isEmpty()){continue;} if (!sending){ counter++; if (counter > 10){ @@ -89,152 +41,9 @@ namespace Converters{ prebuffer.str(""); std::cerr << "Buffer done, starting real-time output..." << std::endl; } - } - if (FLV_in.data[0] == 0x12){ - meta_in = AMF::parse((unsigned char*)FLV_in.data+11, FLV_in.len-15); - if (meta_in.getContentP(0) && (meta_in.getContentP(0)->StrValue() == "onMetaData") && meta_in.getContentP(1)){ - AMF::Object * tmp = meta_in.getContentP(1); - if (tmp->getContentP("videocodecid")){ - switch ((unsigned int)tmp->getContentP("videocodecid")->NumValue()){ - case 2: Meta_Put(meta_out, "video", "codec", "H263"); break; - case 4: Meta_Put(meta_out, "video", "codec", "VP6"); break; - case 7: Meta_Put(meta_out, "video", "codec", "H264"); break; - default: Meta_Put(meta_out, "video", "codec", "?"); break; - } - } - if (tmp->getContentP("audiocodecid")){ - switch ((unsigned int)tmp->getContentP("audiocodecid")->NumValue()){ - case 2: Meta_Put(meta_out, "audio", "codec", "MP3"); break; - case 10: Meta_Put(meta_out, "audio", "codec", "AAC"); break; - default: Meta_Put(meta_out, "audio", "codec", "?"); break; - } - } - if (tmp->getContentP("width")){ - Meta_Put(meta_out, "video", "width", tmp->getContentP("width")->NumValue()); - } - if (tmp->getContentP("height")){ - Meta_Put(meta_out, "video", "height", tmp->getContentP("height")->NumValue()); - } - if (tmp->getContentP("framerate")){ - Meta_Put(meta_out, "video", "fpks", tmp->getContentP("framerate")->NumValue()*1000); - } - if (tmp->getContentP("videodatarate")){ - Meta_Put(meta_out, "video", "bps", (tmp->getContentP("videodatarate")->NumValue()*1024)/8); - } - if (tmp->getContentP("audiodatarate")){ - Meta_Put(meta_out, "audio", "bps", (tmp->getContentP("audiodatarate")->NumValue()*1024)/8); - } - if (tmp->getContentP("audiosamplerate")){ - Meta_Put(meta_out, "audio", "rate", tmp->getContentP("audiosamplerate")->NumValue()); - } - if (tmp->getContentP("audiosamplesize")){ - Meta_Put(meta_out, "audio", "size", tmp->getContentP("audiosamplesize")->NumValue()); - } - if (tmp->getContentP("stereo")){ - if (tmp->getContentP("stereo")->NumValue() == 1){ - Meta_Put(meta_out, "audio", "channels", 2); - }else{ - Meta_Put(meta_out, "audio", "channels", 1); - } - } - } - } - if (FLV_in.data[0] == 0x08){ - char audiodata = FLV_in.data[11]; - if (FLV_in.needsInitData() && FLV_in.isInitData()){ - if ((audiodata & 0xF0) == 0xA0){ - Meta_Put(meta_out, "audio", "init", std::string((char*)FLV_in.data+13, (size_t)FLV_in.len-17)); - }else{ - Meta_Put(meta_out, "audio", "init", std::string((char*)FLV_in.data+12, (size_t)FLV_in.len-16)); - } - continue;//skip rest of parsing, get next tag. - } - pack_out = DTSC::DTMI("audio", DTSC::DTMI_ROOT); - pack_out.addContent(DTSC::DTMI("datatype", "audio")); - pack_out.addContent(DTSC::DTMI("time", FLV_in.tagTime())); - if (!Meta_Has(meta_out, "audio", "codec")){ - switch (audiodata & 0xF0){ - case 0x20: Meta_Put(meta_out, "audio", "codec", "MP3"); break; - case 0xA0: Meta_Put(meta_out, "audio", "codec", "AAC"); break; - default: Meta_Put(meta_out, "audio", "codec", "?"); break; - } - } - if (!Meta_Has(meta_out, "audio", "rate")){ - switch (audiodata & 0x0C){ - case 0x0: Meta_Put(meta_out, "audio", "rate", 5512); break; - case 0x4: Meta_Put(meta_out, "audio", "rate", 11025); break; - case 0x8: Meta_Put(meta_out, "audio", "rate", 22050); break; - case 0xC: Meta_Put(meta_out, "audio", "rate", 44100); break; - } - } - if (!Meta_Has(meta_out, "audio", "size")){ - switch (audiodata & 0x02){ - case 0x0: Meta_Put(meta_out, "audio", "size", 8); break; - case 0x2: Meta_Put(meta_out, "audio", "size", 16); break; - } - } - if (!Meta_Has(meta_out, "audio", "channels")){ - switch (audiodata & 0x01){ - case 0x0: Meta_Put(meta_out, "audio", "channels", 1); break; - case 0x1: Meta_Put(meta_out, "audio", "channels", 2); break; - } - } - if ((audiodata & 0xF0) == 0xA0){ - pack_out.addContent(DTSC::DTMI("data", std::string((char*)FLV_in.data+13, (size_t)FLV_in.len-17))); - }else{ - pack_out.addContent(DTSC::DTMI("data", std::string((char*)FLV_in.data+12, (size_t)FLV_in.len-16))); - } - if (sending){ - std::cout << pack_out.Pack(true); - }else{ - prebuffer << pack_out.Pack(true); - } - } - if (FLV_in.data[0] == 0x09){ - char videodata = FLV_in.data[11]; - if (FLV_in.needsInitData() && FLV_in.isInitData()){ - if ((videodata & 0x0F) == 7){ - Meta_Put(meta_out, "video", "init", std::string((char*)FLV_in.data+16, (size_t)FLV_in.len-20)); - }else{ - Meta_Put(meta_out, "video", "init", std::string((char*)FLV_in.data+12, (size_t)FLV_in.len-16)); - } - continue;//skip rest of parsing, get next tag. - } - if (!Meta_Has(meta_out, "video", "codec")){ - switch (videodata & 0x0F){ - case 2: Meta_Put(meta_out, "video", "codec", "H263"); break; - case 4: Meta_Put(meta_out, "video", "codec", "VP6"); break; - case 7: Meta_Put(meta_out, "video", "codec", "H264"); break; - default: Meta_Put(meta_out, "video", "codec", "?"); break; - } - } - pack_out = DTSC::DTMI("video", DTSC::DTMI_ROOT); - pack_out.addContent(DTSC::DTMI("datatype", "video")); - switch (videodata & 0xF0){ - case 0x10: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break; - case 0x20: pack_out.addContent(DTSC::DTMI("interframe", 1)); break; - case 0x30: pack_out.addContent(DTSC::DTMI("disposableframe", 1)); break; - case 0x40: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break; - case 0x50: continue; break;//the video info byte we just throw away - useless to us... - } - pack_out.addContent(DTSC::DTMI("time", FLV_in.tagTime())); - if ((videodata & 0x0F) == 7){ - switch (FLV_in.data[12]){ - case 1: pack_out.addContent(DTSC::DTMI("nalu", 1)); break; - case 2: pack_out.addContent(DTSC::DTMI("nalu_end", 1)); break; - } - int offset = (FLV_in.data[13] << 16) + (FLV_in.data[14] << 8) + FLV_in.data[15]; - offset = (offset << 8) >> 8; - pack_out.addContent(DTSC::DTMI("offset", offset)); - pack_out.addContent(DTSC::DTMI("data", std::string((char*)FLV_in.data+16, (size_t)FLV_in.len-20))); - }else{ - pack_out.addContent(DTSC::DTMI("data", std::string((char*)FLV_in.data+12, (size_t)FLV_in.len-16))); - } - if (sending){ - std::cout << pack_out.Pack(true); - }else{ - prebuffer << pack_out.Pack(true); - } + prebuffer << pack_out.Pack(true); + }else{ + std::cout << pack_out.Pack(true); } } } diff --git a/util/dtsc.cpp b/util/dtsc.cpp index fd0b6a7e..26601a5d 100644 --- a/util/dtsc.cpp +++ b/util/dtsc.cpp @@ -198,6 +198,13 @@ const char * DTSC::DTMI::Str(){return strval.c_str();}; /// If this object is not a container type, this function will always return 0. int DTSC::DTMI::hasContent(){return contents.size();}; +/// Returns true if this DTSC::DTMI value is non-default. +/// Non-default means it is either not a root element or has content. +bool DTSC::DTMI::isEmpty(){ + if (myType != DTMI_ROOT){return false;} + return (hasContent() == 0); +}; + /// Adds an DTSC::DTMI to this object. Works for all types, but only makes sense for container types. /// This function resets DTMI::packed to an empty string, forcing a repack on the next call to DTMI::Pack. /// If the indice name already exists, replaces the indice. @@ -213,9 +220,12 @@ void DTSC::DTMI::addContent(DTSC::DTMI c){ }; /// Returns a pointer to the object held at indice i. -/// Returns AMF::AMF0_DDV_CONTAINER of indice "error" if no object is held at this indice. +/// Returns null pointer if no object is held at this indice. /// \param i The indice of the object in this container. -DTSC::DTMI* DTSC::DTMI::getContentP(int i){return &contents.at(i);}; +DTSC::DTMI* DTSC::DTMI::getContentP(int i){ + if (contents.size() <= (unsigned int)i){return 0;} + return &contents.at(i); +}; /// Returns a copy of the object held at indice i. /// Returns a AMF::AMF0_DDV_CONTAINER of indice "error" if no object is held at this indice. diff --git a/util/dtsc.h b/util/dtsc.h index 138e3ab4..428a445e 100644 --- a/util/dtsc.h +++ b/util/dtsc.h @@ -62,6 +62,7 @@ namespace DTSC{ std::string & StrValue(); const char * Str(); int hasContent(); + bool isEmpty(); void addContent(DTMI c); DTMI* getContentP(int i); DTMI getContent(int i); diff --git a/util/flv_tag.cpp b/util/flv_tag.cpp index bba87754..919772f0 100644 --- a/util/flv_tag.cpp +++ b/util/flv_tag.cpp @@ -771,3 +771,178 @@ bool FLV::Tag::FileLoader(FILE * f){ fcntl(fileno(f), F_SETFL, preflags); return false; }//FLV_GetPacket + +DTSC::DTMI FLV::Tag::toDTSC(DTSC::DTMI & metadata){ + DTSC::DTMI pack_out; // Storage for outgoing DTMI data. + + if (data[0] == 0x12){ + AMF::Object meta_in = AMF::parse((unsigned char*)data+11, len-15); + if (meta_in.getContentP(0) && (meta_in.getContentP(0)->StrValue() == "onMetaData") && meta_in.getContentP(1)){ + AMF::Object * tmp = meta_in.getContentP(1); + if (tmp->getContentP("videocodecid")){ + switch ((unsigned int)tmp->getContentP("videocodecid")->NumValue()){ + case 2: Meta_Put(metadata, "video", "codec", "H263"); break; + case 4: Meta_Put(metadata, "video", "codec", "VP6"); break; + case 7: Meta_Put(metadata, "video", "codec", "H264"); break; + default: Meta_Put(metadata, "video", "codec", "?"); break; + } + } + if (tmp->getContentP("audiocodecid")){ + switch ((unsigned int)tmp->getContentP("audiocodecid")->NumValue()){ + case 2: Meta_Put(metadata, "audio", "codec", "MP3"); break; + case 10: Meta_Put(metadata, "audio", "codec", "AAC"); break; + default: Meta_Put(metadata, "audio", "codec", "?"); break; + } + } + if (tmp->getContentP("width")){ + Meta_Put(metadata, "video", "width", tmp->getContentP("width")->NumValue()); + } + if (tmp->getContentP("height")){ + Meta_Put(metadata, "video", "height", tmp->getContentP("height")->NumValue()); + } + if (tmp->getContentP("framerate")){ + Meta_Put(metadata, "video", "fpks", tmp->getContentP("framerate")->NumValue()*1000); + } + if (tmp->getContentP("videodatarate")){ + Meta_Put(metadata, "video", "bps", (tmp->getContentP("videodatarate")->NumValue()*1024)/8); + } + if (tmp->getContentP("audiodatarate")){ + Meta_Put(metadata, "audio", "bps", (tmp->getContentP("audiodatarate")->NumValue()*1024)/8); + } + if (tmp->getContentP("audiosamplerate")){ + Meta_Put(metadata, "audio", "rate", tmp->getContentP("audiosamplerate")->NumValue()); + } + if (tmp->getContentP("audiosamplesize")){ + Meta_Put(metadata, "audio", "size", tmp->getContentP("audiosamplesize")->NumValue()); + } + if (tmp->getContentP("stereo")){ + if (tmp->getContentP("stereo")->NumValue() == 1){ + Meta_Put(metadata, "audio", "channels", 2); + }else{ + Meta_Put(metadata, "audio", "channels", 1); + } + } + } + return pack_out;//empty + } + if (data[0] == 0x08){ + char audiodata = data[11]; + if (needsInitData() && isInitData()){ + if ((audiodata & 0xF0) == 0xA0){ + Meta_Put(metadata, "audio", "init", std::string((char*)data+13, (size_t)len-17)); + }else{ + Meta_Put(metadata, "audio", "init", std::string((char*)data+12, (size_t)len-16)); + } + return pack_out;//skip rest of parsing, get next tag. + } + pack_out = DTSC::DTMI("audio", DTSC::DTMI_ROOT); + pack_out.addContent(DTSC::DTMI("datatype", "audio")); + pack_out.addContent(DTSC::DTMI("time", tagTime())); + if (!Meta_Has(metadata, "audio", "codec")){ + switch (audiodata & 0xF0){ + case 0x20: Meta_Put(metadata, "audio", "codec", "MP3"); break; + case 0xA0: Meta_Put(metadata, "audio", "codec", "AAC"); break; + default: Meta_Put(metadata, "audio", "codec", "?"); break; + } + } + if (!Meta_Has(metadata, "audio", "rate")){ + switch (audiodata & 0x0C){ + case 0x0: Meta_Put(metadata, "audio", "rate", 5512); break; + case 0x4: Meta_Put(metadata, "audio", "rate", 11025); break; + case 0x8: Meta_Put(metadata, "audio", "rate", 22050); break; + case 0xC: Meta_Put(metadata, "audio", "rate", 44100); break; + } + } + if (!Meta_Has(metadata, "audio", "size")){ + switch (audiodata & 0x02){ + case 0x0: Meta_Put(metadata, "audio", "size", 8); break; + case 0x2: Meta_Put(metadata, "audio", "size", 16); break; + } + } + if (!Meta_Has(metadata, "audio", "channels")){ + switch (audiodata & 0x01){ + case 0x0: Meta_Put(metadata, "audio", "channels", 1); break; + case 0x1: Meta_Put(metadata, "audio", "channels", 2); break; + } + } + if ((audiodata & 0xF0) == 0xA0){ + pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+13, (size_t)len-17))); + }else{ + pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+12, (size_t)len-16))); + } + return pack_out; + } + if (data[0] == 0x09){ + char videodata = data[11]; + if (needsInitData() && isInitData()){ + if ((videodata & 0x0F) == 7){ + Meta_Put(metadata, "video", "init", std::string((char*)data+16, (size_t)len-20)); + }else{ + Meta_Put(metadata, "video", "init", std::string((char*)data+12, (size_t)len-16)); + } + return pack_out;//skip rest of parsing, get next tag. + } + if (!Meta_Has(metadata, "video", "codec")){ + switch (videodata & 0x0F){ + case 2: Meta_Put(metadata, "video", "codec", "H263"); break; + case 4: Meta_Put(metadata, "video", "codec", "VP6"); break; + case 7: Meta_Put(metadata, "video", "codec", "H264"); break; + default: Meta_Put(metadata, "video", "codec", "?"); break; + } + } + pack_out = DTSC::DTMI("video", DTSC::DTMI_ROOT); + pack_out.addContent(DTSC::DTMI("datatype", "video")); + switch (videodata & 0xF0){ + case 0x10: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break; + case 0x20: pack_out.addContent(DTSC::DTMI("interframe", 1)); break; + case 0x30: pack_out.addContent(DTSC::DTMI("disposableframe", 1)); break; + case 0x40: pack_out.addContent(DTSC::DTMI("keyframe", 1)); break; + case 0x50: return DTSC::DTMI(); break;//the video info byte we just throw away - useless to us... + } + pack_out.addContent(DTSC::DTMI("time", tagTime())); + if ((videodata & 0x0F) == 7){ + switch (data[12]){ + case 1: pack_out.addContent(DTSC::DTMI("nalu", 1)); break; + case 2: pack_out.addContent(DTSC::DTMI("nalu_end", 1)); break; + } + int offset = (data[13] << 16) + (data[14] << 8) + data[15]; + offset = (offset << 8) >> 8; + pack_out.addContent(DTSC::DTMI("offset", offset)); + pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+16, (size_t)len-20))); + }else{ + pack_out.addContent(DTSC::DTMI("data", std::string((char*)data+12, (size_t)len-16))); + } + return pack_out; + } + return pack_out;//should never get here +}//FLV::Tag::toDTSC + +/// Inserts std::string type metadata into the passed DTMI object. +/// \arg meta The DTMI object to put the metadata into. +/// \arg cat Metadata category to insert into. +/// \arg elem Element name to put into the category. +/// \arg val Value to put into the element name. +void FLV::Tag::Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, std::string val){ + if (meta.getContentP(cat) == 0){meta.addContent(DTSC::DTMI(cat));} + meta.getContentP(cat)->addContent(DTSC::DTMI(elem, val)); +} + +/// Inserts uint64_t type metadata into the passed DTMI object. +/// \arg meta The DTMI object to put the metadata into. +/// \arg cat Metadata category to insert into. +/// \arg elem Element name to put into the category. +/// \arg val Value to put into the element name. +void FLV::Tag::Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, uint64_t val){ + if (meta.getContentP(cat) == 0){meta.addContent(DTSC::DTMI(cat));} + meta.getContentP(cat)->addContent(DTSC::DTMI(elem, val)); +} + +/// Returns true if the named category and elementname are available in the metadata. +/// \arg meta The DTMI object to check. +/// \arg cat Metadata category to check. +/// \arg elem Element name to check. +bool FLV::Tag::Meta_Has(DTSC::DTMI & meta, std::string cat, std::string elem){ + if (meta.getContentP(cat) == 0){return false;} + if (meta.getContentP(cat)->getContentP(elem) == 0){return false;} + return true; +} diff --git a/util/flv_tag.h b/util/flv_tag.h index 6f1f7da7..6848995c 100644 --- a/util/flv_tag.h +++ b/util/flv_tag.h @@ -43,6 +43,7 @@ namespace FLV { bool DTSCVideoInit(DTSC::Stream & S); bool DTSCAudioInit(DTSC::Stream & S); bool DTSCMetaInit(DTSC::Stream & S); + DTSC::DTMI toDTSC(DTSC::DTMI & metadata); bool MemLoader(char * D, unsigned int S, unsigned int & P); bool SockLoader(int sock); bool SockLoader(Socket::Connection sock); @@ -56,6 +57,10 @@ namespace FLV { bool MemReadUntil(char * buffer, unsigned int count, unsigned int & sofar, char * D, unsigned int S, unsigned int & P); bool SockReadUntil(char * buffer, unsigned int count, unsigned int & sofar, Socket::Connection & sock); bool FileReadUntil(char * buffer, unsigned int count, unsigned int & sofar, FILE * f); + //DTSC writer helpers + void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, std::string val); + void Meta_Put(DTSC::DTMI & meta, std::string cat, std::string elem, uint64_t val); + bool Meta_Has(DTSC::DTMI & meta, std::string cat, std::string elem); };//Tag };//FLV namespace From 9ae274b0c19df4a7486e45ec9a25793f4abc883d Mon Sep 17 00:00:00 2001 From: Thulinma Date: Wed, 18 Apr 2012 11:23:33 +0200 Subject: [PATCH 2/4] Fixed a minor ordering bug in FLV2DTSC, made Connector_RTMP fully functional in DTSC environment (push support). --- Connector_RTMP/main.cpp | 63 ++++++++++++++++++++--------------------- tools/FLV2DTSC/main.cpp | 9 +++--- 2 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index d6eb2769..94a737a2 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -10,6 +10,7 @@ #include #include #include +#include #include "../util/socket.h" #include "../util/flv_tag.h" #include "../util/amf.h" @@ -137,6 +138,12 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){ /// Tries to get and parse one RTMP chunk at a time. void Connector_RTMP::parseChunk(std::string & inbuffer){ + //for DTSC conversion + static DTSC::DTMI meta_out; + static std::stringstream prebuffer; // Temporary buffer before sending real data + static bool sending = false; + static unsigned int counter = 0; + //for chunk parsing static RTMPStream::Chunk next; FLV::Tag F; static AMF::Object amfdata("empty", AMF::AMF0_DDV_CONTAINER); @@ -209,32 +216,33 @@ void Connector_RTMP::parseChunk(std::string & inbuffer){ RTMPStream::snd_window_size = ntohl(*(int*)next.data.c_str()); Socket.write(RTMPStream::SendCTL(5, RTMPStream::snd_window_size));//send window acknowledgement size (msg 5) break; - case 8: - F.ChunkLoader(next); + case 8://audio data + case 9://video data + case 18://meta data if (SS.connected()){ - #if DEBUG >= 4 - fprintf(stderr, "A"); - #endif - /// \TODO Convert to DTSC properly. - SS.write(std::string(F.data, F.len)); + F.ChunkLoader(next); + DTSC::DTMI pack_out = F.toDTSC(meta_out); + if (!pack_out.isEmpty()){ + if (!sending){ + counter++; + if (counter > 8){ + sending = true; + meta_out.Pack(true);//pack metadata + meta_out.packed.replace(0, 4, DTSC::Magic_Header);//prepare proper header + SS.write(meta_out.packed);//write header/metadata + SS.write(prebuffer.str());//write buffer + prebuffer.str("");//clear buffer + SS.write(pack_out.Pack(true));//simply write + }else{ + prebuffer << pack_out.Pack(true);//buffer + } + }else{ + SS.write(pack_out.Pack(true));//simple write + } + } }else{ #if DEBUG >= 4 - fprintf(stderr, "Received useless audio data\n"); - #endif - Socket.close(); - } - break; - case 9: - F.ChunkLoader(next); - if (SS.connected()){ - #if DEBUG >= 4 - fprintf(stderr, "V"); - #endif - /// \TODO Convert to DTSC properly. - SS.write(std::string(F.data, F.len)); - }else{ - #if DEBUG >= 4 - fprintf(stderr, "Received useless video data\n"); + fprintf(stderr, "Received useless media data\n"); #endif Socket.close(); } @@ -268,15 +276,6 @@ void Connector_RTMP::parseChunk(std::string & inbuffer){ parseAMFCommand(amfdata, 17, next.msg_stream_id); }//parsing AMF0-style } break; - case 18: - #if DEBUG >= 4 - fprintf(stderr, "Received AFM0 data message (metadata)\n"); - #endif - F.ChunkLoader(next); - if (SS.connected()){ - SS.write(std::string(F.data, F.len)); - } - break; case 19: #if DEBUG >= 4 fprintf(stderr, "Received AFM0 shared object\n"); diff --git a/tools/FLV2DTSC/main.cpp b/tools/FLV2DTSC/main.cpp index 6ae6516c..e1ad8b55 100644 --- a/tools/FLV2DTSC/main.cpp +++ b/tools/FLV2DTSC/main.cpp @@ -32,7 +32,7 @@ namespace Converters{ if (pack_out.isEmpty()){continue;} if (!sending){ counter++; - if (counter > 10){ + if (counter > 8){ sending = true; meta_out.Pack(true); meta_out.packed.replace(0, 4, DTSC::Magic_Header); @@ -40,11 +40,12 @@ namespace Converters{ std::cout << prebuffer.rdbuf(); prebuffer.str(""); std::cerr << "Buffer done, starting real-time output..." << std::endl; + }else{ + prebuffer << pack_out.Pack(true);//buffer + continue;//don't also write } - prebuffer << pack_out.Pack(true); - }else{ - std::cout << pack_out.Pack(true); } + std::cout << pack_out.Pack(true);//simply write } } From f527bc5d451128fba09b7ed6d429b566ac63ab22 Mon Sep 17 00:00:00 2001 From: Lekensteyn Date: Sat, 21 Apr 2012 16:56:38 +0200 Subject: [PATCH 3/4] Fix compile error on -lpthread --- Buffer/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Buffer/Makefile b/Buffer/Makefile index 89e4f902..4557dc18 100644 --- a/Buffer/Makefile +++ b/Buffer/Makefile @@ -13,9 +13,9 @@ LIBS = -lpthread .PHONY: clean default default: $(OUT) .cpp.o: - $(CC) $(INCLUDES) $(CCFLAGS) $(LIBS) -c $< -o $@ + $(CC) $(INCLUDES) $(CCFLAGS) -c $< -o $@ $(LIBS) $(OUT): $(OBJ) - $(CC) $(LIBS) -o $(OUT) $(OBJ) + $(CC) -o $(OUT) $(OBJ) $(LIBS) clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ install: $(OUT) From 51c760eef7118c8e14bbff2a03f916effe57d0ee Mon Sep 17 00:00:00 2001 From: Lekensteyn Date: Sun, 22 Apr 2012 15:37:00 +0200 Subject: [PATCH 4/4] Use coreutils' install command, support DESTDIR --- Buffer/Makefile | 3 ++- Connector_HTTP/Makefile | 3 ++- Connector_RAW/Makefile | 3 ++- Connector_RTMP/Makefile | 3 ++- DDV_Controller/Makefile | 3 +++ 5 files changed, 11 insertions(+), 4 deletions(-) diff --git a/Buffer/Makefile b/Buffer/Makefile index 4557dc18..4e3c80f3 100644 --- a/Buffer/Makefile +++ b/Buffer/Makefile @@ -5,6 +5,7 @@ INCLUDES = DEBUG = 4 OPTIMIZE = -g CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) +INSTALL = install CC = $(CROSS)g++ LD = $(CROSS)ld AR = $(CROSS)ar @@ -19,5 +20,5 @@ $(OUT): $(OBJ) clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ install: $(OUT) - cp -f ./$(OUT) /usr/bin/ + $(INSTALL) -D ./$(OUT) $(DESTDIR)/usr/bin/$(OUT) diff --git a/Connector_HTTP/Makefile b/Connector_HTTP/Makefile index 7ccbfc72..75a62ea6 100644 --- a/Connector_HTTP/Makefile +++ b/Connector_HTTP/Makefile @@ -6,6 +6,7 @@ DEBUG = 4 OPTIMIZE = -g CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) -DVERSION=$(VERSION) VERSION = `git describe --tags` +INSTALL = install CC = $(CROSS)g++ LD = $(CROSS)ld AR = $(CROSS)ar @@ -20,7 +21,7 @@ $(OUT): $(OBJ) clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ install: $(OUT) - cp -f ./$(OUT) /usr/bin/ + $(INSTALL) -D ./$(OUT) $(DESTDIR)/usr/bin/$(OUT) cversion: rm -rf ../util/config.o diff --git a/Connector_RAW/Makefile b/Connector_RAW/Makefile index c6b3ec59..a19ba413 100644 --- a/Connector_RAW/Makefile +++ b/Connector_RAW/Makefile @@ -5,6 +5,7 @@ INCLUDES = DEBUG = 4 OPTIMIZE = -g CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) +INSTALL = install CC = $(CROSS)g++ LD = $(CROSS)ld AR = $(CROSS)ar @@ -19,5 +20,5 @@ $(OUT): $(OBJ) clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ install: $(OUT) - cp -f ./$(OUT) /usr/bin/ + $(INSTALL) -D ./$(OUT) $(DESTDIR)/usr/bin/$(OUT) diff --git a/Connector_RTMP/Makefile b/Connector_RTMP/Makefile index 0a337458..162b22f8 100644 --- a/Connector_RTMP/Makefile +++ b/Connector_RTMP/Makefile @@ -6,6 +6,7 @@ STATIC = DEBUG = 4 OPTIMIZE = -g CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) -DVERSION=$(VERSION) +INSTALL = install CC = $(CROSS)g++ LD = $(CROSS)ld AR = $(CROSS)ar @@ -21,7 +22,7 @@ $(OUT): $(OBJ) clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ install: $(OUT) - cp -f ./$(OUT) /usr/bin/ + $(INSTALL) -D ./$(OUT) $(DESTDIR)/usr/bin/$(OUT) cversion: rm -rf ../util/config.o diff --git a/DDV_Controller/Makefile b/DDV_Controller/Makefile index 2782d63f..1ef9613c 100644 --- a/DDV_Controller/Makefile +++ b/DDV_Controller/Makefile @@ -9,6 +9,7 @@ COMPILED_USERNAME = testuser COMPILED_PASSWORD = 179ad45c6ce2cb97cf1029e212046e81 #COMPILED_PASSWORD = testpass CCFLAGS = -Wall -Wextra -funsigned-char $(OPTIMIZE) -DDEBUG=$(DEBUG) -DCOMPILED_USERNAME=$(COMPILED_USERNAME) -DCOMPILED_PASSWORD=$(COMPILED_PASSWORD) -DVERSION=$(VERSION) +INSTALL = install CC = $(CROSS)g++ LD = $(CROSS)ld AR = $(CROSS)ar @@ -24,4 +25,6 @@ clean: rm -rf $(OBJ) $(OUT) Makefile.bak *~ cversion: rm -rf ../util/config.o +install: $(OUT) + $(INSTALL) -D ./$(OUT) $(DESTDIR)/usr/bin/$(OUT)