]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Merge branch 't/build_system_overhaul'
authorAndre Noll <maan@systemlinux.org>
Fri, 20 Dec 2013 12:39:49 +0000 (13:39 +0100)
committerAndre Noll <maan@systemlinux.org>
Fri, 20 Dec 2013 12:47:54 +0000 (13:47 +0100)
This topic was quite some PITA to maintain since its commits heavily
conflict with the changes of all other topic branches which touch
the build system. Cooking since 2013-12-01 and tested on FreeBSD,
NetBSD and on different Linux systems.

abb080 Rebuild error2.h on Makefile changes.
71b616 manual: Move crypt library to the list of optional packages.
185c67 build: Don't insist on curses for CLI support.
474d4d build: Rewrite objlist_to_errlist().
1453e8 build: Reorder Makefile.real.
7fb39c build: Split Makefile.in.
d0ddd2 build: Reorder variables in Makefile.in.
61cc38 build: Add Make variable for clock_gettime_ldflags.
976651 build: Add Make variable for PACKAGE_TARNAME.
19b0d3 build: Introduce Make variables for objects.
fe7666 build: Combine link rules.
2440c4 build: Introduce $prefixed_executables.
2f113b build: Combine rules for object files.
761d9b build: Define Make variables for cppflags.
386572 build: Remove two unused variables from Makefile.in.
40439a build: Collect audio format handlers in afh section.
e926e8 build: Move relevant parts to filter section.
b399d6 build: Move relevant parts to gui section.
1781cc build: Move relevant parts to fade section.
0f4790 build: Move relevant parts to audiod section.
4e9788 build: Move relevant parts to client section.
0c8626 build: Move relevant parts to server section.
755904 build: Create section for para_audioc.
d952d6 build: Create section for para_write.
9734df build: Create section for para_play.
14dee3 build: Create section for para_afh.
b1abc2 build: Create section for para_recv.
bfd5b5 build: Create section for para_filter.
9139d9 build: ldflags conversion: coreaudio.
30f966 build: ldflags conversion: libcurses.
15880b build: ldflags conversion: libnsl.
516421 build: ldflags conversion: libsocket.
ce8273 build: ldflags conversion: libgcrypt.
ad3573 build: ldflags conversion: libssl.
52ac85 build: ldflags conversion: libosl.
37083e build: ldflags conversion: libsamplerate.
7de07a build: ldflags conversion: libreadline.
0e9f1c build: ldflags conversion: libao.
ecac89 build: ldflags conversion: alsa.
6c632d build: ldflags conversion: liboss.
e74262 build: ldflags conversion: libflac.
648197 build: ldflags conversion: libmad.
91ed86 build: ldflags conversion: libfaad.
8ee713 build: ldflags/cppflags conversion: libopus.
b6c705 build: cppflags/ldflags conversion: libspeex.
7aa414 build: ldflags conversion: libvorbis.
80a639 build: ldflags conversion: libogg.
c79cdc build: cppflags/ldflags conversion: libid3tag
a02396 build: Remove duplicates from $all_objs.
d2fc4d build: Remove inactive DEBUG_CPPFLAGS.
e8f310 build: Replace error2.pl by error2.c.
06e33e build: Fix filter output of configure summary.
994889 build: Convert remaining object lists to one object per line format.
782e47 build: Separate curses detection from gui configuration.
fbe4b0 build: Move down fade section.
003815 build: Add object "cmdline" suffix only once.
3097e5 INSTALL: Add an example for cross-compiling.
e8b555 build: Fix make install for cross builds.
aab667 build: Generate man pages directly from ggo files.
9a8a15 build: Remove fnmatch, malloc, realloc tests.
2dcdd9 build: Make crypto optional.
f23353 build: Make audiod optional.
98b801 build: Build para_client only if crypto lib was found.
17ed11 build: Create a separate section for para_server.
02c1e0 build: Compute $all_errlist_objs.
4ec04c build: Replace $extras by per-executable variable.
39707e build: Remove two dead recipes from Makefile.in.
9fc99c build: Remove check for buggy snprintf().

NEWS
afs.h
aft.c
fd.c
flacdec_filter.c
opusdec_filter.c

diff --git a/NEWS b/NEWS
index 980f613a7915e1a48d429ba17993d57572f4184f..29a74a4ca910634c55113e3288b937a1e0831dfe 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -5,9 +5,24 @@ NEWS
 0.5.1 (to be announced) "temporary implication"
 ----------------------------------------------
 
