Some edits to FLV parsing and RTMP fixes... not quite working yet (in Flash player, that is...)

This commit is contained in:
Thulinma 2011-08-13 03:01:33 +02:00
parent ba61ce2cef
commit e2138e2167
3 changed files with 49 additions and 23 deletions

View file

@ -18,12 +18,12 @@
/// Holds all functions and data unique to the RTMP Connector /// Holds all functions and data unique to the RTMP Connector
namespace Connector_RTMP{ namespace Connector_RTMP{
//for connection to server //for connection to server
bool ready4data = false; ///< Set to true when streaming starts. bool ready4data = false; ///< Set to true when streaming starts.
bool inited = false; ///< Set to true when ready to connect to Buffer. 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. bool stopparsing = false; ///< Set to true when all parsing needs to be cancelled.
Socket::Connection Socket; ///< Socket connected to user Socket::Connection Socket; ///< Socket connected to user
std::string streamname = "/tmp/shared_socket"; ///< Stream that will be opened std::string streamname = "/tmp/shared_socket"; ///< Stream that will be opened
void parseChunk(); void parseChunk();
@ -34,11 +34,8 @@ namespace Connector_RTMP{
/// Main Connector_RTMP function /// Main Connector_RTMP function
int Connector_RTMP::Connector_RTMP(Socket::Connection conn){ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){
Socket = conn; Socket = conn;
unsigned int ts;
unsigned int fts = 0;
unsigned int ftst;
Socket::Connection SS; Socket::Connection SS;
FLV::Tag tag; FLV::Tag tag, viddata, auddata;
//first timestamp set //first timestamp set
RTMPStream::firsttime = RTMPStream::getNowMS(); RTMPStream::firsttime = RTMPStream::getNowMS();
@ -111,19 +108,26 @@ int Connector_RTMP::Connector_RTMP(Socket::Connection conn){
case 0: break;//not ready yet case 0: break;//not ready yet
default: default:
if (tag.SockLoader(SS)){//able to read a full packet? if (tag.SockLoader(SS)){//able to read a full packet?
ts = tag.tagTime(); //init data? parse and resent in correct order if all is received
if (ts != 0){ if (((tag.data[0] == 0x09) && (viddata.len == 0)) || ((tag.data[0] == 0x08) && (auddata.len == 0))){
if (fts == 0){fts = ts;ftst = RTMPStream::getNowMS();} if (tag.data[0] == 0x09){viddata = tag;}else{auddata = tag;}
ts -= fts; if ((auddata.len != 0) && (viddata.len != 0)){
tag.tagTime(ts); Socket.write(RTMPStream::SendMedia((unsigned char)viddata.data[0], (unsigned char *)viddata.data+11, viddata.len-15, 0));
ts += ftst; Socket.write(RTMPStream::SendMedia((unsigned char)auddata.data[0], (unsigned char *)auddata.data+11, auddata.len-15, 0));
}else{ #if DEBUG >= 8
ftst = RTMPStream::getNowMS(); fprintf(stderr, "Sent tag to %i: [%u] %s\n", Socket.getSocket(), viddata.tagTime(), viddata.tagType().c_str());
tag.tagTime(ftst); 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)); /// \TODO Check metadata for needed init or not - we now assume init needed, which only works for AAC / H264...
#if DEBUG >= 4 //not gotten init yet? cancel this tag
fprintf(stderr, "Sent a tag to %i\n", Socket.getSocket()); 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 #endif
} }
break; break;
@ -165,7 +169,7 @@ void Connector_RTMP::parseChunk(){
RTMPStream::rec_window_at = RTMPStream::rec_cnt; RTMPStream::rec_window_at = RTMPStream::rec_cnt;
Socket.write(RTMPStream::SendCTL(3, RTMPStream::rec_cnt));//send ack (msg 3) Socket.write(RTMPStream::SendCTL(3, RTMPStream::rec_cnt));//send ack (msg 3)
} }
switch (next.msg_type_id){ switch (next.msg_type_id){
case 0://does not exist case 0://does not exist
#if DEBUG >= 2 #if DEBUG >= 2
@ -276,7 +280,7 @@ void Connector_RTMP::parseChunk(){
if (tmpint & 0x80){fprintf(stderr, "H264 video support detected\n");} if (tmpint & 0x80){fprintf(stderr, "H264 video support detected\n");}
tmpint = (int)amfdata.getContentP(2)->getContentP("audioCodecs")->NumValue(); tmpint = (int)amfdata.getContentP(2)->getContentP("audioCodecs")->NumValue();
if (tmpint & 0x04){fprintf(stderr, "MP3 audio support detected\n");} 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 #endif
Socket.write(RTMPStream::SendCTL(5, RTMPStream::snd_window_size));//send window acknowledgement size (msg 5) 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) Socket.write(RTMPStream::SendCTL(6, RTMPStream::rec_window_size));//send window acknowledgement size (msg 5)

View file

@ -17,7 +17,7 @@ std::string FLV::Error_Str = "";
/// - Not starting with the string "FLV". /// - Not starting with the string "FLV".
/// - The DataOffset is not 9 bytes. /// - The DataOffset is not 9 bytes.
/// - The PreviousTagSize is not 0 bytes. /// - The PreviousTagSize is not 0 bytes.
/// ///
/// Note that we see PreviousTagSize as part of the FLV header, not part of the tag header! /// Note that we see PreviousTagSize as part of the FLV header, not part of the tag header!
bool FLV::check_header(char * header){ bool FLV::check_header(char * header){
if (header[0] != 'F') return false; if (header[0] != 'F') return false;
@ -43,6 +43,27 @@ bool FLV::is_header(char * header){
return true; return true;
}//FLV::is_header }//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. /// Returns a std::string describing the tag in detail.
/// The string includes information about whether the tag is /// The string includes information about whether the tag is
@ -355,7 +376,7 @@ bool FLV::Tag::FileLoader(FILE * f){
int postflags = preflags | O_NONBLOCK; int postflags = preflags | O_NONBLOCK;
fcntl(fileno(f), F_SETFL, postflags); fcntl(fileno(f), F_SETFL, postflags);
if (buf < 15){data = (char*)realloc(data, 15); buf = 15;} if (buf < 15){data = (char*)realloc(data, 15); buf = 15;}
if (done){ if (done){
//read a header //read a header
if (FileReadUntil(data, 11, sofar, f)){ if (FileReadUntil(data, 11, sofar, f)){

View file

@ -11,7 +11,7 @@ namespace FLV {
extern char Header[13]; ///< Holds the last FLV header parsed. 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 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. extern std::string Error_Str; ///< This variable is set if a problem is encountered while parsing the FLV.
//functions //functions
bool check_header(char * header); ///< Checks a FLV Header for validness. 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". 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. int len; ///< Actual length of tag.
bool isKeyframe; ///< True if current tag is a video keyframe. bool isKeyframe; ///< True if current tag is a video keyframe.
char * data; ///< Pointer to tag buffer. 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. std::string tagType(); ///< Returns a std::string describing the tag in detail.
unsigned int tagTime(); ///< Returns the 32-bit timestamp of this tag. unsigned int tagTime(); ///< Returns the 32-bit timestamp of this tag.
void tagTime(unsigned int T); ///< Sets the 32-bit timestamp of this tag. void tagTime(unsigned int T); ///< Sets the 32-bit timestamp of this tag.