+
+ if (request_vout != NULL)
+ {
+ char *visual = var_InheritString (obj, "audio-visual");
+ if (visual != NULL && strcasecmp (visual, "none"))
+ AppendFilter(obj, "visualization", visual, filters,
+ request_vout, &input_format, &output_format);
+ free (visual);
+ }
+
+ /* convert to the output format (minus resampling) if necessary */
+ output_format.i_rate = input_format.i_rate;
+ if (aout_FiltersPipelineCreate (obj, filters->tab, &filters->count,
+ AOUT_MAX_FILTERS, &input_format, &output_format))
+ {
+ msg_Err (obj, "cannot setup filtering pipeline");
+ goto error;
+ }
+ input_format = output_format;
+
+ /* insert the resampler */
+ output_format.i_rate = outfmt->i_rate;
+ assert (AOUT_FMTS_IDENTICAL(&output_format, outfmt));
+ filters->resampler = FindResampler (obj, &input_format,
+ &output_format);
+ if (filters->resampler == NULL && input_format.i_rate != outfmt->i_rate)
+ {
+ msg_Err (obj, "cannot setup a resampler");
+ goto error;
+ }
+ if (filters->rate_filter == NULL)
+ filters->rate_filter = filters->resampler;
+
+ return filters;
+
+error:
+ aout_FiltersPipelineDestroy (filters->tab, filters->count);
+ if (request_vout != NULL)
+ var_DelCallback (obj, "visual", VisualizationCallback, NULL);
+ free (filters);
+ return NULL;
+}
+
+#undef aout_FiltersDelete
+/**
+ * Destroys a chain of audio filters.
+ * \param obj object used with aout_FiltersNew()
+ * \param filters chain to be destroyed
+ * \bug
+ * obj must be NULL iff request_vout was NULL in aout_FiltersNew()
+ * (this implies obj is an audio_output_t pointer if non NULL).
+ */
+void aout_FiltersDelete (vlc_object_t *obj, aout_filters_t *filters)
+{
+ if (filters->resampler != NULL)
+ aout_FiltersPipelineDestroy (&filters->resampler, 1);
+ aout_FiltersPipelineDestroy (filters->tab, filters->count);
+ if (obj != NULL)
+ var_DelCallback (obj, "visual", VisualizationCallback, NULL);
+ free (filters);
+}
+
+bool aout_FiltersAdjustResampling (aout_filters_t *filters, int adjust)
+{
+ if (filters->resampler == NULL)
+ return false;
+
+ if (adjust)
+ filters->resampling += adjust;
+ else
+ filters->resampling = 0;
+ return filters->resampling != 0;
+}
+
+block_t *aout_FiltersPlay (aout_filters_t *filters, block_t *block, int rate)
+{
+ int nominal_rate = 0;
+
+ if (rate != INPUT_RATE_DEFAULT)
+ {
+ filter_t *rate_filter = filters->rate_filter;
+
+ if (rate_filter == NULL)
+ goto drop; /* Without linear, non-nominal rate is impossible. */
+
+ /* Override input rate */
+ nominal_rate = rate_filter->fmt_in.audio.i_rate;
+ rate_filter->fmt_in.audio.i_rate =
+ (nominal_rate * INPUT_RATE_DEFAULT) / rate;
+ }
+
+ block = aout_FiltersPipelinePlay (filters->tab, filters->count, block);
+ if (filters->resampler != NULL)
+ { /* NOTE: the resampler needs to run even if resampling is 0.
+ * The decoder and output rates can still be different. */
+ filters->resampler->fmt_in.audio.i_rate += filters->resampling;
+ block = aout_FiltersPipelinePlay (&filters->resampler, 1, block);
+ filters->resampler->fmt_in.audio.i_rate -= filters->resampling;
+ }
+
+ if (nominal_rate != 0)
+ { /* Restore input rate */
+ assert (filters->rate_filter != NULL);
+ filters->rate_filter->fmt_in.audio.i_rate = nominal_rate;
+ }
+ return block;
+
+drop:
+ block_Release (block);
+ return NULL;