diff options
Diffstat (limited to 'src/video_out/video_out_xshm.c')
-rw-r--r-- | src/video_out/video_out_xshm.c | 642 |
1 files changed, 367 insertions, 275 deletions
diff --git a/src/video_out/video_out_xshm.c b/src/video_out/video_out_xshm.c index 3d4dae3f9..6b52acccd 100644 --- a/src/video_out/video_out_xshm.c +++ b/src/video_out/video_out_xshm.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2000-2003 the xine project + * Copyright (C) 2000-2003, 2008 the xine project * * This file is part of xine, a free video player. * @@ -23,6 +23,8 @@ * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * * xine-specific code by Guenter Bartsch <bartscgr@studbox.uni-stuttgart.de> + * + * fullrange/HD color and crop support added by Torsten Jager <t.jager@gmx.de> */ #ifdef HAVE_CONFIG_H @@ -34,9 +36,6 @@ #include <string.h> #include <math.h> -#include "xine.h" -#include "video_out.h" - #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xatom.h> @@ -51,17 +50,26 @@ #include <pthread.h> #include <netinet/in.h> +#ifdef HAVE_FFMPEG_AVUTIL_H +# include <mem.h> +#else +# include <libavutil/mem.h> +#endif + #define LOG_MODULE "video_out_xshm" #define LOG_VERBOSE /* #define LOG */ -#include "xine_internal.h" +#include "xine.h" +#include <xine/video_out.h> +#include <xine/xine_internal.h> #include "yuv2rgb.h" -#include "xineutils.h" -#include "vo_scale.h" +#include <xine/xineutils.h> +#include <xine/vo_scale.h> #include "x11osd.h" +#include "xine_mmx.h" #define LOCK_DISPLAY(this) {if(this->lock_display) this->lock_display(this->user_data); \ else XLockDisplay(this->display);} @@ -80,13 +88,18 @@ typedef struct { XImage *image; XShmSegmentInfo shminfo; - uint8_t *chunk[3]; /* mem alloc by xmalloc_aligned */ - yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ uint8_t *rgb_dst; + int state, offs0, offs1; /* crop helpers */ + uint8_t *crop_start, *crop_flush, *crop_stop; } xshm_frame_t; +/* frame.state */ +#define FS_DONE 1 +#define FS_LATE 2 +#define FS_FLAGS 4 + typedef struct { vo_driver_t vo_driver; @@ -101,12 +114,15 @@ typedef struct { int use_shm; XColor black; - int yuv2rgb_brightness; - int yuv2rgb_contrast; - int yuv2rgb_saturation; + int brightness; + int contrast; + int saturation; uint8_t *yuv2rgb_cmap; yuv2rgb_factory_t *yuv2rgb_factory; + /* color matrix switching */ + int cm_active, cm_state; + vo_scale_t sc; xshm_frame_t *cur_frame; @@ -135,17 +151,22 @@ typedef struct { } xshm_class_t; +/* import common color matrix stuff */ +#define CM_DRIVER_T xshm_driver_t +#include "color_matrix.c" + static int gX11Fail; /* * first, some utility functions */ + /* called xlocked */ static int HandleXError (Display *display, XErrorEvent *xevent) { char str [1024]; XGetErrorText (display, xevent->error_code, str, 1024); - printf ("video_out_xshm: received X error event: %s\n", str); + printf (LOG_MODULE ": received X error event: %s\n", str); gX11Fail = 1; return 0; @@ -191,8 +212,9 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, if (myimage == NULL ) { xprintf(this->xine, XINE_VERBOSITY_LOG, - _("video_out_xshm: shared memory error when allocating image\n" - "video_out_xshm: => not using MIT Shared Memory extension.\n")); + _("%s: shared memory error when allocating image\n"), LOG_MODULE); + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE); this->use_shm = 0; goto finishShmTesting; } @@ -207,8 +229,9 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, if (shminfo->shmid < 0 ) { xprintf(this->xine, XINE_VERBOSITY_LOG, - _("video_out_xshm: %s: allocating image\n" - "video_out_xshm: => not using MIT Shared Memory extension.\n"), strerror(errno)); + _("%s: %s: allocating image\n"), LOG_MODULE, strerror(errno)); + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE); this->use_shm = 0; goto finishShmTesting; } @@ -217,8 +240,9 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, if (shminfo->shmaddr == ((char *) -1)) { xprintf(this->xine, XINE_VERBOSITY_LOG, - _("video_out_xshm: shared memory error (address error) when allocating image \n" - "video_out_xshm: => not using MIT Shared Memory extension.\n")); + _("%s: shared memory error (address error) when allocating image \n"), LOG_MODULE); + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE); shmctl (shminfo->shmid, IPC_RMID, 0); shminfo->shmid = -1; this->use_shm = 0; @@ -233,10 +257,11 @@ static XImage *create_ximage (xshm_driver_t *this, XShmSegmentInfo *shminfo, XSync(this->display, False); if (gX11Fail) { - xprintf(this->xine, XINE_VERBOSITY_LOG, - _("video_out_xshm: x11 error during shared memory XImage creation\n" - "video_out_xshm: => not using MIT Shared Memory extension.\n")); shmdt (shminfo->shmaddr); + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("%s: x11 error during shared memory XImage creation\n"), LOG_MODULE); + xprintf(this->xine, XINE_VERBOSITY_LOG, + _("%s: => not using MIT Shared Memory extension.\n"), LOG_MODULE); shmctl (shminfo->shmid, IPC_RMID, 0); shminfo->shmid = -1; this->use_shm = 0; @@ -310,7 +335,8 @@ static void dispose_ximage (xshm_driver_t *this, static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { xshm_driver_t *this = (xshm_driver_t *) this_gen; - uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2; + uint32_t capabilities = VO_CAP_CROP | VO_CAP_YV12 | VO_CAP_YUY2 | VO_CAP_BRIGHTNESS + | VO_CAP_CONTRAST | VO_CAP_SATURATION | VO_CAP_COLOR_MATRIX | VO_CAP_FULLRANGE; if( this->xoverlay ) capabilities |= VO_CAP_UNSCALED_OVERLAY; @@ -318,31 +344,30 @@ static uint32_t xshm_get_capabilities (vo_driver_t *this_gen) { return capabilities; } -static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { - xshm_frame_t *frame = (xshm_frame_t *) vo_img ; - /*xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; */ - - vo_img->proc_called = 1; - - if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || - frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) - { - /* we don't support crop, so don't even waste cpu cycles. - * cropping will be performed by video_out.c - */ - return; - } +static void xshm_compute_ideal_size (xshm_driver_t *this, xshm_frame_t *frame) { + _x_vo_scale_compute_ideal_size( &frame->sc ); +} - lprintf ("copy... (format %d)\n", frame->format); +static void xshm_compute_rgb_size (xshm_driver_t *this, xshm_frame_t *frame) { + _x_vo_scale_compute_output_size( &frame->sc ); - if (frame->format == XINE_IMGFMT_YV12) - frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, - src[0], src[1], src[2]); - else - frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, - src[0]); + /* avoid problems in yuv2rgb */ + if (frame->sc.output_height < 1) + frame->sc.output_height = 1; + if (frame->sc.output_width < 8) + frame->sc.output_width = 8; + if (frame->sc.output_width & 1) /* yuv2rgb_mlib needs an even YUV2 width */ + frame->sc.output_width++; - lprintf ("copy...done\n"); + lprintf("frame source (%d) %d x %d => screen output %d x %d%s\n", + frame->vo_frame.id, + frame->sc.delivered_width, frame->sc.delivered_height, + frame->sc.output_width, frame->sc.output_height, + ( frame->sc.delivered_width != frame->sc.output_width + || frame->sc.delivered_height != frame->sc.output_height + ? ", software scaling" + : "" ) + ); } static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { @@ -364,6 +389,188 @@ static void xshm_frame_field (vo_frame_t *vo_img, int which_field) { frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL); } +static void xshm_frame_proc_setup (vo_frame_t *vo_img) { + xshm_frame_t *frame = (xshm_frame_t *) vo_img ; + xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; + int changed = 0, i; + int width, height, gui_width, gui_height; + double gui_pixel_aspect; + + /* Aargh... libmpeg2 decoder calls frame->proc_slice directly, preferredly + while still in mmx mode. This will trash our floating point aspect ratio + calculations below. Switching back once per frame should not harm + performance too much. */ +#ifdef HAVE_MMX + emms (); +#endif + + if (!(frame->state & FS_LATE)) { + /* adjust cropping to what yuv2rgb can handle */ + if (vo_img->format == XINE_IMGFMT_YV12) { + vo_img->crop_left &= ~7; + vo_img->crop_top &= ~1; + } else { + vo_img->crop_left &= ~3; + } + /* check for crop changes */ + if ((vo_img->crop_left != frame->sc.crop_left) + || (vo_img->crop_top != frame->sc.crop_top) + || (vo_img->crop_right != frame->sc.crop_right) + || (vo_img->crop_bottom != frame->sc.crop_bottom)) { + frame->sc.crop_left = vo_img->crop_left; + frame->sc.crop_top = vo_img->crop_top; + frame->sc.crop_right = vo_img->crop_right; + frame->sc.crop_bottom = vo_img->crop_bottom; + changed = 1; + } + } + + if (!(frame->state & FS_DONE)) + changed = 1; + + /* just deal with cropped part */ + width = frame->sc.delivered_width - frame->sc.crop_left - frame->sc.crop_right; + height = frame->sc.delivered_height - frame->sc.crop_top - frame->sc.crop_bottom; + + if (frame->sc.delivered_ratio == 0.0) { + frame->sc.delivered_ratio = height ? (double)width / (double)height : 1.0; + changed = 1; + } + + /* ask gui what output size we'll have for this frame */ + /* get the gui_pixel_aspect before calling xshm_compute_ideal_size() */ + /* note: gui_width and gui_height may be bogus because we may have not yet */ + /* updated video_pixel_aspect (see _x_vo_scale_compute_ideal_size). */ + frame->sc.dest_size_cb (frame->sc.user_data, width, height, + frame->sc.video_pixel_aspect, &gui_width, &gui_height, &gui_pixel_aspect); + + if (changed || (gui_pixel_aspect != frame->sc.gui_pixel_aspect) + || (this->sc.user_ratio != frame->sc.user_ratio)) { + + frame->sc.gui_pixel_aspect = gui_pixel_aspect; + frame->sc.user_ratio = this->sc.user_ratio; + + xshm_compute_ideal_size (this, frame); + + /* now we have updated video_aspect_pixel we use the callback */ + /* again to obtain the correct gui_width and gui_height values. */ + frame->sc.dest_size_cb (frame->sc.user_data, width, height, + frame->sc.video_pixel_aspect, &gui_width, &gui_height, &gui_pixel_aspect); + + changed = 1; + } + + if (changed || (frame->sc.gui_width != gui_width) + || (frame->sc.gui_height != gui_height)) { + int w = frame->sc.output_width, h = frame->sc.output_height; + + frame->sc.gui_width = gui_width; + frame->sc.gui_height = gui_height; + + xshm_compute_rgb_size (this, frame); + + if (!frame->image || (w != frame->sc.output_width) || (h != frame->sc.output_height)) { + /* (re)allocate XImage */ + LOCK_DISPLAY(this); + if (frame->image) + dispose_ximage (this, &frame->shminfo, frame->image); + frame->image = create_ximage (this, &frame->shminfo, + frame->sc.output_width, frame->sc.output_height); + UNLOCK_DISPLAY(this); + } + + changed = 1; + } + + if (changed || !(frame->state & FS_FLAGS)) { + /* set up colorspace converter */ + switch (vo_img->flags & VO_BOTH_FIELDS) { + case VO_TOP_FIELD: + case VO_BOTTOM_FIELD: + frame->yuv2rgb->configure (frame->yuv2rgb, width, height, + 2 * frame->vo_frame.pitches[0], 2 * frame->vo_frame.pitches[1], + frame->sc.output_width, frame->sc.output_height, + frame->image->bytes_per_line * 2); + break; + case VO_BOTH_FIELDS: + frame->yuv2rgb->configure (frame->yuv2rgb, width, height, + frame->vo_frame.pitches[0], frame->vo_frame.pitches[1], + frame->sc.output_width, frame->sc.output_height, + frame->image->bytes_per_line); + break; + } + } + + frame->state |= FS_FLAGS | FS_DONE; + + xshm_frame_field (vo_img, vo_img->flags & VO_BOTH_FIELDS); + + /* cache helpers */ + i = frame->sc.crop_top & 15; + if (i) + i -= 16; + if (vo_img->format == XINE_IMGFMT_YV12) { + frame->offs0 = i * vo_img->pitches[0] + frame->sc.crop_left; + frame->offs1 = (i * vo_img->pitches[1] + frame->sc.crop_left) / 2; + } else { + frame->offs0 = i * vo_img->pitches[0] + frame->sc.crop_left * 2; + } + frame->crop_start = vo_img->base[0] + frame->sc.crop_top * vo_img->pitches[0]; + frame->crop_flush = frame->crop_stop = vo_img->base[0] + + (frame->sc.delivered_height - frame->sc.crop_bottom) * vo_img->pitches[0]; + if (i + frame->sc.crop_bottom < 0) + frame->crop_flush -= 16 * vo_img->pitches[0]; + + /* switch color matrix/range */ + i = cm_from_frame (vo_img); + if (i != this->cm_active) { + this->cm_active = i; + this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, + this->brightness, this->contrast, this->saturation, i); + xprintf (this->xine, XINE_VERBOSITY_LOG, + "video_out_xshm: b %d c %d s %d [%s]\n", + this->brightness, this->contrast, this->saturation, cm_names[i]); + } +} + +static void xshm_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) { + xshm_frame_t *frame = (xshm_frame_t *) vo_img ; + uint8_t *src0; + + /* delayed setup */ + if (!vo_img->proc_called) { + xshm_frame_proc_setup (vo_img); + vo_img->proc_called = 1; + } + + src0 = src[0] + frame->offs0; + if ((src0 < frame->crop_start) || (src0 >= frame->crop_stop)) + return; + + lprintf ("copy... (format %d)\n", frame->format); + + if (frame->format == XINE_IMGFMT_YV12) + frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, + src0, src[1] + frame->offs1, src[2] + frame->offs1); + else + frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, + src0); + + if (src0 >= frame->crop_flush) { + if (vo_img->format == XINE_IMGFMT_YV12) { + frame->yuv2rgb->yuv2rgb_fun (frame->yuv2rgb, frame->rgb_dst, + src0 + 16 * vo_img->pitches[0], + src[1] + frame->offs1 + 8 * vo_img->pitches[1], + src[2] + frame->offs1 + 8 * vo_img->pitches[2]); + } else { + frame->yuv2rgb->yuy22rgb_fun (frame->yuv2rgb, frame->rgb_dst, + src0 + 16 * vo_img->pitches[0]); + } + } + + lprintf ("copy...done\n"); +} + static void xshm_frame_dispose (vo_frame_t *vo_img) { xshm_frame_t *frame = (xshm_frame_t *) vo_img ; xshm_driver_t *this = (xshm_driver_t *) vo_img->driver; @@ -376,9 +583,9 @@ static void xshm_frame_dispose (vo_frame_t *vo_img) { frame->yuv2rgb->dispose (frame->yuv2rgb); - free (frame->chunk[0]); - free (frame->chunk[1]); - free (frame->chunk[2]); + av_free (frame->vo_frame.base[0]); + av_free (frame->vo_frame.base[1]); + av_free (frame->vo_frame.base[2]); free (frame); } @@ -414,186 +621,63 @@ static vo_frame_t *xshm_alloc_frame (vo_driver_t *this_gen) { return (vo_frame_t *) frame; } -static void xshm_compute_ideal_size (xshm_driver_t *this, xshm_frame_t *frame) { - _x_vo_scale_compute_ideal_size( &frame->sc ); -} - -static void xshm_compute_rgb_size (xshm_driver_t *this, xshm_frame_t *frame) { - _x_vo_scale_compute_output_size( &frame->sc ); - - /* avoid problems in yuv2rgb */ - if (frame->sc.output_height < 1) - frame->sc.output_height = 1; - if (frame->sc.output_width < 8) - frame->sc.output_width = 8; - if (frame->sc.output_width & 1) /* yuv2rgb_mlib needs an even YUV2 width */ - frame->sc.output_width++; - - lprintf("frame source (%d) %d x %d => screen output %d x %d%s\n", - frame->vo_frame.id, - frame->sc.delivered_width, frame->sc.delivered_height, - frame->sc.output_width, frame->sc.output_height, - ( frame->sc.delivered_width != frame->sc.output_width - || frame->sc.delivered_height != frame->sc.output_height - ? ", software scaling" - : "" ) - ); -} - static void xshm_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_gen, uint32_t width, uint32_t height, double ratio, int format, int flags) { - xshm_driver_t *this = (xshm_driver_t *) this_gen; xshm_frame_t *frame = (xshm_frame_t *) frame_gen; - int do_adapt; - int gui_width; - int gui_height; - double gui_pixel_aspect; + int j, pitch; flags &= VO_BOTH_FIELDS; - /* ask gui what output size we'll have for this frame */ - /* get the gui_pixel_aspect before calling xshm_compute_ideal_size() */ - /* note: gui_width and gui_height may be bogus because we may have not yet*/ - /* updated video_pixel_aspect (see _x_vo_scale_compute_ideal_size). */ - frame->sc.dest_size_cb (frame->sc.user_data, width, height, - frame->sc.video_pixel_aspect, - &gui_width, &gui_height, - &gui_pixel_aspect); - - /* find out if we need to adapt this frame */ - do_adapt = 0; - + /* (re)allocate yuv buffers */ if ((width != frame->sc.delivered_width) || (height != frame->sc.delivered_height) - || (ratio != frame->sc.delivered_ratio) - || (flags != frame->flags) - || (format != frame->format) - || (gui_pixel_aspect != frame->sc.gui_pixel_aspect) - || (this->sc.user_ratio != frame->sc.user_ratio)) { - - do_adapt = 1; - - lprintf ("frame format (from decoder) has changed => adapt\n"); + || (format != frame->format)) { frame->sc.delivered_width = width; frame->sc.delivered_height = height; - frame->sc.delivered_ratio = ratio; - frame->sc.gui_pixel_aspect = gui_pixel_aspect; - frame->flags = flags; frame->format = format; - frame->sc.user_ratio = this->sc.user_ratio; - - xshm_compute_ideal_size (this, frame); - - /* now we have updated video_aspect_pixel we use the callback */ - /* again to obtain the correct gui_width and gui_height values. */ - frame->sc.dest_size_cb (frame->sc.user_data, width, height, - frame->sc.video_pixel_aspect, - &gui_width, &gui_height, - &gui_pixel_aspect); - } - - if ((frame->sc.gui_width != gui_width) || - (frame->sc.gui_height != gui_height) || - do_adapt) { - - do_adapt = 1; - frame->sc.gui_width = gui_width; - frame->sc.gui_height = gui_height; - - xshm_compute_rgb_size (this, frame); - - lprintf ("gui_size has changed => adapt\n"); - } - - - /* ok, now do what we have to do */ - - if (do_adapt) { - - lprintf ("updating frame to %d x %d\n", - frame->sc.output_width, frame->sc.output_height); - - LOCK_DISPLAY(this); - - /* - * (re-) allocate XImage - */ - if (frame->image) { - - dispose_ximage (this, &frame->shminfo, frame->image); - - if (frame->chunk[0]){ - free (frame->chunk[0]); - frame->chunk[0] = NULL; - } - if (frame->chunk[1]) { - free (frame->chunk[1]); - frame->chunk[1] = NULL; - } - if (frame->chunk[2]) { - free (frame->chunk[2]); - frame->chunk[2] = NULL; - } - - frame->image = NULL; - } - - frame->image = create_ximage (this, &frame->shminfo, - frame->sc.output_width, frame->sc.output_height); - - UNLOCK_DISPLAY(this); + av_freep (&frame->vo_frame.base[0]); + av_freep (&frame->vo_frame.base[1]); + av_freep (&frame->vo_frame.base[2]); + /* bottom black pad for certain crop_top > crop_bottom cases */ if (format == XINE_IMGFMT_YV12) { - frame->vo_frame.pitches[0] = 8*((width + 7) / 8); - frame->vo_frame.pitches[1] = 8*((width + 15) / 16); - frame->vo_frame.pitches[2] = 8*((width + 15) / 16); - frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); - frame->vo_frame.base[1] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[1] * ((height+1)/2), (void **) &frame->chunk[1]); - frame->vo_frame.base[2] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[2] * ((height+1)/2), (void **) &frame->chunk[2]); + pitch = (width + 7) & ~7; + frame->vo_frame.pitches[0] = pitch; + frame->vo_frame.base[0] = av_malloc (pitch * (height + 16)); + memset (frame->vo_frame.base[0] + pitch * height, 0, pitch * 16); + pitch = ((width + 15) & ~15) >> 1; + frame->vo_frame.pitches[1] = pitch; + frame->vo_frame.pitches[2] = pitch; + frame->vo_frame.base[1] = av_malloc (pitch * ((height + 17) / 2)); + memset (frame->vo_frame.base[1] + pitch * height / 2, 128, pitch * 8); + frame->vo_frame.base[2] = av_malloc (pitch * ((height + 17) / 2)); + memset (frame->vo_frame.base[2] + pitch * height / 2, 128, pitch * 8); } else { - frame->vo_frame.pitches[0] = 8*((width + 3) / 4); - frame->vo_frame.base[0] = xine_xmalloc_aligned (16, frame->vo_frame.pitches[0] * height, (void **) &frame->chunk[0]); - frame->chunk[1] = NULL; - frame->chunk[2] = NULL; + pitch = ((width + 3) & ~3) << 1; + frame->vo_frame.pitches[0] = pitch; + frame->vo_frame.base[0] = av_malloc (pitch * (height + 16)); + for (j = pitch * height; j < pitch * (height + 16); j++) + (frame->vo_frame.base[0])[j] = (j & 1) << 7; } - lprintf ("stripe out_ht=%i, deliv_ht=%i\n", - frame->sc.output_height, frame->sc.delivered_height); - - /* - * set up colorspace converter - */ + /* defer the rest to xshm_frame_proc_setup () */ + frame->state &= ~(FS_DONE | FS_LATE); + } - switch (flags) { - case VO_TOP_FIELD: - case VO_BOTTOM_FIELD: - frame->yuv2rgb->configure (frame->yuv2rgb, - frame->sc.delivered_width, - frame->sc.delivered_height, - 2*frame->vo_frame.pitches[0], - 2*frame->vo_frame.pitches[1], - frame->sc.output_width, - frame->sc.output_height, - frame->image->bytes_per_line*2); - break; - case VO_BOTH_FIELDS: - frame->yuv2rgb->configure (frame->yuv2rgb, - frame->sc.delivered_width, - frame->sc.delivered_height, - frame->vo_frame.pitches[0], - frame->vo_frame.pitches[1], - frame->sc.output_width, - frame->sc.output_height, - frame->image->bytes_per_line); - break; - } + if (!isnan (ratio) && (ratio < 1000.0) && (ratio > 0.001) + && (ratio != frame->sc.delivered_ratio)) { + frame->sc.delivered_ratio = ratio; + frame->state &= ~FS_DONE; } - xshm_frame_field ((vo_frame_t *)frame, flags); + if (flags != frame->flags) { + frame->flags = flags; + frame->state &= ~FS_FLAGS; + } } static void xshm_overlay_clut_yuv2rgb(xshm_driver_t *this, vo_overlay_t *overlay, @@ -652,6 +736,8 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { xshm_driver_t *this = (xshm_driver_t *) this_gen; xshm_frame_t *frame = (xshm_frame_t *) frame_gen; + int width = frame->sc.delivered_width - frame->sc.crop_left - frame->sc.crop_right; + int height = frame->sc.delivered_height - frame->sc.crop_top - frame->sc.crop_bottom; /* Alpha Blend here */ if (overlay->rle) { @@ -669,19 +755,19 @@ static void xshm_overlay_blend (vo_driver_t *this_gen, case 16: _x_blend_rgb16 ((uint8_t *)frame->image->data, overlay, frame->sc.output_width, frame->sc.output_height, - frame->sc.delivered_width, frame->sc.delivered_height, + width, height, &this->alphablend_extra_data); break; case 24: _x_blend_rgb24 ((uint8_t *)frame->image->data, overlay, frame->sc.output_width, frame->sc.output_height, - frame->sc.delivered_width, frame->sc.delivered_height, + width, height, &this->alphablend_extra_data); break; case 32: _x_blend_rgb32 ((uint8_t *)frame->image->data, overlay, frame->sc.output_width, frame->sc.output_height, - frame->sc.delivered_width, frame->sc.delivered_height, + width, height, &this->alphablend_extra_data); break; default: @@ -724,6 +810,12 @@ static int xshm_redraw_needed (vo_driver_t *this_gen) { this->sc.delivered_height = this->cur_frame->sc.delivered_height; this->sc.delivered_width = this->cur_frame->sc.delivered_width; this->sc.video_pixel_aspect = this->cur_frame->sc.video_pixel_aspect; + + this->sc.crop_left = this->cur_frame->sc.crop_left; + this->sc.crop_right = this->cur_frame->sc.crop_right; + this->sc.crop_top = this->cur_frame->sc.crop_top; + this->sc.crop_bottom = this->cur_frame->sc.crop_bottom; + if( _x_vo_scale_redraw_needed( &this->sc ) ) { clean_output_area (this, this->cur_frame); @@ -753,6 +845,12 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { this->sc.delivered_height = frame->sc.delivered_height; this->sc.delivered_width = frame->sc.delivered_width; this->sc.video_pixel_aspect = frame->sc.video_pixel_aspect; + + this->sc.crop_left = frame->sc.crop_left; + this->sc.crop_right = frame->sc.crop_right; + this->sc.crop_top = frame->sc.crop_top; + this->sc.crop_bottom = frame->sc.crop_bottom; + if( _x_vo_scale_redraw_needed( &this->sc ) ) { clean_output_area (this, frame); @@ -795,6 +893,27 @@ static void xshm_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) { UNLOCK_DISPLAY(this); lprintf ("display frame done\n"); + + /* just in case somebody changes crop this late - take over for next time */ + /* adjust cropping to what yuv2rgb can handle */ + if (frame_gen->format == XINE_IMGFMT_YV12) { + frame_gen->crop_left &= ~7; + frame_gen->crop_top &= ~1; + } else { + frame_gen->crop_left &= ~3; + } + /* check for crop changes */ + if ((frame_gen->crop_left != frame->sc.crop_left) + || (frame_gen->crop_top != frame->sc.crop_top) + || (frame_gen->crop_right != frame->sc.crop_right) + || (frame_gen->crop_bottom != frame->sc.crop_bottom)) { + frame->sc.crop_left = frame_gen->crop_left; + frame->sc.crop_top = frame_gen->crop_top; + frame->sc.crop_right = frame_gen->crop_right; + frame->sc.crop_bottom = frame_gen->crop_bottom; + frame->state &= ~FS_DONE; + frame->state |= FS_LATE; + } } static int xshm_get_property (vo_driver_t *this_gen, int property) { @@ -806,11 +925,11 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { case VO_PROP_MAX_NUM_FRAMES: return 15; case VO_PROP_BRIGHTNESS: - return this->yuv2rgb_brightness; + return this->brightness; case VO_PROP_CONTRAST: - return this->yuv2rgb_contrast; + return this->contrast; case VO_PROP_SATURATION: - return this->yuv2rgb_saturation; + return this->saturation; case VO_PROP_WINDOW_WIDTH: return this->sc.gui_width; case VO_PROP_WINDOW_HEIGHT: @@ -825,7 +944,7 @@ static int xshm_get_property (vo_driver_t *this_gen, int property) { return this->cur_frame->sc.output_yoffset; default: xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xshm: tried to get unsupported property %d\n", property); + LOG_MODULE ": tried to get unsupported property %d\n", property); } return 0; @@ -835,47 +954,36 @@ static int xshm_set_property (vo_driver_t *this_gen, int property, int value) { xshm_driver_t *this = (xshm_driver_t *) this_gen; - if ( property == VO_PROP_ASPECT_RATIO) { - + switch (property) { + case VO_PROP_ASPECT_RATIO: if (value>=XINE_VO_ASPECT_NUM_RATIOS) value = XINE_VO_ASPECT_AUTO; this->sc.user_ratio = value; xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xshm: aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name(value)); - - } else if (property == VO_PROP_BRIGHTNESS) { - - this->yuv2rgb_brightness = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation); + LOG_MODULE ": aspect ratio changed to %s\n", _x_vo_scale_aspect_ratio_name_table[value]); + break; + case VO_PROP_BRIGHTNESS: + this->brightness = value; + this->cm_active = 0; this->sc.force_redraw = 1; + break; - } else if (property == VO_PROP_CONTRAST) { - - this->yuv2rgb_contrast = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation); - + case VO_PROP_CONTRAST: + this->contrast = value; + this->cm_active = 0; this->sc.force_redraw = 1; + break; - } else if (property == VO_PROP_SATURATION) { - - this->yuv2rgb_saturation = value; - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation); - + case VO_PROP_SATURATION: + this->saturation = value; + this->cm_active = 0; this->sc.force_redraw = 1; + break; - } else { + default: xprintf (this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xshm: tried to set unsupported property %d\n", property); + LOG_MODULE ": tried to set unsupported property %d\n", property); } return value; @@ -999,6 +1107,8 @@ static void xshm_dispose (vo_driver_t *this_gen) { this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + cm_close (this); + LOCK_DISPLAY(this); XFreeGC(this->display, this->gc); UNLOCK_DISPLAY(this); @@ -1049,7 +1159,7 @@ static int ImlibPaletteLUTGet(xshm_driver_t *this) { } -static char *visual_class_name(Visual *visual) { +static const char *visual_class_name(Visual *visual) { switch (visual->class) { case StaticGray: @@ -1167,7 +1277,7 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v } else { xprintf(this->xine, XINE_VERBOSITY_LOG, - _("video_out_xshm: MIT shared memory extension not present on display.\n")); + _("%s: MIT shared memory extension not present on display.\n"), LOG_MODULE); this->use_shm = 0; } @@ -1188,8 +1298,8 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v swapped = cpu_byte_order != this->image_byte_order; xprintf(this->xine, XINE_VERBOSITY_DEBUG, - "video_out_xshm: video mode depth is %d (%d bpp), %s, %sswapped,\n" - "\tred: %08lx, green: %08lx, blue: %08lx\n", + LOG_MODULE ": video mode depth is %d (%d bpp), %s, %sswapped,\n" + LOG_MODULE ": red: %08lx, green: %08lx, blue: %08lx\n", this->depth, this->bpp, visual_class_name(this->visual), swapped ? "" : "not ", @@ -1251,20 +1361,17 @@ static vo_driver_t *xshm_open_plugin_2 (video_driver_class_t *class_gen, const v if (!mode) { xprintf (this->xine, XINE_VERBOSITY_LOG, - _("video_out_xshm: your video mode was not recognized, sorry :-(\n")); + _("%s: your video mode was not recognized, sorry :-(\n"), LOG_MODULE); return NULL; } - this->yuv2rgb_brightness = 0; - this->yuv2rgb_contrast = 128; - this->yuv2rgb_saturation = 128; + cm_init (this); + + this->brightness = 0; + this->contrast = 128; + this->saturation = 128; - this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, - this->yuv2rgb_cmap); - this->yuv2rgb_factory->set_csc_levels (this->yuv2rgb_factory, - this->yuv2rgb_brightness, - this->yuv2rgb_contrast, - this->yuv2rgb_saturation); + this->yuv2rgb_factory = yuv2rgb_factory_init (mode, swapped, this->yuv2rgb_cmap); LOCK_DISPLAY(this); this->xoverlay = x11osd_create (this->xine, this->display, this->screen, @@ -1294,28 +1401,13 @@ static vo_driver_t *xshm_open_plugin_old (video_driver_class_t *class_gen, const /* * class functions */ - -static char* xshm_get_identifier (video_driver_class_t *this_gen) { - return "XShm"; -} - -static char* xshm_get_description (video_driver_class_t *this_gen) { - return _("xine video output plugin using the MIT X shared memory extension"); -} - -static void xshm_dispose_class (video_driver_class_t *this_gen) { - xshm_class_t *this = (xshm_class_t *) this_gen; - - free (this); -} - static void *xshm_init_class (xine_t *xine, void *visual_gen) { xshm_class_t *this = (xshm_class_t *) calloc(1, sizeof(xshm_class_t)); this->driver_class.open_plugin = xshm_open_plugin_old; - this->driver_class.get_identifier = xshm_get_identifier; - this->driver_class.get_description = xshm_get_description; - this->driver_class.dispose = xshm_dispose_class; + this->driver_class.identifier = "XShm"; + this->driver_class.description = N_("xine video output plugin using the MIT X shared memory extension"); + this->driver_class.dispose = default_video_driver_class_dispose; this->config = xine->config; this->xine = xine; @@ -1348,7 +1440,7 @@ static const vo_info_t vo_info_xshm_2 = { const plugin_info_t xine_plugin_info[] EXPORTED = { /* type, API, "name", version, special_info, init_function */ - { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class }, - { PLUGIN_VIDEO_OUT, 21, "xshm", XINE_VERSION_CODE, &vo_info_xshm_2, xshm_init_class_2 }, + { PLUGIN_VIDEO_OUT, 22, "xshm", XINE_VERSION_CODE, &vo_info_xshm, xshm_init_class }, + { PLUGIN_VIDEO_OUT, 22, "xshm", XINE_VERSION_CODE, &vo_info_xshm_2, xshm_init_class_2 }, { PLUGIN_NONE, 0, "", 0, NULL, NULL } }; |