From b78e9bc5626e663681fc5d58690debe34022d079 Mon Sep 17 00:00:00 2001 From: Thulinma Date: Thu, 14 Nov 2013 12:24:11 +0100 Subject: [PATCH] Finally fixed long standing RTMP sync issue. Also added support for getting/setting FLV tag offsets. --- lib/flv_tag.cpp | 28 +++++++++++++++++++++------- lib/flv_tag.h | 6 ++++-- lib/rtmpchunks.cpp | 5 ++++- 3 files changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/flv_tag.cpp b/lib/flv_tag.cpp index 6f296941..49643ba1 100644 --- a/lib/flv_tag.cpp +++ b/lib/flv_tag.cpp @@ -262,6 +262,25 @@ std::string FLV::Tag::tagType(){ return R.str(); } //FLV::Tag::tagtype +/// Returns the 24-bit offset of this tag. +/// Returns 0 if the tag isn't H264 +int FLV::Tag::offset(){ + if (data[11] & 0x0F == 7){ + return (((data[13] << 16) + (data[14] << 8) + data[15]) << 8) >> 8; + }else{ + return 0; + } +} //offset getter + +/// Sets the 24-bit offset of this tag. +/// Ignored if the tag isn't H264 +void FLV::Tag::offset(int o){ + if (data[11] & 0x0F != 7){return;} + data[13] = (o >> 16) & 0xFF; + data[14] = (o >> 8) & 0XFF; + data[15] = o & 0xFF; +} //offset setter + /// Returns the 32-bit timestamp of this tag. unsigned int FLV::Tag::tagTime(){ return (data[4] << 16) + (data[5] << 8) + data[6] + (data[7] << 24); @@ -401,10 +420,7 @@ bool FLV::Tag::DTSCLoader(DTSC::Stream & S){ }else{ data[12] = 2; } - int offset = S.getPacket()["offset"].asInt(); - data[13] = (offset >> 16) & 0xFF; - data[14] = (offset >> 8) & 0XFF; - data[15] = offset & 0xFF; + offset(S.getPacket()["offset"].asInt()); } data[11] = 0; if (track.isMember("codec") && track["codec"].asStringRef() == "H264"){ @@ -1174,9 +1190,7 @@ JSON::Value FLV::Tag::toJSON(JSON::Value & metadata){ pack_out["nalu_end"] = 1; break; } - int offset = (data[13] << 16) + (data[14] << 8) + data[15]; - offset = (offset << 8) >> 8; - pack_out["offset"] = offset; + pack_out["offset"] = offset(); if (len < 21){ return JSON::Value(); } diff --git a/lib/flv_tag.h b/lib/flv_tag.h index b2815aee..1c1e0446 100644 --- a/lib/flv_tag.h +++ b/lib/flv_tag.h @@ -35,8 +35,10 @@ namespace FLV { const char * getAudioCodec(); ///< Returns a c-string with the audio codec name. const char * getVideoCodec(); ///< Returns a c-string with the video codec name. 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. + unsigned int tagTime(); + void tagTime(unsigned int T); + int offset(); + void offset(int o); Tag(); ///< Constructor for a new, empty, tag. Tag(const Tag& O); ///< Copy constructor, copies the contents of an existing tag. Tag & operator=(const Tag& O); ///< Assignment operator - works exactly like the copy constructor. diff --git a/lib/rtmpchunks.cpp b/lib/rtmpchunks.cpp index a9dd78cb..25e0dbf8 100644 --- a/lib/rtmpchunks.cpp +++ b/lib/rtmpchunks.cpp @@ -423,7 +423,10 @@ std::string & RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * d /// \param tag FLV::Tag with media to send. std::string & RTMPStream::SendMedia(FLV::Tag & tag){ static RTMPStream::Chunk ch; - ch.cs_id = ((unsigned char)tag.data[0]); + //Commented bit is more efficient and correct according to RTMP spec. + //Simply passing "4" is the only thing that actually plays correctly, though. + //Adobe, if you're ever reading this... wtf? Seriously. + ch.cs_id = 4;//((unsigned char)tag.data[0]); ch.timestamp = tag.tagTime(); ch.len = tag.len - 15; ch.real_len = tag.len - 15;