]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 't/array_size'
authorAndre Noll <maan@systemlinux.org>
Sat, 5 Mar 2011 11:54:28 +0000 (12:54 +0100)
committerAndre Noll <maan@systemlinux.org>
Sat, 5 Mar 2011 11:54:28 +0000 (12:54 +0100)
25 files changed:
Makefile.in
NEWS
afh.c
afh.h
afh_common.c
afs.c
afs.h
aft.c
command.c
configure.ac
crypt.c
depend.sh
error.h
ggo/audiod.m4
gui.c
ogg_afh.c
ogg_afh_common.c
ogg_afh_common.h
oggdec_filter.c
para.h
score.c
server.c
spx_afh.c
vss.c
wma_afh.c

index 3fbbce21ab5f3fe91d674750a4d3f7804c346188..c64b5ae7250ce5cceb178f39089319ae38894a11 100644 (file)
@@ -99,9 +99,10 @@ else
        Q = @
 endif
 
-.PHONY: all clean distclean maintainer-clean install man tarball\
+.PHONY: dep all clean distclean maintainer-clean install man tarball\
        .FORCE-GIT-VERSION-FILE
-all: @executables@ $(man_pages)
+all: dep @executables@ $(man_pages)
+dep: $(deps)
 man: $(man_pages)
 tarball: $(tarball)
 
@@ -224,8 +225,10 @@ all_objs := $(recv_objs) $(filter_objs) $(client_objs) $(gui_objs) \
        $(audiod_objs) $(audioc_objs) $(fade_objs) $(server_objs) \
        $(write_objs) $(afh_objs)
 
+deps := $(all_objs:.o=.d)
+
 ifeq ($(findstring clean, $(MAKECMDGOALS)),)
--include $(all_objs:.o=.d)
+-include $(deps)
 endif
 
 para_recv: $(recv_objs)
diff --git a/NEWS b/NEWS
index dcc4393b517df293c8eb90344d6471af48dab833..4385ebe17b2d64cd5699d82c7db9534c9ef5136c 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,7 @@
          at the beginning of the stream rather than periodically
          every five seconds. This reduces network traffic and the
          FEC group size.
+       - ogg timing fixes and performance improvements
        - aacdec error message cleanups
        - simplified color error handling
        - para_gui: New option --theme to select a startup theme. Several
diff --git a/afh.c b/afh.c
index 5ce6cfc5a13c383030fe10c240eba8468add021c..c5d7aec296a7a44b2fedfd2532ad838f89654e6c 100644 (file)
--- a/afh.c
+++ b/afh.c
@@ -83,15 +83,16 @@ static void print_chunk_table(struct afh_info *afhi)
        }
 }
 
