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>
36 #include <kate/kate.h>
40 /* #define ENABLE_PACKETIZER */
41 /* #define ENABLE_FORMATTING */
42 #define ENABLE_BITMAPS
44 /*****************************************************************************
45 * decoder_sys_t : decoder descriptor
46 *****************************************************************************/
49 #ifdef ENABLE_PACKETIZER
76 #ifdef ENABLE_FORMATTING
81 /*****************************************************************************
83 *****************************************************************************/
84 static int OpenDecoder ( vlc_object_t * );
85 static void CloseDecoder ( vlc_object_t * );
86 #ifdef ENABLE_PACKETIZER
87 static int OpenPacketizer( vlc_object_t *p_this );
90 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block );
91 static int ProcessHeaders( decoder_t *p_dec );
92 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
94 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp,
96 static void ParseKateComments( decoder_t * );
98 #define DEFAULT_NAME "Default"
101 /*****************************************************************************
103 *****************************************************************************/
105 #ifdef ENABLE_FORMATTING
106 #define FORMAT_TEXT N_("Formatted Subtitles")
107 #define FORMAT_LONGTEXT N_("Kate streams allow for text formatting. " \
108 "VLC partly implements this, but you can choose to disable all formatting.")
113 set_shortname( N_("Kate"));
114 set_description( N_("Kate text subtitles decoder") );
115 set_capability( "decoder", 50 );
116 set_callbacks( OpenDecoder, CloseDecoder );
117 set_category( CAT_INPUT );
118 set_subcategory( SUBCAT_INPUT_SCODEC );
119 add_shortcut( "kate" );
121 #ifdef ENABLE_PACKETIZER
123 set_description( N_("Kate text subtitles packetizer") );
124 set_capability( "packetizer", 100 );
125 set_callbacks( OpenPacketizer, CloseDecoder );
126 add_shortcut( "kate" );
129 #ifdef ENABLE_FORMATTING
130 add_bool( "kate-formatted", true, NULL, FORMAT_TEXT, FORMAT_LONGTEXT,
135 /*****************************************************************************
136 * OpenDecoder: probe the decoder and return score
137 *****************************************************************************
138 * Tries to launch a decoder and return score so that the interface is able
140 *****************************************************************************/
141 static int OpenDecoder( vlc_object_t *p_this )
143 decoder_t *p_dec = (decoder_t*)p_this;
144 decoder_sys_t *p_sys;
146 msg_Dbg( p_dec, "kate: OpenDecoder");
148 if( p_dec->fmt_in.i_codec != VLC_FOURCC('k','a','t','e') )
154 p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **))
156 p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **))
159 /* Allocate the memory needed to store the decoder's structure */
160 if( ( p_dec->p_sys = p_sys =
161 (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
165 #ifdef ENABLE_PACKETIZER
166 p_sys->b_packetizer = false;
168 p_sys->b_ready = false;
171 kate_comment_init( &p_sys->kc );
172 kate_info_init( &p_sys->ki );
174 p_sys->i_num_headers = 0;
175 p_sys->i_headers = 0;
177 /* retrieve options */
178 #ifdef ENABLE_FORMATTING
179 p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" );
185 #ifdef ENABLE_PACKETIZER
186 static int OpenPacketizer( vlc_object_t *p_this )
188 decoder_t *p_dec = (decoder_t*)p_this;
190 int i_ret = OpenDecoder( p_this );
192 if( i_ret == VLC_SUCCESS )
194 p_dec->p_sys->b_packetizer = true;
195 p_dec->fmt_out.i_codec = VLC_FOURCC( 'k', 'a', 't', 'e' );
202 /****************************************************************************
203 * DecodeBlock: the whole thing
204 ****************************************************************************
205 * This function must be fed with kate packets.
206 ****************************************************************************/
207 static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block )
209 decoder_sys_t *p_sys = p_dec->p_sys;
213 if( !pp_block || !*pp_block )
217 if( p_block->i_rate != 0 )
218 p_block->i_length = p_block->i_length * p_block->i_rate / INPUT_RATE_DEFAULT;
220 /* Block to Kate packet */
221 kate_packet_wrap(&kp, p_block->i_buffer, p_block->p_buffer);
223 if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra )
225 /* Headers already available as extra data */
226 p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0];
227 p_sys->i_headers = p_sys->i_num_headers;
229 else if( kp.nbytes && (p_sys->i_headers==0 || p_sys->i_headers < p_sys->ki.num_headers ))
231 /* Backup headers as extra data */
234 p_dec->fmt_in.p_extra =
235 realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra + kp.nbytes + 2 );
236 p_extra = (void*)(((unsigned char*)p_dec->fmt_in.p_extra) + p_dec->fmt_in.i_extra);
237 *(p_extra++) = kp.nbytes >> 8;
238 *(p_extra++) = kp.nbytes & 0xFF;
240 memcpy( p_extra, kp.data, kp.nbytes );
241 p_dec->fmt_in.i_extra += kp.nbytes + 2;
243 block_Release( *pp_block );
244 p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0];
249 if( p_sys->i_headers == p_sys->i_num_headers && p_sys->i_num_headers>0 )
251 if( ProcessHeaders( p_dec ) != VLC_SUCCESS )
253 p_sys->i_headers = 0;
254 p_dec->fmt_in.i_extra = 0;
255 block_Release( *pp_block );
258 else p_sys->i_headers++;
261 return ProcessPacket( p_dec, &kp, pp_block );
264 /*****************************************************************************
265 * ProcessHeaders: process Kate headers.
266 *****************************************************************************/
267 static int ProcessHeaders( decoder_t *p_dec )
269 decoder_sys_t *p_sys = p_dec->p_sys;
276 if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC;
278 p_extra = p_dec->fmt_in.p_extra;
279 i_extra = p_dec->fmt_in.i_extra;
281 /* skip number of headers */
285 /* Take care of the initial Kate header */
286 kp.nbytes = *(p_extra++) << 8;
287 kp.nbytes |= (*(p_extra++) & 0xFF);
289 p_extra += kp.nbytes;
290 i_extra -= (kp.nbytes + 2);
293 msg_Err( p_dec, "header data corrupted");
297 ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
300 msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", ret );
304 msg_Dbg( p_dec, "%s %s text, granule rate %f, granule shift %d",
305 p_sys->ki.language, p_sys->ki.category,
306 (double)p_sys->ki.gps_numerator/p_sys->ki.gps_denominator,
307 p_sys->ki.granule_shift);
309 /* we want markup to be removed for now */
310 kate_info_remove_markup( &p_sys->ki, 1 );
312 /* parse all remaining header packets */
313 for (headeridx=1; headeridx<p_sys->ki.num_headers; ++headeridx)
315 kp.nbytes = *(p_extra++) << 8;
316 kp.nbytes |= (*(p_extra++) & 0xFF);
318 p_extra += kp.nbytes;
319 i_extra -= (kp.nbytes + 2);
322 msg_Err( p_dec, "header %d data corrupted", headeridx);
326 ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp );
329 msg_Err( p_dec, "Kate header %d is corrupted: %d", headeridx, ret);
333 /* header 1 is comments */
336 ParseKateComments( p_dec );
340 #ifdef ENABLE_PACKETIZER
341 if( !p_sys->b_packetizer )
344 /* We have all the headers, initialize decoder */
345 msg_Dbg( p_dec, "we have all headers, initialize libkate for decoding" );
346 ret = kate_decode_init( &p_sys->k, &p_sys->ki );
349 msg_Err( p_dec, "Kate failed to initialize for decoding: %d", ret );
352 p_sys->b_ready = true;
354 #ifdef ENABLE_PACKETIZER
357 p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra;
358 p_dec->fmt_out.p_extra =
359 realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra );
360 memcpy( p_dec->fmt_out.p_extra,
361 p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra );
368 /*****************************************************************************
369 * ProcessPacket: processes a kate packet.
370 *****************************************************************************/
371 static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp,
374 decoder_sys_t *p_sys = p_dec->p_sys;
375 block_t *p_block = *pp_block;
376 subpicture_t *p_buf = NULL;
378 /* Date management */
379 if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts )
381 p_sys->i_pts = p_block->i_pts;
384 *pp_block = NULL; /* To avoid being fed the same packet again */
386 #ifdef ENABLE_PACKETIZER
387 if( p_sys->b_packetizer )
389 /* Date management */
390 p_block->i_dts = p_block->i_pts = p_sys->i_pts;
392 if( p_sys->i_headers >= p_sys->i_num_headers )
393 p_block->i_length = p_sys->i_pts - p_block->i_pts;
395 p_block->i_length = 0;
402 if( p_sys->i_headers >= p_sys->i_num_headers )
403 p_buf = DecodePacket( p_dec, p_kp, p_block );
407 if( p_block ) block_Release( p_block );
413 #ifdef ENABLE_BITMAPS
414 /* nicked off blend.c */
415 static inline void rgb_to_yuv( uint8_t *y, uint8_t *u, uint8_t *v,
416 int r, int g, int b )
418 *y = ( ( ( 66 * r + 129 * g + 25 * b + 128 ) >> 8 ) + 16 );
419 *u = ( ( -38 * r - 74 * g + 112 * b + 128 ) >> 8 ) + 128 ;
420 *v = ( ( 112 * r - 94 * g - 18 * b + 128 ) >> 8 ) + 128 ;
424 /*****************************************************************************
425 * DecodePacket: decodes a Kate packet.
426 *****************************************************************************/
427 static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t *p_block )
429 decoder_sys_t *p_sys = p_dec->p_sys;
430 const kate_event *ev=NULL;
431 subpicture_t *p_spu = NULL;
432 subpicture_region_t *p_bitmap_region = NULL;
434 #ifdef ENABLE_BITMAPS
436 picture_t *pic = NULL;
440 bool tracker_valid = false;
442 ret = kate_decode_packetin( &p_sys->k, p_kp );
445 msg_Err( p_dec, "Kate failed to decode packet: %d", ret );
449 ret = kate_decode_eventout( &p_sys->k, &ev );
452 msg_Err( p_dec, "Kate failed to retrieve event: %d", ret );
457 /* no event to go with this packet, this is normal */
461 /* we have an event */
464 p_spu = p_dec->pf_spu_buffer_new( p_dec );
467 msg_Err( p_dec, "Failed to allocate spu buffer" );
471 p_spu->b_pausable = true;
473 #ifdef ENABLE_BITMAPS
474 if (ev->bitmap && ev->bitmap->type==kate_bitmap_type_paletted && ev->palette) {
475 /* create a separate region for the bitmap */
476 memset( &fmt, 0, sizeof(video_format_t) );
477 fmt.i_chroma = VLC_FOURCC('Y','U','V','P');
479 fmt.i_width = fmt.i_visible_width = ev->bitmap->width;
480 fmt.i_height = fmt.i_visible_height = ev->bitmap->height;
481 fmt.i_x_offset = fmt.i_y_offset = 0;
483 p_bitmap_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
484 if( !p_bitmap_region )
486 msg_Err( p_dec, "cannot allocate SPU region" );
487 p_dec->pf_spu_buffer_del( p_dec, p_spu );
491 /* create the palette */
492 fmt.p_palette->i_entries = ev->palette->ncolors;
493 for (n=0; n<ev->palette->ncolors; ++n)
496 &fmt.p_palette->palette[n][0], &fmt.p_palette->palette[n][1], &fmt.p_palette->palette[n][2],
497 ev->palette->colors[n].r, ev->palette->colors[n].g, ev->palette->colors[n].b
499 fmt.p_palette->palette[n][3] = ev->palette->colors[n].a;
502 /* create the bitmap */
503 pic = &p_bitmap_region->picture;
504 for (y=0; y<ev->bitmap->height; ++y) {
505 uint8_t *dest=pic->Y_PIXELS+pic->Y_PITCH*y;
506 const uint8_t *src=ev->bitmap->pixels+y*ev->bitmap->width;
507 memcpy(dest, src, ev->bitmap->width);
510 msg_Dbg(p_dec, "Created bitmap, %zux%zu, %zu colors\n", ev->bitmap->width, ev->bitmap->height, ev->palette->ncolors);
514 /* Create a new subpicture region */
515 memset( &fmt, 0, sizeof(video_format_t) );
516 fmt.i_chroma = VLC_FOURCC('T','E','X','T');
518 fmt.i_width = fmt.i_height = 0;
519 fmt.i_x_offset = fmt.i_y_offset = 0;
521 #ifdef ENABLE_FORMATTING
522 if (p_sys->b_formatted)
524 ret = kate_tracker_init( &kin, &p_sys->ki, ev);
527 msg_Err( p_dec, "failed to initialize kate tracker, event will be unformatted: %d", ret );
531 // TODO: get window/video sizes/pos - can't find where to get those !
534 ret = kate_tracker_update(&kin, 0, w, h, 0, 0, w, h);
537 kate_tracker_clear(&kin);
538 msg_Err( p_dec, "failed to update kate tracker, event will be unformatted: %d", ret );
544 fmt.i_width = kin.region_w;
545 fmt.i_height = kin.region_h;
548 // TODO: parse tracker and set style, init fmt
549 tracker_valid = true;
557 p_spu->p_region = p_spu->pf_create_region( VLC_OBJECT(p_dec), &fmt );
558 if( !p_spu->p_region )
560 msg_Err( p_dec, "cannot allocate SPU region" );
561 p_dec->pf_spu_buffer_del( p_dec, p_spu );
565 p_spu->p_region->psz_text = strdup(ev->text); /* no leak, this actually gets killed by the core */
566 p_spu->i_start = p_block->i_pts;
567 p_spu->i_stop = p_block->i_pts + INT64_C(1000000)*ev->duration*p_sys->ki.gps_denominator/p_sys->ki.gps_numerator;
568 p_spu->b_ephemer = (p_block->i_length == 0);
569 p_spu->b_absolute = false;
576 p_spu->p_region->i_x = kin.region_x;
577 p_spu->p_region->i_y = kin.region_y;
578 if (p_bitmap_region) {
579 p_bitmap_region->i_x = kin.region_x;
580 p_bitmap_region->i_y = kin.region_y;
584 kate_tracker_clear(&kin);
588 /* Normal text subs, easy markup */
589 p_spu->p_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
590 if (p_bitmap_region) {
591 p_bitmap_region->i_align = SUBPICTURE_ALIGN_BOTTOM;
597 #ifdef ENABLE_BITMAPS
598 /* if we have a bitmap, chain it before the text */
601 p_bitmap_region->p_next = p_spu->p_region;
602 p_spu->p_region = p_bitmap_region;
609 /*****************************************************************************
610 * ParseKateComments: FIXME should be done in demuxer
611 *****************************************************************************/
612 static void ParseKateComments( decoder_t *p_dec )
614 input_thread_t *p_input = (input_thread_t *)p_dec->p_parent;
615 char *psz_name, *psz_value, *psz_comment;
618 if( p_input->i_object_type != VLC_OBJECT_INPUT ) return;
620 while ( i < p_dec->p_sys->kc.comments )
622 psz_comment = strdup( p_dec->p_sys->kc.user_comments[i] );
625 msg_Warn( p_dec, "out of memory" );
628 psz_name = psz_comment;
629 psz_value = strchr( psz_comment, '=' );
634 input_Control( p_input, INPUT_ADD_INFO, _("Kate comment"),
635 psz_name, "%s", psz_value );
642 /*****************************************************************************
643 * CloseDecoder: clean up the decoder
644 *****************************************************************************/
645 static void CloseDecoder( vlc_object_t *p_this )
647 decoder_t *p_dec = (decoder_t *)p_this;
648 decoder_sys_t *p_sys = p_dec->p_sys;
651 kate_clear( &p_sys->k );
652 kate_info_clear( &p_sys->ki );
653 kate_comment_clear( &p_sys->kc );