Trying to reattach patch
11.11.2015 22:01, Pavel Meshkov пишет:
We added UDP output constant bitrate functionality.
Please review patch.
P.S.: It's first patch we send. Please notify me if something made wrong.
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel
From 5d870287a26746dcb0c738b54fd62230285a49af Mon Sep 17 00:00:00 2001
From: Pavel Meshkov <pmesh...@kwikflixtv.com>
Date: Sun, 8 Nov 2015 04:12:25 +0000
Subject: [PATCH] Added "cbr" and "cbr_burst" options for udp output. Related
Trac ticket 4155
---
doc/protocols.texi | 24 ++++++++++++++++++++++--
libavformat/udp.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++--
2 files changed, 72 insertions(+), 4 deletions(-)
diff --git a/doc/protocols.texi b/doc/protocols.texi
index 7c6b9d4..f2fb9dc 100644
--- a/doc/protocols.texi
+++ b/doc/protocols.texi
@@ -1293,6 +1293,19 @@ Explicitly allow or disallow UDP broadcasting.
Note that broadcasting may not work properly on networks having
a broadcast storm protection.
+
+@item cbr=@var{size}
+Set output constant bitrate size in bites.
+
+Bitrate estimation starts from first packet. It means that accuracy rises in
time.
+If a lot of late packets will comes they will be sent emmidiatly. To avoid this
+behaiour see at @code{cbr_burst} option.
+
+@item cbr_burst=@var{size}
+Set output constant bitrate maximum burst in bites. Set max speed
+between two UDP packets.
+
+Recommended value is @code{cbr + 5%}
@end table
@subsection Examples
@@ -1306,9 +1319,16 @@ ffmpeg -i @var{input} -f @var{format}
udp://@var{hostname}:@var{port}
@item
Use @command{ffmpeg} to stream in mpegts format over UDP using 188
-sized UDP packets, using a large input buffer:
+sized UDP packets, using a large input buffer (pkt_size is 188*7=1316):
+@example
+ffmpeg -i @var{input} -f mpegts
udp://@var{hostname}:@var{port}?pkt_size=1316&buffer_size=65535
+@end example
+
+@item
+Use @command{ffmpeg} to stream in mpegts format over UDP using 188
+sized UDP packets, using a large input buffer and constant bitrate output with
5% bitrate burst:
@example
-ffmpeg -i @var{input} -f mpegts
udp://@var{hostname}:@var{port}?pkt_size=188&buffer_size=65535
+ffmpeg -i @var{input} -f mpegts
udp://@var{hostname}:@var{port}?pkt_size=188&buffer_size=65535&cbr=2000000&cbr_burst=2100000
@end example
@item
diff --git a/libavformat/udp.c b/libavformat/udp.c
index 1bda5af..80c346a 100644
--- a/libavformat/udp.c
+++ b/libavformat/udp.c
@@ -76,6 +76,8 @@ typedef struct UDPContext {
const AVClass *class;
int udp_fd;
int ttl;
+ int cbr;
+ int cbr_burst;
int udplite_coverage;
int buffer_size;
int pkt_size;
@@ -88,6 +90,10 @@ typedef struct UDPContext {
int dest_addr_len;
int is_connected;
+ int64_t total_packet_size;
+ int64_t time_start;
+ int64_t time_last_packet;
+
/* Circular Buffer variables for use in UDP receive code */
int circular_buffer_size;
AVFifoBuffer *fifo;
@@ -117,6 +123,8 @@ static const AVOption options[] = {
{ "localaddr", "Local address",
OFFSET(localaddr), AV_OPT_TYPE_STRING, { .str = NULL },
.flags = D|E },
{ "udplite_coverage", "choose UDPLite head size which should be validated
by checksum", OFFSET(udplite_coverage), AV_OPT_TYPE_INT, {.i64 = 0}, 0,
INT_MAX, D|E },
{ "pkt_size", "Maximum UDP packet size",
OFFSET(pkt_size), AV_OPT_TYPE_INT, { .i64 = 1472 }, -1, INT_MAX,
.flags = D|E },
+ { "cbr", "Force CBR (in bites)",
OFFSET(cbr), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, E },
+ { "cbr_burst", "CBR burst (in bites). Must be greater than 'cbr'",
OFFSET(cbr_burst), AV_OPT_TYPE_INT, { .i64 = 0 }, -1, INT_MAX, E },
{ "reuse", "explicitly allow reusing UDP sockets",
OFFSET(reuse_socket), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1, D|E
},
{ "reuse_socket", "explicitly allow reusing UDP sockets",
OFFSET(reuse_socket), AV_OPT_TYPE_INT, { .i64 = -1 }, -1, 1,
.flags = D|E },
{ "broadcast", "explicitly allow or disallow broadcast destination",
OFFSET(is_broadcast), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, E },
@@ -150,7 +158,6 @@ static void log_net_error(void *ctx, int level, const char*
prefix)
av_strerror(ff_neterrno(), errbuf, sizeof(errbuf));
av_log(ctx, level, "%s: %s\n", prefix, errbuf);
}
-
static int udp_set_multicast_ttl(int sockfd, int mcastTTL,
struct sockaddr *addr)
{
@@ -178,7 +185,6 @@ static int udp_join_multicast_group(int sockfd, struct
sockaddr *addr,struct soc
#ifdef IP_ADD_MEMBERSHIP
if (addr->sa_family == AF_INET) {
struct ip_mreq mreq;
-
mreq.imr_multiaddr.s_addr = ((struct sockaddr_in
*)addr)->sin_addr.s_addr;
if (local_addr)
mreq.imr_interface= ((struct sockaddr_in *)local_addr)->sin_addr;
@@ -626,6 +632,22 @@ static int udp_open(URLContext *h, const char *uri, int
flags)
if (av_find_info_tag(buf, sizeof(buf), "pkt_size", p)) {
s->pkt_size = strtol(buf, NULL, 10);
}
+ if (av_find_info_tag(buf, sizeof(buf), "cbr", p)) {
+ s->cbr = strtol(buf, NULL, 10);
+ }
+ if (av_find_info_tag(buf, sizeof(buf), "cbr_burst", p)) {
+ s->cbr_burst = strtol(buf, NULL, 10);
+ if (s->cbr > s->cbr_burst) {
+ av_log(h, AV_LOG_ERROR,
+ "'cbr_burst' value must be greater than 'cbr'\n");
+ goto fail;
+ }
+ if (s->cbr == 0) {
+ av_log(h, AV_LOG_WARNING,
+ "'cbr' option is required for 'cbr_burst'. "
+ "'cbr_burst' will be ignored\n");
+ }
+ }
if (av_find_info_tag(buf, sizeof(buf), "buffer_size", p)) {
s->buffer_size = strtol(buf, NULL, 10);
}
@@ -669,6 +691,9 @@ static int udp_open(URLContext *h, const char *uri, int
flags)
}
h->rw_timeout = s->timeout;
+ /* set start total_packet_size for cbr */
+ s->total_packet_size = 0;
+
/* fill the dest addr */
av_url_split(NULL, 0, NULL, 0, hostname, sizeof(hostname), &port, NULL, 0,
uri);
@@ -935,6 +960,26 @@ static int udp_write(URLContext *h, const uint8_t *buf,
int size)
return ret;
}
+ if (s->cbr > 0) {
+ if (s->total_packet_size == 0) {
+ s->time_start = av_gettime();
+ s->time_last_packet = 0;
+ }
+
+ s->total_packet_size += size;
+
+ if((s->cbr_burst > 0) && (s->time_last_packet > 0)) {
+ while (((int64_t)size * 8 * 1000000) > ( (int64_t)s->cbr_burst *
(av_gettime() - s->time_last_packet)) ) {
+ av_usleep(10);
+ }
+ }
+
+ /* 8 is to convert to bits, 1000000 is 1 second in microseconds (usec)
*/
+ while ((s->total_packet_size * 8 * 1000000) > ((int64_t)s->cbr *
(av_gettime() - s->time_start))) {
+ av_usleep(10);
+ }
+ }
+
if (!s->is_connected) {
ret = sendto (s->udp_fd, buf, size, 0,
(struct sockaddr *) &s->dest_addr,
@@ -942,6 +987,9 @@ static int udp_write(URLContext *h, const uint8_t *buf, int
size)
} else
ret = send(s->udp_fd, buf, size, 0);
+ if ( s->cbr_burst > 0 )
+ s->time_last_packet = av_gettime();
+
return ret < 0 ? ff_neterrno() : ret;
}
--
1.9.1
_______________________________________________
ffmpeg-devel mailing list
ffmpeg-devel@ffmpeg.org
http://ffmpeg.org/mailman/listinfo/ffmpeg-devel