1 /*****************************************************************************
2 * invmem_decoder.c: memory video driver for vlc
3 *****************************************************************************
4 * Copyright (C) 2008 the VideoLAN team
7 * Authors: Robert Paciorek <robert@opcode.eu.org> <http://opcode.eu.org/bercik>
9 * - vmem video output module (Gildas Bazin <gbazin@videolan.org>)
10 * - png video decodec module (Sam Hocevar <sam@zoy.org>)
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
37 #include <vlc_codec.h>
39 #include <vlc_image.h>
40 #include <vlc_filter.h>
42 /*****************************************************************************
44 *****************************************************************************/
45 static int OpenDecoder ( vlc_object_t * );
46 static void CloseDecoder ( vlc_object_t * );
48 static picture_t *DecodeBlock ( decoder_t *, block_t ** );
50 /*****************************************************************************
52 *****************************************************************************/
53 #define T_WIDTH N_( "Width" )
54 #define LT_WIDTH N_( "Video memory buffer width." )
56 #define T_HEIGHT N_( "Height" )
57 #define LT_HEIGHT N_( "Video memory buffer height." )
59 #define T_LOCK N_( "Lock function" )
60 #define LT_LOCK N_( "Address of the locking callback function. This " \
61 "function must return a valid memory address for use " \
62 "by the video renderer." )
64 #define T_UNLOCK N_( "Unlock function" )
65 #define LT_UNLOCK N_( "Address of the unlocking callback function" )
67 #define T_DATA N_( "Callback data" )
68 #define LT_DATA N_( "Data for the locking and unlocking functions" )
70 #define T_CHROMA N_("Chroma")
71 #define LT_CHROMA N_("Output chroma for the memory image as a 4-character " \
72 "string, eg. \"RV32\".")
74 #define INVMEM_HELP N_( "This module make possible making video stream from raw-image " \
75 "generating (to memory) from rendering program uses libvlc. " \
76 "To use this module from libvlc set --codec to invmem, "\
77 "set all --invmem-* options in vlc_argv an use " \
78 "libvlc_media_new(libvlc, \"fake://\", &ex);. " \
79 "Besides is simillar to vmem video output module." )
82 set_category( CAT_INPUT )
83 set_subcategory( SUBCAT_INPUT_VCODEC )
84 set_shortname( N_("Memory video decoder") )
85 set_description( N_("Memory video decoder") )
86 set_help( INVMEM_HELP )
87 set_capability( "decoder", 50 )
88 set_callbacks( OpenDecoder, CloseDecoder )
89 add_shortcut( "invmem" )
91 add_integer( "invmem-width", 0, NULL, T_WIDTH, LT_WIDTH, false )
92 add_integer( "invmem-height", 0, NULL, T_HEIGHT, LT_HEIGHT, false )
93 add_string( "invmem-lock", "0", NULL, T_LOCK, LT_LOCK, true )
94 add_string( "invmem-unlock", "0", NULL, T_UNLOCK, LT_UNLOCK, true )
95 add_string( "invmem-data", "0", NULL, T_DATA, LT_DATA, true )
96 add_string( "invmem-chroma", "RV24", NULL, T_CHROMA, LT_CHROMA, true)
102 void * (*pf_lock) (void *);
103 void (*pf_unlock) (void *);
110 vlc_fourcc_t i_chroma;
114 /*****************************************************************************
115 * OpenDecoder: probe the decoder and return score
116 *****************************************************************************/
117 static int OpenDecoder( vlc_object_t *p_this )
119 decoder_t *p_dec = (decoder_t*)p_this;
120 decoder_sys_t *p_sys;
124 if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','a','k','e'))
129 /* Allocate the memory needed to store the decoder's structure */
130 if( ( p_dec->p_sys = p_sys = malloc(sizeof(decoder_sys_t)) ) == NULL )
134 char* chromaStr = var_CreateGetString( p_dec, "invmem-chroma" );
135 p_sys->i_width = var_CreateGetInteger( p_this, "invmem-width" );
136 p_sys->i_height = var_CreateGetInteger( p_this, "invmem-height" );
137 if( p_sys->i_width == 0 || p_sys->i_height == 0 )
139 msg_Err( p_dec, "--invmem-width and --invmem-height must be > 0" );
143 psz_tmp = var_CreateGetString( p_dec, "invmem-lock" );
144 p_sys->pf_lock = (void * (*) (void *))(intptr_t)atoll( psz_tmp );
147 psz_tmp = var_CreateGetString( p_dec, "invmem-unlock" );
148 p_sys->pf_unlock = (void (*) (void *))(intptr_t)atoll( psz_tmp );
151 psz_tmp = var_CreateGetString( p_dec, "invmem-data" );
152 p_sys->p_data = (void *)(intptr_t)atoll( psz_tmp );
155 if( !p_sys->pf_lock || !p_sys->pf_unlock )
157 msg_Err( p_dec, "Invalid lock or unlock callbacks" );
161 if ( chromaStr == NULL )
163 msg_Err( p_dec, "Invalid invmem-chroma string." );
166 const vlc_fourcc_t chroma = vlc_fourcc_GetCodecFromString( VIDEO_ES, chromaStr );
170 msg_Err( p_dec, "invmem-chroma should be 4 characters long." );
174 /* Set output properties */
177 case VLC_CODEC_RGB15:
178 p_dec->fmt_out.video.i_rmask = 0x001f;
179 p_dec->fmt_out.video.i_gmask = 0x03e0;
180 p_dec->fmt_out.video.i_bmask = 0x7c00;
181 pitch = p_sys->i_width * 2;
183 case VLC_CODEC_RGB16:
184 p_dec->fmt_out.video.i_rmask = 0x001f;
185 p_dec->fmt_out.video.i_gmask = 0x07e0;
186 p_dec->fmt_out.video.i_bmask = 0xf800;
187 pitch = p_sys->i_width * 2;
189 case VLC_CODEC_RGB24:
190 p_dec->fmt_out.video.i_rmask = 0xff0000;
191 p_dec->fmt_out.video.i_gmask = 0x00ff00;
192 p_dec->fmt_out.video.i_bmask = 0x0000ff;
193 pitch = p_sys->i_width * 3;
195 case VLC_CODEC_RGB32:
196 p_dec->fmt_out.video.i_rmask = 0xff0000;
197 p_dec->fmt_out.video.i_gmask = 0x00ff00;
198 p_dec->fmt_out.video.i_bmask = 0x0000ff;
199 pitch = p_sys->i_width * 4;
202 p_dec->fmt_out.video.i_rmask = 0;
203 p_dec->fmt_out.video.i_gmask = 0;
204 p_dec->fmt_out.video.i_bmask = 0;
206 msg_Warn( p_dec, "Unknown chroma %s", chromaStr );
212 p_dec->fmt_out.i_codec = chroma;
213 p_dec->fmt_out.video.i_width = p_dec->p_sys->i_width;
214 p_dec->fmt_out.video.i_height = p_dec->p_sys->i_height;
215 p_dec->fmt_out.video.i_sar_num = 1;
216 p_dec->fmt_out.video.i_sar_den = 1;
217 p_dec->fmt_out.i_cat = VIDEO_ES;
219 p_sys->i_pitch = pitch;
222 p_dec->pf_decode_video = DecodeBlock;
231 /****************************************************************************
232 * DecodeBlock: the whole thing
233 ****************************************************************************
234 * This function must be fed with a complete compressed frame.
235 ****************************************************************************/
236 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
238 decoder_sys_t *p_sys = p_dec->p_sys;
242 if( !pp_block || !*pp_block ) return NULL;
246 // create new picture
247 p_pic = decoder_NewPicture( p_dec );
248 if ( !p_pic ) return NULL;
249 p_pic->b_force = true;
250 p_pic->p->i_pitch = p_dec->p_sys->i_pitch;
251 p_pic->date = p_block->i_pts > VLC_TS_INVALID ? p_block->i_pts : p_block->i_dts;
253 // lock input and copy to picture
254 p_pic->p->p_pixels = p_sys->pf_lock( p_dec->p_sys->p_data );
257 p_sys->pf_unlock( p_dec->p_sys->p_data );
259 block_Release( *pp_block ); *pp_block = NULL;
263 /*****************************************************************************
264 * CloseDecoder: invmem decoder destruction
265 *****************************************************************************/
266 static void CloseDecoder( vlc_object_t *p_this )
268 decoder_t *p_dec = (decoder_t *)p_this;
269 decoder_sys_t *p_sys = p_dec->p_sys;