1 /*****************************************************************************
2 * spu.c: transcoding stream output module (spu)
3 *****************************************************************************
4 * Copyright (C) 2003-2009 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
9 * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
10 * Antoine Cellerier <dionoea at videolan dot org>
12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU Lesser General Public License as published by
14 * the Free Software Foundation; either version 2.1 of the License, or
15 * (at your option) any later version.
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Lesser General Public License for more details.
22 * You should have received a copy of the GNU Lesser General Public License
23 * along with this program; if not, write to the Free Software Foundation,
24 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
25 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
31 #include "transcode.h"
35 #include <vlc_modules.h>
38 static subpicture_t
*spu_new_buffer( decoder_t
*p_dec
,
39 const subpicture_updater_t
*p_upd
)
42 subpicture_t
*p_subpicture
= subpicture_New( p_upd
);
43 if( likely(p_subpicture
!= NULL
) )
44 p_subpicture
->b_subtitle
= true;
48 static int decoder_queue_sub( decoder_t
*p_dec
, subpicture_t
*p_spu
)
50 sout_stream_id_sys_t
*id
= p_dec
->p_queue_ctx
;
52 vlc_mutex_lock(&id
->fifo
.lock
);
53 *id
->fifo
.spu
.last
= p_spu
;
54 id
->fifo
.spu
.last
= &p_spu
->p_next
;
55 vlc_mutex_unlock(&id
->fifo
.lock
);
59 static subpicture_t
*transcode_dequeue_all_subs( sout_stream_id_sys_t
*id
)
61 vlc_mutex_lock(&id
->fifo
.lock
);
62 subpicture_t
*p_subpics
= id
->fifo
.spu
.first
;
63 id
->fifo
.spu
.first
= NULL
;
64 id
->fifo
.spu
.last
= &id
->fifo
.spu
.first
;
65 vlc_mutex_unlock(&id
->fifo
.lock
);
70 static int transcode_spu_new( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
)
72 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
78 /* Initialization of decoder structures */
79 id
->p_decoder
->pf_decode
= NULL
;
80 id
->p_decoder
->pf_spu_buffer_new
= spu_new_buffer
;
81 id
->p_decoder
->pf_queue_sub
= decoder_queue_sub
;
82 id
->p_decoder
->p_queue_ctx
= id
;
83 /* id->p_decoder->p_cfg = p_sys->p_spu_cfg; */
85 id
->p_decoder
->p_module
=
86 module_need_var( id
->p_decoder
, "spu decoder", "codec" );
88 if( !id
->p_decoder
->p_module
)
90 msg_Err( p_stream
, "cannot find spu decoder" );
94 if( !p_sys
->b_soverlay
)
97 /* Initialization of encoder format structures */
98 es_format_Init( &id
->p_encoder
->fmt_in
, id
->p_decoder
->fmt_in
.i_cat
,
99 id
->p_decoder
->fmt_in
.i_codec
);
101 id
->p_encoder
->p_cfg
= p_sys
->p_spu_cfg
;
103 id
->p_encoder
->p_module
=
104 module_need( id
->p_encoder
, "encoder", p_sys
->psz_senc
, true );
106 if( !id
->p_encoder
->p_module
)
108 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
109 msg_Err( p_stream
, "cannot find spu encoder (%s)", p_sys
->psz_senc
);
115 p_sys
->p_spu
= spu_Create( p_stream
, NULL
);
120 void transcode_spu_close( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
)
122 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
124 if( id
->p_decoder
->p_module
)
125 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
126 if( id
->p_decoder
->p_description
)
127 vlc_meta_Delete( id
->p_decoder
->p_description
);
130 if( id
->p_encoder
->p_module
)
131 module_unneed( id
->p_encoder
, id
->p_encoder
->p_module
);
135 spu_Destroy( p_sys
->p_spu
);
140 int transcode_spu_process( sout_stream_t
*p_stream
,
141 sout_stream_id_sys_t
*id
,
142 block_t
*in
, block_t
**out
)
144 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
146 bool b_error
= false;
148 int ret
= id
->p_decoder
->pf_decode( id
->p_decoder
, in
);
149 if( ret
!= VLCDEC_SUCCESS
)
152 subpicture_t
*p_subpics
= transcode_dequeue_all_subs( id
);
153 if( p_subpics
== NULL
)
157 subpicture_t
*p_subpic
= p_subpics
;
158 p_subpics
= p_subpics
->p_next
;
159 p_subpic
->p_next
= NULL
;
163 subpicture_Delete( p_subpic
);
167 if( p_sys
->b_master_sync
&& p_sys
->i_master_drift
)
169 p_subpic
->i_start
-= p_sys
->i_master_drift
;
170 if( p_subpic
->i_stop
) p_subpic
->i_stop
-= p_sys
->i_master_drift
;
173 if( p_sys
->b_soverlay
)
174 spu_PutSubpicture( p_sys
->p_spu
, p_subpic
);
180 es_format_Init( &fmt
, VIDEO_ES
, VLC_CODEC_TEXT
);
182 fmt
.video
.i_sar_num
=
183 fmt
.video
.i_visible_width
=
184 fmt
.video
.i_width
= p_sys
->i_spu_width
;
186 fmt
.video
.i_sar_den
=
187 fmt
.video
.i_visible_height
=
188 fmt
.video
.i_height
= p_sys
->i_spu_height
;
190 subpicture_Update( p_subpic
, &fmt
.video
, &fmt
.video
, p_subpic
->i_start
);
191 es_format_Clean( &fmt
);
193 p_block
= id
->p_encoder
->pf_encode_sub( id
->p_encoder
, p_subpic
);
194 subpicture_Delete( p_subpic
);
196 block_ChainAppend( out
, p_block
);
200 } while( p_subpics
);
202 return b_error
? VLC_EGENERIC
: VLC_SUCCESS
;
205 bool transcode_spu_add( sout_stream_t
*p_stream
, const es_format_t
*p_fmt
,
206 sout_stream_id_sys_t
*id
)
208 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
210 id
->fifo
.spu
.first
= NULL
;
211 id
->fifo
.spu
.last
= &id
->fifo
.spu
.first
;
213 if( p_sys
->i_scodec
)
215 msg_Dbg( p_stream
, "creating subtitle transcoding from fcc=`%4.4s' "
216 "to fcc=`%4.4s'", (char*)&p_fmt
->i_codec
,
217 (char*)&p_sys
->i_scodec
);
219 /* Complete destination format */
220 id
->p_encoder
->fmt_out
.i_codec
= p_sys
->i_scodec
;
222 /* build decoder -> filter -> encoder */
223 if( transcode_spu_new( p_stream
, id
) )
225 msg_Err( p_stream
, "cannot create subtitle chain" );
229 /* open output stream */
230 id
->id
= sout_StreamIdAdd( p_stream
->p_next
, &id
->p_encoder
->fmt_out
);
231 id
->b_transcode
= true;
235 transcode_spu_close( p_stream
, id
);
241 assert( p_sys
->b_soverlay
);
242 msg_Dbg( p_stream
, "subtitle (fcc=`%4.4s') overlaying",
243 (char*)&p_fmt
->i_codec
);
245 id
->b_transcode
= true;
247 /* Build decoder -> filter -> overlaying chain */
248 if( transcode_spu_new( p_stream
, id
) )
250 msg_Err( p_stream
, "cannot create subtitle chain" );