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
*);
43 static void Close(vlc_object_t
*);
47 uint32_t palette
[256];
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
)
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
;
74 /* continous_present_flag b1 */
75 /* forced_on_flag b1 */
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
)
87 i_data
= i_data_length
;
92 uint8_t code
= p_data
[0];
98 uint8_t type
= p_data
[1];
99 uint8_t length
= p_data
[2];
101 p_data
+= 3; i_data
-= 3;
108 case BD_TEXTST_DATA_STRING
:
110 char *psz
= strndup((char *)p_data
, length
);
111 *pp_last
= text_segment_New(psz
);
113 if(p_style
&& *pp_last
)
114 (*pp_last
)->style
= text_style_Duplicate(p_style
);
117 case BD_TEXTST_DATA_FONT_ID
:
120 case BD_TEXTST_DATA_FONT_STYLE
:
121 if(i_data
> 2 && (p_style
|| (p_style
= text_style_Create( STYLE_NO_DEFAULTS
))))
124 p_style
->i_style_flags
|= STYLE_BOLD
;
126 p_style
->i_style_flags
|= STYLE_ITALIC
;
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
135 case BD_TEXTST_DATA_FONT_SIZE
:
137 p_style->f_font_relsize = STYLE_DEFAULT_REL_FONT_SIZE *
138 (p_data[0] << 4) / STYLE_DEFAULT_FONT_SIZE;*/
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
;
148 case BD_TEXTST_DATA_NEWLINE
:
149 *pp_last
= text_segment_New("\n");
151 case BD_TEXTST_DATA_RESET_STYLE
:
154 text_style_Delete(p_style
);
163 pp_last
= &(*pp_last
)->p_next
;
165 p_data
+= length
; i_data
-= length
;
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
)
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
);
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;
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;
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
;
213 uint8_t i_region_count
= p_data
[0];
216 for(uint8_t i
=0; i
<i_region_count
&& i_data
> 4; i
++)
220 *pp_last
= SubpictureUpdaterSysRegionNew();
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,
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
;
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
)
275 decoder_sys_t
*p_sys
= malloc(sizeof(decoder_sys_t
));
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;