📄 dvbsub.c
字号:
/***************************************************************************** * dvbsub.c : DVB subtitles decoder * DVB subtitles encoder (developed for Anevia, www.anevia.com) ***************************************************************************** * Copyright (C) 2003 ANEVIA * Copyright (C) 2003-2005 the VideoLAN team * $Id: dvbsub.c 19610 2007-04-01 01:37:01Z hartman $ * * Authors: Gildas Bazin <gbazin@videolan.org> * Damien LUCAS <damien.lucas@anevia.com> * Laurent Aimar <fenrir@via.ecp.fr> * Jean-Paul Saman <jpsaman #_at_# m2x dot nl> * * 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 * * FIXME: * DVB subtitles coded as strings of characters are not handled correctly. * The character codes in the string should actually be indexes refering to a * character table identified in the subtitle descriptor. *****************************************************************************/#include <vlc/vlc.h>#include <vlc/vout.h>#include <vlc/decoder.h>#include <vlc/sout.h>#include "vlc_bits.h"/* #define DEBUG_DVBSUB 1 */#define POSX_TEXT N_("Decoding X coordinate")#define POSX_LONGTEXT N_("X coordinate of the rendered subtitle")#define POSY_TEXT N_("Decoding Y coordinate")#define POSY_LONGTEXT N_("Y coordinate of the rendered subtitle") #define POS_TEXT N_("Subpicture position")#define POS_LONGTEXT N_( \ "You can enforce the subpicture position on the video " \ "(0=center, 1=left, 2=right, 4=top, 8=bottom, you can " \ "also use combinations of these values, e.g. 6=top-right).")#define ENC_POSX_TEXT N_("Encoding X coordinate")#define ENC_POSX_LONGTEXT N_("X coordinate of the encoded subtitle" )#define ENC_POSY_TEXT N_("Encoding Y coordinate")#define ENC_POSY_LONGTEXT N_("Y coordinate of the encoded subtitle" )static int pi_pos_values[] = { 0, 1, 2, 4, 8, 5, 6, 9, 10 };static char *ppsz_pos_descriptions[] ={ N_("Center"), N_("Left"), N_("Right"), N_("Top"), N_("Bottom"), N_("Top-Left"), N_("Top-Right"), N_("Bottom-Left"), N_("Bottom-Right") };/***************************************************************************** * Module descriptor. *****************************************************************************/static int Open ( vlc_object_t * );static void Close( vlc_object_t * );static subpicture_t *Decode( decoder_t *, block_t ** );static int OpenEncoder ( vlc_object_t * );static void CloseEncoder( vlc_object_t * );static block_t *Encode ( encoder_t *, subpicture_t * );vlc_module_begin();# define DVBSUB_CFG_PREFIX "dvbsub-" set_description( _("DVB subtitles decoder") ); set_capability( "decoder", 50 ); set_category( CAT_INPUT ); set_subcategory( SUBCAT_INPUT_SCODEC ); set_callbacks( Open, Close ); add_integer( DVBSUB_CFG_PREFIX "position", 8, NULL, POS_TEXT, POS_LONGTEXT, VLC_TRUE ); change_integer_list( pi_pos_values, ppsz_pos_descriptions, 0 ); add_integer( DVBSUB_CFG_PREFIX "x", -1, NULL, POSX_TEXT, POSX_LONGTEXT, VLC_FALSE ); add_integer( DVBSUB_CFG_PREFIX "y", -1, NULL, POSY_TEXT, POSY_LONGTEXT, VLC_FALSE );# define ENC_CFG_PREFIX "sout-dvbsub-" add_submodule(); set_description( _("DVB subtitles encoder") ); set_capability( "encoder", 100 ); set_callbacks( OpenEncoder, CloseEncoder ); add_integer( ENC_CFG_PREFIX "x", -1, NULL, ENC_POSX_TEXT, ENC_POSX_LONGTEXT, VLC_FALSE ); add_integer( ENC_CFG_PREFIX "y", -1, NULL, ENC_POSY_TEXT, ENC_POSY_LONGTEXT, VLC_FALSE ); add_suppressed_integer( ENC_CFG_PREFIX "timeout" ); /* Suppressed since 0.8.5 */vlc_module_end();static const char *ppsz_enc_options[] = { "x", "y", NULL };/**************************************************************************** * Local structures **************************************************************************** * Those structures refer closely to the ETSI 300 743 Object model ****************************************************************************//* The object definition gives the position of the object in a region */typedef struct dvbsub_objectdef_s{ int i_id; int i_type; int i_x; int i_y; int i_fg_pc; int i_bg_pc; char *psz_text; /* for string of characters objects */} dvbsub_objectdef_t;/* The entry in the palette CLUT */typedef struct{ uint8_t Y; uint8_t Cr; uint8_t Cb; uint8_t T;} dvbsub_color_t;/* */typedef struct dvbsub_clut_s{ uint8_t i_id; uint8_t i_version; dvbsub_color_t c_2b[4]; dvbsub_color_t c_4b[16]; dvbsub_color_t c_8b[256]; struct dvbsub_clut_s *p_next;} dvbsub_clut_t;/* The Region is an aera on the image * with a list of the object definitions associated and a CLUT */typedef struct dvbsub_region_s{ int i_id; int i_version; int i_x; int i_y; int i_width; int i_height; int i_level_comp; int i_depth; int i_clut; uint8_t *p_pixbuf; int i_object_defs; dvbsub_objectdef_t *p_object_defs; struct dvbsub_region_s *p_next;} dvbsub_region_t;/* The object definition gives the position of the object in a region */typedef struct dvbsub_regiondef_s{ int i_id; int i_x; int i_y;} dvbsub_regiondef_t;/* The page defines the list of regions */typedef struct{ int i_id; int i_timeout; /* in seconds */ int i_state; int i_version; int i_region_defs; dvbsub_regiondef_t *p_region_defs;} dvbsub_page_t;struct decoder_sys_t{ bs_t bs; /* Decoder internal data */ int i_id; int i_ancillary_id; mtime_t i_pts; vlc_bool_t b_absolute; int i_spu_position; int i_spu_x; int i_spu_y; vlc_bool_t b_page; dvbsub_page_t *p_page; dvbsub_region_t *p_regions; dvbsub_clut_t *p_cluts; dvbsub_clut_t default_clut;};/* List of different SEGMENT TYPES *//* According to EN 300-743, table 2 */#define DVBSUB_ST_PAGE_COMPOSITION 0x10#define DVBSUB_ST_REGION_COMPOSITION 0x11#define DVBSUB_ST_CLUT_DEFINITION 0x12#define DVBSUB_ST_OBJECT_DATA 0x13#define DVBSUB_ST_ENDOFDISPLAY 0x80#define DVBSUB_ST_STUFFING 0xff/* List of different OBJECT TYPES *//* According to EN 300-743, table 6 */#define DVBSUB_OT_BASIC_BITMAP 0x00#define DVBSUB_OT_BASIC_CHAR 0x01#define DVBSUB_OT_COMPOSITE_STRING 0x02/* Pixel DATA TYPES *//* According to EN 300-743, table 9 */ #define DVBSUB_DT_2BP_CODE_STRING 0x10#define DVBSUB_DT_4BP_CODE_STRING 0x11#define DVBSUB_DT_8BP_CODE_STRING 0x12#define DVBSUB_DT_24_TABLE_DATA 0x20#define DVBSUB_DT_28_TABLE_DATA 0x21#define DVBSUB_DT_48_TABLE_DATA 0x22#define DVBSUB_DT_END_LINE 0xf0/* List of different Page Composition Segment state *//* According to EN 300-743, 7.2.1 table 3 */#define DVBSUB_PCS_STATE_ACQUISITION 0x01#define DVBSUB_PCS_STATE_CHANGE 0x02/***************************************************************************** * Local prototypes *****************************************************************************/static void decode_segment( decoder_t *, bs_t * );static void decode_page_composition( decoder_t *, bs_t * );static void decode_region_composition( decoder_t *, bs_t * );static void decode_object( decoder_t *, bs_t * );static void decode_clut( decoder_t *, bs_t * );static void free_all( decoder_t * );static void default_clut_init( decoder_t * );static subpicture_t *render( decoder_t * );/***************************************************************************** * Open: probe the decoder and return score ***************************************************************************** * Tries to launch a decoder and return score so that the interface is able * to chose. *****************************************************************************/static int Open( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t *) p_this; decoder_sys_t *p_sys; vlc_value_t val; int i_posx, i_posy; if( p_dec->fmt_in.i_codec != VLC_FOURCC('d','v','b','s') ) { return VLC_EGENERIC; } p_dec->pf_decode_sub = Decode; p_sys = p_dec->p_sys = malloc( sizeof(decoder_sys_t) ); memset( p_sys, 0, sizeof(decoder_sys_t) ); p_sys->i_pts = (mtime_t) 0; p_sys->i_id = p_dec->fmt_in.subs.dvb.i_id & 0xFFFF; p_sys->i_ancillary_id = p_dec->fmt_in.subs.dvb.i_id >> 16; p_sys->p_regions = NULL; p_sys->p_cluts = NULL; p_sys->p_page = NULL; var_Create( p_this, DVBSUB_CFG_PREFIX "position", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_this, DVBSUB_CFG_PREFIX "position", &val ); p_sys->i_spu_position = val.i_int; var_Create( p_this, DVBSUB_CFG_PREFIX "x", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_this, DVBSUB_CFG_PREFIX "x", &val ); i_posx = val.i_int; var_Create( p_this, DVBSUB_CFG_PREFIX "y", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT ); var_Get( p_this, DVBSUB_CFG_PREFIX "y", &val ); i_posy = val.i_int; /* Check if subpicture position was overridden */ p_sys->b_absolute = VLC_TRUE; p_sys->i_spu_x = p_sys->i_spu_y = 0; if( i_posx >= 0 && i_posy >= 0 ) { p_sys->b_absolute = VLC_FALSE; p_sys->i_spu_x = i_posx; p_sys->i_spu_y = i_posy; } es_format_Init( &p_dec->fmt_out, SPU_ES, VLC_FOURCC( 'd','v','b','s' ) ); default_clut_init( p_dec ); return VLC_SUCCESS;}/***************************************************************************** * Close: *****************************************************************************/static void Close( vlc_object_t *p_this ){ decoder_t *p_dec = (decoder_t*) p_this; decoder_sys_t *p_sys = p_dec->p_sys; var_Destroy( p_this, DVBSUB_CFG_PREFIX "x" ); var_Destroy( p_this, DVBSUB_CFG_PREFIX "y" ); var_Destroy( p_this, DVBSUB_CFG_PREFIX "position" ); free_all( p_dec ); free( p_sys );}/***************************************************************************** * Decode: *****************************************************************************/static subpicture_t *Decode( decoder_t *p_dec, block_t **pp_block ){ decoder_sys_t *p_sys = p_dec->p_sys; block_t *p_block; subpicture_t *p_spu = NULL; if( pp_block == NULL || *pp_block == NULL ) return NULL; p_block = *pp_block; *pp_block = NULL; p_sys->i_pts = p_block->i_pts; if( p_sys->i_pts <= 0 ) {#ifdef DEBUG_DVBSUB /* Some DVB channels send stuffing segments in non-dated packets so * don't complain too loudly. */ msg_Warn( p_dec, "non dated subtitle" );#endif block_Release( p_block ); return NULL; } bs_init( &p_sys->bs, p_block->p_buffer, p_block->i_buffer ); if( bs_read( &p_sys->bs, 8 ) != 0x20 ) /* Data identifier */ { msg_Dbg( p_dec, "invalid data identifier" ); block_Release( p_block ); return NULL; } if( bs_read( &p_sys->bs, 8 ) ) /* Subtitle stream id */ { msg_Dbg( p_dec, "invalid subtitle stream id" ); block_Release( p_block ); return NULL; }#ifdef DEBUG_DVBSUB msg_Dbg( p_dec, "subtitle packet received: "I64Fd, p_sys->i_pts );#endif p_sys->b_page = VLC_FALSE; while( bs_show( &p_sys->bs, 8 ) == 0x0f ) /* Sync byte */ { decode_segment( p_dec, &p_sys->bs ); } if( bs_read( &p_sys->bs, 8 ) != 0xff ) /* End marker */ { msg_Warn( p_dec, "end marker not found (corrupted subtitle ?)" ); block_Release( p_block ); return NULL; } /* Check if the page is to be displayed */ if( p_sys->p_page && p_sys->b_page ) p_spu = render( p_dec ); block_Release( p_block ); return p_spu;}/* following functions are local *//***************************************************************************** * default_clut_init: default clut as defined in EN 300-743 section 10 *****************************************************************************/static void default_clut_init( decoder_t *p_dec ){ decoder_sys_t *p_sys = p_dec->p_sys; uint8_t i;#define RGB_TO_Y(r, g, b) ((int16_t) 77 * r + 150 * g + 29 * b) / 256;#define RGB_TO_U(r, g, b) ((int16_t) -44 * r - 87 * g + 131 * b) / 256;#define RGB_TO_V(r, g, b) ((int16_t) 131 * r - 110 * g - 21 * b) / 256; /* 4 entries CLUT */ for( i = 0; i < 4; i++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -