Mercurial > mplayer.hg
comparison libmpcodecs/vf_screenshot.c @ 16446:c82c0d407ec9
screenshot filter
author | henry |
---|---|
date | Sun, 11 Sep 2005 06:42:32 +0000 |
parents | |
children | 40222952440f |
comparison
equal
deleted
inserted
replaced
16445:9597d55ee7ab | 16446:c82c0d407ec9 |
---|---|
1 #include "../config.h" | |
2 #ifdef HAVE_PNG | |
3 | |
4 #include <stdio.h> | |
5 #include <stdlib.h> | |
6 #include <string.h> | |
7 #include <inttypes.h> | |
8 | |
9 #include <sys/types.h> | |
10 #include <sys/stat.h> | |
11 #include <unistd.h> | |
12 | |
13 #include <png.h> | |
14 | |
15 #include "../mp_msg.h" | |
16 | |
17 #include "img_format.h" | |
18 #include "mp_image.h" | |
19 #include "vf.h" | |
20 #include "vf_scale.h" | |
21 | |
22 #include "../libvo/fastmemcpy.h" | |
23 #include "../postproc/swscale.h" | |
24 #include "../postproc/rgb2rgb.h" | |
25 | |
26 struct vf_priv_s { | |
27 int frameno; | |
28 int shot; | |
29 int dw, dh; | |
30 uint8_t *buffer; | |
31 struct SwsContext *ctx; | |
32 mp_image_t *dmpi; | |
33 }; | |
34 | |
35 //===========================================================================// | |
36 | |
37 static int config(struct vf_instance_s* vf, | |
38 int width, int height, int d_width, int d_height, | |
39 unsigned int flags, unsigned int outfmt) | |
40 { | |
41 int int_sws_flags=0; | |
42 SwsFilter *srcFilter, *dstFilter; | |
43 | |
44 sws_getFlagsAndFilterFromCmdLine(&int_sws_flags, &srcFilter, &dstFilter); | |
45 | |
46 vf->priv->ctx=sws_getContext(width, height, outfmt, | |
47 d_width, d_height, IMGFMT_BGR24, | |
48 int_sws_flags | get_sws_cpuflags(), srcFilter, dstFilter, NULL); | |
49 | |
50 vf->priv->dw = d_width; | |
51 vf->priv->dh = d_height; | |
52 | |
53 if (vf->priv->buffer) free(vf->priv->buffer); // probably reconfigured | |
54 vf->priv->dmpi = NULL; | |
55 | |
56 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
57 } | |
58 | |
59 static int write_png(char *fname, unsigned char *buffer, int width, int height, int stride) | |
60 { | |
61 FILE * fp; | |
62 png_structp png_ptr; | |
63 png_infop info_ptr; | |
64 png_byte **row_pointers; | |
65 int k; | |
66 | |
67 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
68 info_ptr = png_create_info_struct(png_ptr); | |
69 fp = NULL; | |
70 | |
71 if (setjmp(png_ptr->jmpbuf)) { | |
72 png_destroy_write_struct(&png_ptr, &info_ptr); | |
73 fclose(fp); | |
74 return 0; | |
75 } | |
76 | |
77 fp = fopen (fname, "wb"); | |
78 if (fp == NULL) { | |
79 mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname); | |
80 return 0; | |
81 } | |
82 | |
83 png_init_io(png_ptr, fp); | |
84 png_set_compression_level(png_ptr, 0); | |
85 | |
86 png_set_IHDR(png_ptr, info_ptr, width, height, | |
87 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, | |
88 PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT); | |
89 | |
90 png_write_info(png_ptr, info_ptr); | |
91 | |
92 png_set_bgr(png_ptr); | |
93 | |
94 row_pointers = (png_byte**)malloc(height*sizeof(png_byte*)); | |
95 for ( k = 0; k <height; k++ ){ | |
96 unsigned char* s=buffer + stride*k; | |
97 row_pointers[k] = s; | |
98 } | |
99 | |
100 png_write_image(png_ptr, row_pointers); | |
101 png_write_end(png_ptr, info_ptr); | |
102 png_destroy_write_struct(&png_ptr, &info_ptr); | |
103 | |
104 free(row_pointers); | |
105 | |
106 fclose (fp); | |
107 } | |
108 | |
109 static int fexists(char *fname) | |
110 { | |
111 struct stat dummy; | |
112 if (stat(fname, &dummy) == 0) return 1; | |
113 else return 0; | |
114 } | |
115 | |
116 static void shot(struct vf_priv_s* priv) | |
117 { | |
118 char fname[102]; | |
119 uint8_t *dst[3]; | |
120 int dst_stride[3]; | |
121 | |
122 priv->shot=0; | |
123 | |
124 do { | |
125 snprintf (fname, 100, "shot%04d.png", ++priv->frameno); | |
126 } while (fexists(fname) && priv->frameno < 100000); | |
127 if (fexists(fname)) return; | |
128 | |
129 mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",fname); | |
130 | |
131 dst_stride[0] = (3*priv->dw+15)&~15; | |
132 dst_stride[1] = dst_stride[2] = 0; | |
133 if (!priv->buffer) | |
134 priv->buffer = (uint8_t*)memalign(16, dst_stride[0]*priv->dh); | |
135 | |
136 dst[0] = priv->buffer; | |
137 dst[1] = dst[2] = 0; | |
138 sws_scale_ordered(priv->ctx, priv->dmpi->planes, priv->dmpi->stride, 0, priv->dmpi->height, dst, dst_stride); | |
139 | |
140 write_png(fname, priv->buffer, priv->dw, priv->dh, dst_stride[0]); | |
141 } | |
142 | |
143 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
144 { | |
145 vf->priv->dmpi=vf_get_image(vf->next,mpi->imgfmt, | |
146 MP_IMGTYPE_EXPORT, 0, | |
147 mpi->w, mpi->h); | |
148 | |
149 vf->priv->dmpi->planes[0]=mpi->planes[0]; | |
150 vf->priv->dmpi->planes[1]=mpi->planes[1]; | |
151 vf->priv->dmpi->planes[2]=mpi->planes[2]; | |
152 vf->priv->dmpi->stride[0]=mpi->stride[0]; | |
153 vf->priv->dmpi->stride[1]=mpi->stride[1]; | |
154 vf->priv->dmpi->stride[2]=mpi->stride[2]; | |
155 vf->priv->dmpi->width=mpi->width; | |
156 vf->priv->dmpi->height=mpi->height; | |
157 | |
158 if(vf->priv->shot) { | |
159 shot(vf->priv); | |
160 } | |
161 | |
162 return vf_next_put_image(vf, vf->priv->dmpi); | |
163 } | |
164 | |
165 int control (vf_instance_t *vf, int request, void *data) | |
166 { | |
167 if(request==VFCTRL_SCREENSHOT) { | |
168 vf->priv->shot=1; | |
169 return CONTROL_TRUE; | |
170 } | |
171 return vf_next_control (vf, request, data); | |
172 } | |
173 | |
174 | |
175 //===========================================================================// | |
176 | |
177 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
178 { | |
179 switch(fmt){ | |
180 case IMGFMT_YV12: | |
181 case IMGFMT_I420: | |
182 case IMGFMT_IYUV: | |
183 case IMGFMT_UYVY: | |
184 case IMGFMT_YUY2: | |
185 case IMGFMT_BGR32: | |
186 case IMGFMT_BGR24: | |
187 case IMGFMT_BGR16: | |
188 case IMGFMT_BGR15: | |
189 case IMGFMT_RGB32: | |
190 case IMGFMT_RGB24: | |
191 case IMGFMT_Y800: | |
192 case IMGFMT_Y8: | |
193 case IMGFMT_YVU9: | |
194 case IMGFMT_IF09: | |
195 case IMGFMT_444P: | |
196 case IMGFMT_422P: | |
197 case IMGFMT_411P: | |
198 return vf_next_query_format(vf, fmt); | |
199 } | |
200 return 0; | |
201 } | |
202 | |
203 static int open(vf_instance_t *vf, char* args) | |
204 { | |
205 vf->config=config; | |
206 vf->control=control; | |
207 vf->put_image=put_image; | |
208 vf->query_format=query_format; | |
209 vf->priv=malloc(sizeof(struct vf_priv_s)); | |
210 vf->priv->frameno=0; | |
211 vf->priv->shot=0; | |
212 vf->priv->buffer=0; | |
213 vf->priv->ctx=0; | |
214 return 1; | |
215 } | |
216 | |
217 static void uninit(vf_instance_t *vf) | |
218 { | |
219 if(vf->priv->ctx) sws_freeContext(vf->priv->ctx); | |
220 if (vf->priv->buffer) free(vf->priv->buffer); | |
221 free(vf->priv); | |
222 } | |
223 | |
224 | |
225 vf_info_t vf_info_screenshot = { | |
226 "screenshot to file", | |
227 "screenshot", | |
228 "A'rpi, Jindrich Makovicka", | |
229 "", | |
230 open, | |
231 NULL | |
232 }; | |
233 | |
234 //===========================================================================// | |
235 | |
236 #endif /* HAVE_PNG */ |