Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

image.c

Go to the documentation of this file.
00001 /*****************************************************************************
00002  * image.c : wrapper for image reading/writing facilities
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: image.c 11980 2005-08-03 14:52:17Z massiot $
00006  *
00007  * Author: Gildas Bazin <[email protected]>
00008  *
00009  * This program is free software; you can redistribute it and/or modify
00010  * it under the terms of the GNU General Public License as published by
00011  * the Free Software Foundation; either version 2 of the License, or
00012  * (at your option) any later version.
00013  *
00014  * This program is distributed in the hope that it will be useful,
00015  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00016  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00017  * GNU General Public License for more details.
00018  *
00019  * You should have received a copy of the GNU General Public License
00020  * along with this program; if not, write to the Free Software
00021  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00022  *****************************************************************************/
00023 
00029 /*****************************************************************************
00030  * Preamble
00031  *****************************************************************************/
00032 #include <ctype.h>
00033 #include <vlc/vlc.h>
00034 #include <vlc/decoder.h>
00035 #include <vlc_filter.h>
00036 #include <vlc_image.h>
00037 
00038 static picture_t *ImageRead( image_handler_t *, block_t *,
00039                              video_format_t *, video_format_t * );
00040 static picture_t *ImageReadUrl( image_handler_t *, const char *,
00041                                 video_format_t *, video_format_t * );
00042 static block_t *ImageWrite( image_handler_t *, picture_t *,
00043                             video_format_t *, video_format_t * );
00044 static int ImageWriteUrl( image_handler_t *, picture_t *,
00045                           video_format_t *, video_format_t *, const char * );
00046 
00047 static picture_t *ImageConvert( image_handler_t *, picture_t *,
00048                                 video_format_t *, video_format_t * );
00049 static picture_t *ImageFilter( image_handler_t *, picture_t *,
00050                                video_format_t *, const char *psz_module );
00051 
00052 static decoder_t *CreateDecoder( vlc_object_t *, video_format_t * );
00053 static void DeleteDecoder( decoder_t * );
00054 static encoder_t *CreateEncoder( vlc_object_t *, video_format_t *,
00055                                  video_format_t * );
00056 static void DeleteEncoder( encoder_t * );
00057 static filter_t *CreateFilter( vlc_object_t *, es_format_t *,
00058                                video_format_t *, const char * );
00059 static void DeleteFilter( filter_t * );
00060 
00061 static vlc_fourcc_t Ext2Fourcc( const char * );
00062 /*static const char *Fourcc2Ext( vlc_fourcc_t );*/
00063 
00068 image_handler_t *__image_HandlerCreate( vlc_object_t *p_this )
00069 {
00070     image_handler_t *p_image = malloc( sizeof(image_handler_t) );
00071 
00072     memset( p_image, 0, sizeof(image_handler_t) );
00073     p_image->p_parent = p_this;
00074 
00075     p_image->pf_read = ImageRead;
00076     p_image->pf_read_url = ImageReadUrl;
00077     p_image->pf_write = ImageWrite;
00078     p_image->pf_write_url = ImageWriteUrl;
00079     p_image->pf_convert = ImageConvert;
00080     p_image->pf_filter = ImageFilter;
00081 
00082     return p_image;
00083 }
00084 
00089 void image_HandlerDelete( image_handler_t *p_image )
00090 {
00091     if( !p_image ) return;
00092 
00093     if( p_image->p_dec ) DeleteDecoder( p_image->p_dec );
00094     if( p_image->p_enc ) DeleteEncoder( p_image->p_enc );
00095     if( p_image->p_filter ) DeleteFilter( p_image->p_filter );
00096 
00097     free( p_image );
00098 }
00099 
00105 static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
00106                              video_format_t *p_fmt_in,
00107                              video_format_t *p_fmt_out )
00108 {
00109     picture_t *p_pic = NULL, *p_tmp;
00110 
00111     /* Check if we can reuse the current decoder */
00112     if( p_image->p_dec &&
00113         p_image->p_dec->fmt_in.i_codec != p_fmt_in->i_chroma )
00114     {
00115         DeleteDecoder( p_image->p_dec );
00116         p_image->p_dec = 0;
00117     }
00118 
00119     /* Start a decoder */
00120     if( !p_image->p_dec )
00121     {
00122         p_image->p_dec = CreateDecoder( p_image->p_parent, p_fmt_in );
00123         if( !p_image->p_dec ) return NULL;
00124     }
00125 
00126     p_block->i_pts = p_block->i_dts = mdate();
00127     while( (p_tmp = p_image->p_dec->pf_decode_video( p_image->p_dec, &p_block ))
00128              != NULL )
00129     {
00130         if ( p_pic != NULL )
00131             p_pic->pf_release( p_pic );
00132         p_pic = p_tmp;
00133     }
00134 
00135     if( p_pic == NULL )
00136     {
00137         msg_Warn( p_image->p_parent, "no image decoded" );
00138         return 0;
00139     }
00140 
00141     if( !p_fmt_out->i_chroma )
00142         p_fmt_out->i_chroma = p_image->p_dec->fmt_out.video.i_chroma;
00143     if( !p_fmt_out->i_width && p_fmt_out->i_height )
00144         p_fmt_out->i_width = p_fmt_out->i_height
00145                               * p_image->p_dec->fmt_out.video.i_aspect
00146                               / VOUT_ASPECT_FACTOR;
00147     if( !p_fmt_out->i_height && p_fmt_out->i_width )
00148         p_fmt_out->i_height = p_fmt_out->i_width * VOUT_ASPECT_FACTOR
00149                                / p_image->p_dec->fmt_out.video.i_aspect;
00150     if( !p_fmt_out->i_width )
00151         p_fmt_out->i_width = p_image->p_dec->fmt_out.video.i_width;
00152     if( !p_fmt_out->i_height )
00153         p_fmt_out->i_height = p_image->p_dec->fmt_out.video.i_height;
00154 
00155     /* Check if we need chroma conversion or resizing */
00156     if( p_image->p_dec->fmt_out.video.i_chroma != p_fmt_out->i_chroma ||
00157         p_image->p_dec->fmt_out.video.i_width != p_fmt_out->i_width ||
00158         p_image->p_dec->fmt_out.video.i_height != p_fmt_out->i_height )
00159     {
00160         if( p_image->p_filter )
00161         if( p_image->p_filter->fmt_in.video.i_chroma !=
00162             p_image->p_dec->fmt_out.video.i_chroma ||
00163             p_image->p_filter->fmt_out.video.i_chroma != p_fmt_out->i_chroma )
00164         {
00165             /* We need to restart a new filter */
00166             DeleteFilter( p_image->p_filter );
00167             p_image->p_filter = 0;
00168         }
00169 
00170         /* Start a filter */
00171         if( !p_image->p_filter )
00172         {
00173             p_image->p_filter =
00174                 CreateFilter( p_image->p_parent, &p_image->p_dec->fmt_out,
00175                               p_fmt_out, NULL );
00176 
00177             if( !p_image->p_filter )
00178             {
00179                 p_pic->pf_release( p_pic );
00180                 return NULL;
00181             }
00182         }
00183         else
00184         {
00185             /* Filters should handle on-the-fly size changes */
00186             p_image->p_filter->fmt_in = p_image->p_dec->fmt_out;
00187             p_image->p_filter->fmt_out = p_image->p_dec->fmt_out;
00188             p_image->p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
00189             p_image->p_filter->fmt_out.video = *p_fmt_out;
00190         }
00191 
00192         p_pic = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
00193         *p_fmt_out = p_image->p_filter->fmt_out.video;
00194     }
00195     else *p_fmt_out = p_image->p_dec->fmt_out.video;
00196 
00197     return p_pic;
00198 }
00199 
00200 static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
00201                                 video_format_t *p_fmt_in,
00202                                 video_format_t *p_fmt_out )
00203 {
00204     block_t *p_block;
00205     picture_t *p_pic;
00206     FILE *file;
00207     int i_size;
00208 
00209     file = fopen( psz_url, "rb" );
00210     if( !file )
00211     {
00212         msg_Dbg( p_image->p_parent, "could not open file %s for reading",
00213                  psz_url );
00214         return NULL;
00215     }
00216 
00217     fseek( file, 0, SEEK_END );
00218     i_size = ftell( file );
00219     fseek( file, 0, SEEK_SET );
00220 
00221     p_block = block_New( p_image->p_parent, i_size );
00222     fread( p_block->p_buffer, sizeof(char), i_size, file );
00223     fclose( file );
00224 
00225     if( !p_fmt_in->i_chroma )
00226     {
00227         /* Try to guess format from file name */
00228         p_fmt_in->i_chroma = Ext2Fourcc( psz_url );
00229     }
00230 
00231     p_pic = ImageRead( p_image, p_block, p_fmt_in, p_fmt_out );
00232 
00233     return p_pic;
00234 }
00235 
00241 void PicRelease( picture_t *p_pic ){};
00242 
00243 static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
00244                             video_format_t *p_fmt_in,
00245                             video_format_t *p_fmt_out )
00246 {
00247     block_t *p_block;
00248     void (*pf_release)( picture_t * );
00249 
00250     /* Check if we can reuse the current encoder */
00251     if( p_image->p_enc &&
00252         ( p_image->p_enc->fmt_out.i_codec != p_fmt_out->i_chroma ||
00253           p_image->p_enc->fmt_out.video.i_width != p_fmt_out->i_width ||
00254           p_image->p_enc->fmt_out.video.i_height != p_fmt_out->i_height ) )
00255     {
00256         DeleteEncoder( p_image->p_enc );
00257         p_image->p_enc = 0;
00258     }
00259 
00260     /* Start an encoder */
00261     if( !p_image->p_enc )
00262     {
00263         p_image->p_enc = CreateEncoder( p_image->p_parent,
00264                                         p_fmt_in, p_fmt_out );
00265         if( !p_image->p_enc ) return NULL;
00266     }
00267 
00268     /* Check if we need chroma conversion or resizing */
00269     if( p_image->p_enc->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
00270         p_image->p_enc->fmt_in.video.i_width != p_fmt_in->i_width ||
00271         p_image->p_enc->fmt_in.video.i_height != p_fmt_in->i_height )
00272     {
00273         picture_t *p_pif;
00274 
00275         if( p_image->p_filter )
00276         if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
00277             p_image->p_filter->fmt_out.video.i_chroma !=
00278             p_image->p_enc->fmt_in.video.i_chroma )
00279         {
00280             /* We need to restart a new filter */
00281             DeleteFilter( p_image->p_filter );
00282             p_image->p_filter = 0;
00283         }
00284 
00285         /* Start a filter */
00286         if( !p_image->p_filter )
00287         {
00288             es_format_t fmt_in;
00289             es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
00290             fmt_in.video = *p_fmt_in;
00291 
00292             p_image->p_filter =
00293                 CreateFilter( p_image->p_parent, &fmt_in,
00294                               &p_image->p_enc->fmt_in.video, NULL );
00295 
00296             if( !p_image->p_filter )
00297             {
00298                 return NULL;
00299             }
00300         }
00301         else
00302         {
00303             /* Filters should handle on-the-fly size changes */
00304             p_image->p_filter->fmt_in.i_codec = p_fmt_in->i_chroma;
00305             p_image->p_filter->fmt_out.video = *p_fmt_in;
00306             p_image->p_filter->fmt_out.i_codec =p_image->p_enc->fmt_in.i_codec;
00307             p_image->p_filter->fmt_out.video = p_image->p_enc->fmt_in.video;
00308         }
00309 
00310         pf_release = p_pic->pf_release;
00311         p_pic->pf_release = PicRelease; /* Small hack */
00312         p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
00313         p_pic->pf_release = pf_release;
00314         p_pic = p_pif;
00315     }
00316 
00317     p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_pic );
00318 
00319     if( !p_block )
00320     {
00321         msg_Dbg( p_image->p_parent, "no image encoded" );
00322         return 0;
00323     }
00324 
00325     return p_block;
00326 }
00327 
00328 static int ImageWriteUrl( image_handler_t *p_image, picture_t *p_pic,
00329                           video_format_t *p_fmt_in, video_format_t *p_fmt_out,
00330                           const char *psz_url )
00331 {
00332     block_t *p_block;
00333     FILE *file;
00334 
00335     if( !p_fmt_out->i_chroma )
00336     {
00337         /* Try to guess format from file name */
00338         p_fmt_out->i_chroma = Ext2Fourcc( psz_url );
00339     }
00340 
00341     file = fopen( psz_url, "wb" );
00342     if( !file )
00343     {
00344         msg_Dbg( p_image->p_parent, "could not open file %s for writing",
00345                  psz_url );
00346         return VLC_EGENERIC;
00347     }
00348 
00349     p_block = ImageWrite( p_image, p_pic, p_fmt_in, p_fmt_out );
00350 
00351     if( p_block )
00352     {
00353         fwrite( p_block->p_buffer, sizeof(char), p_block->i_buffer, file );
00354         block_Release( p_block );
00355     }
00356 
00357     fclose( file );
00358 
00359     return p_block ? VLC_SUCCESS : VLC_EGENERIC;
00360 }
00361 
00367 static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
00368                                 video_format_t *p_fmt_in,
00369                                 video_format_t *p_fmt_out )
00370 {
00371     void (*pf_release)( picture_t * );
00372     picture_t *p_pif;
00373 
00374     if( !p_fmt_out->i_width && !p_fmt_out->i_height &&
00375         p_fmt_out->i_sar_num && p_fmt_out->i_sar_den &&
00376         p_fmt_out->i_sar_num * p_fmt_in->i_sar_den !=
00377         p_fmt_out->i_sar_den * p_fmt_in->i_sar_num )
00378     {
00379         p_fmt_out->i_width =
00380             p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
00381             p_fmt_in->i_width / p_fmt_in->i_sar_den / p_fmt_out->i_sar_num;
00382         p_fmt_out->i_visible_width =
00383             p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
00384             p_fmt_in->i_visible_width / p_fmt_in->i_sar_den /
00385             p_fmt_out->i_sar_num;
00386     }
00387 
00388     if( !p_fmt_out->i_chroma ) p_fmt_out->i_chroma = p_fmt_in->i_chroma;
00389     if( !p_fmt_out->i_width )
00390         p_fmt_out->i_width = p_fmt_out->i_visible_width = p_fmt_in->i_width;
00391     if( !p_fmt_out->i_height )
00392         p_fmt_out->i_height = p_fmt_out->i_visible_height = p_fmt_in->i_height;
00393     if( !p_fmt_out->i_sar_num ) p_fmt_out->i_sar_num = p_fmt_in->i_sar_num;
00394     if( !p_fmt_out->i_sar_den ) p_fmt_out->i_sar_den = p_fmt_in->i_sar_den;
00395     if( !p_fmt_out->i_aspect ) p_fmt_out->i_aspect = p_fmt_in->i_aspect;
00396 
00397     if( p_image->p_filter )
00398     if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
00399         p_image->p_filter->fmt_out.video.i_chroma != p_fmt_out->i_chroma )
00400     {
00401         /* We need to restart a new filter */
00402         DeleteFilter( p_image->p_filter );
00403         p_image->p_filter = 0;
00404     }
00405 
00406     /* Start a filter */
00407     if( !p_image->p_filter )
00408     {
00409         es_format_t fmt_in;
00410         es_format_Init( &fmt_in, VIDEO_ES, p_fmt_in->i_chroma );
00411         fmt_in.video = *p_fmt_in;
00412 
00413         p_image->p_filter =
00414             CreateFilter( p_image->p_parent, &fmt_in, p_fmt_out, NULL );
00415 
00416         if( !p_image->p_filter )
00417         {
00418             return NULL;
00419         }
00420     }
00421     else
00422     {
00423         /* Filters should handle on-the-fly size changes */
00424         p_image->p_filter->fmt_in.video = *p_fmt_in;
00425         p_image->p_filter->fmt_out.video = *p_fmt_out;
00426     }
00427 
00428     pf_release = p_pic->pf_release;
00429     p_pic->pf_release = PicRelease; /* Small hack */
00430     p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
00431     p_pic->pf_release = pf_release;
00432 
00433     if( p_fmt_in->i_chroma == p_fmt_out->i_chroma &&
00434         p_fmt_in->i_width == p_fmt_out->i_width &&
00435         p_fmt_in->i_height == p_fmt_out->i_height )
00436     {
00437         /* Duplicate image */
00438         p_pif = p_image->p_filter->pf_vout_buffer_new( p_image->p_filter );
00439         if( p_pif ) vout_CopyPicture( p_image->p_parent, p_pif, p_pic );
00440     }
00441 
00442     return p_pif;
00443 }
00444 
00450 static picture_t *ImageFilter( image_handler_t *p_image, picture_t *p_pic,
00451                                video_format_t *p_fmt, const char *psz_module )
00452 {
00453     void (*pf_release)( picture_t * );
00454     picture_t *p_pif;
00455 
00456     /* Start a filter */
00457     if( !p_image->p_filter )
00458     {
00459         es_format_t fmt;
00460         es_format_Init( &fmt, VIDEO_ES, p_fmt->i_chroma );
00461         fmt.video = *p_fmt;
00462 
00463         p_image->p_filter =
00464             CreateFilter( p_image->p_parent, &fmt, &fmt.video, psz_module );
00465 
00466         if( !p_image->p_filter )
00467         {
00468             return NULL;
00469         }
00470     }
00471     else
00472     {
00473         /* Filters should handle on-the-fly size changes */
00474         p_image->p_filter->fmt_in.video = *p_fmt;
00475         p_image->p_filter->fmt_out.video = *p_fmt;
00476     }
00477 
00478     pf_release = p_pic->pf_release;
00479     p_pic->pf_release = PicRelease; /* Small hack */
00480     p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
00481     p_pic->pf_release = pf_release;
00482 
00483     return p_pif;
00484 }
00485 
00490 static struct
00491 {
00492     vlc_fourcc_t i_codec;
00493     char *psz_ext;
00494 
00495 } ext_table[] =
00496 {
00497     { VLC_FOURCC('j','p','e','g'), "jpeg" },
00498     { VLC_FOURCC('j','p','e','g'), "jpg"  },
00499     { VLC_FOURCC('l','j','p','g'), "ljpg" },
00500     { VLC_FOURCC('p','n','g',' '), "png" },
00501     { VLC_FOURCC('p','g','m',' '), "pgm" },
00502     { VLC_FOURCC('p','g','m','y'), "pgmyuv" },
00503     { VLC_FOURCC('p','b','m',' '), "pbm" },
00504     { VLC_FOURCC('p','a','m',' '), "pam" },
00505     { VLC_FOURCC('t','g','a',' '), "tga" },
00506     { VLC_FOURCC('b','m','p',' '), "bmp" },
00507     { VLC_FOURCC('p','n','m',' '), "pnm" },
00508     { VLC_FOURCC('x','p','m',' '), "xpm" },
00509     { VLC_FOURCC('x','c','f',' '), "xcf" },
00510     { VLC_FOURCC('p','c','x',' '), "pcx" },
00511     { VLC_FOURCC('g','i','f',' '), "gif" },
00512     { VLC_FOURCC('t','i','f','f'), "tif" },
00513     { VLC_FOURCC('t','i','f','f'), "tiff" },
00514     { VLC_FOURCC('l','b','m',' '), "lbm" },
00515     { 0, NULL }
00516 };
00517 
00518 static vlc_fourcc_t Ext2Fourcc( const char *psz_name )
00519 {
00520     int i;
00521 
00522     psz_name = strrchr( psz_name, '.' );
00523     if( !psz_name ) return 0;
00524     psz_name++;
00525 
00526     for( i = 0; ext_table[i].i_codec; i++ )
00527     {
00528         int j;
00529         for( j = 0; toupper(ext_table[i].psz_ext[j]) == toupper(psz_name[j]);
00530              j++ )
00531         {
00532             if( !ext_table[i].psz_ext[j] && !psz_name[j] )
00533                 return ext_table[i].i_codec;
00534         }
00535     }
00536 
00537     return 0;
00538 }
00539 
00540 /*
00541 static const char *Fourcc2Ext( vlc_fourcc_t i_codec )
00542 {
00543     int i;
00544 
00545     for( i = 0; ext_table[i].i_codec != 0; i++ )
00546     {
00547         if( ext_table[i].i_codec == i_codec ) return ext_table[i].psz_ext;
00548     }
00549 
00550     return NULL;
00551 }
00552 */
00553 
00554 static void video_release_buffer( picture_t *p_pic )
00555 {
00556     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
00557     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
00558     if( p_pic ) free( p_pic );
00559 }
00560 
00561 static picture_t *video_new_buffer( decoder_t *p_dec )
00562 {
00563     picture_t *p_pic = malloc( sizeof(picture_t) );
00564 
00565     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
00566     vout_AllocatePicture( VLC_OBJECT(p_dec), p_pic,
00567                           p_dec->fmt_out.video.i_chroma,
00568                           p_dec->fmt_out.video.i_width,
00569                           p_dec->fmt_out.video.i_height,
00570                           p_dec->fmt_out.video.i_aspect );
00571 
00572     if( !p_pic->i_planes )
00573     {
00574         free( p_pic );
00575         return 0;
00576     }
00577 
00578     p_pic->pf_release = video_release_buffer;
00579     p_pic->i_status = RESERVED_PICTURE;
00580     p_pic->p_sys = NULL;
00581 
00582     return p_pic;
00583 }
00584 
00585 static void video_del_buffer( decoder_t *p_dec, picture_t *p_pic )
00586 {
00587     if( p_pic && p_pic->p_data_orig ) free( p_pic->p_data_orig );
00588     if( p_pic && p_pic->p_sys ) free( p_pic->p_sys );
00589     if( p_pic ) free( p_pic );
00590 }
00591 
00592 static void video_link_picture( decoder_t *p_dec, picture_t *p_pic )
00593 {
00594 }
00595 
00596 static void video_unlink_picture( decoder_t *p_dec, picture_t *p_pic )
00597 {
00598 }
00599 
00600 static decoder_t *CreateDecoder( vlc_object_t *p_this, video_format_t *fmt )
00601 {
00602     decoder_t *p_dec;
00603 
00604     p_dec = vlc_object_create( p_this, VLC_OBJECT_DECODER );
00605     if( p_dec == NULL )
00606     {
00607         msg_Err( p_this, "out of memory" );
00608         return NULL;
00609     }
00610 
00611     p_dec->p_module = NULL;
00612     es_format_Init( &p_dec->fmt_in, VIDEO_ES, fmt->i_chroma );
00613     es_format_Init( &p_dec->fmt_out, VIDEO_ES, 0 );
00614     p_dec->fmt_in.video = *fmt;
00615     p_dec->b_pace_control = VLC_TRUE;
00616 
00617     p_dec->pf_vout_buffer_new = video_new_buffer;
00618     p_dec->pf_vout_buffer_del = video_del_buffer;
00619     p_dec->pf_picture_link    = video_link_picture;
00620     p_dec->pf_picture_unlink  = video_unlink_picture;
00621 
00622     vlc_object_attach( p_dec, p_this );
00623 
00624     /* Find a suitable decoder module */
00625     p_dec->p_module = module_Need( p_dec, "decoder", "$codec", 0 );
00626     if( !p_dec->p_module )
00627     {
00628         msg_Err( p_dec, "no suitable decoder module for fourcc `%4.4s'.\n"
00629                  "VLC probably does not support this image format.",
00630                  (char*)&p_dec->fmt_in.i_codec );
00631 
00632         DeleteDecoder( p_dec );
00633         return NULL;
00634     }
00635 
00636     return p_dec;
00637 }
00638 
00639 static void DeleteDecoder( decoder_t * p_dec )
00640 {
00641     vlc_object_detach( p_dec );
00642 
00643     if( p_dec->p_module ) module_Unneed( p_dec, p_dec->p_module );
00644 
00645     es_format_Clean( &p_dec->fmt_in );
00646     es_format_Clean( &p_dec->fmt_out );
00647 
00648     vlc_object_destroy( p_dec );
00649 }
00650 
00651 static encoder_t *CreateEncoder( vlc_object_t *p_this, video_format_t *fmt_in,
00652                                  video_format_t *fmt_out )
00653 {
00654     encoder_t *p_enc;
00655 
00656     p_enc = vlc_object_create( p_this, VLC_OBJECT_ENCODER );
00657     if( p_enc == NULL )
00658     {
00659         msg_Err( p_this, "out of memory" );
00660         return NULL;
00661     }
00662 
00663     p_enc->p_module = NULL;
00664     es_format_Init( &p_enc->fmt_in, VIDEO_ES, fmt_in->i_chroma );
00665     p_enc->fmt_in.video = *fmt_in;
00666     if( fmt_out->i_width > 0 && fmt_out->i_height > 0 )
00667     {
00668         p_enc->fmt_in.video.i_width = fmt_out->i_width;
00669         p_enc->fmt_in.video.i_height = fmt_out->i_height;
00670 
00671         if( fmt_out->i_visible_width > 0 &&
00672             fmt_out->i_visible_height > 0 )
00673         {
00674             p_enc->fmt_in.video.i_visible_width = fmt_out->i_visible_width;
00675             p_enc->fmt_in.video.i_visible_height = fmt_out->i_visible_height;
00676         }
00677         else
00678         {
00679             p_enc->fmt_in.video.i_visible_width = fmt_out->i_width;
00680             p_enc->fmt_in.video.i_visible_height = fmt_out->i_height;
00681         }
00682     }
00683     else if( fmt_out->i_sar_num && fmt_out->i_sar_den &&
00684              fmt_out->i_sar_num * fmt_in->i_sar_den !=
00685              fmt_out->i_sar_den * fmt_in->i_sar_num )
00686     {
00687         p_enc->fmt_in.video.i_width =
00688             fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den * fmt_in->i_width /
00689             fmt_in->i_sar_den / fmt_out->i_sar_num;
00690         p_enc->fmt_in.video.i_visible_width =
00691             fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den *
00692             fmt_in->i_visible_width / fmt_in->i_sar_den / fmt_out->i_sar_num;
00693     }
00694 
00695     p_enc->fmt_in.video.i_frame_rate = 25;
00696     p_enc->fmt_in.video.i_frame_rate_base = 1;
00697 
00698     es_format_Init( &p_enc->fmt_out, VIDEO_ES, fmt_out->i_chroma );
00699     p_enc->fmt_out.video = *fmt_out;
00700     p_enc->fmt_out.video.i_width = p_enc->fmt_in.video.i_width;
00701     p_enc->fmt_out.video.i_height = p_enc->fmt_in.video.i_height;
00702 
00703     vlc_object_attach( p_enc, p_this );
00704 
00705     /* Find a suitable decoder module */
00706     p_enc->p_module = module_Need( p_enc, "encoder", 0, 0 );
00707     if( !p_enc->p_module )
00708     {
00709         msg_Err( p_enc, "no suitable encoder module for fourcc `%4.4s'.\n"
00710                  "VLC probably does not support this image format.",
00711                  (char*)&p_enc->fmt_out.i_codec );
00712 
00713         DeleteEncoder( p_enc );
00714         return NULL;
00715     }
00716     p_enc->fmt_in.video.i_chroma = p_enc->fmt_in.i_codec;
00717 
00718     return p_enc;
00719 }
00720 
00721 static void DeleteEncoder( encoder_t * p_enc )
00722 {
00723     vlc_object_detach( p_enc );
00724 
00725     if( p_enc->p_module ) module_Unneed( p_enc, p_enc->p_module );
00726 
00727     es_format_Clean( &p_enc->fmt_in );
00728     es_format_Clean( &p_enc->fmt_out );
00729 
00730     vlc_object_destroy( p_enc );
00731 }
00732 
00733 static filter_t *CreateFilter( vlc_object_t *p_this, es_format_t *p_fmt_in,
00734                                video_format_t *p_fmt_out,
00735                                const char *psz_module )
00736 {
00737     filter_t *p_filter;
00738 
00739     p_filter = vlc_object_create( p_this, VLC_OBJECT_FILTER );
00740     vlc_object_attach( p_filter, p_this );
00741 
00742     p_filter->pf_vout_buffer_new =
00743         (picture_t *(*)(filter_t *))video_new_buffer;
00744     p_filter->pf_vout_buffer_del =
00745         (void (*)(filter_t *, picture_t *))video_del_buffer;
00746 
00747     p_filter->fmt_in = *p_fmt_in;
00748     p_filter->fmt_out = *p_fmt_in;
00749     p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
00750     p_filter->fmt_out.video = *p_fmt_out;
00751     p_filter->p_module = module_Need( p_filter, "video filter2", psz_module,
00752                                       0 );
00753 
00754     if( !p_filter->p_module )
00755     {
00756         msg_Dbg( p_filter, "no video filter found" );
00757         DeleteFilter( p_filter );
00758         return NULL;
00759     }
00760 
00761     return p_filter;
00762 }
00763 
00764 static void DeleteFilter( filter_t * p_filter )
00765 {
00766     vlc_object_detach( p_filter );
00767 
00768     if( p_filter->p_module ) module_Unneed( p_filter, p_filter->p_module );
00769 
00770     es_format_Clean( &p_filter->fmt_in );
00771     es_format_Clean( &p_filter->fmt_out );
00772 
00773     vlc_object_destroy( p_filter );
00774 }

Generated on Tue Dec 20 10:14:55 2005 for vlc-0.8.4a by  doxygen 1.4.2