]> git.sesse.net Git - vlc/blob - src/misc/subpicture.c
decoder: inline DecoderSignalWait()
[vlc] / src / misc / subpicture.c
1 /*****************************************************************************
2  * subpicture.c: Subpicture functions
3  *****************************************************************************
4  * Copyright (C) 2010 Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
5  * $Id$
6  *
7  * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
8  *
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.
13  *
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.
18  *
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  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31 #include <assert.h>
32
33 #include <vlc_common.h>
34 #include <vlc_image.h>
35 #include <vlc_subpicture.h>
36 #include "subpicture.h"
37
38 struct subpicture_private_t
39 {
40     video_format_t src;
41     video_format_t dst;
42 };
43
44 subpicture_t *subpicture_New( const subpicture_updater_t *p_upd )
45 {
46     subpicture_t *p_subpic = calloc( 1, sizeof(*p_subpic) );
47     if( !p_subpic )
48         return NULL;
49
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;
56
57     if( p_upd )
58     {
59         subpicture_private_t *p_private = malloc( sizeof(*p_private) );
60         if( !p_private )
61         {
62             free( p_subpic );
63             return NULL;
64         }
65         video_format_Init( &p_private->src, 0 );
66         video_format_Init( &p_private->dst, 0 );
67
68         p_subpic->updater   = *p_upd;
69         p_subpic->p_private = p_private;
70     }
71     else
72     {
73         p_subpic->p_private = NULL;
74
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;
79     }
80     return p_subpic;
81 }
82
83 void subpicture_Delete( subpicture_t *p_subpic )
84 {
85     subpicture_region_ChainDelete( p_subpic->p_region );
86     p_subpic->p_region = NULL;
87
88     if( p_subpic->updater.pf_destroy )
89         p_subpic->updater.pf_destroy( p_subpic );
90
91     if( p_subpic->p_private )
92     {
93         video_format_Clean( &p_subpic->p_private->src );
94         video_format_Clean( &p_subpic->p_private->dst );
95     }
96
97     free( p_subpic->p_private );
98     free( p_subpic );
99 }
100
101 subpicture_t *subpicture_NewFromPicture( vlc_object_t *p_obj,
102                                          picture_t *p_picture, vlc_fourcc_t i_chroma )
103 {
104     /* */
105     video_format_t fmt_in = p_picture->format;
106
107     /* */
108     video_format_t fmt_out;
109     fmt_out = fmt_in;
110     fmt_out.i_chroma = i_chroma;
111
112     /* */
113     image_handler_t *p_image = image_HandlerCreate( p_obj );
114     if( !p_image )
115         return NULL;
116
117     picture_t *p_pip = image_Convert( p_image, p_picture, &fmt_in, &fmt_out );
118
119     image_HandlerDelete( p_image );
120
121     if( !p_pip )
122         return NULL;
123
124     subpicture_t *p_subpic = subpicture_New( NULL );
125     if( !p_subpic )
126     {
127          picture_Release( p_pip );
128          return NULL;
129     }
130
131     p_subpic->i_original_picture_width  = fmt_out.i_width;
132     p_subpic->i_original_picture_height = fmt_out.i_height;
133
134     fmt_out.i_sar_num =
135     fmt_out.i_sar_den = 0;
136
137     p_subpic->p_region = subpicture_region_New( &fmt_out );
138     if( p_subpic->p_region )
139     {
140         picture_Release( p_subpic->p_region->p_picture );
141         p_subpic->p_region->p_picture = p_pip;
142     }
143     else
144     {
145         picture_Release( p_pip );
146     }
147     return p_subpic;
148 }
149
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                         mtime_t i_ts )
154 {
155     subpicture_updater_t *p_upd = &p_subpicture->updater;
156     subpicture_private_t *p_private = p_subpicture->p_private;
157
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;
167
168     subpicture_region_ChainDelete( p_subpicture->p_region );
169     p_subpicture->p_region = NULL;
170
171     p_upd->pf_update( p_subpicture, p_fmt_src, p_fmt_dst, i_ts );
172
173     video_format_Clean( &p_private->src );
174     video_format_Clean( &p_private->dst );
175
176     video_format_Copy( &p_private->src, p_fmt_src );
177     video_format_Copy( &p_private->dst, p_fmt_dst );
178 }
179
180
181 subpicture_region_private_t *subpicture_region_private_New( video_format_t *p_fmt )
182 {
183     subpicture_region_private_t *p_private = malloc( sizeof(*p_private) );
184
185     if( !p_private )
186         return NULL;
187
188     p_private->fmt = *p_fmt;
189     if( p_fmt->p_palette )
190     {
191         p_private->fmt.p_palette = malloc( sizeof(*p_private->fmt.p_palette) );
192         if( p_private->fmt.p_palette )
193             *p_private->fmt.p_palette = *p_fmt->p_palette;
194     }
195     p_private->p_picture = NULL;
196
197     return p_private;
198 }
199
200 void subpicture_region_private_Delete( subpicture_region_private_t *p_private )
201 {
202     if( p_private->p_picture )
203         picture_Release( p_private->p_picture );
204     free( p_private->fmt.p_palette );
205     free( p_private );
206 }
207
208 subpicture_region_t *subpicture_region_New( const video_format_t *p_fmt )
209 {
210     subpicture_region_t *p_region = calloc( 1, sizeof(*p_region ) );
211     if( !p_region )
212         return NULL;
213
214     p_region->fmt = *p_fmt;
215     p_region->fmt.p_palette = NULL;
216     if( p_fmt->i_chroma == VLC_CODEC_YUVP )
217     {
218         p_region->fmt.p_palette = calloc( 1, sizeof(*p_region->fmt.p_palette) );
219         if( p_fmt->p_palette )
220             *p_region->fmt.p_palette = *p_fmt->p_palette;
221     }
222     p_region->i_alpha = 0xff;
223     p_region->p_next = NULL;
224     p_region->p_private = NULL;
225     p_region->psz_text = NULL;
226     p_region->p_style = NULL;
227     p_region->p_picture = NULL;
228
229     if( p_fmt->i_chroma == VLC_CODEC_TEXT )
230         return p_region;
231
232     p_region->p_picture = picture_NewFromFormat( p_fmt );
233     if( !p_region->p_picture )
234     {
235         free( p_region->fmt.p_palette );
236         free( p_region );
237         return NULL;
238     }
239
240     return p_region;
241 }
242
243 void subpicture_region_Delete( subpicture_region_t *p_region )
244 {
245     if( !p_region )
246         return;
247
248     if( p_region->p_private )
249         subpicture_region_private_Delete( p_region->p_private );
250
251     if( p_region->p_picture )
252         picture_Release( p_region->p_picture );
253
254     free( p_region->fmt.p_palette );
255
256     free( p_region->psz_text );
257     free( p_region->psz_html );
258     if( p_region->p_style )
259         text_style_Delete( p_region->p_style );
260     free( p_region );
261 }
262
263 void subpicture_region_ChainDelete( subpicture_region_t *p_head )
264 {
265     while( p_head )
266     {
267         subpicture_region_t *p_next = p_head->p_next;
268
269         subpicture_region_Delete( p_head );
270
271         p_head = p_next;
272     }
273 }
274