sched: Allow more than one running scheduler instance.
[paraslash.git] / vss.c
diff --git a/vss.c b/vss.c
index e336a9e7413d469c71a6221cab0e86b0aae24867..17d46919b53ea962aa7c52a6c2ed88d251f1dbf7 100644 (file)
--- a/vss.c
+++ b/vss.c
 #include "server.cmdline.h"
 #include "list.h"
 #include "send.h"
+#include "sched.h"
 #include "vss.h"
 #include "ipc.h"
 #include "fd.h"
-#include "sched.h"
 
 extern struct misc_meta_data *mmd;
 
@@ -361,8 +361,17 @@ static void vss_get_chunk(int chunk_num, struct vss_task *vsst,
 static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
                int max_bytes)
 {
+       char *buf;
+       size_t len;
        int i, max_chunks = PARA_MAX(1LU, 150 / tv2ms(vss_chunk_time()));
 
+       if (g->first_chunk == 0) {
+               g->num_chunks = 1;
+               vss_get_chunk(0, vsst, &buf, &len);
+               g->bytes = len;
+               return;
+       }
+
        g->num_chunks = 0;
        g->bytes = 0;
        /*
@@ -372,8 +381,6 @@ static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
         * of exactly one chunk for these audio formats.
         */
        for (i = 0;; i++) {
-               char *buf;
-               size_t len;
                int chunk_num = g->first_chunk + i;
 
                if (g->bytes > 0 && i >= max_chunks) /* duration limit */
@@ -502,7 +509,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
 {
        int ret, i, k, n, data_slices;
        size_t len;
-       char *buf;
+       char *buf, *p;
        struct fec_group *g = &fc->group;
 
        if (fc->state == FEC_STATE_NONE) {
@@ -562,16 +569,20 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
                assert(i == g->num_header_slices - 1);
        }
 
-       /* setup data slices */
+       /*
+        * Setup data slices. Note that for ogg streams chunk 0 points to a
+        * buffer on the heap rather than to the mapped audio file.
+        */
        vss_get_chunk(g->first_chunk, vsst, &buf, &len);
-       for (; i < g->num_header_slices + data_slices; i++) {
-               if (buf + g->slice_bytes > vsst->map + mmd->size) {
+       for (p = buf; i < g->num_header_slices + data_slices; i++) {
+               if (p + g->slice_bytes > buf + g->bytes) {
                        /*
-                        * Can not use the memory mapped audio file for this
-                        * slice as it goes beyond the map.
+                        * We must make a copy for this slice since using p
+                        * directly would exceed the buffer.
                         */
-                       uint32_t payload_size = vsst->map + mmd->size - buf;
-                       memcpy(fc->extra_src_buf, buf, payload_size);
+                       uint32_t payload_size = buf + g->bytes - p;
+                       assert(payload_size + FEC_HEADER_SIZE <= fc->mps);
+                       memcpy(fc->extra_src_buf, p, payload_size);
                        if (payload_size < g->slice_bytes)
                                memset(fc->extra_src_buf + payload_size, 0,
                                        g->slice_bytes - payload_size);
@@ -579,8 +590,8 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
                        i++;
                        break;
                }
-               fc->src_data[i] = (const unsigned char *)buf;
-               buf += g->slice_bytes;
+               fc->src_data[i] = (const unsigned char *)p;
+               p += g->slice_bytes;
        }
        if (i < k) {
                /* use arbitrary data for all remaining slices */
@@ -1079,8 +1090,6 @@ static void vss_send(struct vss_task *vsst)
                        senders[i].send(mmd->current_chunk, mmd->chunks_sent,
                                buf, len, vsst->header_buf, vsst->header_len);
                }
-               mmd->chunks_sent++;
-               mmd->current_chunk++;
                /*
                 * Prefault next chunk(s)
                 *
@@ -1093,11 +1102,15 @@ static void vss_send(struct vss_task *vsst)
                 * eliminate the delays completely. Moreover, it is supported
                 * only on Linux. So we do our own read-ahead here.
                 */
-               buf += len;
-               for (i = 0; i < 5 && buf < vsst->map + mmd->size; i++) {
-                       __a_unused volatile char x = *buf;
-                       buf += 4096;
+               if (mmd->current_chunk > 0) { /* chunk 0 might be on the heap */
+                       buf += len;
+                       for (i = 0; i < 5 && buf < vsst->map + mmd->size; i++) {
+                               __a_unused volatile char x = *buf;
+                               buf += 4096;
+                       }
                }
+               mmd->chunks_sent++;
+               mmd->current_chunk++;
        }
 }
 
@@ -1144,11 +1157,12 @@ static void vss_post_select(struct sched *s, struct task *t)
  * Initialize the virtual streaming system task.
  *
  * \param afs_socket The fd for communication with afs.
+ * \param s The scheduler to register the vss task to.
  *
  * This also initializes all supported senders and starts streaming
  * if the --autoplay command line flag was given.
  */
-void init_vss_task(int afs_socket)
+void init_vss_task(int afs_socket, struct sched *s)
 {
        static struct vss_task vss_task_struct, *vsst = &vss_task_struct;
        int i;
@@ -1181,5 +1195,5 @@ void init_vss_task(int afs_socket)
                        &vsst->data_send_barrier);
        }
        sprintf(vsst->task.status, "vss task");
-       register_task(&vsst->task);
+       register_task(s, &vsst->task);
 }