Mercurial > mplayer.hg
annotate libmpcodecs/vf_screenshot.c @ 27450:4da9ce4d8327
Fix 'cast from pointer to integer of different size' on 64bit architectures. Casting to long should work for 32bit and 64bit and not make a difference to the boolean operation (since 'format' is always 32bit (int) the upper 32bit of 'arg' won't matter, but the compiler should be happy now. Casting both to unsigned makes sure the compiler isn't messing things up by sign-extending 'format' to 64bit before masking)
author | ranma |
---|---|
date | Sun, 24 Aug 2008 13:52:54 +0000 |
parents | 1318e956c092 |
children | 4681b6303443 |
rev | line source |
---|---|
17012 | 1 #include "config.h" |
16446 | 2 |
3 #include <stdio.h> | |
4 #include <stdlib.h> | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
5 #ifdef HAVE_MALLOC_H |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
6 #include <malloc.h> |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
7 #endif |
16446 | 8 #include <string.h> |
9 #include <inttypes.h> | |
10 | |
11 #include <sys/types.h> | |
12 #include <sys/stat.h> | |
13 #include <unistd.h> | |
14 | |
17012 | 15 #include "mp_msg.h" |
16446 | 16 |
17 #include "img_format.h" | |
18 #include "mp_image.h" | |
19 #include "vf.h" | |
20 #include "vf_scale.h" | |
21 | |
18861 | 22 #include "libswscale/swscale.h" |
24731 | 23 #include "libavcodec/avcodec.h" |
24 | |
16446 | 25 struct vf_priv_s { |
26 int frameno; | |
16450 | 27 char fname[102]; |
19833 | 28 /// shot stores current screenshot mode: |
29 /// 0: don't take screenshots | |
30 /// 1: take single screenshot, reset to 0 afterwards | |
31 /// 2: take screenshots of each frame | |
16450 | 32 int shot, store_slices; |
33 int dw, dh, stride; | |
16446 | 34 uint8_t *buffer; |
35 struct SwsContext *ctx; | |
24731 | 36 AVCodecContext *avctx; |
37 uint8_t *outbuffer; | |
38 int outbuffer_size; | |
16446 | 39 }; |
40 | |
41 //===========================================================================// | |
42 | |
43 static int config(struct vf_instance_s* vf, | |
44 int width, int height, int d_width, int d_height, | |
45 unsigned int flags, unsigned int outfmt) | |
46 { | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
47 vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt, |
24731 | 48 d_width, d_height, IMGFMT_RGB24); |
16446 | 49 |
24731 | 50 vf->priv->outbuffer_size = d_width * d_height * 3 * 2; |
51 vf->priv->outbuffer = realloc(vf->priv->outbuffer, vf->priv->outbuffer_size); | |
52 vf->priv->avctx->width = d_width; | |
53 vf->priv->avctx->height = d_height; | |
54 vf->priv->avctx->pix_fmt = PIX_FMT_RGB24; | |
55 vf->priv->avctx->compression_level = 0; | |
16446 | 56 vf->priv->dw = d_width; |
57 vf->priv->dh = d_height; | |
16450 | 58 vf->priv->stride = (3*vf->priv->dw+15)&~15; |
16446 | 59 |
60 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
|
61 vf->priv->buffer = NULL; |
16446 | 62 |
63 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
64 } | |
65 | |
24731 | 66 static void write_png(struct vf_priv_s *priv) |
16446 | 67 { |
24731 | 68 char *fname = priv->fname; |
16446 | 69 FILE * fp; |
24731 | 70 AVFrame pic; |
71 int size; | |
16446 | 72 |
73 fp = fopen (fname, "wb"); | |
74 if (fp == NULL) { | |
75 mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname); | |
18484
28fd6f89e1b8
Make return type consistent with usage. Patch by Pierre Lombard.
rathann
parents:
17906
diff
changeset
|
76 return; |
16446 | 77 } |
78 | |
24731 | 79 pic.data[0] = priv->buffer; |
80 pic.linesize[0] = priv->stride; | |
81 size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic); | |
82 if (size > 0) | |
83 fwrite(priv->outbuffer, size, 1, fp); | |
16446 | 84 |
85 fclose (fp); | |
86 } | |
87 | |
88 static int fexists(char *fname) | |
89 { | |
90 struct stat dummy; | |
91 if (stat(fname, &dummy) == 0) return 1; | |
92 else return 0; | |
93 } | |
94 | |
16450 | 95 static void gen_fname(struct vf_priv_s* priv) |
16446 | 96 { |
16450 | 97 do { |
98 snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno); | |
99 } while (fexists(priv->fname) && priv->frameno < 100000); | |
16457 | 100 if (fexists(priv->fname)) { |
101 priv->fname[0] = '\0'; | |
102 return; | |
103 } | |
16450 | 104 |
105 mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname); | |
106 | |
107 } | |
108 | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
109 static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi) |
16450 | 110 { |
16446 | 111 uint8_t *dst[3]; |
112 int dst_stride[3]; | |
113 | |
16450 | 114 dst_stride[0] = priv->stride; |
16446 | 115 dst_stride[1] = dst_stride[2] = 0; |
116 if (!priv->buffer) | |
25800 | 117 priv->buffer = memalign(16, dst_stride[0]*priv->dh); |
16446 | 118 |
119 dst[0] = priv->buffer; | |
120 dst[1] = dst[2] = 0; | |
20930
29c478a2483f
Fix segfault with videos with unusual resolution, patch by Stanislav Maslovski % stanislav P maslovski A gmail P com %
gpoirier
parents:
19833
diff
changeset
|
121 sws_scale_ordered(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride); |
16450 | 122 } |
16446 | 123 |
16450 | 124 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
|
125 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, |
16450 | 126 mpi->type, mpi->flags, mpi->width, mpi->height); |
127 if (vf->priv->shot) { | |
128 vf->priv->store_slices = 1; | |
129 if (!vf->priv->buffer) | |
25800 | 130 vf->priv->buffer = memalign(16, vf->priv->stride*vf->priv->dh); |
16450 | 131 } |
132 | |
133 } | |
134 | |
135 static void draw_slice(struct vf_instance_s* vf, | |
136 unsigned char** src, int* stride, int w,int h, int x, int y){ | |
137 if (vf->priv->store_slices) { | |
138 uint8_t *dst[3]; | |
139 int dst_stride[3]; | |
140 dst_stride[0] = vf->priv->stride; | |
141 dst_stride[1] = dst_stride[2] = 0; | |
142 dst[0] = vf->priv->buffer; | |
143 dst[1] = dst[2] = 0; | |
144 sws_scale_ordered(vf->priv->ctx, src, stride, y, h, dst, dst_stride); | |
145 } | |
146 vf_next_draw_slice(vf,src,stride,w,h,x,y); | |
147 } | |
148 | |
149 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
|
150 // 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
|
151 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
|
152 return; |
16450 | 153 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
|
154 mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height); |
16456 | 155 |
16450 | 156 mpi->planes[0]=vf->dmpi->planes[0]; |
157 mpi->stride[0]=vf->dmpi->stride[0]; | |
158 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
159 mpi->planes[1]=vf->dmpi->planes[1]; | |
160 mpi->planes[2]=vf->dmpi->planes[2]; | |
161 mpi->stride[1]=vf->dmpi->stride[1]; | |
162 mpi->stride[2]=vf->dmpi->stride[2]; | |
163 } | |
164 mpi->width=vf->dmpi->width; | |
165 | |
166 mpi->flags|=MP_IMGFLAG_DIRECT; | |
167 | |
168 mpi->priv=(void*)vf->dmpi; | |
16446 | 169 } |
170 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17012
diff
changeset
|
171 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts) |
16446 | 172 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
173 mp_image_t *dmpi = (mp_image_t *)mpi->priv; |
16450 | 174 |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
175 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
|
176 dmpi = vf->dmpi; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
177 else |
16450 | 178 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
|
179 dmpi=vf_get_image(vf->next,mpi->imgfmt, |
16450 | 180 MP_IMGTYPE_EXPORT, 0, |
181 mpi->width, mpi->height); | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
182 vf_clone_mpi_attributes(dmpi, mpi); |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
183 dmpi->planes[0]=mpi->planes[0]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
184 dmpi->planes[1]=mpi->planes[1]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
185 dmpi->planes[2]=mpi->planes[2]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
186 dmpi->stride[0]=mpi->stride[0]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
187 dmpi->stride[1]=mpi->stride[1]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
188 dmpi->stride[2]=mpi->stride[2]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
189 dmpi->width=mpi->width; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
190 dmpi->height=mpi->height; |
16450 | 191 } |
16446 | 192 |
193 if(vf->priv->shot) { | |
19833 | 194 if (vf->priv->shot==1) |
195 vf->priv->shot=0; | |
16450 | 196 gen_fname(vf->priv); |
16457 | 197 if (vf->priv->fname[0]) { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
198 if (!vf->priv->store_slices) |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
199 scale_image(vf->priv, dmpi); |
24731 | 200 write_png(vf->priv); |
16457 | 201 } |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
202 vf->priv->store_slices = 0; |
16446 | 203 } |
204 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17012
diff
changeset
|
205 return vf_next_put_image(vf, dmpi, pts); |
16446 | 206 } |
207 | |
208 int control (vf_instance_t *vf, int request, void *data) | |
209 { | |
19833 | 210 /** data contains an integer argument |
211 * 0: take screenshot with the next frame | |
212 * 1: take screenshots with each frame until the same command is given once again | |
213 **/ | |
16446 | 214 if(request==VFCTRL_SCREENSHOT) { |
19833 | 215 if (data && *(int*)data) { // repeated screenshot mode |
216 if (vf->priv->shot==2) | |
217 vf->priv->shot=0; | |
218 else | |
219 vf->priv->shot=2; | |
220 } else { // single screenshot | |
221 if (!vf->priv->shot) | |
222 vf->priv->shot=1; | |
223 } | |
16446 | 224 return CONTROL_TRUE; |
225 } | |
226 return vf_next_control (vf, request, data); | |
227 } | |
228 | |
229 | |
230 //===========================================================================// | |
231 | |
232 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
233 { | |
234 switch(fmt){ | |
235 case IMGFMT_YV12: | |
236 case IMGFMT_I420: | |
237 case IMGFMT_IYUV: | |
238 case IMGFMT_UYVY: | |
239 case IMGFMT_YUY2: | |
240 case IMGFMT_BGR32: | |
241 case IMGFMT_BGR24: | |
242 case IMGFMT_BGR16: | |
243 case IMGFMT_BGR15: | |
244 case IMGFMT_RGB32: | |
245 case IMGFMT_RGB24: | |
246 case IMGFMT_Y800: | |
247 case IMGFMT_Y8: | |
248 case IMGFMT_YVU9: | |
249 case IMGFMT_IF09: | |
250 case IMGFMT_444P: | |
251 case IMGFMT_422P: | |
252 case IMGFMT_411P: | |
253 return vf_next_query_format(vf, fmt); | |
254 } | |
255 return 0; | |
256 } | |
257 | |
16874 | 258 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
|
259 // 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
|
260 static int screenshot_open(vf_instance_t *vf, char* args) |
16446 | 261 { |
262 vf->config=config; | |
263 vf->control=control; | |
264 vf->put_image=put_image; | |
265 vf->query_format=query_format; | |
16450 | 266 vf->start_slice=start_slice; |
267 vf->draw_slice=draw_slice; | |
268 vf->get_image=get_image; | |
16874 | 269 vf->uninit=uninit; |
16446 | 270 vf->priv=malloc(sizeof(struct vf_priv_s)); |
271 vf->priv->frameno=0; | |
272 vf->priv->shot=0; | |
16450 | 273 vf->priv->store_slices=0; |
16446 | 274 vf->priv->buffer=0; |
24731 | 275 vf->priv->outbuffer=0; |
16446 | 276 vf->priv->ctx=0; |
24731 | 277 vf->priv->avctx = avcodec_alloc_context(); |
278 avcodec_register_all(); | |
279 if (avcodec_open(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG))) { | |
280 mp_msg(MSGT_VFILTER, MSGL_FATAL, "Could not open libavcodec PNG encoder\n"); | |
281 return 0; | |
282 } | |
16446 | 283 return 1; |
284 } | |
285 | |
286 static void uninit(vf_instance_t *vf) | |
287 { | |
25500 | 288 av_freep(&vf->priv->avctx); |
16446 | 289 if(vf->priv->ctx) sws_freeContext(vf->priv->ctx); |
290 if (vf->priv->buffer) free(vf->priv->buffer); | |
24731 | 291 free(vf->priv->outbuffer); |
16446 | 292 free(vf->priv); |
293 } | |
294 | |
295 | |
25221 | 296 const vf_info_t vf_info_screenshot = { |
16446 | 297 "screenshot to file", |
298 "screenshot", | |
299 "A'rpi, Jindrich Makovicka", | |
300 "", | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
301 screenshot_open, |
16446 | 302 NULL |
303 }; | |
304 | |
305 //===========================================================================// |