diff options
Diffstat (limited to 'src/xine-engine')
-rw-r--r-- | src/xine-engine/video_out.c | 100 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 8 | ||||
-rw-r--r-- | src/xine-engine/vo_scale.c | 63 | ||||
-rw-r--r-- | src/xine-engine/vo_scale.h | 11 |
4 files changed, 147 insertions, 35 deletions
diff --git a/src/xine-engine/video_out.c b/src/xine-engine/video_out.c index eacc59dd5..dfc6aa5b7 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.205 2004/07/19 22:45:48 miguelfreitas Exp $ + * $Id: video_out.c,v 1.206 2004/09/22 20:29:17 miguelfreitas Exp $ * * frame allocation / queuing / scheduling / output functions */ @@ -59,6 +59,8 @@ #define FIRST_FRAME_POLL_DELAY 3000 #define FIRST_FRAME_MAX_POLL 10 /* poll n times at most */ +static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ); + typedef struct { vo_frame_t *first; vo_frame_t *last; @@ -329,7 +331,11 @@ static vo_frame_t *vo_get_frame (xine_video_port_t *this_gen, img->progressive_frame = 0; img->repeat_first_field = 0; img->top_field_first = 1; - img->macroblocks = NULL; + img->crop_left = 0; + img->crop_right = 0; + img->crop_top = 0; + img->crop_bottom = 0; + img->macroblocks = NULL; _x_extra_info_reset ( img->extra_info ); /* let driver ensure this image has the right format */ @@ -425,7 +431,18 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { if (!img->bad_frame) { - + + int dispose_img = 0; + + /* perform cropping when vo driver does not support it */ + if( (img->crop_left || img->crop_top || + img->crop_right || img->crop_bottom) && + (this->grab_only || + !(this->driver->get_capabilities (this->driver) & VO_CAP_CROP)) ) { + img = crop_frame( img->port, img ); + dispose_img = 1; + } + /* do not call proc_*() for frames that will be dropped */ if( !frames_to_skip && !img->proc_called ) vo_frame_driver_proc(img); @@ -461,6 +478,9 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { vo_frame_inc_lock( img ); vo_append_to_img_buf_queue (this->display_img_buf_queue, img); + + if( dispose_img ) + vo_frame_dec_lock( img ); } else { lprintf ("bad_frame\n"); @@ -560,7 +580,6 @@ static int vo_frame_draw (vo_frame_t *img, xine_stream_t *stream) { static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) { vo_frame_t *dupl; - int image_size; if( !this->free_img_buf_queue->first) return NULL; @@ -583,14 +602,19 @@ static vo_frame_t * duplicate_frame( vos_t *this, vo_frame_t *img ) { dupl->ratio = img->ratio; dupl->format = img->format; dupl->flags = img->flags | VO_BOTH_FIELDS; + dupl->progressive_frame = img->progressive_frame; + dupl->repeat_first_field = img->repeat_first_field; + dupl->top_field_first = img->top_field_first; + dupl->crop_left = img->crop_left; + dupl->crop_right = img->crop_right; + dupl->crop_top = img->crop_top; + dupl->crop_bottom = img->crop_bottom; this->driver->update_frame_format (this->driver, dupl, dupl->width, dupl->height, dupl->ratio, dupl->format, dupl->flags); pthread_mutex_unlock (&dupl->mutex); - image_size = img->pitches[0] * img->height; - switch (img->format) { case XINE_IMGFMT_YV12: yv12_to_yv12( @@ -1176,6 +1200,7 @@ int xine_get_next_video_frame (xine_video_port_t *this_gen, frame->height = img->height; frame->pos_stream = img->extra_info->input_normpos; frame->pos_time = img->extra_info->input_time; + frame->frame_number = img->extra_info->frame_number; frame->aspect_ratio = img->ratio; frame->colorspace = img->format; frame->data = img->base[0]; @@ -1508,6 +1533,69 @@ static void vo_flush (xine_video_port_t *this_gen) { } } +/* crop_frame() will allocate a new frame to copy in the given image + * while cropping. maybe someday this will be an automatic post plugin. + */ +static vo_frame_t * crop_frame( xine_video_port_t *this_gen, vo_frame_t *img ) { + + vo_frame_t *dupl; + + dupl = vo_get_frame ( this_gen, + img->width - img->crop_left - img->crop_right, + img->height - img->crop_top - img->crop_bottom, + img->ratio, img->format, img->flags | VO_BOTH_FIELDS); + + dupl->progressive_frame = img->progressive_frame; + dupl->repeat_first_field = img->repeat_first_field; + dupl->top_field_first = img->top_field_first; + + switch (img->format) { + case XINE_IMGFMT_YV12: + yv12_to_yv12( + /* Y */ + img->base[0] + img->crop_top * img->pitches[0] + + img->crop_left, img->pitches[0], + dupl->base[0], dupl->pitches[0], + /* U */ + img->base[1] + img->crop_top/2 * img->pitches[1] + + img->crop_left/2, img->pitches[1], + dupl->base[1], dupl->pitches[1], + /* V */ + img->base[2] + img->crop_top/2 * img->pitches[2] + + img->crop_left/2, img->pitches[2], + dupl->base[2], dupl->pitches[2], + /* width x height */ + dupl->width, dupl->height); + break; + case XINE_IMGFMT_YUY2: + yuy2_to_yuy2( + /* src */ + img->base[0] + img->crop_top * img->pitches[0] + + img->crop_left/2, img->pitches[0], + /* dst */ + dupl->base[0], dupl->pitches[0], + /* width x height */ + dupl->width, dupl->height); + break; + } + + dupl->bad_frame = 0; + dupl->pts = img->pts; + dupl->vpts = img->vpts; + dupl->proc_called = 0; + + dupl->duration = img->duration; + dupl->is_first = img->is_first; + + dupl->stream = img->stream; + memcpy( dupl->extra_info, img->extra_info, sizeof(extra_info_t) ); + + /* delay frame processing for now, we might not even need it (eg. frame will be discarded) */ + /* vo_frame_driver_proc(dupl); */ + + return dupl; +} + xine_video_port_t *_x_vo_new_port (xine_t *xine, vo_driver_t *driver, int grabonly) { vos_t *this; diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index fa4600c5d..0b70998e2 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.108 2004/07/06 22:53:23 miguelfreitas Exp $ + * $Id: video_out.h,v 1.109 2004/09/22 20:29:17 miguelfreitas Exp $ * * * xine version of video_out.h @@ -146,6 +146,9 @@ struct vo_frame_s { */ int progressive_frame; int picture_coding_type; + + /* cropping to be done */ + int crop_left, crop_right, crop_top, crop_bottom; /* extra info coming from input or demuxers */ extra_info_t *extra_info; @@ -289,6 +292,7 @@ struct xine_video_port_s { #define VO_CAP_XVMC_MOCOMP 0x00000004 /* driver can use XvMC motion compensation */ #define VO_CAP_XVMC_IDCT 0x00000008 /* driver can use XvMC idct acceleration */ #define VO_CAP_UNSCALED_OVERLAY 0x00000010 /* driver can blend overlay at output resolution */ +#define VO_CAP_CROP 0x00000020 /* driver can crop */ /* macroblock modes */ #define XINE_MACROBLOCK_INTRA 1 @@ -325,7 +329,7 @@ struct xine_video_port_s { * from generic vo functions. */ -#define VIDEO_OUT_DRIVER_IFACE_VERSION 19 +#define VIDEO_OUT_DRIVER_IFACE_VERSION 20 struct vo_driver_s { diff --git a/src/xine-engine/vo_scale.c b/src/xine-engine/vo_scale.c index 5704a1c8c..021ca72c3 100644 --- a/src/xine-engine/vo_scale.c +++ b/src/xine-engine/vo_scale.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: vo_scale.c,v 1.31 2004/05/11 02:21:16 miguelfreitas Exp $ + * $Id: vo_scale.c,v 1.32 2004/09/22 20:29:17 miguelfreitas Exp $ * * Contains common code to calculate video scaling parameters. * In short, it will map frame dimensions to screen/window size. @@ -56,7 +56,8 @@ void _x_vo_scale_compute_ideal_size (vo_scale_t *this) { * aspect ratio */ - image_ratio = (double) this->delivered_width / (double) this->delivered_height; + image_ratio = (double) (this->delivered_width - (this->crop_left + this->crop_right)) / + (double) (this->delivered_height - (this->crop_top + this->crop_bottom)); switch (this->user_ratio) { case XINE_VO_ASPECT_AUTO: @@ -105,18 +106,22 @@ void _x_vo_scale_compute_ideal_size (vo_scale_t *this) { void _x_vo_scale_compute_output_size (vo_scale_t *this) { + int cropped_width, cropped_height; double x_factor, y_factor, aspect; - aspect = this->video_pixel_aspect / this->gui_pixel_aspect; - x_factor = (double) this->gui_width / (double) (this->delivered_width * aspect); - y_factor = (double) (this->gui_height * aspect) / (double) this->delivered_height; + cropped_width = this->delivered_width - (this->crop_left + this->crop_right); + cropped_height = this->delivered_height - (this->crop_top + this->crop_bottom); + aspect = this->video_pixel_aspect / this->gui_pixel_aspect; + x_factor = (double) this->gui_width / (double) (cropped_width * aspect); + y_factor = (double) (this->gui_height * aspect) / (double) cropped_height; + if (this->scaling_disabled) { - this->output_width = this->delivered_width; - this->output_height = this->delivered_height; - this->displayed_width = this->delivered_width; - this->displayed_height = this->delivered_height; + this->output_width = cropped_width; + this->output_height = cropped_height; + this->displayed_width = cropped_width; + this->displayed_height = cropped_height; } else { @@ -128,44 +133,44 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { * black borders to use. * - exceding zoom shall be accounted by reducing displayed image. */ - if (((double)this->gui_width - (double)this->delivered_width * y_factor) < ((double)this->gui_height - (double)this->delivered_height * x_factor)) { + if (((double)this->gui_width - (double)cropped_width * y_factor) < ((double)this->gui_height - (double)cropped_height * x_factor)) { this->output_width = this->gui_width; - this->displayed_width = (double)this->delivered_width / this->zoom_factor_x + 0.5; + this->displayed_width = (double)cropped_width / this->zoom_factor_x + 0.5; - this->output_height = (double)this->delivered_height * x_factor + 0.5; + this->output_height = (double)cropped_height * x_factor + 0.5; if( this->output_height * this->zoom_factor_y <= this->gui_height ) { - this->displayed_height = this->delivered_height; + this->displayed_height = cropped_height; this->output_height = (double)this->output_height * this->zoom_factor_y + 0.5; } else { - this->displayed_height = (double) this->delivered_height * + this->displayed_height = (double)cropped_height * this->gui_height / this->output_height / this->zoom_factor_y + 0.5; this->output_height = this->gui_height; } } else { this->output_height = this->gui_height; - this->displayed_height = (double)this->delivered_height / this->zoom_factor_y + 0.5; + this->displayed_height = (double)cropped_height / this->zoom_factor_y + 0.5; - this->output_width = (double)this->delivered_width * y_factor + 0.5; + this->output_width = (double)cropped_width * y_factor + 0.5; if( this->output_width * this->zoom_factor_x <= this->gui_width ) { - this->displayed_width = this->delivered_width; + this->displayed_width = cropped_width; this->output_width = (double)this->output_width * this->zoom_factor_x + 0.5; } else { - this->displayed_width = (double) this->delivered_width * + this->displayed_width = (double)cropped_width * this->gui_width / this->output_width / this->zoom_factor_x + 0.5; this->output_width = this->gui_width; } } } else { - if (((double)this->gui_width - (double)this->delivered_width * y_factor) < ((double)this->gui_height - (double)this->delivered_height * x_factor)) { + if (((double)this->gui_width - (double)cropped_width * y_factor) < ((double)this->gui_height - (double)cropped_height * x_factor)) { this->output_width = (double) this->gui_width; - this->output_height = (double) this->delivered_height * x_factor + 0.5; + this->output_height = (double) cropped_height * x_factor + 0.5; } else { - this->output_width = (double) this->delivered_width * y_factor + 0.5; + this->output_width = (double) cropped_width * y_factor + 0.5; this->output_height = (double) this->gui_height; } - this->displayed_width = this->delivered_width; - this->displayed_height = this->delivered_height; + this->displayed_width = cropped_width; + this->displayed_height = cropped_height; } } @@ -188,8 +193,8 @@ void _x_vo_scale_compute_output_size (vo_scale_t *this) { this->output_yoffset = (this->gui_height - this->output_height) * this->output_vertical_position + this->gui_y; - this->displayed_xoffset = (this->delivered_width - this->displayed_width) / 2; - this->displayed_yoffset = (this->delivered_height - this->displayed_height) / 2; + this->displayed_xoffset = ((cropped_width - this->displayed_width) / 2) + this->crop_left; + this->displayed_yoffset = ((cropped_height - this->displayed_height) / 2) + this->crop_top; lprintf ("frame source %d x %d (%d x %d) => screen output %d x %d\n", this->delivered_width, this->delivered_height, @@ -244,7 +249,8 @@ int _x_vo_scale_redraw_needed (vo_scale_t *this) { if( this->frame_output_cb ) { this->frame_output_cb (this->user_data, - this->delivered_width, this->delivered_height, + this->delivered_width - (this->crop_left + this->crop_right), + this->delivered_height - (this->crop_top + this->crop_bottom), this->video_pixel_aspect, &gui_x, &gui_y, &gui_width, &gui_height, &gui_pixel_aspect, &gui_win_x, &gui_win_y ); @@ -365,6 +371,11 @@ void _x_vo_scale_init(vo_scale_t *this, int support_zoom, int scaling_disabled, this->user_ratio = XINE_VO_ASPECT_AUTO; this->delivered_ratio = 0.0; + this->crop_left = 0; + this->crop_right = 0; + this->crop_top = 0; + this->crop_bottom = 0; + this->output_horizontal_position = config->register_range(config, "video.horizontal_position", 50, 0, 100, _("horizontal image position in the output window"), NULL, 10, diff --git a/src/xine-engine/vo_scale.h b/src/xine-engine/vo_scale.h index 736e50fbd..a5fd8d9e4 100644 --- a/src/xine-engine/vo_scale.h +++ b/src/xine-engine/vo_scale.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: vo_scale.h,v 1.12 2004/04/25 14:50:32 komadori Exp $ + * $Id: vo_scale.h,v 1.13 2004/09/22 20:29:18 miguelfreitas Exp $ * * vo_scale.h * @@ -65,6 +65,15 @@ struct vo_scale_s { int delivered_width; int delivered_height; double delivered_ratio; + + /* + * required cropping: + * units: frame pixels + */ + int crop_left; + int crop_right; + int crop_top; + int crop_bottom; /* * displayed part of delivered images, |