]> git.sesse.net Git - vlc/blob - modules/codec/fake.c
A bit of headers cleanup
[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_codec.h>
29
30 #include <vlc_image.h>
31 #include <vlc_filter.h>
32 #include <vlc_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 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." )
66
67 static const 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;
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     p_image = image_ReadUrl( p_handler, psz_file, &fmt_in, &fmt_out );
165     image_HandlerDelete( p_handler );
166
167     if ( p_image == NULL )
168     {
169         msg_Err( p_dec, "unable to read image file %s", psz_file );
170         return VLC_EGENERIC;
171     }
172     msg_Dbg( p_dec, "file %s loaded successfully", psz_file );
173
174     if ( psz_file ) free( psz_file );
175
176     if ( b_keep_ar )
177     {
178         picture_t *p_old = p_image;
179         int i_width, i_height;
180
181         var_Get( p_dec, "fake-width", &val );
182         i_width = val.i_int;
183         var_Get( p_dec, "fake-height", &val );
184         i_height = val.i_int;
185
186         if ( i_width && i_height )
187         {
188             int i_image_ar = fmt_out.i_width * VOUT_ASPECT_FACTOR
189                               / fmt_out.i_height;
190             int i_region_ar = i_width * VOUT_ASPECT_FACTOR / i_height;
191             fmt_in = fmt_out;
192
193             if ( i_aspect == i_image_ar )
194             {
195                 fmt_out.i_width = i_width;
196                 fmt_out.i_height = i_height;
197             }
198             else if ( i_image_ar > i_region_ar )
199             {
200                 fmt_out.i_width = i_width;
201                 fmt_out.i_height = i_width * VOUT_ASPECT_FACTOR
202                                     / i_image_ar;
203                 i_aspect = i_image_ar;
204             }
205             else
206             {
207                 fmt_out.i_height = i_height;
208                 fmt_out.i_width = i_height * i_image_ar
209                                     / VOUT_ASPECT_FACTOR;
210                 i_aspect = i_image_ar;
211             }
212
213             p_handler = image_HandlerCreate( p_dec );
214             p_image = image_Convert( p_handler, p_old, &fmt_in, &fmt_out );
215             image_HandlerDelete( p_handler );
216
217             if ( p_image == NULL )
218             {
219                 msg_Warn( p_dec, "couldn't load resizing module" );
220                 p_image = p_old;
221                 fmt_out = fmt_in;
222             }
223             else
224             {
225                 p_old->pf_release( p_old );
226             }
227         }
228     }
229
230     if ( i_aspect )
231     {
232         fmt_out.i_aspect = i_aspect;
233     }
234     else
235     {
236         fmt_out.i_aspect = fmt_out.i_width
237                             * VOUT_ASPECT_FACTOR / fmt_out.i_height;
238     }
239
240     var_Create( p_dec, "fake-deinterlace", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
241     var_Get( p_dec, "fake-deinterlace", &val );
242     if ( val.b_bool )
243     {
244         picture_t *p_old = p_image;
245
246         var_Create( p_dec, "fake-deinterlace-module",
247                     VLC_VAR_STRING | VLC_VAR_DOINHERIT );
248         var_Get( p_dec, "fake-deinterlace-module", &val );
249
250         p_handler = image_HandlerCreate( p_dec );
251         p_image = image_Filter( p_handler, p_old, &fmt_out, val.psz_string );
252         image_HandlerDelete( p_handler );
253         if ( val.psz_string != NULL ) free( val.psz_string );
254
255         if ( p_image == NULL )
256         {
257             msg_Warn( p_dec, "couldn't load deinterlace module" );
258             p_image = p_old;
259         }
260         else
261         {
262             p_old->pf_release( p_old );
263         }
264     }
265
266     /* Set output properties */
267     p_dec->fmt_out.i_cat = VIDEO_ES;
268     p_dec->fmt_out.i_codec = VLC_FOURCC('I','4','2','0');
269     p_dec->fmt_out.video = fmt_out;
270
271     /* Set callbacks */
272     p_dec->pf_decode_video = DecodeBlock;
273     p_dec->p_sys = (decoder_sys_t *)p_image;
274
275     return VLC_SUCCESS;
276 }
277
278 /****************************************************************************
279  * DecodeBlock: the whole thing
280  ****************************************************************************/
281 static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
282 {
283     picture_t *p_image = (picture_t *)p_dec->p_sys;
284     picture_t *p_pic;
285
286     if( pp_block == NULL || !*pp_block ) return NULL;
287     p_pic = p_dec->pf_vout_buffer_new( p_dec );
288     if( p_pic == NULL )
289     {
290         msg_Err( p_dec, "cannot get picture" );
291         goto error;
292     }
293
294     vout_CopyPicture( p_dec, p_pic, p_image );
295     p_pic->date = (*pp_block)->i_pts;
296
297 error:
298     block_Release( *pp_block );
299     *pp_block = NULL;
300
301     return p_pic;
302 }
303
304 /*****************************************************************************
305  * CloseDecoder: fake decoder destruction
306  *****************************************************************************/
307 static void CloseDecoder( vlc_object_t *p_this )
308 {
309     decoder_t *p_dec = (decoder_t *)p_this;
310     picture_t *p_image = (picture_t *)p_dec->p_sys;
311
312     if( p_image != NULL )
313         p_image->pf_release( p_image );
314 }