2 * vo_png.c, Portable Network Graphics Renderer for MPlayer
4 * Copyright 2001 by Felix Buenemann <atmosfear@users.sourceforge.net>
6 * Uses libpng (which uses zlib), so see according licenses.
21 #include "video_out.h"
22 #include "video_out_internal.h"
23 #include "subopt-helper.h"
25 static vo_info_t info
=
29 "Felix Buenemann <atmosfear@users.sourceforge.net>",
35 int z_compression
= Z_NO_COMPRESSION
;
36 static int framenum
= 0;
42 enum {OK
,ERROR
} status
;
46 config(uint32_t width
, uint32_t height
, uint32_t d_width
, uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
49 if(z_compression
== 0) {
50 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_PNG_Warning1
);
51 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_PNG_Warning2
);
52 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_PNG_Warning3
);
55 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
56 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Compression level %i\n", z_compression
); }
62 struct pngdata
create_png (char * fname
, int image_width
, int image_height
, int swapped
)
66 /*png_structp png_ptr = png_create_write_struct
67 (PNG_LIBPNG_VER_STRING, (png_voidp)user_error_ptr,
68 user_error_fn, user_warning_fn);*/
69 //png_byte *row_pointers[image_height];
70 png
.png_ptr
= png_create_write_struct
71 (PNG_LIBPNG_VER_STRING
, NULL
,
73 png
.info_ptr
= png_create_info_struct(png
.png_ptr
);
76 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
77 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Failed to init png pointer\n"); }
83 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
84 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Failed to init png infopointer\n"); }
85 png_destroy_write_struct(&png
.png_ptr
,
91 if (setjmp(png
.png_ptr
->jmpbuf
)) {
92 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
93 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Internal error!\n"); }
94 png_destroy_write_struct(&png
.png_ptr
, &png
.info_ptr
);
100 png
.fp
= fopen (fname
, "wb");
101 if (png
.fp
== NULL
) {
102 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_PNG_ErrorOpeningForWriting
, strerror(errno
));
107 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
108 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Init IO\n"); }
109 png_init_io(png
.png_ptr
, png
.fp
);
111 /* set the zlib compression level */
112 png_set_compression_level(png
.png_ptr
, z_compression
);
115 /*png_set_IHDR(png_ptr, info_ptr, width, height,
116 bit_depth, color_type, interlace_type,
117 compression_type, filter_type)*/
118 png_set_IHDR(png
.png_ptr
, png
.info_ptr
, image_width
, image_height
,
119 8, PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
,
120 PNG_COMPRESSION_TYPE_DEFAULT
, PNG_FILTER_TYPE_DEFAULT
);
122 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
123 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Write Info\n"); }
124 png_write_info(png
.png_ptr
, png
.info_ptr
);
127 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
128 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Set BGR Conversion\n"); }
129 png_set_bgr(png
.png_ptr
);
136 static uint8_t destroy_png(struct pngdata png
) {
138 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
139 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Write End\n"); }
140 png_write_end(png
.png_ptr
, png
.info_ptr
);
142 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
143 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Destroy Write Struct\n"); }
144 png_destroy_write_struct(&png
.png_ptr
, &png
.info_ptr
);
151 static uint32_t draw_image(mp_image_t
* mpi
){
155 png_byte
*row_pointers
[mpi
->h
];
157 // if -dr or -slices then do nothing:
158 if(mpi
->flags
&(MP_IMGFLAG_DIRECT
|MP_IMGFLAG_DRAW_CALLBACK
)) return VO_TRUE
;
160 snprintf (buf
, 100, "%08d.png", ++framenum
);
162 png
= create_png(buf
, mpi
->w
, mpi
->h
, mpi
->flags
&MP_IMGFLAG_SWAPPED
);
165 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_PNG_ErrorInCreatePng
);
169 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
170 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Creating Row Pointers\n"); }
171 for ( k
= 0; k
< mpi
->h
; k
++ )
172 row_pointers
[k
] = mpi
->planes
[0]+mpi
->stride
[0]*k
;
174 //png_write_flush(png.png_ptr);
175 //png_set_flush(png.png_ptr, nrows);
177 if( mp_msg_test(MSGT_VO
,MSGL_DBG2
) ) {
178 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Writing Image Data\n"); }
179 png_write_image(png
.png_ptr
, row_pointers
);
186 static void draw_osd(void){}
188 static void flip_page (void){}
190 static int draw_frame(uint8_t * src
[])
195 static int draw_slice( uint8_t *src
[],int stride
[],int w
,int h
,int x
,int y
)
201 query_format(uint32_t format
)
206 return VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_ACCEPT_STRIDE
;
211 static void uninit(void){}
213 static void check_events(void){}
215 static int int_zero_to_nine(int *sh
)
217 if ( (*sh
< 0) || (*sh
> 9) )
222 static opt_t subopts
[] = {
223 {"z", OPT_ARG_INT
, &z_compression
, (opt_test_f
)int_zero_to_nine
},
227 static int preinit(const char *arg
)
230 if (subopt_parse(arg
, subopts
) != 0) {
236 static int control(uint32_t request
, void *data
, ...)
239 case VOCTRL_DRAW_IMAGE
:
240 return draw_image(data
);
241 case VOCTRL_QUERY_FORMAT
:
242 return query_format(*((uint32_t*)data
));