summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xine_post_audiochannel.c284
1 files changed, 284 insertions, 0 deletions
diff --git a/xine_post_audiochannel.c b/xine_post_audiochannel.c
new file mode 100644
index 00000000..ef0afb5a
--- /dev/null
+++ b/xine_post_audiochannel.c
@@ -0,0 +1,284 @@
+/*
+ * Copyright (C) 2006 the xine project
+ *
+ * This file is part of xine, a free video player.
+ *
+ * xine is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * xine is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
+ *
+ * $Id:
+ *
+ * audio channel selection post plugin by Petri Hintukainen 01/09/2006
+ * based on upmix.c
+ *
+ * Removes left or right channel from stereo audio track
+ * and fills both channels with same data.
+ * This is useful with some bi-lingual DVB transmissions where
+ * two different languages are sent on same (stereo) audio track.
+ *
+ */
+
+#include <xine/xine_internal.h>
+#include <xine/post.h>
+
+
+typedef struct audioch_parameters_s {
+ int channel;
+} audioch_parameters_t;
+
+START_PARAM_DESCR(audioch_parameters_t)
+PARAM_ITEM(POST_PARAM_TYPE_BOOL, channel, NULL, 0, 1, 0,
+ "select channel (0=left, 1=right)")
+END_PARAM_DESCR(audioch_param_descr)
+
+
+typedef struct audioch_post_plugin_s
+{
+ post_plugin_t post_plugin;
+ xine_post_in_t parameter_input;
+
+ /* Config */
+ int channel; /* 0 - left, 1 - right */
+
+ /* Data */
+ int channels;
+
+} audioch_post_plugin_t;
+
+
+/*
+ * Port functions
+ */
+
+static int audioch_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
+ uint32_t bits, uint32_t rate, int mode)
+{
+ post_audio_port_t *port = (post_audio_port_t *)port_gen;
+ audioch_post_plugin_t *this = (audioch_post_plugin_t *)port->post;
+ uint32_t capabilities;
+
+ _x_post_rewire(&this->post_plugin);
+ _x_post_inc_usage(port);
+
+ port->stream = stream;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+ capabilities = port->original_port->get_capabilities(port->original_port);
+
+ this->channels = _x_ao_mode2channels(mode);
+
+ return port->original_port->open(port->original_port, stream, bits, rate, mode );
+}
+
+static void audioch_port_put_buffer (xine_audio_port_t *port_gen,
+ audio_buffer_t *buf, xine_stream_t *stream)
+{
+ post_audio_port_t *port = (post_audio_port_t *)port_gen;
+ audioch_post_plugin_t *this = (audioch_post_plugin_t *)port->post;
+ int i;
+
+ if(this->channels == 2) {
+ audio_buffer_t *newbuf = port->original_port->get_buffer(port->original_port);
+ newbuf->num_frames = buf->num_frames;
+ newbuf->vpts = buf->vpts;
+ newbuf->frame_header_count = buf->frame_header_count;
+ newbuf->first_access_unit = buf->first_access_unit;
+ newbuf->format.bits = buf->format.bits;
+ newbuf->format.rate = buf->format.rate;
+ newbuf->format.mode = buf->format.mode;
+ _x_extra_info_merge( newbuf->extra_info, buf->extra_info);
+
+ switch(buf->format.bits) {
+ case 8:
+ for(i=0; i<buf->num_frames; i++)
+ newbuf->mem[i*2+1] = newbuf->mem[i*2] = buf->mem[i*2+this->channel];
+ break;
+ case 16:
+ for(i=0; i<buf->num_frames; i++)
+ ((uint16_t*)newbuf->mem)[i*2+1] =
+ ((uint16_t*)newbuf->mem)[i*2] = ((uint16_t*)buf->mem)[i*2+this->channel];
+ break;
+ case 24:
+ for(i=0; i<buf->num_frames*3; i+=3) {
+ newbuf->mem[i*2+0] = newbuf->mem[i*2+3] = buf->mem[i*2+0+3*this->channel];
+ newbuf->mem[i*2+1] = newbuf->mem[i*2+4] = buf->mem[i*2+1+3*this->channel];
+ newbuf->mem[i*2+2] = newbuf->mem[i*2+5] = buf->mem[i*2+2+3*this->channel];
+ }
+ break;
+ case 32:
+ for(i=0; i<buf->num_frames; i++)
+ ((uint32_t*)newbuf->mem)[i*2+1] =
+ ((uint32_t*)newbuf->mem)[i*2] = ((uint32_t*)buf->mem)[i*2+this->channel];
+ break;
+ default: /* ??? */
+ memcpy(newbuf->mem, buf->mem, buf->num_frames*2*buf->format.bits);
+ break;
+ }
+
+ /* pass data to original port */
+ port->original_port->put_buffer(port->original_port, newbuf, stream );
+
+ /* free data from origial buffer */
+ buf->num_frames=0; /* UNDOCUMENTED, but hey, it works! Force old audio_out buffer free. */
+ }
+
+ port->original_port->put_buffer(port->original_port, buf, stream );
+}
+
+/*
+ * Parameter functions
+ */
+
+static xine_post_api_descr_t *audioch_get_param_descr(void)
+{
+ return &audioch_param_descr;
+}
+
+static int audioch_set_parameters(xine_post_t *this_gen, void *param_gen)
+{
+ audioch_post_plugin_t *this = (audioch_post_plugin_t *)this_gen;
+ audioch_parameters_t *param = (audioch_parameters_t *)param_gen;
+
+ this->channel = param->channel;
+ return 1;
+}
+
+static int audioch_get_parameters(xine_post_t *this_gen, void *param_gen)
+{
+ audioch_post_plugin_t *this = (audioch_post_plugin_t *)this_gen;
+ audioch_parameters_t *param = (audioch_parameters_t *)param_gen;
+
+ param->channel = this->channel;
+ return 1;
+}
+
+static char *audioch_get_help(void) {
+ return _("The audiochannel plugin is meant to take stereo audio and \n"
+ "remove left or right channel by replacing both channels \n"
+ "with the same data. \n"
+ "\n"
+ "Parameters \n"
+ " channel: Select channel (left=0, right=1) \n"
+ "\n"
+ );
+}
+
+
+/*
+ * Open / Close
+ */
+
+static void audioch_dispose(post_plugin_t *this_gen)
+{
+ if (_x_post_dispose(this_gen))
+ free(this_gen);
+}
+
+static post_plugin_t *audioch_open_plugin(post_class_t *class_gen,
+ int inputs,
+ xine_audio_port_t **audio_target,
+ xine_video_port_t **video_target)
+{
+ audioch_post_plugin_t *this = (audioch_post_plugin_t*)xine_xmalloc(sizeof(audioch_post_plugin_t));
+ post_in_t *input;
+ post_out_t *output;
+ post_audio_port_t *port;
+ xine_post_in_t *input_param;
+
+ static xine_post_api_t post_api =
+ { audioch_set_parameters, audioch_get_parameters,
+ audioch_get_param_descr, audioch_get_help };
+
+ if (!this || !audio_target || !audio_target[0] ) {
+ free(this);
+ return NULL;
+ }
+
+ _x_post_init(&this->post_plugin, 1, 0);
+
+ port = _x_post_intercept_audio_port(&this->post_plugin,
+ audio_target[ 0 ],
+ &input, &output);
+
+ port->new_port.open = audioch_port_open;
+ port->new_port.put_buffer = audioch_port_put_buffer;
+
+ input->xine_in.name = "audio in";
+ output->xine_out.name = "audio out";
+
+ this->post_plugin.xine_post.audio_input[ 0 ] = &port->new_port;
+ this->post_plugin.dispose = audioch_dispose;
+
+ input_param = &this->parameter_input;
+ input_param->name = "parameters";
+ input_param->type = XINE_POST_DATA_PARAMETERS;
+ input_param->data = &post_api;
+#if XINE_VERSION_CODE >= 10102
+ xine_list_push_back(this->post_plugin.input, input_param);
+#else
+ xine_list_append_content(this->post_plugin.input, input_param);
+#endif
+
+ this->channel = 0;
+
+ this->channels = 0;
+
+ return &this->post_plugin;
+}
+
+/*
+ * Plugin class
+ */
+
+static char *audioch_get_identifier(post_class_t *class_gen)
+{
+ return "audiochannel";
+}
+
+static char *audioch_get_description(post_class_t *class_gen)
+{
+ return "Select audio channel";
+}
+
+static void audioch_class_dispose(post_class_t *class_gen)
+{
+ free(class_gen);
+}
+
+static void *audioch_init_plugin(xine_t *xine, void *data)
+{
+ post_class_t *class = (post_class_t*)malloc(sizeof(post_class_t));
+
+ if(!class)
+ return NULL;
+
+ class->open_plugin = audioch_open_plugin;
+ class->get_identifier = audioch_get_identifier;
+ class->get_description = audioch_get_description;
+ class->dispose = audioch_class_dispose;
+
+ return class;
+}
+
+static post_info_t audioch_info = { XINE_POST_TYPE_AUDIO_FILTER };
+
+#ifndef NO_INFO_EXPORT
+plugin_info_t xine_plugin_info[] __attribute__((visibility("default"))) =
+{
+ /* type, API, "name", version, special_info, init_function */
+ { PLUGIN_POST, 9, "audiochannel", XINE_VERSION_CODE, &audioch_info, &audioch_init_plugin },
+ { PLUGIN_NONE, 0, "", 0, NULL, NULL }
+};
+#endif