Merge branch 'master' of octo.ddvtech.com:pls
This commit is contained in:
		
						commit
						7677388841
					
				
					 4 changed files with 100 additions and 27 deletions
				
			
		|  | @ -2,13 +2,17 @@ | |||
| /// Holds all code for the FLV namespace.
 | ||||
| 
 | ||||
| #include "flv_tag.h" | ||||
| #include "rtmpchunks.h" | ||||
| #include <stdio.h> //for Tag::FileLoader
 | ||||
| #include <unistd.h> //for Tag::FileLoader
 | ||||
| #include <fcntl.h> //for Tag::FileLoader
 | ||||
| #include <stdlib.h> //malloc
 | ||||
| #include <string.h> //memcpy
 | ||||
| 
 | ||||
| char FLV::Header[13]; ///< Holds the last FLV header parsed.
 | ||||
| /// Holds the last FLV header parsed.
 | ||||
| /// Defaults to a audio+video header on FLV version 0x01 if no header received yet.
 | ||||
| char FLV::Header[13] = {'F', 'L', 'V', 0x01, 0x05, 0, 0, 0, 0x09, 0, 0, 0, 0}; | ||||
| 
 | ||||
| bool FLV::Parse_Error = false; ///< This variable is set to true if a problem is encountered while parsing the FLV.
 | ||||
| std::string FLV::Error_Str = ""; | ||||
| 
 | ||||
|  | @ -209,6 +213,16 @@ FLV::Tag::Tag(const Tag& O){ | |||
|   isKeyframe = O.isKeyframe; | ||||
| }//copy constructor
 | ||||
| 
 | ||||
| 
 | ||||
| /// Copy constructor from a RTMP chunk.
 | ||||
| /// Copies the contents of a RTMP chunk into a valid FLV tag.
 | ||||
| /// Exactly the same as making a chunk by through the default (empty) constructor
 | ||||
| /// and then calling FLV::Tag::ChunkLoader with the chunk as argument.
 | ||||
| FLV::Tag::Tag(const RTMPStream::Chunk& O){ | ||||
|   len = 0; buf = 0; data = 0; isKeyframe = false; done = true; sofar = 0; | ||||
|   ChunkLoader(O); | ||||
| } | ||||
| 
 | ||||
| /// Assignment operator - works exactly like the copy constructor.
 | ||||
| /// This operator checks for self-assignment.
 | ||||
