]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode/video.c
Fixed potential NULL dereference when using video filter when transcoding.
[vlc] / modules / stream_out / transcode / video.c
1 /*****************************************************************************
2  * video.c: transcoding stream output module (video)
3  *****************************************************************************
4  * Copyright (C) 2003-2009 the VideoLAN team
5  * $Id$
6  *
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>
11  *
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.
16  *
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.
21  *
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  *****************************************************************************/
26
27 /*****************************************************************************
28  * Preamble
29  *****************************************************************************/
30
31 #include "transcode.h"
32
33 #include <vlc_meta.h>
34 #include <vlc_spu.h>
35 #include <vlc_modules.h>
36
37 #define ENC_FRAMERATE (25 * 1000 + .5)
38 #define ENC_FRAMERATE_BASE 1000
39
40 struct decoder_owner_sys_t
41 {
42     sout_stream_sys_t *p_sys;
43 };
44
45 static void video_del_buffer_decoder( decoder_t *p_decoder, picture_t *p_pic )
46 {
47     VLC_UNUSED(p_decoder);
48     picture_Release( p_pic );
49 }
50
51 static void video_link_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
52 {
53     VLC_UNUSED(p_dec);
54     picture_Hold( p_pic );
55 }
56
57 static void video_unlink_picture_decoder( decoder_t *p_dec, picture_t *p_pic )
58 {
59     VLC_UNUSED(p_dec);
60     picture_Release( p_pic );
61 }
62
63 static picture_t *video_new_buffer_decoder( decoder_t *p_dec )
64 {
65     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
66     return picture_NewFromFormat( &p_dec->fmt_out.video );
67 }
68
69 static picture_t *transcode_video_filter_buffer_new( filter_t *p_filter )
70 {
71     p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
72     return picture_NewFromFormat( &p_filter->fmt_out.video );
73 }
74 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
75 {
76     VLC_UNUSED(p_filter);
77     picture_Release( p_pic );
78 }
79
80 static int transcode_video_filter_allocation_init( filter_t *p_filter,
81                                                    void *p_data )
82 {
83     VLC_UNUSED(p_data);
84     p_filter->pf_video_buffer_new = transcode_video_filter_buffer_new;
85     p_filter->pf_video_buffer_del = transcode_video_filter_buffer_del;
86     return VLC_SUCCESS;
87 }
88
89 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
90 {
91     VLC_UNUSED(p_filter);
92 }
93
94 static void* EncoderThread( void *obj )
95 {
96     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
97     sout_stream_id_t *id = p_sys->id_video;
98     picture_t *p_pic;
99     int canc = vlc_savecancel ();
100
101     for( ;; )
102     {
103         block_t *p_block;
104
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 );
109
110         if( p_sys->b_abort )
111         {
112             vlc_mutex_unlock( &p_sys->lock_out );
113             break;
114         }
115         vlc_mutex_unlock( &p_sys->lock_out );
116
117         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
118
119         vlc_mutex_lock( &p_sys->lock_out );
120         block_ChainAppend( &p_sys->p_buffers, p_block );
121
122         vlc_mutex_unlock( &p_sys->lock_out );
123         picture_Release( p_pic );
124     }
125
126     block_ChainRelease( p_sys->p_buffers );
127
128     vlc_restorecancel (canc);
129     return NULL;
130 }
131
132 int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
133 {
134     sout_stream_sys_t *p_sys = p_stream->p_sys;
135
136     /* Open decoder
137      * Initialization of decoder structures
138      */
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 )
151         return VLC_EGENERIC;
152
153     id->p_decoder->p_owner->p_sys = p_sys;
154     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
155
156     id->p_decoder->p_module =
157         module_need( id->p_decoder, "decoder", "$codec", false );
158
159     if( !id->p_decoder->p_module )
160     {
161         msg_Err( p_stream, "cannot find video decoder" );
162         free( id->p_decoder->p_owner );
163         return VLC_EGENERIC;
164     }
165
166     /*
167      * Open encoder.
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.
171      */
172
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;
177
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;
192
193     id->p_encoder->i_threads = p_sys->i_threads;
194     id->p_encoder->p_cfg = p_sys->p_video_cfg;
195
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 )
199     {
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 );
206         return VLC_EGENERIC;
207     }
208
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 )
213     {
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;
217     }
218     id->p_encoder->p_module = NULL;
219
220     if( p_sys->i_threads >= 1 )
221     {
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 )
229         {
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 );
234             return VLC_ENOMEM;
235         }
236         p_sys->p_buffers = NULL;
237         p_sys->b_abort = false;
238         if( vlc_clone( &p_sys->thread, EncoderThread, p_sys, i_priority ) )
239         {
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 );
244             return VLC_EGENERIC;
245         }
246     }
247     return VLC_SUCCESS;
248 }
249
250 static void transcode_video_filter_init( sout_stream_t *p_stream,
251                                          sout_stream_id_t *id )
252 {
253
254     id->p_f_chain = filter_chain_New( p_stream, "video filter2",
255                                      false,
256                                      transcode_video_filter_allocation_init,
257                                      transcode_video_filter_allocation_clear,
258                                      p_stream->p_sys );
259     /* Deinterlace */
260     if( p_stream->p_sys->b_deinterlace )
261     {
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 );
267     }
268
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 ) )
276     {
277        filter_chain_AppendFilter( id->p_f_chain,
278                                   NULL, NULL,
279                                   &id->p_decoder->fmt_out,
280                                   &id->p_encoder->fmt_in );
281     }
282
283     if( p_stream->p_sys->psz_vf2 )
284     {
285         const es_format_t *p_fmt_out;
286         id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
287                                           true,
288                            transcode_video_filter_allocation_init,
289                            transcode_video_filter_allocation_clear,
290                            p_stream->p_sys );
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;
304     }
305
306 }
307
308 static void transcode_video_encoder_init( sout_stream_t *p_stream,
309                                           sout_stream_id_t *id )
310 {
311     sout_stream_sys_t *p_sys = p_stream->p_sys;
312
313     /* Calculate scaling
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;
317
318     /* with/height scaling */
319     float f_scale_width = 1;
320     float f_scale_height = 1;
321
322     /* width/height of output stream */
323     int i_dst_width;
324     int i_dst_height;
325
326     /* aspect ratio */
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;
331
332     msg_Dbg( p_stream, "decoder aspect is %f:1", f_aspect );
333
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 );
337
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 )
341     {
342         /* Global scaling. Make sure width will remain a factor of 16 */
343         float f_real_scale;
344         int  i_new_height;
345         int i_new_width = i_src_width * p_sys->f_scale;
346
347         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
348             i_new_width -= i_new_width % 16;
349         else
350             i_new_width += 16 - i_new_width % 16;
351
352         f_real_scale = (float)( i_new_width ) / (float) i_src_width;
353
354         i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
355
356         f_scale_width = f_real_scale;
357         f_scale_height = (float) i_new_height / (float) i_src_height;
358     }
359     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
360              id->p_encoder->fmt_out.video.i_height <= 0 )
361     {
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;
365     }
366     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
367              id->p_encoder->fmt_out.video.i_height > 0 )
368     {
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;
372      }
373      else if( id->p_encoder->fmt_out.video.i_width > 0 &&
374               id->p_encoder->fmt_out.video.i_height > 0 )
375      {
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;
379      }
380
381      /* check maxwidth and maxheight */
382      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
383                                                      i_src_width )
384      {
385          f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
386      }
387
388      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
389                                                        i_src_height )
390      {
391          f_scale_height = (float)p_sys->i_maxheight / i_src_height;
392      }
393
394
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 );
398
399      /* f_scale_width and f_scale_height are now final */
400      /* Calculate width, height from scaling
401       * Make sure its multiple of 2
402       */
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);
405
406      /* Change aspect ratio from scaled pixel to output frame */
407      f_aspect = f_aspect * i_dst_width / i_dst_height;
408
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;
414
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;
419
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
423      );
424
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 )
428     {
429         if( id->p_decoder->fmt_out.video.i_frame_rate &&
430             id->p_decoder->fmt_out.video.i_frame_rate_base )
431         {
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;
436         }
437         else
438         {
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;
442         }
443     }
444
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;
449
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 );
453
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 )
457     {
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,
462                      0 );
463     }
464     else
465     {
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,
470                      0 );
471     }
472
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;
477
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 );
481
482     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
483 }
484
485 static int transcode_video_encoder_open( sout_stream_t *p_stream,
486                                          sout_stream_id_t *id )
487 {
488     sout_stream_sys_t *p_sys = p_stream->p_sys;
489
490
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 );
494
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 )
498     {
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 );
502         return VLC_EGENERIC;
503     }
504
505     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
506
507     /*  */
508     id->p_encoder->fmt_out.i_codec =
509         vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
510
511     id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
512     if( !id->id )
513     {
514         msg_Err( p_stream, "cannot add this stream" );
515         return VLC_EGENERIC;
516     }
517
518     return VLC_SUCCESS;
519 }
520
521 void transcode_video_close( sout_stream_t *p_stream,
522                                    sout_stream_id_t *id )
523 {
524     if( p_stream->p_sys->i_threads >= 1 )
525     {
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 );
530
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 );
534
535         picture_fifo_Delete( p_stream->p_sys->pp_pics );
536         p_stream->p_sys->pp_pics = NULL;
537     }
538
539     /* Close decoder */
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 );
544
545     free( id->p_decoder->p_owner );
546
547     /* Close encoder */
548     if( id->p_encoder->p_module )
549         module_unneed( id->p_encoder, id->p_encoder->p_module );
550
551     /* Close filters */
552     if( id->p_f_chain )
553         filter_chain_Delete( id->p_f_chain );
554     if( id->p_uf_chain )
555         filter_chain_Delete( id->p_uf_chain );
556 }
557
558 int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_t *id,
559                                     block_t *in, block_t **out )
560 {
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;
564     *out = NULL;
565
566     if( unlikely( in == NULL ) )
567     {
568         if( p_sys->i_threads == 0 )
569         {
570             block_t *p_block;
571             do {
572                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
573                 block_ChainAppend( out, p_block );
574             } while( p_block );
575         }
576         else
577         {
578             /*
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
581              */
582         }
583         return VLC_SUCCESS;
584     }
585
586
587     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
588     {
589
590         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
591         {
592             mtime_t current_date = mdate();
593             if( unlikely( current_date + 50000 > p_pic->date ) )
594             {
595                 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
596                          current_date + 50000 - p_pic->date );
597                 picture_Release( p_pic );
598                 continue;
599             }
600         }
601
602         if( p_sys->b_master_sync )
603         {
604             mtime_t i_video_drift;
605             mtime_t i_master_drift = p_sys->i_master_drift;
606             mtime_t i_pts;
607
608             i_pts = date_Get( &id->interpolated_pts ) + 1;
609             if ( unlikely( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
610                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT ) )
611             {
612                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
613                 date_Set( &id->interpolated_pts, p_pic->date );
614                 i_pts = p_pic->date + 1;
615             }
616             i_video_drift = p_pic->date - i_pts;
617             b_need_duplicate = false;
618
619             /* Set the pts of the frame being encoded */
620             p_pic->date = i_pts;
621
622             if( unlikely( i_video_drift < (i_master_drift - 50000) ) )
623             {
624 #if 0
625                 msg_Dbg( p_stream, "dropping frame (%i)",
626                          (int)(i_video_drift - i_master_drift) );
627 #endif
628                 picture_Release( p_pic );
629                 continue;
630             }
631             else if( unlikely( i_video_drift > (i_master_drift + 50000) ) )
632             {
633 #if 0
634                 msg_Dbg( p_stream, "adding frame (%i)",
635                          (int)(i_video_drift - i_master_drift) );
636 #endif
637                 b_need_duplicate = true;
638             }
639         }
640
641         if( unlikely( !id->p_encoder->p_module ) )
642         {
643             transcode_video_encoder_init( p_stream, id );
644
645             transcode_video_filter_init( p_stream, id );
646
647             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
648             {
649                 picture_Release( p_pic );
650                 transcode_video_close( p_stream, id );
651                 id->b_transcode = false;
652                 return VLC_EGENERIC;
653             }
654         }
655
656         /* Run filter chain */
657         if( id->p_f_chain )
658             p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
659         if( !p_pic )
660             continue;
661
662         /* Run user specified filter chain */
663         if( id->p_uf_chain )
664             p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
665         if( !p_pic )
666             continue;
667
668         /*
669          * Encoding
670          */
671
672         /* Check if we have a subpicture to overlay */
673         if( p_sys->p_spu )
674         {
675             video_format_t fmt = id->p_encoder->fmt_in.video;
676             if( fmt.i_visible_width <= 0 || fmt.i_visible_height <= 0 )
677             {
678                 fmt.i_visible_width  = fmt.i_width;
679                 fmt.i_visible_height = fmt.i_height;
680                 fmt.i_x_offset       = 0;
681                 fmt.i_y_offset       = 0;
682             }
683
684             subpicture_t *p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt,
685                                                  p_pic->date, p_pic->date, false );
686
687             /* Overlay subpicture */
688             if( p_subpic )
689             {
690                 if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
691                 {
692                     /* We can't modify the picture, we need to duplicate it */
693                     picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
694                     if( likely( p_tmp ) )
695                     {
696                         picture_Copy( p_tmp, p_pic );
697                         picture_Release( p_pic );
698                         p_pic = p_tmp;
699                     }
700                 }
701                 if( unlikely( !p_sys->p_spu_blend ) )
702                     p_sys->p_spu_blend = filter_NewBlend( VLC_OBJECT( p_sys->p_spu ), &fmt );
703                 if( likely( p_sys->p_spu_blend ) )
704                     picture_BlendSubpicture( p_pic, p_sys->p_spu_blend, p_subpic );
705                 subpicture_Delete( p_subpic );
706             }
707         }
708
709         if( p_sys->i_threads == 0 )
710         {
711             block_t *p_block;
712
713             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
714             block_ChainAppend( out, p_block );
715         }
716
717         if( p_sys->b_master_sync )
718         {
719             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
720             if (unlikely ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
721                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT ) )
722             {
723                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
724                 date_Set( &id->interpolated_pts, p_pic->date );
725                 i_pts = p_pic->date + 1;
726             }
727             date_Increment( &id->interpolated_pts, 1 );
728
729             if( unlikely( b_need_duplicate ) )
730             {
731
732                if( p_sys->i_threads >= 1 )
733                {
734                    /* We can't modify the picture, we need to duplicate it */
735                    p_pic2 = video_new_buffer_decoder( id->p_decoder );
736                    if( likely( p_pic2 != NULL ) )
737                    {
738                        picture_Copy( p_pic2, p_pic );
739                        p_pic2->date = i_pts;
740                    }
741                }
742                else
743                {
744                    block_t *p_block;
745                    p_pic->date = i_pts;
746                    p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
747                    block_ChainAppend( out, p_block );
748                }
749            }
750         }
751
752         if( p_sys->i_threads == 0 )
753         {
754             picture_Release( p_pic );
755         }
756         else
757         {
758             vlc_mutex_lock( &p_sys->lock_out );
759             picture_fifo_Push( p_sys->pp_pics, p_pic );
760             *out = p_sys->p_buffers;
761             p_sys->p_buffers = NULL;
762             if( p_pic2 != NULL )
763             {
764                 picture_fifo_Push( p_sys->pp_pics, p_pic2 );
765             }
766             vlc_cond_signal( &p_sys->cond );
767             vlc_mutex_unlock( &p_sys->lock_out );
768         }
769     }
770
771     return VLC_SUCCESS;
772 }
773
774 bool transcode_video_add( sout_stream_t *p_stream, es_format_t *p_fmt,
775                                 sout_stream_id_t *id )
776 {
777     sout_stream_sys_t *p_sys = p_stream->p_sys;
778
779     msg_Dbg( p_stream,
780              "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
781              (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
782
783     /* Complete destination format */
784     id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
785     id->p_encoder->fmt_out.video.i_width  = p_sys->i_width & ~1;
786     id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
787     id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
788
789     /* Build decoder -> filter -> encoder chain */
790     if( transcode_video_new( p_stream, id ) )
791     {
792         msg_Err( p_stream, "cannot create video chain" );
793         return false;
794     }
795
796     /* Stream will be added later on because we don't know
797      * all the characteristics of the decoded stream yet */
798     id->b_transcode = true;
799
800     if( p_sys->f_fps > 0 )
801     {
802         id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->f_fps * ENC_FRAMERATE_BASE) + 0.5;
803         id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
804     }
805
806     return true;
807 }
808