1 /*****************************************************************************
2 * image.c : wrapper for image reading/writing facilities
3 *****************************************************************************
4 * Copyright (C) 2004-2007 VLC authors and VideoLAN
7 * Author: Gildas Bazin <gbazin@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * 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 *****************************************************************************/
39 #include <vlc_common.h>
40 #include <vlc_codec.h>
42 #include <vlc_filter.h>
44 #include <vlc_image.h>
45 #include <vlc_stream.h>
49 #include <vlc_modules.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 );*/
78 #undef image_HandlerCreate
80 * Create an image_handler_t instance
83 image_handler_t
*image_HandlerCreate( vlc_object_t
*p_this
)
85 image_handler_t
*p_image
= calloc( 1, sizeof(image_handler_t
) );
89 p_image
->p_parent
= p_this
;
91 p_image
->pf_read
= ImageRead
;
92 p_image
->pf_read_url
= ImageReadUrl
;
93 p_image
->pf_write
= ImageWrite
;
94 p_image
->pf_write_url
= ImageWriteUrl
;
95 p_image
->pf_convert
= ImageConvert
;
96 p_image
->pf_filter
= ImageFilter
;
102 * Delete the image_handler_t instance
105 void image_HandlerDelete( image_handler_t
*p_image
)
107 if( !p_image
) return;
109 if( p_image
->p_dec
) DeleteDecoder( p_image
->p_dec
);
110 if( p_image
->p_enc
) DeleteEncoder( p_image
->p_enc
);
111 if( p_image
->p_filter
) DeleteFilter( p_image
->p_filter
);
122 static picture_t
*ImageRead( image_handler_t
*p_image
, block_t
*p_block
,
123 video_format_t
*p_fmt_in
,
124 video_format_t
*p_fmt_out
)
126 picture_t
*p_pic
= NULL
, *p_tmp
;
128 /* Check if we can reuse the current decoder */
129 if( p_image
->p_dec
&&
130 p_image
->p_dec
->fmt_in
.i_codec
!= p_fmt_in
->i_chroma
)
132 DeleteDecoder( p_image
->p_dec
);
136 /* Start a decoder */
137 if( !p_image
->p_dec
)
139 p_image
->p_dec
= CreateDecoder( p_image
->p_parent
, p_fmt_in
);
140 if( !p_image
->p_dec
) return NULL
;
143 p_block
->i_pts
= p_block
->i_dts
= mdate();
144 while( (p_tmp
= p_image
->p_dec
->pf_decode_video( p_image
->p_dec
, &p_block
))
148 picture_Release( p_pic
);
154 msg_Warn( p_image
->p_parent
, "no image decoded" );
158 if( !p_fmt_out
->i_chroma
)
159 p_fmt_out
->i_chroma
= p_image
->p_dec
->fmt_out
.video
.i_chroma
;
160 if( !p_fmt_out
->i_width
&& p_fmt_out
->i_height
)
161 p_fmt_out
->i_width
= (int64_t)p_image
->p_dec
->fmt_out
.video
.i_width
*
162 p_image
->p_dec
->fmt_out
.video
.i_sar_num
*
163 p_fmt_out
->i_height
/
164 p_image
->p_dec
->fmt_out
.video
.i_height
/
165 p_image
->p_dec
->fmt_out
.video
.i_sar_den
;
167 if( !p_fmt_out
->i_height
&& p_fmt_out
->i_width
)
168 p_fmt_out
->i_height
= (int64_t)p_image
->p_dec
->fmt_out
.video
.i_height
*
169 p_image
->p_dec
->fmt_out
.video
.i_sar_den
*
171 p_image
->p_dec
->fmt_out
.video
.i_width
/
172 p_image
->p_dec
->fmt_out
.video
.i_sar_num
;
173 if( !p_fmt_out
->i_width
)
174 p_fmt_out
->i_width
= p_image
->p_dec
->fmt_out
.video
.i_width
;
175 if( !p_fmt_out
->i_height
)
176 p_fmt_out
->i_height
= p_image
->p_dec
->fmt_out
.video
.i_height
;
177 if( !p_fmt_out
->i_visible_width
)
178 p_fmt_out
->i_visible_width
= p_fmt_out
->i_width
;
179 if( !p_fmt_out
->i_visible_height
)
180 p_fmt_out
->i_visible_height
= p_fmt_out
->i_height
;
182 /* Check if we need chroma conversion or resizing */
183 if( p_image
->p_dec
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
||
184 p_image
->p_dec
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
185 p_image
->p_dec
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
)
187 if( p_image
->p_filter
)
188 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!=
189 p_image
->p_dec
->fmt_out
.video
.i_chroma
||
190 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
192 /* We need to restart a new filter */
193 DeleteFilter( p_image
->p_filter
);
194 p_image
->p_filter
= 0;
198 if( !p_image
->p_filter
)
201 CreateFilter( p_image
->p_parent
, &p_image
->p_dec
->fmt_out
,
204 if( !p_image
->p_filter
)
206 picture_Release( p_pic
);
212 /* Filters should handle on-the-fly size changes */
213 p_image
->p_filter
->fmt_in
= p_image
->p_dec
->fmt_out
;
214 p_image
->p_filter
->fmt_out
= p_image
->p_dec
->fmt_out
;
215 p_image
->p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
216 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
219 p_pic
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
220 *p_fmt_out
= p_image
->p_filter
->fmt_out
.video
;
222 else *p_fmt_out
= p_image
->p_dec
->fmt_out
.video
;
227 static picture_t
*ImageReadUrl( image_handler_t
*p_image
, const char *psz_url
,
228 video_format_t
*p_fmt_in
,
229 video_format_t
*p_fmt_out
)
233 stream_t
*p_stream
= NULL
;
236 p_stream
= stream_UrlNew( p_image
->p_parent
, psz_url
);
240 msg_Dbg( p_image
->p_parent
, "could not open %s for reading",
245 i_size
= stream_Size( p_stream
);
247 p_block
= block_Alloc( i_size
);
249 stream_Read( p_stream
, p_block
->p_buffer
, i_size
);
251 if( !p_fmt_in
->i_chroma
)
253 char *psz_mime
= NULL
;
254 stream_Control( p_stream
, STREAM_GET_CONTENT_TYPE
, &psz_mime
);
256 p_fmt_in
->i_chroma
= image_Mime2Fourcc( psz_mime
);
259 stream_Delete( p_stream
);
261 if( !p_fmt_in
->i_chroma
)
263 /* Try to guess format from file name */
264 p_fmt_in
->i_chroma
= image_Ext2Fourcc( psz_url
);
267 p_pic
= ImageRead( p_image
, p_block
, p_fmt_in
, p_fmt_out
);
277 static block_t
*ImageWrite( image_handler_t
*p_image
, picture_t
*p_pic
,
278 video_format_t
*p_fmt_in
,
279 video_format_t
*p_fmt_out
)
283 /* Check if we can reuse the current encoder */
284 if( p_image
->p_enc
&&
285 ( p_image
->p_enc
->fmt_out
.i_codec
!= p_fmt_out
->i_chroma
||
286 p_image
->p_enc
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
287 p_image
->p_enc
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
) )
289 DeleteEncoder( p_image
->p_enc
);
293 /* Start an encoder */
294 if( !p_image
->p_enc
)
296 p_image
->p_enc
= CreateEncoder( p_image
->p_parent
,
297 p_fmt_in
, p_fmt_out
);
298 if( !p_image
->p_enc
) return NULL
;
301 /* Check if we need chroma conversion or resizing */
302 if( p_image
->p_enc
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
303 p_image
->p_enc
->fmt_in
.video
.i_width
!= p_fmt_in
->i_width
||
304 p_image
->p_enc
->fmt_in
.video
.i_height
!= p_fmt_in
->i_height
)
306 picture_t
*p_tmp_pic
;
308 if( p_image
->p_filter
)
309 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
310 p_image
->p_filter
->fmt_out
.video
.i_chroma
!=
311 p_image
->p_enc
->fmt_in
.video
.i_chroma
)
313 /* We need to restart a new filter */
314 DeleteFilter( p_image
->p_filter
);
315 p_image
->p_filter
= 0;
319 if( !p_image
->p_filter
)
322 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
323 fmt_in
.video
= *p_fmt_in
;
326 CreateFilter( p_image
->p_parent
, &fmt_in
,
327 &p_image
->p_enc
->fmt_in
.video
, NULL
);
329 if( !p_image
->p_filter
)
336 /* Filters should handle on-the-fly size changes */
337 p_image
->p_filter
->fmt_in
.i_codec
= p_fmt_in
->i_chroma
;
338 p_image
->p_filter
->fmt_out
.video
= *p_fmt_in
;
339 p_image
->p_filter
->fmt_out
.i_codec
=p_image
->p_enc
->fmt_in
.i_codec
;
340 p_image
->p_filter
->fmt_out
.video
= p_image
->p_enc
->fmt_in
.video
;
343 picture_Hold( p_pic
);
346 p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
348 if( likely(p_tmp_pic
!= NULL
) )
350 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
,
352 p_image
->p_filter
->pf_video_buffer_del( p_image
->p_filter
,
360 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
, p_pic
);
365 msg_Dbg( p_image
->p_parent
, "no image encoded" );
372 static int ImageWriteUrl( image_handler_t
*p_image
, picture_t
*p_pic
,
373 video_format_t
*p_fmt_in
, video_format_t
*p_fmt_out
,
374 const char *psz_url
)
379 if( !p_fmt_out
->i_chroma
)
381 /* Try to guess format from file name */
382 p_fmt_out
->i_chroma
= image_Ext2Fourcc( psz_url
);
385 file
= vlc_fopen( psz_url
, "wb" );
388 msg_Err( p_image
->p_parent
, "%s: %m", psz_url
);
392 p_block
= ImageWrite( p_image
, p_pic
, p_fmt_in
, p_fmt_out
);
397 if( fwrite( p_block
->p_buffer
, p_block
->i_buffer
, 1, file
) != 1 )
399 block_Release( p_block
);
402 if( fclose( file
) && !err
)
408 msg_Err( p_image
->p_parent
, "%s: %m", psz_url
);
411 return err
? VLC_EGENERIC
: VLC_SUCCESS
;
415 * Convert an image to a different format
419 static picture_t
*ImageConvert( image_handler_t
*p_image
, picture_t
*p_pic
,
420 video_format_t
*p_fmt_in
,
421 video_format_t
*p_fmt_out
)
425 if( !p_fmt_out
->i_width
&& !p_fmt_out
->i_height
&&
426 p_fmt_out
->i_sar_num
&& p_fmt_out
->i_sar_den
&&
427 p_fmt_out
->i_sar_num
* p_fmt_in
->i_sar_den
!=
428 p_fmt_out
->i_sar_den
* p_fmt_in
->i_sar_num
)
431 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
432 p_fmt_in
->i_width
/ p_fmt_in
->i_sar_den
/ p_fmt_out
->i_sar_num
;
433 p_fmt_out
->i_visible_width
=
434 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
435 p_fmt_in
->i_visible_width
/ p_fmt_in
->i_sar_den
/
436 p_fmt_out
->i_sar_num
;
439 if( !p_fmt_out
->i_chroma
) p_fmt_out
->i_chroma
= p_fmt_in
->i_chroma
;
440 if( !p_fmt_out
->i_width
)
441 p_fmt_out
->i_width
= p_fmt_out
->i_visible_width
= p_fmt_in
->i_width
;
442 if( !p_fmt_out
->i_height
)
443 p_fmt_out
->i_height
= p_fmt_out
->i_visible_height
= p_fmt_in
->i_height
;
444 if( !p_fmt_out
->i_sar_num
) p_fmt_out
->i_sar_num
= p_fmt_in
->i_sar_num
;
445 if( !p_fmt_out
->i_sar_den
) p_fmt_out
->i_sar_den
= p_fmt_in
->i_sar_den
;
447 if( p_image
->p_filter
)
448 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
449 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
451 /* We need to restart a new filter */
452 DeleteFilter( p_image
->p_filter
);
453 p_image
->p_filter
= NULL
;
457 if( !p_image
->p_filter
)
460 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
461 fmt_in
.video
= *p_fmt_in
;
464 CreateFilter( p_image
->p_parent
, &fmt_in
, p_fmt_out
, NULL
);
466 if( !p_image
->p_filter
)
473 /* Filters should handle on-the-fly size changes */
474 p_image
->p_filter
->fmt_in
.video
= *p_fmt_in
;
475 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
478 picture_Hold( p_pic
);
480 p_pif
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
482 if( p_fmt_in
->i_chroma
== p_fmt_out
->i_chroma
&&
483 p_fmt_in
->i_width
== p_fmt_out
->i_width
&&
484 p_fmt_in
->i_height
== p_fmt_out
->i_height
)
486 /* Duplicate image */
487 picture_Release( p_pif
); /* XXX: Better fix must be possible */
488 p_pif
= p_image
->p_filter
->pf_video_buffer_new( p_image
->p_filter
);
490 picture_Copy( p_pif
, p_pic
);
497 * Filter an image with a psz_module filter
501 static picture_t
*ImageFilter( image_handler_t
*p_image
, picture_t
*p_pic
,
502 video_format_t
*p_fmt
, const char *psz_module
)
505 if( !p_image
->p_filter
)
508 es_format_Init( &fmt
, VIDEO_ES
, p_fmt
->i_chroma
);
512 CreateFilter( p_image
->p_parent
, &fmt
, &fmt
.video
, psz_module
);
514 if( !p_image
->p_filter
)
521 /* Filters should handle on-the-fly size changes */
522 p_image
->p_filter
->fmt_in
.video
= *p_fmt
;
523 p_image
->p_filter
->fmt_out
.video
= *p_fmt
;
526 picture_Hold( p_pic
);
528 return p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
537 vlc_fourcc_t i_codec
;
538 const char psz_ext
[7];
542 { VLC_CODEC_JPEG
, "jpeg" },
543 { VLC_CODEC_JPEG
, "jpg" },
544 { VLC_CODEC_JPEGLS
, "ljpg" },
545 { VLC_CODEC_PNG
, "png" },
546 { VLC_CODEC_PGM
, "pgm" },
547 { VLC_CODEC_PGMYUV
, "pgmyuv" },
548 { VLC_FOURCC('p','b','m',' '), "pbm" },
549 { VLC_FOURCC('p','a','m',' '), "pam" },
550 { VLC_CODEC_TARGA
, "tga" },
551 { VLC_CODEC_BMP
, "bmp" },
552 { VLC_CODEC_PNM
, "pnm" },
553 { VLC_FOURCC('x','p','m',' '), "xpm" },
554 { VLC_FOURCC('x','c','f',' '), "xcf" },
555 { VLC_CODEC_PCX
, "pcx" },
556 { VLC_CODEC_GIF
, "gif" },
557 { VLC_CODEC_TIFF
, "tif" },
558 { VLC_CODEC_TIFF
, "tiff" },
559 { VLC_FOURCC('l','b','m',' '), "lbm" },
560 { VLC_CODEC_PPM
, "ppm" },
563 vlc_fourcc_t
image_Type2Fourcc( const char *psz_type
)
565 for( unsigned i
= 0; i
< ARRAY_SIZE(ext_table
); i
++ )
566 if( !strcasecmp( ext_table
[i
].psz_ext
, psz_type
) )
567 return ext_table
[i
].i_codec
;
572 vlc_fourcc_t
image_Ext2Fourcc( const char *psz_name
)
574 psz_name
= strrchr( psz_name
, '.' );
575 if( !psz_name
) return 0;
578 return image_Type2Fourcc( psz_name
);
582 static const char *Fourcc2Ext( vlc_fourcc_t i_codec )
584 for( unsigned i = 0; i < ARRAY_SIZE(ext_table); i++ )
585 if( ext_table[i].i_codec == i_codec )
586 return ext_table[i].psz_ext;
594 vlc_fourcc_t i_codec
;
595 const char *psz_mime
;
598 { VLC_CODEC_BMP
, "image/bmp" },
599 { VLC_CODEC_BMP
, "image/x-bmp" },
600 { VLC_CODEC_BMP
, "image/x-bitmap" },
601 { VLC_CODEC_BMP
, "image/x-ms-bmp" },
602 { VLC_CODEC_PNM
, "image/x-portable-anymap" },
603 { VLC_CODEC_PNM
, "image/x-portable-bitmap" },
604 { VLC_CODEC_PNM
, "image/x-portable-graymap" },
605 { VLC_CODEC_PNM
, "image/x-portable-pixmap" },
606 { VLC_CODEC_GIF
, "image/gif" },
607 { VLC_CODEC_JPEG
, "image/jpeg" },
608 { VLC_CODEC_PCX
, "image/pcx" },
609 { VLC_CODEC_PNG
, "image/png" },
610 { VLC_CODEC_TIFF
, "image/tiff" },
611 { VLC_CODEC_TARGA
, "image/x-tga" },
612 { VLC_FOURCC('x','p','m',' '), "image/x-xpixmap" },
616 vlc_fourcc_t
image_Mime2Fourcc( const char *psz_mime
)
619 for( i
= 0; mime_table
[i
].i_codec
; i
++ )
620 if( !strcmp( psz_mime
, mime_table
[i
].psz_mime
) )
621 return mime_table
[i
].i_codec
;
626 static picture_t
*video_new_buffer( decoder_t
*p_dec
)
628 p_dec
->fmt_out
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
629 return picture_NewFromFormat( &p_dec
->fmt_out
.video
);
632 static void video_del_buffer( decoder_t
*p_dec
, picture_t
*p_pic
)
635 picture_Release( p_pic
);
638 static void video_link_picture( decoder_t
*p_dec
, picture_t
*p_pic
)
641 picture_Hold( p_pic
);
644 static void video_unlink_picture( decoder_t
*p_dec
, picture_t
*p_pic
)
647 picture_Release( p_pic
);
650 static decoder_t
*CreateDecoder( vlc_object_t
*p_this
, video_format_t
*fmt
)
654 p_dec
= vlc_custom_create( p_this
, sizeof( *p_dec
), "image decoder" );
658 p_dec
->p_module
= NULL
;
659 es_format_Init( &p_dec
->fmt_in
, VIDEO_ES
, fmt
->i_chroma
);
660 es_format_Init( &p_dec
->fmt_out
, VIDEO_ES
, 0 );
661 p_dec
->fmt_in
.video
= *fmt
;
662 p_dec
->b_pace_control
= true;
664 p_dec
->pf_vout_buffer_new
= video_new_buffer
;
665 p_dec
->pf_vout_buffer_del
= video_del_buffer
;
666 p_dec
->pf_picture_link
= video_link_picture
;
667 p_dec
->pf_picture_unlink
= video_unlink_picture
;
669 /* Find a suitable decoder module */
670 p_dec
->p_module
= module_need( p_dec
, "decoder", "$codec", false );
671 if( !p_dec
->p_module
)
673 msg_Err( p_dec
, "no suitable decoder module for fourcc `%4.4s'. "
674 "VLC probably does not support this image format.",
675 (char*)&p_dec
->fmt_in
.i_codec
);
677 DeleteDecoder( p_dec
);
684 static void DeleteDecoder( decoder_t
* p_dec
)
686 if( p_dec
->p_module
) module_unneed( p_dec
, p_dec
->p_module
);
688 es_format_Clean( &p_dec
->fmt_in
);
689 es_format_Clean( &p_dec
->fmt_out
);
691 if( p_dec
->p_description
)
692 vlc_meta_Delete( p_dec
->p_description
);
694 vlc_object_release( p_dec
);
698 static encoder_t
*CreateEncoder( vlc_object_t
*p_this
, video_format_t
*fmt_in
,
699 video_format_t
*fmt_out
)
703 p_enc
= sout_EncoderCreate( p_this
);
707 p_enc
->p_module
= NULL
;
708 es_format_Init( &p_enc
->fmt_in
, VIDEO_ES
, fmt_in
->i_chroma
);
709 p_enc
->fmt_in
.video
= *fmt_in
;
710 if( fmt_out
->i_width
> 0 && fmt_out
->i_height
> 0 )
712 p_enc
->fmt_in
.video
.i_width
= fmt_out
->i_width
;
713 p_enc
->fmt_in
.video
.i_height
= fmt_out
->i_height
;
715 if( fmt_out
->i_visible_width
> 0 &&
716 fmt_out
->i_visible_height
> 0 )
718 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_visible_width
;
719 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_visible_height
;
723 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_width
;
724 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_height
;
727 else if( fmt_out
->i_sar_num
&& fmt_out
->i_sar_den
&&
728 fmt_out
->i_sar_num
* fmt_in
->i_sar_den
!=
729 fmt_out
->i_sar_den
* fmt_in
->i_sar_num
)
731 p_enc
->fmt_in
.video
.i_width
=
732 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
* fmt_in
->i_width
/
733 fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
734 p_enc
->fmt_in
.video
.i_visible_width
=
735 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
*
736 fmt_in
->i_visible_width
/ fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
739 p_enc
->fmt_in
.video
.i_frame_rate
= 25;
740 p_enc
->fmt_in
.video
.i_frame_rate_base
= 1;
742 es_format_Init( &p_enc
->fmt_out
, VIDEO_ES
, fmt_out
->i_chroma
);
743 p_enc
->fmt_out
.video
= *fmt_out
;
744 p_enc
->fmt_out
.video
.i_width
= p_enc
->fmt_in
.video
.i_width
;
745 p_enc
->fmt_out
.video
.i_height
= p_enc
->fmt_in
.video
.i_height
;
747 /* Find a suitable decoder module */
748 p_enc
->p_module
= module_need( p_enc
, "encoder", NULL
, false );
749 if( !p_enc
->p_module
)
751 msg_Err( p_enc
, "no suitable encoder module for fourcc `%4.4s'.\n"
752 "VLC probably does not support this image format.",
753 (char*)&p_enc
->fmt_out
.i_codec
);
755 DeleteEncoder( p_enc
);
758 p_enc
->fmt_in
.video
.i_chroma
= p_enc
->fmt_in
.i_codec
;
763 static void DeleteEncoder( encoder_t
* p_enc
)
765 if( p_enc
->p_module
) module_unneed( p_enc
, p_enc
->p_module
);
767 es_format_Clean( &p_enc
->fmt_in
);
768 es_format_Clean( &p_enc
->fmt_out
);
770 vlc_object_release( p_enc
);
774 static filter_t
*CreateFilter( vlc_object_t
*p_this
, es_format_t
*p_fmt_in
,
775 video_format_t
*p_fmt_out
,
776 const char *psz_module
)
780 p_filter
= vlc_custom_create( p_this
, sizeof(filter_t
), "filter" );
781 p_filter
->pf_video_buffer_new
=
782 (picture_t
*(*)(filter_t
*))video_new_buffer
;
783 p_filter
->pf_video_buffer_del
=
784 (void (*)(filter_t
*, picture_t
*))video_del_buffer
;
786 p_filter
->fmt_in
= *p_fmt_in
;
787 p_filter
->fmt_out
= *p_fmt_in
;
788 p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
789 p_filter
->fmt_out
.video
= *p_fmt_out
;
790 p_filter
->p_module
= module_need( p_filter
, "video filter2",
793 if( !p_filter
->p_module
)
795 msg_Dbg( p_filter
, "no video filter found" );
796 DeleteFilter( p_filter
);
803 static void DeleteFilter( filter_t
* p_filter
)
805 if( p_filter
->p_module
) module_unneed( p_filter
, p_filter
->p_module
);
807 es_format_Clean( &p_filter
->fmt_in
);
808 es_format_Clean( &p_filter
->fmt_out
);
810 vlc_object_release( p_filter
);