Attempt to make RTMP properly compatible with all codecs

This commit is contained in:
Thulinma 2011-08-14 18:07:03 +02:00
parent d57d4c496a
commit feaf33e13e
3 changed files with 43 additions and 5 deletions

View file

@ -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

View file

@ -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]){

View file

@ -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.