rendered paste body/***************************************************************************
* 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 <xine_internal.h>
#include "hde_xine.h"
#include "hde_io.h"
#include "vo_scale.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
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