summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Roitzsch <mroi@users.sourceforge.net>2004-01-07 19:52:42 +0000
committerMichael Roitzsch <mroi@users.sourceforge.net>2004-01-07 19:52:42 +0000
commit5e25dd8a73f15e8116da5ce8fda14f8f671473ce (patch)
treed47d0a7c256fe25905f4fcd66302dbee68c5faa9
parent6f75f546fd6e928245911e8ebcea680a7c9046b6 (diff)
downloadxine-lib-5e25dd8a73f15e8116da5ce8fda14f8f671473ce.tar.gz
xine-lib-5e25dd8a73f15e8116da5ce8fda14f8f671473ce.tar.bz2
the new, refined post plugin architecture
* post plugins are now much safer (fewer races/inconsistencies) and easier to write * all post plugins are ported to the new architecture (and should work) * ports can now be opened and closed with a NULL stream CVS patchset: 6007 CVS date: 2004/01/07 19:52:42
-rw-r--r--ChangeLog1
-rw-r--r--src/post/deinterlace/xine_plugin.c242
-rw-r--r--src/post/goom/xine_goom.c181
-rw-r--r--src/post/mosaico/mosaico.c742
-rw-r--r--src/post/mosaico/switch.c445
-rw-r--r--src/post/planar/boxblur.c181
-rw-r--r--src/post/planar/denoise3d.c188
-rw-r--r--src/post/planar/eq.c174
-rw-r--r--src/post/planar/eq2.c177
-rw-r--r--src/post/planar/expand.c333
-rw-r--r--src/post/planar/invert.c156
-rw-r--r--src/post/planar/planar.c18
-rwxr-xr-xsrc/post/planar/pp.c188
-rw-r--r--src/post/planar/unsharp.c171
-rw-r--r--src/post/visualizations/fftgraph.c171
-rw-r--r--src/post/visualizations/fftscope.c183
-rw-r--r--src/post/visualizations/fooviz.c162
-rw-r--r--src/post/visualizations/oscope.c165
-rw-r--r--src/post/visualizations/visualizations.c8
-rw-r--r--src/xine-engine/audio_out.c77
-rw-r--r--src/xine-engine/audio_out.h6
-rw-r--r--src/xine-engine/post.c865
-rw-r--r--src/xine-engine/post.h252
-rw-r--r--src/xine-engine/video_out.c66
-rw-r--r--src/xine-engine/video_out.h8
25 files changed, 2153 insertions, 3007 deletions
diff --git a/ChangeLog b/ChangeLog
index 4427e709b..e11e1cdff 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,7 @@ xine-lib (1-rc4)
* fixed problem with jumpy visualization especially on ogg files
* dxr3: fix situation, where the initial menu on some DVDs would have
the wrong aspect
+ * major refinement of post plugin architecture fixes a lot of races
xine-lib (1-rc3a)
* new subtitle formats: jacobsub, subviewer 2.0, subrip 0.9
diff --git a/src/post/deinterlace/xine_plugin.c b/src/post/deinterlace/xine_plugin.c
index 2843a2073..565c0cc29 100644
--- a/src/post/deinterlace/xine_plugin.c
+++ b/src/post/deinterlace/xine_plugin.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_plugin.c,v 1.27 2003/12/24 13:36:13 miguelfreitas Exp $
+ * $Id: xine_plugin.c,v 1.28 2004/01/07 19:52:42 mroi Exp $
*
* advanced video deinterlacer plugin
* Jun/2003 by Miguel Freitas
@@ -44,7 +44,7 @@ post_info_t deinterlace_special_info = { XINE_POST_TYPE_VIDEO_FILTER };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 7, "tvtime", XINE_VERSION_CODE, &deinterlace_special_info, &deinterlace_init_plugin },
+ { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 8, "tvtime", XINE_VERSION_CODE, &deinterlace_special_info, &deinterlace_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
@@ -101,12 +101,10 @@ END_PARAM_DESCR( param_descr )
/* plugin structure */
struct post_plugin_deinterlace_s {
- post_plugin_t post;
+ post_plugin_t post;
+ xine_post_in_t parameter_input;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
int cur_method;
int enabled;
int pulldown;
@@ -256,12 +254,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_deinterlace_out_s post_deinterlace_out_t;
-struct post_deinterlace_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_deinterlace_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int inputs,
@@ -274,27 +266,23 @@ static void deinterlace_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void deinterlace_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int deinterlace_rewire(xine_post_out_t *output, void *data);
-
/* replaced video_port functions */
static int deinterlace_get_property(xine_video_port_t *port_gen, int property);
static int deinterlace_set_property(xine_video_port_t *port_gen, int property, int value);
static void deinterlace_flush(xine_video_port_t *port_gen);
static void deinterlace_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *deinterlace_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
static void deinterlace_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* frame intercept check */
+static int deinterlace_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
+
/* replaced vo_frame functions */
static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream);
static void *deinterlace_init_plugin(xine_t *xine, void *data)
{
- post_class_deinterlace_t *class = (post_class_deinterlace_t *)malloc(sizeof(post_class_deinterlace_t));
- config_values_t *cfg;
+ post_class_deinterlace_t *class = (post_class_deinterlace_t *)xine_xmalloc(sizeof(post_class_deinterlace_t));
uint32_t config_flags = xine_mm_accel();
int i;
@@ -341,44 +329,6 @@ static void *deinterlace_init_plugin(xine_t *xine, void *data)
enum_methods[i+1] = NULL;
- cfg = xine->config;
-
- /*
- * We don't need to register config options, post plugins have
- * their own method for configuration purpose
- */
- /*
- class->init_param.method =
- cfg->register_enum (cfg, "post.tvtime_method", 1, enum_methods,
- param_descr.parameter[0].description,
- NULL, 10, NULL, NULL);
- class->init_param.enabled = 1;
- class->init_param.pulldown =
- cfg->register_enum (cfg, "post.tvtime_pulldown", 1, enum_pulldown,
- param_descr.parameter[2].description,
- NULL, 10, NULL, NULL);
- class->init_param.framerate_mode =
- cfg->register_enum (cfg, "post.tvtime_framerate_mode", 0, enum_framerate,
- param_descr.parameter[3].description,
- NULL, 10, NULL, NULL);
- class->init_param.judder_correction =
- cfg->register_bool (cfg, "post.tvtime_judder_correction", 1,
- param_descr.parameter[4].description,
- NULL, 10, NULL, NULL);
- class->init_param.use_progressive_frame_flag =
- cfg->register_bool (cfg, "post.tvtime_use_progressive_frame_flag", 1,
- param_descr.parameter[5].description,
- NULL, 10, NULL, NULL);
- class->init_param.chroma_filter =
- cfg->register_bool (cfg, "post.tvtime_chroma_filter", 0,
- param_descr.parameter[6].description,
- NULL, 10, NULL, NULL);
- class->init_param.cheap_mode =
- cfg->register_bool (cfg, "post.tvtime_cheap_mode", 0,
- param_descr.parameter[7].description,
- NULL, 10, NULL, NULL);
- */
-
/* Some default values */
class->init_param.method = 1; /* First (plugin) method available */
class->init_param.enabled = 1;
@@ -398,22 +348,18 @@ static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int input
xine_video_port_t **video_target)
{
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)xine_xmalloc(sizeof(post_plugin_deinterlace_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_deinterlace_out_t *output = (post_deinterlace_out_t *)malloc(sizeof(post_deinterlace_out_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
post_class_deinterlace_t *class = (post_class_deinterlace_t *)class_gen;
post_video_port_t *port;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
-
- this->stream = NULL;
- memset( &this->recent_frame, 0, sizeof(this->recent_frame) );
+
+ _x_post_init(&this->post, 0, 1);
this->tvtime = tvtime_new_context();
this->tvtime_changed++;
@@ -422,41 +368,26 @@ static post_plugin_t *deinterlace_open_plugin(post_class_t *class_gen, int input
set_parameters ((xine_post_t *)&this->post, &class->init_param);
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
/* replace with our own get_frame function */
- port->port.open = deinterlace_open;
- port->port.get_frame = deinterlace_get_frame;
- port->port.close = deinterlace_close;
- port->port.get_property = deinterlace_get_property;
- port->port.set_property = deinterlace_set_property;
- port->port.flush = deinterlace_flush;
+ port->new_port.open = deinterlace_open;
+ port->new_port.close = deinterlace_close;
+ port->new_port.get_property = deinterlace_get_property;
+ port->new_port.set_property = deinterlace_set_property;
+ port->new_port.flush = deinterlace_flush;
+ port->intercept_frame = deinterlace_intercept_frame;
+ port->new_frame->draw = deinterlace_draw;
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
-
+ input_api = &this->parameter_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "deinterlaced video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = deinterlace_rewire;
- output->plugin = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = deinterlace_dispose;
@@ -482,45 +413,14 @@ static void deinterlace_class_dispose(post_class_t *class_gen)
static void deinterlace_dispose(post_plugin_t *this_gen)
{
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)this_gen;
- post_deinterlace_out_t *output = (post_deinterlace_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- _flush_frames(this);
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int deinterlace_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_deinterlace_out_t *output = (post_deinterlace_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
-
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ _flush_frames(this);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
}
+
static int deinterlace_get_property(xine_video_port_t *port_gen, int property) {
post_video_port_t *port = (post_video_port_t *)port_gen;
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post;
@@ -565,59 +465,37 @@ static void deinterlace_open(xine_video_port_t *port_gen, xine_stream_t *stream)
{
post_video_port_t *port = (post_video_port_t *)port_gen;
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post;
- this->stream = stream;
+
+ _x_post_rewire_video(port);
+ _x_post_inc_usage(port);
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
port->original_port->open(port->original_port, stream);
port->original_port->set_property(port->original_port,
XINE_PARAM_VO_DEINTERLACE,
!this->cur_method);
}
-static vo_frame_t *deinterlace_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static void deinterlace_close(xine_video_port_t *port_gen, xine_stream_t *stream)
{
post_video_port_t *port = (post_video_port_t *)port_gen;
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- pthread_mutex_lock (&this->lock);
-
- _x_post_intercept_video_frame(frame, port);
- /* do not intercept if not enabled or not interlaced */
- if( this->enabled && this->cur_method &&
- (flags & VO_INTERLACED_FLAG) &&
- (format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2) ) {
- /* replace with our own draw function */
- frame->draw = deinterlace_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
- pthread_mutex_unlock (&this->lock);
-
- return frame;
+ port->stream = NULL;
+ _flush_frames(this);
+ port->original_port->close(port->original_port, stream);
+ _x_post_dec_usage(port);
}
-static void deinterlace_close(xine_video_port_t *port_gen, xine_stream_t *stream)
+
+static int deinterlace_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post;
- int i;
-
- this->stream = NULL;
-
- for( i = 0; i < NUM_RECENT_FRAMES; i++ ) {
- if( this->recent_frame[i] ) {
- this->recent_frame[i]->free(this->recent_frame[i]);
- this->recent_frame[i] = NULL;
- }
- }
-
- port->original_port->close(port->original_port, stream);
+ return (this->enabled && this->cur_method &&
+ (frame->flags & VO_INTERLACED_FLAG) &&
+ (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2) );
}
@@ -641,12 +519,15 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
{
post_video_port_t *port = (post_video_port_t *)frame->port;
post_plugin_deinterlace_t *this = (post_plugin_deinterlace_t *)port->post;
+ vo_frame_t *orig_frame;
vo_frame_t *deinterlaced_frame;
vo_frame_t *yuy2_frame;
int i, skip, progressive = 0;
- _x_post_restore_video_frame(frame, port);
-
+ orig_frame = frame;
+ _x_post_frame_copy_up(frame, frame->next);
+ frame = frame->next;
+
/* update tvtime context and method */
pthread_mutex_lock (&this->lock);
if( this->tvtime_changed ) {
@@ -686,10 +567,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
yuy2_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YUY2, frame->flags | VO_BOTH_FIELDS);
-
- yuy2_frame->pts = frame->pts;
- yuy2_frame->duration = frame->duration;
- _x_extra_info_merge(yuy2_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, yuy2_frame);
/* the logic for deciding upsampling to use comes from:
* http://www.hometheaterhifi.com/volume_8_2/dvd-benchmark-special-report-chroma-bug-4-2001.html
@@ -732,7 +610,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
pthread_mutex_unlock (&this->lock);
skip = yuy2_frame->draw(yuy2_frame, stream);
pthread_mutex_lock (&this->lock);
- frame->vpts = yuy2_frame->vpts;
+ _x_post_frame_copy_down(frame, yuy2_frame);
} else {
int force24fps;
@@ -880,7 +758,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = deinterlaced_frame->draw(deinterlaced_frame, stream);
}
- frame->vpts = deinterlaced_frame->vpts;
+ _x_post_frame_copy_down(frame, deinterlaced_frame);
deinterlaced_frame->free(deinterlaced_frame);
pthread_mutex_lock (&this->lock);
@@ -987,7 +865,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = deinterlaced_frame->draw(deinterlaced_frame, stream);
}
- frame->vpts = deinterlaced_frame->vpts;
+ _x_post_frame_copy_down(frame, deinterlaced_frame);
deinterlaced_frame->free(deinterlaced_frame);
pthread_mutex_lock (&this->lock);
}
@@ -1005,7 +883,12 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
this->recent_frame[i]->free(this->recent_frame[i]);
for( ; i ; i-- )
this->recent_frame[i] = this->recent_frame[i-1];
- this->recent_frame[0] = yuy2_frame;
+ if (port->stream)
+ this->recent_frame[0] = yuy2_frame;
+ else
+ /* do not keep this frame when no stream is connected to us,
+ * otherwise, this frame might never get freed */
+ yuy2_frame->free(yuy2_frame);
pthread_mutex_unlock (&this->lock);
@@ -1013,6 +896,7 @@ static int deinterlace_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = frame->draw(frame, stream);
}
+ _x_post_frame_copy_down(orig_frame, frame);
return skip;
}
diff --git a/src/post/goom/xine_goom.c b/src/post/goom/xine_goom.c
index 71851fb9f..e7d0f1eea 100644
--- a/src/post/goom/xine_goom.c
+++ b/src/post/goom/xine_goom.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xine_goom.c,v 1.47 2003/12/14 22:13:25 siggi Exp $
+ * $Id: xine_goom.c,v 1.48 2004/01/07 19:52:42 mroi Exp $
*
* GOOM post plugin.
*
@@ -71,7 +71,7 @@ struct post_plugin_goom_s {
/* private data */
xine_video_port_t *vo_port;
- xine_stream_t *stream;
+ post_out_t video_output;
post_class_goom_t *class;
@@ -82,8 +82,6 @@ struct post_plugin_goom_s {
gint16 data [2][512];
audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */
- int bits;
- int mode;
int channels;
int sample_rate;
int sample_counter;
@@ -92,25 +90,14 @@ struct post_plugin_goom_s {
int width_back, height_back;
double ratio;
int fps;
- int use_asm;
int csc_method;
yuv_planes_t yuv;
/* frame skipping */
int skip_frame;
- int title_flag;
- char *msg;
- int msg_index;
- int msg_flag;
- char msg_buf[1024];
};
-typedef struct post_goom_out_s post_goom_out_t;
-struct post_goom_out_s {
- xine_post_out_t out;
- post_plugin_goom_t *post;
-};
/* plugin class initialization function */
static void *goom_init_plugin(xine_t *xine, void *);
@@ -123,7 +110,7 @@ post_info_t goom_special_info = {
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 7, "goom", XINE_VERSION_CODE, &goom_special_info, &goom_init_plugin },
+ { PLUGIN_POST | PLUGIN_MUST_PRELOAD, 8, "goom", XINE_VERSION_CODE, &goom_special_info, &goom_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
@@ -140,7 +127,6 @@ static void goom_class_dispose(post_class_t *class_gen);
static void goom_dispose(post_plugin_t *this_gen);
/* rewire function */
-static int goom_rewire_audio(xine_post_out_t *output, void *data);
static int goom_rewire_video(xine_post_out_t *output, void *data);
static int goom_port_open(xine_audio_port_t *this, xine_stream_t *stream,
@@ -232,33 +218,27 @@ static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_goom_t *this = (post_plugin_goom_t *)xine_xmalloc(sizeof(post_plugin_goom_t));
- post_class_goom_t *class = (post_class_goom_t*) class_gen;
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_goom_out_t *output = (post_goom_out_t *)malloc(sizeof(post_goom_out_t));
- post_goom_out_t *outputv = (post_goom_out_t *)malloc(sizeof(post_goom_out_t));
+ post_plugin_goom_t *this = (post_plugin_goom_t *)xine_xmalloc(sizeof(post_plugin_goom_t));
+ post_class_goom_t *class = (post_class_goom_t*) class_gen;
+ post_in_t *input;
+ post_out_t *output;
+ post_out_t *outputv;
post_audio_port_t *port;
xine_cfg_entry_t fps_entry, width_entry, height_entry, csc_method_entry;
- if (!this || !input || !output || !outputv || !video_target || !video_target[0] ||
- !audio_target || !audio_target[0] ) {
+ if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0]) {
free(this);
- free(input);
- free(output);
- free(outputv);
return NULL;
}
- memset(this, 0, sizeof(post_plugin_goom_t));
- memset(input, 0, sizeof(xine_post_in_t));
- memset(output, 0, sizeof(post_goom_out_t));
- memset(outputv, 0, sizeof(post_goom_out_t));
-
+ _x_post_init(&this->post, 1, 0);
+
/*
* Lookup config entries.
*/
this->class = class;
class->ip = this;
+ this->vo_port = video_target[0];
this->metronom = _x_metronom_init(1, 0, class->xine);
@@ -283,54 +263,28 @@ static post_plugin_t *goom_open_plugin(post_class_t *class_gen, int inputs,
this->width_back = this->width;
this->height_back = this->height;
- this->title_flag = 0;
- this->msg_flag = 0;
- this->msg_index = 0;
- this->msg = NULL;
-
goom_init (this->width_back, this->height_back, 0);
this->ratio = (double)this->width_back/(double)this->height_back;
this->sample_counter = 0;
- this->stream = NULL;
- this->vo_port = video_target[0];
this->buf.mem = NULL;
this->buf.mem_size = 0;
- port = _x_post_intercept_audio_port(&this->post, audio_target[0]);
- port->port.open = goom_port_open;
- port->port.close = goom_port_close;
- port->port.put_buffer = goom_port_put_buffer;
-
- input->name = "audio in";
- input->type = XINE_POST_DATA_AUDIO;
- input->data = (xine_audio_port_t *)&port->port;
-
- output->out.name = "audio out";
- output->out.type = XINE_POST_DATA_AUDIO;
- output->out.data = (xine_audio_port_t **)&port->original_port;
- output->out.rewire = goom_rewire_audio;
- output->post = this;
-
- outputv->out.name = "generated video";
- outputv->out.type = XINE_POST_DATA_VIDEO;
- outputv->out.data = (xine_video_port_t **)&this->vo_port;
- outputv->out.rewire = goom_rewire_video;
- outputv->post = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *) * 2);
- this->post.xine_post.audio_input[0] = &port->port;
- this->post.xine_post.audio_input[1] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 1);
- this->post.xine_post.video_input[0] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.output, output);
+ port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output);
+ port->new_port.open = goom_port_open;
+ port->new_port.close = goom_port_close;
+ port->new_port.put_buffer = goom_port_put_buffer;
+
+ outputv = &this->video_output;
+ outputv->xine_out.name = "generated video";
+ outputv->xine_out.type = XINE_POST_DATA_VIDEO;
+ outputv->xine_out.data = (xine_video_port_t **)&this->vo_port;
+ outputv->xine_out.rewire = goom_rewire_video;
+ outputv->post = &this->post;
xine_list_append_content(this->post.output, outputv);
+
+ this->post.xine_post.audio_input[0] = &port->new_port;
this->post.dispose = goom_dispose;
@@ -356,65 +310,35 @@ static void goom_class_dispose(post_class_t *class_gen)
static void goom_dispose(post_plugin_t *this_gen)
{
post_plugin_goom_t *this = (post_plugin_goom_t *)this_gen;
- xine_post_out_t *output = (xine_post_out_t *)xine_list_last_content(this_gen->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->data;
-
- this->class->ip = NULL;
-
- goom_close();
- this->metronom->exit(this->metronom);
+ if (_x_post_dispose(this_gen)) {
+ this->class->ip = NULL;
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- if(this->buf.mem)
- free(this->buf.mem);
- free(this);
-}
+ goom_close();
+ this->metronom->exit(this->metronom);
-static int goom_rewire_audio(xine_post_out_t *output_gen, void *data)
-{
- post_goom_out_t *output = (post_goom_out_t *)output_gen;
- xine_audio_port_t *old_port = *(xine_audio_port_t **)output_gen->data;
- xine_audio_port_t *new_port = (xine_audio_port_t *)data;
- post_plugin_goom_t *this = (post_plugin_goom_t *)output->post;
-
- if (!data)
- return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream, this->bits, this->sample_rate, this->mode);
+ if(this->buf.mem)
+ free(this->buf.mem);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_audio_port_t **)output_gen->data = new_port;
- return 1;
}
+
static int goom_rewire_video(xine_post_out_t *output_gen, void *data)
{
- post_goom_out_t *output = (post_goom_out_t *)output_gen;
+ post_out_t *output = (post_out_t *)output_gen;
xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
xine_video_port_t *new_port = (xine_video_port_t *)data;
post_plugin_goom_t *this = (post_plugin_goom_t *)output->post;
if (!data)
return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream);
- }
+ /* register our stream at the new output port */
+ old_port->close(old_port, NULL);
+ new_port->open(new_port, NULL);
/* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
+ this->vo_port = new_port;
return 1;
}
@@ -424,16 +348,25 @@ static int goom_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_goom_t *this = (post_plugin_goom_t *)port->post;
- this->bits = bits;
- this->mode = mode;
+ _x_post_rewire_audio(port);
+ _x_post_inc_usage(port);
+
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+
this->channels = _x_ao_mode2channels(mode);
+ this->sample_rate = rate;
this->samples_per_frame = rate / this->fps;
- this->sample_rate = rate;
- this->stream = stream;
this->data_idx = 0;
init_yuv_planes(&this->yuv, this->width, this->height);
this->skip_frame = 0;
+ this->vo_port->open(this->vo_port, NULL);
this->metronom->set_master(this->metronom, stream->metronom);
return port->original_port->open(port->original_port, stream, bits, rate, mode );
@@ -446,11 +379,14 @@ static void goom_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream )
free_yuv_planes(&this->yuv);
- this->stream = NULL;
+ port->stream = NULL;
+ this->vo_port->close(this->vo_port, NULL);
this->metronom->set_master(this->metronom, NULL);
port->original_port->close(port->original_port, stream );
+
+ _x_post_dec_usage(port);
}
static void goom_port_put_buffer (xine_audio_port_t *port_gen,
@@ -459,7 +395,6 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen,
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_goom_t *this = (post_plugin_goom_t *)port->post;
vo_frame_t *frame;
- /* uint32_t *goom_frame; */
uint8_t *goom_frame, *goom_frame_end;
int16_t *data;
int8_t *data8;
@@ -475,11 +410,11 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen,
this->buf.mem_size = buf->mem_size;
}
memcpy(this->buf.mem, buf->mem,
- buf->num_frames*this->channels*((this->bits == 8)?1:2));
+ buf->num_frames*this->channels*((port->bits == 8)?1:2));
this->buf.num_frames = buf->num_frames;
/* pass data to original port */
- port->original_port->put_buffer(port->original_port, buf, stream );
+ port->original_port->put_buffer(port->original_port, buf, stream);
/* we must not use original data anymore, it should have already being moved
* to the fifo of free audio buffers. just use our private copy instead.
@@ -492,7 +427,7 @@ static void goom_port_put_buffer (xine_audio_port_t *port_gen,
do {
- if( this->bits == 8 ) {
+ if( port->bits == 8 ) {
data8 = (int8_t *)buf->mem;
data8 += samples_used * this->channels;
diff --git a/src/post/mosaico/mosaico.c b/src/post/mosaico/mosaico.c
index 8d5eafc61..ca7d043e9 100644
--- a/src/post/mosaico/mosaico.c
+++ b/src/post/mosaico/mosaico.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: mosaico.c,v 1.20 2003/12/14 22:13:25 siggi Exp $
+ * $Id: mosaico.c,v 1.21 2004/01/07 19:52:42 mroi Exp $
*/
/*
@@ -33,13 +33,7 @@
#include "xine_internal.h"
#include "post.h"
-#define MOVERSION (5)
-
-#define DEFAULT_X (50)
-#define DEFAULT_Y (50)
-#define DEFAULT_W (150)
-#define DEFAULT_H (150)
-#define MAXPIP (5)
+/* FIXME: This plugin needs to handle overlays as well. */
/* plugin class initialization function */
static void *mosaico_init_plugin(xine_t *xine, void *);
@@ -49,34 +43,54 @@ post_info_t mosaico_special_info = { XINE_POST_TYPE_VIDEO_COMPOSE };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST, 7, "mosaico", MOVERSION, &mosaico_special_info, &mosaico_init_plugin },
+ { PLUGIN_POST, 8, "mosaico", XINE_VERSION_CODE, &mosaico_special_info, &mosaico_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
-typedef struct mosaico_stream_s mosaico_stream_t;
-struct mosaico_stream_s {
- unsigned int x, y, w, h;
+typedef struct mosaico_parameters_s {
+ unsigned int pip_num;
+ unsigned int x, y, w, h;
+} mosaico_parameters_t;
+
+START_PARAM_DESCR(mosaico_parameters_t)
+PARAM_ITEM(POST_PARAM_TYPE_INT, pip_num, NULL, 1, INT_MAX, 1,
+ "which picture slots settings are being edited")
+PARAM_ITEM(POST_PARAM_TYPE_INT, x, NULL, 0, INT_MAX, 50,
+ "x coordinate of the pasted picture")
+PARAM_ITEM(POST_PARAM_TYPE_INT, y, NULL, 0, INT_MAX, 50,
+ "y coordinate of the pasted picture")
+PARAM_ITEM(POST_PARAM_TYPE_INT, w, NULL, 0, INT_MAX, 150,
+ "width of the pasted picture")
+PARAM_ITEM(POST_PARAM_TYPE_INT, h, NULL, 0, INT_MAX, 150,
+ "height of the pasted picture")
+END_PARAM_DESCR(mosaico_param_descr)
+
+typedef struct post_class_mosaico_s post_class_mosaico_t;
+typedef struct post_mosaico_s post_mosaico_t;
+
+struct post_class_mosaico_s {
+ post_class_t class;
+ xine_t *xine;
};
-/* plugin structure */
-typedef struct post_mosaico_out_s post_mosaico_out_t;
-struct post_mosaico_out_s {
- xine_post_out_t xine_out;
- /* keep the stream for open/close when rewiring */
- xine_stream_t *stream;
- vo_frame_t *saved_frame;
- vo_frame_t *saved_frame_2[MAXPIP];
- pthread_mutex_t mut1, mut2;
- mosaico_stream_t info[MAXPIP];
- xine_video_port_t *vo_port;
- unsigned int pip;
+/* plugin structures */
+typedef struct mosaico_pip_s mosaico_pip_t;
+struct mosaico_pip_s {
+ unsigned int x, y, w, h;
+ vo_frame_t *frame;
};
-typedef struct post_class_mosaico_s post_class_mosaico_t;
-struct post_class_mosaico_s {
- post_class_t class;
- xine_t *xine;
- post_mosaico_out_t *ip;
+struct post_mosaico_s {
+ post_plugin_t post;
+ xine_post_in_t parameter_input;
+
+ mosaico_pip_t *pip;
+ int64_t vpts_limit;
+ pthread_cond_t vpts_limit_changed;
+ int64_t skip_vpts;
+ int skip;
+ pthread_mutex_t mutex;
+ unsigned int pip_count;
};
/* plugin class functions */
@@ -90,70 +104,26 @@ static void mosaico_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void mosaico_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int mosaico_rewire(xine_post_out_t *output, void *data);
+/* parameter functions */
+static xine_post_api_descr_t *mosaico_get_param_descr(void);
+static int mosaico_set_parameters(xine_post_t *this_gen, void *param_gen);
+static int mosaico_get_parameters(xine_post_t *this_gen, void *param_gen);
+static char *mosaico_get_help(void);
-/* replaced video_port functions */
-static void mosaico_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *mosaico_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
+/* replaced video port functions */
static void mosaico_close(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *mosaico_get_frame_2(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
+
+/* frame intercept check */
+static int mosaico_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
+static int mosaico_draw_background(vo_frame_t *frame, xine_stream_t *stream);
static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream);
-static int mosaico_draw_2(vo_frame_t *frame, xine_stream_t *stream);
-
-static void x_changed_cb(void *data, xine_cfg_entry_t *cfg) {
- post_class_mosaico_t *class = (post_class_mosaico_t *)data;
- int i;
- sscanf(cfg->key, "post.mosaico_input%d", &i);
- if(class->ip) {
- post_mosaico_out_t *this = class->ip;
- this->info[i].x = cfg->num_value;
- }
-}
-
-static void y_changed_cb(void *data, xine_cfg_entry_t *cfg) {
- post_class_mosaico_t *class = (post_class_mosaico_t *)data;
- int i;
- sscanf(cfg->key, "post.mosaico_input%d", &i);
- if(class->ip) {
- post_mosaico_out_t *this = class->ip;
- this->info[i].y = cfg->num_value;
- }
-}
-
-static void w_changed_cb(void *data, xine_cfg_entry_t *cfg) {
- post_class_mosaico_t *class = (post_class_mosaico_t *)data;
- int i;
- sscanf(cfg->key, "post.mosaico_input%d", &i);
- if(class->ip) {
- post_mosaico_out_t *this = class->ip;
- this->info[i].w = cfg->num_value;
- }
-}
-
-static void h_changed_cb(void *data, xine_cfg_entry_t *cfg) {
- post_class_mosaico_t *class = (post_class_mosaico_t *)data;
- int i;
- sscanf(cfg->key, "post.mosaico_input%d", &i);
- if(class->ip) {
- post_mosaico_out_t *this = class->ip;
- this->info[i].h = cfg->num_value;
- }
-}
static void *mosaico_init_plugin(xine_t *xine, void *data)
{
- post_class_mosaico_t *this = (post_class_mosaico_t *)malloc(sizeof(post_class_mosaico_t));
- config_values_t *cfg;
- int i;
- char string[255];
+ post_class_mosaico_t *this = (post_class_mosaico_t *)xine_xmalloc(sizeof(post_class_mosaico_t));
if (!this)
return NULL;
@@ -163,19 +133,6 @@ static void *mosaico_init_plugin(xine_t *xine, void *data)
this->class.get_description = mosaico_get_description;
this->class.dispose = mosaico_class_dispose;
this->xine = xine;
- this->ip = NULL;
- cfg = xine->config;
-
- for(i=1;i<=MAXPIP;i++) {
- sprintf(string, "post.mosaico_input%d_x", i);
- cfg->register_num (cfg, string, DEFAULT_X, _("Default x position"), NULL, 10, x_changed_cb, this);
- sprintf(string, "post.mosaico_input%d_y", i);
- cfg->register_num (cfg, string, DEFAULT_Y, _("Default y position"), NULL, 10, y_changed_cb, this);
- sprintf(string, "post.mosaico_input%d_w", i);
- cfg->register_num (cfg, string, DEFAULT_W, _("Default width"), NULL, 10, w_changed_cb, this);
- sprintf(string, "post.mosaico_input%d_h", i);
- cfg->register_num (cfg, string, DEFAULT_H, _("Default height"), NULL, 10, h_changed_cb, this);
- }
return &this->class;
}
@@ -184,100 +141,62 @@ static post_plugin_t *mosaico_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_t *this = (post_plugin_t *)malloc(sizeof(post_plugin_t));
- xine_post_in_t *input1 = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input2;
- post_mosaico_out_t *output = (post_mosaico_out_t *)malloc(sizeof(post_mosaico_out_t));
- post_class_mosaico_t *class = (post_class_mosaico_t *) class_gen;
- post_video_port_t *port, *port2;
- xine_cfg_entry_t x_entry, y_entry, w_entry, h_entry;
+ post_mosaico_t *this = (post_mosaico_t *)xine_xmalloc(sizeof(post_mosaico_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
+ post_video_port_t *port;
+ static xine_post_api_t post_api =
+ { mosaico_set_parameters, mosaico_get_parameters, mosaico_get_param_descr, mosaico_get_help };
int i;
- char string[255];
- if(inputs < 2) return NULL;
-
lprintf("mosaico open\n");
- if (!this || !input1 || !output || !video_target || !video_target[0]) {
+ if (inputs < 2 || !this || !video_target || !video_target[0]) {
free(this);
- free(input1);
- free(output);
return NULL;
}
+
+ _x_post_init(&this->post, 0, inputs);
- class->ip = output;
-
- this->input = xine_list_new();
- this->output = xine_list_new();
-
- output->vo_port = video_target[0];
-
-/* background */
- port = _x_post_intercept_video_port(this, video_target[0]);
- port->port.open = mosaico_open;
- port->port.get_frame = mosaico_get_frame;
- port->port.close = mosaico_close;
- input1->name = "video in";
- input1->type = XINE_POST_DATA_VIDEO;
- input1->data = (xine_video_port_t *)&port->port;
- output->xine_out.name = "video out";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = mosaico_rewire;
- output->stream = NULL;
- output->pip = inputs-1;
- xine_list_append_content(this->output, output);
-
-/* init mutex */
- pthread_mutex_init(&output->mut1, NULL);
- pthread_mutex_init(&output->mut2, NULL);
- output->saved_frame = NULL;
- this->xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->xine_post.audio_input[0] = NULL;
- this->xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * (inputs+1));
- this->xine_post.video_input[0] = &port->port;
- xine_list_append_content(this->input, input1);
-
- for(i=1;i<inputs;i++) {
- /*registry operations*/
- input2 = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- output->saved_frame_2[i-1] = NULL;
- sprintf(string, "post.mosaico_input%d_x", i);
- if(xine_config_lookup_entry(class->xine, string, &x_entry))
- x_changed_cb(class, &x_entry);
-
- sprintf(string, "post.mosaico_input%d_y", i);
- if(xine_config_lookup_entry(class->xine, string, &y_entry))
- y_changed_cb(class, &y_entry);
-
- sprintf(string, "post.mosaico_input%d_w", i);
- if(xine_config_lookup_entry(class->xine, string, &w_entry))
- w_changed_cb(class, &w_entry);
-
- sprintf(string, "post.mosaico_input%d_h", i);
- if(xine_config_lookup_entry(class->xine, string, &h_entry))
- h_changed_cb(class, &h_entry);
-
- port2 = _x_post_intercept_video_port(this, video_target[i]);
-
- /* replace with our own get_frame function */
- port2->port.open = mosaico_open;
- port2->port.get_frame = mosaico_get_frame_2;
- port2->port.close = mosaico_close;
-
- sprintf(string, "video in %d", i);
- input2->name = strdup(string);
- input2->type = XINE_POST_DATA_VIDEO;
- input2->data = (xine_video_port_t *)&port2->port;
+ this->pip = (mosaico_pip_t *)xine_xmalloc(sizeof(mosaico_pip_t) * (inputs - 1));
+ this->pip_count = inputs - 1;
+
+ pthread_cond_init(&this->vpts_limit_changed, NULL);
+ pthread_mutex_init(&this->mutex, NULL);
+
+ /* the port for the background video */
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->intercept_frame = mosaico_intercept_frame;
+ port->new_frame->draw = mosaico_draw_background;
+ port->port_lock = &this->mutex;
+ port->frame_lock = &this->mutex;
+ this->post.xine_post.video_input[0] = &port->new_port;
+
+ for (i = 0; i < inputs - 1; i++) {
+ this->pip[i].x = 50;
+ this->pip[i].y = 50;
+ this->pip[i].w = 150;
+ this->pip[i].h = 150;
- this->xine_post.video_input[i] = &port2->port;
- xine_list_append_content(this->input, input2);
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, NULL);
+ port->new_port.close = mosaico_close;
+ port->intercept_frame = mosaico_intercept_frame;
+ port->new_frame->draw = mosaico_draw;
+ port->port_lock = &this->mutex;
+ port->frame_lock = &this->mutex;
+ this->post.xine_post.video_input[i+1] = &port->new_port;
}
- this->xine_post.video_input[i+1] = NULL;
- this->dispose = mosaico_dispose;
+ input_api = &this->parameter_input;
+ input_api->name = "parameters";
+ input_api->type = XINE_POST_DATA_PARAMETERS;
+ input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+
+ this->post.dispose = mosaico_dispose;
- return this;
+ return &this->post;
}
static char *mosaico_get_identifier(post_class_t *class_gen)
@@ -296,116 +215,102 @@ static void mosaico_class_dispose(post_class_t *class_gen)
}
-static void mosaico_dispose(post_plugin_t *this)
+static void mosaico_dispose(post_plugin_t *this_gen)
{
- post_mosaico_out_t *output = (post_mosaico_out_t *)xine_list_first_content(this->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
+ post_mosaico_t *this = (post_mosaico_t *)this_gen;
- if (output->stream)
- port->close(port, output->stream);
-
- free(this->xine_post.audio_input);
- free(this->xine_post.video_input);
- free(xine_list_first_content(this->input));
- free(xine_list_first_content(this->output));
- xine_list_free(this->input);
- xine_list_free(this->output);
- free(this);
+ if (_x_post_dispose(this_gen)) {
+ free(this->pip);
+ pthread_cond_destroy(&this->vpts_limit_changed);
+ pthread_mutex_destroy(&this->mutex);
+ free(this);
+ }
}
-static int mosaico_rewire(xine_post_out_t *output_gen, void *data)
+static xine_post_api_descr_t *mosaico_get_param_descr(void)
{
- post_mosaico_out_t *output = (post_mosaico_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- /*xine_post_in_t *input = (xine_post_in_t *) data;*/
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->stream);
- new_port->open(new_port, output->stream);
- }
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
- return 1;
+ return &mosaico_param_descr;
}
-static void mosaico_open(xine_video_port_t *port_gen, xine_stream_t *stream)
+static int mosaico_set_parameters(xine_post_t *this_gen, void *param_gen)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_mosaico_out_t *output = (post_mosaico_out_t *)xine_list_first_content(port->post->output);
-
- output->stream = stream;
- port->original_port->open(port->original_port, stream);
-
+ post_mosaico_t *this = (post_mosaico_t *)this_gen;
+ mosaico_parameters_t *param = (mosaico_parameters_t *)param_gen;
+
+ if (param->pip_num > this->pip_count) return 0;
+ this->pip[param->pip_num - 1].x = param->x;
+ this->pip[param->pip_num - 1].y = param->y;
+ this->pip[param->pip_num - 1].w = param->w;
+ this->pip[param->pip_num - 1].h = param->h;
+ return 1;
}
-static vo_frame_t *mosaico_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static int mosaico_get_parameters(xine_post_t *this_gen, void *param_gen)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
- _x_post_intercept_video_frame(frame, port);
- /* replace with our own draw function */
- frame->draw = mosaico_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
-
- return frame;
+ post_mosaico_t *this = (post_mosaico_t *)this_gen;
+ mosaico_parameters_t *param = (mosaico_parameters_t *)param_gen;
+
+ if (param->pip_num > this->pip_count || param->pip_num < 1)
+ param->pip_num = 1;
+ param->x = this->pip[param->pip_num - 1].x;
+ param->y = this->pip[param->pip_num - 1].y;
+ param->w = this->pip[param->pip_num - 1].w;
+ param->h = this->pip[param->pip_num - 1].h;
+ return 1;
}
-static vo_frame_t *mosaico_get_frame_2(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static char *mosaico_get_help(void)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
- _x_post_intercept_video_frame(frame, port);
- /* replace with our own draw function */
- frame->draw = mosaico_draw_2;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
-
- return frame;
+ return _("Mosaico does simple picture in picture effects.\n"
+ "\n"
+ "Parameters\n"
+ " pip_num: the number of the picture slot the following settings apply to\n"
+ " x: the x coordinate of the left upper corner of the picture\n"
+ " y: the y coordinate of the left upper corner of the picture\n"
+ " w: the width of the picture\n"
+ " h: the height of the picture\n");
}
+
static void mosaico_close(xine_video_port_t *port_gen, xine_stream_t *stream)
{
post_video_port_t *port = (post_video_port_t *)port_gen;
- post_mosaico_out_t *output = (post_mosaico_out_t *)xine_list_first_content(port->post->output);
- output->stream = NULL;
- port->original_port->close(port->original_port, stream);
+ post_mosaico_t *this = (post_mosaico_t *)port->post;
+ vo_frame_t *free_frame;
+ int pip_num;
+
+ for (pip_num = 0; pip_num < this->pip_count; pip_num++)
+ if (this->post.xine_post.video_input[pip_num+1] == port_gen) break;
+
+ pthread_mutex_lock(&this->mutex);
+ free_frame = this->pip[pip_num].frame;
+ this->pip[pip_num].frame = NULL;
+ port->original_port->close(port->original_port, NULL);
+ pthread_mutex_unlock(&this->mutex);
+
+ if (free_frame)
+ free_frame->free(free_frame);
+ port->stream = NULL;
+ _x_post_dec_usage(port);
}
-static void frame_copy_content(vo_frame_t *to, vo_frame_t *from) {
- int size;
- if((to == NULL)||(from == NULL)) {
- lprintf("Something wrong in frame_copy_content\n");
- return;
- }
+static int mosaico_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
+{
+ /* TODO: only YV12 supported */
+ return (frame->format == XINE_IMGFMT_YV12);
+}
- if(to->format != from->format) {
- lprintf("frame_copy_content : buffers have different format\n");
- return;
- }
+
+static void frame_copy_content(vo_frame_t *to, vo_frame_t *from)
+{
+ int size;
switch (from->format) {
case XINE_IMGFMT_YUY2:
- size = to->pitches[0] * to->height;
- xine_fast_memcpy(to->base[0], from->base[0], size);
+ /* TODO: implement conversion to YV12 or implement support to paste
+ * frames of different types together */
break;
case XINE_IMGFMT_YV12:
@@ -420,193 +325,164 @@ static void frame_copy_content(vo_frame_t *to, vo_frame_t *from) {
/* V */
size = to->pitches[2] * ((to->height + 1) / 2);
xine_fast_memcpy(to->base[2], from->base[2], size);
-
- }
-}
-
-static int _mosaico_draw_1(vo_frame_t *frame, post_mosaico_out_t *output) {
-
- post_video_port_t *port;
-
- if(frame != NULL) {
- port = (post_video_port_t *)frame->port;
- pthread_mutex_lock(&output->mut1);
- if(output->saved_frame != NULL) output->saved_frame->free(output->saved_frame);
- output->saved_frame = port->original_port->get_frame(port->original_port,
- frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
- output->saved_frame->pts = frame->pts;
- output->saved_frame->duration = frame->duration;
- output->saved_frame->bad_frame = frame->bad_frame;
- frame_copy_content(output->saved_frame, frame);
- pthread_mutex_unlock(&output->mut1);
}
- return 0;
}
-static int _mosaico_draw_2(vo_frame_t *frame, post_mosaico_out_t *output, int cont) {
-
- unsigned long i, j, wx, wy, ciclo;
- unsigned long zx, zy, wid, wid2, des1, des2, hei;
- unsigned long scalex, scaley, pos_in_x, pos_in_y, pos_in;
- post_video_port_t *port;
-
- pthread_mutex_lock(&output->mut1);
- pthread_mutex_lock(&output->mut2);
-
- if((output->saved_frame_2[cont] == NULL)&&(frame == NULL)) {
- lprintf("frame_2 NULL\n");
- pthread_mutex_unlock(&output->mut1);
- pthread_mutex_unlock(&output->mut2);
- return 0;
- }
-
- if(output->saved_frame == NULL) {
- lprintf("saved frame NULL\n");
- pthread_mutex_unlock(&output->mut1);
- pthread_mutex_unlock(&output->mut2);
- return 0;
- }
-
- if(frame != NULL) {
- port = (post_video_port_t *)frame->port;
- if(output->saved_frame_2[cont] != NULL) {
- output->saved_frame_2[cont]->free(output->saved_frame_2[cont]);
- output->saved_frame_2[cont] = NULL;
- }
+static void frame_paste(post_mosaico_t *this, vo_frame_t *background, int pip_num)
+{
+ unsigned long target_width, target_height;
+ unsigned long source_width, source_height;
+ unsigned long background_width;
+ unsigned long scale_x, scale_y;
+ const int shift_x = 3, shift_y = 3;
+ unsigned long pos_x, pos_y, pos;
+ unsigned long target_offset, source_offset;
+ unsigned long i, j;
+
+ if (!this->pip[pip_num].frame) return;
- output->saved_frame_2[cont] = port->original_port->get_frame(port->original_port,
- frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
- output->saved_frame_2[cont]->pts = frame->pts;
- output->saved_frame_2[cont]->duration = frame->duration;
- output->saved_frame_2[cont]->bad_frame = frame->bad_frame;
-
- frame_copy_content(output->saved_frame_2[cont], frame);
- }
-
- for(ciclo=1;ciclo<=output->pip;ciclo++) {
- if(output->saved_frame_2[ciclo-1] == NULL) continue;
- /*initialize vars*/
- wx = output->info[ciclo].w;
- wy = output->info[ciclo].h;
- scalex = scaley = 3;
- wid = output->saved_frame->width ;
- wid2 = output->saved_frame_2[ciclo-1]->width ;
- wid2 <<= scalex;
- hei = output->saved_frame_2[ciclo-1]->height;
- hei <<= scaley;
- zx = wid2 / wx;
- zy = hei / wy;
- pos_in_x = output->info[ciclo].x; pos_in_y = output->info[ciclo].y;
- pos_in = pos_in_y*wid+pos_in_x;
-
-
- switch (output->saved_frame_2[ciclo-1]->format) {
- case XINE_IMGFMT_YUY2:
- lprintf("not supported\n");
- /*size = new_frame->pitches[0] * new_frame->height;
- for (i = 0; i < size; i++)
- new_frame->base[0][i] = frame->base[0][i];*/
- break;
+ target_width = this->pip[pip_num].w;
+ target_height = this->pip[pip_num].h;
+ background_width = background->width;
+ source_width = this->pip[pip_num].frame->width;
+ source_height = this->pip[pip_num].frame->height;
+ scale_x = (source_width << shift_x) / target_width;
+ scale_y = (source_height << shift_y) / target_height;
+ pos_x = this->pip[pip_num].x;
+ pos_y = this->pip[pip_num].y;
+ pos = pos_y * background_width + pos_x;
+
+ switch (this->pip[pip_num].frame->format) {
+ case XINE_IMGFMT_YUY2:
+ /* TODO: implement YUY2 */
+ break;
- case XINE_IMGFMT_YV12:
- /* Y */
- for(j = 0; j < wy; j++)
- for (i = 0; i < wx; i++) {
- des1 = (i+ j*wid);
- des2 = ((i*zx)>>scalex)+(((j*zy)>>scaley) * (wid2>>scalex));
-/*
- if(!j) printf("%d %d\n", (i*zx)/scalex, wid2/scalex);
- if(!i) printf("%d %d\n", ((j*zy)>>scaley), (hei>>scaley));
-*/
- output->saved_frame->base[0][pos_in + des1] = output->saved_frame_2[ciclo-1]->base[0][des2];
- }
-
- /* U */
- wid = (wid+1) / 2;
- wid2 = (wid2+1) / 2;
- pos_in_x = (pos_in_x+1)/2;pos_in_y = (pos_in_y+1)/2;
- pos_in = pos_in_y * wid + pos_in_x;
- wx = (wx+1)/2; wy = (wy+1)/2;
- for(j = 0; j < wy; j++)
- for (i = 0; i < wx; i++) {
- des1 = (i+ j*wid);
- des2 = ((i*zx)>>scalex)+(((j*zy)>>scaley) * (wid2>>scalex));
- output->saved_frame->base[1][pos_in + des1] = output->saved_frame_2[ciclo-1]->base[1][(des2)];
- }
-
- /* V */
- for(j = 0; j < wy; j++)
- for (i = 0; i < wx; i++) {
- des1 = (i+ j*wid);
- des2 = ((i*zx)>>scalex)+(((j*zy)>>scaley) * (wid2>>scalex));
- output->saved_frame->base[2][pos_in + des1] = output->saved_frame_2[ciclo-1]->base[2][des2];
- }
-
- break;
- default:
- xprintf(output->stream->xine, XINE_VERBOSITY_DEBUG,
- "Mosaico: cannot handle image format %d\n", frame->format);
- /*new_frame->free(new_frame);
- _x_post_restore_video_frame(frame, port);
- return frame->draw(frame, stream);*/
- }
+ case XINE_IMGFMT_YV12:
+ /* Y */
+ target_offset = 0;
+ for (j = 0; j < target_height; j++, target_offset += (background_width - target_width))
+ for (i = 0; i < target_width; i++, target_offset++) {
+ source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width);
+ background->base[0][pos + target_offset] = this->pip[pip_num].frame->base[0][source_offset];
+ }
+
+ background_width = (background_width + 1) / 2;
+ source_width = (source_width + 1) / 2;
+ pos_x = (pos_x + 1) / 2;
+ pos_y = (pos_y + 1) / 2;
+ pos = pos_y * background_width + pos_x;
+ target_width = (target_width + 1) / 2;
+ target_height = (target_height + 1) / 2;
+
+ /* U */
+ target_offset = 0;
+ for (j = 0; j < target_height; j++, target_offset += (background_width - target_width))
+ for (i = 0; i < target_width; i++, target_offset++) {
+ source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width);
+ background->base[1][pos + target_offset] = this->pip[pip_num].frame->base[1][source_offset];
+ }
+
+ /* V */
+ target_offset = 0;
+ for (j = 0; j < target_height; j++, target_offset += (background_width - target_width))
+ for (i = 0; i < target_width; i++, target_offset++) {
+ source_offset = ((i * scale_x) >> shift_x) + (((j * scale_y) >> shift_y) * source_width);
+ background->base[2][pos + target_offset] = this->pip[pip_num].frame->base[2][source_offset];
+ }
+
+ break;
}
-
- pthread_mutex_unlock(&output->mut1);
- pthread_mutex_unlock(&output->mut2);
-
- return 0;
}
-static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream)
+static int mosaico_draw_background(vo_frame_t *frame, xine_stream_t *stream)
{
-/* vo_frame_t *new_frame;*/
- int skip;
post_video_port_t *port = (post_video_port_t *)frame->port;
- post_mosaico_out_t *output = (post_mosaico_out_t *)xine_list_first_content(port->post->output);
-
- _mosaico_draw_1(frame, output);
- _mosaico_draw_2(NULL, output, 0);
- pthread_mutex_lock(&output->mut1);
- if(output->saved_frame != NULL) {
- skip = output->saved_frame->draw(output->saved_frame, stream);
- /* new_frame->free(new_frame);*/
- frame->vpts = output->saved_frame->vpts;
- pthread_mutex_unlock(&output->mut1);
- _x_post_restore_video_frame(frame, port);
+ post_mosaico_t *this = (post_mosaico_t *)port->post;
+ vo_frame_t *background;
+ int pip_num, skip;
+
+ pthread_mutex_lock(&this->mutex);
+ if (frame->bad_frame) {
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
+
+ this->vpts_limit = frame->vpts + frame->duration;
+ if (skip) {
+ this->skip = skip;
+ this->skip_vpts = frame->vpts;
+ } else
+ this->skip = 0;
+
+ pthread_mutex_unlock(&this->mutex);
+ pthread_cond_broadcast(&this->vpts_limit_changed);
+
return skip;
}
- lprintf("ERROR!! oh oh\n\n");
- return 0;
+
+ background = port->original_port->get_frame(port->original_port,
+ frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
+ _x_post_frame_copy_up(frame, background);
+ frame_copy_content(background, frame);
+
+ for (pip_num = 0; pip_num < this->pip_count; pip_num++)
+ frame_paste(this, background, pip_num);
+
+ skip = background->draw(background, stream);
+ _x_post_frame_copy_down(frame, background);
+ this->vpts_limit = background->vpts + background->duration;
+ background->free(background);
+
+ if (skip) {
+ this->skip = skip;
+ this->skip_vpts = frame->vpts;
+ } else
+ this->skip = 0;
+
+ pthread_mutex_unlock(&this->mutex);
+ pthread_cond_broadcast(&this->vpts_limit_changed);
+
+ return skip;
}
-static int mosaico_draw_2(vo_frame_t *frame, xine_stream_t *stream)
+static int mosaico_draw(vo_frame_t *frame, xine_stream_t *stream)
{
-/* vo_frame_t *new_frame;*/
post_video_port_t *port = (post_video_port_t *)frame->port;
- post_mosaico_out_t *output = (post_mosaico_out_t *)xine_list_first_content(port->post->output);
- xine_video_port_t *pt;
- xine_post_in_t *in;
- int i = 0;
-
- in = xine_list_first_content(port->post->input);
-
- while(in != NULL) {
- pt = in->data;
- if(pt == frame->port) {
- lprintf("trovato %d\n", i);
- break;
- }
- in = xine_list_next_content(port->post->input);
- i++;
- }
-
- _mosaico_draw_1(NULL, output);
- _mosaico_draw_2(frame, output, i-1);
-
-
- _x_post_restore_video_frame(frame, port);
+ post_mosaico_t *this = (post_mosaico_t *)port->post;
+ vo_frame_t *free_frame;
+ int pip_num, skip;
- return 0;
+ for (pip_num = 0; pip_num < this->pip_count; pip_num++)
+ if (this->post.xine_post.video_input[pip_num+1] == frame->port) break;
+ _x_assert(pip_num < this->pip_count);
+
+ frame->lock(frame);
+
+ pthread_mutex_lock(&this->mutex);
+
+ /* the original output will never see this frame again */
+ _x_post_frame_u_turn(frame, stream);
+ while (frame->vpts > this->vpts_limit || !this->vpts_limit)
+ /* we are too early */
+ pthread_cond_wait(&this->vpts_limit_changed, &this->mutex);
+ free_frame = this->pip[pip_num].frame;
+ if (port->stream)
+ this->pip[pip_num].frame = frame;
+
+ if (this->skip && frame->vpts <= this->skip_vpts)
+ skip = this->skip;
+ else
+ skip = 0;
+
+ pthread_mutex_unlock(&this->mutex);
+
+ if (free_frame)
+ free_frame->free(free_frame);
+ if (!port->stream)
+ /* do not keep this frame when no stream is connected to us,
+ * otherwise, this frame might never get freed */
+ frame->free(frame);
+
+ return skip;
}
diff --git a/src/post/mosaico/switch.c b/src/post/mosaico/switch.c
index a03774041..260bbf79a 100644
--- a/src/post/mosaico/switch.c
+++ b/src/post/mosaico/switch.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: switch.c,v 1.11 2003/12/14 22:13:25 siggi Exp $
+ * $Id: switch.c,v 1.12 2004/01/07 19:52:42 mroi Exp $
*/
/*
@@ -33,7 +33,7 @@
#include "xine_internal.h"
#include "post.h"
-#define SWVERSION (5)
+/* FIXME: This plugin needs to handle overlays as well. */
/* plugin class initialization function */
static void *switch_init_plugin(xine_t *xine, void *);
@@ -43,28 +43,43 @@ post_info_t switch_special_info = { XINE_POST_TYPE_VIDEO_COMPOSE };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST, 7, "switch", SWVERSION, &switch_special_info, &switch_init_plugin },
+ { PLUGIN_POST, 8, "switch", XINE_VERSION_CODE, &switch_special_info, &switch_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
-/* plugin structure */
-typedef struct post_switch_out_s post_switch_out_t;
-struct post_switch_out_s {
- xine_post_out_t xine_out;
- /* keep the stream for open/close when rewiring */
- xine_stream_t *stream;
- pthread_mutex_t mut1;
- unsigned int pip;
- unsigned int selected_source;
-};
+typedef struct switch_parameter_s {
+ unsigned int select;
+} switch_parameter_t;
+
+
+START_PARAM_DESCR(switch_parameter_t)
+PARAM_ITEM(POST_PARAM_TYPE_INT, select, NULL, 1, INT_MAX, 1,
+ "the input source which will be passed through to the output")
+END_PARAM_DESCR(switch_param_descr)
typedef struct post_class_switch_s post_class_switch_t;
+typedef struct post_switch_s post_switch_t;
+
struct post_class_switch_s {
- post_class_t class;
- xine_t *xine;
- post_switch_out_t *ip;
+ post_class_t class;
+ xine_t *xine;
};
+/* plugin structure */
+struct post_switch_s {
+ post_plugin_t post;
+ xine_post_in_t parameter_input;
+
+ int64_t vpts_limit;
+ pthread_cond_t display_condition_changed;
+ int64_t skip_vpts;
+ int skip;
+ pthread_mutex_t mutex;
+ unsigned int source_count;
+ unsigned int selected_source;
+};
+
+
/* plugin class functions */
static post_plugin_t *switch_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
@@ -76,40 +91,19 @@ static void switch_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void switch_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int switch_rewire(xine_post_out_t *output, void *data);
-
-/* replaced video_port functions */
-static void switch_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *switch_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static vo_frame_t *switch_get_frame_2(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void switch_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* parameter functions */
+static xine_post_api_descr_t *switch_get_param_descr(void);
+static int switch_set_parameters(xine_post_t *this_gen, void *param_gen);
+static int switch_get_parameters(xine_post_t *this_gen, void *param_gen);
+static char *switch_get_help(void);
/* replaced vo_frame functions */
static int switch_draw(vo_frame_t *frame, xine_stream_t *stream);
-static int switch_draw_2(vo_frame_t *frame, xine_stream_t *stream);
-
-static void source_changed_cb(void *data, xine_cfg_entry_t *cfg) {
- post_class_switch_t *class = (post_class_switch_t *)data;
- if(class->ip) {
- post_switch_out_t *this = class->ip;
- pthread_mutex_lock(&this->mut1);
-
- this->selected_source = cfg->num_value;
- pthread_mutex_unlock(&this->mut1);
- }
-}
static void *switch_init_plugin(xine_t *xine, void *data)
{
- post_class_switch_t *this = (post_class_switch_t *)malloc(sizeof(post_class_switch_t));
- config_values_t *cfg;
- char string[255];
+ post_class_switch_t *this = (post_class_switch_t *)xine_xmalloc(sizeof(post_class_switch_t));
if (!this)
return NULL;
@@ -119,11 +113,6 @@ static void *switch_init_plugin(xine_t *xine, void *data)
this->class.get_description = switch_get_description;
this->class.dispose = switch_class_dispose;
this->xine = xine;
- this->ip = NULL;
- cfg = xine->config;
-
- sprintf(string, "post.switch_active");
- cfg->register_num (cfg, string, 0, _("Default active stream"), NULL, 10, source_changed_cb, this);
return &this->class;
}
@@ -132,90 +121,53 @@ static post_plugin_t *switch_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_t *this = (post_plugin_t *)malloc(sizeof(post_plugin_t));
- xine_post_in_t *input1 = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input2;
- post_switch_out_t *output = (post_switch_out_t *)malloc(sizeof(post_switch_out_t));
- post_class_switch_t *class = (post_class_switch_t *) class_gen;
- post_video_port_t *port = NULL;/*, *port2;*/
- /* int i; */
- char string[255];
- xine_cfg_entry_t entry;
-
+ post_switch_t *this = (post_switch_t *)xine_xmalloc(sizeof(post_switch_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
+ post_video_port_t *port;
+ static xine_post_api_t post_api =
+ { switch_set_parameters, switch_get_parameters, switch_get_param_descr, switch_get_help };
+ int i;
- if(inputs < 2) return NULL;
-
lprintf("switch open\n");
- if (!this || !input1 || !output || !video_target || !video_target[0]) {
+ if (inputs < 2 || !this || !video_target || !video_target[0]) {
free(this);
- free(input1);
- free(output);
return NULL;
}
-
- class->ip = output;
-
- this->input = xine_list_new();
- this->output = xine_list_new();
-
- this->xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->xine_post.audio_input[0] = NULL;
- this->xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * (inputs+1));
-
- /* for(i=0; i<inputs; i++) { */
-
- /* first input */
- input2 = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
-
- port = _x_post_intercept_video_port(this, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = switch_open;
- port->port.get_frame = switch_get_frame;
- port->port.close = switch_close;
-
- sprintf(string, "video in 0");
- input2->name = strdup(string);
- input2->type = XINE_POST_DATA_VIDEO;
- input2->data = (xine_video_port_t *)&port->port;
-
- this->xine_post.video_input[0] = &port->port;
- xine_list_append_content(this->input, input2);
-
- /* second input */
- input2 = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
-
- port = _x_post_intercept_video_port(this, video_target[1]);
- /* replace with our own get_frame function */
- port->port.open = switch_open;
- port->port.get_frame = switch_get_frame_2;
- port->port.close = switch_close;
-
- sprintf(string, "video in 1");
- input2->name = strdup(string);
- input2->type = XINE_POST_DATA_VIDEO;
- input2->data = (xine_video_port_t *)&port->port;
-
- this->xine_post.video_input[1] = &port->port;
- xine_list_append_content(this->input, input2);
- /* output */
- output->xine_out.name = "video out";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = switch_rewire;
- output->stream = NULL;
- xine_list_append_content(this->output, output);
-
- pthread_mutex_init(&output->mut1, NULL);
+ _x_post_init(&this->post, 0, inputs);
- if(xine_config_lookup_entry(class->xine, "post.switch_active", &entry))
- source_changed_cb(class, &entry);
+ this->source_count = inputs;
+ this->selected_source = 1;
+
+ pthread_cond_init(&this->display_condition_changed, NULL);
+ pthread_mutex_init(&this->mutex, NULL);
+
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->new_frame->draw = switch_draw;
+ port->port_lock = &this->mutex;
+ port->frame_lock = &this->mutex;
+ this->post.xine_post.video_input[0] = &port->new_port;
+
+ for (i = 1; i < inputs; i++) {
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, NULL);
+ port->new_frame->draw = switch_draw;
+ port->port_lock = &this->mutex;
+ port->frame_lock = &this->mutex;
+ this->post.xine_post.video_input[i] = &port->new_port;
+ }
+
+ input_api = &this->parameter_input;
+ input_api->name = "parameters";
+ input_api->type = XINE_POST_DATA_PARAMETERS;
+ input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
- this->xine_post.video_input[2] = NULL;
- this->dispose = switch_dispose;
+ this->post.dispose = switch_dispose;
- return this;
+ return &this->post;
}
static char *switch_get_identifier(post_class_t *class_gen)
@@ -225,7 +177,7 @@ static char *switch_get_identifier(post_class_t *class_gen)
static char *switch_get_description(post_class_t *class_gen)
{
- return "Switch is a post plugin able to switch at any time from different streams";
+ return "Switch is a post plugin able to switch at any time between different streams";
}
static void switch_class_dispose(post_class_t *class_gen)
@@ -234,217 +186,90 @@ static void switch_class_dispose(post_class_t *class_gen)
}
-static void switch_dispose(post_plugin_t *this)
+static void switch_dispose(post_plugin_t *this_gen)
{
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(this->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
+ post_switch_t *this = (post_switch_t *)this_gen;
- if (output->stream)
- port->close(port, output->stream);
-
- free(this->xine_post.audio_input);
- free(this->xine_post.video_input);
- free(xine_list_first_content(this->input));
- free(xine_list_first_content(this->output));
- xine_list_free(this->input);
- xine_list_free(this->output);
- free(this);
-}
-
-
-static int switch_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_switch_out_t *output = (post_switch_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- /*xine_post_in_t *input = (xine_post_in_t *) data;*/
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->stream);
- new_port->open(new_port, output->stream);
+ if (_x_post_dispose(this_gen)) {
+ pthread_cond_destroy(&this->display_condition_changed);
+ pthread_mutex_destroy(&this->mutex);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
- return 1;
}
-static void switch_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(port->post->output);
-
- output->stream = stream;
- port->original_port->open(port->original_port, stream);
-
-}
-static vo_frame_t *switch_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static xine_post_api_descr_t *switch_get_param_descr(void)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(port->post->output);
-
- pthread_mutex_lock(&output->mut1);
- frame = port->original_port->get_frame(port->original_port,
- width, height , ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- /* replace with our own draw function */
- frame->draw = switch_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- pthread_mutex_unlock(&output->mut1);
-
- return frame;
+ return &switch_param_descr;
}
-static vo_frame_t *switch_get_frame_2(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static int switch_set_parameters(xine_post_t *this_gen, void *param_gen)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(port->post->output);
-
- pthread_mutex_lock(&output->mut1);
-
- frame = port->original_port->get_frame(port->original_port,
- width, height , ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- /* replace with our own draw function */
- frame->draw = switch_draw_2;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- pthread_mutex_unlock(&output->mut1);
-
- return frame;
+ post_switch_t *this = (post_switch_t *)this_gen;
+ switch_parameter_t *param = (switch_parameter_t *)param_gen;
+
+ if (param->select > this->source_count) return 0;
+ pthread_mutex_lock(&this->mutex);
+ this->selected_source = param->select;
+ pthread_mutex_unlock(&this->mutex);
+ pthread_cond_broadcast(&this->display_condition_changed);
+ return 1;
}
-static void switch_close(xine_video_port_t *port_gen, xine_stream_t *stream)
+static int switch_get_parameters(xine_post_t *this_gen, void *param_gen)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(port->post->output);
- output->stream = NULL;
- port->original_port->close(port->original_port, stream);
-}
-
-static void frame_copy_content(vo_frame_t *to, vo_frame_t *from) {
- int size;
-
- if((to == NULL)||(from == NULL)) {
- lprintf("Something wrong in frame_copy_content\n");
- return;
- }
-
- if(to->format != from->format) {
- lprintf("frame_copy_content : buffers have different format\n");
- return;
- }
-
- switch (from->format) {
- case XINE_IMGFMT_YUY2:
- size = to->pitches[0] * to->height;
- xine_fast_memcpy(to->base[0], from->base[0], size);
- break;
+ post_switch_t *this = (post_switch_t *)this_gen;
+ switch_parameter_t *param = (switch_parameter_t *)param_gen;
- case XINE_IMGFMT_YV12:
- /* Y */
- size = to->pitches[0] * to->height;
- xine_fast_memcpy(to->base[0], from->base[0], size);
-
- /* U */
- size = to->pitches[1] * ((to->height + 1) / 2);
- xine_fast_memcpy(to->base[1], from->base[1], size);
-
- /* V */
- size = to->pitches[2] * ((to->height + 1) / 2);
- xine_fast_memcpy(to->base[2], from->base[2], size);
-
- }
+ param->select = this->selected_source;
+ return 1;
}
-static int switch_draw_2(vo_frame_t *frame, xine_stream_t *stream)
+static char *switch_get_help(void)
{
- int skip;
- post_video_port_t *port = (post_video_port_t *)frame->port;
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(port->post->output);
- vo_frame_t *res_frame;
-
- pthread_mutex_lock(&output->mut1);
-
- if(!output->selected_source) {
- /* printf("draw_2 quitting\n"); */
- _x_post_restore_video_frame(frame, port);
- pthread_mutex_unlock(&output->mut1);
- return 0;
- }
- /* printf("draw_2\n"); */
-
- res_frame = port->original_port->get_frame(port->original_port,
- frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
- res_frame->pts = frame->pts;
- res_frame->duration = frame->duration;
- res_frame->bad_frame = frame->bad_frame;
- _x_extra_info_merge(res_frame->extra_info, frame->extra_info);
-
-
- frame_copy_content(res_frame, frame);
-
- skip = res_frame->draw(res_frame, stream);
-
- res_frame->free(res_frame);
- frame->vpts = res_frame->vpts;
-
- _x_post_restore_video_frame(frame, port);
-
- pthread_mutex_unlock(&output->mut1);
-
- return skip;
+ return _("Switch can be used for fast switching between multiple inputs.\n"
+ "\n"
+ "Parameters\n"
+ " select: the number of the input which will be passed to the output\n");
}
+
static int switch_draw(vo_frame_t *frame, xine_stream_t *stream)
{
- int skip;
post_video_port_t *port = (post_video_port_t *)frame->port;
- post_switch_out_t *output = (post_switch_out_t *)xine_list_first_content(port->post->output);
- vo_frame_t *res_frame;
-
- pthread_mutex_lock(&output->mut1);
+ post_switch_t *this = (post_switch_t *)port->post;
+ int source_num, skip;
- if(output->selected_source) {
- /* printf("draw_1 quitting\n"); */
- _x_post_restore_video_frame(frame, port);
- pthread_mutex_unlock(&output->mut1);
- return 0;
+ for (source_num = 1; source_num <= this->source_count; source_num++)
+ if (this->post.xine_post.video_input[source_num-1] == frame->port) break;
+ _x_assert(source_num <= this->source_count);
+
+ pthread_mutex_lock(&this->mutex);
+ /* the original output will probably never see this frame again */
+ _x_post_frame_u_turn(frame, stream);
+ while (this->selected_source != source_num &&
+ (frame->vpts > this->vpts_limit || !this->vpts_limit))
+ /* we are too early */
+ pthread_cond_wait(&this->display_condition_changed, &this->mutex);
+ if (this->selected_source == source_num) {
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, NULL);
+ _x_post_frame_copy_down(frame, frame->next);
+ this->vpts_limit = frame->vpts + frame->duration;
+ if (skip) {
+ this->skip = skip;
+ this->skip_vpts = frame->vpts;
+ } else
+ this->skip = 0;
+ pthread_mutex_unlock(&this->mutex);
+ pthread_cond_broadcast(&this->display_condition_changed);
+ } else {
+ if (this->skip && frame->vpts <= this->skip_vpts)
+ skip = this->skip;
+ else
+ skip = 0;
+ pthread_mutex_unlock(&this->mutex);
}
- /* printf("draw_1\n"); */
-
- res_frame = port->original_port->get_frame(port->original_port,
- frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
- res_frame->pts = frame->pts;
- res_frame->duration = frame->duration;
- res_frame->bad_frame = frame->bad_frame;
- _x_extra_info_merge(res_frame->extra_info, frame->extra_info);
-
-
- frame_copy_content(res_frame, frame);
-
- skip = res_frame->draw(res_frame, stream);
- res_frame->free(res_frame);
- frame->vpts = res_frame->vpts;
-
- _x_post_restore_video_frame(frame, port);
-
- pthread_mutex_unlock(&output->mut1);
-
return skip;
}
diff --git a/src/post/planar/boxblur.c b/src/post/planar/boxblur.c
index 1504773c1..f85b6ad31 100644
--- a/src/post/planar/boxblur.c
+++ b/src/post/planar/boxblur.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: boxblur.c,v 1.11 2003/12/07 15:33:26 miguelfreitas Exp $
+ * $Id: boxblur.c,v 1.12 2004/01/07 19:52:42 mroi Exp $
*
* mplayer's boxblur
* Copyright (C) 2002 Michael Niedermayer <michaelni@gmx.at>
@@ -65,12 +65,10 @@ struct post_plugin_boxblur_s {
post_plugin_t post;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
boxblur_parameters_t params;
+ xine_post_in_t params_input;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
@@ -119,12 +117,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_boxblur_out_s post_boxblur_out_t;
-struct post_boxblur_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_boxblur_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *boxblur_open_plugin(post_class_t *class_gen, int inputs,
@@ -137,15 +129,8 @@ static void boxblur_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void boxblur_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int boxblur_rewire(xine_post_out_t *output, void *data);
-
-/* replaced video_port functions */
-static void boxblur_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *boxblur_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void boxblur_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* frame intercept check */
+static int boxblur_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
static int boxblur_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -171,61 +156,40 @@ static post_plugin_t *boxblur_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)malloc(sizeof(post_plugin_boxblur_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_boxblur_out_t *output = (post_boxblur_out_t *)malloc(sizeof(post_boxblur_out_t));
- post_video_port_t *port;
+ post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)xine_xmalloc(sizeof(post_plugin_boxblur_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
+ post_video_port_t *port;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
-
- this->stream = NULL;
-
+
+ _x_post_init(&this->post, 0, 1);
+
this->params.luma_radius = 2;
this->params.luma_power = 1;
this->params.chroma_radius = -1;
this->params.chroma_power = -1;
- pthread_mutex_init (&this->lock, NULL);
-
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = boxblur_open;
- port->port.get_frame = boxblur_get_frame;
- port->port.close = boxblur_close;
-
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
+ pthread_mutex_init(&this->lock, NULL);
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->intercept_frame = boxblur_intercept_frame;
+ port->new_frame->draw = boxblur_draw;
+
+ input_api = &this->params_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "boxblured video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = boxblur_rewire;
- output->plugin = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = boxblur_dispose;
@@ -251,81 +215,17 @@ static void boxblur_class_dispose(post_class_t *class_gen)
static void boxblur_dispose(post_plugin_t *this_gen)
{
post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)this_gen;
- post_boxblur_out_t *output = (post_boxblur_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int boxblur_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_boxblur_out_t *output = (post_boxblur_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
- if (!data)
- return 0;
-
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ pthread_mutex_destroy(&this->lock);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
}
-static void boxblur_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)port->post;
- this->stream = stream;
- port->original_port->open(port->original_port, stream);
-}
-static vo_frame_t *boxblur_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static int boxblur_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = boxblur_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
-
- return frame;
-}
-
-static void boxblur_close(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_boxblur_t *this = (post_plugin_boxblur_t *)port->post;
-
- this->stream = NULL;
-
- port->original_port->close(port->original_port, stream);
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
@@ -413,8 +313,6 @@ static int boxblur_draw(vo_frame_t *frame, xine_stream_t *stream)
int cw, ch;
int skip;
- _x_post_restore_video_frame(frame, port);
-
if( !frame->bad_frame ) {
@@ -423,11 +321,9 @@ static int boxblur_draw(vo_frame_t *frame, xine_stream_t *stream)
yv12_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
-
- yv12_frame->pts = frame->pts;
- yv12_frame->duration = frame->duration;
- _x_extra_info_merge(yv12_frame->extra_info, frame->extra_info);
-
+
+ _x_post_frame_copy_up(frame, yv12_frame);
+
yuy2_to_yv12(frame->base[0], frame->pitches[0],
yv12_frame->base[0], yv12_frame->pitches[0],
yv12_frame->base[1], yv12_frame->pitches[1],
@@ -443,11 +339,7 @@ static int boxblur_draw(vo_frame_t *frame, xine_stream_t *stream)
out_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
-
- _x_extra_info_merge(out_frame->extra_info, frame->extra_info);
-
- out_frame->pts = frame->pts;
- out_frame->duration = frame->duration;
+ _x_post_frame_copy_up(frame, out_frame);
pthread_mutex_lock (&this->lock);
@@ -475,16 +367,17 @@ static int boxblur_draw(vo_frame_t *frame, xine_stream_t *stream)
pthread_mutex_unlock (&this->lock);
skip = out_frame->draw(out_frame, stream);
-
- frame->vpts = out_frame->vpts;
+
+ _x_post_frame_copy_down(frame, out_frame);
out_frame->free(out_frame);
yv12_frame->free(yv12_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
-
return skip;
}
diff --git a/src/post/planar/denoise3d.c b/src/post/planar/denoise3d.c
index 36ba6490c..e4d8d65b2 100644
--- a/src/post/planar/denoise3d.c
+++ b/src/post/planar/denoise3d.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: denoise3d.c,v 1.11 2003/12/07 15:33:26 miguelfreitas Exp $
+ * $Id: denoise3d.c,v 1.12 2004/01/07 19:52:42 mroi Exp $
*
* mplayer's denoise3d
* Copyright (C) 2003 Daniel Moreno <comac@comac.darktech.org>
@@ -70,16 +70,14 @@ struct post_plugin_denoise3d_s {
post_plugin_t post;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
denoise3d_parameters_t params;
+ xine_post_in_t params_input;
- int Coefs[4][512];
- unsigned char Line[MAX_LINE_WIDTH];
- vo_frame_t *prev_frame;
+ int Coefs[4][512];
+ unsigned char Line[MAX_LINE_WIDTH];
+ vo_frame_t *prev_frame;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
#define ABS(A) ( (A) > 0 ? (A) : -(A) )
@@ -156,12 +154,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_denoise3d_out_s post_denoise3d_out_t;
-struct post_denoise3d_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_denoise3d_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *denoise3d_open_plugin(post_class_t *class_gen, int inputs,
@@ -174,16 +166,12 @@ static void denoise3d_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void denoise3d_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int denoise3d_rewire(xine_post_out_t *output, void *data);
-
-/* replaced video_port functions */
-static void denoise3d_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *denoise3d_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
+/* replaced video_port functios */
static void denoise3d_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* frame intercept check */
+static int denoise3d_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
+
/* replaced vo_frame functions */
static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -208,61 +196,41 @@ static post_plugin_t *denoise3d_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_denoise3d_t *this = (post_plugin_denoise3d_t *)malloc(sizeof(post_plugin_denoise3d_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_denoise3d_out_t *output = (post_denoise3d_out_t *)malloc(sizeof(post_denoise3d_out_t));
- post_video_port_t *port;
+ post_plugin_denoise3d_t *this = (post_plugin_denoise3d_t *)xine_xmalloc(sizeof(post_plugin_denoise3d_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
+ post_video_port_t *port;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
- this->stream = NULL;
-
+ _x_post_init(&this->post, 0, 1);
+
this->params.luma = PARAM1_DEFAULT;
this->params.chroma = PARAM2_DEFAULT;
this->params.time = PARAM3_DEFAULT;
this->prev_frame = NULL;
- pthread_mutex_init (&this->lock, NULL);
+ pthread_mutex_init(&this->lock, NULL);
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = denoise3d_open;
- port->port.get_frame = denoise3d_get_frame;
- port->port.close = denoise3d_close;
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->new_port.close = denoise3d_close;
+ port->intercept_frame = denoise3d_intercept_frame;
+ port->new_frame->draw = denoise3d_draw;
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
-
+ input_api = &this->params_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "denoise3d video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = denoise3d_rewire;
- output->plugin = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = denoise3d_dispose;
@@ -290,72 +258,13 @@ static void denoise3d_class_dispose(post_class_t *class_gen)
static void denoise3d_dispose(post_plugin_t *this_gen)
{
post_plugin_denoise3d_t *this = (post_plugin_denoise3d_t *)this_gen;
- post_denoise3d_out_t *output = (post_denoise3d_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int denoise3d_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_denoise3d_out_t *output = (post_denoise3d_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
- if (!data)
- return 0;
-
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ pthread_mutex_destroy(&this->lock);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
}
-static void denoise3d_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_denoise3d_t *this = (post_plugin_denoise3d_t *)port->post;
- this->stream = stream;
- port->original_port->open(port->original_port, stream);
-}
-
-static vo_frame_t *denoise3d_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = denoise3d_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
-
- return frame;
-}
static void denoise3d_close(xine_video_port_t *port_gen, xine_stream_t *stream)
{
@@ -367,11 +276,18 @@ static void denoise3d_close(xine_video_port_t *port_gen, xine_stream_t *stream)
this->prev_frame = NULL;
}
- this->stream = NULL;
-
port->original_port->close(port->original_port, stream);
+ port->stream = NULL;
+ _x_post_dec_usage(port);
+}
+
+
+static int denoise3d_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
+{
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
+
#define LowPass(Prev, Curr, Coef) (((Prev)*Coef[Prev - Curr] + (Curr)*(65536-(Coef[Prev - Curr]))) / 65536)
static void deNoise(unsigned char *Frame,
@@ -427,8 +343,6 @@ static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream)
int cw, ch;
int skip;
- _x_post_restore_video_frame(frame, port);
-
if( !frame->bad_frame ) {
@@ -438,9 +352,7 @@ static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream)
yv12_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
- yv12_frame->pts = frame->pts;
- yv12_frame->duration = frame->duration;
- _x_extra_info_merge(yv12_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, yv12_frame);
yuy2_to_yv12(frame->base[0], frame->pitches[0],
yv12_frame->base[0], yv12_frame->pitches[0],
@@ -457,11 +369,7 @@ static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream)
out_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
-
- _x_extra_info_merge(out_frame->extra_info, frame->extra_info);
-
- out_frame->pts = frame->pts;
- out_frame->duration = frame->duration;
+ _x_post_frame_copy_up(frame, out_frame);
pthread_mutex_lock (&this->lock);
@@ -492,18 +400,24 @@ static int denoise3d_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = out_frame->draw(out_frame, stream);
- frame->vpts = out_frame->vpts;
+ _x_post_frame_copy_down(frame, out_frame);
out_frame->free(out_frame);
if(this->prev_frame)
this->prev_frame->free(this->prev_frame);
- this->prev_frame = yv12_frame;
+ if(port->stream)
+ this->prev_frame = yv12_frame;
+ else
+ /* do not keep this frame when no stream is connected to us,
+ * otherwise, this frame might never get freed */
+ yv12_frame->free(yv12_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
-
return skip;
}
diff --git a/src/post/planar/eq.c b/src/post/planar/eq.c
index e9c413af0..7925d3e31 100644
--- a/src/post/planar/eq.c
+++ b/src/post/planar/eq.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: eq.c,v 1.10 2003/12/07 15:33:26 miguelfreitas Exp $
+ * $Id: eq.c,v 1.11 2004/01/07 19:52:42 mroi Exp $
*
* mplayer's eq (soft video equalizer)
* Copyright (C) Richard Felker
@@ -148,10 +148,8 @@ struct post_plugin_eq_s {
post_plugin_t post;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
- eq_parameters_t params;
+ eq_parameters_t params;
+ xine_post_in_t params_input;
pthread_mutex_t lock;
};
@@ -207,12 +205,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_eq_out_s post_eq_out_t;
-struct post_eq_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_eq_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs,
@@ -225,17 +217,12 @@ static void eq_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void eq_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int eq_rewire(xine_post_out_t *output, void *data);
-
/* replaced video_port functions */
static int eq_get_property(xine_video_port_t *port_gen, int property);
static int eq_set_property(xine_video_port_t *port_gen, int property, int value);
-static void eq_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *eq_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void eq_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+
+/* frame intercept check */
+static int eq_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
static int eq_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -261,67 +248,46 @@ static post_plugin_t *eq_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_eq_t *this = (post_plugin_eq_t *)malloc(sizeof(post_plugin_eq_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_eq_out_t *output = (post_eq_out_t *)malloc(sizeof(post_eq_out_t));
+ post_plugin_eq_t *this = (post_plugin_eq_t *)xine_xmalloc(sizeof(post_plugin_eq_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
post_video_port_t *port;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
- this->stream = NULL;
-
process = process_C;
#ifdef ARCH_X86
if( xine_mm_accel() & MM_ACCEL_X86_MMX )
process = process_MMX;
#endif
+ _x_post_init(&this->post, 0, 1);
+
this->params.brightness = 0;
this->params.contrast = 0;
pthread_mutex_init (&this->lock, NULL);
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = eq_open;
- port->port.get_frame = eq_get_frame;
- port->port.close = eq_close;
- port->port.get_property = eq_get_property;
- port->port.set_property = eq_set_property;
-
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->new_port.get_property = eq_get_property;
+ port->new_port.set_property = eq_set_property;
+ port->intercept_frame = eq_intercept_frame;
+ port->new_frame->draw = eq_draw;
+ input_api = &this->params_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "eqd video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = eq_rewire;
- output->plugin = this;
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = eq_dispose;
@@ -347,43 +313,14 @@ static void eq_class_dispose(post_class_t *class_gen)
static void eq_dispose(post_plugin_t *this_gen)
{
post_plugin_eq_t *this = (post_plugin_eq_t *)this_gen;
- post_eq_out_t *output = (post_eq_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int eq_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_eq_out_t *output = (post_eq_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ pthread_mutex_destroy(&this->lock);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
}
+
static int eq_get_property(xine_video_port_t *port_gen, int property) {
post_video_port_t *port = (post_video_port_t *)port_gen;
post_plugin_eq_t *this = (post_plugin_eq_t *)port->post;
@@ -412,49 +349,13 @@ static int eq_set_property(xine_video_port_t *port_gen, int property, int value)
return port->original_port->set_property(port->original_port, property, value);
}
-static void eq_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_eq_t *this = (post_plugin_eq_t *)port->post;
- this->stream = stream;
- port->original_port->open(port->original_port, stream);
-}
-
-static vo_frame_t *eq_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = eq_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
-
- return frame;
-}
-static void eq_close(xine_video_port_t *port_gen, xine_stream_t *stream)
+static int eq_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_eq_t *this = (post_plugin_eq_t *)port->post;
-
- this->stream = NULL;
-
- port->original_port->close(port->original_port, stream);
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
-
-
static int eq_draw(vo_frame_t *frame, xine_stream_t *stream)
{
post_video_port_t *port = (post_video_port_t *)frame->port;
@@ -463,8 +364,6 @@ static int eq_draw(vo_frame_t *frame, xine_stream_t *stream)
vo_frame_t *yv12_frame;
int skip;
- _x_post_restore_video_frame(frame, port);
-
if( !frame->bad_frame &&
((this->params.brightness != 0) || (this->params.contrast != 0)) ) {
@@ -474,9 +373,7 @@ static int eq_draw(vo_frame_t *frame, xine_stream_t *stream)
yv12_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
- yv12_frame->pts = frame->pts;
- yv12_frame->duration = frame->duration;
- _x_extra_info_merge(yv12_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, yv12_frame);
yuy2_to_yv12(frame->base[0], frame->pitches[0],
yv12_frame->base[0], yv12_frame->pitches[0],
@@ -493,11 +390,7 @@ static int eq_draw(vo_frame_t *frame, xine_stream_t *stream)
out_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
-
- _x_extra_info_merge(out_frame->extra_info, frame->extra_info);
-
- out_frame->pts = frame->pts;
- out_frame->duration = frame->duration;
+ _x_post_frame_copy_up(frame, out_frame);
pthread_mutex_lock (&this->lock);
@@ -514,15 +407,16 @@ static int eq_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = out_frame->draw(out_frame, stream);
- frame->vpts = out_frame->vpts;
+ _x_post_frame_copy_down(frame, out_frame);
out_frame->free(out_frame);
yv12_frame->free(yv12_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
-
return skip;
}
diff --git a/src/post/planar/eq2.c b/src/post/planar/eq2.c
index e4db57b24..005fc07db 100644
--- a/src/post/planar/eq2.c
+++ b/src/post/planar/eq2.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: eq2.c,v 1.12 2003/12/07 15:33:26 miguelfreitas Exp $
+ * $Id: eq2.c,v 1.13 2004/01/07 19:52:42 mroi Exp $
*
* mplayer's eq2 (soft video equalizer)
* Software equalizer (brightness, contrast, gamma, saturation)
@@ -308,10 +308,9 @@ struct post_plugin_eq2_s {
post_plugin_t post;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
eq2_parameters_t params;
+ xine_post_in_t params_input;
+
vf_eq2_t eq2;
pthread_mutex_t lock;
@@ -387,12 +386,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_eq2_out_s post_eq2_out_t;
-struct post_eq2_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_eq2_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *eq2_open_plugin(post_class_t *class_gen, int inputs,
@@ -405,17 +398,12 @@ static void eq2_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void eq2_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int eq2_rewire(xine_post_out_t *output, void *data);
-
/* replaced video_port functions */
static int eq2_get_property(xine_video_port_t *port_gen, int property);
static int eq2_set_property(xine_video_port_t *port_gen, int property, int value);
-static void eq2_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *eq2_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void eq2_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+
+/* frame intercept check */
+static int eq2_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -441,23 +429,20 @@ static post_plugin_t *eq2_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_eq2_t *this = (post_plugin_eq2_t *)malloc(sizeof(post_plugin_eq2_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_eq2_out_t *output = (post_eq2_out_t *)malloc(sizeof(post_eq2_out_t));
+ post_plugin_eq2_t *this = (post_plugin_eq2_t *)xine_xmalloc(sizeof(post_plugin_eq2_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
post_video_port_t *port;
- vf_eq2_t *eq2;
+ vf_eq2_t *eq2;
int i;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
-
- this->stream = NULL;
+
+ _x_post_init(&this->post, 0, 1);
eq2 = &this->eq2;
for (i = 0; i < 3; i++) {
@@ -480,42 +465,24 @@ static post_plugin_t *eq2_open_plugin(post_class_t *class_gen, int inputs,
eq2->ggamma = this->params.ggamma = 1.0;
eq2->bgamma = this->params.bgamma = 1.0;
- pthread_mutex_init (&this->lock, NULL);
+ pthread_mutex_init(&this->lock, NULL);
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = eq2_open;
- port->port.get_frame = eq2_get_frame;
- port->port.close = eq2_close;
- port->port.get_property = eq2_get_property;
- port->port.set_property = eq2_set_property;
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->new_port.get_property = eq2_get_property;
+ port->new_port.set_property = eq2_set_property;
+ port->intercept_frame = eq2_intercept_frame;
+ port->new_frame->draw = eq2_draw;
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
-
+ input_api = &this->params_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "eqd video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = eq2_rewire;
- output->plugin = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = eq2_dispose;
@@ -543,43 +510,14 @@ static void eq2_class_dispose(post_class_t *class_gen)
static void eq2_dispose(post_plugin_t *this_gen)
{
post_plugin_eq2_t *this = (post_plugin_eq2_t *)this_gen;
- post_eq2_out_t *output = (post_eq2_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int eq2_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_eq2_out_t *output = (post_eq2_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ pthread_mutex_destroy(&this->lock);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
}
+
static int eq2_get_property(xine_video_port_t *port_gen, int property) {
post_video_port_t *port = (post_video_port_t *)port_gen;
post_plugin_eq2_t *this = (post_plugin_eq2_t *)port->post;
@@ -614,48 +552,12 @@ static int eq2_set_property(xine_video_port_t *port_gen, int property, int value
return port->original_port->set_property(port->original_port, property, value);
}
-static void eq2_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_eq2_t *this = (post_plugin_eq2_t *)port->post;
- this->stream = stream;
- port->original_port->open(port->original_port, stream);
-}
-static vo_frame_t *eq2_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static int eq2_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = eq2_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
-
- return frame;
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
-static void eq2_close(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_eq2_t *this = (post_plugin_eq2_t *)port->post;
-
- this->stream = NULL;
-
- port->original_port->close(port->original_port, stream);
-}
-
-
-
static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream)
{
@@ -667,8 +569,6 @@ static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream)
int skip;
int i;
- _x_post_restore_video_frame(frame, port);
-
if( !frame->bad_frame &&
(eq2->param[0].adjust || eq2->param[1].adjust || eq2->param[2].adjust) ) {
@@ -678,9 +578,7 @@ static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream)
yv12_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
- yv12_frame->pts = frame->pts;
- yv12_frame->duration = frame->duration;
- _x_extra_info_merge(yv12_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, yv12_frame);
yuy2_to_yv12(frame->base[0], frame->pitches[0],
yv12_frame->base[0], yv12_frame->pitches[0],
@@ -696,11 +594,7 @@ static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream)
out_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
-
- _x_extra_info_merge(out_frame->extra_info, frame->extra_info);
-
- out_frame->pts = frame->pts;
- out_frame->duration = frame->duration;
+ _x_post_frame_copy_up(frame, out_frame);
pthread_mutex_lock (&this->lock);
@@ -722,15 +616,16 @@ static int eq2_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = out_frame->draw(out_frame, stream);
- frame->vpts = out_frame->vpts;
+ _x_post_frame_copy_down(frame, out_frame);
out_frame->free(out_frame);
yv12_frame->free(yv12_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
-
return skip;
}
diff --git a/src/post/planar/expand.c b/src/post/planar/expand.c
index 9f3cda2cf..5848775fb 100644
--- a/src/post/planar/expand.c
+++ b/src/post/planar/expand.c
@@ -27,7 +27,6 @@
*/
#include "xine_internal.h"
-#include "xineutils.h"
#include "post.h"
/* The expand trick explained:
@@ -45,13 +44,11 @@
* image into a frame with pre-attached black borders. This is the way:
* - when the decoder asks for a new frame, we allocate an enlarged
* frame from the original port and prepare it with black borders
- * - we clone the frame by copying its vo_frame_t structure
- * - we modify this structure so that the decoder will only see
+ * - we modify this frame's base pointers so that the decoder will only see
* the area between the black bars
* - this frame is given to the decoder, which paints its image inside
- * - when the decoder draws the frame, we intercept that and draw
- * the enlarged version instead
- * - same with freeing the frame
+ * - when the decoder draws the frame, the post plugin architecture
+ * will automatically restore the old pointers
* This way, the decoder (or any other post plugin down the tree) will only
* see the frame area between the black bars and by that modify the
* enlarged version directly. No need for later copying.
@@ -74,22 +71,14 @@ PARAM_ITEM(POST_PARAM_TYPE_INT, overlay_y_offset, NULL, -500, 500, 0,
"manually shift the overlay vertically")
END_PARAM_DESCR(expand_param_descr)
-typedef struct post_expand_out_s {
- xine_post_out_t xine_out;
- /* keep the stream for open/close when rewiring */
- xine_stream_t *stream;
-} post_expand_out_t;
-
typedef struct post_expand_s {
post_plugin_t post;
- post_overlay_manager_t *overlay_manager;
+ xine_post_in_t parameter_input;
+
int enable_automatic_shift;
int overlay_y_offset;
int top_bar_height;
-
- vo_frame_t **frames_prealloc;
- int num_frames;
} post_expand_t;
/* plugin class functions */
@@ -103,27 +92,19 @@ static void expand_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void expand_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int expand_rewire(xine_post_out_t *output, void *data);
-
/* parameter functions */
static xine_post_api_descr_t *expand_get_param_descr(void);
static int expand_set_parameters(xine_post_t *this_gen, void *param_gen);
static int expand_get_parameters(xine_post_t *this_gen, void *param_gen);
+static char *expand_get_help (void);
-/* replaced video_port functions */
-static void expand_open(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* replaced video port functions */
static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width,
uint32_t height, double ratio,
int format, int flags);
-static video_overlay_manager_t *expand_get_overlay_manager(xine_video_port_t *port_gen);
-static void expand_close(xine_video_port_t *port_gen, xine_stream_t *stream);
-/* replaced vo_frame functions */
-static int expand_draw(vo_frame_t *frame, xine_stream_t *stream);
-static void expand_free(vo_frame_t *frame);
-static void expand_field(vo_frame_t *frame, int which_field);
-static void expand_lock(vo_frame_t *frame);
+/* overlay manager intercept check */
+static int expand_intercept_ovl(post_video_port_t *port);
/* replaced overlay manager functions */
static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen, void *event);
@@ -144,78 +125,44 @@ void *expand_init_plugin(xine_t *xine, void *data)
return class;
}
-static char * get_help (void) {
- return _("The expand plugin is meant to take frames of arbitrary aspect ratio and "
- "converts them to 4:3 aspect by adding black bars on the top and bottom "
- "of the frame. This allows us to shift overlays down into the black area "
- "so they don't cover the image.\n"
- "\n"
- "Parameters (FIXME: better help)\n"
- " Enable_automatic_shift: Enable automatic overlay shifting\n"
- " Overlay_y_offset: Manually shift the overlay vertically\n"
- "\n"
- );
-}
static post_plugin_t *expand_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_expand_t *this = (post_expand_t *)malloc(sizeof(post_expand_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_param = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_expand_out_t *output = (post_expand_out_t *)malloc(sizeof(post_expand_out_t));
+ post_expand_t *this = (post_expand_t *)xine_xmalloc(sizeof(post_expand_t));
+ post_in_t *input;
+ xine_post_in_t *input_param;
+ post_out_t *output;
post_video_port_t *port;
static xine_post_api_t post_api =
- { expand_set_parameters, expand_get_parameters, expand_get_param_descr, get_help };
+ { expand_set_parameters, expand_get_parameters, expand_get_param_descr, expand_get_help };
- if (!this || !input || !input_param || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_param);
- free(output);
return NULL;
}
- this->overlay_manager = NULL;
+ _x_post_init(&this->post, 0, 1);
+
this->enable_automatic_shift = 0;
this->overlay_y_offset = 0;
- this->frames_prealloc = NULL;
- this->num_frames = 0;
-
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = expand_open;
- port->port.get_frame = expand_get_frame;
- port->port.get_overlay_manager = expand_get_overlay_manager;
- port->port.close = expand_close;
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->new_port.get_frame = expand_get_frame;
+ port->intercept_ovl = expand_intercept_ovl;
+ port->new_manager->add_event = expand_overlay_add_event;
+ input_param = &this->parameter_input;
input_param->name = "parameters";
input_param->type = XINE_POST_DATA_PARAMETERS;
input_param->data = &post_api;
-
- output->xine_out.name = "expanded video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = expand_rewire;
- output->stream = NULL;
+ xine_list_append_content(this->post.input, input_param);
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
+ input->xine_in.name = "video";
+ output->xine_out.name = "expanded video";
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_param);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = expand_dispose;
@@ -240,47 +187,10 @@ static void expand_class_dispose(post_class_t *class_gen)
static void expand_dispose(post_plugin_t *this_gen)
{
- post_expand_out_t *output = (post_expand_out_t *)xine_list_first_content(this_gen->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
post_expand_t *this = (post_expand_t *)this_gen;
- int i;
-
- if (output->stream)
- port->close(port, output->stream);
- free(this->overlay_manager);
-
- for (i = 0; i < this->num_frames; i++)
- free(this->frames_prealloc[i]);
- free(this->frames_prealloc);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int expand_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_expand_out_t *output = (post_expand_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->stream);
- new_port->open(new_port, output->stream);
- }
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
- return 1;
+ if (_x_post_dispose(this_gen))
+ free(this);
}
@@ -309,25 +219,32 @@ static int expand_get_parameters(xine_post_t *this_gen, void *param_gen)
return 1;
}
-
-static void expand_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_expand_out_t *output = (post_expand_out_t *)xine_list_first_content(port->post->output);
- output->stream = stream;
- port->original_port->open(port->original_port, stream);
+static char *expand_get_help(void) {
+ return _("The expand plugin is meant to take frames of arbitrary aspect ratio and "
+ "converts them to 4:3 aspect by adding black bars on the top and bottom "
+ "of the frame. This allows us to shift overlays down into the black area "
+ "so they don't cover the image.\n"
+ "\n"
+ "Parameters (FIXME: better help)\n"
+ " Enable_automatic_shift: Enable automatic overlay shifting\n"
+ " Overlay_y_offset: Manually shift the overlay vertically\n"
+ "\n"
+ );
}
+
static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width,
uint32_t height, double ratio,
int format, int flags)
{
post_video_port_t *port = (post_video_port_t *)port_gen;
post_expand_t *this = (post_expand_t *)port->post;
- vo_frame_t *original_frame, *cloned_frame = NULL;
+ vo_frame_t *frame;
uint32_t new_height, top_bar_height;
int i, end;
+ _x_post_rewire_video(port);
+
if (ratio <= 0.0) ratio = (double)width / (double)height;
/* Calculate height of expanded frame */
@@ -336,171 +253,77 @@ static vo_frame_t *expand_get_frame(xine_video_port_t *port_gen, uint32_t width,
top_bar_height = (new_height - height) / 2;
top_bar_height = (top_bar_height + 1) & ~1;
- ((post_expand_t *)port->post)->top_bar_height = top_bar_height;
+ this->top_bar_height = top_bar_height;
if (new_height > height &&
(format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2)) {
- original_frame = port->original_port->get_frame(port->original_port,
+ frame = port->original_port->get_frame(port->original_port,
width, new_height, 4.0 / 3.0, format, flags);
- /* search for a free frame among the preallocated */
- while (!cloned_frame) {
- for (i = 0; i < this->num_frames; i++)
- /* misusing is_first as a free flag */
- if (this->frames_prealloc[i]->is_first) break;
- if (i >= this->num_frames) {
- /* no free frame found -> we need to allocate some more */
- this->frames_prealloc =
- realloc(this->frames_prealloc, sizeof(vo_frame_t *) * (this->num_frames + 15));
- for (i = this->num_frames; i < this->num_frames + 15; i++) {
- this->frames_prealloc[i] = (vo_frame_t *)malloc(sizeof(vo_frame_t));
- this->frames_prealloc[i]->is_first = 1;
- }
- this->num_frames += 15;
- } else
- cloned_frame = this->frames_prealloc[i];
- }
- /* misusing is_first as a free flag */
- cloned_frame->is_first = 0;
-
- xine_fast_memcpy(cloned_frame, original_frame, sizeof(vo_frame_t));
- /* replace with our own functions */
- cloned_frame->draw = expand_draw;
- cloned_frame->free = expand_free;
- /* decoders should not copy the frames, since they won't be displayed as is */
- /* FIXME: We might get speed improvements with copy-capable outputs by:
- * - copying the top black bar here
- * - letting the decoder copy the image
- * - copying the bottom black bar in expand_draw()
- */
- cloned_frame->proc_slice = NULL;
- cloned_frame->proc_frame = NULL;
- cloned_frame->field = expand_field;
- cloned_frame->lock = expand_lock;
-
- cloned_frame->port = port_gen;
- /* misuse the next pointer to remember the original */
- cloned_frame->next = original_frame;
+ _x_post_inc_usage(port);
+ frame = _x_post_intercept_video_frame(frame, port);
/* paint black bars in the top and bottom of the frame and hide these
* from the decoders by modifying the pointers to and
* the size of the drawing area */
- cloned_frame->height = height;
- cloned_frame->ratio = ratio;
+ frame->height = height;
+ frame->ratio = ratio;
switch (format) {
case XINE_IMGFMT_YV12:
/* paint top bar */
- memset(cloned_frame->base[0], 0, cloned_frame->pitches[0] * top_bar_height );
- memset(cloned_frame->base[1], 128, cloned_frame->pitches[1] * top_bar_height / 2);
- memset(cloned_frame->base[2], 128, cloned_frame->pitches[2] * top_bar_height / 2);
+ memset(frame->base[0], 0, frame->pitches[0] * top_bar_height );
+ memset(frame->base[1], 128, frame->pitches[1] * top_bar_height / 2);
+ memset(frame->base[2], 128, frame->pitches[2] * top_bar_height / 2);
/* paint bottom bar */
- memset(cloned_frame->base[0] + cloned_frame->pitches[0] * (top_bar_height + height) , 0,
- cloned_frame->pitches[0] * (new_height - top_bar_height - height) );
- memset(cloned_frame->base[1] + cloned_frame->pitches[1] * (top_bar_height + height) / 2, 128,
- cloned_frame->pitches[1] * (new_height - top_bar_height - height) / 2);
- memset(cloned_frame->base[2] + cloned_frame->pitches[2] * (top_bar_height + height) / 2, 128,
- cloned_frame->pitches[2] * (new_height - top_bar_height - height) / 2);
+ memset(frame->base[0] + frame->pitches[0] * (top_bar_height + height) , 0,
+ frame->pitches[0] * (new_height - top_bar_height - height) );
+ memset(frame->base[1] + frame->pitches[1] * (top_bar_height + height) / 2, 128,
+ frame->pitches[1] * (new_height - top_bar_height - height) / 2);
+ memset(frame->base[2] + frame->pitches[2] * (top_bar_height + height) / 2, 128,
+ frame->pitches[2] * (new_height - top_bar_height - height) / 2);
/* modify drawing area */
- cloned_frame->base[0] += cloned_frame->pitches[0] * top_bar_height;
- cloned_frame->base[1] += cloned_frame->pitches[1] * top_bar_height / 2;
- cloned_frame->base[2] += cloned_frame->pitches[2] * top_bar_height / 2;
+ frame->base[0] += frame->pitches[0] * top_bar_height;
+ frame->base[1] += frame->pitches[1] * top_bar_height / 2;
+ frame->base[2] += frame->pitches[2] * top_bar_height / 2;
break;
case XINE_IMGFMT_YUY2:
/* paint top bar */
- end = cloned_frame->pitches[0] * top_bar_height;
+ end = frame->pitches[0] * top_bar_height;
for (i = 0; i < end; i += 2) {
- cloned_frame->base[0][i] = 0;
- cloned_frame->base[0][i+1] = 128;
+ frame->base[0][i] = 0;
+ frame->base[0][i+1] = 128;
}
/* paint bottom bar */
- end = cloned_frame->pitches[0] * new_height;
- for (i = cloned_frame->pitches[0] * (top_bar_height + height); i < end; i += 2) {
- cloned_frame->base[0][i] = 0;
- cloned_frame->base[0][i+1] = 128;
+ end = frame->pitches[0] * new_height;
+ for (i = frame->pitches[0] * (top_bar_height + height); i < end; i += 2) {
+ frame->base[0][i] = 0;
+ frame->base[0][i+1] = 128;
}
/* modify drawing area */
- cloned_frame->base[0] += cloned_frame->pitches[0] * top_bar_height;
+ frame->base[0] += frame->pitches[0] * top_bar_height;
}
} else {
- cloned_frame = port->original_port->get_frame(port->original_port,
+ frame = port->original_port->get_frame(port->original_port,
width, height, ratio, format, flags);
/* no need to intercept this one, we are not going to do anything with it */
}
- return cloned_frame;
-}
-
-static video_overlay_manager_t *expand_get_overlay_manager(xine_video_port_t *port_gen)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_expand_t *this = (post_expand_t *)port->post;
-
- if (!this->overlay_manager) {
- /* create a new overlay manager to intercept */
- this->overlay_manager = _x_post_intercept_overlay_manager(&this->post,
- port->original_port->get_overlay_manager(port->original_port));
- /* replace with our own add_event function */
- this->overlay_manager->manager.add_event = expand_overlay_add_event;
- } else {
- /* the original port might have changed */
- this->overlay_manager->original_manager =
- port->original_port->get_overlay_manager(port->original_port);
- }
-
- return &this->overlay_manager->manager;
-}
-
-static void expand_close(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_expand_out_t *output = (post_expand_out_t *)xine_list_first_content(port->post->output);
- output->stream = NULL;
- port->original_port->close(port->original_port, stream);
+ return frame;
}
-static int expand_draw(vo_frame_t *frame, xine_stream_t *stream)
-{
- vo_frame_t *original_frame = frame->next;
- int skip;
-
- original_frame->pts = frame->pts;
- original_frame->duration = frame->duration;
- original_frame->bad_frame = frame->bad_frame;
- _x_extra_info_merge(original_frame->extra_info, frame->extra_info);
- skip = original_frame->draw(original_frame, stream);
- frame->vpts = original_frame->vpts;
- return skip;
-}
-
-static void expand_free(vo_frame_t *frame)
+static int expand_intercept_ovl(post_video_port_t *port)
{
- vo_frame_t *original_frame = frame->next;
-
- original_frame->free(original_frame);
- if (--frame->lock_counter == 0)
- /* misusing is_first as a free flag */
- frame->is_first = 1;
-}
-
-static void expand_field(vo_frame_t *frame, int which_field)
-{
-}
-
-static void expand_lock(vo_frame_t *frame)
-{
- vo_frame_t *original_frame = frame->next;
-
- original_frame->lock(original_frame);
- frame->lock_counter++;
+ /* we always intercept overlay manager */
+ return 1;
}
static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen, void *event_gen)
{
- post_overlay_manager_t *ovl_manager = (post_overlay_manager_t *)this_gen;
- video_overlay_event_t *event = (video_overlay_event_t *)event_gen;
- post_expand_t *this = (post_expand_t *)ovl_manager->post;
+ video_overlay_event_t *event = (video_overlay_event_t *)event_gen;
+ post_video_port_t *port = _x_post_ovl_manager_to_port(this_gen);
+ post_expand_t *this = (post_expand_t *)port->post;
if (event->event_type == OVERLAY_EVENT_SHOW) {
switch (event->object.object_type) {
@@ -517,5 +340,5 @@ static int32_t expand_overlay_add_event(video_overlay_manager_t *this_gen, void
}
}
- return ovl_manager->original_manager->add_event(ovl_manager->original_manager, event_gen);
+ return port->original_manager->add_event(port->original_manager, event_gen);
}
diff --git a/src/post/planar/invert.c b/src/post/planar/invert.c
index 9d76fc73b..613565aa8 100644
--- a/src/post/planar/invert.c
+++ b/src/post/planar/invert.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: invert.c,v 1.18 2003/12/09 00:02:35 f1rmb Exp $
+ * $Id: invert.c,v 1.19 2004/01/07 19:52:42 mroi Exp $
*/
/*
@@ -31,14 +31,6 @@
/* plugin class initialization function */
void *invert_init_plugin(xine_t *xine, void *);
-/* plugin structure */
-typedef struct post_invert_out_s post_invert_out_t;
-struct post_invert_out_s {
- xine_post_out_t xine_out;
- /* keep the stream for open/close when rewiring */
- xine_stream_t *stream;
-};
-
/* plugin class functions */
static post_plugin_t *invert_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
@@ -50,15 +42,8 @@ static void invert_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void invert_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int invert_rewire(xine_post_out_t *output, void *data);
-
-/* replaced video_port functions */
-static void invert_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *invert_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void invert_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* frame intercept check */
+static int invert_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
static int invert_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -84,45 +69,24 @@ static post_plugin_t *invert_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_t *this = (post_plugin_t *)malloc(sizeof(post_plugin_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_invert_out_t *output = (post_invert_out_t *)malloc(sizeof(post_invert_out_t));
+ post_plugin_t *this = (post_plugin_t *)xine_xmalloc(sizeof(post_plugin_t));
+ post_in_t *input;
+ post_out_t *output;
post_video_port_t *port;
- if (!this || !input || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(output);
return NULL;
}
- port = _x_post_intercept_video_port(this, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = invert_open;
- port->port.get_frame = invert_get_frame;
- port->port.close = invert_close;
-
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
-
- output->xine_out.name = "inverted video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = invert_rewire;
- output->stream = NULL;
+ _x_post_init(this, 0, 1);
- this->xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->xine_post.audio_input[0] = NULL;
- this->xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->xine_post.video_input[0] = &port->port;
- this->xine_post.video_input[1] = NULL;
-
- this->input = xine_list_new();
- this->output = xine_list_new();
-
- xine_list_append_content(this->input, input);
- xine_list_append_content(this->output, output);
+ port = _x_post_intercept_video_port(this, video_target[0], &input, &output);
+ port->intercept_frame = invert_intercept_frame;
+ port->new_frame->draw = invert_draw;
+ input->xine_in.name = "video";
+ output->xine_out.name = "inverted video";
+ this->xine_post.video_input[0] = &port->new_port;
this->dispose = invert_dispose;
@@ -147,77 +111,14 @@ static void invert_class_dispose(post_class_t *class_gen)
static void invert_dispose(post_plugin_t *this)
{
- post_invert_out_t *output = (post_invert_out_t *)xine_list_first_content(this->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (output->stream)
- port->close(port, output->stream);
-
- free(this->xine_post.audio_input);
- free(this->xine_post.video_input);
- free(xine_list_first_content(this->input));
- free(xine_list_first_content(this->output));
- xine_list_free(this->input);
- xine_list_free(this->output);
- free(this);
-}
-
-
-static int invert_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_invert_out_t *output = (post_invert_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->stream);
- new_port->open(new_port, output->stream);
- }
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
- return 1;
+ if (_x_post_dispose(this))
+ free(this);
}
-static void invert_open(xine_video_port_t *port_gen, xine_stream_t *stream)
+static int invert_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_invert_out_t *output = (post_invert_out_t *)xine_list_first_content(port->post->output);
- output->stream = stream;
- port->original_port->open(port->original_port, stream);
-}
-
-static vo_frame_t *invert_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = invert_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
-
- return frame;
-}
-
-static void invert_close(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_invert_out_t *output = (post_invert_out_t *)xine_list_first_content(port->post->output);
- output->stream = NULL;
- port->original_port->close(port->original_port, stream);
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
@@ -227,12 +128,16 @@ static int invert_draw(vo_frame_t *frame, xine_stream_t *stream)
vo_frame_t *inverted_frame;
int size, i, skip;
+ if (frame->bad_frame) {
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
+ return skip;
+ }
+
inverted_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, frame->format, frame->flags | VO_BOTH_FIELDS);
- inverted_frame->pts = frame->pts;
- inverted_frame->duration = frame->duration;
- inverted_frame->bad_frame = frame->bad_frame;
- _x_extra_info_merge(inverted_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, inverted_frame);
switch (inverted_frame->format) {
case XINE_IMGFMT_YUY2:
@@ -254,17 +159,10 @@ static int invert_draw(vo_frame_t *frame, xine_stream_t *stream)
for (i = 0; i < size; i++)
inverted_frame->base[2][i] = 0xff - frame->base[2][i];
break;
- default:
- xprintf(stream->xine, XINE_VERBOSITY_DEBUG,
- "invert: cannot handle image format %d\n", frame->format);
- inverted_frame->free(inverted_frame);
- _x_post_restore_video_frame(frame, port);
- return frame->draw(frame, stream);
}
skip = inverted_frame->draw(inverted_frame, stream);
+ _x_post_frame_copy_down(frame, inverted_frame);
inverted_frame->free(inverted_frame);
- frame->vpts = inverted_frame->vpts;
- _x_post_restore_video_frame(frame, port);
return skip;
}
diff --git a/src/post/planar/planar.c b/src/post/planar/planar.c
index 0c869eff3..2abcb5ea0 100644
--- a/src/post/planar/planar.c
+++ b/src/post/planar/planar.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: planar.c,v 1.6 2003/12/14 22:13:25 siggi Exp $
+ * $Id: planar.c,v 1.7 2004/01/07 19:52:42 mroi Exp $
*
* catalog for planar post plugins
*/
@@ -52,13 +52,13 @@ post_info_t pp_special_info = { XINE_POST_TYPE_VIDEO_FILTER };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST, 7, "expand", XINE_VERSION_CODE+1, &expand_special_info, &expand_init_plugin },
- { PLUGIN_POST, 7, "invert", XINE_VERSION_CODE+1, &invert_special_info, &invert_init_plugin },
- { PLUGIN_POST, 7, "eq", XINE_VERSION_CODE, &eq_special_info, &eq_init_plugin },
- { PLUGIN_POST, 7, "denoise3d", XINE_VERSION_CODE, &denoise3d_special_info, &denoise3d_init_plugin },
- { PLUGIN_POST, 7, "boxblur", XINE_VERSION_CODE, &boxblur_special_info, &boxblur_init_plugin },
- { PLUGIN_POST, 7, "eq2", XINE_VERSION_CODE, &eq2_special_info, &eq2_init_plugin },
- { PLUGIN_POST, 7, "unsharp", XINE_VERSION_CODE, &unsharp_special_info, &unsharp_init_plugin },
- { PLUGIN_POST, 7, "pp", XINE_VERSION_CODE, &pp_special_info, &pp_init_plugin },
+ { PLUGIN_POST, 8, "expand", XINE_VERSION_CODE, &expand_special_info, &expand_init_plugin },
+ { PLUGIN_POST, 8, "invert", XINE_VERSION_CODE, &invert_special_info, &invert_init_plugin },
+ { PLUGIN_POST, 8, "eq", XINE_VERSION_CODE, &eq_special_info, &eq_init_plugin },
+ { PLUGIN_POST, 8, "denoise3d", XINE_VERSION_CODE, &denoise3d_special_info, &denoise3d_init_plugin },
+ { PLUGIN_POST, 8, "boxblur", XINE_VERSION_CODE, &boxblur_special_info, &boxblur_init_plugin },
+ { PLUGIN_POST, 8, "eq2", XINE_VERSION_CODE, &eq2_special_info, &eq2_init_plugin },
+ { PLUGIN_POST, 8, "unsharp", XINE_VERSION_CODE, &unsharp_special_info, &unsharp_init_plugin },
+ { PLUGIN_POST, 8, "pp", XINE_VERSION_CODE, &pp_special_info, &pp_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/post/planar/pp.c b/src/post/planar/pp.c
index b2c81f173..95fcfb4f1 100755
--- a/src/post/planar/pp.c
+++ b/src/post/planar/pp.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: pp.c,v 1.4 2003/12/07 15:33:26 miguelfreitas Exp $
+ * $Id: pp.c,v 1.5 2004/01/07 19:52:42 mroi Exp $
*
* plugin for ffmpeg libpostprocess
*/
@@ -61,12 +61,11 @@ struct post_plugin_pp_s {
post_plugin_t post;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
int frame_width;
int frame_height;
- pp_parameters_t params;
+ pp_parameters_t params;
+ xine_post_in_t params_input;
/* libpostproc specific stuff */
int pp_flags;
@@ -140,12 +139,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_pp_out_s post_pp_out_t;
-struct post_pp_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_pp_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *pp_open_plugin(post_class_t *class_gen, int inputs,
@@ -158,15 +151,8 @@ static void pp_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void pp_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int pp_rewire(xine_post_out_t *output, void *data);
-
-/* replaced video_port functions */
-static void pp_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *pp_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void pp_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* frame intercept check */
+static int pp_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
static int pp_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -192,23 +178,20 @@ static post_plugin_t *pp_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_plugin_pp_t *this = (post_plugin_pp_t *)malloc(sizeof(post_plugin_pp_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_pp_out_t *output = (post_pp_out_t *)malloc(sizeof(post_pp_out_t));
+ post_plugin_pp_t *this = (post_plugin_pp_t *)xine_xmalloc(sizeof(post_plugin_pp_t));
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
post_video_port_t *port;
- uint32_t cpu_caps;
+ uint32_t cpu_caps;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
- this->stream = NULL;
-
+ _x_post_init(&this->post, 0, 1);
+
this->params.quality = 3;
strcpy(this->params.mode, "de");
@@ -227,38 +210,20 @@ static post_plugin_t *pp_open_plugin(post_class_t *class_gen, int inputs,
pthread_mutex_init (&this->lock, NULL);
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = pp_open;
- port->port.get_frame = pp_get_frame;
- port->port.close = pp_close;
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->intercept_frame = pp_intercept_frame;
+ port->new_frame->draw = pp_draw;
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
-
+ input_api = &this->params_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "pped video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = pp_rewire;
- output->plugin = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
+ this->post.xine_post.video_input[0] = &port->new_port;
this->post.dispose = pp_dispose;
@@ -284,91 +249,24 @@ static void pp_class_dispose(post_class_t *class_gen)
static void pp_dispose(post_plugin_t *this_gen)
{
post_plugin_pp_t *this = (post_plugin_pp_t *)this_gen;
- post_pp_out_t *output = (post_pp_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (this->stream)
- port->close(port, this->stream);
-
- if(this->pp_mode) {
- pp_free_mode(this->pp_mode);
- this->pp_mode = NULL;
- }
-
- if(this->pp_context) {
- pp_free_context(this->pp_context);
- this->pp_context = NULL;
- }
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-
-static int pp_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_pp_out_t *output = (post_pp_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ if(this->pp_mode) {
+ pp_free_mode(this->pp_mode);
+ this->pp_mode = NULL;
+ }
+ if(this->pp_context) {
+ pp_free_context(this->pp_context);
+ this->pp_context = NULL;
+ }
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
-}
-
-static void pp_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_pp_t *this = (post_plugin_pp_t *)port->post;
- this->stream = stream;
- port->original_port->open(port->original_port, stream);
}
-static vo_frame_t *pp_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = pp_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
- return frame;
-}
-
-static void pp_close(xine_video_port_t *port_gen, xine_stream_t *stream)
+static int pp_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_pp_t *this = (post_plugin_pp_t *)port->post;
-
- this->stream = NULL;
-
- port->original_port->close(port->original_port, stream);
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
@@ -381,8 +279,6 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream)
int skip;
int pp_flags;
- _x_post_restore_video_frame(frame, port);
-
if( !frame->bad_frame ) {
/* convert to YV12 if needed */
@@ -391,9 +287,7 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream)
yv12_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
- yv12_frame->pts = frame->pts;
- yv12_frame->duration = frame->duration;
- _x_extra_info_merge(yv12_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, yv12_frame);
yuy2_to_yv12(frame->base[0], frame->pitches[0],
yv12_frame->base[0], yv12_frame->pitches[0],
@@ -409,10 +303,7 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream)
out_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
- _x_extra_info_merge(out_frame->extra_info, frame->extra_info);
-
- out_frame->pts = frame->pts;
- out_frame->duration = frame->duration;
+ _x_post_frame_copy_up(frame, out_frame);
pthread_mutex_lock (&this->lock);
@@ -451,18 +342,21 @@ static int pp_draw(vo_frame_t *frame, xine_stream_t *stream)
if(this->pp_mode) {
skip = out_frame->draw(out_frame, stream);
- frame->vpts = out_frame->vpts;
+ _x_post_frame_copy_down(frame, out_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
out_frame->free(out_frame);
yv12_frame->free(yv12_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
-
return skip;
}
diff --git a/src/post/planar/unsharp.c b/src/post/planar/unsharp.c
index f60530fb9..31359f500 100644
--- a/src/post/planar/unsharp.c
+++ b/src/post/planar/unsharp.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: unsharp.c,v 1.12 2003/12/07 15:33:26 miguelfreitas Exp $
+ * $Id: unsharp.c,v 1.13 2004/01/07 19:52:42 mroi Exp $
*
* mplayer's unsharp
* Copyright (C) 2002 Rémi Guyomarch <rguyom@pobox.com>
@@ -166,13 +166,11 @@ struct post_plugin_unsharp_s {
post_plugin_t post;
/* private data */
- xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
unsharp_parameters_t params;
+ xine_post_in_t params_input;
struct vf_priv_s priv;
- pthread_mutex_t lock;
+ pthread_mutex_t lock;
};
@@ -251,12 +249,6 @@ static xine_post_api_t post_api = {
get_help,
};
-typedef struct post_unsharp_out_s post_unsharp_out_t;
-struct post_unsharp_out_s {
- xine_post_out_t xine_out;
-
- post_plugin_unsharp_t *plugin;
-};
/* plugin class functions */
static post_plugin_t *unsharp_open_plugin(post_class_t *class_gen, int inputs,
@@ -269,15 +261,8 @@ static void unsharp_class_dispose(post_class_t *class_gen);
/* plugin instance functions */
static void unsharp_dispose(post_plugin_t *this_gen);
-/* rewire function */
-static int unsharp_rewire(xine_post_out_t *output, void *data);
-
-/* replaced video_port functions */
-static void unsharp_open(xine_video_port_t *port_gen, xine_stream_t *stream);
-static vo_frame_t *unsharp_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags);
-static void unsharp_close(xine_video_port_t *port_gen, xine_stream_t *stream);
+/* frame intercept check */
+static int unsharp_intercept_frame(post_video_port_t *port, vo_frame_t *frame);
/* replaced vo_frame functions */
static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream);
@@ -304,21 +289,18 @@ static post_plugin_t *unsharp_open_plugin(post_class_t *class_gen, int inputs,
xine_video_port_t **video_target)
{
post_plugin_unsharp_t *this = (post_plugin_unsharp_t *)xine_xmalloc(sizeof(post_plugin_unsharp_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- xine_post_in_t *input_api = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_unsharp_out_t *output = (post_unsharp_out_t *)malloc(sizeof(post_unsharp_out_t));
- post_video_port_t *port;
+ post_in_t *input;
+ xine_post_in_t *input_api;
+ post_out_t *output;
+ post_video_port_t *port;
- if (!this || !input || !input_api || !output || !video_target || !video_target[0]) {
+ if (!this || !video_target || !video_target[0]) {
free(this);
- free(input);
- free(input_api);
- free(output);
return NULL;
}
- this->stream = NULL;
-
+ _x_post_init(&this->post, 0, 1);
+
this->params.luma_matrix_width = 5;
this->params.luma_matrix_height = 5;
this->params.luma_amount = 0.0;
@@ -329,39 +311,21 @@ static post_plugin_t *unsharp_open_plugin(post_class_t *class_gen, int inputs,
pthread_mutex_init (&this->lock, NULL);
- port = _x_post_intercept_video_port(&this->post, video_target[0]);
- /* replace with our own get_frame function */
- port->port.open = unsharp_open;
- port->port.get_frame = unsharp_get_frame;
- port->port.close = unsharp_close;
+ port = _x_post_intercept_video_port(&this->post, video_target[0], &input, &output);
+ port->intercept_frame = unsharp_intercept_frame;
+ port->new_frame->draw = unsharp_draw;
- input->name = "video";
- input->type = XINE_POST_DATA_VIDEO;
- input->data = (xine_video_port_t *)&port->port;
-
+ input_api = &this->params_input;
input_api->name = "parameters";
input_api->type = XINE_POST_DATA_PARAMETERS;
input_api->data = &post_api;
+ xine_list_append_content(this->post.input, input_api);
+ input->xine_in.name = "video";
output->xine_out.name = "unsharped video";
- output->xine_out.type = XINE_POST_DATA_VIDEO;
- output->xine_out.data = (xine_video_port_t **)&port->original_port;
- output->xine_out.rewire = unsharp_rewire;
- output->plugin = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *));
- this->post.xine_post.audio_input[0] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 2);
- this->post.xine_post.video_input[0] = &port->port;
- this->post.xine_post.video_input[1] = NULL;
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
+ this->post.xine_post.video_input[0] = &port->new_port;
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.input, input_api);
- xine_list_append_content(this->post.output, output);
-
set_parameters ((xine_post_t *)this, &this->params);
this->post.dispose = unsharp_dispose;
@@ -407,86 +371,20 @@ static void unsharp_free_SC(post_plugin_unsharp_t *this)
static void unsharp_dispose(post_plugin_t *this_gen)
{
post_plugin_unsharp_t *this = (post_plugin_unsharp_t *)this_gen;
- post_unsharp_out_t *output = (post_unsharp_out_t *)xine_list_first_content(this->post.output);
- xine_video_port_t *port = *(xine_video_port_t **)output->xine_out.data;
-
- if (this->stream)
- port->close(port, this->stream);
-
- unsharp_free_SC(this);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_next_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- free(this);
-}
-
-static int unsharp_rewire(xine_post_out_t *output_gen, void *data)
-{
- post_unsharp_out_t *output = (post_unsharp_out_t *)output_gen;
- xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
- xine_video_port_t *new_port = (xine_video_port_t *)data;
-
- if (!data)
- return 0;
-
- if (output->plugin->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, output->plugin->stream);
- new_port->open(new_port, output->plugin->stream);
+ if (_x_post_dispose(this_gen)) {
+ unsharp_free_SC(this);
+ pthread_mutex_destroy(&this->lock);
+ free(this);
}
- /* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
-
- return 1;
}
-static void unsharp_open(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_unsharp_t *this = (post_plugin_unsharp_t *)port->post;
- this->stream = stream;
- port->original_port->open(port->original_port, stream);
-}
-static vo_frame_t *unsharp_get_frame(xine_video_port_t *port_gen, uint32_t width,
- uint32_t height, double ratio,
- int format, int flags)
+static int unsharp_intercept_frame(post_video_port_t *port, vo_frame_t *frame)
{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- vo_frame_t *frame;
-
- frame = port->original_port->get_frame(port->original_port,
- width, height, ratio, format, flags);
-
- _x_post_intercept_video_frame(frame, port);
- if( format == XINE_IMGFMT_YV12 || format == XINE_IMGFMT_YUY2 ) {
- /* replace with our own draw function */
- frame->draw = unsharp_draw;
- /* decoders should not copy the frames, since they won't be displayed */
- frame->proc_slice = NULL;
- frame->proc_frame = NULL;
- }
-
- return frame;
+ return (frame->format == XINE_IMGFMT_YV12 || frame->format == XINE_IMGFMT_YUY2);
}
-static void unsharp_close(xine_video_port_t *port_gen, xine_stream_t *stream)
-{
- post_video_port_t *port = (post_video_port_t *)port_gen;
- post_plugin_unsharp_t *this = (post_plugin_unsharp_t *)port->post;
-
- this->stream = NULL;
-
- port->original_port->close(port->original_port, stream);
-}
-
-
static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream)
{
@@ -496,8 +394,6 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream)
vo_frame_t *yv12_frame;
int skip;
- _x_post_restore_video_frame(frame, port);
-
if( !frame->bad_frame &&
(this->priv.lumaParam.amount || this->priv.chromaParam.amount) ) {
@@ -508,9 +404,7 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream)
yv12_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
- yv12_frame->pts = frame->pts;
- yv12_frame->duration = frame->duration;
- _x_extra_info_merge(yv12_frame->extra_info, frame->extra_info);
+ _x_post_frame_copy_up(frame, yv12_frame);
yuy2_to_yv12(frame->base[0], frame->pitches[0],
yv12_frame->base[0], yv12_frame->pitches[0],
@@ -527,11 +421,7 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream)
out_frame = port->original_port->get_frame(port->original_port,
frame->width, frame->height, frame->ratio, XINE_IMGFMT_YV12, frame->flags | VO_BOTH_FIELDS);
-
- _x_extra_info_merge(out_frame->extra_info, frame->extra_info);
-
- out_frame->pts = frame->pts;
- out_frame->duration = frame->duration;
+ _x_post_frame_copy_up(frame, out_frame);
pthread_mutex_lock (&this->lock);
@@ -565,15 +455,16 @@ static int unsharp_draw(vo_frame_t *frame, xine_stream_t *stream)
skip = out_frame->draw(out_frame, stream);
- frame->vpts = out_frame->vpts;
+ _x_post_frame_copy_down(frame, out_frame);
out_frame->free(out_frame);
yv12_frame->free(yv12_frame);
} else {
- skip = frame->draw(frame, stream);
+ _x_post_frame_copy_up(frame, frame->next);
+ skip = frame->next->draw(frame->next, stream);
+ _x_post_frame_copy_down(frame, frame->next);
}
-
return skip;
}
diff --git a/src/post/visualizations/fftgraph.c b/src/post/visualizations/fftgraph.c
index 40a667621..2105b646b 100644
--- a/src/post/visualizations/fftgraph.c
+++ b/src/post/visualizations/fftgraph.c
@@ -20,7 +20,7 @@
* FftGraph Visualization Post Plugin For xine
* by Thibaut Mattern (tmattern@noos.fr)
*
- * $Id: fftgraph.c,v 1.8 2003/12/03 10:52:41 andruil Exp $
+ * $Id: fftgraph.c,v 1.9 2004/01/07 19:52:42 mroi Exp $
*
*/
@@ -61,7 +61,7 @@ struct post_plugin_fftgraph_s {
/* private data */
xine_video_port_t *vo_port;
- xine_stream_t *stream;
+ post_out_t video_output;
/* private metronom for syncing the video */
metronom_t *metronom;
@@ -72,10 +72,7 @@ struct post_plugin_fftgraph_s {
complex_t wave[MAXCHANNELS][NUMSAMPLES];
audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */
- int bits;
- int mode;
int channels;
- int sample_rate;
int sample_counter;
int samples_per_frame;
@@ -189,47 +186,20 @@ static void draw_fftgraph(post_plugin_fftgraph_t *this, vo_frame_t *frame) {
* xine video post plugin functions
*************************************************************************/
-typedef struct post_fftgraph_out_s post_fftgraph_out_t;
-struct post_fftgraph_out_s {
- xine_post_out_t out;
- post_plugin_fftgraph_t *post;
-};
-
-static int fftgraph_rewire_audio(xine_post_out_t *output_gen, void *data)
-{
- post_fftgraph_out_t *output = (post_fftgraph_out_t *)output_gen;
- xine_audio_port_t *old_port = *(xine_audio_port_t **)output_gen->data;
- xine_audio_port_t *new_port = (xine_audio_port_t *)data;
- post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)output->post;
-
- if (!data)
- return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream, this->bits, this->sample_rate, this->mode);
- }
- /* reconnect ourselves */
- *(xine_audio_port_t **)output_gen->data = new_port;
- return 1;
-}
-
static int fftgraph_rewire_video(xine_post_out_t *output_gen, void *data)
{
- post_fftgraph_out_t *output = (post_fftgraph_out_t *)output_gen;
+ post_out_t *output = (post_out_t *)output_gen;
xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
xine_video_port_t *new_port = (xine_video_port_t *)data;
post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)output->post;
if (!data)
return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream);
- }
+ /* register our stream at the new output port */
+ old_port->close(old_port, NULL);
+ new_port->open(new_port, NULL);
/* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
+ this->vo_port = new_port;
return 1;
}
@@ -244,19 +214,27 @@ static int fftgraph_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream
/* printf("fftgraph_port_open, port_gen=%p, stream=%p, this=%p\n", port_gen, stream, this); */
+ _x_post_rewire_audio(port);
+ _x_post_inc_usage(port);
+
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+
this->ratio = (double)FFTGRAPH_WIDTH / (double)FFTGRAPH_HEIGHT;
- this->bits = bits;
- this->mode = mode;
this->channels = _x_ao_mode2channels(mode);
if( this->channels > MAXCHANNELS )
this->channels = MAXCHANNELS;
this->lines_per_channel = FFTGRAPH_HEIGHT / this->channels;
this->samples_per_frame = rate / FPS;
- this->sample_rate = rate;
- this->stream = stream;
this->data_idx = 0;
+ this->vo_port->open(this->vo_port, NULL);
this->metronom->set_master(this->metronom, stream->metronom);
this->fft = fft_new(FFT_BITS);
@@ -316,13 +294,17 @@ static void fftgraph_port_close(xine_audio_port_t *port_gen, xine_stream_t *stre
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)port->post;
- this->stream = NULL;
+ port->stream = NULL;
+
fft_dispose(this->fft);
this->fft = NULL;
+ this->vo_port->close(this->vo_port, NULL);
this->metronom->set_master(this->metronom, NULL);
port->original_port->close(port->original_port, stream );
+
+ _x_post_dec_usage(port);
}
static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen,
@@ -343,7 +325,7 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen,
this->buf.mem_size = buf->mem_size;
}
memcpy(this->buf.mem, buf->mem,
- buf->num_frames*this->channels*((this->bits == 8)?1:2));
+ buf->num_frames*this->channels*((port->bits == 8)?1:2));
this->buf.num_frames = buf->num_frames;
/* pass data to original port */
@@ -358,7 +340,7 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen,
do {
- if( this->bits == 8 ) {
+ if( port->bits == 8 ) {
data8 = (int8_t *)buf->mem;
data8 += samples_used * this->channels;
@@ -394,7 +376,7 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen,
VO_BOTH_FIELDS);
frame->extra_info->invalid = 1;
frame->bad_frame = 0;
- frame->duration = 90000 * this->samples_per_frame / this->sample_rate;
+ frame->duration = 90000 * this->samples_per_frame / port->rate;
frame->pts = pts;
this->metronom->got_video_frame(this->metronom, frame);
@@ -411,23 +393,15 @@ static void fftgraph_port_put_buffer (xine_audio_port_t *port_gen,
static void fftgraph_dispose(post_plugin_t *this_gen)
{
post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)this_gen;
- xine_post_out_t *output = (xine_post_out_t *)xine_list_last_content(this_gen->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->data;
-
- this->metronom->exit(this->metronom);
-
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- if(this->buf.mem)
- free(this->buf.mem);
- free(this);
+
+ if (_x_post_dispose(this_gen)) {
+
+ this->metronom->exit(this->metronom);
+
+ if(this->buf.mem)
+ free(this->buf.mem);
+ free(this);
+ }
}
/* plugin class functions */
@@ -435,64 +409,39 @@ static post_plugin_t *fftgraph_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_class_fftgraph_t *class = (post_class_fftgraph_t *)class_gen;
- post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)malloc(sizeof(post_plugin_fftgraph_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_fftgraph_out_t *output = (post_fftgraph_out_t *)malloc(sizeof(post_fftgraph_out_t));
- post_fftgraph_out_t *outputv = (post_fftgraph_out_t *)malloc(sizeof(post_fftgraph_out_t));
- post_audio_port_t *port;
-
- if (!this || !input || !output || !outputv || !video_target || !video_target[0] ||
- !audio_target || !audio_target[0] ) {
+ post_class_fftgraph_t *class = (post_class_fftgraph_t *)class_gen;
+ post_plugin_fftgraph_t *this = (post_plugin_fftgraph_t *)xine_xmalloc(sizeof(post_plugin_fftgraph_t));
+ post_in_t *input;
+ post_out_t *output;
+ post_out_t *outputv;
+ post_audio_port_t *port;
+
+ if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0] ) {
free(this);
- free(input);
- free(output);
- free(outputv);
return NULL;
}
+ _x_post_init(&this->post, 1, 0);
+
this->metronom = _x_metronom_init(1, 0, class->xine);
- this->sample_counter = 0;
- this->stream = NULL;
this->vo_port = video_target[0];
- this->buf.mem = NULL;
- this->buf.mem_size = 0;
-
- port = _x_post_intercept_audio_port(&this->post, audio_target[0]);
- port->port.open = fftgraph_port_open;
- port->port.close = fftgraph_port_close;
- port->port.put_buffer = fftgraph_port_put_buffer;
-
- input->name = "audio in";
- input->type = XINE_POST_DATA_AUDIO;
- input->data = (xine_audio_port_t *)&port->port;
-
- output->out.name = "audio out";
- output->out.type = XINE_POST_DATA_AUDIO;
- output->out.data = (xine_audio_port_t **)&port->original_port;
- output->out.rewire = fftgraph_rewire_audio;
- output->post = this;
-
- outputv->out.name = "generated video";
- outputv->out.type = XINE_POST_DATA_VIDEO;
- outputv->out.data = (xine_video_port_t **)&this->vo_port;
- outputv->out.rewire = fftgraph_rewire_video;
- outputv->post = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *) * 2);
- this->post.xine_post.audio_input[0] = &port->port;
- this->post.xine_post.audio_input[1] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 1);
- this->post.xine_post.video_input[0] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.output, output);
+
+ port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output);
+ port->new_port.open = fftgraph_port_open;
+ port->new_port.close = fftgraph_port_close;
+ port->new_port.put_buffer = fftgraph_port_put_buffer;
+
+ outputv = &this->video_output;
+ outputv->xine_out.name = "generated video";
+ outputv->xine_out.type = XINE_POST_DATA_VIDEO;
+ outputv->xine_out.data = (xine_video_port_t **)&this->vo_port;
+ outputv->xine_out.rewire = fftgraph_rewire_video;
+ outputv->post = &this->post;
xine_list_append_content(this->post.output, outputv);
+ this->post.xine_post.audio_input[0] = &port->new_port;
+
this->post.dispose = fftgraph_dispose;
return &this->post;
diff --git a/src/post/visualizations/fftscope.c b/src/post/visualizations/fftscope.c
index 4113d4d7d..b2d4e4770 100644
--- a/src/post/visualizations/fftscope.c
+++ b/src/post/visualizations/fftscope.c
@@ -22,7 +22,7 @@
*
* FFT code by Steve Haehnichen, originally licensed under GPL v1
*
- * $Id: fftscope.c,v 1.23 2003/12/13 23:01:45 tmmm Exp $
+ * $Id: fftscope.c,v 1.24 2004/01/07 19:52:42 mroi Exp $
*
*/
@@ -51,9 +51,9 @@ typedef struct post_plugin_fftscope_s post_plugin_fftscope_t;
typedef struct post_class_fftscope_s post_class_fftscope_t;
struct post_class_fftscope_s {
- post_class_t post_class;
-
- xine_t *xine;
+ post_class_t post_class;
+
+ xine_t *xine;
};
struct post_plugin_fftscope_s {
@@ -61,8 +61,8 @@ struct post_plugin_fftscope_s {
/* private data */
xine_video_port_t *vo_port;
- xine_stream_t *stream;
-
+ post_out_t video_output;
+
/* private metronom for syncing the video */
metronom_t *metronom;
@@ -77,10 +77,7 @@ struct post_plugin_fftscope_s {
int amp_age[MAXCHANNELS][NUMSAMPLES / 2];
audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */
- int bits;
- int mode;
int channels;
- int sample_rate;
int sample_counter;
int samples_per_frame;
@@ -253,47 +250,20 @@ static void draw_fftscope(post_plugin_fftscope_t *this, vo_frame_t *frame) {
* xine video post plugin functions
*************************************************************************/
-typedef struct post_fftscope_out_s post_fftscope_out_t;
-struct post_fftscope_out_s {
- xine_post_out_t out;
- post_plugin_fftscope_t *post;
-};
-
-static int fftscope_rewire_audio(xine_post_out_t *output_gen, void *data)
-{
- post_fftscope_out_t *output = (post_fftscope_out_t *)output_gen;
- xine_audio_port_t *old_port = *(xine_audio_port_t **)output_gen->data;
- xine_audio_port_t *new_port = (xine_audio_port_t *)data;
- post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)output->post;
-
- if (!data)
- return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream, this->bits, this->sample_rate, this->mode);
- }
- /* reconnect ourselves */
- *(xine_audio_port_t **)output_gen->data = new_port;
- return 1;
-}
-
static int fftscope_rewire_video(xine_post_out_t *output_gen, void *data)
{
- post_fftscope_out_t *output = (post_fftscope_out_t *)output_gen;
+ post_out_t *output = (post_out_t *)output_gen;
xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
xine_video_port_t *new_port = (xine_video_port_t *)data;
post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)output->post;
if (!data)
return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream);
- }
+ /* register our stream at the new output port */
+ old_port->close(old_port, NULL);
+ new_port->open(new_port, NULL);
/* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
+ this->vo_port = new_port;
return 1;
}
@@ -304,19 +274,27 @@ static int fftscope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream
post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)port->post;
int c, i;
+ _x_post_rewire_audio(port);
+ _x_post_inc_usage(port);
+
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+
this->ratio = (double)FFT_WIDTH/(double)FFT_HEIGHT;
- this->bits = bits;
- this->mode = mode;
this->channels = _x_ao_mode2channels(mode);
if( this->channels > MAXCHANNELS )
this->channels = MAXCHANNELS;
this->samples_per_frame = rate / FPS;
- this->sample_rate = rate;
- this->stream = stream;
this->data_idx = 0;
this->fft = fft_new(FFT_BITS);
+ this->vo_port->open(this->vo_port, NULL);
this->metronom->set_master(this->metronom, stream->metronom);
for (c = 0; c < this->channels; c++) {
@@ -337,21 +315,25 @@ static void fftscope_port_close(xine_audio_port_t *port_gen, xine_stream_t *stre
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)port->post;
- this->stream = NULL;
+ port->stream = NULL;
+
fft_dispose(this->fft);
this->fft = NULL;
+ this->vo_port->close(this->vo_port, NULL);
this->metronom->set_master(this->metronom, NULL);
port->original_port->close(port->original_port, stream );
+
+ _x_post_dec_usage(port);
}
static void fftscope_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;
+ post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)port->post;
- vo_frame_t *frame;
+ vo_frame_t *frame;
int16_t *data;
int8_t *data8;
int samples_used = 0;
@@ -364,7 +346,7 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen,
this->buf.mem_size = buf->mem_size;
}
memcpy(this->buf.mem, buf->mem,
- buf->num_frames*this->channels*((this->bits == 8)?1:2));
+ buf->num_frames*this->channels*((port->bits == 8)?1:2));
this->buf.num_frames = buf->num_frames;
/* pass data to original port */
@@ -379,7 +361,7 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen,
do {
- if( this->bits == 8 ) {
+ if( port->bits == 8 ) {
data8 = (int8_t *)buf->mem;
data8 += samples_used * this->channels;
@@ -415,7 +397,7 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen,
VO_BOTH_FIELDS);
frame->extra_info->invalid = 1;
frame->bad_frame = 0;
- frame->duration = 90000 * this->samples_per_frame / this->sample_rate;
+ frame->duration = 90000 * this->samples_per_frame / port->rate;
frame->pts = pts;
this->metronom->got_video_frame(this->metronom, frame);
@@ -432,23 +414,15 @@ static void fftscope_port_put_buffer (xine_audio_port_t *port_gen,
static void fftscope_dispose(post_plugin_t *this_gen)
{
post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)this_gen;
- xine_post_out_t *output = (xine_post_out_t *)xine_list_last_content(this_gen->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->data;
-
- this->metronom->exit(this->metronom);
-
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- if(this->buf.mem)
- free(this->buf.mem);
- free(this);
+
+ if (_x_post_dispose(this_gen)) {
+
+ this->metronom->exit(this->metronom);
+
+ if(this->buf.mem)
+ free(this->buf.mem);
+ free(this);
+ }
}
/* plugin class functions */
@@ -456,64 +430,39 @@ static post_plugin_t *fftscope_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_class_fftscope_t *class = (post_class_fftscope_t *)class_gen;
- post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)malloc(sizeof(post_plugin_fftscope_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_fftscope_out_t *output = (post_fftscope_out_t *)malloc(sizeof(post_fftscope_out_t));
- post_fftscope_out_t *outputv = (post_fftscope_out_t *)malloc(sizeof(post_fftscope_out_t));
- post_audio_port_t *port;
-
- if (!this || !input || !output || !outputv || !video_target || !video_target[0] ||
- !audio_target || !audio_target[0] ) {
+ post_plugin_fftscope_t *this = (post_plugin_fftscope_t *)xine_xmalloc(sizeof(post_plugin_fftscope_t));
+ post_class_fftscope_t *class = (post_class_fftscope_t *)class_gen;
+ post_in_t *input;
+ post_out_t *output;
+ post_out_t *outputv;
+ post_audio_port_t *port;
+
+ if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0] ) {
free(this);
- free(input);
- free(output);
- free(outputv);
return NULL;
}
+
+ _x_post_init(&this->post, 1, 0);
this->metronom = _x_metronom_init(1, 0, class->xine);
- this->sample_counter = 0;
- this->stream = NULL;
this->vo_port = video_target[0];
- this->buf.mem = NULL;
- this->buf.mem_size = 0;
-
- port = _x_post_intercept_audio_port(&this->post, audio_target[0]);
- port->port.open = fftscope_port_open;
- port->port.close = fftscope_port_close;
- port->port.put_buffer = fftscope_port_put_buffer;
-
- input->name = "audio in";
- input->type = XINE_POST_DATA_AUDIO;
- input->data = (xine_audio_port_t *)&port->port;
-
- output->out.name = "audio out";
- output->out.type = XINE_POST_DATA_AUDIO;
- output->out.data = (xine_audio_port_t **)&port->original_port;
- output->out.rewire = fftscope_rewire_audio;
- output->post = this;
-
- outputv->out.name = "generated video";
- outputv->out.type = XINE_POST_DATA_VIDEO;
- outputv->out.data = (xine_video_port_t **)&this->vo_port;
- outputv->out.rewire = fftscope_rewire_video;
- outputv->post = this;
-
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *) * 2);
- this->post.xine_post.audio_input[0] = &port->port;
- this->post.xine_post.audio_input[1] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 1);
- this->post.xine_post.video_input[0] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.output, output);
+
+ port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output);
+ port->new_port.open = fftscope_port_open;
+ port->new_port.close = fftscope_port_close;
+ port->new_port.put_buffer = fftscope_port_put_buffer;
+
+ outputv = &this->video_output;
+ outputv->xine_out.name = "generated video";
+ outputv->xine_out.type = XINE_POST_DATA_VIDEO;
+ outputv->xine_out.data = (xine_video_port_t **)&this->vo_port;
+ outputv->xine_out.rewire = fftscope_rewire_video;
+ outputv->post = &this->post;
xine_list_append_content(this->post.output, outputv);
+ this->post.xine_post.audio_input[0] = &port->new_port;
+
this->post.dispose = fftscope_dispose;
return &this->post;
diff --git a/src/post/visualizations/fooviz.c b/src/post/visualizations/fooviz.c
index bf5326a39..d72ee4354 100644
--- a/src/post/visualizations/fooviz.c
+++ b/src/post/visualizations/fooviz.c
@@ -23,7 +23,7 @@
* process. It simply paints the screen a solid color and rotates through
* colors on each iteration.
*
- * $Id: fooviz.c,v 1.18 2003/12/14 22:13:25 siggi Exp $
+ * $Id: fooviz.c,v 1.19 2004/01/07 19:52:42 mroi Exp $
*
*/
@@ -55,7 +55,7 @@ struct post_plugin_fooviz_s {
/* private data */
xine_video_port_t *vo_port;
- xine_stream_t *stream;
+ post_out_t video_output;
/* private metronom for syncing the video */
metronom_t *metronom;
@@ -66,10 +66,7 @@ struct post_plugin_fooviz_s {
short data [2][NUMSAMPLES];
audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */
- int bits;
- int mode;
int channels;
- int sample_rate;
int sample_counter;
int samples_per_frame;
@@ -86,47 +83,20 @@ struct post_plugin_fooviz_s {
* xine video post plugin functions
*************************************************************************/
-typedef struct post_fooviz_out_s post_fooviz_out_t;
-struct post_fooviz_out_s {
- xine_post_out_t out;
- post_plugin_fooviz_t *post;
-};
-
-static int fooviz_rewire_audio(xine_post_out_t *output_gen, void *data)
-{
- post_fooviz_out_t *output = (post_fooviz_out_t *)output_gen;
- xine_audio_port_t *old_port = *(xine_audio_port_t **)output_gen->data;
- xine_audio_port_t *new_port = (xine_audio_port_t *)data;
- post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)output->post;
-
- if (!data)
- return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream, this->bits, this->sample_rate, this->mode);
- }
- /* reconnect ourselves */
- *(xine_audio_port_t **)output_gen->data = new_port;
- return 1;
-}
-
static int fooviz_rewire_video(xine_post_out_t *output_gen, void *data)
{
- post_fooviz_out_t *output = (post_fooviz_out_t *)output_gen;
+ post_out_t *output = (post_out_t *)output_gen;
xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
xine_video_port_t *new_port = (xine_video_port_t *)data;
post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)output->post;
if (!data)
return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream);
- }
+ /* register our stream at the new output port */
+ old_port->close(old_port, NULL);
+ new_port->open(new_port, NULL);
/* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
+ this->vo_port = new_port;
return 1;
}
@@ -136,15 +106,23 @@ static int fooviz_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)port->post;
+ _x_post_rewire_audio(port);
+ _x_post_inc_usage(port);
+
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+
this->ratio = (double)FOO_WIDTH/(double)FOO_HEIGHT;
- this->bits = bits;
- this->mode = mode;
this->channels = _x_ao_mode2channels(mode);
this->samples_per_frame = rate / FPS;
- this->sample_rate = rate;
- this->stream = stream;
this->data_idx = 0;
+ this->vo_port->open(this->vo_port, NULL);
this->metronom->set_master(this->metronom, stream->metronom);
return port->original_port->open(port->original_port, stream, bits, rate, mode );
@@ -155,11 +133,14 @@ static void fooviz_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)port->post;
- this->stream = NULL;
+ port->stream = NULL;
+ this->vo_port->close(this->vo_port, NULL);
this->metronom->set_master(this->metronom, NULL);
port->original_port->close(port->original_port, stream );
+
+ _x_post_dec_usage(port);
}
static void fooviz_port_put_buffer (xine_audio_port_t *port_gen,
@@ -180,7 +161,7 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen,
this->buf.mem_size = buf->mem_size;
}
memcpy(this->buf.mem, buf->mem,
- buf->num_frames*this->channels*((this->bits == 8)?1:2));
+ buf->num_frames*this->channels*((port->bits == 8)?1:2));
this->buf.num_frames = buf->num_frames;
/* pass data to original port */
@@ -197,7 +178,7 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen,
do {
- if( this->bits == 8 ) {
+ if( port->bits == 8 ) {
data8 = (int8_t *)buf->mem;
data8 += samples_used * this->channels;
@@ -229,7 +210,7 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen,
VO_BOTH_FIELDS);
frame->extra_info->invalid = 1;
frame->bad_frame = 0;
- frame->duration = 90000 * this->samples_per_frame / this->sample_rate;
+ frame->duration = 90000 * this->samples_per_frame / port->rate;
frame->pts = pts;
this->metronom->got_video_frame(this->metronom, frame);
@@ -247,23 +228,15 @@ static void fooviz_port_put_buffer (xine_audio_port_t *port_gen,
static void fooviz_dispose(post_plugin_t *this_gen)
{
post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)this_gen;
- xine_post_out_t *output = (xine_post_out_t *)xine_list_last_content(this_gen->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->data;
- this->metronom->exit(this->metronom);
+ if (_x_post_dispose(this_gen)) {
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- if(this->buf.mem)
- free(this->buf.mem);
- free(this);
+ this->metronom->exit(this->metronom);
+
+ if(this->buf.mem)
+ free(this->buf.mem);
+ free(this);
+ }
}
/* plugin class functions */
@@ -271,64 +244,39 @@ static post_plugin_t *fooviz_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_class_fooviz_t *class = (post_class_fooviz_t *)class_gen;
- post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)malloc(sizeof(post_plugin_fooviz_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_fooviz_out_t *output = (post_fooviz_out_t *)malloc(sizeof(post_fooviz_out_t));
- post_fooviz_out_t *outputv = (post_fooviz_out_t *)malloc(sizeof(post_fooviz_out_t));
- post_audio_port_t *port;
+ post_class_fooviz_t *class = (post_class_fooviz_t *)class_gen;
+ post_plugin_fooviz_t *this = (post_plugin_fooviz_t *)xine_xmalloc(sizeof(post_plugin_fooviz_t));
+ post_in_t *input;
+ post_out_t *output;
+ post_out_t *outputv;
+ post_audio_port_t *port;
- if (!this || !input || !output || !outputv || !video_target || !video_target[0] ||
- !audio_target || !audio_target[0] ) {
+ if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0] ) {
free(this);
- free(input);
- free(output);
- free(outputv);
return NULL;
}
+ _x_post_init(&this->post, 1, 0);
+
this->metronom = _x_metronom_init(1, 0, class->xine);
- this->sample_counter = 0;
- this->stream = NULL;
this->vo_port = video_target[0];
- this->buf.mem = NULL;
- this->buf.mem_size = 0;
- port = _x_post_intercept_audio_port(&this->post, audio_target[0]);
- port->port.open = fooviz_port_open;
- port->port.close = fooviz_port_close;
- port->port.put_buffer = fooviz_port_put_buffer;
-
- input->name = "audio in";
- input->type = XINE_POST_DATA_AUDIO;
- input->data = (xine_audio_port_t *)&port->port;
-
- output->out.name = "audio out";
- output->out.type = XINE_POST_DATA_AUDIO;
- output->out.data = (xine_audio_port_t **)&port->original_port;
- output->out.rewire = fooviz_rewire_audio;
- output->post = this;
-
- outputv->out.name = "generated video";
- outputv->out.type = XINE_POST_DATA_VIDEO;
- outputv->out.data = (xine_video_port_t **)&this->vo_port;
- outputv->out.rewire = fooviz_rewire_video;
- outputv->post = this;
+ port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output);
+ port->new_port.open = fooviz_port_open;
+ port->new_port.close = fooviz_port_close;
+ port->new_port.put_buffer = fooviz_port_put_buffer;
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *) * 2);
- this->post.xine_post.audio_input[0] = &port->port;
- this->post.xine_post.audio_input[1] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 1);
- this->post.xine_post.video_input[0] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.output, output);
+ outputv = &this->video_output;
+ outputv->xine_out.name = "generated video";
+ outputv->xine_out.type = XINE_POST_DATA_VIDEO;
+ outputv->xine_out.data = (xine_video_port_t **)&this->vo_port;
+ outputv->xine_out.rewire = fooviz_rewire_video;
+ outputv->post = &this->post;
xine_list_append_content(this->post.output, outputv);
+ this->post.xine_post.audio_input[0] = &port->new_port;
+
this->post.dispose = fooviz_dispose;
return &this->post;
@@ -372,6 +320,6 @@ post_info_t fooviz_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST, 7, "fooviz", XINE_VERSION_CODE, &fooviz_special_info, &fooviz_init_plugin },
+ { PLUGIN_POST, 8, "fooviz", XINE_VERSION_CODE, &fooviz_special_info, &fooviz_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/post/visualizations/oscope.c b/src/post/visualizations/oscope.c
index 7b2427b83..658a56d28 100644
--- a/src/post/visualizations/oscope.c
+++ b/src/post/visualizations/oscope.c
@@ -20,7 +20,7 @@
* Basic Oscilloscope Visualization Post Plugin For xine
* by Mike Melanson (melanson@pcisys.net)
*
- * $Id: oscope.c,v 1.15 2003/12/03 10:52:41 andruil Exp $
+ * $Id: oscope.c,v 1.16 2004/01/07 19:52:42 mroi Exp $
*
*/
@@ -54,7 +54,7 @@ struct post_plugin_oscope_s {
/* private data */
xine_video_port_t *vo_port;
- xine_stream_t *stream;
+ post_out_t video_output;
/* private metronom for syncing the video */
metronom_t *metronom;
@@ -65,10 +65,7 @@ struct post_plugin_oscope_s {
short data [MAXCHANNELS][NUMSAMPLES];
audio_buffer_t buf; /* dummy buffer just to hold a copy of audio data */
- int bits;
- int mode;
int channels;
- int sample_rate;
int sample_counter;
int samples_per_frame;
@@ -157,47 +154,19 @@ static void draw_oscope_dots(post_plugin_oscope_t *this) {
* xine video post plugin functions
*************************************************************************/
-typedef struct post_oscope_out_s post_oscope_out_t;
-struct post_oscope_out_s {
- xine_post_out_t out;
- post_plugin_oscope_t *post;
-};
-
-static int oscope_rewire_audio(xine_post_out_t *output_gen, void *data)
-{
- post_oscope_out_t *output = (post_oscope_out_t *)output_gen;
- xine_audio_port_t *old_port = *(xine_audio_port_t **)output_gen->data;
- xine_audio_port_t *new_port = (xine_audio_port_t *)data;
- post_plugin_oscope_t *this = (post_plugin_oscope_t *)output->post;
-
- if (!data)
- return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream, this->bits, this->sample_rate, this->mode);
- }
- /* reconnect ourselves */
- *(xine_audio_port_t **)output_gen->data = new_port;
- return 1;
-}
-
static int oscope_rewire_video(xine_post_out_t *output_gen, void *data)
{
- post_oscope_out_t *output = (post_oscope_out_t *)output_gen;
+ post_out_t *output = (post_out_t *)output_gen;
xine_video_port_t *old_port = *(xine_video_port_t **)output_gen->data;
xine_video_port_t *new_port = (xine_video_port_t *)data;
post_plugin_oscope_t *this = (post_plugin_oscope_t *)output->post;
if (!data)
return 0;
- if (this->stream) {
- /* register our stream at the new output port */
- old_port->close(old_port, this->stream);
- new_port->open(new_port, this->stream);
- }
+ old_port->close(old_port, NULL);
+ new_port->open(new_port, NULL);
/* reconnect ourselves */
- *(xine_video_port_t **)output_gen->data = new_port;
+ this->vo_port = new_port;
return 1;
}
@@ -207,17 +176,27 @@ static int oscope_port_open(xine_audio_port_t *port_gen, xine_stream_t *stream,
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_oscope_t *this = (post_plugin_oscope_t *)port->post;
+ _x_post_rewire_audio(port);
+ _x_post_inc_usage(port);
+
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+
this->ratio = (double)OSCOPE_WIDTH/(double)OSCOPE_HEIGHT;
- this->bits = bits;
- this->mode = mode;
this->channels = _x_ao_mode2channels(mode);
+ if( this->channels > MAXCHANNELS )
+ this->channels = MAXCHANNELS;
this->samples_per_frame = rate / FPS;
- this->sample_rate = rate;
- this->stream = stream;
this->data_idx = 0;
init_yuv_planes(&this->yuv, OSCOPE_WIDTH, OSCOPE_HEIGHT);
+ this->vo_port->open(this->vo_port, NULL);
this->metronom->set_master(this->metronom, stream->metronom);
return port->original_port->open(port->original_port, stream, bits, rate, mode );
@@ -228,19 +207,22 @@ static void oscope_port_close(xine_audio_port_t *port_gen, xine_stream_t *stream
post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_oscope_t *this = (post_plugin_oscope_t *)port->post;
- this->stream = NULL;
+ port->stream = NULL;
+ this->vo_port->close(this->vo_port, NULL);
this->metronom->set_master(this->metronom, NULL);
port->original_port->close(port->original_port, stream );
+
+ _x_post_dec_usage(port);
}
static void oscope_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;
+ post_audio_port_t *port = (post_audio_port_t *)port_gen;
post_plugin_oscope_t *this = (post_plugin_oscope_t *)port->post;
- vo_frame_t *frame;
+ vo_frame_t *frame;
int16_t *data;
int8_t *data8;
int samples_used = 0;
@@ -253,7 +235,7 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen,
this->buf.mem_size = buf->mem_size;
}
memcpy(this->buf.mem, buf->mem,
- buf->num_frames*this->channels*((this->bits == 8)?1:2));
+ buf->num_frames*this->channels*((port->bits == 8)?1:2));
this->buf.num_frames = buf->num_frames;
/* pass data to original port */
@@ -268,7 +250,7 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen,
do {
- if( this->bits == 8 ) {
+ if( port->bits == 8 ) {
data8 = (int8_t *)buf->mem;
data8 += samples_used * this->channels;
@@ -298,7 +280,7 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen,
VO_BOTH_FIELDS);
frame->extra_info->invalid = 1;
frame->bad_frame = 0;
- frame->duration = 90000 * this->samples_per_frame / this->sample_rate;
+ frame->duration = 90000 * this->samples_per_frame / port->rate;
frame->pts = pts;
this->metronom->got_video_frame(this->metronom, frame);
@@ -317,23 +299,15 @@ static void oscope_port_put_buffer (xine_audio_port_t *port_gen,
static void oscope_dispose(post_plugin_t *this_gen)
{
post_plugin_oscope_t *this = (post_plugin_oscope_t *)this_gen;
- xine_post_out_t *output = (xine_post_out_t *)xine_list_last_content(this_gen->output);
- xine_video_port_t *port = *(xine_video_port_t **)output->data;
- this->metronom->exit(this->metronom);
+ if (_x_post_dispose(this_gen)) {
+
+ this->metronom->exit(this->metronom);
- if (this->stream)
- port->close(port, this->stream);
-
- free(this->post.xine_post.audio_input);
- free(this->post.xine_post.video_input);
- free(xine_list_first_content(this->post.input));
- free(xine_list_first_content(this->post.output));
- xine_list_free(this->post.input);
- xine_list_free(this->post.output);
- if(this->buf.mem)
- free(this->buf.mem);
- free(this);
+ if(this->buf.mem)
+ free(this->buf.mem);
+ free(this);
+ }
}
/* plugin class functions */
@@ -341,64 +315,39 @@ static post_plugin_t *oscope_open_plugin(post_class_t *class_gen, int inputs,
xine_audio_port_t **audio_target,
xine_video_port_t **video_target)
{
- post_class_oscope_t *class = (post_class_oscope_t *)class_gen;
- post_plugin_oscope_t *this = (post_plugin_oscope_t *)malloc(sizeof(post_plugin_oscope_t));
- xine_post_in_t *input = (xine_post_in_t *)malloc(sizeof(xine_post_in_t));
- post_oscope_out_t *output = (post_oscope_out_t *)malloc(sizeof(post_oscope_out_t));
- post_oscope_out_t *outputv = (post_oscope_out_t *)malloc(sizeof(post_oscope_out_t));
- post_audio_port_t *port;
+ post_class_oscope_t *class = (post_class_oscope_t *)class_gen;
+ post_plugin_oscope_t *this = (post_plugin_oscope_t *)xine_xmalloc(sizeof(post_plugin_oscope_t));
+ post_in_t *input;
+ post_out_t *output;
+ post_out_t *outputv;
+ post_audio_port_t *port;
- if (!this || !input || !output || !outputv || !video_target || !video_target[0] ||
- !audio_target || !audio_target[0] ) {
+ if (!this || !video_target || !video_target[0] || !audio_target || !audio_target[0] ) {
free(this);
- free(input);
- free(output);
- free(outputv);
return NULL;
}
+ _x_post_init(&this->post, 1, 0);
+
this->metronom = _x_metronom_init(1, 0, class->xine);
- this->sample_counter = 0;
- this->stream = NULL;
this->vo_port = video_target[0];
- this->buf.mem = NULL;
- this->buf.mem_size = 0;
- port = _x_post_intercept_audio_port(&this->post, audio_target[0]);
- port->port.open = oscope_port_open;
- port->port.close = oscope_port_close;
- port->port.put_buffer = oscope_port_put_buffer;
-
- input->name = "audio in";
- input->type = XINE_POST_DATA_AUDIO;
- input->data = (xine_audio_port_t *)&port->port;
-
- output->out.name = "audio out";
- output->out.type = XINE_POST_DATA_AUDIO;
- output->out.data = (xine_audio_port_t **)&port->original_port;
- output->out.rewire = oscope_rewire_audio;
- output->post = this;
-
- outputv->out.name = "generated video";
- outputv->out.type = XINE_POST_DATA_VIDEO;
- outputv->out.data = (xine_video_port_t **)&this->vo_port;
- outputv->out.rewire = oscope_rewire_video;
- outputv->post = this;
+ port = _x_post_intercept_audio_port(&this->post, audio_target[0], &input, &output);
+ port->new_port.open = oscope_port_open;
+ port->new_port.close = oscope_port_close;
+ port->new_port.put_buffer = oscope_port_put_buffer;
- this->post.xine_post.audio_input = (xine_audio_port_t **)malloc(sizeof(xine_audio_port_t *) * 2);
- this->post.xine_post.audio_input[0] = &port->port;
- this->post.xine_post.audio_input[1] = NULL;
- this->post.xine_post.video_input = (xine_video_port_t **)malloc(sizeof(xine_video_port_t *) * 1);
- this->post.xine_post.video_input[0] = NULL;
-
- this->post.input = xine_list_new();
- this->post.output = xine_list_new();
-
- xine_list_append_content(this->post.input, input);
- xine_list_append_content(this->post.output, output);
+ outputv = &this->video_output;
+ outputv->xine_out.name = "generated video";
+ outputv->xine_out.type = XINE_POST_DATA_VIDEO;
+ outputv->xine_out.data = (xine_video_port_t **)&this->vo_port;
+ outputv->xine_out.rewire = oscope_rewire_video;
+ outputv->post = &this->post;
xine_list_append_content(this->post.output, outputv);
+ this->post.xine_post.audio_input[0] = &port->new_port;
+
this->post.dispose = oscope_dispose;
return &this->post;
diff --git a/src/post/visualizations/visualizations.c b/src/post/visualizations/visualizations.c
index 64f17c570..92a5df1fa 100644
--- a/src/post/visualizations/visualizations.c
+++ b/src/post/visualizations/visualizations.c
@@ -19,7 +19,7 @@
*
* This file contains plugin entries for several visualization post plugins.
*
- * $Id: visualizations.c,v 1.9 2003/12/14 22:13:25 siggi Exp $
+ * $Id: visualizations.c,v 1.10 2004/01/07 19:52:42 mroi Exp $
*/
#ifdef HAVE_CONFIG_H
@@ -48,8 +48,8 @@ post_info_t fftgraph_special_info = { XINE_POST_TYPE_AUDIO_VISUALIZATION };
plugin_info_t xine_plugin_info[] = {
/* type, API, "name", version, special_info, init_function */
- { PLUGIN_POST, 7, "oscope", XINE_VERSION_CODE, &oscope_special_info, &oscope_init_plugin },
- { PLUGIN_POST, 7, "fftscope", XINE_VERSION_CODE, &fftscope_special_info, &fftscope_init_plugin },
- { PLUGIN_POST, 7, "fftgraph", XINE_VERSION_CODE, &fftgraph_special_info, &fftgraph_init_plugin },
+ { PLUGIN_POST, 8, "oscope", XINE_VERSION_CODE, &oscope_special_info, &oscope_init_plugin },
+ { PLUGIN_POST, 8, "fftscope", XINE_VERSION_CODE, &fftscope_special_info, &fftscope_init_plugin },
+ { PLUGIN_POST, 8, "fftgraph", XINE_VERSION_CODE, &fftgraph_special_info, &fftgraph_init_plugin },
{ PLUGIN_NONE, 0, "", 0, NULL, NULL }
};
diff --git a/src/xine-engine/audio_out.c b/src/xine-engine/audio_out.c
index 7654f7ecf..84caca40c 100644
--- a/src/xine-engine/audio_out.c
+++ b/src/xine-engine/audio_out.c
@@ -17,7 +17,7 @@
* along with self program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: audio_out.c,v 1.161 2004/01/01 14:20:52 mroi Exp $
+ * $Id: audio_out.c,v 1.162 2004/01/07 19:52:42 mroi Exp $
*
* 22-8-2001 James imported some useful AC3 sections from the previous alsa driver.
* (c) 2001 Andy Lo A Foe <andy@alsaplayer.org>
@@ -100,6 +100,8 @@
#define ZERO_BUF_SIZE 5000
+#define NULL_STREAM (xine_stream_t *)-1
+
/* By adding gap errors (difference between reported and expected
* sound card clock) into metronom's vpts_offset we can use its
* smoothing algorithms to correct sound card clock drifts.
@@ -1041,6 +1043,7 @@ static void *ao_loop (void *this_gen) {
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams); stream;
stream = xine_list_next_content(this->streams)) {
+ if (stream == NULL_STREAM) continue;
stream->metronom->set_option(stream->metronom, METRONOM_ADJ_VPTS_OFFSET,
-gap/SYNC_GAP_RATE );
last_sync_time = cur_time;
@@ -1116,37 +1119,31 @@ int xine_get_next_audio_frame (xine_audio_port_t *this_gen,
xine_audio_frame_t *frame) {
aos_t *this = (aos_t *) this_gen;
- audio_buffer_t *in_buf, *out_buf;
- xine_stream_t *stream;
+ audio_buffer_t *in_buf = NULL, *out_buf;
+ xine_stream_t *stream = NULL;
lprintf ("get_next_audio_frame\n");
- do {
+ while (!in_buf || !stream) {
stream = xine_list_first_content(this->streams);
- if (!stream)
- xine_usec_sleep (1000);
- } while( !stream );
+ if (!stream) {
+ xine_usec_sleep (5000);
+ continue;
+ }
- pthread_mutex_lock (&this->out_fifo->mutex);
-
- in_buf = this->out_fifo->first;
-
- /* FIXME: ugly, use conditions and locks instead */
-
- while (!in_buf
- && (stream->demux_plugin->get_status (stream->demux_plugin)==DEMUX_OK)) {
-
- pthread_mutex_unlock(&this->out_fifo->mutex);
- xine_usec_sleep (1000);
- pthread_mutex_lock(&this->out_fifo->mutex);
-
+ /* FIXME: ugly, use conditions and locks instead? */
+
+ pthread_mutex_lock (&this->out_fifo->mutex);
in_buf = this->out_fifo->first;
- }
-
- if (!in_buf) {
- pthread_mutex_unlock(&this->out_fifo->mutex);
- xprintf (this->xine, XINE_VERBOSITY_DEBUG, "audio_audio: EOS\n");
- return 0;
+ if (!in_buf) {
+ pthread_mutex_unlock(&this->out_fifo->mutex);
+ if (stream != NULL_STREAM && stream->audio_fifo->fifo_size == 0 &&
+ stream->demux_plugin->get_status(stream->demux_plugin) !=DEMUX_OK)
+ /* no further data can be expected here */
+ return 0;
+ xine_usec_sleep (5000);
+ continue;
+ }
}
in_buf = fifo_remove_int (this->out_fifo);
@@ -1303,24 +1300,27 @@ static int ao_open(xine_audio_port_t *this_gen, xine_stream_t *stream,
return 0;
}
- pthread_mutex_lock(&this->streams_lock);
- xine_list_append_content(this->streams, stream);
- pthread_mutex_unlock(&this->streams_lock);
-
/*
* set metainfo
*/
- channels = _x_ao_mode2channels( mode );
- if( channels == 0 )
- channels = 255; /* unknown */
+ if (stream) {
+ channels = _x_ao_mode2channels( mode );
+ if( channels == 0 )
+ channels = 255; /* unknown */
- _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_MODE, mode);
- _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_CHANNELS, channels);
- _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_BITS, bits);
- _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, rate);
+ _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_MODE, mode);
+ _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_CHANNELS, channels);
+ _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_BITS, bits);
+ _x_stream_info_set(stream, XINE_STREAM_INFO_AUDIO_SAMPLERATE, rate);
- stream->metronom->set_audio_rate(stream->metronom, this->audio_step);
+ stream->metronom->set_audio_rate(stream->metronom, this->audio_step);
+ }
+ if (stream == NULL) stream = NULL_STREAM;
+ pthread_mutex_lock(&this->streams_lock);
+ xine_list_append_content(this->streams, stream);
+ pthread_mutex_unlock(&this->streams_lock);
+
return this->output.rate;
}
@@ -1381,6 +1381,7 @@ static void ao_close(xine_audio_port_t *this_gen, xine_stream_t *stream) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "ao_close\n");
/* unregister stream */
+ if (stream == NULL) stream = NULL_STREAM;
pthread_mutex_lock(&this->streams_lock);
for (cur = xine_list_first_content(this->streams); cur;
cur = xine_list_next_content(this->streams))
diff --git a/src/xine-engine/audio_out.h b/src/xine-engine/audio_out.h
index bef0bd409..23591e60d 100644
--- a/src/xine-engine/audio_out.h
+++ b/src/xine-engine/audio_out.h
@@ -17,7 +17,7 @@
* 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_out.h,v 1.65 2003/12/31 23:29:06 jcdutton Exp $
+ * $Id: audio_out.h,v 1.66 2004/01/07 19:52:42 mroi Exp $
*/
#ifndef HAVE_AUDIO_OUT_H
#define HAVE_AUDIO_OUT_H
@@ -185,6 +185,8 @@ struct xine_audio_port_s {
/* open audio driver for audio output
* return value: 0:failure, >0:output sample rate
*/
+ /* when you are not a full-blown stream, but still need to open the port
+ * (e.g. you are a post plugin) it is legal to pass a NULL stream */
int (*open) (xine_audio_port_t *, xine_stream_t *stream,
uint32_t bits, uint32_t rate, int mode);
@@ -201,6 +203,8 @@ struct xine_audio_port_s {
void (*put_buffer) (xine_audio_port_t *, audio_buffer_t *buf, xine_stream_t *stream);
/* audio driver is no longer used by decoder => close */
+ /* when you are not a full-blown stream, but still need to close the port
+ * (e.g. you are a post plugin) it is legal to pass a NULL stream */
void (*close) (xine_audio_port_t *self, xine_stream_t *stream);
/* called on xine exit */
diff --git a/src/xine-engine/post.c b/src/xine-engine/post.c
index a5bb90afa..58771dbb9 100644
--- a/src/xine-engine/post.c
+++ b/src/xine-engine/post.c
@@ -17,152 +17,354 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: post.c,v 1.20 2003/12/09 00:02:36 f1rmb Exp $
+ * $Id: post.c,v 1.21 2004/01/07 19:52:43 mroi Exp $
*/
/*
* some helper functions for post plugins
*/
+#define POST_INTERNAL
+#define XINE_ENGINE_INTERNAL
+
#include "post.h"
#include <stdarg.h>
+
+void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_inputs) {
+ int audio_inputs_size = (num_audio_inputs + 1) * sizeof(xine_audio_port_t *);
+ int video_inputs_size = (num_video_inputs + 1) * sizeof(xine_video_port_t *);
+
+ post->input = xine_list_new();
+ post->output = xine_list_new();
+ post->xine_post.audio_input = (xine_audio_port_t **)xine_xmalloc(audio_inputs_size);
+ post->xine_post.video_input = (xine_video_port_t **)xine_xmalloc(video_inputs_size);
+}
+
+
/* dummy intercept functions that just pass the call on to the original port */
static uint32_t post_video_get_capabilities(xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->get_capabilities(port->original_port);
+ uint32_t caps;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ caps = port->original_port->get_capabilities(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return caps;
}
static void post_video_open(xine_video_port_t *port_gen, xine_stream_t *stream) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+
+ _x_post_rewire_video(port);
+ _x_post_inc_usage(port);
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->open(port->original_port, stream);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
}
static vo_frame_t *post_video_get_frame(xine_video_port_t *port_gen, uint32_t width,
uint32_t height, double ratio, int format, int flags) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->get_frame(port->original_port,
+ vo_frame_t *frame;
+
+ _x_post_rewire_video(port);
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ frame = port->original_port->get_frame(port->original_port,
width, height, ratio, format, flags);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+
+ if (frame && (!port->intercept_frame || port->intercept_frame(port, frame))) {
+ _x_post_inc_usage(port);
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ frame = _x_post_intercept_video_frame(frame, port);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
+ }
+
+ return frame;
}
static vo_frame_t *post_video_get_last_frame(xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->get_last_frame(port->original_port);
-}
+ vo_frame_t *frame;
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ frame = port->original_port->get_last_frame(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return frame;
+}
+
static void post_video_enable_ovl(xine_video_port_t *port_gen, int ovl_enable) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->enable_ovl(port->original_port, ovl_enable);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
}
static void post_video_close(xine_video_port_t *port_gen, xine_stream_t *stream) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->close(port->original_port, stream);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ port->stream = NULL;
+ _x_post_dec_usage(port);
}
static void post_video_exit(xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->exit(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
}
static video_overlay_manager_t *post_video_get_overlay_manager(xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->get_overlay_manager(port->original_port);
+ video_overlay_manager_t *manager;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ manager = port->original_port->get_overlay_manager(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+
+ if (port->intercept_ovl && port->intercept_ovl(port)) {
+ if (manager && !port->original_manager)
+ /* this is the first access to overlay manager */
+ _x_post_intercept_overlay_manager(manager, port);
+ else
+ /* the original port might have changed */
+ port->original_manager = manager;
+ return port->new_manager;
+ } else
+ return manager;
}
static void post_video_flush(xine_video_port_t *port_gen) {
post_video_port_t *port = (post_video_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->flush(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
}
static int post_video_status(xine_video_port_t *port_gen, xine_stream_t *stream,
int *width, int *height, int64_t *img_duration) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->status(port->original_port, stream, width, height, img_duration);
+ int status;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ status = port->original_port->status(port->original_port, stream, width, height, img_duration);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return status;
}
static int post_video_get_property(xine_video_port_t *port_gen, int property) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->get_property(port->original_port, property);
+ int prop;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ prop = port->original_port->get_property(port->original_port, property);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return prop;
}
static int post_video_set_property(xine_video_port_t *port_gen, int property, int value) {
post_video_port_t *port = (post_video_port_t *)port_gen;
- return port->original_port->set_property(port->original_port, property, value);
+ int val;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ val = port->original_port->set_property(port->original_port, property, value);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return val;
}
-post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *original) {
- post_video_port_t *post_port = (post_video_port_t *)malloc(sizeof(post_video_port_t));
+
+static int post_video_rewire(xine_post_out_t *output_gen, void *data) {
+ post_out_t *output = (post_out_t *)output_gen;
+ xine_video_port_t *new_port = (xine_video_port_t *)data;
+ post_video_port_t *input_port = (post_video_port_t *)output->user_data;
- if (!post_port)
+ if (!new_port)
+ return 0;
+ pthread_mutex_lock(&input_port->next_port_lock);
+ pthread_mutex_lock(&input_port->usage_lock);
+ input_port->next_port = new_port;
+ while (input_port->next_port) {
+ if (input_port->usage_count == 0) {
+ /* we can safely rewire right here, the plugin is not in use */
+ input_port->original_port = new_port;
+ input_port->next_port = NULL;
+ }
+ pthread_mutex_unlock(&input_port->usage_lock);
+ if (input_port->next_port)
+ pthread_cond_wait(&input_port->next_port_wire, &input_port->next_port_lock);
+ pthread_mutex_lock(&input_port->usage_lock);
+ }
+ pthread_mutex_unlock(&input_port->usage_lock);
+ pthread_mutex_unlock(&input_port->next_port_lock);
+ return 1;
+}
+
+
+post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *original,
+ post_in_t **input, post_out_t **output) {
+ post_video_port_t *port = (post_video_port_t *)xine_xmalloc(sizeof(post_video_port_t));
+
+ if (!port)
return NULL;
- post_port->port.get_capabilities = post_video_get_capabilities;
- post_port->port.open = post_video_open;
- post_port->port.get_frame = post_video_get_frame;
- post_port->port.get_last_frame = post_video_get_last_frame;
- post_port->port.enable_ovl = post_video_enable_ovl;
- post_port->port.close = post_video_close;
- post_port->port.exit = post_video_exit;
- post_port->port.get_overlay_manager = post_video_get_overlay_manager;
- post_port->port.flush = post_video_flush;
- post_port->port.status = post_video_status;
- post_port->port.get_property = post_video_get_property;
- post_port->port.set_property = post_video_set_property;
- post_port->port.driver = original->driver;
+ port->new_port.get_capabilities = post_video_get_capabilities;
+ port->new_port.open = post_video_open;
+ port->new_port.get_frame = post_video_get_frame;
+ port->new_port.get_last_frame = post_video_get_last_frame;
+ port->new_port.enable_ovl = post_video_enable_ovl;
+ port->new_port.close = post_video_close;
+ port->new_port.exit = post_video_exit;
+ port->new_port.get_overlay_manager = post_video_get_overlay_manager;
+ port->new_port.flush = post_video_flush;
+ port->new_port.status = post_video_status;
+ port->new_port.get_property = post_video_get_property;
+ port->new_port.set_property = post_video_set_property;
+ port->new_port.driver = original->driver;
+
+ port->original_port = original;
+ port->new_frame = &port->frame_storage;
+ port->new_manager = &port->manager_storage;
+ port->post = post;
+
+ pthread_mutex_init(&port->next_port_lock, NULL);
+ pthread_cond_init(&port->next_port_wire, NULL);
+ pthread_mutex_init(&port->usage_lock, NULL);
+ pthread_mutex_init(&port->free_frames_lock, NULL);
- post_port->original_port = original;
- post_port->post = post;
+ if (input) {
+ *input = (post_in_t *)xine_xmalloc(sizeof(post_in_t));
+ if (!*input) return port;
+ (*input)->xine_in.name = "video in";
+ (*input)->xine_in.type = XINE_POST_DATA_VIDEO;
+ (xine_video_port_t *)(*input)->xine_in.data = &port->new_port;
+ (*input)->post = post;
+ xine_list_append_content(post->input, *input);
+ }
- return post_port;
+ if (output) {
+ *output = (post_out_t *)xine_xmalloc(sizeof(post_out_t));
+ if (!*output) return port;
+ (*output)->xine_out.name = "video out";
+ (*output)->xine_out.type = XINE_POST_DATA_VIDEO;
+ (xine_video_port_t **)(*output)->xine_out.data = &port->original_port;
+ (*output)->xine_out.rewire = post_video_rewire;
+ (*output)->post = post;
+ (*output)->user_data = port;
+ xine_list_append_content(post->output, *output);
+ }
+
+ return port;
+}
+
+
+void _x_post_rewire_video(post_video_port_t *port) {
+ if (port->next_port) {
+ pthread_mutex_lock(&port->next_port_lock);
+ if (port->next_port) {
+ port->next_port->open(port->next_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream);
+ port->original_port->close(port->original_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream);
+ port->original_port = port->next_port;
+ port->next_port = NULL;
+ pthread_mutex_unlock(&port->next_port_lock);
+ pthread_cond_broadcast(&port->next_port_wire);
+ } else
+ pthread_mutex_unlock(&port->next_port_lock);
+ }
}
/* dummy intercept functions for frames */
static void post_frame_free(vo_frame_t *vo_img) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- _x_post_restore_video_frame(vo_img, port);
- vo_img->free(vo_img);
-}
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ if (--vo_img->lock_counter == 0) {
+ /* this frame is free */
+ vo_img = _x_post_restore_video_frame(vo_img, port);
+ vo_img->free(vo_img);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
+ _x_post_dec_usage(port);
+ } else {
+ /* this frame is still in use */
+ _x_post_frame_copy_up(vo_img, vo_img->next);
+ vo_img->next->free(vo_img->next);
+ _x_post_frame_copy_down(vo_img, vo_img->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
+ }
+}
+
static void post_frame_proc_slice(vo_frame_t *vo_img, uint8_t **src) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- vo_img->port = port->original_port;
- port->original_frame.proc_slice(vo_img, src);
- vo_img->port = &port->port;
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ _x_post_frame_copy_up(vo_img, vo_img->next);
+ vo_img->next->proc_slice(vo_img->next, src);
+ _x_post_frame_copy_down(vo_img, vo_img->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
}
static void post_frame_proc_frame(vo_frame_t *vo_img) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- vo_img->port = port->original_port;
- port->original_frame.proc_frame(vo_img);
- vo_img->port = &port->port;
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ _x_post_frame_copy_up(vo_img, vo_img->next);
+ vo_img->next->proc_frame(vo_img->next);
+ _x_post_frame_copy_down(vo_img, vo_img->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
}
static void post_frame_field(vo_frame_t *vo_img, int which_field) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- vo_img->port = port->original_port;
- port->original_frame.field(vo_img, which_field);
- vo_img->port = &port->port;
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ _x_post_frame_copy_up(vo_img, vo_img->next);
+ vo_img->next->field(vo_img->next, which_field);
+ _x_post_frame_copy_down(vo_img, vo_img->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
}
static int post_frame_draw(vo_frame_t *vo_img, xine_stream_t *stream) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- _x_post_restore_video_frame(vo_img, port);
- return vo_img->draw(vo_img, stream);
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+ int skip;
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ _x_post_frame_copy_up(vo_img, vo_img->next);
+ skip = vo_img->next->draw(vo_img->next, stream);
+ _x_post_frame_copy_down(vo_img, vo_img->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
+ return skip;
}
static void post_frame_lock(vo_frame_t *vo_img) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- vo_img->port = port->original_port;
- port->original_frame.lock(vo_img);
- vo_img->port = &port->port;
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ _x_post_frame_copy_up(vo_img, vo_img->next);
+ vo_img->lock_counter++;
+ vo_img->next->lock(vo_img->next);
+ _x_post_frame_copy_down(vo_img, vo_img->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
}
static void post_frame_dispose(vo_frame_t *vo_img) {
- post_video_port_t *port = (post_video_port_t *)vo_img->port;
- _x_post_restore_video_frame(vo_img, port);
+ post_video_port_t *port = _x_post_video_frame_to_port(vo_img);
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ vo_img = _x_post_restore_video_frame(vo_img, port);
vo_img->dispose(vo_img);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
+ _x_post_dec_usage(port);
}
static void post_frame_proc_macro_block(int x,
@@ -180,164 +382,308 @@ static void post_frame_proc_macro_block(int x,
int second_field,
int (*f_mot_pmv)[2],
int (*b_mot_pmv)[2]) {
- post_video_port_t *port = (post_video_port_t *)current_frame->port;
- _x_post_restore_video_frame(current_frame, port);
- _x_post_restore_video_frame(forward_ref_frame, port);
- _x_post_restore_video_frame(backward_ref_frame, port);
- current_frame->proc_macro_block(x, y, mb_type, motion_type, mv_field_sel,
- dmvector, cbp, dct_type, current_frame,
- forward_ref_frame, backward_ref_frame,
- picture_structure, second_field,
- f_mot_pmv, b_mot_pmv);
-}
-
-
-
-void _x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {
- port->original_frame.port = frame->port;
- port->original_frame.free = frame->free;
- port->original_frame.proc_slice = frame->proc_slice;
- port->original_frame.proc_frame = frame->proc_frame;
- port->original_frame.proc_macro_block = frame->proc_macro_block;
- port->original_frame.field = frame->field;
- port->original_frame.draw = frame->draw;
- port->original_frame.lock = frame->lock;
- port->original_frame.dispose = frame->dispose;
-
- frame->port = &port->port;
- frame->free = post_frame_free;
- frame->proc_slice = frame->proc_slice ? post_frame_proc_slice : NULL;
- frame->proc_frame = frame->proc_frame ? post_frame_proc_frame : NULL;
- frame->proc_macro_block = frame->proc_macro_block ? post_frame_proc_macro_block : NULL;
- frame->field = post_frame_field;
- frame->draw = post_frame_draw;
- frame->lock = post_frame_lock;
- frame->dispose = post_frame_dispose;
-}
-
-void _x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) {
- frame->port = port->original_port;
- frame->free = port->original_frame.free;
- frame->proc_slice = port->original_frame.proc_slice;
- frame->proc_frame = port->original_frame.proc_frame;
- frame->proc_macro_block = port->original_frame.proc_macro_block;
- frame->field = port->original_frame.field;
- frame->draw = port->original_frame.draw;
- frame->lock = port->original_frame.lock;
- frame->dispose = port->original_frame.dispose;
+ post_video_port_t *port = _x_post_video_frame_to_port(current_frame);
+
+ if (port->frame_lock) pthread_mutex_lock(port->frame_lock);
+ _x_post_frame_copy_up(current_frame, current_frame->next);
+ current_frame->next->proc_macro_block(x, y, mb_type, motion_type, mv_field_sel,
+ dmvector, cbp, dct_type, current_frame->next,
+ forward_ref_frame, backward_ref_frame,
+ picture_structure, second_field,
+ f_mot_pmv, b_mot_pmv);
+ _x_post_frame_copy_down(current_frame, current_frame->next);
+ if (port->frame_lock) pthread_mutex_unlock(port->frame_lock);
+}
+
+
+vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port) {
+ vo_frame_t *new_frame;
+
+ /* get a free frame slot */
+ pthread_mutex_lock(&port->free_frames_lock);
+ if (port->free_frame_slots) {
+ new_frame = port->free_frame_slots;
+ port->free_frame_slots = new_frame->next;
+ } else {
+ new_frame = (vo_frame_t *)xine_xmalloc(sizeof(vo_frame_t));
+ }
+ pthread_mutex_unlock(&port->free_frames_lock);
+
+ /* make a copy and attach the original */
+ xine_fast_memcpy(new_frame, frame, sizeof(vo_frame_t));
+ new_frame->next = frame;
+
+ /* modify the frame with the intercept functions */
+ new_frame->port = &port->new_port;
+ new_frame->proc_frame =
+ port->new_frame->proc_frame ? port->new_frame->proc_frame : NULL;
+ new_frame->proc_slice =
+ port->new_frame->proc_slice ? port->new_frame->proc_slice : NULL;
+ new_frame->proc_macro_block =
+ port->new_frame->proc_macro_block ? port->new_frame->proc_macro_block : NULL;
+ new_frame->field =
+ port->new_frame->field ? port->new_frame->field : post_frame_field;
+ new_frame->draw =
+ port->new_frame->draw ? port->new_frame->draw : post_frame_draw;
+ new_frame->lock =
+ port->new_frame->lock ? port->new_frame->lock : post_frame_lock;
+ new_frame->free =
+ port->new_frame->free ? port->new_frame->free : post_frame_free;
+ new_frame->dispose =
+ port->new_frame->dispose ? port->new_frame->dispose : post_frame_dispose;
+
+ if (!port->new_frame->draw) {
+ /* draw will most likely modify the frame, so the decoder
+ * should only request preprocessing when there is no new draw */
+ if (frame->proc_frame && !new_frame->proc_frame)
+ new_frame->proc_frame = post_frame_proc_frame;
+ if (frame->proc_slice && !new_frame->proc_slice)
+ new_frame->proc_slice = post_frame_proc_slice;
+ if (frame->proc_macro_block && !new_frame->proc_macro_block)
+ new_frame->proc_macro_block = post_frame_proc_macro_block;
+ }
+
+ return new_frame;
+}
+
+vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port) {
+ /* the first attched context is the original frame */
+ vo_frame_t *original = frame->next;
+
+ /* propagate any changes */
+ _x_post_frame_copy_up(frame, original);
+
+ /* put the now free slot into the free frames list */
+ pthread_mutex_lock(&port->free_frames_lock);
+ frame->next = port->free_frame_slots;
+ port->free_frame_slots = frame;
+ pthread_mutex_unlock(&port->free_frames_lock);
+
+ return original;
+}
+
+void _x_post_frame_copy_up(vo_frame_t *from, vo_frame_t *to) {
+ /* propagate changes upwards (from decoders to video out) */
+ to->pts = from->pts;
+ to->bad_frame = from->bad_frame;
+ to->duration = from->duration;
+ to->top_field_first = from->top_field_first;
+ to->repeat_first_field = from->repeat_first_field;
+ to->progressive_frame = from->progressive_frame;
+ to->picture_coding_type = from->picture_coding_type;
+ to->drawn = from->drawn;
+ to->macroblocks = from->macroblocks;
+ to->stream = from->stream;
+
+ if (to->extra_info != from->extra_info)
+ _x_extra_info_merge(to->extra_info, from->extra_info);
+}
+
+void _x_post_frame_copy_down(vo_frame_t *to, vo_frame_t *from) {
+ /* propagate changes downwards (from video out to decoders) */
+ to->vpts = from->vpts;
+ to->duration = from->duration;
+ to->stream = from->stream;
+
+ if (to->extra_info != from->extra_info)
+ _x_extra_info_merge(to->extra_info, from->extra_info);
+}
+
+void _x_post_frame_u_turn(vo_frame_t *frame, xine_stream_t *stream) {
+ /* frame's travel will end here => do the housekeeping */
+ frame->stream = stream;
+ if (stream) {
+ _x_extra_info_merge(frame->extra_info, stream->video_decoder_extra_info);
+ stream->metronom->got_video_frame(stream->metronom, frame);
+ }
}
/* dummy intercept functions that just pass the call on to the original overlay manager */
static void post_overlay_init(video_overlay_manager_t *ovl_gen) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- ovl->original_manager->init(ovl->original_manager);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ port->original_manager->init(port->original_manager);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
}
static void post_overlay_dispose(video_overlay_manager_t *ovl_gen) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- ovl->original_manager->dispose(ovl->original_manager);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ port->original_manager->dispose(port->original_manager);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
}
static int32_t post_overlay_get_handle(video_overlay_manager_t *ovl_gen, int object_type) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- return ovl->original_manager->get_handle(ovl->original_manager, object_type);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+ int32_t handle;
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ handle = port->original_manager->get_handle(port->original_manager, object_type);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
+ return handle;
}
static void post_overlay_free_handle(video_overlay_manager_t *ovl_gen, int32_t handle) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- ovl->original_manager->free_handle(ovl->original_manager, handle);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ port->original_manager->free_handle(port->original_manager, handle);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
}
static int32_t post_overlay_add_event(video_overlay_manager_t *ovl_gen, void *event) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- return ovl->original_manager->add_event(ovl->original_manager, event);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+ int32_t result;
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ result = port->original_manager->add_event(port->original_manager, event);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
+ return result;
}
static void post_overlay_flush_events(video_overlay_manager_t *ovl_gen) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- ovl->original_manager->flush_events(ovl->original_manager);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ port->original_manager->flush_events(port->original_manager);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
}
static int post_overlay_redraw_needed(video_overlay_manager_t *ovl_gen, int64_t vpts) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- return ovl->original_manager->redraw_needed(ovl->original_manager, vpts);
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
+ int redraw;
+
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ redraw = port->original_manager->redraw_needed(port->original_manager, vpts);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
+ return redraw;
}
static void post_overlay_multiple_overlay_blend(video_overlay_manager_t *ovl_gen, int64_t vpts,
vo_driver_t *output, vo_frame_t *vo_img, int enabled) {
- post_overlay_manager_t *ovl = (post_overlay_manager_t *)ovl_gen;
- ovl->original_manager->multiple_overlay_blend(ovl->original_manager, vpts, output, vo_img, enabled);
-}
-
-
-post_overlay_manager_t *_x_post_intercept_overlay_manager(post_plugin_t *post,
- video_overlay_manager_t *original) {
- post_overlay_manager_t *post_ovl = (post_overlay_manager_t *)malloc(sizeof(post_overlay_manager_t));
+ post_video_port_t *port = _x_post_ovl_manager_to_port(ovl_gen);
- if (!post_ovl)
- return NULL;
+ if (port->manager_lock) pthread_mutex_lock(port->manager_lock);
+ port->original_manager->multiple_overlay_blend(port->original_manager, vpts, output, vo_img, enabled);
+ if (port->manager_lock) pthread_mutex_unlock(port->manager_lock);
+}
+
+
+void _x_post_intercept_overlay_manager(video_overlay_manager_t *original, post_video_port_t *port) {
+ if (!port->new_manager->init)
+ port->new_manager->init = post_overlay_init;
+ if (!port->new_manager->dispose)
+ port->new_manager->dispose = post_overlay_dispose;
+ if (!port->new_manager->get_handle)
+ port->new_manager->get_handle = post_overlay_get_handle;
+ if (!port->new_manager->free_handle)
+ port->new_manager->free_handle = post_overlay_free_handle;
+ if (!port->new_manager->add_event)
+ port->new_manager->add_event = post_overlay_add_event;
+ if (!port->new_manager->flush_events)
+ port->new_manager->flush_events = post_overlay_flush_events;
+ if (!port->new_manager->redraw_needed)
+ port->new_manager->redraw_needed = post_overlay_redraw_needed;
+ if (!port->new_manager->multiple_overlay_blend)
+ port->new_manager->multiple_overlay_blend = post_overlay_multiple_overlay_blend;
- post_ovl->manager.init = post_overlay_init;
- post_ovl->manager.dispose = post_overlay_dispose;
- post_ovl->manager.get_handle = post_overlay_get_handle;
- post_ovl->manager.free_handle = post_overlay_free_handle;
- post_ovl->manager.add_event = post_overlay_add_event;
- post_ovl->manager.flush_events = post_overlay_flush_events;
- post_ovl->manager.redraw_needed = post_overlay_redraw_needed;
- post_ovl->manager.multiple_overlay_blend = post_overlay_multiple_overlay_blend;
-
- post_ovl->original_manager = original;
- post_ovl->post = post;
-
- return post_ovl;
+ port->original_manager = original;
}
/* dummy intercept functions that just pass the call on to the original port */
static uint32_t post_audio_get_capabilities(xine_audio_port_t *port_gen) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
- return port->original_port->get_capabilities(port->original_port);
+ uint32_t caps;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ caps = port->original_port->get_capabilities(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return caps;
}
static int post_audio_get_property(xine_audio_port_t *port_gen, int property) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
- return port->original_port->get_property(port->original_port, property);
+ int prop;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ prop = port->original_port->get_property(port->original_port, property);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return prop;
}
static int post_audio_set_property(xine_audio_port_t *port_gen, int property, int value) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
- return port->original_port->set_property(port->original_port, property, value);
+ int val;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ val = port->original_port->set_property(port->original_port, property, value);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return val;
}
static int post_audio_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;
- return port->original_port->open(port->original_port, stream, bits, rate, mode);
-}
-
-static audio_buffer_t * post_audio_get_buffer(xine_audio_port_t *port_gen) {
+ int result;
+
+ _x_post_rewire_audio(port);
+ _x_post_inc_usage(port);
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ result = port->original_port->open(port->original_port, stream, bits, rate, mode);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ if (stream)
+ port->stream = stream;
+ else
+ port->stream = POST_NULL_STREAM;
+ port->bits = bits;
+ port->rate = rate;
+ port->mode = mode;
+ return result;
+}
+
+static audio_buffer_t *post_audio_get_buffer(xine_audio_port_t *port_gen) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
- return port->original_port->get_buffer(port->original_port);
+ audio_buffer_t *buf;
+
+ _x_post_rewire_audio(port);
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ buf = port->original_port->get_buffer(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return buf;
}
static void post_audio_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;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->put_buffer(port->original_port, buf, stream);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
}
static void post_audio_close(xine_audio_port_t *port_gen, xine_stream_t *stream) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->close(port->original_port, stream);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ port->stream = NULL;
+ _x_post_dec_usage(port);
}
static void post_audio_exit(xine_audio_port_t *port_gen) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->exit(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
}
-static int post_audio_control (xine_audio_port_t *port_gen, int cmd, ...) {
+static int post_audio_control(xine_audio_port_t *port_gen, int cmd, ...) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
va_list args;
void *arg;
@@ -345,7 +691,9 @@ static int post_audio_control (xine_audio_port_t *port_gen, int cmd, ...) {
va_start(args, cmd);
arg = va_arg(args, void*);
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
rval = port->original_port->control(port->original_port, cmd, arg);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
va_end(args);
return rval;
@@ -353,36 +701,229 @@ static int post_audio_control (xine_audio_port_t *port_gen, int cmd, ...) {
static void post_audio_flush(xine_audio_port_t *port_gen) {
post_audio_port_t *port = (post_audio_port_t *)port_gen;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
port->original_port->flush(port->original_port);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
}
static int post_audio_status(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;
- return port->original_port->status(port->original_port, stream, bits, rate, mode);
+ int result;
+
+ if (port->port_lock) pthread_mutex_lock(port->port_lock);
+ result = port->original_port->status(port->original_port, stream, bits, rate, mode);
+ if (port->port_lock) pthread_mutex_unlock(port->port_lock);
+ return result;
}
-post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *original) {
- post_audio_port_t *post_port = (post_audio_port_t *)malloc(sizeof(post_audio_port_t));
+static int post_audio_rewire(xine_post_out_t *output_gen, void *data) {
+ post_out_t *output = (post_out_t *)output_gen;
+ xine_audio_port_t *new_port = (xine_audio_port_t *)data;
+ post_audio_port_t *input_port = (post_audio_port_t *)output->user_data;
+
+ if (!new_port)
+ return 0;
+ pthread_mutex_lock(&input_port->next_port_lock);
+ pthread_mutex_lock(&input_port->usage_lock);
+ input_port->next_port = new_port;
+ while (input_port->next_port) {
+ if (input_port->usage_count == 0) {
+ /* we can safely rewire right here, the plugin is not in use */
+ input_port->original_port = new_port;
+ input_port->next_port = NULL;
+ }
+ pthread_mutex_unlock(&input_port->usage_lock);
+ if (input_port->next_port)
+ pthread_cond_wait(&input_port->next_port_wire, &input_port->next_port_lock);
+ pthread_mutex_lock(&input_port->usage_lock);
+ }
+ pthread_mutex_unlock(&input_port->usage_lock);
+ pthread_mutex_unlock(&input_port->next_port_lock);
+ return 1;
+}
+
+post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *original,
+ post_in_t **input, post_out_t **output) {
+ post_audio_port_t *port = (post_audio_port_t *)xine_xmalloc(sizeof(post_audio_port_t));
- if (!post_port)
+ if (!port)
return NULL;
- post_port->port.open = post_audio_open;
- post_port->port.get_buffer = post_audio_get_buffer;
- post_port->port.put_buffer = post_audio_put_buffer;
- post_port->port.close = post_audio_close;
- post_port->port.exit = post_audio_exit;
- post_port->port.get_capabilities = post_audio_get_capabilities;
- post_port->port.get_property = post_audio_get_property;
- post_port->port.set_property = post_audio_set_property;
- post_port->port.control = post_audio_control;
- post_port->port.flush = post_audio_flush;
- post_port->port.status = post_audio_status;
+ port->new_port.open = post_audio_open;
+ port->new_port.get_buffer = post_audio_get_buffer;
+ port->new_port.put_buffer = post_audio_put_buffer;
+ port->new_port.close = post_audio_close;
+ port->new_port.exit = post_audio_exit;
+ port->new_port.get_capabilities = post_audio_get_capabilities;
+ port->new_port.get_property = post_audio_get_property;
+ port->new_port.set_property = post_audio_set_property;
+ port->new_port.control = post_audio_control;
+ port->new_port.flush = post_audio_flush;
+ port->new_port.status = post_audio_status;
+
+ port->original_port = original;
+ port->post = post;
+
+ pthread_mutex_init(&port->next_port_lock, NULL);
+ pthread_cond_init(&port->next_port_wire, NULL);
+ pthread_mutex_init(&port->usage_lock, NULL);
+
+ if (input) {
+ *input = (post_in_t *)xine_xmalloc(sizeof(post_in_t));
+ if (!*input) return port;
+ (*input)->xine_in.name = "audio in";
+ (*input)->xine_in.type = XINE_POST_DATA_AUDIO;
+ (xine_audio_port_t *)(*input)->xine_in.data = &port->new_port;
+ (*input)->post = post;
+ xine_list_append_content(post->input, *input);
+ }
+
+ if (output) {
+ *output = (post_out_t *)xine_xmalloc(sizeof(post_out_t));
+ if (!*output) return port;
+ (*output)->xine_out.name = "audio out";
+ (*output)->xine_out.type = XINE_POST_DATA_AUDIO;
+ (xine_audio_port_t **)(*output)->xine_out.data = &port->original_port;
+ (*output)->xine_out.rewire = post_audio_rewire;
+ (*output)->post = post;
+ (*output)->user_data = port;
+ xine_list_append_content(post->output, *output);
+ }
+
+ return port;
+}
+
+
+void _x_post_rewire_audio(post_audio_port_t *port) {
+ if (port->next_port) {
+ pthread_mutex_lock(&port->next_port_lock);
+ if (port->next_port) {
+ port->next_port->open(port->next_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream,
+ port->bits, port->rate, port->mode);
+ port->original_port->close(port->original_port, (port->stream == POST_NULL_STREAM) ? NULL : port->stream);
+ port->original_port = port->next_port;
+ port->next_port = NULL;
+ pthread_mutex_unlock(&port->next_port_lock);
+ pthread_cond_broadcast(&port->next_port_wire);
+ } else
+ pthread_mutex_unlock(&port->next_port_lock);
+ }
+}
+
+
+int _x_post_dispose(post_plugin_t *this) {
+ int i, in_use = 0;
+
+ /* acquire all usage locks */
+ for (i = 0; this->xine_post.audio_input[i]; i++) {
+ post_audio_port_t *port = (post_audio_port_t *)this->xine_post.audio_input[i];
+ pthread_mutex_lock(&port->usage_lock);
+ }
+ for (i = 0; this->xine_post.video_input[i]; i++) {
+ post_video_port_t *port = (post_video_port_t *)this->xine_post.video_input[i];
+ pthread_mutex_lock(&port->usage_lock);
+ }
+
+ /* we can set this witout harm, because it is always checked with
+ * usage lock held */
+ this->dispose_pending = 1;
+
+ /* check counters */
+ for (i = 0; this->xine_post.audio_input[i]; i++) {
+ post_audio_port_t *port = (post_audio_port_t *)this->xine_post.audio_input[i];
+ if (port->usage_count > 0) {
+ in_use = 1;
+ break;
+ }
+ }
+ for (i = 0; this->xine_post.video_input[i]; i++) {
+ post_video_port_t *port = (post_video_port_t *)this->xine_post.video_input[i];
+ if (port->usage_count > 0) {
+ in_use = 1;
+ break;
+ }
+ }
+
+ /* free the locks */
+ for (i = 0; this->xine_post.audio_input[i]; i++) {
+ post_audio_port_t *port = (post_audio_port_t *)this->xine_post.audio_input[i];
+ pthread_mutex_unlock(&port->usage_lock);
+ }
+ for (i = 0; this->xine_post.video_input[i]; i++) {
+ post_video_port_t *port = (post_video_port_t *)this->xine_post.video_input[i];
+ pthread_mutex_unlock(&port->usage_lock);
+ }
+
+ if (!in_use) {
+ xine_post_in_t *input;
+ xine_post_out_t *output;
+
+ /* we can really dispose it */
+
+ free(this->xine_post.audio_input);
+ free(this->xine_post.video_input);
+
+ for (input = xine_list_first_content(this->input); input;
+ input = xine_list_next_content(this->input)) {
+ switch (input->type) {
+ case XINE_POST_DATA_VIDEO:
+ {
+ post_video_port_t *port = (post_video_port_t *)input->data;
+ vo_frame_t *first, *second;
+
+ pthread_mutex_destroy(&port->next_port_lock);
+ pthread_cond_destroy(&port->next_port_wire);
+ pthread_mutex_destroy(&port->usage_lock);
+ pthread_mutex_destroy(&port->free_frames_lock);
+
+ second = NULL;
+ for (first = port->free_frame_slots; first;
+ second = first, first = first->next)
+ free(second);
+ free(second);
+
+ free(port);
+ free(input);
+ }
+ break;
+ case XINE_POST_DATA_AUDIO:
+ {
+ post_audio_port_t *port = (post_audio_port_t *)input->data;
+
+ pthread_mutex_destroy(&port->next_port_lock);
+ pthread_cond_destroy(&port->next_port_wire);
+ pthread_mutex_destroy(&port->usage_lock);
+
+ free(port);
+ free(input);
+ }
+ break;
+ }
+ }
+ for (output = xine_list_first_content(this->output); output;
+ output = xine_list_next_content(this->output)) {
+ switch (output->type) {
+ case XINE_POST_DATA_VIDEO:
+ if (output->rewire == post_video_rewire)
+ /* we allocated it, we free it */
+ free(output);
+ break;
+ case XINE_POST_DATA_AUDIO:
+ if (output->rewire == post_audio_rewire)
+ /* we allocated it, we free it */
+ free(output);
+ break;
+ }
+ }
+
+ xine_list_free(this->input);
+ xine_list_free(this->output);
- post_port->original_port = original;
- post_port->post = post;
+ return 1;
+ }
- return post_port;
+ return 0;
}
diff --git a/src/xine-engine/post.h b/src/xine-engine/post.h
index 5c3055929..1ddc1b580 100644
--- a/src/xine-engine/post.h
+++ b/src/xine-engine/post.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: post.h,v 1.16 2003/12/14 22:13:26 siggi Exp $
+ * $Id: post.h,v 1.17 2004/01/07 19:52:43 mroi Exp $
*
* post plugin definitions
*
@@ -30,20 +30,25 @@
# include "xine.h"
# include "video_out.h"
# include "audio_out.h"
+# include "xine_internal.h"
# include "xineutils.h"
#else
# include <xine.h>
# include <xine/video_out.h>
# include <xine/audio_out.h>
+# include <xine/xine_internal.h>
# include <xine/xineutils.h>
#endif
-#define POST_PLUGIN_IFACE_VERSION 7
+#define POST_PLUGIN_IFACE_VERSION 8
+
+#define POST_NULL_STREAM (xine_stream_t *)-1
typedef struct post_class_s post_class_t;
typedef struct post_plugin_s post_plugin_t;
-
+typedef struct post_in_s post_in_t;
+typedef struct post_out_s post_out_t;
struct post_class_s {
@@ -89,6 +94,9 @@ struct post_plugin_s {
*/
void (*dispose) (post_plugin_t *this);
+ /* has dispose been called */
+ int dispose_pending;
+
/* plugins don't have to care for the stuff below */
/* used when the user requests a list of all inputs/outputs */
@@ -99,6 +107,33 @@ struct post_plugin_s {
void *node;
};
+/* helper function to initialize a post_plugin_t */
+void _x_post_init(post_plugin_t *post, int num_audio_inputs, int num_video_inputs);
+
+struct post_in_s {
+
+ /* public part of the input */
+ xine_post_in_t xine_in;
+
+ /* backward reference so that you have access to the post plugin */
+ post_plugin_t *post;
+
+ /* you can fill this to your liking */
+ void *user_data;
+};
+
+struct post_out_s {
+
+ /* public part of the output */
+ xine_post_out_t xine_out;
+
+ /* backward reference so that you have access to the post plugin */
+ post_plugin_t *post;
+
+ /* you can fill this to your liking */
+ void *user_data;
+};
+
/* Post plugins work by intercepting calls to video or audio ports
* in the sense of the decorator design pattern. They reuse the
@@ -117,48 +152,130 @@ typedef struct post_video_port_s post_video_port_t;
struct post_video_port_s {
/* the new public port with replaced function pointers */
- xine_video_port_t port;
+ xine_video_port_t new_port;
/* the original port to call its functions from inside yours */
- xine_video_port_t *original_port;
+ xine_video_port_t *original_port;
- /* here you can keep information about the frames */
- vo_frame_t original_frame;
+ /* when we are rewiring, next port points to the new port */
+ xine_video_port_t *next_port;
+
+ /* rewiring synchronization */
+ pthread_mutex_t next_port_lock;
+ pthread_cond_t next_port_wire;
+
+ /* if you want to decide yourself, whether a given frame should
+ * be intercepted, fill in this function; get_frame() acts as
+ * a template method and asks your function; return a boolean;
+ * the default is to intercept all frames */
+ int (*intercept_frame)(post_video_port_t *self, vo_frame_t *frame);
+
+ /* the new frame function pointers */
+ vo_frame_t *new_frame;
+
+ /* if you want to decide yourself, whether the overlay manager should
+ * be intercepted, fill in this function; get_overlay_manager() acts as
+ * a template method and asks your function; return a boolean;
+ * the default is _not_ to intercept the overlay manager */
+ int (*intercept_ovl)(post_video_port_t *self);
- /* backward reference so that you have access to the post plugin
- * when the call only gives you the port */
- post_plugin_t *post;
-};
-
-/* use this to create a new, trivially decorated video port in which
- * port functions can be replaced with own implementations */
-post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *port);
-
-/* use this to decorate and to undecorate a frame so that its functions
- * can be replaced with own implementations */
-void _x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port);
-void _x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port);
-
-
-/* helper structure for intercepting overlay manager calls */
-typedef struct post_overlay_manager_s post_overlay_manager_t;
-struct post_overlay_manager_s {
-
/* the new public overlay manager with replaced function pointers */
- video_overlay_manager_t manager;
+ video_overlay_manager_t *new_manager;
/* the original manager to call its functions from inside yours */
video_overlay_manager_t *original_manager;
+ /* usage counter: how many objects are floating around that need
+ * these pointers to exist */
+ int usage_count;
+ pthread_mutex_t usage_lock;
+
+ /* the stream we are being fed by; NULL means no stream is connected,
+ * POST_NULL_STREAM means a NULL stream is connected */
+ xine_stream_t *stream;
+
+ /* point to a mutex here, if you need some synchronization */
+ pthread_mutex_t *port_lock;
+ pthread_mutex_t *frame_lock;
+ pthread_mutex_t *manager_lock;
+
/* backward reference so that you have access to the post plugin
- * when the call only gives you the overlay manager */
+ * when the call only gives you the port */
post_plugin_t *post;
+
+ /* you can fill this to your liking */
+ void *user_data;
+
+#ifdef POST_INTERNAL
+ /* some of the above members are to be directly included here, but
+ * adding the structures would mean that post_video_port_t becomes
+ * depended of the sizes of these structs; solution: we add pointers
+ * above and have them point into the memory provided here;
+ * note that the overlay manager needs to be first so that we can
+ * reconstruct the post_video_port_t* from overlay manager calls */
+
+ /* any change here requires a change in _x_post_ovl_manager_to_port()
+ * below! */
+
+ video_overlay_manager_t manager_storage;
+ vo_frame_t frame_storage;
+
+ /* this is used to keep a linked list of free vo_frame_t's */
+ vo_frame_t *free_frame_slots;
+ pthread_mutex_t free_frames_lock;
+#endif
};
+/* use this to create a new decorated video port in which
+ * port functions will be replaced with own implementations;
+ * for convenience, this can also create a related post_in_t and post_out_t */
+post_video_port_t *_x_post_intercept_video_port(post_plugin_t *post, xine_video_port_t *port,
+ post_in_t **input, post_out_t **output);
+
+/* this will execute pending rewire operations, calling this at the beginning
+ * of decoder-called functions like get_frame() and open() is a good idea
+ * (if you do not intercept get_frame() or open(), this will be done automatically) */
+void _x_post_rewire_video(post_video_port_t *port);
+
+/* use this to decorate and to undecorate a frame so that its functions
+ * can be replaced with own implementations, decoration is usually done in
+ * get_frame(), undecoration in frame->free() */
+vo_frame_t *_x_post_intercept_video_frame(vo_frame_t *frame, post_video_port_t *port);
+vo_frame_t *_x_post_restore_video_frame(vo_frame_t *frame, post_video_port_t *port);
+
+/* when you want to pass a frame call on to the original issuer of the frame,
+ * you need to propagate potential changes up and down the pipe, so the usual
+ * procedure for this situation would be:
+ *
+ * _x_post_frame_copy_up(frame, frame->next);
+ * frame->next->function(frame->next);
+ * _x_post_frame_copy_down(frame, frame->next);
+ */
+void _x_post_frame_copy_up(vo_frame_t *from, vo_frame_t *to);
+void _x_post_frame_copy_down(vo_frame_t *to, vo_frame_t *from);
+
+/* when you shortcut a frames usual draw() travel so that it will never reach
+ * the draw() function of the original issuer, you still have to do some
+ * housekeeping on the frame, before returning control down the pipe */
+void _x_post_frame_u_turn(vo_frame_t *frame, xine_stream_t *stream);
+
/* use this to create a new, trivially decorated overlay manager in which
* port functions can be replaced with own implementations */
-post_overlay_manager_t *_x_post_intercept_overlay_manager(post_plugin_t *post,
- video_overlay_manager_t *original);
+void _x_post_intercept_overlay_manager(video_overlay_manager_t *manager, post_video_port_t *port);
+
+/* pointer retrieval functions */
+static inline post_video_port_t *_x_post_video_frame_to_port(vo_frame_t *frame) {
+ return (post_video_port_t *)frame->port;
+}
+
+static inline post_video_port_t *_x_post_ovl_manager_to_port(video_overlay_manager_t *manager) {
+#ifdef POST_INTERNAL
+ return (post_video_port_t *)( (uint8_t *)manager -
+ (unsigned)&(((post_video_port_t *)NULL)->manager_storage) );
+#else
+ return (post_video_port_t *)( (uint8_t *)manager - sizeof(post_video_port_t) );
+#endif
+}
/* helper structure for intercepting audio port calls */
@@ -166,19 +283,86 @@ typedef struct post_audio_port_s post_audio_port_t;
struct post_audio_port_s {
/* the new public port with replaced function pointers */
- xine_audio_port_t port;
+ xine_audio_port_t new_port;
/* the original port to call its functions from inside yours */
xine_audio_port_t *original_port;
+ /* when we are rewiring, next port points to the new port */
+ xine_audio_port_t *next_port;
+
+ /* rewiring synchronization */
+ pthread_mutex_t next_port_lock;
+ pthread_cond_t next_port_wire;
+
+ /* usage counter: how many objects are floating around that need
+ * these pointers to exist */
+ int usage_count;
+ pthread_mutex_t usage_lock;
+
+ /* the stream we are being fed by; NULL means no stream is connected,
+ * POST_NULL_STREAM means a NULL stream is connected */
+ xine_stream_t *stream;
+
+ /* some values remembered by port->open() */
+ uint32_t bits;
+ uint32_t rate;
+ uint32_t mode;
+
+ /* point to a mutex here, if you need some synchronization */
+ pthread_mutex_t *port_lock;
+
/* backward reference so that you have access to the post plugin
* when the call only gives you the port */
post_plugin_t *post;
+
+ /* you can fill this to your liking */
+ void *user_data;
};
-/* use this to create a new, trivially decorated audio port in which
- * port functions can be replaced with own implementations */
-post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *port);
+/* use this to create a new decorated audio port in which
+ * port functions will be replaced with own implementations */
+post_audio_port_t *_x_post_intercept_audio_port(post_plugin_t *post, xine_audio_port_t *port,
+ post_in_t **input, post_out_t **output);
+
+/* this will execute pending rewire operations, calling this at the beginning
+ * of decoder-called functions like get_buffer() and open() is a good idea
+ * (if you do not intercept get_buffer() or open(), this will be done automatically) */
+void _x_post_rewire_audio(post_audio_port_t *port);
+
+
+/* the standard disposal operation; returns 1 if the plugin is really
+ * disposed and you should free everything you malloc()ed yourself */
+int _x_post_dispose(post_plugin_t *post);
+
+
+/* macros to handle usage counter */
+
+/* WARNING!
+ * note that _x_post_dec_usage() can call dispose, so be sure to
+ * not use any potentially already freed memory after this */
+
+#define _x_post_inc_usage(port) \
+do { \
+ pthread_mutex_lock(&(port)->usage_lock); \
+ (port)->usage_count++; \
+ pthread_mutex_unlock(&(port)->usage_lock); \
+} while(0)
+
+#define _x_post_dec_usage(port) \
+do { \
+ pthread_mutex_lock(&(port)->usage_lock); \
+ (port)->usage_count--; \
+ if ((port)->usage_count == 0) { \
+ pthread_cond_broadcast(&(port)->next_port_wire); \
+ if ((port)->post->dispose_pending) { \
+ pthread_mutex_unlock(&(port)->usage_lock); \
+ (port)->post->dispose((port)->post); \
+ } else \
+ pthread_mutex_unlock(&(port)->usage_lock); \
+ } else \
+ pthread_mutex_unlock(&(port)->usage_lock); \
+} while(0)
/* macros to create parameter descriptors */
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c
index 7c835288e..594a8199a 100644
--- a/src/xine-engine/video_out.c
+++ b/src/xine-engine/video_out.c
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.c,v 1.183 2003/12/05 15:55:05 f1rmb Exp $
+ * $Id: video_out.c,v 1.184 2004/01/07 19:52:43 mroi Exp $
*
* frame allocation / queuing / scheduling / output functions
*/
@@ -52,6 +52,8 @@
#define NUM_FRAME_BUFFERS 15
+#define NULL_STREAM (xine_stream_t *)-1
+
typedef struct {
vo_frame_t *first;
vo_frame_t *last;
@@ -405,6 +407,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams); stream;
stream = xine_list_next_content(this->streams)) {
+ if (stream == NULL_STREAM) continue;
pthread_mutex_lock (&stream->first_frame_lock);
if (stream->first_frame_flag == 2) {
stream->first_frame_flag = (this->grab_only)?0:1;
@@ -456,6 +459,7 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) {
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams); stream;
stream = xine_list_next_content(this->streams)) {
+ if (stream == NULL_STREAM) continue;
_x_stream_info_set(stream, XINE_STREAM_INFO_SKIPPED_FRAMES,
1000 * this->num_frames_skipped / this->num_frames_delivered);
_x_stream_info_set(stream, XINE_STREAM_INFO_DISCARDED_FRAMES,
@@ -809,6 +813,7 @@ static void overlay_and_display_frame (vos_t *this,
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams); stream;
stream = xine_list_next_content(this->streams)) {
+ if (stream == NULL_STREAM) continue;
pthread_mutex_lock (&stream->first_frame_lock);
if (stream->first_frame_flag) {
stream->first_frame_flag = 0;
@@ -955,6 +960,7 @@ static void *video_out_loop (void *this_gen) {
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams); stream;
stream = xine_list_next_content(this->streams)) {
+ if (stream == NULL_STREAM) continue;
if (stream->video_decoder_plugin && stream->video_fifo) {
buf_element_t *buf;
@@ -1041,44 +1047,30 @@ static void *video_out_loop (void *this_gen) {
int xine_get_next_video_frame (xine_video_port_t *this_gen,
xine_video_frame_t *frame) {
- vos_t *this = (vos_t *) this_gen;
- vo_frame_t *img;
- xine_stream_t *stream=NULL;
+ vos_t *this = (vos_t *) this_gen;
+ vo_frame_t *img = NULL;
+ xine_stream_t *stream = NULL;
- while (!stream) {
+ while (!img || !stream) {
stream = xine_list_first_content(this->streams);
- if (!stream)
- xine_usec_sleep (1000);
- }
-
- pthread_mutex_lock(&this->display_img_buf_queue->mutex);
-
- img = this->display_img_buf_queue->first;
-
- /* FIXME: ugly, use conditions and locks instead */
-
- lprintf ("get_next_video_frame demux status = %d, fifo_size=%d\n",
- stream->demux_plugin->get_status (stream->demux_plugin),
- stream->video_fifo->fifo_size);
-
- while ( !img && (stream->video_fifo->fifo_size
- || (stream->demux_plugin->get_status (stream->demux_plugin)==DEMUX_OK))) {
+ if (!stream) {
+ xine_usec_sleep (5000);
+ continue;
+ }
- pthread_mutex_unlock(&this->display_img_buf_queue->mutex);
- xine_usec_sleep (1000);
+ /* FIXME: ugly, use conditions and locks instead? */
+
pthread_mutex_lock(&this->display_img_buf_queue->mutex);
-
img = this->display_img_buf_queue->first;
- xprintf (this->xine, XINE_VERBOSITY_DEBUG,
- "video_out: get_next_video_frame demux status = %d, fifo_size=%d\n",
- stream->demux_plugin->get_status (stream->demux_plugin), stream->video_fifo->fifo_size);
-
-
- }
-
- if (!img) {
- pthread_mutex_unlock(&this->display_img_buf_queue->mutex);
- return 0;
+ if (!img) {
+ pthread_mutex_unlock(&this->display_img_buf_queue->mutex);
+ if (stream != NULL_STREAM && stream->video_fifo->fifo_size == 0 &&
+ stream->demux_plugin->get_status(stream->demux_plugin) != DEMUX_OK)
+ /* no further data can be expected here */
+ return 0;
+ xine_usec_sleep (5000);
+ continue;
+ }
}
/*
@@ -1126,9 +1118,10 @@ static void vo_open (xine_video_port_t *this_gen, xine_stream_t *stream) {
this->discard_frames = 0;
this->last_delivery_pts = 0;
this->warn_threshold_event_sent = this->warn_threshold_exceeded = 0;
- if (!this->overlay_enabled && stream->spu_channel_user > -2)
+ if (!this->overlay_enabled && (stream == NULL || stream->spu_channel_user > -2))
/* enable overlays if our new stream might want to show some */
this->overlay_enabled = 1;
+ if (stream == NULL) stream = NULL_STREAM;
pthread_mutex_lock(&this->streams_lock);
xine_list_append_content(this->streams, stream);
pthread_mutex_unlock(&this->streams_lock);
@@ -1146,6 +1139,7 @@ static void vo_close (xine_video_port_t *this_gen, xine_stream_t *stream) {
this->video_opened = 0;
/* unregister stream */
+ if (stream == NULL) stream = NULL_STREAM;
pthread_mutex_lock(&this->streams_lock);
for (cur = xine_list_first_content(this->streams); cur;
cur = xine_list_next_content(this->streams))
@@ -1374,7 +1368,7 @@ static void vo_enable_overlay (xine_video_port_t *this_gen, int overlay_enabled)
pthread_mutex_lock(&this->streams_lock);
for (stream = xine_list_first_content(this->streams) ; stream ;
stream = xine_list_next_content(this->streams)) {
- if (stream->spu_channel_user > -2) {
+ if (stream == NULL_STREAM || stream->spu_channel_user > -2) {
pthread_mutex_unlock(&this->streams_lock);
return;
}
diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h
index 4a3372113..3a7db490d 100644
--- a/src/xine-engine/video_out.h
+++ b/src/xine-engine/video_out.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: video_out.h,v 1.104 2003/12/14 22:13:26 siggi Exp $
+ * $Id: video_out.h,v 1.105 2004/01/07 19:52:43 mroi Exp $
*
*
* xine version of video_out.h
@@ -190,6 +190,8 @@ struct xine_video_port_s {
uint32_t (*get_capabilities) (xine_video_port_t *self); /* for constants see below */
/* open display driver for video output */
+ /* when you are not a full-blown stream, but still need to open the port
+ * (e.g. you are a post plugin) it is legal to pass a NULL stream */
void (*open) (xine_video_port_t *self, xine_stream_t *stream);
/*
@@ -224,11 +226,13 @@ struct xine_video_port_s {
int (*get_property) (xine_video_port_t *self, int property);
int (*set_property) (xine_video_port_t *self, int property, int value);
- /* return true if port is opened for this stream */
+ /* return true if port is opened for this stream, stream can be NULL */
int (*status) (xine_video_port_t *self, xine_stream_t *stream,
int *width, int *height, int64_t *img_duration);
/* video driver is no longer used by decoder => close */
+ /* when you are not a full-blown stream, but still need to close the port
+ * (e.g. you are a post plugin) it is legal to pass a NULL stream */
void (*close) (xine_video_port_t *self, xine_stream_t *stream);
/* called on xine exit */