]> git.sesse.net Git - vlc/blobdiff - src/misc/image.c
Hum, this isn't needed anymore.
[vlc] / src / misc / image.c
index af7d6dd1dc216d4313642ae0f4c8bbc7e53a1a25..c321a6301b86bb5d9a18c8b453e5b0062a8ed97d 100644 (file)
@@ -1,7 +1,7 @@
 /*****************************************************************************
  * image.c : wrapper for image reading/writing facilities
  *****************************************************************************
- * Copyright (C) 2004 VideoLAN
+ * Copyright (C) 2004 the VideoLAN team
  * $Id$
  *
  * Author: Gildas Bazin <gbazin@videolan.org>
@@ -18,7 +18,7 @@
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
  *****************************************************************************/
 
 /**
@@ -34,6 +34,8 @@
 #include <vlc/decoder.h>
 #include <vlc_filter.h>
 #include <vlc_image.h>
+#include <vlc_stream.h>
+#include <charset.h>
 
 static picture_t *ImageRead( image_handler_t *, block_t *,
                              video_format_t *, video_format_t * );
@@ -46,6 +48,8 @@ static int ImageWriteUrl( image_handler_t *, picture_t *,
 
 static picture_t *ImageConvert( image_handler_t *, picture_t *,
                                 video_format_t *, video_format_t * );
+static picture_t *ImageFilter( image_handler_t *, picture_t *,
+                               video_format_t *, const char *psz_module );
 
 static decoder_t *CreateDecoder( vlc_object_t *, video_format_t * );
 static void DeleteDecoder( decoder_t * );
@@ -53,11 +57,11 @@ static encoder_t *CreateEncoder( vlc_object_t *, video_format_t *,
                                  video_format_t * );
 static void DeleteEncoder( encoder_t * );
 static filter_t *CreateFilter( vlc_object_t *, es_format_t *,
-                               video_format_t * );
+                               video_format_t *, const char * );
 static void DeleteFilter( filter_t * );
 
 static vlc_fourcc_t Ext2Fourcc( const char * );
-static const char *Fourcc2Ext( vlc_fourcc_t );
+/*static const char *Fourcc2Ext( vlc_fourcc_t );*/
 
 /**
  * Create an image_handler_t instance
@@ -75,6 +79,7 @@ image_handler_t *__image_HandlerCreate( vlc_object_t *p_this )
     p_image->pf_write = ImageWrite;
     p_image->pf_write_url = ImageWriteUrl;
     p_image->pf_convert = ImageConvert;
+    p_image->pf_filter = ImageFilter;
 
     return p_image;
 }
@@ -103,7 +108,7 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
                              video_format_t *p_fmt_in,
                              video_format_t *p_fmt_out )
 {
-    picture_t *p_pic;
+    picture_t *p_pic = NULL, *p_tmp;
 
     /* Check if we can reuse the current decoder */
     if( p_image->p_dec &&
@@ -121,17 +126,29 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
     }
 
     p_block->i_pts = p_block->i_dts = mdate();
-    p_pic = p_image->p_dec->pf_decode_video( p_image->p_dec, &p_block );
-    p_image->p_dec->pf_decode_video( p_image->p_dec, &p_block );
+    while( (p_tmp = p_image->p_dec->pf_decode_video( p_image->p_dec, &p_block ))
+             != NULL )
+    {
+        if ( p_pic != NULL )
+            p_pic->pf_release( p_pic );
+        p_pic = p_tmp;
+    }
 
-    if( !p_pic )
+    if( p_pic == NULL )
     {
-        msg_Dbg( p_image->p_parent, "no image decoded" );
+        msg_Warn( p_image->p_parent, "no image decoded" );
         return 0;
     }
 
     if( !p_fmt_out->i_chroma )
         p_fmt_out->i_chroma = p_image->p_dec->fmt_out.video.i_chroma;
