12 #include <sys/types.h>
20 #include "img_format.h"
25 #include "libvo/fastmemcpy.h"
26 #include "postproc/swscale.h"
27 #include "postproc/rgb2rgb.h"
32 int shot
, store_slices
;
35 struct SwsContext
*ctx
;
38 //===========================================================================//
40 static int config(struct vf_instance_s
* vf
,
41 int width
, int height
, int d_width
, int d_height
,
42 unsigned int flags
, unsigned int outfmt
)
44 vf
->priv
->ctx
=sws_getContextFromCmdLine(width
, height
, outfmt
,
45 d_width
, d_height
, IMGFMT_BGR24
);
47 vf
->priv
->dw
= d_width
;
48 vf
->priv
->dh
= d_height
;
49 vf
->priv
->stride
= (3*vf
->priv
->dw
+15)&~15;
51 if (vf
->priv
->buffer
) free(vf
->priv
->buffer
); // probably reconfigured
52 vf
->priv
->buffer
= NULL
;
54 return vf_next_config(vf
,width
,height
,d_width
,d_height
,flags
,outfmt
);
57 static void write_png(char *fname
, unsigned char *buffer
, int width
, int height
, int stride
)
62 png_byte
**row_pointers
;
65 png_ptr
= png_create_write_struct (PNG_LIBPNG_VER_STRING
, NULL
, NULL
, NULL
);
66 info_ptr
= png_create_info_struct(png_ptr
);
69 if (setjmp(png_ptr
->jmpbuf
)) {
70 png_destroy_write_struct(&png_ptr
, &info_ptr
);
75 fp
= fopen (fname
, "wb");
77 mp_msg(MSGT_VFILTER
,MSGL_ERR
,"\nPNG Error opening %s for writing!\n", fname
);
81 png_init_io(png_ptr
, fp
);
82 png_set_compression_level(png_ptr
, 0);
84 png_set_IHDR(png_ptr
, info_ptr
, width
, height
,
85 8, PNG_COLOR_TYPE_RGB
, PNG_INTERLACE_NONE
,
86 PNG_COMPRESSION_TYPE_DEFAULT
, PNG_FILTER_TYPE_DEFAULT
);
88 png_write_info(png_ptr
, info_ptr
);
92 row_pointers
= (png_byte
**)malloc(height
*sizeof(png_byte
*));
93 for (k
= 0; k
< height
; k
++) {
94 unsigned char* s
=buffer
+ stride
*k
;
98 png_write_image(png_ptr
, row_pointers
);
99 png_write_end(png_ptr
, info_ptr
);
100 png_destroy_write_struct(&png_ptr
, &info_ptr
);
107 static int fexists(char *fname
)
110 if (stat(fname
, &dummy
) == 0) return 1;
114 static void gen_fname(struct vf_priv_s
* priv
)
117 snprintf (priv
->fname
, 100, "shot%04d.png", ++priv
->frameno
);
118 } while (fexists(priv
->fname
) && priv
->frameno
< 100000);
119 if (fexists(priv
->fname
)) {
120 priv
->fname
[0] = '\0';
124 mp_msg(MSGT_VFILTER
,MSGL_INFO
,"*** screenshot '%s' ***\n",priv
->fname
);
128 static void scale_image(struct vf_priv_s
* priv
, mp_image_t
*mpi
)
133 dst_stride
[0] = priv
->stride
;
134 dst_stride
[1] = dst_stride
[2] = 0;
136 priv
->buffer
= (uint8_t*)memalign(16, dst_stride
[0]*priv
->dh
);
138 dst
[0] = priv
->buffer
;
140 sws_scale_ordered(priv
->ctx
, mpi
->planes
, mpi
->stride
, 0, mpi
->height
, dst
, dst_stride
);
143 static void start_slice(struct vf_instance_s
* vf
, mp_image_t
*mpi
){
144 vf
->dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
145 mpi
->type
, mpi
->flags
, mpi
->width
, mpi
->height
);
146 if (vf
->priv
->shot
) {
147 vf
->priv
->store_slices
= 1;
148 if (!vf
->priv
->buffer
)
149 vf
->priv
->buffer
= (uint8_t*)memalign(16, vf
->priv
->stride
*vf
->priv
->dh
);
154 static void draw_slice(struct vf_instance_s
* vf
,
155 unsigned char** src
, int* stride
, int w
,int h
, int x
, int y
){
156 if (vf
->priv
->store_slices
) {
159 dst_stride
[0] = vf
->priv
->stride
;
160 dst_stride
[1] = dst_stride
[2] = 0;
161 dst
[0] = vf
->priv
->buffer
;
163 sws_scale_ordered(vf
->priv
->ctx
, src
, stride
, y
, h
, dst
, dst_stride
);
165 vf_next_draw_slice(vf
,src
,stride
,w
,h
,x
,y
);
168 static void get_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
){
169 // FIXME: should vf.c really call get_image when using slices??
170 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
172 vf
->dmpi
= vf_get_image(vf
->next
, mpi
->imgfmt
,
173 mpi
->type
, mpi
->flags
/* | MP_IMGFLAG_READABLE*/, mpi
->width
, mpi
->height
);
175 mpi
->planes
[0]=vf
->dmpi
->planes
[0];
176 mpi
->stride
[0]=vf
->dmpi
->stride
[0];
177 if(mpi
->flags
&MP_IMGFLAG_PLANAR
){
178 mpi
->planes
[1]=vf
->dmpi
->planes
[1];
179 mpi
->planes
[2]=vf
->dmpi
->planes
[2];
180 mpi
->stride
[1]=vf
->dmpi
->stride
[1];
181 mpi
->stride
[2]=vf
->dmpi
->stride
[2];
183 mpi
->width
=vf
->dmpi
->width
;
185 mpi
->flags
|=MP_IMGFLAG_DIRECT
;
187 mpi
->priv
=(void*)vf
->dmpi
;
190 static int put_image(struct vf_instance_s
* vf
, mp_image_t
*mpi
, double pts
)
192 mp_image_t
*dmpi
= (mp_image_t
*)mpi
->priv
;
194 if (mpi
->flags
& MP_IMGFLAG_DRAW_CALLBACK
)
197 if(!(mpi
->flags
&MP_IMGFLAG_DIRECT
)){
198 dmpi
=vf_get_image(vf
->next
,mpi
->imgfmt
,
199 MP_IMGTYPE_EXPORT
, 0,
200 mpi
->width
, mpi
->height
);
201 vf_clone_mpi_attributes(dmpi
, mpi
);
202 dmpi
->planes
[0]=mpi
->planes
[0];
203 dmpi
->planes
[1]=mpi
->planes
[1];
204 dmpi
->planes
[2]=mpi
->planes
[2];
205 dmpi
->stride
[0]=mpi
->stride
[0];
206 dmpi
->stride
[1]=mpi
->stride
[1];
207 dmpi
->stride
[2]=mpi
->stride
[2];
208 dmpi
->width
=mpi
->width
;
209 dmpi
->height
=mpi
->height
;
215 if (vf
->priv
->fname
[0]) {
216 if (!vf
->priv
->store_slices
)
217 scale_image(vf
->priv
, dmpi
);
218 write_png(vf
->priv
->fname
, vf
->priv
->buffer
, vf
->priv
->dw
, vf
->priv
->dh
, vf
->priv
->stride
);
220 vf
->priv
->store_slices
= 0;
223 return vf_next_put_image(vf
, dmpi
, pts
);
226 int control (vf_instance_t
*vf
, int request
, void *data
)
228 if(request
==VFCTRL_SCREENSHOT
) {
232 return vf_next_control (vf
, request
, data
);
236 //===========================================================================//
238 static int query_format(struct vf_instance_s
* vf
, unsigned int fmt
)
259 return vf_next_query_format(vf
, fmt
);
264 static void uninit(vf_instance_t
*vf
);
265 // open conflicts with stdio.h at least under MinGW
266 static int screenshot_open(vf_instance_t
*vf
, char* args
)
270 vf
->put_image
=put_image
;
271 vf
->query_format
=query_format
;
272 vf
->start_slice
=start_slice
;
273 vf
->draw_slice
=draw_slice
;
274 vf
->get_image
=get_image
;
276 vf
->priv
=malloc(sizeof(struct vf_priv_s
));
279 vf
->priv
->store_slices
=0;
285 static void uninit(vf_instance_t
*vf
)
287 if(vf
->priv
->ctx
) sws_freeContext(vf
->priv
->ctx
);
288 if (vf
->priv
->buffer
) free(vf
->priv
->buffer
);
293 vf_info_t vf_info_screenshot
= {
294 "screenshot to file",
296 "A'rpi, Jindrich Makovicka",
302 //===========================================================================//
304 #endif /* HAVE_PNG */