-static ssize_t ogg_convert(char *inbuffer, size_t len, struct filter_node *fn)
-{
- ssize_t ret;
- struct private_oggdec_data *pod = fn->private_data;
- struct oggdec_filter_args_info *conf = fn->conf;
- /* make the buffer known to the read callback cb_read() */
- pod->inbuf = inbuffer;
- pod->inbuf_len = len;
- pod->converted = 0;
-
- if (!pod->vf) {
- if (*fn->fc->input_error < 0)
- return *fn->fc->input_error;
- if (!len)
- return 0;
- pod->vf = para_malloc(sizeof(struct OggVorbis_File));
- PARA_NOTICE_LOG("input buffer: %zd, opening ov callbacks\n", len);
- ret = ov_open_callbacks(fn, pod->vf,
- NULL, /* no initial buffer */
- 0, /* no initial bytes */
- ovc); /* the ov_open_callbacks */
- if (ret == OV_ENOTVORBIS || ret == OV_EBADHEADER) {
- /* this might be due to the input buffer being too small */
- int ib = 1024 * conf->initial_buffer_arg; /* initial buffer */
- if (len < ib) {
- PARA_INFO_LOG("initial input buffer %zd/%d, "
- "waiting for more data\n", len, ib);
- free(pod->vf);
- pod->vf = NULL;
- return 0;
- }
- return ret == OV_ENOTVORBIS?
- -E_OGGDEC_NOTVORBIS : -E_OGGDEC_BADHEADER;
- }
- if (ret == OV_EREAD)
- return -E_OGGDEC_READ;
- if (ret == OV_EVERSION)
- return -E_OGGDEC_VERSION;
- if (ret < 0)
- return -E_OGGDEC_FAULT;
- fn->fc->channels = ov_info(pod->vf, 0)->channels;
- fn->fc->samplerate = ov_info(pod->vf, 0)->rate;
- PARA_NOTICE_LOG("%d channels, %d Hz\n", fn->fc->channels,
- fn->fc->samplerate);
- /* wait a bit to avoid buffer underruns */
- tv_add(now, &(struct timeval){0, 500 * 1000}, &pod->stream_start);
- return pod->converted;
- }
- if (tv_diff(now, &pod->stream_start, NULL) < 0) {
- PARA_DEBUG_LOG("initial delay..\n");
- return 0;
- }
- while (fn->loaded < fn->bufsize) {
- int length = fn->bufsize - fn->loaded;
- long read_ret = ov_read(pod->vf, fn->buf + fn->loaded, length,
- ENDIAN, 2 /* 16 bit */, 1 /* signed */, NULL);
- if (read_ret == 0)
- return pod->converted;
- if (read_ret == OV_HOLE) {
- if (!fn->loaded) {
- PARA_INFO_LOG("hole, delaying playback\n");
- tv_add(now, &(struct timeval){0, 500 * 1000}, &pod->stream_start);
- }
- return pod->converted;
- }
- if (read_ret < 0)
- return -E_OGGDEC_BADLINK;
- fn->loaded += read_ret;
- }
- return pod->converted;
-}
-
-static int oggdec_parse_config(int argc, char **argv, void **config)
-{
- int ret;
- struct oggdec_filter_args_info *ogg_conf;
-
- ogg_conf = para_calloc(sizeof(*ogg_conf));
- ret = -E_OGGDEC_SYNTAX;
- if (oggdec_cmdline_parser(argc, argv, ogg_conf))
- goto err;
- ret = -ERRNO_TO_PARA_ERROR(EINVAL);
- if (ogg_conf->bufsize_arg < 0)
- goto err;
- if (ogg_conf->bufsize_arg >= INT_MAX / 1024)
- goto err;
- if (ogg_conf->initial_buffer_arg < 0)
- goto err;
- if (ogg_conf->initial_buffer_arg >= INT_MAX / 1024)
- goto err;
- *config = ogg_conf;
- return 1;
-err:
- free(ogg_conf);
- return ret;
-}
-
-static void oggdec_free_config(void *conf)
-{
- oggdec_cmdline_parser_free(conf);
-}
-