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 *****************************************************************************/
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>
50 #include <vlc_modules.h>
52 static picture_t
*ImageRead( image_handler_t
*, block_t
*,
53 video_format_t
*, video_format_t
* );
54 static picture_t
*ImageReadUrl( image_handler_t
*, const char *,
55 video_format_t
*, video_format_t
* );
56 static block_t
*ImageWrite( image_handler_t
*, picture_t
*,
57 video_format_t
*, video_format_t
* );
58 static int ImageWriteUrl( image_handler_t
*, picture_t
*,
59 video_format_t
*, video_format_t
*, const char * );
61 static picture_t
*ImageConvert( image_handler_t
*, picture_t
*,
62 video_format_t
*, video_format_t
* );
64 static decoder_t
*CreateDecoder( vlc_object_t
*, video_format_t
* );
65 static void DeleteDecoder( decoder_t
* );
66 static encoder_t
*CreateEncoder( vlc_object_t
*, video_format_t
*,
68 static void DeleteEncoder( encoder_t
* );
69 static filter_t
*CreateFilter( vlc_object_t
*, es_format_t
*,
71 static void DeleteFilter( filter_t
* );
73 vlc_fourcc_t
image_Type2Fourcc( const char * );
74 vlc_fourcc_t
image_Ext2Fourcc( const char * );
75 /*static const char *Fourcc2Ext( vlc_fourcc_t );*/
77 #undef image_HandlerCreate
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
;
96 p_image
->outfifo
= picture_fifo_New();
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
);
113 picture_fifo_Delete( p_image
->outfifo
);
124 static int ImageQueueVideo( decoder_t
*p_dec
, picture_t
*p_pic
)
126 image_handler_t
*p_image
= p_dec
->p_queue_ctx
;
127 picture_fifo_Push( p_image
->outfifo
, p_pic
);
131 static picture_t
*ImageRead( image_handler_t
*p_image
, block_t
*p_block
,
132 video_format_t
*p_fmt_in
,
133 video_format_t
*p_fmt_out
)
135 picture_t
*p_pic
= NULL
;
137 /* Check if we can reuse the current decoder */
138 if( p_image
->p_dec
&&
139 p_image
->p_dec
->fmt_in
.i_codec
!= p_fmt_in
->i_chroma
)
141 DeleteDecoder( p_image
->p_dec
);
145 /* Start a decoder */
146 if( !p_image
->p_dec
)
148 p_image
->p_dec
= CreateDecoder( p_image
->p_parent
, p_fmt_in
);
149 if( !p_image
->p_dec
)
151 block_Release(p_block
);
154 if( p_image
->p_dec
->fmt_out
.i_cat
!= VIDEO_ES
)
156 DeleteDecoder( p_image
->p_dec
);
157 p_image
->p_dec
= NULL
;
158 block_Release(p_block
);
161 p_image
->p_dec
->pf_queue_video
= ImageQueueVideo
;
162 p_image
->p_dec
->p_queue_ctx
= p_image
;
165 p_block
->i_pts
= p_block
->i_dts
= mdate();
166 int ret
= p_image
->p_dec
->pf_decode( p_image
->p_dec
, p_block
);
167 if( ret
== VLCDEC_SUCCESS
)
170 p_image
->p_dec
->pf_decode( p_image
->p_dec
, NULL
);
172 p_pic
= picture_fifo_Pop( p_image
->outfifo
);
174 unsigned lostcount
= 0;
176 while( ( lostpic
= picture_fifo_Pop( p_image
->outfifo
) ) != NULL
)
178 picture_Release( lostpic
);
182 msg_Warn( p_image
->p_parent
, "Image decoder output more than one "
183 "picture (%d)", lostcount
);
188 msg_Warn( p_image
->p_parent
, "no image decoded" );
192 if( !p_fmt_out
->i_chroma
)
193 p_fmt_out
->i_chroma
= p_image
->p_dec
->fmt_out
.video
.i_chroma
;
194 if( !p_fmt_out
->i_width
&& p_fmt_out
->i_height
)
195 p_fmt_out
->i_width
= (int64_t)p_image
->p_dec
->fmt_out
.video
.i_width
*
196 p_image
->p_dec
->fmt_out
.video
.i_sar_num
*
197 p_fmt_out
->i_height
/
198 p_image
->p_dec
->fmt_out
.video
.i_height
/
199 p_image
->p_dec
->fmt_out
.video
.i_sar_den
;
201 if( !p_fmt_out
->i_height
&& p_fmt_out
->i_width
)
202 p_fmt_out
->i_height
= (int64_t)p_image
->p_dec
->fmt_out
.video
.i_height
*
203 p_image
->p_dec
->fmt_out
.video
.i_sar_den
*
205 p_image
->p_dec
->fmt_out
.video
.i_width
/
206 p_image
->p_dec
->fmt_out
.video
.i_sar_num
;
207 if( !p_fmt_out
->i_width
)
208 p_fmt_out
->i_width
= p_image
->p_dec
->fmt_out
.video
.i_width
;
209 if( !p_fmt_out
->i_height
)
210 p_fmt_out
->i_height
= p_image
->p_dec
->fmt_out
.video
.i_height
;
211 if( !p_fmt_out
->i_visible_width
)
212 p_fmt_out
->i_visible_width
= p_fmt_out
->i_width
;
213 if( !p_fmt_out
->i_visible_height
)
214 p_fmt_out
->i_visible_height
= p_fmt_out
->i_height
;
216 /* Check if we need chroma conversion or resizing */
217 if( p_image
->p_dec
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
||
218 p_image
->p_dec
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
219 p_image
->p_dec
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
)
221 if( p_image
->p_filter
)
222 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!=
223 p_image
->p_dec
->fmt_out
.video
.i_chroma
||
224 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
226 /* We need to restart a new filter */
227 DeleteFilter( p_image
->p_filter
);
228 p_image
->p_filter
= 0;
232 if( !p_image
->p_filter
)
235 CreateFilter( p_image
->p_parent
, &p_image
->p_dec
->fmt_out
,
238 if( !p_image
->p_filter
)
240 picture_Release( p_pic
);
246 /* Filters should handle on-the-fly size changes */
247 p_image
->p_filter
->fmt_in
= p_image
->p_dec
->fmt_out
;
248 p_image
->p_filter
->fmt_out
= p_image
->p_dec
->fmt_out
;
249 p_image
->p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
250 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
253 p_pic
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
255 video_format_Clean( p_fmt_out
);
256 video_format_Copy( p_fmt_out
, &p_image
->p_filter
->fmt_out
.video
);
260 video_format_Clean( p_fmt_out
);
261 video_format_Copy( p_fmt_out
, &p_image
->p_dec
->fmt_out
.video
);
267 static picture_t
*ImageReadUrl( image_handler_t
*p_image
, const char *psz_url
,
268 video_format_t
*p_fmt_in
,
269 video_format_t
*p_fmt_out
)
273 stream_t
*p_stream
= NULL
;
276 p_stream
= vlc_stream_NewURL( p_image
->p_parent
, psz_url
);
280 msg_Dbg( p_image
->p_parent
, "could not open %s for reading",
285 if( vlc_stream_GetSize( p_stream
, &i_size
) || i_size
> SSIZE_MAX
)
287 msg_Dbg( p_image
->p_parent
, "could not read %s", psz_url
);
291 p_block
= vlc_stream_Block( p_stream
, i_size
);
292 if( p_block
== NULL
)
295 if( !p_fmt_in
->i_chroma
)
297 char *psz_mime
= stream_MimeType( p_stream
);
298 if( psz_mime
!= NULL
)
300 p_fmt_in
->i_chroma
= image_Mime2Fourcc( psz_mime
);
304 vlc_stream_Delete( p_stream
);
306 if( !p_fmt_in
->i_chroma
)
308 /* Try to guess format from file name */
309 p_fmt_in
->i_chroma
= image_Ext2Fourcc( psz_url
);
312 p_pic
= ImageRead( p_image
, p_block
, p_fmt_in
, p_fmt_out
);
316 vlc_stream_Delete( p_stream
);
325 static block_t
*ImageWrite( image_handler_t
*p_image
, picture_t
*p_pic
,
326 video_format_t
*p_fmt_in
,
327 video_format_t
*p_fmt_out
)
331 /* Check if we can reuse the current encoder */
332 if( p_image
->p_enc
&&
333 ( p_image
->p_enc
->fmt_out
.i_codec
!= p_fmt_out
->i_chroma
||
334 p_image
->p_enc
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
335 p_image
->p_enc
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
) )
337 DeleteEncoder( p_image
->p_enc
);
341 /* Start an encoder */
342 if( !p_image
->p_enc
)
344 p_image
->p_enc
= CreateEncoder( p_image
->p_parent
,
345 p_fmt_in
, p_fmt_out
);
346 if( !p_image
->p_enc
) return NULL
;
349 /* Check if we need chroma conversion or resizing */
350 if( p_image
->p_enc
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
351 p_image
->p_enc
->fmt_in
.video
.i_width
!= p_fmt_in
->i_width
||
352 p_image
->p_enc
->fmt_in
.video
.i_height
!= p_fmt_in
->i_height
)
354 picture_t
*p_tmp_pic
;
356 if( p_image
->p_filter
)
357 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
358 p_image
->p_filter
->fmt_out
.video
.i_chroma
!=
359 p_image
->p_enc
->fmt_in
.video
.i_chroma
)
361 /* We need to restart a new filter */
362 DeleteFilter( p_image
->p_filter
);
363 p_image
->p_filter
= 0;
367 if( !p_image
->p_filter
)
370 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
371 fmt_in
.video
= *p_fmt_in
;
374 CreateFilter( p_image
->p_parent
, &fmt_in
,
375 &p_image
->p_enc
->fmt_in
.video
);
377 if( !p_image
->p_filter
)
384 /* Filters should handle on-the-fly size changes */
385 p_image
->p_filter
->fmt_in
.i_codec
= p_fmt_in
->i_chroma
;
386 p_image
->p_filter
->fmt_out
.video
= *p_fmt_in
;
387 p_image
->p_filter
->fmt_out
.i_codec
=p_image
->p_enc
->fmt_in
.i_codec
;
388 p_image
->p_filter
->fmt_out
.video
= p_image
->p_enc
->fmt_in
.video
;
391 picture_Hold( p_pic
);
394 p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
396 if( likely(p_tmp_pic
!= NULL
) )
398 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
,
400 picture_Release( p_tmp_pic
);
407 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
, p_pic
);
412 msg_Dbg( p_image
->p_parent
, "no image encoded" );
419 static int ImageWriteUrl( image_handler_t
*p_image
, picture_t
*p_pic
,
420 video_format_t
*p_fmt_in
, video_format_t
*p_fmt_out
,
421 const char *psz_url
)
426 if( !p_fmt_out
->i_chroma
)
428 /* Try to guess format from file name */
429 p_fmt_out
->i_chroma
= image_Ext2Fourcc( psz_url
);
432 file
= vlc_fopen( psz_url
, "wb" );
435 msg_Err( p_image
->p_parent
, "%s: %s", psz_url
, vlc_strerror_c(errno
) );
439 p_block
= ImageWrite( p_image
, p_pic
, p_fmt_in
, p_fmt_out
);
444 if( fwrite( p_block
->p_buffer
, p_block
->i_buffer
, 1, file
) != 1 )
446 block_Release( p_block
);
449 if( fclose( file
) && !err
)
455 msg_Err( p_image
->p_parent
, "%s: %s", psz_url
, vlc_strerror_c(errno
) );
458 return err
? VLC_EGENERIC
: VLC_SUCCESS
;
462 * Convert an image to a different format
466 static picture_t
*ImageConvert( image_handler_t
*p_image
, picture_t
*p_pic
,
467 video_format_t
*p_fmt_in
,
468 video_format_t
*p_fmt_out
)
472 if( !p_fmt_out
->i_width
&& !p_fmt_out
->i_height
&&
473 p_fmt_out
->i_sar_num
&& p_fmt_out
->i_sar_den
&&
474 p_fmt_out
->i_sar_num
* p_fmt_in
->i_sar_den
!=
475 p_fmt_out
->i_sar_den
* p_fmt_in
->i_sar_num
)
478 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
479 p_fmt_in
->i_width
/ p_fmt_in
->i_sar_den
/ p_fmt_out
->i_sar_num
;
480 p_fmt_out
->i_visible_width
=
481 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
482 p_fmt_in
->i_visible_width
/ p_fmt_in
->i_sar_den
/
483 p_fmt_out
->i_sar_num
;
486 if( !p_fmt_out
->i_chroma
) p_fmt_out
->i_chroma
= p_fmt_in
->i_chroma
;
487 if( !p_fmt_out
->i_width
)
488 p_fmt_out
->i_width
= p_fmt_out
->i_visible_width
= p_fmt_in
->i_width
;
489 if( !p_fmt_out
->i_height
)
490 p_fmt_out
->i_height
= p_fmt_out
->i_visible_height
= p_fmt_in
->i_height
;
491 if( !p_fmt_out
->i_sar_num
) p_fmt_out
->i_sar_num
= p_fmt_in
->i_sar_num
;
492 if( !p_fmt_out
->i_sar_den
) p_fmt_out
->i_sar_den
= p_fmt_in
->i_sar_den
;
494 if( p_image
->p_filter
)
495 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
496 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
498 /* We need to restart a new filter */
499 DeleteFilter( p_image
->p_filter
);
500 p_image
->p_filter
= NULL
;
504 if( !p_image
->p_filter
)
507 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
508 fmt_in
.video
= *p_fmt_in
;
511 CreateFilter( p_image
->p_parent
, &fmt_in
, p_fmt_out
);
513 if( !p_image
->p_filter
)
520 /* Filters should handle on-the-fly size changes */
521 p_image
->p_filter
->fmt_in
.video
= *p_fmt_in
;
522 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
525 picture_Hold( p_pic
);
527 p_pif
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
529 if( p_fmt_in
->i_chroma
== p_fmt_out
->i_chroma
&&
530 p_fmt_in
->i_width
== p_fmt_out
->i_width
&&
531 p_fmt_in
->i_height
== p_fmt_out
->i_height
)
533 /* Duplicate image */
534 picture_Release( p_pif
); /* XXX: Better fix must be possible */
535 p_pif
= filter_NewPicture( p_image
->p_filter
);
537 picture_Copy( p_pif
, p_pic
);
549 vlc_fourcc_t i_codec
;
550 const char psz_ext
[7];
554 { VLC_CODEC_JPEG
, "jpeg" },
555 { VLC_CODEC_JPEG
, "jpg" },
556 { VLC_CODEC_JPEGLS
, "ljpg" },
557 { VLC_CODEC_BPG
, "bpg" },
558 { VLC_CODEC_PNG
, "png" },
559 { VLC_CODEC_PGM
, "pgm" },
560 { VLC_CODEC_PGMYUV
, "pgmyuv" },
561 { VLC_FOURCC('p','b','m',' '), "pbm" },
562 { VLC_FOURCC('p','a','m',' '), "pam" },
563 { VLC_CODEC_TARGA
, "tga" },
564 { VLC_CODEC_BMP
, "bmp" },
565 { VLC_CODEC_PNM
, "pnm" },
566 { VLC_FOURCC('x','p','m',' '), "xpm" },
567 { VLC_FOURCC('x','c','f',' '), "xcf" },
568 { VLC_CODEC_PCX
, "pcx" },
569 { VLC_CODEC_GIF
, "gif" },
570 { VLC_CODEC_SVG
, "svg" },
571 { VLC_CODEC_TIFF
, "tif" },
572 { VLC_CODEC_TIFF
, "tiff" },
573 { VLC_FOURCC('l','b','m',' '), "lbm" },
574 { VLC_CODEC_PPM
, "ppm" },
577 vlc_fourcc_t
image_Type2Fourcc( const char *psz_type
)
579 for( unsigned i
= 0; i
< ARRAY_SIZE(ext_table
); i
++ )
580 if( !strcasecmp( ext_table
[i
].psz_ext
, psz_type
) )
581 return ext_table
[i
].i_codec
;
586 vlc_fourcc_t
image_Ext2Fourcc( const char *psz_name
)
588 psz_name
= strrchr( psz_name
, '.' );
589 if( !psz_name
) return 0;
592 return image_Type2Fourcc( psz_name
);
597 vlc_fourcc_t i_codec
;
598 const char *psz_mime
;
601 { VLC_CODEC_BMP
, "image/bmp" },
602 { VLC_CODEC_BMP
, "image/x-bmp" },
603 { VLC_CODEC_BMP
, "image/x-bitmap" },
604 { VLC_CODEC_BMP
, "image/x-ms-bmp" },
605 { VLC_CODEC_PNM
, "image/x-portable-anymap" },
606 { VLC_CODEC_PNM
, "image/x-portable-bitmap" },
607 { VLC_CODEC_PNM
, "image/x-portable-graymap" },
608 { VLC_CODEC_PNM
, "image/x-portable-pixmap" },
609 { VLC_CODEC_GIF
, "image/gif" },
610 { VLC_CODEC_JPEG
, "image/jpeg" },
611 { VLC_CODEC_BPG
, "image/bpg" },
612 { VLC_CODEC_PCX
, "image/pcx" },
613 { VLC_CODEC_PNG
, "image/png" },
614 { VLC_CODEC_SVG
, "image/svg+xml" },
615 { VLC_CODEC_TIFF
, "image/tiff" },
616 { VLC_CODEC_TARGA
, "image/x-tga" },
617 { VLC_FOURCC('x','p','m',' '), "image/x-xpixmap" },
621 vlc_fourcc_t
image_Mime2Fourcc( const char *psz_mime
)
623 for( int i
= 0; mime_table
[i
].i_codec
; i
++ )
624 if( !strcmp( psz_mime
, mime_table
[i
].psz_mime
) )
625 return mime_table
[i
].i_codec
;
629 static int video_update_format( decoder_t
*p_dec
)
631 p_dec
->fmt_out
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
635 static picture_t
*video_new_buffer( decoder_t
*p_dec
)
637 return picture_NewFromFormat( &p_dec
->fmt_out
.video
);
640 static decoder_t
*CreateDecoder( vlc_object_t
*p_this
, video_format_t
*fmt
)
644 p_dec
= vlc_custom_create( p_this
, sizeof( *p_dec
), "image decoder" );
648 p_dec
->p_module
= NULL
;
649 es_format_Init( &p_dec
->fmt_in
, VIDEO_ES
, fmt
->i_chroma
);
650 es_format_Init( &p_dec
->fmt_out
, VIDEO_ES
, 0 );
651 p_dec
->fmt_in
.video
= *fmt
;
652 p_dec
->b_frame_drop_allowed
= false;
654 p_dec
->pf_vout_format_update
= video_update_format
;
655 p_dec
->pf_vout_buffer_new
= video_new_buffer
;
657 /* Find a suitable decoder module */
658 p_dec
->p_module
= module_need( p_dec
, "video decoder", "$codec", false );
659 if( !p_dec
->p_module
)
661 msg_Err( p_dec
, "no suitable decoder module for fourcc `%4.4s'. "
662 "VLC probably does not support this image format.",
663 (char*)&p_dec
->fmt_in
.i_codec
);
665 DeleteDecoder( p_dec
);
672 static void DeleteDecoder( decoder_t
* p_dec
)
674 if( p_dec
->p_module
) module_unneed( p_dec
, p_dec
->p_module
);
676 es_format_Clean( &p_dec
->fmt_in
);
677 es_format_Clean( &p_dec
->fmt_out
);
679 if( p_dec
->p_description
)
680 vlc_meta_Delete( p_dec
->p_description
);
682 vlc_object_release( p_dec
);
686 static encoder_t
*CreateEncoder( vlc_object_t
*p_this
, video_format_t
*fmt_in
,
687 video_format_t
*fmt_out
)
691 p_enc
= sout_EncoderCreate( p_this
);
695 p_enc
->p_module
= NULL
;
696 es_format_Init( &p_enc
->fmt_in
, VIDEO_ES
, fmt_in
->i_chroma
);
697 p_enc
->fmt_in
.video
= *fmt_in
;
699 if( p_enc
->fmt_in
.video
.i_visible_width
== 0 ||
700 p_enc
->fmt_in
.video
.i_visible_height
== 0 ||
701 p_enc
->fmt_out
.video
.i_visible_width
== 0 ||
702 p_enc
->fmt_out
.video
.i_visible_height
== 0 )
704 if( fmt_out
->i_width
> 0 && fmt_out
->i_height
> 0 )
706 p_enc
->fmt_in
.video
.i_width
= fmt_out
->i_width
;
707 p_enc
->fmt_in
.video
.i_height
= fmt_out
->i_height
;
709 if( fmt_out
->i_visible_width
> 0 &&
710 fmt_out
->i_visible_height
> 0 )
712 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_visible_width
;
713 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_visible_height
;
717 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_width
;
718 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_height
;
721 } else if( fmt_out
->i_sar_num
&& fmt_out
->i_sar_den
&&
722 fmt_out
->i_sar_num
* fmt_in
->i_sar_den
!=
723 fmt_out
->i_sar_den
* fmt_in
->i_sar_num
)
725 p_enc
->fmt_in
.video
.i_width
=
726 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
* fmt_in
->i_width
/
727 fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
728 p_enc
->fmt_in
.video
.i_visible_width
=
729 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
*
730 fmt_in
->i_visible_width
/ fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
733 p_enc
->fmt_in
.video
.i_frame_rate
= 25;
734 p_enc
->fmt_in
.video
.i_frame_rate_base
= 1;
736 es_format_Init( &p_enc
->fmt_out
, VIDEO_ES
, fmt_out
->i_chroma
);
737 p_enc
->fmt_out
.video
= *fmt_out
;
738 p_enc
->fmt_out
.video
.i_width
= p_enc
->fmt_in
.video
.i_width
;
739 p_enc
->fmt_out
.video
.i_height
= p_enc
->fmt_in
.video
.i_height
;
741 /* Find a suitable decoder module */
742 p_enc
->p_module
= module_need( p_enc
, "encoder", NULL
, false );
743 if( !p_enc
->p_module
)
745 msg_Err( p_enc
, "no suitable encoder module for fourcc `%4.4s'.\n"
746 "VLC probably does not support this image format.",
747 (char*)&p_enc
->fmt_out
.i_codec
);
749 DeleteEncoder( p_enc
);
752 p_enc
->fmt_in
.video
.i_chroma
= p_enc
->fmt_in
.i_codec
;
757 static void DeleteEncoder( encoder_t
* p_enc
)
759 if( p_enc
->p_module
) module_unneed( p_enc
, p_enc
->p_module
);
761 es_format_Clean( &p_enc
->fmt_in
);
762 es_format_Clean( &p_enc
->fmt_out
);
764 vlc_object_release( p_enc
);
768 static filter_t
*CreateFilter( vlc_object_t
*p_this
, es_format_t
*p_fmt_in
,
769 video_format_t
*p_fmt_out
)
773 p_filter
= vlc_custom_create( p_this
, sizeof(filter_t
), "filter" );
774 p_filter
->owner
.video
.buffer_new
=
775 (picture_t
*(*)(filter_t
*))video_new_buffer
;
777 es_format_Copy( &p_filter
->fmt_in
, p_fmt_in
);
778 es_format_Copy( &p_filter
->fmt_out
, p_fmt_in
);
779 video_format_Copy( &p_filter
->fmt_out
.video
, p_fmt_out
);
780 p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
781 p_filter
->p_module
= module_need( p_filter
, "video converter", NULL
, false );
783 if( !p_filter
->p_module
)
785 msg_Dbg( p_filter
, "no video converter found" );
786 DeleteFilter( p_filter
);
793 static void DeleteFilter( filter_t
* p_filter
)
795 if( p_filter
->p_module
) module_unneed( p_filter
, p_filter
->p_module
);
797 es_format_Clean( &p_filter
->fmt_in
);
798 es_format_Clean( &p_filter
->fmt_out
);
800 vlc_object_release( p_filter
);