diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index 5e34521e..8a6cb5f2 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -18,12 +18,12 @@ /// Holds all functions and data unique to the RTMP Connector namespace Connector_RTMP{ - + //for connection to server bool ready4data = false; ///< Set to true when streaming starts. bool inited = false; ///< Set to true when ready to connect to Buffer. bool stopparsing = false; ///< Set to true when all parsing needs to be cancelled. - + Socket::Connection Socket; ///< Socket connected to user std::string streamname = "/tmp/shared_socket"; ///< Stream that will be opened void parseChunk(); @@ -34,11 +34,8 @@ namespace Connector_RTMP{ /// Main Connector_RTMP function int Connector_RTMP::Connector_RTMP(Socket::Connection conn){ Socket = conn; - unsigned int ts; - unsigned int fts = 0; - unsigned int ftst; Socket::Connection SS; - FLV::Tag tag; + FLV::Tag tag, viddata, auddata; //first timestamp set RTMPStream::firsttime = RTMPStream::getNowMS(); @@ -111,19 +108,26 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){ case 0: break;//not ready yet default: if (tag.SockLoader(SS)){//able to read a full packet? - ts = tag.tagTime(); - if (ts != 0){ - if (fts == 0){fts = ts;ftst = RTMPStream::getNowMS();} - ts -= fts; - tag.tagTime(ts); - ts += ftst; - }else{ - ftst = RTMPStream::getNowMS(); - tag.tagTime(ftst); + //init data? parse and resent in correct order if all is received + if (((tag.data[0] == 0x09) && (viddata.len == 0)) || ((tag.data[0] == 0x08) && (auddata.len == 0))){ + if (tag.data[0] == 0x09){viddata = tag;}else{auddata = tag;} + if ((auddata.len != 0) && (viddata.len != 0)){ + Socket.write(RTMPStream::SendMedia((unsigned char)viddata.data[0], (unsigned char *)viddata.data+11, viddata.len-15, 0)); + Socket.write(RTMPStream::SendMedia((unsigned char)auddata.data[0], (unsigned char *)auddata.data+11, auddata.len-15, 0)); + #if DEBUG >= 8 + fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), viddata.tagTime(), viddata.tagType().c_str()); + fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), auddata.tagTime(), auddata.tagType().c_str()); + #endif + } + break; } - Socket.write(RTMPStream::SendMedia((unsigned char)tag.data[0], (unsigned char *)tag.data+11, tag.len-15, ts)); - #if DEBUG >= 4 - fprintf(stderr, "Sent a tag to %i\n", Socket.getSocket()); + /// \TODO Check metadata for needed init or not - we now assume init needed, which only works for AAC / H264... + //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())); + #if DEBUG >= 8 + fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), tag.tagTime(), tag.tagType().c_str()); #endif } break; @@ -165,7 +169,7 @@ void Connector_RTMP::parseChunk(){ RTMPStream::rec_window_at = RTMPStream::rec_cnt; Socket.write(RTMPStream::SendCTL(3, RTMPStream::rec_cnt));//send ack (msg 3) } - + switch (next.msg_type_id){ case 0://does not exist #if DEBUG >= 2 @@ -276,7 +280,7 @@ void Connector_RTMP::parseChunk(){ if (tmpint & 0x80){fprintf(stderr, "H264 video support detected\n");} tmpint = (int)amfdata.getContentP(2)->getContentP("audioCodecs")->NumValue(); if (tmpint & 0x04){fprintf(stderr, "MP3 audio support detected\n");} - if (tmpint & 0x400){fprintf(stderr, "AAC video support detected\n");} + if (tmpint & 0x400){fprintf(stderr, "AAC audio support detected\n");} #endif Socket.write(RTMPStream::SendCTL(5, RTMPStream::snd_window_size));//send window acknowledgement size (msg 5) Socket.write(RTMPStream::SendCTL(6, RTMPStream::rec_window_size));//send window acknowledgement size (msg 5) diff --git a/util/flv_tag.cpp b/util/flv_tag.cpp index 140183f3..f595bbff 100644 --- a/util/flv_tag.cpp +++ b/util/flv_tag.cpp @@ -17,7 +17,7 @@ std::string FLV::Error_Str = ""; /// - Not starting with the string "FLV". /// - The DataOffset is not 9 bytes. /// - The PreviousTagSize is not 0 bytes. -/// +/// /// Note that we see PreviousTagSize as part of the FLV header, not part of the tag header! bool FLV::check_header(char * header){ if (header[0] != 'F') return false; @@ -43,6 +43,27 @@ bool FLV::is_header(char * header){ return true; }//FLV::is_header +/// True if current tag is init data for this media type. +bool FLV::Tag::isInitData(){ + switch (data[0]){ + case 0x09: + switch (data[11] & 0xF0){ + case 0x50: return true; break; + } + if ((data[11] & 0x0F) == 7){ + switch (data[12]){ + case 0: return true; break; + } + } + break; + case 0x08: + if ((data[12] == 0) && ((data[11] & 0xF0) == 0xA0)){ + return true; + } + break; + } + return false; +} /// Returns a std::string describing the tag in detail. /// The string includes information about whether the tag is @@ -355,7 +376,7 @@ bool FLV::Tag::FileLoader(FILE * f){ int postflags = preflags | O_NONBLOCK; fcntl(fileno(f), F_SETFL, postflags); if (buf < 15){data = (char*)realloc(data, 15); buf = 15;} - + if (done){ //read a header if (FileReadUntil(data, 11, sofar, f)){ diff --git a/util/flv_tag.h b/util/flv_tag.h index 74d0ffa7..2ad39673 100644 --- a/util/flv_tag.h +++ b/util/flv_tag.h @@ -11,7 +11,7 @@ namespace FLV { extern char Header[13]; ///< Holds the last FLV header parsed. extern bool Parse_Error; ///< This variable is set to true if a problem is encountered while parsing the FLV. extern std::string Error_Str; ///< This variable is set if a problem is encountered while parsing the FLV. - + //functions bool check_header(char * header); ///< Checks a FLV Header for validness. bool is_header(char * header); ///< Checks the first 3 bytes for the string "FLV". @@ -22,6 +22,7 @@ namespace FLV { int len; ///< Actual length of tag. bool isKeyframe; ///< True if current tag is a video keyframe. char * data; ///< Pointer to tag buffer. + bool isInitData(); ///< True if current tag is init data for this media type. std::string tagType(); ///< Returns a std::string describing the tag in detail. unsigned int tagTime(); ///< Returns the 32-bit timestamp of this tag. void tagTime(unsigned int T); ///< Sets the 32-bit timestamp of this tag.