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>
38 #include <vlc_charset.h>
39 #include <vlc_network.h>
42 #ifdef HAVE_LIBAVCODEC_AVCODEC_H
43 # include <libavcodec/avcodec.h>
44 #elif defined(HAVE_FFMPEG_AVCODEC_H)
45 # include <ffmpeg/avcodec.h>
50 #ifdef HAVE_POSTPROC_POSTPROCESS_H
51 # include <postproc/postprocess.h>
53 # include <libpostproc/postprocess.h>
56 #define SOUT_CFG_PREFIX "sout-switcher-"
57 #define MAX_PICTURES 10
59 #define MAX_THRESHOLD 99999999
61 /*****************************************************************************
63 *****************************************************************************/
64 static int Open ( vlc_object_t
* );
65 static void Close ( vlc_object_t
* );
67 static sout_stream_id_t
*Add( sout_stream_t
*, es_format_t
* );
68 static int Del( sout_stream_t
*, sout_stream_id_t
* );
69 static int Send( sout_stream_t
*, sout_stream_id_t
*, block_t
* );
71 static mtime_t
Process( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
73 static int UnpackFromFile( sout_stream_t
*p_stream
, const char *psz_file
,
74 int i_width
, int i_height
,
76 static void NetCommand( sout_stream_t
*p_stream
);
77 static mtime_t
VideoCommand( sout_stream_t
*p_stream
, sout_stream_id_t
*id
);
78 static block_t
*VideoGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
80 static block_t
*AudioGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
83 /*****************************************************************************
85 *****************************************************************************/
86 #define FILES_TEXT N_("Files")
87 #define FILES_LONGTEXT N_( \
88 "Full paths of the files separated by colons." )
89 #define SIZES_TEXT N_("Sizes")
90 #define SIZES_LONGTEXT N_( \
91 "List of sizes separated by colons (720x576:480x576)." )
92 #define RATIO_TEXT N_("Aspect ratio")
93 #define RATIO_LONGTEXT N_( \
94 "Aspect ratio (4:3, 16:9)." )
95 #define PORT_TEXT N_("Command UDP port")
96 #define PORT_LONGTEXT N_( \
97 "UDP port to listen to for commands." )
98 #define COMMAND_TEXT N_("Command")
99 #define COMMAND_LONGTEXT N_( \
100 "Initial command to execute." )
101 #define GOP_TEXT N_("GOP size")
102 #define GOP_LONGTEXT N_( \
103 "Number of P frames between two I frames." )
104 #define QSCALE_TEXT N_("Quantizer scale")
105 #define QSCALE_LONGTEXT N_( \
106 "Fixed quantizer scale to use." )
107 #define AUDIO_TEXT N_("Mute audio")
108 #define AUDIO_LONGTEXT N_( \
109 "Mute audio when command is not 0." )
112 set_description( N_("MPEG2 video switcher stream output") )
113 set_capability( "sout stream", 50 )
114 add_shortcut( "switcher" )
115 set_callbacks( Open
, Close
)
117 add_string( SOUT_CFG_PREFIX
"files", "", NULL
, FILES_TEXT
,
118 FILES_LONGTEXT
, false );
119 add_string( SOUT_CFG_PREFIX
"sizes", "", NULL
, SIZES_TEXT
,
120 SIZES_LONGTEXT
, false );
121 add_string( SOUT_CFG_PREFIX
"aspect-ratio", "4:3", NULL
, RATIO_TEXT
,
122 RATIO_LONGTEXT
, false );
123 add_integer( SOUT_CFG_PREFIX
"port", 5001, NULL
,
124 PORT_TEXT
, PORT_LONGTEXT
, true );
125 add_integer( SOUT_CFG_PREFIX
"command", 0, NULL
,
126 COMMAND_TEXT
, COMMAND_LONGTEXT
, true );
127 add_integer( SOUT_CFG_PREFIX
"gop", 8, NULL
,
128 GOP_TEXT
, GOP_LONGTEXT
, true );
129 add_integer( SOUT_CFG_PREFIX
"qscale", 5, NULL
,
130 QSCALE_TEXT
, QSCALE_LONGTEXT
, true );
131 add_bool( SOUT_CFG_PREFIX
"mute-audio", 1, NULL
,
132 AUDIO_TEXT
, AUDIO_LONGTEXT
, true );
135 static const char *const ppsz_sout_options
[] = {
136 "files", "sizes", "aspect-ratio", "port", "command", "gop", "qscale",
140 struct sout_stream_sys_t
142 sout_stream_t
*p_out
;
146 sout_stream_id_t
*pp_audio_ids
[MAX_AUDIO
];
150 picture_t p_pictures
[MAX_PICTURES
];
155 int i_cmd
, i_old_cmd
;
158 struct sout_stream_id_t
161 bool b_switcher_video
;
162 bool b_switcher_audio
;
168 AVCodecContext
*ff_enc_c
;
170 uint8_t *p_buffer_out
;
175 /*****************************************************************************
177 *****************************************************************************/
178 static int Open( vlc_object_t
*p_this
)
180 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
181 sout_stream_sys_t
*p_sys
;
183 char *psz_files
, *psz_sizes
;
184 int i_height
= 0, i_width
= 0;
186 p_sys
= malloc( sizeof(sout_stream_sys_t
) );
187 memset( p_sys
, 0, sizeof(sout_stream_sys_t
) );
189 p_sys
->p_out
= sout_StreamNew( p_stream
->p_sout
, p_stream
->psz_next
);
192 msg_Err( p_stream
, "cannot create chain" );
197 config_ChainParse( p_stream
, SOUT_CFG_PREFIX
, ppsz_sout_options
,
200 var_Get( p_stream
, SOUT_CFG_PREFIX
"files", &val
);
201 psz_files
= val
.psz_string
;
202 var_Get( p_stream
, SOUT_CFG_PREFIX
"sizes", &val
);
203 psz_sizes
= val
.psz_string
;
205 p_sys
->i_nb_pictures
= 0;
206 while ( psz_files
&& *psz_files
)
208 char * psz_file
= psz_files
;
209 char * psz_size
= psz_sizes
;
211 while ( *psz_files
&& *psz_files
!= ':' )
213 if ( *psz_files
== ':' )
218 while ( *psz_sizes
&& *psz_sizes
!= ':' )
220 if ( *psz_sizes
== ':' )
222 if ( sscanf( psz_size
, "%dx%d", &i_width
, &i_height
) != 2 )
224 msg_Err( p_stream
, "bad size %s for file %s", psz_size
,
231 if ( UnpackFromFile( p_stream
, psz_file
, i_width
, i_height
,
232 &p_sys
->p_pictures
[p_sys
->i_nb_pictures
] ) < 0 )
237 p_sys
->i_nb_pictures
++;
240 var_Get( p_stream
, SOUT_CFG_PREFIX
"aspect-ratio", &val
);
241 if ( val
.psz_string
)
243 char *psz_parser
= strchr( val
.psz_string
, ':' );
247 *psz_parser
++ = '\0';
248 p_sys
->i_aspect
= atoi( val
.psz_string
) * VOUT_ASPECT_FACTOR
249 / atoi( psz_parser
);
253 msg_Warn( p_stream
, "bad aspect ratio %s", val
.psz_string
);
254 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
257 free( val
.psz_string
);
261 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
264 var_Get( p_stream
, SOUT_CFG_PREFIX
"port", &val
);
265 p_sys
->i_fd
= net_ListenUDP1( p_stream
, NULL
, val
.i_int
);
266 if ( p_sys
->i_fd
< 0 )
272 var_Get( p_stream
, SOUT_CFG_PREFIX
"command", &val
);
273 p_sys
->i_cmd
= val
.i_int
;
274 p_sys
->i_old_cmd
= 0;
276 var_Get( p_stream
, SOUT_CFG_PREFIX
"gop", &val
);
277 p_sys
->i_gop
= val
.i_int
;
279 var_Get( p_stream
, SOUT_CFG_PREFIX
"qscale", &val
);
280 p_sys
->i_qscale
= val
.i_int
;
282 var_Get( p_stream
, SOUT_CFG_PREFIX
"mute-audio", &val
);
283 p_sys
->b_audio
= val
.b_bool
;
285 p_stream
->pf_add
= Add
;
286 p_stream
->pf_del
= Del
;
287 p_stream
->pf_send
= Send
;
288 p_stream
->p_sys
= p_sys
;
291 avcodec_register_all();
296 /*****************************************************************************
298 *****************************************************************************/
299 static void Close( vlc_object_t
* p_this
)
301 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
302 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
304 sout_StreamDelete( p_sys
->p_out
);
309 /*****************************************************************************
310 * Add: Add an input elementary stream
311 *****************************************************************************/
312 static sout_stream_id_t
*Add( sout_stream_t
*p_stream
, es_format_t
*p_fmt
)
314 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
315 sout_stream_id_t
*id
;
317 id
= malloc( sizeof( sout_stream_id_t
) );
318 memset( id
, 0, sizeof( sout_stream_id_t
) );
321 if ( p_fmt
->i_cat
== VIDEO_ES
322 && (p_fmt
->i_codec
== VLC_FOURCC('m', 'p', 'g', 'v')
323 || p_fmt
->i_codec
== VLC_FOURCC('f', 'a', 'k', 'e')) )
325 id
->b_switcher_video
= true;
326 p_fmt
->i_codec
= VLC_FOURCC('m', 'p', 'g', 'v');
328 "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_FOURCC('m', 'p', 'g', 'a')
335 int i_ff_codec
= CODEC_ID_MP2
;
338 id
->b_switcher_audio
= true;
340 "creating audio switcher for fcc=`%4.4s' cmd:%d",
341 (char*)&p_fmt
->i_codec
, p_sys
->i_cmd
);
343 /* Allocate the encoder right now. */
344 if( i_ff_codec
== 0 )
346 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)" );
357 id
->ff_enc_c
= avcodec_alloc_context();
359 /* Set CPU capabilities */
360 unsigned i_cpu
= vlc_CPU();
361 id
->ff_enc_c
->dsp_mask
= 0;
362 if( !(i_cpu
& CPU_CAPABILITY_MMX
) )
364 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMX
;
366 if( !(i_cpu
& CPU_CAPABILITY_MMXEXT
) )
368 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMXEXT
;
370 if( !(i_cpu
& CPU_CAPABILITY_3DNOW
) )
372 id
->ff_enc_c
->dsp_mask
|= FF_MM_3DNOW
;
374 if( !(i_cpu
& CPU_CAPABILITY_SSE
) )
376 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE
;
377 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE2
;
380 id
->ff_enc_c
->sample_rate
= p_fmt
->audio
.i_rate
;
381 id
->ff_enc_c
->channels
= p_fmt
->audio
.i_channels
;
382 id
->ff_enc_c
->bit_rate
= p_fmt
->i_bitrate
;
384 if( avcodec_open( id
->ff_enc_c
, id
->ff_enc
) )
386 msg_Err( p_stream
, "cannot open encoder" );
390 id
->p_buffer_out
= malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE
* 2 );
391 id
->p_samples
= malloc( id
->ff_enc_c
->frame_size
392 * p_fmt
->audio
.i_channels
* sizeof(int16_t) );
393 memset( id
->p_samples
, 0,
394 id
->ff_enc_c
->frame_size
* p_fmt
->audio
.i_channels
397 for ( i
= 0; i
< MAX_AUDIO
; i
++ )
399 if ( p_sys
->pp_audio_ids
[i
] == NULL
)
401 p_sys
->pp_audio_ids
[i
] = id
;
405 if ( i
== MAX_AUDIO
)
407 msg_Err( p_stream
, "too many audio streams!" );
414 msg_Dbg( p_stream
, "do not know what to do when switching (fcc=`%4.4s')",
415 (char*)&p_fmt
->i_codec
);
419 memcpy( &id
->f_src
, p_fmt
, sizeof( es_format_t
) );
421 /* open output stream */
422 id
->id
= p_sys
->p_out
->pf_add( p_sys
->p_out
, p_fmt
);
424 if ( id
->id
== NULL
)
433 /*****************************************************************************
434 * Del: Del an elementary stream
435 *****************************************************************************/
436 static int Del( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
438 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
440 if ( id
->b_switcher_audio
)
443 for ( i
= 0; i
< MAX_AUDIO
; i
++ )
445 if ( p_sys
->pp_audio_ids
[i
] == id
)
447 p_sys
->pp_audio_ids
[i
] = NULL
;
455 avcodec_close( id
->ff_enc_c
);
456 av_free( id
->ff_enc_c
);
457 av_free( id
->p_frame
);
458 free( id
->p_buffer_out
);
463 p_sys
->p_out
->pf_del( p_sys
->p_out
, id
->id
);
470 /*****************************************************************************
471 * Send: Process an input packet
472 *****************************************************************************/
473 static int Send( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
476 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
480 block_Release( p_buffer
);
484 if ( !id
->b_switcher_video
&& !id
->b_switcher_audio
)
486 return p_sys
->p_out
->pf_send( p_sys
->p_out
, id
->id
, p_buffer
);
489 block_ChainAppend( &id
->p_queued
, p_buffer
);
491 if ( id
->b_switcher_video
)
493 /* Check for commands for every video frame. */
494 NetCommand( p_stream
);
496 while ( id
->p_queued
!= NULL
)
501 if ( p_sys
->i_old_cmd
!= p_sys
->i_cmd
)
503 i_dts
= VideoCommand( p_stream
, id
);
506 i_dts
= Process( p_stream
, id
, i_dts
);
508 for ( i
= 0; i
< MAX_AUDIO
; i
++ )
510 if ( p_sys
->pp_audio_ids
[i
] != NULL
)
511 Process( p_stream
, p_sys
->pp_audio_ids
[i
], i_dts
);
519 /*****************************************************************************
520 * Process: Process and dispatch buffers
521 *****************************************************************************/
522 static mtime_t
Process( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
525 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
527 block_t
*p_blocks
= NULL
;
528 block_t
*p_blocks_out
= NULL
;
530 /* Find out the blocks we need. */
531 while ( id
->p_queued
!= NULL
532 && (!i_max_dts
|| id
->p_queued
->i_dts
<= i_max_dts
) )
534 block_t
*p_next
= id
->p_queued
->p_next
;
535 id
->p_queued
->p_next
= NULL
;
536 i_dts
= id
->p_queued
->i_dts
;
537 block_ChainAppend( &p_blocks
, id
->p_queued
);
538 id
->p_queued
= p_next
;
541 if ( p_sys
->i_old_cmd
== 0 )
544 if ( p_blocks
!= NULL
)
545 p_sys
->p_out
->pf_send( p_sys
->p_out
, id
->id
, p_blocks
);
549 if ( p_sys
->i_old_cmd
== -1 )
551 /* No output at all */
552 while ( p_blocks
!= NULL
)
554 block_t
* p_next
= p_blocks
->p_next
;
555 block_Release( p_blocks
);
561 while ( p_blocks
!= NULL
)
563 block_t
* p_next
= p_blocks
->p_next
;
566 if ( id
->b_switcher_video
)
568 p_out
= VideoGetBuffer( p_stream
, id
, p_blocks
);
572 p_out
= AudioGetBuffer( p_stream
, id
, p_blocks
);
577 block_ChainAppend( &p_blocks_out
, p_out
);
581 if ( p_blocks_out
!= NULL
)
582 p_sys
->p_out
->pf_send( p_sys
->p_out
, id
->id
, p_blocks_out
);
586 /*****************************************************************************
587 * UnpackFromFile: Read a YUV picture and store it in our format
588 *****************************************************************************/
589 static int UnpackFromFile( sout_stream_t
*p_stream
, const char *psz_file
,
590 int i_width
, int i_height
,
594 FILE *p_file
= utf8_fopen( psz_file
, "r" );
596 if ( p_file
== NULL
)
598 msg_Err( p_stream
, "file %s not found", psz_file
);
602 vout_InitPicture( VLC_OBJECT(p_stream
), p_pic
, VLC_FOURCC('I','4','2','0'),
604 i_width
* VOUT_ASPECT_FACTOR
/ i_height
);
605 for ( i
= 0; i
< p_pic
->i_planes
; i
++ )
607 p_pic
->p
[i
].p_pixels
= malloc( p_pic
->p
[i
].i_lines
*
608 p_pic
->p
[i
].i_pitch
);
609 memset( p_pic
->p
[i
].p_pixels
, 0, p_pic
->p
[i
].i_lines
*
610 p_pic
->p
[i
].i_pitch
);
613 for ( i
= 0; i
< i_height
; i
++ )
616 uint8_t p_buffer
[i_width
* 2];
617 uint8_t *p_char
= p_buffer
;
618 uint8_t *p_y
= &p_pic
->p
[0].p_pixels
[i
* p_pic
->p
[0].i_pitch
];
619 uint8_t *p_u
= &p_pic
->p
[1].p_pixels
[i
/2 * p_pic
->p
[1].i_pitch
];
620 uint8_t *p_v
= &p_pic
->p
[2].p_pixels
[i
/2 * p_pic
->p
[2].i_pitch
];
622 if ( fread( p_buffer
, 2, i_width
, p_file
) != (size_t)i_width
)
624 msg_Err( p_stream
, "premature end of file %s", psz_file
);
626 for ( i
= 0; i
< p_pic
->i_planes
; i
++ )
628 free( p_pic
->p
[i
].p_pixels
);
634 for ( j
= 0; j
< i_width
; j
++ )
636 uint8_t **pp_chroma
= i_chroma
? &p_v
: &p_u
;
637 i_chroma
= !i_chroma
;
639 **pp_chroma
= (**pp_chroma
+ *p_char
+ 1) / 2;
641 **pp_chroma
= *p_char
;
652 /*****************************************************************************
653 * NetCommand: Get a command from the network
654 *****************************************************************************/
655 static void NetCommand( sout_stream_t
*p_stream
)
657 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
659 int i_len
= recv( p_sys
->i_fd
, psz_buffer
, sizeof( psz_buffer
) - 1, 0 );
663 psz_buffer
[i_len
] = '\0';
664 int i_cmd
= strtol( psz_buffer
, NULL
, 0 );
665 if ( i_cmd
< -1 || i_cmd
> p_sys
->i_nb_pictures
)
667 msg_Err( p_stream
, "got a wrong command (%d)", i_cmd
);
671 p_sys
->i_cmd
= i_cmd
;
673 msg_Dbg( p_stream
, "new command: %d old:%d", p_sys
->i_cmd
,
678 /*****************************************************************************
679 * VideoCommand: Create/Delete a video encoder
680 *****************************************************************************/
681 static mtime_t
VideoCommand( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
683 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
685 if ( p_sys
->i_cmd
== 0 && !(id
->p_queued
->i_flags
& BLOCK_FLAG_TYPE_I
) )
687 mtime_t i_dts
= id
->p_queued
->i_dts
;
688 block_t
*p_block
= id
->p_queued
->p_next
;
690 while ( p_block
!= NULL
)
692 if ( p_block
->i_flags
& BLOCK_FLAG_TYPE_I
)
694 i_dts
= p_block
->i_dts
;
695 p_block
= p_block
->p_next
;
701 p_sys
->i_old_cmd
= p_sys
->i_cmd
;
705 avcodec_close( id
->ff_enc_c
);
706 av_free( id
->ff_enc_c
);
707 av_free( id
->p_frame
);
708 free( id
->p_buffer_out
);
712 if ( p_sys
->i_cmd
> 0 )
714 /* Create a new encoder. */
715 int i_ff_codec
= CODEC_ID_MPEG2VIDEO
;
716 int i_aspect_num
, i_aspect_den
;
718 if( i_ff_codec
== 0 )
720 msg_Err( p_stream
, "cannot find encoder" );
724 id
->ff_enc
= avcodec_find_encoder( i_ff_codec
);
727 msg_Err( p_stream
, "cannot find encoder (avcodec)" );
731 id
->ff_enc_c
= avcodec_alloc_context();
733 /* Set CPU capabilities */
734 unsigned i_cpu
= vlc_CPU();
735 id
->ff_enc_c
->dsp_mask
= 0;
736 if( !(i_cpu
& CPU_CAPABILITY_MMX
) )
738 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMX
;
740 if( !(i_cpu
& CPU_CAPABILITY_MMXEXT
) )
742 id
->ff_enc_c
->dsp_mask
|= FF_MM_MMXEXT
;
744 if( !(i_cpu
& CPU_CAPABILITY_3DNOW
) )
746 id
->ff_enc_c
->dsp_mask
|= FF_MM_3DNOW
;
748 if( !(i_cpu
& CPU_CAPABILITY_SSE
) )
750 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE
;
751 id
->ff_enc_c
->dsp_mask
|= FF_MM_SSE2
;
754 id
->ff_enc_c
->width
= p_sys
->p_pictures
[p_sys
->i_cmd
-1].format
.i_width
;
755 id
->ff_enc_c
->height
= p_sys
->p_pictures
[p_sys
->i_cmd
-1].format
.i_height
;
756 av_reduce( &i_aspect_num
, &i_aspect_den
,
758 VOUT_ASPECT_FACTOR
, 1 << 30 /* something big */ );
759 av_reduce( &id
->ff_enc_c
->sample_aspect_ratio
.num
,
760 &id
->ff_enc_c
->sample_aspect_ratio
.den
,
761 i_aspect_num
* (int64_t)id
->ff_enc_c
->height
,
762 i_aspect_den
* (int64_t)id
->ff_enc_c
->width
, 1 << 30 );
764 #if LIBAVCODEC_BUILD >= 4754
765 id
->ff_enc_c
->time_base
.num
= 1;
766 id
->ff_enc_c
->time_base
.den
= 25; /* FIXME */
768 id
->ff_enc_c
->frame_rate
= 25; /* FIXME */
769 id
->ff_enc_c
->frame_rate_base
= 1;
772 id
->ff_enc_c
->gop_size
= 200;
773 id
->ff_enc_c
->max_b_frames
= 0;
775 id
->ff_enc_c
->flags
|= CODEC_FLAG_QSCALE
776 | CODEC_FLAG_INPUT_PRESERVED
777 | CODEC_FLAG_LOW_DELAY
;
779 id
->ff_enc_c
->mb_decision
= FF_MB_DECISION_SIMPLE
;
780 id
->ff_enc_c
->pix_fmt
= PIX_FMT_YUV420P
;
782 if( avcodec_open( id
->ff_enc_c
, id
->ff_enc
) )
784 msg_Err( p_stream
, "cannot open encoder" );
788 id
->p_buffer_out
= malloc( id
->ff_enc_c
->width
* id
->ff_enc_c
->height
* 3 );
789 id
->p_frame
= avcodec_alloc_frame();
790 id
->p_frame
->linesize
[0] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[0].i_pitch
;
791 id
->p_frame
->linesize
[1] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[1].i_pitch
;
792 id
->p_frame
->linesize
[2] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[2].i_pitch
;
793 id
->p_frame
->data
[0] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[0].p_pixels
;
794 id
->p_frame
->data
[1] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[1].p_pixels
;
795 id
->p_frame
->data
[2] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[2].p_pixels
;
797 id
->i_nb_pred
= p_sys
->i_gop
;
803 /*****************************************************************************
804 * VideoGetBuffer: Build an alternate video buffer
805 *****************************************************************************/
806 static block_t
*VideoGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
809 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
813 id
->p_frame
->quality
= p_sys
->i_qscale
* powf(2.0, FF_LAMBDA_SHIFT
+ 7.0)
815 id
->p_frame
->interlaced_frame
= 0;
816 id
->p_frame
->top_field_first
= 1;
817 id
->p_frame
->pts
= p_buffer
->i_dts
;
819 if ( id
->i_nb_pred
>= p_sys
->i_gop
)
821 id
->p_frame
->pict_type
= FF_I_TYPE
;
823 id
->p_frame
->me_threshold
= 0;
824 id
->p_frame
->mb_threshold
= 0;
830 id
->p_frame
->pict_type
= FF_P_TYPE
;
832 if ( id
->p_frame
->mb_type
!= NULL
)
834 id
->p_frame
->me_threshold
= MAX_THRESHOLD
;
835 id
->p_frame
->mb_threshold
= MAX_THRESHOLD
;
841 i_out
= avcodec_encode_video( id
->ff_enc_c
, id
->p_buffer_out
,
842 id
->ff_enc_c
->width
* id
->ff_enc_c
->height
* 3,
849 if ( id
->p_frame
->mb_type
== NULL
850 && id
->ff_enc_c
->coded_frame
->pict_type
!= FF_I_TYPE
)
852 int mb_width
= (id
->ff_enc_c
->width
+ 15) / 16;
853 int mb_height
= (id
->ff_enc_c
->height
+ 15) / 16;
854 int h_chroma_shift
, v_chroma_shift
;
857 avcodec_get_chroma_sub_sample( id
->ff_enc_c
->pix_fmt
, &h_chroma_shift
,
860 id
->p_frame
->motion_subsample_log2
861 = id
->ff_enc_c
->coded_frame
->motion_subsample_log2
;
862 id
->p_frame
->mb_type
= malloc( ((mb_width
+ 1) * (mb_height
+ 1) + 1)
863 * sizeof(uint32_t) );
864 vlc_memcpy( id
->p_frame
->mb_type
, id
->ff_enc_c
->coded_frame
->mb_type
,
865 (mb_width
+ 1) * mb_height
* sizeof(id
->p_frame
->mb_type
[0]));
867 for ( i
= 0; i
< 2; i
++ )
869 int stride
= ((16 * mb_width
)
870 >> id
->ff_enc_c
->coded_frame
->motion_subsample_log2
) + 1;
871 int height
= ((16 * mb_height
)
872 >> id
->ff_enc_c
->coded_frame
->motion_subsample_log2
);
873 int b8_stride
= mb_width
* 2 + 1;
875 if ( id
->ff_enc_c
->coded_frame
->motion_val
[i
] )
877 id
->p_frame
->motion_val
[i
] = malloc( 2 * stride
* height
879 vlc_memcpy( id
->p_frame
->motion_val
[i
],
880 id
->ff_enc_c
->coded_frame
->motion_val
[i
],
881 2 * stride
* height
* sizeof(int16_t) );
883 if ( id
->ff_enc_c
->coded_frame
->ref_index
[i
] )
885 id
->p_frame
->ref_index
[i
] = malloc( b8_stride
* 2 * mb_height
887 vlc_memcpy( id
->p_frame
->ref_index
[i
],
888 id
->ff_enc_c
->coded_frame
->ref_index
[i
],
889 b8_stride
* 2 * mb_height
* sizeof(int8_t));
895 p_out
= block_New( p_stream
, i_out
);
896 vlc_memcpy( p_out
->p_buffer
, id
->p_buffer_out
, i_out
);
897 p_out
->i_length
= p_buffer
->i_length
;
898 p_out
->i_pts
= p_buffer
->i_dts
;
899 p_out
->i_dts
= p_buffer
->i_dts
;
900 p_out
->i_rate
= p_buffer
->i_rate
;
902 switch ( id
->ff_enc_c
->coded_frame
->pict_type
)
905 p_out
->i_flags
|= BLOCK_FLAG_TYPE_I
;
908 p_out
->i_flags
|= BLOCK_FLAG_TYPE_P
;
911 p_out
->i_flags
|= BLOCK_FLAG_TYPE_B
;
917 block_Release( p_buffer
);
922 /*****************************************************************************
923 * AudioGetBuffer: Build an alternate audio buffer
924 *****************************************************************************/
925 static block_t
*AudioGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
931 i_out
= avcodec_encode_audio( id
->ff_enc_c
, id
->p_buffer_out
,
932 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE
,
938 p_out
= block_New( p_stream
, i_out
);
939 vlc_memcpy( p_out
->p_buffer
, id
->p_buffer_out
, i_out
);
940 p_out
->i_length
= p_buffer
->i_length
;
941 p_out
->i_pts
= p_buffer
->i_dts
;
942 p_out
->i_dts
= p_buffer
->i_dts
;
943 p_out
->i_rate
= p_buffer
->i_rate
;
945 block_Release( p_buffer
);