vss: Use the stripped header also at stream start.
authorAndre Noll <maan@systemlinux.org>
Mon, 1 Nov 2010 08:28:11 +0000 (09:28 +0100)
committerAndre Noll <maan@systemlinux.org>
Sat, 29 Jan 2011 10:43:34 +0000 (11:43 +0100)
For ogg vorbis streams the stripped header is computed when a new audio file is
opened, but chunk zero, the unmodified header, is used for the first FEC group.
This not only wastes bandwidth but might cause vss to abort because the length
of the real header was not taken into account when computing the FEC
parameters.

Solve this by introducing vss_get_chunk() which returns either the stripped
header or calls afh_get_chunk() to obtain a reference to a "real" chunk.

vss.c

diff --git a/vss.c b/vss.c
index 2dab278..940e923 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -338,6 +338,26 @@ static int initialize_fec_client(struct fec_client *fc, struct vss_task *vsst)
        return 1;
 }
 
+static void vss_get_chunk(int chunk_num, struct vss_task *vsst,
+               char **buf, size_t *sz)
+{
+       /*
+        * Chunk zero is special for header streams: It is the first portion of
+        * the audio file which consists of the audio file header. It may be
+        * arbitrary large due to embedded meta data. Audio format handlers may
+        * replace the header by a stripped one with meta data omitted which is
+        * of bounded size. We always use the stripped header for streaming
+        * rather than the unmodified header (chunk zero).
+        */
+       if (chunk_num == 0 && vsst->header_len > 0) {
+               *buf = vsst->header_buf; /* stripped header */
+               *sz = vsst->header_len;
+               return;
+       }
+       afh_get_chunk(chunk_num, &mmd->afd.afhi, vsst->map, (const char **)buf,
+               sz);
+}
+
 static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
                int max_bytes)
 {
@@ -352,7 +372,7 @@ 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++) {
-               const char *buf;
+               char *buf;
                size_t len;
                int chunk_num = g->first_chunk + i;
 
@@ -360,7 +380,7 @@ static void compute_group_size(struct vss_task *vsst, struct fec_group *g,
                        break;
                if (chunk_num >= mmd->afd.afhi.chunks_total) /* eof */
                        break;
-               afh_get_chunk(chunk_num, &mmd->afd.afhi, vsst->map, &buf, &len);
+               vss_get_chunk(chunk_num, vsst, &buf, &len);
                if (g->bytes + len > max_bytes)
                        break;
                /* Include this chunk */
@@ -482,7 +502,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;
-       const char *buf;
+       char *buf;
        struct fec_group *g = &fc->group;
 
        if (fc->state == FEC_STATE_NONE) {
@@ -543,7 +563,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
        }
 
        /* setup data slices */
-       afh_get_chunk(g->first_chunk, &mmd->afd.afhi, vsst->map, &buf, &len);
+       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) {
                        /*
@@ -1062,7 +1082,7 @@ static void vss_send(struct vss_task *vsst)
        compute_chunk_time(mmd->chunks_sent, &mmd->afd.afhi.chunk_tv,
                &mmd->stream_start, &due);
        if (tv_diff(&due, now, NULL) <= 0) {
-               const char *buf;
+               char *buf;
                size_t len;
 
                if (!mmd->chunks_sent) {
@@ -1075,8 +1095,7 @@ static void vss_send(struct vss_task *vsst)
                 * they might have still some data queued which can be sent in
                 * this case.
                 */
-               afh_get_chunk(mmd->current_chunk, &mmd->afd.afhi, vsst->map,
-                       &buf, &len);
+               vss_get_chunk(mmd->current_chunk, vsst, &buf, &len);
                for (i = 0; senders[i].name; i++) {
                        if (!senders[i].send)
                                continue;