From ee66911aeab325627c349edcb5f7e1fa40aeabf7 Mon Sep 17 00:00:00 2001
From: Andre Noll <maan@systemlinux.org>
Date: Sat, 7 Aug 2010 16:50:59 +0200
Subject: [PATCH] FEC initialization cleanups.

Initialization was performed in two steps: During vss_send and
during compute_next_fec_slice(). This patch moves the init code
for fec clients to the single location.
---
 vss.c | 151 +++++++++++++++++++++++++++++-----------------------------
 1 file changed, 76 insertions(+), 75 deletions(-)

diff --git a/vss.c b/vss.c
index 941f22fd..7980ccc8 100644
--- a/vss.c
+++ b/vss.c
@@ -229,9 +229,9 @@ static int need_audio_header(struct fec_client *fc, struct vss_task *vsst)
 	return 1;
 }
 
-static int num_slices(long unsigned bytes, struct fec_client *fc, int rs)
+static int num_slices(long unsigned bytes, int mps, int rs)
 {
-	int m = fc->fcp->max_slice_bytes - FEC_HEADER_SIZE;
+	int m = mps - FEC_HEADER_SIZE;
 	int ret;
 
 	assert(m > 0);
@@ -254,48 +254,84 @@ static void set_group_timing(struct fec_client *fc, struct fec_group *g)
 		tv2ms(&g->duration), tv2ms(chunk_tv), tv2ms(&g->slice_duration));
 }
 
-static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
+static int initialize_fec_client(struct fec_client *fc, struct vss_task *vsst)
 {
-	int ret, i, k, data_slices;
+	int k, n, ret, mps;
 	int hs, ds, rs; /* header/data/redundant slices */
+	struct fec_client_parms *fcp = fc->fcp;
+
+	/* set mps */
+	if (fcp->init_fec) {
+		/*
+		 * Set the maximum slice size to the Maximum Packet Size if the
+		 * transport protocol allows to determine this value. The user
+		 * can specify a slice size up to this value.
+		 */
+		ret = fcp->init_fec(fc->sc);
+		if (ret < 0)
+			return ret;
+		mps = ret;
+	} else
+		mps = generic_max_transport_msg_size(fc->sc->fd);
+	if (mps <= FEC_HEADER_SIZE)
+		return -ERRNO_TO_PARA_ERROR(EINVAL);
+
+	rs = fc->fcp->slices_per_group - fc->fcp->data_slices_per_group;
+	ret = num_slices(vsst->header_len, mps, rs);
+	if (ret < 0)
+		goto err;
+	hs = ret;
+	ret = num_slices(afh_get_largest_chunk_size(&mmd->afd.afhi),
+		mps, rs);
+	if (ret < 0)
+		goto err;
+	ds = ret;
+	k = ret + ds;
+	if (k < fc->fcp->data_slices_per_group)
+		k = fc->fcp->data_slices_per_group;
+	n = k + rs;
+	PARA_CRIT_LOG("hs: %d, ds: %d, rs: %d, k: %d, n: %d\n", hs, ds, rs, k, n);
+	fec_free(fc->parms);
+	ret = fec_new(k, n, &fc->parms);
+	if (ret < 0)
+		return ret;
+	fc->num_extra_slices = k - fc->fcp->data_slices_per_group;
+	PARA_NOTICE_LOG("fec parms %d:%d:%d (%d extra slices)\n",
+		mps, k, n, fc->num_extra_slices);
+	fc->src_data = para_realloc(fc->src_data, k * sizeof(char *));
+	fc->enc_buf = para_realloc(fc->enc_buf, mps);
+	memset(fc->enc_buf, 0, mps);
+	fc->extra_src_buf = para_realloc(fc->extra_src_buf, mps);
+	memset(fc->extra_src_buf, 0, mps);
+
+	fc->fcp->max_slice_bytes = mps;
+	fc->state = FEC_STATE_READY_TO_RUN;
+	fc->next_header_time.tv_sec = 0;
+	fc->stream_start = *now;
+	fc->first_stream_chunk = mmd->current_chunk;
+	return 1;
+err:
+	fec_free(fc->parms);
+	return ret;
+}
+
+static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
+{
+	int ret, i, k, n, data_slices;
 	size_t len;
 	const char *buf, *start_buf;
 	struct fec_group *g = &fc->group;
-	unsigned slice_bytes = fc->fcp->max_slice_bytes - FEC_HEADER_SIZE;
+	unsigned slice_bytes;
 	uint32_t max_data_size;
 
-	rs = fc->fcp->slices_per_group - fc->fcp->data_slices_per_group;
 	if (fc->first_stream_chunk < 0) {
-		int n;
-
-		ret = num_slices(vsst->header_len, fc, rs);
-		if (ret < 0)
-			return ret;
-		hs = ret;
-		ret = num_slices(afh_get_largest_chunk_size(&mmd->afd.afhi),
-			fc, rs);
-		if (ret < 0)
-			return ret;
-		ds = ret;
-		k = 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);
+		ret = initialize_fec_client(fc, vsst);
 		if (ret < 0)
 			return ret;
-		fc->stream_start = *now;
-		fc->first_stream_chunk = mmd->current_chunk;
 		g->first_chunk = mmd->current_chunk;
 		g->num = 0;
 		g->start = *now;
+		
 	} else {
 		struct timeval tmp;
 		if (g->first_chunk + g->num_chunks >= mmd->afd.afhi.chunks_total)
@@ -306,13 +342,18 @@ static int setup_next_fec_group(struct fec_client *fc, struct vss_task *vsst)
 		 */
 		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++;
 	}
