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>
37 /*****************************************************************************
39 *****************************************************************************/
40 static int Open (vlc_object_t
*);
41 static void Close(vlc_object_t
*);
45 uint32_t palette
[256];
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
)
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
)
68 text_segment_t
**pp_last
= &p_region
->p_segments
;
69 text_style_t
*p_style
= NULL
;
72 /* continous_present_flag b1 */
73 /* forced_on_flag b1 */
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
)
83 i_data
= i_data_length
;
88 uint8_t code
= p_data
[0];
94 uint8_t type
= p_data
[1];
95 uint8_t length
= p_data
[2];
97 p_data
+= 3; i_data
-= 3;
104 case BD_TEXTST_DATA_STRING
:
106 char *psz
= strndup((char *)p_data
, length
);
107 *pp_last
= text_segment_New(psz
);
109 if(p_style
&& *pp_last
)
110 (*pp_last
)->style
= text_style_Duplicate(p_style
);
113 case BD_TEXTST_DATA_FONT_ID
:
116 case BD_TEXTST_DATA_FONT_STYLE
:
117 if(i_data
> 2 && (p_style
|| (p_style
= text_style_Create( STYLE_NO_DEFAULTS
))))
120 p_style
->i_style_flags
|= STYLE_BOLD
;
122 p_style
->i_style_flags
|= STYLE_ITALIC
;
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
131 case BD_TEXTST_DATA_FONT_SIZE
:
133 p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
134 (p_data[0] << 4) / STYLE_DEFAULT_FONT_SIZE;*/
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
;
144 case BD_TEXTST_DATA_NEWLINE
:
145 *pp_last
= text_segment_New("\n");
147 case BD_TEXTST_DATA_RESET_STYLE
:
150 text_style_Delete(p_style
);
159 pp_last
= &(*pp_last
)->p_next
;
161 p_data
+= length
; i_data
-= length
;
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
)
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
);
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;
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;
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
;
206 uint8_t i_region_count
= p_data
[0];
209 for(uint8_t i
=0; i
<i_region_count
&& i_data
> 0; i
++)
213 *pp_last
= SubpictureUpdaterSysRegionNew();
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
;
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
)
269 decoder_sys_t
*p_sys
= malloc(sizeof(decoder_sys_t
));
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;