diff --git a/trunk/src/core/srs_core_error.hpp b/trunk/src/core/srs_core_error.hpp index a0d7a470d..082ca0e1e 100755 --- a/trunk/src/core/srs_core_error.hpp +++ b/trunk/src/core/srs_core_error.hpp @@ -57,7 +57,9 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define ERROR_RTMP_REQ_CONNECT 305 #define ERROR_RTMP_REQ_TCURL 306 #define ERROR_RTMP_MESSAGE_DECODE 307 +#define ERROR_RTMP_MESSAGE_ENCODE 308 #define ERROR_SYSTEM_STREAM_INIT 400 +#define ERROR_SYSTEM_PACKET_INVALID 401 #endif \ No newline at end of file diff --git a/trunk/src/core/srs_core_protocol.cpp b/trunk/src/core/srs_core_protocol.cpp index 139c7a520..48c592654 100755 --- a/trunk/src/core/srs_core_protocol.cpp +++ b/trunk/src/core/srs_core_protocol.cpp @@ -884,12 +884,17 @@ int SrsMessage::get_perfer_cid() return packet->get_perfer_cid(); } -void SrsMessage::set_packet(SrsPacket* pkt) +void SrsMessage::set_packet(SrsPacket* pkt, int stream_id) { if (packet) { delete packet; } + packet = pkt; + + header.message_type = packet->get_message_type(); + header.payload_length = packet->get_payload_length(); + header.stream_id = stream_id; } int SrsMessage::encode_packet() @@ -900,8 +905,14 @@ int SrsMessage::encode_packet() srs_warn("packet is empty, send out empty message."); return ret; } + // realloc the payload. + size = 0; + if (payload) { + delete[] payload; + payload = NULL; + } - return ret; + return packet->encode(size, (char*&)payload); } SrsPacket::SrsPacket() @@ -923,6 +934,66 @@ int SrsPacket::get_perfer_cid() return 0; } +int SrsPacket::get_message_type() +{ + return 0; +} + +int SrsPacket::get_payload_length() +{ + return get_size(); +} + +int SrsPacket::encode(int& psize, char*& ppayload) +{ + int ret = ERROR_SUCCESS; + + int size = get_size(); + char* payload = NULL; + + SrsStream stream; + + if (size > 0) { + payload = new char[size]; + + if ((ret = stream.initialize(payload, size)) != ERROR_SUCCESS) { + srs_error("initialize the stream failed. ret=%d", ret); + delete[] payload; + return ret; + } + } + + if ((ret = encode_packet(&stream)) != ERROR_SUCCESS) { + srs_error("encode the packet failed. ret=%d", ret); + delete[] payload; + return ret; + } + + psize = size; + ppayload = payload; + srs_verbose("encode the packet success. size=%d", size); + + return ret; +} + +int SrsPacket::get_size() +{ + return 0; +} + +int SrsPacket::encode_packet(SrsStream* stream) +{ + int ret = ERROR_SUCCESS; + + srs_assert(stream != NULL); + + ret = ERROR_SYSTEM_PACKET_INVALID; + srs_error("current packet is not support to sendout. " + "paket=%s, ret=%d", get_class_name(), ret); + + return ret; +} + SrsConnectAppPacket::SrsConnectAppPacket() { command_name = RTMP_AMF0_COMMAND_CONNECT; @@ -1013,3 +1084,31 @@ int SrsSetWindowAckSizePacket::get_perfer_cid() return RTMP_CID_ProtocolControl; } +int SrsSetWindowAckSizePacket::get_message_type() +{ + return RTMP_MSG_WindowAcknowledgementSize; +} + +int SrsSetWindowAckSizePacket::get_size() +{ + return 4; +} + +int SrsSetWindowAckSizePacket::encode_packet(SrsStream* stream) +{ + int ret = ERROR_SUCCESS; + + if (!stream->require(4)) { + ret = ERROR_RTMP_MESSAGE_ENCODE; + srs_error("encode ack size packet failed. ret=%d", ret); + return ret; + } + + stream->write_4bytes(ackowledgement_window_size); + + srs_verbose("encode ack size packet " + "success. ack_size=%d", ackowledgement_window_size); + + return ret; +} + diff --git a/trunk/src/core/srs_core_protocol.hpp b/trunk/src/core/srs_core_protocol.hpp index e6c3a4d61..20c4367ad 100755 --- a/trunk/src/core/srs_core_protocol.hpp +++ b/trunk/src/core/srs_core_protocol.hpp @@ -46,6 +46,9 @@ class SrsMessage; class SrsChunkStream; class SrsAmf0Object; +// convert class name to string. +#define CLASS_NAME_STRING(className) #className + /** * max rtmp header size: * 1bytes basic header, @@ -237,9 +240,10 @@ public: virtual int get_perfer_cid(); /** * set the encoded packet to encode_packet() to payload. + * @stream_id, the id of stream which is created by createStream. * @remark, user never free the pkt, the message will auto free it. */ - virtual void set_packet(SrsPacket* pkt); + virtual void set_packet(SrsPacket* pkt, int stream_id = 0); /** * encode the packet to message payload bytes. * @remark there exists empty packet, so maybe the payload is NULL. @@ -259,6 +263,36 @@ public: virtual int decode(SrsStream* stream); public: virtual int get_perfer_cid(); + virtual int get_payload_length(); +public: + /** + * subpacket must override to provide the right message type. + */ + virtual int get_message_type(); + /** + * the subpacket can override this encode, + * for example, video and audio will directly set the payload withou memory copy, + * other packet which need to serialize/encode to bytes by override the + * get_size and encode_packet. + */ + virtual int encode(int& size, char*& payload); +protected: + /** + * subpacket can override to calc the packet size. + */ + virtual int get_size(); + /** + * subpacket can override to encode the payload to stream. + */ + virtual int encode_packet(SrsStream* stream); +protected: + /** + * subpacket must override to provide the right class name. + */ + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsPacket); + } }; /** @@ -279,6 +313,11 @@ public: virtual ~SrsConnectAppPacket(); public: virtual int decode(SrsStream* stream); +protected: + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsConnectAppPacket); + } }; /** @@ -299,6 +338,16 @@ public: virtual int decode(SrsStream* stream); public: virtual int get_perfer_cid(); +public: + virtual int get_message_type(); +protected: + virtual int get_size(); + virtual int encode_packet(SrsStream* stream); +protected: + virtual const char* get_class_name() + { + return CLASS_NAME_STRING(SrsSetWindowAckSizePacket); + } }; /** diff --git a/trunk/src/core/srs_core_stream.cpp b/trunk/src/core/srs_core_stream.cpp index 3b5e1d6af..3ea887638 100755 --- a/trunk/src/core/srs_core_stream.cpp +++ b/trunk/src/core/srs_core_stream.cpp @@ -141,3 +141,14 @@ std::string SrsStream::read_string(int len) return value; } +void SrsStream::write_4bytes(int32_t value) +{ + srs_assert(require(4)); + + pp = (char*)&value; + *p++ = pp[3]; + *p++ = pp[2]; + *p++ = pp[1]; + *p++ = pp[0]; +} + diff --git a/trunk/src/core/srs_core_stream.hpp b/trunk/src/core/srs_core_stream.hpp index 9055492f5..13ee31b55 100755 --- a/trunk/src/core/srs_core_stream.hpp +++ b/trunk/src/core/srs_core_stream.hpp @@ -91,6 +91,11 @@ public: * get string from stream, length specifies by param len. */ virtual std::string read_string(int len); +public: + /** + * write 4bytes int to stream. + */ + virtual void write_4bytes(int32_t value); }; #endif \ No newline at end of file