1 /*****************************************************************************
2 * fake.c: decoder reading from a fake stream, outputting a fixed image
3 *****************************************************************************
4 * Copyright (C) 2005 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
28 #include <vlc/decoder.h>
30 #include "vlc_image.h"
31 #include "vlc_filter.h"
34 /*****************************************************************************
36 *****************************************************************************/
37 static int OpenDecoder ( vlc_object_t * );
38 static void CloseDecoder ( vlc_object_t * );
40 static picture_t *DecodeBlock ( decoder_t *, block_t ** );
42 /*****************************************************************************
44 *****************************************************************************/
45 #define FILE_TEXT N_("Image file")
46 #define FILE_LONGTEXT N_( \
47 "Path of the image file for fake input." )
48 #define WIDTH_TEXT N_("Video width")
49 #define WIDTH_LONGTEXT N_( \
50 "Output video width." )
51 #define HEIGHT_TEXT N_("Video height")
52 #define HEIGHT_LONGTEXT N_( \
53 "Output video height." )
54 #define KEEP_AR_TEXT N_("Keep aspect ratio")
55 #define KEEP_AR_LONGTEXT N_( \
56 "Consider width and height as maximum values." )
57 #define ASPECT_RATIO_TEXT N_("Background aspect ratio")
58 #define ASPECT_RATIO_LONGTEXT N_( \
59 "Aspect ratio of the image file (4:3, 16:9). Default is square pixels." )
60 #define DEINTERLACE_TEXT N_("Deinterlace video")
61 #define DEINTERLACE_LONGTEXT N_( \
62 "Deinterlace the image after loading it." )
63 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
64 #define DEINTERLACE_MODULE_LONGTEXT N_( \
65 "Deinterlace module to use." )
67 static char *ppsz_deinterlace_type[] =
69 "deinterlace", "ffmpeg-deinterlace"
73 set_category( CAT_INPUT );
74 set_subcategory( SUBCAT_INPUT_VCODEC );
75 set_shortname( _("Fake") );
76 set_description( _("Fake video decoder") );
77 set_capability( "decoder", 1000 );
78 set_callbacks( OpenDecoder, CloseDecoder );
79 add_shortcut( "fake" );
81 add_file( "fake-file", "", NULL, FILE_TEXT,
82 FILE_LONGTEXT, VLC_FALSE );
83 add_integer( "fake-width", 0, NULL, WIDTH_TEXT,
84 WIDTH_LONGTEXT, VLC_TRUE );
85 add_integer( "fake-height", 0, NULL, HEIGHT_TEXT,
86 HEIGHT_LONGTEXT, VLC_TRUE );
87 add_bool( "fake-keep-ar", 0, NULL, KEEP_AR_TEXT, KEEP_AR_LONGTEXT,
89 add_string( "fake-aspect-ratio", "", NULL,
90 ASPECT_RATIO_TEXT, ASPECT_RATIO_LONGTEXT, VLC_TRUE );
91 add_bool( "fake-deinterlace", 0, NULL, DEINTERLACE_TEXT,
92 DEINTERLACE_LONGTEXT, VLC_FALSE );
93 add_string( "fake-deinterlace-module", "deinterlace", NULL,
94 DEINTERLACE_MODULE_TEXT, DEINTERLACE_MODULE_LONGTEXT,
96 change_string_list( ppsz_deinterlace_type, 0, 0 );
99 /*****************************************************************************
100 * OpenDecoder: probe the decoder and return score
101 *****************************************************************************/
102 static int OpenDecoder( vlc_object_t *p_this )
104 decoder_t *p_dec = (decoder_t*)p_this;
106 image_handler_t *p_handler;
107 video_format_t fmt_in, fmt_out;
109 char *psz_file, *psz_local;
110 vlc_bool_t b_keep_ar;
113 if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','a','k','e') )
118 var_Create( p_dec, "fake-file", VLC_VAR_STRING | VLC_VAR_DOINHERIT );
119 var_Get( p_dec, "fake-file", &val );
120 if( val.psz_string == NULL || !*val.psz_string )
122 if( val.psz_string ) free( val.psz_string );
123 msg_Err( p_dec, "specify a file with --fake-file=..." );
126 psz_file = val.psz_string;
128 memset( &fmt_in, 0, sizeof(fmt_in) );
129 memset( &fmt_out, 0, sizeof(fmt_out) );
130 fmt_out.i_chroma = VLC_FOURCC('I','4','2','0');
132 var_Create( p_dec, "fake-keep-ar", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
133 var_Get( p_dec, "fake-keep-ar", &val );
134 b_keep_ar = val.b_bool;
136 var_Create( p_dec, "fake-width", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
137 var_Create( p_dec, "fake-height", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
138 var_Create( p_dec, "fake-aspect-ratio",
139 VLC_VAR_STRING | VLC_VAR_DOINHERIT );
141 var_Get( p_dec, "fake-aspect-ratio", &val );
142 if ( val.psz_string )
144 char *psz_parser = strchr( val.psz_string, ':' );
148 *psz_parser++ = '\0';
149 i_aspect = atoi( val.psz_string )
150 * VOUT_ASPECT_FACTOR / atoi( psz_parser );
152 free( val.psz_string );
157 var_Get( p_dec, "fake-width", &val );
158 fmt_out.i_width = val.i_int;
159 var_Get( p_dec, "fake-height", &val );
160 fmt_out.i_height = val.i_int;
163 p_handler = image_HandlerCreate( p_dec );
164 psz_local = ToLocale( psz_file );
165 p_image = image_ReadUrl( p_handler, psz_local, &fmt_in, &fmt_out );
166 LocaleFree( psz_local );
167 image_HandlerDelete( p_handler );
169 if ( p_image == NULL )
171 msg_Err( p_dec, "unable to read image file %s", psz_file );
174 msg_Dbg( p_dec, "file %s loaded successfully", psz_file );
176 if ( psz_file ) free( psz_file );
180 picture_t *p_old = p_image;
181 int i_width, i_height;
183 var_Get( p_dec, "fake-width", &val );
185 var_Get( p_dec, "fake-height", &val );
186 i_height = val.i_int;
188 if ( i_width && i_height )
190 int i_image_ar = fmt_out.i_width * VOUT_ASPECT_FACTOR
192 int i_region_ar = i_width * VOUT_ASPECT_FACTOR / i_height;
195 if ( i_aspect == i_image_ar )
197 fmt_out.i_width = i_width;
198 fmt_out.i_height = i_height;
200 else if ( i_image_ar > i_region_ar )
202 fmt_out.i_width = i_width;
203 fmt_out.i_height = i_width * VOUT_ASPECT_FACTOR
205 i_aspect = i_image_ar;
209 fmt_out.i_height = i_height;
210 fmt_out.i_width = i_height * i_image_ar
211 / VOUT_ASPECT_FACTOR;
212 i_aspect = i_image_ar;
215 p_handler = image_HandlerCreate( p_dec );
216 p_image = image_Convert( p_handler, p_old, &fmt_in, &fmt_out );
217 image_HandlerDelete( p_handler );
219 if ( p_image == NULL )
221 msg_Warn( p_dec, "couldn't load resizing module" );
227 p_old->pf_release( p_old );
234 fmt_out.i_aspect = i_aspect;
238 fmt_out.i_aspect = fmt_out.i_width
239 * VOUT_ASPECT_FACTOR / fmt_out.i_height;
242 var_Create( p_dec, "fake-deinterlace", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
243 var_Get( p_dec, "fake-deinterlace", &val );
246 picture_t *p_old = p_image;
248 var_Create( p_dec, "fake-deinterlace-module",
249 VLC_VAR_STRING | VLC_VAR_DOINHERIT );
250 var_Get( p_dec, "fake-deinterlace-module", &val );
252 p_handler = image_HandlerCreate( p_dec );
253 p_image = image_Filter( p_handler, p_old, &fmt_out, val.psz_string );
254 image_HandlerDelete( p_handler );
255 if ( val.psz_string != NULL ) free( val.psz_string );
257 if ( p_image == NULL )
259 msg_Warn( p_dec, "couldn't load deinterlace module" );
264 p_old->pf_release( p_old );
268 /* Set output properties */
269 p_dec->fmt_out.i_cat = VIDEO_ES;
270 p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
271 p_dec->fmt_out.video = fmt_out;
274 p_dec->pf_decode_video = DecodeBlock;
275 p_dec->p_sys = (decoder_sys_t *)p_image;
280 /****************************************************************************
281 * DecodeBlock: the whole thing
282 ****************************************************************************/
283 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
285 picture_t *p_image = (picture_t *)p_dec->p_sys;
288 if( pp_block == NULL || !*pp_block ) return NULL;
289 p_pic = p_dec->pf_vout_buffer_new( p_dec );
292 msg_Err( p_dec, "cannot get picture" );
296 vout_CopyPicture( p_dec, p_pic, p_image );
297 p_pic->date = (*pp_block)->i_pts;
300 block_Release( *pp_block );
306 /*****************************************************************************
307 * CloseDecoder: fake decoder destruction
308 *****************************************************************************/
309 static void CloseDecoder( vlc_object_t *p_this )
311 decoder_t *p_dec = (decoder_t *)p_this;
312 picture_t *p_image = (picture_t *)p_dec->p_sys;
314 if( p_image != NULL )
315 p_image->pf_release( p_image );