Blame view

trunk/src/rtmp/srs_protocol_buffer.cpp 5.3 KB
winlin authored
1 2 3
/*
The MIT License (MIT)
4
Copyright (c) 2013-2014 winlin
winlin authored
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23

Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
the Software without restriction, including without limitation the rights to
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
24
#include <srs_protocol_buffer.hpp>
winlin authored
25
26
#include <srs_kernel_error.hpp>
27
#include <srs_kernel_log.hpp>
28
#include <srs_kernel_utility.hpp>
29
#include <srs_core_performance.hpp>
winlin authored
30
31
// the default recv buffer size
32
#define SRS_DEFAULT_RECV_BUFFER_SIZE 32768
33
34 35 36 37
// the max header size,
// @see SrsProtocol::read_message_header().
#define SRS_RTMP_MAX_MESSAGE_HEADER 11
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
SrsSimpleBuffer::SrsSimpleBuffer()
{
}

SrsSimpleBuffer::~SrsSimpleBuffer()
{
}

int SrsSimpleBuffer::length()
{
    int len = (int)data.size();
    srs_assert(len >= 0);
    return len;
}

char* SrsSimpleBuffer::bytes()
{
    return (length() == 0)? NULL : &data.at(0);
}

void SrsSimpleBuffer::erase(int size)
{
    if (size <= 0) {
        return;
    }
    
    if (size >= length()) {
        data.clear();
        return;
    }
    
    data.erase(data.begin(), data.begin() + size);
}

void SrsSimpleBuffer::append(const char* bytes, int size)
{
    srs_assert(size > 0);

    data.insert(data.end(), bytes, bytes + size);
}
79
#ifdef SRS_PERF_MERGED_READ
80 81 82 83 84 85 86
IMergeReadHandler::IMergeReadHandler()
{
}

IMergeReadHandler::~IMergeReadHandler()
{
}
87
#endif
winlin authored
88
89
SrsFastBuffer::SrsFastBuffer()
winlin authored
90
{
91
#ifdef SRS_PERF_MERGED_READ
92 93
    merged_read = false;
    _handler = NULL;
94
#endif
95
    
96
    nb_buffer = SRS_DEFAULT_RECV_BUFFER_SIZE;
97 98
    buffer = new char[nb_buffer];
    p = end = buffer;
winlin authored
99 100
}
101 102 103 104 105 106 107 108 109 110 111
void SrsFastBuffer::set_buffer(int buffer_size)
{
    // only realloc when buffer changed bigger
    if (buffer_size <= nb_buffer) {
        return;
    }
    
    int start = p - buffer;
    int cap = end - p;
    
    char* buf = new char[buffer_size];
112 113 114
    if (cap > 0) {
        memcpy(buf, buffer, nb_buffer);
    }
115 116 117 118 119 120 121
    srs_freep(buffer);
    
    buffer = buf;
    p = buffer + start;
    end = p + cap;
}
122
SrsFastBuffer::~SrsFastBuffer()
winlin authored
123
{
124
    srs_freep(buffer);
winlin authored
125 126
}
127
char SrsFastBuffer::read_1byte()
winlin authored
128
{
129 130
    srs_assert(end - p >= 1);
    return *p++;
winlin authored
131 132
}
133
char* SrsFastBuffer::read_slice(int size)
134
{
135 136
    srs_assert(end - p >= size);
    srs_assert(p + size > buffer);
137
    
138 139
    char* ptr = p;
    p += size;
140
    
141 142 143 144 145 146 147
    // reset when consumed all.
    if (p == end) {
        p = end = buffer;
        srs_verbose("all consumed, reset fast buffer");
    }

    return ptr;
winlin authored
148 149
}
150
void SrsFastBuffer::skip(int size)
winlin authored
151
{
152 153 154
    srs_assert(end - p >= size);
    srs_assert(p + size > buffer);
    p += size;
winlin authored
155 156
}
157
int SrsFastBuffer::grow(ISrsBufferReader* reader, int required_size)
winlin authored
158
{
159 160 161 162 163 164 165 166
    int ret = ERROR_SUCCESS;

    if (required_size < 0) {
        ret = ERROR_SYSTEM_SIZE_NEGATIVE;
        srs_error("size is negative. size=%d, ret=%d", required_size, ret);
        return ret;
    }
167
    // when read payload and need to grow, reset buffer.
168 169 170 171 172
    // or there is no space to read.
    int max_to_read = buffer + nb_buffer - end;
    if (end - p < required_size 
        && (required_size > SRS_RTMP_MAX_MESSAGE_HEADER || max_to_read < required_size)
    ) {
173 174
        int nb_cap = end - p;
        srs_verbose("move fast buffer %d bytes", nb_cap);
175 176 177 178 179
        if (nb_cap < nb_buffer) {
            buffer = (char*)memmove(buffer, p, nb_cap);
            p = buffer;
            end = p + nb_cap;
        }
180 181 182 183
    }

    while (end - p < required_size) {
        // the max to read is the left bytes.
184
        max_to_read = buffer + nb_buffer - end;
185 186 187 188 189 190 191
        
        if (max_to_read <= 0) {
            ret = ERROR_RTMP_BUFFER_OVERFLOW;
            srs_error("buffer overflow, required=%d, max=%d, ret=%d", required_size, nb_buffer, ret);
            return ret;
        }
        
192
        ssize_t nread;
193
        if ((ret = reader->read(end, max_to_read, &nread)) != ERROR_SUCCESS) {
194
            return ret;
195 196
        }
        
197
#ifdef SRS_PERF_MERGED_READ
198 199 200 201 202 203 204
        /**
        * to improve read performance, merge some packets then read,
        * when it on and read small bytes, we sleep to wait more data.,
        * that is, we merge some data to read together.
        * @see https://github.com/winlinvip/simple-rtmp-server/issues/241
        */
        if (merged_read && _handler) {
205
            _handler->on_read(nread);
206
        }
207
#endif
208
        
209
        // we just move the ptr to next.
210
        srs_assert((int)nread > 0);
211
        end += nread;
212 213 214
    }
    
    return ret;
winlin authored
215 216
}
217
#ifdef SRS_PERF_MERGED_READ
218
void SrsFastBuffer::set_merge_read(bool v, IMergeReadHandler* handler)
219 220 221 222
{
    merged_read = v;
    _handler = handler;
}
223
#endif
224