]> git.sesse.net Git - vlc/commitdiff
* modules/codec/png.c: PNG decoder using libpng.
authorGildas Bazin <gbazin@videolan.org>
Thu, 16 Dec 2004 17:44:38 +0000 (17:44 +0000)
committerGildas Bazin <gbazin@videolan.org>
Thu, 16 Dec 2004 17:44:38 +0000 (17:44 +0000)
configure.ac
modules/codec/Modules.am
modules/codec/png.c [new file with mode: 0644]

index c4bbd4530bf74a2086f7917e86b4238dc51a5ebf..851a065b8554be432327550ae83de823c83b691b 100644 (file)
@@ -955,7 +955,7 @@ VLC_ADD_PLUGINS([trivial_mixer spdif_mixer float32_mixer])
 VLC_ADD_PLUGINS([aout_file equalizer])
 VLC_ADD_PLUGINS([i420_rgb i420_yuy2 i422_yuy2 i420_ymga])
 VLC_ADD_PLUGINS([id3 playlist export sgimb m3u xtag])
-VLC_ADD_PLUGINS([rawvideo blend scale time marq])
+VLC_ADD_PLUGINS([rawvideo blend scale time marq logo])
 VLC_ADD_PLUGINS([wav araw subtitle vobsub adpcm a52sys dtssys au])
 VLC_ADD_PLUGINS([access_file access_udp access_tcp access_http ipv4 access_mms])
 VLC_ADD_PLUGINS([access_ftp access_directory sap http])
@@ -2443,8 +2443,7 @@ dnl  dirac decoder plugin
 dnl
 AC_ARG_ENABLE(dirac,
 [  --enable-dirac         experimental dirac codec (default disabled)])
