X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=vss.c;h=c6e4053321c950e8ae03c352382610515de561cb;hp=aae601d14153d6973a8a86f8f8a93e69cd6c8bbd;hb=70f527312e613fd89be88177dc2a44ad24b2d27c;hpb=7cb521f3eeb7fda02344c523989d5903251e673e diff --git a/vss.c b/vss.c index aae601d1..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,46 +251,51 @@ 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); - k = fc->fcp->data_slices_per_group + fc->num_extra_slices; if (fc->first_stream_chunk < 0) { - uint32_t largest = afh_get_largest_chunk_size(&mmd->afd.afhi) - + vsst->header_len; - uint8_t needed, want; + uint8_t hs, ds; /* needed header/data slices */ + uint8_t rs = fc->fcp->slices_per_group + - fc->fcp->data_slices_per_group; /* redundant slices */ + int n; - ret = num_slices(largest, fc, &needed); + ret = num_slices(vsst->header_len, fc, &hs); + if (ret < 0) + return ret; + ret = num_slices(afh_get_largest_chunk_size(&mmd->afd.afhi), + fc, &ds); + if (ret < 0) + return ret; + k = (int)hs + ds; + if (k > 255) + return -E_BAD_CT; + if (k < fc->fcp->data_slices_per_group) + k = fc->fcp->data_slices_per_group; + n = k + rs; + fc->num_extra_slices = k - fc->fcp->data_slices_per_group; + PARA_NOTICE_LOG("fec parms %d:%d:%d (%d extra slices)\n", + slice_bytes, k, n, fc->num_extra_slices); + fec_free(fc->parms); + fc->src_data = para_realloc(fc->src_data, k * sizeof(char *)); + ret = fec_new(k, n, &fc->parms); if (ret < 0) return ret; - if (needed > fc->fcp->data_slices_per_group) - PARA_WARNING_LOG("fec parms insufficient for this audio file\n"); - want = PARA_MAX(needed, fc->fcp->data_slices_per_group); - if (want != k) { - fec_free(fc->parms); - fc->src_data = para_realloc(fc->src_data, want * sizeof(char *)); - ret = fec_new(want, want + fc->fcp->slices_per_group - - fc->fcp->data_slices_per_group, &fc->parms); - if (ret < 0) - return ret; - k = want; - fc->num_extra_slices = 0; - if (k > fc->fcp->data_slices_per_group) { - fc->num_extra_slices = k - fc->fcp->data_slices_per_group; - PARA_NOTICE_LOG("using %d extra slices\n", - fc->num_extra_slices); - } - } fc->stream_start = *now; fc->first_stream_chunk = mmd->current_chunk; g->first_chunk = mmd->current_chunk; g->num = 0; + g->start = *now; } else { - /* use duration of the previous group for the timing of this group */ - set_slice_duration(fc, g); + /* + * 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; + set_group_timing(fc, g); g->first_chunk += g->num_chunks; g->num++; } @@ -315,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; @@ -353,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; }