From c817e921b447f42519ce605bb80dbb85bc7e2267 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Fri, 27 Nov 2009 20:36:23 +0100 Subject: [PATCH] FEC: Improve and simplify group timing. The computation of the group start time was not as accurate as it could be because it did not take into account that the first FEC group has to be taken into account twice. This could lead to buffer underruns between the first and the second group. This patch fixes this flaw by computing the group start start(n) of the nth FEC group as start(n) = start(n - 1) + duration(n - 1), which is not only more accurate but also a bit simpler than what we had before. In order to do so, we have to remember the duration of the previous group. The new ->duration member of struct fec_group is used for this purpose. The patch also renames set_slice_duration() to set_group_timing() as this function now computes and stores both the slice duration and the group duration. --- vss.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/vss.c b/vss.c index 6db42bde..c6e40533 100644 --- a/vss.c +++ b/vss.c @@ -121,6 +121,8 @@ struct fec_group { uint32_t num_chunks; /** When the first chunk was sent. */ struct timeval start; + /** The duration of the full group. */ + struct timeval duration; /** The group duration divided by the number of slices. */ struct timeval slice_duration; /** Group contains the audio file header that occupies that many slices. */ @@ -232,15 +234,16 @@ static int num_slices(long unsigned bytes, struct fec_client *fc, uint8_t *resul return 1; } -static void set_slice_duration(struct fec_client *fc, struct fec_group *g) +/* set group start and group duration */ +static void set_group_timing(struct fec_client *fc, struct fec_group *g) { - struct timeval group_duration, *chunk_tv = vss_chunk_time(); + struct timeval *chunk_tv = vss_chunk_time(); - tv_scale(g->num_chunks, chunk_tv, &group_duration); + tv_scale(g->num_chunks, chunk_tv, &g->duration); tv_divide(fc->fcp->slices_per_group + fc->num_extra_slices, - &group_duration, &g->slice_duration); + &g->duration, &g->slice_duration); PARA_DEBUG_LOG("durations (group/chunk/slice): %lu/%lu/%lu\n", - tv2ms(&group_duration), tv2ms(chunk_tv), tv2ms(&g->slice_duration)); + tv2ms(&g->duration), tv2ms(chunk_tv), tv2ms(&g->slice_duration)); } static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst) @@ -248,12 +251,10 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst) int ret, i, k, data_slices; size_t len; const char *buf, *start_buf; - struct timeval tmp, *chunk_tv = vss_chunk_time(); struct fec_group *g = &fc->group; unsigned slice_bytes = fc->fcp->max_slice_bytes - FEC_HEADER_SIZE; uint32_t max_data_size; - assert(chunk_tv); if (fc->first_stream_chunk < 0) { uint8_t hs, ds; /* needed header/data slices */ uint8_t rs = fc->fcp->slices_per_group @@ -285,10 +286,16 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst) fc->first_stream_chunk = mmd->current_chunk; g->first_chunk = mmd->current_chunk; g->num = 0; + g->start = *now; } else { + /* + * Start and duration of this group depend only on the previous + * group. Compute the new group start as g->start += g->duration. + */ + struct timeval tmp = g->start; + tv_add(&tmp, &g->duration, &g->start); k = fc->fcp->data_slices_per_group + fc->num_extra_slices; - /* use duration of the previous group for the timing of this group */ - set_slice_duration(fc, g); + set_group_timing(fc, g); g->first_chunk += g->num_chunks; g->num++; } @@ -316,7 +323,7 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst) assert(g->num_chunks); fc->current_slice_num = 0; if (g->num == 0) - set_slice_duration(fc, g); + set_group_timing(fc, g); /* setup header slices */ buf = vsst->header_buf; @@ -354,14 +361,6 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst) g->first_chunk + g->num_chunks - 1, g->num_header_slices, data_slices ); - /* set group start */ - if (g->num != 0 && vsst->header_len != 0 && fc->first_stream_chunk == 0) - /* chunk #0 is the audio file header */ - tv_scale(g->first_chunk - 1, chunk_tv, &tmp); - else - tv_scale(g->first_chunk - fc->first_stream_chunk, - chunk_tv, &tmp); - tv_add(&fc->stream_start, &tmp, &g->start); return 1; } -- 2.39.2