| FLV::Tag & FLV::Tag::operator= (const FLV::Tag& O){ | ||||
|  | @ -231,6 +245,32 @@ FLV::Tag & FLV::Tag::operator= (const FLV::Tag& O){ | |||
|   return *this; | ||||
| }//assignment operator
 | ||||
| 
 | ||||
| /// FLV loader function from chunk.
 | ||||
| /// Copies the contents and wraps it in a FLV header.
 | ||||
| bool FLV::Tag::ChunkLoader(const RTMPStream::Chunk& O){ | ||||
|   len = O.len + 15; | ||||
|   if (len > 0){ | ||||
|     if (!data){ | ||||
|       data = (char*)malloc(len); | ||||
|       buf = len; | ||||
|     }else{ | ||||
|       if (buf < len){ | ||||
|         data = (char*)realloc(data, len); | ||||
|         buf = len; | ||||
|       } | ||||
|     } | ||||
|     memcpy(data+11, &(O.data[0]), O.len); | ||||
|   } | ||||
|   ((unsigned int *)(data+len-4))[0] = O.len; | ||||
|   data[0] = O.msg_type_id; | ||||
|   data[3] = O.len & 0xFF; | ||||
|   data[2] = (O.len >> 8) & 0xFF; | ||||
|   data[1] = (O.len >> 16) & 0xFF; | ||||
|   tagTime(O.timestamp); | ||||
|   return true; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| /// Helper function for FLV::MemLoader.
 | ||||
| /// This function will try to read count bytes from data buffer D into buffer.
 | ||||
| /// This function should be called repeatedly until true.
 | ||||
|  |  | |||
|  | @ -5,6 +5,11 @@ | |||
| #include "socket.h" | ||||
| #include <string> | ||||
| 
 | ||||
| //forward declaration of RTMPStream::Chunk to avoid circular dependencies.
 | ||||
| namespace RTMPStream{ | ||||
|   class Chunk; | ||||
| }; | ||||
| 
 | ||||
| /// This namespace holds all FLV-parsing related functionality.
 | ||||
| namespace FLV { | ||||
|   //variables
 | ||||
|  | @ -30,7 +35,9 @@ namespace FLV { | |||
|       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.
 | ||||
|       Tag(const RTMPStream::Chunk& O); ///<Copy constructor from a RTMP chunk.
 | ||||
|       //loader functions
 | ||||
|       bool ChunkLoader(const RTMPStream::Chunk& O); | ||||
|       bool MemLoader(char * D, unsigned int S, unsigned int & P); | ||||
|       bool SockLoader(int sock); | ||||
|       bool SockLoader(Socket::Connection sock); | ||||
|  |  | |||
|  | @ -2,6 +2,7 @@ | |||
| /// Holds all code for the RTMPStream namespace.
 | ||||
| 
 | ||||
| #include "rtmpchunks.h" | ||||
| #include "flv_tag.h" | ||||
| #include "crypto.h" | ||||
| 
 | ||||
| char versionstring[] = "WWW.DDVTECH.COM "; ///< String that is repeated in the RTMP handshake
 | ||||
|  | @ -41,7 +42,7 @@ std::string RTMPStream::Chunk::Pack(){ | |||
|   RTMPStream::Chunk prev = lastsend[cs_id]; | ||||
|   unsigned int tmpi; | ||||
|   unsigned char chtype = 0x00; | ||||
|   timestamp -= firsttime; | ||||
|   //timestamp -= firsttime;
 | ||||
|   if ((prev.msg_type_id > 0) && (prev.cs_id == cs_id)){ | ||||
|     if (msg_stream_id == prev.msg_stream_id){ | ||||
|       chtype = 0x40;//do not send msg_stream_id
 | ||||
|  | @ -54,6 +55,8 @@ std::string RTMPStream::Chunk::Pack(){ | |||
|         } | ||||
|       } | ||||
|     } | ||||
|     //override - we always sent type 0x00 if the timestamp has decreased since last chunk in this channel
 | ||||
|     if (timestamp < prev.timestamp){chtype = 0x00;} | ||||
|   } | ||||
|   if (cs_id <= 63){ | ||||
|     output += (unsigned char)(chtype | cs_id); | ||||
|  | @ -76,15 +79,15 @@ std::string RTMPStream::Chunk::Pack(){ | |||
|       tmpi = timestamp - prev.timestamp; | ||||
|     } | ||||
|     if (tmpi >= 0x00ffffff){ntime = tmpi; tmpi = 0x00ffffff;} | ||||
|     output += (unsigned char)(tmpi / (256*256)); | ||||
|     output += (unsigned char)(tmpi / 256); | ||||
|     output += (unsigned char)(tmpi % 256); | ||||
|     output += (unsigned char)((tmpi >> 16) & 0xff); | ||||
|     output += (unsigned char)((tmpi >> 8) & 0xff); | ||||
|     output += (unsigned char)(tmpi & 0xff); | ||||
|     if (chtype != 0x80){ | ||||
|       //len
 | ||||
|       tmpi = len; | ||||
|       output += (unsigned char)(tmpi / (256*256)); | ||||
|       output += (unsigned char)(tmpi / 256); | ||||
|       output += (unsigned char)(tmpi % 256); | ||||
|       output += (unsigned char)((tmpi >> 16) & 0xff); | ||||
|       output += (unsigned char)((tmpi >> 8) & 0xff); | ||||
|       output += (unsigned char)(tmpi & 0xff); | ||||
|       //msg type id
 | ||||
|       output += (unsigned char)msg_type_id; | ||||
|       if (chtype != 0x40){ | ||||
|  | @ -98,10 +101,10 @@ std::string RTMPStream::Chunk::Pack(){ | |||
|   } | ||||
|   //support for 0x00ffffff timestamps
 | ||||
|   if (ntime){ | ||||
|     output += (unsigned char)(ntime % 256); | ||||
|     output += (unsigned char)(ntime / 256); | ||||
|     output += (unsigned char)(ntime / (256*256)); | ||||
|     output += (unsigned char)(ntime / (256*256*256)); | ||||
|     output += (unsigned char)(ntime & 0xff); | ||||
|     output += (unsigned char)((ntime >> 8) & 0xff); | ||||
|     output += (unsigned char)((ntime >> 16) & 0xff); | ||||
|     output += (unsigned char)((ntime >> 24) & 0xff); | ||||
|   } | ||||
|   len_left = 0; | ||||
|   while (len_left < len){ | ||||
|  | @ -162,7 +165,7 @@ std::string RTMPStream::SendChunk(unsigned int cs_id, unsigned char msg_type_id, | |||
| /// \param ts Timestamp of the media data, relative to current system time.
 | ||||
| std::string RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts){ | ||||
|   RTMPStream::Chunk ch; | ||||
|   ch.cs_id = msg_type_id; | ||||
|   ch.cs_id = msg_type_id+42; | ||||
|   ch.timestamp = ts; | ||||
|   ch.len = len; | ||||
|   ch.real_len = len; | ||||
|  | @ -173,6 +176,21 @@ std::string RTMPStream::SendMedia(unsigned char msg_type_id, unsigned char * dat | |||
|   return ch.Pack(); | ||||
| }//SendMedia
 | ||||
| 
 | ||||
| /// Packs up a chunk with media contents.
 | ||||
| /// \param tag FLV::Tag with media to send.
 | ||||
| std::string RTMPStream::SendMedia(FLV::Tag & tag){ | ||||
|   RTMPStream::Chunk ch; | ||||
|   ch.cs_id = ((unsigned char)tag.data[0]); | ||||
|   ch.timestamp = tag.tagTime(); | ||||
|   ch.len = tag.len-15; | ||||
|   ch.real_len = tag.len-15; | ||||
|   ch.len_left = 0; | ||||
|   ch.msg_type_id = (unsigned char)tag.data[0]; | ||||
|   ch.msg_stream_id = 1; | ||||
|   ch.data.append(tag.data+11, (size_t)(tag.len-15)); | ||||
|   return ch.Pack(); | ||||
| }//SendMedia
 | ||||
| 
 | ||||
| /// Packs up a chunk for a control message with 1 argument.
 | ||||
| std::string RTMPStream::SendCTL(unsigned char type, unsigned int data){ | ||||
|   RTMPStream::Chunk ch; | ||||
|  | @ -199,7 +217,7 @@ std::string RTMPStream::SendCTL(unsigned char type, unsigned int data, unsigned | |||
|   ch.msg_type_id = type; | ||||
|   ch.msg_stream_id = 0; | ||||
|   ch.data.resize(5); | ||||
|   *(int*)((char*)ch.data.c_str()) = htonl(data); | ||||
|   *(unsigned int*)((char*)ch.data.c_str()) = htonl(data); | ||||
|   ch.data[4] = data2; | ||||
|   return ch.Pack(); | ||||
| }//SendCTL
 | ||||
|  | @ -215,7 +233,7 @@ std::string RTMPStream::SendUSR(unsigned char type, unsigned int data){ | |||
|   ch.msg_type_id = 4; | ||||
|   ch.msg_stream_id = 0; | ||||
|   ch.data.resize(6); | ||||
|   *(int*)((char*)ch.data.c_str()+2) = htonl(data); | ||||
|   *(unsigned int*)(((char*)ch.data.c_str())+2) = htonl(data); | ||||
|   ch.data[0] = 0; | ||||
|   ch.data[1] = type; | ||||
|   return ch.Pack(); | ||||
|  | @ -232,8 +250,8 @@ std::string RTMPStream::SendUSR(unsigned char type, unsigned int data, unsigned | |||
|   ch.msg_type_id = 4; | ||||
|   ch.msg_stream_id = 0; | ||||
|   ch.data.resize(10); | ||||
|   *(int*)((char*)ch.data.c_str()+2) = htonl(data); | ||||
|   *(int*)((char*)ch.data.c_str()+6) = htonl(data2); | ||||
|   *(unsigned int*)(((char*)ch.data.c_str())+2) = htonl(data); | ||||
|   *(unsigned int*)(((char*)ch.data.c_str())+6) = htonl(data2); | ||||
|   ch.data[0] = 0; | ||||
|   ch.data[1] = type; | ||||
|   return ch.Pack(); | ||||
|  | @ -274,7 +292,8 @@ bool RTMPStream::Chunk::Parse(std::string & indata){ | |||
|   RTMPStream::Chunk prev = lastrecv[cs_id]; | ||||
| 
 | ||||
|   //process the rest of the header, for each chunk type
 | ||||
|   switch (chunktype & 0xC0){ | ||||
|   headertype = chunktype & 0xC0; | ||||
|   switch (headertype){ | ||||
|     case 0x00: | ||||
|       if (indata.size() < i+11) return false; //can't read whole header
 | ||||
|       timestamp = indata[i++]*256*256; | ||||
|  | @ -296,7 +315,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){ | |||
|       timestamp = indata[i++]*256*256; | ||||
|       timestamp += indata[i++]*256; | ||||
|       timestamp += indata[i++]; | ||||
|       timestamp += prev.timestamp; | ||||
|       if (timestamp != 0x00ffffff){timestamp += prev.timestamp;} | ||||
|       len = indata[i++]*256*256; | ||||
|       len += indata[i++]*256; | ||||
|       len += indata[i++]; | ||||
|  | @ -310,7 +329,7 @@ bool RTMPStream::Chunk::Parse(std::string & indata){ | |||
|       timestamp = indata[i++]*256*256; | ||||
|       timestamp += indata[i++]*256; | ||||
|       timestamp += indata[i++]; | ||||
|       timestamp += prev.timestamp; | ||||
|       if (timestamp != 0x00ffffff){timestamp += prev.timestamp;} | ||||
|       len = prev.len; | ||||
|       len_left = prev.len_left; | ||||
|       msg_type_id = prev.msg_type_id; | ||||
|  |  | |||
|  | @ -9,6 +9,11 @@ | |||
| #include <string> | ||||
| #include <arpa/inet.h> | ||||
| 
 | ||||
| //forward declaration of FLV::Tag to avoid circular dependencies.
 | ||||
| namespace FLV{ | ||||
|   class Tag; | ||||
| }; | ||||
| 
 | ||||
| /// Contains all functions and classes needed for RTMP connections.
 | ||||
| namespace RTMPStream{ | ||||
| 
 | ||||
|  | @ -30,6 +35,7 @@ namespace RTMPStream{ | |||
|   /// Holds a single RTMP chunk, either send or receive direction.
 | ||||
|   class Chunk{ | ||||
|     public: | ||||
|       unsigned char headertype; ///< For input chunks, the type of header. This is calculated automatically for output chunks.
 | ||||
|       unsigned int cs_id; ///< ContentStream ID
 | ||||
|       unsigned int timestamp; ///< Timestamp of this chunk.
 | ||||
|       unsigned int len; ///< Length of the complete chunk.
 | ||||
|  | @ -50,6 +56,7 @@ namespace RTMPStream{ | |||
| 
 | ||||
|   std::string SendChunk(unsigned int cs_id, unsigned char msg_type_id, unsigned int msg_stream_id, std::string data); | ||||
|   std::string SendMedia(unsigned char msg_type_id, unsigned char * data, int len, unsigned int ts); | ||||
|   std::string SendMedia(FLV::Tag & tag); | ||||
|   std::string SendCTL(unsigned char type, unsigned int data); | ||||
|   std::string SendCTL(unsigned char type, unsigned int data, unsigned char data2); | ||||
|   std::string SendUSR(unsigned char type, unsigned int data); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Erik Zandvliet
						Erik Zandvliet