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;
556 bool tracker_valid = false;
558 ret = kate_decode_packetin( &p_sys->k, p_kp );
561 msg_Err( p_dec, "Kate failed to decode packet: %d", ret );
565 ret = kate_decode_eventout( &p_sys->k, &ev );
568 msg_Err( p_dec, "Kate failed to retrieve event: %d", ret );
573 /* no event to go with this packet, this is normal */
577 /* we have an event */
580 p_spu = p_dec->pf_spu_buffer_new( p_dec );
583 msg_Err( p_dec, "Failed to allocate spu buffer" );
587 /* these may be 0 for "not specified" */
588 p_spu->i_original_picture_width = p_sys->ki.original_canvas_width;
589 p_spu->i_original_picture_height = p_sys->ki.original_canvas_height;
591 /* Create a new subpicture region */
592 memset( &fmt, 0, sizeof(video_format_t) );
594 #ifdef ENABLE_FORMATTING
595 if (p_sys->b_formatted)
597 ret = kate_tracker_init( &kin, &p_sys->ki, ev );
600 msg_Err( p_dec, "failed to initialize kate tracker, event will be unformatted: %d", ret );
604 int w = 720, h = 576; /* give sensible defaults just in case we fail to get the actual size */
605 GetVideoSize(p_dec, &w, &h);
606 ret = kate_tracker_update(&kin, 0, w, h, 0, 0, w, h);
609 kate_tracker_clear(&kin);
610 msg_Err( p_dec, "failed to update kate tracker, event will be unformatted: %d", ret );
614 // TODO: parse tracker and set style, init fmt
615 tracker_valid = true;
621 #ifdef ENABLE_BITMAPS
622 if (ev->bitmap && ev->bitmap->type==kate_bitmap_type_paletted && ev->palette) {
623 /* create a separate region for the bitmap */
624 memset( &fmt, 0, sizeof(video_format_t) );
625 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
627 fmt.i_width = fmt.i_visible_width = ev->bitmap->width;
628 fmt.i_height = fmt.i_visible_height = ev->bitmap->height;
629 fmt.i_x_offset = fmt.i_y_offset = 0;
631 p_bitmap_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
632 if( !p_bitmap_region )
634 msg_Err( p_dec, "cannot allocate SPU region" );
635 p_dec->pf_spu_buffer_del( p_dec, p_spu );
639 /* create the palette */
640 CreateKatePalette( fmt.p_palette, ev->palette );
642 /* create the bitmap */
643 CreateKateBitmap( &p_bitmap_region->picture, ev->bitmap );
645 msg_Dbg(p_dec, "Created bitmap, %zux%zu, %zu colors\n", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors);
650 fmt.i_chroma = VLC_FOURCC('T','E','X','T');
652 fmt.i_width = fmt.i_height = 0;
653 fmt.i_x_offset = fmt.i_y_offset = 0;
654 p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
655 if( !p_spu->p_region )
657 msg_Err( p_dec, "cannot allocate SPU region" );
658 p_dec->pf_spu_buffer_del( p_dec, p_spu );
662 SetupText( p_dec, p_spu, ev );
664 p_spu->i_start = p_block->i_pts;
665 p_spu->i_stop = p_block->i_pts + INT64_C(1000000)*ev->duration*p_sys->ki.gps_denominator/p_sys->ki.gps_numerator;
666 p_spu->b_ephemer = (p_block->i_length == 0);
667 p_spu->b_absolute = false;
669 /* default positioning */
670 p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
673 p_bitmap_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
675 p_spu->p_region->i_x = 0;
676 p_spu->p_region->i_y = 10;
678 /* override if tracker info present */
683 p_spu->p_region->i_x = kin.region_x;
684 p_spu->p_region->i_y = kin.region_y;
685 p_spu->b_absolute = true;
688 kate_tracker_clear(&kin);
691 #ifdef ENABLE_BITMAPS
692 /* if we have a bitmap, chain it before the text */
695 p_bitmap_region->p_next = p_spu->p_region;
696 p_spu->p_region = p_bitmap_region;
703 /*****************************************************************************
704 * ParseKateComments: FIXME should be done in demuxer
705 *****************************************************************************/
706 static void ParseKateComments( decoder_t *p_dec )
708 input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
709 char *psz_name, *psz_value, *psz_comment;
712 if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
714 while ( i < p_dec->p_sys->kc.comments )
716 psz_comment = strdup( p_dec->p_sys->kc.user_comments[i] );
719 msg_Warn( p_dec, "out of memory" );
722 psz_name = psz_comment;
723 psz_value = strchr( psz_comment, '=' );
728 input_Control( p_input, INPUT_ADD_INFO, _("Kate comment"),
729 psz_name, "%s", psz_value );
736 /*****************************************************************************
737 * CloseDecoder: clean up the decoder
738 *****************************************************************************/
739 static void CloseDecoder( vlc_object_t *p_this )
741 decoder_t *p_dec = (decoder_t *)p_this;
742 decoder_sys_t *p_sys = p_dec->p_sys;
745 kate_clear( &p_sys->k );
746 kate_info_clear( &p_sys->ki );
747 kate_comment_clear( &p_sys->kc );