/*************************************************************************** * Copyright (C) 2008 by Reel Multimedia Vertriebs GmbH * * E-Mail : info @ reel-multimedia.com * * Internet: www.reel-multimedia.com * * * * This code 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. * * * * This program 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. * ***************************************************************************/ #ifdef HAVE_CONFIG_H # include "config.h" #endif #define LOG_MODULE "hde-video" #define LOG_VERBOSE #define LOG #define LOG_FUNC 0 #define LOG_ERR 1 #include #include "hde_xine.h" #include "hde_io.h" #include "vo_scale.h" #include #include #include #include #include #include #include #include #include #include typedef struct hde_frame_s { vo_frame_t vo_frame; } hde_frame_t; typedef struct hde_driver_class_s { video_driver_class_t video_driver_class; xine_t *xine; int instance; int type; config_values_t *config; } hde_driver_class_t; typedef struct hde_driver_s { vo_driver_t vo_driver; hde_driver_class_t *class; alphablend_t alphablend; int ov_changed; } hde_driver_t; static void hde_frame_proc_frame ( vo_frame_t *frame_gen ) { llprintf ( LOG_FUNC, "hde_frame_proc_frame\n" ); /* we reduce the vpts to give the card some extra decoding time */ /* if (frame_gen->format != XINE_IMGFMT_DXR3 && !frame_gen->proc_called) frame_gen->vpts -= DECODE_PIPE_PREBUFFER; frame_gen->proc_called = 1; */ frame_gen->proc_called = 1; } // hde_frame_proc_frame static void hde_frame_proc_slice ( vo_frame_t *frame_gen, uint8_t **src ) { llprintf ( LOG_FUNC, "hde_frame_proc_slice\n" ); // hde_frame_t *frame = (hde_frame_t *)frame_gen; // hde_driver_t *this = (hde_driver_t *)frame_gen->driver; /* we reduce the vpts to give the card some extra decoding time */ /* if (frame_gen->format != XINE_IMGFMT_DXR3 && !frame_gen->proc_called) frame_gen->vpts -= DECODE_PIPE_PREBUFFER; frame_gen->proc_called = 1; if (frame_gen->format != XINE_IMGFMT_DXR3 && this->enc && this->enc->on_frame_copy) this->enc->on_frame_copy(this, frame, src); */ frame_gen->proc_called = 1; } // hde_frame_proc_slice static void hde_frame_field ( vo_frame_t *vo_img, int which_field ) { llprintf ( LOG_FUNC, "hde_frame_field\n" ); /* dummy function */ } // hde_frame_field static void hde_frame_dispose ( vo_frame_t *frame_gen ) { llprintf ( LOG_FUNC, "hde_frame_dispose\n" ); hde_frame_t *frame = ( hde_frame_t * ) frame_gen; if (frame->vo_frame.base[0]) free(frame->vo_frame.base[0]); if (frame->vo_frame.base[1]) free(frame->vo_frame.base[1]); if (frame->vo_frame.base[2]) free(frame->vo_frame.base[2]); pthread_mutex_destroy ( &frame->vo_frame.mutex ); free ( frame ); } // hde_frame_dispose static uint32_t hde_get_capabilities ( vo_driver_t *this_gen ) { llprintf ( LOG_FUNC, "hde_get_capabilities\n" ); return VO_CAP_YV12 | VO_CAP_YUY2; } // hde_get_capabilities static vo_frame_t *hde_alloc_frame ( vo_driver_t *this_gen ) { llprintf ( LOG_FUNC, "hde_alloc_frame\n" ); hde_frame_t *frame; //hde_driver_t *this = (hde_driver_t *)this_gen; frame = ( hde_frame_t * ) xine_xmalloc ( sizeof ( hde_frame_t ) ); pthread_mutex_init ( &frame->vo_frame.mutex, NULL ); frame->vo_frame.proc_frame = hde_frame_proc_frame; frame->vo_frame.proc_slice = hde_frame_proc_slice; frame->vo_frame.field = hde_frame_field; frame->vo_frame.dispose = hde_frame_dispose; frame->vo_frame.driver = this_gen; return &frame->vo_frame; } // hde_alloc_frame static void hde_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 ) { llprintf ( LOG_FUNC, "hde_update_frame_format w:%d h:%d r:%f f:%c%c%c%c flags:%d\n", width, height, ratio, ( format&0xff ), ( format&0xff00 ) >>8, ( format&0xff0000 ) >>16, ( format&0xff000000 ) >>24, flags ); hde_frame_t *frame = (hde_frame_t *)frame_gen; // hde_driver_t *this = (hde_driver_t *)frame_gen->driver; if ( format == XINE_IMGFMT_HDE ) { frame->vo_frame.width = width; frame->vo_frame.height = height; frame->vo_frame.ratio = ratio; } else { if (frame->vo_frame.base[0]) free(frame->vo_frame.base[0]); if (frame->vo_frame.base[1]) free(frame->vo_frame.base[1]); if (frame->vo_frame.base[2]) free(frame->vo_frame.base[2]); frame->vo_frame.width = width; frame->vo_frame.height = height; frame->vo_frame.ratio = ratio; if(format == XINE_IMGFMT_YUY2) { frame->vo_frame.pitches[0] = 32 * ((width+15)/16); frame->vo_frame.base[0] = xine_xmalloc(frame->vo_frame.pitches[0]*height); frame->vo_frame.base[1] = frame->vo_frame.base[2] = 0; } else if (format == XINE_IMGFMT_YV12) { frame->vo_frame.pitches[0] = 16 * ((width+15)/16); 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(frame->vo_frame.pitches[0]*height); frame->vo_frame.base[1] = xine_xmalloc(frame->vo_frame.pitches[1]*height); frame->vo_frame.base[2] = xine_xmalloc(frame->vo_frame.pitches[2]*height); } // if } // if } // hde_update_frame_format static void hde_overlay_begin ( vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed ) { llprintf ( LOG_FUNC, "hde_overlay_begin\n" ); hde_driver_t *this = (hde_driver_t *)frame_gen->driver; this->ov_changed = changed; if(this->ov_changed) hde_io_fb_begin(); } // hde_overlay_begin static void hde_overlay_blend ( vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay ) { llprintf ( LOG_FUNC, "hde_overlay_blend\n" ); hde_frame_t *frame = (hde_frame_t *)frame_gen; hde_driver_t *this = (hde_driver_t *)frame_gen->driver; if(!this->ov_changed) return; this->alphablend.offset_x = frame->vo_frame.overlay_offset_x; this->alphablend.offset_y = frame->vo_frame.overlay_offset_y; hde_io_fb_blend(&this->alphablend, overlay); } // hde_overlay_blend static void hde_overlay_end ( vo_driver_t *this_gen, vo_frame_t *frame_gen ) { llprintf ( LOG_FUNC, "hde_overlay_end\n" ); hde_driver_t *this = (hde_driver_t *)frame_gen->driver; if(!this->ov_changed) return; hde_io_fb_end(); } // hde_overlay_end static void hde_display_frame ( vo_driver_t *this_gen, vo_frame_t *frame_gen ) { llprintf ( LOG_FUNC, "hde_display_frame\n" ); hde_frame_t *frame = (hde_frame_t *)frame_gen; if ( frame->vo_frame.format == XINE_IMGFMT_HDE ) { frame->vo_frame.format = XINE_IMGFMT_HDE; frame_gen->free(frame_gen); } else { frame_gen->free(frame_gen); } // if } // hde_display_frame static int hde_redraw_needed ( vo_driver_t *this_gen ) { // llprintf(LOG_FUNC, "hde_redraw_needed\n"); xine_usec_sleep(10); return 0; } // hde_redraw_needed static int hde_get_property ( vo_driver_t *this_gen, int property ) { llprintf ( LOG_FUNC, "hde_get_property %d\n", property ); hde_driver_t *this = ( hde_driver_t * ) this_gen; switch ( property ) { case VO_PROP_SATURATION: case VO_PROP_CONTRAST: case VO_PROP_BRIGHTNESS: return 0; case VO_PROP_ASPECT_RATIO: return XINE_VO_ASPECT_AUTO; case VO_PROP_COLORKEY: return 0; case VO_PROP_ZOOM_X: case VO_PROP_ZOOM_Y: case VO_PROP_TVMODE: return 0; case VO_PROP_WINDOW_WIDTH: return 720; case VO_PROP_WINDOW_HEIGHT: return 576; case VO_PROP_MAX_NUM_FRAMES: return 0; // default } // switch xprintf ( this->class->xine, XINE_VERBOSITY_DEBUG, "hde_get_property: property %d not implemented.\n", property ); return 0; } // hde_get_property static int hde_set_property ( vo_driver_t *this_gen, int property, int value ) { llprintf ( LOG_FUNC, "hde_set_property %d=%d\n", property, value ); return 0; } // hde_set_property static void hde_get_property_min_max ( vo_driver_t *this_gen, int property, int *min, int *max ) { llprintf ( LOG_FUNC, "hde_get_property_min_max %d\n", property ); switch ( property ) { case VO_PROP_SATURATION: case VO_PROP_CONTRAST: case VO_PROP_BRIGHTNESS: *min = 0; *max = 1000; break; default: *min = 0; *max = 0; } // switch } // hde_get_property_min_max static int hde_gui_data_exchange ( vo_driver_t *this_gen, int data_type, void *data ) { llprintf ( LOG_FUNC, "hde_gui_data_exchange\n" ); return 0; } // hde_gui_data_exchange static void hde_dispose ( vo_driver_t *this_gen ) { hde_driver_t *this = ( hde_driver_t * ) this_gen; _x_alphablend_free(&this->alphablend); this->class->instance = 0; gHdeIO.video_used = 0; hde_io_done(); free ( this ); } // hde_dispose static vo_driver_t *hde_vo_open_plugin ( video_driver_class_t *class_gen, const void *visual_gen ) { llprintf ( LOG_FUNC, "hde_vo_open_plugin\n" ); hde_driver_t *this; hde_driver_class_t *class = ( hde_driver_class_t * ) class_gen; if (class->instance) return NULL; this = ( hde_driver_t * ) xine_xmalloc ( sizeof ( hde_driver_t ) ); if ( !this ) return NULL; this->vo_driver.get_capabilities = hde_get_capabilities; this->vo_driver.alloc_frame = hde_alloc_frame; this->vo_driver.update_frame_format = hde_update_frame_format; this->vo_driver.overlay_begin = hde_overlay_begin; this->vo_driver.overlay_blend = hde_overlay_blend; this->vo_driver.overlay_end = hde_overlay_end; this->vo_driver.display_frame = hde_display_frame; this->vo_driver.redraw_needed = hde_redraw_needed; this->vo_driver.get_property = hde_get_property; this->vo_driver.set_property = hde_set_property; this->vo_driver.get_property_min_max = hde_get_property_min_max; this->vo_driver.gui_data_exchange = hde_gui_data_exchange; this->vo_driver.dispose = hde_dispose; this->class = class; _x_alphablend_init(&this->alphablend, class->xine); class->instance = 1; gHdeIO.video_used = 1; hde_io_init(); return &this->vo_driver; } // hde_vo_open_plugin static char *hde_vo_get_identifier ( video_driver_class_t *class_gen ) { llprintf ( LOG_FUNC, "hde_vo_get_identifier\n" ); hde_driver_class_t *class = ( hde_driver_class_t * ) class_gen; switch(class->type) { case XINE_VISUAL_TYPE_X11 : return HDE_VIDEO_ID_X11; case XINE_VISUAL_TYPE_AA : return HDE_VIDEO_ID_AA; case XINE_VISUAL_TYPE_FB : return HDE_VIDEO_ID_FB; } // switch return HDE_VIDEO_ID; } // hde_vo_get_identifier static char *hde_vo_get_description ( video_driver_class_t *class_gen ) { llprintf ( LOG_FUNC, "hde_vo_get_description\n" ); return HDE_VIDEO_DESCR; } // hde_vo_get_description static void hde_vo_class_dispose ( video_driver_class_t *class_gen ) { llprintf ( LOG_FUNC, "hde_vo_class_dispose\n" ); hde_driver_class_t *class = ( hde_driver_class_t * ) class_gen; gHdeIO.video = 0; hde_io_done(); free ( class ); } // hde_vo_class_dispose void *hde_video_init ( xine_t *xine, void *visual_gen, int type) { llprintf ( LOG_FUNC, "hde_video_init\n" ); hde_driver_class_t *this; this = ( hde_driver_class_t * ) xine_xmalloc ( sizeof ( hde_driver_class_t ) ); if ( !this ) return NULL; //this->devnum = xine->config->register_num ( xine->config, CONF_KEY, 0, CONF_NAME, CONF_HELP, 10, NULL, NULL ); this->video_driver_class.open_plugin = hde_vo_open_plugin; this->video_driver_class.get_identifier = hde_vo_get_identifier; this->video_driver_class.get_description = hde_vo_get_description; this->video_driver_class.dispose = hde_vo_class_dispose; this->xine = xine; this->instance = 0; this->type = type; gHdeIO.video = 1; hde_io_init(); return &this->video_driver_class; } // hde_video_init void *hde_video_init_x11 ( xine_t *xine, void *visual_gen ) { return hde_video_init(xine, visual_gen, XINE_VISUAL_TYPE_X11); } // hde_video_init_x11 void *hde_video_init_aa ( xine_t *xine, void *visual_gen ) { return hde_video_init(xine, visual_gen, XINE_VISUAL_TYPE_AA); } // hde_video_init_aa void *hde_video_init_fb ( xine_t *xine, void *visual_gen ) { return hde_video_init(xine, visual_gen, XINE_VISUAL_TYPE_FB); } // hde_video_init_fb