From 4c537cd0770d81fc3c3937010b75a67f18370d84 Mon Sep 17 00:00:00 2001 From: Andre Noll Date: Sun, 3 Jan 2010 03:00:46 +0100 Subject: [PATCH] Consolidate decoder code by introducing prepare_filter_node(). --- aacdec_filter.c | 28 ++++++---------------------- buffer_tree.c | 8 ++++++++ buffer_tree.h | 1 + filter.h | 1 + filter_common.c | 20 ++++++++++++++++++++ mp3dec_filter.c | 28 ++++++++++++++-------------- oggdec_filter.c | 18 +++++++++++++----- wmadec_filter.c | 20 ++++++++------------ 8 files changed, 71 insertions(+), 53 deletions(-) diff --git a/aacdec_filter.c b/aacdec_filter.c index 0b520da4..f41fe8b1 100644 --- a/aacdec_filter.c +++ b/aacdec_filter.c @@ -235,29 +235,13 @@ static void aacdec_post_select(__a_unused struct sched *s, struct task *t) next_buffer: t->error = 0; - iqs = btr_get_input_queue_size(btrn); - if (iqs < 2048) { - if (!btr_no_parent(btrn)) /* wait for more data */ - return; - } - if (btr_bytes_pending(btrn) > AACDEC_MAX_PENDING) - return; - /* avoid "buffer too small" errors from the decoder */ - for (;;) { - len = btr_next_buffer(btrn, (char **)&inbuf); - if (len >= 2048) - break; - if (btr_merge(btrn) < 2) /* only one buffer left */ - break; - } - //PARA_CRIT_LOG("next buffer: %zu\n", len); - if (len == 0) { - if (btr_no_parent(btrn)) { - ret = -E_AACDEC_EOF; - goto err; - } + ret = prepare_filter_node(btrn, 2048); + if (ret < 0) + goto err; + if (ret == 0) return; - } + len = btr_next_buffer(btrn, (char **)&inbuf); + iqs = btr_get_input_queue_size(btrn); if (!padd->initialized) { unsigned long rate = 0; unsigned char channels = 0; diff --git a/buffer_tree.c b/buffer_tree.c index 2c02c694..7e0ec278 100644 --- a/buffer_tree.c +++ b/buffer_tree.c @@ -363,3 +363,11 @@ void btr_merge_to(struct btr_node *btrn, size_t dest_size) return; } } + +bool btr_eof(struct btr_node *btrn) +{ + char *buf; + size_t len = btr_next_buffer(btrn, &buf); + + return (len == 0 && btr_no_parent(btrn)); +} diff --git a/buffer_tree.h b/buffer_tree.h index 4d3502d5..094bfeac 100644 --- a/buffer_tree.h +++ b/buffer_tree.h @@ -21,3 +21,4 @@ void btr_pushdown(struct btr_node *btrn); void *btr_context(struct btr_node *btrn); int btr_merge(struct btr_node *btrn); void btr_merge_to(struct btr_node *btrn, size_t dest_size); +bool btr_eof(struct btr_node *btrn); diff --git a/filter.h b/filter.h index ab187df2..ec8631f8 100644 --- a/filter.h +++ b/filter.h @@ -204,6 +204,7 @@ void filter_init(void); int check_filter_arg(char *filter_arg, void **conf); void filter_post_select(__a_unused struct sched *s, struct task *t); void print_filter_helps(int detailed); +int prepare_filter_node(struct btr_node *btrn, size_t min_len); static inline void write_int16_host_endian(char *buf, int val) { diff --git a/filter_common.c b/filter_common.c index 94e553b6..bc5539d0 100644 --- a/filter_common.c +++ b/filter_common.c @@ -275,3 +275,23 @@ void print_filter_helps(int detailed) } } + +/** 640K ought to be enough for everybody ;) */ +#define FILTER_MAX_PENDING (640 * 1024) + +int prepare_filter_node(struct btr_node *btrn, size_t min_len) +{ + size_t iqs; + + if (btr_eof(btrn)) + return -E_FC_EOF; + if (btr_bytes_pending(btrn) > FILTER_MAX_PENDING) + return 0; + iqs = btr_get_input_queue_size(btrn); + if (iqs < min_len && !btr_no_parent(btrn)) + return 0; + assert(iqs != 0); + /* avoid "buffer too small" errors from the decoder */ + btr_merge_to(btrn, min_len); + return 1; +} diff --git a/mp3dec_filter.c b/mp3dec_filter.c index 9eed6393..dfec0c4c 100644 --- a/mp3dec_filter.c +++ b/mp3dec_filter.c @@ -207,23 +207,21 @@ static void mp3dec_post_select(__a_unused struct sched *s, struct task *t) int i, ret; struct private_mp3dec_data *pmd = fn->private_data; struct btr_node *btrn = fn->btrn; - size_t loaded, used, len = btr_get_input_queue_size(btrn); + size_t loaded, used, len, iqs; char *inbuffer, *outbuffer; +next_buffer: pmd->stream.error = 0; t->error = 0; - if (btr_bytes_pending(btrn) > MP3DEC_MAX_PENDING) - return; - if (need_bad_data_delay(pmd, len)) + iqs = btr_get_input_queue_size(btrn); + if (need_bad_data_delay(pmd, iqs)) return; - if (len <= pmd->input_len_barrier && btr_no_parent(btrn)) { - ret = -E_MP3DEC_EOF; + ret = prepare_filter_node(btrn, pmd->input_len_barrier); + if (ret < 0) goto err; - } -next_buffer: - len = btr_next_buffer(btrn, &inbuffer); - if (len == 0) + if (ret == 0) return; + len = btr_next_buffer(btrn, &inbuffer); mad_stream_buffer(&pmd->stream, (unsigned char *)inbuffer, len); next_frame: ret = mad_header_decode(&pmd->frame.header, &pmd->stream); @@ -231,10 +229,12 @@ next_frame: used = used_mad_buffer_bytes(&pmd->stream, len); btr_consume(btrn, used); if (pmd->stream.error == MAD_ERROR_BUFLEN) { - pmd->input_len_barrier = len - used; - ret = btr_merge(btrn); - if (ret != 2) - return; + if (len == iqs && btr_no_parent(btrn)) { + ret = -E_MP3DEC_EOF; + goto err; + } + pmd->input_len_barrier += 100; + goto next_buffer; } else if (pmd->stream.error != MAD_ERROR_LOSTSYNC) PARA_DEBUG_LOG("header decode: %s\n", mad_stream_errorstr(&pmd->stream)); diff --git a/oggdec_filter.c b/oggdec_filter.c index fc03077b..f968bf14 100644 --- a/oggdec_filter.c +++ b/oggdec_filter.c @@ -43,6 +43,7 @@ struct private_oggdec_data { unsigned int channels; /** Current sample rate in Hz. */ unsigned int samplerate; + size_t min_iqs; }; static size_t cb_read_nobtr(void *buf, size_t size, size_t nmemb, void *datasource) @@ -202,12 +203,19 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t) struct filter_node *fn = container_of(t, struct filter_node, task); struct private_oggdec_data *pod = fn->private_data; struct btr_node *btrn = fn->btrn; - size_t iqs = btr_get_input_queue_size(btrn); + size_t iqs, len; int ret; + char *in; t->error = 0; - if (!pod->vf && iqs) { - struct oggdec_filter_args_info *conf = fn->conf; + ret = prepare_filter_node(btrn, pod->min_iqs); + if (ret < 0) + goto err; + if (ret == 0) + return; + len = btr_next_buffer(btrn, &in); + iqs = btr_get_input_queue_size(btrn); + if (!pod->vf) { int oret; pod->vf = para_malloc(sizeof(struct OggVorbis_File)); @@ -218,10 +226,10 @@ static void ogg_post_select(__a_unused struct sched *s, struct task *t) ovc); /* the ov_open_callbacks */ if (oret == OV_ENOTVORBIS || oret == OV_EBADHEADER) { /* this might be due to the input buffer being too small */ - int ib = 1024 * conf->initial_buffer_arg; /* initial buffer */ - if (iqs < ib) { + if (!btr_no_parent(btrn)) { free(pod->vf); pod->vf = NULL; + pod->min_iqs = iqs + 1; return; } ret = (oret == OV_ENOTVORBIS)? diff --git a/wmadec_filter.c b/wmadec_filter.c index 4bbc2413..7681a762 100644 --- a/wmadec_filter.c +++ b/wmadec_filter.c @@ -1249,25 +1249,21 @@ static void wmadec_post_select(__a_unused struct sched *s, struct task *t) int ret, converted = 0; struct private_wmadec_data *pwd = fn->private_data; struct btr_node *btrn = fn->btrn; - size_t iqs, len, min_len; + size_t len, min_len; char *in; min_len = pwd? WMA_FRAME_SKIP + pwd->ahi.block_align : 8192; next_buffer: t->error = 0; - if (btr_bytes_pending(btrn) > WMADEC_MAX_PENDING) + ret = prepare_filter_node(btrn, min_len); + if (ret < 0) + goto err; + if (ret == 0) return; - iqs = btr_get_input_queue_size(btrn); - if (iqs < min_len) { - if (!btr_no_parent(btrn)) /* wait for more data */ - return; - ret = -E_WMADEC_EOF; + len = btr_next_buffer(btrn, (char **)&in); + ret = -E_WMADEC_EOF; + if (len < min_len) goto err; - } - /* avoid "buffer too small" errors from the decoder */ - btr_merge_to(btrn, min_len); - len = btr_next_buffer(btrn, &in); - assert(len >= min_len); if (!pwd) { ret = wma_decode_init(in, len, &pwd); if (ret < 0) -- 2.39.2