diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/post/deinterlace/xine_plugin.c | 242 | ||||
-rw-r--r-- | src/post/goom/xine_goom.c | 181 | ||||
-rw-r--r-- | src/post/mosaico/mosaico.c | 742 | ||||
-rw-r--r-- | src/post/mosaico/switch.c | 445 | ||||
-rw-r--r-- | src/post/planar/boxblur.c | 181 | ||||
-rw-r--r-- | src/post/planar/denoise3d.c | 188 | ||||
-rw-r--r-- | src/post/planar/eq.c | 174 | ||||
-rw-r--r-- | src/post/planar/eq2.c | 177 | ||||
-rw-r--r-- | src/post/planar/expand.c | 333 | ||||
-rw-r--r-- | src/post/planar/invert.c | 156 | ||||
-rw-r--r-- | src/post/planar/planar.c | 18 | ||||
-rwxr-xr-x | src/post/planar/pp.c | 188 | ||||
-rw-r--r-- | src/post/planar/unsharp.c | 171 | ||||
-rw-r--r-- | src/post/visualizations/fftgraph.c | 171 | ||||
-rw-r--r-- | src/post/visualizations/fftscope.c | 183 | ||||
-rw-r--r-- | src/post/visualizations/fooviz.c | 162 | ||||
-rw-r--r-- | src/post/visualizations/oscope.c | 165 | ||||
-rw-r--r-- | src/post/visualizations/visualizations.c | 8 | ||||
-rw-r--r-- | src/xine-engine/audio_out.c | 77 | ||||
-rw-r--r-- | src/xine-engine/audio_out.h | 6 | ||||
-rw-r--r-- | src/xine-engine/post.c | 865 | ||||
-rw-r--r-- | src/xine-engine/post.h | 252 | ||||
-rw-r--r-- | src/xine-engine/video_out.c | 66 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 8 |
24 files changed, 2152 insertions, 3007 deletions
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 */ |