+	slice_bytes = fc->fcp->max_slice_bytes - FEC_HEADER_SIZE;
+	PARA_CRIT_LOG("slice_bytes: %d\n", slice_bytes);
+	k = fc->fcp->data_slices_per_group + fc->num_extra_slices;
+	n = fc->fcp->slices_per_group + fc->num_extra_slices;
+	PARA_CRIT_LOG("k: %d, n: %d\n", k, n);
 	if (need_audio_header(fc, vsst)) {
-		ret = num_slices(vsst->header_len, fc, rs);
+		ret = num_slices(vsst->header_len, fc->fcp->max_slice_bytes,
+			n - k);
 		if (ret < 0)
 			return ret;
 		g->num_header_slices = ret;
@@ -813,42 +854,6 @@ err:
 	mmd->new_vss_status_flags = VSS_NEXT;
 }
 
-static int initialize_fec_client(struct fec_client *fc)
-{
-	int ret;
-	struct fec_client_parms *fcp = fc->fcp;
-
-	if (fcp->init_fec) {
-		/*
-		 * Set the maximum slice size to the Maximum Packet Size if the
-		 * transport protocol allows to determine this value. The user
-		 * can specify a slice size up to this value.
-		 */
-		ret = fcp->init_fec(fc->sc);
-		if (ret < 0)
-			return ret;
-		if (!fcp->max_slice_bytes || fcp->max_slice_bytes > ret)
-			fcp->max_slice_bytes = ret;
-	}
-	if (fcp->max_slice_bytes < FEC_HEADER_SIZE + fcp->data_slices_per_group)
-		return -ERRNO_TO_PARA_ERROR(EINVAL);
-	ret = fec_new(fcp->data_slices_per_group, fcp->slices_per_group,
-		&fc->parms);
-	if (ret < 0)
-		goto err;
-	fc->first_stream_chunk = -1; /* stream not yet started */
-	fc->src_data = para_malloc(fc->fcp->slices_per_group * sizeof(char *));
-	fc->enc_buf = para_calloc(fc->fcp->max_slice_bytes);
-	fc->num_extra_slices = 0;
-	fc->extra_src_buf = para_calloc(fc->fcp->max_slice_bytes);
-	fc->next_header_time.tv_sec = 0;
-	fc->state = FEC_STATE_READY_TO_RUN;
-	return 1;
-err:
-	fec_free(fc->parms);
-	return ret;
-}
-
 /**
  * Main sending function.
  *
@@ -860,7 +865,7 @@ err:
  */
 static void vss_send(struct vss_task *vsst)
 {
-	int ret, i, fec_active = 0;
+	int i, fec_active = 0;
 	struct timeval due;
 	struct fec_client *fc, *tmp_fc;
 
@@ -876,11 +881,7 @@ static void vss_send(struct vss_task *vsst)
 		case FEC_STATE_DISABLED:
 			continue;
 		case FEC_STATE_NONE:
-			ret = initialize_fec_client(fc);
-			if (ret < 0) {
-				PARA_ERROR_LOG("%s\n", para_strerror(-ret));
-				continue;
-			}
+			fc->first_stream_chunk = -1; /* need setup */
 			/* fall through */
 		case FEC_STATE_READY_TO_RUN:
 			break;
-- 
2.39.5