-static int cat_file(void *audio_file_data, struct afh_info *afhi)
+static int cat_file(struct afh_info *afhi, int audio_format_id,
+               void *audio_file_data, size_t audio_file_size)
 {
        int ret;
        struct timeval stream_start;
        long unsigned i, first_chunk, last_chunk;
        const char *buf;
+       char *header;
        size_t size;
 
-
        if (conf.begin_chunk_arg < 0) {
                if (-conf.begin_chunk_arg > afhi->chunks_total)
                        return -ERRNO_TO_PARA_ERROR(EINVAL);
@@ -114,14 +115,18 @@ static int cat_file(void *audio_file_data, struct afh_info *afhi)
                return -ERRNO_TO_PARA_ERROR(EINVAL);
        if (!afhi->chunks_total)
                return 1;
-       afh_get_header(afhi, audio_file_data, &buf, &size);
-       if (size && first_chunk && !conf.no_header_given) {
-               PARA_INFO_LOG("writing audio file header (%zu bytes)\n", size);
-               ret = write(STDOUT_FILENO, buf, size);
-               if (ret < 0)
-                       return ret;
-               if (ret != size)
-                       return -E_AFH_SHORT_WRITE;
+       if (first_chunk > 0 && !conf.no_header_given) {
+               afh_get_header(afhi, audio_format_id, audio_file_data, audio_file_size,
+                       &header, &size);
+               if (size > 0) {
+                       PARA_INFO_LOG("writing header (%zu bytes)\n", size);
+                       ret = write(STDOUT_FILENO, header, size); /* FIXME */
+                       afh_free_header(header, audio_format_id);
+                       if (ret < 0)
+                               return ret;
+                       if (ret != size)
+                               return -E_AFH_SHORT_WRITE;
+               }
        }
        PARA_NOTICE_LOG("writing chunks %lu - %lu\n", first_chunk, last_chunk);
        gettimeofday(&stream_start, NULL);
@@ -184,23 +189,25 @@ int main(int argc, char **argv)
                        fd, &afhi);
                if (ret < 0)
                        goto out;
+
                audio_format_num = ret;
                if (conf.stream_given)
-                       ret = cat_file(audio_file_data, &afhi);
+                       ret = cat_file(&afhi, audio_format_num,
+                               audio_file_data, audio_file_size);
                else {
                        printf("File %d: %s\n", i + 1, conf.inputs[i]);
                        print_info(audio_format_num, &afhi);
                        if (conf.chunk_table_given)
                                print_chunk_table(&afhi);
-                       free(afhi.techinfo);
-                       free(afhi.tags.artist);
-                       free(afhi.tags.title);
-                       free(afhi.tags.year);
-                       free(afhi.tags.album);
-                       free(afhi.tags.comment);
-                       free(afhi.chunk_table);
                        printf("\n");
                }
+               free(afhi.techinfo);
+               free(afhi.tags.artist);
+               free(afhi.tags.title);
+               free(afhi.tags.year);
+               free(afhi.tags.album);
+               free(afhi.tags.comment);
+               free(afhi.chunk_table);
                ret2 = para_munmap(audio_file_data, audio_file_size);
                if (ret2 < 0 && ret >= 0)
                        ret = ret2;
diff --git a/afh.h b/afh.h
index 8f74e236501189de420d1eec75a9a40b952b1707..8b747f8a436b0da18f3cd83a8e90c50e23e7ea83 100644 (file)
--- a/afh.h
+++ b/afh.h
  * for all supported audio formats.
  */
 struct taginfo {
-       /** TPE1 (id3v2) / ARTIST (vorbis) / ©ART (aac) */
+       /** TPE1 (id3v2) / ARTIST (vorbis) / ART (aac)/ author(spx) */
        char *artist;
-       /** TIT2/TITLE/©nam */
+       /** TIT2/TITLE/nam */
        char *title;
-       /** TDRC/YEAR/©day */
+       /** TDRC/YEAR/day */
        char *year;
-       /** TALB/ALBUM/©alb */
+       /** TALB/ALBUM/alb */
        char *album;
-       /** COMM/COMMENT/©cmt */
+       /** COMM/COMMENT/cmt */
        char *comment;
 };
 
@@ -42,11 +42,6 @@ struct afh_info {
        uint32_t *chunk_table;
        /** Period of time between sending data chunks. */
        struct timeval chunk_tv;
-       /**
-        * The position of the header within the audio file. Ignored if \a
-        * header_len equals zero.
-        */
-       uint32_t header_offset;
        /**
         * The header is needed by senders in case a new client connects in the
         * middle of the stream. The length of the header defaults to zero
@@ -95,6 +90,8 @@ struct audio_format_handler {
         */
        int (*get_file_info)(char *map, size_t numbytes, int fd,
                struct afh_info *afi);
+
+       void (*get_header)(void *map, size_t mapsize, char **buf, size_t *len);
 };
 
 void afh_init(void);
@@ -104,4 +101,7 @@ int compute_afhi(const char *path, char *data, size_t size,
 const char *audio_format_name(int);
 void afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
                void *map, const char **buf, size_t *len);
-void afh_get_header(struct afh_info *afhi, void *map, const char **buf, size_t *len);
+uint32_t afh_get_largest_chunk_size(struct afh_info *afhi);
+void afh_get_header(struct afh_info *afhi, uint8_t audio_format_id,
+               void *map, size_t mapsize, char **buf, size_t *len);
+void afh_free_header(char *header_buf, uint8_t audio_format_id);
index dd2ae6507e7510da3d1e57c95e03cda51fbf74ca..7ecab4e47a9bd7e47bcc7e378043d62d663cf343 100644 (file)
@@ -160,7 +160,6 @@ int compute_afhi(const char *path, char *data, size_t size, int fd,
 {
        int ret, i, format;
 
-       afhi->header_offset = 0;
        afhi->header_len = 0;
        afhi->techinfo = NULL;
        afhi->tags.artist = NULL;
@@ -249,21 +248,52 @@ void afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
  * Get the header of an audio file.
  *
  * \param afhi The audio file handler data describing the file.
+ * \param audio_format_id Determines the audio format handler.
  * \param map The data of the audio file.
+ * \param mapsize The amount of bytes of the mmapped audio file.
  * \param buf The length of the header is stored here.
  * \param len Points to a buffer containing the header on return.
  *
  * This function sets \a buf to \p NULL and \a len to zero if \a map or \a
  * afhi is \p NULL, or if the current audio format does not need special
  * header treatment.
+ *
+ * Otherwise, it is checked whether the audio format handler given by
+ * \a audio_format_id defines a ->get_header() method. If it does, this
+ * method is called to obtain the header. If ->get_header() is \p NULL,
+ * a reference to the first chunk of the audio file is returned.
+ *
+ * Once the header is no longer needed, the caller must call \ref
+ * afh_free_header() to free the resources allocated by this function.
  */
-void afh_get_header(struct afh_info *afhi, void *map, const char **buf, size_t *len)
+void afh_get_header(struct afh_info *afhi, uint8_t audio_format_id,
+               void *map, size_t mapsize, char **buf, size_t *len)
 {
+       struct audio_format_handler *afh = afl + audio_format_id;
+
        if (!map || !afhi || !afhi->header_len) {
                *buf = NULL;
                *len = 0;
                return;
        }
-       *len = afhi->header_len;
-       *buf = map + afhi->header_offset;
+       if (!afh->get_header) {
+               *len = afhi->header_len;
+               *buf = map;
+               return;
+       }
+       afh->get_header(map, mapsize, buf, len);
+}
+
+/**
+ * Deallocate any resources obtained from afh_get_header().
+ *
+ * \param header_buf Pointer obtained via afh_get_header().
+ * \param audio_format_id Determines the audio format handler.
+ */
+void afh_free_header(char *header_buf, uint8_t audio_format_id)
+{
+       struct audio_format_handler *afh = afl + audio_format_id;
+
+       if (afh->get_header)
+               free(header_buf);
 }
diff --git a/afs.c b/afs.c
index 2fb28b71eeabca63194400731ef19499b83806ca..c2fd6d52daa58ef4cf0a118ce855898465053f2b 100644 (file)
--- a/afs.c
+++ b/afs.c
@@ -951,7 +951,7 @@ static void register_command_task(uint32_t cookie)
 
        ct->task.pre_select = command_pre_select;
        ct->task.post_select = command_post_select;
-       sprintf(ct->task.status, "command task");
+       sprintf(ct->task.status, "afs command task");
        register_task(&ct->task);
 }
 
diff --git a/afs.h b/afs.h
index 699998b03979abb33afa8eb9fae5db709ddffd2a..96da2da027cf27268c7b5ad1b4af6755b593f7e6 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -21,7 +21,7 @@ struct afs_info {
        uint32_t image_id;
        /** Lyrics blob associated with this file (foreign key). */
        uint32_t lyrics_id;
-       /** Mp3, ogg or aac. */
+       /** Mp3, ogg, aac, wma, spx. */
        uint8_t audio_format_id;
        /** Amplification value. */
        uint8_t amp;
@@ -131,6 +131,8 @@ struct audio_file_data {
        struct afh_info afhi;
        /** Size of the largest chunk. */
        uint32_t max_chunk_size;
+       /** Needed to get the audio file header. */
+       uint8_t audio_format_id;
 };
 
 /**
diff --git a/aft.c b/aft.c
index 412318b27eb656acabbb5c66faa352c8f56494c3..266188b5b370a3e7e3e8aaa092ca093aca7c6c04 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -344,16 +344,16 @@ enum afhi_offsets {
        AFHI_BITRATE_OFFSET = 4,
        /** Position of the frequency. */
        AFHI_FREQUENCY_OFFSET = 8,
-       /** Location of the audio file header. */
-       AFHI_HEADER_OFFSET_OFFSET = 12,
+       /** Was: Location of the audio file header. */
+       AFHI_UNUSED1_OFFSET = 12,
        /* Length of the audio file header. Zero means: No header. */
        AFHI_HEADER_LEN_OFFSET = 16,
        /** The total number of chunks (4 bytes). */
        CHUNKS_TOTAL_OFFSET = 20,
        /** The length of the audio file header (4 bytes). */
        HEADER_LEN_OFFSET = 24,
-       /** The start of the audio file header (4 bytes). */
-       HEADER_OFFSET_OFFSET = 28,
+       /** Was: The start of the audio file header (4 bytes). */
+       AFHI_UNUSED2_OFFSET = 28,
        /** The seconds part of the chunk time (4 bytes). */
        CHUNK_TV_TV_SEC_OFFSET = 32,
        /** The microseconds part of the chunk time (4 bytes). */
@@ -388,12 +388,12 @@ static void save_afhi(struct afh_info *afhi, char *buf)
        write_u32(buf + AFHI_SECONDS_TOTAL_OFFSET, afhi->seconds_total);
        write_u32(buf + AFHI_BITRATE_OFFSET, afhi->bitrate);
        write_u32(buf + AFHI_FREQUENCY_OFFSET, afhi->frequency);
-       write_u32(buf + AFHI_HEADER_OFFSET_OFFSET, afhi->header_offset);
+       write_u32(buf + AFHI_UNUSED1_OFFSET, 0);
        write_u32(buf + AFHI_HEADER_LEN_OFFSET, afhi->header_len);
        write_u8(buf + AFHI_CHANNELS_OFFSET, afhi->channels);
        write_u32(buf + CHUNKS_TOTAL_OFFSET, afhi->chunks_total);
        write_u32(buf + HEADER_LEN_OFFSET, afhi->header_len);
-       write_u32(buf + HEADER_OFFSET_OFFSET, afhi->header_offset);
+       write_u32(buf + AFHI_UNUSED2_OFFSET, 0);
        write_u32(buf + CHUNK_TV_TV_SEC_OFFSET, afhi->chunk_tv.tv_sec);
        write_u32(buf + CHUNK_TV_TV_USEC_OFFSET, afhi->chunk_tv.tv_usec);
        p = buf + AFHI_INFO_STRING_OFFSET;
@@ -411,12 +411,10 @@ static void load_afhi(const char *buf, struct afh_info *afhi)
        afhi->seconds_total = read_u32(buf + AFHI_SECONDS_TOTAL_OFFSET);
        afhi->bitrate = read_u32(buf + AFHI_BITRATE_OFFSET);
        afhi->frequency = read_u32(buf + AFHI_FREQUENCY_OFFSET);
-       afhi->header_offset = read_u32(buf + AFHI_HEADER_OFFSET_OFFSET);
        afhi->header_len = read_u32(buf + AFHI_HEADER_LEN_OFFSET);
        afhi->channels = read_u8(buf + AFHI_CHANNELS_OFFSET);
        afhi->chunks_total = read_u32(buf + CHUNKS_TOTAL_OFFSET);
        afhi->header_len = read_u32(buf + HEADER_LEN_OFFSET);
-       afhi->header_offset = read_u32(buf + HEADER_OFFSET_OFFSET);
        afhi->chunk_tv.tv_sec = read_u32(buf + CHUNK_TV_TV_SEC_OFFSET);
        afhi->chunk_tv.tv_usec = read_u32(buf + CHUNK_TV_TV_USEC_OFFSET);
        afhi->techinfo = (char *)buf + AFHI_INFO_STRING_OFFSET;
@@ -1126,6 +1124,7 @@ int open_and_update_audio_file(struct osl_row *aft_row, long score,
        new_afsi.last_played = time(NULL);
        save_afsi(&new_afsi, &afsi_obj); /* in-place update */
 
+       afd->audio_format_id = old_afsi.audio_format_id;
        load_chunk_table(&afd->afhi, chunk_table_obj.data);
        ret = make_status_items(afd, &old_afsi, path, score, file_hash);
        if (ret < 0)
index f462016b2e572f6a58691362cb52c9bdb280ea91..f9ef6cd75ab8733408d3c2542230ae806281bf85 100644 (file)
--- a/command.c
+++ b/command.c
@@ -743,24 +743,24 @@ __noreturn void handle_connect(int fd, const char *peername)
        /* we need a blocking fd here as recv() might return EAGAIN otherwise. */
        ret = mark_fd_blocking(fd);
        if (ret < 0)
-               goto err_out;
+               goto net_err;
        /* send Welcome message */
        ret = send_va_buffer(fd, "This is para_server, version "
                PACKAGE_VERSION  ".\n" );
        if (ret < 0)
-               goto err_out;
+               goto net_err;
        /* recv auth request line */
        ret = recv_buffer(fd, buf, sizeof(buf));
        if (ret < 0)
-               goto err_out;
+               goto net_err;
        if (ret < 10) {
                ret = -E_AUTH_REQUEST;
-               goto err_out;
+               goto net_err;
        }
        numbytes = ret;
        ret = -E_AUTH_REQUEST;
        if (strncmp(buf, AUTH_REQUEST_MSG, strlen(AUTH_REQUEST_MSG)))
-               goto err_out;
+               goto net_err;
        p = buf + strlen(AUTH_REQUEST_MSG);
        PARA_DEBUG_LOG("received auth request for user %s\n", p);
        ret = -E_BAD_USER;
@@ -770,7 +770,7 @@ __noreturn void handle_connect(int fd, const char *peername)
                ret = para_encrypt_buffer(u->rsa, rand_buf, sizeof(rand_buf),
                        (unsigned char *)buf);
                if (ret < 0)
-                       goto err_out;
+                       goto net_err;
                numbytes = ret;
        } else {
                /*
index f3a2d1333f457f2cae6c313456a7fe295a479279..e8b2118cdede3d2a1ebabbe751cbaf2b2b741cec 100644 (file)
@@ -133,7 +133,7 @@ server_errlist_objs="server afh_common mp3_afh vss command net string signal
        ipc dccp_send fd user_list chunk_queue afs aft mood score attribute
        blob playlist sha1 sched acl send_common udp_send color fec
        server_command_list afs_command_list wma_afh wma_common"
-server_ldflags="-losl"
+server_ldflags=""
 server_audio_formats="mp3 wma"
 
 write_cmdline_objs="add_cmdline(write file_write)"
@@ -268,7 +268,7 @@ else
        extras="$extras server"
        executables="$executables server"
        AC_SUBST(osl_cppflags)
-       server_ldflags="$server_ldflags -L$with_osl_libs"
+       server_ldflags="$server_ldflags $osl_libs -losl"
 fi
 CPPFLAGS="$OLD_CPPFLAGS"
 LDFLAGS="$OLD_LDFLAGS"
diff --git a/crypt.c b/crypt.c
index 917948c6185710fb828b441025b8d46a0fdc2924..cdcb6149d04254a0def3bcc903823f71ae3a89e5 100644 (file)
--- a/crypt.c
+++ b/crypt.c
@@ -203,6 +203,8 @@ int para_encrypt_buffer(RSA *rsa, unsigned char *inbuf,
        return ret < 0? -E_ENCRYPT : ret;
 }
 
+#define RC4_ALIGN 8
+
 /**
  * Encrypt and send a buffer.
  *
@@ -218,10 +220,16 @@ int rc4_send_bin_buffer(struct rc4_context *rc4c, const char *buf, size_t len)
 {
        int ret;
        unsigned char *tmp;
+       static unsigned char remainder[RC4_ALIGN];
+       size_t l1 = ROUND_DOWN(len, RC4_ALIGN), l2 = ROUND_UP(len, RC4_ALIGN);
 
        assert(len);
-       tmp = para_malloc(len + 8);
-       RC4(&rc4c->send_key, len, (const unsigned char *)buf, tmp);
+       tmp = para_malloc(l2);
+       RC4(&rc4c->send_key, l1, (const unsigned char *)buf, tmp);
+       if (len > l1) {
+               memcpy(remainder, buf + l1, len - l1);
+               RC4(&rc4c->send_key, len - l1, remainder, tmp + l1);
+       }
        ret = write_all(rc4c->fd, (char *)tmp, &len);
        free(tmp);
        return ret;
index aad45a3c8d4ff8f6882893683fd8763ac4970c9f..60d4eba6b8fc22ca5d0431444ec65d7cb2c74ab2 100755 (executable)
--- a/depend.sh
+++ b/depend.sh
@@ -19,4 +19,4 @@ shift
 
 LC_ALL=C gcc -MM -MG "$@" \
        | sed -e "s@^\(.*\)\.o:@$object_dir/\1.d $object_dir/\1.o:@" \
-       -e "s@[         ^]\([a-zA-Z0-9_]\+\.cmdline.h\)@ $cmdline_dir/\1@g"
+       -e "s@[         ^]\([a-zA-Z0-9_]\{1,\}\.cmdline.h\)@ $cmdline_dir/\1@g"
diff --git a/error.h b/error.h
index 3dfee0dda071d56462fc2ab93d81390bc6002c3c..5a2e39b468fa58d7cb66bc3ca07f71012b02c2e2 100644 (file)
--- a/error.h
+++ b/error.h
@@ -351,6 +351,8 @@ extern const char **para_errlist[];
 
 #define OGG_AFH_ERRORS \
        PARA_ERROR(VORBIS, "vorbis synthesis header-in error (not vorbis?)"), \
+       PARA_ERROR(OGG_PACKET_IN, "ogg_stream_packetin() failed"), \
+       PARA_ERROR(OGG_STREAM_FLUSH, "ogg_stream_flush() failed"), \
 
 
 #define VSS_ERRORS \
index 289917c3fddfb96debfd9e8425b005b97276b532..2659b93af07006787b4e1731c4349d94d594d285 100644 (file)
@@ -136,22 +136,23 @@ option "no_default_filters" D
 #~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 "Configure filters manually"
 flag off
-details="
+details = "
        If (and only if) this option is set, the --filter options
-       (see below) take effect. Otherwise, the compiled-in default
-       filters mp3dec, oggdec and aacdec are activated for mp3, ogg,
-       aac streams respectively.
-
-       You have to configure filters manually if you want to use
-       the amp filter or the compress filter which are not activated
-       by default.
-
-       Playing udp streams also requires that the output of the udp
-       receiver must be fed into the fecdec filter first to produce
-       a stream which can be decoded by the appropriate decoder
-       (mp3dec, oggdec, aacdec, wmadec). In other words, the fecdec
-       filter should be specified as the first filter of the filter
-       configuration for udp streaming.
+       (see below) take effect. Otherwise, the compiled-in defaults
+       apply.  These defaults depend on the receiver being used as
+       described below.
+
+       For http streams, only a single filter per audio format,
+       the decoder for that format, is activated. On the other hand,
+       since udp and dccp streams are sent fec-encoded by para_server,
+       the client side must feed the output of the receiver into
+       the fecdec filter first. Therefore the default for udp and
+       dccp streams is to activate the fecdec filter, followed by
+       the appropriate decoder.
+
+       You must give this option if you want to use any other filter,
+       for example the amp or the compress filter.
+
 "
 
 option "filter" f
diff --git a/gui.c b/gui.c
index eba1e2a59331564a40677a123d1220dc9120c059..38addd9815cc5bf2775c80278679a1e9c64e872e 100644 (file)
--- a/gui.c
+++ b/gui.c
@@ -400,11 +400,13 @@ static int draw_top_rbe(unsigned *lines)
        rbe = ringbuffer_get(bot_win_rb, fvr);
        if (!rbe)
                return -1;
-       /* first rbe might be only partially visible */
-       offset = (*lines - bot.lines) * bot.cols;
        len = strlen(rbe->msg);
-       if (offset < 0 || len < offset)
-               return -1;
+       if (*lines > bot.lines) {
+               /* first rbe is only partially visible */
+               offset = (*lines - bot.lines) * bot.cols;
+               assert(offset <= len);
+       } else
+               offset = 0;
        wattron(bot.win, COLOR_PAIR(rbe->color));
        waddstr(bot.win, rbe->msg + offset);
        *lines = NUM_LINES(len - offset);
index ef42c497062c228ddab10497c3388ffa2b8de90b..144a2690bf80da24d298ab2bb56c5403835157dc 100644 (file)
--- a/ogg_afh.c
+++ b/ogg_afh.c
@@ -21,7 +21,7 @@ struct private_vorbis_data {
 };
 
 static int vorbis_packet_callback(ogg_packet *packet, int packet_num,
-               struct afh_info *afhi, void *private_data)
+               __a_unused int serial, struct afh_info *afhi, void *private_data)
 {
        struct private_vorbis_data *pvd = private_data;
 
@@ -65,6 +65,99 @@ static int ogg_vorbis_get_file_info(char *map, size_t numbytes, __a_unused int f
        return ret;
 }
 
+struct vorbis_get_header_data {
+       ogg_stream_state os;
+       char *buf;
+       size_t len;
+};
+
+static void add_ogg_page(ogg_page *og, struct vorbis_get_header_data *vghd)
+{
+       size_t old_len = vghd->len;
+       size_t new_len = vghd->len + og->header_len + og->body_len;
+       char *buf = para_realloc(vghd->buf, new_len), *p = buf + old_len;
+
+       memcpy(p, og->header, og->header_len);
+       memcpy(p + og->header_len, og->body, og->body_len);
+       vghd->buf = buf;
+       vghd->len = new_len;
+       PARA_DEBUG_LOG("header/body/old/new: %lu/%lu/%zu/%zu\n",
+               og->header_len, og->body_len, old_len, new_len);
+}
+
+static int vorbis_get_header_callback(ogg_packet *packet, int packet_num,
+               int serial, __a_unused struct afh_info *afhi, void *private_data)
+{
+       int ret;
+       struct vorbis_get_header_data *vghd = private_data;
+       ogg_page og;
+       static unsigned char dummy_packet[] = {
+               0x03,
+               'v', 'o', 'r', 'b', 'i', 's',
+               0x06, 0x00, 0x00, 0x00,
+               'd', 'u', 'm', 'm', 'y', '\0',
+               0x00, 0x00, 0x00, 0x00, /* no comment :) */
+               0xff /* framing bit */
+       };
+
+       PARA_DEBUG_LOG("processing ogg packet #%d\n", packet_num);
+       if (packet_num > 2)
+               return 0;
+       if (packet_num == 0) {
+               ogg_stream_init(&vghd->os, serial);
+               ret = -E_OGG_PACKET_IN;
+               ret = ogg_stream_packetin(&vghd->os, packet);
+               if (ret < 0)
+                       goto out;
+               ret = -E_OGG_STREAM_FLUSH;
+               if (ogg_stream_flush(&vghd->os, &og) == 0)
+                       goto out;
+               add_ogg_page(&og, vghd);
+               return 1;
+       }
+       if (packet_num == 1) {
+               PARA_INFO_LOG("replacing metadata packet\n");
+               ogg_packet replacement = *packet;
+               replacement.packet = dummy_packet;
+               replacement.bytes = sizeof(dummy_packet);
+               ret = ogg_stream_packetin(&vghd->os, &replacement);
+               if (ret >= 0)
+                       return 1;
+               ret = -E_OGG_PACKET_IN;
+               goto out;
+       }
+       ret = -E_OGG_PACKET_IN;
+       if (ogg_stream_packetin(&vghd->os, packet) < 0)
+               goto out;
+       while (ogg_stream_flush(&vghd->os, &og))
+               add_ogg_page(&og, vghd);
+       ret = 0;
+out:
+       ogg_stream_clear(&vghd->os);
+       return ret;
+}
+
+static void vorbis_get_header(void *map, size_t mapsize, char **buf,
+               size_t *len)
+{
+       int ret;
+       struct vorbis_get_header_data vghd = {.len = 0};
+       struct ogg_afh_callback_info cb = {
+               .packet_callback = vorbis_get_header_callback,
+               .private_data = &vghd,
+       };
+
+       ret = ogg_get_file_info(map, mapsize, NULL, &cb);
+       if (ret < 0)
+               goto fail;
+       *buf = vghd.buf;
+       *len = vghd.len;
+       PARA_INFO_LOG("created %zu byte ogg vorbis header\n", *len);
+       return;
+fail:
+       PARA_ERROR_LOG("%s\n", para_strerror(-ret));
+}
+
 static const char* ogg_suffixes[] = {"ogg", NULL};
 
 /**
@@ -74,6 +167,7 @@ static const char* ogg_suffixes[] = {"ogg", NULL};
  */
 void ogg_init(struct audio_format_handler *afh)
 {
-       afh->get_file_info = ogg_vorbis_get_file_info,
+       afh->get_file_info = ogg_vorbis_get_file_info;
+       afh->get_header = vorbis_get_header;
        afh->suffixes = ogg_suffixes;
 }
index 1deb5cdae194b1bf5b026ffd719d2f316fcba086..cb59d36383a104836bbff4ef59f233f464ae4743 100644 (file)
@@ -37,13 +37,16 @@ static int process_packets_2_and_3(ogg_sync_state *oss,
                         * apparent at packetout.
                         */
                        ogg_stream_pagein(stream, &page);
+                       PARA_INFO_LOG("ogg page serial: %d\n",
+                               ogg_page_serialno(&page));
                        while (i < 2) {
                                ret = ogg_stream_packetout(stream, &packet);
                                if (ret == 0)
                                        break;
                                if (ret < 0)
                                        return -E_STREAM_PACKETOUT;
-                               ret = ci->packet_callback(&packet, i + 1, afhi,
+                               ret = ci->packet_callback(&packet, i + 1,
+                                       ogg_page_serialno(&page), afhi,
                                        ci->private_data);
                                if (ret < 0)
                                        return ret;
@@ -77,30 +80,28 @@ static int process_ogg_packets(ogg_sync_state *oss, struct afh_info *afhi,
        ret = -E_STREAM_PACKETOUT;
        if (ogg_stream_packetout(&stream, &packet) != 1)
                goto out;
-       ret = ci->packet_callback(&packet, 0, afhi, ci->private_data);
+       ret = ci->packet_callback(&packet, 0, ogg_page_serialno(&page),
+               afhi, ci->private_data);
        if (ret < 0)
                goto out;
        ret = process_packets_2_and_3(oss, &stream, afhi, ci);
        if (ret < 0)
                goto out;
-       afhi->header_offset = 0;
-       afhi->header_len = oss->returned;
        ret = 1;
 out:
        ogg_stream_clear(&stream);
        return ret;
 }
 
-static void set_chunk_tv(int num_frames, int num_chunks, int frequency,
+static void set_chunk_tv(int frames_per_chunk, int frequency,
                struct timeval *result)
 {
-       uint64_t x = (uint64_t)num_frames * 1000 * 1000
-               / frequency / num_chunks;
+       uint64_t x = (uint64_t)frames_per_chunk * 1000 * 1000 / frequency;
 
        result->tv_sec = x / 1000 / 1000;
        result->tv_usec = x % (1000 * 1000);
-       PARA_INFO_LOG("%d chunks, chunk time: %lums\n", num_chunks,
-               tv2ms(result));
+       PARA_INFO_LOG("%d frames per chunk, chunk time: %lums\n",
+               frames_per_chunk, tv2ms(result));
 }
 
 /**
@@ -110,9 +111,9 @@ static void set_chunk_tv(int num_frames, int num_chunks, int frequency,
  * given by \a map and \a numbytes and passes each packet to the callback
  * defined by \a ci.
  *
- * If the packet callback indicates success, the chunk table is built.  Chunk
- * zero contains the first three ogg packets while all other chunks consist of
- * exactly one ogg page.
+ * If the packet callback indicates success and \a afhi is not \p NULL, the
+ * chunk table is built. Chunk zero contains the first three ogg packets while
+ * all other chunks consist of exactly one ogg page.
  *
  * \param map Audio file data.
  * \param numbytes The length of \a map.
@@ -143,9 +144,12 @@ int ogg_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
        ret = process_ogg_packets(&oss, afhi, ci);
        if (ret < 0)
                goto out;
+       if (!afhi)
+               goto out;
+       afhi->header_len = oss.returned;
        oss.returned = 0;
        oss.fill = numbytes;
-       /* count ogg packages and get duration of the file */
+       /* count ogg pages and get duration of the file */
        for (i = 0; ogg_sync_pageseek(&oss, &op) > 0; i++)
                num_frames = ogg_page_granulepos(&op);
        PARA_INFO_LOG("%d pages, %llu frames\n", i, num_frames);
@@ -178,7 +182,7 @@ int ogg_get_file_info(char *map, size_t numbytes, struct afh_info *afhi,
                }
        }
        afhi->chunks_total = j;
-       set_chunk_tv(num_frames, j, afhi->frequency, &afhi->chunk_tv);
+       set_chunk_tv(frames_per_chunk, afhi->frequency, &afhi->chunk_tv);
        ret = 0;
 out:
        ogg_sync_clear(&oss);
index 01f8d6c532fb93a37231286ed66da7cf09eb5530..89c8268b1fa0335bf98675c89135a7d1531a9630 100644 (file)
@@ -24,7 +24,7 @@ struct ogg_afh_callback_info {
          * reached and no further ogg packets should be processed.
          */
        int (*packet_callback)(ogg_packet *packet, int packet_num,
-               struct afh_info *afhi, void *private_data);
+               int serial, struct afh_info *afhi, void *private_data);
        /** Vorbis/speex specific data. */
        void *private_data;
 };
index 1bc6d2f748e8cbe7c3067e3479e91ef771fb7667..44d299feaf5c67c4a4c78e192e61a4267881e568 100644 (file)
@@ -35,7 +35,6 @@ struct private_oggdec_data {
        /** The number of channels of the current stream. */
        unsigned int channels;
        /** Current sample rate in Hz. */
-       struct timeval stream_start;
        unsigned int sample_rate;
 };
 
@@ -114,7 +113,7 @@ static void ogg_close(struct filter_node *fn)
        fn->private_data = NULL;
 }
 
-#define OGGDEC_OUTPUT_CHUNK_SIZE (64 * 1024)
+#define OGGDEC_OUTPUT_CHUNK_SIZE (640 * 1024)
 
 static int oggdec_execute(struct btr_node *btrn, const char *cmd, char **result)
 {
@@ -130,12 +129,12 @@ static int ogg_init(struct filter_node *fn)
        struct btr_node *btrn = fn->btrn;
        int ret, oret;
        size_t iqs;
+       struct OggVorbis_File *vf = para_malloc(sizeof(*vf));
 
-       pod->vf = para_malloc(sizeof(struct OggVorbis_File));
        PARA_NOTICE_LOG("iqs: %zu, min_iqs: %zu, opening ov callbacks\n",
                btr_get_input_queue_size(btrn), fn->min_iqs);
 open:
-       oret = ov_open_callbacks(fn, pod->vf,
+       oret = ov_open_callbacks(fn, vf,
                NULL, /* no initial buffer */
                0, /* no initial bytes */
                ovc); /* the ov_open_callbacks */
@@ -165,20 +164,19 @@ open:
        ret = -E_OGGDEC_FAULT;
        if (oret < 0)
                goto out;
-       pod->channels = ov_info(pod->vf, 0)->channels;
-       pod->sample_rate = ov_info(pod->vf, 0)->rate;
-       tv_add(now, &(struct timeval)EMBRACE(0, 300 * 1000), &pod->stream_start);
+       pod->channels = ov_info(vf, 0)->channels;
+       pod->sample_rate = ov_info(vf, 0)->rate;
        PARA_NOTICE_LOG("%d channels, %d Hz\n", pod->channels,
                pod->sample_rate);
        ret = 1;
 out:
-       if (ret <= 0) {
-               free(pod->vf);
-               pod->vf = NULL;
-       } else {
+       if (ret <= 0)
+               free(vf);
+       else {
                btr_consume(btrn, pod->converted);
                pod->converted = 0;
                fn->min_iqs = 0;
+               pod->vf = vf;
        }
        return ret;
 }
@@ -186,15 +184,14 @@ out:
 static void ogg_pre_select(__a_unused struct sched *s, struct task *t)
 {
        struct filter_node *fn = container_of(t, struct filter_node, task);
-       struct private_oggdec_data *pod = fn->private_data;
        int ret;
 
        t->error = 0;
        ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
-       if (ret < 0)
+       if (ret != 0)
                sched_min_delay(s);
        else
-               sched_request_barrier(&pod->stream_start, s);
+               sched_request_timeout_ms(100, s);
 }
 
 static void ogg_post_select(__a_unused struct sched *s, struct task *t)
@@ -203,12 +200,14 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t)
        struct private_oggdec_data *pod = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret, ns;
+       char *out;
+       ssize_t read_ret, have;
 
-       if (tv_diff(&pod->stream_start, now, NULL) > 0)
-               return;
        pod->converted = 0;
        t->error = 0;
        ret = ns = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
+       if (ret <= 0)
+               goto out;
        if (!pod->vf) {
                if (ret <= 0)
                        goto out;
@@ -217,24 +216,36 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t)
                if (ret <= 0)
                        goto out;
        }
-       for (;;) {
-               char *out = para_malloc(OGGDEC_OUTPUT_CHUNK_SIZE);
-               ssize_t read_ret = ov_read(pod->vf, out, OGGDEC_OUTPUT_CHUNK_SIZE,
+       out = para_malloc(OGGDEC_OUTPUT_CHUNK_SIZE);
+       for (have = 0;;) {
+               read_ret = ov_read(pod->vf, out + have,
+                       OGGDEC_OUTPUT_CHUNK_SIZE - have,
                        ENDIAN, 2 /* 16 bit */, 1 /* signed */, NULL);
                btr_consume(btrn, pod->converted);
                pod->converted = 0;
                if (read_ret <= 0)
-                       free(out);
-               ret = ns;
-               if (read_ret == 0 || read_ret == OV_HOLE)
-                       goto out;
-               ret = -E_OGGDEC_BADLINK;
-               if (read_ret < 0)
-                       goto out;
-               btr_add_output(out, read_ret, btrn);
-               if (btr_get_output_queue_size(btrn) > 128 * 1024)
-                       return; /* enough data for the moment */
+                       break;
+               have += read_ret;
+               if (have >= OGGDEC_OUTPUT_CHUNK_SIZE)
+                       break;
+       }
+       if (have == 0)
+               free(out);
+       else if (have < OGGDEC_OUTPUT_CHUNK_SIZE)
+               out = para_realloc(out, have);
+       if (have > 0) {
+               btr_add_output(out, have, btrn);
+               fn->min_iqs = 0;
        }
+       ret = ns;
+       if (read_ret == OV_HOLE) /* avoid buffer underruns */
+               fn->min_iqs = 9000;
+       if (read_ret == 0 || read_ret == OV_HOLE)
+               goto out;
+       ret = -E_OGGDEC_BADLINK;
+       if (read_ret < 0)
+               goto out;
+       ret = 0;
 out:
        if (ret < 0) {
                t->error = ret;
diff --git a/para.h b/para.h
index c30e4710ee7ff9b2d725dee06b7ec4a378e1c820..29c5c2b89c4ac3e0ca820c26c07cd8be4755f266 100644 (file)
--- a/para.h
+++ b/para.h
@@ -165,6 +165,16 @@ _static_inline_ long int para_random(unsigned max)
        return ((max + 0.0) * (random() / (RAND_MAX + 1.0)));
 }
 
+/** Round up x to next multiple of y. */
+#define ROUND_UP(x, y) ({ \
+       const typeof(y) _divisor = y; \
+       ((x) + _divisor - 1) / _divisor * _divisor; })
+
+/** Round down x to multiple of y. */
+#define ROUND_DOWN(x, y) ({ \
+       const typeof(y) _divisor = y; \
+       (x) / _divisor * _divisor; })
+
 /** Divide and round up to next integer. */
 #define DIV_ROUND_UP(x, y) ({ \
        typeof(y) _divisor = y; \
diff --git a/score.c b/score.c
index 27fec711047f230c96215be2d90def9db3320bbe..f5fe4a833f6f6f99ca3d9afca49175113b1eac78 100644 (file)
--- a/score.c
+++ b/score.c
@@ -38,8 +38,8 @@ static int ptr_compare(const struct osl_object *obj1, const struct osl_object *o
  */
 static int score_compare(const struct osl_object *obj1, const struct osl_object *obj2)
 {
-       int d1 = *(int*)obj1->data;
-       int d2 = *(int*)obj2->data;
+       long d1 = *(long *)obj1->data;
+       long d2 = *(long *)obj2->data;
        int ret = NUM_COMPARE(d2, d1);
 
        if (ret)
@@ -141,7 +141,7 @@ int score_add(const struct osl_row *aft_row, long score)
        size = score_table_desc.column_descriptions[SCORECOL_SCORE].data_size;
        score_objs[SCORECOL_SCORE].data = para_malloc(size);
        score_objs[SCORECOL_SCORE].size = size;
-       *(int *)(score_objs[SCORECOL_SCORE].data) = score;
+       *(long *)(score_objs[SCORECOL_SCORE].data) = score;
 
 //     PARA_DEBUG_LOG("adding %p\n", *(void **) (score_objs[SCORECOL_AFT_ROW].data));
        ret = osl(osl_add_row(score_table, score_objs));
index 849b707a43043a501ab92cadbed6af66f725a139..35d6f19137b3a881482df4e65c3945d6bcdb8a78 100644 (file)
--- a/server.c
+++ b/server.c
@@ -426,6 +426,7 @@ static void init_server_command_task(int argc, char **argv)
        if (ret < 0)
                goto err;
        add_close_on_fork_list(sct->listen_fd); /* child doesn't need the listener */
+       sprintf(sct->task.status, "server command task");
        register_task(&sct->task);
        return;
 err:
index 6414f4c4ebba4fda67b7d64a32d570b50ba0436d..e693c4150e03b7dae9b991c343ec7abbfe980db0 100644 (file)
--- a/spx_afh.c
+++ b/spx_afh.c
@@ -139,7 +139,8 @@ static int spx_get_comments(unsigned char *comments, int length,
 static const char* speex_suffixes[] = {"spx", "speex", NULL};
 
 static int spx_packet_callback(ogg_packet *packet, int packet_num,
-               struct afh_info *afhi, void *private_data)
+               __a_unused int serial, struct afh_info *afhi,
+               void *private_data)
 {
        struct private_spx_data *psd = private_data;
        int ret;
diff --git a/vss.c b/vss.c
index 916a71d518762f63675c65c195f87b6fdce089e1..ba6f7c4c655134d11d79e6411ab92d63b4efd160 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -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;
@@ -334,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)
 {
@@ -348,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;
 
@@ -356,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 */
@@ -478,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) {
@@ -515,22 +539,36 @@ 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 */
-       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) {
                        /*
                         * 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 +664,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 +845,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 +1025,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);
@@ -1041,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) {
@@ -1054,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;
@@ -1146,5 +1186,6 @@ void init_vss_task(int afs_socket)
                tv_add(&vsst->autoplay_barrier, &vsst->announce_tv,
                        &vsst->data_send_barrier);
        }
+       sprintf(vsst->task.status, "vss task");
        register_task(&vsst->task);
 }
index 9b7d85b3fd7d059c34476419841af8e9d3da42a1..255342dca56d4f8b8ff5a7bea199b78c76c5e55d 100644 (file)
--- a/wma_afh.c
+++ b/wma_afh.c
@@ -257,7 +257,6 @@ static int wma_get_file_info(char *map, size_t numbytes, __a_unused int fd,
        afhi->frequency = ahi.sample_rate;
        afhi->channels = ahi.channels;
        afhi->header_len = ahi.header_len;
-       afhi->header_offset = 0;
        wma_make_chunk_table(map + ahi.header_len, numbytes - ahi.header_len,
                ahi.block_align, afhi);
        read_asf_tags(map, ahi.header_len, &afhi->tags);