]> git.sesse.net Git - vlc/blob - modules/stream_out/transcode/video.c
Avoid potential integer overflow when computing AR 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     sout_stream_sys_t *p_ssys = p_dec->p_owner->p_sys;
66     if( p_ssys->i_threads >= 1 )
67     {
68         int i_first_pic = p_ssys->i_first_pic;
69
70         if( p_ssys->i_first_pic != p_ssys->i_last_pic )
71         {
72             /* Encoder still has stuff to encode, wait to clear-up the list */
73             while( p_ssys->i_first_pic == i_first_pic )
74             {
75 #warning THERE IS DEFINITELY A BUG! LOCKING IS INSUFFICIENT!
76                 msleep( 10000 );
77                 barrier ();
78             }
79         }
80     }
81
82     p_dec->fmt_out.video.i_chroma = p_dec->fmt_out.i_codec;
83     return picture_NewFromFormat( &p_dec->fmt_out.video );
84 }
85
86 static picture_t *transcode_video_filter_buffer_new( filter_t *p_filter )
87 {
88     p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
89     return picture_NewFromFormat( &p_filter->fmt_out.video );
90 }
91 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
92 {
93     VLC_UNUSED(p_filter);
94     picture_Release( p_pic );
95 }
96
97 static int transcode_video_filter_allocation_init( filter_t *p_filter,
98                                                    void *p_data )
99 {
100     VLC_UNUSED(p_data);
101     p_filter->pf_video_buffer_new = transcode_video_filter_buffer_new;
102     p_filter->pf_video_buffer_del = transcode_video_filter_buffer_del;
103     return VLC_SUCCESS;
104 }
105
106 static void transcode_video_filter_allocation_clear( filter_t *p_filter )
107 {
108     VLC_UNUSED(p_filter);
109 }
110
111 static void* EncoderThread( void *obj )
112 {
113     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
114     sout_stream_id_t *id = p_sys->id_video;
115     picture_t *p_pic;
116     int canc = vlc_savecancel ();
117
118     for( ;; )
119     {
120         block_t *p_block;
121
122         vlc_mutex_lock( &p_sys->lock_out );
123         while( !p_sys->b_abort && p_sys->i_last_pic == p_sys->i_first_pic )
124             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
125
126         if( p_sys->b_abort )
127         {
128             vlc_mutex_unlock( &p_sys->lock_out );
129             break;
130         }
131
132         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
133         p_sys->i_first_pic %= PICTURE_RING_SIZE;
134         vlc_mutex_unlock( &p_sys->lock_out );
135
136         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
137
138         vlc_mutex_lock( &p_sys->lock_out );
139         block_ChainAppend( &p_sys->p_buffers, p_block );
140
141         vlc_mutex_unlock( &p_sys->lock_out );
142         picture_Release( p_pic );
143     }
144
145     while( p_sys->i_last_pic != p_sys->i_first_pic )
146     {
147         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
148         p_sys->i_first_pic %= PICTURE_RING_SIZE;
149         picture_Release( p_pic );
150     }
151     block_ChainRelease( p_sys->p_buffers );
152
153     vlc_restorecancel (canc);
154     return NULL;
155 }
156
157 int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_t *id )
158 {
159     sout_stream_sys_t *p_sys = p_stream->p_sys;
160
161     /* Open decoder
162      * Initialization of decoder structures
163      */
164     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
165     id->p_decoder->fmt_out.i_extra = 0;
166     id->p_decoder->fmt_out.p_extra = 0;
167     id->p_decoder->pf_decode_video = NULL;
168     id->p_decoder->pf_get_cc = NULL;
169     id->p_decoder->pf_get_cc = 0;
170     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
171     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
172     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
173     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
174     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
175     if( !id->p_decoder->p_owner )
176         return VLC_EGENERIC;
177
178     id->p_decoder->p_owner->p_sys = p_sys;
179     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
180
181     id->p_decoder->p_module =
182         module_need( id->p_decoder, "decoder", "$codec", false );
183
184     if( !id->p_decoder->p_module )
185     {
186         msg_Err( p_stream, "cannot find video decoder" );
187         free( id->p_decoder->p_owner );
188         return VLC_EGENERIC;
189     }
190
191     /*
192      * Open encoder.
193      * Because some info about the decoded input will only be available
194      * once the first frame is decoded, we actually only test the availability
195      * of the encoder here.
196      */
197
198     /* Initialization of encoder format structures */
199     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
200                     id->p_decoder->fmt_out.i_codec );
201     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
202
203     /* The dimensions will be set properly later on.
204      * Just put sensible values so we can test an encoder is available. */
205     id->p_encoder->fmt_in.video.i_width =
206         id->p_encoder->fmt_out.video.i_width
207           ? id->p_encoder->fmt_out.video.i_width
208           : id->p_decoder->fmt_in.video.i_width
209             ? id->p_decoder->fmt_in.video.i_width : 16;
210     id->p_encoder->fmt_in.video.i_height =
211         id->p_encoder->fmt_out.video.i_height
212           ? id->p_encoder->fmt_out.video.i_height
213           : id->p_decoder->fmt_in.video.i_height
214             ? id->p_decoder->fmt_in.video.i_height : 16;
215     id->p_encoder->fmt_in.video.i_frame_rate = ENC_FRAMERATE;
216     id->p_encoder->fmt_in.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
217
218     id->p_encoder->i_threads = p_sys->i_threads;
219     id->p_encoder->p_cfg = p_sys->p_video_cfg;
220
221     id->p_encoder->p_module =
222         module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
223     if( !id->p_encoder->p_module )
224     {
225         msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
226                  p_sys->psz_venc ? p_sys->psz_venc : "any",
227                  (char *)&p_sys->i_vcodec );
228         module_unneed( id->p_decoder, id->p_decoder->p_module );
229         id->p_decoder->p_module = 0;
230         free( id->p_decoder->p_owner );
231         return VLC_EGENERIC;
232     }
233
234     /* Close the encoder.
235      * We'll open it only when we have the first frame. */
236     module_unneed( id->p_encoder, id->p_encoder->p_module );
237     if( id->p_encoder->fmt_out.p_extra )
238     {
239         free( id->p_encoder->fmt_out.p_extra );
240         id->p_encoder->fmt_out.p_extra = NULL;
241         id->p_encoder->fmt_out.i_extra = 0;
242     }
243     id->p_encoder->p_module = NULL;
244
245     if( p_sys->i_threads >= 1 )
246     {
247         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
248                            VLC_THREAD_PRIORITY_VIDEO;
249         p_sys->id_video = id;
250         vlc_mutex_init( &p_sys->lock_out );
251         vlc_cond_init( &p_sys->cond );
252         memset( p_sys->pp_pics, 0, sizeof(p_sys->pp_pics) );
253         p_sys->i_first_pic = 0;
254         p_sys->i_last_pic = 0;
255         p_sys->p_buffers = NULL;
256         p_sys->b_abort = 0;
257         if( vlc_clone( &p_sys->thread, EncoderThread, p_sys, i_priority ) )
258         {
259             msg_Err( p_stream, "cannot spawn encoder thread" );
260             module_unneed( id->p_decoder, id->p_decoder->p_module );
261             id->p_decoder->p_module = 0;
262             free( id->p_decoder->p_owner );
263             return VLC_EGENERIC;
264         }
265     }
266     return VLC_SUCCESS;
267 }
268
269 static void transcode_video_filter_init( sout_stream_t *p_stream,
270                                          sout_stream_id_t *id )
271 {
272
273     id->p_f_chain = filter_chain_New( p_stream, "video filter2",
274                                      false,
275                                      transcode_video_filter_allocation_init,
276                                      transcode_video_filter_allocation_clear,
277                                      p_stream->p_sys );
278     /* Deinterlace */
279     if( p_stream->p_sys->b_deinterlace )
280     {
281        filter_chain_AppendFilter( id->p_f_chain,
282                                   p_stream->p_sys->psz_deinterlace,
283                                   p_stream->p_sys->p_deinterlace_cfg,
284                                   &id->p_decoder->fmt_out,
285                                   &id->p_decoder->fmt_out );
286     }
287
288     /* Take care of the scaling and chroma conversions */
289     if( ( id->p_decoder->fmt_out.video.i_chroma !=
290           id->p_encoder->fmt_in.video.i_chroma ) ||
291         ( id->p_decoder->fmt_out.video.i_width !=
292           id->p_encoder->fmt_in.video.i_width ) ||
293         ( id->p_decoder->fmt_out.video.i_height !=
294           id->p_encoder->fmt_in.video.i_height ) )
295     {
296        filter_chain_AppendFilter( id->p_f_chain,
297                                   NULL, NULL,
298                                   &id->p_decoder->fmt_out,
299                                   &id->p_encoder->fmt_in );
300     }
301
302     if( p_stream->p_sys->psz_vf2 )
303     {
304         const es_format_t *p_fmt_out;
305         id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
306                                           true,
307                            transcode_video_filter_allocation_init,
308                            transcode_video_filter_allocation_clear,
309                            p_stream->p_sys );
310         filter_chain_Reset( id->p_uf_chain, &id->p_encoder->fmt_in,
311                             &id->p_encoder->fmt_in );
312         filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 );
313         p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
314         es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
315         id->p_encoder->fmt_out.video.i_width =
316             id->p_encoder->fmt_in.video.i_width;
317         id->p_encoder->fmt_out.video.i_height =
318             id->p_encoder->fmt_in.video.i_height;
319         id->p_encoder->fmt_out.video.i_sar_num =
320             id->p_encoder->fmt_in.video.i_sar_num;
321         id->p_encoder->fmt_out.video.i_sar_den =
322             id->p_encoder->fmt_in.video.i_sar_den;
323     }
324
325 }
326
327 static void transcode_video_encoder_init( sout_stream_t *p_stream,
328                                           sout_stream_id_t *id )
329 {
330     sout_stream_sys_t *p_sys = p_stream->p_sys;
331
332     /* Calculate scaling
333      * width/height of source */
334     int i_src_width = id->p_decoder->fmt_out.video.i_width;
335     int i_src_height = id->p_decoder->fmt_out.video.i_height;
336
337     /* with/height scaling */
338     float f_scale_width = 1;
339     float f_scale_height = 1;
340
341     /* width/height of output stream */
342     int i_dst_width;
343     int i_dst_height;
344
345     /* aspect ratio */
346     float f_aspect = (double)id->p_decoder->fmt_out.video.i_sar_num *
347                      id->p_decoder->fmt_out.video.i_width /
348                      id->p_decoder->fmt_out.video.i_sar_den /
349                      id->p_decoder->fmt_out.video.i_height;
350
351     msg_Dbg( p_stream, "decoder aspect is %f:1", f_aspect );
352
353     /* Change f_aspect from source frame to source pixel */
354     f_aspect = f_aspect * i_src_height / i_src_width;
355     msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
356
357     /* Calculate scaling factor for specified parameters */
358     if( id->p_encoder->fmt_out.video.i_width <= 0 &&
359         id->p_encoder->fmt_out.video.i_height <= 0 && p_sys->f_scale )
360     {
361         /* Global scaling. Make sure width will remain a factor of 16 */
362         float f_real_scale;
363         int  i_new_height;
364         int i_new_width = i_src_width * p_sys->f_scale;
365
366         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
367             i_new_width -= i_new_width % 16;
368         else
369             i_new_width += 16 - i_new_width % 16;
370
371         f_real_scale = (float)( i_new_width ) / (float) i_src_width;
372
373         i_new_height = __MAX( 16, i_src_height * (float)f_real_scale );
374
375         f_scale_width = f_real_scale;
376         f_scale_height = (float) i_new_height / (float) i_src_height;
377     }
378     else if( id->p_encoder->fmt_out.video.i_width > 0 &&
379              id->p_encoder->fmt_out.video.i_height <= 0 )
380     {
381         /* Only width specified */
382         f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
383         f_scale_height = f_scale_width;
384     }
385     else if( id->p_encoder->fmt_out.video.i_width <= 0 &&
386              id->p_encoder->fmt_out.video.i_height > 0 )
387     {
388          /* Only height specified */
389          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
390          f_scale_width = f_scale_height;
391      }
392      else if( id->p_encoder->fmt_out.video.i_width > 0 &&
393               id->p_encoder->fmt_out.video.i_height > 0 )
394      {
395          /* Width and height specified */
396          f_scale_width = (float)id->p_encoder->fmt_out.video.i_width/i_src_width;
397          f_scale_height = (float)id->p_encoder->fmt_out.video.i_height/i_src_height;
398      }
399
400      /* check maxwidth and maxheight */
401      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
402                                                      i_src_width )
403      {
404          f_scale_width = (float)p_sys->i_maxwidth / i_src_width;
405      }
406
407      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
408                                                        i_src_height )
409      {
410          f_scale_height = (float)p_sys->i_maxheight / i_src_height;
411      }
412
413
414      /* Change aspect ratio from source pixel to scaled pixel */
415      f_aspect = f_aspect * f_scale_height / f_scale_width;
416      msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
417
418      /* f_scale_width and f_scale_height are now final */
419      /* Calculate width, height from scaling
420       * Make sure its multiple of 2
421       */
422      i_dst_width =  2 * (int)(f_scale_width*i_src_width/2+0.5);
423      i_dst_height = 2 * (int)(f_scale_height*i_src_height/2+0.5);
424
425      /* Change aspect ratio from scaled pixel to output frame */
426      f_aspect = f_aspect * i_dst_width / i_dst_height;
427
428      /* Store calculated values */
429      id->p_encoder->fmt_out.video.i_width =
430      id->p_encoder->fmt_out.video.i_visible_width = i_dst_width;
431      id->p_encoder->fmt_out.video.i_height =
432      id->p_encoder->fmt_out.video.i_visible_height = i_dst_height;
433
434      id->p_encoder->fmt_in.video.i_width =
435      id->p_encoder->fmt_in.video.i_visible_width = i_dst_width;
436      id->p_encoder->fmt_in.video.i_height =
437      id->p_encoder->fmt_in.video.i_visible_height = i_dst_height;
438
439      msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
440          i_src_width, i_src_height,
441          i_dst_width, i_dst_height
442      );
443
444     /* Handle frame rate conversion */
445     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
446         !id->p_encoder->fmt_out.video.i_frame_rate_base )
447     {
448         if( id->p_decoder->fmt_out.video.i_frame_rate &&
449             id->p_decoder->fmt_out.video.i_frame_rate_base )
450         {
451             id->p_encoder->fmt_out.video.i_frame_rate =
452                 id->p_decoder->fmt_out.video.i_frame_rate;
453             id->p_encoder->fmt_out.video.i_frame_rate_base =
454                 id->p_decoder->fmt_out.video.i_frame_rate_base;
455         }
456         else
457         {
458             /* Pick a sensible default value */
459             id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
460             id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
461         }
462     }
463
464     id->p_encoder->fmt_in.video.i_frame_rate =
465         id->p_encoder->fmt_out.video.i_frame_rate;
466     id->p_encoder->fmt_in.video.i_frame_rate_base =
467         id->p_encoder->fmt_out.video.i_frame_rate_base;
468
469     date_Init( &id->interpolated_pts,
470                id->p_encoder->fmt_out.video.i_frame_rate,
471                id->p_encoder->fmt_out.video.i_frame_rate_base );
472
473     /* Check whether a particular aspect ratio was requested */
474     if( id->p_encoder->fmt_out.video.i_sar_num <= 0 ||
475         id->p_encoder->fmt_out.video.i_sar_den <= 0 )
476     {
477         vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
478                      &id->p_encoder->fmt_out.video.i_sar_den,
479                      (uint64_t)id->p_decoder->fmt_out.video.i_sar_num * i_src_width  * i_dst_height,
480                      (uint64_t)id->p_decoder->fmt_out.video.i_sar_den * i_src_height * i_dst_width,
481                      0 );
482     }
483     else
484     {
485         vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
486                      &id->p_encoder->fmt_out.video.i_sar_den,
487                      id->p_encoder->fmt_out.video.i_sar_num,
488                      id->p_encoder->fmt_out.video.i_sar_den,
489                      0 );
490     }
491
492     id->p_encoder->fmt_in.video.i_sar_num =
493         id->p_encoder->fmt_out.video.i_sar_num;
494     id->p_encoder->fmt_in.video.i_sar_den =
495         id->p_encoder->fmt_out.video.i_sar_den;
496
497     msg_Dbg( p_stream, "encoder aspect is %i:%i",
498              id->p_encoder->fmt_out.video.i_sar_num * id->p_encoder->fmt_out.video.i_width,
499              id->p_encoder->fmt_out.video.i_sar_den * id->p_encoder->fmt_out.video.i_height );
500
501     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
502 }
503
504 static int transcode_video_encoder_open( sout_stream_t *p_stream,
505                                          sout_stream_id_t *id )
506 {
507     sout_stream_sys_t *p_sys = p_stream->p_sys;
508
509
510     msg_Dbg( p_stream, "destination (after video filters) %ix%i",
511              id->p_encoder->fmt_in.video.i_width,
512              id->p_encoder->fmt_in.video.i_height );
513
514     id->p_encoder->p_module =
515         module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
516     if( !id->p_encoder->p_module )
517     {
518         msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
519                  p_sys->psz_venc ? p_sys->psz_venc : "any",
520                  (char *)&p_sys->i_vcodec );
521         return VLC_EGENERIC;
522     }
523
524     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
525
526     /*  */
527     id->p_encoder->fmt_out.i_codec =
528         vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
529
530     id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
531     if( !id->id )
532     {
533         msg_Err( p_stream, "cannot add this stream" );
534         return VLC_EGENERIC;
535     }
536
537     return VLC_SUCCESS;
538 }
539
540 void transcode_video_close( sout_stream_t *p_stream,
541                                    sout_stream_id_t *id )
542 {
543     if( p_stream->p_sys->i_threads >= 1 )
544     {
545         vlc_mutex_lock( &p_stream->p_sys->lock_out );
546         p_stream->p_sys->b_abort = true;
547         vlc_cond_signal( &p_stream->p_sys->cond );
548         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
549
550         vlc_join( p_stream->p_sys->thread, NULL );
551         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
552         vlc_cond_destroy( &p_stream->p_sys->cond );
553     }
554
555     /* Close decoder */
556     if( id->p_decoder->p_module )
557         module_unneed( id->p_decoder, id->p_decoder->p_module );
558     if( id->p_decoder->p_description )
559         vlc_meta_Delete( id->p_decoder->p_description );
560
561     free( id->p_decoder->p_owner );
562
563     /* Close encoder */
564     if( id->p_encoder->p_module )
565         module_unneed( id->p_encoder, id->p_encoder->p_module );
566
567     /* Close filters */
568     if( id->p_f_chain )
569         filter_chain_Delete( id->p_f_chain );
570     if( id->p_uf_chain )
571         filter_chain_Delete( id->p_uf_chain );
572 }
573
574 int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_t *id,
575                                     block_t *in, block_t **out )
576 {
577     sout_stream_sys_t *p_sys = p_stream->p_sys;
578     bool b_need_duplicate = false;
579     picture_t *p_pic, *p_pic2 = NULL;
580     *out = NULL;
581
582     if( in == NULL )
583     {
584         if( p_sys->i_threads == 0 )
585         {
586             block_t *p_block;
587             do {
588                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
589                 block_ChainAppend( out, p_block );
590             } while( p_block );
591         }
592         else
593         {
594             /*
595              * FIXME: we need EncoderThread() to flush buffers and signal us
596              * when it's done so we can send the last frames to the chain
597              */
598         }
599         return VLC_SUCCESS;
600     }
601
602
603     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
604     {
605
606         if( p_stream->p_sout->i_out_pace_nocontrol && p_sys->b_hurry_up )
607         {
608             mtime_t current_date = mdate();
609             if( current_date + 50000 > p_pic->date )
610             {
611                 msg_Dbg( p_stream, "late picture skipped (%"PRId64")",
612                          current_date + 50000 - p_pic->date );
613                 picture_Release( p_pic );
614                 continue;
615             }
616         }
617
618         if( p_sys->b_master_sync )
619         {
620             mtime_t i_video_drift;
621             mtime_t i_master_drift = p_sys->i_master_drift;
622             mtime_t i_pts;
623
624             i_pts = date_Get( &id->interpolated_pts ) + 1;
625             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
626                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
627             {
628                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
629                 date_Set( &id->interpolated_pts, p_pic->date );
630                 i_pts = p_pic->date + 1;
631             }
632             i_video_drift = p_pic->date - i_pts;
633             b_need_duplicate = false;
634
635             /* Set the pts of the frame being encoded */
636             p_pic->date = i_pts;
637
638             if( i_video_drift < (i_master_drift - 50000) )
639             {
640 #if 0
641                 msg_Dbg( p_stream, "dropping frame (%i)",
642                          (int)(i_video_drift - i_master_drift) );
643 #endif
644                 picture_Release( p_pic );
645                 continue;
646             }
647             else if( i_video_drift > (i_master_drift + 50000) )
648             {
649 #if 0
650                 msg_Dbg( p_stream, "adding frame (%i)",
651                          (int)(i_video_drift - i_master_drift) );
652 #endif
653                 b_need_duplicate = true;
654             }
655         }
656
657         if( unlikely( !id->p_encoder->p_module ) )
658         {
659             transcode_video_encoder_init( p_stream, id );
660
661             transcode_video_filter_init( p_stream, id );
662
663             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
664             {
665                 picture_Release( p_pic );
666                 transcode_video_close( p_stream, id );
667                 id->b_transcode = false;
668                 return VLC_EGENERIC;
669             }
670         }
671
672         /* Run filter chain */
673         if( id->p_f_chain )
674             p_pic = filter_chain_VideoFilter( id->p_f_chain, p_pic );
675
676         /*
677          * Encoding
678          */
679
680         /* Check if we have a subpicture to overlay */
681         if( p_sys->p_spu )
682         {
683             video_format_t fmt = id->p_encoder->fmt_in.video;
684             if( fmt.i_visible_width <= 0 || fmt.i_visible_height <= 0 )
685             {
686                 fmt.i_visible_width  = fmt.i_width;
687                 fmt.i_visible_height = fmt.i_height;
688                 fmt.i_x_offset       = 0;
689                 fmt.i_y_offset       = 0;
690             }
691
692             subpicture_t *p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt,
693                                                  p_pic->date, p_pic->date, false );
694
695             /* Overlay subpicture */
696             if( p_subpic )
697             {
698                 if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
699                 {
700                     /* We can't modify the picture, we need to duplicate it */
701                     picture_t *p_tmp = video_new_buffer_decoder( id->p_decoder );
702                     if( p_tmp )
703                     {
704                         picture_Copy( p_tmp, p_pic );
705                         picture_Release( p_pic );
706                         p_pic = p_tmp;
707                     }
708                 }
709                 if( !p_sys->p_spu_blend )
710                     p_sys->p_spu_blend = filter_NewBlend( VLC_OBJECT( p_sys->p_spu ), &fmt );
711                 if( p_sys->p_spu_blend )
712                     picture_BlendSubpicture( p_pic, p_sys->p_spu_blend, p_subpic );
713                 subpicture_Delete( p_subpic );
714             }
715         }
716
717         /* Run user specified filter chain */
718         if( id->p_uf_chain )
719             p_pic = filter_chain_VideoFilter( id->p_uf_chain, p_pic );
720
721         if( p_sys->i_threads == 0 )
722         {
723             block_t *p_block;
724
725             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
726             block_ChainAppend( out, p_block );
727         }
728
729         if( p_sys->b_master_sync )
730         {
731             mtime_t i_pts = date_Get( &id->interpolated_pts ) + 1;
732             if ( p_pic->date - i_pts > MASTER_SYNC_MAX_DRIFT
733                   || p_pic->date - i_pts < -MASTER_SYNC_MAX_DRIFT )
734             {
735                 msg_Dbg( p_stream, "drift is too high, resetting master sync" );
736                 date_Set( &id->interpolated_pts, p_pic->date );
737                 i_pts = p_pic->date + 1;
738             }
739             date_Increment( &id->interpolated_pts, 1 );
740
741             if( unlikely( b_need_duplicate ) )
742             {
743
744                if( p_sys->i_threads >= 1 )
745                {
746                    /* We can't modify the picture, we need to duplicate it */
747                    p_pic2 = video_new_buffer_decoder( id->p_decoder );
748                    if( p_pic2 != NULL )
749                    {
750                        picture_Copy( p_pic2, p_pic );
751                        p_pic2->date = i_pts;
752                    }
753                }
754                else
755                {
756                    block_t *p_block;
757                    p_pic->date = i_pts;
758                    p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
759                    block_ChainAppend( out, p_block );
760                }
761            }
762         }
763
764         if( p_sys->i_threads == 0 )
765         {
766             picture_Release( p_pic );
767         }
768         else
769         {
770             vlc_mutex_lock( &p_sys->lock_out );
771             p_sys->pp_pics[p_sys->i_last_pic++] = p_pic;
772             p_sys->i_last_pic %= PICTURE_RING_SIZE;
773             *out = p_sys->p_buffers;
774             p_sys->p_buffers = NULL;
775             if( p_pic2 != NULL )
776             {
777                 p_sys->pp_pics[p_sys->i_last_pic++] = p_pic2;
778                 p_sys->i_last_pic %= PICTURE_RING_SIZE;
779             }
780             vlc_cond_signal( &p_sys->cond );
781             vlc_mutex_unlock( &p_sys->lock_out );
782         }
783     }
784
785     return VLC_SUCCESS;
786 }
787
788 bool transcode_video_add( sout_stream_t *p_stream, es_format_t *p_fmt,
789                                 sout_stream_id_t *id )
790 {
791     sout_stream_sys_t *p_sys = p_stream->p_sys;
792
793     msg_Dbg( p_stream,
794              "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
795              (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
796
797     /* Complete destination format */
798     id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
799     id->p_encoder->fmt_out.video.i_width  = p_sys->i_width & ~1;
800     id->p_encoder->fmt_out.video.i_height = p_sys->i_height & ~1;
801     id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
802
803     /* Build decoder -> filter -> encoder chain */
804     if( transcode_video_new( p_stream, id ) )
805     {
806         msg_Err( p_stream, "cannot create video chain" );
807         return false;
808     }
809
810     /* Stream will be added later on because we don't know
811      * all the characteristics of the decoded stream yet */
812     id->b_transcode = true;
813
814     if( p_sys->f_fps > 0 )
815     {
816         id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->f_fps * 1000) + 0.5;
817         id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
818     }
819
820     return true;
821 }
822