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_codec.h>
30 #include <vlc_image.h>
31 #include <vlc_filter.h>
32 #include <vlc_charset.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 const 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
;
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 p_image
= image_ReadUrl( p_handler
, psz_file
, &fmt_in
, &fmt_out
);
165 image_HandlerDelete( p_handler
);
167 if ( p_image
== NULL
)
169 msg_Err( p_dec
, "unable to read image file %s", psz_file
);
172 msg_Dbg( p_dec
, "file %s loaded successfully", psz_file
);
174 if ( psz_file
) free( psz_file
);
178 picture_t
*p_old
= p_image
;
179 int i_width
, i_height
;
181 var_Get( p_dec
, "fake-width", &val
);
183 var_Get( p_dec
, "fake-height", &val
);
184 i_height
= val
.i_int
;
186 if ( i_width
&& i_height
)
188 int i_image_ar
= fmt_out
.i_width
* VOUT_ASPECT_FACTOR
190 int i_region_ar
= i_width
* VOUT_ASPECT_FACTOR
/ i_height
;
193 if ( i_aspect
== i_image_ar
)
195 fmt_out
.i_width
= i_width
;
196 fmt_out
.i_height
= i_height
;
198 else if ( i_image_ar
> i_region_ar
)
200 fmt_out
.i_width
= i_width
;
201 fmt_out
.i_height
= i_width
* VOUT_ASPECT_FACTOR
203 i_aspect
= i_image_ar
;
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
;
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
);
217 if ( p_image
== NULL
)
219 msg_Warn( p_dec
, "couldn't load resizing module" );
225 p_old
->pf_release( p_old
);
232 fmt_out
.i_aspect
= i_aspect
;
236 fmt_out
.i_aspect
= fmt_out
.i_width
237 * VOUT_ASPECT_FACTOR
/ fmt_out
.i_height
;
240 var_Create( p_dec
, "fake-deinterlace", VLC_VAR_BOOL
| VLC_VAR_DOINHERIT
);
241 var_Get( p_dec
, "fake-deinterlace", &val
);
244 picture_t
*p_old
= p_image
;
246 var_Create( p_dec
, "fake-deinterlace-module",
247 VLC_VAR_STRING
| VLC_VAR_DOINHERIT
);
248 var_Get( p_dec
, "fake-deinterlace-module", &val
);
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
);
255 if ( p_image
== NULL
)
257 msg_Warn( p_dec
, "couldn't load deinterlace module" );
262 p_old
->pf_release( p_old
);
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
;
272 p_dec
->pf_decode_video
= DecodeBlock
;
273 p_dec
->p_sys
= (decoder_sys_t
*)p_image
;
278 /****************************************************************************
279 * DecodeBlock: the whole thing
280 ****************************************************************************/
281 static picture_t
*DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
283 picture_t
*p_image
= (picture_t
*)p_dec
->p_sys
;
286 if( pp_block
== NULL
|| !*pp_block
) return NULL
;
287 p_pic
= p_dec
->pf_vout_buffer_new( p_dec
);
290 msg_Err( p_dec
, "cannot get picture" );
294 vout_CopyPicture( p_dec
, p_pic
, p_image
);
295 p_pic
->date
= (*pp_block
)->i_pts
;
298 block_Release( *pp_block
);
304 /*****************************************************************************
305 * CloseDecoder: fake decoder destruction
306 *****************************************************************************/
307 static void CloseDecoder( vlc_object_t
*p_this
)
309 decoder_t
*p_dec
= (decoder_t
*)p_this
;
310 picture_t
*p_image
= (picture_t
*)p_dec
->p_sys
;
312 if( p_image
!= NULL
)
313 p_image
->pf_release( p_image
);