diff --git a/Connector_RTMP/main.cpp b/Connector_RTMP/main.cpp index 8a6cb5f2..9ffc7d49 100644 --- a/Connector_RTMP/main.cpp +++ b/Connector_RTMP/main.cpp @@ -36,6 +36,7 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){ Socket = conn; Socket::Connection SS; FLV::Tag tag, viddata, auddata; + bool viddone = false, auddone = false; //first timestamp set RTMPStream::firsttime = RTMPStream::getNowMS(); @@ -107,21 +108,32 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){ break; case 0: break;//not ready yet default: + bool justdone = false; if (tag.SockLoader(SS)){//able to read a full packet? //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)){ + /// \TODO Check metadata for needed audio/video init or not - we now assume both video/audio are always present... + if (((tag.data[0] == 0x09) && !viddone) || ((tag.data[0] == 0x08) && !auddone)){ + if (tag.needsInitData()){ + if (tag.data[0] == 0x09){viddata = tag;}else{auddata = tag;} + } + if (tag.data[0] == 0x09){viddone = true;}else{auddone = true;} + justdone = true; + } + 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)); - 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()); + #endif + } + if (auddata.len != 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(), auddata.tagTime(), auddata.tagType().c_str()); #endif } break; } - /// \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 diff --git a/util/flv_tag.cpp b/util/flv_tag.cpp index f595bbff..3be1f4e1 100644 --- a/util/flv_tag.cpp +++ b/util/flv_tag.cpp @@ -43,6 +43,31 @@ bool FLV::is_header(char * header){ return true; }//FLV::is_header +/// True if this media type requires init data. +/// Will always return false if the tag type is not 0x08 or 0x09. +/// Returns true for H263, AVC (H264), AAC. +/// \todo Check if MP3 does or does not require init data... +bool FLV::Tag::needsInitData(){ + switch (data[0]){ + case 0x09: + switch (data[11] & 0x0F){ + case 2: return true; break;//H263 requires init data + case 7: return true; break;//AVC requires init data + default: return false; break;//other formats do not + } + break; + case 0x08: + switch (data[11] & 0xF0){ + case 0x20: return false; break;//MP3 does not...? Unsure. + case 0xA0: return true; break;//AAC requires init data + case 0xE0: return false; break;//MP38kHz does not...? + default: return false; break;//other formats do not + } + break; + } + return false;//only audio/video can require init data +} + /// True if current tag is init data for this media type. bool FLV::Tag::isInitData(){ switch (data[0]){ diff --git a/util/flv_tag.h b/util/flv_tag.h index 2ad39673..1d7bbc41 100644 --- a/util/flv_tag.h +++ b/util/flv_tag.h @@ -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 needsInitData(); ///< True if this media type requires init data. 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.