From: Michael R. <mr...@us...> - 2004-01-07 19:52:46
|
Update of /cvsroot/xine/xine-lib/src/post/mosaico In directory sc8-pr-cvs1:/tmp/cvs-serv31477/src/post/mosaico Modified Files: mosaico.c switch.c Log Message: the new, refined post plugin architecture * post plugins are now much safer (fewer races/inconsistencies) and easier to write * all post plugins are ported to the new architecture (and should work) * ports can now be opened and closed with a NULL stream Index: mosaico.c =================================================================== RCS file: /cvsroot/xine/xine-lib/src/post/mosaico/mosaico.c,v retrieving revision 1.20 retrieving revision 1.21 diff -u -r1.20 -r1.21 --- mosaico.c 14 Dec 2003 22:13:25 -0000 1.20 +++ mosaico.c 7 Jan 2004 19:52:42 -0000 1.21 @@ -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 @@ 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 @@ /* 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 @@ 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 @@ 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]; + this->pip = (mosaico_pip_t *)xine_xmalloc(sizeof(mosaico_pip_t) * (inputs - 1)); + this->pip_count = inputs - 1; -/* 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; + 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; + } + + 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[i+1] = NULL; - this->dispose = mosaico_dispose; + 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_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; + return &mosaico_param_descr; +} - 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; +static int mosaico_set_parameters(xine_post_t *this_gen, void *param_gen) +{ + 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 void mosaico_open(xine_video_port_t *port_gen, xine_stream_t *stream) +static int mosaico_get_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 || 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(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; + 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"); +} + - 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; -} - -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 void mosaico_close(xine_video_port_t *port_gen, xine_stream_t *stream) { post_video_port_t *port = (post_video_port_t *)port_gen; - vo_frame_t *frame; + post_mosaico_t *this = (post_mosaico_t *)port->post; + vo_frame_t *free_frame; + int pip_num; - 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; + 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); - return frame; + if (free_frame) + free_frame->free(free_frame); + port->stream = NULL; + _x_post_dec_usage(port); } -static void mosaico_close(xine_video_port_t *port_gen, xine_stream_t *stream) + +static int mosaico_intercept_frame(post_video_port_t *port, vo_frame_t *frame) { - 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); + /* TODO: only YV12 supported */ + return (frame->format == XINE_IMGFMT_YV12); } -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; - } +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 @@ /* 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; - } - - 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; +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; - frame_copy_content(output->saved_frame_2[cont], frame); - } + if (!this->pip[pip_num].frame) return; + + 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; - 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; - - 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);*/ - } + switch (this->pip[pip_num].frame->format) { + case XINE_IMGFMT_YUY2: + /* TODO: implement YUY2 */ + break; + + 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); + post_mosaico_t *this = (post_mosaico_t *)port->post; + vo_frame_t *background; + int pip_num, skip; - _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); + 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; + + 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); - return 0; + 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; } Index: switch.c =================================================================== RCS file: /cvsroot/xine/xine-lib/src/post/mosaico/switch.c,v retrieving revision 1.11 retrieving revision 1.12 diff -u -r1.11 -r1.12 --- switch.c 14 Dec 2003 22:13:25 -0000 1.11 +++ switch.c 7 Jan 2004 19:52:42 -0000 1.12 @@ -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 @@ 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 @@ /* 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 @@ 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 @@ 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_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_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); + if (_x_post_dispose(this_gen)) { + pthread_cond_destroy(&this->display_condition_changed); + pthread_mutex_destroy(&this->mutex); + free(this); + } } -static int switch_rewire(xine_post_out_t *output_gen, void *data) +static xine_post_api_descr_t *switch_get_param_descr(void) { - 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); - } - /* reconnect ourselves */ - *(xine_video_port_t **)output_gen->data = new_port; - return 1; + return &switch_param_descr; } -static void switch_open(xine_video_port_t *port_gen, xine_stream_t *stream) +static int switch_set_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 = 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) -{ - 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; -} - -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) -{ - 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; - - 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); - - } + post_switch_t *this = (post_switch_t *)this_gen; + switch_parameter_t *param = (switch_parameter_t *)param_gen; + + 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; } |