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