Mercurial > mplayer.hg
annotate libmpcodecs/vf_screenshot.c @ 34757:da38eb1e2069
subassconvert: handle "\r\n" line ends
Previously the code converting text subtitles to ASS format converted newline
characters, and only those, to ASS "new line" markup. If the subtitles
contained "\r\n", the "\r" was thus left in the text. In previous libass
versions the "\r" was not visible, but in the current one it produces an empty
box. Improve the conversion to remove the "\r" in that case. Also treat a lone
"\r" as a newline.
Picked from mplayer2/3e0a2705
author | cboesch |
---|---|
date | Sat, 07 Apr 2012 11:17:09 +0000 |
parents | c7db9db9105c |
children | bec9e755fb9b |
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->compression_level = 0; | |
16446 | 73 vf->priv->dw = d_width; |
74 vf->priv->dh = d_height; | |
16450 | 75 vf->priv->stride = (3*vf->priv->dw+15)&~15; |
16446 | 76 |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
31082
diff
changeset
|
77 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
|
78 vf->priv->buffer = NULL; |
16446 | 79 |
80 return vf_next_config(vf,width,height,d_width,d_height,flags,outfmt); | |
81 } | |
82 | |
24731 | 83 static void write_png(struct vf_priv_s *priv) |
16446 | 84 { |
24731 | 85 char *fname = priv->fname; |
16446 | 86 FILE * fp; |
24731 | 87 AVFrame pic; |
88 int size; | |
16446 | 89 |
90 fp = fopen (fname, "wb"); | |
91 if (fp == NULL) { | |
27947 | 92 mp_msg(MSGT_VFILTER,MSGL_ERR,"\nPNG Error opening %s for writing!\n", fname); |
93 return; | |
16446 | 94 } |
27947 | 95 |
24731 | 96 pic.data[0] = priv->buffer; |
97 pic.linesize[0] = priv->stride; | |
98 size = avcodec_encode_video(priv->avctx, priv->outbuffer, priv->outbuffer_size, &pic); | |
99 if (size > 0) | |
100 fwrite(priv->outbuffer, size, 1, fp); | |
16446 | 101 |
102 fclose (fp); | |
103 } | |
104 | |
105 static int fexists(char *fname) | |
106 { | |
107 struct stat dummy; | |
108 if (stat(fname, &dummy) == 0) return 1; | |
109 else return 0; | |
110 } | |
111 | |
16450 | 112 static void gen_fname(struct vf_priv_s* priv) |
16446 | 113 { |
16450 | 114 do { |
27947 | 115 snprintf (priv->fname, 100, "shot%04d.png", ++priv->frameno); |
16450 | 116 } while (fexists(priv->fname) && priv->frameno < 100000); |
16457 | 117 if (fexists(priv->fname)) { |
27947 | 118 priv->fname[0] = '\0'; |
119 return; | |
16457 | 120 } |
16450 | 121 |
122 mp_msg(MSGT_VFILTER,MSGL_INFO,"*** screenshot '%s' ***\n",priv->fname); | |
123 | |
124 } | |
125 | |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
126 static void scale_image(struct vf_priv_s* priv, mp_image_t *mpi) |
16450 | 127 { |
29064
67c256364220
Consistently use MP_MAX_PLANES as size for plane pointer/stride arrays in libmpcodecs.
reimar
parents:
28594
diff
changeset
|
128 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
|
129 int dst_stride[MP_MAX_PLANES] = {0}; |
27947 | 130 |
16450 | 131 dst_stride[0] = priv->stride; |
16446 | 132 if (!priv->buffer) |
31003
00825525514e
Replace memalign(x) (x > 8) by av_malloc() to prevent crashes on systems
zuxy
parents:
30642
diff
changeset
|
133 priv->buffer = av_malloc(dst_stride[0]*priv->dh); |
16446 | 134 |
135 dst[0] = priv->buffer; | |
30150
16c71b965952
Replace deprecated sws_scale_ordered usages by sws_scale (which does the same).
reimar
parents:
30143
diff
changeset
|
136 sws_scale(priv->ctx, mpi->planes, mpi->stride, 0, priv->dh, dst, dst_stride); |
16450 | 137 } |
16446 | 138 |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
139 static void start_slice(struct vf_instance *vf, mp_image_t *mpi) |
27948 | 140 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
141 vf->dmpi=vf_get_image(vf->next,mpi->imgfmt, |
27947 | 142 mpi->type, mpi->flags, mpi->width, mpi->height); |
16450 | 143 if (vf->priv->shot) { |
27947 | 144 vf->priv->store_slices = 1; |
145 if (!vf->priv->buffer) | |
31003
00825525514e
Replace memalign(x) (x > 8) by av_malloc() to prevent crashes on systems
zuxy
parents:
30642
diff
changeset
|
146 vf->priv->buffer = av_malloc(vf->priv->stride*vf->priv->dh); |
16450 | 147 } |
27947 | 148 |
16450 | 149 } |
150 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
151 static void draw_slice(struct vf_instance *vf, unsigned char** src, |
27948 | 152 int* stride, int w,int h, int x, int y) |
153 { | |
16450 | 154 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
|
155 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
|
156 int dst_stride[MP_MAX_PLANES] = {0}; |
27947 | 157 dst_stride[0] = vf->priv->stride; |
158 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
|
159 sws_scale(vf->priv->ctx, src, stride, y, h, dst, dst_stride); |
16450 | 160 } |
161 vf_next_draw_slice(vf,src,stride,w,h,x,y); | |
162 } | |
163 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
164 static void get_image(struct vf_instance *vf, mp_image_t *mpi) |
27948 | 165 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
166 // 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
|
167 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
|
168 return; |
27947 | 169 vf->dmpi= vf_get_image(vf->next, mpi->imgfmt, |
170 mpi->type, mpi->flags/* | MP_IMGFLAG_READABLE*/, mpi->width, mpi->height); | |
16456 | 171 |
16450 | 172 mpi->planes[0]=vf->dmpi->planes[0]; |
173 mpi->stride[0]=vf->dmpi->stride[0]; | |
174 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
27947 | 175 mpi->planes[1]=vf->dmpi->planes[1]; |
176 mpi->planes[2]=vf->dmpi->planes[2]; | |
177 mpi->stride[1]=vf->dmpi->stride[1]; | |
178 mpi->stride[2]=vf->dmpi->stride[2]; | |
16450 | 179 } |
180 mpi->width=vf->dmpi->width; | |
181 | |
182 mpi->flags|=MP_IMGFLAG_DIRECT; | |
27947 | 183 |
16450 | 184 mpi->priv=(void*)vf->dmpi; |
16446 | 185 } |
186 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
187 static int put_image(struct vf_instance *vf, mp_image_t *mpi, double pts) |
16446 | 188 { |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
189 mp_image_t *dmpi = (mp_image_t *)mpi->priv; |
27947 | 190 |
16464
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
191 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
|
192 dmpi = vf->dmpi; |
0a828abf1f0f
Fix multiple issues: No picture at all, broken pictures, only every second
reimar
parents:
16457
diff
changeset
|
193 else |
16450 | 194 if(!(mpi->flags&MP_IMGFLAG_DIRECT)){ |
27947 | 195 dmpi=vf_get_image(vf->next,mpi->imgfmt, |
196 MP_IMGTYPE_EXPORT, 0, | |
197 mpi->width, mpi->height); | |
198 vf_clone_mpi_attributes(dmpi, mpi); | |
199 dmpi->planes[0]=mpi->planes[0]; | |
200 dmpi->planes[1]=mpi->planes[1]; | |
201 dmpi->planes[2]=mpi->planes[2]; | |
202 dmpi->stride[0]=mpi->stride[0]; | |
203 dmpi->stride[1]=mpi->stride[1]; | |
204 dmpi->stride[2]=mpi->stride[2]; | |
205 dmpi->width=mpi->width; | |
206 dmpi->height=mpi->height; | |
16450 | 207 } |
16446 | 208 |
209 if(vf->priv->shot) { | |
27947 | 210 if (vf->priv->shot==1) |
211 vf->priv->shot=0; | |
212 gen_fname(vf->priv); | |
213 if (vf->priv->fname[0]) { | |
214 if (!vf->priv->store_slices) | |
215 scale_image(vf->priv, dmpi); | |
216 write_png(vf->priv); | |
217 } | |
218 vf->priv->store_slices = 0; | |
16446 | 219 } |
220 | |
17906
20aca9baf5d8
passing pts through the filter layer (lets see if pts or cola comes out at the end)
michael
parents:
17012
diff
changeset
|
221 return vf_next_put_image(vf, dmpi, pts); |
16446 | 222 } |
223 | |
29702
28fb967d78d8
Mark some functions that do not need external visibility as static.
diego
parents:
29064
diff
changeset
|
224 static int control (vf_instance_t *vf, int request, void *data) |
16446 | 225 { |
19833 | 226 /** data contains an integer argument |
227 * 0: take screenshot with the next frame | |
228 * 1: take screenshots with each frame until the same command is given once again | |
229 **/ | |
16446 | 230 if(request==VFCTRL_SCREENSHOT) { |
27947 | 231 if (data && *(int*)data) { // repeated screenshot mode |
232 if (vf->priv->shot==2) | |
233 vf->priv->shot=0; | |
234 else | |
235 vf->priv->shot=2; | |
236 } else { // single screenshot | |
237 if (!vf->priv->shot) | |
238 vf->priv->shot=1; | |
239 } | |
16446 | 240 return CONTROL_TRUE; |
241 } | |
242 return vf_next_control (vf, request, data); | |
243 } | |
244 | |
245 | |
246 //===========================================================================// | |
247 | |
30642
a972c1a4a012
cosmetics: Rename struct vf_instance_s --> vf_instance.
diego
parents:
30638
diff
changeset
|
248 static int query_format(struct vf_instance *vf, unsigned int fmt) |
16446 | 249 { |
250 switch(fmt){ | |
251 case IMGFMT_YV12: | |
252 case IMGFMT_I420: | |
253 case IMGFMT_IYUV: | |
254 case IMGFMT_UYVY: | |
255 case IMGFMT_YUY2: | |
256 case IMGFMT_BGR32: | |
257 case IMGFMT_BGR24: | |
258 case IMGFMT_BGR16: | |
259 case IMGFMT_BGR15: | |
31082
92f88bb315c5
Add support for 12-bit color mode on framebuffer devices.
cehoyos
parents:
31003
diff
changeset
|
260 case IMGFMT_BGR12: |
16446 | 261 case IMGFMT_RGB32: |
262 case IMGFMT_RGB24: | |
27947 | 263 case IMGFMT_Y800: |
264 case IMGFMT_Y8: | |
265 case IMGFMT_YVU9: | |
266 case IMGFMT_IF09: | |
267 case IMGFMT_444P: | |
268 case IMGFMT_422P: | |
269 case IMGFMT_411P: | |
270 return vf_next_query_format(vf, fmt); | |
16446 | 271 } |
272 return 0; | |
273 } | |
274 | |
27949
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
275 static void uninit(vf_instance_t *vf) |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
276 { |
30143 | 277 avcodec_close(vf->priv->avctx); |
27949
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
278 av_freep(&vf->priv->avctx); |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
279 if(vf->priv->ctx) sws_freeContext(vf->priv->ctx); |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
31082
diff
changeset
|
280 av_free(vf->priv->buffer); |
27949
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
281 free(vf->priv->outbuffer); |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
282 free(vf->priv); |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
283 } |
88d793e52bd9
cosmetics: Move up uninit() to avoid a forward declaration.
diego
parents:
27948
diff
changeset
|
284 |
30638
a7b908875c14
Rename open() vf initialization function to vf_open().
diego
parents:
30421
diff
changeset
|
285 static int vf_open(vf_instance_t *vf, char *args) |
16446 | 286 { |
287 vf->config=config; | |
288 vf->control=control; | |
289 vf->put_image=put_image; | |
290 vf->query_format=query_format; | |
16450 | 291 vf->start_slice=start_slice; |
292 vf->draw_slice=draw_slice; | |
293 vf->get_image=get_image; | |
16874 | 294 vf->uninit=uninit; |
16446 | 295 vf->priv=malloc(sizeof(struct vf_priv_s)); |
296 vf->priv->frameno=0; | |
297 vf->priv->shot=0; | |
16450 | 298 vf->priv->store_slices=0; |
16446 | 299 vf->priv->buffer=0; |
24731 | 300 vf->priv->outbuffer=0; |
16446 | 301 vf->priv->ctx=0; |
34566
f3d53cd55376
Update deprecated avcodec_alloc_context()/avcodec_open() API calls
siretart
parents:
32537
diff
changeset
|
302 vf->priv->avctx = avcodec_alloc_context3(NULL); |
34659 | 303 vf->priv->avctx->pix_fmt = PIX_FMT_RGB24; |
24731 | 304 avcodec_register_all(); |
34566
f3d53cd55376
Update deprecated avcodec_alloc_context()/avcodec_open() API calls
siretart
parents:
32537
diff
changeset
|
305 if (avcodec_open2(vf->priv->avctx, avcodec_find_encoder(CODEC_ID_PNG), NULL)) { |
24731 | 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 //===========================================================================// |