0.4.6 (to be announced) "deterministic entropy"
-----------------------------------------------
+ - For DCCP/OGG streams the audio file header is only sent once
+ at the beginning of the stream rather than periodically
+ every five seconds. This reduces network traffic and the
+ FEC group size.
+
--------------------------------------------
0.4.5 (2010-12-17) "symmetric randomization"
--------------------------------------------
int i, ret;
unsigned char *p, *inbuf, *outbuffer;
char *btr_buf;
- size_t len, skip, consumed, loaded, iqs;
+ size_t len, skip, consumed, loaded;
next_buffer:
t->error = 0;
len = btr_next_buffer(btrn, (char **)&inbuf);
len = PARA_MIN(len, (size_t)8192);
consumed = 0;
- iqs = btr_get_input_queue_size(btrn);
if (!padd->initialized) {
unsigned long rate = 0;
unsigned char channels = 0;
ret = -E_AAC_DECODE;
if (padd->error_count++ > MAX_ERRORS)
goto err;
- PARA_ERROR_LOG("frame_error: %d (%s), consumed: %zu + %zd + %lu\n",
- err, NeAACDecGetErrorMessage(padd->frame_info.error),
+ /* Suppress non-fatal bitstream error message at BOF/EOF */
+ if (len < fn->min_iqs || padd->consumed_total == 0) {
+ consumed = len;
+ goto success;
+ }
+ PARA_ERROR_LOG("%s\n", NeAACDecGetErrorMessage(err));
+ PARA_ERROR_LOG("consumed: %zu + %zd + %lu\n",
padd->consumed_total, consumed,
padd->frame_info.bytesconsumed);
- PARA_ERROR_LOG("%s\n", NeAACDecGetErrorMessage(
- padd->frame_info.error));
if (consumed < len)
consumed++; /* catch 21 */
goto success;
static void init_colors_or_die(void)
{
- int ret, i;
+ int i;
if (!want_colors())
return;
daemon_set_default_log_colors();
daemon_set_flag(DF_COLOR_LOG);
- for (i = 0; i < conf.log_color_given; i++) {
- ret = daemon_set_log_color(conf.log_color_arg[i]);
- if (ret < 0)
- exit(EXIT_FAILURE);
- }
+ for (i = 0; i < conf.log_color_given; i++)
+ daemon_set_log_color_or_die(conf.log_color_arg[i]);
}
/**
* \param value Human-readable color spec.
* \param dst Result pointer for the escape sequence.
*
- * \return -1 on errors, 1 on success.
- *
* Format of \a value: [fg [bg]] [attr].
*/
-int color_parse(const char *value, char *dst)
+void color_parse_or_die(const char *value, char *dst)
{
const char *ptr = value;
int attr = -1;
if (!strcasecmp(value, "reset")) {
strcpy(dst, COLOR_RESET);
- return 1;
+ return;
}
/* [fg [bg]] [attr] */
*dst++ = 'm';
}
*dst = 0;
- return 1;
+ return;
bad:
- PARA_ERROR_LOG("bad color value '%s'\n", value);
- return -1;
+ PARA_EMERG_LOG("bad color value '%s'\n", value);
+ exit(EXIT_FAILURE);
}
/** Switch back to normal colors. */
#define COLOR_RESET "\033[m"
-int color_parse(const char *value, char *dst);
+void color_parse_or_die(const char *value, char *dst);
#include <dirent.h>
#include <openssl/rc4.h>
#include <osl.h>
+#include <stdbool.h>
#include "para.h"
#include "error.h"
[LL_CRIT] = "magenta bold",
[LL_EMERG] = "red bold",
};
- for (i = 0; i < NUM_LOGLEVELS; i++) {
- int ret = color_parse(default_log_colors[i], me->log_colors[i]);
- assert(ret >= 0);
- }
+ for (i = 0; i < NUM_LOGLEVELS; i++)
+ color_parse_or_die(default_log_colors[i], me->log_colors[i]);
}
/**
*
* \return 1 On success, -1 on errors.
*/
-int daemon_set_log_color(char const *arg)
+void daemon_set_log_color_or_die(char const *arg)
{
char *p = strchr(arg, ':');
int ret, ll;
goto err;
ll = ret;
p++;
- ret = color_parse(p, me->log_colors[ll]);
- if (ret < 0)
- goto err;
- return 1;
+ color_parse_or_die(p, me->log_colors[ll]);
+ return;
err:
- PARA_ERROR_LOG("%s: color syntax error\n", arg);
- return -1;
-
+ PARA_EMERG_LOG("%s: color syntax error\n", arg);
+ exit(EXIT_FAILURE);
}
/**
void daemon_clear_flag(unsigned flag);
void daemon_set_loglevel(char *loglevel);
void daemon_set_default_log_colors(void);
-int daemon_set_log_color(char const *arg);
+void daemon_set_log_color_or_die(char const *arg);
/** Daemon log configuration flags. */
enum daemon_flags {
dfc->fcp.slices_per_group = conf.dccp_slices_per_group_arg;
dfc->fcp.init_fec = dccp_init_fec;
dfc->fcp.send_fec = dccp_send_fec;
+ dfc->fcp.need_periodic_header = false;
dfc->fc = vss_add_fec_client(sc, &dfc->fcp);
}
#include <sys/types.h>
#include <dirent.h>
#include <osl.h>
+#include <stdbool.h>
#include "para.h"
#include "error.h"
/** Version text used by various commands if -V switch was given. */
#define VERSION_TEXT(prefix) "para_" prefix " " PACKAGE_VERSION \
" (" GIT_VERSION ": " CODENAME ")" "\n" \
- "Copyright (C) 2010 Andre Noll\n" \
+ "Copyright (C) 2011 Andre Noll\n" \
"This is free software with ABSOLUTELY NO WARRANTY." \
" See COPYING for details.\n" \
"Written by Andre Noll.\n" \
uint8_t slices_per_group;
/** Number of slices minus number of redundant slices. */
uint8_t data_slices_per_group;
+ /** Whether the header must be sent periodically. */
+ bool need_periodic_header;
/**
* Transport-layer initialisation for FEC support.
*
#include <openssl/rc4.h>
#include <regex.h>
#include <osl.h>
+#include <stdbool.h>
#include "para.h"
#include "error.h"
static void init_colors_or_die(void)
{
- int ret, i;
+ int i;
if (!want_colors())
return;
daemon_set_flag(DF_COLOR_LOG);
daemon_set_default_log_colors();
- for (i = 0; i < conf.log_color_given; i++) {
- ret = daemon_set_log_color(conf.log_color_arg[i]);
- if (ret < 0)
- exit(EXIT_FAILURE);
- }
+ for (i = 0; i < conf.log_color_given; i++)
+ daemon_set_log_color_or_die(conf.log_color_arg[i]);
}
/*
#include <netinet/udp.h>
#include <net/if.h>
#include <osl.h>
+#include <stdbool.h>
#include "server.cmdline.h"
#include "para.h"
ut->fcp.data_slices_per_group = scd->data_slices_per_group;
ut->fcp.init_fec = udp_init_fec;
ut->fcp.send_fec = udp_send_fec;
+ ut->fcp.need_periodic_header = true;
sc->private_data = ut;
sc->fd = -1;
return false;
if (vsst->header_len == 0)
return false;
- if (fc->group.num && tv_diff(&fc->next_header_time, now, NULL) > 0)
- return false;
+ if (fc->group.num > 0) {
+ if (!fc->fcp->need_periodic_header)
+ return false;
+ if (tv_diff(&fc->next_header_time, now, NULL) > 0)
+ return false;
+ }
tv_add(now, &vsst->header_interval, &fc->next_header_time);
return true;
}
+static bool need_data_slices(struct fec_client *fc, struct vss_task *vsst)
+{
+ if (fc->group.num > 0)
+ return true;
+ if (!vsst->header_buf)
+ return true;
+ if (vsst->header_len == 0)
+ return true;
+ if (fc->fcp->need_periodic_header)
+ return true;
+ return false;
+}
+
static int num_slices(long unsigned bytes, int max_payload, int rs)
{
int ret;
}
/* set group start and group duration */
-static void set_group_timing(struct fec_client *fc, struct fec_group *g)
+static void set_group_timing(struct fec_client *fc, struct vss_task *vsst)
{
+ struct fec_group *g = &fc->group;
struct timeval *chunk_tv = vss_chunk_time();
- tv_scale(g->num_chunks, chunk_tv, &g->duration);
+ if (!need_data_slices(fc, vsst))
+ ms2tv(200, &g->duration);
+ else
+ tv_scale(g->num_chunks, chunk_tv, &g->duration);
tv_divide(fc->fcp->slices_per_group + fc->num_extra_slices,
&g->duration, &g->slice_duration);
PARA_DEBUG_LOG("durations (group/chunk/slice): %lu/%lu/%lu\n",
if (ret < 0)
return ret;
ds = ret;
- k = hs + ds;
+ if (fc->fcp->need_periodic_header)
+ k = hs + ds;
+ else
+ k = PARA_MAX(hs, ds);
if (k < fc->fcp->data_slices_per_group)
k = fc->fcp->data_slices_per_group;
fc->num_extra_slices = k - fc->fcp->data_slices_per_group;
g->slice_bytes = 1;
return 1;
}
+ if (!need_data_slices(fc, vsst)) {
+ g->bytes = 0;
+ g->num_chunks = 0;
+ g->slice_bytes = DIV_ROUND_UP(vsst->header_len, k);
+ g->num_header_slices = k;
+ return 1;
+ }
h = vsst->header_len;
max_group_bytes = (k - num_slices(h, max_slice_bytes, n - k))
* max_slice_bytes;
*/
tmp = g->start;
tv_add(&tmp, &g->duration, &g->start);
- set_group_timing(fc, g);
+ set_group_timing(fc, vsst);
g->first_chunk += g->num_chunks;
g->num++;
}
assert(g->num_header_slices + data_slices <= k);
fc->current_slice_num = 0;
if (g->num == 0)
- set_group_timing(fc, g);
+ set_group_timing(fc, vsst);
/* setup header slices */
buf = vsst->header_buf;