X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fvmem.c;h=3f117da1fa41c0f185371d87d1366200baaceb9b;hb=e801e17989806362fff307836cf441db9cdab7d3;hp=57e05303e5c39c35cc1954f9fc5d846b9a269571;hpb=55c960749e8f91763e720ac610d5dd56f90fcde1;p=vlc diff --git a/modules/video_output/vmem.c b/modules/video_output/vmem.c index 57e05303e5..3f117da1fa 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,320 @@ # include "config.h" #endif +#include + #include #include -#include +#include +#include /***************************************************************************** - * Local prototypes + * Module descriptor *****************************************************************************/ -static int Create ( vlc_object_t * ); -static void Destroy ( vlc_object_t * ); +#define T_WIDTH N_("Width") +#define LT_WIDTH N_("Video memory buffer width.") -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 * ); +#define T_HEIGHT N_("Height") +#define LT_HEIGHT N_("Video memory buffer height.") -/***************************************************************************** - * Module descriptor - *****************************************************************************/ -#define T_WIDTH N_( "Width" ) -#define LT_WIDTH N_( "Video memory buffer width." ) +#define T_PITCH N_("Pitch") +#define LT_PITCH N_("Video memory buffer pitch in bytes.") -#define T_HEIGHT N_( "Height" ) -#define LT_HEIGHT N_( "Video memory buffer height." ) +#define T_CHROMA N_("Chroma") +#define LT_CHROMA N_("Output chroma for the memory image as a 4-character " \ + "string, eg. \"RV32\".") -#define T_PITCH N_( "Pitch" ) -#define LT_PITCH N_( "Video memory buffer pitch in bytes." ) +static int Open (vlc_object_t *); +static void Close(vlc_object_t *); -#define T_CHROMA N_( "Chroma" ) -#define LT_CHROMA N_( "Output chroma for the memory image as a 4-character " \ - "string, eg. \"RV32\"." ) +vlc_module_begin() + set_description(N_("Video memory output")) + set_shortname(N_("Video memory")) -#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." ) + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_capability("vout display", 0) -#define T_UNLOCK N_( "Unlock function" ) -#define LT_UNLOCK N_( "Address of the unlocking callback function" ) + 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 */ -#define T_DATA N_( "Callback data" ) -#define LT_DATA N_( "Data for the locking and unlocking functions" ) + set_callbacks(Open, Close) +vlc_module_end() -vlc_module_begin () - set_description( N_( "Video memory output" ) ) - set_shortname( N_("Video memory") ) +/***************************************************************************** + * Local prototypes + *****************************************************************************/ +struct picture_sys_t { + vout_display_sys_t *sys; + void *id; +}; - set_category( CAT_VIDEO ) - set_subcategory( SUBCAT_VIDEO_VOUT ) - set_capability( "video output", 0 ) +/* NOTE: the callback prototypes must match those of LibVLC */ +struct vout_display_sys_t { + picture_pool_t *pool; + unsigned count; - 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 ) + 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); - set_callbacks( Create, Destroy ) -vlc_module_end () + unsigned pitches[PICTURE_PLANE_MAX]; + unsigned lines[PICTURE_PLANE_MAX]; +}; -/***************************************************************************** - * vout_sys_t: video output descriptor - *****************************************************************************/ -struct vout_sys_t +typedef unsigned (*vlc_format_cb)(void **, char *, unsigned *, unsigned *, + unsigned *, unsigned *); + +static picture_pool_t *Pool (vout_display_t *, unsigned); +static void Prepare(vout_display_t *, picture_t *, subpicture_t *); +static void Display(vout_display_t *, picture_t *, subpicture_t *); +static int Control(vout_display_t *, int, va_list); + +static void Lock(void *data, picture_t *pic) { - int i_width, i_height, i_pitch; + vout_display_sys_t *sys = data; + picture_sys_t *picsys = pic->p_sys; + void *planes[PICTURE_PLANE_MAX]; - void (*pf_lock) (void *, void **); - void (*pf_unlock) (void *); - void *p_data; -}; + picsys->id = sys->lock(sys->opaque, planes); -/***************************************************************************** - * Create: allocates video thread - ***************************************************************************** - * This function allocates and initializes a vout method. - *****************************************************************************/ -static int Create( vlc_object_t *p_this ) + for (int i = 0; i < pic->i_planes; i++) + pic->p[i].p_pixels = planes[i]; +} + +static void Unlock(void *data, picture_t *pic) { - vout_thread_t *p_vout = ( vout_thread_t * )p_this; + vout_display_sys_t *sys = data; + picture_sys_t *picsys = pic->p_sys; + void *planes[PICTURE_PLANE_MAX]; - /* Allocate instance and initialize some members */ - p_vout->p_sys = malloc( sizeof( vout_sys_t ) ); - if( ! p_vout->p_sys ) - return VLC_ENOMEM; + assert(!picture_IsReferenced(pic)); - 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; + for (int i = 0; i < pic->i_planes; i++) + planes[i] = pic->p[i].p_pixels; + + if (sys->unlock != NULL) + sys->unlock(sys->opaque, picsys->id, planes); - return VLC_SUCCESS; } /***************************************************************************** - * Init: initialize video thread + * Open: allocates video thread + ***************************************************************************** + * This function allocates and initializes a vout method. *****************************************************************************/ -static int Init( vout_thread_t *p_vout ) +static int Open(vlc_object_t *object) { - 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." ); - return VLC_EGENERIC; - } + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys = malloc(sizeof(*sys)); + if (unlikely(!sys)) + return VLC_ENOMEM; - i_chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, psz_chroma ); - free( psz_chroma ); + /* Get the callbacks */ + vlc_format_cb setup = var_InheritAddress(vd, "vmem-setup"); - if( !i_chroma ) - { - msg_Err( p_vout, "vmem-chroma should be 4 characters long" ); + sys->lock = var_InheritAddress(vd, "vmem-lock"); + if (sys->lock == NULL) { + msg_Err(vd, "missing lock callback"); + free(sys); 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; + video_format_ApplyRotation(&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; + } + fmt.i_x_offset = fmt.i_y_offset = 0; + fmt.i_visible_width = fmt.i_width; + fmt.i_visible_height = fmt.i_height; - 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 = Prepare; + vd->display = Display; + vd->control = Control; + vd->manage = NULL; + + /* */ + vout_display_SendEventFullscreen(vd, false); + vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height); + vout_display_DeleteWindow(vd, NULL); + 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); - 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; - } + picture_pool_Enum(sys->pool, Unlock, sys); + picture_pool_Release(sys->pool); + free(sys); +} - p_pic->p->i_pitch = i_pitch; +static picture_pool_t *Pool(vout_display_t *vd, unsigned count) +{ + vout_display_sys_t *sys = vd->sys; - p_pic->pf_lock = LockPicture; - p_pic->pf_unlock = UnlockPicture; + if (sys->pool) + return sys->pool; - p_pic->i_status = DESTROYED_PICTURE; - p_pic->i_type = DIRECT_PICTURE; + if (count > sys->count) + count = sys->count; - PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; + picture_t *pictures[count]; - I_OUTPUTPICTURES++; + for (unsigned i = 0; i < count; i++) { + picture_sys_t *picsys = malloc(sizeof (*picsys)); + if (unlikely(picsys == NULL)) + { + count = i; + break; + } + picsys->sys = sys; + picsys->id = NULL; - return VLC_SUCCESS; -} + picture_resource_t rsc = { .p_sys = picsys }; -/***************************************************************************** - * End: terminate video thread output method - *****************************************************************************/ -static void End( vout_thread_t *p_vout ) -{ - (void)p_vout; -} + 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]; + } -/***************************************************************************** - * Destroy: destroy video thread - ***************************************************************************** - * Terminate an output method created by Create - *****************************************************************************/ -static void Destroy( vlc_object_t *p_this ) -{ - vout_thread_t *p_vout = ( vout_thread_t * )p_this; + pictures[i] = picture_NewFromResource(&vd->fmt, &rsc); + if (!pictures[i]) { + free(rsc.p_sys); + count = i; + break; + } + } + + /* */ + sys->pool = picture_pool_New(count, pictures); + if (!sys->pool) { + for (unsigned i = 0; i < count; i++) + picture_Release(pictures[i]); + } - /* Destroy structure */ - free( p_vout->p_sys ); + picture_pool_Enum(sys->pool, Lock, sys); + return sys->pool; } -/***************************************************************************** - * 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 void Prepare(vout_display_t *vd, picture_t *pic, subpicture_t *subpic) { - int i_index; - void *planes[p_pic->i_planes]; - - p_vout->p_sys->pf_lock( p_vout->p_sys->p_data, planes ); - - for( i_index = 0; i_index < p_pic->i_planes; i_index++ ) - { - p_pic->p[i_index].p_pixels = planes[i_index]; - } - - return VLC_SUCCESS; + Unlock(vd->sys, pic); + VLC_UNUSED(subpic); } -/***************************************************************************** - * 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 Display(vout_display_t *vd, picture_t *pic, subpicture_t *subpic) { - p_vout->p_sys->pf_unlock( p_vout->p_sys->p_data ); + vout_display_sys_t *sys = vd->sys; - (void)p_pic; + if (sys->display != NULL) + sys->display(sys->opaque, pic->p_sys->id); - return VLC_SUCCESS; + Lock(sys, pic); + picture_Release(pic); + VLC_UNUSED(subpic); } +static int Control(vout_display_t *vd, int query, va_list args) +{ + (void) vd; (void) query; (void) args; + return VLC_EGENERIC; +}