Qt: fix build
[vlc.git] / modules / codec / arib / aribsub.c
blob9bcc92f37b770a97d6f2ef1dfdfc73ea732e2076
1 /*****************************************************************************
2 * aribsub.c : ARIB subtitles decoder
3 *****************************************************************************
4 * Copyright (C) 2012 Naohiro KORIYAMA
6 * Authors: Naohiro KORIYAMA <nkoriyama@gmail.com>
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU Lesser General Public License as published by
10 * the Free Software Foundation; either version 2.1 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program; if not, write to the Free Software Foundation,
20 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
21 *****************************************************************************/
23 #ifdef HAVE_CONFIG_H
24 # include "config.h"
25 #endif
27 #include <vlc_common.h>
28 #include <vlc_plugin.h>
29 #include <vlc_codec.h>
31 #ifdef HAVE_ARIBB24
32 #include "substext.h"
33 #include <aribb24/parser.h>
34 #include <aribb24/decoder.h>
35 #endif
37 //#define DEBUG_ARIBSUB 1
39 /*****************************************************************************
40 * Module descriptor.
41 *****************************************************************************/
42 static int Open( vlc_object_t * );
43 static void Close( vlc_object_t * );
44 static int Decode( decoder_t *, block_t * );
46 #define IGNORE_RUBY_TEXT N_("Ignore ruby(furigana)")
47 #define IGNORE_RUBY_LONGTEXT N_("Ignore ruby(furigana) in the subtitle.")
48 #define USE_CORETEXT_TEXT N_("Use Core Text renderer")
49 #define USE_CORETEXT_LONGTEXT N_("Use Core Text renderer in the subtitle.")
51 vlc_module_begin ()
52 # define ARIBSUB_CFG_PREFIX "aribsub-"
53 set_description( N_("ARIB subtitles decoder") )
54 set_shortname( N_("ARIB subtitles") )
55 set_capability( "spu decoder", 50 )
56 set_category( CAT_INPUT )
57 set_subcategory( SUBCAT_INPUT_SCODEC )
58 set_callbacks( Open, Close )
60 add_bool( ARIBSUB_CFG_PREFIX "ignore-ruby", false, IGNORE_RUBY_TEXT, IGNORE_RUBY_LONGTEXT, true )
61 add_bool( ARIBSUB_CFG_PREFIX "use-coretext", false, USE_CORETEXT_TEXT, USE_CORETEXT_LONGTEXT, true )
62 vlc_module_end ()
65 /****************************************************************************
66 * Local structures
67 ****************************************************************************/
69 struct decoder_sys_t
71 bool b_a_profile;
72 bool b_ignore_ruby;
73 bool b_use_coretext;
74 bool b_ignore_position_adjustment;
76 arib_instance_t *p_arib_instance;
77 char *psz_arib_base_dir;
80 /*****************************************************************************
81 * Local prototypes
82 *****************************************************************************/
83 static subpicture_t *render( decoder_t *, arib_parser_t *,
84 arib_decoder_t *, block_t * );
86 static char* get_arib_base_dir( void );
87 static void messages_callback_handler( void *, const char *psz_message );
89 /*****************************************************************************
90 * Open: probe the decoder and return score
91 *****************************************************************************
92 * Tries to launch a decoder and return score so that the interface is able
93 * to choose.
94 *****************************************************************************/
95 static int Open( vlc_object_t *p_this )
97 decoder_t *p_dec = (decoder_t *) p_this;
98 decoder_sys_t *p_sys;
100 if( p_dec->fmt_in.i_codec != VLC_CODEC_ARIB_A &&
101 p_dec->fmt_in.i_codec != VLC_CODEC_ARIB_C )
103 return VLC_EGENERIC;
106 p_sys = (decoder_sys_t*) calloc( 1, sizeof(decoder_sys_t) );
107 if( p_sys == NULL )
109 return VLC_ENOMEM;
112 p_sys->p_arib_instance = arib_instance_new( (void *) p_this );
113 if ( !p_sys->p_arib_instance )
115 free( p_sys );
116 return VLC_EGENERIC;
119 p_dec->p_sys = p_sys;
120 p_dec->pf_decode = Decode;
121 p_dec->fmt_out.i_codec = 0;
123 p_sys->b_a_profile = ( p_dec->fmt_in.i_codec == VLC_CODEC_ARIB_A );
125 p_sys->b_ignore_ruby =
126 var_InheritBool( p_this, ARIBSUB_CFG_PREFIX "ignore-ruby" );
127 p_sys->b_use_coretext =
128 var_InheritBool( p_this, ARIBSUB_CFG_PREFIX "use-coretext" );
129 p_sys->b_ignore_position_adjustment = p_sys->b_use_coretext;
130 p_sys->p_arib_instance->b_use_private_conv = p_sys->b_use_coretext;
131 p_sys->p_arib_instance->b_replace_ellipsis = p_sys->b_use_coretext;
133 char *psz_basedir = get_arib_base_dir();
134 arib_set_base_path( p_sys->p_arib_instance, psz_basedir );
135 free( psz_basedir );
137 arib_register_messages_callback( p_sys->p_arib_instance,
138 messages_callback_handler );
140 return VLC_SUCCESS;
143 /*****************************************************************************
144 * Close:
145 *****************************************************************************/
146 static void Close( vlc_object_t *p_this )
148 decoder_t *p_dec = (decoder_t*) p_this;
149 decoder_sys_t *p_sys = p_dec->p_sys;
151 arib_instance_destroy( p_sys->p_arib_instance );
152 free( p_sys->psz_arib_base_dir );
154 var_Destroy( p_this, ARIBSUB_CFG_PREFIX "ignore-ruby" );
155 var_Destroy( p_this, ARIBSUB_CFG_PREFIX "use-coretext" );
157 free( p_sys );
160 /*****************************************************************************
161 * Decode:
162 *****************************************************************************/
163 static int Decode( decoder_t *p_dec, block_t *p_block )
165 decoder_sys_t *p_sys = p_dec->p_sys;
167 if( p_block == NULL ) /* No Drain */
168 return VLCDEC_SUCCESS;
170 if( p_block->i_flags & BLOCK_FLAG_CORRUPTED )
172 block_Release( p_block );
173 return VLCDEC_SUCCESS;
176 arib_parser_t *p_parser = arib_get_parser( p_sys->p_arib_instance );
177 arib_decoder_t *p_decoder = arib_get_decoder( p_sys->p_arib_instance );
178 if ( p_parser && p_decoder )
180 arib_parse_pes( p_parser, p_block->p_buffer, p_block->i_buffer );
181 subpicture_t *p_spu = render( p_dec, p_parser, p_decoder, p_block );
182 if( p_spu != NULL )
183 decoder_QueueSub( p_dec, p_spu );
186 block_Release( p_block );
187 return VLCDEC_SUCCESS;
190 /* following functions are local */
192 static void messages_callback_handler( void *p_opaque, const char *psz_message )
194 decoder_t *p_dec = ( decoder_t * ) p_opaque;
195 msg_Dbg( p_dec, "%s", psz_message );
198 static char* get_arib_base_dir()
200 char *psz_data_dir = config_GetUserDir( VLC_DATA_DIR );
201 if( psz_data_dir == NULL )
203 return NULL;
206 char *psz_arib_base_dir;
207 if( asprintf( &psz_arib_base_dir, "%s"DIR_SEP"arib", psz_data_dir ) < 0 )
209 psz_arib_base_dir = NULL;
211 free( psz_data_dir );
213 return psz_arib_base_dir;
216 static subpicture_t *render( decoder_t *p_dec, arib_parser_t *p_parser,
217 arib_decoder_t *p_arib_decoder, block_t *p_block )
219 decoder_sys_t *p_sys = p_dec->p_sys;
220 subpicture_t *p_spu = NULL;
221 char *psz_subtitle = NULL;
223 size_t i_data_size;
224 const unsigned char *psz_data = arib_parser_get_data( p_parser, &i_data_size );
225 if( !psz_data || !i_data_size )
226 return NULL;
228 size_t i_subtitle_size = i_data_size * 4;
229 psz_subtitle = (char*) calloc( i_subtitle_size + 1, sizeof(*psz_subtitle) );
230 if( psz_subtitle == NULL )
232 return NULL;
234 if( p_sys->b_a_profile )
235 arib_initialize_decoder_a_profile( p_arib_decoder );
236 else
237 arib_initialize_decoder_c_profile( p_arib_decoder );
239 i_subtitle_size = arib_decode_buffer( p_arib_decoder,
240 psz_data,
241 i_data_size,
242 psz_subtitle,
243 i_subtitle_size );
244 #ifdef DEBUG_ARIBSUB
245 msg_Dbg( p_dec, "psz_subtitle [%s]", psz_subtitle );
246 unsigned const char* start = psz_data;
247 unsigned const char* end = psz_data + i_data_size;
248 char* psz_subtitle_data_hex = (char*) calloc(
249 i_data_size * 3 + 1, sizeof(char) );
250 char* psz_subtitle_data_hex_idx = psz_subtitle_data_hex;
251 while( start < end )
253 sprintf(psz_subtitle_data_hex_idx, "%02x ", *start++);
254 psz_subtitle_data_hex_idx += 3;
256 msg_Dbg( p_dec, "psz_subtitle_data [%s]", psz_subtitle_data_hex);
257 free( psz_subtitle_data_hex );
258 #endif
260 p_spu = decoder_NewSubpictureText( p_dec );
261 if( p_spu == NULL )
263 goto decoder_NewSubpictureText_failed;
266 p_spu->i_start = p_block->i_pts;
267 p_spu->i_stop = p_block->i_pts + arib_decoder_get_time( p_arib_decoder );
268 p_spu->b_ephemer = (p_spu->i_start == p_spu->i_stop);
269 p_spu->b_absolute = true;
271 subpicture_updater_sys_t *p_spu_sys = p_spu->updater.p_sys;
273 arib_text_region_t *p_region = p_spu_sys->p_region =
274 (arib_text_region_t*) calloc( 1, sizeof(arib_text_region_t) );
275 if( p_region == NULL )
277 goto malloc_failed;
279 for( const arib_buf_region_t *p_buf_region = arib_decoder_get_regions( p_arib_decoder );
280 p_buf_region; p_buf_region = p_buf_region->p_next )
282 if( p_sys->b_ignore_ruby && p_buf_region->i_fontheight == 18 )
284 continue;
287 int i_size = p_buf_region->p_end - p_buf_region->p_start;
288 char *psz_text = (char*) calloc( i_size + 1, sizeof(char) );
289 if( psz_text == NULL )
291 goto malloc_failed;
293 strncpy(psz_text, p_buf_region->p_start, i_size);
294 psz_text[i_size] = '\0';
295 #ifdef DEBUG_ARIBSUB
296 msg_Dbg( p_dec, "psz_text [%s]", psz_text );
297 #endif
299 p_region->psz_text = strdup( psz_text );
300 free( psz_text );
301 p_region->psz_fontname = NULL;
302 p_region->i_font_color = p_buf_region->i_foreground_color;
303 p_region->i_planewidth = p_buf_region->i_planewidth;
304 p_region->i_planeheight = p_buf_region->i_planeheight;
305 p_region->i_fontwidth = p_buf_region->i_fontwidth;
306 p_region->i_fontheight = p_buf_region->i_fontheight;
307 p_region->i_verint = p_buf_region->i_verint;
308 p_region->i_horint = p_buf_region->i_horint;
309 p_region->i_charleft = p_buf_region->i_charleft;
310 p_region->i_charbottom = p_buf_region->i_charbottom;
311 p_region->i_charleft_adj = 0;
312 p_region->i_charbottom_adj = 0;
313 if( !p_sys->b_ignore_position_adjustment )
315 p_region->i_charleft_adj = p_buf_region->i_horadj;
316 p_region->i_charbottom_adj = p_buf_region->i_veradj;
318 p_region->p_next = NULL;
319 if( p_buf_region->p_next != NULL )
321 p_region = p_region->p_next =
322 (arib_text_region_t*) calloc( 1, sizeof(arib_text_region_t) );
323 if( p_region == NULL )
325 goto malloc_failed;
330 decoder_NewSubpictureText_failed:
331 malloc_failed:
332 arib_finalize_decoder( p_arib_decoder );
333 free( psz_subtitle );
335 return p_spu;