[libdvbpsi-devel] examples/dvbinfo: limit fifo size

Jean-Paul Saman git at videolan.org
Wed Jun 27 14:29:04 CEST 2012


libdvbpsi | branch: master | Jean-Paul Saman <jean-paul.saman at m2x.nl> | Wed Jun 20 16:37:36 2012 +0200| [41e5a3bd5e326ab1c147aa2f5db1fcaeeb6b3224] | committer: Jean-Paul Saman

examples/dvbinfo: limit fifo size

Implemented a function fifo_size() that returns the current size of the fifo.
The dvbinfo example program uses fifo_size() to detect if the total size of
buffers inside the fifo exceeds a certain threshold. The threshold is currently
defined at compile time.

> http://git.videolan.org/gitweb.cgi/libdvbpsi.git/?a=commit;h=41e5a3bd5e326ab1c147aa2f5db1fcaeeb6b3224
---

 examples/dvbinfo/buffer.c  |   12 ++++++++++++
 examples/dvbinfo/buffer.h  |    2 ++
 examples/dvbinfo/dvbinfo.c |   45 ++++++++++++++++++++++++++++++++++++++++++++
 examples/dvbinfo/dvbinfo.h |    1 +
 4 files changed, 60 insertions(+)

diff --git a/examples/dvbinfo/buffer.c b/examples/dvbinfo/buffer.c
index 6633938..f03a3bb 100644
--- a/examples/dvbinfo/buffer.c
+++ b/examples/dvbinfo/buffer.c
@@ -44,6 +44,7 @@ struct fifo_s
     pthread_cond_t  wait;
     bool       b_force_wake;
     ssize_t    i_count;
+    size_t     i_size; /* fifo size in bytes */
     buffer_t  *p_first;
     buffer_t **pp_last;
 };
@@ -73,6 +74,7 @@ fifo_t *fifo_new(void)
     if (fifo == NULL) return NULL;
 
     fifo->i_count = 0;
+    fifo->i_size = 0;
     fifo->b_force_wake = false;
     fifo->p_first = NULL;
     fifo->pp_last = &fifo->p_first;
@@ -129,6 +131,14 @@ ssize_t fifo_count(fifo_t *fifo)
     return count;
 }
 
