summaryrefslogtreecommitdiff
path: root/src/video_out/video_out_xshm.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/video_out/video_out_xshm.c')
-rw-r--r--src/video_out/video_out_xshm.c642
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 }
};