]> git.sesse.net Git - vlc/blob - modules/codec/kate.c
basic support for Kate streams as subtitles
[vlc] / modules / codec / kate.c
1 /*****************************************************************************
2  * kate.c : a decoder for the kate bitstream format
3  *****************************************************************************
4  * Copyright (C) 2000-2006 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/vlc.h>
32 #include <vlc_input.h>
33 #include <vlc_codec.h>
34
35 #include <kate/kate.h>
36
37 #include "vlc_osd.h"
38
39 /* #define ENABLE_PACKETIZER */
40 /* #define ENABLE_FORMATTING */
41 /* #define ENABLE_BITMAPS */
42
43 /*****************************************************************************
44  * decoder_sys_t : decoder descriptor
45  *****************************************************************************/
46 struct decoder_sys_t
47 {
48 #ifdef ENABLE_PACKETIZER
49     /* Module mode */
50     bool b_packetizer;
51 #endif
52
53     /*
54      * Input properties
55      */
56     int i_num_headers;
57     int i_headers;
58
59     /*
60      * Kate properties
61      */
62     bool           b_ready;
63     kate_info      ki;
64     kate_comment   kc;
65     kate_state     k;
66
67     /*
68      * Common properties
69      */
70     mtime_t i_pts;
71
72     /*
73      * Options
74      */
75 #ifdef ENABLE_FORMATTING
76     bool   b_formatted;
77 #endif
78 };
79
80 /*****************************************************************************
81  * Local prototypes
82  *****************************************************************************/
83 static int  OpenDecoder   ( vlc_object_t * );
84 static void CloseDecoder  ( vlc_object_t * );
85 #ifdef ENABLE_PACKETIZER
86 static int OpenPacketizer( vlc_object_t *p_this );
87 #endif
88
89 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block );
90 static int ProcessHeaders( decoder_t *p_dec );
91 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
92                             block_t **pp_block );
93 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp,
94                             block_t *p_block );
95 static void ParseKateComments( decoder_t * );
96
97 #define DEFAULT_NAME "Default"
98 #define MAX_LINE 8192
99
100 /*****************************************************************************
101  * Module descriptor.
102  *****************************************************************************/
103
104 #ifdef ENABLE_FORMATTING
105 #define FORMAT_TEXT N_("Formatted Subtitles")
106 #define FORMAT_LONGTEXT N_("Kate streams allow for text formatting. " \
107  "VLC partly implements this, but you can choose to disable all formatting.")
108 #endif
109
110
111 vlc_module_begin();
112     set_shortname( _("Kate"));
113     set_description( _("Kate text subtitles decoder") );
114     set_capability( "decoder", 50 );
115     set_callbacks( OpenDecoder, CloseDecoder );
116     set_category( CAT_INPUT );
117     set_subcategory( SUBCAT_INPUT_SCODEC );
118     add_shortcut( "kate" );
119
120 #ifdef ENABLE_PACKETIZER
121     add_submodule();
122     set_description( _("Kate text subtitles packetizer") );
123     set_capability( "packetizer", 100 );
124     set_callbacks( OpenPacketizer, CloseDecoder );
125     add_shortcut( "kate" );
126 #endif
127
128 #ifdef ENABLE_FORMATTING
129     add_bool( "kate-formatted", true, NULL, FORMAT_TEXT, FORMAT_LONGTEXT,
130                  false );
131 #endif
132 vlc_module_end();
133
134 /*****************************************************************************
135  * OpenDecoder: probe the decoder and return score
136  *****************************************************************************
137  * Tries to launch a decoder and return score so that the interface is able
138  * to chose.
139  *****************************************************************************/
140 static int OpenDecoder( vlc_object_t *p_this )
141 {
142     decoder_t     *p_dec = (decoder_t*)p_this;
143     decoder_sys_t *p_sys;
144
145     msg_Dbg( p_dec, "kate: OpenDecoder");
146
147     if( p_dec->fmt_in.i_codec != VLC_FOURCC('k','a','t','e') )
148     {
149         return VLC_EGENERIC;
150     }
151
152     /* Set callbacks */
153     p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **))
154         DecodeBlock;
155     p_dec->pf_packetize    = (block_t *(*)(decoder_t *, block_t **))
156         DecodeBlock;
157
158     /* Allocate the memory needed to store the decoder's structure */
159     if( ( p_dec->p_sys = p_sys =
160           (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
161     {
162         msg_Err( p_dec, "out of memory" );
163         return VLC_ENOMEM;
164     }
165
166     /* init of p_sys */
167 #ifdef ENABLE_PACKETIZER
168     p_sys->b_packetizer = false;
169 #endif
170     p_sys->b_ready = false;
171     p_sys->i_pts = 0;
172
173     kate_comment_init( &p_sys->kc );
174     kate_info_init( &p_sys->ki );
175
176     p_sys->i_num_headers = 0;
177     p_sys->i_headers = 0;
178
179     /* retrieve options */
180 #ifdef ENABLE_FORMATTING
181     p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" );
182 #endif
183
184     return VLC_SUCCESS;
185 }
186
187 #ifdef ENABLE_PACKETIZER
188 static int OpenPacketizer( vlc_object_t *p_this )
189 {
190     decoder_t *p_dec = (decoder_t*)p_this;
191
192     int i_ret = OpenDecoder( p_this );
193
194     if( i_ret == VLC_SUCCESS )
195     {
196         p_dec->p_sys->b_packetizer = true;
197         p_dec->fmt_out.i_codec = VLC_FOURCC( 'k', 'a', 't', 'e' );
198     }
199
200     return i_ret;
201 }
202 #endif
203
204 /****************************************************************************
205  * DecodeBlock: the whole thing
206  ****************************************************************************
207  * This function must be fed with kate packets.
208  ****************************************************************************/
209 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
210 {
211     decoder_sys_t *p_sys = p_dec->p_sys;
212     block_t *p_block;
213     kate_packet kp;
214
215     if( !pp_block || !*pp_block ) return NULL;
216
217     p_block = *pp_block;
218
219     /* Block to Kate packet */
220     kate_packet_wrap(&kp, p_block->i_buffer, p_block->p_buffer);
221
222     if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
223     {
224         /* Headers already available as extra data */
225         p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0];
226         p_sys->i_headers = p_sys->i_num_headers;
227     }
228     else if( kp.nbytes && (p_sys->i_headers==0 || p_sys->i_headers < p_sys->ki.num_headers ))
229     {
230         /* Backup headers as extra data */
231         uint8_t *p_extra;
232
233         p_dec->fmt_in.p_extra =
234             realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra + kp.nbytes + 2 );
235         p_extra = (void*)(((unsigned char*)p_dec->fmt_in.p_extra) + p_dec->fmt_in.i_extra);
236         *(p_extra++) = kp.nbytes >> 8;
237         *(p_extra++) = kp.nbytes & 0xFF;
238
239         memcpy( p_extra, kp.data, kp.nbytes );
240         p_dec->fmt_in.i_extra += kp.nbytes + 2;
241
242         block_Release( *pp_block );
243         p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0];
244         p_sys->i_headers++;
245         return NULL;
246     }
247
248     if( p_sys->i_headers == p_sys->i_num_headers && p_sys->i_num_headers>0 )
249     {
250         if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
251         {
252             p_sys->i_headers = 0;
253             p_dec->fmt_in.i_extra = 0;
254             block_Release( *pp_block );
255             return NULL;
256         }
257         else p_sys->i_headers++;
258     }
259
260     return ProcessPacket( p_dec, &kp, pp_block );
261 }
262
263 /*****************************************************************************
264  * ProcessHeaders: process Kate headers.
265  *****************************************************************************/
266 static int ProcessHeaders( decoder_t *p_dec )
267 {
268     decoder_sys_t *p_sys = p_dec->p_sys;
269     kate_packet kp;
270     uint8_t *p_extra;
271     int i_extra;
272     int headeridx;
273     int ret;
274
275     if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
276
277     p_extra = p_dec->fmt_in.p_extra;
278     i_extra = p_dec->fmt_in.i_extra;
279
280     /* skip number of headers */
281     ++p_extra;
282     --i_extra;
283
284     /* Take care of the initial Kate header */
285     kp.nbytes = *(p_extra++) << 8;
286     kp.nbytes |= (*(p_extra++) & 0xFF);
287     kp.data = p_extra;
288     p_extra += kp.nbytes;
289     i_extra -= (kp.nbytes + 2);
290     if( i_extra < 0 )
291     {
292         msg_Err( p_dec, "header data corrupted");
293         return VLC_EGENERIC;
294     }
295
296     ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
297     if( ret < 0 )
298     {
299         msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", ret );
300         return VLC_EGENERIC;
301     }
302
303     msg_Dbg( p_dec, "%s %s text, granule rate %f, granule shift %d",
304              p_sys->ki.language, p_sys->ki.category,
305              (double)p_sys->ki.gps_numerator/p_sys->ki.gps_denominator,
306              p_sys->ki.granule_shift);
307
308     /* we want markup to be removed for now */
309     kate_info_remove_markup( &p_sys->ki, 1 );
310
311     /* parse all remaining header packets */
312     for (headeridx=1; headeridx<p_sys->ki.num_headers; ++headeridx)
313     {
314         kp.nbytes = *(p_extra++) << 8;
315         kp.nbytes |= (*(p_extra++) & 0xFF);
316         kp.data = p_extra;
317         p_extra += kp.nbytes;
318         i_extra -= (kp.nbytes + 2);
319         if( i_extra < 0 )
320         {
321             msg_Err( p_dec, "header %d data corrupted", headeridx);
322             return VLC_EGENERIC;
323         }
324
325         ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
326         if( ret < 0 )
327         {
328             msg_Err( p_dec, "Kate header %d is corrupted: %d", headeridx, ret);
329             return VLC_EGENERIC;
330         }
331
332         /* header 1 is comments */
333         if( headeridx == 1 )
334         {
335             ParseKateComments( p_dec );
336         }
337     }
338
339 #ifdef ENABLE_PACKETIZER
340     if( !p_sys->b_packetizer )
341 #endif
342     {
343         /* We have all the headers, initialize decoder */
344         msg_Dbg( p_dec, "we have all headers, initialize libkate for decoding" );
345         ret = kate_decode_init( &p_sys->k, &p_sys->ki );
346         if (ret < 0)
347         {
348             msg_Err( p_dec, "Kate failed to initialize for decoding: %d", ret );
349             return VLC_EGENERIC;
350         }
351         p_sys->b_ready = true;
352     }
353 #ifdef ENABLE_PACKETIZER
354     else
355     {
356         p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
357         p_dec->fmt_out.p_extra =
358             realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
359         memcpy( p_dec->fmt_out.p_extra,
360                 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
361     }
362 #endif
363
364     return VLC_SUCCESS;
365 }
366
367 /*****************************************************************************
368  * ProcessPacket: processes a kate packet.
369  *****************************************************************************/
370 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
371                             block_t **pp_block )
372 {
373     decoder_sys_t *p_sys = p_dec->p_sys;
374     block_t *p_block = *pp_block;
375     subpicture_t *p_buf = NULL;
376
377     /* Date management */
378     if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
379     {
380         p_sys->i_pts = p_block->i_pts;
381     }
382
383     *pp_block = NULL; /* To avoid being fed the same packet again */
384
385 #ifdef ENABLE_PACKETIZER
386     if( p_sys->b_packetizer )
387     {
388         /* Date management */
389         p_block->i_dts = p_block->i_pts = p_sys->i_pts;
390
391         if( p_sys->i_headers >= p_sys->i_num_headers )
392             p_block->i_length = p_sys->i_pts - p_block->i_pts;
393         else
394             p_block->i_length = 0;
395
396         p_buf = p_block;
397     }
398     else
399 #endif
400     {
401         if( p_sys->i_headers >= p_sys->i_num_headers )
402             p_buf = DecodePacket( p_dec, p_kp, p_block );
403         else
404             p_buf = NULL;
405
406         if( p_block ) block_Release( p_block );
407     }
408
409     return p_buf;
410 }
411
412 #ifdef ENABLE_BITMAPS
413 /* nicked off blend.c */
414 static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
415                                int r, int g, int b )
416 {
417     *y = ( ( (  66 * r + 129 * g +  25 * b + 128 ) >> 8 ) + 16 );
418     *u =   ( ( -38 * r -  74 * g + 112 * b + 128 ) >> 8 ) + 128 ;
419     *v =   ( ( 112 * r -  94 * g -  18 * b + 128 ) >> 8 ) + 128 ;
420 }
421 #endif
422
423 /*****************************************************************************
424  * DecodePacket: decodes a Kate packet.
425  *****************************************************************************/
426 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t *p_block )
427 {
428     decoder_sys_t *p_sys = p_dec->p_sys;
429     const kate_event *ev=NULL;
430     subpicture_t *p_spu = NULL;
431     subpicture_region_t *p_bitmap_region = NULL;
432     int ret;
433 #ifdef ENABLE_BITMAPS
434     size_t n, y;
435     picture_t *pic = NULL;
436 #endif
437     video_format_t fmt;
438     kate_tracker kin;
439     bool tracker_valid = false;
440
441     ret = kate_decode_packetin( &p_sys->k, p_kp );
442     if( ret < 0 )
443     {
444         msg_Err( p_dec, "Kate failed to decode packet: %d", ret );
445         return NULL;
446     }
447
448     ret = kate_decode_eventout( &p_sys->k, &ev );
449     if( ret < 0 )
450     {
451         msg_Err( p_dec, "Kate failed to retrieve event: %d", ret );
452         return NULL;
453     }
454     if( ret > 0 )
455     {
456         /* no event to go with this packet, this is normal */
457         return NULL;
458     }
459
460     /* we have an event */
461
462     /* Get a new spu */
463     p_spu = p_dec->pf_spu_buffer_new( p_dec );
464     if( !p_spu )
465     {
466         msg_Err( p_dec, "Failed to allocate spu buffer" );
467         return NULL;
468     }
469
470     p_spu->b_pausable = true;
471
472 #ifdef ENABLE_BITMAPS
473     if (ev->bitmap && ev->palette) {
474         /* create a separate region for the bitmap */
475         memset( &fmt, 0, sizeof(video_format_t) );
476         fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
477         fmt.i_aspect = 0;
478         fmt.i_width = fmt.i_visible_width = ev->bitmap->width;
479         fmt.i_height = fmt.i_visible_height = ev->bitmap->height;
480         fmt.i_x_offset = fmt.i_y_offset = 0;
481
482         p_bitmap_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
483         if( !p_bitmap_region )
484         {
485             msg_Err( p_dec, "cannot allocate SPU region" );
486             p_dec->pf_spu_buffer_del( p_dec, p_spu );
487             return NULL;
488         }
489
490         /* create the palette */
491         fmt.p_palette->i_entries = ev->palette->ncolors;
492         for (n=0; n<ev->palette->ncolors; ++n)
493         {
494             rgb_to_yuv(
495                 &fmt.p_palette->palette[n][0], &fmt.p_palette->palette[n][1], &fmt.p_palette->palette[n][2],
496                 ev->palette->colors[n].r, ev->palette->colors[n].g, ev->palette->colors[n].b
497             );
498             fmt.p_palette->palette[n][3] = ev->palette->colors[n].a;
499         }
500
501         /* create the bitmap */
502         pic = &p_bitmap_region->picture;
503         for (y=0; y<ev->bitmap->height; ++y) {
504           uint8_t *dest=pic->Y_PIXELS+pic->Y_PITCH*y;
505           const uint8_t *src=ev->bitmap->pixels+y*ev->bitmap->width;
506           memcpy(dest, src, ev->bitmap->width);
507         }
508
509         msg_Dbg(p_dec, "Created bitmap, %dx%d, %d colors\n", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors);
510     }
511 #endif
512
513     /* Create a new subpicture region */
514     memset( &fmt, 0, sizeof(video_format_t) );
515     fmt.i_chroma = VLC_FOURCC('T','E','X','T');
516     fmt.i_aspect = 0;
517     fmt.i_width = fmt.i_height = 0;
518     fmt.i_x_offset = fmt.i_y_offset = 0;
519
520 #ifdef ENABLE_FORMATTING
521     if (p_sys->b_formatted)
522     {
523         ret = kate_tracker_init( &kin, &p_sys->ki, ev);
524         if( ret < 0)
525         {
526             msg_Err( p_dec, "failed to initialize kate tracker, event will be unformatted: %d", ret );
527         }
528         else
529         {
530             // TODO: get window/video sizes/pos - can't find where to get those !
531             int w = 640;
532             int h = 480;
533             ret = kate_tracker_update(&kin, 0, w, h, 0, 0, w, h);
534             if( ret < 0)
535             {
536                 kate_tracker_clear(&kin);
537                 msg_Err( p_dec, "failed to update kate tracker, event will be unformatted: %d", ret );
538             }
539             else
540             {
541                 if (kin.has.region)
542                 {
543                     fmt.i_width = kin.region_w;
544                     fmt.i_height = kin.region_h;
545                 }
546
547                 // TODO: parse tracker and set style, init fmt
548                 tracker_valid = true;
549             }
550         }
551     }
552 #endif
553
554
555
556     p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
557     if( !p_spu->p_region )
558     {
559         msg_Err( p_dec, "cannot allocate SPU region" );
560         p_dec->pf_spu_buffer_del( p_dec, p_spu );
561         return NULL;
562     }
563
564     p_spu->p_region->psz_text = strdup(ev->text); /* no leak, this actually gets killed by the core */
565     p_spu->i_start = p_block->i_pts;
566     p_spu->i_stop = p_block->i_pts + I64C(1000000)*ev->duration*p_sys->ki.gps_denominator/p_sys->ki.gps_numerator;
567     p_spu->b_ephemer = (p_block->i_length == 0);
568     p_spu->b_absolute = false;
569
570     if (tracker_valid)
571     {
572         p_spu->i_flags = 0;
573         if (kin.has.region)
574         {
575             p_spu->p_region->i_x = kin.region_x;
576             p_spu->p_region->i_y = kin.region_y;
577             if (p_bitmap_region) {
578                 p_bitmap_region->i_x = kin.region_x;
579                 p_bitmap_region->i_y = kin.region_y;
580             }
581         }
582
583         kate_tracker_clear(&kin);
584     }
585     else
586     {
587         /* Normal text subs, easy markup */
588         p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
589         if (p_bitmap_region) {
590             p_bitmap_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
591         }
592         p_spu->i_x = 0;
593         p_spu->i_y = 10;
594     }
595
596 #ifdef ENABLE_BITMAPS
597     /* if we have a bitmap, chain it before the text */
598     if (p_bitmap_region)
599     {
600         p_bitmap_region->p_next = p_spu->p_region;
601         p_spu->p_region = p_bitmap_region;
602     }
603 #endif
604
605     return p_spu;
606 }
607
608 /*****************************************************************************
609  * ParseKateComments: FIXME should be done in demuxer
610  *****************************************************************************/
611 static void ParseKateComments( decoder_t *p_dec )
612 {
613     input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
614     char *psz_name, *psz_value, *psz_comment;
615     int i = 0;
616
617     if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
618
619     while ( i < p_dec->p_sys->kc.comments )
620     {
621         psz_comment = strdup( p_dec->p_sys->kc.user_comments[i] );
622         if( !psz_comment )
623         {
624             msg_Warn( p_dec, "out of memory" );
625             break;
626         }
627         psz_name = psz_comment;
628         psz_value = strchr( psz_comment, '=' );
629         if( psz_value )
630         {
631             *psz_value = '\0';
632             psz_value++;
633             input_Control( p_input, INPUT_ADD_INFO, _("Kate comment"),
634                            psz_name, "%s", psz_value );
635         }
636         free( psz_comment );
637         i++;
638     }
639 }
640
641 /*****************************************************************************
642  * CloseDecoder: clean up the decoder
643  *****************************************************************************/
644 static void CloseDecoder( vlc_object_t *p_this )
645 {
646     decoder_t *p_dec = (decoder_t *)p_this;
647     decoder_sys_t *p_sys = p_dec->p_sys;
648
649     if (p_sys->b_ready)
650         kate_clear( &p_sys->k );
651     kate_info_clear( &p_sys->ki );
652     kate_comment_clear( &p_sys->kc );
653
654     free( p_sys );
655 }
656