Mercurial > mplayer.hg
annotate libmpcodecs/vf_screenshot.c @ 32439:2f1ccd169a7f
Improve vd_ffmpeg aspect handling to respect container aspect if possible
(i.e. until the first resolution or aspect change) and to use correct
aspect if only resolution changes but not the pixel aspect.
author | reimar |
---|---|
date | Fri, 22 Oct 2010 17:36:11 +0000 |
parents | 92f88bb315c5 |
children | 8fa2f43cb760 |
rev | line source |
---|---|
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
1 /* |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
2 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
3 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
4 * MPlayer is free software; you can redistribute it and/or modify |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
5 * it under the terms of the GNU General Public License as published by |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
6 * the Free Software Foundation; either version 2 of the License, or |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
7 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
8 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
9 * MPlayer is distributed in the hope that it will be useful, |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
12 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
13 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
14 * You should have received a copy of the GNU General Public License along |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
15 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
17 */ |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
30150
diff
changeset
|
18 |
17012 | 19 #include "config.h" |
16446 | 20 |
21 #include <stdio.h> | |
22 #include <stdlib.h> | |
28594
df67d03dde3b
Convert HAVE_MALLOC_H into a 0/1 definition, fixes the warning:
diego
parents:
27949
diff
changeset
|
23 #if HAVE_MALLOC_H |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
24 #include <malloc.h> |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
25 #endif |
16446 | 26 #include <string.h> |
27 #include <inttypes.h> | |
28 | |
29 #include <sys/types.h> | |
30 #include <sys/stat.h> | |
31 #include <unistd.h> | |
32 | |
17012 | 33 #include "mp_msg.h" |
16446 | 34 |
35 #include "img_format.h" | |
36 #include "mp_image.h" | |
37 #include "vf.h" | |
38 #include "vf_scale.h" | |
39 | |
18861 | 40 #include "libswscale/swscale.h" |
24731 | 41 #include "libavcodec/avcodec.h" |
42 | |
16446 | 43 struct vf_priv_s { |
44 int frameno; | |
16450 | 45 char fname[102]; |
19833 | 46 /// shot stores current screenshot mode: |
47 /// 0: don't take screenshots | |
48 /// 1: take single screenshot, reset to 0 afterwards | |
49 /// 2: take screenshots of each frame | |
16450 | 50 int shot, store_slices; |
51 int dw, dh, stride; | |
16446 | 52 uint8_t *buffer; |
53 struct SwsContext *ctx; | |
24731 | 54 AVCodecContext *avctx; |
55 uint8_t *outbuffer; | |
56 int outbuffer_size; | |
16446 | 57 }; |
58 | |
59 //===========================================================================// | |
60 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
61 static int config(struct vf_instance *vf, |
27947 | 62 int width, int height, int d_width, int d_height, |
63 unsigned int flags, unsigned int outfmt) | |
16446 | 64 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
65 vf->priv->ctx=sws_getContextFromCmdLine(width, height, outfmt, |
27947 | 66 d_width, d_height, IMGFMT_RGB24); |
16446 | 67 |
24731 | 68 vf->priv->outbuffer_size = d_width * d_height * 3 * 2; |
69 vf->priv->outbuffer = realloc(vf->priv->outbuffer, vf->priv->outbuffer_size); | |
70 vf->priv->avctx->width = d_width; | |
71 vf->priv->avctx->height = d_height; | |
72 vf->priv->avctx->pix_fmt = PIX_FMT_RGB24; | |
73 vf->priv->avctx->compression_level = 0; | |
16446 | 74 vf->priv->dw = d_width; |
75 vf->priv->dh = d_height; | |
16450 | 76 vf->priv->stride = (3*vf->priv->dw+15)&~15; |
16446 | 77 |
78 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
|
79 vf->priv->buffer = NULL; |
16446 | 80 |
81 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
82 } | |
83 | |
24731 | 84 static void write_png(struct vf_priv_s *priv) |
16446 | 85 { |
24731 | 86 char *fname = priv->fname; |
16446 | 87 FILE * fp; |
24731 | 88 AVFrame pic; |
89 int size; | |
16446 | 90 |
91 fp = fopen (fname, "wb"); | |
92 if (fp == NULL) { | |
27947 | 93 mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname); |
94 return; | |
16446 | 95 } |
27947 | 96 |
24731 | 97 pic.data[0] = priv->buffer; |
98 pic.linesize[0] = priv->stride; | |
99 size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic); | |
100 if (size > 0) | |
101 fwrite(priv->outbuffer, size, 1, fp); | |
16446 | 102 |
103 fclose (fp); | |
104 } | |
105 | |
106 static int fexists(char *fname) | |
107 { | |
108 struct stat dummy; | |
109 if (stat(fname, &dummy) == 0) return 1; | |
110 else return 0; | |
111 } | |
112 | |
16450 | 113 static void gen_fname(struct vf_priv_s* priv) |
16446 | 114 { |
16450 | 115 do { |
27947 | 116 snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno); |
16450 | 117 } while (fexists(priv->fname) && priv->frameno < 100000); |
16457 | 118 if (fexists(priv->fname)) { |
27947 | 119 priv->fname[0] = '\0'; |
120 return; | |
16457 | 121 } |
16450 | 122 |
123 mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname); | |
124 | |
125 } | |
126 | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
127 static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi) |
16450 | 128 { |
29064
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
129 uint8_t *dst[MP_MAX_PLANES] = {NULL}; |
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
130 int dst_stride[MP_MAX_PLANES] = {0}; |
27947 | 131 |
16450 | 132 dst_stride[0] = priv->stride; |
16446 | 133 if (!priv->buffer) |
31003
00825525514e
Replace memalign(x) (x > 8) by av_malloc() to prevent crashes on systems
zuxy
parents:
30642
diff
changeset
|
134 priv->buffer = av_malloc(dst_stride[0]*priv->dh); |
16446 | 135 |
136 dst[0] = priv->buffer; | |
30150
16c71b965952
Replace deprecated sws_scale_ordered usages by sws_scale (which does the same).
reimar
parents:
30143
diff
changeset
|
137 sws_scale(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride); |
16450 | 138 } |
16446 | 139 |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
140 static void start_slice(struct vf_instance *vf, mp_image_t *mpi) |
27948 | 141 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
142 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, |
27947 | 143 mpi->type, mpi->flags, mpi->width, mpi->height); |
16450 | 144 if (vf->priv->shot) { |
27947 | 145 vf->priv->store_slices = 1; |
146 if (!vf->priv->buffer) | |
31003
00825525514e
Replace memalign(x) (x > 8) by av_malloc() to prevent crashes on systems
zuxy
parents:
30642
diff
changeset
|
147 vf->priv->buffer = av_malloc(vf->priv->stride*vf->priv->dh); |
16450 | 148 } |
27947 | 149 |
16450 | 150 } |
151 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
152 static void draw_slice(struct vf_instance *vf, unsigned char** src, |
27948 | 153 int* stride, int w,int h, int x, int y) |
154 { | |
16450 | 155 if (vf->priv->store_slices) { |
29064
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
156 uint8_t *dst[MP_MAX_PLANES] = {NULL}; |
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
157 int dst_stride[MP_MAX_PLANES] = {0}; |
27947 | 158 dst_stride[0] = vf->priv->stride; |
159 dst[0] = vf->priv->buffer; | |
30150
16c71b965952
Replace deprecated sws_scale_ordered usages by sws_scale (which does the same).
reimar
parents:
30143
diff
changeset
|
160 sws_scale(vf->priv->ctx, src, stride, y, h, dst, dst_stride); |
16450 | 161 } |
162 vf_next_draw_slice(vf,src,stride,w,h,x,y); | |
163 } | |
164 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
165 static void get_image(struct vf_instance *vf, mp_image_t *mpi) |
27948 | 166 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
167 // 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
|
168 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
|
169 return; |
27947 | 170 vf->dmpi= vf_get_image(vf->next, mpi->imgfmt, |
171 mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height); | |
16456 | 172 |
16450 | 173 mpi->planes[0]=vf->dmpi->planes[0]; |
174 mpi->stride[0]=vf->dmpi->stride[0]; | |
175 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
27947 | 176 mpi->planes[1]=vf->dmpi->planes[1]; |
177 mpi->planes[2]=vf->dmpi->planes[2]; | |
178 mpi->stride[1]=vf->dmpi->stride[1]; | |
179 mpi->stride[2]=vf->dmpi->stride[2]; | |
16450 | 180 } |
181 mpi->width=vf->dmpi->width; | |
182 | |
183 mpi->flags|=MP_IMGFLAG_DIRECT; | |
27947 | 184 |
16450 | 185 mpi->priv=(void*)vf->dmpi; |
16446 | 186 } |
187 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
188 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) |
16446 | 189 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
190 mp_image_t *dmpi = (mp_image_t *)mpi->priv; |
27947 | 191 |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
192 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
|
193 dmpi = vf->dmpi; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
194 else |
16450 | 195 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ |
27947 | 196 dmpi=vf_get_image(vf->next,mpi->imgfmt, |
197 MP_IMGTYPE_EXPORT, 0, | |
198 mpi->width, mpi->height); | |
199 vf_clone_mpi_attributes(dmpi, mpi); | |
200 dmpi->planes[0]=mpi->planes[0]; | |
201 dmpi->planes[1]=mpi->planes[1]; | |
202 dmpi->planes[2]=mpi->planes[2]; | |
203 dmpi->stride[0]=mpi->stride[0]; | |
204 dmpi->stride[1]=mpi->stride[1]; | |
205 dmpi->stride[2]=mpi->stride[2]; | |
206 dmpi->width=mpi->width; | |
207 dmpi->height=mpi->height; | |
16450 | 208 } |
16446 | 209 |
210 if(vf->priv->shot) { | |
27947 | 211 if (vf->priv->shot==1) |
212 vf->priv->shot=0; | |
213 gen_fname(vf->priv); | |
214 if (vf->priv->fname[0]) { | |
215 if (!vf->priv->store_slices) | |
216 scale_image(vf->priv, dmpi); | |
217 write_png(vf->priv); | |
218 } | |
219 vf->priv->store_slices = 0; | |
16446 | 220 } |
221 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17012
diff
changeset
|
222 return vf_next_put_image(vf, dmpi, pts); |
16446 | 223 } |
224 | |
29702
28fb967d78d8
Mark some functions that do not need external visibility as static.
diego
parents:
29064
diff
changeset
|
225 static int control (vf_instance_t *vf, int request, void *data) |
16446 | 226 { |
19833 | 227 /** data contains an integer argument |
228 * 0: take screenshot with the next frame | |
229 * 1: take screenshots with each frame until the same command is given once again | |
230 **/ | |
16446 | 231 if(request==VFCTRL_SCREENSHOT) { |
27947 | 232 if (data && *(int*)data) { // repeated screenshot mode |
233 if (vf->priv->shot==2) | |
234 vf->priv->shot=0; | |
235 else | |
236 vf->priv->shot=2; | |
237 } else { // single screenshot | |
238 if (!vf->priv->shot) | |
239 vf->priv->shot=1; | |
240 } | |
16446 | 241 return CONTROL_TRUE; |
242 } | |
243 return vf_next_control (vf, request, data); | |
244 } | |
245 | |
246 | |
247 //===========================================================================// | |
248 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
249 static int query_format(struct vf_instance *vf, unsigned int fmt) |
16446 | 250 { |
251 switch(fmt){ | |
252 case IMGFMT_YV12: | |
253 case IMGFMT_I420: | |
254 case IMGFMT_IYUV: | |
255 case IMGFMT_UYVY: | |
256 case IMGFMT_YUY2: | |
257 case IMGFMT_BGR32: | |
258 case IMGFMT_BGR24: | |
259 case IMGFMT_BGR16: | |
260 case IMGFMT_BGR15: | |
31082
92f88bb315c5
Add support for 12-bit color mode on framebuffer devices.
cehoyos
parents:
31003
diff
changeset
|
261 case IMGFMT_BGR12: |
16446 | 262 case IMGFMT_RGB32: |
263 case IMGFMT_RGB24: | |
27947 | 264 case IMGFMT_Y800: |
265 case IMGFMT_Y8: | |
266 case IMGFMT_YVU9: | |
267 case IMGFMT_IF09: | |
268 case IMGFMT_444P: | |
269 case IMGFMT_422P: | |
270 case IMGFMT_411P: | |
271 return vf_next_query_format(vf, fmt); | |
16446 | 272 } |
273 return 0; | |
274 } | |
275 | |
27949
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
276 static void uninit(vf_instance_t *vf) |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
277 { |
30143 | 278 avcodec_close(vf->priv->avctx); |
27949
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
279 av_freep(&vf->priv->avctx); |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
280 if(vf->priv->ctx) sws_freeContext(vf->priv->ctx); |
31003
00825525514e
Replace memalign(x) (x > 8) by av_malloc() to prevent crashes on systems
zuxy
parents:
30642
diff
changeset
|
281 if (vf->priv->buffer) av_free(vf->priv->buffer); |
27949
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
282 free(vf->priv->outbuffer); |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
283 free(vf->priv); |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
284 } |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
285 |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
30421
diff
changeset
|
286 static int vf_open(vf_instance_t *vf, char *args) |
16446 | 287 { |
288 vf->config=config; | |
289 vf->control=control; | |
290 vf->put_image=put_image; | |
291 vf->query_format=query_format; | |
16450 | 292 vf->start_slice=start_slice; |
293 vf->draw_slice=draw_slice; | |
294 vf->get_image=get_image; | |
16874 | 295 vf->uninit=uninit; |
16446 | 296 vf->priv=malloc(sizeof(struct vf_priv_s)); |
297 vf->priv->frameno=0; | |
298 vf->priv->shot=0; | |
16450 | 299 vf->priv->store_slices=0; |
16446 | 300 vf->priv->buffer=0; |
24731 | 301 vf->priv->outbuffer=0; |
16446 | 302 vf->priv->ctx=0; |
24731 | 303 vf->priv->avctx = avcodec_alloc_context(); |
304 avcodec_register_all(); | |
305 if (avcodec_open(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG))) { | |
306 mp_msg(MSGT_VFILTER, MSGL_FATAL, "Could not open libavcodec PNG encoder\n"); | |
307 return 0; | |
308 } | |
16446 | 309 return 1; |
310 } | |
311 | |
312 | |
25221 | 313 const vf_info_t vf_info_screenshot = { |
16446 | 314 "screenshot to file", |
315 "screenshot", | |
316 "A'rpi, Jindrich Makovicka", | |
317 "", | |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
30421
diff
changeset
|
318 vf_open, |
16446 | 319 NULL |
320 }; | |
321 | |
322 //===========================================================================// |