1 /*****************************************************************************
2 * switcher.c: MPEG2 video switcher module
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
36 #include <vlc_avcodec.h>
37 #include <vlc_filter.h>
40 #include <vlc_block.h>
43 #include <vlc_network.h>
46 #ifdef HAVE_LIBAVCODEC_AVCODEC_H
47 # include <libavcodec/avcodec.h>
48 #elif defined(HAVE_FFMPEG_AVCODEC_H)
49 # include <ffmpeg/avcodec.h>
54 #ifdef HAVE_POSTPROC_POSTPROCESS_H
55 # include <postproc/postprocess.h>
57 # include <libpostproc/postprocess.h>
60 #define SOUT_CFG_PREFIX "sout-switcher-"
61 #define MAX_PICTURES 10
63 #define MAX_THRESHOLD 99999999
65 /*****************************************************************************
67 *****************************************************************************/
68 static int Open ( vlc_object_t
* );
69 static void Close ( vlc_object_t
* );
71 static sout_stream_id_t
*Add( sout_stream_t
*, es_format_t
* );
72 static int Del( sout_stream_t
*, sout_stream_id_t
* );
73 static int Send( sout_stream_t
*, sout_stream_id_t
*, block_t
* );
75 static mtime_t
Process( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
77 static int UnpackFromFile( sout_stream_t
*p_stream
, const char *psz_file
,
78 int i_width
, int i_height
,
80 static void NetCommand( sout_stream_t
*p_stream
);
81 static mtime_t
VideoCommand( sout_stream_t
*p_stream
, sout_stream_id_t
*id
);
82 static block_t
*VideoGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
84 static block_t
*AudioGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
87 /*****************************************************************************
89 *****************************************************************************/
90 #define FILES_TEXT N_("Files")
91 #define FILES_LONGTEXT N_( \
92 "Full paths of the files separated by colons." )
93 #define SIZES_TEXT N_("Sizes")
94 #define SIZES_LONGTEXT N_( \
95 "List of sizes separated by colons (720x576:480x576)." )
96 #define RATIO_TEXT N_("Aspect ratio")
97 #define RATIO_LONGTEXT N_( \
98 "Aspect ratio (4:3, 16:9)." )
99 #define PORT_TEXT N_("Command UDP port")
100 #define PORT_LONGTEXT N_( \
101 "UDP port to listen to for commands." )
102 #define COMMAND_TEXT N_("Command")
103 #define COMMAND_LONGTEXT N_( \
104 "Initial command to execute." )
105 #define GOP_TEXT N_("GOP size")
106 #define GOP_LONGTEXT N_( \
107 "Number of P frames between two I frames." )
108 #define QSCALE_TEXT N_("Quantizer scale")
109 #define QSCALE_LONGTEXT N_( \
110 "Fixed quantizer scale to use." )
111 #define AUDIO_TEXT N_("Mute audio")
112 #define AUDIO_LONGTEXT N_( \
113 "Mute audio when command is not 0." )
116 set_description( N_("MPEG2 video switcher stream output") )
117 set_capability( "sout stream", 50 )
118 add_shortcut( "switcher" )
119 set_callbacks( Open
, Close
)
121 add_string( SOUT_CFG_PREFIX
"files", "", FILES_TEXT
,
122 FILES_LONGTEXT
, false )
123 add_string( SOUT_CFG_PREFIX
"sizes", "", SIZES_TEXT
,
124 SIZES_LONGTEXT
, false )
125 add_string( SOUT_CFG_PREFIX
"aspect-ratio", "4:3", RATIO_TEXT
,
126 RATIO_LONGTEXT
, false )
127 add_integer( SOUT_CFG_PREFIX
"port", 5001, NULL
,
128 PORT_TEXT
, PORT_LONGTEXT
, true )
129 add_integer( SOUT_CFG_PREFIX
"command", 0, NULL
,
130 COMMAND_TEXT
, COMMAND_LONGTEXT
, true )
131 add_integer( SOUT_CFG_PREFIX
"gop", 8, NULL
,
132 GOP_TEXT
, GOP_LONGTEXT
, true )
133 add_integer( SOUT_CFG_PREFIX
"qscale", 5, NULL
,
134 QSCALE_TEXT
, QSCALE_LONGTEXT
, true )
135 add_bool( SOUT_CFG_PREFIX
"mute-audio", true, NULL
,
136 AUDIO_TEXT
, AUDIO_LONGTEXT
, true )
139 static const char *const ppsz_sout_options
[] = {
140 "files", "sizes", "aspect-ratio", "port", "command", "gop", "qscale",
144 struct sout_stream_sys_t
149 sout_stream_id_t
*pp_audio_ids
[MAX_AUDIO
];
153 picture_t p_pictures
[MAX_PICTURES
];
158 int i_cmd
, i_old_cmd
;
161 struct sout_stream_id_t
164 bool b_switcher_video
;
165 bool b_switcher_audio
;
171 AVCodecContext
*ff_enc_c
;
173 uint8_t *p_buffer_out
;
178 /*****************************************************************************
180 *****************************************************************************/
181 static int Open( vlc_object_t
*p_this
)
183 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
184 sout_stream_sys_t
*p_sys
;
186 char *psz_files
, *psz_sizes
;
187 int i_height
= 0, i_width
= 0;
189 p_sys
= calloc( 1, sizeof(sout_stream_sys_t
) );
193 if( !p_stream
->p_next
)
195 msg_Err( p_stream
, "cannot create chain" );
200 config_ChainParse( p_stream
, SOUT_CFG_PREFIX
, ppsz_sout_options
,
203 var_Get( p_stream
, SOUT_CFG_PREFIX
"files", &val
);
204 psz_files
= val
.psz_string
;
205 var_Get( p_stream
, SOUT_CFG_PREFIX
"sizes", &val
);
206 psz_sizes
= val
.psz_string
;
208 p_sys
->i_nb_pictures
= 0;
209 while ( psz_files
&& *psz_files
)
211 char * psz_file
= psz_files
;
212 char * psz_size
= psz_sizes
;
214 while ( *psz_files
&& *psz_files
!= ':' )
216 if ( *psz_files
== ':' )
221 while ( *psz_sizes
&& *psz_sizes
!= ':' )
223 if ( *psz_sizes
== ':' )
225 if ( sscanf( psz_size
, "%dx%d", &i_width
, &i_height
) != 2 )
227 msg_Err( p_stream
, "bad size %s for file %s", psz_size
,
234 if ( UnpackFromFile( p_stream
, psz_file
, i_width
, i_height
,
235 &p_sys
->p_pictures
[p_sys
->i_nb_pictures
] ) < 0 )
240 p_sys
->i_nb_pictures
++;
243 var_Get( p_stream
, SOUT_CFG_PREFIX
"aspect-ratio", &val
);
244 if ( val
.psz_string
)
246 char *psz_parser
= strchr( val
.psz_string
, ':' );
250 *psz_parser
++ = '\0';
251 p_sys
->i_aspect
= atoi( val
.psz_string
) * VOUT_ASPECT_FACTOR
252 / atoi( psz_parser
);
256 msg_Warn( p_stream
, "bad aspect ratio %s", val
.psz_string
);
257 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
260 free( val
.psz_string
);
264 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
267 var_Get( p_stream
, SOUT_CFG_PREFIX
"port", &val
);
268 p_sys
->i_fd
= net_ListenUDP1( VLC_OBJECT(p_stream
), NULL
, val
.i_int
);
269 if ( p_sys
->i_fd
< 0 )
275 var_Get( p_stream
, SOUT_CFG_PREFIX
"command", &val
);
276 p_sys
->i_cmd
= val
.i_int
;
277 p_sys
->i_old_cmd
= 0;
279 var_Get( p_stream
, SOUT_CFG_PREFIX
"gop", &val
);
280 p_sys
->i_gop
= val
.i_int
;
282 var_Get( p_stream
, SOUT_CFG_PREFIX
"qscale", &val
);
283 p_sys
->i_qscale
= val
.i_int
;
285 var_Get( p_stream
, SOUT_CFG_PREFIX
"mute-audio", &val
);
286 p_sys
->b_audio
= val
.b_bool
;
288 p_stream
->pf_add
= Add
;
289 p_stream
->pf_del
= Del
;
290 p_stream
->pf_send
= Send
;
291 p_stream
->p_sys
= p_sys
;
294 avcodec_register_all();
299 /*****************************************************************************
301 *****************************************************************************/
302 static void Close( vlc_object_t
* p_this
)
304 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
305 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
310 /*****************************************************************************
311 * Add: Add an input elementary stream
312 *****************************************************************************/
313 static sout_stream_id_t
*Add( sout_stream_t
*p_stream
, es_format_t
*p_fmt
)
315 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
316 sout_stream_id_t
*id
;
318 id
= calloc( 1, sizeof( sout_stream_id_t
) );
322 if( p_fmt
->i_cat
== VIDEO_ES
&&
323 ( p_fmt
->i_codec
== VLC_CODEC_MPGV
||
324 p_fmt
->i_codec
== VLC_FOURCC('f', 'a', 'k', 'e') ) )
326 id
->b_switcher_video
= true;
327 p_fmt
->i_codec
= VLC_CODEC_MPGV
;
328 msg_Dbg( p_stream
, "creating video switcher for fcc=`%4.4s' cmd:%d",
329 (char*)&p_fmt
->i_codec
, p_sys
->i_cmd
);
331 else if ( p_fmt
->i_cat
== AUDIO_ES
&&
332 p_fmt
->i_codec
== VLC_CODEC_MPGA
&&
335 int i_ff_codec
= CODEC_ID_MP2
;
338 id
->b_switcher_audio
= true;
339 msg_Dbg( p_stream
, "creating audio switcher for fcc=`%4.4s' cmd:%d",
340 (char*)&p_fmt
->i_codec
, p_sys
->i_cmd
);
342 /* Allocate the encoder right now. */
343 if( i_ff_codec
== 0 )
345 msg_Err( p_stream
, "cannot find encoder" );
350 id
->ff_enc
= avcodec_find_encoder( i_ff_codec
);
353 msg_Err( p_stream
, "cannot find encoder (avcodec)" );
358 id
->ff_enc_c
= avcodec_alloc_context();
360 /* Set CPU capabilities */
361 unsigned i_cpu
= vlc_CPU();
362 id
->ff_enc_c
->dsp_mask
= 0;
363 if( !(i_cpu
& CPU_CAPABILITY_MMX
) )
365 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMX
;
367 if( !(i_cpu
& CPU_CAPABILITY_MMXEXT
) )
369 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMXEXT
;
371 if( !(i_cpu
& CPU_CAPABILITY_3DNOW
) )
373 id
->ff_enc_c
->dsp_mask
|= FF_MM_3DNOW
;
375 if( !(i_cpu
& CPU_CAPABILITY_SSE
) )
377 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE
;
378 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE2
;
381 id
->ff_enc_c
->sample_rate
= p_fmt
->audio
.i_rate
;
382 id
->ff_enc_c
->channels
= p_fmt
->audio
.i_channels
;
383 id
->ff_enc_c
->bit_rate
= p_fmt
->i_bitrate
;
386 if( avcodec_open( id
->ff_enc_c
, id
->ff_enc
) )
388 vlc_avcodec_unlock();
389 msg_Err( p_stream
, "cannot open encoder" );
390 av_free( id
->ff_enc_c
);
394 vlc_avcodec_unlock();
396 id
->p_buffer_out
= malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE
* 2 );
397 id
->p_samples
= calloc( id
->ff_enc_c
->frame_size
* p_fmt
->audio
.i_channels
,
399 if( !id
->p_buffer_out
|| !id
->p_samples
)
402 for( i
= 0; i
< MAX_AUDIO
; i
++ )
404 if( p_sys
->pp_audio_ids
[i
] == NULL
)
406 p_sys
->pp_audio_ids
[i
] = id
;
412 msg_Err( p_stream
, "too many audio streams!" );
418 msg_Dbg( p_stream
, "do not know what to do when switching (fcc=`%4.4s')",
419 (char*)&p_fmt
->i_codec
);
423 memcpy( &id
->f_src
, p_fmt
, sizeof( es_format_t
) );
425 /* open output stream */
426 id
->id
= p_stream
->p_next
->pf_add( p_stream
->p_next
, p_fmt
);
433 avcodec_close( id
->ff_enc_c
);
434 vlc_avcodec_unlock();
435 free( id
->p_samples
);
436 free( id
->p_buffer_out
);
437 av_free( id
->ff_enc_c
);
442 /*****************************************************************************
443 * Del: Del an elementary stream
444 *****************************************************************************/
445 static int Del( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
447 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
449 if ( id
->b_switcher_audio
)
452 for ( i
= 0; i
< MAX_AUDIO
; i
++ )
454 if ( p_sys
->pp_audio_ids
[i
] == id
)
456 p_sys
->pp_audio_ids
[i
] = NULL
;
465 avcodec_close( id
->ff_enc_c
);
466 vlc_avcodec_unlock();
467 av_free( id
->ff_enc_c
);
468 av_free( id
->p_frame
);
469 free( id
->p_buffer_out
);
474 p_stream
->p_next
->pf_del( p_stream
->p_next
, id
->id
);
481 /*****************************************************************************
482 * Send: Process an input packet
483 *****************************************************************************/
484 static int Send( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
487 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
491 block_Release( p_buffer
);
495 if ( !id
->b_switcher_video
&& !id
->b_switcher_audio
)
497 return p_stream
->p_next
->pf_send( p_stream
->p_next
, id
->id
, p_buffer
);
500 block_ChainAppend( &id
->p_queued
, p_buffer
);
502 if ( id
->b_switcher_video
)
504 /* Check for commands for every video frame. */
505 NetCommand( p_stream
);
507 while ( id
->p_queued
!= NULL
)
512 if ( p_sys
->i_old_cmd
!= p_sys
->i_cmd
)
514 i_dts
= VideoCommand( p_stream
, id
);
517 i_dts
= Process( p_stream
, id
, i_dts
);
519 for ( i
= 0; i
< MAX_AUDIO
; i
++ )
521 if ( p_sys
->pp_audio_ids
[i
] != NULL
)
522 Process( p_stream
, p_sys
->pp_audio_ids
[i
], i_dts
);
530 /*****************************************************************************
531 * Process: Process and dispatch buffers
532 *****************************************************************************/
533 static mtime_t
Process( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
536 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
538 block_t
*p_blocks
= NULL
;
539 block_t
*p_blocks_out
= NULL
;
541 /* Find out the blocks we need. */
542 while ( id
->p_queued
!= NULL
543 && (!i_max_dts
|| id
->p_queued
->i_dts
<= i_max_dts
) )
545 block_t
*p_next
= id
->p_queued
->p_next
;
546 id
->p_queued
->p_next
= NULL
;
547 i_dts
= id
->p_queued
->i_dts
;
548 block_ChainAppend( &p_blocks
, id
->p_queued
);
549 id
->p_queued
= p_next
;
552 if ( p_sys
->i_old_cmd
== 0 )
555 if ( p_blocks
!= NULL
)
556 p_stream
->p_next
->pf_send( p_stream
->p_next
, id
->id
, p_blocks
);
560 if ( p_sys
->i_old_cmd
== -1 )
562 /* No output at all */
563 while ( p_blocks
!= NULL
)
565 block_t
* p_next
= p_blocks
->p_next
;
566 block_Release( p_blocks
);
572 while ( p_blocks
!= NULL
)
574 block_t
* p_next
= p_blocks
->p_next
;
577 if ( id
->b_switcher_video
)
579 p_out
= VideoGetBuffer( p_stream
, id
, p_blocks
);
583 p_out
= AudioGetBuffer( p_stream
, id
, p_blocks
);
588 block_ChainAppend( &p_blocks_out
, p_out
);
592 if ( p_blocks_out
!= NULL
)
593 p_stream
->p_next
->pf_send( p_stream
->p_next
, id
->id
, p_blocks_out
);
597 /*****************************************************************************
598 * UnpackFromFile: Read a YUV picture and store it in our format
599 *****************************************************************************/
600 static int UnpackFromFile( sout_stream_t
*p_stream
, const char *psz_file
,
601 int i_width
, int i_height
,
605 FILE *p_file
= vlc_fopen( psz_file
, "r" );
607 if ( p_file
== NULL
)
609 msg_Err( p_stream
, "file %s not found", psz_file
);
613 if( picture_Setup( p_pic
, VLC_CODEC_I420
,
614 i_width
, i_height
, 1, 1 ) )
616 msg_Err( p_stream
, "unknown chroma" );
619 for ( i
= 0; i
< p_pic
->i_planes
; i
++ )
621 p_pic
->p
[i
].p_pixels
= malloc( p_pic
->p
[i
].i_lines
*
622 p_pic
->p
[i
].i_pitch
);
623 memset( p_pic
->p
[i
].p_pixels
, 0, p_pic
->p
[i
].i_lines
*
624 p_pic
->p
[i
].i_pitch
);
627 for ( i
= 0; i
< i_height
; i
++ )
630 uint8_t p_buffer
[i_width
* 2];
631 uint8_t *p_char
= p_buffer
;
632 uint8_t *p_y
= &p_pic
->p
[0].p_pixels
[i
* p_pic
->p
[0].i_pitch
];
633 uint8_t *p_u
= &p_pic
->p
[1].p_pixels
[i
/2 * p_pic
->p
[1].i_pitch
];
634 uint8_t *p_v
= &p_pic
->p
[2].p_pixels
[i
/2 * p_pic
->p
[2].i_pitch
];
636 if ( fread( p_buffer
, 2, i_width
, p_file
) != (size_t)i_width
)
638 msg_Err( p_stream
, "premature end of file %s", psz_file
);
640 for ( i
= 0; i
< p_pic
->i_planes
; i
++ )
642 free( p_pic
->p
[i
].p_pixels
);
648 for ( j
= 0; j
< i_width
; j
++ )
650 uint8_t **pp_chroma
= i_chroma
? &p_v
: &p_u
;
651 i_chroma
= !i_chroma
;
653 **pp_chroma
= (**pp_chroma
+ *p_char
+ 1) / 2;
655 **pp_chroma
= *p_char
;
666 /*****************************************************************************
667 * NetCommand: Get a command from the network
668 *****************************************************************************/
669 static void NetCommand( sout_stream_t
*p_stream
)
671 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
673 int i_len
= recv( p_sys
->i_fd
, psz_buffer
, sizeof( psz_buffer
) - 1, 0 );
677 psz_buffer
[i_len
] = '\0';
678 int i_cmd
= strtol( psz_buffer
, NULL
, 0 );
679 if ( i_cmd
< -1 || i_cmd
> p_sys
->i_nb_pictures
)
681 msg_Err( p_stream
, "got a wrong command (%d)", i_cmd
);
685 p_sys
->i_cmd
= i_cmd
;
687 msg_Dbg( p_stream
, "new command: %d old:%d", p_sys
->i_cmd
,
692 /*****************************************************************************
693 * VideoCommand: Create/Delete a video encoder
694 *****************************************************************************/
695 static mtime_t
VideoCommand( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
697 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
699 if ( p_sys
->i_cmd
== 0 && !(id
->p_queued
->i_flags
& BLOCK_FLAG_TYPE_I
) )
701 mtime_t i_dts
= id
->p_queued
->i_dts
;
702 block_t
*p_block
= id
->p_queued
->p_next
;
704 while ( p_block
!= NULL
)
706 if ( p_block
->i_flags
& BLOCK_FLAG_TYPE_I
)
708 i_dts
= p_block
->i_dts
;
709 p_block
= p_block
->p_next
;
715 p_sys
->i_old_cmd
= p_sys
->i_cmd
;
720 avcodec_close( id
->ff_enc_c
);
721 vlc_avcodec_unlock();
722 av_free( id
->ff_enc_c
);
723 av_free( id
->p_frame
);
724 free( id
->p_buffer_out
);
728 if ( p_sys
->i_cmd
> 0 )
730 /* Create a new encoder. */
731 int i_ff_codec
= CODEC_ID_MPEG2VIDEO
;
732 int i_aspect_num
, i_aspect_den
;
734 if( i_ff_codec
== 0 )
736 msg_Err( p_stream
, "cannot find encoder" );
740 id
->ff_enc
= avcodec_find_encoder( i_ff_codec
);
743 msg_Err( p_stream
, "cannot find encoder (avcodec)" );
747 id
->ff_enc_c
= avcodec_alloc_context();
749 /* Set CPU capabilities */
750 unsigned i_cpu
= vlc_CPU();
751 id
->ff_enc_c
->dsp_mask
= 0;
752 if( !(i_cpu
& CPU_CAPABILITY_MMX
) )
754 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMX
;
756 if( !(i_cpu
& CPU_CAPABILITY_MMXEXT
) )
758 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMXEXT
;
760 if( !(i_cpu
& CPU_CAPABILITY_3DNOW
) )
762 id
->ff_enc_c
->dsp_mask
|= FF_MM_3DNOW
;
764 if( !(i_cpu
& CPU_CAPABILITY_SSE
) )
766 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE
;
767 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE2
;
770 id
->ff_enc_c
->width
= p_sys
->p_pictures
[p_sys
->i_cmd
-1].format
.i_width
;
771 id
->ff_enc_c
->height
= p_sys
->p_pictures
[p_sys
->i_cmd
-1].format
.i_height
;
772 av_reduce( &i_aspect_num
, &i_aspect_den
,
774 VOUT_ASPECT_FACTOR
, 1 << 30 /* something big */ );
775 av_reduce( &id
->ff_enc_c
->sample_aspect_ratio
.num
,
776 &id
->ff_enc_c
->sample_aspect_ratio
.den
,
777 i_aspect_num
* (int64_t)id
->ff_enc_c
->height
,
778 i_aspect_den
* (int64_t)id
->ff_enc_c
->width
, 1 << 30 );
780 #if LIBAVCODEC_BUILD >= 4754
781 id
->ff_enc_c
->time_base
.num
= 1;
782 id
->ff_enc_c
->time_base
.den
= 25; /* FIXME */
784 id
->ff_enc_c
->frame_rate
= 25; /* FIXME */
785 id
->ff_enc_c
->frame_rate_base
= 1;
788 id
->ff_enc_c
->gop_size
= 200;
789 id
->ff_enc_c
->max_b_frames
= 0;
791 id
->ff_enc_c
->flags
|= CODEC_FLAG_QSCALE
792 | CODEC_FLAG_INPUT_PRESERVED
793 | CODEC_FLAG_LOW_DELAY
;
795 id
->ff_enc_c
->mb_decision
= FF_MB_DECISION_SIMPLE
;
796 id
->ff_enc_c
->pix_fmt
= PIX_FMT_YUV420P
;
799 if( avcodec_open( id
->ff_enc_c
, id
->ff_enc
) )
801 vlc_avcodec_unlock();
802 msg_Err( p_stream
, "cannot open encoder" );
805 vlc_avcodec_unlock();
807 id
->p_buffer_out
= malloc( id
->ff_enc_c
->width
* id
->ff_enc_c
->height
* 3 );
808 id
->p_frame
= avcodec_alloc_frame();
809 id
->p_frame
->linesize
[0] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[0].i_pitch
;
810 id
->p_frame
->linesize
[1] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[1].i_pitch
;
811 id
->p_frame
->linesize
[2] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[2].i_pitch
;
812 id
->p_frame
->data
[0] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[0].p_pixels
;
813 id
->p_frame
->data
[1] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[1].p_pixels
;
814 id
->p_frame
->data
[2] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[2].p_pixels
;
816 id
->i_nb_pred
= p_sys
->i_gop
;
822 /*****************************************************************************
823 * VideoGetBuffer: Build an alternate video buffer
824 *****************************************************************************/
825 static block_t
*VideoGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
828 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
832 id
->p_frame
->quality
= p_sys
->i_qscale
* powf(2.0, FF_LAMBDA_SHIFT
+ 7.0)
834 id
->p_frame
->interlaced_frame
= 0;
835 id
->p_frame
->top_field_first
= 1;
836 id
->p_frame
->pts
= p_buffer
->i_dts
;
838 if ( id
->i_nb_pred
>= p_sys
->i_gop
)
840 id
->p_frame
->pict_type
= FF_I_TYPE
;
842 id
->p_frame
->me_threshold
= 0;
843 id
->p_frame
->mb_threshold
= 0;
849 id
->p_frame
->pict_type
= FF_P_TYPE
;
851 if ( id
->p_frame
->mb_type
!= NULL
)
853 id
->p_frame
->me_threshold
= MAX_THRESHOLD
;
854 id
->p_frame
->mb_threshold
= MAX_THRESHOLD
;
860 i_out
= avcodec_encode_video( id
->ff_enc_c
, id
->p_buffer_out
,
861 id
->ff_enc_c
->width
* id
->ff_enc_c
->height
* 3,
868 if ( id
->p_frame
->mb_type
== NULL
869 && id
->ff_enc_c
->coded_frame
->pict_type
!= FF_I_TYPE
)
871 int mb_width
= (id
->ff_enc_c
->width
+ 15) / 16;
872 int mb_height
= (id
->ff_enc_c
->height
+ 15) / 16;
873 int h_chroma_shift
, v_chroma_shift
;
876 avcodec_get_chroma_sub_sample( id
->ff_enc_c
->pix_fmt
, &h_chroma_shift
,
879 id
->p_frame
->motion_subsample_log2
880 = id
->ff_enc_c
->coded_frame
->motion_subsample_log2
;
881 id
->p_frame
->mb_type
= malloc( ((mb_width
+ 1) * (mb_height
+ 1) + 1)
882 * sizeof(uint32_t) );
883 vlc_memcpy( id
->p_frame
->mb_type
, id
->ff_enc_c
->coded_frame
->mb_type
,
884 (mb_width
+ 1) * mb_height
* sizeof(id
->p_frame
->mb_type
[0]));
886 for ( i
= 0; i
< 2; i
++ )
888 int stride
= ((16 * mb_width
)
889 >> id
->ff_enc_c
->coded_frame
->motion_subsample_log2
) + 1;
890 int height
= ((16 * mb_height
)
891 >> id
->ff_enc_c
->coded_frame
->motion_subsample_log2
);
892 int b8_stride
= mb_width
* 2 + 1;
894 if ( id
->ff_enc_c
->coded_frame
->motion_val
[i
] )
896 id
->p_frame
->motion_val
[i
] = malloc( 2 * stride
* height
898 vlc_memcpy( id
->p_frame
->motion_val
[i
],
899 id
->ff_enc_c
->coded_frame
->motion_val
[i
],
900 2 * stride
* height
* sizeof(int16_t) );
902 if ( id
->ff_enc_c
->coded_frame
->ref_index
[i
] )
904 id
->p_frame
->ref_index
[i
] = malloc( b8_stride
* 2 * mb_height
906 vlc_memcpy( id
->p_frame
->ref_index
[i
],
907 id
->ff_enc_c
->coded_frame
->ref_index
[i
],
908 b8_stride
* 2 * mb_height
* sizeof(int8_t));
914 p_out
= block_New( p_stream
, i_out
);
915 vlc_memcpy( p_out
->p_buffer
, id
->p_buffer_out
, i_out
);
916 p_out
->i_length
= p_buffer
->i_length
;
917 p_out
->i_pts
= p_buffer
->i_dts
;
918 p_out
->i_dts
= p_buffer
->i_dts
;
919 p_out
->i_rate
= p_buffer
->i_rate
;
921 switch ( id
->ff_enc_c
->coded_frame
->pict_type
)
924 p_out
->i_flags
|= BLOCK_FLAG_TYPE_I
;
927 p_out
->i_flags
|= BLOCK_FLAG_TYPE_P
;
930 p_out
->i_flags
|= BLOCK_FLAG_TYPE_B
;
936 block_Release( p_buffer
);
941 /*****************************************************************************
942 * AudioGetBuffer: Build an alternate audio buffer
943 *****************************************************************************/
944 static block_t
*AudioGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
951 i_out
= avcodec_encode_audio( id
->ff_enc_c
, id
->p_buffer_out
,
952 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE
,
958 p_out
= block_New( p_stream
, i_out
);
959 vlc_memcpy( p_out
->p_buffer
, id
->p_buffer_out
, i_out
);
960 p_out
->i_length
= p_buffer
->i_length
;
961 p_out
->i_pts
= p_buffer
->i_dts
;
962 p_out
->i_dts
= p_buffer
->i_dts
;
963 p_out
->i_rate
= p_buffer
->i_rate
;
965 block_Release( p_buffer
);