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