config: add more generic config_GetSysDir()
[vlc.git] / modules / codec / textst.c
blobc5c414f1cb12b60ede1329adee8ff43da5ea576e
1 /*****************************************************************************
2 * textst.c: HDMV TextST subtitles decoder
3 *****************************************************************************
4 * Copyright (C) 2017 Videolan Authors
6 * Adapted from libluray textst_decode.c
7 * Copyright (C) 2013 Petri Hintukainen <phintuka@users.sourceforge.net>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 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 Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
25 * Preamble
26 *****************************************************************************/
27 #ifdef HAVE_CONFIG_H
28 # include "config.h"
29 #endif
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
35 #include "substext.h"
37 /*****************************************************************************
38 * Module descriptor
39 *****************************************************************************/
40 static int Open (vlc_object_t *);
41 static void Close(vlc_object_t *);
43 struct decoder_sys_t
45 uint32_t palette[256];
48 vlc_module_begin()
49 set_description(N_("HDMV TextST subtitles decoder"))
50 set_category(CAT_INPUT)
51 set_subcategory(SUBCAT_INPUT_SCODEC)
52 set_capability("spu decoder", 10)
53 set_callbacks(Open, Close)
54 vlc_module_end()
56 #define BD_TEXTST_DATA_STRING 1
57 #define BD_TEXTST_DATA_FONT_ID 2
58 #define BD_TEXTST_DATA_FONT_STYLE 3
59 #define BD_TEXTST_DATA_FONT_SIZE 4
60 #define BD_TEXTST_DATA_FONT_COLOR 5
61 #define BD_TEXTST_DATA_NEWLINE 0x0a
62 #define BD_TEXTST_DATA_RESET_STYLE 0x0b
64 static size_t textst_FillRegion(decoder_t *p_dec, const uint8_t *p_data, size_t i_data,
65 subpicture_updater_sys_region_t *p_region)
67 VLC_UNUSED(p_dec);
68 text_segment_t **pp_last = &p_region->p_segments;
69 text_style_t *p_style = NULL;
71 /* p_data[0] */
72 /* continous_present_flag b1 */
73 /* forced_on_flag b1 */
74 /* ? b6 */
76 //uint8_t region_style_id_ref = p_data[1];
77 uint16_t i_data_length = GetWBE(&p_data[2]);
79 p_data += 4; i_data -= 4;
80 if( i_data < i_data_length )
81 return i_data;
82 else
83 i_data = i_data_length;
85 while (i_data > 3)
87 /* parse header */
88 uint8_t code = p_data[0];
89 if (code != 0x1b) {
90 p_data++; i_data--;
91 continue;
94 uint8_t type = p_data[1];
95 uint8_t length = p_data[2];
97 p_data += 3; i_data -= 3;
99 if(length > i_data)
100 break;
102 switch (type)
104 case BD_TEXTST_DATA_STRING:
106 char *psz = strndup((char *)p_data, length);
107 *pp_last = text_segment_New(psz);
108 free(psz);
109 if(p_style && *pp_last)
110 (*pp_last)->style = text_style_Duplicate(p_style);
112 break;
113 case BD_TEXTST_DATA_FONT_ID:
114 //p_data[0] font_id;
115 break;
116 case BD_TEXTST_DATA_FONT_STYLE:
117 if(i_data > 2 && (p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS ))))
119 if(p_data[0] & 0x01)
120 p_style->i_style_flags |= STYLE_BOLD;
121 if(p_data[0] & 0x02)
122 p_style->i_style_flags |= STYLE_ITALIC;
123 if(p_data[0] & 0x04)
124 p_style->i_style_flags |= STYLE_OUTLINE;
125 p_style->i_outline_color = p_dec->p_sys->palette[p_data[1]] & 0x00FFFFFF;
126 p_style->i_outline_alpha = p_dec->p_sys->palette[p_data[1]] >> 24;
127 p_style->i_features |= STYLE_HAS_FLAGS | STYLE_HAS_OUTLINE_ALPHA | STYLE_HAS_OUTLINE_COLOR;
128 //p_data[2] outline__thickness
130 break;
131 case BD_TEXTST_DATA_FONT_SIZE:
132 /*if(i_data > 0)
133 p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
134 (p_data[0] << 4) / STYLE_DEFAULT_FONT_SIZE;*/
135 break;
136 case BD_TEXTST_DATA_FONT_COLOR:
137 if(i_data > 1 && (p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS ))))
139 p_style->i_font_color = p_dec->p_sys->palette[p_data[1]] & 0x00FFFFFF;
140 p_style->i_font_alpha = p_dec->p_sys->palette[p_data[1]] >> 24;
141 p_style->i_features |= STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR;
143 break;
144 case BD_TEXTST_DATA_NEWLINE:
145 *pp_last = text_segment_New("\n");
146 break;
147 case BD_TEXTST_DATA_RESET_STYLE:
148 if(p_style)
150 text_style_Delete(p_style);
151 p_style = NULL;
153 break;
154 default:
155 break;
158 if(*pp_last)
159 pp_last = &(*pp_last)->p_next;
161 p_data += length; i_data -= length;
164 if(p_style)
165 text_style_Delete(p_style);
167 return i_data_length;
170 static size_t textst_Decode_palette(decoder_t *p_dec, const uint8_t *p_data, size_t i_data)
172 if(i_data < 2)
173 return i_data;
174 uint16_t i_size = GetWBE(&p_data[0]);
175 p_data += 2; i_data -= 2;
177 i_size = i_data = __MIN(i_data, i_size);
178 while (i_data > 4)
180 p_dec->p_sys->palette[p_data[0]] = /* YCrCbT to ARGB */
181 ( (uint32_t)((float)p_data[1] +1.402f * (p_data[2]-128)) << 16 ) |
182 ( (uint32_t)((float)p_data[1] -0.34414 * (p_data[3]-128) -0.71414 * (p_data[2]-128)) << 8 ) |
183 ( (uint32_t)((float)p_data[1] +1.722 * (p_data[3]-128)) ) |
184 ( (0xFF - p_data[4]) << 24 );
185 p_data += 5; i_data -= 5;
188 return i_size;
191 static void textst_FillRegions(decoder_t *p_dec, const uint8_t *p_data, size_t i_data,
192 subpicture_updater_sys_region_t *p_region)
194 subpicture_updater_sys_region_t **pp_last = &p_region;
195 bool palette_update_flag = p_data[0] >> 7;
196 p_data++; i_data--;
198 if (palette_update_flag)
200 size_t i_read = textst_Decode_palette(p_dec, p_data, i_data);
201 p_data += i_read; i_data -= i_read;
204 if(i_data > 2)
206 uint8_t i_region_count = p_data[0];
207 p_data++; i_data--;
209 for(uint8_t i=0; i<i_region_count && i_data > 0; i++)
211 if(*pp_last == NULL)
213 *pp_last = SubpictureUpdaterSysRegionNew();
214 if(!*pp_last)
215 break;
217 size_t i_read = textst_FillRegion(p_dec, p_data, i_data, *pp_last);
218 (*pp_last)->align = SUBPICTURE_ALIGN_BOTTOM;
219 pp_last = &(*pp_last)->p_next;
220 p_data += i_read; i_data -= i_read;
225 static int Decode(decoder_t *p_dec, block_t *p_block)
227 subpicture_t *p_sub = NULL;
228 if (p_block == NULL) /* No Drain */
229 return VLCDEC_SUCCESS;
231 if (p_block->i_buffer > 18 &&
232 (p_block->i_flags & BLOCK_FLAG_CORRUPTED) == 0 &&
233 (p_sub = decoder_NewSubpictureText(p_dec)))
235 p_sub->i_start = ((int64_t) (p_block->p_buffer[3] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[4]);
236 p_sub->i_stop = ((int64_t) (p_block->p_buffer[8] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[9]);
237 p_sub->i_start = VLC_TS_0 + p_sub->i_start * 100 / 9;
238 p_sub->i_stop = VLC_TS_0 + p_sub->i_stop * 100 / 9;
239 if (p_sub->i_start < p_block->i_dts)
241 p_sub->i_stop += p_block->i_dts - p_sub->i_start;
242 p_sub->i_start = p_block->i_dts;
245 textst_FillRegions(p_dec, &p_block->p_buffer[13], p_block->i_buffer - 13,
246 &p_sub->updater.p_sys->region);
248 p_sub->b_absolute = false;
249 decoder_QueueSub(p_dec, p_sub);
252 block_Release(p_block);
253 return VLCDEC_SUCCESS;
256 static void Close(vlc_object_t *object)
258 decoder_t *p_dec = (decoder_t*)object;
259 free(p_dec->p_sys);
262 static int Open(vlc_object_t *object)
264 decoder_t *p_dec = (decoder_t*)object;
266 if (p_dec->fmt_in.i_codec != VLC_CODEC_BD_TEXT)
267 return VLC_EGENERIC;
269 decoder_sys_t *p_sys = malloc(sizeof(decoder_sys_t));
270 if(!p_sys)
271 return VLC_ENOMEM;
272 memset(p_sys->palette, 0xFF, 256 * sizeof(uint32_t));
274 p_dec->p_sys = p_sys;
275 p_dec->pf_decode = Decode;
276 p_dec->fmt_out.i_codec = 0;
278 return VLC_SUCCESS;