+    if( !p_fmt_out->i_width && p_fmt_out->i_height )
+        p_fmt_out->i_width = p_fmt_out->i_height
+                              * p_image->p_dec->fmt_out.video.i_aspect
+                              / VOUT_ASPECT_FACTOR;
+    if( !p_fmt_out->i_height && p_fmt_out->i_width )
+        p_fmt_out->i_height = p_fmt_out->i_width * VOUT_ASPECT_FACTOR
+                               / p_image->p_dec->fmt_out.video.i_aspect;
     if( !p_fmt_out->i_width )
         p_fmt_out->i_width = p_image->p_dec->fmt_out.video.i_width;
     if( !p_fmt_out->i_height )
@@ -157,7 +174,7 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
         {
             p_image->p_filter =
                 CreateFilter( p_image->p_parent, &p_image->p_dec->fmt_out,
-                              p_fmt_out );
+                              p_fmt_out, NULL );
 
             if( !p_image->p_filter )
             {
@@ -188,24 +205,24 @@ static picture_t *ImageReadUrl( image_handler_t *p_image, const char *psz_url,
 {
     block_t *p_block;
     picture_t *p_pic;
-    FILE *file;
+    stream_t *p_stream = NULL;
     int i_size;
 
-    file = fopen( psz_url, "rb" );
-    if( !file )
+    p_stream = stream_UrlNew( p_image->p_parent, psz_url );
+
+    if( !p_stream )
     {
-        msg_Dbg( p_image->p_parent, "could not open file %s for reading",
+        msg_Dbg( p_image->p_parent, "could not open %s for reading",
                  psz_url );
         return NULL;
     }
 
-    fseek( file, 0, SEEK_END );
-    i_size = ftell( file );
-    fseek( file, 0, SEEK_SET );
+    i_size = stream_Size( p_stream );
 
     p_block = block_New( p_image->p_parent, i_size );
-    fread( p_block->p_buffer, sizeof(char), i_size, file );
-    fclose( file );
+
+    stream_Read( p_stream, p_block->p_buffer, i_size );
+    stream_Delete( p_stream );
 
     if( !p_fmt_in->i_chroma )
     {
@@ -255,7 +272,7 @@ static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
         p_image->p_enc->fmt_in.video.i_width != p_fmt_in->i_width ||
         p_image->p_enc->fmt_in.video.i_height != p_fmt_in->i_height )
     {
-        picture_t *p_pif;
+        picture_t *p_tmp_pic;
 
         if( p_image->p_filter )
         if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
@@ -276,7 +293,7 @@ static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
 
             p_image->p_filter =
                 CreateFilter( p_image->p_parent, &fmt_in,
-                              &p_image->p_enc->fmt_in.video );
+                              &p_image->p_enc->fmt_in.video, NULL );
 
             if( !p_image->p_filter )
             {
@@ -294,12 +311,18 @@ static block_t *ImageWrite( image_handler_t *p_image, picture_t *p_pic,
 
         pf_release = p_pic->pf_release;
         p_pic->pf_release = PicRelease; /* Small hack */
-        p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
+        p_tmp_pic =
+            p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
         p_pic->pf_release = pf_release;
-        p_pic = p_pif;
-    }
 
-    p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_pic );
+        p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_tmp_pic );
+
+        p_image->p_filter->pf_vout_buffer_del( p_image->p_filter, p_tmp_pic );
+    }
+    else
+    {
+        p_block = p_image->p_enc->pf_encode_video( p_image->p_enc, p_pic );
+    }
 
     if( !p_block )
     {
@@ -323,7 +346,7 @@ static int ImageWriteUrl( image_handler_t *p_image, picture_t *p_pic,
         p_fmt_out->i_chroma = Ext2Fourcc( psz_url );
     }
 
-    file = fopen( psz_url, "wb" );
+    file = utf8_fopen( psz_url, "wb" );
     if( !file )
     {
         msg_Dbg( p_image->p_parent, "could not open file %s for writing",
@@ -356,9 +379,28 @@ static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
     void (*pf_release)( picture_t * );
     picture_t *p_pif;
 
+    if( !p_fmt_out->i_width && !p_fmt_out->i_height &&
+        p_fmt_out->i_sar_num && p_fmt_out->i_sar_den &&
+        p_fmt_out->i_sar_num * p_fmt_in->i_sar_den !=
+        p_fmt_out->i_sar_den * p_fmt_in->i_sar_num )
+    {
+        p_fmt_out->i_width =
+            p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
+            p_fmt_in->i_width / p_fmt_in->i_sar_den / p_fmt_out->i_sar_num;
+        p_fmt_out->i_visible_width =
+            p_fmt_in->i_sar_num * (int64_t)p_fmt_out->i_sar_den *
+            p_fmt_in->i_visible_width / p_fmt_in->i_sar_den /
+            p_fmt_out->i_sar_num;
+    }
+
     if( !p_fmt_out->i_chroma ) p_fmt_out->i_chroma = p_fmt_in->i_chroma;
-    if( !p_fmt_out->i_width ) p_fmt_out->i_width = p_fmt_in->i_width;
-    if( !p_fmt_out->i_height ) p_fmt_out->i_height = p_fmt_in->i_height;
+    if( !p_fmt_out->i_width )
+        p_fmt_out->i_width = p_fmt_out->i_visible_width = p_fmt_in->i_width;
+    if( !p_fmt_out->i_height )
+        p_fmt_out->i_height = p_fmt_out->i_visible_height = p_fmt_in->i_height;
+    if( !p_fmt_out->i_sar_num ) p_fmt_out->i_sar_num = p_fmt_in->i_sar_num;
+    if( !p_fmt_out->i_sar_den ) p_fmt_out->i_sar_den = p_fmt_in->i_sar_den;
+    if( !p_fmt_out->i_aspect ) p_fmt_out->i_aspect = p_fmt_in->i_aspect;
 
     if( p_image->p_filter )
     if( p_image->p_filter->fmt_in.video.i_chroma != p_fmt_in->i_chroma ||
@@ -377,7 +419,7 @@ static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
         fmt_in.video = *p_fmt_in;
 
         p_image->p_filter =
-            CreateFilter( p_image->p_parent, &fmt_in, p_fmt_out );
+            CreateFilter( p_image->p_parent, &fmt_in, p_fmt_out, NULL );
 
         if( !p_image->p_filter )
         {
@@ -408,6 +450,47 @@ static picture_t *ImageConvert( image_handler_t *p_image, picture_t *p_pic,
     return p_pif;
 }
 
+/**
+ * Filter an image with a psz_module filter
+ *
+ */
+
+static picture_t *ImageFilter( image_handler_t *p_image, picture_t *p_pic,
+                               video_format_t *p_fmt, const char *psz_module )
+{
+    void (*pf_release)( picture_t * );
+    picture_t *p_pif;
+
+    /* Start a filter */
+    if( !p_image->p_filter )
+    {
+        es_format_t fmt;
+        es_format_Init( &fmt, VIDEO_ES, p_fmt->i_chroma );
+        fmt.video = *p_fmt;
+
+        p_image->p_filter =
+            CreateFilter( p_image->p_parent, &fmt, &fmt.video, psz_module );
+
+        if( !p_image->p_filter )
+        {
+            return NULL;
+        }
+    }
+    else
+    {
+        /* Filters should handle on-the-fly size changes */
+        p_image->p_filter->fmt_in.video = *p_fmt;
+        p_image->p_filter->fmt_out.video = *p_fmt;
+    }
+
+    pf_release = p_pic->pf_release;
+    p_pic->pf_release = PicRelease; /* Small hack */
+    p_pif = p_image->p_filter->pf_video_filter( p_image->p_filter, p_pic );
+    p_pic->pf_release = pf_release;
+
+    return p_pif;
+}
+
 /**
  * Misc functions
  *
@@ -427,6 +510,16 @@ static struct
     { VLC_FOURCC('p','g','m','y'), "pgmyuv" },
     { VLC_FOURCC('p','b','m',' '), "pbm" },
     { VLC_FOURCC('p','a','m',' '), "pam" },
+    { VLC_FOURCC('t','g','a',' '), "tga" },
+    { VLC_FOURCC('b','m','p',' '), "bmp" },
+    { VLC_FOURCC('p','n','m',' '), "pnm" },
+    { VLC_FOURCC('x','p','m',' '), "xpm" },
+    { VLC_FOURCC('x','c','f',' '), "xcf" },
+    { VLC_FOURCC('p','c','x',' '), "pcx" },
+    { VLC_FOURCC('g','i','f',' '), "gif" },
+    { VLC_FOURCC('t','i','f','f'), "tif" },
+    { VLC_FOURCC('t','i','f','f'), "tiff" },
+    { VLC_FOURCC('l','b','m',' '), "lbm" },
     { 0, NULL }
 };
 
@@ -452,6 +545,7 @@ static vlc_fourcc_t Ext2Fourcc( const char *psz_name )
     return 0;
 }
 
+/*
 static const char *Fourcc2Ext( vlc_fourcc_t i_codec )
 {
     int i;
@@ -463,6 +557,7 @@ static const char *Fourcc2Ext( vlc_fourcc_t i_codec )
 
     return NULL;
 }
+*/
 
 static void video_release_buffer( picture_t *p_pic )
 {
@@ -580,14 +675,29 @@ static encoder_t *CreateEncoder( vlc_object_t *p_this, video_format_t *fmt_in,
     {
         p_enc->fmt_in.video.i_width = fmt_out->i_width;
         p_enc->fmt_in.video.i_height = fmt_out->i_height;
+
+        if( fmt_out->i_visible_width > 0 &&
+            fmt_out->i_visible_height > 0 )
+        {
+            p_enc->fmt_in.video.i_visible_width = fmt_out->i_visible_width;
+            p_enc->fmt_in.video.i_visible_height = fmt_out->i_visible_height;
+        }
+        else
+        {
+            p_enc->fmt_in.video.i_visible_width = fmt_out->i_width;
+            p_enc->fmt_in.video.i_visible_height = fmt_out->i_height;
+        }
     }
     else if( fmt_out->i_sar_num && fmt_out->i_sar_den &&
-            fmt_out->i_sar_num * fmt_in->i_sar_den !=
+             fmt_out->i_sar_num * fmt_in->i_sar_den !=
              fmt_out->i_sar_den * fmt_in->i_sar_num )
     {
         p_enc->fmt_in.video.i_width =
-           fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den * fmt_in->i_width /
+            fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den * fmt_in->i_width /
             fmt_in->i_sar_den / fmt_out->i_sar_num;
+        p_enc->fmt_in.video.i_visible_width =
+            fmt_in->i_sar_num * (int64_t)fmt_out->i_sar_den *
+            fmt_in->i_visible_width / fmt_in->i_sar_den / fmt_out->i_sar_num;
     }
 
     p_enc->fmt_in.video.i_frame_rate = 25;
@@ -629,7 +739,8 @@ static void DeleteEncoder( encoder_t * p_enc )
 }
 
 static filter_t *CreateFilter( vlc_object_t *p_this, es_format_t *p_fmt_in,
-                               video_format_t *p_fmt_out )
+                               video_format_t *p_fmt_out,
+                               const char *psz_module )
 {
     filter_t *p_filter;
 
@@ -645,7 +756,8 @@ static filter_t *CreateFilter( vlc_object_t *p_this, es_format_t *p_fmt_in,
     p_filter->fmt_out = *p_fmt_in;
     p_filter->fmt_out.i_codec = p_fmt_out->i_chroma;
     p_filter->fmt_out.video = *p_fmt_out;
-    p_filter->p_module = module_Need( p_filter, "video filter2", 0, 0 );
+    p_filter->p_module = module_Need( p_filter, "video filter2", psz_module,
+                                      0 );
 
     if( !p_filter->p_module )
     {