📄 kate.c
字号:
/***************************************************************************** * kate.c : a decoder for the kate bitstream format ***************************************************************************** * Copyright (C) 2000-2006 the VideoLAN team * $Id: 09f2ed29fc0fb1089471f297f56593109a64ba8b $ * * Authors: Vincent Penquerc'h <ogg.k.ogg.k@googlemail.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************//***************************************************************************** * Preamble *****************************************************************************/#ifdef HAVE_CONFIG_H# include "config.h"#endif#include <vlc_common.h>#include <vlc_plugin.h>#include <vlc_input.h>#include <vlc_codec.h>#include <vlc_osd.h>#include <kate/kate.h>/* #define ENABLE_PACKETIZER */#define ENABLE_FORMATTING#define ENABLE_BITMAPS/***************************************************************************** * decoder_sys_t : decoder descriptor *****************************************************************************/struct decoder_sys_t{#ifdef ENABLE_PACKETIZER /* Module mode */ bool b_packetizer;#endif /* * Input properties */ int i_num_headers; int i_headers; /* * Kate properties */ bool b_ready; kate_info ki; kate_comment kc; kate_state k; /* * Common properties */ mtime_t i_pts; /* * Options */#ifdef ENABLE_FORMATTING bool b_formatted;#endif};/***************************************************************************** * Local prototypes *****************************************************************************/static int OpenDecoder ( vlc_object_t * );static void CloseDecoder ( vlc_object_t * );#ifdef ENABLE_PACKETIZERstatic int OpenPacketizer( vlc_object_t *p_this );#endifstatic subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block );static int ProcessHeaders( decoder_t *p_dec );static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp, block_t **pp_block );static subpicture_t *DecodePacket( decoder_t *p_dec, kate_packet *p_kp, block_t *p_block );static void ParseKateComments( decoder_t * );#define DEFAULT_NAME "Default"#define MAX_LINE 8192/***************************************************************************** * Module descriptor. *****************************************************************************/#ifdef ENABLE_FORMATTING#define FORMAT_TEXT N_("Formatted Subtitles")#define FORMAT_LONGTEXT N_("Kate streams allow for text formatting. " \ "VLC partly implements this, but you can choose to disable all formatting.")#endifvlc_module_begin(); set_shortname( N_("Kate")); set_description( N_("Kate text subtitles decoder") ); set_capability( "decoder", 50 ); set_callbacks( OpenDecoder, CloseDecoder ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_SCODEC ); add_shortcut( "kate" );#ifdef ENABLE_PACKETIZER add_submodule(); set_description( N_("Kate text subtitles packetizer") ); set_capability( "packetizer", 100 ); set_callbacks( OpenPacketizer, CloseDecoder ); add_shortcut( "kate" );#endif#ifdef ENABLE_FORMATTING add_bool( "kate-formatted", true, NULL, FORMAT_TEXT, FORMAT_LONGTEXT, true );#endifvlc_module_end();/***************************************************************************** * OpenDecoder: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/static int OpenDecoder( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*)p_this; decoder_sys_t *p_sys; msg_Dbg( p_dec, "kate: OpenDecoder"); if( p_dec->fmt_in.i_codec != VLC_FOURCC('k','a','t','e') ) { return VLC_EGENERIC; } /* Set callbacks */ p_dec->pf_decode_sub = (subpicture_t *(*)(decoder_t *, block_t **)) DecodeBlock; p_dec->pf_packetize = (block_t *(*)(decoder_t *, block_t **)) DecodeBlock; /* Allocate the memory needed to store the decoder's structure */ if( ( p_dec->p_sys = p_sys = (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL ) return VLC_ENOMEM; /* init of p_sys */#ifdef ENABLE_PACKETIZER p_sys->b_packetizer = false;#endif p_sys->b_ready = false; p_sys->i_pts = 0; kate_comment_init( &p_sys->kc ); kate_info_init( &p_sys->ki ); p_sys->i_num_headers = 0; p_sys->i_headers = 0; /* retrieve options */#ifdef ENABLE_FORMATTING p_sys->b_formatted = var_CreateGetBool( p_dec, "kate-formatted" );#endif return VLC_SUCCESS;}#ifdef ENABLE_PACKETIZERstatic int OpenPacketizer( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*)p_this; int i_ret = OpenDecoder( p_this ); if( i_ret == VLC_SUCCESS ) { p_dec->p_sys->b_packetizer = true; p_dec->fmt_out.i_codec = VLC_FOURCC( 'k', 'a', 't', 'e' ); } return i_ret;}#endif/**************************************************************************** * DecodeBlock: the whole thing **************************************************************************** * This function must be fed with kate packets. ****************************************************************************/static subpicture_t *DecodeBlock( decoder_t *p_dec, block_t **pp_block ){ decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; kate_packet kp; if( !pp_block || !*pp_block ) return NULL; p_block = *pp_block; if( p_block->i_rate != 0 ) p_block->i_length = p_block->i_length * p_block->i_rate / INPUT_RATE_DEFAULT; /* Block to Kate packet */ kate_packet_wrap(&kp, p_block->i_buffer, p_block->p_buffer); if( p_sys->i_headers == 0 && p_dec->fmt_in.i_extra ) { /* Headers already available as extra data */ p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0]; p_sys->i_headers = p_sys->i_num_headers; } else if( kp.nbytes && (p_sys->i_headers==0 || p_sys->i_headers < p_sys->ki.num_headers )) { /* Backup headers as extra data */ uint8_t *p_extra; p_dec->fmt_in.p_extra = realloc( p_dec->fmt_in.p_extra, p_dec->fmt_in.i_extra + kp.nbytes + 2 ); p_extra = (void*)(((unsigned char*)p_dec->fmt_in.p_extra) + p_dec->fmt_in.i_extra); *(p_extra++) = kp.nbytes >> 8; *(p_extra++) = kp.nbytes & 0xFF; memcpy( p_extra, kp.data, kp.nbytes ); p_dec->fmt_in.i_extra += kp.nbytes + 2; block_Release( *pp_block ); p_sys->i_num_headers = ((unsigned char*)p_dec->fmt_in.p_extra)[0]; p_sys->i_headers++; return NULL; } if( p_sys->i_headers == p_sys->i_num_headers && p_sys->i_num_headers>0 ) { if( ProcessHeaders( p_dec ) != VLC_SUCCESS ) { p_sys->i_headers = 0; p_dec->fmt_in.i_extra = 0; block_Release( *pp_block ); return NULL; } else p_sys->i_headers++; } return ProcessPacket( p_dec, &kp, pp_block );}/***************************************************************************** * ProcessHeaders: process Kate headers. *****************************************************************************/static int ProcessHeaders( decoder_t *p_dec ){ decoder_sys_t *p_sys = p_dec->p_sys; kate_packet kp; uint8_t *p_extra; int i_extra; int headeridx; int ret; if( !p_dec->fmt_in.i_extra ) return VLC_EGENERIC; p_extra = p_dec->fmt_in.p_extra; i_extra = p_dec->fmt_in.i_extra; /* skip number of headers */ ++p_extra; --i_extra; /* Take care of the initial Kate header */ kp.nbytes = *(p_extra++) << 8; kp.nbytes |= (*(p_extra++) & 0xFF); kp.data = p_extra; p_extra += kp.nbytes; i_extra -= (kp.nbytes + 2); if( i_extra < 0 ) { msg_Err( p_dec, "header data corrupted"); return VLC_EGENERIC; } ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); if( ret < 0 ) { msg_Err( p_dec, "this bitstream does not contain Kate data (%d)", ret ); return VLC_EGENERIC; } msg_Dbg( p_dec, "%s %s text, granule rate %f, granule shift %d", p_sys->ki.language, p_sys->ki.category, (double)p_sys->ki.gps_numerator/p_sys->ki.gps_denominator, p_sys->ki.granule_shift); /* parse all remaining header packets */ for (headeridx=1; headeridx<p_sys->ki.num_headers; ++headeridx) { kp.nbytes = *(p_extra++) << 8; kp.nbytes |= (*(p_extra++) & 0xFF); kp.data = p_extra; p_extra += kp.nbytes; i_extra -= (kp.nbytes + 2); if( i_extra < 0 ) { msg_Err( p_dec, "header %d data corrupted", headeridx); return VLC_EGENERIC; } ret = kate_decode_headerin( &p_sys->ki, &p_sys->kc, &kp ); if( ret < 0 ) { msg_Err( p_dec, "Kate header %d is corrupted: %d", headeridx, ret); return VLC_EGENERIC; } /* header 1 is comments */ if( headeridx == 1 ) { ParseKateComments( p_dec ); } }#ifdef ENABLE_PACKETIZER if( !p_sys->b_packetizer )#endif { /* We have all the headers, initialize decoder */ msg_Dbg( p_dec, "we have all headers, initialize libkate for decoding" ); ret = kate_decode_init( &p_sys->k, &p_sys->ki ); if (ret < 0) { msg_Err( p_dec, "Kate failed to initialize for decoding: %d", ret ); return VLC_EGENERIC; } p_sys->b_ready = true; }#ifdef ENABLE_PACKETIZER else { p_dec->fmt_out.i_extra = p_dec->fmt_in.i_extra; p_dec->fmt_out.p_extra = realloc( p_dec->fmt_out.p_extra, p_dec->fmt_out.i_extra ); memcpy( p_dec->fmt_out.p_extra, p_dec->fmt_in.p_extra, p_dec->fmt_out.i_extra ); }#endif return VLC_SUCCESS;}/***************************************************************************** * ProcessPacket: processes a kate packet. *****************************************************************************/static subpicture_t *ProcessPacket( decoder_t *p_dec, kate_packet *p_kp, block_t **pp_block ){ decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block = *pp_block; subpicture_t *p_buf = NULL; /* Date management */ if( p_block->i_pts > 0 && p_block->i_pts != p_sys->i_pts ) { p_sys->i_pts = p_block->i_pts; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -