From 9c1aa53f0cda586aa13a022452d16a2704055578 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 11 May 2014 21:21:15 +0200 Subject: [PATCH] Never start playback at an empty chunk. 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 | 2 ++ afh_common.c | 29 ++++++++++++++++++++++++++++- afh_recv.c | 10 +++++++--- vss.c | 3 ++- 4 files changed, 39 insertions(+), 5 deletions(-) diff --git a/afh.h b/afh.h index 2264cc61..f0ea8124 100644 --- 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); diff --git a/afh_common.c b/afh_common.c index cad972d9..c5a25e36 100644 --- a/afh_common.c +++ b/afh_common.c @@ -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; } /** diff --git a/afh_recv.c b/afh_recv.c index 0c7b3946..89722fef 100644 --- a/afh_recv.c +++ b/afh_recv.c @@ -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 3ace49e9..d6f914e7 100644 --- 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(); } -- 2.30.2