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.
30 #include <sys/types.h>
34 #include "fmt-conversion.h"
38 #include "video_out.h"
39 #include "video_out_internal.h"
40 #include "subopt-helper.h"
41 #include "libavcodec/avcodec.h"
45 static const vo_info_t info
=
49 "Felix Buenemann <atmosfear@users.sourceforge.net>",
53 const LIBVO_EXTERN (png
)
55 static int z_compression
;
56 static char *png_outdir
;
59 static AVCodecContext
*avctx
;
60 static uint8_t *outbuffer
;
63 static void png_mkdir(char *buf
, int verbose
) {
67 if ( mkdir(buf
, 0755) < 0 ) {
69 if ( mkdir(buf
) < 0 ) {
71 switch (errno
) { /* use switch in case other errors need to be caught
72 and handled in the future */
74 if ( stat(buf
, &stat_p
) < 0 ) {
75 mp_msg(MSGT_VO
, MSGL_ERR
, "%s: %s: %s\n", info
.short_name
,
76 MSGTR_VO_GenericError
, strerror(errno
) );
77 mp_msg(MSGT_VO
, MSGL_ERR
, "%s: %s %s\n", info
.short_name
,
78 MSGTR_VO_UnableToAccess
,buf
);
79 exit_player(EXIT_ERROR
);
81 if ( !S_ISDIR(stat_p
.st_mode
) ) {
82 mp_msg(MSGT_VO
, MSGL_ERR
, "%s: %s %s\n", info
.short_name
,
83 buf
, MSGTR_VO_ExistsButNoDirectory
);
84 exit_player(EXIT_ERROR
);
86 if ( !(stat_p
.st_mode
& S_IWUSR
) ) {
87 mp_msg(MSGT_VO
, MSGL_ERR
, "%s: %s - %s\n", info
.short_name
,
88 buf
, MSGTR_VO_DirExistsButNotWritable
);
89 exit_player(EXIT_ERROR
);
92 mp_msg(MSGT_VO
, MSGL_INFO
, "%s: %s - %s\n", info
.short_name
,
93 buf
, MSGTR_VO_DirExistsAndIsWritable
);
97 mp_msg(MSGT_VO
, MSGL_ERR
, "%s: %s: %s\n", info
.short_name
,
98 MSGTR_VO_GenericError
, strerror(errno
) );
99 mp_msg(MSGT_VO
, MSGL_ERR
, "%s: %s - %s\n", info
.short_name
,
100 buf
, MSGTR_VO_CantCreateDirectory
);
101 exit_player(EXIT_ERROR
);
103 } else if ( verbose
) {
104 mp_msg(MSGT_VO
, MSGL_INFO
, "%s: %s - %s\n", info
.short_name
,
105 buf
, MSGTR_VO_DirectoryCreateSuccess
);
110 config(uint32_t width
, uint32_t height
, uint32_t d_width
, uint32_t d_height
, uint32_t flags
, char *title
, uint32_t format
)
114 if(z_compression
== 0) {
115 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_PNG_Warning1
);
116 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_PNG_Warning2
);
117 mp_msg(MSGT_VO
,MSGL_INFO
, MSGTR_LIBVO_PNG_Warning3
);
120 snprintf(buf
, BUFLENGTH
, "%s", png_outdir
);
122 mp_msg(MSGT_VO
,MSGL_DBG2
, "PNG Compression level %i\n", z_compression
);
128 static uint32_t draw_image(mp_image_t
* mpi
){
135 // if -dr or -slices then do nothing:
136 if(mpi
->flags
&(MP_IMGFLAG_DIRECT
|MP_IMGFLAG_DRAW_CALLBACK
)) return VO_TRUE
;
138 snprintf (buf
, 100, "%s/%08d.png", png_outdir
, ++framenum
);
139 outfile
= fopen(buf
, "wb");
141 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_PNG_ErrorOpeningForWriting
, strerror(errno
));
145 avctx
->width
= mpi
->w
;
146 avctx
->height
= mpi
->h
;
147 avctx
->pix_fmt
= imgfmt2pixfmt(mpi
->imgfmt
);
148 pic
.data
[0] = mpi
->planes
[0];
149 pic
.linesize
[0] = mpi
->stride
[0];
150 buffersize
= mpi
->w
* mpi
->h
* 8;
151 if (outbuffer_size
< buffersize
) {
152 av_freep(&outbuffer
);
153 outbuffer
= av_malloc(buffersize
);
154 outbuffer_size
= buffersize
;
156 res
= avcodec_encode_video(avctx
, outbuffer
, outbuffer_size
, &pic
);
159 mp_msg(MSGT_VO
,MSGL_WARN
, MSGTR_LIBVO_PNG_ErrorInCreatePng
);
164 fwrite(outbuffer
, res
, 1, outfile
);
170 static void draw_osd(void){}
172 static void flip_page (void){}
174 static int draw_frame(uint8_t * src
[])
179 static int draw_slice( uint8_t *src
[],int stride
[],int w
,int h
,int x
,int y
)
185 query_format(uint32_t format
)
187 const int supported_flags
= VFCAP_CSP_SUPPORTED
|VFCAP_CSP_SUPPORTED_BY_HW
|VFCAP_ACCEPT_STRIDE
;
190 return use_alpha
? 0 : supported_flags
;
192 return use_alpha
? supported_flags
: 0;
197 static void uninit(void){
198 avcodec_close(avctx
);
200 av_freep(&outbuffer
);
208 static void check_events(void){}
210 static int int_zero_to_nine(void *value
)
213 return *sh
>= 0 && *sh
<= 9;
216 static const opt_t subopts
[] = {
217 {"alpha", OPT_ARG_BOOL
, &use_alpha
, NULL
},
218 {"z", OPT_ARG_INT
, &z_compression
, int_zero_to_nine
},
219 {"outdir", OPT_ARG_MSTRZ
, &png_outdir
, NULL
},
223 static int preinit(const char *arg
)
226 png_outdir
= strdup(".");
228 if (subopt_parse(arg
, subopts
) != 0) {
231 avcodec_register_all();
232 avctx
= avcodec_alloc_context();
233 if (avcodec_open(avctx
, avcodec_find_encoder(CODEC_ID_PNG
)) < 0) {
237 avctx
->compression_level
= z_compression
;
241 static int control(uint32_t request
, void *data
, ...)
244 case VOCTRL_DRAW_IMAGE
:
245 return draw_image(data
);
246 case VOCTRL_QUERY_FORMAT
:
247 return query_format(*((uint32_t*)data
));