-if test "${enable_dirac}" = "yes"
-then
+if test "${enable_dirac}" = "yes"; then
   AC_CHECK_HEADERS(libdirac_decoder/dirac_parser.h, [
     AC_CHECK_LIB(dirac_decoder, dirac_decoder_init, [
       VLC_ADD_PLUGINS([dirac])
@@ -2454,6 +2453,25 @@ then
   ])
 fi
 
+dnl
+dnl  PNG decoder module
+dnl
+AC_ARG_ENABLE(png,
+  [  --enable-png            PNG support (default enabled)])
+if test "${enable_png}" != "no"; then
+AC_CHECK_HEADERS(png.h, [
+  LDFLAGS="${LDFLAGS_save} -lz"
+  AC_CHECK_LIB(png, png_set_rows, [
+    VLC_ADD_LDFLAGS([png],[-lpng -lz])
+    VLC_ADD_PLUGINS([png])
+    VLC_ADD_LDFLAGS([svcdsub],[-lpng -lz])
+    VLC_ADD_LDFLAGS([cvdsub],[-lpng -lz -lm])
+    AC_DEFINE(HAVE_LIBPNG, [], [Define if you have the PNG library: libpng])],
+    [],[-lz])
+  LDFLAGS="${LDFLAGS_save}"
+  ])
+fi
+
 dnl
 dnl H264 encoder plugin (using libx264)
 dnl
@@ -2517,25 +2535,6 @@ then
 fi
 
 
-dnl
-dnl  Video Filters
-dnl
-
-dnl
-dnl   png
-dnl
-AC_CHECK_HEADERS(png.h, [
-  LDFLAGS="${LDFLAGS_save} -lz"
-  AC_CHECK_LIB(png, png_set_rows, [
-    VLC_ADD_LDFLAGS([logo],[-lpng -lz])
-    VLC_ADD_PLUGINS([logo])
-    VLC_ADD_LDFLAGS([svcdsub],[-lpng -lz])
-    VLC_ADD_LDFLAGS([cvdsub],[-lpng -lz -lm])
-    AC_DEFINE(HAVE_LIBPNG, [], [Define if you have the PNG library: libpng])],
-    [],[-lz])
-  ])
-  LDFLAGS="${LDFLAGS_save}"
-
 dnl
 dnl  Video plugins
 dnl
@@ -3257,7 +3256,7 @@ if test "${enable_skins2}" = "yes" || (test "${SYS}" != "darwin" && test "${SYS}
   dnl freetype
   if test "${FREETYPE_CONFIG}" != "no"; then
     VLC_ADD_CPPFLAGS([skins2],[`${FREETYPE_CONFIG} --cflags`])
-    VLC_ADD_LDFLAGS([skins2],[`${FREETYPE_CONFIG} --libs` -lpng])
+    VLC_ADD_LDFLAGS([skins2],[`${FREETYPE_CONFIG} --libs`])
   else
     skins2_missing_lib="yes"
     if test "${enable_skins2}" = "yes"; then
index 2fa4ce3151c57d334148050736e1dd1d549d08ee..5ada1330eff437d0e64bcdabab9737a41ac6a3ff 100644 (file)
@@ -22,3 +22,4 @@ SOURCES_mash = mash.cpp
 SOURCES_x264 = x264.c
 SOURCES_toolame = toolame.c
 SOURCES_dirac = dirac.c
+SOURCES_png = png.c
diff --git a/modules/codec/png.c b/modules/codec/png.c
new file mode 100644 (file)
index 0000000..68397fa
--- /dev/null
@@ -0,0 +1,222 @@
+/*****************************************************************************
+ * png.c: png decoder module making use of libpng.
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id$
+ *
+ * Authors: Gildas Bazin <gbazin@videolan.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * 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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <vlc/vlc.h>
+#include <vlc/decoder.h>
+
+#include <png.h>
+
+/*****************************************************************************
+ * decoder_sys_t : png decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+    vlc_bool_t b_error;
+};
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+static int  OpenDecoder   ( vlc_object_t * );
+static void CloseDecoder  ( vlc_object_t * );
+
+static picture_t *DecodeBlock  ( decoder_t *, block_t ** );
+
+/*****************************************************************************
+ * Module descriptor
+ *****************************************************************************/
+vlc_module_begin();
+    set_category( CAT_INPUT );
+    set_subcategory( SUBCAT_INPUT_VCODEC );
+    set_description( _("PNG video decoder") );
+    set_capability( "decoder", 1000 );
+    set_callbacks( OpenDecoder, CloseDecoder );
+    add_shortcut( "png" );
+vlc_module_end();
+
+/*****************************************************************************
+ * OpenDecoder: probe the decoder and return score
+ *****************************************************************************/
+static int OpenDecoder( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t*)p_this;
+    decoder_sys_t *p_sys;
+
+    if( p_dec->fmt_in.i_codec != VLC_FOURCC('p','n','g',' ') )
+    {
+        return VLC_EGENERIC;
+    }
+
+    /* Allocate the memory needed to store the decoder's structure */
+    if( ( p_dec->p_sys = p_sys =
+          (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+    {
+        msg_Err( p_dec, "out of memory" );
+        return VLC_EGENERIC;
+    }
+
+    /* Set output properties */
+    p_dec->fmt_out.i_cat = VIDEO_ES;
+    p_dec->fmt_out.i_codec = VLC_FOURCC('R','V','3','2');
+
+    /* Set callbacks */
+    p_dec->pf_decode_video = DecodeBlock;
+
+    return VLC_SUCCESS;
+}
+
+static void user_read( png_structp p_png, png_bytep data, png_size_t i_length )
+{
+    block_t *p_block = (block_t *)png_get_io_ptr( p_png );
+    png_size_t i_read = __MIN( p_block->i_buffer, (int)i_length );
+    memcpy( data, p_block->p_buffer, i_length );
+    p_block->p_buffer += i_length;
+    p_block->i_buffer -= i_length;
+
+    if( i_length != i_read ) png_error( p_png, "not enough data" );
+}
+
+static void user_error( png_structp p_png, png_const_charp error_msg )
+{
+    decoder_t *p_dec = (decoder_t *)png_get_error_ptr( p_png );
+    p_dec->p_sys->b_error = VLC_TRUE;
+    msg_Err( p_dec, error_msg );
+}
+
+static void user_warning( png_structp p_png, png_const_charp warning_msg )
+{
+    decoder_t *p_dec = (decoder_t *)png_get_error_ptr( p_png );
+    msg_Warn( p_dec, warning_msg );
+}
+
+/****************************************************************************
+ * DecodeBlock: the whole thing
+ ****************************************************************************
+ * This function must be fed with a complete compressed frame.
+ ****************************************************************************/
+static picture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
+{
+    decoder_sys_t *p_sys = p_dec->p_sys;
+    block_t *p_block;
+    picture_t *p_pic = 0;
+
+    png_uint_32 i_width, i_height;
+    int i_color_type, i_interlace_type, i_compression_type, i_filter_type;
+    int i_bit_depth, i;
+
+    png_structp p_png;
+    png_infop p_info, p_end_info;
+    png_bytep *p_row_pointers = NULL;
+
+    if( !pp_block || !*pp_block ) return NULL;
+
+    p_block = *pp_block;
+    p_sys->b_error = VLC_FALSE;
+
+    p_png = png_create_read_struct( PNG_LIBPNG_VER_STRING, 0, 0, 0 );
+    p_info = png_create_info_struct( p_png );
+    p_end_info = png_create_info_struct( p_png );
+    png_set_read_fn( p_png, (void *)p_block, user_read );
+    png_set_error_fn( p_png, (void *)p_dec, user_error, user_warning );
+
+    png_read_info( p_png, p_info );
+    if( p_sys->b_error ) goto error;
+
+    png_get_IHDR( p_png, p_info, &i_width, &i_height,
+                  &i_bit_depth, &i_color_type, &i_interlace_type,
+                  &i_compression_type, &i_filter_type);
+    if( p_sys->b_error ) goto error;
+
+    /* Set output properties */
+    p_dec->fmt_out.i_codec = VLC_FOURCC('R','V','3','2');
+    p_dec->fmt_out.video.i_width = i_width;
+    p_dec->fmt_out.video.i_height = i_height;
+    p_dec->fmt_out.video.i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
+
+    if( i_color_type == PNG_COLOR_TYPE_PALETTE )
+        png_set_palette_to_rgb( p_png );
+
+    if( i_color_type == PNG_COLOR_TYPE_GRAY ||
+        i_color_type == PNG_COLOR_TYPE_GRAY_ALPHA )
+          png_set_gray_to_rgb( p_png );
+
+    /* Strip to 8 bits per channel */
+    if( i_bit_depth == 16 ) png_set_strip_16( p_png );
+
+    if( png_get_valid( p_png, p_info, PNG_INFO_tRNS ) )
+    {
+        png_set_tRNS_to_alpha( p_png );
+    }
+    else if( !(i_color_type & PNG_COLOR_MASK_ALPHA) )
+    {
+        p_dec->fmt_out.i_codec = VLC_FOURCC('R','V','2','4');
+    }
+    if( i_color_type & PNG_COLOR_MASK_COLOR &&
+        p_dec->fmt_out.i_codec != VLC_FOURCC('R','V','2','4') )
+    {
+        /* Invert colors */
+        png_set_bgr( p_png );
+    }
+
+    /* Get a new picture */
+    p_pic = p_dec->pf_vout_buffer_new( p_dec );
+    if( !p_pic ) goto error;
+
+    /* Decode picture */
+    p_row_pointers = malloc( sizeof(png_bytep) * i_height );
+    for( i = 0; i < (int)i_height; i++ )
+        p_row_pointers[i] = p_pic->p->p_pixels + p_pic->p->i_pitch * i;
+
+    png_read_image( p_png, p_row_pointers );
+    if( p_sys->b_error ) goto error;
+    png_read_end( p_png, p_end_info );
+    if( p_sys->b_error ) goto error;
+
+    png_destroy_read_struct( &p_png, &p_info, &p_end_info );
+    free( p_row_pointers );
+
+    block_Release( p_block ); *pp_block = NULL;
+    return p_pic;
+
+ error:
+
+    if( p_row_pointers ) free( p_row_pointers );
+    png_destroy_read_struct( &p_png, &p_info, &p_end_info );
+    block_Release( p_block ); *pp_block = NULL;
+    return NULL;
+}
+
+/*****************************************************************************
+ * CloseDecoder: png decoder destruction
+ *****************************************************************************/
+static void CloseDecoder( vlc_object_t *p_this )
+{
+    decoder_t *p_dec = (decoder_t *)p_this;
+    decoder_sys_t *p_sys = p_dec->p_sys;
+
+    free( p_sys );
+}