1 /*****************************************************************************
2 * video.c: transcoding stream output module (video)
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>
37 #define ENC_FRAMERATE (25 * 1000)
38 #define ENC_FRAMERATE_BASE 1000
40 struct decoder_owner_sys_t
42 sout_stream_sys_t
*p_sys
;
45 static void video_del_buffer_decoder( decoder_t
*p_decoder
, picture_t
*p_pic
)
47 VLC_UNUSED(p_decoder
);
48 picture_Release( p_pic
);
51 static void video_link_picture_decoder( decoder_t
*p_dec
, picture_t
*p_pic
)
54 picture_Hold( p_pic
);
57 static void video_unlink_picture_decoder( decoder_t
*p_dec
, picture_t
*p_pic
)
60 picture_Release( p_pic
);
63 static picture_t
*video_new_buffer_decoder( decoder_t
*p_dec
)
65 p_dec
->fmt_out
.video
.i_chroma
= p_dec
->fmt_out
.i_codec
;
66 return picture_NewFromFormat( &p_dec
->fmt_out
.video
);
69 static picture_t
*video_new_buffer_encoder( encoder_t
*p_enc
)
71 p_enc
->fmt_in
.video
.i_chroma
= p_enc
->fmt_in
.i_codec
;
72 return picture_NewFromFormat( &p_enc
->fmt_in
.video
);
75 static picture_t
*transcode_video_filter_buffer_new( filter_t
*p_filter
)
77 p_filter
->fmt_out
.video
.i_chroma
= p_filter
->fmt_out
.i_codec
;
78 return picture_NewFromFormat( &p_filter
->fmt_out
.video
);
80 static void transcode_video_filter_buffer_del( filter_t
*p_filter
, picture_t
*p_pic
)
83 picture_Release( p_pic
);
86 static int transcode_video_filter_allocation_init( filter_t
*p_filter
,
90 p_filter
->pf_video_buffer_new
= transcode_video_filter_buffer_new
;
91 p_filter
->pf_video_buffer_del
= transcode_video_filter_buffer_del
;
95 static void transcode_video_filter_allocation_clear( filter_t
*p_filter
)
100 static void* EncoderThread( void *obj
)
102 sout_stream_sys_t
*p_sys
= (sout_stream_sys_t
*)obj
;
103 sout_stream_id_sys_t
*id
= p_sys
->id_video
;
104 picture_t
*p_pic
= NULL
;
105 int canc
= vlc_savecancel ();
106 block_t
*p_block
= NULL
;
111 vlc_mutex_lock( &p_sys
->lock_out
);
112 while( !p_sys
->b_abort
&&
113 (p_pic
= picture_fifo_Pop( p_sys
->pp_pics
)) == NULL
)
114 vlc_cond_wait( &p_sys
->cond
, &p_sys
->lock_out
);
116 if( p_sys
->b_abort
&& !p_pic
)
118 vlc_mutex_unlock( &p_sys
->lock_out
);
121 vlc_mutex_unlock( &p_sys
->lock_out
);
125 p_block
= id
->p_encoder
->pf_encode_video( id
->p_encoder
, p_pic
);
127 vlc_mutex_lock( &p_sys
->lock_out
);
128 block_ChainAppend( &p_sys
->p_buffers
, p_block
);
130 vlc_mutex_unlock( &p_sys
->lock_out
);
131 picture_Release( p_pic
);
134 vlc_mutex_lock( &p_sys
->lock_out
);
137 vlc_mutex_unlock( &p_sys
->lock_out
);
140 vlc_mutex_unlock( &p_sys
->lock_out
);
143 /*Encode what we have in the buffer on closing*/
144 vlc_mutex_lock( &p_sys
->lock_out
);
145 while( (p_pic
= picture_fifo_Pop( p_sys
->pp_pics
)) != NULL
)
147 p_block
= id
->p_encoder
->pf_encode_video( id
->p_encoder
, p_pic
);
149 block_ChainAppend( &p_sys
->p_buffers
, p_block
);
151 picture_Release( p_pic
);
154 /*Now flush encoder*/
156 p_block
= id
->p_encoder
->pf_encode_video(id
->p_encoder
, NULL
);
157 block_ChainAppend( &p_sys
->p_buffers
, p_block
);
160 vlc_mutex_unlock( &p_sys
->lock_out
);
163 vlc_restorecancel (canc
);
167 int transcode_video_new( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
)
169 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
172 * Initialization of decoder structures
174 id
->p_decoder
->fmt_out
= id
->p_decoder
->fmt_in
;
175 id
->p_decoder
->fmt_out
.i_extra
= 0;
176 id
->p_decoder
->fmt_out
.p_extra
= 0;
177 id
->p_decoder
->pf_decode_video
= NULL
;
178 id
->p_decoder
->pf_get_cc
= NULL
;
179 id
->p_decoder
->pf_get_cc
= 0;
180 id
->p_decoder
->pf_vout_buffer_new
= video_new_buffer_decoder
;
181 id
->p_decoder
->pf_vout_buffer_del
= video_del_buffer_decoder
;
182 id
->p_decoder
->pf_picture_link
= video_link_picture_decoder
;
183 id
->p_decoder
->pf_picture_unlink
= video_unlink_picture_decoder
;
184 id
->p_decoder
->p_owner
= malloc( sizeof(decoder_owner_sys_t
) );
185 if( !id
->p_decoder
->p_owner
)
188 id
->p_decoder
->p_owner
->p_sys
= p_sys
;
189 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
191 id
->p_decoder
->p_module
=
192 module_need( id
->p_decoder
, "decoder", "$codec", false );
194 if( !id
->p_decoder
->p_module
)
196 msg_Err( p_stream
, "cannot find video decoder" );
197 free( id
->p_decoder
->p_owner
);
203 * Because some info about the decoded input will only be available
204 * once the first frame is decoded, we actually only test the availability
205 * of the encoder here.
208 /* Initialization of encoder format structures */
209 es_format_Init( &id
->p_encoder
->fmt_in
, id
->p_decoder
->fmt_in
.i_cat
,
210 id
->p_decoder
->fmt_out
.i_codec
);
211 id
->p_encoder
->fmt_in
.video
.i_chroma
= id
->p_decoder
->fmt_out
.i_codec
;
213 /* The dimensions will be set properly later on.
214 * Just put sensible values so we can test an encoder is available. */
215 id
->p_encoder
->fmt_in
.video
.i_width
=
216 id
->p_encoder
->fmt_out
.video
.i_width
217 ? id
->p_encoder
->fmt_out
.video
.i_width
218 : id
->p_decoder
->fmt_in
.video
.i_width
219 ? id
->p_decoder
->fmt_in
.video
.i_width
: 16;
220 id
->p_encoder
->fmt_in
.video
.i_height
=
221 id
->p_encoder
->fmt_out
.video
.i_height
222 ? id
->p_encoder
->fmt_out
.video
.i_height
223 : id
->p_decoder
->fmt_in
.video
.i_height
224 ? id
->p_decoder
->fmt_in
.video
.i_height
: 16;
225 id
->p_encoder
->fmt_in
.video
.i_visible_width
=
226 id
->p_encoder
->fmt_out
.video
.i_visible_width
227 ? id
->p_encoder
->fmt_out
.video
.i_visible_width
228 : id
->p_decoder
->fmt_in
.video
.i_visible_width
229 ? id
->p_decoder
->fmt_in
.video
.i_visible_width
: id
->p_encoder
->fmt_in
.video
.i_width
;
230 id
->p_encoder
->fmt_in
.video
.i_visible_height
=
231 id
->p_encoder
->fmt_out
.video
.i_visible_height
232 ? id
->p_encoder
->fmt_out
.video
.i_visible_height
233 : id
->p_decoder
->fmt_in
.video
.i_visible_height
234 ? id
->p_decoder
->fmt_in
.video
.i_visible_height
: id
->p_encoder
->fmt_in
.video
.i_height
;
235 id
->p_encoder
->fmt_in
.video
.i_frame_rate
= id
->p_decoder
->fmt_out
.video
.i_frame_rate
;
236 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
= id
->p_decoder
->fmt_out
.video
.i_frame_rate_base
;
238 id
->p_encoder
->i_threads
= p_sys
->i_threads
;
239 id
->p_encoder
->p_cfg
= p_sys
->p_video_cfg
;
241 id
->p_encoder
->p_module
=
242 module_need( id
->p_encoder
, "encoder", p_sys
->psz_venc
, true );
243 if( !id
->p_encoder
->p_module
)
245 msg_Err( p_stream
, "cannot find video encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
246 p_sys
->psz_venc
? p_sys
->psz_venc
: "any",
247 (char *)&p_sys
->i_vcodec
);
248 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
249 id
->p_decoder
->p_module
= 0;
250 free( id
->p_decoder
->p_owner
);
254 /* Close the encoder.
255 * We'll open it only when we have the first frame. */
256 module_unneed( id
->p_encoder
, id
->p_encoder
->p_module
);
257 if( id
->p_encoder
->fmt_out
.p_extra
)
259 free( id
->p_encoder
->fmt_out
.p_extra
);
260 id
->p_encoder
->fmt_out
.p_extra
= NULL
;
261 id
->p_encoder
->fmt_out
.i_extra
= 0;
263 id
->p_encoder
->p_module
= NULL
;
265 if( p_sys
->i_threads
>= 1 )
267 int i_priority
= p_sys
->b_high_priority
? VLC_THREAD_PRIORITY_OUTPUT
:
268 VLC_THREAD_PRIORITY_VIDEO
;
269 p_sys
->id_video
= id
;
270 vlc_mutex_init( &p_sys
->lock_out
);
271 vlc_cond_init( &p_sys
->cond
);
272 p_sys
->pp_pics
= picture_fifo_New();
273 if( p_sys
->pp_pics
== NULL
)
275 msg_Err( p_stream
, "cannot create picture fifo" );
276 vlc_mutex_destroy( &p_sys
->lock_out
);
277 vlc_cond_destroy( &p_sys
->cond
);
278 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
279 id
->p_decoder
->p_module
= NULL
;
280 free( id
->p_decoder
->p_owner
);
283 p_sys
->p_buffers
= NULL
;
284 p_sys
->b_abort
= false;
285 if( vlc_clone( &p_sys
->thread
, EncoderThread
, p_sys
, i_priority
) )
287 msg_Err( p_stream
, "cannot spawn encoder thread" );
288 vlc_mutex_destroy( &p_sys
->lock_out
);
289 vlc_cond_destroy( &p_sys
->cond
);
290 picture_fifo_Delete( p_sys
->pp_pics
);
291 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
292 id
->p_decoder
->p_module
= NULL
;
293 free( id
->p_decoder
->p_owner
);
300 static void transcode_video_filter_init( sout_stream_t
*p_stream
,
301 sout_stream_id_sys_t
*id
)
303 es_format_t
*p_fmt_out
= &id
->p_decoder
->fmt_out
;
304 id
->p_encoder
->fmt_in
.video
.i_chroma
= id
->p_encoder
->fmt_in
.i_codec
;
306 id
->p_f_chain
= filter_chain_New( p_stream
, "video filter2",
308 transcode_video_filter_allocation_init
,
309 transcode_video_filter_allocation_clear
,
311 filter_chain_Reset( id
->p_f_chain
, p_fmt_out
, p_fmt_out
);
314 if( p_stream
->p_sys
->b_deinterlace
)
316 filter_chain_AppendFilter( id
->p_f_chain
,
317 p_stream
->p_sys
->psz_deinterlace
,
318 p_stream
->p_sys
->p_deinterlace_cfg
,
319 &id
->p_decoder
->fmt_out
,
320 &id
->p_decoder
->fmt_out
);
322 p_fmt_out
= filter_chain_GetFmtOut( id
->p_f_chain
);
325 /* Check that we have visible_width/height*/
326 if( !p_fmt_out
->video
.i_visible_height
)
327 p_fmt_out
->video
.i_visible_height
= p_fmt_out
->video
.i_height
;
328 if( !p_fmt_out
->video
.i_visible_width
)
329 p_fmt_out
->video
.i_visible_width
= p_fmt_out
->video
.i_width
;
331 if( p_stream
->p_sys
->psz_vf2
)
333 id
->p_uf_chain
= filter_chain_New( p_stream
, "video filter2",
335 transcode_video_filter_allocation_init
,
336 transcode_video_filter_allocation_clear
,
338 filter_chain_Reset( id
->p_uf_chain
, p_fmt_out
,
339 &id
->p_encoder
->fmt_in
);
340 if( p_fmt_out
->video
.i_chroma
!= id
->p_encoder
->fmt_in
.video
.i_chroma
)
342 filter_chain_AppendFilter( id
->p_uf_chain
,
345 &id
->p_encoder
->fmt_in
);
347 filter_chain_AppendFromString( id
->p_uf_chain
, p_stream
->p_sys
->psz_vf2
);
348 p_fmt_out
= filter_chain_GetFmtOut( id
->p_uf_chain
);
349 es_format_Copy( &id
->p_encoder
->fmt_in
, p_fmt_out
);
350 id
->p_encoder
->fmt_out
.video
.i_width
=
351 id
->p_encoder
->fmt_in
.video
.i_width
;
352 id
->p_encoder
->fmt_out
.video
.i_height
=
353 id
->p_encoder
->fmt_in
.video
.i_height
;
354 id
->p_encoder
->fmt_out
.video
.i_sar_num
=
355 id
->p_encoder
->fmt_in
.video
.i_sar_num
;
356 id
->p_encoder
->fmt_out
.video
.i_sar_den
=
357 id
->p_encoder
->fmt_in
.video
.i_sar_den
;
362 /* Take care of the scaling and chroma conversions. */
363 static void conversion_video_filter_append( sout_stream_id_sys_t
*id
)
365 const es_format_t
*p_fmt_out
= &id
->p_decoder
->fmt_out
;
367 p_fmt_out
= filter_chain_GetFmtOut( id
->p_f_chain
);
370 p_fmt_out
= filter_chain_GetFmtOut( id
->p_uf_chain
);
372 if( ( p_fmt_out
->video
.i_chroma
!= id
->p_encoder
->fmt_in
.video
.i_chroma
) ||
373 ( p_fmt_out
->video
.i_width
!= id
->p_encoder
->fmt_in
.video
.i_width
) ||
374 ( p_fmt_out
->video
.i_height
!= id
->p_encoder
->fmt_in
.video
.i_height
) )
376 filter_chain_AppendFilter( id
->p_uf_chain
? id
->p_uf_chain
: id
->p_f_chain
,
379 &id
->p_encoder
->fmt_in
);
383 static void transcode_video_encoder_init( sout_stream_t
*p_stream
,
384 sout_stream_id_sys_t
*id
)
386 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
388 const es_format_t
*p_fmt_out
= &id
->p_decoder
->fmt_out
;
389 if( id
->p_f_chain
) {
390 p_fmt_out
= filter_chain_GetFmtOut( id
->p_f_chain
);
392 if( id
->p_uf_chain
) {
393 p_fmt_out
= filter_chain_GetFmtOut( id
->p_uf_chain
);
397 * width/height of source */
398 int i_src_visible_width
= p_fmt_out
->video
.i_visible_width
;
399 int i_src_visible_height
= p_fmt_out
->video
.i_visible_height
;
401 if (i_src_visible_width
== 0)
402 i_src_visible_width
= p_fmt_out
->video
.i_width
;
403 if (i_src_visible_height
== 0)
404 i_src_visible_height
= p_fmt_out
->video
.i_height
;
407 /* with/height scaling */
408 float f_scale_width
= 1;
409 float f_scale_height
= 1;
412 float f_aspect
= (double)p_fmt_out
->video
.i_sar_num
*
413 p_fmt_out
->video
.i_width
/
414 p_fmt_out
->video
.i_sar_den
/
415 p_fmt_out
->video
.i_height
;
417 msg_Dbg( p_stream
, "decoder aspect is %f:1", f_aspect
);
419 /* Change f_aspect from source frame to source pixel */
420 f_aspect
= f_aspect
* i_src_visible_height
/ i_src_visible_width
;
421 msg_Dbg( p_stream
, "source pixel aspect is %f:1", f_aspect
);
423 /* Calculate scaling factor for specified parameters */
424 if( id
->p_encoder
->fmt_out
.video
.i_visible_width
<= 0 &&
425 id
->p_encoder
->fmt_out
.video
.i_visible_height
<= 0 && p_sys
->f_scale
)
427 /* Global scaling. Make sure width will remain a factor of 16 */
430 int i_new_width
= i_src_visible_width
* p_sys
->f_scale
;
432 if( i_new_width
% 16 <= 7 && i_new_width
>= 16 )
433 i_new_width
-= i_new_width
% 16;
435 i_new_width
+= 16 - i_new_width
% 16;
437 f_real_scale
= (float)( i_new_width
) / (float) i_src_visible_width
;
439 i_new_height
= __MAX( 16, i_src_visible_height
* (float)f_real_scale
);
441 f_scale_width
= f_real_scale
;
442 f_scale_height
= (float) i_new_height
/ (float) i_src_visible_height
;
444 else if( id
->p_encoder
->fmt_out
.video
.i_visible_width
> 0 &&
445 id
->p_encoder
->fmt_out
.video
.i_visible_height
<= 0 )
447 /* Only width specified */
448 f_scale_width
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_width
/i_src_visible_width
;
449 f_scale_height
= f_scale_width
;
451 else if( id
->p_encoder
->fmt_out
.video
.i_visible_width
<= 0 &&
452 id
->p_encoder
->fmt_out
.video
.i_visible_height
> 0 )
454 /* Only height specified */
455 f_scale_height
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_height
/i_src_visible_height
;
456 f_scale_width
= f_scale_height
;
458 else if( id
->p_encoder
->fmt_out
.video
.i_visible_width
> 0 &&
459 id
->p_encoder
->fmt_out
.video
.i_visible_height
> 0 )
461 /* Width and height specified */
462 f_scale_width
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_width
/i_src_visible_width
;
463 f_scale_height
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_height
/i_src_visible_height
;
466 /* check maxwidth and maxheight */
467 if( p_sys
->i_maxwidth
&& f_scale_width
> (float)p_sys
->i_maxwidth
/
468 i_src_visible_width
)
470 f_scale_width
= (float)p_sys
->i_maxwidth
/ i_src_visible_width
;
473 if( p_sys
->i_maxheight
&& f_scale_height
> (float)p_sys
->i_maxheight
/
474 i_src_visible_height
)
476 f_scale_height
= (float)p_sys
->i_maxheight
/ i_src_visible_height
;
480 /* Change aspect ratio from source pixel to scaled pixel */
481 f_aspect
= f_aspect
* f_scale_height
/ f_scale_width
;
482 msg_Dbg( p_stream
, "scaled pixel aspect is %f:1", f_aspect
);
484 /* f_scale_width and f_scale_height are now final */
485 /* Calculate width, height from scaling
486 * Make sure its multiple of 2
488 /* width/height of output stream */
489 int i_dst_visible_width
= 2 * (int)(f_scale_width
*i_src_visible_width
/2+0.5);
490 int i_dst_visible_height
= 2 * (int)(f_scale_height
*i_src_visible_height
/2+0.5);
491 int i_dst_width
= 2 * (int)(f_scale_width
*p_fmt_out
->video
.i_width
/2+0.5);
492 int i_dst_height
= 2 * (int)(f_scale_height
*p_fmt_out
->video
.i_height
/2+0.5);
494 /* Change aspect ratio from scaled pixel to output frame */
495 f_aspect
= f_aspect
* i_dst_visible_width
/ i_dst_visible_height
;
497 /* Store calculated values */
498 id
->p_encoder
->fmt_out
.video
.i_width
= i_dst_width
;
499 id
->p_encoder
->fmt_out
.video
.i_visible_width
= i_dst_visible_width
;
500 id
->p_encoder
->fmt_out
.video
.i_height
= i_dst_height
;
501 id
->p_encoder
->fmt_out
.video
.i_visible_height
= i_dst_visible_height
;
503 id
->p_encoder
->fmt_in
.video
.i_width
= i_dst_width
;
504 id
->p_encoder
->fmt_in
.video
.i_visible_width
= i_dst_visible_width
;
505 id
->p_encoder
->fmt_in
.video
.i_height
= i_dst_height
;
506 id
->p_encoder
->fmt_in
.video
.i_visible_height
= i_dst_visible_height
;
508 msg_Dbg( p_stream
, "source %ix%i, destination %ix%i",
509 i_src_visible_width
, i_src_visible_height
,
510 i_dst_visible_width
, i_dst_visible_height
513 /* Handle frame rate conversion */
514 if( !id
->p_encoder
->fmt_out
.video
.i_frame_rate
||
515 !id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
)
517 if( p_fmt_out
->video
.i_frame_rate
&&
518 p_fmt_out
->video
.i_frame_rate_base
)
520 id
->p_encoder
->fmt_out
.video
.i_frame_rate
=
521 p_fmt_out
->video
.i_frame_rate
;
522 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
=
523 p_fmt_out
->video
.i_frame_rate_base
;
527 /* Pick a sensible default value */
528 id
->p_encoder
->fmt_out
.video
.i_frame_rate
= ENC_FRAMERATE
;
529 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
= ENC_FRAMERATE_BASE
;
533 id
->p_encoder
->fmt_in
.video
.i_frame_rate
=
534 id
->p_encoder
->fmt_out
.video
.i_frame_rate
;
535 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
=
536 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
;
538 vlc_ureduce( &id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
539 &id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
,
540 id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
541 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
,
543 msg_Dbg( p_stream
, "source fps %d/%d, destination %d/%d",
544 id
->p_decoder
->fmt_out
.video
.i_frame_rate
,
545 id
->p_decoder
->fmt_out
.video
.i_frame_rate_base
,
546 id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
547 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
);
549 id
->i_output_frame_interval
= id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
* CLOCK_FREQ
/ id
->p_encoder
->fmt_out
.video
.i_frame_rate
;
550 msg_Info( p_stream
, "output interval %d (base %d)",
551 id
->i_output_frame_interval
, id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
);
553 date_Init( &id
->next_output_pts
,
554 id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
557 /* Check whether a particular aspect ratio was requested */
558 if( id
->p_encoder
->fmt_out
.video
.i_sar_num
<= 0 ||
559 id
->p_encoder
->fmt_out
.video
.i_sar_den
<= 0 )
561 vlc_ureduce( &id
->p_encoder
->fmt_out
.video
.i_sar_num
,
562 &id
->p_encoder
->fmt_out
.video
.i_sar_den
,
563 (uint64_t)p_fmt_out
->video
.i_sar_num
* i_src_visible_width
* i_dst_visible_height
,
564 (uint64_t)p_fmt_out
->video
.i_sar_den
* i_src_visible_height
* i_dst_visible_width
,
569 vlc_ureduce( &id
->p_encoder
->fmt_out
.video
.i_sar_num
,
570 &id
->p_encoder
->fmt_out
.video
.i_sar_den
,
571 id
->p_encoder
->fmt_out
.video
.i_sar_num
,
572 id
->p_encoder
->fmt_out
.video
.i_sar_den
,
576 id
->p_encoder
->fmt_in
.video
.i_sar_num
=
577 id
->p_encoder
->fmt_out
.video
.i_sar_num
;
578 id
->p_encoder
->fmt_in
.video
.i_sar_den
=
579 id
->p_encoder
->fmt_out
.video
.i_sar_den
;
581 msg_Dbg( p_stream
, "encoder aspect is %i:%i",
582 id
->p_encoder
->fmt_out
.video
.i_sar_num
* id
->p_encoder
->fmt_out
.video
.i_width
,
583 id
->p_encoder
->fmt_out
.video
.i_sar_den
* id
->p_encoder
->fmt_out
.video
.i_height
);
587 static int transcode_video_encoder_open( sout_stream_t
*p_stream
,
588 sout_stream_id_sys_t
*id
)
590 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
593 msg_Dbg( p_stream
, "destination (after video filters) %ix%i",
594 id
->p_encoder
->fmt_in
.video
.i_width
,
595 id
->p_encoder
->fmt_in
.video
.i_height
);
597 id
->p_encoder
->p_module
=
598 module_need( id
->p_encoder
, "encoder", p_sys
->psz_venc
, true );
599 if( !id
->p_encoder
->p_module
)
601 msg_Err( p_stream
, "cannot find video encoder (module:%s fourcc:%4.4s)",
602 p_sys
->psz_venc
? p_sys
->psz_venc
: "any",
603 (char *)&p_sys
->i_vcodec
);
607 id
->p_encoder
->fmt_in
.video
.i_chroma
= id
->p_encoder
->fmt_in
.i_codec
;
610 id
->p_encoder
->fmt_out
.i_codec
=
611 vlc_fourcc_GetCodec( VIDEO_ES
, id
->p_encoder
->fmt_out
.i_codec
);
613 id
->id
= sout_StreamIdAdd( p_stream
->p_next
, &id
->p_encoder
->fmt_out
);
616 msg_Err( p_stream
, "cannot add this stream" );
623 void transcode_video_close( sout_stream_t
*p_stream
,
624 sout_stream_id_sys_t
*id
)
626 if( p_stream
->p_sys
->i_threads
>= 1 )
628 vlc_mutex_lock( &p_stream
->p_sys
->lock_out
);
629 p_stream
->p_sys
->b_abort
= true;
630 vlc_cond_signal( &p_stream
->p_sys
->cond
);
631 vlc_mutex_unlock( &p_stream
->p_sys
->lock_out
);
633 vlc_join( p_stream
->p_sys
->thread
, NULL
);
634 vlc_mutex_destroy( &p_stream
->p_sys
->lock_out
);
635 vlc_cond_destroy( &p_stream
->p_sys
->cond
);
637 picture_fifo_Delete( p_stream
->p_sys
->pp_pics
);
638 block_ChainRelease( p_stream
->p_sys
->p_buffers
);
639 p_stream
->p_sys
->pp_pics
= NULL
;
643 if( id
->p_decoder
->p_module
)
644 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
645 if( id
->p_decoder
->p_description
)
646 vlc_meta_Delete( id
->p_decoder
->p_description
);
648 free( id
->p_decoder
->p_owner
);
651 if( id
->p_encoder
->p_module
)
652 module_unneed( id
->p_encoder
, id
->p_encoder
->p_module
);
656 filter_chain_Delete( id
->p_f_chain
);
658 filter_chain_Delete( id
->p_uf_chain
);
661 static void OutputFrame( sout_stream_sys_t
*p_sys
, picture_t
*p_pic
, sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
, block_t
**out
)
664 picture_t
*p_pic2
= NULL
;
665 const mtime_t original_date
= p_pic
->date
;
666 bool b_need_duplicate
=false;
667 /* If input pts is lower than next_output_pts - output_frame_interval
668 * Then the future input frame should fit better and we can drop this one
670 * We check it here also because we can have case that video filters outputs multiple
671 * pictures but we don't need to use them all, for example yadif2x and outputting to some
672 * different fps value
674 if( ( original_date
) <
675 ( date_Get( &id
->next_output_pts
) - (mtime_t
)id
->i_output_frame_interval
) )
678 msg_Dbg( p_stream
, "dropping frame (%"PRId64
" + %"PRId64
" vs %"PRId64
")",
679 p_pic
->date
, id
->i_input_frame_interval
, date_Get(&id
->next_output_pts
) );
681 picture_Release( p_pic
);
688 /* Check if we have a subpicture to overlay */
691 video_format_t fmt
= id
->p_encoder
->fmt_in
.video
;
692 if( fmt
.i_visible_width
<= 0 || fmt
.i_visible_height
<= 0 )
694 fmt
.i_visible_width
= fmt
.i_width
;
695 fmt
.i_visible_height
= fmt
.i_height
;
700 subpicture_t
*p_subpic
= spu_Render( p_sys
->p_spu
, NULL
, &fmt
, &fmt
,
701 p_pic
->date
, p_pic
->date
, false );
703 /* Overlay subpicture */
706 if( picture_IsReferenced( p_pic
) && !filter_chain_GetLength( id
->p_f_chain
) )
708 /* We can't modify the picture, we need to duplicate it,
709 * in this point the picture is already p_encoder->fmt.in format*/
710 picture_t
*p_tmp
= video_new_buffer_encoder( id
->p_encoder
);
711 if( likely( p_tmp
) )
713 picture_Copy( p_tmp
, p_pic
);
714 picture_Release( p_pic
);
718 if( unlikely( !p_sys
->p_spu_blend
) )
719 p_sys
->p_spu_blend
= filter_NewBlend( VLC_OBJECT( p_sys
->p_spu
), &fmt
);
720 if( likely( p_sys
->p_spu_blend
) )
721 picture_BlendSubpicture( p_pic
, p_sys
->p_spu_blend
, p_subpic
);
722 subpicture_Delete( p_subpic
);
727 p_pic
->date
= date_Get( &id
->next_output_pts
);
728 /*This pts is handled, increase clock to next one*/
729 date_Increment( &id
->next_output_pts
, id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
);
731 if( p_sys
->i_threads
== 0 )
735 p_block
= id
->p_encoder
->pf_encode_video( id
->p_encoder
, p_pic
);
736 block_ChainAppend( out
, p_block
);
739 /* we need to duplicate while next_output_pts + output_frame_interval < input_pts (next input pts)*/
740 b_need_duplicate
= ( date_Get( &id
->next_output_pts
) + id
->i_output_frame_interval
) <
743 if( p_sys
->i_threads
)
745 if( p_sys
->b_master_sync
)
747 p_pic2
= video_new_buffer_encoder( id
->p_encoder
);
748 if( likely( p_pic2
!= NULL
) )
749 picture_Copy( p_pic2
, p_pic
);
751 vlc_mutex_lock( &p_sys
->lock_out
);
752 picture_fifo_Push( p_sys
->pp_pics
, p_pic
);
753 vlc_cond_signal( &p_sys
->cond
);
754 vlc_mutex_unlock( &p_sys
->lock_out
);
757 while( (p_sys
->b_master_sync
&& b_need_duplicate
))
759 if( p_sys
->i_threads
>= 1 )
761 picture_t
*p_tmp
= NULL
;
762 /* We can't modify the picture, we need to duplicate it */
763 p_tmp
= video_new_buffer_encoder( id
->p_encoder
);
764 if( likely( p_tmp
!= NULL
) )
766 picture_Copy( p_tmp
, p_pic2
);
767 p_tmp
->date
= date_Get( &id
->next_output_pts
);
768 vlc_mutex_lock( &p_sys
->lock_out
);
769 picture_fifo_Push( p_sys
->pp_pics
, p_tmp
);
770 vlc_cond_signal( &p_sys
->cond
);
771 vlc_mutex_unlock( &p_sys
->lock_out
);
777 p_pic
->date
= date_Get( &id
->next_output_pts
);
778 p_block
= id
->p_encoder
->pf_encode_video(id
->p_encoder
, p_pic
);
779 block_ChainAppend( out
, p_block
);
782 msg_Dbg( p_stream
, "duplicated frame");
784 date_Increment( &id
->next_output_pts
, id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
);
785 b_need_duplicate
= ( date_Get( &id
->next_output_pts
) + id
->i_output_frame_interval
) <
789 if( p_sys
->i_threads
&& p_pic2
)
790 picture_Release( p_pic2
);
791 else if ( p_sys
->i_threads
== 0 )
792 picture_Release( p_pic
);
795 int transcode_video_process( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
,
796 block_t
*in
, block_t
**out
)
798 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
799 picture_t
*p_pic
= NULL
;
802 if( unlikely( in
== NULL
) )
804 if( p_sys
->i_threads
== 0 )
808 p_block
= id
->p_encoder
->pf_encode_video(id
->p_encoder
, NULL
);
809 block_ChainAppend( out
, p_block
);
814 msg_Dbg( p_stream
, "Flushing thread and waiting that");
815 vlc_mutex_lock( &p_stream
->p_sys
->lock_out
);
816 p_stream
->p_sys
->b_abort
= true;
817 vlc_cond_signal( &p_stream
->p_sys
->cond
);
818 vlc_mutex_unlock( &p_stream
->p_sys
->lock_out
);
820 vlc_join( p_stream
->p_sys
->thread
, NULL
);
821 vlc_mutex_lock( &p_sys
->lock_out
);
822 *out
= p_sys
->p_buffers
;
823 p_sys
->p_buffers
= NULL
;
824 vlc_mutex_unlock( &p_sys
->lock_out
);
826 msg_Dbg( p_stream
, "Flushing done");
832 while( (p_pic
= id
->p_decoder
->pf_decode_video( id
->p_decoder
, &in
)) )
835 if( p_stream
->p_sout
->i_out_pace_nocontrol
&& p_sys
->b_hurry_up
)
837 mtime_t current_date
= mdate();
838 if( unlikely( (current_date
- 50000) > p_pic
->date
) )
840 msg_Dbg( p_stream
, "late picture skipped (%"PRId64
")",
841 current_date
- 50000 - p_pic
->date
);
842 picture_Release( p_pic
);
848 id
->p_encoder
->p_module
&&
849 !video_format_IsSimilar( &p_sys
->fmt_input_video
, &id
->p_decoder
->fmt_out
.video
)
853 msg_Info( p_stream
, "aspect-ratio changed, reiniting. %i -> %i : %i -> %i.",
854 p_sys
->fmt_input_video
.i_sar_num
, id
->p_decoder
->fmt_out
.video
.i_sar_num
,
855 p_sys
->fmt_input_video
.i_sar_den
, id
->p_decoder
->fmt_out
.video
.i_sar_den
859 filter_chain_Delete( id
->p_f_chain
);
860 id
->p_f_chain
= NULL
;
862 filter_chain_Delete( id
->p_uf_chain
);
863 id
->p_uf_chain
= NULL
;
865 /* Reinitialize filters */
866 id
->p_encoder
->fmt_out
.video
.i_visible_width
= p_sys
->i_width
& ~1;
867 id
->p_encoder
->fmt_out
.video
.i_visible_height
= p_sys
->i_height
& ~1;
868 id
->p_encoder
->fmt_out
.video
.i_sar_num
= id
->p_encoder
->fmt_out
.video
.i_sar_den
= 0;
870 transcode_video_filter_init( p_stream
, id
);
871 transcode_video_encoder_init( p_stream
, id
);
872 conversion_video_filter_append( id
);
873 memcpy( &p_sys
->fmt_input_video
, &id
->p_decoder
->fmt_out
.video
, sizeof(video_format_t
));
877 if( unlikely( !id
->p_encoder
->p_module
) )
880 filter_chain_Delete( id
->p_f_chain
);
882 filter_chain_Delete( id
->p_uf_chain
);
883 id
->p_f_chain
= id
->p_uf_chain
= NULL
;
885 transcode_video_filter_init( p_stream
, id
);
886 transcode_video_encoder_init( p_stream
, id
);
887 conversion_video_filter_append( id
);
888 memcpy( &p_sys
->fmt_input_video
, &id
->p_decoder
->fmt_out
.video
, sizeof(video_format_t
));
890 if( transcode_video_encoder_open( p_stream
, id
) != VLC_SUCCESS
)
892 picture_Release( p_pic
);
893 transcode_video_close( p_stream
, id
);
894 id
->b_transcode
= false;
897 date_Set( &id
->next_output_pts
, p_pic
->date
);
900 /*Input lipsync and drop check */
901 if( p_sys
->b_master_sync
)
903 /* If input pts lower than next_output_pts - output_frame_interval
904 * Then the future input frame should fit better and we can drop this one
906 * We check this here as we don't need to run video filter at all for pictures
907 * we are going to drop anyway
909 * Duplication need is checked in OutputFrame */
910 if( ( p_pic
->date
) <
911 ( date_Get( &id
->next_output_pts
) - (mtime_t
)id
->i_output_frame_interval
) )
914 msg_Dbg( p_stream
, "dropping frame (%"PRId64
" + %"PRId64
" vs %"PRId64
")",
915 p_pic
->date
, id
->i_input_frame_interval
, date_Get(&id
->next_output_pts
) );
917 picture_Release( p_pic
);
921 msg_Dbg( p_stream
, "not dropping frame");
926 /* Run the filter and output chains; first with the picture,
927 * and then with NULL as many times as we need until they
928 * stop outputting frames.
931 picture_t
*p_filtered_pic
= p_pic
;
933 /* Run filter chain */
935 p_filtered_pic
= filter_chain_VideoFilter( id
->p_f_chain
, p_filtered_pic
);
936 if( !p_filtered_pic
)
940 picture_t
*p_user_filtered_pic
= p_filtered_pic
;
942 /* Run user specified filter chain */
944 p_user_filtered_pic
= filter_chain_VideoFilter( id
->p_uf_chain
, p_user_filtered_pic
);
945 if( !p_user_filtered_pic
)
948 OutputFrame( p_sys
, p_user_filtered_pic
, p_stream
, id
, out
);
950 p_filtered_pic
= NULL
;
957 if( p_sys
->i_threads
>= 1 )
959 /* Pick up any return data the encoder thread wants to output. */
960 vlc_mutex_lock( &p_sys
->lock_out
);
961 *out
= p_sys
->p_buffers
;
962 p_sys
->p_buffers
= NULL
;
963 vlc_mutex_unlock( &p_sys
->lock_out
);
969 bool transcode_video_add( sout_stream_t
*p_stream
, es_format_t
*p_fmt
,
970 sout_stream_id_sys_t
*id
)
972 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
975 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
976 (char*)&p_fmt
->i_codec
, (char*)&p_sys
->i_vcodec
);
978 /* Complete destination format */
979 id
->p_encoder
->fmt_out
.i_codec
= p_sys
->i_vcodec
;
980 id
->p_encoder
->fmt_out
.video
.i_visible_width
= p_sys
->i_width
& ~1;
981 id
->p_encoder
->fmt_out
.video
.i_visible_height
= p_sys
->i_height
& ~1;
982 id
->p_encoder
->fmt_out
.i_bitrate
= p_sys
->i_vbitrate
;
984 /* Build decoder -> filter -> encoder chain */
985 if( transcode_video_new( p_stream
, id
) )
987 msg_Err( p_stream
, "cannot create video chain" );
991 /* Stream will be added later on because we don't know
992 * all the characteristics of the decoded stream yet */
993 id
->b_transcode
= true;
997 id
->p_encoder
->fmt_out
.video
.i_frame_rate
= (p_sys
->fps_num
);
998 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
= (p_sys
->fps_den
? p_sys
->fps_den
: 1);