From 35717646cd8fab7120546bcfc84f1cdee273ea3f Mon Sep 17 00:00:00 2001
From: Cary Tetrick <cary.tetrick@gmail.com>
Date: Wed, 11 Feb 2015 18:40:46 -0600
Subject: [PATCH] Topic: Socket options for librtmp

This reimplements a change authored by Brian Brice <bbrice@gmail.com> 2015-01-19
"librtmp: Allow changing the socket send buffer size"
(Brian is aware of this change).
also negates change by Michael Niedermayer <michaelni@gmx.at>  2015-01-23 10:45:35
"avformat/librtmp: Fix build with --disable-network --enable-librtmp"
because it is no longer necessary.

The reason for this is that the socket settings changes need to be made in librtmp
internally because:
  1. librtmp may attemp a new socket connection internally.
     in that case, it would not get the buffer settings.
  2. if using the tee muxer to send to more than one destination, the arguments
     can't be passed through the flv muxer. passing them as key-value paires in
	 the manner already supported in librtmp works for that use case.

A patch has been sent to the librtmp mailing list rtmpdump@mplayerhq.hu
with the title "subject: librtmp arguments added for socket buffer size".

*This* patch is dependent on the one above, and should be applied after it
appears in the git://git.ffmpeg.org/rtmpdump repository.

Options to the ffmpeg commandline in support of now arguments in librtmp.
    rtmp_buffer_size - sets rtmp socket send buffer size in bytes.
        this is the same as the patch it replaces.
    rtmp_nodelay - on or off. defaults to on.
        allows users to control whether nagel is active.
	rtmp_buffchunks - on or off. default is off.
        allows users to try using internal buffering instead of writing 128 byte
		chunks to sockets.

See this thread on Zeranoe forum:
http://ffmpeg.zeranoe.com/forum/viewtopic.php?f=7&t=657&p=7823#p7823

I believe this addresses case 1604 on the ffmpeg tracker.
"Summary of the bug: Rtmp output to justin.tv fps continually drops, ..."
- note the memory problem mentioned had been fixed. This fix only applies if
librtmp is enabled.
https://trac.ffmpeg.org/ticket/1604

Defualt behavior leaves things unchanged. Users must employ options intentionally.

Changes to be committed:
    modified:   libavformat/librtmp.c
---
 libavformat/librtmp.c | 39 +++++++++++++++++++++++++--------------
 1 file changed, 25 insertions(+), 14 deletions(-)

diff --git a/libavformat/librtmp.c b/libavformat/librtmp.c
index bfa9a71..36652b5 100644
--- a/libavformat/librtmp.c
+++ b/libavformat/librtmp.c
@@ -28,9 +28,6 @@
 #include "libavutil/mathematics.h"
 #include "libavutil/opt.h"
 #include "avformat.h"
-#if CONFIG_NETWORK
-#include "network.h"
-#endif
 #include "url.h"
 
 #include <librtmp/rtmp.h>
@@ -51,7 +48,9 @@ typedef struct LibRTMPContext {
     char *client_buffer_time;
     int live;
     char *temp_filename;
-    int buffer_size;
+    char *buffer_size;
+    int tcp_nodelay;
+    int buf_chunks;
 } LibRTMPContext;
 
 static void rtmp_log(int level, const char *fmt, va_list args)
@@ -155,6 +154,13 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
             len += strlen(ctx->swfurl);
     }
 
+    if (ctx->buffer_size)
+        len += strlen(ctx->buffer_size) + sizeof(" sndBuffer=");
+    if (ctx->tcp_nodelay == 0)
+        len += sizeof(" tcpNodelay=0");
+    if (ctx->buf_chunks)
+        len += sizeof(" bufferChunks=1");
+
     if (!(ctx->temp_filename = filename = av_malloc(len)))
         return AVERROR(ENOMEM);
 
@@ -209,6 +215,14 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
         av_strlcat(filename, " buffer=", len);
         av_strlcat(filename, ctx->client_buffer_time, len);
     }
+    if (ctx->buffer_size) {
+        av_strlcat(filename, " sndBuffer=", len);
+        av_strlcat(filename, ctx->buffer_size, len);
+    }
+    if (ctx->tcp_nodelay == 0)
+        av_strlcat(filename, " tcpNodelay=0", len);
+    if (ctx->buf_chunks)
+        av_strlcat(filename, " bufferChunks=1", len);
     if (ctx->swfurl || ctx->swfverify) {
         av_strlcat(filename, " swfUrl=", len);
 
@@ -234,13 +248,6 @@ static int rtmp_open(URLContext *s, const char *uri, int flags)
         goto fail;
     }
 
-#if CONFIG_NETWORK
-    if (ctx->buffer_size >= 0 && (flags & AVIO_FLAG_WRITE)) {
-        int tmp = ctx->buffer_size;
-        setsockopt(r->m_sb.sb_socket, SOL_SOCKET, SO_SNDBUF, &tmp, sizeof(tmp));
-    }
-#endif
-
     s->is_streamed = 1;
     return 0;
 fail:
@@ -322,9 +329,13 @@ static const AVOption options[] = {
     {"rtmp_swfurl", "URL of the SWF player. By default no value will be sent", OFFSET(swfurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
     {"rtmp_swfverify", "URL to player swf file, compute hash/size automatically. (unimplemented)", OFFSET(swfverify), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC},
     {"rtmp_tcurl", "URL of the target stream. Defaults to proto://host[:port]/app.", OFFSET(tcurl), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, DEC|ENC},
-#if CONFIG_NETWORK
-    {"rtmp_buffer_size", "set buffer size in bytes", OFFSET(buffer_size), AV_OPT_TYPE_INT, {.i64 = -1}, -1, INT_MAX, DEC|ENC },
-#endif
+    {"rtmp_buffer_size", "set buffer size in bytes. Otherwise, use system default.", OFFSET(buffer_size), AV_OPT_TYPE_STRING, {.str = NULL }, 0, 0, ENC},
+    {"rtmp_nodelay", "use TCP_NODELAY", OFFSET(tcp_nodelay), AV_OPT_TYPE_INT, {.i64 = 1}, 0, 1, ENC, "rtmp_nodelay"},
+    {"off", "nagel algorithm active", 0, AV_OPT_TYPE_CONST, {.i64 = 0}, 0, 0, ENC, "rtmp_nodelay"},
+    {"on", "nagel algorithm disabled. Diabled by default.", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, ENC, "rtmp_nodelay"},
+    {"rtmp_bufchunks", "buffer rtmp chunks before sending packet.", OFFSET(buf_chunks), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, ENC, "rtmp_bufchunks"},
+    {"off", "write each rtmp chuck to socket. Off by default.", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, ENC, "rtmp_bufchunks"},
+    {"on", "buffer all rtmp chunks in packet", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, ENC, "rtmp_bufchunks"},
     { NULL },
 };
 
-- 
1.9.4.msysgit.2

