]> git.sesse.net Git - vlc/blob - modules/codec/kate.c
Use var_InheritString for --decklink-video-connection.
[vlc] / modules / codec / kate.c
1 /*****************************************************************************
2  * kate.c : a decoder for the kate bitstream format
3  *****************************************************************************
4  * Copyright (C) 2000-2008 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 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 General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
30
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_input.h>
34 #include <vlc_codec.h>
35 #include "../demux/xiph.h"
36
37 #include <kate/kate.h>
38 #ifdef HAVE_TIGER
39 # include <tiger/tiger.h>
40 #endif
41
42 /* #define ENABLE_PACKETIZER */
43 /* #define ENABLE_PROFILE */
44
45 #ifdef ENABLE_PROFILE
46 # define PROFILE_START(name) int64_t profile_start_##name = mdate()
47 # define PROFILE_STOP(name) fprintf( stderr, #name ": %f ms\n", (mdate() - profile_start_##name)/1000.0f )
48 #else
49 # define PROFILE_START(name) ((void)0)
50 # define PROFILE_STOP(name) ((void)0)
51 #endif
52
53 #define CHECK_TIGER_RET( statement )                                   \
54     do                                                                 \
55     {                                                                  \
56         int i_ret = (statement);                                       \
57         if( i_ret < 0 )                                                \
58         {                                                              \
59             msg_Dbg( p_dec, "Error in " #statement ": %d", i_ret );    \
60         }                                                              \
61     } while( 0 )
62
63 /*****************************************************************************
64  * decoder_sys_t : decoder descriptor
65  *****************************************************************************/
66 struct decoder_sys_t
67 {
68 #ifdef ENABLE_PACKETIZER
69     /* Module mode */
70     bool b_packetizer;
71 #endif
72
73     /*
74      * Input properties
75      */
76     bool b_has_headers;
77
78     /*
79      * Kate properties
80      */
81     bool           b_ready;
82     kate_info      ki;
83     kate_comment   kc;
84     kate_state     k;
85
86     /*
87      * Common properties
88      */
89     mtime_t i_pts;
90     mtime_t i_max_stop;
91
92     /* decoder_sys_t is shared between decoder and spu units */
93     vlc_mutex_t lock;
94     int         i_refcount;
95
96 #ifdef HAVE_TIGER
97     /*
98      * Tiger properties
99      */
100     tiger_renderer    *p_tr;
101     bool               b_dirty;
102
103     uint32_t           i_tiger_default_font_color;
104     uint32_t           i_tiger_default_background_color;
105     tiger_font_effect  e_tiger_default_font_effect;
106     double             f_tiger_default_font_effect_strength;
107     char              *psz_tiger_default_font_desc;
108     double             f_tiger_quality;
109 #endif
110
111     /*
112      * Options
113      */
114     bool   b_formatted;
115     bool   b_use_tiger;
116 };
117
118 struct subpicture_updater_sys_t
119 {
120     decoder_sys_t *p_dec_sys;
121     mtime_t        i_start;
122 };
123
124
125 /*
126  * This is a global list of existing decoders.
127  * The reason for this list is that:
128  *  - I want to be able to reconfigure Tiger when user prefs change
129  *  - User prefs are variables which are not specific to a decoder (eg, if
130  *    there are several decoders, there will still be one set of variables)
131  *  - A callback set on those will not be passed a pointer to the decoder
132  *    (as the decoder isn't known, and there could be multiple ones)
133  *  - Creating variables in the decoder will create different ones, with
134  *    values copied from the relevant user pref, so a callback on those
135  *    won't be called when the user pref is changed
136  * Therefore, each decoder will register/unregister itself with this list,
137  * callbacks will be set for the user prefs, and these will in turn walk
138  * through this list and tell each decoder to update the relevant variable.
139  * HOWEVER.
140  * VLC's variable system is still in my way as I can't get the value of
141  * the user pref variables at decoder start *unless* I create my own vars
142  * which inherit from the user ones, but those are utterly useless after
143  * that first use, since they'll be detached from the ones the user can
144  * change. So, I create them, read their values, and then destroy them.
145  */
146 static vlc_mutex_t kate_decoder_list_mutex = VLC_STATIC_MUTEX;
147 static size_t kate_decoder_list_size = 0;
148 static decoder_t **kate_decoder_list = NULL;
149
150 /*****************************************************************************
151  * Local prototypes
152  *****************************************************************************/
153 static int  OpenDecoder   ( vlc_object_t * );
154 static void CloseDecoder  ( vlc_object_t * );
155 #ifdef ENABLE_PACKETIZER
156 static int OpenPacketizer( vlc_object_t *p_this );
157 #endif
158
159 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block );
160 static int ProcessHeaders( decoder_t *p_dec );
161 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
162                             block_t **pp_block );
163 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp,
164                             block_t *p_block );
165 static void ParseKateComments( decoder_t * );
166 static subpicture_t *SetupSimpleKateSPU( decoder_t *p_dec, subpicture_t *p_spu,
167                             const kate_event *ev );
168 static void DecSysRelease( decoder_sys_t *p_sys );
169 static void DecSysHold( decoder_sys_t *p_sys );
170 #ifdef HAVE_TIGER
171 static uint32_t GetTigerColor( decoder_t *p_dec, const char *psz_prefix );
172 static char *GetTigerString( decoder_t *p_dec, const char *psz_name );
173 static int GetTigerInteger( decoder_t *p_dec, const char *psz_name );
174 static double GetTigerFloat( decoder_t *p_dec, const char *psz_name );
175 static void UpdateTigerFontColor( decoder_t *p_dec );
176 static void UpdateTigerBackgroundColor( decoder_t *p_dec );
177 static void UpdateTigerFontEffect( decoder_t *p_dec );
178 static void UpdateTigerQuality( decoder_t *p_dec );
179 static void UpdateTigerFontDesc( decoder_t *p_dec );
180 static int TigerConfigurationCallback( vlc_object_t *p_this, const char *psz_var,
181                                        vlc_value_t oldvar, vlc_value_t newval,
182                                        void *p_data );
183 static int OnConfigurationChanged( decoder_t *p_dec, const char *psz_var,
184                                    vlc_value_t oldval, vlc_value_t newval);
185 #endif
186
187 #define DEFAULT_NAME "Default"
188 #define MAX_LINE 8192
189
190 /*****************************************************************************
191  * Module descriptor.
192  *****************************************************************************/
193
194 #define FORMAT_TEXT N_("Formatted Subtitles")
195 #define FORMAT_LONGTEXT N_("Kate streams allow for text formatting. " \
196  "VLC partly implements this, but you can choose to disable all formatting." \
197  "Note that this has no effect is rendering via Tiger is enabled.")
198
199 #ifdef HAVE_TIGER
200
201 static const tiger_font_effect pi_font_effects[] = { tiger_font_plain, tiger_font_shadow, tiger_font_outline };
202 static const char * const ppsz_font_effect_names[] = { N_("None"), N_("Shadow"), N_("Outline") };
203
204 /* nicked off freetype.c */
205 static const int pi_color_values[] = {
206   0x00000000, 0x00808080, 0x00C0C0C0, 0x00FFFFFF, 0x00800000,
207   0x00FF0000, 0x00FF00FF, 0x00FFFF00, 0x00808000, 0x00008000, 0x00008080,
208   0x0000FF00, 0x00800080, 0x00000080, 0x000000FF, 0x0000FFFF };
209 static const char *const ppsz_color_descriptions[] = {
210   N_("Black"), N_("Gray"), N_("Silver"), N_("White"), N_("Maroon"),
211   N_("Red"), N_("Fuchsia"), N_("Yellow"), N_("Olive"), N_("Green"), N_("Teal"),
212   N_("Lime"), N_("Purple"), N_("Navy"), N_("Blue"), N_("Aqua") };
213
214 #define TIGER_TEXT N_("Use Tiger for rendering")
215 #define TIGER_LONGTEXT N_("Kate streams can be rendered using the Tiger library. " \
216  "Disabling this will only render static text and bitmap based streams.")
217
218 #define TIGER_QUALITY_DEFAULT 1.0
219 #define TIGER_QUALITY_TEXT N_("Rendering quality")
220 #define TIGER_QUALITY_LONGTEXT N_("Select rendering quality, at the expense of speed. " \
221  "0 is fastest, 1 is highest quality.")
222
223 #define TIGER_DEFAULT_FONT_EFFECT_DEFAULT 0
224 #define TIGER_DEFAULT_FONT_EFFECT_TEXT N_("Default font effect")
225 #define TIGER_DEFAULT_FONT_EFFECT_LONGTEXT N_("Add a font effect to text to improve readability " \
226  "against different backgrounds.")
227
228 #define TIGER_DEFAULT_FONT_EFFECT_STRENGTH_DEFAULT 0.5
229 #define TIGER_DEFAULT_FONT_EFFECT_STRENGTH_TEXT N_("Default font effect strength")
230 #define TIGER_DEFAULT_FONT_EFFECT_STRENGTH_LONGTEXT N_("How pronounced to make the chosen font effect " \
231  "(effect dependent).")
232
233 #define TIGER_DEFAULT_FONT_DESC_DEFAULT ""
234 #define TIGER_DEFAULT_FONT_DESC_TEXT N_("Default font description")
235 #define TIGER_DEFAULT_FONT_DESC_LONGTEXT N_("Which font description to use if the Kate stream " \
236  "does not specify particular font parameters (name, size, etc) to use. " \
237  "A blank name will let Tiger choose font parameters where appropriate.")
238
239 #define TIGER_DEFAULT_FONT_COLOR_DEFAULT 0x00ffffff
240 #define TIGER_DEFAULT_FONT_COLOR_TEXT N_("Default font color")
241 #define TIGER_DEFAULT_FONT_COLOR_LONGTEXT N_("Default font color to use if the Kate stream " \
242  "does not specify a particular font color to use.")
243
244 #define TIGER_DEFAULT_FONT_ALPHA_DEFAULT 0xff
245 #define TIGER_DEFAULT_FONT_ALPHA_TEXT N_("Default font alpha")
246 #define TIGER_DEFAULT_FONT_ALPHA_LONGTEXT N_("Transparency of the default font color if the Kate stream " \
247  "does not specify a particular font color to use.")
248
249 #define TIGER_DEFAULT_BACKGROUND_COLOR_DEFAULT 0x00ffffff
250 #define TIGER_DEFAULT_BACKGROUND_COLOR_TEXT N_("Default background color")
251 #define TIGER_DEFAULT_BACKGROUND_COLOR_LONGTEXT N_("Default background color if the Kate stream " \
252  "does not specify a background color to use.")
253
254 #define TIGER_DEFAULT_BACKGROUND_ALPHA_DEFAULT 0
255 #define TIGER_DEFAULT_BACKGROUND_ALPHA_TEXT N_("Default background alpha")
256 #define TIGER_DEFAULT_BACKGROUND_ALPHA_LONGTEXT N_("Transparency of the default background color if the Kate stream " \
257  "does not specify a particular background color to use.")
258
259 #endif
260
261 #define HELP_TEXT N_( \
262     "Kate is a codec for text and image based overlays.\n" \
263     "The Tiger rendering library is needed to render complex Kate streams, " \
264     "but VLC can still render static text and image based subtitles if " \
265     "it is not available.\n" \
266     "Note that changing settings below will not take effect until a new stream is played. " \
267     "This will hopefully be fixed soon." \
268     )
269
270 vlc_module_begin ()
271     set_shortname( N_("Kate"))
272     set_description( N_("Kate overlay decoder") )
273     set_help( HELP_TEXT )
274     set_capability( "decoder", 50 )
275     set_callbacks( OpenDecoder, CloseDecoder )
276     set_category( CAT_INPUT )
277     set_subcategory( SUBCAT_INPUT_SCODEC )
278     add_shortcut( "kate" )
279
280     add_bool( "kate-formatted", true, NULL, FORMAT_TEXT, FORMAT_LONGTEXT,
281               true )
282
283 #ifdef HAVE_TIGER
284     add_bool( "kate-use-tiger", true, NULL, TIGER_TEXT, TIGER_LONGTEXT,
285               true )
286     add_float_with_range( "kate-tiger-quality",
287                           TIGER_QUALITY_DEFAULT, 0.0f, 1.0f, TigerConfigurationCallback,
288                           TIGER_QUALITY_TEXT, TIGER_QUALITY_LONGTEXT,
289                           true )
290
291     set_section( N_("Tiger rendering defaults"), NULL );
292     add_string( "kate-tiger-default-font-desc",
293                 TIGER_DEFAULT_FONT_DESC_DEFAULT, TigerConfigurationCallback,
294                 TIGER_DEFAULT_FONT_DESC_TEXT, TIGER_DEFAULT_FONT_DESC_LONGTEXT, true);
295     add_integer_with_range( "kate-tiger-default-font-effect",
296                             TIGER_DEFAULT_FONT_EFFECT_DEFAULT,
297                             0, sizeof(pi_font_effects)/sizeof(pi_font_effects[0])-1, TigerConfigurationCallback,
298                             TIGER_DEFAULT_FONT_EFFECT_TEXT, TIGER_DEFAULT_FONT_EFFECT_LONGTEXT,
299                             true )
300     change_integer_list( pi_font_effects, ppsz_font_effect_names, NULL );
301     add_float_with_range( "kate-tiger-default-font-effect-strength",
302               TIGER_DEFAULT_FONT_EFFECT_STRENGTH_DEFAULT, 0.0f, 1.0f, TigerConfigurationCallback,
303               TIGER_DEFAULT_FONT_EFFECT_STRENGTH_TEXT, TIGER_DEFAULT_FONT_EFFECT_STRENGTH_LONGTEXT,
304               true )
305     add_integer_with_range( "kate-tiger-default-font-color",
306                             TIGER_DEFAULT_FONT_COLOR_DEFAULT, 0, 0x00ffffff, TigerConfigurationCallback,
307                             TIGER_DEFAULT_FONT_COLOR_TEXT, TIGER_DEFAULT_FONT_COLOR_LONGTEXT,
308                             true);
309     change_integer_list( pi_color_values, ppsz_color_descriptions, NULL );
310     add_integer_with_range( "kate-tiger-default-font-alpha",
311                             TIGER_DEFAULT_FONT_ALPHA_DEFAULT, 0, 255, TigerConfigurationCallback,
312                             TIGER_DEFAULT_FONT_ALPHA_TEXT, TIGER_DEFAULT_FONT_ALPHA_LONGTEXT,
313                             true);
314     add_integer_with_range( "kate-tiger-default-background-color",
315                             TIGER_DEFAULT_BACKGROUND_COLOR_DEFAULT, 0, 0x00ffffff, TigerConfigurationCallback,
316                             TIGER_DEFAULT_BACKGROUND_COLOR_TEXT, TIGER_DEFAULT_BACKGROUND_COLOR_LONGTEXT,
317                             true);
318     change_integer_list( pi_color_values, ppsz_color_descriptions, NULL );
319     add_integer_with_range( "kate-tiger-default-background-alpha",
320                             TIGER_DEFAULT_BACKGROUND_ALPHA_DEFAULT, 0, 255, TigerConfigurationCallback,
321                             TIGER_DEFAULT_BACKGROUND_ALPHA_TEXT, TIGER_DEFAULT_BACKGROUND_ALPHA_LONGTEXT,
322                             true);
323 #endif
324
325 #ifdef ENABLE_PACKETIZER
326     add_submodule ()
327     set_description( N_("Kate text subtitles packetizer") )
328     set_capability( "packetizer", 100 )
329     set_callbacks( OpenPacketizer, CloseDecoder )
330     add_shortcut( "kate" )
331 #endif
332
333 vlc_module_end ()
334
335 /*****************************************************************************
336  * OpenDecoder: probe the decoder and return score
337  *****************************************************************************
338  * Tries to launch a decoder and return score so that the interface is able
339  * to chose.
340  *****************************************************************************/
341 static int OpenDecoder( vlc_object_t *p_this )
342 {
343     decoder_t     *p_dec = (decoder_t*)p_this;
344     decoder_sys_t *p_sys;
345
346     if( p_dec->fmt_in.i_codec != VLC_CODEC_KATE )
347     {
348         return VLC_EGENERIC;
349     }
350
351     msg_Dbg( p_dec, "kate: OpenDecoder");
352
353     /* Set callbacks */
354     p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **))
355         DecodeBlock;
356     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
357         DecodeBlock;
358
359     /* Allocate the memory needed to store the decoder's structure */
360     if( ( p_dec->p_sys = p_sys = malloc(sizeof(*p_sys)) ) == NULL )
361         return VLC_ENOMEM;
362
363     vlc_mutex_init( &p_sys->lock );
364     p_sys->i_refcount = 0;
365     DecSysHold( p_sys );
366
367     /* init of p_sys */
368 #ifdef ENABLE_PACKETIZER
369     p_sys->b_packetizer = false;
370 #endif
371     p_sys->b_ready = false;
372     p_sys->i_pts =
373     p_sys->i_max_stop = VLC_TS_INVALID;
374
375     kate_comment_init( &p_sys->kc );
376     kate_info_init( &p_sys->ki );
377
378     p_sys->b_has_headers = false;
379
380     /* retrieve options */
381     p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" );
382
383     vlc_mutex_lock( &kate_decoder_list_mutex );
384
385 #ifdef HAVE_TIGER
386
387     p_sys->b_use_tiger = var_CreateGetBool( p_dec, "kate-use-tiger" );
388
389     p_sys->p_tr = NULL;
390
391     /* get initial value of configuration */
392     p_sys->i_tiger_default_font_color = GetTigerColor( p_dec, "kate-tiger-default-font" );
393     p_sys->i_tiger_default_background_color = GetTigerColor( p_dec, "kate-tiger-default-background" );
394     p_sys->e_tiger_default_font_effect = GetTigerInteger( p_dec, "kate-tiger-default-font-effect" );
395     p_sys->f_tiger_default_font_effect_strength = GetTigerFloat( p_dec, "kate-tiger-default-font-effect-strength" );
396     p_sys->psz_tiger_default_font_desc = GetTigerString( p_dec, "kate-tiger-default-font-desc" );
397     p_sys->f_tiger_quality = GetTigerFloat( p_dec, "kate-tiger-quality" );
398
399     if( p_sys->b_use_tiger )
400     {
401         int i_ret = tiger_renderer_create( &p_sys->p_tr );
402         if( i_ret < 0 )
403         {
404             msg_Warn ( p_dec, "Failed to create Tiger renderer, falling back to basic rendering" );
405             p_sys->p_tr = NULL;
406             p_sys->b_use_tiger = false;
407         }
408
409         CHECK_TIGER_RET( tiger_renderer_set_surface_clear_color( p_sys->p_tr, 1, 0, 0, 0, 0 ) );
410
411         UpdateTigerFontEffect( p_dec );
412         UpdateTigerFontColor( p_dec );
413         UpdateTigerBackgroundColor( p_dec );
414         UpdateTigerQuality( p_dec );
415         UpdateTigerFontDesc( p_dec );
416     }
417
418 #else
419
420     p_sys->b_use_tiger = false;
421
422 #endif
423
424     es_format_Init( &p_dec->fmt_out, SPU_ES, 0 );
425
426     /* add the decoder to the global list */
427     decoder_t **list = realloc( kate_decoder_list, (kate_decoder_list_size+1) * sizeof( *list ));
428     if( list )
429     {
430         list[ kate_decoder_list_size++ ] = p_dec;
431         kate_decoder_list = list;
432     }
433
434     vlc_mutex_unlock( &kate_decoder_list_mutex );
435
436     return VLC_SUCCESS;
437 }
438
439 #ifdef ENABLE_PACKETIZER
440 static int OpenPacketizer( vlc_object_t *p_this )
441 {
442     decoder_t *p_dec = (decoder_t*)p_this;
443
444     int i_ret = OpenDecoder( p_this );
445
446     if( i_ret == VLC_SUCCESS )
447     {
448         p_dec->p_sys->b_packetizer = true;
449         p_dec->fmt_out.i_codec = VLC_CODEC_KATE;
450     }
451
452     return i_ret;
453 }
454 #endif
455
456 /****************************************************************************
457  * DecodeBlock: the whole thing
458  ****************************************************************************
459  * This function must be fed with kate packets.
460  ****************************************************************************/
461 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
462 {
463     decoder_sys_t *p_sys = p_dec->p_sys;
464     block_t *p_block;
465     kate_packet kp;
466
467     if( !pp_block || !*pp_block )
468         return NULL;
469
470     p_block = *pp_block;
471
472     if( p_block->i_flags & (BLOCK_FLAG_DISCONTINUITY|BLOCK_FLAG_CORRUPTED) )
473     {
474 #ifdef HAVE_TIGER
475         if( p_block->i_flags & BLOCK_FLAG_DISCONTINUITY)
476         {
477             /* Hmm, should we wait before flushing the renderer ? I think not, but not certain... */
478             vlc_mutex_lock( &p_sys->lock );
479             tiger_renderer_seek( p_sys->p_tr, 0 );
480             vlc_mutex_unlock( &p_sys->lock );
481         }
482 #endif
483         p_sys->i_max_stop = VLC_TS_INVALID;
484         block_Release( p_block );
485         return NULL;
486     }
487
488     /* Block to Kate packet */
489     kate_packet_wrap(&kp, p_block->i_buffer, p_block->p_buffer);
490
491     if( !p_sys->b_has_headers )
492     {
493         if( ProcessHeaders( p_dec ) )
494         {
495             block_Release( *pp_block );
496             return NULL;
497         }
498         p_sys->b_has_headers = true;
499     }
500
501     return ProcessPacket( p_dec, &kp, pp_block );
502 }
503
504 /*****************************************************************************
505  * ProcessHeaders: process Kate headers.
506  *****************************************************************************/
507 static int ProcessHeaders( decoder_t *p_dec )
508 {
509     decoder_sys_t *p_sys = p_dec->p_sys;
510     kate_packet kp;
511
512     unsigned pi_size[XIPH_MAX_HEADER_COUNT];
513     void     *pp_data[XIPH_MAX_HEADER_COUNT];
514     unsigned i_count;
515     if( xiph_SplitHeaders( pi_size, pp_data, &i_count,
516                            p_dec->fmt_in.i_extra, p_dec->fmt_in.p_extra) )
517         return VLC_EGENERIC;
518     int i_ret = VLC_SUCCESS;
519     if( i_count < 1 )
520     {
521         i_ret = VLC_EGENERIC;
522         goto end;
523     }
524
525     /* Take care of the initial Kate header */
526     kp.nbytes = pi_size[0];
527     kp.data   = pp_data[0];
528     i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
529     if( i_ret < 0 )
530     {
531         msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", i_ret );
532         goto end;
533     }
534
535     msg_Dbg( p_dec, "%s %s text, granule rate %f, granule shift %d",
536              p_sys->ki.language, p_sys->ki.category,
537              (double)p_sys->ki.gps_numerator/p_sys->ki.gps_denominator,
538              p_sys->ki.granule_shift);
539
540     /* parse all remaining header packets */
541     for( unsigned i_headeridx = 1; i_headeridx < i_count; i_headeridx++ )
542     {
543         kp.nbytes = pi_size[i_headeridx];
544         kp.data   = pp_data[i_headeridx];
545         i_ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
546         if( i_ret < 0 )
547         {
548             msg_Err( p_dec, "Kate header %d is corrupted: %d", i_headeridx, i_ret );
549             goto end;
550         }
551
552         /* header 1 is comments */
553         if( i_headeridx == 1 )
554         {
555             ParseKateComments( p_dec );
556         }
557     }
558
559 #ifdef ENABLE_PACKETIZER
560     if( !p_sys->b_packetizer )
561 #endif
562     {
563         /* We have all the headers, initialize decoder */
564         msg_Dbg( p_dec, "we have all headers, initialize libkate for decoding" );
565         i_ret = kate_decode_init( &p_sys->k, &p_sys->ki );
566         if (i_ret < 0)
567         {
568             msg_Err( p_dec, "Kate failed to initialize for decoding: %d", i_ret );
569             return VLC_EGENERIC;
570         }
571         p_sys->b_ready = true;
572     }
573 #ifdef ENABLE_PACKETIZER
574     else
575     {
576         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
577         p_dec->fmt_out.p_extra = xrealloc( p_dec->fmt_out.p_extra,
578                                                   p_dec->fmt_out.i_extra );
579         memcpy( p_dec->fmt_out.p_extra,
580                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
581     }
582 #endif
583
584 end:
585     for( unsigned i = 0; i < i_count; i++ )
586         free( pp_data[i] );
587     return i_ret < 0 ? VLC_EGENERIC : VLC_SUCCESS;
588 }
589
590 /*****************************************************************************
591  * ProcessPacket: processes a kate packet.
592  *****************************************************************************/
593 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
594                             block_t **pp_block )
595 {
596     decoder_sys_t *p_sys = p_dec->p_sys;
597     block_t *p_block = *pp_block;
598     subpicture_t *p_buf = NULL;
599
600     /* Date management */
601     if( p_block->i_pts > VLC_TS_INVALID && p_block->i_pts != p_sys->i_pts )
602     {
603         p_sys->i_pts = p_block->i_pts;
604     }
605
606     *pp_block = NULL; /* To avoid being fed the same packet again */
607
608 #ifdef ENABLE_PACKETIZER
609     if( p_sys->b_packetizer )
610     {
611         /* Date management */
612         p_block->i_dts = p_block->i_pts = p_sys->i_pts;
613
614         if( p_sys->i_headers >= p_sys->i_num_headers )
615             p_block->i_length = p_sys->i_pts - p_block->i_pts;
616         else
617             p_block->i_length = 0;
618
619         p_buf = p_block;
620     }
621     else
622 #endif
623     {
624         p_buf = DecodePacket( p_dec, p_kp, p_block );
625
626         if( p_block )
627             block_Release( p_block );
628     }
629
630     return p_buf;
631 }
632
633 /* nicked off blend.c */
634 static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
635                                int r, int g, int b )
636 {
637     *y = ( ( (  66 * r + 129 * g +  25 * b + 128 ) >> 8 ) + 16 );
638     *u =   ( ( -38 * r -  74 * g + 112 * b + 128 ) >> 8 ) + 128 ;
639     *v =   ( ( 112 * r -  94 * g -  18 * b + 128 ) >> 8 ) + 128 ;
640 }
641
642 /*
643   This retrieves the size of the video.
644   The best case is when the original video size is known, as we can then
645   scale images to match. In this case, since VLC autoscales, we want to
646   return the original size and let VLC scale everything.
647   if the original size is not known, then VLC can't resize, so we return
648   the size of the incoming video. If sizes in the Kate stream are in
649   relative units, it works fine. If they are absolute, you get what you
650   ask for. Images aren't rescaled.
651 */
652 static void GetVideoSize( decoder_t *p_dec, int *w, int *h )
653 {
654     /* searching for vout to get its size is frowned upon, so we don't and
655        use a default size if the original canvas size is not specified. */
656 #if 1
657     decoder_sys_t *p_sys = p_dec->p_sys;
658     if( p_sys->ki.original_canvas_width > 0 && p_sys->ki.original_canvas_height > 0 )
659     {
660         *w = p_sys->ki.original_canvas_width;
661         *h = p_sys->ki.original_canvas_height;
662         msg_Dbg( p_dec, "original canvas %zu %zu",
663                  p_sys->ki.original_canvas_width, p_sys->ki.original_canvas_height );
664     }
665     else
666     {
667         /* nothing, leave defaults */
668         msg_Dbg( p_dec, "original canvas size unknown");
669     }
670 #else
671     /* keep this just in case it might be allowed one day ;) */
672     vout_thread_t *p_vout;
673     p_vout = vlc_object_find( (vlc_object_t*)p_dec, VLC_OBJECT_VOUT, FIND_CHILD );
674     if( p_vout )
675     {
676         decoder_sys_t *p_sys = p_dec->p_sys;
677         if( p_sys->ki.original_canvas_width > 0 && p_sys->ki.original_canvas_height > 0 )
678         {
679             *w = p_sys->ki.original_canvas_width;
680             *h = p_sys->ki.original_canvas_height;
681         }
682         else
683         {
684             *w = p_vout->fmt_in.i_width;
685             *h = p_vout->fmt_in.i_height;
686         }
687         msg_Dbg( p_dec, "video: in %d %d, out %d %d, original canvas %zu %zu",
688                  p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,
689                  p_vout->fmt_out.i_width, p_vout->fmt_out.i_height,
690                  p_sys->ki.original_canvas_width, p_sys->ki.original_canvas_height );
691         vlc_object_release( p_vout );
692     }
693 #endif
694 }
695
696 static void CreateKateBitmap( picture_t *pic, const kate_bitmap *bitmap )
697 {
698     size_t y;
699
700     for( y=0; y<bitmap->height; ++y )
701     {
702         uint8_t *dest = pic->Y_PIXELS+pic->Y_PITCH*y;
703         const uint8_t *src = bitmap->pixels+y*bitmap->width;
704         memcpy( dest, src, bitmap->width );
705     }
706 }
707
708 static void CreateKatePalette( video_palette_t *fmt_palette, const kate_palette *palette )
709 {
710     size_t n;
711
712     fmt_palette->i_entries = palette->ncolors;
713     for( n=0; n<palette->ncolors; ++n )
714     {
715         rgb_to_yuv(
716             &fmt_palette->palette[n][0], &fmt_palette->palette[n][1], &fmt_palette->palette[n][2],
717             palette->colors[n].r, palette->colors[n].g, palette->colors[n].b
718         );
719         fmt_palette->palette[n][3] = palette->colors[n].a;
720     }
721 }
722
723 static void SetupText( decoder_t *p_dec, subpicture_t *p_spu, const kate_event *ev )
724 {
725     decoder_sys_t *p_sys = p_dec->p_sys;
726
727     if( ev->text_encoding != kate_utf8 )
728     {
729         msg_Warn( p_dec, "Text isn't UTF-8, unsupported, ignored" );
730         return;
731     }
732
733     switch( ev->text_markup_type )
734     {
735         case kate_markup_none:
736             p_spu->p_region->psz_text = strdup( ev->text ); /* no leak, this actually gets killed by the core */
737             break;
738         case kate_markup_simple:
739             if( p_sys->b_formatted )
740             {
741                 /* the HTML renderer expects a top level text tag pair */
742                 char *buffer = NULL;
743                 if( asprintf( &buffer, "<text>%s</text>", ev->text ) >= 0 )
744                 {
745                     p_spu->p_region->psz_html = buffer;
746                 }
747                 break;
748             }
749             /* if not formatted, we fall through */
750         default:
751             /* we don't know about this one, so remove markup and display as text */
752             {
753                 char *copy = strdup( ev->text );
754                 size_t len0 = strlen( copy ) + 1;
755                 kate_text_remove_markup( ev->text_encoding, copy, &len0 );
756                 p_spu->p_region->psz_text = copy;
757             }
758             break;
759     }
760 }
761
762 #ifdef HAVE_TIGER
763
764 static void TigerDestroySubpicture( subpicture_t *p_subpic )
765 {
766     DecSysRelease( p_subpic->updater.p_sys->p_dec_sys );
767     free( p_subpic->updater.p_sys );
768 }
769 /*
770  * We get premultiplied alpha, but VLC doesn't expect this, so we demultiply
771  * alpha to avoid double multiply (and thus thinner text than we should)).
772  * Best would be to have VLC be able to handle premultiplied alpha, as it
773  * would be faster to blend as well.
774  *
775  * Also, we flip color components around for big endian machines, as Tiger
776  * outputs ARGB or ABGR (the one we selected here) in host endianness.
777  */
778 static void PostprocessTigerImage( plane_t *p_plane, unsigned int i_width )
779 {
780     PROFILE_START( tiger_renderer_postprocess );
781     int y;
782     for( y=0; y<p_plane->i_lines; ++y )
783     {
784         uint8_t *p_line = (uint8_t*)(p_plane->p_pixels + y*p_plane->i_pitch);
785         unsigned int x;
786         for( x=0; x<i_width; ++x )
787         {
788             uint8_t *p_pixel = p_line+x*4;
789 #ifdef WORDS_BIGENDIAN
790             uint8_t a = p_pixel[0];
791 #else
792             uint8_t a = p_pixel[3];
793 #endif
794             if( a )
795             {
796 #ifdef WORDS_BIGENDIAN
797                 uint8_t tmp = p_pixel[2];
798                 p_pixel[0] = clip_uint8_vlc((p_pixel[3] * 255 + a / 2) / a);
799                 p_pixel[3] = a;
800                 p_pixel[2] = clip_uint8_vlc((p_pixel[1] * 255 + a / 2) / a);
801                 p_pixel[1] = clip_uint8_vlc((tmp * 255 + a / 2) / a);
802 #else
803                 p_pixel[0] = clip_uint8_vlc((p_pixel[0] * 255 + a / 2) / a);
804                 p_pixel[1] = clip_uint8_vlc((p_pixel[1] * 255 + a / 2) / a);
805                 p_pixel[2] = clip_uint8_vlc((p_pixel[2] * 255 + a / 2) / a);
806 #endif
807             }
808             else
809             {
810                 p_pixel[0] = 0;
811                 p_pixel[1] = 0;
812                 p_pixel[2] = 0;
813                 p_pixel[3] = 0;
814             }
815         }
816     }
817     PROFILE_STOP( tiger_renderer_postprocess );
818 }
819
820 static int TigerValidateSubpicture( subpicture_t *p_subpic,
821                                     bool b_fmt_src, const video_format_t *p_fmt_src,
822                                     bool b_fmt_dst, const video_format_t *p_fmt_dst,
823                                     mtime_t ts )
824 {
825     decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;
826
827     if( b_fmt_src || b_fmt_dst )
828         return VLC_EGENERIC;
829
830     PROFILE_START( TigerValidateSubpicture );
831
832     /* time in seconds from the start of the stream */
833     kate_float t = (p_subpic->updater.p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
834
835     /* it is likely that the current region (if any) can be kept as is; test for this */
836     vlc_mutex_lock( &p_sys->lock );
837     int i_ret;
838     if( p_sys->b_dirty || tiger_renderer_is_dirty( p_sys->p_tr ) )
839     {
840         i_ret = VLC_EGENERIC;
841         goto exit;
842     }
843     if( tiger_renderer_update( p_sys->p_tr, t, 1 ) >= 0 &&
844         tiger_renderer_is_dirty( p_sys->p_tr ) )
845     {
846         i_ret = VLC_EGENERIC;
847         goto exit;
848     }
849
850     i_ret = VLC_SUCCESS;
851 exit:
852     vlc_mutex_unlock( &p_sys->lock );
853     PROFILE_STOP( TigerValidateSubpicture );
854     return i_ret;
855 }
856
857 /* Tiger renders can end up looking a bit crap since they get overlaid on top of
858    a subsampled YUV image, so there can be a fair amount of chroma bleeding.
859    Looks good with white though since it's all luma. Hopefully that will be the
860    common case. */
861 static void TigerUpdateSubpicture( subpicture_t *p_subpic,
862                                    const video_format_t *p_fmt_src,
863                                    const video_format_t *p_fmt_dst,
864                                    mtime_t ts )
865 {
866     decoder_sys_t *p_sys = p_subpic->updater.p_sys->p_dec_sys;
867     plane_t *p_plane;
868     kate_float t;
869     int i_ret;
870
871
872     /* time in seconds from the start of the stream */
873     t = (p_subpic->updater.p_sys->i_start + ts - p_subpic->i_start ) / 1000000.0f;
874
875     PROFILE_START( TigerUpdateSubpicture );
876
877     /* create a full frame region - this will also tell Tiger the size of the frame */
878     video_format_t fmt = *p_fmt_dst;
879     fmt.i_chroma         = VLC_CODEC_RGBA;
880     fmt.i_bits_per_pixel = 0;
881     fmt.i_width          =
882     fmt.i_visible_width  = p_fmt_src->i_width;
883     fmt.i_height         =
884     fmt.i_visible_height = p_fmt_src->i_height;
885     fmt.i_x_offset       = fmt.i_y_offset = 0;
886
887     subpicture_region_t *p_r = subpicture_region_New( &fmt );
888     if( !p_r )
889         return;
890
891     p_r->i_x = 0;
892     p_r->i_y = 0;
893     p_r->i_align = SUBPICTURE_ALIGN_TOP | SUBPICTURE_ALIGN_LEFT;
894
895     vlc_mutex_lock( &p_sys->lock );
896
897     p_plane = &p_r->p_picture->p[0];
898     i_ret = tiger_renderer_set_buffer( p_sys->p_tr, p_plane->p_pixels, fmt.i_width, p_plane->i_lines, p_plane->i_pitch, 1 );
899     if( i_ret < 0 )
900     {
901         goto failure;
902     }
903
904     PROFILE_START( tiger_renderer_update );
905     i_ret = tiger_renderer_update( p_sys->p_tr, t, 1 );
906     if( i_ret < 0 )
907     {
908         goto failure;
909     }
910     PROFILE_STOP( tiger_renderer_update );
911
912     PROFILE_START( tiger_renderer_render );
913     i_ret = tiger_renderer_render( p_sys->p_tr );
914     if( i_ret < 0 )
915     {
916         goto failure;
917     }
918     PROFILE_STOP( tiger_renderer_render );
919
920     PostprocessTigerImage( p_plane, fmt.i_width );
921     p_subpic->p_region = p_r;
922     p_sys->b_dirty = false;
923
924     PROFILE_STOP( TigerUpdateSubpicture );
925
926     vlc_mutex_unlock( &p_sys->lock );
927
928     return;
929
930 failure:
931     vlc_mutex_unlock( &p_sys->lock );
932     subpicture_region_ChainDelete( p_r );
933 }
934
935 static uint32_t GetTigerColor( decoder_t *p_dec, const char *psz_prefix )
936 {
937     char *psz_tmp;
938     uint32_t i_color = 0;
939
940     if( asprintf( &psz_tmp, "%s-color", psz_prefix ) >= 0 )
941     {
942         uint32_t i_rgb = var_CreateGetInteger( p_dec, psz_tmp );
943         var_Destroy( p_dec, psz_tmp );
944         free( psz_tmp );
945         i_color |= i_rgb;
946     }
947
948     if( asprintf( &psz_tmp, "%s-alpha", psz_prefix ) >= 0 )
949     {
950         uint32_t i_alpha = var_CreateGetInteger( p_dec, psz_tmp );
951         var_Destroy( p_dec, psz_tmp );
952         free( psz_tmp );
953         i_color |= (i_alpha << 24);
954     }
955
956     return i_color;
957 }
958
959 static char *GetTigerString( decoder_t *p_dec, const char *psz_name )
960 {
961     char *psz_value = var_CreateGetString( p_dec, psz_name );
962     if( psz_value)
963     {
964         psz_value = strdup( psz_value );
965     }
966     var_Destroy( p_dec, psz_name );
967     return psz_value;
968 }
969
970 static int GetTigerInteger( decoder_t *p_dec, const char *psz_name )
971 {
972     int i_value = var_CreateGetInteger( p_dec, psz_name );
973     var_Destroy( p_dec, psz_name );
974     return i_value;
975 }
976
977 static double GetTigerFloat( decoder_t *p_dec, const char *psz_name )
978 {
979     double f_value = var_CreateGetFloat( p_dec, psz_name );
980     var_Destroy( p_dec, psz_name );
981     return f_value;
982 }
983
984 static void UpdateTigerQuality( decoder_t *p_dec )
985 {
986     decoder_sys_t *p_sys = (decoder_sys_t*)p_dec->p_sys;
987     CHECK_TIGER_RET( tiger_renderer_set_quality( p_sys->p_tr, p_sys->f_tiger_quality ) );
988     p_sys->b_dirty = true;
989 }
990
991 static void UpdateTigerFontDesc( decoder_t *p_dec )
992 {
993     decoder_sys_t *p_sys = (decoder_sys_t*)p_dec->p_sys;
994     CHECK_TIGER_RET( tiger_renderer_set_default_font_description( p_sys->p_tr, p_sys->psz_tiger_default_font_desc ) );
995     p_sys->b_dirty = true;
996 }
997
998 static void UpdateTigerFontColor( decoder_t *p_dec )
999 {
1000     decoder_sys_t *p_sys = (decoder_sys_t*)p_dec->p_sys;
1001     double f_a = ((p_sys->i_tiger_default_font_color >> 24) & 0xff) / 255.0;
1002     double f_r = ((p_sys->i_tiger_default_font_color >> 16) & 0xff) / 255.0;
1003     double f_g = ((p_sys->i_tiger_default_font_color >> 8) & 0xff) / 255.0;
1004     double f_b = (p_sys->i_tiger_default_font_color & 0xff) / 255.0;
1005     CHECK_TIGER_RET( tiger_renderer_set_default_font_color( p_sys->p_tr, f_r, f_g, f_b, f_a ) );
1006     p_sys->b_dirty = true;
1007 }
1008
1009 static void UpdateTigerBackgroundColor( decoder_t *p_dec )
1010 {
1011     decoder_sys_t *p_sys = (decoder_sys_t*)p_dec->p_sys;
1012     double f_a = ((p_sys->i_tiger_default_background_color >> 24) & 0xff) / 255.0;
1013     double f_r = ((p_sys->i_tiger_default_background_color >> 16) & 0xff) / 255.0;
1014     double f_g = ((p_sys->i_tiger_default_background_color >> 8) & 0xff) / 255.0;
1015     double f_b = (p_sys->i_tiger_default_background_color & 0xff) / 255.0;
1016     CHECK_TIGER_RET( tiger_renderer_set_default_background_fill_color( p_sys->p_tr, f_r, f_g, f_b, f_a ) );
1017     p_sys->b_dirty = true;
1018 }
1019
1020 static void UpdateTigerFontEffect( decoder_t *p_dec )
1021 {
1022     decoder_sys_t *p_sys = (decoder_sys_t*)p_dec->p_sys;
1023     CHECK_TIGER_RET( tiger_renderer_set_default_font_effect( p_sys->p_tr,
1024                                                              p_sys->e_tiger_default_font_effect,
1025                                                              p_sys->f_tiger_default_font_effect_strength ) );
1026     p_sys->b_dirty = true;
1027 }
1028
1029 static int OnConfigurationChanged( decoder_t *p_dec, const char *psz_var,
1030                                    vlc_value_t oldval, vlc_value_t newval )
1031 {
1032     decoder_sys_t *p_sys = (decoder_sys_t*)p_dec->p_sys;
1033
1034     VLC_UNUSED( oldval );
1035
1036     vlc_mutex_lock( &p_sys->lock );
1037
1038     msg_Dbg( p_dec, "OnConfigurationChanged: %s", psz_var );
1039
1040     if( !p_sys->b_use_tiger || !p_sys->p_tr )
1041     {
1042         vlc_mutex_unlock( &p_sys->lock );
1043         return VLC_SUCCESS;
1044     }
1045
1046 #define TEST_TIGER_VAR( name ) \
1047     if( !strcmp( name, psz_var ) )
1048
1049     TEST_TIGER_VAR( "kate-tiger-quality" )
1050     {
1051         p_sys->f_tiger_quality = newval.f_float;
1052         UpdateTigerQuality( p_dec );
1053     }
1054
1055     TEST_TIGER_VAR( "kate-tiger-default-font-desc" )
1056     {
1057         if( p_sys->psz_tiger_default_font_desc )
1058         {
1059             free( p_sys->psz_tiger_default_font_desc );
1060             p_sys->psz_tiger_default_font_desc = NULL;
1061         }
1062         if( newval.psz_string )
1063         {
1064             p_sys->psz_tiger_default_font_desc = strdup( newval.psz_string );
1065         }
1066         UpdateTigerFontDesc( p_dec );
1067     }
1068
1069     TEST_TIGER_VAR( "kate-tiger-default-font-color" )
1070     {
1071         p_sys->i_tiger_default_font_color = (p_sys->i_tiger_default_font_color & 0xff00000000) | newval.i_int;
1072         UpdateTigerFontColor( p_dec );
1073     }
1074
1075     TEST_TIGER_VAR( "kate-tiger-default-font-alpha" )
1076     {
1077         p_sys->i_tiger_default_font_color = (p_sys->i_tiger_default_font_color & 0x00ffffff) | (newval.i_int<<24);
1078         UpdateTigerFontColor( p_dec );
1079     }
1080
1081     TEST_TIGER_VAR( "kate-tiger-default-background-color" )
1082     {
1083         p_sys->i_tiger_default_background_color = (p_sys->i_tiger_default_background_color & 0xff00000000) | newval.i_int;
1084         UpdateTigerBackgroundColor( p_dec );
1085     }
1086
1087     TEST_TIGER_VAR( "kate-tiger-default-background-alpha" )
1088     {
1089         p_sys->i_tiger_default_background_color = (p_sys->i_tiger_default_background_color & 0x00ffffff) | (newval.i_int<<24);
1090         UpdateTigerBackgroundColor( p_dec );
1091     }
1092
1093     TEST_TIGER_VAR( "kate-tiger-default-font-effect" )
1094     {
1095         p_sys->e_tiger_default_font_effect = (tiger_font_effect)newval.i_int;
1096         UpdateTigerFontEffect( p_dec );
1097     }
1098
1099     TEST_TIGER_VAR( "kate-tiger-default-font-effect-strength" )
1100     {
1101         p_sys->f_tiger_default_font_effect_strength = newval.f_float;
1102         UpdateTigerFontEffect( p_dec );
1103     }
1104
1105 #undef TEST_TIGER_VAR
1106
1107     vlc_mutex_unlock( &p_sys->lock );
1108
1109     return VLC_SUCCESS;
1110 }
1111
1112 static int TigerConfigurationCallback( vlc_object_t *p_this, const char *psz_var,
1113                                        vlc_value_t oldval, vlc_value_t newval,
1114                                        void *p_data )
1115 {
1116     size_t i_idx;
1117
1118     VLC_UNUSED( p_this );
1119     VLC_UNUSED( oldval );
1120     VLC_UNUSED( newval );
1121     VLC_UNUSED( p_data );
1122
1123     vlc_mutex_lock( &kate_decoder_list_mutex );
1124
1125     /* Update all existing decoders from the global user prefs */
1126     for( i_idx = 0; i_idx < kate_decoder_list_size; i_idx++ )
1127     {
1128         decoder_t *p_dec = kate_decoder_list[ i_idx ];
1129         OnConfigurationChanged( p_dec, psz_var, oldval, newval );
1130     }
1131
1132     vlc_mutex_unlock( &kate_decoder_list_mutex );
1133
1134     return VLC_SUCCESS;
1135 }
1136
1137 #endif
1138
1139 /*****************************************************************************
1140  * DecodePacket: decodes a Kate packet.
1141  *****************************************************************************/
1142 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t *p_block )
1143 {
1144     decoder_sys_t *p_sys = p_dec->p_sys;
1145     const kate_event *ev = NULL;
1146     subpicture_t *p_spu = NULL;
1147     int i_ret;
1148
1149     if( !p_sys->b_ready )
1150     {
1151         msg_Err( p_dec, "Cannot decode Kate packet, decoder not initialized" );
1152         return NULL;
1153     }
1154
1155     i_ret = kate_decode_packetin( &p_sys->k, p_kp );
1156     if( i_ret < 0 )
1157     {
1158         msg_Err( p_dec, "Kate failed to decode packet: %d", i_ret );
1159         return NULL;
1160     }
1161
1162     i_ret = kate_decode_eventout( &p_sys->k, &ev );
1163     if( i_ret < 0 )
1164     {
1165         msg_Err( p_dec, "Kate failed to retrieve event: %d", i_ret );
1166         return NULL;
1167     }
1168     if( i_ret > 0 )
1169     {
1170         /* no event to go with this packet, this is normal */
1171         return NULL;
1172     }
1173
1174     /* we have an event */
1175
1176     /* Get a new spu */
1177     subpicture_updater_sys_t *p_spu_sys = NULL;
1178     if( p_sys->b_use_tiger)
1179     {
1180         p_spu_sys = malloc( sizeof(*p_spu_sys) );
1181         if( !p_spu_sys )
1182             return NULL;
1183     }
1184     subpicture_updater_t updater = {
1185 #ifdef HAVE_TIGER
1186         .pf_validate = TigerValidateSubpicture,
1187         .pf_update   = TigerUpdateSubpicture,
1188         .pf_destroy  = TigerDestroySubpicture,
1189 #endif
1190         .p_sys       = p_spu_sys,
1191     };
1192     p_spu = decoder_NewSubpicture( p_dec, p_sys->b_use_tiger ? &updater : NULL );
1193     if( !p_spu )
1194     {
1195         free( p_spu_sys );
1196         /* this will happen for lyrics as there is no vout - so no error */
1197         /* msg_Err( p_dec, "Failed to allocate spu buffer" ); */
1198         return NULL;
1199     }
1200
1201     p_spu->i_start = p_block->i_pts;
1202     p_spu->i_stop = p_block->i_pts + INT64_C(1000000)*ev->duration*p_sys->ki.gps_denominator/p_sys->ki.gps_numerator;
1203     p_spu->b_ephemer = false;
1204     p_spu->b_absolute = false;
1205
1206 #ifdef HAVE_TIGER
1207     if( p_sys->b_use_tiger)
1208     {
1209         p_spu_sys->p_dec_sys = p_sys;
1210         p_spu_sys->i_start   = p_block->i_pts;
1211         DecSysHold( p_sys );
1212
1213         p_spu->i_stop = __MAX( p_sys->i_max_stop, p_spu->i_stop );
1214         p_spu->b_ephemer = true;
1215         p_spu->b_absolute = true;
1216
1217         /* add the event to tiger */
1218         vlc_mutex_lock( &p_sys->lock );
1219         CHECK_TIGER_RET( tiger_renderer_add_event( p_sys->p_tr, ev->ki, ev ) );
1220         vlc_mutex_unlock( &p_sys->lock );
1221     }
1222     else
1223 #endif
1224     {
1225         p_spu = SetupSimpleKateSPU( p_dec, p_spu, ev );
1226     }
1227
1228     return p_spu;
1229 }
1230
1231 /*****************************************************************************
1232  * SetupSimpleKateSPU: creates text/bitmap regions where appropriate
1233  *****************************************************************************/
1234 static subpicture_t *SetupSimpleKateSPU( decoder_t *p_dec, subpicture_t *p_spu,
1235                                          const kate_event *ev )
1236 {
1237     decoder_sys_t *p_sys = p_dec->p_sys;
1238     video_format_t fmt;
1239     subpicture_region_t *p_bitmap_region = NULL;
1240     video_palette_t palette;
1241     kate_tracker kin;
1242     bool b_tracker_valid = false;
1243     int i_ret;
1244
1245     /* these may be 0 for "not specified" */
1246     p_spu->i_original_picture_width = p_sys->ki.original_canvas_width;
1247     p_spu->i_original_picture_height = p_sys->ki.original_canvas_height;
1248
1249     /* Create a new subpicture region */
1250     memset( &fmt, 0, sizeof(video_format_t) );
1251
1252     if (p_sys->b_formatted)
1253     {
1254         i_ret = kate_tracker_init( &kin, &p_sys->ki, ev );
1255         if( i_ret < 0)
1256         {
1257             msg_Err( p_dec, "failed to initialize kate tracker, event will be unformatted: %d", i_ret );
1258         }
1259         else
1260         {
1261             int w = 720, h = 576; /* give sensible defaults just in case we fail to get the actual size */
1262             GetVideoSize(p_dec, &w, &h);
1263             i_ret = kate_tracker_update(&kin, 0, w, h, 0, 0, w, h);
1264             if( i_ret < 0)
1265             {
1266                 kate_tracker_clear(&kin);
1267                 msg_Err( p_dec, "failed to update kate tracker, event will be unformatted: %d", i_ret );
1268             }
1269             else
1270             {
1271                 // TODO: parse tracker and set style, init fmt
1272                 b_tracker_valid = true;
1273             }
1274         }
1275     }
1276
1277     if (ev->bitmap && ev->bitmap->type==kate_bitmap_type_paletted && ev->palette) {
1278
1279         /* create a separate region for the bitmap */
1280         memset( &fmt, 0, sizeof(video_format_t) );
1281         fmt.i_chroma = VLC_CODEC_YUVP;
1282         fmt.i_width = fmt.i_visible_width = ev->bitmap->width;
1283         fmt.i_height = fmt.i_visible_height = ev->bitmap->height;
1284         fmt.i_x_offset = fmt.i_y_offset = 0;
1285         fmt.p_palette = &palette;
1286         CreateKatePalette( fmt.p_palette, ev->palette );
1287
1288         p_bitmap_region = subpicture_region_New( &fmt );
1289         if( !p_bitmap_region )
1290         {
1291             msg_Err( p_dec, "cannot allocate SPU region" );
1292             decoder_DeleteSubpicture( p_dec, p_spu );
1293             return NULL;
1294         }
1295
1296         /* create the bitmap */
1297         CreateKateBitmap( p_bitmap_region->p_picture, ev->bitmap );
1298
1299         msg_Dbg(p_dec, "Created bitmap, %zux%zu, %zu colors", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors);
1300     }
1301
1302     /* text region */
1303     fmt.i_chroma = VLC_CODEC_TEXT;
1304     fmt.i_sar_num = 0;
1305     fmt.i_sar_den = 1;
1306     fmt.i_width = fmt.i_height = 0;
1307     fmt.i_x_offset = fmt.i_y_offset = 0;
1308     p_spu->p_region = subpicture_region_New( &fmt );
1309     if( !p_spu->p_region )
1310     {
1311         msg_Err( p_dec, "cannot allocate SPU region" );
1312         decoder_DeleteSubpicture( p_dec, p_spu );
1313         return NULL;
1314     }
1315
1316     SetupText( p_dec, p_spu, ev );
1317
1318     /* default positioning */
1319     p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
1320     if (p_bitmap_region)
1321     {
1322         p_bitmap_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
1323     }
1324     p_spu->p_region->i_x = 0;
1325     p_spu->p_region->i_y = 10;
1326
1327     /* override if tracker info present */
1328     if (b_tracker_valid)
1329     {
1330         if (kin.has.region)
1331         {
1332             p_spu->p_region->i_x = kin.region_x;
1333             p_spu->p_region->i_y = kin.region_y;
1334             if (p_bitmap_region)
1335             {
1336                 p_bitmap_region->i_x = kin.region_x;
1337                 p_bitmap_region->i_y = kin.region_y;
1338             }
1339             p_spu->b_absolute = true;
1340         }
1341
1342         kate_tracker_clear(&kin);
1343     }
1344
1345     /* if we have a bitmap, chain it before the text */
1346     if (p_bitmap_region)
1347     {
1348         p_bitmap_region->p_next = p_spu->p_region;
1349         p_spu->p_region = p_bitmap_region;
1350     }
1351
1352     return p_spu;
1353 }
1354
1355 /*****************************************************************************
1356  * ParseKateComments:
1357  *****************************************************************************/
1358 static void ParseKateComments( decoder_t *p_dec )
1359 {
1360     char *psz_name, *psz_value, *psz_comment;
1361     int i = 0;
1362
1363     while ( i < p_dec->p_sys->kc.comments )
1364     {
1365         psz_comment = strdup( p_dec->p_sys->kc.user_comments[i] );
1366         if( !psz_comment )
1367             break;
1368         psz_name = psz_comment;
1369         psz_value = strchr( psz_comment, '=' );
1370         if( psz_value )
1371         {
1372             *psz_value = '\0';
1373             psz_value++;
1374
1375             if( !p_dec->p_description )
1376                 p_dec->p_description = vlc_meta_New();
1377             if( p_dec->p_description )
1378                 vlc_meta_AddExtra( p_dec->p_description, psz_name, psz_value );
1379         }
1380         free( psz_comment );
1381         i++;
1382     }
1383 }
1384
1385 /*****************************************************************************
1386  * CloseDecoder: clean up the decoder
1387  *****************************************************************************/
1388 static void CloseDecoder( vlc_object_t *p_this )
1389 {
1390     decoder_t *p_dec = (decoder_t *)p_this;
1391     size_t     i_index;
1392
1393     /* remove the decoder from the global list */
1394     vlc_mutex_lock( &kate_decoder_list_mutex );
1395     for( i_index = 0; i_index < kate_decoder_list_size; i_index++ )
1396     {
1397         if( kate_decoder_list[ i_index ] == p_dec )
1398         {
1399             kate_decoder_list[ i_index ] = kate_decoder_list[ --kate_decoder_list_size ];
1400             break;
1401         }
1402     }
1403     vlc_mutex_unlock( &kate_decoder_list_mutex );
1404
1405     msg_Dbg( p_dec, "Closing Kate decoder" );
1406     DecSysRelease( p_dec->p_sys );
1407 }
1408
1409 static void DecSysHold( decoder_sys_t *p_sys )
1410 {
1411     vlc_mutex_lock( &p_sys->lock );
1412     p_sys->i_refcount++;
1413     vlc_mutex_unlock( &p_sys->lock );
1414 }
1415
1416 static void DecSysRelease( decoder_sys_t *p_sys )
1417 {
1418     vlc_mutex_lock( &p_sys->lock );
1419     p_sys->i_refcount--;
1420     if( p_sys->i_refcount > 0)
1421     {
1422         vlc_mutex_unlock( &p_sys->lock );
1423         return;
1424     }
1425
1426     vlc_mutex_unlock( &p_sys->lock );
1427     vlc_mutex_destroy( &p_sys->lock );
1428
1429 #ifdef HAVE_TIGER
1430     if( p_sys->p_tr )
1431         tiger_renderer_destroy( p_sys->p_tr );
1432     free( p_sys->psz_tiger_default_font_desc );
1433 #endif
1434
1435     if (p_sys->b_ready)
1436         kate_clear( &p_sys->k );
1437     kate_info_clear( &p_sys->ki );
1438     kate_comment_clear( &p_sys->kc );
1439
1440     free( p_sys );
1441 }
1442