1 /*****************************************************************************
2 * video.c: transcoding stream output module (video)
3 *****************************************************************************
4 * Copyright (C) 2003-2009 the VideoLAN team
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
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 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 General Public License for more details.
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, 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 + .5)
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 *transcode_video_filter_buffer_new( filter_t *p_filter )
71 p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
72 return picture_NewFromFormat( &p_filter->fmt_out.video );
74 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
77 picture_Release( p_pic );
80 static int transcode_video_filter_allocation_init( filter_t *p_filter,
84 p_filter->pf_video_buffer_new = transcode_video_filter_buffer_new;
85 p_filter->pf_video_buffer_del = transcode_video_filter_buffer_del;
89 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
94 static void* EncoderThread( void *obj )
96 sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
97 sout_stream_id_t *id = p_sys->id_video;
99 int canc = vlc_savecancel ();
105 vlc_mutex_lock( &p_sys->lock_out );
106 while( !p_sys->b_abort &&
107 (p_pic = picture_fifo_Pop( p_sys->pp_pics )) == NULL )
108 vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
112 vlc_mutex_unlock( &p_sys->lock_out );
115 vlc_mutex_unlock( &p_sys->lock_out );
117 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
119 vlc_mutex_lock( &p_sys->lock_out );
120 block_ChainAppend( &p_sys->p_buffers, p_block );
122 vlc_mutex_unlock( &p_sys->lock_out );
123 picture_Release( p_pic );
126 block_ChainRelease( p_sys->p_buffers );
128 vlc_restorecancel (canc);
132 int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
134 sout_stream_sys_t *p_sys = p_stream->p_sys;
137 * Initialization of decoder structures
139 id->p_decoder->fmt_out = id->p_decoder->fmt_in;
140 id->p_decoder->fmt_out.i_extra = 0;
141 id->p_decoder->fmt_out.p_extra = 0;
142 id->p_decoder->pf_decode_video = NULL;
143 id->p_decoder->pf_get_cc = NULL;
144 id->p_decoder->pf_get_cc = 0;
145 id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
146 id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
147 id->p_decoder->pf_picture_link = video_link_picture_decoder;
148 id->p_decoder->pf_picture_unlink = video_unlink_picture_decoder;
149 id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
150 if( !id->p_decoder->p_owner )
153 id->p_decoder->p_owner->p_sys = p_sys;
154 /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
156 id->p_decoder->p_module =
157 module_need( id->p_decoder, "decoder", "$codec", false );
159 if( !id->p_decoder->p_module )
161 msg_Err( p_stream, "cannot find video decoder" );
162 free( id->p_decoder->p_owner );
168 * Because some info about the decoded input will only be available
169 * once the first frame is decoded, we actually only test the availability
170 * of the encoder here.
173 /* Initialization of encoder format structures */
174 es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
175 id->p_decoder->fmt_out.i_codec );
176 id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
178 /* The dimensions will be set properly later on.
179 * Just put sensible values so we can test an encoder is available. */
180 id->p_encoder->fmt_in.video.i_width =
181 id->p_encoder->fmt_out.video.i_width
182 ? id->p_encoder->fmt_out.video.i_width
183 : id->p_decoder->fmt_in.video.i_width
184 ? id->p_decoder->fmt_in.video.i_width : 16;
185 id->p_encoder->fmt_in.video.i_height =
186 id->p_encoder->fmt_out.video.i_height
187 ? id->p_encoder->fmt_out.video.i_height
188 : id->p_decoder->fmt_in.video.i_height
189 ? id->p_decoder->fmt_in.video.i_height : 16;
190 id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
191 id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
193 id->p_encoder->i_threads = p_sys->i_threads;
194 id->p_encoder->p_cfg = p_sys->p_video_cfg;
196 id->p_encoder->p_module =
197 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
198 if( !id->p_encoder->p_module )
200 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
201 p_sys->psz_venc ? p_sys->psz_venc : "any",
202 (char *)&p_sys->i_vcodec );
203 module_unneed( id->p_decoder, id->p_decoder->p_module );
204 id->p_decoder->p_module = 0;
205 free( id->p_decoder->p_owner );
209 /* Close the encoder.
210 * We'll open it only when we have the first frame. */
211 module_unneed( id->p_encoder, id->p_encoder->p_module );
212 if( id->p_encoder->fmt_out.p_extra )
214 free( id->p_encoder->fmt_out.p_extra );
215 id->p_encoder->fmt_out.p_extra = NULL;
216 id->p_encoder->fmt_out.i_extra = 0;
218 id->p_encoder->p_module = NULL;
220 if( p_sys->i_threads >= 1 )
222 int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
223 VLC_THREAD_PRIORITY_VIDEO;
224 p_sys->id_video = id;
225 vlc_mutex_init( &p_sys->lock_out );
226 vlc_cond_init( &p_sys->cond );
227 p_sys->pp_pics = picture_fifo_New();
228 if( p_sys->pp_pics == NULL )
230 msg_Err( p_stream, "cannot create picture fifo" );
231 module_unneed( id->p_decoder, id->p_decoder->p_module );
232 id->p_decoder->p_module = NULL;
233 free( id->p_decoder->p_owner );
236 p_sys->p_buffers = NULL;
237 p_sys->b_abort = false;
238 if( vlc_clone( &p_sys->thread, EncoderThread, p_sys, i_priority ) )
240 msg_Err( p_stream, "cannot spawn encoder thread" );
241 module_unneed( id->p_decoder, id->p_decoder->p_module );
242 id->p_decoder->p_module = NULL;
243 free( id->p_decoder->p_owner );
250 static void transcode_video_filter_init( sout_stream_t *p_stream,
251 sout_stream_id_t *id )
254 id->p_f_chain = filter_chain_New( p_stream, "video filter2",
256 transcode_video_filter_allocation_init,
257 transcode_video_filter_allocation_clear,
260 if( p_stream->p_sys->b_deinterlace )
262 filter_chain_AppendFilter( id->p_f_chain,
263 p_stream->p_sys->psz_deinterlace,
264 p_stream->p_sys->p_deinterlace_cfg,
265 &id->p_decoder->fmt_out,
266 &id->p_decoder->fmt_out );
269 /* Take care of the scaling and chroma conversions */
270 if( ( id->p_decoder->fmt_out.video.i_chroma !=
271 id->p_encoder->fmt_in.video.i_chroma ) ||
272 ( id->p_decoder->fmt_out.video.i_width !=
273 id->p_encoder->fmt_in.video.i_width ) ||
274 ( id->p_decoder->fmt_out.video.i_height !=
275 id->p_encoder->fmt_in.video.i_height ) )
277 filter_chain_AppendFilter( id->p_f_chain,
279 &id->p_decoder->fmt_out,
280 &id->p_encoder->fmt_in );
283 if( p_stream->p_sys->psz_vf2 )
285 const es_format_t *p_fmt_out;
286 id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
288 transcode_video_filter_allocation_init,
289 transcode_video_filter_allocation_clear,
291 filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
292 &id->p_encoder->fmt_in );
293 filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 );
294 p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
295 es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
296 id->p_encoder->fmt_out.video.i_width =
297 id->p_encoder->fmt_in.video.i_width;
298 id->p_encoder->fmt_out.video.i_height =
299 id->p_encoder->fmt_in.video.i_height;
300 id->p_encoder->fmt_out.video.i_sar_num =
301 id->p_encoder->fmt_in.video.i_sar_num;
302 id->p_encoder->fmt_out.video.i_sar_den =
303 id->p_encoder->fmt_in.video.i_sar_den;
308 static void transcode_video_encoder_init( sout_stream_t *p_stream,
309 sout_stream_id_t *id )
311 sout_stream_sys_t *p_sys = p_stream->p_sys;
314 * width/height of source */
315 int i_src_width = id->p_decoder->fmt_out.video.i_width;
316 int i_src_height = id->p_decoder->fmt_out.video.i_height;
318 /* with/height scaling */
319 float f_scale_width = 1;
320 float f_scale_height = 1;
322 /* width/height of output stream */
327 float f_aspect = (double)id->p_decoder->fmt_out.video.i_sar_num *
328 id->p_decoder->fmt_out.video.i_width /
329 id->p_decoder->fmt_out.video.i_sar_den /
330 id->p_decoder->fmt_out.video.i_height;
332 msg_Dbg( p_stream, "decoder aspect is %f:1", f_aspect );
334 /* Change f_aspect from source frame to source pixel */
335 f_aspect = f_aspect * i_src_height / i_src_width;
336 msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
338 /* Calculate scaling factor for specified parameters */
339 if( id->p_encoder->fmt_out.video.i_width <= 0 &&
340 id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
342 /* Global scaling. Make sure width will remain a factor of 16 */
345 int i_new_width = i_src_width * p_sys->f_scale;
347 if( i_new_width % 16 <= 7 && i_new_width >= 16 )
348 i_new_width -= i_new_width % 16;
350 i_new_width += 16 - i_new_width % 16;
352 f_real_scale = (float)( i_new_width ) / (float) i_src_width;
354 i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
356 f_scale_width = f_real_scale;
357 f_scale_height = (float) i_new_height / (float) i_src_height;
359 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
360 id->p_encoder->fmt_out.video.i_height <= 0 )
362 /* Only width specified */
363 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
364 f_scale_height = f_scale_width;
366 else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
367 id->p_encoder->fmt_out.video.i_height > 0 )
369 /* Only height specified */
370 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
371 f_scale_width = f_scale_height;
373 else if( id->p_encoder->fmt_out.video.i_width > 0 &&
374 id->p_encoder->fmt_out.video.i_height > 0 )
376 /* Width and height specified */
377 f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
378 f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
381 /* check maxwidth and maxheight */
382 if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
385 f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
388 if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
391 f_scale_height = (float)p_sys->i_maxheight / i_src_height;
395 /* Change aspect ratio from source pixel to scaled pixel */
396 f_aspect = f_aspect * f_scale_height / f_scale_width;
397 msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
399 /* f_scale_width and f_scale_height are now final */
400 /* Calculate width, height from scaling
401 * Make sure its multiple of 2
403 i_dst_width = 2 * (int)(f_scale_width*i_src_width/2+0.5);
404 i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5);
406 /* Change aspect ratio from scaled pixel to output frame */
407 f_aspect = f_aspect * i_dst_width / i_dst_height;
409 /* Store calculated values */
410 id->p_encoder->fmt_out.video.i_width =
411 id->p_encoder->fmt_out.video.i_visible_width = i_dst_width;
412 id->p_encoder->fmt_out.video.i_height =
413 id->p_encoder->fmt_out.video.i_visible_height = i_dst_height;
415 id->p_encoder->fmt_in.video.i_width =
416 id->p_encoder->fmt_in.video.i_visible_width = i_dst_width;
417 id->p_encoder->fmt_in.video.i_height =
418 id->p_encoder->fmt_in.video.i_visible_height = i_dst_height;
420 msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
421 i_src_width, i_src_height,
422 i_dst_width, i_dst_height
425 /* Handle frame rate conversion */
426 if( !id->p_encoder->fmt_out.video.i_frame_rate ||
427 !id->p_encoder->fmt_out.video.i_frame_rate_base )
429 if( id->p_decoder->fmt_out.video.i_frame_rate &&
430 id->p_decoder->fmt_out.video.i_frame_rate_base )
432 id->p_encoder->fmt_out.video.i_frame_rate =
433 id->p_decoder->fmt_out.video.i_frame_rate;
434 id->p_encoder->fmt_out.video.i_frame_rate_base =
435 id->p_decoder->fmt_out.video.i_frame_rate_base;
439 /* Pick a sensible default value */
440 id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
441 id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
445 id->p_encoder->fmt_in.video.i_frame_rate =
446 id->p_encoder->fmt_out.video.i_frame_rate;
447 id->p_encoder->fmt_in.video.i_frame_rate_base =
448 id->p_encoder->fmt_out.video.i_frame_rate_base;
450 date_Init( &id->interpolated_pts,
451 id->p_encoder->fmt_out.video.i_frame_rate,
452 id->p_encoder->fmt_out.video.i_frame_rate_base );
454 /* Check whether a particular aspect ratio was requested */
455 if( id->p_encoder->fmt_out.video.i_sar_num <= 0 ||
456 id->p_encoder->fmt_out.video.i_sar_den <= 0 )
458 vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
459 &id->p_encoder->fmt_out.video.i_sar_den,
460 (uint64_t)id->p_decoder->fmt_out.video.i_sar_num * i_src_width * i_dst_height,
461 (uint64_t)id->p_decoder->fmt_out.video.i_sar_den * i_src_height * i_dst_width,
466 vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
467 &id->p_encoder->fmt_out.video.i_sar_den,
468 id->p_encoder->fmt_out.video.i_sar_num,
469 id->p_encoder->fmt_out.video.i_sar_den,
473 id->p_encoder->fmt_in.video.i_sar_num =
474 id->p_encoder->fmt_out.video.i_sar_num;
475 id->p_encoder->fmt_in.video.i_sar_den =
476 id->p_encoder->fmt_out.video.i_sar_den;
478 msg_Dbg( p_stream, "encoder aspect is %i:%i",
479 id->p_encoder->fmt_out.video.i_sar_num * id->p_encoder->fmt_out.video.i_width,
480 id->p_encoder->fmt_out.video.i_sar_den * id->p_encoder->fmt_out.video.i_height );
482 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
485 static int transcode_video_encoder_open( sout_stream_t *p_stream,
486 sout_stream_id_t *id )
488 sout_stream_sys_t *p_sys = p_stream->p_sys;
491 msg_Dbg( p_stream, "destination (after video filters) %ix%i",
492 id->p_encoder->fmt_in.video.i_width,
493 id->p_encoder->fmt_in.video.i_height );
495 id->p_encoder->p_module =
496 module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
497 if( !id->p_encoder->p_module )
499 msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
500 p_sys->psz_venc ? p_sys->psz_venc : "any",
501 (char *)&p_sys->i_vcodec );
505 id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
508 id->p_encoder->fmt_out.i_codec =
509 vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
511 id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
514 msg_Err( p_stream, "cannot add this stream" );
521 void transcode_video_close( sout_stream_t *p_stream,
522 sout_stream_id_t *id )
524 if( p_stream->p_sys->i_threads >= 1 )
526 vlc_mutex_lock( &p_stream->p_sys->lock_out );
527 p_stream->p_sys->b_abort = true;
528 vlc_cond_signal( &p_stream->p_sys->cond );
529 vlc_mutex_unlock( &p_stream->p_sys->lock_out );
531 vlc_join( p_stream->p_sys->thread, NULL );
532 vlc_mutex_destroy( &p_stream->p_sys->lock_out );
533 vlc_cond_destroy( &p_stream->p_sys->cond );
535 picture_fifo_Delete( p_stream->p_sys->pp_pics );
536 p_stream->p_sys->pp_pics = NULL;
540 if( id->p_decoder->p_module )
541 module_unneed( id->p_decoder, id->p_decoder->p_module );
542 if( id->p_decoder->p_description )
543 vlc_meta_Delete( id->p_decoder->p_description );
545 free( id->p_decoder->p_owner );
548 if( id->p_encoder->p_module )
549 module_unneed( id->p_encoder, id->p_encoder->p_module );
553 filter_chain_Delete( id->p_f_chain );
555 filter_chain_Delete( id->p_uf_chain );
558 int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_t *id,
559 block_t *in, block_t **out )
561 sout_stream_sys_t *p_sys = p_stream->p_sys;
562 bool b_need_duplicate = false;
563 picture_t *p_pic, *p_pic2 = NULL;
566 if( unlikely( in == NULL ) )
568 if( p_sys->i_threads == 0 )
572 p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
573 block_ChainAppend( out, p_block );
579 * FIXME: we need EncoderThread() to flush buffers and signal us
580 * when it's done so we can send the last frames to the chain
587 while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
590 if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
592 mtime_t current_date = mdate();
593 if( unlikely( current_date + 50000 > p_pic->date ) )
595 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
596 current_date + 50000 - p_pic->date );
597 picture_Release( p_pic );
602 if( p_sys->b_master_sync )
604 mtime_t i_master_drift = p_sys->i_master_drift;
605 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
606 mtime_t i_video_drift = p_pic->date - i_pts;
608 if ( unlikely( i_video_drift > MASTER_SYNC_MAX_DRIFT
609 || i_video_drift < -MASTER_SYNC_MAX_DRIFT ) )
612 "drift is too high (%"PRId64", resetting master sync",
614 date_Set( &id->interpolated_pts, p_pic->date );
615 i_pts = p_pic->date + 1;
617 i_video_drift = p_pic->date - i_pts;
618 b_need_duplicate = false;
620 /* Set the pts of the frame being encoded */
623 if( unlikely( i_video_drift < (i_master_drift - 50000) ) )
626 msg_Dbg( p_stream, "dropping frame (%i)",
627 (int)(i_video_drift - i_master_drift) );
629 picture_Release( p_pic );
632 else if( unlikely( i_video_drift > (i_master_drift + 50000) ) )
635 msg_Dbg( p_stream, "adding frame (%i)",
636 (int)(i_video_drift - i_master_drift) );
638 b_need_duplicate = true;
642 if( unlikely( !id->p_encoder->p_module ) )
644 transcode_video_encoder_init( p_stream, id );
646 transcode_video_filter_init( p_stream, id );
648 if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
650 picture_Release( p_pic );
651 transcode_video_close( p_stream, id );
652 id->b_transcode = false;
657 /* Run filter chain */
659 p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
663 /* Run user specified filter chain */
665 p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
673 /* Check if we have a subpicture to overlay */
676 video_format_t fmt = id->p_encoder->fmt_in.video;
677 if( fmt.i_visible_width <= 0 || fmt.i_visible_height <= 0 )
679 fmt.i_visible_width = fmt.i_width;
680 fmt.i_visible_height = fmt.i_height;
685 subpicture_t *p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt,
686 p_pic->date, p_pic->date, false );
688 /* Overlay subpicture */
691 if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
693 /* We can't modify the picture, we need to duplicate it */
694 picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
695 if( likely( p_tmp ) )
697 picture_Copy( p_tmp, p_pic );
698 picture_Release( p_pic );
702 if( unlikely( !p_sys->p_spu_blend ) )
703 p_sys->p_spu_blend = filter_NewBlend( VLC_OBJECT( p_sys->p_spu ), &fmt );
704 if( likely( p_sys->p_spu_blend ) )
705 picture_BlendSubpicture( p_pic, p_sys->p_spu_blend, p_subpic );
706 subpicture_Delete( p_subpic );
710 if( p_sys->i_threads == 0 )
714 p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
715 block_ChainAppend( out, p_block );
718 if( p_sys->b_master_sync )
720 mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
721 mtime_t i_video_drift = p_pic->date - i_pts;
722 if (unlikely ( i_video_drift > MASTER_SYNC_MAX_DRIFT
723 || i_video_drift < -MASTER_SYNC_MAX_DRIFT ) )
726 "drift is too high (%"PRId64"), resetting master sync",
728 date_Set( &id->interpolated_pts, p_pic->date );
729 i_pts = p_pic->date + 1;
731 date_Increment( &id->interpolated_pts, 1 );
733 if( unlikely( b_need_duplicate ) )
736 if( p_sys->i_threads >= 1 )
738 /* We can't modify the picture, we need to duplicate it */
739 p_pic2 = video_new_buffer_decoder( id->p_decoder );
740 if( likely( p_pic2 != NULL ) )
742 picture_Copy( p_pic2, p_pic );
743 p_pic2->date = i_pts;
750 p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
751 block_ChainAppend( out, p_block );
756 if( p_sys->i_threads == 0 )
758 picture_Release( p_pic );
762 vlc_mutex_lock( &p_sys->lock_out );
763 picture_fifo_Push( p_sys->pp_pics, p_pic );
764 *out = p_sys->p_buffers;
765 p_sys->p_buffers = NULL;
768 picture_fifo_Push( p_sys->pp_pics, p_pic2 );
770 vlc_cond_signal( &p_sys->cond );
771 vlc_mutex_unlock( &p_sys->lock_out );
778 bool transcode_video_add( sout_stream_t *p_stream, es_format_t *p_fmt,
779 sout_stream_id_t *id )
781 sout_stream_sys_t *p_sys = p_stream->p_sys;
784 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
785 (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
787 /* Complete destination format */
788 id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
789 id->p_encoder->fmt_out.video.i_width = p_sys->i_width & ~1;
790 id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
791 id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
793 /* Build decoder -> filter -> encoder chain */
794 if( transcode_video_new( p_stream, id ) )
796 msg_Err( p_stream, "cannot create video chain" );
800 /* Stream will be added later on because we don't know
801 * all the characteristics of the decoded stream yet */
802 id->b_transcode = true;
804 if( p_sys->f_fps > 0 )
806 id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->f_fps * ENC_FRAMERATE_BASE) + 0.5;
807 id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;