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 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 *****************************************************************************/
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(const uint8_t *data
, size_t size
, const char *charset
)
83 char *text
= malloc(size
);
89 for (size_t i
= 0; i
< size
; i
++) {
90 uint8_t code
= data
[i
];
96 /* TODO: italics begin/end 0x80/0x81, underline being/end 0x82/0x83 */
98 text
[text_size
++] = code
;
100 text
[text_size
++] = '\n';
103 char *u8
= FromCharset(charset
, text
, text_size
);
108 static subpicture_t
*Decode(decoder_t
*dec
, block_t
**block
)
110 if (block
== NULL
|| *block
== NULL
)
113 subpicture_t
*sub
= NULL
;
115 block_t
*b
= *block
; *block
= NULL
;
116 if (b
->i_flags
& (BLOCK_FLAG_DISCONTINUITY
|BLOCK_FLAG_CORRUPTED
))
118 if (b
->i_buffer
< 128)
121 int payload_size
= (b
->i_buffer
/ 128) * 112;
122 uint8_t *payload
= malloc(payload_size
);
125 for (unsigned i
= 0; i
< b
->i_buffer
/ 128; i
++)
126 memcpy(&payload
[112 * i
], &b
->p_buffer
[128 * i
+ 16], 112);
128 sub
= decoder_NewSubpicture(dec
, NULL
);
133 sub
->i_start
= b
->i_pts
;
134 sub
->i_stop
= b
->i_pts
+ b
->i_length
;
135 sub
->b_ephemer
= b
->i_length
== 0;
136 sub
->b_absolute
= false;
137 //sub->i_original_picture_width = 0;
138 //sub->i_original_picture_height = 0;
141 video_format_Init(&fmt
, VLC_CODEC_TEXT
);
142 sub
->p_region
= subpicture_region_New(&fmt
);
143 video_format_Clean(&fmt
);
146 sub
->p_region
->p_text
= text_segment_New( ParseText(payload
,
148 cct_nums
[dec
->p_sys
->cct
- CCT_BEGIN
].str
) );
149 sub
->p_region
->i_align
= SUBPICTURE_ALIGN_BOTTOM
;
159 static int ExtractCCT(const decoder_t
*dec
, cct_number_value_t
*cct_number
)
161 uint8_t *header
= dec
->fmt_in
.p_extra
;
163 msg_Err(dec
, "NULL EBU header (GSI block)\n");
167 if (GSI_BLOCK_SIZE
!= dec
->fmt_in
.i_extra
) {
168 msg_Err(dec
, "EBU header is not in expected size (%d)\n", dec
->fmt_in
.i_extra
);
172 int cct
= (header
[12] << 8) | header
[13];
173 if (CCT_BEGIN
> cct
|| CCT_END
< cct
) {
174 msg_Err(dec
, "EBU header contains illegal CCT (0x%x)\n", cct
);
183 static int Open(vlc_object_t
*object
)
185 decoder_t
*dec
= (decoder_t
*)object
;
187 if (dec
->fmt_in
.i_codec
!= VLC_CODEC_EBU_STL
)
190 cct_number_value_t cct
;
191 int rc
= ExtractCCT(dec
, &cct
);
192 if (VLC_SUCCESS
!= rc
)
195 msg_Dbg(dec
, "CCT=0x%x", cct
);
197 decoder_sys_t
*sys
= malloc(sizeof(*sys
));
204 dec
->pf_decode_sub
= Decode
;
205 dec
->fmt_out
.i_cat
= SPU_ES
;
206 dec
->fmt_out
.i_codec
= 0;
210 static void Close(vlc_object_t
*object
)
212 decoder_t
*dec
= (decoder_t
*)object
;
213 decoder_sys_t
*sys
= dec
->p_sys
;