1 /*****************************************************************************
2 * stl.c: EBU STL decoder
3 *****************************************************************************
4 * Copyright (C) 2010 Laurent Aimar
7 * Authors: Laurent Aimar <fenrir _AT_ videolan _DOT_ org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 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 General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_codec.h>
35 #include <vlc_memory.h>
36 #include <vlc_charset.h>
38 /*****************************************************************************
40 *****************************************************************************/
41 static int Open (vlc_object_t
*);
42 static void Close(vlc_object_t
*);
45 set_description(N_("EBU STL subtitles decoder"))
46 set_category(CAT_INPUT
)
47 set_subcategory(SUBCAT_INPUT_SCODEC
)
48 set_capability("decoder", 10)
49 set_callbacks(Open
, Close
)
52 /*****************************************************************************
53 * Local definitions/prototypes
54 *****************************************************************************/
55 #define GSI_BLOCK_SIZE 1024
58 CCT_ISO_6937_2
= 0x3030, CCT_BEGIN
= CCT_ISO_6937_2
,
59 CCT_ISO_8859_5
= 0x3031,
60 CCT_ISO_8859_6
= 0x3032,
61 CCT_ISO_8859_7
= 0x3033,
62 CCT_ISO_8859_8
= 0x3034, CCT_END
= CCT_ISO_8859_8
66 cct_number_value_t value
;
70 struct decoder_sys_t
{
71 cct_number_value_t cct
;
74 static cct_number_t cct_nums
[] = { {CCT_ISO_6937_2
, "ISO_6937-2"},
75 {CCT_ISO_8859_5
, "ISO_8859-5"},
76 {CCT_ISO_8859_6
, "ISO_8859-6"},
77 {CCT_ISO_8859_7
, "ISO_8859-7"},
78 {CCT_ISO_8859_8
, "ISO_8859-8"} };
81 static char *ParseText(uint8_t *data
, int size
, const char *charset
)
83 char *text
= strdup("");
86 for (int i
= 0; i
< size
; i
++) {
87 uint8_t code
= data
[i
];
94 if ((code
>= 0x20 && code
<= 0x7e) ||
95 (code
>= 0xa0 && code
<= 0xff) )
96 snprintf(tmp
, sizeof(tmp
), "%c", code
);
98 else if (code
== 0x80)
99 snprintf(tmp
, sizeof(tmp
), "<i>");
100 else if (code
== 0x81)
101 snprintf(tmp
, sizeof(tmp
), "</i>");
102 else if (code
== 0x82)
103 snprintf(tmp
, sizeof(tmp
), "<u>");
104 else if (code
== 0x83)
105 snprintf(tmp
, sizeof(tmp
), "</u>");
106 else if (code
== 0x8a)
107 snprintf(tmp
, sizeof(tmp
), "\n");
115 size_t t_size
= strlen(t
);
116 text
= realloc_or_free(text
, t_size
+ text_size
+ 1);
119 memcpy(&text
[text_size
], t
, t_size
);
121 text
[text_size
] = '\0';
123 return FromCharset(charset
, text
, text_size
);
126 static subpicture_t
*Decode(decoder_t
*dec
, block_t
**block
)
128 if (block
== NULL
|| *block
== NULL
)
131 subpicture_t
*sub
= NULL
;
133 block_t
*b
= *block
; *block
= NULL
;
134 if (b
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
))
136 if (b
->i_buffer
< 128)
139 int payload_size
= (b
->i_buffer
/ 128) * 112;
140 uint8_t *payload
= malloc(payload_size
);
143 for (int i
= 0; i
< b
->i_buffer
/ 128; i
++)
144 memcpy(&payload
[112 * i
], &b
->p_buffer
[128 * i
+ 16], 112);
146 sub
= decoder_NewSubpicture(dec
, NULL
);
151 sub
->i_start
= b
->i_pts
;
152 sub
->i_stop
= b
->i_pts
+ b
->i_length
;
153 sub
->b_ephemer
= b
->i_length
== 0;
154 sub
->b_absolute
= false;
155 //sub->i_original_picture_width = 0;
156 //sub->i_original_picture_height = 0;
159 video_format_Init(&fmt
, VLC_CODEC_TEXT
);
160 sub
->p_region
= subpicture_region_New(&fmt
);
161 video_format_Clean(&fmt
);
164 sub
->p_region
->psz_text
= ParseText(payload
,
166 cct_nums
[dec
->p_sys
->cct
- CCT_BEGIN
].str
);
167 sub
->p_region
->psz_html
= NULL
;
177 static int ExtractCCT(const decoder_t
*dec
, cct_number_value_t
*cct_number
)
179 uint8_t *header
= dec
->fmt_in
.p_extra
;
181 msg_Err(dec
, "NULL EBU header (GSI block)\n");
185 if (GSI_BLOCK_SIZE
!= dec
->fmt_in
.i_extra
) {
186 msg_Err(dec
, "EBU header is not in expected size (%d)\n", dec
->fmt_in
.i_extra
);
190 int cct
= (header
[12] << 8) | header
[13];
191 if (CCT_BEGIN
> cct
|| CCT_END
< cct
) {
192 msg_Err(dec
, "EBU header contains illegal CCT (0x%x)\n", cct
);
201 static int Open(vlc_object_t
*object
)
203 decoder_t
*dec
= (decoder_t
*)object
;
205 if (dec
->fmt_in
.i_codec
!= VLC_CODEC_EBU_STL
)
208 cct_number_value_t cct
;
209 int rc
= ExtractCCT(dec
, &cct
);
210 if (VLC_SUCCESS
!= rc
)
213 msg_Dbg(dec
, "CCT=0x%x", cct
);
215 decoder_sys_t
*sys
= malloc(sizeof(*sys
));
222 dec
->pf_decode_sub
= Decode
;
223 dec
->fmt_out
.i_cat
= SPU_ES
;
224 dec
->fmt_out
.i_codec
= 0;
228 static void Close(vlc_object_t
*object
)
230 decoder_t
*dec
= (decoder_t
*)object
;
231 decoder_sys_t
*sys
= dec
->p_sys
;