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 const 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 const video_format_t
*, const video_format_t
* );
58 static int ImageWriteUrl( image_handler_t
*, picture_t
*,
59 const video_format_t
*, video_format_t
*, const char * );
61 static picture_t
*ImageConvert( image_handler_t
*, picture_t
*,
62 const video_format_t
*, video_format_t
* );
64 static decoder_t
*CreateDecoder( vlc_object_t
*, const video_format_t
* );
65 static void DeleteDecoder( decoder_t
* );
66 static encoder_t
*CreateEncoder( vlc_object_t
*, const video_format_t
*,
67 const video_format_t
* );
68 static void DeleteEncoder( encoder_t
* );
69 static filter_t
*CreateFilter( vlc_object_t
*, const es_format_t
*,
70 const video_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 const 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
);
320 /* FIXME: refactor by splitting video_format_IsSimilar() API */
321 static bool BitMapFormatIsSimilar( const video_format_t
*f1
,
322 const video_format_t
*f2
)
324 if( f1
->i_chroma
== VLC_CODEC_RGB15
||
325 f1
->i_chroma
== VLC_CODEC_RGB16
||
326 f1
->i_chroma
== VLC_CODEC_RGB24
||
327 f1
->i_chroma
== VLC_CODEC_RGB32
)
329 video_format_t v1
= *f1
;
330 video_format_t v2
= *f2
;
332 video_format_FixRgb( &v1
);
333 video_format_FixRgb( &v2
);
335 if( v1
.i_rmask
!= v2
.i_rmask
||
336 v1
.i_gmask
!= v2
.i_gmask
||
337 v1
.i_bmask
!= v2
.i_bmask
)
348 static block_t
*ImageWrite( image_handler_t
*p_image
, picture_t
*p_pic
,
349 const video_format_t
*p_fmt_in
,
350 const video_format_t
*p_fmt_out
)
354 /* Check if we can reuse the current encoder */
355 if( p_image
->p_enc
&&
356 ( p_image
->p_enc
->fmt_out
.i_codec
!= p_fmt_out
->i_chroma
||
357 p_image
->p_enc
->fmt_out
.video
.i_width
!= p_fmt_out
->i_width
||
358 p_image
->p_enc
->fmt_out
.video
.i_height
!= p_fmt_out
->i_height
) )
360 DeleteEncoder( p_image
->p_enc
);
364 /* Start an encoder */
365 if( !p_image
->p_enc
)
367 p_image
->p_enc
= CreateEncoder( p_image
->p_parent
,
368 p_fmt_in
, p_fmt_out
);
369 if( !p_image
->p_enc
) return NULL
;
372 /* Check if we need chroma conversion or resizing */
373 if( p_image
->p_enc
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
374 p_image
->p_enc
->fmt_in
.video
.i_width
!= p_fmt_in
->i_width
||
375 p_image
->p_enc
->fmt_in
.video
.i_height
!= p_fmt_in
->i_height
||
376 !BitMapFormatIsSimilar( &p_image
->p_enc
->fmt_in
.video
, p_fmt_in
) )
378 picture_t
*p_tmp_pic
;
380 if( p_image
->p_filter
)
381 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
382 p_image
->p_filter
->fmt_out
.video
.i_chroma
!=
383 p_image
->p_enc
->fmt_in
.video
.i_chroma
||
384 !BitMapFormatIsSimilar( &p_image
->p_filter
->fmt_in
.video
, p_fmt_in
) )
386 /* We need to restart a new filter */
387 DeleteFilter( p_image
->p_filter
);
388 p_image
->p_filter
= 0;
392 if( !p_image
->p_filter
)
395 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
396 fmt_in
.video
= *p_fmt_in
;
399 CreateFilter( p_image
->p_parent
, &fmt_in
,
400 &p_image
->p_enc
->fmt_in
.video
);
402 if( !p_image
->p_filter
)
409 /* Filters should handle on-the-fly size changes */
410 p_image
->p_filter
->fmt_in
.i_codec
= p_fmt_in
->i_chroma
;
411 p_image
->p_filter
->fmt_out
.video
= *p_fmt_in
;
412 p_image
->p_filter
->fmt_out
.i_codec
=p_image
->p_enc
->fmt_in
.i_codec
;
413 p_image
->p_filter
->fmt_out
.video
= p_image
->p_enc
->fmt_in
.video
;
416 picture_Hold( p_pic
);
419 p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
421 if( likely(p_tmp_pic
!= NULL
) )
423 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
,
425 picture_Release( p_tmp_pic
);
432 p_block
= p_image
->p_enc
->pf_encode_video( p_image
->p_enc
, p_pic
);
437 msg_Dbg( p_image
->p_parent
, "no image encoded" );
444 static int ImageWriteUrl( image_handler_t
*p_image
, picture_t
*p_pic
,
445 const video_format_t
*p_fmt_in
, video_format_t
*p_fmt_out
,
446 const char *psz_url
)
451 if( !p_fmt_out
->i_chroma
)
453 /* Try to guess format from file name */
454 p_fmt_out
->i_chroma
= image_Ext2Fourcc( psz_url
);
457 file
= vlc_fopen( psz_url
, "wb" );
460 msg_Err( p_image
->p_parent
, "%s: %s", psz_url
, vlc_strerror_c(errno
) );
464 p_block
= ImageWrite( p_image
, p_pic
, p_fmt_in
, p_fmt_out
);
469 if( fwrite( p_block
->p_buffer
, p_block
->i_buffer
, 1, file
) != 1 )
471 block_Release( p_block
);
474 if( fclose( file
) && !err
)
480 msg_Err( p_image
->p_parent
, "%s: %s", psz_url
, vlc_strerror_c(errno
) );
483 return err
? VLC_EGENERIC
: VLC_SUCCESS
;
487 * Convert an image to a different format
491 static picture_t
*ImageConvert( image_handler_t
*p_image
, picture_t
*p_pic
,
492 const video_format_t
*p_fmt_in
,
493 video_format_t
*p_fmt_out
)
497 if( !p_fmt_out
->i_width
&& !p_fmt_out
->i_height
&&
498 p_fmt_out
->i_sar_num
&& p_fmt_out
->i_sar_den
&&
499 p_fmt_out
->i_sar_num
* p_fmt_in
->i_sar_den
!=
500 p_fmt_out
->i_sar_den
* p_fmt_in
->i_sar_num
)
503 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
504 p_fmt_in
->i_width
/ p_fmt_in
->i_sar_den
/ p_fmt_out
->i_sar_num
;
505 p_fmt_out
->i_visible_width
=
506 p_fmt_in
->i_sar_num
* (int64_t)p_fmt_out
->i_sar_den
*
507 p_fmt_in
->i_visible_width
/ p_fmt_in
->i_sar_den
/
508 p_fmt_out
->i_sar_num
;
511 if( !p_fmt_out
->i_chroma
) p_fmt_out
->i_chroma
= p_fmt_in
->i_chroma
;
512 if( !p_fmt_out
->i_width
)
513 p_fmt_out
->i_width
= p_fmt_out
->i_visible_width
= p_fmt_in
->i_width
;
514 if( !p_fmt_out
->i_height
)
515 p_fmt_out
->i_height
= p_fmt_out
->i_visible_height
= p_fmt_in
->i_height
;
516 if( !p_fmt_out
->i_sar_num
) p_fmt_out
->i_sar_num
= p_fmt_in
->i_sar_num
;
517 if( !p_fmt_out
->i_sar_den
) p_fmt_out
->i_sar_den
= p_fmt_in
->i_sar_den
;
519 if( p_image
->p_filter
)
520 if( p_image
->p_filter
->fmt_in
.video
.i_chroma
!= p_fmt_in
->i_chroma
||
521 p_image
->p_filter
->fmt_out
.video
.i_chroma
!= p_fmt_out
->i_chroma
)
523 /* We need to restart a new filter */
524 DeleteFilter( p_image
->p_filter
);
525 p_image
->p_filter
= NULL
;
529 if( !p_image
->p_filter
)
532 es_format_Init( &fmt_in
, VIDEO_ES
, p_fmt_in
->i_chroma
);
533 fmt_in
.video
= *p_fmt_in
;
536 CreateFilter( p_image
->p_parent
, &fmt_in
, p_fmt_out
);
538 if( !p_image
->p_filter
)
545 /* Filters should handle on-the-fly size changes */
546 p_image
->p_filter
->fmt_in
.video
= *p_fmt_in
;
547 p_image
->p_filter
->fmt_out
.video
= *p_fmt_out
;
550 picture_Hold( p_pic
);
552 p_pif
= p_image
->p_filter
->pf_video_filter( p_image
->p_filter
, p_pic
);
554 if( p_fmt_in
->i_chroma
== p_fmt_out
->i_chroma
&&
555 p_fmt_in
->i_width
== p_fmt_out
->i_width
&&
556 p_fmt_in
->i_height
== p_fmt_out
->i_height
)
558 /* Duplicate image */
559 picture_Release( p_pif
); /* XXX: Better fix must be possible */
560 p_pif
= filter_NewPicture( p_image
->p_filter
);
562 picture_Copy( p_pif
, p_pic
);
574 vlc_fourcc_t i_codec
;
575 const char psz_ext
[7];
579 { VLC_CODEC_JPEG
, "jpeg" },
580 { VLC_CODEC_JPEG
, "jpg" },
581 { VLC_CODEC_JPEGLS
, "ljpg" },
582 { VLC_CODEC_BPG
, "bpg" },
583 { VLC_CODEC_PNG
, "png" },
584 { VLC_CODEC_PGM
, "pgm" },
585 { VLC_CODEC_PGMYUV
, "pgmyuv" },
586 { VLC_FOURCC('p','b','m',' '), "pbm" },
587 { VLC_FOURCC('p','a','m',' '), "pam" },
588 { VLC_CODEC_TARGA
, "tga" },
589 { VLC_CODEC_BMP
, "bmp" },
590 { VLC_CODEC_PNM
, "pnm" },
591 { VLC_FOURCC('x','p','m',' '), "xpm" },
592 { VLC_FOURCC('x','c','f',' '), "xcf" },
593 { VLC_CODEC_PCX
, "pcx" },
594 { VLC_CODEC_GIF
, "gif" },
595 { VLC_CODEC_SVG
, "svg" },
596 { VLC_CODEC_TIFF
, "tif" },
597 { VLC_CODEC_TIFF
, "tiff" },
598 { VLC_FOURCC('l','b','m',' '), "lbm" },
599 { VLC_CODEC_PPM
, "ppm" },
602 vlc_fourcc_t
image_Type2Fourcc( const char *psz_type
)
604 for( unsigned i
= 0; i
< ARRAY_SIZE(ext_table
); i
++ )
605 if( !strcasecmp( ext_table
[i
].psz_ext
, psz_type
) )
606 return ext_table
[i
].i_codec
;
611 vlc_fourcc_t
image_Ext2Fourcc( const char *psz_name
)
613 psz_name
= strrchr( psz_name
, '.' );
614 if( !psz_name
) return 0;
617 return image_Type2Fourcc( psz_name
);
622 vlc_fourcc_t i_codec
;
623 const char *psz_mime
;
626 { VLC_CODEC_BMP
, "image/bmp" },
627 { VLC_CODEC_BMP
, "image/x-bmp" },
628 { VLC_CODEC_BMP
, "image/x-bitmap" },
629 { VLC_CODEC_BMP
, "image/x-ms-bmp" },
630 { VLC_CODEC_PNM
, "image/x-portable-anymap" },
631 { VLC_CODEC_PNM
, "image/x-portable-bitmap" },
632 { VLC_CODEC_PNM
, "image/x-portable-graymap" },
633 { VLC_CODEC_PNM
, "image/x-portable-pixmap" },
634 { VLC_CODEC_GIF
, "image/gif" },
635 { VLC_CODEC_JPEG
, "image/jpeg" },
636 { VLC_CODEC_BPG
, "image/bpg" },
637 { VLC_CODEC_PCX
, "image/pcx" },
638 { VLC_CODEC_PNG
, "image/png" },
639 { VLC_CODEC_SVG
, "image/svg+xml" },
640 { VLC_CODEC_TIFF
, "image/tiff" },
641 { VLC_CODEC_TARGA
, "image/x-tga" },
642 { VLC_FOURCC('x','p','m',' '), "image/x-xpixmap" },
646 vlc_fourcc_t
image_Mime2Fourcc( const char *psz_mime
)
648 for( int i
= 0; mime_table
[i
].i_codec
; i
++ )
649 if( !strcmp( psz_mime
, mime_table
[i
].psz_mime
) )
650 return mime_table
[i
].i_codec
;
654 static int video_update_format( decoder_t
*p_dec
)
656 p_dec
->fmt_out
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
660 static picture_t
*video_new_buffer( decoder_t
*p_dec
)
662 return picture_NewFromFormat( &p_dec
->fmt_out
.video
);
665 static decoder_t
*CreateDecoder( vlc_object_t
*p_this
, const video_format_t
*fmt
)
669 p_dec
= vlc_custom_create( p_this
, sizeof( *p_dec
), "image decoder" );
673 p_dec
->p_module
= NULL
;
674 es_format_InitFromVideo( &p_dec
->fmt_in
, fmt
);
675 es_format_Init( &p_dec
->fmt_out
, VIDEO_ES
, 0 );
676 p_dec
->b_frame_drop_allowed
= false;
678 p_dec
->pf_vout_format_update
= video_update_format
;
679 p_dec
->pf_vout_buffer_new
= video_new_buffer
;
681 /* Find a suitable decoder module */
682 p_dec
->p_module
= module_need_var( p_dec
, "video decoder", "codec" );
683 if( !p_dec
->p_module
)
685 msg_Err( p_dec
, "no suitable decoder module for fourcc `%4.4s'. "
686 "VLC probably does not support this image format.",
687 (char*)&p_dec
->fmt_in
.i_codec
);
689 DeleteDecoder( p_dec
);
696 static void DeleteDecoder( decoder_t
* p_dec
)
698 if( p_dec
->p_module
) module_unneed( p_dec
, p_dec
->p_module
);
700 es_format_Clean( &p_dec
->fmt_in
);
701 es_format_Clean( &p_dec
->fmt_out
);
703 if( p_dec
->p_description
)
704 vlc_meta_Delete( p_dec
->p_description
);
706 vlc_object_release( p_dec
);
710 static encoder_t
*CreateEncoder( vlc_object_t
*p_this
, const video_format_t
*fmt_in
,
711 const video_format_t
*fmt_out
)
715 p_enc
= sout_EncoderCreate( p_this
);
719 p_enc
->p_module
= NULL
;
720 es_format_InitFromVideo( &p_enc
->fmt_in
, fmt_in
);
722 if( p_enc
->fmt_in
.video
.i_visible_width
== 0 ||
723 p_enc
->fmt_in
.video
.i_visible_height
== 0 ||
724 p_enc
->fmt_out
.video
.i_visible_width
== 0 ||
725 p_enc
->fmt_out
.video
.i_visible_height
== 0 )
727 if( fmt_out
->i_width
> 0 && fmt_out
->i_height
> 0 )
729 p_enc
->fmt_in
.video
.i_width
= fmt_out
->i_width
;
730 p_enc
->fmt_in
.video
.i_height
= fmt_out
->i_height
;
732 if( fmt_out
->i_visible_width
> 0 &&
733 fmt_out
->i_visible_height
> 0 )
735 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_visible_width
;
736 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_visible_height
;
740 p_enc
->fmt_in
.video
.i_visible_width
= fmt_out
->i_width
;
741 p_enc
->fmt_in
.video
.i_visible_height
= fmt_out
->i_height
;
744 } else if( fmt_out
->i_sar_num
&& fmt_out
->i_sar_den
&&
745 fmt_out
->i_sar_num
* fmt_in
->i_sar_den
!=
746 fmt_out
->i_sar_den
* fmt_in
->i_sar_num
)
748 p_enc
->fmt_in
.video
.i_width
=
749 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
* fmt_in
->i_width
/
750 fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
751 p_enc
->fmt_in
.video
.i_visible_width
=
752 fmt_in
->i_sar_num
* (int64_t)fmt_out
->i_sar_den
*
753 fmt_in
->i_visible_width
/ fmt_in
->i_sar_den
/ fmt_out
->i_sar_num
;
756 p_enc
->fmt_in
.video
.i_frame_rate
= 25;
757 p_enc
->fmt_in
.video
.i_frame_rate_base
= 1;
759 es_format_InitFromVideo( &p_enc
->fmt_out
, fmt_out
);
760 p_enc
->fmt_out
.video
.i_width
= p_enc
->fmt_in
.video
.i_width
;
761 p_enc
->fmt_out
.video
.i_height
= p_enc
->fmt_in
.video
.i_height
;
763 /* Find a suitable decoder module */
764 p_enc
->p_module
= module_need( p_enc
, "encoder", NULL
, false );
765 if( !p_enc
->p_module
)
767 msg_Err( p_enc
, "no suitable encoder module for fourcc `%4.4s'.\n"
768 "VLC probably does not support this image format.",
769 (char*)&p_enc
->fmt_out
.i_codec
);
771 DeleteEncoder( p_enc
);
774 p_enc
->fmt_in
.video
.i_chroma
= p_enc
->fmt_in
.i_codec
;
779 static void DeleteEncoder( encoder_t
* p_enc
)
781 if( p_enc
->p_module
) module_unneed( p_enc
, p_enc
->p_module
);
783 es_format_Clean( &p_enc
->fmt_in
);
784 es_format_Clean( &p_enc
->fmt_out
);
786 vlc_object_release( p_enc
);
790 static picture_t
*filter_new_picture( filter_t
*p_filter
)
792 return picture_NewFromFormat( &p_filter
->fmt_out
.video
);
795 static filter_t
*CreateFilter( vlc_object_t
*p_this
, const es_format_t
*p_fmt_in
,
796 const video_format_t
*p_fmt_out
)
800 p_filter
= vlc_custom_create( p_this
, sizeof(filter_t
), "filter" );
801 p_filter
->owner
.video
.buffer_new
= filter_new_picture
;
803 es_format_Copy( &p_filter
->fmt_in
, p_fmt_in
);
804 es_format_Copy( &p_filter
->fmt_out
, p_fmt_in
);
805 video_format_Copy( &p_filter
->fmt_out
.video
, p_fmt_out
);
807 /* whatever the input offset, write at offset 0 in the target image */
808 p_filter
->fmt_out
.video
.i_x_offset
= 0;
809 p_filter
->fmt_out
.video
.i_y_offset
= 0;
811 p_filter
->fmt_out
.i_codec
= p_fmt_out
->i_chroma
;
812 p_filter
->p_module
= module_need( p_filter
, "video converter", NULL
, false );
814 if( !p_filter
->p_module
)
816 msg_Dbg( p_filter
, "no video converter found" );
817 DeleteFilter( p_filter
);
824 static void DeleteFilter( filter_t
* p_filter
)
826 if( p_filter
->p_module
) module_unneed( p_filter
, p_filter
->p_module
);
828 es_format_Clean( &p_filter
->fmt_in
);
829 es_format_Clean( &p_filter
->fmt_out
);
831 vlc_object_release( p_filter
);