qml/KeyNavigableTableView: Add 'delegate' and 'contentY' aliases
[vlc.git] / modules / codec / textst.c
blob26852f924851831b9bc1173c4a4559e7e65b530e
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 "../demux/mpeg/timestamps.h"
37 #include "substext.h"
39 /*****************************************************************************
40 * Module descriptor
41 *****************************************************************************/
42 static int Open (vlc_object_t *);
44 typedef struct
46 uint32_t palette[256];
47 } decoder_sys_t;
49 vlc_module_begin()
50 set_description(N_("HDMV TextST subtitles decoder"))
51 set_category(CAT_INPUT)
52 set_subcategory(SUBCAT_INPUT_SCODEC)
53 set_capability("spu decoder", 10)
54 set_callback(Open)
55 vlc_module_end()
57 #define BD_TEXTST_DATA_STRING 1
58 #define BD_TEXTST_DATA_FONT_ID 2
59 #define BD_TEXTST_DATA_FONT_STYLE 3
60 #define BD_TEXTST_DATA_FONT_SIZE 4
61 #define BD_TEXTST_DATA_FONT_COLOR 5
62 #define BD_TEXTST_DATA_NEWLINE 0x0a
63 #define BD_TEXTST_DATA_RESET_STYLE 0x0b
65 static size_t textst_FillRegion(decoder_t *p_dec, const uint8_t *p_data, size_t i_data,
66 substext_updater_region_t *p_region)
68 decoder_sys_t *p_sys = p_dec->p_sys;
69 text_segment_t **pp_last = &p_region->p_segments;
70 text_style_t *p_style = NULL;
72 /* p_data[0] */
73 /* continous_present_flag b1 */
74 /* forced_on_flag b1 */
75 /* ? b6 */
77 assert( i_data >= 4 );
79 //uint8_t region_style_id_ref = p_data[1];
80 uint16_t i_data_length = GetWBE(&p_data[2]);
82 p_data += 4; i_data -= 4;
83 if( i_data < i_data_length )
84 return i_data;
85 else
86 i_data = i_data_length;
88 while (i_data > 3)
90 /* parse header */
91 uint8_t code = p_data[0];
92 if (code != 0x1b) {
93 p_data++; i_data--;
94 continue;
97 uint8_t type = p_data[1];
98 uint8_t length = p_data[2];
100 p_data += 3; i_data -= 3;
102 if(length > i_data)
103 break;
105 switch (type)
107 case BD_TEXTST_DATA_STRING:
109 char *psz = strndup((char *)p_data, length);
110 *pp_last = text_segment_New(psz);
111 free(psz);
112 if(p_style && *pp_last)
113 (*pp_last)->style = text_style_Duplicate(p_style);
115 break;
116 case BD_TEXTST_DATA_FONT_ID:
117 //p_data[0] font_id;
118 break;
119 case BD_TEXTST_DATA_FONT_STYLE:
120 if(i_data > 2 && (p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS ))))
122 if(p_data[0] & 0x01)
123 p_style->i_style_flags |= STYLE_BOLD;
124 if(p_data[0] & 0x02)
125 p_style->i_style_flags |= STYLE_ITALIC;
126 if(p_data[0] & 0x04)
127 p_style->i_style_flags |= STYLE_OUTLINE;
128 p_style->i_outline_color = p_sys->palette[p_data[1]] & 0x00FFFFFF;
129 p_style->i_outline_alpha = p_sys->palette[p_data[1]] >> 24;
130 p_style->i_features |= STYLE_HAS_FLAGS | STYLE_HAS_OUTLINE_ALPHA | STYLE_HAS_OUTLINE_COLOR;
131 //p_data[2] outline__thickness
133 break;
134 case BD_TEXTST_DATA_FONT_SIZE:
135 /*if(i_data > 0)
136 p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
137 (p_data[0] << 4) / STYLE_DEFAULT_FONT_SIZE;*/
138 break;
139 case BD_TEXTST_DATA_FONT_COLOR:
140 if(i_data > 1 && (p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS ))))
142 p_style->i_font_color = p_sys->palette[p_data[1]] & 0x00FFFFFF;
143 p_style->i_font_alpha = p_sys->palette[p_data[1]] >> 24;
144 p_style->i_features |= STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR;
146 break;
147 case BD_TEXTST_DATA_NEWLINE:
148 *pp_last = text_segment_New("\n");
149 break;
150 case BD_TEXTST_DATA_RESET_STYLE:
151 if(p_style)
153 text_style_Delete(p_style);
154 p_style = NULL;
156 break;
157 default:
158 break;
161 if(*pp_last)
162 pp_last = &(*pp_last)->p_next;
164 p_data += length; i_data -= length;
167 if(p_style)
168 text_style_Delete(p_style);
170 return i_data_length;
173 static size_t textst_Decode_palette(decoder_t *p_dec, const uint8_t *p_data, size_t i_data)
175 if(i_data < 2)
176 return i_data;
178 decoder_sys_t *p_sys = p_dec->p_sys;
180 uint16_t i_size = GetWBE(&p_data[0]);
181 p_data += 2; i_data -= 2;
183 i_size = i_data = __MIN(i_data, i_size);
184 while (i_data > 4)
186 p_sys->palette[p_data[0]] = /* YCrCbT to ARGB */
187 ( (uint32_t)((float)p_data[1] +1.402f * (p_data[2]-128)) << 16 ) |
188 ( (uint32_t)((float)p_data[1] -0.34414 * (p_data[3]-128) -0.71414 * (p_data[2]-128)) << 8 ) |
189 ( (uint32_t)((float)p_data[1] +1.722 * (p_data[3]-128)) ) |
190 ( (0xFF - p_data[4]) << 24 );
191 p_data += 5; i_data -= 5;
194 return i_size;
197 static void textst_FillRegions(decoder_t *p_dec, const uint8_t *p_data, size_t i_data,
198 substext_updater_region_t *p_region)
200 substext_updater_region_t **pp_last = &p_region;
201 bool palette_update_flag = p_data[0] >> 7;
202 p_data++; i_data--;
204 if (palette_update_flag)
206 size_t i_read = textst_Decode_palette(p_dec, p_data, i_data);
207 p_data += i_read; i_data -= i_read;
210 if(i_data > 2)
212 uint8_t i_region_count = p_data[0];
213 p_data++; i_data--;
215 for(uint8_t i=0; i<i_region_count && i_data > 4; i++)
217 if(*pp_last == NULL)
219 *pp_last = SubpictureUpdaterSysRegionNew();
220 if(!*pp_last)
221 break;
223 size_t i_read = textst_FillRegion(p_dec, p_data, i_data, *pp_last);
224 (*pp_last)->align = SUBPICTURE_ALIGN_BOTTOM;
225 pp_last = &(*pp_last)->p_next;
226 p_data += i_read; i_data -= i_read;
231 static int Decode(decoder_t *p_dec, block_t *p_block)
233 subpicture_t *p_sub = NULL;
234 if (p_block == NULL) /* No Drain */
235 return VLCDEC_SUCCESS;
237 if (p_block->i_buffer > 18 &&
238 (p_block->i_flags & BLOCK_FLAG_CORRUPTED) == 0 &&
239 (p_sub = decoder_NewSubpictureText(p_dec)))
241 p_sub->i_start = FROM_SCALE(((int64_t)(p_block->p_buffer[3] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[4]));
242 p_sub->i_stop = FROM_SCALE(((int64_t)(p_block->p_buffer[8] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[9]));
243 if (p_sub->i_start < p_block->i_dts)
245 p_sub->i_stop += p_block->i_dts - p_sub->i_start;
246 p_sub->i_start = p_block->i_dts;
249 subtext_updater_sys_t *p_spusys = p_sub->updater.p_sys;
250 textst_FillRegions(p_dec, &p_block->p_buffer[13], p_block->i_buffer - 13,
251 &p_spusys->region);
253 p_sub->b_absolute = false;
254 decoder_QueueSub(p_dec, p_sub);
257 block_Release(p_block);
258 return VLCDEC_SUCCESS;
261 static int Open(vlc_object_t *object)
263 decoder_t *p_dec = (decoder_t*)object;
265 if (p_dec->fmt_in.i_codec != VLC_CODEC_BD_TEXT)
266 return VLC_EGENERIC;
268 decoder_sys_t *p_sys = vlc_obj_malloc(object, sizeof(decoder_sys_t));
269 if(!p_sys)
270 return VLC_ENOMEM;
271 memset(p_sys->palette, 0xFF, 256 * sizeof(uint32_t));
273 p_dec->p_sys = p_sys;
274 p_dec->pf_decode = Decode;
275 p_dec->fmt_out.i_codec = 0;
277 return VLC_SUCCESS;