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);
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)
*/
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;
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.
*
*/
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;
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;