filter: separate owner structure from the filter itself
[vlc.git] / modules / stream_out / transcode / video.c
1 /*****************************************************************************
2  * video.c: transcoding stream output module (video)
3  *****************************************************************************
4  * Copyright (C) 2003-2009 VLC authors and VideoLAN
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 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.
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 Lesser General Public License for more details.
21  *
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  *****************************************************************************/
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)
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 *video_new_buffer_encoder( encoder_t *p_enc )
70 {
71     p_enc->fmt_in.video.i_chroma = p_enc->fmt_in.i_codec;
72     return picture_NewFromFormat( &p_enc->fmt_in.video );
73 }
74
75 static picture_t *transcode_video_filter_buffer_new( filter_t *p_filter )
76 {
77     p_filter->fmt_out.video.i_chroma = p_filter->fmt_out.i_codec;
78     return picture_NewFromFormat( &p_filter->fmt_out.video );
79 }
80 static void transcode_video_filter_buffer_del( filter_t *p_filter, picture_t *p_pic )
81 {
82     VLC_UNUSED(p_filter);
83     picture_Release( p_pic );
84 }
85
86 static int transcode_video_filter_allocation_init( filter_t *p_filter,
87                                                    void *p_data )
88 {
89     VLC_UNUSED(p_data);
90     p_filter->owner.video.buffer_new = transcode_video_filter_buffer_new;
91     p_filter->owner.video.buffer_del = transcode_video_filter_buffer_del;
92     return VLC_SUCCESS;
93 }
94
95 static void* EncoderThread( void *obj )
96 {
97     sout_stream_sys_t *p_sys = (sout_stream_sys_t*)obj;
98     sout_stream_id_sys_t *id = p_sys->id_video;
99     picture_t *p_pic = NULL;
100     int canc = vlc_savecancel ();
101     block_t *p_block = NULL;
102
103     for( ;; )
104     {
105
106         vlc_mutex_lock( &p_sys->lock_out );
107         while( !p_sys->b_abort &&
108                (p_pic = picture_fifo_Pop( p_sys->pp_pics )) == NULL )
109             vlc_cond_wait( &p_sys->cond, &p_sys->lock_out );
110
111         if( p_sys->b_abort && !p_pic )
112         {
113             vlc_mutex_unlock( &p_sys->lock_out );
114             break;
115         }
116         vlc_mutex_unlock( &p_sys->lock_out );
117
118         if( p_pic )
119         {
120             p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
121
122             vlc_mutex_lock( &p_sys->lock_out );
123             block_ChainAppend( &p_sys->p_buffers, p_block );
124
125             vlc_mutex_unlock( &p_sys->lock_out );
126             picture_Release( p_pic );
127         }
128
129         vlc_mutex_lock( &p_sys->lock_out );
130         if( p_sys->b_abort )
131         {
132             vlc_mutex_unlock( &p_sys->lock_out );
133             break;
134         }
135         vlc_mutex_unlock( &p_sys->lock_out );
136     }
137
138     /*Encode what we have in the buffer on closing*/
139     vlc_mutex_lock( &p_sys->lock_out );
140     while( (p_pic = picture_fifo_Pop( p_sys->pp_pics )) != NULL )
141     {
142         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
143
144         block_ChainAppend( &p_sys->p_buffers, p_block );
145
146         picture_Release( p_pic );
147     }
148
149     /*Now flush encoder*/
150     do {
151        p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
152        block_ChainAppend( &p_sys->p_buffers, p_block );
153     } while( p_block );
154
155     vlc_mutex_unlock( &p_sys->lock_out );
156
157
158     vlc_restorecancel (canc);
159     return NULL;
160 }
161
162 int transcode_video_new( sout_stream_t *p_stream, sout_stream_id_sys_t *id )
163 {
164     sout_stream_sys_t *p_sys = p_stream->p_sys;
165
166     /* Open decoder
167      * Initialization of decoder structures
168      */
169     id->p_decoder->fmt_out = id->p_decoder->fmt_in;
170     id->p_decoder->fmt_out.i_extra = 0;
171     id->p_decoder->fmt_out.p_extra = 0;
172     id->p_decoder->pf_decode_video = NULL;
173     id->p_decoder->pf_get_cc = NULL;
174     id->p_decoder->pf_get_cc = 0;
175     id->p_decoder->pf_vout_buffer_new = video_new_buffer_decoder;
176     id->p_decoder->pf_vout_buffer_del = video_del_buffer_decoder;
177     id->p_decoder->pf_picture_link    = video_link_picture_decoder;
178     id->p_decoder->pf_picture_unlink  = video_unlink_picture_decoder;
179     id->p_decoder->p_owner = malloc( sizeof(decoder_owner_sys_t) );
180     if( !id->p_decoder->p_owner )
181         return VLC_EGENERIC;
182
183     id->p_decoder->p_owner->p_sys = p_sys;
184     /* id->p_decoder->p_cfg = p_sys->p_video_cfg; */
185
186     id->p_decoder->p_module =
187         module_need( id->p_decoder, "decoder", "$codec", false );
188
189     if( !id->p_decoder->p_module )
190     {
191         msg_Err( p_stream, "cannot find video decoder" );
192         free( id->p_decoder->p_owner );
193         return VLC_EGENERIC;
194     }
195
196     /*
197      * Open encoder.
198      * Because some info about the decoded input will only be available
199      * once the first frame is decoded, we actually only test the availability
200      * of the encoder here.
201      */
202
203     /* Initialization of encoder format structures */
204     es_format_Init( &id->p_encoder->fmt_in, id->p_decoder->fmt_in.i_cat,
205                     id->p_decoder->fmt_out.i_codec );
206     id->p_encoder->fmt_in.video.i_chroma = id->p_decoder->fmt_out.i_codec;
207
208     /* The dimensions will be set properly later on.
209      * Just put sensible values so we can test an encoder is available. */
210     id->p_encoder->fmt_in.video.i_width =
211         id->p_encoder->fmt_out.video.i_width
212           ? id->p_encoder->fmt_out.video.i_width
213           : id->p_decoder->fmt_in.video.i_width
214             ? id->p_decoder->fmt_in.video.i_width : 16;
215     id->p_encoder->fmt_in.video.i_height =
216         id->p_encoder->fmt_out.video.i_height
217           ? id->p_encoder->fmt_out.video.i_height
218           : id->p_decoder->fmt_in.video.i_height
219             ? id->p_decoder->fmt_in.video.i_height : 16;
220     id->p_encoder->fmt_in.video.i_visible_width =
221         id->p_encoder->fmt_out.video.i_visible_width
222           ? id->p_encoder->fmt_out.video.i_visible_width
223           : id->p_decoder->fmt_in.video.i_visible_width
224             ? id->p_decoder->fmt_in.video.i_visible_width : id->p_encoder->fmt_in.video.i_width;
225     id->p_encoder->fmt_in.video.i_visible_height =
226         id->p_encoder->fmt_out.video.i_visible_height
227           ? id->p_encoder->fmt_out.video.i_visible_height
228           : id->p_decoder->fmt_in.video.i_visible_height
229             ? id->p_decoder->fmt_in.video.i_visible_height : id->p_encoder->fmt_in.video.i_height;
230
231     id->p_encoder->i_threads = p_sys->i_threads;
232     id->p_encoder->p_cfg = p_sys->p_video_cfg;
233
234     id->p_encoder->p_module =
235         module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
236     if( !id->p_encoder->p_module )
237     {
238         msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
239                  p_sys->psz_venc ? p_sys->psz_venc : "any",
240                  (char *)&p_sys->i_vcodec );
241         module_unneed( id->p_decoder, id->p_decoder->p_module );
242         id->p_decoder->p_module = 0;
243         free( id->p_decoder->p_owner );
244         return VLC_EGENERIC;
245     }
246
247     /* Close the encoder.
248      * We'll open it only when we have the first frame. */
249     module_unneed( id->p_encoder, id->p_encoder->p_module );
250     if( id->p_encoder->fmt_out.p_extra )
251     {
252         free( id->p_encoder->fmt_out.p_extra );
253         id->p_encoder->fmt_out.p_extra = NULL;
254         id->p_encoder->fmt_out.i_extra = 0;
255     }
256     id->p_encoder->p_module = NULL;
257
258     if( p_sys->i_threads >= 1 )
259     {
260         int i_priority = p_sys->b_high_priority ? VLC_THREAD_PRIORITY_OUTPUT :
261                            VLC_THREAD_PRIORITY_VIDEO;
262         p_sys->id_video = id;
263         vlc_mutex_init( &p_sys->lock_out );
264         vlc_cond_init( &p_sys->cond );
265         p_sys->pp_pics = picture_fifo_New();
266         if( p_sys->pp_pics == NULL )
267         {
268             msg_Err( p_stream, "cannot create picture fifo" );
269             vlc_mutex_destroy( &p_sys->lock_out );
270             vlc_cond_destroy( &p_sys->cond );
271             module_unneed( id->p_decoder, id->p_decoder->p_module );
272             id->p_decoder->p_module = NULL;
273             free( id->p_decoder->p_owner );
274             return VLC_ENOMEM;
275         }
276         p_sys->p_buffers = NULL;
277         p_sys->b_abort = false;
278         if( vlc_clone( &p_sys->thread, EncoderThread, p_sys, i_priority ) )
279         {
280             msg_Err( p_stream, "cannot spawn encoder thread" );
281             vlc_mutex_destroy( &p_sys->lock_out );
282             vlc_cond_destroy( &p_sys->cond );
283             picture_fifo_Delete( p_sys->pp_pics );
284             module_unneed( id->p_decoder, id->p_decoder->p_module );
285             id->p_decoder->p_module = NULL;
286             free( id->p_decoder->p_owner );
287             return VLC_EGENERIC;
288         }
289     }
290     return VLC_SUCCESS;
291 }
292
293 static void transcode_video_filter_init( sout_stream_t *p_stream,
294                                          sout_stream_id_sys_t *id )
295 {
296     es_format_t *p_fmt_out = &id->p_decoder->fmt_out;
297     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
298
299     id->p_f_chain = filter_chain_New( p_stream, "video filter2",
300                                       false,
301                                       transcode_video_filter_allocation_init,
302                                       NULL, p_stream->p_sys );
303     filter_chain_Reset( id->p_f_chain, p_fmt_out, p_fmt_out );
304
305     /* Deinterlace */
306     if( p_stream->p_sys->b_deinterlace )
307     {
308         filter_chain_AppendFilter( id->p_f_chain,
309                                    p_stream->p_sys->psz_deinterlace,
310                                    p_stream->p_sys->p_deinterlace_cfg,
311                                    &id->p_decoder->fmt_out,
312                                    &id->p_decoder->fmt_out );
313
314         p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain );
315     }
316
317     /* Check that we have visible_width/height*/
318     if( !p_fmt_out->video.i_visible_height )
319         p_fmt_out->video.i_visible_height = p_fmt_out->video.i_height;
320     if( !p_fmt_out->video.i_visible_width )
321         p_fmt_out->video.i_visible_width = p_fmt_out->video.i_width;
322
323     if( p_stream->p_sys->psz_vf2 )
324     {
325         id->p_uf_chain = filter_chain_New( p_stream, "video filter2",
326                                            true,
327                            transcode_video_filter_allocation_init,
328                                            NULL, p_stream->p_sys );
329         filter_chain_Reset( id->p_uf_chain, p_fmt_out,
330                             &id->p_encoder->fmt_in );
331         if( p_fmt_out->video.i_chroma != id->p_encoder->fmt_in.video.i_chroma )
332         {
333             filter_chain_AppendFilter( id->p_uf_chain,
334                                    NULL, NULL,
335                                    p_fmt_out,
336                                    &id->p_encoder->fmt_in );
337         }
338         filter_chain_AppendFromString( id->p_uf_chain, p_stream->p_sys->psz_vf2 );
339         p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
340         es_format_Copy( &id->p_encoder->fmt_in, p_fmt_out );
341         id->p_encoder->fmt_out.video.i_width =
342             id->p_encoder->fmt_in.video.i_width;
343         id->p_encoder->fmt_out.video.i_height =
344             id->p_encoder->fmt_in.video.i_height;
345         id->p_encoder->fmt_out.video.i_sar_num =
346             id->p_encoder->fmt_in.video.i_sar_num;
347         id->p_encoder->fmt_out.video.i_sar_den =
348             id->p_encoder->fmt_in.video.i_sar_den;
349     }
350
351 }
352
353 /* Take care of the scaling and chroma conversions. */
354 static void conversion_video_filter_append( sout_stream_id_sys_t *id )
355 {
356     const es_format_t *p_fmt_out = &id->p_decoder->fmt_out;
357     if( id->p_f_chain )
358         p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain );
359
360     if( id->p_uf_chain )
361         p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
362
363     if( ( p_fmt_out->video.i_chroma != id->p_encoder->fmt_in.video.i_chroma ) ||
364         ( p_fmt_out->video.i_width != id->p_encoder->fmt_in.video.i_width ) ||
365         ( p_fmt_out->video.i_height != id->p_encoder->fmt_in.video.i_height ) )
366     {
367         filter_chain_AppendFilter( id->p_uf_chain ? id->p_uf_chain : id->p_f_chain,
368                                    NULL, NULL,
369                                    p_fmt_out,
370                                    &id->p_encoder->fmt_in );
371     }
372 }
373
374 static void transcode_video_encoder_init( sout_stream_t *p_stream,
375                                           sout_stream_id_sys_t *id )
376 {
377     sout_stream_sys_t *p_sys = p_stream->p_sys;
378
379     const es_format_t *p_fmt_out = &id->p_decoder->fmt_out;
380     if( id->p_f_chain ) {
381         p_fmt_out = filter_chain_GetFmtOut( id->p_f_chain );
382     }
383     if( id->p_uf_chain ) {
384         p_fmt_out = filter_chain_GetFmtOut( id->p_uf_chain );
385     }
386
387     /* Calculate scaling
388      * width/height of source */
389     int i_src_visible_width = p_fmt_out->video.i_visible_width;
390     int i_src_visible_height = p_fmt_out->video.i_visible_height;
391
392     if (i_src_visible_width == 0)
393         i_src_visible_width = p_fmt_out->video.i_width;
394     if (i_src_visible_height == 0)
395         i_src_visible_height = p_fmt_out->video.i_height;
396
397
398     /* with/height scaling */
399     float f_scale_width = 1;
400     float f_scale_height = 1;
401
402     /* aspect ratio */
403     float f_aspect = (double)p_fmt_out->video.i_sar_num *
404                      p_fmt_out->video.i_width /
405                      p_fmt_out->video.i_sar_den /
406                      p_fmt_out->video.i_height;
407
408     msg_Dbg( p_stream, "decoder aspect is %f:1", f_aspect );
409
410     /* Change f_aspect from source frame to source pixel */
411     f_aspect = f_aspect * i_src_visible_height / i_src_visible_width;
412     msg_Dbg( p_stream, "source pixel aspect is %f:1", f_aspect );
413
414     /* Calculate scaling factor for specified parameters */
415     if( id->p_encoder->fmt_out.video.i_visible_width <= 0 &&
416         id->p_encoder->fmt_out.video.i_visible_height <= 0 && p_sys->f_scale )
417     {
418         /* Global scaling. Make sure width will remain a factor of 16 */
419         float f_real_scale;
420         int  i_new_height;
421         int i_new_width = i_src_visible_width * p_sys->f_scale;
422
423         if( i_new_width % 16 <= 7 && i_new_width >= 16 )
424             i_new_width -= i_new_width % 16;
425         else
426             i_new_width += 16 - i_new_width % 16;
427
428         f_real_scale = (float)( i_new_width ) / (float) i_src_visible_width;
429
430         i_new_height = __MAX( 16, i_src_visible_height * (float)f_real_scale );
431
432         f_scale_width = f_real_scale;
433         f_scale_height = (float) i_new_height / (float) i_src_visible_height;
434     }
435     else if( id->p_encoder->fmt_out.video.i_visible_width > 0 &&
436              id->p_encoder->fmt_out.video.i_visible_height <= 0 )
437     {
438         /* Only width specified */
439         f_scale_width = (float)id->p_encoder->fmt_out.video.i_visible_width/i_src_visible_width;
440         f_scale_height = f_scale_width;
441     }
442     else if( id->p_encoder->fmt_out.video.i_visible_width <= 0 &&
443              id->p_encoder->fmt_out.video.i_visible_height > 0 )
444     {
445          /* Only height specified */
446          f_scale_height = (float)id->p_encoder->fmt_out.video.i_visible_height/i_src_visible_height;
447          f_scale_width = f_scale_height;
448      }
449      else if( id->p_encoder->fmt_out.video.i_visible_width > 0 &&
450               id->p_encoder->fmt_out.video.i_visible_height > 0 )
451      {
452          /* Width and height specified */
453          f_scale_width = (float)id->p_encoder->fmt_out.video.i_visible_width/i_src_visible_width;
454          f_scale_height = (float)id->p_encoder->fmt_out.video.i_visible_height/i_src_visible_height;
455      }
456
457      /* check maxwidth and maxheight */
458      if( p_sys->i_maxwidth && f_scale_width > (float)p_sys->i_maxwidth /
459                                                      i_src_visible_width )
460      {
461          f_scale_width = (float)p_sys->i_maxwidth / i_src_visible_width;
462      }
463
464      if( p_sys->i_maxheight && f_scale_height > (float)p_sys->i_maxheight /
465                                                        i_src_visible_height )
466      {
467          f_scale_height = (float)p_sys->i_maxheight / i_src_visible_height;
468      }
469
470
471      /* Change aspect ratio from source pixel to scaled pixel */
472      f_aspect = f_aspect * f_scale_height / f_scale_width;
473      msg_Dbg( p_stream, "scaled pixel aspect is %f:1", f_aspect );
474
475      /* f_scale_width and f_scale_height are now final */
476      /* Calculate width, height from scaling
477       * Make sure its multiple of 2
478       */
479      /* width/height of output stream */
480      int i_dst_visible_width =  2 * (int)(f_scale_width*i_src_visible_width/2+0.5);
481      int i_dst_visible_height = 2 * (int)(f_scale_height*i_src_visible_height/2+0.5);
482      int i_dst_width =  2 * (int)(f_scale_width*p_fmt_out->video.i_width/2+0.5);
483      int i_dst_height = 2 * (int)(f_scale_height*p_fmt_out->video.i_height/2+0.5);
484
485      /* Change aspect ratio from scaled pixel to output frame */
486      f_aspect = f_aspect * i_dst_visible_width / i_dst_visible_height;
487
488      /* Store calculated values */
489      id->p_encoder->fmt_out.video.i_width = i_dst_width;
490      id->p_encoder->fmt_out.video.i_visible_width = i_dst_visible_width;
491      id->p_encoder->fmt_out.video.i_height = i_dst_height;
492      id->p_encoder->fmt_out.video.i_visible_height = i_dst_visible_height;
493
494      id->p_encoder->fmt_in.video.i_width = i_dst_width;
495      id->p_encoder->fmt_in.video.i_visible_width = i_dst_visible_width;
496      id->p_encoder->fmt_in.video.i_height = i_dst_height;
497      id->p_encoder->fmt_in.video.i_visible_height = i_dst_visible_height;
498
499      msg_Dbg( p_stream, "source %ix%i, destination %ix%i",
500          i_src_visible_width, i_src_visible_height,
501          i_dst_visible_width, i_dst_visible_height
502      );
503
504     /* Handle frame rate conversion */
505     if( !id->p_encoder->fmt_out.video.i_frame_rate ||
506         !id->p_encoder->fmt_out.video.i_frame_rate_base )
507     {
508         if( p_fmt_out->video.i_frame_rate &&
509             p_fmt_out->video.i_frame_rate_base )
510         {
511             id->p_encoder->fmt_out.video.i_frame_rate =
512                 p_fmt_out->video.i_frame_rate;
513             id->p_encoder->fmt_out.video.i_frame_rate_base =
514                 p_fmt_out->video.i_frame_rate_base;
515         }
516         else
517         {
518             /* Pick a sensible default value */
519             id->p_encoder->fmt_out.video.i_frame_rate = ENC_FRAMERATE;
520             id->p_encoder->fmt_out.video.i_frame_rate_base = ENC_FRAMERATE_BASE;
521         }
522     }
523
524     id->p_encoder->fmt_in.video.orientation =
525         id->p_encoder->fmt_out.video.orientation =
526         id->p_decoder->fmt_in.video.orientation;
527
528     id->p_encoder->fmt_in.video.i_frame_rate =
529         id->p_encoder->fmt_out.video.i_frame_rate;
530     id->p_encoder->fmt_in.video.i_frame_rate_base =
531         id->p_encoder->fmt_out.video.i_frame_rate_base;
532
533     vlc_ureduce( &id->p_encoder->fmt_in.video.i_frame_rate,
534         &id->p_encoder->fmt_in.video.i_frame_rate_base,
535         id->p_encoder->fmt_in.video.i_frame_rate,
536         id->p_encoder->fmt_in.video.i_frame_rate_base,
537         0 );
538      msg_Dbg( p_stream, "source fps %d/%d, destination %d/%d",
539         id->p_decoder->fmt_out.video.i_frame_rate,
540         id->p_decoder->fmt_out.video.i_frame_rate_base,
541         id->p_encoder->fmt_in.video.i_frame_rate,
542         id->p_encoder->fmt_in.video.i_frame_rate_base );
543
544     id->i_input_frame_interval  = id->p_decoder->fmt_out.video.i_frame_rate_base * CLOCK_FREQ / id->p_decoder->fmt_out.video.i_frame_rate;
545     msg_Info( p_stream, "input interval %d (base %d)",
546                         id->i_input_frame_interval, id->p_decoder->fmt_out.video.i_frame_rate_base );
547
548     id->i_output_frame_interval = id->p_encoder->fmt_in.video.i_frame_rate_base * CLOCK_FREQ / id->p_encoder->fmt_in.video.i_frame_rate;
549     msg_Info( p_stream, "output interval %d (base %d)",
550                         id->i_output_frame_interval, id->p_encoder->fmt_in.video.i_frame_rate_base );
551
552     date_Init( &id->next_input_pts,
553                id->p_decoder->fmt_out.video.i_frame_rate,
554                1 );
555
556     date_Init( &id->next_output_pts,
557                id->p_encoder->fmt_in.video.i_frame_rate,
558                1 );
559
560     /* Check whether a particular aspect ratio was requested */
561     if( id->p_encoder->fmt_out.video.i_sar_num <= 0 ||
562         id->p_encoder->fmt_out.video.i_sar_den <= 0 )
563     {
564         vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
565                      &id->p_encoder->fmt_out.video.i_sar_den,
566                      (uint64_t)p_fmt_out->video.i_sar_num * i_src_visible_width  * i_dst_visible_height,
567                      (uint64_t)p_fmt_out->video.i_sar_den * i_src_visible_height * i_dst_visible_width,
568                      0 );
569     }
570     else
571     {
572         vlc_ureduce( &id->p_encoder->fmt_out.video.i_sar_num,
573                      &id->p_encoder->fmt_out.video.i_sar_den,
574                      id->p_encoder->fmt_out.video.i_sar_num,
575                      id->p_encoder->fmt_out.video.i_sar_den,
576                      0 );
577     }
578
579     id->p_encoder->fmt_in.video.i_sar_num =
580         id->p_encoder->fmt_out.video.i_sar_num;
581     id->p_encoder->fmt_in.video.i_sar_den =
582         id->p_encoder->fmt_out.video.i_sar_den;
583
584     msg_Dbg( p_stream, "encoder aspect is %i:%i",
585              id->p_encoder->fmt_out.video.i_sar_num * id->p_encoder->fmt_out.video.i_width,
586              id->p_encoder->fmt_out.video.i_sar_den * id->p_encoder->fmt_out.video.i_height );
587
588 }
589
590 static int transcode_video_encoder_open( sout_stream_t *p_stream,
591                                          sout_stream_id_sys_t *id )
592 {
593     sout_stream_sys_t *p_sys = p_stream->p_sys;
594
595
596     msg_Dbg( p_stream, "destination (after video filters) %ix%i",
597              id->p_encoder->fmt_in.video.i_width,
598              id->p_encoder->fmt_in.video.i_height );
599
600     id->p_encoder->p_module =
601         module_need( id->p_encoder, "encoder", p_sys->psz_venc, true );
602     if( !id->p_encoder->p_module )
603     {
604         msg_Err( p_stream, "cannot find video encoder (module:%s fourcc:%4.4s)",
605                  p_sys->psz_venc ? p_sys->psz_venc : "any",
606                  (char *)&p_sys->i_vcodec );
607         return VLC_EGENERIC;
608     }
609
610     id->p_encoder->fmt_in.video.i_chroma = id->p_encoder->fmt_in.i_codec;
611
612     /*  */
613     id->p_encoder->fmt_out.i_codec =
614         vlc_fourcc_GetCodec( VIDEO_ES, id->p_encoder->fmt_out.i_codec );
615
616     id->id = sout_StreamIdAdd( p_stream->p_next, &id->p_encoder->fmt_out );
617     if( !id->id )
618     {
619         msg_Err( p_stream, "cannot add this stream" );
620         return VLC_EGENERIC;
621     }
622
623     return VLC_SUCCESS;
624 }
625
626 void transcode_video_close( sout_stream_t *p_stream,
627                                    sout_stream_id_sys_t *id )
628 {
629     if( p_stream->p_sys->i_threads >= 1 )
630     {
631         vlc_mutex_lock( &p_stream->p_sys->lock_out );
632         p_stream->p_sys->b_abort = true;
633         vlc_cond_signal( &p_stream->p_sys->cond );
634         vlc_mutex_unlock( &p_stream->p_sys->lock_out );
635
636         vlc_join( p_stream->p_sys->thread, NULL );
637         vlc_mutex_destroy( &p_stream->p_sys->lock_out );
638         vlc_cond_destroy( &p_stream->p_sys->cond );
639
640         picture_fifo_Delete( p_stream->p_sys->pp_pics );
641         block_ChainRelease( p_stream->p_sys->p_buffers );
642         p_stream->p_sys->pp_pics = NULL;
643     }
644
645     /* Close decoder */
646     if( id->p_decoder->p_module )
647         module_unneed( id->p_decoder, id->p_decoder->p_module );
648     if( id->p_decoder->p_description )
649         vlc_meta_Delete( id->p_decoder->p_description );
650
651     free( id->p_decoder->p_owner );
652
653     /* Close encoder */
654     if( id->p_encoder->p_module )
655         module_unneed( id->p_encoder, id->p_encoder->p_module );
656
657     /* Close filters */
658     if( id->p_f_chain )
659         filter_chain_Delete( id->p_f_chain );
660     if( id->p_uf_chain )
661         filter_chain_Delete( id->p_uf_chain );
662 }
663
664 static void OutputFrame( sout_stream_t *p_stream, picture_t *p_pic, sout_stream_id_sys_t *id, block_t **out )
665 {
666     sout_stream_sys_t *p_sys = p_stream->p_sys;
667     picture_t *p_pic2 = NULL;
668     const mtime_t original_date = p_pic->date;
669     bool b_need_duplicate=false;
670     /* If input pts is lower than next_output_pts - output_frame_interval
671      * Then the future input frame should fit better and we can drop this one 
672      *
673      * We check it here also because we can have case that video filters outputs multiple
674      * pictures but we don't need to use them all, for example yadif2x and outputting to some
675      * different fps value
676      */
677     if( ( original_date ) <
678         ( date_Get( &id->next_output_pts ) - (mtime_t)id->i_output_frame_interval ) )
679     {
680 #if 0
681         msg_Dbg( p_stream, "dropping frame (%"PRId64" + %"PRId64" vs %"PRId64")",
682                  p_pic->date, id->i_input_frame_interval, date_Get(&id->next_output_pts) );
683 #endif
684         picture_Release( p_pic );
685         return;
686     }
687
688     /*
689      * Encoding
690      */
691     /* Check if we have a subpicture to overlay */
692     if( p_sys->p_spu )
693     {
694         video_format_t fmt = id->p_encoder->fmt_in.video;
695         if( fmt.i_visible_width <= 0 || fmt.i_visible_height <= 0 )
696         {
697             fmt.i_visible_width  = fmt.i_width;
698             fmt.i_visible_height = fmt.i_height;
699             fmt.i_x_offset       = 0;
700             fmt.i_y_offset       = 0;
701         }
702
703         subpicture_t *p_subpic = spu_Render( p_sys->p_spu, NULL, &fmt, &fmt,
704                                              p_pic->date, p_pic->date, false );
705
706         /* Overlay subpicture */
707         if( p_subpic )
708         {
709             if( picture_IsReferenced( p_pic ) && !filter_chain_GetLength( id->p_f_chain ) )
710             {
711                 /* We can't modify the picture, we need to duplicate it,
712                  * in this point the picture is already p_encoder->fmt.in format*/
713                 picture_t *p_tmp = video_new_buffer_encoder( id->p_encoder );
714                 if( likely( p_tmp ) )
715                 {
716                     picture_Copy( p_tmp, p_pic );
717                     picture_Release( p_pic );
718                     p_pic = p_tmp;
719                 }
720             }
721             if( unlikely( !p_sys->p_spu_blend ) )
722                 p_sys->p_spu_blend = filter_NewBlend( VLC_OBJECT( p_sys->p_spu ), &fmt );
723             if( likely( p_sys->p_spu_blend ) )
724                 picture_BlendSubpicture( p_pic, p_sys->p_spu_blend, p_subpic );
725             subpicture_Delete( p_subpic );
726         }
727     }
728
729     /* set output pts*/
730     p_pic->date = date_Get( &id->next_output_pts );
731     /*This pts is handled, increase clock to next one*/
732     date_Increment( &id->next_output_pts, id->p_encoder->fmt_in.video.i_frame_rate_base );
733
734     if( p_sys->i_threads == 0 )
735     {
736         block_t *p_block;
737
738         p_block = id->p_encoder->pf_encode_video( id->p_encoder, p_pic );
739         block_ChainAppend( out, p_block );
740     }
741
742     /* we need to duplicate while next_output_pts + output_frame_interval < input_pts (next input pts)*/
743     b_need_duplicate = ( date_Get( &id->next_output_pts ) + id->i_output_frame_interval ) <
744                        ( original_date );
745
746     if( p_sys->i_threads )
747     {
748         if( p_sys->b_master_sync )
749         {
750             p_pic2 = video_new_buffer_encoder( id->p_encoder );
751             if( likely( p_pic2 != NULL ) )
752                 picture_Copy( p_pic2, p_pic );
753         }
754         vlc_mutex_lock( &p_sys->lock_out );
755         picture_fifo_Push( p_sys->pp_pics, p_pic );
756         vlc_cond_signal( &p_sys->cond );
757         vlc_mutex_unlock( &p_sys->lock_out );
758     }
759
760     while( (p_sys->b_master_sync && b_need_duplicate ))
761     {
762         if( p_sys->i_threads >= 1 )
763         {
764             picture_t *p_tmp = NULL;
765             /* We can't modify the picture, we need to duplicate it */
766             p_tmp = video_new_buffer_encoder( id->p_encoder );
767             if( likely( p_tmp != NULL ) )
768             {
769                 picture_Copy( p_tmp, p_pic2 );
770                 p_tmp->date = date_Get( &id->next_output_pts );
771                 vlc_mutex_lock( &p_sys->lock_out );
772                 picture_fifo_Push( p_sys->pp_pics, p_tmp );
773                 vlc_cond_signal( &p_sys->cond );
774                 vlc_mutex_unlock( &p_sys->lock_out );
775             }
776         }
777         else
778         {
779             block_t *p_block;
780             p_pic->date = date_Get( &id->next_output_pts );
781             p_block = id->p_encoder->pf_encode_video(id->p_encoder, p_pic);
782             block_ChainAppend( out, p_block );
783         }
784 #if 0
785         msg_Dbg( p_stream, "duplicated frame");
786 #endif
787         date_Increment( &id->next_output_pts, id->p_encoder->fmt_in.video.i_frame_rate_base );
788         b_need_duplicate = ( date_Get( &id->next_output_pts ) + id->i_output_frame_interval ) <
789                            ( original_date );
790     }
791
792     if( p_sys->i_threads && p_pic2 )
793         picture_Release( p_pic2 );
794     else if ( p_sys->i_threads == 0 )
795         picture_Release( p_pic );
796 }
797
798 int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
799                                     block_t *in, block_t **out )
800 {
801     sout_stream_sys_t *p_sys = p_stream->p_sys;
802     picture_t *p_pic = NULL;
803     *out = NULL;
804
805     if( unlikely( in == NULL ) )
806     {
807         if( p_sys->i_threads == 0 )
808         {
809             block_t *p_block;
810             do {
811                 p_block = id->p_encoder->pf_encode_video(id->p_encoder, NULL );
812                 block_ChainAppend( out, p_block );
813             } while( p_block );
814         }
815         else
816         {
817             msg_Dbg( p_stream, "Flushing thread and waiting that");
818             vlc_mutex_lock( &p_stream->p_sys->lock_out );
819             p_stream->p_sys->b_abort = true;
820             vlc_cond_signal( &p_stream->p_sys->cond );
821             vlc_mutex_unlock( &p_stream->p_sys->lock_out );
822
823             vlc_join( p_stream->p_sys->thread, NULL );
824             vlc_mutex_lock( &p_sys->lock_out );
825             *out = p_sys->p_buffers;
826             p_sys->p_buffers = NULL;
827             vlc_mutex_unlock( &p_sys->lock_out );
828
829             msg_Dbg( p_stream, "Flushing done");
830         }
831         return VLC_SUCCESS;
832     }
833
834
835     while( (p_pic = id->p_decoder->pf_decode_video( id->p_decoder, &in )) )
836     {
837
838         if( unlikely (
839              id->p_encoder->p_module &&
840              !video_format_IsSimilar( &id->fmt_input_video, &id->p_decoder->fmt_out.video )
841             )
842           )
843         {
844             msg_Info( p_stream, "aspect-ratio changed, reiniting. %i -> %i : %i -> %i.",
845                         id->fmt_input_video.i_sar_num, id->p_decoder->fmt_out.video.i_sar_num,
846                         id->fmt_input_video.i_sar_den, id->p_decoder->fmt_out.video.i_sar_den
847                     );
848             /* Close filters */
849             if( id->p_f_chain )
850                 filter_chain_Delete( id->p_f_chain );
851             id->p_f_chain = NULL;
852             if( id->p_uf_chain )
853                 filter_chain_Delete( id->p_uf_chain );
854             id->p_uf_chain = NULL;
855
856             /* Reinitialize filters */
857             id->p_encoder->fmt_out.video.i_visible_width  = p_sys->i_width & ~1;
858             id->p_encoder->fmt_out.video.i_visible_height = p_sys->i_height & ~1;
859             id->p_encoder->fmt_out.video.i_sar_num = id->p_encoder->fmt_out.video.i_sar_den = 0;
860
861             transcode_video_filter_init( p_stream, id );
862             transcode_video_encoder_init( p_stream, id );
863             conversion_video_filter_append( id );
864             memcpy( &id->fmt_input_video, &id->p_decoder->fmt_out.video, sizeof(video_format_t));
865         }
866
867
868         if( unlikely( !id->p_encoder->p_module ) )
869         {
870             if( id->p_f_chain )
871                 filter_chain_Delete( id->p_f_chain );
872             if( id->p_uf_chain )
873                 filter_chain_Delete( id->p_uf_chain );
874             id->p_f_chain = id->p_uf_chain = NULL;
875
876             transcode_video_filter_init( p_stream, id );
877             transcode_video_encoder_init( p_stream, id );
878             conversion_video_filter_append( id );
879             memcpy( &id->fmt_input_video, &id->p_decoder->fmt_out.video, sizeof(video_format_t));
880
881             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
882             {
883                 picture_Release( p_pic );
884                 transcode_video_close( p_stream, id );
885                 id->b_transcode = false;
886                 return VLC_EGENERIC;
887             }
888             date_Set( &id->next_output_pts, p_pic->date );
889             date_Set( &id->next_input_pts, p_pic->date );
890         }
891
892         /*Input lipsync and drop check */
893         if( p_sys->b_master_sync )
894         {
895             /* If input pts lower than next_output_pts - output_frame_interval
896              * Then the future input frame should fit better and we can drop this one 
897              *
898              * We check this here as we don't need to run video filter at all for pictures
899              * we are going to drop anyway
900              *
901              * Duplication need is checked in OutputFrame */
902             if( ( p_pic->date ) <
903                 ( date_Get( &id->next_output_pts ) - (mtime_t)id->i_output_frame_interval ) )
904             {
905 #if 0
906                 msg_Dbg( p_stream, "dropping frame (%"PRId64" + %"PRId64" vs %"PRId64")",
907                          p_pic->date, id->i_input_frame_interval, date_Get(&id->next_output_pts) );
908 #endif
909                 picture_Release( p_pic );
910                 continue;
911             }
912 #if 0
913             msg_Dbg( p_stream, "not dropping frame");
914 #endif
915
916         }
917         /* Check input drift regardless, if it's more than 100ms from our approximation, we most likely have lost pictures
918          * and are in danger to become out of sync, so better reset timestamps then */
919         if( likely( p_pic->date != VLC_TS_INVALID ) )
920         {
921             mtime_t input_drift = p_pic->date - date_Get( &id->next_input_pts );
922             if( unlikely( (input_drift > (CLOCK_FREQ/10)) ||
923                           (input_drift < -(CLOCK_FREQ/10))
924                ) )
925             {
926                 msg_Warn( p_stream, "Reseting video sync" );
927                 date_Set( &id->next_output_pts, p_pic->date );
928                 date_Set( &id->next_input_pts, p_pic->date );
929             }
930         }
931         date_Increment( &id->next_input_pts, id->p_decoder->fmt_out.video.i_frame_rate_base );
932
933         /* Run the filter and output chains; first with the picture,
934          * and then with NULL as many times as we need until they
935          * stop outputting frames.
936          */
937         for ( ;; ) {
938             picture_t *p_filtered_pic = p_pic;
939
940             /* Run filter chain */
941             if( id->p_f_chain )
942                 p_filtered_pic = filter_chain_VideoFilter( id->p_f_chain, p_filtered_pic );
943             if( !p_filtered_pic )
944                 break;
945
946             for ( ;; ) {
947                 picture_t *p_user_filtered_pic = p_filtered_pic;
948
949                 /* Run user specified filter chain */
950                 if( id->p_uf_chain )
951                     p_user_filtered_pic = filter_chain_VideoFilter( id->p_uf_chain, p_user_filtered_pic );
952                 if( !p_user_filtered_pic )
953                     break;
954
955                 OutputFrame( p_stream, p_user_filtered_pic, id, out );
956
957                 p_filtered_pic = NULL;
958             }
959
960             p_pic = NULL;
961         }
962     }
963
964     if( p_sys->i_threads >= 1 )
965     {
966         /* Pick up any return data the encoder thread wants to output. */
967         vlc_mutex_lock( &p_sys->lock_out );
968         *out = p_sys->p_buffers;
969         p_sys->p_buffers = NULL;
970         vlc_mutex_unlock( &p_sys->lock_out );
971     }
972
973     return VLC_SUCCESS;
974 }
975
976 bool transcode_video_add( sout_stream_t *p_stream, es_format_t *p_fmt,
977                                 sout_stream_id_sys_t *id )
978 {
979     sout_stream_sys_t *p_sys = p_stream->p_sys;
980
981     msg_Dbg( p_stream,
982              "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
983              (char*)&p_fmt->i_codec, (char*)&p_sys->i_vcodec );
984
985     /* Complete destination format */
986     id->p_encoder->fmt_out.i_codec = p_sys->i_vcodec;
987     id->p_encoder->fmt_out.video.i_visible_width  = p_sys->i_width & ~1;
988     id->p_encoder->fmt_out.video.i_visible_height = p_sys->i_height & ~1;
989     id->p_encoder->fmt_out.i_bitrate = p_sys->i_vbitrate;
990
991     /* Build decoder -> filter -> encoder chain */
992     if( transcode_video_new( p_stream, id ) )
993     {
994         msg_Err( p_stream, "cannot create video chain" );
995         return false;
996     }
997
998     /* Stream will be added later on because we don't know
999      * all the characteristics of the decoded stream yet */
1000     id->b_transcode = true;
1001
1002     if( p_sys->fps_num )
1003     {
1004         id->p_encoder->fmt_out.video.i_frame_rate = (p_sys->fps_num );
1005         id->p_encoder->fmt_out.video.i_frame_rate_base = (p_sys->fps_den ? p_sys->fps_den : 1);
1006     }
1007
1008     return true;
1009 }
1010