X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=modules%2Fvideo_output%2Fvmem.c;h=be1ef6d23acf3f2f6e13a0ffe9ad1fca867467ba;hb=0ce024271b3ff2f997781e05ad15463865a83539;hp=5de7f09af0a5966bd513bf8bba27db8899fb77b5;hpb=514a804f231641c2ca86d96281939df2a3843721;p=vlc diff --git a/modules/video_output/vmem.c b/modules/video_output/vmem.c index 5de7f09af0..be1ef6d23a 100644 --- a/modules/video_output/vmem.c +++ b/modules/video_output/vmem.c @@ -29,273 +29,285 @@ # 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_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_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 return a valid memory address for use " \ - "by the video renderer." ) - -#define T_UNLOCK N_( "Unlock function" ) -#define LT_UNLOCK N_( "Address of the unlocking callback function" ) - -#define T_DATA N_( "Callback data" ) -#define LT_DATA N_( "Data for the locking and unlocking functions" ) - -vlc_module_begin( ); - set_description( N_( "Video memory module" ) ); - set_shortname( N_("Video memory") ); - - 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(); +#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_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_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.") + +#define T_UNLOCK N_("Unlock function") +#define LT_UNLOCK N_("Address of the unlocking callback function") + +#define T_DATA N_("Callback data") +#define LT_DATA N_("Data for the locking and unlocking functions") + +static int Open (vlc_object_t *); +static void Close(vlc_object_t *); + +vlc_module_begin() + set_description(N_("Video memory output")) + set_shortname(N_("Video memory")) + + set_category(CAT_VIDEO) + set_subcategory(SUBCAT_VIDEO_VOUT) + set_capability("vout display", 0) + + add_integer("vmem-width", 320, NULL, T_WIDTH, LT_WIDTH, false) + change_private() + add_integer("vmem-height", 200, NULL, T_HEIGHT, LT_HEIGHT, false) + change_private() + add_integer("vmem-pitch", 640, NULL, T_PITCH, LT_PITCH, false) + change_private() + add_string("vmem-chroma", "RV16", NULL, T_CHROMA, LT_CHROMA, true) + change_private() + add_string("vmem-lock", "0", NULL, T_LOCK, LT_LOCK, true) + change_volatile() + add_string("vmem-unlock", "0", NULL, T_UNLOCK, LT_UNLOCK, true) + change_volatile() + add_string("vmem-data", "0", NULL, T_DATA, LT_DATA, true) + change_volatile() + + 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; - - void * (*pf_lock) (void *); - void (*pf_unlock) (void *); - void *p_data; +struct picture_sys_t { + void (*lock)(void *sys, void **plane); + void (*unlock)(void *sys); + void *sys; }; -/***************************************************************************** - * Create: allocates video thread - ***************************************************************************** - * This function allocates and initializes a vout method. - *****************************************************************************/ -static int Create( vlc_object_t *p_this ) -{ - 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 ) - return VLC_ENOMEM; +struct vout_display_sys_t { + picture_pool_t *pool; +}; - 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; +static picture_pool_t *Pool (vout_display_t *, unsigned); +static void Display(vout_display_t *, picture_t *); +static int Control(vout_display_t *, int, va_list); +static void Manage (vout_display_t *); - return VLC_SUCCESS; -} +static int Lock(picture_t *); +static void Unlock(picture_t *); /***************************************************************************** - * 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, i_chroma; - - i_width = config_GetInt( p_vout, "vmem-width" ); - i_height = config_GetInt( p_vout, "vmem-height" ); - i_pitch = config_GetInt( p_vout, "vmem-pitch" ); - - psz_chroma = config_GetPsz( p_vout, "vmem-chroma" ); - if( psz_chroma ) - { - if( strlen( psz_chroma ) < 4 ) - { - msg_Err( p_vout, "vmem-chroma should be 4 characters long" ); - free( psz_chroma ); - return VLC_EGENERIC; - } - i_chroma = VLC_FOURCC( psz_chroma[0], psz_chroma[1], - psz_chroma[2], psz_chroma[3] ); - free( psz_chroma ); - } - else - { - msg_Err( p_vout, "Cannot find chroma information." ); + vout_display_t *vd = (vout_display_t *)object; + + /* */ + char *chroma_format = var_CreateGetString(vd, "vmem-chroma"); + const vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString(VIDEO_ES, chroma_format); + free(chroma_format); + if (!chroma) { + msg_Err(vd, "vmem-chroma should be 4 characters long"); return VLC_EGENERIC; } - psz_tmp = config_GetPsz( p_vout, "vmem-lock" ); - p_vout->p_sys->pf_lock = (void * (*) (void *))(intptr_t)atoll( psz_tmp ); - free( psz_tmp ); + /* */ + picture_sys_t cfg; - psz_tmp = config_GetPsz( p_vout, "vmem-unlock" ); - p_vout->p_sys->pf_unlock = (void (*) (void *))(intptr_t)atoll( psz_tmp ); - free( psz_tmp ); + char *tmp; + tmp = var_CreateGetString(vd, "vmem-lock"); + cfg.lock = (void (*)(void *, void **))(intptr_t)atoll(tmp); + free(tmp); - psz_tmp = config_GetPsz( p_vout, "vmem-data" ); - p_vout->p_sys->p_data = (void *)(intptr_t)atoll( psz_tmp ); - free( psz_tmp ); + tmp = var_CreateGetString(vd, "vmem-unlock"); + cfg.unlock = (void (*)(void *))(intptr_t)atoll(tmp); + free(tmp); - if( !p_vout->p_sys->pf_lock || !p_vout->p_sys->pf_unlock ) - { - msg_Err( p_vout, "Invalid lock or unlock callbacks" ); + tmp = var_CreateGetString(vd, "vmem-data"); + cfg.sys = (void *)(intptr_t)atoll(tmp); + free(tmp); + + /* lock and unlock are mandatory */ + if (!cfg.lock || !cfg.unlock) { + msg_Err(vd, "Invalid lock or unlock callbacks"); return VLC_EGENERIC; } - I_OUTPUTPICTURES = 0; + /* */ + video_format_t fmt = vd->fmt; - /* 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; + fmt.i_chroma = chroma; + fmt.i_width = var_CreateGetInteger(vd, "vmem-width"); + fmt.i_height = var_CreateGetInteger(vd, "vmem-height"); /* Define the bitmasks */ - switch( i_chroma ) + switch (chroma) { - case VLC_FOURCC( 'R','V','1','5' ): - 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_FOURCC( 'R','V','1','6' ): - 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_FOURCC( 'R','V','2','4' ): - p_vout->output.i_rmask = 0xff0000; - p_vout->output.i_gmask = 0x00ff00; - p_vout->output.i_bmask = 0x0000ff; + case VLC_CODEC_RGB24: + fmt.i_rmask = 0xff0000; + fmt.i_gmask = 0x00ff00; + fmt.i_bmask = 0x0000ff; break; - - case VLC_FOURCC( 'R','V','3','2' ): - p_vout->output.i_rmask = 0xff0000; - p_vout->output.i_gmask = 0x00ff00; - p_vout->output.i_bmask = 0x0000ff; + case VLC_CODEC_RGB32: + fmt.i_rmask = 0xff0000; + fmt.i_gmask = 0x00ff00; + fmt.i_bmask = 0x0000ff; + break; + 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_sys_t *sys; + vd->sys = sys = calloc(1, sizeof(*sys)); + if (!sys) + return VLC_EGENERIC; - /* 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; - } + /* */ + const int pitch = var_CreateGetInteger(vd, "vmem-pitch"); + picture_resource_t rsc; + rsc.p_sys = malloc(sizeof(*rsc.p_sys)); + *rsc.p_sys = cfg; + for (int 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 = fmt.i_height; + rsc.p[i].i_pitch = pitch; } - - /* Allocate the picture */ - if( p_pic == NULL ) - { - return VLC_SUCCESS; + picture_t *picture = picture_NewFromResource(&fmt, &rsc); + if (!picture) { + free(rsc.p_sys); + free(sys); + return VLC_EGENERIC; } - vout_InitPicture( VLC_OBJECT(p_vout), p_pic, p_vout->output.i_chroma, - p_vout->output.i_width, p_vout->output.i_height, - p_vout->output.i_aspect ); - - p_pic->p->i_pitch = i_pitch; - - p_pic->pf_lock = LockPicture; - p_pic->pf_unlock = UnlockPicture; - - p_pic->i_status = DESTROYED_PICTURE; - p_pic->i_type = DIRECT_PICTURE; - - PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic; - - I_OUTPUTPICTURES++; + /* */ + picture_pool_configuration_t pool; + memset(&pool, 0, sizeof(pool)); + pool.picture_count = 1; + pool.picture = &picture; + pool.lock = Lock; + pool.unlock = Unlock; + sys->pool = picture_pool_NewExtended(&pool); + if (!sys->pool) { + picture_Release(picture); + free(sys); + return VLC_EGENERIC; + } + /* */ + vout_display_info_t info = vd->info; + info.has_hide_mouse = true; + + /* */ + vd->fmt = fmt; + vd->info = info; + vd->pool = Pool; + vd->prepare = NULL; + vd->display = Display; + vd->control = Control; + vd->manage = Manage; + + /* */ + vout_display_SendEventFullscreen(vd, false); + vout_display_SendEventDisplaySize(vd, fmt.i_width, fmt.i_height, false); return VLC_SUCCESS; } -/***************************************************************************** - * End: terminate video thread output method - *****************************************************************************/ -static void End( vout_thread_t *p_vout ) +static void Close(vlc_object_t *object) { - (void)p_vout; + vout_display_t *vd = (vout_display_t *)object; + vout_display_sys_t *sys = vd->sys; + + picture_pool_Delete(sys->pool); + free(sys); } -/***************************************************************************** - * Destroy: destroy video thread - ***************************************************************************** - * Terminate an output method created by Create - *****************************************************************************/ -static void Destroy( vlc_object_t *p_this ) +/* */ +static picture_pool_t *Pool(vout_display_t *vd, unsigned count) { - vout_thread_t *p_vout = ( vout_thread_t * )p_this; - - /* Destroy structure */ - free( p_vout->p_sys ); + VLC_UNUSED(count); + return vd->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 Display(vout_display_t *vd, picture_t *picture) { - p_pic->p->p_pixels = p_vout->p_sys->pf_lock( p_vout->p_sys->p_data ); - - return VLC_SUCCESS; + VLC_UNUSED(vd); + assert(!picture_IsReferenced(picture)); + picture_Release(picture); +} +static int Control(vout_display_t *vd, int query, va_list args) +{ + 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; + } +} +static void Manage(vout_display_t *vd) +{ + VLC_UNUSED(vd); } -/***************************************************************************** - * UnlockPicture: unlock a picture - ***************************************************************************** - * This function unlocks a previously locked picture. - *****************************************************************************/ -static int UnlockPicture( vout_thread_t *p_vout, picture_t *p_pic ) +/* */ +static int Lock(picture_t *picture) { - p_vout->p_sys->pf_unlock( p_vout->p_sys->p_data ); + picture_sys_t *sys = picture->p_sys; + + void *planes[PICTURE_PLANE_MAX]; + sys->lock(sys->sys, planes); - (void)p_pic; + for (int i = 0; i < picture->i_planes; i++) + picture->p[i].p_pixels = planes[i]; return VLC_SUCCESS; } +static void Unlock(picture_t *picture) +{ + picture_sys_t *sys = picture->p_sys; + + sys->unlock(sys->sys); +}