vlc_image: add extradata as codec parameter
[vlc.git] / src / misc / subpicture.c
blobdd9fafe3ebc1dd26bbd08af7724fcbc158ec4aae
1 /*****************************************************************************
2 * subpicture.c: Subpicture functions
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
5 * $Id$
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 #include <assert.h>
33 #include <vlc_common.h>
34 #include <vlc_image.h>
35 #include <vlc_subpicture.h>
36 #include "subpicture.h"
38 struct subpicture_private_t
40 video_format_t src;
41 video_format_t dst;
44 subpicture_t *subpicture_New( const subpicture_updater_t *p_upd )
46 subpicture_t *p_subpic = calloc( 1, sizeof(*p_subpic) );
47 if( !p_subpic )
48 return NULL;
50 p_subpic->i_order = 0;
51 p_subpic->b_absolute = true;
52 p_subpic->b_fade = false;
53 p_subpic->b_subtitle = false;
54 p_subpic->i_alpha = 0xFF;
55 p_subpic->p_region = NULL;
57 if( p_upd )
59 subpicture_private_t *p_private = malloc( sizeof(*p_private) );
60 if( !p_private )
62 free( p_subpic );
63 return NULL;
65 video_format_Init( &p_private->src, 0 );
66 video_format_Init( &p_private->dst, 0 );
68 p_subpic->updater = *p_upd;
69 p_subpic->p_private = p_private;
71 else
73 p_subpic->p_private = NULL;
75 p_subpic->updater.pf_validate = NULL;
76 p_subpic->updater.pf_update = NULL;
77 p_subpic->updater.pf_destroy = NULL;
78 p_subpic->updater.p_sys = NULL;
80 return p_subpic;
83 void subpicture_Delete( subpicture_t *p_subpic )
85 subpicture_region_ChainDelete( p_subpic->p_region );
86 p_subpic->p_region = NULL;
88 if( p_subpic->updater.pf_destroy )
89 p_subpic->updater.pf_destroy( p_subpic );
91 if( p_subpic->p_private )
93 video_format_Clean( &p_subpic->p_private->src );
94 video_format_Clean( &p_subpic->p_private->dst );
97 free( p_subpic->p_private );
98 free( p_subpic );
101 subpicture_t *subpicture_NewFromPicture( vlc_object_t *p_obj,
102 picture_t *p_picture, vlc_fourcc_t i_chroma )
104 /* */
105 video_format_t fmt_in = p_picture->format;
107 /* */
108 video_format_t fmt_out;
109 fmt_out = fmt_in;
110 fmt_out.i_chroma = i_chroma;
112 /* */
113 image_handler_t *p_image = image_HandlerCreate( p_obj );
114 if( !p_image )
115 return NULL;
117 picture_t *p_pip = image_Convert( p_image, p_picture, &fmt_in, &fmt_out );
119 image_HandlerDelete( p_image );
121 if( !p_pip )
122 return NULL;
124 subpicture_t *p_subpic = subpicture_New( NULL );
125 if( !p_subpic )
127 picture_Release( p_pip );
128 return NULL;
131 p_subpic->i_original_picture_width = fmt_out.i_visible_width;
132 p_subpic->i_original_picture_height = fmt_out.i_visible_height;
134 fmt_out.i_sar_num =
135 fmt_out.i_sar_den = 0;
137 p_subpic->p_region = subpicture_region_New( &fmt_out );
138 if( p_subpic->p_region )
140 picture_Release( p_subpic->p_region->p_picture );
141 p_subpic->p_region->p_picture = p_pip;
143 else
145 picture_Release( p_pip );
147 return p_subpic;
150 void subpicture_Update( subpicture_t *p_subpicture,
151 const video_format_t *p_fmt_src,
152 const video_format_t *p_fmt_dst,
153 vlc_tick_t i_ts )
155 subpicture_updater_t *p_upd = &p_subpicture->updater;
156 subpicture_private_t *p_private = p_subpicture->p_private;
158 if( !p_upd->pf_validate )
159 return;
160 if( !p_upd->pf_validate( p_subpicture,
161 !video_format_IsSimilar( p_fmt_src,
162 &p_private->src ), p_fmt_src,
163 !video_format_IsSimilar( p_fmt_dst,
164 &p_private->dst ), p_fmt_dst,
165 i_ts ) )
166 return;
168 subpicture_region_ChainDelete( p_subpicture->p_region );
169 p_subpicture->p_region = NULL;
171 p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts );
173 video_format_Clean( &p_private->src );
174 video_format_Clean( &p_private->dst );
176 video_format_Copy( &p_private->src, p_fmt_src );
177 video_format_Copy( &p_private->dst, p_fmt_dst );
181 subpicture_region_private_t *subpicture_region_private_New( video_format_t *p_fmt )
183 subpicture_region_private_t *p_private = malloc( sizeof(*p_private) );
185 if( !p_private )
186 return NULL;
188 if ( video_format_Copy( &p_private->fmt, p_fmt ) != VLC_SUCCESS )
190 free( p_private );
191 return NULL;
194 p_private->p_picture = NULL;
195 return p_private;
198 void subpicture_region_private_Delete( subpicture_region_private_t *p_private )
200 if( p_private->p_picture )
201 picture_Release( p_private->p_picture );
202 video_format_Clean( &p_private->fmt );
203 free( p_private );
206 subpicture_region_t *subpicture_region_New( const video_format_t *p_fmt )
208 subpicture_region_t *p_region = calloc( 1, sizeof(*p_region ) );
209 if( !p_region )
210 return NULL;
212 if ( p_fmt->i_chroma == VLC_CODEC_YUVP )
214 video_format_Copy( &p_region->fmt, p_fmt );
215 /* YUVP should have a palette */
216 if( p_region->fmt.p_palette == NULL )
218 p_region->fmt.p_palette = calloc( 1, sizeof(*p_region->fmt.p_palette) );
219 if( p_region->fmt.p_palette == NULL )
221 free( p_region );
222 return NULL;
226 else
228 p_region->fmt = *p_fmt;
229 p_region->fmt.p_palette = NULL;
232 p_region->i_alpha = 0xff;
233 p_region->b_balanced_text = true;
235 if( p_fmt->i_chroma == VLC_CODEC_TEXT )
236 return p_region;
238 p_region->p_picture = picture_NewFromFormat( p_fmt );
239 if( !p_region->p_picture )
241 video_format_Clean( &p_region->fmt );
242 free( p_region );
243 return NULL;
246 return p_region;
249 void subpicture_region_Delete( subpicture_region_t *p_region )
251 if( !p_region )
252 return;
254 if( p_region->p_private )
255 subpicture_region_private_Delete( p_region->p_private );
257 if( p_region->p_picture )
258 picture_Release( p_region->p_picture );
260 text_segment_ChainDelete( p_region->p_text );
261 video_format_Clean( &p_region->fmt );
262 free( p_region );
265 void subpicture_region_ChainDelete( subpicture_region_t *p_head )
267 while( p_head )
269 subpicture_region_t *p_next = p_head->p_next;
271 subpicture_region_Delete( p_head );
273 p_head = p_next;
277 #include <vlc_filter.h>
279 unsigned picture_BlendSubpicture(picture_t *dst,
280 filter_t *blend, subpicture_t *src)
282 unsigned done = 0;
284 assert(src && !src->b_fade && src->b_absolute);
286 for (subpicture_region_t *r = src->p_region; r != NULL; r = r->p_next) {
287 assert(r->p_picture && r->i_align == 0);
288 if (filter_ConfigureBlend(blend, dst->format.i_width,
289 dst->format.i_height, &r->fmt)
290 || filter_Blend(blend, dst, r->i_x, r->i_y, r->p_picture,
291 src->i_alpha * r->i_alpha / 255))
292 msg_Err(blend, "blending %4.4s to %4.4s failed",
293 (char *)&blend->fmt_in.video.i_chroma,
294 (char *)&blend->fmt_out.video.i_chroma );
295 else
296 done++;
298 return done;
301 subpicture_region_t* subpicture_region_Copy( subpicture_region_t *p_region_src )
303 if (!p_region_src)
304 return NULL;
305 subpicture_region_t *p_region_dst = subpicture_region_New(&p_region_src->fmt);
306 if (unlikely(!p_region_dst))
307 return NULL;
309 p_region_dst->i_x = p_region_src->i_x;
310 p_region_dst->i_y = p_region_src->i_y;
311 p_region_dst->i_align = p_region_src->i_align;
312 p_region_dst->i_alpha = p_region_src->i_alpha;
314 p_region_dst->p_text = text_segment_Copy( p_region_src->p_text );
316 //Palette is already copied by subpicture_region_New, we just have to duplicate p_pixels
317 for (int i = 0; i < p_region_src->p_picture->i_planes; i++)
318 memcpy(p_region_dst->p_picture->p[i].p_pixels,
319 p_region_src->p_picture->p[i].p_pixels,
320 p_region_src->p_picture->p[i].i_lines * p_region_src->p_picture->p[i].i_pitch);
321 return p_region_dst;