-       - audiod improvements and fixes.
-       - buffer tree robustness improvements.
-       - cleanup of the mood subsystem.
+Lots of fixes and improvements all over the place, and a major overhaul
+of the build system.
+
+       - Audiod improvements and fixes.
+       - Buffer tree robustness improvements.
+       - Cleanup of the mood subsystem.
+       - Fixes and cleanups for the flac decoder.
+       - Latency improvements for the ogg/opus decoder.
+       - Crypto support is now optional. On systems without
+         openssl/gcrypt, the build succeeds but para_server,
+         para_audiod, para_client won't be built.
+       - The build system now works for cross-compile setups.
+       - The dependency tree has been flattened, which speeds up
+         builds and avoids to recreate the man pages on every change.
+       - The error code helper has been rewritten from perl to C,
+         which further improves build time.
+       - Many small bugs in the build system have been identified
+         and fixed.
 
 ----------------------------------------
 0.5.0 (2013-08-23) "invertible validity"
diff --git a/afs.h b/afs.h
index a63968f16a22c30c30cee724d929059cce549c20..8a6b927c74f78f86cad9e748fa04dd02a88bb2ef 100644 (file)
--- a/afs.h
+++ b/afs.h
@@ -279,13 +279,9 @@ int aft_get_row_of_path(const char *path, struct osl_row **row);
 int open_and_update_audio_file(struct osl_row *aft_row, long score,
        struct audio_file_data *afd);
 int load_afd(int shmid, struct audio_file_data *afd);
-int load_afsi(struct afs_info *afsi, struct osl_object *obj);
-void save_afsi(struct afs_info *afsi, struct osl_object *obj);
 int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi);
 int get_afhi_of_row(const struct osl_row *row, struct afh_info *afhi);
-int get_afsi_of_path(const char *path, struct afs_info *afsi);
 int get_audio_file_path_of_row(const struct osl_row *row, char **path);
-int get_afsi_object_of_row(const struct osl_row *row, struct osl_object *obj);
 int audio_file_loop(void *private_data, osl_rbtree_loop_func *func);
 void aft_check_callback(int fd, __a_unused const struct osl_object *query);
 
diff --git a/aft.c b/aft.c
index 377740d132b831d126e0015f241ed65095c2e661..f529416aec375779419a1a936699f6f0584da051 100644 (file)
--- a/aft.c
+++ b/aft.c
@@ -163,7 +163,7 @@ enum afsi_offsets {
        AFSI_SIZE = 32
 };
 
-/**
+/*
  * Convert a struct afs_info to an osl object.
  *
  * \param afsi Pointer to the audio file info to be converted.
@@ -171,7 +171,7 @@ enum afsi_offsets {
  *
  * \sa load_afsi().
  */
-void save_afsi(struct afs_info *afsi, struct osl_object *obj)
+static void save_afsi(struct afs_info *afsi, struct osl_object *obj)
 {
        char *buf = obj->data;
 
@@ -186,17 +186,17 @@ void save_afsi(struct afs_info *afsi, struct osl_object *obj)
        memset(buf + AFSI_AUDIO_FORMAT_UNUSED_OFFSET, 0, 2);
 }
 
-/**
- *  Get the audio file selector info struct stored in an osl object.
+/*
+ * Get the audio file selector info struct stored in an osl object.
  *
  * \param afsi Points to the audio_file info structure to be filled in.
  * \param obj The osl object holding the data.
  *
- * \return Positive on success, negative on errors. Possible errors: \p E_BAD_AFS.
+ * \return Standard.
  *
  * \sa save_afsi().
  */
-int load_afsi(struct afs_info *afsi, struct osl_object *obj)
+static int load_afsi(struct afs_info *afsi, struct osl_object *obj)
 {
        char *buf = obj->data;
        if (obj->size < AFSI_SIZE)
@@ -493,15 +493,16 @@ static int aft_get_row_of_hash(unsigned char *hash, struct osl_row **row)
        return osl(osl_get_row(audio_file_table, AFTCOL_HASH, &obj, row));
 }
 
-/**
- * Get the osl object holding the audio file selector info of a row.
+/*
+ * Get the audio file selector info object of a row.
  *
  * \param row Pointer to a row in the audio file table.
  * \param obj Result pointer.
  *
  * \return Standard.
  */
-int get_afsi_object_of_row(const struct osl_row *row, struct osl_object *obj)
+static int get_afsi_object_of_row(const struct osl_row *row,
+               struct osl_object *obj)
 {
        return osl(osl_get_object(audio_file_table, row, AFTCOL_AFSI, obj));
 }
@@ -541,15 +542,15 @@ int get_afsi_of_row(const struct osl_row *row, struct afs_info *afsi)
        return load_afsi(afsi, &obj);
 }
 
-/**
+/*
  * Get the audio file selector info, given the path of an audio table.
  *
  * \param path The full path of the audio file.
  * \param afsi Result pointer.
  *
- * \return Positive on success, negative on errors.
+ * \return Standard.
  */
