]> git.sesse.net Git - vlc/blob - modules/codec/fake.c
All: missing #include "charset.h"
[vlc] / modules / codec / fake.c
1 /*****************************************************************************
2  * fake.c: decoder reading from a fake stream, outputting a fixed image
3  *****************************************************************************
4  * Copyright (C) 2005 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Christophe Massiot <massiot@via.ecp.fr>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <vlc/vlc.h>
28 #include <vlc/decoder.h>
29
30 #include "vlc_image.h"
31 #include "vlc_filter.h"
32 #include "charset.h"
33
34 /*****************************************************************************
35  * Local prototypes
36  *****************************************************************************/
37 static int  OpenDecoder   ( vlc_object_t * );
38 static void CloseDecoder  ( vlc_object_t * );
39
40 static picture_t *DecodeBlock  ( decoder_t *, block_t ** );
41
42 /*****************************************************************************
43  * Module descriptor
44  *****************************************************************************/
45 #define FILE_TEXT N_("Image file")
46 #define FILE_LONGTEXT N_( \
47     "Path of the image file when using the fake input." )
48 #define WIDTH_TEXT N_("Video width")
49 #define WIDTH_LONGTEXT N_( \
50     "Allows you to specify the output video width." )
51 #define HEIGHT_TEXT N_("Video height")
52 #define HEIGHT_LONGTEXT N_( \
53     "Allows you to specify the output video height." )
54 #define KEEP_AR_TEXT N_("Keep aspect ratio")
55 #define KEEP_AR_LONGTEXT N_( \
56     "If selected, width and height will be considered 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     "Allows you to deinterlace the image after loading." )
63 #define DEINTERLACE_MODULE_TEXT N_("Deinterlace module")
64 #define DEINTERLACE_MODULE_LONGTEXT N_( \
65     "Specifies the deinterlace module to use." )
66
67 static char *ppsz_deinterlace_type[] =
68 {
69     "deinterlace", "ffmpeg-deinterlace"
70 };
71
72 vlc_module_begin();
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" );
80
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,
88               VLC_TRUE );
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,
95                 VLC_FALSE );
96         change_string_list( ppsz_deinterlace_type, 0, 0 );
97 vlc_module_end();
98
99 /*****************************************************************************
100  * OpenDecoder: probe the decoder and return score
101  *****************************************************************************/
102 static int OpenDecoder( vlc_object_t *p_this )
103 {
104     decoder_t *p_dec = (decoder_t*)p_this;
105     vlc_value_t val;
106     image_handler_t *p_handler;
107     video_format_t fmt_in, fmt_out;
108     picture_t *p_image;
109     char *psz_file, *psz_local;
110     vlc_bool_t b_keep_ar;
111     int i_aspect = 0;
112
113     if( p_dec->fmt_in.i_codec != VLC_FOURCC('f','a','k','e') )
114     {
115         return VLC_EGENERIC;
116     }
117
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 )
121     {
122         if( val.psz_string ) free( val.psz_string );
123         msg_Err( p_dec, "specify a file with --fake-file=..." );
124         return VLC_EGENERIC;
125     }
126     psz_file = val.psz_string;
127
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');
131
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;
135
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 );
140
141     var_Get( p_dec, "fake-aspect-ratio", &val );
142     if ( val.psz_string )
143     {
144         char *psz_parser = strchr( val.psz_string, ':' );
145
146         if( psz_parser )
147         {
148             *psz_parser++ = '\0';
149             i_aspect = atoi( val.psz_string )
150                                    * VOUT_ASPECT_FACTOR / atoi( psz_parser );
151         }
152         free( val.psz_string );
153     }
154
155     if ( !b_keep_ar )
156     {
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;
161     }
162
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 );
168
169     if ( p_image == NULL )
170     {
171         msg_Err( p_dec, "unable to read image file %s", psz_file );
172         return VLC_EGENERIC;
173     }
174     msg_Dbg( p_dec, "file %s loaded successfully", psz_file );
175
176     if ( psz_file ) free( psz_file );
177
178     if ( b_keep_ar )
179     {
180         picture_t *p_old = p_image;
181         int i_width, i_height;
182
183         var_Get( p_dec, "fake-width", &val );
184         i_width = val.i_int;
185         var_Get( p_dec, "fake-height", &val );
186         i_height = val.i_int;
187
188         if ( i_width && i_height )
189         {
190             int i_image_ar = fmt_out.i_width * VOUT_ASPECT_FACTOR
191                               / fmt_out.i_height;
192             int i_region_ar = i_width * VOUT_ASPECT_FACTOR / i_height;
193             fmt_in = fmt_out;
194
195             if ( i_aspect == i_image_ar )
196             {
197                 fmt_out.i_width = i_width;
198                 fmt_out.i_height = i_height;
199             }
200             else if ( i_image_ar > i_region_ar )
201             {
202                 fmt_out.i_width = i_width;
203                 fmt_out.i_height = i_width * VOUT_ASPECT_FACTOR
204                                     / i_image_ar;
205                 i_aspect = i_image_ar;
206             }
207             else
208             {
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;
213             }
214
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 );
218
219             if ( p_image == NULL )
220             {
221                 msg_Warn( p_dec, "couldn't load resizing module" );
222                 p_image = p_old;
223                 fmt_out = fmt_in;
224             }
225             else
226             {
227                 p_old->pf_release( p_old );
228             }
229         }
230     }
231
232     if ( i_aspect )
233     {
234         fmt_out.i_aspect = i_aspect;
235     }
236     else
237     {
238         fmt_out.i_aspect = fmt_out.i_width
239                             * VOUT_ASPECT_FACTOR / fmt_out.i_height;
240     }
241
242     var_Create( p_dec, "fake-deinterlace", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
243     var_Get( p_dec, "fake-deinterlace", &val );
244     if ( val.b_bool )
245     {
246         picture_t *p_old = p_image;
247
248         var_Create( p_dec, "fake-deinterlace-module",
249                     VLC_VAR_STRING | VLC_VAR_DOINHERIT );
250         var_Get( p_dec, "fake-deinterlace-module", &val );
251
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 );
256
257         if ( p_image == NULL )
258         {
259             msg_Warn( p_dec, "couldn't load deinterlace module" );
260             p_image = p_old;
261         }
262         else
263         {
264             p_old->pf_release( p_old );
265         }
266     }
267
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;
272
273     /* Set callbacks */
274     p_dec->pf_decode_video = DecodeBlock;
275     p_dec->p_sys = (decoder_sys_t *)p_image;
276
277     return VLC_SUCCESS;
278 }
279
280 /****************************************************************************
281  * DecodeBlock: the whole thing
282  ****************************************************************************/
283 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
284 {
285     picture_t *p_image = (picture_t *)p_dec->p_sys;
286     picture_t *p_pic;
287
288     if( pp_block == NULL || !*pp_block ) return NULL;
289     p_pic = p_dec->pf_vout_buffer_new( p_dec );
290     if( p_pic == NULL )
291     {
292         msg_Err( p_dec, "cannot get picture" );
293         goto error;
294     }
295
296     vout_CopyPicture( p_dec, p_pic, p_image );
297     p_pic->date = (*pp_block)->i_pts;
298
299 error:
300     block_Release( *pp_block );
301     *pp_block = NULL;
302
303     return p_pic;
304 }
305
306 /*****************************************************************************
307  * CloseDecoder: fake decoder destruction
308  *****************************************************************************/
309 static void CloseDecoder( vlc_object_t *p_this )
310 {
311     decoder_t *p_dec = (decoder_t *)p_this;
312     picture_t *p_image = (picture_t *)p_dec->p_sys;
313
314     if( p_image != NULL )
315         p_image->pf_release( p_image );
316 }