1 /*****************************************************************************
2 * kate.c : a decoder for the kate bitstream format
3 *****************************************************************************
4 * Copyright (C) 2000-2006 the VideoLAN team
7 * Authors: Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com>
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.
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.
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 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_input.h>
34 #include <vlc_codec.h>
37 #include <kate/kate.h>
39 /* #define ENABLE_PACKETIZER */
40 #define ENABLE_FORMATTING
41 #define ENABLE_BITMAPS
43 /*****************************************************************************
44 * decoder_sys_t : decoder descriptor
45 *****************************************************************************/
48 #ifdef ENABLE_PACKETIZER
75 #ifdef ENABLE_FORMATTING
80 /*****************************************************************************
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 );
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,
93 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp,
95 static void ParseKateComments( decoder_t * );
97 #define DEFAULT_NAME "Default"
100 /*****************************************************************************
102 *****************************************************************************/
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.")
112 set_shortname( N_("Kate"));
113 set_description( N_("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" );
120 #ifdef ENABLE_PACKETIZER
122 set_description( N_("Kate text subtitles packetizer") );
123 set_capability( "packetizer", 100 );
124 set_callbacks( OpenPacketizer, CloseDecoder );
125 add_shortcut( "kate" );
128 #ifdef ENABLE_FORMATTING
129 add_bool( "kate-formatted", true, NULL, FORMAT_TEXT, FORMAT_LONGTEXT,
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
139 *****************************************************************************/
140 static int OpenDecoder( vlc_object_t *p_this )
142 decoder_t *p_dec = (decoder_t*)p_this;
143 decoder_sys_t *p_sys;
145 msg_Dbg( p_dec, "kate: OpenDecoder");
147 if( p_dec->fmt_in.i_codec != VLC_FOURCC('k','a','t','e') )
153 p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **))
155 p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **))
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 )
164 #ifdef ENABLE_PACKETIZER
165 p_sys->b_packetizer = false;
167 p_sys->b_ready = false;
170 kate_comment_init( &p_sys->kc );
171 kate_info_init( &p_sys->ki );
173 p_sys->i_num_headers = 0;
174 p_sys->i_headers = 0;
176 /* retrieve options */
177 #ifdef ENABLE_FORMATTING
178 p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" );
184 #ifdef ENABLE_PACKETIZER
185 static int OpenPacketizer( vlc_object_t *p_this )
187 decoder_t *p_dec = (decoder_t*)p_this;
189 int i_ret = OpenDecoder( p_this );
191 if( i_ret == VLC_SUCCESS )
193 p_dec->p_sys->b_packetizer = true;
194 p_dec->fmt_out.i_codec = VLC_FOURCC( 'k', 'a', 't', 'e' );
201 /****************************************************************************
202 * DecodeBlock: the whole thing
203 ****************************************************************************
204 * This function must be fed with kate packets.
205 ****************************************************************************/
206 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
208 decoder_sys_t *p_sys = p_dec->p_sys;
212 if( !pp_block || !*pp_block )
216 if( p_block->i_rate != 0 )
217 p_block->i_length = p_block->i_length * p_block->i_rate / INPUT_RATE_DEFAULT;
219 /* Block to Kate packet */
220 kate_packet_wrap(&kp, p_block->i_buffer, p_block->p_buffer);
222 if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
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;
228 else if( kp.nbytes && (p_sys->i_headers==0 || p_sys->i_headers < p_sys->ki.num_headers ))
230 /* Backup headers as extra data */
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;
239 memcpy( p_extra, kp.data, kp.nbytes );
240 p_dec->fmt_in.i_extra += kp.nbytes + 2;
242 block_Release( *pp_block );
243 p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0];
248 if( p_sys->i_headers == p_sys->i_num_headers && p_sys->i_num_headers>0 )
250 if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
252 p_sys->i_headers = 0;
253 p_dec->fmt_in.i_extra = 0;
254 block_Release( *pp_block );
257 else p_sys->i_headers++;
260 return ProcessPacket( p_dec, &kp, pp_block );
263 /*****************************************************************************
264 * ProcessHeaders: process Kate headers.
265 *****************************************************************************/
266 static int ProcessHeaders( decoder_t *p_dec )
268 decoder_sys_t *p_sys = p_dec->p_sys;
275 if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
277 p_extra = p_dec->fmt_in.p_extra;
278 i_extra = p_dec->fmt_in.i_extra;
280 /* skip number of headers */
284 /* Take care of the initial Kate header */
285 kp.nbytes = *(p_extra++) << 8;
286 kp.nbytes |= (*(p_extra++) & 0xFF);
288 p_extra += kp.nbytes;
289 i_extra -= (kp.nbytes + 2);
292 msg_Err( p_dec, "header data corrupted");
296 ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
299 msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", ret );
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);
308 /* parse all remaining header packets */
309 for (headeridx=1; headeridx<p_sys->ki.num_headers; ++headeridx)
311 kp.nbytes = *(p_extra++) << 8;
312 kp.nbytes |= (*(p_extra++) & 0xFF);
314 p_extra += kp.nbytes;
315 i_extra -= (kp.nbytes + 2);
318 msg_Err( p_dec, "header %d data corrupted", headeridx);
322 ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
325 msg_Err( p_dec, "Kate header %d is corrupted: %d", headeridx, ret);
329 /* header 1 is comments */
332 ParseKateComments( p_dec );
336 #ifdef ENABLE_PACKETIZER
337 if( !p_sys->b_packetizer )
340 /* We have all the headers, initialize decoder */
341 msg_Dbg( p_dec, "we have all headers, initialize libkate for decoding" );
342 ret = kate_decode_init( &p_sys->k, &p_sys->ki );
345 msg_Err( p_dec, "Kate failed to initialize for decoding: %d", ret );
348 p_sys->b_ready = true;
350 #ifdef ENABLE_PACKETIZER
353 p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
354 p_dec->fmt_out.p_extra =
355 realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
356 memcpy( p_dec->fmt_out.p_extra,
357 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
364 /*****************************************************************************
365 * ProcessPacket: processes a kate packet.
366 *****************************************************************************/
367 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
370 decoder_sys_t *p_sys = p_dec->p_sys;
371 block_t *p_block = *pp_block;
372 subpicture_t *p_buf = NULL;
374 /* Date management */
375 if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
377 p_sys->i_pts = p_block->i_pts;
380 *pp_block = NULL; /* To avoid being fed the same packet again */
382 #ifdef ENABLE_PACKETIZER
383 if( p_sys->b_packetizer )
385 /* Date management */
386 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
388 if( p_sys->i_headers >= p_sys->i_num_headers )
389 p_block->i_length = p_sys->i_pts - p_block->i_pts;
391 p_block->i_length = 0;
398 if( p_sys->i_headers >= p_sys->i_num_headers )
399 p_buf = DecodePacket( p_dec, p_kp, p_block );
403 if( p_block ) block_Release( p_block );
409 #ifdef ENABLE_BITMAPS
410 /* nicked off blend.c */
411 static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
412 int r, int g, int b )
414 *y = ( ( ( 66 * r + 129 * g + 25 * b + 128 ) >> 8 ) + 16 );
415 *u = ( ( -38 * r - 74 * g + 112 * b + 128 ) >> 8 ) + 128 ;
416 *v = ( ( 112 * r - 94 * g - 18 * b + 128 ) >> 8 ) + 128 ;
421 This retrieves the size of the video.
422 The best case is when the original video size is known, as we can then
423 scale images to match. In this case, since VLC autoscales, we want to
424 return the original size and let VLC scale everything.
425 if the original size is not known, then VLC can't resize, so we return
426 the size of the incoming video. If sizes in the Kate stream are in
427 relative units, it works fine. If they are absolute, you get what you
428 ask for. Images aren't rescaled.
430 static void GetVideoSize( decoder_t *p_dec, int *w, int *h )
432 /* searching for vout to get its size is frowned upon, so we don't and
433 use a default size if the original canvas size is not specified. */
435 decoder_sys_t *p_sys = p_dec->p_sys;
436 if( p_sys->ki.original_canvas_width > 0 && p_sys->ki.original_canvas_height > 0 )
438 *w = p_sys->ki.original_canvas_width;
439 *h = p_sys->ki.original_canvas_height;
440 msg_Dbg( p_dec, "original canvas %zu %zu\n",
441 p_sys->ki.original_canvas_width, p_sys->ki.original_canvas_height );
445 /* nothing, leave defaults */
446 msg_Dbg( p_dec, "original canvas size unknown\n");
449 /* keep this just in case it might be allowed one day ;) */
450 vout_thread_t *p_vout;
451 p_vout = vlc_object_find( (vlc_object_t*)p_dec, VLC_OBJECT_VOUT, FIND_CHILD );
454 decoder_sys_t *p_sys = p_dec->p_sys;
455 if( p_sys->ki.original_canvas_width > 0 && p_sys->ki.original_canvas_height > 0 )
457 *w = p_sys->ki.original_canvas_width;
458 *h = p_sys->ki.original_canvas_height;
462 *w = p_vout->fmt_in.i_width;
463 *h = p_vout->fmt_in.i_height;
465 msg_Dbg( p_dec, "video: in %d %d, out %d %d, original canvas %zu %zu\n",
466 p_vout->fmt_in.i_width, p_vout->fmt_in.i_height,
467 p_vout->fmt_out.i_width, p_vout->fmt_out.i_height,
468 p_sys->ki.original_canvas_width, p_sys->ki.original_canvas_height );
469 vlc_object_release( p_vout );
474 #ifdef ENABLE_BITMAPS
476 static void CreateKateBitmap( picture_t *pic, const kate_bitmap *bitmap )
480 for( y=0; y<bitmap->height; ++y )
482 uint8_t *dest = pic->Y_PIXELS+pic->Y_PITCH*y;
483 const uint8_t *src = bitmap->pixels+y*bitmap->width;
484 memcpy( dest, src, bitmap->width );
488 static void CreateKatePalette( video_palette_t *fmt_palette, const kate_palette *palette )
492 fmt_palette->i_entries = palette->ncolors;
493 for( n=0; n<palette->ncolors; ++n )
496 &fmt_palette->palette[n][0], &fmt_palette->palette[n][1], &fmt_palette->palette[n][2],
497 palette->colors[n].r, palette->colors[n].g, palette->colors[n].b
499 fmt_palette->palette[n][3] = palette->colors[n].a;
505 static void SetupText( decoder_t *p_dec, subpicture_t *p_spu, const kate_event *ev )
507 decoder_sys_t *p_sys = p_dec->p_sys;
509 if( ev->text_encoding != kate_utf8 )
511 msg_Warn( p_dec, "Text isn't UTF-8, unsupported, ignored" );
515 switch( ev->text_markup_type )
517 case kate_markup_none:
518 p_spu->p_region->psz_text = strdup( ev->text ); /* no leak, this actually gets killed by the core */
520 case kate_markup_simple:
521 if( p_sys->b_formatted )
523 /* the HTML renderer expects a top level text tag pair */
525 if( asprintf( &buffer, "<text>%s</text>", ev->text ) >= 0 )
527 p_spu->p_region->psz_html = buffer;
531 /* if not formatted, we fall through */
533 /* we don't know about this one, so remove markup and display as text */
535 char *copy = strdup( ev->text );
536 size_t len0 = strlen( copy ) + 1;
537 kate_text_remove_markup( ev->text_encoding, copy, &len0 );
538 p_spu->p_region->psz_text = copy;
544 /*****************************************************************************
545 * DecodePacket: decodes a Kate packet.
546 *****************************************************************************/
547 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t *p_block )
549 decoder_sys_t *p_sys = p_dec->p_sys;
550 const kate_event *ev = NULL;
551 subpicture_t *p_spu = NULL;
552 subpicture_region_t *p_bitmap_region = NULL;
555 video_format_t palette;
557 bool tracker_valid = false;
559 ret = kate_decode_packetin( &p_sys->k, p_kp );
562 msg_Err( p_dec, "Kate failed to decode packet: %d", ret );
566 ret = kate_decode_eventout( &p_sys->k, &ev );
569 msg_Err( p_dec, "Kate failed to retrieve event: %d", ret );
574 /* no event to go with this packet, this is normal */
578 /* we have an event */
581 p_spu = p_dec->pf_spu_buffer_new( p_dec );
584 msg_Err( p_dec, "Failed to allocate spu buffer" );
588 /* these may be 0 for "not specified" */
589 p_spu->i_original_picture_width = p_sys->ki.original_canvas_width;
590 p_spu->i_original_picture_height = p_sys->ki.original_canvas_height;
592 /* Create a new subpicture region */
593 memset( &fmt, 0, sizeof(video_format_t) );
595 #ifdef ENABLE_FORMATTING
596 if (p_sys->b_formatted)
598 ret = kate_tracker_init( &kin, &p_sys->ki, ev );
601 msg_Err( p_dec, "failed to initialize kate tracker, event will be unformatted: %d", ret );
605 int w = 720, h = 576; /* give sensible defaults just in case we fail to get the actual size */
606 GetVideoSize(p_dec, &w, &h);
607 ret = kate_tracker_update(&kin, 0, w, h, 0, 0, w, h);
610 kate_tracker_clear(&kin);
611 msg_Err( p_dec, "failed to update kate tracker, event will be unformatted: %d", ret );
615 // TODO: parse tracker and set style, init fmt
616 tracker_valid = true;
622 #ifdef ENABLE_BITMAPS
623 if (ev->bitmap && ev->bitmap->type==kate_bitmap_type_paletted && ev->palette) {
625 /* create a separate region for the bitmap */
626 memset( &fmt, 0, sizeof(video_format_t) );
627 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
629 fmt.i_width = fmt.i_visible_width = ev->bitmap->width;
630 fmt.i_height = fmt.i_visible_height = ev->bitmap->height;
631 fmt.i_x_offset = fmt.i_y_offset = 0;
632 fmt.p_palette = &palette;
633 CreateKatePalette( fmt.p_palette, ev->palette );
635 p_bitmap_region = subpicture_region_New( &fmt );
636 if( !p_bitmap_region )
638 msg_Err( p_dec, "cannot allocate SPU region" );
639 p_dec->pf_spu_buffer_del( p_dec, p_spu );
643 /* create the bitmap */
644 CreateKateBitmap( p_bitmap_region->p_picture, ev->bitmap );
646 msg_Dbg(p_dec, "Created bitmap, %zux%zu, %zu colors\n", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors);
651 fmt.i_chroma = VLC_FOURCC('T','E','X','T');
653 fmt.i_width = fmt.i_height = 0;
654 fmt.i_x_offset = fmt.i_y_offset = 0;
655 p_spu->p_region = subpicture_region_New( &fmt );
656 if( !p_spu->p_region )
658 msg_Err( p_dec, "cannot allocate SPU region" );
659 p_dec->pf_spu_buffer_del( p_dec, p_spu );
663 SetupText( p_dec, p_spu, ev );
665 p_spu->i_start = p_block->i_pts;
666 p_spu->i_stop = p_block->i_pts + INT64_C(1000000)*ev->duration*p_sys->ki.gps_denominator/p_sys->ki.gps_numerator;
667 p_spu->b_ephemer = (p_block->i_length == 0);
668 p_spu->b_absolute = false;
670 /* default positioning */
671 p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
674 p_bitmap_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
676 p_spu->p_region->i_x = 0;
677 p_spu->p_region->i_y = 10;
679 /* override if tracker info present */
684 p_spu->p_region->i_x = kin.region_x;
685 p_spu->p_region->i_y = kin.region_y;
686 p_spu->b_absolute = true;
689 kate_tracker_clear(&kin);
692 #ifdef ENABLE_BITMAPS
693 /* if we have a bitmap, chain it before the text */
696 p_bitmap_region->p_next = p_spu->p_region;
697 p_spu->p_region = p_bitmap_region;
704 /*****************************************************************************
705 * ParseKateComments: FIXME should be done in demuxer
706 *****************************************************************************/
707 static void ParseKateComments( decoder_t *p_dec )
709 input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
710 char *psz_name, *psz_value, *psz_comment;
713 if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
715 while ( i < p_dec->p_sys->kc.comments )
717 psz_comment = strdup( p_dec->p_sys->kc.user_comments[i] );
720 psz_name = psz_comment;
721 psz_value = strchr( psz_comment, '=' );
726 input_Control( p_input, INPUT_ADD_INFO, _("Kate comment"),
727 psz_name, "%s", psz_value );
734 /*****************************************************************************
735 * CloseDecoder: clean up the decoder
736 *****************************************************************************/
737 static void CloseDecoder( vlc_object_t *p_this )
739 decoder_t *p_dec = (decoder_t *)p_this;
740 decoder_sys_t *p_sys = p_dec->p_sys;
743 kate_clear( &p_sys->k );
744 kate_info_clear( &p_sys->ki );
745 kate_comment_clear( &p_sys->kc );