From: Andre Noll Date: Mon, 30 Nov 2009 22:50:48 +0000 (+0100) Subject: fecdec: Wait until the second FEC group is complete. X-Git-Tag: v0.3.6~3 X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=commitdiff_plain;h=7b4830d1d2191f0affd0aeedb7fa08e59d3148f7 fecdec: Wait until the second FEC group is complete. Currently the fecdec filter starts writing output as soon as the first slice of the second group arrives. This makes the logic in fecdec_filter.c quite convoluted and does not help much to avoid buffer underruns. Waiting for completion of the second group simplifies the code quite a bit and adds more more buffering to the fecdec filter which should make buffer underruns less likely. --- diff --git a/fecdec_filter.c b/fecdec_filter.c index 18dcb34d..a6218e43 100644 --- a/fecdec_filter.c +++ b/fecdec_filter.c @@ -70,20 +70,6 @@ struct fecdec_group { unsigned char **data; }; -/** - * The fecdec filter defers decoding of the first group until the first slice - * of the next group was received. This avoids buffer underruns in subsequent - * filters of the filter chain. - */ -enum group_completion_status { - /** No complete group received so far. */ - GCS_NO_COMPLETE_GROUP, - /** First group received, but not yet decoded. */ - GCS_FIRST_GROUP_COMPLETE, - /** At least one complete group decoded. */ - GCS_FIRST_GROUP_DECODED, -}; - /** * Data private to the fecdec filter. */ @@ -94,8 +80,6 @@ struct private_fecdec_data { struct fecdec_group groups[NUM_FEC_GROUPS]; /** Whether an audio file header was already received. */ int have_header; - /** See \ref group_completion_status. */ - unsigned completion_status; /** Points to the first received group. */ struct fecdec_group *first_complete_group; }; @@ -175,8 +159,7 @@ static struct fecdec_group *try_to_free_group(struct private_fecdec_data *pfd) * Don't clear the first complete group if it has not yet been * decoded. */ - if (pfd->completion_status == GCS_FIRST_GROUP_COMPLETE - && pfd->first_complete_group == fg) + if (fg == pfd->first_complete_group) continue; clear_group(fg); return fg; @@ -196,8 +179,8 @@ static struct fecdec_group *free_oldest_group(struct private_fecdec_data *pfd) PARA_WARNING_LOG("Clearing incomplete group %d " "(contains %d slices)\n", oldest->h.group_num, oldest->num_received_slices); - assert(pfd->completion_status != GCS_FIRST_GROUP_COMPLETE - || oldest != pfd->first_complete_group); + if (oldest == pfd->first_complete_group) + pfd->first_complete_group = NULL; clear_group(oldest); return oldest; } @@ -390,41 +373,39 @@ static int dispatch_slice(char *buf, size_t len, struct fec_header *h, ret = get_group(h, pfd, &fg); if (ret < 0) return ret; - if (!add_slice(buf, fg)) + if (!add_slice(buf, fg)) /* group already complete */ return 1; - if (group_complete(fg)) { - if (pfd->completion_status == GCS_NO_COMPLETE_GROUP) { - enum fec_group_usability u = group_is_usable(fg, pfd); - assert(u != FEC_GROUP_USABLE_SKIP_HEADER); - if (u == FEC_GROUP_UNUSABLE) - return 1; - pfd->completion_status = GCS_FIRST_GROUP_COMPLETE; - pfd->first_complete_group = fg; + if (!group_complete(fg)) + return 1; + /* this slice completed the group */ + if (pfd->fec) + goto decode; + /* it's either the first or the second complete group */ + if (!pfd->first_complete_group) { /* it's the first group */ + enum fec_group_usability u = group_is_usable(fg, pfd); + assert(u != FEC_GROUP_USABLE_SKIP_HEADER); + if (u == FEC_GROUP_UNUSABLE) /* forget it */ return 1; - } - assert(pfd->fec); - ret = decode_group(fg, fn); - if (ret < 0) - return ret; + pfd->first_complete_group = fg; /* remember it */ return 1; } - if (pfd->completion_status == GCS_NO_COMPLETE_GROUP) - return 1; - if (pfd->completion_status == GCS_FIRST_GROUP_DECODED) - return 1; - if (fg == pfd->first_complete_group) - return 1; - assert(!pfd->fec); + /* we have two complete groups, let's go */ k = h->data_slices_per_group; n = h->slices_per_group; PARA_NOTICE_LOG("init fec (%d, %d)\n", k, n); ret = fec_new(k, n, &pfd->fec); if (ret < 0) return ret; + /* decode and clear the first group */ ret = decode_group(pfd->first_complete_group, fn); if (ret < 0) return ret; - pfd->completion_status = GCS_FIRST_GROUP_DECODED; + clear_group(pfd->first_complete_group); + pfd->first_complete_group = NULL; +decode: + ret = decode_group(fg, fn); + if (ret < 0) + return ret; return 1; } @@ -468,7 +449,6 @@ static void fecdec_open(struct filter_node *fn) fn->bufsize = FECDEC_DEFAULT_OUTBUF_SIZE; fn->buf = para_malloc(fn->bufsize); pfd = para_calloc(sizeof(*pfd)); - pfd->completion_status = GCS_NO_COMPLETE_GROUP; fn->private_data = pfd; fn->loaded = 0; }