contrib: cargo: use cargo/vendored-openssl if needed
[vlc.git] / modules / codec / textst.c
bloba74d9a930bb8e2cfef4f65a60d932377fa3c6295
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 *);
43 static void Close(vlc_object_t *);
45 typedef struct
47 uint32_t palette[256];
48 } decoder_sys_t;
50 vlc_module_begin()
51 set_description(N_("HDMV TextST subtitles decoder"))
52 set_category(CAT_INPUT)
53 set_subcategory(SUBCAT_INPUT_SCODEC)
54 set_capability("spu decoder", 10)
55 set_callbacks(Open, Close)
56 vlc_module_end()
58 #define BD_TEXTST_DATA_STRING 1
59 #define BD_TEXTST_DATA_FONT_ID 2
60 #define BD_TEXTST_DATA_FONT_STYLE 3
61 #define BD_TEXTST_DATA_FONT_SIZE 4
62 #define BD_TEXTST_DATA_FONT_COLOR 5
63 #define BD_TEXTST_DATA_NEWLINE 0x0a
64 #define BD_TEXTST_DATA_RESET_STYLE 0x0b
66 static size_t textst_FillRegion(decoder_t *p_dec, const uint8_t *p_data, size_t i_data,
67 substext_updater_region_t *p_region)
69 decoder_sys_t *p_sys = p_dec->p_sys;
70 text_segment_t **pp_last = &p_region->p_segments;
71 text_style_t *p_style = NULL;
73 /* p_data[0] */
74 /* continous_present_flag b1 */
75 /* forced_on_flag b1 */
76 /* ? b6 */
78 assert( i_data >= 4 );
80 //uint8_t region_style_id_ref = p_data[1];
81 uint16_t i_data_length = GetWBE(&p_data[2]);
83 p_data += 4; i_data -= 4;
84 if( i_data < i_data_length )
85 return i_data;
86 else
87 i_data = i_data_length;
89 while (i_data > 3)
91 /* parse header */
92 uint8_t code = p_data[0];
93 if (code != 0x1b) {
94 p_data++; i_data--;
95 continue;
98 uint8_t type = p_data[1];
99 uint8_t length = p_data[2];
101 p_data += 3; i_data -= 3;
103 if(length > i_data)
104 break;
106 switch (type)
108 case BD_TEXTST_DATA_STRING:
110 char *psz = strndup((char *)p_data, length);
111 *pp_last = text_segment_New(psz);
112 free(psz);
113 if(p_style && *pp_last)
114 (*pp_last)->style = text_style_Duplicate(p_style);
116 break;
117 case BD_TEXTST_DATA_FONT_ID:
118 //p_data[0] font_id;
119 break;
120 case BD_TEXTST_DATA_FONT_STYLE:
121 if(i_data > 2 && (p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS ))))
123 if(p_data[0] & 0x01)
124 p_style->i_style_flags |= STYLE_BOLD;
125 if(p_data[0] & 0x02)
126 p_style->i_style_flags |= STYLE_ITALIC;
127 if(p_data[0] & 0x04)
128 p_style->i_style_flags |= STYLE_OUTLINE;
129 p_style->i_outline_color = p_sys->palette[p_data[1]] & 0x00FFFFFF;
130 p_style->i_outline_alpha = p_sys->palette[p_data[1]] >> 24;
131 p_style->i_features |= STYLE_HAS_FLAGS | STYLE_HAS_OUTLINE_ALPHA | STYLE_HAS_OUTLINE_COLOR;
132 //p_data[2] outline__thickness
134 break;
135 case BD_TEXTST_DATA_FONT_SIZE:
136 /*if(i_data > 0)
137 p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
138 (p_data[0] << 4) / STYLE_DEFAULT_FONT_SIZE;*/
139 break;
140 case BD_TEXTST_DATA_FONT_COLOR:
141 if(i_data > 1 && (p_style || (p_style = text_style_Create( STYLE_NO_DEFAULTS ))))
143 p_style->i_font_color = p_sys->palette[p_data[1]] & 0x00FFFFFF;
144 p_style->i_font_alpha = p_sys->palette[p_data[1]] >> 24;
145 p_style->i_features |= STYLE_HAS_FONT_ALPHA | STYLE_HAS_FONT_COLOR;
147 break;
148 case BD_TEXTST_DATA_NEWLINE:
149 *pp_last = text_segment_New("\n");
150 break;
151 case BD_TEXTST_DATA_RESET_STYLE:
152 if(p_style)
154 text_style_Delete(p_style);
155 p_style = NULL;
157 break;
158 default:
159 break;
162 if(*pp_last)
163 pp_last = &(*pp_last)->p_next;
165 p_data += length; i_data -= length;
168 if(p_style)
169 text_style_Delete(p_style);
171 return i_data_length;
174 static size_t textst_Decode_palette(decoder_t *p_dec, const uint8_t *p_data, size_t i_data)
176 if(i_data < 2)
177 return i_data;
179 decoder_sys_t *p_sys = p_dec->p_sys;
181 uint16_t i_size = GetWBE(&p_data[0]);
182 p_data += 2; i_data -= 2;
184 i_size = i_data = __MIN(i_data, i_size);
185 while (i_data > 4)
187 p_sys->palette[p_data[0]] = /* YCrCbT to ARGB */
188 ( (uint32_t)((float)p_data[1] +1.402f * (p_data[2]-128)) << 16 ) |
189 ( (uint32_t)((float)p_data[1] -0.34414 * (p_data[3]-128) -0.71414 * (p_data[2]-128)) << 8 ) |
190 ( (uint32_t)((float)p_data[1] +1.722 * (p_data[3]-128)) ) |
191 ( (0xFF - p_data[4]) << 24 );
192 p_data += 5; i_data -= 5;
195 return i_size;
198 static void textst_FillRegions(decoder_t *p_dec, const uint8_t *p_data, size_t i_data,
199 substext_updater_region_t *p_region)
201 substext_updater_region_t **pp_last = &p_region;
202 bool palette_update_flag = p_data[0] >> 7;
203 p_data++; i_data--;
205 if (palette_update_flag)
207 size_t i_read = textst_Decode_palette(p_dec, p_data, i_data);
208 p_data += i_read; i_data -= i_read;
211 if(i_data > 2)
213 uint8_t i_region_count = p_data[0];
214 p_data++; i_data--;
216 for(uint8_t i=0; i<i_region_count && i_data > 4; i++)
218 if(*pp_last == NULL)
220 *pp_last = SubpictureUpdaterSysRegionNew();
221 if(!*pp_last)
222 break;
224 size_t i_read = textst_FillRegion(p_dec, p_data, i_data, *pp_last);
225 (*pp_last)->align = SUBPICTURE_ALIGN_BOTTOM;
226 pp_last = &(*pp_last)->p_next;
227 p_data += i_read; i_data -= i_read;
232 static int Decode(decoder_t *p_dec, block_t *p_block)
234 subpicture_t *p_sub = NULL;
235 if (p_block == NULL) /* No Drain */
236 return VLCDEC_SUCCESS;
238 if (p_block->i_buffer > 18 &&
239 (p_block->i_flags & BLOCK_FLAG_CORRUPTED) == 0 &&
240 (p_sub = decoder_NewSubpictureText(p_dec)))
242 p_sub->i_start = FROM_SCALE(((int64_t)(p_block->p_buffer[3] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[4]));
243 p_sub->i_stop = FROM_SCALE(((int64_t)(p_block->p_buffer[8] & 0x01) << 32) | GetDWBE(&p_block->p_buffer[9]));
244 if (p_sub->i_start < p_block->i_dts)
246 p_sub->i_stop += p_block->i_dts - p_sub->i_start;
247 p_sub->i_start = p_block->i_dts;
250 subtext_updater_sys_t *p_spusys = p_sub->updater.p_sys;
251 textst_FillRegions(p_dec, &p_block->p_buffer[13], p_block->i_buffer - 13,
252 &p_spusys->region);
254 p_sub->b_absolute = false;
255 decoder_QueueSub(p_dec, p_sub);
258 block_Release(p_block);
259 return VLCDEC_SUCCESS;
262 static void Close(vlc_object_t *object)
264 decoder_t *p_dec = (decoder_t*)object;
265 free(p_dec->p_sys);
268 static int Open(vlc_object_t *object)
270 decoder_t *p_dec = (decoder_t*)object;
272 if (p_dec->fmt_in.i_codec != VLC_CODEC_BD_TEXT)
273 return VLC_EGENERIC;
275 decoder_sys_t *p_sys = malloc(sizeof(decoder_sys_t));
276 if(!p_sys)
277 return VLC_ENOMEM;
278 memset(p_sys->palette, 0xFF, 256 * sizeof(uint32_t));
280 p_dec->p_sys = p_sys;
281 p_dec->pf_decode = Decode;
282 p_dec->fmt_out.i_codec = 0;
284 return VLC_SUCCESS;