X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fvmem.c;h=72944c0521990aa55e9dc8b1e1e2db20a418c5d6;hb=41e9bfae66e110a2d82b6f44db4e0eb664f5572e;hp=57e05303e5c39c35cc1954f9fc5d846b9a269571;hpb=52c18c4dec68158eedd655e0502820b7d7b6128f;p=vlc diff --git a/modules/video_output/vmem.c b/modules/video_output/vmem.c index 57e05303e5..72944c0521 100644 --- a/modules/video_output/vmem.c +++ b/modules/video_output/vmem.c @@ -1,24 +1,24 @@ /***************************************************************************** * vmem.c: memory video driver for vlc ***************************************************************************** - * Copyright (C) 2008 the VideoLAN team - * $Id$ + * Copyright (C) 2008 VLC authors and VideoLAN + * Copyrgiht (C) 2010 Rémi Denis-Courmont * * Authors: Sam Hocevar * - * This program 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 + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation; either version 2.1 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. + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser 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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/ /***************************************************************************** @@ -29,283 +29,326 @@ # include "config.h" #endif +#include + #include #include -#include - -/***************************************************************************** - * Local prototypes - *****************************************************************************/ -static int Create ( vlc_object_t * ); -static void Destroy ( vlc_object_t * ); - -static int Init ( vout_thread_t * ); -static void End ( vout_thread_t * ); -static int LockPicture ( vout_thread_t *, picture_t * ); -static int UnlockPicture ( vout_thread_t *, picture_t * ); +#include +#include /***************************************************************************** * Module descriptor *****************************************************************************/ -#define T_WIDTH N_( "Width" ) -#define LT_WIDTH N_( "Video memory buffer width." ) +#define T_WIDTH N_("Width") +#define LT_WIDTH N_("Video memory buffer width.") -#define T_HEIGHT N_( "Height" ) -#define LT_HEIGHT N_( "Video memory buffer height." ) +#define T_HEIGHT N_("Height") +#define LT_HEIGHT N_("Video memory buffer height.") -#define T_PITCH N_( "Pitch" ) -#define LT_PITCH N_( "Video memory buffer pitch in bytes." ) +#define T_PITCH N_("Pitch") +#define LT_PITCH N_("Video memory buffer pitch in bytes.") -#define T_CHROMA N_( "Chroma" ) -#define LT_CHROMA N_( "Output chroma for the memory image as a 4-character " \ - "string, eg. \"RV32\"." ) +#define T_CHROMA N_("Chroma") +#define LT_CHROMA N_("Output chroma for the memory image as a 4-character " \ + "string, eg. \"RV32\".") -#define T_LOCK N_( "Lock function" ) -#define LT_LOCK N_( "Address of the locking callback function. This " \ - "function must fill in valid plane memory address " \ - "information for use by the video renderer." ) +static int Open (vlc_object_t *); +static void Close(vlc_object_t *); -#define T_UNLOCK N_( "Unlock function" ) -#define LT_UNLOCK N_( "Address of the unlocking callback function" ) +vlc_module_begin() + set_description(N_("Video memory output")) + set_shortname(N_("Video memory")) -#define T_DATA N_( "Callback data" ) -#define LT_DATA N_( "Data for the locking and unlocking functions" ) + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_capability("vout display", 0) -vlc_module_begin () - set_description( N_( "Video memory output" ) ) - set_shortname( N_("Video memory") ) + add_integer("vmem-width", 320, T_WIDTH, LT_WIDTH, false) + change_private() + add_integer("vmem-height", 200, T_HEIGHT, LT_HEIGHT, false) + change_private() + add_integer("vmem-pitch", 640, T_PITCH, LT_PITCH, false) + change_private() + add_string("vmem-chroma", "RV16", T_CHROMA, LT_CHROMA, true) + change_private() + add_obsolete_string("vmem-lock") /* obsoleted since 1.1.1 */ + add_obsolete_string("vmem-unlock") /* obsoleted since 1.1.1 */ + add_obsolete_string("vmem-data") /* obsoleted since 1.1.1 */ - set_category( CAT_VIDEO ) - set_subcategory( SUBCAT_VIDEO_VOUT ) - set_capability( "video output", 0 ) - - add_integer( "vmem-width", 320, NULL, T_WIDTH, LT_WIDTH, false ) - add_integer( "vmem-height", 200, NULL, T_HEIGHT, LT_HEIGHT, false ) - add_integer( "vmem-pitch", 640, NULL, T_PITCH, LT_PITCH, false ) - add_string( "vmem-chroma", "RV16", NULL, T_CHROMA, LT_CHROMA, true ) - add_string( "vmem-lock", "0", NULL, T_LOCK, LT_LOCK, true ) - add_string( "vmem-unlock", "0", NULL, T_UNLOCK, LT_UNLOCK, true ) - add_string( "vmem-data", "0", NULL, T_DATA, LT_DATA, true ) - - set_callbacks( Create, Destroy ) -vlc_module_end () + set_callbacks(Open, Close) +vlc_module_end() /***************************************************************************** - * vout_sys_t: video output descriptor + * Local prototypes *****************************************************************************/ -struct vout_sys_t -{ - int i_width, i_height, i_pitch; +struct picture_sys_t { + vout_display_sys_t *sys; + void *id; +}; + +/* NOTE: the callback prototypes must match those of LibVLC */ +struct vout_display_sys_t { + picture_pool_t *pool; + unsigned count; - void (*pf_lock) (void *, void **); - void (*pf_unlock) (void *); - void *p_data; + void *opaque; + void *(*lock)(void *sys, void **plane); + void (*unlock)(void *sys, void *id, void *const *plane); + void (*display)(void *sys, void *id); + void (*cleanup)(void *sys); + + unsigned pitches[PICTURE_PLANE_MAX]; + unsigned lines[PICTURE_PLANE_MAX]; }; +typedef unsigned (*vlc_format_cb)(void **, char *, unsigned *, unsigned *, + unsigned *, unsigned *); + +static picture_pool_t *Pool (vout_display_t *, unsigned); +static void Display(vout_display_t *, picture_t *, subpicture_t *); +static int Control(vout_display_t *, int, va_list); + +static int Lock(picture_t *); +static void Unlock(picture_t *); + /***************************************************************************** - * Create: allocates video thread + * Open: allocates video thread ***************************************************************************** * This function allocates and initializes a vout method. *****************************************************************************/ -static int Create( vlc_object_t *p_this ) +static int Open(vlc_object_t *object) { - vout_thread_t *p_vout = ( vout_thread_t * )p_this; - - /* Allocate instance and initialize some members */ - p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); - if( ! p_vout->p_sys ) + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys = malloc(sizeof(*sys)); + if (unlikely(!sys)) return VLC_ENOMEM; - p_vout->pf_init = Init; - p_vout->pf_end = End; - p_vout->pf_manage = NULL; - p_vout->pf_render = NULL; - p_vout->pf_display = NULL; + /* Get the callbacks */ + vlc_format_cb setup = var_InheritAddress(vd, "vmem-setup"); - return VLC_SUCCESS; -} - -/***************************************************************************** - * Init: initialize video thread - *****************************************************************************/ -static int Init( vout_thread_t *p_vout ) -{ - int i_index; - picture_t *p_pic; - char *psz_chroma, *psz_tmp; - int i_width, i_height, i_pitch; - vlc_fourcc_t i_chroma; - - i_width = var_CreateGetInteger( p_vout, "vmem-width" ); - i_height = var_CreateGetInteger( p_vout, "vmem-height" ); - i_pitch = var_CreateGetInteger( p_vout, "vmem-pitch" ); - - psz_chroma = var_CreateGetString( p_vout, "vmem-chroma" ); - if( !psz_chroma ) - { - msg_Err( p_vout, "Cannot find chroma information." ); + sys->lock = var_InheritAddress(vd, "vmem-lock"); + if (sys->lock == NULL) { + msg_Err(vd, "missing lock callback"); + free(sys); return VLC_EGENERIC; } - - i_chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, psz_chroma ); - free( psz_chroma ); - - if( !i_chroma ) - { - msg_Err( p_vout, "vmem-chroma should be 4 characters long" ); - return VLC_EGENERIC; + sys->unlock = var_InheritAddress(vd, "vmem-unlock"); + sys->display = var_InheritAddress(vd, "vmem-display"); + sys->cleanup = var_InheritAddress(vd, "vmem-cleanup"); + sys->opaque = var_InheritAddress(vd, "vmem-data"); + sys->pool = NULL; + + /* Define the video format */ + video_format_t fmt = vd->fmt; + + if (setup != NULL) { + char chroma[5]; + + memcpy(chroma, &fmt.i_chroma, 4); + chroma[4] = '\0'; + memset(sys->pitches, 0, sizeof(sys->pitches)); + memset(sys->lines, 0, sizeof(sys->lines)); + + sys->count = setup(&sys->opaque, chroma, &fmt.i_width, &fmt.i_height, + sys->pitches, sys->lines); + if (sys->count == 0) { + msg_Err(vd, "video format setup failure (no pictures)"); + free(sys); + return VLC_EGENERIC; + } + fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma); + + } else { + char *chroma = var_InheritString(vd, "vmem-chroma"); + fmt.i_chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma); + free(chroma); + + fmt.i_width = var_InheritInteger(vd, "vmem-width"); + fmt.i_height = var_InheritInteger(vd, "vmem-height"); + sys->pitches[0] = var_InheritInteger(vd, "vmem-pitch"); + sys->lines[0] = fmt.i_height; + for (size_t i = 1; i < PICTURE_PLANE_MAX; i++) + { + sys->pitches[i] = sys->pitches[0]; + sys->lines[i] = sys->lines[0]; + } + sys->count = 1; + sys->cleanup = NULL; } - psz_tmp = var_CreateGetString( p_vout, "vmem-lock" ); - p_vout->p_sys->pf_lock = (void (*) (void *, void **))(intptr_t)atoll( psz_tmp ); - free( psz_tmp ); - - psz_tmp = var_CreateGetString( p_vout, "vmem-unlock" ); - p_vout->p_sys->pf_unlock = (void (*) (void *))(intptr_t)atoll( psz_tmp ); - free( psz_tmp ); - - psz_tmp = var_CreateGetString( p_vout, "vmem-data" ); - p_vout->p_sys->p_data = (void *)(intptr_t)atoll( psz_tmp ); - free( psz_tmp ); - - if( !p_vout->p_sys->pf_lock || !p_vout->p_sys->pf_unlock ) - { - msg_Err( p_vout, "Invalid lock or unlock callbacks" ); + if (!fmt.i_chroma) { + msg_Err(vd, "vmem-chroma should be 4 characters long"); + free(sys); return VLC_EGENERIC; } - I_OUTPUTPICTURES = 0; - - /* Initialize the output structure */ - p_vout->output.i_chroma = i_chroma; - p_vout->output.pf_setpalette = NULL; - p_vout->output.i_width = i_width; - p_vout->output.i_height = i_height; - p_vout->output.i_aspect = p_vout->output.i_width - * VOUT_ASPECT_FACTOR / p_vout->output.i_height; - /* Define the bitmasks */ - switch( i_chroma ) + switch (fmt.i_chroma) { - case VLC_CODEC_RGB15: - p_vout->output.i_rmask = 0x001f; - p_vout->output.i_gmask = 0x03e0; - p_vout->output.i_bmask = 0x7c00; + case VLC_CODEC_RGB15: + fmt.i_rmask = 0x001f; + fmt.i_gmask = 0x03e0; + fmt.i_bmask = 0x7c00; break; - - case VLC_CODEC_RGB16: - p_vout->output.i_rmask = 0x001f; - p_vout->output.i_gmask = 0x07e0; - p_vout->output.i_bmask = 0xf800; + case VLC_CODEC_RGB16: + fmt.i_rmask = 0x001f; + fmt.i_gmask = 0x07e0; + fmt.i_bmask = 0xf800; break; - - case VLC_CODEC_RGB24: - p_vout->output.i_rmask = 0xff0000; - p_vout->output.i_gmask = 0x00ff00; - p_vout->output.i_bmask = 0x0000ff; + case VLC_CODEC_RGB24: + case VLC_CODEC_RGB32: + fmt.i_rmask = 0xff0000; + fmt.i_gmask = 0x00ff00; + fmt.i_bmask = 0x0000ff; break; - - case VLC_CODEC_RGB32: - p_vout->output.i_rmask = 0xff0000; - p_vout->output.i_gmask = 0x00ff00; - p_vout->output.i_bmask = 0x0000ff; + default: + fmt.i_rmask = 0; + fmt.i_gmask = 0; + fmt.i_bmask = 0; break; } - /* Try to initialize 1 direct buffer */ - p_pic = NULL; + /* */ + vout_display_info_t info = vd->info; + info.has_hide_mouse = true; + + /* */ + vd->sys = sys; + vd->fmt = fmt; + vd->info = info; + vd->pool = Pool; + vd->prepare = NULL; + vd->display = Display; + vd->control = Control; + vd->manage = NULL; + + /* */ + vout_display_SendEventFullscreen(vd, false); + vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, false); + return VLC_SUCCESS; +} - /* Find an empty picture slot */ - for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ ) - { - if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE ) - { - p_pic = p_vout->p_picture + i_index; - break; - } - } +static void Close(vlc_object_t *object) +{ + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys = vd->sys; - /* Allocate the picture */ - if( p_pic == NULL ) - { - return VLC_SUCCESS; - } + if (sys->cleanup) + sys->cleanup(sys->opaque); + picture_pool_Delete(sys->pool); + free(sys); +} - if( picture_Setup( p_pic, p_vout->output.i_chroma, - p_vout->output.i_width, p_vout->output.i_height, - p_vout->output.i_aspect ) ) - { - free( p_pic ); - return VLC_EGENERIC; - } +/* */ +static picture_pool_t *Pool(vout_display_t *vd, unsigned count) +{ + vout_display_sys_t *sys = vd->sys; - p_pic->p->i_pitch = i_pitch; + if (sys->pool) + return sys->pool; - p_pic->pf_lock = LockPicture; - p_pic->pf_unlock = UnlockPicture; + if (count > sys->count) + count = sys->count; - p_pic->i_status = DESTROYED_PICTURE; - p_pic->i_type = DIRECT_PICTURE; + picture_t *pictures[count]; - PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; + for (unsigned i = 0; i < count; i++) { + picture_resource_t rsc; - I_OUTPUTPICTURES++; + rsc.p_sys = malloc(sizeof(*rsc.p_sys)); + if (unlikely(!rsc.p_sys)) { + count = i; + break; + } - return VLC_SUCCESS; + rsc.p_sys->sys = sys; + rsc.p_sys->id = NULL; + + for (unsigned i = 0; i < PICTURE_PLANE_MAX; i++) { + /* vmem-lock is responsible for the allocation */ + rsc.p[i].p_pixels = NULL; + rsc.p[i].i_lines = sys->lines[i]; + rsc.p[i].i_pitch = sys->pitches[i]; + } + + pictures[i] = picture_NewFromResource(&vd->fmt, &rsc); + if (!pictures[i]) { + free(rsc.p_sys); + count = i; + break; + } + } + + /* */ + picture_pool_configuration_t pool; + memset(&pool, 0, sizeof(pool)); + pool.picture_count = count; + pool.picture = pictures; + pool.lock = Lock; + pool.unlock = Unlock; + sys->pool = picture_pool_NewExtended(&pool); + if (!sys->pool) { + for (unsigned i = 0; i < count; i++) + picture_Release(pictures[i]); + } + + return sys->pool; } -/***************************************************************************** - * End: terminate video thread output method - *****************************************************************************/ -static void End( vout_thread_t *p_vout ) +static void Display(vout_display_t *vd, picture_t *picture, subpicture_t *subpicture) { - (void)p_vout; + vout_display_sys_t *sys = vd->sys; + + assert(!picture_IsReferenced(picture)); + if (sys->display != NULL) + sys->display(sys->opaque, picture->p_sys->id); + picture_Release(picture); + VLC_UNUSED(subpicture); } -/***************************************************************************** - * Destroy: destroy video thread - ***************************************************************************** - * Terminate an output method created by Create - *****************************************************************************/ -static void Destroy( vlc_object_t *p_this ) +static int Control(vout_display_t *vd, int query, va_list args) { - vout_thread_t *p_vout = ( vout_thread_t * )p_this; - - /* Destroy structure */ - free( p_vout->p_sys ); + switch (query) { + case VOUT_DISPLAY_CHANGE_FULLSCREEN: + case VOUT_DISPLAY_CHANGE_DISPLAY_SIZE: { + const vout_display_cfg_t *cfg = va_arg(args, const vout_display_cfg_t *); + if (cfg->display.width != vd->fmt.i_width || + cfg->display.height != vd->fmt.i_height) + return VLC_EGENERIC; + if (cfg->is_fullscreen) + return VLC_EGENERIC; + return VLC_SUCCESS; + } + default: + return VLC_EGENERIC; + } } -/***************************************************************************** - * LockPicture: lock a picture - ***************************************************************************** - * This function locks the picture and prepares it for direct pixel access. - *****************************************************************************/ -static int LockPicture( vout_thread_t *p_vout, picture_t *p_pic ) +/* */ +static int Lock(picture_t *picture) { - int i_index; - void *planes[p_pic->i_planes]; + picture_sys_t *picsys = picture->p_sys; + vout_display_sys_t *sys = picsys->sys; + void *planes[PICTURE_PLANE_MAX]; - p_vout->p_sys->pf_lock( p_vout->p_sys->p_data, planes ); + picsys->id = sys->lock(sys->opaque, planes); - for( i_index = 0; i_index < p_pic->i_planes; i_index++ ) - { - p_pic->p[i_index].p_pixels = planes[i_index]; - } + for (int i = 0; i < picture->i_planes; i++) + picture->p[i].p_pixels = planes[i]; return VLC_SUCCESS; } -/***************************************************************************** - * UnlockPicture: unlock a picture - ***************************************************************************** - * This function unlocks a previously locked picture. - *****************************************************************************/ -static int UnlockPicture( vout_thread_t *p_vout, picture_t *p_pic ) +static void Unlock(picture_t *picture) { - p_vout->p_sys->pf_unlock( p_vout->p_sys->p_data ); + picture_sys_t *picsys = picture->p_sys; + vout_display_sys_t *sys = picsys->sys; - (void)p_pic; + void *planes[PICTURE_PLANE_MAX]; - return VLC_SUCCESS; -} + for (int i = 0; i < picture->i_planes; i++) + planes[i] = picture->p[i].p_pixels; + if (sys->unlock != NULL) + sys->unlock(sys->opaque, picsys->id, planes); +}