1 /*****************************************************************************
2 * stl.c: EBU STL demuxer
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_demux.h>
36 /*****************************************************************************
38 *****************************************************************************/
39 static int Open (vlc_object_t
*);
40 static void Close(vlc_object_t
*);
43 set_description(N_("EBU STL subtitles parser"))
44 set_category(CAT_INPUT
)
45 set_subcategory(SUBCAT_INPUT_DEMUX
)
46 set_capability("demux", 1)
47 set_callbacks(Open
, Close
)
48 add_shortcut("stl", "subtitle")
51 /*****************************************************************************
52 * Local definitions/prototypes
53 *****************************************************************************/
71 static int ParseInteger(uint8_t *data
, int size
)
74 assert(size
< sizeof(tmp
));
75 memcpy(tmp
, data
, size
);
78 return strtol(tmp
, NULL
, 10);
80 static int64_t ParseTimeCode(uint8_t *data
, double fps
)
82 return INT64_C(1000000) * (data
[0] * 3600 +
87 static int64_t ParseTextTimeCode(uint8_t *data
, double fps
)
90 for (int i
= 0; i
< 4; i
++)
91 tmp
[i
] = ParseInteger(&data
[2 * i
], 2);
92 return ParseTimeCode(tmp
, fps
);
95 static int Control(demux_t
*demux
, int query
, va_list args
)
97 demux_sys_t
*sys
= demux
->p_sys
;
99 case DEMUX_GET_LENGTH
: {
100 int64_t *l
= va_arg(args
, int64_t *);
101 *l
= sys
->count
> 0 ? sys
->index
[sys
->count
-1].stop
: 0;
104 case DEMUX_GET_TIME
: {
105 int64_t *t
= va_arg(args
, int64_t *);
106 *t
= sys
->current
< sys
->count
? sys
->index
[sys
->count
-1].start
: 0;
109 case DEMUX_SET_NEXT_DEMUX_TIME
: {
110 sys
->next_date
= va_arg(args
, int64_t);
113 case DEMUX_SET_TIME
: {
114 int64_t t
= va_arg(args
, int64_t);
116 while (sys
->current
< sys
->count
) {
117 if (sys
->index
[sys
->current
].stop
> t
) {
118 stream_Seek(demux
->s
, 1024 + 128LL * sys
->index
[sys
->current
].index
);
125 case DEMUX_SET_POSITION
:
126 case DEMUX_GET_POSITION
:
132 static int Demux(demux_t
*demux
)
134 demux_sys_t
*sys
= demux
->p_sys
;
136 while(sys
->current
< sys
->count
) {
137 stl_entry_t
*s
= &sys
->index
[sys
->current
];
138 if (s
->start
> sys
->next_date
)
141 block_t
*b
= stream_Block(demux
->s
, 128 * s
->count
);
144 b
->i_pts
= VLC_TS_0
+ s
->start
;
145 if (s
->stop
> s
->start
)
146 b
->i_length
= s
->stop
- s
->start
;
147 es_out_Send(demux
->out
, sys
->es
, b
);
151 return sys
->current
< sys
->count
? 1 : 0;
154 static int Open(vlc_object_t
*object
)
156 demux_t
*demux
= (demux_t
*)object
;
159 if (stream_Peek(demux
->s
, &peek
, 11) != 11)
162 bool is_stl_25
= !memcmp(&peek
[3], "STL25.01", 8);
163 bool is_stl_30
= !memcmp(&peek
[3], "STL30.01", 8);
164 if (!is_stl_25
&& !is_stl_30
)
166 const double fps
= is_stl_25
? 25 : 30;
168 uint8_t header
[1024];
169 if (stream_Read(demux
->s
, header
, sizeof(header
)) != sizeof(header
)) {
170 msg_Err(demux
, "Incomplete EBU STL header");
173 const int cct
= ParseInteger(&header
[12], 2);
174 const mtime_t program_start
= ParseTextTimeCode(&header
[256], fps
);
175 const int tti_count
= ParseInteger(&header
[238], 5);
176 msg_Dbg(demux
, "Detected EBU STL : CCT=%d TTI=%d start=%8.8s %"PRId64
, cct
, tti_count
, &header
[256], program_start
);
178 demux_sys_t
*sys
= xmalloc(sizeof(*sys
));
182 sys
->index
= xcalloc(tti_count
, sizeof(*sys
->index
));
185 bool comment
= false;
186 stl_entry_t
*s
= &sys
->index
[0];
189 for (int i
= 0; i
< tti_count
; i
++) {
191 if (stream_Read(demux
->s
, tti
, 16) != 16 ||
192 stream_Read(demux
->s
, NULL
, 112) != 112) {
193 msg_Warn(demux
, "Incomplete EBU STL file");
196 const int ebn
= tti
[3];
197 if (ebn
>= 0xf0 && ebn
<= 0xfd)
203 comment
= tti
[15] != 0;
204 s
->start
= ParseTimeCode(&tti
[5], fps
) - program_start
;
205 s
->stop
= ParseTimeCode(&tti
[9], fps
) - program_start
;
209 if (ebn
== 0xff && !comment
)
210 s
= &sys
->index
[++sys
->count
];
211 if (ebn
== 0xff && sys
->count
< tti_count
)
215 stream_Seek(demux
->s
, 1024 + 128LL * sys
->index
[0].index
);
218 es_format_Init(&fmt
, SPU_ES
, VLC_CODEC_EBU_STL
);
219 fmt
.i_extra
= sizeof(header
);
220 fmt
.p_extra
= header
;
222 sys
->es
= es_out_Add(demux
->out
, &fmt
);
226 es_format_Clean(&fmt
);
229 demux
->pf_demux
= Demux
;
230 demux
->pf_control
= Control
;
234 static void Close(vlc_object_t
*object
)
236 demux_t
*demux
= (demux_t
*)object
;
237 demux_sys_t
*sys
= demux
->p_sys
;