Commit 953dd723 authored by Michael Niedermayer's avatar Michael Niedermayer

Merge commit '84a125c4'

* commit '84a125c4':
  rtmp: Allocate the prev_pkt arrays dynamically
Merged-by: 's avatarMichael Niedermayer <michaelni@gmx.at>
parents 1d4476d5 84a125c4
...@@ -129,20 +129,42 @@ int ff_amf_read_null(GetByteContext *bc) ...@@ -129,20 +129,42 @@ int ff_amf_read_null(GetByteContext *bc)
return 0; return 0;
} }
int ff_rtmp_check_alloc_array(RTMPPacket **prev_pkt, int *nb_prev_pkt,
int channel)
{
int nb_alloc;
RTMPPacket *ptr;
if (channel < *nb_prev_pkt)
return 0;
nb_alloc = channel + 16;
// This can't use the av_reallocp family of functions, since we
// would need to free each element in the array before the array
// itself is freed.
ptr = av_realloc_array(*prev_pkt, nb_alloc, sizeof(**prev_pkt));
if (!ptr)
return AVERROR(ENOMEM);
memset(ptr + *nb_prev_pkt, 0, (nb_alloc - *nb_prev_pkt) * sizeof(*ptr));
*prev_pkt = ptr;
*nb_prev_pkt = nb_alloc;
return 0;
}
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
int chunk_size, RTMPPacket *prev_pkt) int chunk_size, RTMPPacket **prev_pkt, int *nb_prev_pkt)
{ {
uint8_t hdr; uint8_t hdr;
if (ffurl_read(h, &hdr, 1) != 1) if (ffurl_read(h, &hdr, 1) != 1)
return AVERROR(EIO); return AVERROR(EIO);
return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt, hdr); return ff_rtmp_packet_read_internal(h, p, chunk_size, prev_pkt,
nb_prev_pkt, hdr);
} }
static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
int chunk_size, RTMPPacket *prev_pkt, int chunk_size, RTMPPacket **prev_pkt_ptr,
uint8_t hdr) int *nb_prev_pkt, uint8_t hdr)
{ {
uint8_t buf[16]; uint8_t buf[16];
...@@ -151,6 +173,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, ...@@ -151,6 +173,7 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
enum RTMPPacketType type; enum RTMPPacketType type;
int written = 0; int written = 0;
int ret, toread; int ret, toread;
RTMPPacket *prev_pkt;
written++; written++;
channel_id = hdr & 0x3F; channel_id = hdr & 0x3F;
...@@ -162,6 +185,10 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, ...@@ -162,6 +185,10 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
written += channel_id + 1; written += channel_id + 1;
channel_id = AV_RL16(buf) + 64; channel_id = AV_RL16(buf) + 64;
} }
if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
channel_id)) < 0)
return ret;
prev_pkt = *prev_pkt_ptr;
size = prev_pkt[channel_id].size; size = prev_pkt[channel_id].size;
type = prev_pkt[channel_id].type; type = prev_pkt[channel_id].type;
extra = prev_pkt[channel_id].extra; extra = prev_pkt[channel_id].extra;
...@@ -252,10 +279,12 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p, ...@@ -252,10 +279,12 @@ static int rtmp_packet_read_one_chunk(URLContext *h, RTMPPacket *p,
} }
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
RTMPPacket *prev_pkt, uint8_t hdr) RTMPPacket **prev_pkt, int *nb_prev_pkt,
uint8_t hdr)
{ {
while (1) { while (1) {
int ret = rtmp_packet_read_one_chunk(h, p, chunk_size, prev_pkt, hdr); int ret = rtmp_packet_read_one_chunk(h, p, chunk_size, prev_pkt,
nb_prev_pkt, hdr);
if (ret > 0 || ret != AVERROR(EAGAIN)) if (ret > 0 || ret != AVERROR(EAGAIN))
return ret; return ret;
...@@ -265,13 +294,20 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, ...@@ -265,13 +294,20 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
} }
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt, int ff_rtmp_packet_write(URLContext *h, RTMPPacket *pkt,
int chunk_size, RTMPPacket *prev_pkt) int chunk_size, RTMPPacket **prev_pkt_ptr,
int *nb_prev_pkt)
{ {
uint8_t pkt_hdr[16], *p = pkt_hdr; uint8_t pkt_hdr[16], *p = pkt_hdr;
int mode = RTMP_PS_TWELVEBYTES; int mode = RTMP_PS_TWELVEBYTES;
int off = 0; int off = 0;
int written = 0; int written = 0;
int ret; int ret;
RTMPPacket *prev_pkt;
if ((ret = ff_rtmp_check_alloc_array(prev_pkt_ptr, nb_prev_pkt,
pkt->channel_id)) < 0)
return ret;
prev_pkt = *prev_pkt_ptr;
pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp; pkt->ts_delta = pkt->timestamp - prev_pkt[pkt->channel_id].timestamp;
......
...@@ -114,10 +114,12 @@ void ff_rtmp_packet_destroy(RTMPPacket *pkt); ...@@ -114,10 +114,12 @@ void ff_rtmp_packet_destroy(RTMPPacket *pkt);
* @param chunk_size current chunk size * @param chunk_size current chunk size
* @param prev_pkt previously read packet headers for all channels * @param prev_pkt previously read packet headers for all channels
* (may be needed for restoring incomplete packet header) * (may be needed for restoring incomplete packet header)
* @param nb_prev_pkt number of allocated elements in prev_pkt
* @return number of bytes read on success, negative value otherwise * @return number of bytes read on success, negative value otherwise
*/ */
int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
int chunk_size, RTMPPacket *prev_pkt); int chunk_size, RTMPPacket **prev_pkt,
int *nb_prev_pkt);
/** /**
* Read internal RTMP packet sent by the server. * Read internal RTMP packet sent by the server.
* *
...@@ -126,11 +128,13 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p, ...@@ -126,11 +128,13 @@ int ff_rtmp_packet_read(URLContext *h, RTMPPacket *p,
* @param chunk_size current chunk size * @param chunk_size current chunk size
* @param prev_pkt previously read packet headers for all channels * @param prev_pkt previously read packet headers for all channels
* (may be needed for restoring incomplete packet header) * (may be needed for restoring incomplete packet header)
* @param nb_prev_pkt number of allocated elements in prev_pkt
* @param c the first byte already read * @param c the first byte already read
* @return number of bytes read on success, negative value otherwise * @return number of bytes read on success, negative value otherwise
*/ */
int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
RTMPPacket *prev_pkt, uint8_t c); RTMPPacket **prev_pkt, int *nb_prev_pkt,
uint8_t c);
/** /**
* Send RTMP packet to the server. * Send RTMP packet to the server.
...@@ -140,10 +144,12 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size, ...@@ -140,10 +144,12 @@ int ff_rtmp_packet_read_internal(URLContext *h, RTMPPacket *p, int chunk_size,
* @param chunk_size current chunk size * @param chunk_size current chunk size
* @param prev_pkt previously sent packet headers for all channels * @param prev_pkt previously sent packet headers for all channels
* (may be used for packet header compressing) * (may be used for packet header compressing)
* @param nb_prev_pkt number of allocated elements in prev_pkt
* @return number of bytes written on success, negative value otherwise * @return number of bytes written on success, negative value otherwise
*/ */
int ff_rtmp_packet_write(URLContext *h, RTMPPacket *p, int ff_rtmp_packet_write(URLContext *h, RTMPPacket *p,
int chunk_size, RTMPPacket *prev_pkt); int chunk_size, RTMPPacket **prev_pkt,
int *nb_prev_pkt);
/** /**
* Print information and contents of RTMP packet. * Print information and contents of RTMP packet.
...@@ -153,6 +159,16 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *p, ...@@ -153,6 +159,16 @@ int ff_rtmp_packet_write(URLContext *h, RTMPPacket *p,
*/ */
void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p); void ff_rtmp_packet_dump(void *ctx, RTMPPacket *p);
/**
* Enlarge the prev_pkt array to fit the given channel
*
* @param prev_pkt array with previously sent packet headers
* @param nb_prev_pkt number of allocated elements in prev_pkt
* @param channel the channel number that needs to be allocated
*/
int ff_rtmp_check_alloc_array(RTMPPacket **prev_pkt, int *nb_prev_pkt,
int channel);
/** /**
* @name Functions used to work with the AMF format (which is also used in .flv) * @name Functions used to work with the AMF format (which is also used in .flv)
* @see amf_* funcs in libavformat/flvdec.c * @see amf_* funcs in libavformat/flvdec.c
......
...@@ -77,7 +77,8 @@ typedef struct TrackedMethod { ...@@ -77,7 +77,8 @@ typedef struct TrackedMethod {
typedef struct RTMPContext { typedef struct RTMPContext {
const AVClass *class; const AVClass *class;
URLContext* stream; ///< TCP stream used in interactions with RTMP server URLContext* stream; ///< TCP stream used in interactions with RTMP server
RTMPPacket prev_pkt[2][RTMP_CHANNELS]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing) RTMPPacket *prev_pkt[2]; ///< packet history used when reading and sending packets ([0] for reading, [1] for writing)
int nb_prev_pkt[2]; ///< number of elements in prev_pkt
int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into int in_chunk_size; ///< size of the chunks incoming RTMP packets are divided into
int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into int out_chunk_size; ///< size of the chunks outgoing RTMP packets are divided into
int is_input; ///< input/output flag int is_input; ///< input/output flag
...@@ -238,7 +239,7 @@ static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track) ...@@ -238,7 +239,7 @@ static int rtmp_send_packet(RTMPContext *rt, RTMPPacket *pkt, int track)
} }
ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
fail: fail:
ff_rtmp_packet_destroy(pkt); ff_rtmp_packet_destroy(pkt);
return ret; return ret;
...@@ -405,7 +406,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -405,7 +406,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
GetByteContext gbc; GetByteContext gbc;
if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size, if ((ret = ff_rtmp_packet_read(rt->stream, &pkt, rt->in_chunk_size,
rt->prev_pkt[0])) < 0) &rt->prev_pkt[0], &rt->nb_prev_pkt[0])) < 0)
return ret; return ret;
cp = pkt.data; cp = pkt.data;
bytestream2_init(&gbc, cp, pkt.size); bytestream2_init(&gbc, cp, pkt.size);
...@@ -441,7 +442,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -441,7 +442,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
bytestream_put_be32(&p, rt->server_bw); bytestream_put_be32(&p, rt->server_bw);
pkt.size = p - pkt.data; pkt.size = p - pkt.data;
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -454,7 +455,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -454,7 +455,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
bytestream_put_byte(&p, 2); // dynamic bytestream_put_byte(&p, 2); // dynamic
pkt.size = p - pkt.data; pkt.size = p - pkt.data;
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -468,7 +469,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -468,7 +469,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
bytestream_put_be16(&p, 0); // 0 -> Stream Begin bytestream_put_be16(&p, 0); // 0 -> Stream Begin
bytestream_put_be32(&p, 0); bytestream_put_be32(&p, 0);
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -481,7 +482,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -481,7 +482,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
p = pkt.data; p = pkt.data;
bytestream_put_be32(&p, rt->out_chunk_size); bytestream_put_be32(&p, rt->out_chunk_size);
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -516,7 +517,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -516,7 +517,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
pkt.size = p - pkt.data; pkt.size = p - pkt.data;
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -531,7 +532,7 @@ static int read_connect(URLContext *s, RTMPContext *rt) ...@@ -531,7 +532,7 @@ static int read_connect(URLContext *s, RTMPContext *rt)
ff_amf_write_number(&p, 8192); ff_amf_write_number(&p, 8192);
pkt.size = p - pkt.data; pkt.size = p - pkt.data;
ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &pkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&pkt); ff_rtmp_packet_destroy(&pkt);
return ret; return ret;
...@@ -1452,7 +1453,7 @@ static int handle_chunk_size(URLContext *s, RTMPPacket *pkt) ...@@ -1452,7 +1453,7 @@ static int handle_chunk_size(URLContext *s, RTMPPacket *pkt)
/* Send the same chunk size change packet back to the server, /* Send the same chunk size change packet back to the server,
* setting the outgoing chunk size to the same as the incoming one. */ * setting the outgoing chunk size to the same as the incoming one. */
if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size, if ((ret = ff_rtmp_packet_write(rt->stream, pkt, rt->out_chunk_size,
rt->prev_pkt[1])) < 0) &rt->prev_pkt[1], &rt->nb_prev_pkt[1])) < 0)
return ret; return ret;
rt->out_chunk_size = AV_RB32(pkt->data); rt->out_chunk_size = AV_RB32(pkt->data);
} }
...@@ -1781,7 +1782,7 @@ static int write_begin(URLContext *s) ...@@ -1781,7 +1782,7 @@ static int write_begin(URLContext *s)
bytestream2_put_be32(&pbc, rt->nb_streamid); bytestream2_put_be32(&pbc, rt->nb_streamid);
ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&spkt); ff_rtmp_packet_destroy(&spkt);
...@@ -1828,7 +1829,7 @@ static int write_status(URLContext *s, RTMPPacket *pkt, ...@@ -1828,7 +1829,7 @@ static int write_status(URLContext *s, RTMPPacket *pkt,
spkt.size = pp - spkt.data; spkt.size = pp - spkt.data;
ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&spkt); ff_rtmp_packet_destroy(&spkt);
return ret; return ret;
...@@ -1929,7 +1930,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt) ...@@ -1929,7 +1930,7 @@ static int send_invoke_response(URLContext *s, RTMPPacket *pkt)
} }
spkt.size = pp - spkt.data; spkt.size = pp - spkt.data;
ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size, ret = ff_rtmp_packet_write(rt->stream, &spkt, rt->out_chunk_size,
rt->prev_pkt[1]); &rt->prev_pkt[1], &rt->nb_prev_pkt[1]);
ff_rtmp_packet_destroy(&spkt); ff_rtmp_packet_destroy(&spkt);
return ret; return ret;
} }
...@@ -2259,7 +2260,8 @@ static int get_packet(URLContext *s, int for_header) ...@@ -2259,7 +2260,8 @@ static int get_packet(URLContext *s, int for_header)
for (;;) { for (;;) {
RTMPPacket rpkt = { 0 }; RTMPPacket rpkt = { 0 };
if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt, if ((ret = ff_rtmp_packet_read(rt->stream, &rpkt,
rt->in_chunk_size, rt->prev_pkt[0])) <= 0) { rt->in_chunk_size, &rt->prev_pkt[0],
&rt->nb_prev_pkt[0])) <= 0) {
if (ret == 0) { if (ret == 0) {
return AVERROR(EAGAIN); return AVERROR(EAGAIN);
} else { } else {
...@@ -2340,9 +2342,11 @@ static int rtmp_close(URLContext *h) ...@@ -2340,9 +2342,11 @@ static int rtmp_close(URLContext *h)
} }
if (rt->state > STATE_HANDSHAKED) if (rt->state > STATE_HANDSHAKED)
ret = gen_delete_stream(h, rt); ret = gen_delete_stream(h, rt);
for (i = 0; i < 2; i++) for (i = 0; i < 2; i++) {
for (j = 0; j < RTMP_CHANNELS; j++) for (j = 0; j < rt->nb_prev_pkt[i]; j++)
ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]); ff_rtmp_packet_destroy(&rt->prev_pkt[i][j]);
av_freep(&rt->prev_pkt[i]);
}
free_tracked_methods(rt); free_tracked_methods(rt);
av_freep(&rt->flv_data); av_freep(&rt->flv_data);
...@@ -2563,11 +2567,14 @@ reconnect: ...@@ -2563,11 +2567,14 @@ reconnect:
goto fail; goto fail;
if (rt->do_reconnect) { if (rt->do_reconnect) {
int i;
ffurl_close(rt->stream); ffurl_close(rt->stream);
rt->stream = NULL; rt->stream = NULL;
rt->do_reconnect = 0; rt->do_reconnect = 0;
rt->nb_invokes = 0; rt->nb_invokes = 0;
memset(rt->prev_pkt, 0, sizeof(rt->prev_pkt)); for (i = 0; i < 2; i++)
memset(rt->prev_pkt[i], 0,
sizeof(**rt->prev_pkt) * rt->nb_prev_pkt[i]);
free_tracked_methods(rt); free_tracked_methods(rt);
goto reconnect; goto reconnect;
} }
...@@ -2688,6 +2695,10 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) ...@@ -2688,6 +2695,10 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
pkttype == RTMP_PT_NOTIFY) { pkttype == RTMP_PT_NOTIFY) {
if (pkttype == RTMP_PT_NOTIFY) if (pkttype == RTMP_PT_NOTIFY)
pktsize += 16; pktsize += 16;
if ((ret = ff_rtmp_check_alloc_array(&rt->prev_pkt[1],
&rt->nb_prev_pkt[1],
channel)) < 0)
return ret;
rt->prev_pkt[1][channel].channel_id = 0; rt->prev_pkt[1][channel].channel_id = 0;
} }
...@@ -2748,7 +2759,8 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size) ...@@ -2748,7 +2759,8 @@ static int rtmp_write(URLContext *s, const uint8_t *buf, int size)
if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt, if ((ret = ff_rtmp_packet_read_internal(rt->stream, &rpkt,
rt->in_chunk_size, rt->in_chunk_size,
rt->prev_pkt[0], c)) <= 0) &rt->prev_pkt[0],
&rt->nb_prev_pkt[0], c)) <= 0)
return ret; return ret;
if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0) if ((ret = rtmp_parse_result(s, rt, &rpkt)) < 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment