Mercurial > mplayer.hg
annotate libmpcodecs/vf_ass.c @ 27815:f92271dc5f17
Remove X11 backing store: this is now a useless flag.
Also, it is mandatory for Xserver 1.5.x (part of Xorg 7.4, shipped on all
Linux distributions starting from Oct. 08) and will be removed
from Xserver 1.6 anyhow ...
Patch by Stephane Marchesin (marchesin at icps dot u dash strasbg dot fr).
For more info, see long flame thread at:
http://lists.mplayerhq.hu/pipermail/mplayer-dev-eng/2008-August/058323.html
author | ben |
---|---|
date | Wed, 29 Oct 2008 22:03:36 +0000 |
parents | 82601a38e2a7 |
children | 0f1b5b68af32 |
rev | line source |
---|---|
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19563
diff
changeset
|
1 // -*- c-basic-offset: 8; indent-tabs-mode: t -*- |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19563
diff
changeset
|
2 // vim:ts=8:sw=8:noet:ai: |
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19563
diff
changeset
|
3 /* |
26727 | 4 * Copyright (C) 2006 Evgeniy Stepanov <eugeni.stepanov@gmail.com> |
5 * | |
6 * This file is part of MPlayer. | |
7 * | |
8 * MPlayer is free software; you can redistribute it and/or modify | |
9 * it under the terms of the GNU General Public License as published by | |
10 * the Free Software Foundation; either version 2 of the License, or | |
11 * (at your option) any later version. | |
12 * | |
13 * MPlayer is distributed in the hope that it will be useful, | |
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 * GNU General Public License for more details. | |
17 * | |
18 * You should have received a copy of the GNU General Public License along | |
19 * with MPlayer; if not, write to the Free Software Foundation, Inc., | |
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
21 */ | |
20008
fa122b7c71c6
Add copyright notice and vim/emacs comments to libass and vf_ass.c.
eugeni
parents:
19563
diff
changeset
|
22 |
18937 | 23 #include "config.h" |
24 | |
25 #include <stdio.h> | |
26 #include <stdlib.h> | |
27 #include <string.h> | |
24545
9e5126679d44
Replace stdint.h #include by functionally equivalent inttypes.h.
diego
parents:
23134
diff
changeset
|
28 #include <inttypes.h> |
18937 | 29 #include <assert.h> |
30 | |
31 #include "config.h" | |
32 #include "mp_msg.h" | |
33 #include "help_mp.h" | |
34 | |
35 #include "img_format.h" | |
36 #include "mp_image.h" | |
37 #include "vf.h" | |
38 | |
39 #include "libvo/fastmemcpy.h" | |
40 | |
41 #include "m_option.h" | |
42 #include "m_struct.h" | |
43 | |
44 #include "libass/ass.h" | |
45 #include "libass/ass_mp.h" | |
46 | |
47 #define _r(c) ((c)>>24) | |
48 #define _g(c) (((c)>>16)&0xFF) | |
49 #define _b(c) (((c)>>8)&0xFF) | |
50 #define _a(c) ((c)&0xFF) | |
51 #define rgba2y(c) ( (( 263*_r(c) + 516*_g(c) + 100*_b(c)) >> 10) + 16 ) | |
52 #define rgba2u(c) ( ((-152*_r(c) - 298*_g(c) + 450*_b(c)) >> 10) + 128 ) | |
53 #define rgba2v(c) ( (( 450*_r(c) - 376*_g(c) - 73*_b(c)) >> 10) + 128 ) | |
54 | |
55 | |
24969
c2b7ba444ade
begin moving const filter data to .text/.rodata sections
rfelker
parents:
24545
diff
changeset
|
56 static const struct vf_priv_s { |
18937 | 57 int outh, outw; |
58 | |
59 unsigned int outfmt; | |
60 | |
61 // 1 = auto-added filter: insert only if chain does not support EOSD already | |
62 // 0 = insert always | |
63 int auto_insert; | |
64 | |
20477 | 65 ass_renderer_t* ass_priv; |
18937 | 66 |
67 unsigned char* planes[3]; | |
68 unsigned char* dirty_rows; | |
24969
c2b7ba444ade
begin moving const filter data to .text/.rodata sections
rfelker
parents:
24545
diff
changeset
|
69 } vf_priv_dflt; |
18937 | 70 |
71 extern int opt_screen_size_x; | |
72 extern int opt_screen_size_y; | |
73 | |
74 extern ass_track_t* ass_track; | |
75 extern float sub_delay; | |
76 extern int sub_visibility; | |
77 | |
78 static int config(struct vf_instance_s* vf, | |
79 int width, int height, int d_width, int d_height, | |
80 unsigned int flags, unsigned int outfmt) | |
81 { | |
82 if (outfmt == IMGFMT_IF09) return 0; | |
83 | |
84 vf->priv->outh = height + ass_top_margin + ass_bottom_margin; | |
85 vf->priv->outw = width; | |
86 | |
87 if(!opt_screen_size_x && !opt_screen_size_y){ | |
88 d_width = d_width * vf->priv->outw / width; | |
89 d_height = d_height * vf->priv->outh / height; | |
90 } | |
91 | |
19065
26ed3fcd5cd4
drops casts from void * on malloc/calloc, leftover on libmpcodecs
reynaldo
parents:
18937
diff
changeset
|
92 vf->priv->planes[1] = malloc(vf->priv->outw * vf->priv->outh); |
26ed3fcd5cd4
drops casts from void * on malloc/calloc, leftover on libmpcodecs
reynaldo
parents:
18937
diff
changeset
|
93 vf->priv->planes[2] = malloc(vf->priv->outw * vf->priv->outh); |
26ed3fcd5cd4
drops casts from void * on malloc/calloc, leftover on libmpcodecs
reynaldo
parents:
18937
diff
changeset
|
94 vf->priv->dirty_rows = malloc(vf->priv->outh); |
18937 | 95 |
96 if (vf->priv->ass_priv) { | |
23134
1de2a46a0987
Add -ass-hinting option for setting font hinting method.
eugeni
parents:
22027
diff
changeset
|
97 ass_configure(vf->priv->ass_priv, vf->priv->outw, vf->priv->outh, 0); |
20446
e8adc3778348
Split ass_configure() into several smaller functions.
eugeni
parents:
20012
diff
changeset
|
98 ass_set_aspect_ratio(vf->priv->ass_priv, ((double)d_width) / d_height); |
18937 | 99 } |
100 | |
101 return vf_next_config(vf, vf->priv->outw, vf->priv->outh, d_width, d_height, flags, outfmt); | |
102 } | |
103 | |
104 static void get_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
105 { | |
106 if(mpi->type == MP_IMGTYPE_IPB) return; | |
107 if(mpi->flags & MP_IMGFLAG_PRESERVE) return; | |
108 if(mpi->imgfmt != vf->priv->outfmt) return; // colorspace differ | |
109 | |
110 // width never changes, always try full DR | |
111 mpi->priv = vf->dmpi = vf_get_image(vf->next, mpi->imgfmt, | |
20656
839c48c35ce8
ass renderer absolutely needs readable target mpi.
reimar
parents:
20629
diff
changeset
|
112 mpi->type, mpi->flags | MP_IMGFLAG_READABLE, |
18937 | 113 vf->priv->outw, |
114 vf->priv->outh); | |
115 | |
116 if((vf->dmpi->flags & MP_IMGFLAG_DRAW_CALLBACK) && | |
117 !(vf->dmpi->flags & MP_IMGFLAG_DIRECT)){ | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20477
diff
changeset
|
118 mp_msg(MSGT_ASS, MSGL_INFO, MSGTR_MPCODECS_FullDRNotPossible); |
18937 | 119 return; |
120 } | |
121 | |
122 // set up mpi as a cropped-down image of dmpi: | |
123 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
124 mpi->planes[0]=vf->dmpi->planes[0] + ass_top_margin * vf->dmpi->stride[0]; | |
125 mpi->planes[1]=vf->dmpi->planes[1] + (ass_top_margin >> mpi->chroma_y_shift) * vf->dmpi->stride[1]; | |
126 mpi->planes[2]=vf->dmpi->planes[2] + (ass_top_margin >> mpi->chroma_y_shift) * vf->dmpi->stride[2]; | |
127 mpi->stride[1]=vf->dmpi->stride[1]; | |
128 mpi->stride[2]=vf->dmpi->stride[2]; | |
129 } else { | |
130 mpi->planes[0]=vf->dmpi->planes[0] + ass_top_margin * vf->dmpi->stride[0]; | |
131 } | |
132 mpi->stride[0]=vf->dmpi->stride[0]; | |
133 mpi->width=vf->dmpi->width; | |
134 mpi->flags|=MP_IMGFLAG_DIRECT; | |
135 mpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK; | |
136 // vf->dmpi->flags&=~MP_IMGFLAG_DRAW_CALLBACK; | |
137 } | |
138 | |
139 static void blank(mp_image_t *mpi, int y1, int y2) | |
140 { | |
141 int color[3] = {16, 128, 128}; // black (YUV) | |
142 int y; | |
143 unsigned char* dst; | |
144 int chroma_rows = (y2 - y1) >> mpi->chroma_y_shift; | |
145 | |
146 dst = mpi->planes[0] + y1 * mpi->stride[0]; | |
147 for (y = 0; y < y2 - y1; ++y) { | |
148 memset(dst, color[0], mpi->w); | |
149 dst += mpi->stride[0]; | |
150 } | |
151 dst = mpi->planes[1] + (y1 >> mpi->chroma_y_shift) * mpi->stride[1]; | |
152 for (y = 0; y < chroma_rows ; ++y) { | |
153 memset(dst, color[1], mpi->chroma_width); | |
154 dst += mpi->stride[1]; | |
155 } | |
156 dst = mpi->planes[2] + (y1 >> mpi->chroma_y_shift) * mpi->stride[2]; | |
157 for (y = 0; y < chroma_rows ; ++y) { | |
158 memset(dst, color[2], mpi->chroma_width); | |
159 dst += mpi->stride[2]; | |
160 } | |
161 } | |
162 | |
163 static int prepare_image(struct vf_instance_s* vf, mp_image_t *mpi) | |
164 { | |
165 if(mpi->flags&MP_IMGFLAG_DIRECT || mpi->flags&MP_IMGFLAG_DRAW_CALLBACK){ | |
166 vf->dmpi = mpi->priv; | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20477
diff
changeset
|
167 if (!vf->dmpi) { mp_msg(MSGT_ASS, MSGL_WARN, MSGTR_MPCODECS_FunWhydowegetNULL); return 0; } |
18937 | 168 mpi->priv = NULL; |
169 // we've used DR, so we're ready... | |
170 if (ass_top_margin) | |
171 blank(vf->dmpi, 0, ass_top_margin); | |
172 if (ass_bottom_margin) | |
173 blank(vf->dmpi, vf->priv->outh - ass_bottom_margin, vf->priv->outh); | |
174 if(!(mpi->flags&MP_IMGFLAG_PLANAR)) | |
175 vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette | |
176 return 0; | |
177 } | |
178 | |
179 // hope we'll get DR buffer: | |
180 vf->dmpi = vf_get_image(vf->next, vf->priv->outfmt, | |
20656
839c48c35ce8
ass renderer absolutely needs readable target mpi.
reimar
parents:
20629
diff
changeset
|
181 MP_IMGTYPE_TEMP, MP_IMGFLAG_ACCEPT_STRIDE | MP_IMGFLAG_READABLE, |
18937 | 182 vf->priv->outw, vf->priv->outh); |
183 | |
184 // copy mpi->dmpi... | |
185 if(mpi->flags&MP_IMGFLAG_PLANAR){ | |
186 memcpy_pic(vf->dmpi->planes[0] + ass_top_margin * vf->dmpi->stride[0], | |
187 mpi->planes[0], mpi->w, mpi->h, | |
188 vf->dmpi->stride[0], mpi->stride[0]); | |
189 memcpy_pic(vf->dmpi->planes[1] + (ass_top_margin >> mpi->chroma_y_shift) * vf->dmpi->stride[1], | |
190 mpi->planes[1], mpi->w >> mpi->chroma_x_shift, mpi->h >> mpi->chroma_y_shift, | |
191 vf->dmpi->stride[1], mpi->stride[1]); | |
192 memcpy_pic(vf->dmpi->planes[2] + (ass_top_margin >> mpi->chroma_y_shift) * vf->dmpi->stride[2], | |
193 mpi->planes[2], mpi->w >> mpi->chroma_x_shift, mpi->h >> mpi->chroma_y_shift, | |
194 vf->dmpi->stride[2], mpi->stride[2]); | |
195 } else { | |
196 memcpy_pic(vf->dmpi->planes[0] + ass_top_margin * vf->dmpi->stride[0], | |
197 mpi->planes[0], mpi->w*(vf->dmpi->bpp/8), mpi->h, | |
198 vf->dmpi->stride[0], mpi->stride[0]); | |
199 vf->dmpi->planes[1] = mpi->planes[1]; // passthrough rgb8 palette | |
200 } | |
201 if (ass_top_margin) | |
202 blank(vf->dmpi, 0, ass_top_margin); | |
203 if (ass_bottom_margin) | |
204 blank(vf->dmpi, vf->priv->outh - ass_bottom_margin, vf->priv->outh); | |
205 return 0; | |
206 } | |
207 | |
208 /** | |
209 * \brief Copy specified rows from render_context.dmpi to render_context.planes, upsampling to 4:4:4 | |
210 */ | |
211 static void copy_from_image(struct vf_instance_s* vf, int first_row, int last_row) | |
212 { | |
213 int pl; | |
214 int i, j, k; | |
215 unsigned char val; | |
216 int chroma_rows; | |
217 | |
218 first_row -= (first_row % 2); | |
219 last_row += (last_row % 2); | |
220 chroma_rows = (last_row - first_row) / 2; | |
221 | |
222 for (pl = 1; pl < 3; ++pl) { | |
21154 | 223 int dst_stride = vf->priv->outw; |
18937 | 224 int src_stride = vf->dmpi->stride[pl]; |
225 | |
226 unsigned char* src = vf->dmpi->planes[pl] + (first_row/2) * src_stride; | |
227 unsigned char* dst = vf->priv->planes[pl] + first_row * dst_stride; | |
228 unsigned char* dst_next = dst + dst_stride; | |
229 for(i = 0; i < chroma_rows; ++i) | |
230 { | |
231 if ((vf->priv->dirty_rows[first_row + i*2] == 0) || | |
232 (vf->priv->dirty_rows[first_row + i*2 + 1] == 0)) { | |
233 for (j = 0, k = 0; j < vf->dmpi->chroma_width; ++j, k+=2) { | |
234 val = *(src + j); | |
235 *(dst + k) = val; | |
236 *(dst + k + 1) = val; | |
237 *(dst_next + k) = val; | |
238 *(dst_next + k + 1) = val; | |
239 } | |
240 } | |
241 src += src_stride; | |
242 dst = dst_next + dst_stride; | |
243 dst_next = dst + dst_stride; | |
244 } | |
245 } | |
246 for (i = first_row; i < last_row; ++i) | |
247 vf->priv->dirty_rows[i] = 1; | |
248 } | |
249 | |
250 /** | |
251 * \brief Copy all previously copied rows back to render_context.dmpi | |
252 */ | |
253 static void copy_to_image(struct vf_instance_s* vf) | |
254 { | |
255 int pl; | |
256 int i, j, k; | |
257 for (pl = 1; pl < 3; ++pl) { | |
258 int dst_stride = vf->dmpi->stride[pl]; | |
21154 | 259 int src_stride = vf->priv->outw; |
18937 | 260 |
261 unsigned char* dst = vf->dmpi->planes[pl]; | |
262 unsigned char* src = vf->priv->planes[pl]; | |
263 unsigned char* src_next = vf->priv->planes[pl] + src_stride; | |
264 for(i = 0; i < vf->dmpi->chroma_height; ++i) | |
265 { | |
266 if ((vf->priv->dirty_rows[i*2] == 1)) { | |
267 assert(vf->priv->dirty_rows[i*2 + 1] == 1); | |
268 for (j = 0, k = 0; j < vf->dmpi->chroma_width; ++j, k+=2) { | |
269 unsigned val = 0; | |
270 val += *(src + k); | |
271 val += *(src + k + 1); | |
272 val += *(src_next + k); | |
273 val += *(src_next + k + 1); | |
274 *(dst + j) = val >> 2; | |
275 } | |
276 } | |
277 dst += dst_stride; | |
278 src = src_next + src_stride; | |
279 src_next = src + src_stride; | |
280 } | |
281 } | |
282 } | |
283 | |
284 static void my_draw_bitmap(struct vf_instance_s* vf, unsigned char* bitmap, int bitmap_w, int bitmap_h, int stride, int dst_x, int dst_y, unsigned color) | |
285 { | |
286 unsigned char y = rgba2y(color); | |
287 unsigned char u = rgba2u(color); | |
288 unsigned char v = rgba2v(color); | |
289 unsigned char opacity = 255 - _a(color); | |
20012 | 290 unsigned char *src, *dsty, *dstu, *dstv; |
18937 | 291 int i, j; |
292 mp_image_t* dmpi = vf->dmpi; | |
293 | |
294 src = bitmap; | |
20012 | 295 dsty = dmpi->planes[0] + dst_x + dst_y * dmpi->stride[0]; |
21154 | 296 dstu = vf->priv->planes[1] + dst_x + dst_y * vf->priv->outw; |
297 dstv = vf->priv->planes[2] + dst_x + dst_y * vf->priv->outw; | |
18937 | 298 for (i = 0; i < bitmap_h; ++i) { |
299 for (j = 0; j < bitmap_w; ++j) { | |
20012 | 300 unsigned k = ((unsigned)src[j]) * opacity / 255; |
301 dsty[j] = (k*y + (255-k)*dsty[j]) / 255; | |
302 dstu[j] = (k*u + (255-k)*dstu[j]) / 255; | |
303 dstv[j] = (k*v + (255-k)*dstv[j]) / 255; | |
18937 | 304 } |
20012 | 305 src += stride; |
306 dsty += dmpi->stride[0]; | |
21154 | 307 dstu += vf->priv->outw; |
308 dstv += vf->priv->outw; | |
18937 | 309 } |
310 } | |
311 | |
312 static int render_frame(struct vf_instance_s* vf, mp_image_t *mpi, const ass_image_t* img) | |
313 { | |
314 if (img) { | |
315 memset(vf->priv->dirty_rows, 0, vf->priv->outh); // reset dirty rows | |
316 while (img) { | |
317 copy_from_image(vf, img->dst_y, img->dst_y + img->h); | |
318 my_draw_bitmap(vf, img->bitmap, img->w, img->h, img->stride, | |
319 img->dst_x, img->dst_y, img->color); | |
320 img = img->next; | |
321 } | |
322 copy_to_image(vf); | |
323 } | |
324 return 0; | |
325 } | |
326 | |
327 static int put_image(struct vf_instance_s* vf, mp_image_t *mpi, double pts) | |
328 { | |
329 ass_image_t* images = 0; | |
330 if (sub_visibility && vf->priv->ass_priv && ass_track && (pts != MP_NOPTS_VALUE)) | |
25813 | 331 images = ass_mp_render_frame(vf->priv->ass_priv, ass_track, (pts+sub_delay) * 1000 + .5, NULL); |
18937 | 332 |
333 prepare_image(vf, mpi); | |
334 if (images) render_frame(vf, mpi, images); | |
335 | |
336 return vf_next_put_image(vf, vf->dmpi, pts); | |
337 } | |
338 | |
339 static int query_format(struct vf_instance_s* vf, unsigned int fmt) | |
340 { | |
341 switch(fmt){ | |
342 case IMGFMT_YV12: | |
343 case IMGFMT_I420: | |
344 case IMGFMT_IYUV: | |
345 return vf_next_query_format(vf, vf->priv->outfmt); | |
346 } | |
347 return 0; | |
348 } | |
349 | |
350 static int control(vf_instance_t *vf, int request, void *data) | |
351 { | |
19521 | 352 switch (request) { |
353 case VFCTRL_INIT_EOSD: | |
20477 | 354 vf->priv->ass_priv = ass_renderer_init((ass_library_t*)data); |
20706
6ae01628975f
Initialize fontconfig in VFCTRL_INIT_EOSD handler.
eugeni
parents:
20656
diff
changeset
|
355 if (!vf->priv->ass_priv) return CONTROL_FALSE; |
6ae01628975f
Initialize fontconfig in VFCTRL_INIT_EOSD handler.
eugeni
parents:
20656
diff
changeset
|
356 ass_configure_fonts(vf->priv->ass_priv); |
6ae01628975f
Initialize fontconfig in VFCTRL_INIT_EOSD handler.
eugeni
parents:
20656
diff
changeset
|
357 return CONTROL_TRUE; |
19521 | 358 case VFCTRL_DRAW_EOSD: |
359 if (vf->priv->ass_priv) return CONTROL_TRUE; | |
360 break; | |
18937 | 361 } |
362 return vf_next_control(vf, request, data); | |
363 } | |
364 | |
365 static void uninit(struct vf_instance_s* vf) | |
366 { | |
367 if (vf->priv->ass_priv) | |
20477 | 368 ass_renderer_done(vf->priv->ass_priv); |
18937 | 369 if (vf->priv->planes[1]) |
370 free(vf->priv->planes[1]); | |
371 if (vf->priv->planes[2]) | |
372 free(vf->priv->planes[2]); | |
373 if (vf->priv->dirty_rows) | |
374 free(vf->priv->dirty_rows); | |
375 } | |
376 | |
24969
c2b7ba444ade
begin moving const filter data to .text/.rodata sections
rfelker
parents:
24545
diff
changeset
|
377 static const unsigned int fmt_list[]={ |
18937 | 378 IMGFMT_YV12, |
379 IMGFMT_I420, | |
380 IMGFMT_IYUV, | |
381 0 | |
382 }; | |
383 | |
384 static int open(vf_instance_t *vf, char* args) | |
385 { | |
386 int flags; | |
387 vf->priv->outfmt = vf_match_csp(&vf->next,fmt_list,IMGFMT_YV12); | |
388 if (vf->priv->outfmt) | |
389 flags = vf_next_query_format(vf, vf->priv->outfmt); | |
390 if (!vf->priv->outfmt || (vf->priv->auto_insert && flags&VFCAP_EOSD)) | |
391 { | |
392 uninit(vf); | |
393 return 0; | |
394 } | |
395 | |
396 if (vf->priv->auto_insert) | |
20629
e8885ec63928
Introduce MSGT_ASS, use it for all libass messages.
eugeni
parents:
20477
diff
changeset
|
397 mp_msg(MSGT_ASS, MSGL_INFO, "[ass] auto-open\n"); |
18937 | 398 |
399 vf->config = config; | |
400 vf->query_format = query_format; | |
401 vf->uninit = uninit; | |
402 vf->control = control; | |
403 vf->get_image = get_image; | |
404 vf->put_image = put_image; | |
405 vf->default_caps=VFCAP_EOSD; | |
406 return 1; | |
407 } | |
408 | |
409 #define ST_OFF(f) M_ST_OFF(struct vf_priv_s,f) | |
24969
c2b7ba444ade
begin moving const filter data to .text/.rodata sections
rfelker
parents:
24545
diff
changeset
|
410 static const m_option_t vf_opts_fields[] = { |
18937 | 411 {"auto", ST_OFF(auto_insert), CONF_TYPE_FLAG, 0 , 0, 1, NULL}, |
412 { NULL, NULL, 0, 0, 0, 0, NULL } | |
413 }; | |
414 | |
24969
c2b7ba444ade
begin moving const filter data to .text/.rodata sections
rfelker
parents:
24545
diff
changeset
|
415 static const m_struct_t vf_opts = { |
18937 | 416 "ass", |
417 sizeof(struct vf_priv_s), | |
418 &vf_priv_dflt, | |
419 vf_opts_fields | |
420 }; | |
421 | |
24969
c2b7ba444ade
begin moving const filter data to .text/.rodata sections
rfelker
parents:
24545
diff
changeset
|
422 const vf_info_t vf_info_ass = { |
18937 | 423 "Render ASS/SSA subtitles", |
424 "ass", | |
425 "Evgeniy Stepanov", | |
426 "", | |
427 open, | |
428 &vf_opts | |
429 }; | |
430 |