]> git.tuebingen.mpg.de Git - paraslash.git/blobdiff - vss.c
Introduce get_header() for ogg/vorbis.
[paraslash.git] / vss.c
diff --git a/vss.c b/vss.c
index 121373dc2f4fb77bb62985d20909b8ccefc972ae..2dab278dfff9c20983e3353e9a86a7147904262a 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -1,5 +1,5 @@
 /*
- * Copyright (C) 1997-2010 Andre Noll <maan@systemlinux.org>
+ * Copyright (C) 1997-2011 Andre Noll <maan@systemlinux.org>
  *
  * Licensed under the GPL v2. For licencing details see COPYING.
  */
@@ -86,7 +86,7 @@ struct vss_task {
        /** Used by the scheduler. */
        struct task task;
        /** Pointer to the header of the mapped audio file. */
-       const char *header_buf;
+       char *header_buf;
        /** Length of the audio file header. */
        size_t header_len;
        /** Time between audio file headers are sent. */
@@ -167,6 +167,8 @@ struct fec_client {
        struct timeval next_header_time;
        /** Used for the last source pointer of an audio file. */
        unsigned char *extra_src_buf;
+       /** Needed for the last slice of the audio file header. */
+       unsigned char *extra_header_buf;
        /** Extra slices needed to store largest chunk + header. */
        int num_extra_slices;
        /** Contains the FEC-encoded data. */
@@ -211,10 +213,11 @@ static void write_fec_header(struct fec_client *fc, struct vss_task *vsst)
        write_u32(buf + 14, g->bytes);
 
        write_u8(buf + 18, fc->current_slice_num);
+       write_u8(buf + 19, 0); /* unused */
        write_u16(buf + 20, g->slice_bytes);
        write_u8(buf + 22, g->first_chunk? 0 : 1);
        write_u8(buf + 23, vsst->header_len? 1 : 0);
-       memset(buf + 24, 0, 7);
+       memset(buf + 24, 0, 8);
 }
 
 static bool need_audio_header(struct fec_client *fc, struct vss_task *vsst)
@@ -326,6 +329,7 @@ static int initialize_fec_client(struct fec_client *fc, struct vss_task *vsst)
        fc->src_data = para_realloc(fc->src_data, k * sizeof(char *));
        fc->enc_buf = para_realloc(fc->enc_buf, fc->mps);
        fc->extra_src_buf = para_realloc(fc->extra_src_buf, fc->mps);
+       fc->extra_header_buf = para_realloc(fc->extra_header_buf, fc->mps);
 
        fc->state = FEC_STATE_READY_TO_RUN;
        fc->next_header_time.tv_sec = 0;
@@ -515,12 +519,27 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
        fc->current_slice_num = 0;
        if (g->num == 0)
                set_group_timing(fc, vsst);
-
        /* setup header slices */
        buf = vsst->header_buf;
        for (i = 0; i < g->num_header_slices; i++) {
-               fc->src_data[i] = (const unsigned char *)buf;
-               buf += g->slice_bytes;
+               if (buf + g->slice_bytes <= vsst->header_buf + vsst->header_len) {
+                       fc->src_data[i] = (const unsigned char *)buf;
+                       buf += g->slice_bytes;
+                       continue;
+               }
+               /*
+                * Can not use vss->header_buf for this slice as it
+                * goes beyond the buffer. This slice will not be fully
+                * used.
+                */
+               uint32_t payload_size = vsst->header_buf
+                       + vsst->header_len - buf;
+               memcpy(fc->extra_header_buf, buf, payload_size);
+               if (payload_size < g->slice_bytes)
+                       memset(fc->extra_header_buf + payload_size, 0,
+                               g->slice_bytes - payload_size);
+               fc->src_data[i] = fc->extra_header_buf;
+               assert(i == g->num_header_slices - 1);
        }
 
        /* setup data slices */
@@ -529,8 +548,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
                if (buf + g->slice_bytes > vsst->map + mmd->size) {
                        /*
                         * Can not use the memory mapped audio file for this
-                        * slice as it goes beyond the map. This slice will not
-                        * be fully used.
+                        * slice as it goes beyond the map.
                         */
                        uint32_t payload_size = vsst->map + mmd->size - buf;
                        memcpy(fc->extra_src_buf, buf, payload_size);
@@ -626,6 +644,7 @@ void vss_del_fec_client(struct fec_client *fc)
        free(fc->src_data);
        free(fc->enc_buf);
        free(fc->extra_src_buf);
+       free(fc->extra_header_buf);
        fec_free(fc->parms);
        free(fc);
 }
@@ -806,6 +825,8 @@ static void vss_eof(struct vss_task *vsst)
        if (mmd->new_vss_status_flags & VSS_NOMORE)
                mmd->new_vss_status_flags = VSS_NEXT;
        set_eof_barrier(vsst);
+       afh_free_header(vsst->header_buf, mmd->afd.audio_format_id);
+       vsst->header_buf = NULL;
        para_munmap(vsst->map, mmd->size);
        vsst->map = NULL;
        mmd->chunks_sent = 0;
@@ -984,8 +1005,8 @@ static void recv_afs_result(struct vss_task *vsst, fd_set *rfds)
        mmd->events++;
        mmd->num_played++;
        mmd->new_vss_status_flags &= (~VSS_NEXT);
-       afh_get_header(&mmd->afd.afhi, vsst->map, &vsst->header_buf,
-               &vsst->header_len);
+       afh_get_header(&mmd->afd.afhi, mmd->afd.audio_format_id,
+               vsst->map, mmd->size, &vsst->header_buf, &vsst->header_len);
        return;
 err:
        free(mmd->afd.afhi.chunk_table);