2 * Portable Network Graphics renderer
4 * Copyright 2001 by Felix Buenemann <atmosfear@users.sourceforge.net>
6 * Uses libpng (which uses zlib), so see according licenses.
8 * This file is part of MPlayer.
10 * MPlayer is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * MPlayer is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License along
21 * with MPlayer; if not, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
36 #include "video_out.h"
37 #include "video_out_internal.h"
38 #include "subopt-helper.h"
40 static const vo_info_t info
=
44 "Felix Buenemann <atmosfear@users.sourceforge.net>",
48 const LIBVO_EXTERN (png
)
50 static int z_compression
= Z_NO_COMPRESSION
;
51 static int framenum
= 0;
58 enum {OK
,ERROR
} status
;
62 config(uint32_t width
, uint32_t height
, uint32_t d_width
, uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
65 if(z_compression
== 0) {
66 mp_tmsg(MSGT_VO
,MSGL_INFO
, "[VO_PNG] Warning: compression level set to 0, compression disabled!\n");
67 mp_tmsg(MSGT_VO
,MSGL_INFO
, "[VO_PNG] Info: Use -vo png:z=<n> to set compression level from 0 to 9.\n");
68 mp_tmsg(MSGT_VO
,MSGL_INFO
, "[VO_PNG] Info: (0 = no compression, 1 = fastest, lowest - 9 best, slowest compression)\n");
71 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Compression level %i\n", z_compression
);
77 static struct pngdata
create_png (char * fname
, int image_width
, int image_height
, int swapped
)
81 /*png_structp png_ptr = png_create_write_struct
82 (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
83 user_error_fn, user_warning_fn);*/
84 //png_byte *row_pointers[image_height];
85 png
.png_ptr
= png_create_write_struct
86 (PNG_LIBPNG_VER_STRING
, NULL
,
88 png
.info_ptr
= png_create_info_struct(png
.png_ptr
);
91 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Failed to init png pointer\n");
97 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Failed to init png infopointer\n");
98 png_destroy_write_struct(&png
.png_ptr
,
104 if (setjmp(png
.png_ptr
->jmpbuf
)) {
105 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Internal error!\n");
106 png_destroy_write_struct(&png
.png_ptr
, &png
.info_ptr
);
112 png
.fp
= fopen (fname
, "wb");
113 if (png
.fp
== NULL
) {
114 mp_tmsg(MSGT_VO
,MSGL_WARN
, "\n[VO_PNG] Error opening '%s' for writing!\n", strerror(errno
));
119 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Init IO\n");
120 png_init_io(png
.png_ptr
, png
.fp
);
122 /* set the zlib compression level */
123 png_set_compression_level(png
.png_ptr
, z_compression
);
126 /*png_set_IHDR(png_ptr, info_ptr, width, height,
127 bit_depth, color_type, interlace_type,
128 compression_type, filter_type)*/
129 png_set_IHDR(png
.png_ptr
, png
.info_ptr
, image_width
, image_height
,
130 8, use_alpha
? PNG_COLOR_TYPE_RGBA
: PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
,
131 PNG_COMPRESSION_TYPE_DEFAULT
, PNG_FILTER_TYPE_DEFAULT
);
133 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Write Info\n");
134 png_write_info(png
.png_ptr
, png
.info_ptr
);
137 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Set BGR Conversion\n");
138 png_set_bgr(png
.png_ptr
);
145 static uint8_t destroy_png(struct pngdata png
) {
147 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Write End\n");
148 png_write_end(png
.png_ptr
, png
.info_ptr
);
150 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Destroy Write Struct\n");
151 png_destroy_write_struct(&png
.png_ptr
, &png
.info_ptr
);
158 static uint32_t draw_image(mp_image_t
* mpi
){
162 png_byte
*row_pointers
[mpi
->h
];
164 // if -dr or -slices then do nothing:
165 if(mpi
->flags
&(MP_IMGFLAG_DIRECT
|MP_IMGFLAG_DRAW_CALLBACK
)) return VO_TRUE
;
167 snprintf (buf
, 100, "%08d.png", ++framenum
);
169 png
= create_png(buf
, mpi
->w
, mpi
->h
, IMGFMT_IS_BGR(mpi
->imgfmt
));
172 mp_tmsg(MSGT_VO
,MSGL_WARN
, "[VO_PNG] Error in create_png.\n");
176 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Creating Row Pointers\n");
177 for ( k
= 0; k
< mpi
->h
; k
++ )
178 row_pointers
[k
] = mpi
->planes
[0]+mpi
->stride
[0]*k
;
180 //png_write_flush(png.png_ptr);
181 //png_set_flush(png.png_ptr, nrows);
183 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
184 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Writing Image Data\n"); }
185 png_write_image(png
.png_ptr
, row_pointers
);
192 static void draw_osd(void){}
194 static void flip_page (void){}
196 static int draw_frame(uint8_t * src
[])
201 static int draw_slice( uint8_t *src
[],int stride
[],int w
,int h
,int x
,int y
)
207 query_format(uint32_t format
)
209 const int supported_flags
= VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_ACCEPT_STRIDE
;
213 return use_alpha
? 0 : supported_flags
;
216 return use_alpha
? supported_flags
: 0;
221 static void uninit(void){}
223 static void check_events(void){}
225 static int int_zero_to_nine(int *sh
)
227 if ( (*sh
< 0) || (*sh
> 9) )
232 static const opt_t subopts
[] = {
233 {"alpha", OPT_ARG_BOOL
, &use_alpha
, NULL
},
234 {"z", OPT_ARG_INT
, &z_compression
, (opt_test_f
)int_zero_to_nine
},
238 static int preinit(const char *arg
)
242 if (subopt_parse(arg
, subopts
) != 0) {
248 static int control(uint32_t request
, void *data
)
251 case VOCTRL_DRAW_IMAGE
:
252 return draw_image(data
);
253 case VOCTRL_QUERY_FORMAT
:
254 return query_format(*((uint32_t*)data
));