1 /*****************************************************************************
2 * csri.c : Load CSRI subtitle renderer
3 *****************************************************************************
4 * Copyright (C) 2007 the VideoLAN team
7 * Authors: David Lamparter <equinox@videolan.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 *****************************************************************************/
35 #include <vlc_common.h>
36 #include <vlc_plugin.h>
38 #include <vlc_codec.h>
40 #include <vlc_input.h>
42 #include <csri/csri.h>
43 #include <csri/stream.h>
45 /*****************************************************************************
47 *****************************************************************************/
48 static int Create ( vlc_object_t
* );
49 static void Destroy( vlc_object_t
* );
52 set_shortname( N_("Subtitles (advanced)"))
53 set_description( N_("Wrapper for subtitle renderers using CSRI/asa") )
54 set_capability( "decoder", 60 )
55 set_category( CAT_INPUT
)
56 set_subcategory( SUBCAT_INPUT_SCODEC
)
57 set_callbacks( Create
, Destroy
)
60 /*****************************************************************************
62 *****************************************************************************/
63 static subpicture_t
*DecodeBlock( decoder_t
*, block_t
** );
64 static void DestroySubpicture( subpicture_t
* );
65 static void PreRender( spu_t
*, subpicture_t
*, const video_format_t
* );
66 static void UpdateRegions( spu_t
*, subpicture_t
*,
67 const video_format_t
*, mtime_t
);
69 /*****************************************************************************
70 * decoder_sys_t: decoder data
71 *****************************************************************************/
74 subpicture_t
*p_spu_final
;
75 video_format_t fmt_cached
;
76 csri_inst
*p_instance
;
78 struct csri_stream_ext
*p_stream_ext
;
80 void (*pf_push_packet
)(csri_inst
*inst
, const void *packet
,
81 size_t packetlen
, double pts_start
,
85 struct subpicture_sys_t
93 /*****************************************************************************
94 * Create: Open CSRI renderer
95 *****************************************************************************
97 *****************************************************************************/
98 static int Create( vlc_object_t
*p_this
)
100 decoder_t
*p_dec
= (decoder_t
*)p_this
;
101 decoder_sys_t
*p_sys
;
103 struct csri_stream_ext
*p_stream_ext
;
105 if( p_dec
->fmt_in
.i_codec
!= VLC_FOURCC('s','s','a',' ') )
108 p_render
= csri_renderer_default();
111 msg_Err( p_dec
, "can't load csri renderer" );
114 p_stream_ext
= csri_query_ext(p_render
, CSRI_EXT_STREAM_ASS
);
117 msg_Err( p_dec
, "csri renderer does not support ASS streaming" );
121 p_dec
->pf_decode_sub
= DecodeBlock
;
123 p_dec
->p_sys
= p_sys
= calloc( 1, sizeof( decoder_sys_t
) );
127 p_sys
->p_stream_ext
= p_stream_ext
;
128 p_sys
->pf_push_packet
= p_stream_ext
->push_packet
;
129 p_sys
->p_instance
= p_stream_ext
->init_stream( p_render
,
130 p_dec
->fmt_in
.p_extra
,
131 p_dec
->fmt_in
.p_extra
? strnlen( p_dec
->fmt_in
.p_extra
, p_dec
->fmt_in
.i_extra
) : 0,
136 /*****************************************************************************
138 *****************************************************************************
140 *****************************************************************************/
141 static void Destroy( vlc_object_t
*p_this
)
143 decoder_t
*p_dec
= (decoder_t
*)p_this
;
144 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
146 if( p_sys
->p_stream_ext
->discard
)
147 p_sys
->p_stream_ext
->discard( p_sys
->p_instance
, true );
151 /****************************************************************************
152 * DecodeBlock: the whole thing
153 ****************************************************************************
154 * This function must be fed with complete subtitles units.
155 ****************************************************************************/
156 static subpicture_t
*DecodeBlock( decoder_t
*p_dec
, block_t
**pp_block
)
158 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
160 subpicture_t
*p_spu
= NULL
;
163 //msg_Dbg( p_dec, "DecodeBlock %p", (void *)pp_block);
164 if( !pp_block
|| *pp_block
== NULL
)
170 if( p_block
->i_buffer
== 0 || p_block
->p_buffer
[0] == '\0' )
172 block_Release( p_block
);
176 p_spu
= decoder_NewSubpicture( p_dec
);
179 msg_Warn( p_dec
, "can't get spu buffer" );
180 block_Release( p_block
);
184 p_spu
->p_sys
= malloc( sizeof( subpicture_sys_t
));
187 decoder_DeleteSubpicture( p_dec
, p_spu
);
188 block_Release( p_block
);
191 p_spu
->p_sys
->p_dec
= p_dec
;
193 p_spu
->p_sys
->i_subs_len
= p_block
->i_buffer
;
194 p_spu
->p_sys
->p_subs_data
= malloc( p_block
->i_buffer
);
195 if( !p_spu
->p_sys
->p_subs_data
)
197 free( p_spu
->p_sys
);
198 decoder_DeleteSubpicture( p_dec
, p_spu
);
199 block_Release( p_block
);
202 memcpy( p_spu
->p_sys
->p_subs_data
, p_block
->p_buffer
,
204 p_spu
->p_sys
->i_pts
= p_block
->i_pts
;
206 p_spu
->i_start
= p_block
->i_pts
;
207 p_spu
->i_stop
= p_block
->i_pts
+ p_block
->i_length
;
208 p_spu
->b_ephemer
= false;
209 p_spu
->b_absolute
= false;
211 //msg_Dbg( p_dec, "BS %lf..%lf", p_spu->i_start * 0.000001, p_spu->i_stop * 0.000001);
212 p_sys
->pf_push_packet( p_sys
->p_instance
,
213 p_spu
->p_sys
->p_subs_data
, p_spu
->p_sys
->i_subs_len
,
214 p_spu
->i_start
* 0.000001,
215 p_spu
->i_stop
* 0.000001);
217 p_spu
->pf_pre_render
= PreRender
;
218 p_spu
->pf_update_regions
= UpdateRegions
;
219 p_spu
->pf_destroy
= DestroySubpicture
;
221 block_Release( p_block
);
226 static void DestroySubpicture( subpicture_t
*p_subpic
)
228 //msg_Dbg( p_subpic->p_sys->p_dec, "drop spu %p", (void *)p_subpic );
229 free( p_subpic
->p_sys
->p_subs_data
);
230 free( p_subpic
->p_sys
);
233 static void PreRender( spu_t
*p_spu
, subpicture_t
*p_subpic
,
234 const video_format_t
*p_fmt
)
236 decoder_t
*p_dec
= p_subpic
->p_sys
->p_dec
;
237 p_dec
->p_sys
->p_spu_final
= p_subpic
;
242 static void UpdateRegions( spu_t
*p_spu
, subpicture_t
*p_subpic
,
243 const video_format_t
*p_fmt
, mtime_t i_ts
)
245 decoder_t
*p_dec
= p_subpic
->p_sys
->p_dec
;
246 decoder_sys_t
*p_sys
= p_dec
->p_sys
;
248 subpicture_region_t
*p_spu_region
;
251 /* TODO maybe checking if we really need redrawing */
252 subpicture_region_ChainDelete( p_subpic
->p_region
);
253 p_subpic
->p_region
= NULL
;
255 /* FIXME check why this is needed */
256 if( p_subpic
!= p_sys
->p_spu_final
)
260 msg_Warn( p_dec
, "---- fmt: %dx%d %dx%d chroma=%4.4s",
261 p_fmt
->i_width
, p_fmt
->i_height
,
262 p_fmt
->i_visible_width
, p_fmt
->i_visible_height
,
263 (const char*)&p_fmt
->i_chroma
);
265 /* XXX On x86 at least our RGBA is mapped to their BGRA
266 * TODO confirm that is the same on big endian cpu */
268 fmt
.i_chroma
= VLC_FOURCC('R','G','B','A');
269 fmt
.i_width
= fmt
.i_visible_width
;
270 fmt
.i_height
= fmt
.i_visible_height
;
271 fmt
.i_bits_per_pixel
= 0;
272 fmt
.i_x_offset
= fmt
.i_y_offset
= 0;
276 if( memcmp(&fmt
, &p_sys
->fmt_cached
, sizeof(fmt
)) )
278 //msg_Warn( p_dec, "---- fmt: new %dx%d", fmt.i_width, fmt.i_height );
280 struct csri_fmt csri_fmt
;
281 memset(&csri_fmt
, 0, sizeof(csri_fmt
));
282 csri_fmt
.pixfmt
= CSRI_F_BGRA
;
283 csri_fmt
.width
= fmt
.i_width
;
284 csri_fmt
.height
= fmt
.i_height
;
285 if( csri_request_fmt( p_sys
->p_instance
, &csri_fmt
) )
286 msg_Dbg( p_dec
, "csri error: format not supported" );
288 p_sys
->fmt_cached
= fmt
;
291 p_subpic
->i_original_picture_height
= fmt
.i_height
;
292 p_subpic
->i_original_picture_width
= fmt
.i_width
;
294 p_spu_region
= p_subpic
->p_region
= subpicture_region_New( &fmt
);
298 struct csri_frame csri_frame
;
301 p_spu_region
->i_align
= SUBPICTURE_ALIGN_TOP
| SUBPICTURE_ALIGN_LEFT
;
302 memset( p_spu_region
->p_picture
->Y_PIXELS
, 0x00, p_spu_region
->p_picture
->Y_PITCH
* p_sys
->fmt_cached
.i_height
);
305 const mtime_t i_stream_date
= p_subpic
->p_sys
->i_pts
+ (i_ts
- p_subpic
->i_start
);
307 //msg_Dbg( p_dec, "TS %lf", ts * 0.000001 );
308 memset( &csri_frame
, 0, sizeof(csri_frame
) );
309 csri_frame
.pixfmt
= CSRI_F_BGRA
;
310 csri_frame
.planes
[0] = (unsigned char*)p_spu_region
->p_picture
->Y_PIXELS
;
311 csri_frame
.strides
[0] = p_spu_region
->p_picture
->Y_PITCH
;
312 csri_render( p_sys
->p_instance
, &csri_frame
, i_stream_date
* 0.000001 );