1 /*****************************************************************************
2 * image.c : wrapper for image reading/writing facilities
3 *****************************************************************************
4 * Copyright (C) 2004-2007 the VideoLAN team
7 * Author: Gildas Bazin <gbazin@videolan.org>
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 *****************************************************************************/
26 * This file contains the functions to handle the image_handler_t type
29 /*****************************************************************************
31 *****************************************************************************/
40 #include <vlc_common.h>
41 #include <vlc_codec.h>
43 #include <vlc_filter.h>
45 #include <vlc_image.h>
46 #include <vlc_stream.h>
47 #include <vlc_charset.h>
51 static picture_t
*ImageRead( image_handler_t
*, block_t
*,
52 video_format_t
*, video_format_t
* );
53 static picture_t
*ImageReadUrl( image_handler_t
*, const char *,
54 video_format_t
*, video_format_t
* );
55 static block_t
*ImageWrite( image_handler_t
*, picture_t
*,
56 video_format_t
*, video_format_t
* );
57 static int ImageWriteUrl( image_handler_t
*, picture_t
*,
58 video_format_t
*, video_format_t
*, const char * );
60 static picture_t
*ImageConvert( image_handler_t
*, picture_t
*,
61 video_format_t
*, video_format_t
* );
62 static picture_t
*ImageFilter( image_handler_t
*, picture_t
*,
63 video_format_t
*, const char *psz_module
);
65 static decoder_t
*CreateDecoder( vlc_object_t
*, video_format_t
* );
66 static void DeleteDecoder( decoder_t
* );
67 static encoder_t
*CreateEncoder( vlc_object_t
*, video_format_t
*,
69 static void DeleteEncoder( encoder_t
* );
70 static filter_t
*CreateFilter( vlc_object_t
*, es_format_t
*,
71 video_format_t
*, const char * );
72 static void DeleteFilter( filter_t
* );
74 vlc_fourcc_t
image_Type2Fourcc( const char * );
75 vlc_fourcc_t
image_Ext2Fourcc( const char * );
76 /*static const char *Fourcc2Ext( vlc_fourcc_t );*/
79 * Create an image_handler_t instance
82 image_handler_t
*__image_HandlerCreate( vlc_object_t
*p_this
)
84 image_handler_t
*p_image
= calloc( 1, sizeof(image_handler_t
) );
88 p_image
->p_parent
= p_this
;
90 p_image
->pf_read
= ImageRead
;
91 p_image
->pf_read_url
= ImageReadUrl
;
92 p_image
->pf_write
= ImageWrite
;
93 p_image
->pf_write_url
= ImageWriteUrl
;
94 p_image
->pf_convert
= ImageConvert
;
95 p_image
->pf_filter
= ImageFilter
;
101 * Delete the image_handler_t instance
104 void image_HandlerDelete( image_handler_t
*p_image
)
106 if( !p_image
) return;
108 if( p_image
->p_dec
) DeleteDecoder( p_image
->p_dec
);
109 if( p_image
->p_enc
) DeleteEncoder( p_image
->p_enc
);
110 if( p_image
->p_filter
) DeleteFilter( p_image
->p_filter
);
121 static picture_t
*ImageRead( image_handler_t
*p_image
, block_t
*p_block
,
122 video_format_t
*p_fmt_in
,
123 video_format_t
*p_fmt_out
)
125 picture_t
*p_pic
= NULL
, *p_tmp
;
127 /* Check if we can reuse the current decoder */
128 if( p_image
->p_dec
&&
129 p_image
->p_dec
->fmt_in
.i_codec
!= p_fmt_in
->i_chroma
)
131 DeleteDecoder( p_image
->p_dec
);
135 /* Start a decoder */
136 if( !p_image
->p_dec
)
138 p_image
->p_dec
= CreateDecoder( p_image
->p_parent
, p_fmt_in
);
139 if( !p_image
->p_dec
) return NULL
;
142 p_block
->i_pts
= p_block
->i_dts
= mdate();
143 while( (p_tmp
= p_image
->p_dec
->pf_decode_video( p_image
->p_dec
, &p_block
))
147 picture_Release( p_pic
);
153 msg_Warn( p_image
->p_parent
, "no image decoded" );
157 if( !p_fmt_out
->i_chroma
)
158 p_fmt_out
->i_chroma
= p_image
->p_dec
->fmt_out
.video
.i_chroma
;
159 if( !p_fmt_out
->i_width
&& p_fmt_out
->i_height
)
160 p_fmt_out
->i_width
= p_fmt_out
->i_height
161 * p_image
->p_dec
->fmt_out
.video
.i_aspect
162 / VOUT_ASPECT_FACTOR
;
163 if( !p_fmt_out
->i_height
&& p_fmt_out
->i_width
)
164 p_fmt_out
->i_height
= p_fmt_out
->i_width
* VOUT_ASPECT_FACTOR
165 / p_image
->p_dec
->fmt_out
.video
.i_aspect
;
166 if( !p_fmt_out
->i_width
)
167 p_fmt_out
->i_width
= p_image
->p_dec
->fmt_out
.video
.i_width
;
168 if( !p_fmt_out
->i_height
)
169 p_fmt_out
->i_height
= p_image
->p_dec
->fmt_out
.video
.i_height
;
171 /* Check if we need chroma conversion or resizing */
172 if( p_image
->p_dec
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
||
173 p_image
->p_dec
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
174 p_image
->p_dec
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
)
176 if( p_image
->p_filter
)
177 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!=
178 p_image
->p_dec
->fmt_out
.video
.i_chroma
||
179 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
181 /* We need to restart a new filter */
182 DeleteFilter( p_image
->p_filter
);
183 p_image
->p_filter
= 0;
187 if( !p_image
->p_filter
)
190 CreateFilter( p_image
->p_parent
, &p_image
->p_dec
->fmt_out
,
193 if( !p_image
->p_filter
)
195 picture_Release( p_pic
);
201 /* Filters should handle on-the-fly size changes */
202 p_image
->p_filter
->fmt_in
= p_image
->p_dec
->fmt_out
;
203 p_image
->p_filter
->fmt_out
= p_image
->p_dec
->fmt_out
;
204 p_image
->p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
205 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
208 p_pic
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
209 *p_fmt_out
= p_image
->p_filter
->fmt_out
.video
;
211 else *p_fmt_out
= p_image
->p_dec
->fmt_out
.video
;
216 static picture_t
*ImageReadUrl( image_handler_t
*p_image
, const char *psz_url
,
217 video_format_t
*p_fmt_in
,
218 video_format_t
*p_fmt_out
)
222 stream_t
*p_stream
= NULL
;
225 p_stream
= stream_UrlNew( p_image
->p_parent
, psz_url
);
229 msg_Dbg( p_image
->p_parent
, "could not open %s for reading",
234 i_size
= stream_Size( p_stream
);
236 p_block
= block_New( p_image
->p_parent
, i_size
);
238 stream_Read( p_stream
, p_block
->p_buffer
, i_size
);
240 if( !p_fmt_in
->i_chroma
)
242 char *psz_mime
= NULL
;
243 stream_Control( p_stream
, STREAM_GET_CONTENT_TYPE
, &psz_mime
);
245 p_fmt_in
->i_chroma
= image_Mime2Fourcc( psz_mime
);
248 stream_Delete( p_stream
);
250 if( !p_fmt_in
->i_chroma
)
252 /* Try to guess format from file name */
253 p_fmt_in
->i_chroma
= image_Ext2Fourcc( psz_url
);
256 p_pic
= ImageRead( p_image
, p_block
, p_fmt_in
, p_fmt_out
);
266 static block_t
*ImageWrite( image_handler_t
*p_image
, picture_t
*p_pic
,
267 video_format_t
*p_fmt_in
,
268 video_format_t
*p_fmt_out
)
272 /* Check if we can reuse the current encoder */
273 if( p_image
->p_enc
&&
274 ( p_image
->p_enc
->fmt_out
.i_codec
!= p_fmt_out
->i_chroma
||
275 p_image
->p_enc
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
276 p_image
->p_enc
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
) )
278 DeleteEncoder( p_image
->p_enc
);
282 /* Start an encoder */
283 if( !p_image
->p_enc
)
285 p_image
->p_enc
= CreateEncoder( p_image
->p_parent
,
286 p_fmt_in
, p_fmt_out
);
287 if( !p_image
->p_enc
) return NULL
;
290 /* Check if we need chroma conversion or resizing */
291 if( p_image
->p_enc
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
292 p_image
->p_enc
->fmt_in
.video
.i_width
!= p_fmt_in
->i_width
||
293 p_image
->p_enc
->fmt_in
.video
.i_height
!= p_fmt_in
->i_height
)
295 picture_t
*p_tmp_pic
;
297 if( p_image
->p_filter
)
298 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
299 p_image
->p_filter
->fmt_out
.video
.i_chroma
!=
300 p_image
->p_enc
->fmt_in
.video
.i_chroma
)
302 /* We need to restart a new filter */
303 DeleteFilter( p_image
->p_filter
);
304 p_image
->p_filter
= 0;
308 if( !p_image
->p_filter
)
311 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
312 fmt_in
.video
= *p_fmt_in
;
315 CreateFilter( p_image
->p_parent
, &fmt_in
,
316 &p_image
->p_enc
->fmt_in
.video
, NULL
);
318 if( !p_image
->p_filter
)
325 /* Filters should handle on-the-fly size changes */
326 p_image
->p_filter
->fmt_in
.i_codec
= p_fmt_in
->i_chroma
;
327 p_image
->p_filter
->fmt_out
.video
= *p_fmt_in
;
328 p_image
->p_filter
->fmt_out
.i_codec
=p_image
->p_enc
->fmt_in
.i_codec
;
329 p_image
->p_filter
->fmt_out
.video
= p_image
->p_enc
->fmt_in
.video
;
332 picture_Hold( p_pic
);
335 p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
337 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
, p_tmp_pic
);
339 p_image
->p_filter
->pf_vout_buffer_del( p_image
->p_filter
, p_tmp_pic
);
343 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
, p_pic
);
348 msg_Dbg( p_image
->p_parent
, "no image encoded" );
355 static int ImageWriteUrl( image_handler_t
*p_image
, picture_t
*p_pic
,
356 video_format_t
*p_fmt_in
, video_format_t
*p_fmt_out
,
357 const char *psz_url
)
362 if( !p_fmt_out
->i_chroma
)
364 /* Try to guess format from file name */
365 p_fmt_out
->i_chroma
= image_Ext2Fourcc( psz_url
);
368 file
= utf8_fopen( psz_url
, "wb" );
371 msg_Err( p_image
->p_parent
, "%s: %m", psz_url
);
375 p_block
= ImageWrite( p_image
, p_pic
, p_fmt_in
, p_fmt_out
);
380 if( fwrite( p_block
->p_buffer
, p_block
->i_buffer
, 1, file
) != 1 )
382 block_Release( p_block
);
385 if( fclose( file
) && !err
)
391 msg_Err( p_image
->p_parent
, "%s: %m", psz_url
);
394 return err
? VLC_EGENERIC
: VLC_SUCCESS
;
398 * Convert an image to a different format
402 static picture_t
*ImageConvert( image_handler_t
*p_image
, picture_t
*p_pic
,
403 video_format_t
*p_fmt_in
,
404 video_format_t
*p_fmt_out
)
408 if( !p_fmt_out
->i_width
&& !p_fmt_out
->i_height
&&
409 p_fmt_out
->i_sar_num
&& p_fmt_out
->i_sar_den
&&
410 p_fmt_out
->i_sar_num
* p_fmt_in
->i_sar_den
!=
411 p_fmt_out
->i_sar_den
* p_fmt_in
->i_sar_num
)
414 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
415 p_fmt_in
->i_width
/ p_fmt_in
->i_sar_den
/ p_fmt_out
->i_sar_num
;
416 p_fmt_out
->i_visible_width
=
417 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
418 p_fmt_in
->i_visible_width
/ p_fmt_in
->i_sar_den
/
419 p_fmt_out
->i_sar_num
;
422 if( !p_fmt_out
->i_chroma
) p_fmt_out
->i_chroma
= p_fmt_in
->i_chroma
;
423 if( !p_fmt_out
->i_width
)
424 p_fmt_out
->i_width
= p_fmt_out
->i_visible_width
= p_fmt_in
->i_width
;
425 if( !p_fmt_out
->i_height
)
426 p_fmt_out
->i_height
= p_fmt_out
->i_visible_height
= p_fmt_in
->i_height
;
427 if( !p_fmt_out
->i_sar_num
) p_fmt_out
->i_sar_num
= p_fmt_in
->i_sar_num
;
428 if( !p_fmt_out
->i_sar_den
) p_fmt_out
->i_sar_den
= p_fmt_in
->i_sar_den
;
429 if( !p_fmt_out
->i_aspect
) p_fmt_out
->i_aspect
= p_fmt_in
->i_aspect
;
431 if( p_image
->p_filter
)
432 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
433 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
435 /* We need to restart a new filter */
436 DeleteFilter( p_image
->p_filter
);
437 p_image
->p_filter
= NULL
;
441 if( !p_image
->p_filter
)
444 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
445 fmt_in
.video
= *p_fmt_in
;
448 CreateFilter( p_image
->p_parent
, &fmt_in
, p_fmt_out
, NULL
);
450 if( !p_image
->p_filter
)
457 /* Filters should handle on-the-fly size changes */
458 p_image
->p_filter
->fmt_in
.video
= *p_fmt_in
;
459 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
462 picture_Hold( p_pic
);
464 p_pif
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
466 if( p_fmt_in
->i_chroma
== p_fmt_out
->i_chroma
&&
467 p_fmt_in
->i_width
== p_fmt_out
->i_width
&&
468 p_fmt_in
->i_height
== p_fmt_out
->i_height
)
470 /* Duplicate image */
471 picture_Release( p_pif
); /* XXX: Better fix must be possible */
472 p_pif
= p_image
->p_filter
->pf_vout_buffer_new( p_image
->p_filter
);
474 picture_Copy( p_pif
, p_pic
);
481 * Filter an image with a psz_module filter
485 static picture_t
*ImageFilter( image_handler_t
*p_image
, picture_t
*p_pic
,
486 video_format_t
*p_fmt
, const char *psz_module
)
489 if( !p_image
->p_filter
)
492 es_format_Init( &fmt
, VIDEO_ES
, p_fmt
->i_chroma
);
496 CreateFilter( p_image
->p_parent
, &fmt
, &fmt
.video
, psz_module
);
498 if( !p_image
->p_filter
)
505 /* Filters should handle on-the-fly size changes */
506 p_image
->p_filter
->fmt_in
.video
= *p_fmt
;
507 p_image
->p_filter
->fmt_out
.video
= *p_fmt
;
510 picture_Hold( p_pic
);
512 return p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
521 vlc_fourcc_t i_codec
;
526 { VLC_CODEC_JPEG
, "jpeg" },
527 { VLC_CODEC_JPEG
, "jpg" },
528 { VLC_CODEC_JPEGLS
, "ljpg" },
529 { VLC_CODEC_PNG
, "png" },
530 { VLC_CODEC_PGM
, "pgm" },
531 { VLC_CODEC_PGMYUV
, "pgmyuv" },
532 { VLC_FOURCC('p','b','m',' '), "pbm" },
533 { VLC_FOURCC('p','a','m',' '), "pam" },
534 { VLC_CODEC_TARGA
, "tga" },
535 { VLC_CODEC_BMP
, "bmp" },
536 { VLC_CODEC_PNM
, "pnm" },
537 { VLC_FOURCC('x','p','m',' '), "xpm" },
538 { VLC_FOURCC('x','c','f',' '), "xcf" },
539 { VLC_CODEC_PCX
, "pcx" },
540 { VLC_CODEC_GIF
, "gif" },
541 { VLC_CODEC_TIFF
, "tif" },
542 { VLC_CODEC_TIFF
, "tiff" },
543 { VLC_FOURCC('l','b','m',' '), "lbm" },
547 vlc_fourcc_t
image_Type2Fourcc( const char *psz_type
)
551 for( i
= 0; ext_table
[i
].i_codec
; i
++ )
552 if( !strcasecmp( ext_table
[i
].psz_ext
, psz_type
) )
553 return ext_table
[i
].i_codec
;
558 vlc_fourcc_t
image_Ext2Fourcc( const char *psz_name
)
560 psz_name
= strrchr( psz_name
, '.' );
561 if( !psz_name
) return 0;
564 return image_Type2Fourcc( psz_name
);
568 static const char *Fourcc2Ext( vlc_fourcc_t i_codec )
572 for( i = 0; ext_table[i].i_codec != 0; i++ )
574 if( ext_table[i].i_codec == i_codec ) return ext_table[i].psz_ext;
583 vlc_fourcc_t i_codec
;
584 const char *psz_mime
;
587 { VLC_CODEC_BMP
, "image/bmp" },
588 { VLC_CODEC_BMP
, "image/x-bmp" },
589 { VLC_CODEC_BMP
, "image/x-bitmap" },
590 { VLC_CODEC_BMP
, "image/x-ms-bmp" },
591 { VLC_CODEC_PNM
, "image/x-portable-anymap" },
592 { VLC_CODEC_PNM
, "image/x-portable-bitmap" },
593 { VLC_CODEC_PNM
, "image/x-portable-graymap" },
594 { VLC_CODEC_PNM
, "image/x-portable-pixmap" },
595 { VLC_CODEC_GIF
, "image/gif" },
596 { VLC_CODEC_JPEG
, "image/jpeg" },
597 { VLC_CODEC_PCX
, "image/pcx" },
598 { VLC_CODEC_PNG
, "image/png" },
599 { VLC_CODEC_TIFF
, "image/tiff" },
600 { VLC_CODEC_TARGA
, "iamge/x-tga" },
601 { VLC_FOURCC('x','p','m',' '), "image/x-xpixmap" },
605 vlc_fourcc_t
image_Mime2Fourcc( const char *psz_mime
)
608 for( i
= 0; mime_table
[i
].i_codec
; i
++ )
609 if( !strcmp( psz_mime
, mime_table
[i
].psz_mime
) )
610 return mime_table
[i
].i_codec
;
615 static picture_t
*video_new_buffer( decoder_t
*p_dec
)
617 p_dec
->fmt_out
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
618 return picture_New( p_dec
->fmt_out
.video
.i_chroma
,
619 p_dec
->fmt_out
.video
.i_width
,
620 p_dec
->fmt_out
.video
.i_height
,
621 p_dec
->fmt_out
.video
.i_aspect
);
624 static void video_del_buffer( decoder_t
*p_dec
, picture_t
*p_pic
)
626 if( p_pic
->i_refcount
!= 1 )
627 msg_Err( p_dec
, "invalid picture reference count" );
629 p_pic
->i_refcount
= 0;
630 picture_Delete( p_pic
);
633 static void video_link_picture( decoder_t
*p_dec
, picture_t
*p_pic
)
636 picture_Hold( p_pic
);
639 static void video_unlink_picture( decoder_t
*p_dec
, picture_t
*p_pic
)
642 picture_Release( p_pic
);
645 static decoder_t
*CreateDecoder( vlc_object_t
*p_this
, video_format_t
*fmt
)
649 p_dec
= vlc_object_create( p_this
, VLC_OBJECT_DECODER
);
653 p_dec
->p_module
= NULL
;
654 es_format_Init( &p_dec
->fmt_in
, VIDEO_ES
, fmt
->i_chroma
);
655 es_format_Init( &p_dec
->fmt_out
, VIDEO_ES
, 0 );
656 p_dec
->fmt_in
.video
= *fmt
;
657 p_dec
->b_pace_control
= true;
659 p_dec
->pf_vout_buffer_new
= video_new_buffer
;
660 p_dec
->pf_vout_buffer_del
= video_del_buffer
;
661 p_dec
->pf_picture_link
= video_link_picture
;
662 p_dec
->pf_picture_unlink
= video_unlink_picture
;
664 vlc_object_attach( p_dec
, p_this
);
666 /* Find a suitable decoder module */
667 p_dec
->p_module
= module_need( p_dec
, "decoder", "$codec", false );
668 if( !p_dec
->p_module
)
670 msg_Err( p_dec
, "no suitable decoder module for fourcc `%4.4s'. "
671 "VLC probably does not support this image format.",
672 (char*)&p_dec
->fmt_in
.i_codec
);
674 DeleteDecoder( p_dec
);
681 static void DeleteDecoder( decoder_t
* p_dec
)
683 vlc_object_detach( p_dec
);
685 if( p_dec
->p_module
) module_unneed( p_dec
, p_dec
->p_module
);
687 es_format_Clean( &p_dec
->fmt_in
);
688 es_format_Clean( &p_dec
->fmt_out
);
690 if( p_dec
->p_description
)
691 vlc_meta_Delete( p_dec
->p_description
);
693 vlc_object_release( p_dec
);
697 static encoder_t
*CreateEncoder( vlc_object_t
*p_this
, video_format_t
*fmt_in
,
698 video_format_t
*fmt_out
)
702 p_enc
= sout_EncoderCreate( p_this
);
706 p_enc
->p_module
= NULL
;
707 es_format_Init( &p_enc
->fmt_in
, VIDEO_ES
, fmt_in
->i_chroma
);
708 p_enc
->fmt_in
.video
= *fmt_in
;
709 if( fmt_out
->i_width
> 0 && fmt_out
->i_height
> 0 )
711 p_enc
->fmt_in
.video
.i_width
= fmt_out
->i_width
;
712 p_enc
->fmt_in
.video
.i_height
= fmt_out
->i_height
;
714 if( fmt_out
->i_visible_width
> 0 &&
715 fmt_out
->i_visible_height
> 0 )
717 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_visible_width
;
718 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_visible_height
;
722 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_width
;
723 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_height
;
726 else if( fmt_out
->i_sar_num
&& fmt_out
->i_sar_den
&&
727 fmt_out
->i_sar_num
* fmt_in
->i_sar_den
!=
728 fmt_out
->i_sar_den
* fmt_in
->i_sar_num
)
730 p_enc
->fmt_in
.video
.i_width
=
731 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
* fmt_in
->i_width
/
732 fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
733 p_enc
->fmt_in
.video
.i_visible_width
=
734 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
*
735 fmt_in
->i_visible_width
/ fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
738 p_enc
->fmt_in
.video
.i_frame_rate
= 25;
739 p_enc
->fmt_in
.video
.i_frame_rate_base
= 1;
741 es_format_Init( &p_enc
->fmt_out
, VIDEO_ES
, fmt_out
->i_chroma
);
742 p_enc
->fmt_out
.video
= *fmt_out
;
743 p_enc
->fmt_out
.video
.i_width
= p_enc
->fmt_in
.video
.i_width
;
744 p_enc
->fmt_out
.video
.i_height
= p_enc
->fmt_in
.video
.i_height
;
746 vlc_object_attach( p_enc
, p_this
);
748 /* Find a suitable decoder module */
749 p_enc
->p_module
= module_need( p_enc
, "encoder", NULL
, false );
750 if( !p_enc
->p_module
)
752 msg_Err( p_enc
, "no suitable encoder module for fourcc `%4.4s'.\n"
753 "VLC probably does not support this image format.",
754 (char*)&p_enc
->fmt_out
.i_codec
);
756 DeleteEncoder( p_enc
);
759 p_enc
->fmt_in
.video
.i_chroma
= p_enc
->fmt_in
.i_codec
;
764 static void DeleteEncoder( encoder_t
* p_enc
)
766 vlc_object_detach( p_enc
);
768 if( p_enc
->p_module
) module_unneed( p_enc
, p_enc
->p_module
);
770 es_format_Clean( &p_enc
->fmt_in
);
771 es_format_Clean( &p_enc
->fmt_out
);
773 vlc_object_release( p_enc
);
777 static filter_t
*CreateFilter( vlc_object_t
*p_this
, es_format_t
*p_fmt_in
,
778 video_format_t
*p_fmt_out
,
779 const char *psz_module
)
781 static const char typename
[] = "filter";
784 p_filter
= vlc_custom_create( p_this
, sizeof(filter_t
),
785 VLC_OBJECT_GENERIC
, typename
);
786 vlc_object_set_name( p_filter
, psz_module
);
787 vlc_object_attach( p_filter
, p_this
);
789 p_filter
->pf_vout_buffer_new
=
790 (picture_t
*(*)(filter_t
*))video_new_buffer
;
791 p_filter
->pf_vout_buffer_del
=
792 (void (*)(filter_t
*, picture_t
*))video_del_buffer
;
794 p_filter
->fmt_in
= *p_fmt_in
;
795 p_filter
->fmt_out
= *p_fmt_in
;
796 p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
797 p_filter
->fmt_out
.video
= *p_fmt_out
;
798 p_filter
->p_module
= module_need( p_filter
, "video filter2",
801 if( !p_filter
->p_module
)
803 msg_Dbg( p_filter
, "no video filter found" );
804 DeleteFilter( p_filter
);
811 static void DeleteFilter( filter_t
* p_filter
)
813 vlc_object_detach( p_filter
);
815 if( p_filter
->p_module
) module_unneed( p_filter
, p_filter
->p_module
);
817 es_format_Clean( &p_filter
->fmt_in
);
818 es_format_Clean( &p_filter
->fmt_out
);
820 vlc_object_release( p_filter
);