diff --git a/trunk/src/protocol/srs_rtmp_buffer.cpp b/trunk/src/protocol/srs_rtmp_buffer.cpp index 8ca039a21..06995655a 100644 --- a/trunk/src/protocol/srs_rtmp_buffer.cpp +++ b/trunk/src/protocol/srs_rtmp_buffer.cpp @@ -23,6 +23,8 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include +#include + #include #include #include @@ -58,10 +60,16 @@ SrsFastBuffer::SrsFastBuffer() #endif nb_buffer = SRS_DEFAULT_RECV_BUFFER_SIZE; - buffer = new char[nb_buffer]; + buffer = (char*)malloc(nb_buffer); p = end = buffer; } +SrsFastBuffer::~SrsFastBuffer() +{ + free(buffer); + buffer = NULL; +} + int SrsFastBuffer::size() { return end - p; @@ -75,33 +83,23 @@ char* SrsFastBuffer::bytes() void SrsFastBuffer::set_buffer(int buffer_size) { // the user-space buffer size limit to a max value. - int nb_max_buf = srs_min(buffer_size, SRS_MAX_SOCKET_BUFFER); - if (nb_max_buf < buffer_size) { - srs_warn("limit the user-space buffer from %d to %d", buffer_size, nb_max_buf); + int nb_resize_buf = srs_min(buffer_size, SRS_MAX_SOCKET_BUFFER); + if (buffer_size > SRS_MAX_SOCKET_BUFFER) { + srs_warn("limit the user-space buffer from %d to %d", buffer_size, SRS_MAX_SOCKET_BUFFER); } // only realloc when buffer changed bigger - if (nb_max_buf <= nb_buffer) { + if (nb_resize_buf <= nb_buffer) { return; } int start = p - buffer; - int cap = end - p; - - char* buf = new char[nb_max_buf]; - if (cap > 0) { - memcpy(buf, buffer, nb_buffer); - } - srs_freep(buffer); + int nb_bytes = end - p; - buffer = buf; + buffer = (char*)realloc(buffer, nb_resize_buf); + nb_buffer = nb_resize_buf; p = buffer + start; - end = p + cap; -} - -SrsFastBuffer::~SrsFastBuffer() -{ - srs_freep(buffer); + end = p + nb_bytes; } char SrsFastBuffer::read_1byte() @@ -117,12 +115,6 @@ char* SrsFastBuffer::read_slice(int size) char* ptr = p; p += size; - - // reset when consumed all. - if (p == end) { - p = end = buffer; - srs_verbose("all consumed, reset fast buffer"); - } return ptr; } @@ -138,7 +130,7 @@ int SrsFastBuffer::grow(ISrsBufferReader* reader, int required_size) { int ret = ERROR_SUCCESS; - // generally the required size is ok. + // already got required size of bytes. if (end - p >= required_size) { return ret; } @@ -146,31 +138,42 @@ int SrsFastBuffer::grow(ISrsBufferReader* reader, int required_size) // must be positive. srs_assert(required_size > 0); - // when read payload or there is no space to read, - // reset the buffer with exists bytes. - int max_to_read = buffer + nb_buffer - end; - if (required_size > SRS_RTMP_MAX_MESSAGE_HEADER || max_to_read < required_size) { - int nb_cap = end - p; - srs_verbose("move fast buffer %d bytes", nb_cap); - if (nb_cap < nb_buffer) { - buffer = (char*)memmove(buffer, p, nb_cap); + // the free space of buffer, + // buffer = consumed_bytes + exists_bytes + free_space. + int nb_free_space = buffer + nb_buffer - end; + // resize the space when no left space. + if (nb_free_space < required_size) { + // the bytes already in buffer + int nb_exists_bytes = end - p; + srs_assert(nb_exists_bytes >= 0); + srs_verbose("move fast buffer %d bytes", nb_exists_bytes); + + if (!nb_exists_bytes) { + // reset when buffer is empty. + p = end = buffer; + srs_verbose("all consumed, reset fast buffer"); + } else { + // move the left bytes to start of buffer. + srs_assert(nb_exists_bytes < nb_buffer); + buffer = (char*)memmove(buffer, p, nb_exists_bytes); p = buffer; - end = p + nb_cap; + end = p + nb_exists_bytes; } } - // directly check the available bytes to read in buffer. - max_to_read = buffer + nb_buffer - end; - if (max_to_read < required_size) { + // check whether enough free space in buffer. + nb_free_space = buffer + nb_buffer - end; + if (nb_free_space < required_size) { ret = ERROR_READER_BUFFER_OVERFLOW; - srs_error("buffer overflow, required=%d, max=%d, ret=%d", required_size, nb_buffer, ret); + srs_error("buffer overflow, required=%d, max=%d, left=%d, ret=%d", + required_size, nb_buffer, nb_free_space, ret); return ret; } // buffer is ok, read required size of bytes. while (end - p < required_size) { ssize_t nread; - if ((ret = reader->read(end, max_to_read, &nread)) != ERROR_SUCCESS) { + if ((ret = reader->read(end, nb_free_space, &nread)) != ERROR_SUCCESS) { return ret; } @@ -189,7 +192,7 @@ int SrsFastBuffer::grow(ISrsBufferReader* reader, int required_size) // we just move the ptr to next. srs_assert((int)nread > 0); end += nread; - max_to_read -= nread; + nb_free_space -= nread; } return ret; diff --git a/trunk/src/protocol/srs_rtmp_buffer.hpp b/trunk/src/protocol/srs_rtmp_buffer.hpp index 912417d5b..336d8f924 100644 --- a/trunk/src/protocol/srs_rtmp_buffer.hpp +++ b/trunk/src/protocol/srs_rtmp_buffer.hpp @@ -59,6 +59,12 @@ public: /** * the buffer provices bytes cache for protocol. generally, * protocol recv data from socket, put into buffer, decode to RTMP message. +* Usage: +* ISrsBufferReader* r = ......; +* SrsFastBuffer* fb = ......; +* fb->grow(r, 1024); +* char* header = fb->read_slice(100); +* char* payload = fb->read_payload(924); */ // TODO: FIXME: add utest for it. class SrsFastBuffer @@ -79,7 +85,7 @@ private: // ptr to the buffer. // buffer <= p <= end <= buffer+nb_buffer char* buffer; - // the max size of buffer. + // the size of buffer. int nb_buffer; public: SrsFastBuffer(); @@ -97,7 +103,7 @@ public: virtual char* bytes(); /** * create buffer with specifeid size. - * @param buffer the size of buffer. + * @param buffer the size of buffer. ignore when smaller than SRS_MAX_SOCKET_BUFFER. * @remark when MR(SRS_PERF_MERGED_READ) disabled, always set to 8K. * @remark when buffer changed, the previous ptr maybe invalid. * @see https://github.com/winlinvip/simple-rtmp-server/issues/241 @@ -112,8 +118,8 @@ public: /** * read a slice in size bytes, move to next bytes. * user can use this char* ptr directly, and should never free it. - * @remark assert buffer already grow(size). - * @remark the ptr returned maybe invalid after grow(x). + * @remark user can use the returned ptr util grow(size), + * for the ptr returned maybe invalid after grow(x). */ virtual char* read_slice(int size); /**