vss: Avoid large FEC parameters for the DCCP transport.
authorAndre Noll <maan@systemlinux.org>
Mon, 1 Nov 2010 15:30:22 +0000 (16:30 +0100)
committerAndre Noll <maan@systemlinux.org>
Sat, 27 Nov 2010 08:32:44 +0000 (09:32 +0100)
Now that for DCCP streams the audio file header is sent only once at client
connect time, we can go one step further and send the header as its own FEC
group. Then all subsequent FEC groups contain data slices only, hence the
maximal required size for a FEC group reduces from

header_size + largest_chunk_size

to

max(header_size, largest_chunk_size)

This patch introduces a new helper function need_data_slices() which returns
false only at the beginning of a DCCP stream. In this case FEC group 0 consists
of the header only and an arbitrary time interval of 200ms is used for this
group.

vss.c

diff --git a/vss.c b/vss.c
index 8c16c95..121373d 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -237,6 +237,19 @@ static bool need_audio_header(struct fec_client *fc, struct vss_task *vsst)
        return true;
 }
 
+static bool need_data_slices(struct fec_client *fc, struct vss_task *vsst)
+{
+       if (fc->group.num > 0)
+               return true;
+       if (!vsst->header_buf)
+               return true;
+       if (vsst->header_len == 0)
+               return true;
+       if (fc->fcp->need_periodic_header)
+               return true;
+       return false;
+}
+
 static int num_slices(long unsigned bytes, int max_payload, int rs)
 {
        int ret;
@@ -250,11 +263,15 @@ static int num_slices(long unsigned bytes, int max_payload, int rs)
 }
 
 /* set group start and group duration */
-static void set_group_timing(struct fec_client *fc, struct fec_group *g)
+static void set_group_timing(struct fec_client *fc, struct vss_task *vsst)
 {
+       struct fec_group *g = &fc->group;
        struct timeval *chunk_tv = vss_chunk_time();
 
-       tv_scale(g->num_chunks, chunk_tv, &g->duration);
+       if (!need_data_slices(fc, vsst))
+               ms2tv(200, &g->duration);
+       else
+               tv_scale(g->num_chunks, chunk_tv, &g->duration);
        tv_divide(fc->fcp->slices_per_group + fc->num_extra_slices,
                &g->duration, &g->slice_duration);
        PARA_DEBUG_LOG("durations (group/chunk/slice): %lu/%lu/%lu\n",
@@ -292,7 +309,10 @@ static int initialize_fec_client(struct fec_client *fc, struct vss_task *vsst)
        if (ret < 0)
                return ret;
        ds = ret;
-       k = hs + ds;
+       if (fc->fcp->need_periodic_header)
+               k = hs + ds;
+       else
+               k = PARA_MAX(hs, ds);
        if (k < fc->fcp->data_slices_per_group)
                k = fc->fcp->data_slices_per_group;
        fc->num_extra_slices = k - fc->fcp->data_slices_per_group;
@@ -411,6 +431,13 @@ static int compute_slice_size(struct fec_client *fc, struct vss_task *vsst)
                        g->slice_bytes = 1;
                return 1;
        }
+       if (!need_data_slices(fc, vsst)) {
+               g->bytes = 0;
+               g->num_chunks = 0;
+               g->slice_bytes = DIV_ROUND_UP(vsst->header_len, k);
+               g->num_header_slices = k;
+               return 1;
+       }
        h = vsst->header_len;
        max_group_bytes = (k - num_slices(h, max_slice_bytes, n - k))
                * max_slice_bytes;
@@ -471,7 +498,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
                 */
                tmp = g->start;
                tv_add(&tmp, &g->duration, &g->start);
-               set_group_timing(fc, g);
+               set_group_timing(fc, vsst);
                g->first_chunk += g->num_chunks;
                g->num++;
        }
@@ -487,7 +514,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
        assert(g->num_header_slices + data_slices <= k);
        fc->current_slice_num = 0;
        if (g->num == 0)
-               set_group_timing(fc, g);
+               set_group_timing(fc, vsst);
 
        /* setup header slices */
        buf = vsst->header_buf;