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 /*****************************************************************************
26 *****************************************************************************/
31 #include <vlc_common.h>
32 #include <vlc_plugin.h>
33 #include <vlc_codec.h>
35 #include "../demux/mpeg/timestamps.h"
39 /*****************************************************************************
41 *****************************************************************************/
42 static int Open (vlc_object_t
*);
46 uint32_t palette
[256];
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)
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
;
73 /* continous_present_flag b1 */
74 /* forced_on_flag b1 */
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
)
86 i_data
= i_data_length
;
91 uint8_t code
= p_data
[0];
97 uint8_t type
= p_data
[1];
98 uint8_t length
= p_data
[2];
100 p_data
+= 3; i_data
-= 3;
107 case BD_TEXTST_DATA_STRING
:
109 char *psz
= strndup((char *)p_data
, length
);
110 *pp_last
= text_segment_New(psz
);
112 if(p_style
&& *pp_last
)
113 (*pp_last
)->style
= text_style_Duplicate(p_style
);
116 case BD_TEXTST_DATA_FONT_ID
:
119 case BD_TEXTST_DATA_FONT_STYLE
:
120 if(i_data
> 2 && (p_style
|| (p_style
= text_style_Create( STYLE_NO_DEFAULTS
))))
123 p_style
->i_style_flags
|= STYLE_BOLD
;
125 p_style
->i_style_flags
|= STYLE_ITALIC
;
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
134 case BD_TEXTST_DATA_FONT_SIZE
:
136 p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
137 (p_data[0] << 4) / STYLE_DEFAULT_FONT_SIZE;*/
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
;
147 case BD_TEXTST_DATA_NEWLINE
:
148 *pp_last
= text_segment_New("\n");
150 case BD_TEXTST_DATA_RESET_STYLE
:
153 text_style_Delete(p_style
);
162 pp_last
= &(*pp_last
)->p_next
;
164 p_data
+= length
; i_data
-= length
;
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
)
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
);
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;
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;
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
;
212 uint8_t i_region_count
= p_data
[0];
215 for(uint8_t i
=0; i
<i_region_count
&& i_data
> 4; i
++)
219 *pp_last
= SubpictureUpdaterSysRegionNew();
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,
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
)
268 decoder_sys_t
*p_sys
= vlc_obj_malloc(object
, sizeof(decoder_sys_t
));
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;