]> git.tuebingen.mpg.de Git - paraslash.git/commitdiff
Never start playback at an empty chunk.
authorAndre Noll <maan@systemlinux.org>
Sun, 11 May 2014 19:21:15 +0000 (21:21 +0200)
committerAndre Noll <maan@systemlinux.org>
Tue, 1 Jul 2014 17:37:46 +0000 (19:37 +0200)
The chunk table of ogg/* audio files often contains "empty" chunks
which correspond to time slices for which the virtual streaming system
does not need to send any data. When playback is started at an empty
chunk, an unnecessary delay results.

To overcome this issue, this commit introduces a new public helper
afh_get_start_chunk() which looks for the first non-empty chunk before
the given chunk number.

The new function is called from afh_recv.c and from vss.c so that
both para_play and para_server now avoid to start streaming at an
empty chunk.

afh.h
afh_common.c
afh_recv.c
vss.c

diff --git a/afh.h b/afh.h
index 2264cc6139501e26d1f46ba89960cf5e630308c2..f0ea8124c8df762ad950554dd8e796e28b5d9b83 100644 (file)
--- a/afh.h
+++ b/afh.h
@@ -101,6 +101,8 @@ 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);
+int32_t afh_get_start_chunk(int32_t approx_chunk_num,
+               const 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 cad972d94026eb1f1587fdf7201b752786b801b7..c5a25e36bfe889d22318fa28e5cf23088c2cbb67 100644 (file)
@@ -264,6 +264,12 @@ const char *audio_format_name(int i)
        return afl[i].name;
 }
 
+static inline size_t get_chunk_len(long unsigned chunk_num,
+               const struct afh_info *afhi)
+{
+       return afhi->chunk_table[chunk_num + 1] - afhi->chunk_table[chunk_num];
+}
+
 /**
  * Get one chunk of audio data.
  *
@@ -281,7 +287,28 @@ void afh_get_chunk(long unsigned chunk_num, struct afh_info *afhi,
 {
        size_t pos = afhi->chunk_table[chunk_num];
        *buf = map + pos;
-       *len = afhi->chunk_table[chunk_num + 1] - pos;
+       *len = get_chunk_len(chunk_num, afhi);
+}
+
+/**
+ * Find a suitable start chunk.
+ *
+ * \param approx_chunk_num Upper bound for the chunk number to return.
+ * \param afhi Needed for the chunk table.
+ *
+ * \return The first non-empty chunk <= \a approx_chunk_num.
+ *
+ * \sa \ref afh_get_chunk().
+ */
+int32_t afh_get_start_chunk(int32_t approx_chunk_num,
+               const struct afh_info *afhi)
+{
+       int32_t k;
+
+       for (k = PARA_MAX(0, approx_chunk_num); k >= 0; k--)
+               if (get_chunk_len(k, afhi) > 0)
+                       break;
+       return k;
 }
 
 /**
index 0c7b3946377b6d25be9549834920054e3034de0d..89722fef5b305351bac9668c1dab966d2f8bfafe 100644 (file)
@@ -59,7 +59,8 @@ static int afh_execute(struct btr_node *btrn, const char *cmd, char **result)
                        return ret;
                if (x >= pard->afhi.chunks_total)
                        return -ERRNO_TO_PARA_ERROR(EINVAL);
-               pard->first_chunk = pard->current_chunk = x;
+               pard->first_chunk = afh_get_start_chunk(x, &pard->afhi);
+               pard->current_chunk = pard->first_chunk;
                rn->task.error = 0;
                return 1;
        }
@@ -110,9 +111,12 @@ static int afh_recv_open(struct receiver_node *rn)
        if (PARA_ABS(conf->begin_chunk_arg) >= afhi->chunks_total)
                goto out_clear_afhi;
        if (conf->begin_chunk_arg >= 0)
-               pard->first_chunk = conf->begin_chunk_arg;
+               pard->first_chunk = afh_get_start_chunk(
+                       conf->begin_chunk_arg, &pard->afhi);
        else
-               pard->first_chunk = afhi->chunks_total + conf->begin_chunk_arg;
+               pard->first_chunk = afh_get_start_chunk(
+                       afhi->chunks_total + conf->begin_chunk_arg,
+                       &pard->afhi);
        if (conf->end_chunk_given) {
                ret = -ERRNO_TO_PARA_ERROR(EINVAL);
                if (PARA_ABS(conf->end_chunk_arg) > afhi->chunks_total)
diff --git a/vss.c b/vss.c
index 3ace49e9e90e8fb27144964a0f61f1fae267e843..d6f914e72870efb58b8fd81570e31e0b939a4c2e 100644 (file)
--- a/vss.c
+++ b/vss.c
@@ -924,7 +924,8 @@ static void vss_pre_select(struct sched *s, struct task *t)
                tv_add(now, &vsst->announce_tv, &vsst->data_send_barrier);
                set_eof_barrier(vsst);
                mmd->chunks_sent = 0;
-               mmd->current_chunk = mmd->repos_request;
+               mmd->current_chunk = afh_get_start_chunk(mmd->repos_request,
+                       &mmd->afd.afhi);
                mmd->new_vss_status_flags &= ~VSS_REPOS;
                set_mmd_offset();
        }