From 8ccc88d005e54bfb8ef247e841f820a4d742ccd0 Mon Sep 17 00:00:00 2001 From: Christophe Thommeret Date: Tue, 8 Apr 2008 15:03:13 +0100 Subject: New video out plugin ("raw") Here is a new video output plugin that passes raw data to the front end through supplied callbacks. --HG-- extra : transplant_source : -AT%2A%0A%EB%F5%1Eu4%9E%12%C4%B8%0B%87%13%A5%9D%CA --- ChangeLog | 1 + include/xine.h.in | 71 +++++ src/video_out/Makefile.am | 11 +- src/video_out/video_out_raw.c | 614 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 694 insertions(+), 3 deletions(-) create mode 100644 src/video_out/video_out_raw.c diff --git a/ChangeLog b/ChangeLog index 3f115c6b0..981e4961c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -7,6 +7,7 @@ xine-lib (1.1.12) 2008-??-?? * Various Real codec improvements, including: - RV20 no longer causes segfaults (observed on amd64); - Cook is now handled by ffmpeg. + * Added a video output plugin intended for passing raw data to the front end. xine-lib (1.1.11.1) 2008-03-30 * Security fixes: diff --git a/include/xine.h.in b/include/xine.h.in index 979094779..c97d778d4 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -175,6 +175,7 @@ void xine_close_video_driver (xine_t *self, xine_video_port_t *driver) XINE_PRO #define XINE_VISUAL_TYPE_CACA 8 #define XINE_VISUAL_TYPE_MACOSX 9 #define XINE_VISUAL_TYPE_XCB 11 +#define XINE_VISUAL_TYPE_RAW 12 /* * free all resources, close all plugins, close engine. @@ -1285,6 +1286,76 @@ typedef struct { } xcb_visual_t; +/************************************************** + * XINE_VO_RAW struct definitions + *************************************************/ +/* frame_format definitions */ +#define XINE_VORAW_YV12 1 +#define XINE_VORAW_YUY2 2 +#define XINE_VORAW_RGB 4 + +/* maximum number of overlays the raw driver can handle */ +#define XINE_VORAW_MAX_OVL 16 + +/* raw_overlay_t struct used in raw_overlay_cb callback */ +typedef struct { + uint8_t *ovl_rgba; + int ovl_w, ovl_h; /* overlay's width and height */ + int ovl_x, ovl_y; /* overlay's top-left display position */ +} raw_overlay_t; + +/* this is the visual data struct any raw gui + * must supply to the xine_open_video_driver call + * ("data" parameter) + */ +typedef struct { + void *user_data; + + /* OR'ed frame_format + * a frontend must at least support rgb + * a frontend supporting yuv must support both yv12 and yuy2 + * then possible combinations are: + * XINE_VORAW_RGB ( rgb ) + * XINE_VORAW_YV12|XINE_VORAW_YUY2|XINE_VORAW_RGB ( yv12, yuy2 and rgb ) + * + * Be aware that rgb requires more cpu than yuv, + * so avoid its usage for video playback. + * However, it's usefull for single frame capture (e.g. thumbs) + */ + int supported_formats; + + /* raw output callback + * this will be called by the video driver for every frame + * + * If frame_format==XINE_VORAW_YV12, data0 points to frame_width*frame_height Y values + * data1 points to (frame_width/2)*(frame_height/2) U values + * data2 points to (frame_width/2)*(frame_height/2) V values + * + * If frame_format==XINE_VORAW_YUY2, data0 points to frame_width*frame_height*2 YU/Y²V values + * data1 is NULL + * data2 is NULL + * + * If frame_format==XINE_VORAW_RGB, data0 points to frame_width*frame_height*3 RGB values + * data1 is NULL + * data2 is NULL + */ + void (*raw_output_cb) (void *user_data, int frame_format, + int frame_width, int frame_height, + double frame_aspect, + void *data0, void *data1, void *data2); + + /* raw overlay callback + * this will be called by the video driver for every new overlay state + * overlays_array points to an array of num_ovl raw_overlay_t + * Note that num_ovl can be 0, meaning "end of overlay display" + * num_ovl is at most XINE_VORAW_MAX_OVL */ + void (*raw_overlay_cb) (void *user_data, int num_ovl, + raw_overlay_t *overlays_array); +} raw_visual_t; +/********************************************** + * end of vo_raw defs + *********************************************/ + /* * this is the visual data struct any fb gui * may supply to the xine_open_video_driver call diff --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am index 6376e7629..28aca041b 100644 --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -100,6 +100,7 @@ xineplug_LTLIBRARIES = $(xshm_module) $(xv_module) $(xvmc_module) \ $(xxmc_module) \ $(xcbshm_module) \ $(xcbxv_module) \ + xineplug_vo_out_raw.la \ xineplug_vo_out_none.la xineplug_vo_out_xcbshm_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_xcbshm.c $(XCBOSD) @@ -134,7 +135,7 @@ xineplug_vo_out_opengl_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(OPENGL_LIBS) \ $(GLUT_LIBS) $(GLU_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(DYNAMIC_LD_LIBS) $(LTLIBINTL) xineplug_vo_out_opengl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(MLIB_CFLAGS) -fno-strict-aliasing -xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c +xineplug_vo_out_syncfb_la_SOURCES = video_out_syncfb.c xineplug_vo_out_syncfb_la_LIBADD = $(XINE_LIB) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_syncfb_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) @@ -177,11 +178,11 @@ xineplug_vo_out_sdl_la_SOURCES = video_out_sdl.c xineplug_vo_out_sdl_la_LIBADD = $(XINE_LIB) $(SDL_LIBS) $(X_LIBS) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_sdl_la_CFLAGS = $(VISIBILITY_FLAG) $(X_CFLAGS) $(SDL_CFLAGS) -xineplug_vo_out_stk_la_SOURCES = video_out_stk.c +xineplug_vo_out_stk_la_SOURCES = video_out_stk.c xineplug_vo_out_stk_la_LIBADD = $(XINE_LIB) $(LIBSTK_LIBS) $(PTHREAD_LIBS) xineplug_vo_out_stk_la_CFLAGS = $(VISIBILITY_FLAG) $(LIBSTK_CFLAGS) -xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c +xineplug_vo_out_directx_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c video_out_directx.c xineplug_vo_out_directx_la_CPPFLAGS = $(AM_CPPFLAGS) $(DIRECTX_CPPFLAGS) xineplug_vo_out_directx_la_LIBADD = $(XINE_LIB) $(DIRECTX_VIDEO_LIBS) $(PTHREAD_LIBS) xineplug_vo_out_directx_la_CFLAGS = $(VISIBILITY_FLAG) @@ -190,6 +191,10 @@ xineplug_vo_out_none_la_SOURCES = video_out_none.c xineplug_vo_out_none_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) xineplug_vo_out_none_la_CFLAGS = $(VISIBILITY_FLAG) +xineplug_vo_out_raw_la_SOURCES = yuv2rgb.c yuv2rgb_mmx.c yuv2rgb_mlib.c video_out_raw.c +xineplug_vo_out_raw_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) $(LTLIBINTL) +xineplug_vo_out_raw_la_CFLAGS = $(VISIBILITY_FLAG) + xineplug_vo_out_macosx_la_SOURCES = video_out_macosx.m xineplug_vo_out_macosx_la_CPPFLAGS = $(AM_CPPFLAGS) $(X_CFLAGS) $(MLIB_CFLAGS) xineplug_vo_out_macosx_la_OBJCFLAGS = $(VISIBILITY_FLAG) diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c new file mode 100644 index 000000000..17cbc1b4e --- /dev/null +++ b/src/video_out/video_out_raw.c @@ -0,0 +1,614 @@ +/* + * Copyright (C) 2007 the xine project + * + * This file is part of xine, a free video player. + * + * xine is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * xine is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * + * video_out_raw.c, a video output plugin to pass raw data to frontend + * + * Written by Christophe Thommeret , + * based on others' video output plugins. + * + */ + +/* #define LOG */ +#define LOG_MODULE "video_out_raw" + +/* Allow frontend some time to render frames +* However, frontends are strongly advised to render synchronously */ +#define NUM_FRAMES_BACKLOG 4 +#define BYTES_PER_PIXEL 3 + + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "xine.h" +#include "video_out.h" + +#include "xine_internal.h" +#include "yuv2rgb.h" +#include "xineutils.h" + + + +typedef struct { + vo_frame_t vo_frame; + + int width, height, format, flags; + double ratio; + uint8_t *chunk[4]; /* mem alloc by xmalloc_aligned */ + uint8_t *rgb, *rgb_dst; + yuv2rgb_t *yuv2rgb; /* yuv2rgb converter set up for this frame */ + +} raw_frame_t; + +typedef struct { + vo_driver_t vo_driver; + + void *user_data; + + void (*raw_output_cb) (void *user_data, int format, + int frame_width, int frame_height, double frame_aspect, + void *data0, void *data1, void *data2); + + void (*raw_overlay_cb) (void *user_data, int num_ovl, + raw_overlay_t *overlays_p); + + int ovl_changed; + raw_overlay_t overlays[XINE_VORAW_MAX_OVL]; + yuv2rgb_t *ovl_yuv2rgb; + + int doYV12; + int doYUY2; + yuv2rgb_factory_t *yuv2rgb_factory; + /* Frame state */ + raw_frame_t *frame[NUM_FRAMES_BACKLOG]; + xine_t *xine; +} raw_driver_t; + + +typedef struct { + video_driver_class_t driver_class; + xine_t *xine; +} raw_class_t; + + + +static void raw_overlay_clut_yuv2rgb(raw_driver_t *this, vo_overlay_t *overlay, raw_frame_t *frame) +{ + int i; + clut_t* clut = (clut_t*) overlay->color; + + if (!overlay->rgb_clut) { + for ( i=0; icolor)/sizeof(overlay->color[0]); i++ ) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->rgb_clut++; + } + if (!overlay->hili_rgb_clut) { + clut = (clut_t*) overlay->hili_color; + for ( i=0; icolor)/sizeof(overlay->color[0]); i++) { + *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(frame->yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); + } + overlay->hili_rgb_clut++; + } +} + + +static int raw_process_ovl( raw_driver_t *this_gen, vo_overlay_t *overlay ) +{ + raw_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; + + if ( overlay->width<=0 || overlay->height<=0 ) + return 0; + + if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) ) + ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 ); + ovl->ovl_w = overlay->width; + ovl->ovl_h = overlay->height; + ovl->ovl_x = overlay->x; + ovl->ovl_y = overlay->y; + + int num_rle = overlay->num_rle; + rle_elem_t *rle = overlay->rle; + uint8_t *rgba = ovl->ovl_rgba; + clut_t *low_colors = (clut_t*)overlay->color; + clut_t *hili_colors = (clut_t*)overlay->hili_color; + uint8_t *low_trans = overlay->trans; + uint8_t *hili_trans = overlay->hili_trans; + clut_t *colors; + uint8_t *trans; + uint8_t alpha; + int rlelen = 0; + uint8_t clr = 0; + int i, pos=0, x, y; + + while ( num_rle>0 ) { + x = pos%ovl->ovl_w; + y = pos/ovl->ovl_w; + if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) { + colors = hili_colors; + trans = hili_trans; + } + else { + colors = low_colors; + trans = low_trans; + } + rlelen = rle->len; + clr = rle->color; + alpha = trans[clr]; + for ( i=0; iovl_changed; +} + + +static void raw_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + + if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL ) + return; + + if (overlay->rle) { + if (!overlay->rgb_clut || !overlay->hili_rgb_clut) + raw_overlay_clut_yuv2rgb (this, overlay, frame); + if ( raw_process_ovl( this, overlay ) ) + ++this->ovl_changed; + } +} + + +static void raw_overlay_end (vo_driver_t *this_gen, vo_frame_t *vo_img) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + int i; + + if ( !this->ovl_changed ) + return; + + this->raw_overlay_cb( this->user_data, this->ovl_changed-1, &this->overlays ); + + this->ovl_changed = 0; +} + + +static void raw_frame_proc_slice (vo_frame_t *vo_img, uint8_t **src) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + + vo_img->proc_called = 1; + if (! frame->rgb_dst) + return; + + if( frame->vo_frame.crop_left || frame->vo_frame.crop_top || + frame->vo_frame.crop_right || frame->vo_frame.crop_bottom ) + { + /* TODO: ?!? */ + return; + } + + 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]); +} + + + +static void raw_frame_field (vo_frame_t *vo_img, int which_field) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + raw_driver_t *this = (raw_driver_t *) vo_img->driver; + + if ( frame->format==XINE_IMGFMT_YV12 && this->doYV12 ) { + frame->rgb_dst = 0; + return; + } + else if ( frame->format==XINE_IMGFMT_YUY2 && this->doYUY2 ) { + frame->rgb_dst = 0; + return; + } + + switch (which_field) { + case VO_TOP_FIELD: + frame->rgb_dst = (uint8_t *)frame->rgb; + break; + case VO_BOTTOM_FIELD: + frame->rgb_dst = (uint8_t *)frame->rgb + frame->width * BYTES_PER_PIXEL; + break; + case VO_BOTH_FIELDS: + frame->rgb_dst = (uint8_t *)frame->rgb; + break; + } + + frame->yuv2rgb->next_slice (frame->yuv2rgb, NULL); +} + + + +static void raw_frame_dispose (vo_frame_t *vo_img) +{ + raw_frame_t *frame = (raw_frame_t *) vo_img ; + + frame->yuv2rgb->dispose (frame->yuv2rgb); + + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame->chunk[3]); + free (frame); +} + + + +static vo_frame_t *raw_alloc_frame (vo_driver_t *this_gen) +{ + raw_frame_t *frame; + raw_driver_t *this = (raw_driver_t *) this_gen; + + frame = (raw_frame_t *) xine_xmalloc (sizeof (raw_frame_t)); + + if (!frame) + return NULL; + + pthread_mutex_init (&frame->vo_frame.mutex, NULL); + + /* + * supply required functions/fields + */ + frame->vo_frame.proc_slice = raw_frame_proc_slice; + frame->vo_frame.proc_frame = NULL; + frame->vo_frame.field = raw_frame_field; + frame->vo_frame.dispose = raw_frame_dispose; + frame->vo_frame.driver = this_gen; + + /* + * colorspace converter for this frame + */ + frame->yuv2rgb = this->yuv2rgb_factory->create_converter (this->yuv2rgb_factory); + + return (vo_frame_t *) frame; +} + + + +static void raw_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) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + + /* Check frame size and format and reallocate if necessary */ + if ((frame->width != width) + || (frame->height != height) + || (frame->format != format) + || (frame->flags != flags)) { +/* lprintf ("updating frame to %d x %d (ratio=%g, format=%08x)\n", width, height, ratio, format); */ + + flags &= VO_BOTH_FIELDS; + + /* (re-) allocate render space */ + free (frame->chunk[0]); + free (frame->chunk[1]); + free (frame->chunk[2]); + free (frame->chunk[3]); + + 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]); + } 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; + } + frame->rgb = xine_xmalloc_aligned (16, BYTES_PER_PIXEL*width*height, + (void **) &frame->chunk[3]); + + /* set up colorspace converter */ + switch (flags) { + 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], + width, + height, + BYTES_PER_PIXEL*width * 2); + break; + case VO_BOTH_FIELDS: + frame->yuv2rgb->configure (frame->yuv2rgb, + width, + height, + frame->vo_frame.pitches[0], + frame->vo_frame.pitches[1], + width, + height, + BYTES_PER_PIXEL*width); + break; + } + + frame->width = width; + frame->height = height; + frame->format = format; + + raw_frame_field ((vo_frame_t *)frame, flags); + } + + frame->ratio = ratio; +} + + + +static int raw_redraw_needed (vo_driver_t *this_gen) +{ + return 0; +} + + + +static void raw_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + raw_frame_t *frame = (raw_frame_t *) frame_gen; + int i; + + if (this->frame[NUM_FRAMES_BACKLOG-1]) { + this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame.free (&this->frame[NUM_FRAMES_BACKLOG-1]->vo_frame); + } + for (i = NUM_FRAMES_BACKLOG-1; i > 0; i--) + this->frame[i] = this->frame[i-1]; + this->frame[0] = frame; + + if ( frame->rgb_dst ) { + this->raw_output_cb( this->user_data, XINE_VORAW_RGB, frame->width, frame->height, frame->ratio, frame->rgb, 0, 0 ); + } + else if ( frame->format==XINE_IMGFMT_YV12 ) { + this->raw_output_cb( this->user_data, XINE_VORAW_YV12, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], + frame->vo_frame.base[1], frame->vo_frame.base[2] ); + } + else { + this->raw_output_cb( this->user_data, XINE_VORAW_YUY2, frame->width, frame->height, frame->ratio, frame->vo_frame.base[0], 0, 0 ); + } +} + + + +static int raw_get_property (vo_driver_t *this_gen, int property) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + + switch (property) { + case VO_PROP_ASPECT_RATIO: + return XINE_VO_ASPECT_AUTO; + case VO_PROP_MAX_NUM_FRAMES: + return 15; + case VO_PROP_BRIGHTNESS: + return 0; + case VO_PROP_CONTRAST: + return 128; + case VO_PROP_SATURATION: + return 128; + case VO_PROP_WINDOW_WIDTH: + return 0; + case VO_PROP_WINDOW_HEIGHT: + return 0; + default: + return 0; + } +} + + + +static int raw_set_property (vo_driver_t *this_gen, int property, int value) +{ + return value; +} + + + +static void raw_get_property_min_max (vo_driver_t *this_gen, int property, int *min, int *max) +{ + *min = 0; + *max = 0; +} + + + +static int raw_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) +{ + return 0; +} + + + +static uint32_t raw_get_capabilities (vo_driver_t *this_gen) +{ + uint32_t capabilities = VO_CAP_YV12 | VO_CAP_YUY2; + return capabilities; +} + + + +static void raw_dispose (vo_driver_t *this_gen) +{ + raw_driver_t *this = (raw_driver_t *) this_gen; + int i; + + for (i = 0; i < NUM_FRAMES_BACKLOG; i++) + if (this->frame[i]) + this->frame[i]->vo_frame.dispose (&this->frame[i]->vo_frame); + + this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); + + for ( i=0; ioverlays[i].ovl_rgba ); + + free (this); +} + + + +static vo_driver_t *raw_open_plugin (video_driver_class_t *class_gen, const void *visual_gen) +{ + raw_class_t *class = (raw_class_t *) class_gen; + raw_visual_t *visual = (raw_visual_t *) visual_gen; + raw_driver_t *this; + int i; + + this = (raw_driver_t *) xine_xmalloc (sizeof (raw_driver_t)); + + if (!this) + return NULL; + + this->raw_output_cb = visual->raw_output_cb; + this->user_data = visual->user_data; + this->xine = class->xine; + this->raw_overlay_cb = visual->raw_overlay_cb; + this->doYV12 = visual->supported_formats&XINE_VORAW_YV12; + this->doYUY2 = visual->supported_formats&XINE_VORAW_YUY2; + + this->vo_driver.get_capabilities = raw_get_capabilities; + this->vo_driver.alloc_frame = raw_alloc_frame; + this->vo_driver.update_frame_format = raw_update_frame_format; + this->vo_driver.overlay_begin = raw_overlay_begin; + this->vo_driver.overlay_blend = raw_overlay_blend; + this->vo_driver.overlay_end = raw_overlay_end; + this->vo_driver.display_frame = raw_display_frame; + this->vo_driver.get_property = raw_get_property; + this->vo_driver.set_property = raw_set_property; + this->vo_driver.get_property_min_max = raw_get_property_min_max; + this->vo_driver.gui_data_exchange = raw_gui_data_exchange; + this->vo_driver.dispose = raw_dispose; + this->vo_driver.redraw_needed = raw_redraw_needed; + + this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 1, NULL); /* converts to rgb */ + + for (i = 0; i < NUM_FRAMES_BACKLOG; i++) + this->frame[i] = 0; + + for ( i=0; ioverlays[i].ovl_w = this->overlays[i].ovl_h = 2; + this->overlays[i].ovl_rgba = (uint8_t*)malloc(2*2*4); + this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; + } + this->ovl_changed = 0; + + /* we have to use a second converter for overlays + * because "MODE_24_BGR, 1 (swap)" breaks overlays conversion */ + yuv2rgb_factory_t *factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); + this->ovl_yuv2rgb = factory->create_converter( factory ); + factory->dispose( factory ); + + return &this->vo_driver; +} + +/* + * class functions + */ + +static char* raw_get_identifier (video_driver_class_t *this_gen) +{ + return "raw"; +} + + + +static char* raw_get_description (video_driver_class_t *this_gen) +{ + return _("xine video output plugin passing raw data to supplied callback"); +} + + + +static void raw_dispose_class (video_driver_class_t *this_gen) +{ + raw_class_t *this = (raw_class_t *) this_gen; + free (this); +} + + + +static void *raw_init_class (xine_t *xine, void *visual_gen) +{ + raw_class_t *this = (raw_class_t *) xine_xmalloc (sizeof (raw_class_t)); + + this->driver_class.open_plugin = raw_open_plugin; + this->driver_class.get_identifier = raw_get_identifier; + this->driver_class.get_description = raw_get_description; + this->driver_class.dispose = raw_dispose_class; + this->xine = xine; + + return this; +} + + + +static const vo_info_t vo_info_raw = { + 7, /* priority */ + XINE_VISUAL_TYPE_RAW /* visual type */ +}; + + +/* + * exported plugin catalog entry + */ + +const plugin_info_t xine_plugin_info[] EXPORTED = { + /* type, API, "name", version, special_info, init_function */ + { PLUGIN_VIDEO_OUT, 21, "raw", XINE_VERSION_CODE, &vo_info_raw, raw_init_class }, + { PLUGIN_NONE, 0, "", 0, NULL, NULL } +}; -- cgit v1.2.3 From f994871d8dd8c599de5ecb3c92a7b33a90bea400 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 8 Apr 2008 15:21:05 +0100 Subject: Bump version to 1.1.12; bump interface age due to the new video-out plugin. --HG-- extra : transplant_source : %ED%E5%16J%82%ECe%85%7F%FA%95%1Dv%8D%88%EE%AC%FE%40%9E --- configure.ac | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 9acb49427..fc569a7d4 100644 --- a/configure.ac +++ b/configure.ac @@ -16,9 +16,9 @@ dnl XINE_SUB += 1; XINE_PATCH = ''; continue with XINE_LT_* values below dnl XINE_MAJOR=1 XINE_MINOR=1 -XINE_SUB=11 +XINE_SUB=12 dnl XINE_PATCH should be left empty or set to ".1" or ".2" or something similar -XINE_PATCH=.1 +XINE_PATCH= dnl Release series number (usually $XINE_MAJOR.$XINE_MINOR) XINE_SERIES=1.1 @@ -53,9 +53,9 @@ dnl are platform dependent dnl * in Linux, the library will be named dnl libname.so.(XINE_LT_CURRENT - XINE_LT_AGE).XINE_LT_AGE.XINE_LT_REVISION -XINE_LT_CURRENT=21 +XINE_LT_CURRENT=22 XINE_LT_REVISION=0 -XINE_LT_AGE=20 +XINE_LT_AGE=21 dnl for a release tarball do "rm .cvsversion" before "make dist" if test -f "${srcdir-.}/.cvsversion"; then -- cgit v1.2.3 From 8b92842f51f9a4f9f9dd3b3933219ed7baaa5d3b Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Tue, 8 Apr 2008 15:29:42 +0100 Subject: Bump packaging version. --HG-- extra : transplant_source : %F0q%BB%C9%FC7%14%3F%20%14%885WF%84mM%99%D2G --- debian/changelog | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/debian/changelog b/debian/changelog index 9f2640f7d..cd6e353a3 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,4 @@ -xine-lib (1.1.10.1+hg-0) unstable; urgency=low +xine-lib (1.1.12~hg-0) unstable; urgency=low [ Darren Salt ] * Hg snapshot. @@ -7,7 +7,7 @@ xine-lib (1.1.10.1+hg-0) unstable; urgency=low * remove gs from build-dependencies * change the maintainer field to xine-devel@lists.sourceforge.net. - -- Darren Salt Thu, 07 Feb 2008 17:52:34 +0000 + -- Darren Salt Tue, 08 Apr 2008 15:29:17 +0100 xine-lib (1.1.5~cvs-0) unstable; urgency=low -- cgit v1.2.3 From ee56e3667e66059efeb04ce767c35ab1c67ddd41 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Wed, 9 Apr 2008 17:42:21 +0100 Subject: Pull in some packaging changes from xine-lib-deb. --- debian/control | 22 +++++++++++----------- debian/rules | 25 +++++++++++++++++++------ 2 files changed, 30 insertions(+), 17 deletions(-) diff --git a/debian/control b/debian/control index a1faae54c..f83f8f650 100644 --- a/debian/control +++ b/debian/control @@ -7,23 +7,23 @@ Build-Depends: debhelper (>= 5.0.1), binutils (>= 2.12.90.0.9), pkg-config, libavcodec-dev (>= 0.cvs20070307-3) | libavcodeccvs-dev, libavformat-dev (>= 0.cvs20070307-3) | libavformatcvs-dev, libpostproc-dev (>= 0.cvs20070307-3) | libpostproccvs-dev, - libxcb-xinerama0-dev | libxv-dev (<< 1:1.0.3), libxcb-xv0-dev | libxv-dev (<< 1:1.0.3), - libxcb-xvmc0-dev | libxv-dev (<< 1:1.0.3), libxcb-shm0-dev | libxv-dev (<< 1:1.0.3), + libxcb-xv0-dev | libxv-dev (<< 1:1.0.3), + libxcb-shm0-dev | libxv-dev (<< 1:1.0.3), libxcb-shape0-dev | libxv-dev (<< 1:1.0.3), - libxinerama-dev, libxv-dev, libxvmc-dev, libxt-dev, + libxinerama-dev, libxv-dev, libxvmc-dev, libxt-dev, libasound2-dev [!kfreebsd-i386 !kfreebsd-amd64 !hurd-i386], + libcam-dev [kfreebsd-i386 kfreebsd-amd64], libaa1-dev, libcaca-dev, libmodplug-dev, - libmagick9-dev, libpng12-dev, libfreetype6-dev, + libjack-dev, libpulse-dev, libartsc0-dev, + libmagick9-dev | libmagick-dev, libpng12-dev, libfreetype6-dev, libogg-dev, libvorbis-dev, libtheora-dev, libesd0-dev, libgnomevfs2-dev, - zlib1g-dev, libartsc0-dev, - liblircclient-dev, libjack0.100.0-dev | libjack-dev, + liblircclient-dev, libdirectfb-dev (>= 0.9.22), libgtk2.0-dev, - libflac-dev, libpulse-dev, libsdl1.2-dev, libwavpack-dev, - libsmbclient-dev, libspeex-dev, libmng-dev, - libmad0-dev, libmpcdec-dev, libcdio-dev (>= 0.76-1), - w3m, transfig, sgmltools-lite, gs-gpl | gs -Build-Conflicts: libdvdnav-dev, libvcdinfo-dev + libflac-dev, libsdl1.2-dev, libwavpack-dev, + libsmbclient-dev, libspeex-dev, libmng-dev, + libmad0-dev, libmpcdec-dev, libcdio-dev (>= 0.76-1), + zlib1g-dev, w3m, transfig, sgmltools-lite, gs-gpl | gs Standards-Version: 3.7.2 Package: libxine-dev diff --git a/debian/rules b/debian/rules index 604954649..b44bccd81 100755 --- a/debian/rules +++ b/debian/rules @@ -34,6 +34,18 @@ ifeq (,$(findstring nostrip,$(DEB_BUILD_OPTIONS))) BUILD_TARGET := debug endif +ifneq (,$(findstring mips,$(DEB_HOST_GNU_TYPE))) + DEB_BUILD_CONFIG_OPTIONS += PTHREAD_LIBS="-lpthread" +endif + +# taken from the qemu package +# Support multiple makes at once +ifneq (,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) +NJOBS := $(patsubst parallel=%,%,$(filter parallel=%,$(DEB_BUILD_OPTIONS))) +else +NJOBS := 1 +endif + # note also "noauto" to inhibit running of autogen.sh # the "optimize" flag disables compatibility hacks @@ -67,6 +79,7 @@ CONFIGURE_FLAGS := --prefix=/usr \ --with-external-ffmpeg \ --with-freetype \ --with-wavpack \ + --enable-ipv6 \ $(DEB_BUILD_CONFIG_OPTIONS) \ CFLAGS="$(CFLAGS)" @@ -87,7 +100,7 @@ endif build: configure-stamp build-stamp build-stamp: dh_testdir - $(MAKE) + $(MAKE) -j $(NJOBS) touch build-stamp update-config-sub-guess: @@ -100,11 +113,11 @@ clean: dh_testdir dh_testroot rm -f build-stamp configure-stamp po/*.gmo po/stamp-po - -$(MAKE) distclean - # remove more cruft leftover by autohell - rm -f doc/faq/faq.html doc/faq/faq.txt doc/hackersguide/hackersguide.html m4/caca.m4 - -test -f .noauto || find . -name Makefile.in -print | xargs -r rm - test -f .noauto || rm -rf compile config.guess configure depcomp install-sh ltmain.sh missing aclocal.m4 include/configure.h.in + if test -f .noauto; then \ + [ ! -f Makefile ] || $(MAKE) distclean; \ + else \ + [ ! -f Makefile ] || $(MAKE) maintainer-clean; \ + fi dh_clean install: build -- cgit v1.2.3 From ce8b89d12b5c2d53f56d8a2325afeacc6cc61b4d Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 11 Apr 2008 15:02:57 +0100 Subject: Remove an unnecessary volume scale conversion. The value being converted is already of the correct type. --- src/audio_out/audio_pulse_out.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c index cefcc7367..05b61c309 100644 --- a/src/audio_out/audio_pulse_out.c +++ b/src/audio_out/audio_pulse_out.c @@ -217,7 +217,7 @@ static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info return; this->cvolume = info->volume; - this->swvolume = pa_sw_volume_to_linear(pa_cvolume_avg(&info->volume)); + this->swvolume = pa_cvolume_avg(&info->volume); this->muted = info->mute; } -- cgit v1.2.3 From 41573e618cf0989673677daefd1be7871506d0ef Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 11 Apr 2008 15:20:10 +0100 Subject: Test for pulseaudio 0.9.7 to determine which muting method to use. --- configure.ac | 10 ++++++++++ src/audio_out/audio_pulse_out.c | 16 ++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/configure.ac b/configure.ac index fc569a7d4..127e23c0d 100644 --- a/configure.ac +++ b/configure.ac @@ -1099,6 +1099,16 @@ AC_ARG_WITH([pulseaudio], if test "x$with_pulseaudio" != "xno"; then PKG_CHECK_MODULES([PULSEAUDIO], [libpulse], [have_pulseaudio="yes"], [have_pulseaudio="no"]) + if test x"$have_pulseaudio" = xyes; then + AC_MSG_CHECKING([for pulseaudio >= 0.9.7]) + PKG_CHECK_EXISTS([libpulse >= 0.9.7], + [have_pulseaudio_0_9_7="yes"], + [have_pulseaudio_0_9_7="no"]) + AC_MSG_RESULT([$have_pulseaudio_0_9_7]) + if test x"$have_pulseaudio_0_9_7" = xyes; then + AC_DEFINE([HAVE_PULSEAUDIO_0_9_7], 1, [define this if you have pulseaudio >= 0.9.7]) + fi + fi fi AM_CONDITIONAL(HAVE_PULSEAUDIO, [test "x$have_pulseaudio" = x"yes"]) diff --git a/src/audio_out/audio_pulse_out.c b/src/audio_out/audio_pulse_out.c index 05b61c309..fa58cf011 100644 --- a/src/audio_out/audio_pulse_out.c +++ b/src/audio_out/audio_pulse_out.c @@ -218,7 +218,11 @@ static void __xine_pa_sink_info_callback(pa_context *c, const pa_sink_input_info this->cvolume = info->volume; this->swvolume = pa_cvolume_avg(&info->volume); +#ifdef HAVE_PULSEAUDIO_0_9_7 this->muted = info->mute; +#else + this->muted = pa_cvolume_is_muted (&this->cvolume); +#endif } static int connect_context(pulse_driver_t *this) { @@ -661,9 +665,21 @@ static int ao_pulse_set_property (ao_driver_t *this_gen, int property, int value this->muted = value; +#ifdef HAVE_PULSEAUDIO_0_9_7 o = pa_context_set_sink_input_mute(this->context, pa_stream_get_index(this->stream), value, __xine_pa_context_success_callback, this); +#else + /* FIXME: breaks (volume=0 after unmuting) unless the volume is + * adjusted first (due to swvolume not being initialised properly) + */ + if ( value ) + pa_cvolume_mute(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels); + else + pa_cvolume_set(&this->cvolume, pa_stream_get_sample_spec(this->stream)->channels, this->swvolume); + o = pa_context_set_sink_input_volume(this->context, pa_stream_get_index(this->stream), + &this->cvolume, __xine_pa_context_success_callback, this); +#endif result = value; } -- cgit v1.2.3 From 5c29923095c53ae9788bf77b7b6d416a689434e6 Mon Sep 17 00:00:00 2001 From: Darren Salt Date: Fri, 11 Apr 2008 19:46:29 +0100 Subject: Add a function for listing video output plugins of the given type(s). --- include/xine.h.in | 2 ++ src/xine-engine/load_plugins.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/xine.h.in b/include/xine.h.in index c97d778d4..219ec8687 100644 --- a/include/xine.h.in +++ b/include/xine.h.in @@ -1071,6 +1071,8 @@ const char *xine_get_post_plugin_description (xine_t *self, /* get lists of available audio and video output plugins */ const char *const *xine_list_audio_output_plugins (xine_t *self) XINE_PROTECTED; const char *const *xine_list_video_output_plugins (xine_t *self) XINE_PROTECTED; +/* typemask is (1ULL << XINE_VISUAL_TYPE_FOO) | ... */ +const char *const *xine_list_video_output_plugins_typed (xine_t *self, uint64_t typemask) XINE_PROTECTED; /* get list of available demultiplexor plugins */ const char *const *xine_list_demuxer_plugins(xine_t *self) XINE_PROTECTED; diff --git a/src/xine-engine/load_plugins.c b/src/xine-engine/load_plugins.c index 0188fb01d..30077a38e 100644 --- a/src/xine-engine/load_plugins.c +++ b/src/xine-engine/load_plugins.c @@ -1665,6 +1665,36 @@ const char *const *xine_list_video_output_plugins (xine_t *xine) { return catalog->ids; } +const char *const *xine_list_video_output_plugins_typed(xine_t *xine, uint64_t typemask) +{ + plugin_catalog_t *catalog = xine->plugin_catalog; + plugin_node_t *node; + int list_id, list_size, i; + + pthread_mutex_lock (&catalog->lock); + + list_size = xine_sarray_size (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1]); + + for (list_id = i = 0; list_id < list_size; list_id++) + { + node = xine_sarray_get (catalog->plugin_lists[PLUGIN_VIDEO_OUT - 1], list_id); + if (typemask & (1ULL << ((vo_info_t *)node->info->special_info)->visual_type)) + { + const char *id = node->info->id; + int j = i; + while (--j >= 0) + if (!strcmp (catalog->ids[j], id)) + goto ignore; /* already listed */ + catalog->ids[i++] = id; + } + ignore: ; + } + catalog->ids[i] = NULL; + + pthread_mutex_unlock (&catalog->lock); + return catalog->ids; +} + static ao_driver_t *_load_audio_driver (xine_t *this, plugin_node_t *node, void *data) { -- cgit v1.2.3