Mercurial > mplayer.hg
annotate libmpcodecs/vf_screenshot.c @ 17197:0ab565f7ed60
Avoid gcc warnings:
'...' might be used uninitialized in this function
In this case 'H', 'N', 'D', and 'F' can indeed be
used unitialized, thus possibly causing all sorts of problems.
Patch by Peter Breitenlohner
author | rathann |
---|---|
date | Thu, 15 Dec 2005 20:39:59 +0000 |
parents | 6ff3379a0862 |
children | 20aca9baf5d8 |
rev | line source |
---|---|
17012 | 1 #include "config.h" |
16446 | 2 #ifdef HAVE_PNG |
3 | |
4 #include <stdio.h> | |
5 #include <stdlib.h> | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
6 #ifdef HAVE_MALLOC_H |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
7 #include <malloc.h> |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
8 #endif |
16446 | 9 #include <string.h> |
10 #include <inttypes.h> | |
11 | |
12 #include <sys/types.h> | |
13 #include <sys/stat.h> | |
14 #include <unistd.h> | |
15 | |
16 #include <png.h> | |
17 | |
17012 | 18 #include "mp_msg.h" |
16446 | 19 |
20 #include "img_format.h" | |
21 #include "mp_image.h" | |
22 #include "vf.h" | |
23 #include "vf_scale.h" | |
24 | |
17012 | 25 #include "libvo/fastmemcpy.h" |
26 #include "postproc/swscale.h" | |
27 #include "postproc/rgb2rgb.h" | |
16446 | 28 |
29 struct vf_priv_s { | |
30 int frameno; | |
16450 | 31 char fname[102]; |
32 int shot, store_slices; | |
33 int dw, dh, stride; | |
16446 | 34 uint8_t *buffer; |
35 struct SwsContext *ctx; | |
36 }; | |
37 | |
38 //===========================================================================// | |
39 | |
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) | |
43 { | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
44 vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt, |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
45 d_width, d_height, IMGFMT_BGR24); |
16446 | 46 |
47 vf->priv->dw = d_width; | |
48 vf->priv->dh = d_height; | |
16450 | 49 vf->priv->stride = (3*vf->priv->dw+15)&~15; |
16446 | 50 |
51 if (vf->priv->buffer) free(vf->priv->buffer); // probably reconfigured | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
52 vf->priv->buffer = NULL; |
16446 | 53 |
54 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
55 } | |
56 | |
57 static int write_png(char *fname, unsigned char *buffer, int width, int height, int stride) | |
58 { | |
59 FILE * fp; | |
60 png_structp png_ptr; | |
61 png_infop info_ptr; | |
62 png_byte **row_pointers; | |
63 int k; | |
64 | |
65 png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); | |
66 info_ptr = png_create_info_struct(png_ptr); | |
67 fp = NULL; | |
68 | |
69 if (setjmp(png_ptr->jmpbuf)) { | |
70 png_destroy_write_struct(&png_ptr, &info_ptr); | |
71 fclose(fp); | |
72 return 0; | |
73 } | |
74 | |
75 fp = fopen (fname, "wb"); | |
76 if (fp == NULL) { | |
77 mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname); | |
78 return 0; | |
79 } | |
80 | |
81 png_init_io(png_ptr, fp); | |
82 png_set_compression_level(png_ptr, 0); | |
83 | |
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); | |
87 | |
88 png_write_info(png_ptr, info_ptr); | |
89 | |
90 png_set_bgr(png_ptr); | |
91 | |
92 row_pointers = (png_byte**)malloc(height*sizeof(png_byte*)); | |
16450 | 93 for (k = 0; k < height; k++) { |
16446 | 94 unsigned char* s=buffer + stride*k; |
95 row_pointers[k] = s; | |
96 } | |
97 | |
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); | |
101 | |
102 free(row_pointers); | |
103 | |
104 fclose (fp); | |
105 } | |
106 | |
107 static int fexists(char *fname) | |
108 { | |
109 struct stat dummy; | |
110 if (stat(fname, &dummy) == 0) return 1; | |
111 else return 0; | |
112 } | |
113 | |
16450 | 114 static void gen_fname(struct vf_priv_s* priv) |
16446 | 115 { |
16450 | 116 do { |
117 snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno); | |
118 } while (fexists(priv->fname) && priv->frameno < 100000); | |
16457 | 119 if (fexists(priv->fname)) { |
120 priv->fname[0] = '\0'; | |
121 return; | |
122 } | |
16450 | 123 |
124 mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname); | |
125 | |
126 } | |
127 | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
128 static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi) |
16450 | 129 { |
16446 | 130 uint8_t *dst[3]; |
131 int dst_stride[3]; | |
132 | |
16450 | 133 dst_stride[0] = priv->stride; |
16446 | 134 dst_stride[1] = dst_stride[2] = 0; |
135 if (!priv->buffer) | |
136 priv->buffer = (uint8_t*)memalign(16, dst_stride[0]*priv->dh); | |
137 | |
138 dst[0] = priv->buffer; | |
139 dst[1] = dst[2] = 0; | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
140 sws_scale_ordered(priv->ctx, mpi->planes, mpi->stride, 0, mpi->height, dst, dst_stride); |
16450 | 141 } |
16446 | 142 |
16450 | 143 static void start_slice(struct vf_instance_s* vf, mp_image_t *mpi){ |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
144 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, |
16450 | 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); | |
150 } | |
151 | |
152 } | |
153 | |
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) { | |
157 uint8_t *dst[3]; | |
158 int dst_stride[3]; | |
159 dst_stride[0] = vf->priv->stride; | |
160 dst_stride[1] = dst_stride[2] = 0; | |
161 dst[0] = vf->priv->buffer; | |
162 dst[1] = dst[2] = 0; | |
163 sws_scale_ordered(vf->priv->ctx, src, stride, y, h, dst, dst_stride); | |
164 } | |
165 vf_next_draw_slice(vf,src,stride,w,h,x,y); | |
166 } | |
167 | |
168 static void get_image(struct vf_instance_s* vf, mp_image_t *mpi){ | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
169 // FIXME: should vf.c really call get_image when using slices?? |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
170 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
171 return; |
16450 | 172 vf->dmpi= vf_get_image(vf->next, mpi->imgfmt, |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
173 mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height); |
16456 | 174 |
16450 | 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]; | |
182 } | |
183 mpi->width=vf->dmpi->width; | |
184 | |
185 mpi->flags|=MP_IMGFLAG_DIRECT; | |
186 | |
187 mpi->priv=(void*)vf->dmpi; | |
16446 | 188 } |
189 | |
190 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
191 { | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
192 mp_image_t *dmpi = (mp_image_t *)mpi->priv; |
16450 | 193 |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
194 if (mpi->flags & MP_IMGFLAG_DRAW_CALLBACK) |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
195 dmpi = vf->dmpi; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
196 else |
16450 | 197 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
198 dmpi=vf_get_image(vf->next,mpi->imgfmt, |
16450 | 199 MP_IMGTYPE_EXPORT, 0, |
200 mpi->width, mpi->height); | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
201 vf_clone_mpi_attributes(dmpi, mpi); |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
202 dmpi->planes[0]=mpi->planes[0]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
203 dmpi->planes[1]=mpi->planes[1]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
204 dmpi->planes[2]=mpi->planes[2]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
205 dmpi->stride[0]=mpi->stride[0]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
206 dmpi->stride[1]=mpi->stride[1]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
207 dmpi->stride[2]=mpi->stride[2]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
208 dmpi->width=mpi->width; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
209 dmpi->height=mpi->height; |
16450 | 210 } |
16446 | 211 |
212 if(vf->priv->shot) { | |
16450 | 213 vf->priv->shot=0; |
214 gen_fname(vf->priv); | |
16457 | 215 if (vf->priv->fname[0]) { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
216 if (!vf->priv->store_slices) |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
217 scale_image(vf->priv, dmpi); |
16457 | 218 write_png(vf->priv->fname, vf->priv->buffer, vf->priv->dw, vf->priv->dh, vf->priv->stride); |
219 } | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
220 vf->priv->store_slices = 0; |
16446 | 221 } |
222 | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
223 return vf_next_put_image(vf, dmpi); |
16446 | 224 } |
225 | |
226 int control (vf_instance_t *vf, int request, void *data) | |
227 { | |
228 if(request==VFCTRL_SCREENSHOT) { | |
229 vf->priv->shot=1; | |
230 return CONTROL_TRUE; | |
231 } | |
232 return vf_next_control (vf, request, data); | |
233 } | |
234 | |
235 | |
236 //===========================================================================// | |
237 | |
238 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
239 { | |
240 switch(fmt){ | |
241 case IMGFMT_YV12: | |
242 case IMGFMT_I420: | |
243 case IMGFMT_IYUV: | |
244 case IMGFMT_UYVY: | |
245 case IMGFMT_YUY2: | |
246 case IMGFMT_BGR32: | |
247 case IMGFMT_BGR24: | |
248 case IMGFMT_BGR16: | |
249 case IMGFMT_BGR15: | |
250 case IMGFMT_RGB32: | |
251 case IMGFMT_RGB24: | |
252 case IMGFMT_Y800: | |
253 case IMGFMT_Y8: | |
254 case IMGFMT_YVU9: | |
255 case IMGFMT_IF09: | |
256 case IMGFMT_444P: | |
257 case IMGFMT_422P: | |
258 case IMGFMT_411P: | |
259 return vf_next_query_format(vf, fmt); | |
260 } | |
261 return 0; | |
262 } | |
263 | |
16874 | 264 static void uninit(vf_instance_t *vf); |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
265 // open conflicts with stdio.h at least under MinGW |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
266 static int screenshot_open(vf_instance_t *vf, char* args) |
16446 | 267 { |
268 vf->config=config; | |
269 vf->control=control; | |
270 vf->put_image=put_image; | |
271 vf->query_format=query_format; | |
16450 | 272 vf->start_slice=start_slice; |
273 vf->draw_slice=draw_slice; | |
274 vf->get_image=get_image; | |
16874 | 275 vf->uninit=uninit; |
16446 | 276 vf->priv=malloc(sizeof(struct vf_priv_s)); |
277 vf->priv->frameno=0; | |
278 vf->priv->shot=0; | |
16450 | 279 vf->priv->store_slices=0; |
16446 | 280 vf->priv->buffer=0; |
281 vf->priv->ctx=0; | |
282 return 1; | |
283 } | |
284 | |
285 static void uninit(vf_instance_t *vf) | |
286 { | |
287 if(vf->priv->ctx) sws_freeContext(vf->priv->ctx); | |
288 if (vf->priv->buffer) free(vf->priv->buffer); | |
289 free(vf->priv); | |
290 } | |
291 | |
292 | |
293 vf_info_t vf_info_screenshot = { | |
294 "screenshot to file", | |
295 "screenshot", | |
296 "A'rpi, Jindrich Makovicka", | |
297 "", | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
298 screenshot_open, |
16446 | 299 NULL |
300 }; | |
301 | |
302 //===========================================================================// | |
303 | |
304 #endif /* HAVE_PNG */ |