Mercurial > mplayer.hg
annotate libmpcodecs/vf_screenshot.c @ 25194:e816d546c4fe
ao_null: Make duration of "buffered" audio constant
Choose the "buffer size" for the amount of audio the driver accepts so
that it corresponds to about 0.2 seconds of playback based on the
number of channels, sample size and samplerate.
author | uau |
---|---|
date | Sat, 01 Dec 2007 01:39:39 +0000 |
parents | 1d9ea74f79a0 |
children | 00fff9a3b735 |
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" |
16446 | 23 |
24731 | 24 #ifdef USE_LIBAVCODEC_SO |
25 #include <ffmpeg/avcodec.h> | |
26 #else | |
27 #include "libavcodec/avcodec.h" | |
28 #endif | |
29 | |
16446 | 30 struct vf_priv_s { |
31 int frameno; | |
16450 | 32 char fname[102]; |
19833 | 33 /// shot stores current screenshot mode: |
34 /// 0: don't take screenshots | |
35 /// 1: take single screenshot, reset to 0 afterwards | |
36 /// 2: take screenshots of each frame | |
16450 | 37 int shot, store_slices; |
38 int dw, dh, stride; | |
16446 | 39 uint8_t *buffer; |
40 struct SwsContext *ctx; | |
24731 | 41 AVCodecContext *avctx; |
42 uint8_t *outbuffer; | |
43 int outbuffer_size; | |
16446 | 44 }; |
45 | |
46 //===========================================================================// | |
47 | |
48 static int config(struct vf_instance_s* vf, | |
49 int width, int height, int d_width, int d_height, | |
50 unsigned int flags, unsigned int outfmt) | |
51 { | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
52 vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt, |
24731 | 53 d_width, d_height, IMGFMT_RGB24); |
16446 | 54 |
24731 | 55 vf->priv->outbuffer_size = d_width * d_height * 3 * 2; |
56 vf->priv->outbuffer = realloc(vf->priv->outbuffer, vf->priv->outbuffer_size); | |
57 vf->priv->avctx->width = d_width; | |
58 vf->priv->avctx->height = d_height; | |
59 vf->priv->avctx->pix_fmt = PIX_FMT_RGB24; | |
60 vf->priv->avctx->compression_level = 0; | |
16446 | 61 vf->priv->dw = d_width; |
62 vf->priv->dh = d_height; | |
16450 | 63 vf->priv->stride = (3*vf->priv->dw+15)&~15; |
16446 | 64 |
65 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
|
66 vf->priv->buffer = NULL; |
16446 | 67 |
68 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
69 } | |
70 | |
24731 | 71 static void write_png(struct vf_priv_s *priv) |
16446 | 72 { |
24731 | 73 char *fname = priv->fname; |
16446 | 74 FILE * fp; |
24731 | 75 AVFrame pic; |
76 int size; | |
16446 | 77 |
78 fp = fopen (fname, "wb"); | |
79 if (fp == NULL) { | |
80 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
|
81 return; |
16446 | 82 } |
83 | |
24731 | 84 pic.data[0] = priv->buffer; |
85 pic.linesize[0] = priv->stride; | |
86 size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic); | |
87 if (size > 0) | |
88 fwrite(priv->outbuffer, size, 1, fp); | |
16446 | 89 |
90 fclose (fp); | |
91 } | |
92 | |
93 static int fexists(char *fname) | |
94 { | |
95 struct stat dummy; | |
96 if (stat(fname, &dummy) == 0) return 1; | |
97 else return 0; | |
98 } | |
99 | |
16450 | 100 static void gen_fname(struct vf_priv_s* priv) |
16446 | 101 { |
16450 | 102 do { |
103 snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno); | |
104 } while (fexists(priv->fname) && priv->frameno < 100000); | |
16457 | 105 if (fexists(priv->fname)) { |
106 priv->fname[0] = '\0'; | |
107 return; | |
108 } | |
16450 | 109 |
110 mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname); | |
111 | |
112 } | |
113 | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
114 static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi) |
16450 | 115 { |
16446 | 116 uint8_t *dst[3]; |
117 int dst_stride[3]; | |
118 | |
16450 | 119 dst_stride[0] = priv->stride; |
16446 | 120 dst_stride[1] = dst_stride[2] = 0; |
121 if (!priv->buffer) | |
122 priv->buffer = (uint8_t*)memalign(16, dst_stride[0]*priv->dh); | |
123 | |
124 dst[0] = priv->buffer; | |
125 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
|
126 sws_scale_ordered(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride); |
16450 | 127 } |
16446 | 128 |
16450 | 129 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
|
130 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, |
16450 | 131 mpi->type, mpi->flags, mpi->width, mpi->height); |
132 if (vf->priv->shot) { | |
133 vf->priv->store_slices = 1; | |
134 if (!vf->priv->buffer) | |
135 vf->priv->buffer = (uint8_t*)memalign(16, vf->priv->stride*vf->priv->dh); | |
136 } | |
137 | |
138 } | |
139 | |
140 static void draw_slice(struct vf_instance_s* vf, | |
141 unsigned char** src, int* stride, int w,int h, int x, int y){ | |
142 if (vf->priv->store_slices) { | |
143 uint8_t *dst[3]; | |
144 int dst_stride[3]; | |
145 dst_stride[0] = vf->priv->stride; | |
146 dst_stride[1] = dst_stride[2] = 0; | |
147 dst[0] = vf->priv->buffer; | |
148 dst[1] = dst[2] = 0; | |
149 sws_scale_ordered(vf->priv->ctx, src, stride, y, h, dst, dst_stride); | |
150 } | |
151 vf_next_draw_slice(vf,src,stride,w,h,x,y); | |
152 } | |
153 | |
154 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
|
155 // 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
|
156 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
|
157 return; |
16450 | 158 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
|
159 mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height); |
16456 | 160 |
16450 | 161 mpi->planes[0]=vf->dmpi->planes[0]; |
162 mpi->stride[0]=vf->dmpi->stride[0]; | |
163 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
164 mpi->planes[1]=vf->dmpi->planes[1]; | |
165 mpi->planes[2]=vf->dmpi->planes[2]; | |
166 mpi->stride[1]=vf->dmpi->stride[1]; | |
167 mpi->stride[2]=vf->dmpi->stride[2]; | |
168 } | |
169 mpi->width=vf->dmpi->width; | |
170 | |
171 mpi->flags|=MP_IMGFLAG_DIRECT; | |
172 | |
173 mpi->priv=(void*)vf->dmpi; | |
16446 | 174 } |
175 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17012
diff
changeset
|
176 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts) |
16446 | 177 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
178 mp_image_t *dmpi = (mp_image_t *)mpi->priv; |
16450 | 179 |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
180 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
|
181 dmpi = vf->dmpi; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
182 else |
16450 | 183 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
|
184 dmpi=vf_get_image(vf->next,mpi->imgfmt, |
16450 | 185 MP_IMGTYPE_EXPORT, 0, |
186 mpi->width, mpi->height); | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
187 vf_clone_mpi_attributes(dmpi, mpi); |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
188 dmpi->planes[0]=mpi->planes[0]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
189 dmpi->planes[1]=mpi->planes[1]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
190 dmpi->planes[2]=mpi->planes[2]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
191 dmpi->stride[0]=mpi->stride[0]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
192 dmpi->stride[1]=mpi->stride[1]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
193 dmpi->stride[2]=mpi->stride[2]; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
194 dmpi->width=mpi->width; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
195 dmpi->height=mpi->height; |
16450 | 196 } |
16446 | 197 |
198 if(vf->priv->shot) { | |
19833 | 199 if (vf->priv->shot==1) |
200 vf->priv->shot=0; | |
16450 | 201 gen_fname(vf->priv); |
16457 | 202 if (vf->priv->fname[0]) { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
203 if (!vf->priv->store_slices) |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
204 scale_image(vf->priv, dmpi); |
24731 | 205 write_png(vf->priv); |
16457 | 206 } |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
207 vf->priv->store_slices = 0; |
16446 | 208 } |
209 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17012
diff
changeset
|
210 return vf_next_put_image(vf, dmpi, pts); |
16446 | 211 } |
212 | |
213 int control (vf_instance_t *vf, int request, void *data) | |
214 { | |
19833 | 215 /** data contains an integer argument |
216 * 0: take screenshot with the next frame | |
217 * 1: take screenshots with each frame until the same command is given once again | |
218 **/ | |
16446 | 219 if(request==VFCTRL_SCREENSHOT) { |
19833 | 220 if (data && *(int*)data) { // repeated screenshot mode |
221 if (vf->priv->shot==2) | |
222 vf->priv->shot=0; | |
223 else | |
224 vf->priv->shot=2; | |
225 } else { // single screenshot | |
226 if (!vf->priv->shot) | |
227 vf->priv->shot=1; | |
228 } | |
16446 | 229 return CONTROL_TRUE; |
230 } | |
231 return vf_next_control (vf, request, data); | |
232 } | |
233 | |
234 | |
235 //===========================================================================// | |
236 | |
237 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
238 { | |
239 switch(fmt){ | |
240 case IMGFMT_YV12: | |
241 case IMGFMT_I420: | |
242 case IMGFMT_IYUV: | |
243 case IMGFMT_UYVY: | |
244 case IMGFMT_YUY2: | |
245 case IMGFMT_BGR32: | |
246 case IMGFMT_BGR24: | |
247 case IMGFMT_BGR16: | |
248 case IMGFMT_BGR15: | |
249 case IMGFMT_RGB32: | |
250 case IMGFMT_RGB24: | |
251 case IMGFMT_Y800: | |
252 case IMGFMT_Y8: | |
253 case IMGFMT_YVU9: | |
254 case IMGFMT_IF09: | |
255 case IMGFMT_444P: | |
256 case IMGFMT_422P: | |
257 case IMGFMT_411P: | |
258 return vf_next_query_format(vf, fmt); | |
259 } | |
260 return 0; | |
261 } | |
262 | |
16874 | 263 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
|
264 // 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
|
265 static int screenshot_open(vf_instance_t *vf, char* args) |
16446 | 266 { |
267 vf->config=config; | |
268 vf->control=control; | |
269 vf->put_image=put_image; | |
270 vf->query_format=query_format; | |
16450 | 271 vf->start_slice=start_slice; |
272 vf->draw_slice=draw_slice; | |
273 vf->get_image=get_image; | |
16874 | 274 vf->uninit=uninit; |
16446 | 275 vf->priv=malloc(sizeof(struct vf_priv_s)); |
276 vf->priv->frameno=0; | |
277 vf->priv->shot=0; | |
16450 | 278 vf->priv->store_slices=0; |
16446 | 279 vf->priv->buffer=0; |
24731 | 280 vf->priv->outbuffer=0; |
16446 | 281 vf->priv->ctx=0; |
24731 | 282 vf->priv->avctx = avcodec_alloc_context(); |
283 avcodec_register_all(); | |
284 if (avcodec_open(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG))) { | |
285 mp_msg(MSGT_VFILTER, MSGL_FATAL, "Could not open libavcodec PNG encoder\n"); | |
286 return 0; | |
287 } | |
16446 | 288 return 1; |
289 } | |
290 | |
291 static void uninit(vf_instance_t *vf) | |
292 { | |
293 if(vf->priv->ctx) sws_freeContext(vf->priv->ctx); | |
294 if (vf->priv->buffer) free(vf->priv->buffer); | |
24731 | 295 free(vf->priv->outbuffer); |
16446 | 296 free(vf->priv); |
297 } | |
298 | |
299 | |
300 vf_info_t vf_info_screenshot = { | |
301 "screenshot to file", | |
302 "screenshot", | |
303 "A'rpi, Jindrich Makovicka", | |
304 "", | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
305 screenshot_open, |
16446 | 306 NULL |
307 }; | |
308 | |
309 //===========================================================================// |