-int get_afsi_of_path(const char *path, struct afs_info *afsi)
+static int get_afsi_of_path(const char *path, struct afs_info *afsi)
 {
        struct osl_object obj;
        int ret = get_afsi_object_of_path(path, &obj);
diff --git a/fd.c b/fd.c
index 4d4a859b08cf0e13dddea8aa724f94099a0518b1..f70dedc1ec57fd7f2779b5818bb02e7746dfa263 100644 (file)
--- a/fd.c
+++ b/fd.c
@@ -168,7 +168,7 @@ __printf_2_3 int write_va_buffer(int fd, const char *fmt, ...)
  *
  * \return Zero or a negative error code. If the underlying call to readv(2)
  * returned zero (indicating an end of file condition) or failed for some
- * reason other than \p EAGAIN, a negative return value is returned.
+ * reason other than \p EAGAIN, a negative error code is returned.
  *
  * In any case, \a num_bytes contains the number of bytes that have been
  * successfully read from \a fd (zero if the first readv() call failed with
index 09b319a029a5c392a2d1616eb4fc5602be97d1cc..bf881725165f38415267193473f56bc145dc2b5c 100644 (file)
@@ -25,7 +25,7 @@ struct private_flacdec_data {
         * We can not consume directly what was copied by the read callback
         * because we might need to feed unconsumend bytes to the decoder again
         * after the read callback ran out of data and returned ABORT. So we
-        * track how many bytes are unconsumed so far.
+        * track how many bytes have been fed to libflac but are unconsumed so far.
         */
        size_t unconsumed;
 };
@@ -63,6 +63,16 @@ static FLAC__StreamDecoderReadStatus read_cb(
        }
        if (*bytes > 0)
                return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE;
+       /**
+       * Nothing was copied. If the input queue of the btrn is smaller than
+       * the minimal input queue size, our parent must have been gone, so
+       * we're not going to get more input. Since our remaining data is not
+       * sufficient do decode a single frame, we have an EOF condition.
+       */
+       if (btr_get_input_queue_size(btrn) < fn->min_iqs) {
+               assert(btr_no_parent(btrn));
+               return FLAC__STREAM_DECODER_READ_STATUS_END_OF_STREAM;
+       }
        /*
         * We are kind of screwed here. Returning CONTINUE with a byte count of
         * zero leads to an endless loop, so we must return either EOF or
@@ -144,7 +154,7 @@ static FLAC__StreamDecoderWriteStatus write_cb(
                        write_int16_host_endian(outbuffer + 4 * k + 2, right);
                }
        }
-       btr_add_output(outbuffer, n * 4, btrn);
+       btr_add_output(outbuffer, n * channels * 2, btrn);
        flac_consume(fn);
        return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE;
 }
@@ -222,6 +232,7 @@ static int flacdec_post_select(__a_unused struct sched *s, struct task *t)
        struct private_flacdec_data *pfd = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret;
+       FLAC__StreamDecoderState state;
 
        if (output_queue_full(btrn))
                return 0;
@@ -240,7 +251,6 @@ static int flacdec_post_select(__a_unused struct sched *s, struct task *t)
                goto out;
        }
        pfd->have_more = false;
-       FLAC__StreamDecoderState state;
        FLAC__stream_decoder_process_single(pfd->decoder);
        state = FLAC__stream_decoder_get_state(pfd->decoder);
        ret = -E_FLACDEC_EOF;
@@ -248,10 +258,12 @@ static int flacdec_post_select(__a_unused struct sched *s, struct task *t)
                goto out;
        if (state == FLAC__STREAM_DECODER_ABORTED) {
                FLAC__stream_decoder_flush(pfd->decoder);
-               fn->min_iqs = pfd->unconsumed + 1;
+               pfd->unconsumed = 0; /* feed unconsumed bytes again */
+               fn->min_iqs = btr_get_input_queue_size(btrn) + 1;
                ret = 1;
                goto out;
        }
+       pfd->have_more = true;
        fn->min_iqs = 0;
        ret = 1;
 out:
index 90e65bc369571fbf9e8cde134efc07a17b76e124..c3b405cc338df6666342e863aa3a0ac053ea8500 100644 (file)
@@ -72,6 +72,7 @@ struct opusdec_context {
        int channels;
        int preskip;
        bool have_opus_stream;
+       bool have_more;
        ogg_int32_t opus_serialno;
 };
 
@@ -204,60 +205,84 @@ static int decode_packet(struct opusdec_context *ctx, ogg_packet *op,
        return 1;
 }
 
+#define OPUSDEC_MAX_OUTPUT_SIZE (1024 * 1024)
+
 static int opusdec_post_select(__a_unused struct sched *s, struct task *t)
 {
        struct filter_node *fn = container_of(t, struct filter_node, task);
        struct opusdec_context *ctx = fn->private_data;
        struct btr_node *btrn = fn->btrn;
        int ret;
-       char *btr_buf, *data;
-       size_t nbytes;
        ogg_packet op;
 
        ret = btr_node_status(btrn, fn->min_iqs, BTR_NT_INTERNAL);
-       if (ret <= 0)
-               goto out;
-       btr_merge(btrn, fn->min_iqs);
-       nbytes = btr_next_buffer(btrn, &btr_buf);
-       nbytes = PARA_MIN(nbytes, (size_t)32768);
-       ret = 0;
-       if (nbytes == 0)
-               goto out;
-       data = ogg_sync_buffer(&ctx->oy, nbytes);
-       memcpy(data, btr_buf, nbytes);
-       btr_consume(btrn, nbytes);
-       ogg_sync_wrote(&ctx->oy, nbytes);
-       for (;;) { /* loop over all ogg pages we got */
-               ret = 0;
-               if (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1)
+       if (ret < 0) {
+               if (ret != -E_BTR_EOF) /* fatal error */
+                       goto out;
+               if (!ctx->have_more) /* EOF */
                        goto out;
-               if (!ctx->stream_init) {
-                       ogg_stream_init(&ctx->os, ogg_page_serialno(&ctx->ogg_page));
+       } else if (ret == 0 && !ctx->have_more) /* nothing to do */
+               goto out;
+       if (btr_get_output_queue_size(btrn) > OPUSDEC_MAX_OUTPUT_SIZE)
+               return 0;
+       for (;;) {
+               int serial;
+               if (ctx->stream_init) {
+                       ret = ogg_stream_packetout(&ctx->os, &op);
+                       if (ret == 1)
+                               break;
+               }
+               while (ogg_sync_pageout(&ctx->oy, &ctx->ogg_page) != 1) {
+                       char *btr_buf, *data;
+                       size_t nbytes = btr_next_buffer(btrn, &btr_buf);
+                       nbytes = PARA_MIN(nbytes, (size_t)24 * 1024);
+                       //PARA_CRIT_LOG("nbytes: %d\n", nbytes);
+                       ctx->have_more = false;
+                       if (nbytes == 0)
+                               return 0;
+                       data = ogg_sync_buffer(&ctx->oy, nbytes);
+                       memcpy(data, btr_buf, nbytes);
+                       btr_consume(btrn, nbytes);
+                       ogg_sync_wrote(&ctx->oy, nbytes);
+               }
+               ctx->have_more = true;
+               serial = ogg_page_serialno(&ctx->ogg_page);
+               if (ctx->stream_init) {
+                       if (serial != ctx->os.serialno)
+                               ogg_stream_reset_serialno(&ctx->os, serial);
+               } else {
+                       ogg_stream_init(&ctx->os, serial);
                        ctx->stream_init = true;
                }
-               if (ogg_page_serialno(&ctx->ogg_page) != ctx->os.serialno)
-                       ogg_stream_reset_serialno(&ctx->os,
-                               ogg_page_serialno(&ctx->ogg_page));
                /* Add page to the bitstream */
                ogg_stream_pagein(&ctx->os, &ctx->ogg_page);
-               for (;;) { /* loop over all opus packets */
-                       ret = ogg_stream_packetout(&ctx->os, &op);
-                       if (ret != 1)
-                               break;
-                       ret = decode_packet(ctx, &op, btrn);
-                       if (ret < 0)
-                               goto out;
-                       ctx->packet_count++;
-                       if (ctx->eos)
-                               ctx->have_opus_stream = false;
-               }
        }
+       ret = decode_packet(ctx, &op, btrn);
+       if (ret < 0)
+               goto out;
+       ctx->packet_count++;
+       if (ctx->eos)
+               ctx->have_opus_stream = false;
 out:
        if (ret < 0)
                btr_remove_node(&fn->btrn);
        return ret;
 }
 
+static void opusdec_pre_select(struct sched *s, struct task *t)
+{
+       struct filter_node *fn = container_of(t, struct filter_node, task);
+       struct opusdec_context *ctx = fn->private_data;
+       int ret = btr_node_status(fn->btrn, fn->min_iqs, BTR_NT_INTERNAL);
+
+       if (ret != 0)
+               return sched_min_delay(s);
+       if (ctx->have_more)
+               return;
+       if (btr_get_output_queue_size(fn->btrn) <= OPUSDEC_MAX_OUTPUT_SIZE)
+               return sched_min_delay(s);
+}
+
 /**
  * The init function of the opusdec filter.
  *
@@ -269,7 +294,7 @@ void opusdec_filter_init(struct filter *f)
 {
        f->open = opusdec_open;
        f->close = opusdec_close;
-       f->pre_select = generic_filter_pre_select;
+       f->pre_select = opusdec_pre_select;
        f->post_select = opusdec_post_select;
        f->execute = opusdec_execute;
 }