+size_t fifo_size(fifo_t *fifo)
+{
+    pthread_mutex_lock(&fifo->lock);
+    size_t size = fifo->i_size;
+    pthread_mutex_unlock(&fifo->lock);
+    return size;
+}
+
 void fifo_push(fifo_t *fifo, buffer_t *buffer)
 {
     buffer_t *p_last;
@@ -148,6 +158,7 @@ void fifo_push(fifo_t *fifo, buffer_t *buffer)
     *fifo->pp_last = buffer;
     fifo->pp_last = &p_last->p_next;
     fifo->i_count += i_depth;
+    fifo->i_size += buffer->i_size;
 
     assert(fifo->p_first != NULL);
     assert(fifo->pp_last  != NULL);
@@ -175,6 +186,7 @@ buffer_t *fifo_pop(fifo_t *fifo)
 
     fifo->p_first = buffer->p_next;
     fifo->i_count--;
+    fifo->i_size -= buffer->i_size;
 
     if (fifo->p_first == NULL)
     {
diff --git a/examples/dvbinfo/buffer.h b/examples/dvbinfo/buffer.h
index 0196510..151f93a 100644
--- a/examples/dvbinfo/buffer.h
+++ b/examples/dvbinfo/buffer.h
@@ -46,6 +46,7 @@ void buffer_free(buffer_t *buffer);
  * fifo_new()  - create a new fifo holding buffer_t pointers
  * fifo_free() - release fifo and all buffers contained therein
  * fifo_count()- number of buffers in fifo_t
+ * fifo_size() - total size of buffers in fifo_t
  * fifo_push() - push buffer at end of fifo
  * fifo_pop()  - pop buffer from start of fifo
  * fifo_wake() - wake up fifo listeners
@@ -53,6 +54,7 @@ void buffer_free(buffer_t *buffer);
 fifo_t *fifo_new(void);
 void fifo_free(fifo_t *fifo);
 ssize_t fifo_count(fifo_t *fifo);
+size_t fifo_size(fifo_t *fifo);
 void fifo_push(fifo_t *fifo, buffer_t *buffer);
 buffer_t *fifo_pop(fifo_t *fifo);
 void fifo_wake(fifo_t *fifo);
diff --git a/examples/dvbinfo/dvbinfo.c b/examples/dvbinfo/dvbinfo.c
index 774041a..a333d0b 100644
--- a/examples/dvbinfo/dvbinfo.c
+++ b/examples/dvbinfo/dvbinfo.c
@@ -64,6 +64,7 @@
 #   include "tcp.h"
 #endif
 
+#define FIFO_THRESHOLD_SIZE (400 * 1024 * 1024) /* threshold in bytes */
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
 
 static const int   i_summary_mode[] = { SUM_BANDWIDTH, SUM_TABLE, SUM_PACKET, SUM_WIRE };
@@ -77,6 +78,10 @@ typedef struct dvbinfo_capture_s
     fifo_t  *fifo;
     fifo_t  *empty;
 
+    pthread_mutex_t lock;
+    pthread_cond_t  fifo_full;
+    bool     b_fifo_full;
+
     size_t   size;  /* prefered capture size */
 
     params_t *params;
@@ -277,6 +282,30 @@ static void *dvbinfo_capture(void *data)
 
         buffer->i_date = mdate();
 
+        /* check fifo size */
+        if (fifo_size(capture->fifo) >= FIFO_THRESHOLD_SIZE)
+        {
+            pthread_mutex_lock(&capture->lock);
+            capture->b_fifo_full = true;
+            pthread_mutex_unlock(&capture->lock);
+
+            if (param->b_file)
+            {
+                /* wait till buffer becomes smaller again */
+                pthread_mutex_lock(&capture->lock);
+                while(capture->b_fifo_full)
+                    pthread_cond_wait(&capture->fifo_full, &capture->lock);
+                pthread_mutex_unlock(&capture->lock);
+            }
+            else
+            {
+                libdvbpsi_log(capture->params, DVBINFO_LOG_ERROR,
+                          "error fifo full discarding buffer");
+                fifo_push(capture->empty, buffer);
+                continue;
+            }
+        }
+
         /* store buffer */
         fifo_push(capture->fifo, buffer);
         buffer = NULL;
@@ -374,6 +403,15 @@ static int dvbinfo_process(dvbinfo_capture_t *capture)
         /* reuse buffer */
         fifo_push(capture->empty, buffer);
         buffer = NULL;
+
+        /* check fifo size */
+        if (fifo_size(capture->fifo) < FIFO_THRESHOLD_SIZE)
+        {
+            pthread_mutex_lock(&capture->lock);
+            capture->b_fifo_full = false;
+            pthread_cond_signal(&capture->fifo_full);
+            pthread_mutex_unlock(&capture->lock);
+        }
     }
 
     libdvbpsi_exit(stream);
@@ -407,6 +445,9 @@ int main(int argc, char **pp_argv)
     capture.params = param;
     capture.fifo = fifo_new();
     capture.empty = fifo_new();
+    capture.b_fifo_full = false;
+    pthread_mutex_init(&capture.lock, NULL);
+    pthread_cond_init(&capture.fifo_full, NULL);
 
     static const struct option long_options[] =
     {
@@ -461,6 +502,7 @@ int main(int argc, char **pp_argv)
                     }
                     /* */
                     param->pf_read = read;
+                    param->b_file = true;
                 }
                 break;
 
@@ -647,6 +689,9 @@ int main(int argc, char **pp_argv)
     fifo_free((&capture)->fifo);
     fifo_free((&capture)->empty);
 
+    pthread_mutex_destroy(&capture.lock);
+    pthread_cond_destroy(&capture.fifo_full);
+
 #ifdef HAVE_SYS_SOCKET_H
     if (param->b_monitor)
         closelog();
diff --git a/examples/dvbinfo/dvbinfo.h b/examples/dvbinfo/dvbinfo.h
index 9ce2815..9c7e472 100644
--- a/examples/dvbinfo/dvbinfo.h
+++ b/examples/dvbinfo/dvbinfo.h
@@ -40,6 +40,7 @@ typedef struct params_s
     int  port;
     bool b_udp;
     bool b_tcp;
+    bool b_file;
 
     /* */
     int  fd_in;



More information about the libdvbpsi-devel mailing list