1 /*****************************************************************************
2 * video.c: transcoding stream output module (video)
3 *****************************************************************************
4 * Copyright (C) 2003-2009 VLC authors and VideoLAN
7 * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8 * Gildas Bazin <gbazin@videolan.org>
9 * Jean-Paul Saman <jpsaman #_at_# m2x dot nl>
10 * Antoine Cellerier <dionoea at videolan dot org>
12 * This program is free software; you can redistribute it and/or modify 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.
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.
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 *****************************************************************************/
27 /*****************************************************************************
29 *****************************************************************************/
31 #include "transcode.h"
36 #include <vlc_modules.h>
38 #define ENC_FRAMERATE (25 * 1000)
39 #define ENC_FRAMERATE_BASE 1000
41 static const es_format_t
* video_output_format( sout_stream_id_sys_t
*id
)
44 return filter_chain_GetFmtOut( id
->p_uf_chain
);
45 else if( id
->p_f_chain
)
46 return filter_chain_GetFmtOut( id
->p_f_chain
);
47 return &id
->p_decoder
->fmt_out
;
50 static int video_update_format_decoder( decoder_t
*p_dec
)
52 sout_stream_t
*stream
= (sout_stream_t
*) p_dec
->p_owner
;
53 sout_stream_sys_t
*sys
= stream
->p_sys
;
54 sout_stream_id_sys_t
*id
= p_dec
->p_queue_ctx
;
55 filter_chain_t
*test_chain
;
57 filter_owner_t filter_owner
= {
61 if( !id
->b_transcode
)
64 if( id
->p_encoder
->fmt_in
.i_codec
== p_dec
->fmt_out
.i_codec
||
65 video_format_IsSimilar( &id
->p_encoder
->fmt_in
.video
,
66 &video_output_format( id
)->video
) )
69 msg_Dbg( stream
, "Checking if filter chain %4.4s -> %4.4s is possible",
70 (char *)&p_dec
->fmt_out
.i_codec
, (char*)&id
->p_encoder
->fmt_in
.i_codec
);
71 test_chain
= filter_chain_NewVideo( stream
, false, &filter_owner
);
72 filter_chain_Reset( test_chain
, &p_dec
->fmt_out
, &p_dec
->fmt_out
);
74 int chain_works
= filter_chain_AppendConverter( test_chain
, &p_dec
->fmt_out
,
75 &id
->p_encoder
->fmt_in
);
76 filter_chain_Delete( test_chain
);
77 msg_Dbg( stream
, "Filter chain testing done, input chroma %4.4s seems to be %s for transcode",
78 (char *)&p_dec
->fmt_out
.video
.i_chroma
,
79 chain_works
== 0 ? "possible" : "not possible");
83 static picture_t
*video_new_buffer_decoder( decoder_t
*p_dec
)
85 return picture_NewFromFormat( &p_dec
->fmt_out
.video
);
88 static picture_t
*video_new_buffer_encoder( encoder_t
*p_enc
)
90 return picture_NewFromFormat( &p_enc
->fmt_in
.video
);
93 static picture_t
*transcode_video_filter_buffer_new( filter_t
*p_filter
)
95 p_filter
->fmt_out
.video
.i_chroma
= p_filter
->fmt_out
.i_codec
;
96 return picture_NewFromFormat( &p_filter
->fmt_out
.video
);
99 static void* EncoderThread( void *obj
)
101 sout_stream_sys_t
*p_sys
= (sout_stream_sys_t
*)obj
;
102 sout_stream_id_sys_t
*id
= p_sys
->id_video
;
103 picture_t
*p_pic
= NULL
;
104 int canc
= vlc_savecancel ();
105 block_t
*p_block
= NULL
;
107 vlc_mutex_lock( &p_sys
->lock_out
);
111 while( !p_sys
->b_abort
&&
112 (p_pic
= picture_fifo_Pop( p_sys
->pp_pics
)) == NULL
)
113 vlc_cond_wait( &p_sys
->cond
, &p_sys
->lock_out
);
114 vlc_sem_post( &p_sys
->picture_pool_has_room
);
118 /* release lock while encoding */
119 vlc_mutex_unlock( &p_sys
->lock_out
);
120 p_block
= id
->p_encoder
->pf_encode_video( id
->p_encoder
, p_pic
);
121 picture_Release( p_pic
);
122 vlc_mutex_lock( &p_sys
->lock_out
);
124 block_ChainAppend( &p_sys
->p_buffers
, p_block
);
131 /*Encode what we have in the buffer on closing*/
132 while( (p_pic
= picture_fifo_Pop( p_sys
->pp_pics
)) != NULL
)
134 vlc_sem_post( &p_sys
->picture_pool_has_room
);
135 p_block
= id
->p_encoder
->pf_encode_video( id
->p_encoder
, p_pic
);
136 picture_Release( p_pic
);
137 block_ChainAppend( &p_sys
->p_buffers
, p_block
);
140 /*Now flush encoder*/
142 p_block
= id
->p_encoder
->pf_encode_video(id
->p_encoder
, NULL
);
143 block_ChainAppend( &p_sys
->p_buffers
, p_block
);
146 vlc_mutex_unlock( &p_sys
->lock_out
);
148 vlc_restorecancel (canc
);
153 static int decoder_queue_video( decoder_t
*p_dec
, picture_t
*p_pic
)
155 sout_stream_id_sys_t
*id
= p_dec
->p_queue_ctx
;
157 vlc_mutex_lock(&id
->fifo
.lock
);
158 *id
->fifo
.pic
.last
= p_pic
;
159 id
->fifo
.pic
.last
= &p_pic
->p_next
;
160 vlc_mutex_unlock(&id
->fifo
.lock
);
164 static picture_t
*transcode_dequeue_all_pics( sout_stream_id_sys_t
*id
)
166 vlc_mutex_lock(&id
->fifo
.lock
);
167 picture_t
*p_pics
= id
->fifo
.pic
.first
;
168 id
->fifo
.pic
.first
= NULL
;
169 id
->fifo
.pic
.last
= &id
->fifo
.pic
.first
;
170 vlc_mutex_unlock(&id
->fifo
.lock
);
175 static int transcode_video_new( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
)
177 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
180 * Initialization of decoder structures
182 id
->p_decoder
->fmt_out
= id
->p_decoder
->fmt_in
;
183 id
->p_decoder
->fmt_out
.i_extra
= 0;
184 id
->p_decoder
->fmt_out
.p_extra
= NULL
;
185 id
->p_decoder
->fmt_out
.psz_language
= NULL
;
186 id
->p_decoder
->pf_decode
= NULL
;
187 id
->p_decoder
->pf_queue_video
= decoder_queue_video
;
188 id
->p_decoder
->p_queue_ctx
= id
;
189 id
->p_decoder
->pf_get_cc
= NULL
;
190 id
->p_decoder
->pf_vout_format_update
= video_update_format_decoder
;
191 id
->p_decoder
->pf_vout_buffer_new
= video_new_buffer_decoder
;
192 id
->p_decoder
->p_owner
= (decoder_owner_sys_t
*) p_stream
;
194 id
->p_decoder
->p_module
=
195 module_need( id
->p_decoder
, "video decoder", "$codec", false );
197 if( !id
->p_decoder
->p_module
)
199 msg_Err( p_stream
, "cannot find video decoder" );
205 * Because some info about the decoded input will only be available
206 * once the first frame is decoded, we actually only test the availability
207 * of the encoder here.
210 /* Initialization of encoder format structures */
211 es_format_Init( &id
->p_encoder
->fmt_in
, id
->p_decoder
->fmt_in
.i_cat
,
212 id
->p_decoder
->fmt_out
.i_codec
);
214 /* The dimensions will be set properly later on.
215 * Just put sensible values so we can test an encoder is available. */
216 id
->p_encoder
->fmt_in
.video
.i_width
=
217 id
->p_encoder
->fmt_out
.video
.i_width
218 ? id
->p_encoder
->fmt_out
.video
.i_width
219 : id
->p_decoder
->fmt_in
.video
.i_width
220 ? id
->p_decoder
->fmt_in
.video
.i_width
: 16;
221 id
->p_encoder
->fmt_in
.video
.i_height
=
222 id
->p_encoder
->fmt_out
.video
.i_height
223 ? id
->p_encoder
->fmt_out
.video
.i_height
224 : id
->p_decoder
->fmt_in
.video
.i_height
225 ? id
->p_decoder
->fmt_in
.video
.i_height
: 16;
226 id
->p_encoder
->fmt_in
.video
.i_visible_width
=
227 id
->p_encoder
->fmt_out
.video
.i_visible_width
228 ? id
->p_encoder
->fmt_out
.video
.i_visible_width
229 : id
->p_decoder
->fmt_in
.video
.i_visible_width
230 ? id
->p_decoder
->fmt_in
.video
.i_visible_width
: id
->p_encoder
->fmt_in
.video
.i_width
;
231 id
->p_encoder
->fmt_in
.video
.i_visible_height
=
232 id
->p_encoder
->fmt_out
.video
.i_visible_height
233 ? id
->p_encoder
->fmt_out
.video
.i_visible_height
234 : id
->p_decoder
->fmt_in
.video
.i_visible_height
235 ? id
->p_decoder
->fmt_in
.video
.i_visible_height
: id
->p_encoder
->fmt_in
.video
.i_height
;
236 /* The same goes with frame rate. Some encoders need it to be initialized */
237 id
->p_encoder
->fmt_in
.video
.i_frame_rate
= ENC_FRAMERATE
;
238 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
= ENC_FRAMERATE_BASE
;
240 id
->p_encoder
->i_threads
= p_sys
->i_threads
;
241 id
->p_encoder
->p_cfg
= p_sys
->p_video_cfg
;
243 id
->p_encoder
->p_module
=
244 module_need( id
->p_encoder
, "encoder", p_sys
->psz_venc
, true );
245 if( !id
->p_encoder
->p_module
)
247 msg_Err( p_stream
, "cannot find video encoder (module:%s fourcc:%4.4s). Take a look few lines earlier to see possible reason.",
248 p_sys
->psz_venc
? p_sys
->psz_venc
: "any",
249 (char *)&p_sys
->i_vcodec
);
250 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
251 id
->p_decoder
->p_module
= 0;
255 /* Close the encoder.
256 * We'll open it only when we have the first frame. */
257 module_unneed( id
->p_encoder
, id
->p_encoder
->p_module
);
258 if( id
->p_encoder
->fmt_out
.p_extra
)
260 free( id
->p_encoder
->fmt_out
.p_extra
);
261 id
->p_encoder
->fmt_out
.p_extra
= NULL
;
262 id
->p_encoder
->fmt_out
.i_extra
= 0;
264 id
->p_encoder
->fmt_in
.video
.i_chroma
= id
->p_encoder
->fmt_in
.i_codec
;
265 id
->p_encoder
->p_module
= NULL
;
267 if( p_sys
->i_threads
<= 0 )
270 int i_priority
= p_sys
->b_high_priority
? VLC_THREAD_PRIORITY_OUTPUT
:
271 VLC_THREAD_PRIORITY_VIDEO
;
272 p_sys
->id_video
= id
;
273 p_sys
->pp_pics
= picture_fifo_New();
274 if( p_sys
->pp_pics
== NULL
)
276 msg_Err( p_stream
, "cannot create picture fifo" );
277 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
278 id
->p_decoder
->p_module
= NULL
;
282 vlc_sem_init( &p_sys
->picture_pool_has_room
, p_sys
->pool_size
);
283 vlc_mutex_init( &p_sys
->lock_out
);
284 vlc_cond_init( &p_sys
->cond
);
285 p_sys
->p_buffers
= NULL
;
286 p_sys
->b_abort
= false;
287 if( vlc_clone( &p_sys
->thread
, EncoderThread
, p_sys
, i_priority
) )
289 msg_Err( p_stream
, "cannot spawn encoder thread" );
290 vlc_mutex_destroy( &p_sys
->lock_out
);
291 vlc_cond_destroy( &p_sys
->cond
);
292 picture_fifo_Delete( p_sys
->pp_pics
);
293 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
294 id
->p_decoder
->p_module
= NULL
;
300 static void transcode_video_filter_init( sout_stream_t
*p_stream
,
301 sout_stream_id_sys_t
*id
)
303 filter_owner_t owner
= {
304 .sys
= p_stream
->p_sys
,
306 .buffer_new
= transcode_video_filter_buffer_new
,
309 const es_format_t
*p_fmt_out
= &id
->p_decoder
->fmt_out
;
311 id
->p_encoder
->fmt_in
.video
.i_chroma
= id
->p_encoder
->fmt_in
.i_codec
;
312 id
->p_f_chain
= filter_chain_NewVideo( p_stream
, false, &owner
);
313 filter_chain_Reset( id
->p_f_chain
, p_fmt_out
, p_fmt_out
);
315 /* Check that we have visible_width/height*/
316 if( !id
->p_decoder
->fmt_out
.video
.i_visible_height
)
317 id
->p_decoder
->fmt_out
.video
.i_visible_height
= id
->p_decoder
->fmt_out
.video
.i_height
;
318 if( !id
->p_decoder
->fmt_out
.video
.i_visible_width
)
319 id
->p_decoder
->fmt_out
.video
.i_visible_width
= id
->p_decoder
->fmt_out
.video
.i_width
;
322 if( p_stream
->p_sys
->psz_deinterlace
!= NULL
)
324 filter_chain_AppendFilter( id
->p_f_chain
,
325 p_stream
->p_sys
->psz_deinterlace
,
326 p_stream
->p_sys
->p_deinterlace_cfg
,
327 &id
->p_decoder
->fmt_out
,
328 &id
->p_decoder
->fmt_out
);
330 p_fmt_out
= filter_chain_GetFmtOut( id
->p_f_chain
);
332 if( p_stream
->p_sys
->b_master_sync
)
334 filter_chain_AppendFilter( id
->p_f_chain
,
338 &id
->p_encoder
->fmt_in
);
340 p_fmt_out
= filter_chain_GetFmtOut( id
->p_f_chain
);
343 if( p_stream
->p_sys
->psz_vf2
)
345 id
->p_uf_chain
= filter_chain_NewVideo( p_stream
, true, &owner
);
346 filter_chain_Reset( id
->p_uf_chain
, p_fmt_out
,
347 &id
->p_encoder
->fmt_in
);
348 if( p_fmt_out
->video
.i_chroma
!= id
->p_encoder
->fmt_in
.video
.i_chroma
)
350 filter_chain_AppendConverter( id
->p_uf_chain
, p_fmt_out
,
351 &id
->p_encoder
->fmt_in
);
353 filter_chain_AppendFromString( id
->p_uf_chain
, p_stream
->p_sys
->psz_vf2
);
354 p_fmt_out
= filter_chain_GetFmtOut( id
->p_uf_chain
);
355 es_format_Copy( &id
->p_encoder
->fmt_in
, p_fmt_out
);
356 id
->p_encoder
->fmt_out
.video
.i_width
=
357 id
->p_encoder
->fmt_in
.video
.i_width
;
358 id
->p_encoder
->fmt_out
.video
.i_height
=
359 id
->p_encoder
->fmt_in
.video
.i_height
;
360 id
->p_encoder
->fmt_out
.video
.i_sar_num
=
361 id
->p_encoder
->fmt_in
.video
.i_sar_num
;
362 id
->p_encoder
->fmt_out
.video
.i_sar_den
=
363 id
->p_encoder
->fmt_in
.video
.i_sar_den
;
366 /* Keep colorspace etc info along */
367 id
->p_encoder
->fmt_in
.video
.space
= id
->p_decoder
->fmt_out
.video
.space
;
368 id
->p_encoder
->fmt_in
.video
.transfer
= id
->p_decoder
->fmt_out
.video
.transfer
;
369 id
->p_encoder
->fmt_in
.video
.primaries
= id
->p_decoder
->fmt_out
.video
.primaries
;
370 id
->p_encoder
->fmt_in
.video
.b_color_range_full
= id
->p_decoder
->fmt_out
.video
.b_color_range_full
;
373 /* Take care of the scaling and chroma conversions. */
374 static void conversion_video_filter_append( sout_stream_id_sys_t
*id
)
376 const es_format_t
*p_fmt_out
= video_output_format( id
);
378 if( ( p_fmt_out
->video
.i_chroma
!= id
->p_encoder
->fmt_in
.video
.i_chroma
) ||
379 ( p_fmt_out
->video
.i_width
!= id
->p_encoder
->fmt_in
.video
.i_width
) ||
380 ( p_fmt_out
->video
.i_height
!= id
->p_encoder
->fmt_in
.video
.i_height
) )
382 filter_chain_AppendConverter( id
->p_uf_chain
? id
->p_uf_chain
: id
->p_f_chain
,
383 p_fmt_out
, &id
->p_encoder
->fmt_in
);
387 static void transcode_video_framerate_init( sout_stream_t
*p_stream
,
388 sout_stream_id_sys_t
*id
,
389 const es_format_t
*p_fmt_out
)
391 /* Handle frame rate conversion */
392 if( !id
->p_encoder
->fmt_out
.video
.i_frame_rate
||
393 !id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
)
395 if( p_fmt_out
->video
.i_frame_rate
&&
396 p_fmt_out
->video
.i_frame_rate_base
)
398 id
->p_encoder
->fmt_out
.video
.i_frame_rate
=
399 p_fmt_out
->video
.i_frame_rate
;
400 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
=
401 p_fmt_out
->video
.i_frame_rate_base
;
405 /* Pick a sensible default value */
406 id
->p_encoder
->fmt_out
.video
.i_frame_rate
= ENC_FRAMERATE
;
407 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
= ENC_FRAMERATE_BASE
;
411 id
->p_encoder
->fmt_in
.video
.i_frame_rate
=
412 id
->p_encoder
->fmt_out
.video
.i_frame_rate
;
413 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
=
414 id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
;
416 vlc_ureduce( &id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
417 &id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
,
418 id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
419 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
,
421 msg_Dbg( p_stream
, "source fps %u/%u, destination %u/%u",
422 id
->p_decoder
->fmt_out
.video
.i_frame_rate
,
423 id
->p_decoder
->fmt_out
.video
.i_frame_rate_base
,
424 id
->p_encoder
->fmt_in
.video
.i_frame_rate
,
425 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
);
429 static void transcode_video_size_init( sout_stream_t
*p_stream
,
430 sout_stream_id_sys_t
*id
,
431 const es_format_t
*p_fmt_out
)
433 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
436 * width/height of source */
437 int i_src_visible_width
= p_fmt_out
->video
.i_visible_width
;
438 int i_src_visible_height
= p_fmt_out
->video
.i_visible_height
;
440 if (i_src_visible_width
== 0)
441 i_src_visible_width
= p_fmt_out
->video
.i_width
;
442 if (i_src_visible_height
== 0)
443 i_src_visible_height
= p_fmt_out
->video
.i_height
;
446 /* with/height scaling */
447 float f_scale_width
= 1;
448 float f_scale_height
= 1;
451 float f_aspect
= (double)p_fmt_out
->video
.i_sar_num
*
452 p_fmt_out
->video
.i_width
/
453 p_fmt_out
->video
.i_sar_den
/
454 p_fmt_out
->video
.i_height
;
456 msg_Dbg( p_stream
, "decoder aspect is %f:1", f_aspect
);
458 /* Change f_aspect from source frame to source pixel */
459 f_aspect
= f_aspect
* i_src_visible_height
/ i_src_visible_width
;
460 msg_Dbg( p_stream
, "source pixel aspect is %f:1", f_aspect
);
462 /* Calculate scaling factor for specified parameters */
463 if( id
->p_encoder
->fmt_out
.video
.i_visible_width
<= 0 &&
464 id
->p_encoder
->fmt_out
.video
.i_visible_height
<= 0 && p_sys
->f_scale
)
466 /* Global scaling. Make sure width will remain a factor of 16 */
469 int i_new_width
= i_src_visible_width
* p_sys
->f_scale
;
471 if( i_new_width
% 16 <= 7 && i_new_width
>= 16 )
472 i_new_width
-= i_new_width
% 16;
474 i_new_width
+= 16 - i_new_width
% 16;
476 f_real_scale
= (float)( i_new_width
) / (float) i_src_visible_width
;
478 i_new_height
= __MAX( 16, i_src_visible_height
* (float)f_real_scale
);
480 f_scale_width
= f_real_scale
;
481 f_scale_height
= (float) i_new_height
/ (float) i_src_visible_height
;
483 else if( id
->p_encoder
->fmt_out
.video
.i_visible_width
> 0 &&
484 id
->p_encoder
->fmt_out
.video
.i_visible_height
<= 0 )
486 /* Only width specified */
487 f_scale_width
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_width
/i_src_visible_width
;
488 f_scale_height
= f_scale_width
;
490 else if( id
->p_encoder
->fmt_out
.video
.i_visible_width
<= 0 &&
491 id
->p_encoder
->fmt_out
.video
.i_visible_height
> 0 )
493 /* Only height specified */
494 f_scale_height
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_height
/i_src_visible_height
;
495 f_scale_width
= f_scale_height
;
497 else if( id
->p_encoder
->fmt_out
.video
.i_visible_width
> 0 &&
498 id
->p_encoder
->fmt_out
.video
.i_visible_height
> 0 )
500 /* Width and height specified */
501 f_scale_width
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_width
/i_src_visible_width
;
502 f_scale_height
= (float)id
->p_encoder
->fmt_out
.video
.i_visible_height
/i_src_visible_height
;
505 /* check maxwidth and maxheight */
506 if( p_sys
->i_maxwidth
&& f_scale_width
> (float)p_sys
->i_maxwidth
/
507 i_src_visible_width
)
509 f_scale_width
= (float)p_sys
->i_maxwidth
/ i_src_visible_width
;
512 if( p_sys
->i_maxheight
&& f_scale_height
> (float)p_sys
->i_maxheight
/
513 i_src_visible_height
)
515 f_scale_height
= (float)p_sys
->i_maxheight
/ i_src_visible_height
;
519 /* Change aspect ratio from source pixel to scaled pixel */
520 f_aspect
= f_aspect
* f_scale_height
/ f_scale_width
;
521 msg_Dbg( p_stream
, "scaled pixel aspect is %f:1", f_aspect
);
523 /* f_scale_width and f_scale_height are now final */
524 /* Calculate width, height from scaling
525 * Make sure its multiple of 2
527 /* width/height of output stream */
528 int i_dst_visible_width
= lroundf(f_scale_width
*i_src_visible_width
);
529 int i_dst_visible_height
= lroundf(f_scale_height
*i_src_visible_height
);
530 int i_dst_width
= lroundf(f_scale_width
*p_fmt_out
->video
.i_width
);
531 int i_dst_height
= lroundf(f_scale_height
*p_fmt_out
->video
.i_height
);
533 if( i_dst_width
& 1 ) ++i_dst_width
;
534 if( i_dst_height
& 1 ) ++i_dst_height
;
536 /* Store calculated values */
537 id
->p_encoder
->fmt_out
.video
.i_width
= i_dst_width
;
538 id
->p_encoder
->fmt_out
.video
.i_visible_width
= i_dst_visible_width
;
539 id
->p_encoder
->fmt_out
.video
.i_height
= i_dst_height
;
540 id
->p_encoder
->fmt_out
.video
.i_visible_height
= i_dst_visible_height
;
542 id
->p_encoder
->fmt_in
.video
.i_width
= i_dst_width
;
543 id
->p_encoder
->fmt_in
.video
.i_visible_width
= i_dst_visible_width
;
544 id
->p_encoder
->fmt_in
.video
.i_height
= i_dst_height
;
545 id
->p_encoder
->fmt_in
.video
.i_visible_height
= i_dst_visible_height
;
547 msg_Dbg( p_stream
, "source %ix%i, destination %ix%i",
548 i_src_visible_width
, i_src_visible_height
,
549 i_dst_visible_width
, i_dst_visible_height
553 static void transcode_video_sar_init( sout_stream_t
*p_stream
,
554 sout_stream_id_sys_t
*id
,
555 const es_format_t
*p_fmt_out
)
557 int i_src_visible_width
= p_fmt_out
->video
.i_visible_width
;
558 int i_src_visible_height
= p_fmt_out
->video
.i_visible_height
;
560 if (i_src_visible_width
== 0)
561 i_src_visible_width
= p_fmt_out
->video
.i_width
;
562 if (i_src_visible_height
== 0)
563 i_src_visible_height
= p_fmt_out
->video
.i_height
;
565 /* Check whether a particular aspect ratio was requested */
566 if( id
->p_encoder
->fmt_out
.video
.i_sar_num
<= 0 ||
567 id
->p_encoder
->fmt_out
.video
.i_sar_den
<= 0 )
569 vlc_ureduce( &id
->p_encoder
->fmt_out
.video
.i_sar_num
,
570 &id
->p_encoder
->fmt_out
.video
.i_sar_den
,
571 (uint64_t)p_fmt_out
->video
.i_sar_num
* id
->p_encoder
->fmt_out
.video
.i_width
* p_fmt_out
->video
.i_height
,
572 (uint64_t)p_fmt_out
->video
.i_sar_den
* id
->p_encoder
->fmt_out
.video
.i_height
* p_fmt_out
->video
.i_width
,
577 vlc_ureduce( &id
->p_encoder
->fmt_out
.video
.i_sar_num
,
578 &id
->p_encoder
->fmt_out
.video
.i_sar_den
,
579 id
->p_encoder
->fmt_out
.video
.i_sar_num
,
580 id
->p_encoder
->fmt_out
.video
.i_sar_den
,
584 id
->p_encoder
->fmt_in
.video
.i_sar_num
=
585 id
->p_encoder
->fmt_out
.video
.i_sar_num
;
586 id
->p_encoder
->fmt_in
.video
.i_sar_den
=
587 id
->p_encoder
->fmt_out
.video
.i_sar_den
;
589 msg_Dbg( p_stream
, "encoder aspect is %i:%i",
590 id
->p_encoder
->fmt_out
.video
.i_sar_num
* id
->p_encoder
->fmt_out
.video
.i_width
,
591 id
->p_encoder
->fmt_out
.video
.i_sar_den
* id
->p_encoder
->fmt_out
.video
.i_height
);
595 static void transcode_video_encoder_init( sout_stream_t
*p_stream
,
596 sout_stream_id_sys_t
*id
)
598 const es_format_t
*p_fmt_out
= video_output_format( id
);
600 id
->p_encoder
->fmt_in
.video
.orientation
=
601 id
->p_encoder
->fmt_out
.video
.orientation
=
602 id
->p_decoder
->fmt_in
.video
.orientation
;
604 transcode_video_framerate_init( p_stream
, id
, p_fmt_out
);
606 transcode_video_size_init( p_stream
, id
, p_fmt_out
);
607 transcode_video_sar_init( p_stream
, id
, p_fmt_out
);
611 static int transcode_video_encoder_open( sout_stream_t
*p_stream
,
612 sout_stream_id_sys_t
*id
)
614 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
617 msg_Dbg( p_stream
, "destination (after video filters) %ix%i",
618 id
->p_encoder
->fmt_in
.video
.i_width
,
619 id
->p_encoder
->fmt_in
.video
.i_height
);
621 id
->p_encoder
->p_module
=
622 module_need( id
->p_encoder
, "encoder", p_sys
->psz_venc
, true );
623 if( !id
->p_encoder
->p_module
)
625 msg_Err( p_stream
, "cannot find video encoder (module:%s fourcc:%4.4s)",
626 p_sys
->psz_venc
? p_sys
->psz_venc
: "any",
627 (char *)&p_sys
->i_vcodec
);
631 id
->p_encoder
->fmt_in
.video
.i_chroma
= id
->p_encoder
->fmt_in
.i_codec
;
634 id
->p_encoder
->fmt_out
.i_codec
=
635 vlc_fourcc_GetCodec( VIDEO_ES
, id
->p_encoder
->fmt_out
.i_codec
);
637 id
->id
= sout_StreamIdAdd( p_stream
->p_next
, &id
->p_encoder
->fmt_out
);
640 msg_Err( p_stream
, "cannot add this stream" );
647 void transcode_video_close( sout_stream_t
*p_stream
,
648 sout_stream_id_sys_t
*id
)
650 if( p_stream
->p_sys
->i_threads
>= 1 && !p_stream
->p_sys
->b_abort
)
652 vlc_mutex_lock( &p_stream
->p_sys
->lock_out
);
653 p_stream
->p_sys
->b_abort
= true;
654 vlc_cond_signal( &p_stream
->p_sys
->cond
);
655 vlc_mutex_unlock( &p_stream
->p_sys
->lock_out
);
657 vlc_join( p_stream
->p_sys
->thread
, NULL
);
659 picture_fifo_Delete( p_stream
->p_sys
->pp_pics
);
660 block_ChainRelease( p_stream
->p_sys
->p_buffers
);
663 if( p_stream
->p_sys
->i_threads
>= 1 )
665 vlc_mutex_destroy( &p_stream
->p_sys
->lock_out
);
666 vlc_cond_destroy( &p_stream
->p_sys
->cond
);
670 if( id
->p_decoder
->p_module
)
671 module_unneed( id
->p_decoder
, id
->p_decoder
->p_module
);
672 if( id
->p_decoder
->p_description
)
673 vlc_meta_Delete( id
->p_decoder
->p_description
);
676 if( id
->p_encoder
->p_module
)
677 module_unneed( id
->p_encoder
, id
->p_encoder
->p_module
);
681 filter_chain_Delete( id
->p_f_chain
);
683 filter_chain_Delete( id
->p_uf_chain
);
686 static void OutputFrame( sout_stream_t
*p_stream
, picture_t
*p_pic
, sout_stream_id_sys_t
*id
, block_t
**out
)
688 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
693 /* Check if we have a subpicture to overlay */
696 video_format_t fmt
= id
->p_encoder
->fmt_in
.video
;
697 if( fmt
.i_visible_width
<= 0 || fmt
.i_visible_height
<= 0 )
699 fmt
.i_visible_width
= fmt
.i_width
;
700 fmt
.i_visible_height
= fmt
.i_height
;
705 subpicture_t
*p_subpic
= spu_Render( p_sys
->p_spu
, NULL
, &fmt
,
706 &id
->p_decoder
->fmt_out
.video
,
707 p_pic
->date
, p_pic
->date
, false );
709 /* Overlay subpicture */
712 if( filter_chain_IsEmpty( id
->p_f_chain
) )
714 /* We can't modify the picture, we need to duplicate it,
715 * in this point the picture is already p_encoder->fmt.in format*/
716 picture_t
*p_tmp
= video_new_buffer_encoder( id
->p_encoder
);
717 if( likely( p_tmp
) )
719 picture_Copy( p_tmp
, p_pic
);
720 picture_Release( p_pic
);
724 if( unlikely( !p_sys
->p_spu_blend
) )
725 p_sys
->p_spu_blend
= filter_NewBlend( VLC_OBJECT( p_sys
->p_spu
), &fmt
);
726 if( likely( p_sys
->p_spu_blend
) )
727 picture_BlendSubpicture( p_pic
, p_sys
->p_spu_blend
, p_subpic
);
728 subpicture_Delete( p_subpic
);
732 if( p_sys
->i_threads
== 0 )
736 p_block
= id
->p_encoder
->pf_encode_video( id
->p_encoder
, p_pic
);
737 block_ChainAppend( out
, p_block
);
740 if( p_sys
->i_threads
)
742 vlc_sem_wait( &p_sys
->picture_pool_has_room
);
743 vlc_mutex_lock( &p_sys
->lock_out
);
744 picture_fifo_Push( p_sys
->pp_pics
, p_pic
);
745 vlc_cond_signal( &p_sys
->cond
);
746 vlc_mutex_unlock( &p_sys
->lock_out
);
749 if ( p_sys
->i_threads
== 0 )
750 picture_Release( p_pic
);
753 int transcode_video_process( sout_stream_t
*p_stream
, sout_stream_id_sys_t
*id
,
754 block_t
*in
, block_t
**out
)
756 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
758 bool b_error
= false;
760 int ret
= id
->p_decoder
->pf_decode( id
->p_decoder
, in
);
761 if( ret
!= VLCDEC_SUCCESS
)
764 picture_t
*p_pics
= transcode_dequeue_all_pics( id
);
770 picture_t
*p_pic
= p_pics
;
771 p_pics
= p_pics
->p_next
;
772 p_pic
->p_next
= NULL
;
776 picture_Release( p_pic
);
781 id
->p_encoder
->p_module
&&
782 !video_format_IsSimilar( &id
->fmt_input_video
, &id
->p_decoder
->fmt_out
.video
)
786 msg_Info( p_stream
, "aspect-ratio changed, reiniting. %i -> %i : %i -> %i.",
787 id
->fmt_input_video
.i_sar_num
, id
->p_decoder
->fmt_out
.video
.i_sar_num
,
788 id
->fmt_input_video
.i_sar_den
, id
->p_decoder
->fmt_out
.video
.i_sar_den
792 filter_chain_Delete( id
->p_f_chain
);
793 id
->p_f_chain
= NULL
;
795 filter_chain_Delete( id
->p_uf_chain
);
796 id
->p_uf_chain
= NULL
;
798 /* Reinitialize filters */
799 id
->p_encoder
->fmt_out
.video
.i_visible_width
= p_sys
->i_width
& ~1;
800 id
->p_encoder
->fmt_out
.video
.i_visible_height
= p_sys
->i_height
& ~1;
801 id
->p_encoder
->fmt_out
.video
.i_sar_num
= id
->p_encoder
->fmt_out
.video
.i_sar_den
= 0;
803 transcode_video_encoder_init( p_stream
, id
);
804 transcode_video_filter_init( p_stream
, id
);
805 conversion_video_filter_append( id
);
806 memcpy( &id
->fmt_input_video
, &id
->p_decoder
->fmt_out
.video
, sizeof(video_format_t
));
810 if( unlikely( !id
->p_encoder
->p_module
) )
813 filter_chain_Delete( id
->p_f_chain
);
815 filter_chain_Delete( id
->p_uf_chain
);
816 id
->p_f_chain
= id
->p_uf_chain
= NULL
;
818 transcode_video_encoder_init( p_stream
, id
);
819 transcode_video_filter_init( p_stream
, id
);
820 conversion_video_filter_append( id
);
821 memcpy( &id
->fmt_input_video
, &id
->p_decoder
->fmt_out
.video
, sizeof(video_format_t
));
823 if( transcode_video_encoder_open( p_stream
, id
) != VLC_SUCCESS
)
825 picture_Release( p_pic
);
826 transcode_video_close( p_stream
, id
);
827 id
->b_transcode
= false;
833 /* Run the filter and output chains; first with the picture,
834 * and then with NULL as many times as we need until they
835 * stop outputting frames.
838 picture_t
*p_filtered_pic
= p_pic
;
840 /* Run filter chain */
842 p_filtered_pic
= filter_chain_VideoFilter( id
->p_f_chain
, p_filtered_pic
);
843 if( !p_filtered_pic
)
847 picture_t
*p_user_filtered_pic
= p_filtered_pic
;
849 /* Run user specified filter chain */
851 p_user_filtered_pic
= filter_chain_VideoFilter( id
->p_uf_chain
, p_user_filtered_pic
);
852 if( !p_user_filtered_pic
)
855 OutputFrame( p_stream
, p_user_filtered_pic
, id
, out
);
857 p_filtered_pic
= NULL
;
864 if( p_sys
->i_threads
>= 1 )
866 /* Pick up any return data the encoder thread wants to output. */
867 vlc_mutex_lock( &p_sys
->lock_out
);
868 *out
= p_sys
->p_buffers
;
869 p_sys
->p_buffers
= NULL
;
870 vlc_mutex_unlock( &p_sys
->lock_out
);
874 if( unlikely( in
== NULL
) )
876 if( p_sys
->i_threads
== 0 )
878 if( id
->p_encoder
->p_module
)
882 p_block
= id
->p_encoder
->pf_encode_video(id
->p_encoder
, NULL
);
883 block_ChainAppend( out
, p_block
);
889 msg_Dbg( p_stream
, "Flushing thread and waiting that");
890 vlc_mutex_lock( &p_stream
->p_sys
->lock_out
);
891 p_stream
->p_sys
->b_abort
= true;
892 vlc_cond_signal( &p_stream
->p_sys
->cond
);
893 vlc_mutex_unlock( &p_stream
->p_sys
->lock_out
);
895 vlc_join( p_stream
->p_sys
->thread
, NULL
);
896 vlc_mutex_lock( &p_sys
->lock_out
);
897 *out
= p_sys
->p_buffers
;
898 p_sys
->p_buffers
= NULL
;
899 vlc_mutex_unlock( &p_sys
->lock_out
);
901 msg_Dbg( p_stream
, "Flushing done");
905 return b_error
? VLC_EGENERIC
: VLC_SUCCESS
;
908 bool transcode_video_add( sout_stream_t
*p_stream
, const es_format_t
*p_fmt
,
909 sout_stream_id_sys_t
*id
)
911 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
914 "creating video transcoding from fcc=`%4.4s' to fcc=`%4.4s'",
915 (char*)&p_fmt
->i_codec
, (char*)&p_sys
->i_vcodec
);
917 id
->fifo
.audio
.first
= NULL
;
918 id
->fifo
.audio
.last
= &id
->fifo
.audio
.first
;
920 /* Complete destination format */
921 id
->p_encoder
->fmt_out
.i_codec
= p_sys
->i_vcodec
;
922 id
->p_encoder
->fmt_out
.video
.i_visible_width
= p_sys
->i_width
& ~1;
923 id
->p_encoder
->fmt_out
.video
.i_visible_height
= p_sys
->i_height
& ~1;
924 id
->p_encoder
->fmt_out
.i_bitrate
= p_sys
->i_vbitrate
;
926 /* Build decoder -> filter -> encoder chain */
927 if( transcode_video_new( p_stream
, id
) )
929 msg_Err( p_stream
, "cannot create video chain" );
933 /* Stream will be added later on because we don't know
934 * all the characteristics of the decoded stream yet */
935 id
->b_transcode
= true;
939 id
->p_encoder
->fmt_in
.video
.i_frame_rate
= id
->p_encoder
->fmt_out
.video
.i_frame_rate
= (p_sys
->fps_num
);
940 id
->p_encoder
->fmt_in
.video
.i_frame_rate_base
= id
->p_encoder
->fmt_out
.video
.i_frame_rate_base
= (p_sys
->fps_den
? p_sys
->fps_den
: 1);