| Index: patched-ffmpeg-mt/libavformat/rtmpproto.c
|
| ===================================================================
|
| --- patched-ffmpeg-mt/libavformat/rtmpproto.c (revision 41250)
|
| +++ patched-ffmpeg-mt/libavformat/rtmpproto.c (working copy)
|
| @@ -72,6 +72,9 @@
|
| int flv_size; ///< current buffer size
|
| int flv_off; ///< number of bytes read from current buffer
|
| RTMPPacket out_pkt; ///< rtmp packet, created from flv a/v or metadata (for output)
|
| + uint32_t client_report_size; ///< number of bytes after which client should report to server
|
| + uint32_t bytes_read; ///< number of bytes read from server
|
| + uint32_t last_bytes_read; ///< number of bytes read last reported to server
|
| } RTMPContext;
|
|
|
| #define PLAYER_KEY_OPEN_PART_LEN 30 ///< length of partial key used for first client digest signing
|
| @@ -110,7 +113,7 @@
|
| ff_rtmp_packet_create(&pkt, RTMP_SYSTEM_CHANNEL, RTMP_PT_INVOKE, 0, 4096);
|
| p = pkt.data;
|
|
|
| - snprintf(tcurl, sizeof(tcurl), "%s://%s:%d/%s", proto, host, port, rt->app);
|
| + ff_url_join(tcurl, sizeof(tcurl), proto, NULL, host, port, "/%s", rt->app);
|
| ff_amf_write_string(&p, "connect");
|
| ff_amf_write_number(&p, 1.0);
|
| ff_amf_write_object_start(&p);
|
| @@ -337,6 +340,21 @@
|
| ff_rtmp_packet_destroy(&pkt);
|
| }
|
|
|
| +/**
|
| + * Generates report on bytes read so far and sends it to the server.
|
| + */
|
| +static void gen_bytes_read(URLContext *s, RTMPContext *rt, uint32_t ts)
|
| +{
|
| + RTMPPacket pkt;
|
| + uint8_t *p;
|
| +
|
| + ff_rtmp_packet_create(&pkt, RTMP_NETWORK_CHANNEL, RTMP_PT_BYTES_READ, ts, 4);
|
| + p = pkt.data;
|
| + bytestream_put_be32(&p, rt->bytes_read);
|
| + ff_rtmp_packet_write(rt->stream, &pkt, rt->chunk_size, rt->prev_pkt[1]);
|
| + ff_rtmp_packet_destroy(&pkt);
|
| +}
|
| +
|
| //TODO: Move HMAC code somewhere. Eventually.
|
| #define HMAC_IPAD_VAL 0x36
|
| #define HMAC_OPAD_VAL 0x5C
|
| @@ -556,6 +574,16 @@
|
| if (t == 6)
|
| gen_pong(s, rt, pkt);
|
| break;
|
| + case RTMP_PT_CLIENT_BW:
|
| + if (pkt->data_size < 4) {
|
| + av_log(LOG_CONTEXT, AV_LOG_ERROR,
|
| + "Client bandwidth report packet is less than 4 bytes long (%d)\n",
|
| + pkt->data_size);
|
| + return -1;
|
| + }
|
| + av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Client bandwidth = %d\n", AV_RB32(pkt->data));
|
| + rt->client_report_size = AV_RB32(pkt->data) >> 1;
|
| + break;
|
| case RTMP_PT_INVOKE:
|
| //TODO: check for the messages sent for wrong state?
|
| if (!memcmp(pkt->data, "\002\000\006_error", 9)) {
|
| @@ -669,6 +697,12 @@
|
| return AVERROR(EIO);
|
| }
|
| }
|
| + rt->bytes_read += ret;
|
| + if (rt->bytes_read > rt->last_bytes_read + rt->client_report_size) {
|
| + av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Sending bytes read report\n");
|
| + gen_bytes_read(s, rt, rpkt.timestamp + 1);
|
| + rt->last_bytes_read = rt->bytes_read;
|
| + }
|
|
|
| ret = rtmp_parse_result(s, rt, &rpkt);
|
| if (ret < 0) {//serious error in current packet
|
| @@ -778,12 +812,12 @@
|
| s->priv_data = rt;
|
| rt->is_input = !(flags & URL_WRONLY);
|
|
|
| - url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
|
| - path, sizeof(path), s->filename);
|
| + ff_url_split(proto, sizeof(proto), NULL, 0, hostname, sizeof(hostname), &port,
|
| + path, sizeof(path), s->filename);
|
|
|
| if (port < 0)
|
| port = RTMP_DEFAULT_PORT;
|
| - snprintf(buf, sizeof(buf), "tcp://%s:%d", hostname, port);
|
| + ff_url_join(buf, sizeof(buf), "tcp", NULL, hostname, port, NULL);
|
|
|
| if (url_open(&rt->stream, buf, URL_RDWR) < 0) {
|
| av_log(LOG_CONTEXT, AV_LOG_ERROR, "Cannot open connection %s\n", buf);
|
| @@ -826,6 +860,10 @@
|
| }
|
| strncat(rt->playpath, fname, sizeof(rt->playpath) - 5);
|
|
|
| + rt->client_report_size = 1048576;
|
| + rt->bytes_read = 0;
|
| + rt->last_bytes_read = 0;
|
| +
|
| av_log(LOG_CONTEXT, AV_LOG_DEBUG, "Proto = %s, path = %s, app = %s, fname = %s\n",
|
| proto, path, rt->app, rt->playpath);
|
| gen_connect(s, rt, proto, hostname, port);
|
|
|