default="2"
optional
-option "sample_rate" s
+option "samplerate" s
#~~~~~~~~~~~~~~~~~~~~~
"force given sample rate (only neccessary for
struct timeval next_chunk;
/** the return value of snd_pcm_hw_params_get_buffer_time_max() */
unsigned buffer_time;
+ unsigned samplerate;
+ unsigned channels;
};
/*
snd_pcm_uframes_t period_size;
struct private_alsa_data *pad = para_calloc(sizeof(struct private_alsa_data));
struct alsa_write_args_info *conf = w->conf;
-
+ struct writer_node_group *wng = w->wng;
+
+ if (!conf->samplerate_given && wng->samplerate)
+ pad->samplerate = *wng->samplerate;
+ else
+ pad->samplerate = conf->samplerate_arg;
+ if (!conf->channels_given && wng->channels)
+ pad->channels = *wng->channels;
+ else
+ pad->channels = conf->channels_arg;
+ PARA_INFO_LOG("%d channel(s), %dHz\n", pad->channels, pad->samplerate);
w->private_data = pad;
snd_pcm_info_alloca(&info);
err = snd_pcm_open(&pad->handle, conf->device_arg,
if (snd_pcm_hw_params_set_format(pad->handle, hwparams, FORMAT) < 0)
return -E_SAMPLE_FORMAT;
if (snd_pcm_hw_params_set_channels(pad->handle, hwparams,
- conf->channels_arg) < 0)
+ pad->channels) < 0)
return -E_CHANNEL_COUNT;
if (snd_pcm_hw_params_set_rate_near(pad->handle, hwparams,
- (unsigned int*) &conf->sample_rate_arg, 0) < 0)
+ &pad->samplerate, 0) < 0)
return -E_SET_RATE;
err = snd_pcm_hw_params_get_buffer_time_max(hwparams, &pad->buffer_time, 0);
if (err < 0 || !pad->buffer_time)
if (snd_pcm_sw_params(pad->handle, swparams) < 0)
return -E_SW_PARAMS;
pad->bytes_per_frame = snd_pcm_format_physical_width(FORMAT)
- * conf->channels_arg / 8;
+ * pad->channels / 8;
if (snd_pcm_nonblock(pad->handle, 1))
PARA_ERROR_LOG("%s\n", "failed to set nonblock mode");
return period_size * pad->bytes_per_frame;
struct writer_node_group *wng = wn->wng;
struct timeval diff;
- t->ret = 0;
- if (*wng->input_eof && *wng->loaded < pad->bytes_per_frame)
- return;
t->ret = 1;
- if (*wng->loaded < pad->bytes_per_frame)
+ if (*wng->input_eof && *wng->loaded < pad->bytes_per_frame)
return;
if (tv_diff(&s->now, &pad->next_chunk, &diff) < 0) {
if (tv_diff(&s->timeout, &diff, NULL) > 0)
s->timeout = diff;
} else {
s->timeout.tv_sec = 0;
- s->timeout.tv_usec = 0;
+ s->timeout.tv_usec = 1000;
}
+// PARA_INFO_LOG("timeout: %lu\n", tv2ms(&s->timeout));
}
static void alsa_write_post_select(struct sched *s, struct task *t)
struct private_alsa_data *pad = wn->private_data;
struct writer_node_group *wng = wn->wng;
size_t frames = *wng->loaded / pad->bytes_per_frame;
- snd_pcm_sframes_t ret, result = 0;
+ snd_pcm_sframes_t ret;
unsigned char *data = (unsigned char*)wng->buf;
+ struct timeval tv;
t->ret = 0;
+// PARA_INFO_LOG("%zd frames\n", frames);
if (!frames) {
if (*wng->input_eof)
t->ret = *wng->loaded;
}
if (tv_diff(&s->now, &pad->next_chunk, NULL) < 0)
return;
-// PARA_INFO_LOG("%zd frames\n", frames);
-// while (frames > 0) {
- ret = snd_pcm_writei(pad->handle, data, frames);
- if (ret == -EAGAIN || (ret >= 0 && ret < frames)) {
- struct timeval tv;
- ms2tv(pad->buffer_time / 2000, &tv);
- PARA_DEBUG_LOG("EAGAIN. frames: %d, ret: %lu\n", frames, ret);
- tv_add(&s->now, &tv, &pad->next_chunk);
- } else if (ret == -EPIPE) {
- PARA_WARNING_LOG("%s", "EPIPE\n");
- snd_pcm_prepare(pad->handle);
- } else if (ret < 0) {
- t->ret = -E_ALSA_WRITE;
- return;
- }
- if (ret >= 0) {
- result += ret;
- frames -= ret;
- data += ret * pad->bytes_per_frame;
- }
-// if (ret == -EAGAIN)
-// break;
-// }
- t->ret = result * pad->bytes_per_frame;
+ ret = snd_pcm_writei(pad->handle, data, frames);
+ if (ret == -EPIPE) {
+ PARA_WARNING_LOG("%s", "EPIPE\n");
+ snd_pcm_prepare(pad->handle);
+ return;
+ }
+ if (ret < 0) {
+ PARA_WARNING_LOG("%s", "ALSA ERROR\n");
+ t->ret = -E_ALSA_WRITE;
+ return;
+ }
+// ms2tv(pad->buffer_time / 4000, &tv);
+ ms2tv(1, &tv);
+ tv_add(&s->now, &tv, &pad->next_chunk);
+ t->ret = ret * pad->bytes_per_frame;
// PARA_INFO_LOG("ret: %d, frames: %zd\n", t->ret, frames);
}
s->wng->buf = s->fc->outbuf;
s->wng->loaded = s->fc->out_loaded;
s->wng->input_eof = &s->fc->eof;
+ s->wng->channels = &s->fc->channels;
+ s->wng->samplerate = &s->fc->samplerate;
s->fc->output_eof = &s->wng->eof;
+ PARA_INFO_LOG("samplerate: %d\n", *s->wng->samplerate);
} else {
s->wng->buf = s->receiver_node->buf;
s->wng->loaded = &s->receiver_node->loaded;
s->wng->writer_nodes[i].writer = a->writers[i];
sprintf(s->wng->writer_nodes[i].task.status, "writer_node");
}
- ret = wng_open(s->wng);
+ ret = wng_open(s->wng); /* FIXME */
s->wstime = *now;
current_decoder = slot_num;
activate_inactive_grab_clients(slot_num, s->format, &s->fc->filters);
{
int i;
+ t->ret = 1;
now = &s->now;
if (audiod_status != AUDIOD_ON)
kill_all_decoders();
else if (playing)
open_current_receiver();
FOR_EACH_SLOT(i) {
- struct receiver_node *rn;
+ struct slot_info *s = &slot[i];
+ struct audio_format_info *a;
try_to_close_slot(i);
- if (slot[i].format < 0)
+ if (s->format < 0)
+ continue;
+ a = &afi[s->format];
+ if (!s->receiver_node)
continue;
- rn = slot[i].receiver_node;
- if (rn && rn->loaded && !slot[i].wng) {
+ if (!a->num_filters) {
+ if (s->receiver_node->loaded && !s->wng)
+ open_writers(i);
+ continue;
+ }
+ if (s->receiver_node->loaded && !s->fc) {
open_filters(i);
- open_writers(i);
+ continue;
}
+ if (s->fc && *s->fc->out_loaded && !s->wng)
+ open_writers(i);
}
}
{
/* only save away the current time for other users */
now = &s->now;
+ t->ret = 1;
}
static void init_audiod_task(struct task *t)
static void command_pre_select(struct sched *s, struct task *t)
{
struct command_task *ct = t->private_data;
+ t->ret = 1;
para_fd_set(ct->fd, &s->rfds, &s->max_fileno);
}
int ret;
struct command_task *ct = t->private_data;
+ t->ret = 1; /* always successful */
if (audiod_status != AUDIOD_OFF)
audiod_status_dump();
- t->ret = 1; /* always successful */
if (!FD_ISSET(ct->fd, &s->rfds))
return;
ret = handle_connect(ct->fd);
PARA_ERROR(AAC_READ, "aac read error"), \
PARA_ERROR(STSZ, "did not find stcz atom"), \
PARA_ERROR(MP4ASC, "audio spec config error"), \
+ PARA_ERROR(AAC_OVERRUN, "aac output buffer overrun"), \
#define AAC_COMMON_ERRORS \
int conv, conv_total = 0;
t->ret = -E_FC_EOF;
- if (*fc->output_eof)
+ if (fc->output_eof && *fc->output_eof)
goto err_out;
again:
ib = fc->inbuf;
loaded = &fn->loaded;
}
conv_total += conv;
- PARA_INFO_LOG("eof (in/out/fc): %d/%d/%d out_loaded: %d, conv: %d, conv_total: %d\n", *fc->input_eof,
- *fc->output_eof, fc->eof, *fc->out_loaded, conv, conv_total);
+// PARA_INFO_LOG("eof (in/out/fc): %d/%d/%d out_loaded: %d, conv: %d, conv_total: %d\n", *fc->input_eof,
+// *fc->output_eof, fc->eof, *fc->out_loaded, conv, conv_total);
if (conv)
goto again;
t->ret = 1;
again:
list_for_each_entry_safe(t, tmp, &pre_select_list, pre_select_node) {
t->pre_select(s, t);
- if (t->ret > 0 || !t->event_handler)
+// PARA_INFO_LOG("%s \n", t->status);
+ if (t->ret > 0)
+ continue;
+ if (!t->event_handler)
continue;
t->event_handler(t);
goto again;
list_for_each_entry_safe(t, tmp, &post_select_list, post_select_node) {
t->post_select(s, t);
+// PARA_INFO_LOG("%s \n", t->status);
if (t->ret > 0 || !t->event_handler)
continue;
t->event_handler(t);
size_t *loaded;
int *eof;
unsigned channels;
- unsigned sample_rate;
+ unsigned samplerate;
struct task task;
};
return;
}
cwt->channels = 2;
- cwt->sample_rate = 44100;
+ cwt->samplerate = 44100;
a = (unsigned char*)cwt->buf;
t->ret = -E_NO_WAV_HEADER;
if (a[0] != 'R' || a[1] != 'I' || a[2] != 'F' || a[3] != 'F')
return;
cwt->channels = (unsigned) a[22];
- cwt->sample_rate = a[24] + (a[25] << 8) + (a[26] << 16) + (a[27] << 24);
+ cwt->samplerate = a[24] + (a[25] << 8) + (a[26] << 16) + (a[27] << 24);
*cwt->loaded -= WAV_HEADER_LEN;
memmove(cwt->buf, cwt->buf + WAV_HEADER_LEN, *cwt->loaded);
t->ret = -E_WAV_HEADER_SUCCESS;
- PARA_INFO_LOG("channels: %d, sample_rate: %d\n", cwt->channels, cwt->sample_rate);
+ PARA_INFO_LOG("channels: %d, sample rate: %d\n", cwt->channels, cwt->samplerate);
}
static void initial_delay_pre_select(struct sched *s, struct task *t)
wng->loaded = &sit.loaded;
wng->input_eof = &sit.eof;
wng->task.event_handler = wng_event_handler;
+ wng->channels = &cwt.channels;
+ wng->samplerate = &cwt.samplerate;
ret = wng_open(wng);
if (ret < 0) {
PARA_ERROR_LOG("%s\n", PARA_STRERROR(-ret));
int *input_eof;
int eof;
char *buf;
+ unsigned int *channels;
+ unsigned int *samplerate;
size_t *loaded;
struct task task;
};