diff mbox series

[FFmpeg-devel,v2] libavformat/libsrt.c: Add statistics option to output SRT statistics with av_log()

Message ID 20240319115108.65823-1-ryan@mccartney.info
State New
Headers show
Series [FFmpeg-devel,v2] libavformat/libsrt.c: Add statistics option to output SRT statistics with av_log() | expand

Checks

Context Check Description
yinshiyou/make_loongarch64 success Make finished
yinshiyou/make_fate_loongarch64 success Make fate finished
andriy/make_x86 success Make finished
andriy/make_fate_x86 success Make fate finished

Commit Message

Ryan McCartney March 19, 2024, 11:51 a.m. UTC
---
 libavformat/libsrt.c | 37 +++++++++++++++++++++++++++++++++++++
 1 file changed, 37 insertions(+)

Comments

Zhao Zhili April 2, 2024, 2:45 p.m. UTC | #1
> 在 2024年3月19日,下午7:51,Ryan McCartney <ryan@mccartney.info> 写道:
> 
> ---
> libavformat/libsrt.c | 37 +++++++++++++++++++++++++++++++++++++
> 1 file changed, 37 insertions(+)
> 
> diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c
> index a7aafea536..80d52b1737 100644
> --- a/libavformat/libsrt.c
> +++ b/libavformat/libsrt.c
> @@ -56,6 +56,8 @@ typedef struct SRTContext {
>     int eid;
>     int64_t rw_timeout;
>     int64_t listen_timeout;
> +    int64_t lastStatsTime;
> +    int64_t stats;
>     int recv_buffer_size;
>     int send_buffer_size;
> 
> @@ -100,6 +102,7 @@ typedef struct SRTContext {
> static const AVOption libsrt_options[] = {
>     { "timeout",        "Timeout of socket I/O operations (in microseconds)",                   OFFSET(rw_timeout),       AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
>     { "listen_timeout", "Connection awaiting timeout (in microseconds)" ,                       OFFSET(listen_timeout),   AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
> +    { "stats",          "Show SRT statistics in the log output",                                OFFSET(stats),            AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },  
>     { "send_buffer_size", "Socket send buffer size (in bytes)",                                 OFFSET(send_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
>     { "recv_buffer_size", "Socket receive buffer size (in bytes)",                              OFFSET(recv_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
>     { "pkt_size",       "Maximum SRT packet size",                                              OFFSET(payload_size),     AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, SRT_LIVE_MAX_PAYLOAD_SIZE, .flags = D|E, .unit = "payload_size" },
> @@ -158,6 +161,29 @@ static int libsrt_neterrno(URLContext *h)
>     return os_errno ? AVERROR(os_errno) : AVERROR_UNKNOWN;
> }
> 
> +static int libsrt_stats(URLContext *h,int read)
> +{   
> +    SRTContext *s = h->priv_data;
> +    SRT_TRACEBSTATS trace;
> +
> +    int ret = srt_bistats(s->fd, &trace, 0,1);
> +    int64_t timeNow = trace.msTimeStamp;
> +    int64_t timeNext = s->lastStatsTime + s->stats;
> +
> +    if((ret >= 0) && (timeNow > timeNext )){
> +        s->lastStatsTime = timeNow;
> +
> +        if(read > 0){
> +            av_log(h, AV_LOG_INFO, "[srt-stats] rate=%.2fMbps bw=%.2fMbps rtt=%.2fms total=%jdpkts retrans=%jdpkts loss=%jdpkts \n", trace.mbpsRecvRate,trace.mbpsBandwidth,trace.msRTT,trace.pktRecvTotal,trace.pktRcvRetrans,trace.pktRcvLossTotal);
> +        }
> +        else{
> +            av_log(h, AV_LOG_INFO, "[srt-stats] rate=%.2fMbps bw=%.2fMbps rtt=%.2fms total=%jdpkts retrans=%jdpkts loss=%jdpkts \n", trace.mbpsSendRate,trace.mbpsBandwidth,trace.msRTT,trace.pktSentTotal,trace.pktRetrans,trace.pktSndLossTotal);
> +        }
> +    }
> +
> +    return 0;
> +}

The implementation is simple but not flexible enough. We need more than print. I have this issue on my mind but don’t figure out a solution yet.

> +
> static int libsrt_getsockopt(URLContext *h, int fd, SRT_SOCKOPT optname, const char * optnamestr, void * optval, int * optlen)
> {
>     if (srt_getsockopt(fd, 0, optname, optval, optlen) < 0) {
> @@ -557,6 +583,9 @@ static int libsrt_open(URLContext *h, const char *uri, int flags)
>                 goto err;
>             }
>         }
> +        if (av_find_info_tag(buf, sizeof(buf), "stats", p)) {
> +            s->stats = strtol(buf, NULL, 10);
> +        }
> #if SRT_VERSION_VALUE >= 0x010302
>         if (av_find_info_tag(buf, sizeof(buf), "enforced_encryption", p)) {
>             s->enforced_encryption = strtol(buf, NULL, 10);
> @@ -686,6 +715,10 @@ static int libsrt_read(URLContext *h, uint8_t *buf, int size)
>     SRTContext *s = h->priv_data;
>     int ret;
> 
> +    if(s->stats > 0){
> +        libsrt_stats(h,1);
> +    }
> +
>     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
>         ret = libsrt_network_wait_fd_timeout(h, s->eid, 0, h->rw_timeout, &h->interrupt_callback);
>         if (ret)
> @@ -705,6 +738,10 @@ static int libsrt_write(URLContext *h, const uint8_t *buf, int size)
>     SRTContext *s = h->priv_data;
>     int ret;
> 
> +    if(s->stats > 0){
> +        libsrt_stats(h,0);
> +    }
> +
>     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
>         ret = libsrt_network_wait_fd_timeout(h, s->eid, 1, h->rw_timeout, &h->interrupt_callback);
>         if (ret)
> -- 
> 2.43.0
> 
> 
> _______________________________________________
> ffmpeg-devel mailing list
> ffmpeg-devel@ffmpeg.org
> https://ffmpeg.org/mailman/listinfo/ffmpeg-devel
> 
> To unsubscribe, visit link above, or email
diff mbox series

Patch

diff --git a/libavformat/libsrt.c b/libavformat/libsrt.c
index a7aafea536..80d52b1737 100644
--- a/libavformat/libsrt.c
+++ b/libavformat/libsrt.c
@@ -56,6 +56,8 @@  typedef struct SRTContext {
     int eid;
     int64_t rw_timeout;
     int64_t listen_timeout;
+    int64_t lastStatsTime;
+    int64_t stats;
     int recv_buffer_size;
     int send_buffer_size;
 
@@ -100,6 +102,7 @@  typedef struct SRTContext {
 static const AVOption libsrt_options[] = {
     { "timeout",        "Timeout of socket I/O operations (in microseconds)",                   OFFSET(rw_timeout),       AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
     { "listen_timeout", "Connection awaiting timeout (in microseconds)" ,                       OFFSET(listen_timeout),   AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },
+    { "stats",          "Show SRT statistics in the log output",                                OFFSET(stats),            AV_OPT_TYPE_INT64, { .i64 = -1 }, -1, INT64_MAX, .flags = D|E },  
     { "send_buffer_size", "Socket send buffer size (in bytes)",                                 OFFSET(send_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
     { "recv_buffer_size", "Socket receive buffer size (in bytes)",                              OFFSET(recv_buffer_size), AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, INT_MAX,   .flags = D|E },
     { "pkt_size",       "Maximum SRT packet size",                                              OFFSET(payload_size),     AV_OPT_TYPE_INT,      { .i64 = -1 }, -1, SRT_LIVE_MAX_PAYLOAD_SIZE, .flags = D|E, .unit = "payload_size" },
@@ -158,6 +161,29 @@  static int libsrt_neterrno(URLContext *h)
     return os_errno ? AVERROR(os_errno) : AVERROR_UNKNOWN;
 }
 
+static int libsrt_stats(URLContext *h,int read)
+{   
+    SRTContext *s = h->priv_data;
+    SRT_TRACEBSTATS trace;
+
+    int ret = srt_bistats(s->fd, &trace, 0,1);
+    int64_t timeNow = trace.msTimeStamp;
+    int64_t timeNext = s->lastStatsTime + s->stats;
+
+    if((ret >= 0) && (timeNow > timeNext )){
+        s->lastStatsTime = timeNow;
+
+        if(read > 0){
+            av_log(h, AV_LOG_INFO, "[srt-stats] rate=%.2fMbps bw=%.2fMbps rtt=%.2fms total=%jdpkts retrans=%jdpkts loss=%jdpkts \n", trace.mbpsRecvRate,trace.mbpsBandwidth,trace.msRTT,trace.pktRecvTotal,trace.pktRcvRetrans,trace.pktRcvLossTotal);
+        }
+        else{
+            av_log(h, AV_LOG_INFO, "[srt-stats] rate=%.2fMbps bw=%.2fMbps rtt=%.2fms total=%jdpkts retrans=%jdpkts loss=%jdpkts \n", trace.mbpsSendRate,trace.mbpsBandwidth,trace.msRTT,trace.pktSentTotal,trace.pktRetrans,trace.pktSndLossTotal);
+        }
+    }
+
+    return 0;
+}
+
 static int libsrt_getsockopt(URLContext *h, int fd, SRT_SOCKOPT optname, const char * optnamestr, void * optval, int * optlen)
 {
     if (srt_getsockopt(fd, 0, optname, optval, optlen) < 0) {
@@ -557,6 +583,9 @@  static int libsrt_open(URLContext *h, const char *uri, int flags)
                 goto err;
             }
         }
+        if (av_find_info_tag(buf, sizeof(buf), "stats", p)) {
+            s->stats = strtol(buf, NULL, 10);
+        }
 #if SRT_VERSION_VALUE >= 0x010302
         if (av_find_info_tag(buf, sizeof(buf), "enforced_encryption", p)) {
             s->enforced_encryption = strtol(buf, NULL, 10);
@@ -686,6 +715,10 @@  static int libsrt_read(URLContext *h, uint8_t *buf, int size)
     SRTContext *s = h->priv_data;
     int ret;
 
+    if(s->stats > 0){
+        libsrt_stats(h,1);
+    }
+
     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
         ret = libsrt_network_wait_fd_timeout(h, s->eid, 0, h->rw_timeout, &h->interrupt_callback);
         if (ret)
@@ -705,6 +738,10 @@  static int libsrt_write(URLContext *h, const uint8_t *buf, int size)
     SRTContext *s = h->priv_data;
     int ret;
 
+    if(s->stats > 0){
+        libsrt_stats(h,0);
+    }
+
     if (!(h->flags & AVIO_FLAG_NONBLOCK)) {
         ret = libsrt_network_wait_fd_timeout(h, s->eid, 1, h->rw_timeout, &h->interrupt_callback);
         if (ret)