contrib: Bump libmicrodns to 0.1.2
[vlc.git] / src / misc / subpicture.c
blob6dcd6618104e89d4f4af09b777edc48a8e55d118
1 /*****************************************************************************
2 * subpicture.c: Subpicture functions
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
6 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program 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 Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 /*****************************************************************************
24 * Preamble
25 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30 #include <assert.h>
32 #include <vlc_common.h>
33 #include <vlc_image.h>
34 #include <vlc_subpicture.h>
35 #include "subpicture.h"
37 struct subpicture_private_t
39 video_format_t src;
40 video_format_t dst;
43 subpicture_t *subpicture_New( const subpicture_updater_t *p_upd )
45 subpicture_t *p_subpic = calloc( 1, sizeof(*p_subpic) );
46 if( !p_subpic )
47 return NULL;
49 p_subpic->i_order = 0;
50 p_subpic->b_absolute = true;
51 p_subpic->b_fade = false;
52 p_subpic->b_subtitle = false;
53 p_subpic->i_alpha = 0xFF;
54 p_subpic->p_region = NULL;
56 if( p_upd )
58 subpicture_private_t *p_private = malloc( sizeof(*p_private) );
59 if( !p_private )
61 free( p_subpic );
62 return NULL;
64 video_format_Init( &p_private->src, 0 );
65 video_format_Init( &p_private->dst, 0 );
67 p_subpic->updater = *p_upd;
68 p_subpic->p_private = p_private;
70 else
72 p_subpic->p_private = NULL;
74 p_subpic->updater.pf_validate = NULL;
75 p_subpic->updater.pf_update = NULL;
76 p_subpic->updater.pf_destroy = NULL;
77 p_subpic->updater.p_sys = NULL;
79 return p_subpic;
82 void subpicture_Delete( subpicture_t *p_subpic )
84 subpicture_region_ChainDelete( p_subpic->p_region );
85 p_subpic->p_region = NULL;
87 if( p_subpic->updater.pf_destroy )
88 p_subpic->updater.pf_destroy( p_subpic );
90 if( p_subpic->p_private )
92 video_format_Clean( &p_subpic->p_private->src );
93 video_format_Clean( &p_subpic->p_private->dst );
96 free( p_subpic->p_private );
97 free( p_subpic );
100 subpicture_t *subpicture_NewFromPicture( vlc_object_t *p_obj,
101 picture_t *p_picture, vlc_fourcc_t i_chroma )
103 /* */
104 video_format_t fmt_in = p_picture->format;
106 /* */
107 video_format_t fmt_out;
108 fmt_out = fmt_in;
109 fmt_out.i_chroma = i_chroma;
111 /* */
112 image_handler_t *p_image = image_HandlerCreate( p_obj );
113 if( !p_image )
114 return NULL;
116 picture_t *p_pip = image_Convert( p_image, p_picture, &fmt_in, &fmt_out );
118 image_HandlerDelete( p_image );
120 if( !p_pip )
121 return NULL;
123 subpicture_t *p_subpic = subpicture_New( NULL );
124 if( !p_subpic )
126 picture_Release( p_pip );
127 return NULL;
130 p_subpic->i_original_picture_width = fmt_out.i_visible_width;
131 p_subpic->i_original_picture_height = fmt_out.i_visible_height;
133 fmt_out.i_sar_num =
134 fmt_out.i_sar_den = 0;
136 p_subpic->p_region = subpicture_region_New( &fmt_out );
137 if( p_subpic->p_region )
139 picture_Release( p_subpic->p_region->p_picture );
140 p_subpic->p_region->p_picture = p_pip;
142 else
144 picture_Release( p_pip );
146 return p_subpic;
149 void subpicture_Update( subpicture_t *p_subpicture,
150 const video_format_t *p_fmt_src,
151 const video_format_t *p_fmt_dst,
152 vlc_tick_t i_ts )
154 subpicture_updater_t *p_upd = &p_subpicture->updater;
155 subpicture_private_t *p_private = p_subpicture->p_private;
157 if( !p_upd->pf_validate )
158 return;
159 if( !p_upd->pf_validate( p_subpicture,
160 !video_format_IsSimilar( p_fmt_src,
161 &p_private->src ), p_fmt_src,
162 !video_format_IsSimilar( p_fmt_dst,
163 &p_private->dst ), p_fmt_dst,
164 i_ts ) )
165 return;
167 subpicture_region_ChainDelete( p_subpicture->p_region );
168 p_subpicture->p_region = NULL;
170 p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts );
172 video_format_Clean( &p_private->src );
173 video_format_Clean( &p_private->dst );
175 video_format_Copy( &p_private->src, p_fmt_src );
176 video_format_Copy( &p_private->dst, p_fmt_dst );
180 subpicture_region_private_t *subpicture_region_private_New( video_format_t *p_fmt )
182 subpicture_region_private_t *p_private = malloc( sizeof(*p_private) );
184 if( !p_private )
185 return NULL;
187 if ( video_format_Copy( &p_private->fmt, p_fmt ) != VLC_SUCCESS )
189 free( p_private );
190 return NULL;
193 p_private->p_picture = NULL;
194 return p_private;
197 void subpicture_region_private_Delete( subpicture_region_private_t *p_private )
199 if( p_private->p_picture )
200 picture_Release( p_private->p_picture );
201 video_format_Clean( &p_private->fmt );
202 free( p_private );
205 subpicture_region_t * subpicture_region_NewInternal( const video_format_t *p_fmt )
207 subpicture_region_t *p_region = calloc( 1, sizeof(*p_region ) );
208 if( !p_region )
209 return NULL;
211 p_region->zoom_h.den = p_region->zoom_h.num = 1;
212 p_region->zoom_v.den = p_region->zoom_v.num = 1;
214 if ( p_fmt->i_chroma == VLC_CODEC_YUVP )
216 video_format_Copy( &p_region->fmt, p_fmt );
217 /* YUVP should have a palette */
218 if( p_region->fmt.p_palette == NULL )
220 p_region->fmt.p_palette = calloc( 1, sizeof(*p_region->fmt.p_palette) );
221 if( p_region->fmt.p_palette == NULL )
223 free( p_region );
224 return NULL;
228 else
230 p_region->fmt = *p_fmt;
231 p_region->fmt.p_palette = NULL;
234 p_region->i_alpha = 0xff;
235 p_region->b_balanced_text = true;
237 return p_region;
240 subpicture_region_t *subpicture_region_New( const video_format_t *p_fmt )
242 subpicture_region_t *p_region =
243 subpicture_region_NewInternal( p_fmt );
244 if( !p_region )
245 return NULL;
247 if( p_fmt->i_chroma == VLC_CODEC_TEXT )
248 return p_region;
250 p_region->p_picture = picture_NewFromFormat( p_fmt );
251 if( !p_region->p_picture )
253 video_format_Clean( &p_region->fmt );
254 free( p_region );
255 return NULL;
258 return p_region;
261 void subpicture_region_Delete( subpicture_region_t *p_region )
263 if( !p_region )
264 return;
266 if( p_region->p_private )
267 subpicture_region_private_Delete( p_region->p_private );
269 if( p_region->p_picture )
270 picture_Release( p_region->p_picture );
272 text_segment_ChainDelete( p_region->p_text );
273 video_format_Clean( &p_region->fmt );
274 free( p_region );
277 void subpicture_region_ChainDelete( subpicture_region_t *p_head )
279 while( p_head )
281 subpicture_region_t *p_next = p_head->p_next;
283 subpicture_region_Delete( p_head );
285 p_head = p_next;
289 #include <vlc_filter.h>
291 unsigned picture_BlendSubpicture(picture_t *dst,
292 vlc_blender_t *blend, subpicture_t *src)
294 unsigned done = 0;
296 assert(src && !src->b_fade && src->b_absolute);
298 for (subpicture_region_t *r = src->p_region; r != NULL; r = r->p_next) {
299 assert(r->p_picture && r->i_align == 0);
300 if (filter_ConfigureBlend(blend, dst->format.i_width,
301 dst->format.i_height, &r->fmt)
302 || filter_Blend(blend, dst, r->i_x, r->i_y, r->p_picture,
303 src->i_alpha * r->i_alpha / 255))
304 msg_Err(blend, "blending %4.4s to %4.4s failed",
305 (char *)&blend->fmt_in.video.i_chroma,
306 (char *)&blend->fmt_out.video.i_chroma );
307 else
308 done++;
310 return done;
313 subpicture_region_t* subpicture_region_Copy( subpicture_region_t *p_region_src )
315 if (!p_region_src)
316 return NULL;
317 subpicture_region_t *p_region_dst = subpicture_region_New(&p_region_src->fmt);
318 if (unlikely(!p_region_dst))
319 return NULL;
321 p_region_dst->i_x = p_region_src->i_x;
322 p_region_dst->i_y = p_region_src->i_y;
323 p_region_dst->i_align = p_region_src->i_align;
324 p_region_dst->i_alpha = p_region_src->i_alpha;
326 p_region_dst->p_text = text_segment_Copy( p_region_src->p_text );
328 //Palette is already copied by subpicture_region_New, we just have to duplicate p_pixels
329 for (int i = 0; i < p_region_src->p_picture->i_planes; i++)
330 memcpy(p_region_dst->p_picture->p[i].p_pixels,
331 p_region_src->p_picture->p[i].p_pixels,
332 p_region_src->p_picture->p[i].i_lines * p_region_src->p_picture->p[i].i_pitch);
333 return p_region_dst;