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 #include "../codec/avcodec/avcodec.h"
62 #define SOUT_CFG_PREFIX "sout-switcher-"
63 #define MAX_PICTURES 10
65 #define MAX_THRESHOLD 99999999
67 /*****************************************************************************
69 *****************************************************************************/
70 static int Open ( vlc_object_t
* );
71 static void Close ( vlc_object_t
* );
73 static sout_stream_id_t
*Add( sout_stream_t
*, es_format_t
* );
74 static int Del( sout_stream_t
*, sout_stream_id_t
* );
75 static int Send( sout_stream_t
*, sout_stream_id_t
*, block_t
* );
77 static mtime_t
Process( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
79 static int UnpackFromFile( sout_stream_t
*p_stream
, const char *psz_file
,
80 int i_width
, int i_height
,
82 static void NetCommand( sout_stream_t
*p_stream
);
83 static mtime_t
VideoCommand( sout_stream_t
*p_stream
, sout_stream_id_t
*id
);
84 static block_t
*VideoGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
86 static block_t
*AudioGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
89 /*****************************************************************************
91 *****************************************************************************/
92 #define FILES_TEXT N_("Files")
93 #define FILES_LONGTEXT N_( \
94 "Full paths of the files separated by colons." )
95 #define SIZES_TEXT N_("Sizes")
96 #define SIZES_LONGTEXT N_( \
97 "List of sizes separated by colons (720x576:480x576)." )
98 #define RATIO_TEXT N_("Aspect ratio")
99 #define RATIO_LONGTEXT N_( \
100 "Aspect ratio (4:3, 16:9)." )
101 #define PORT_TEXT N_("Command UDP port")
102 #define PORT_LONGTEXT N_( \
103 "UDP port to listen to for commands." )
104 #define COMMAND_TEXT N_("Command")
105 #define COMMAND_LONGTEXT N_( \
106 "Initial command to execute." )
107 #define GOP_TEXT N_("GOP size")
108 #define GOP_LONGTEXT N_( \
109 "Number of P frames between two I frames." )
110 #define QSCALE_TEXT N_("Quantizer scale")
111 #define QSCALE_LONGTEXT N_( \
112 "Fixed quantizer scale to use." )
113 #define AUDIO_TEXT N_("Mute audio")
114 #define AUDIO_LONGTEXT N_( \
115 "Mute audio when command is not 0." )
118 set_description( N_("MPEG2 video switcher stream output") )
119 set_capability( "sout stream", 50 )
120 add_shortcut( "switcher" )
121 set_callbacks( Open
, Close
)
123 add_string( SOUT_CFG_PREFIX
"files", "", FILES_TEXT
,
124 FILES_LONGTEXT
, false )
125 add_string( SOUT_CFG_PREFIX
"sizes", "", SIZES_TEXT
,
126 SIZES_LONGTEXT
, false )
127 add_string( SOUT_CFG_PREFIX
"aspect-ratio", "4:3", RATIO_TEXT
,
128 RATIO_LONGTEXT
, false )
129 add_integer( SOUT_CFG_PREFIX
"port", 5001,
130 PORT_TEXT
, PORT_LONGTEXT
, true )
131 add_integer( SOUT_CFG_PREFIX
"command", 0,
132 COMMAND_TEXT
, COMMAND_LONGTEXT
, true )
133 add_integer( SOUT_CFG_PREFIX
"gop", 8,
134 GOP_TEXT
, GOP_LONGTEXT
, true )
135 add_integer( SOUT_CFG_PREFIX
"qscale", 5,
136 QSCALE_TEXT
, QSCALE_LONGTEXT
, true )
137 add_bool( SOUT_CFG_PREFIX
"mute-audio", true,
138 AUDIO_TEXT
, AUDIO_LONGTEXT
, true )
141 static const char *const ppsz_sout_options
[] = {
142 "files", "sizes", "aspect-ratio", "port", "command", "gop", "qscale",
146 struct sout_stream_sys_t
151 sout_stream_id_t
*pp_audio_ids
[MAX_AUDIO
];
155 picture_t p_pictures
[MAX_PICTURES
];
160 int i_cmd
, i_old_cmd
;
163 struct sout_stream_id_t
166 bool b_switcher_video
;
167 bool b_switcher_audio
;
173 AVCodecContext
*ff_enc_c
;
175 uint8_t *p_buffer_out
;
180 /*****************************************************************************
182 *****************************************************************************/
183 static int Open( vlc_object_t
*p_this
)
185 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
186 sout_stream_sys_t
*p_sys
;
188 char *psz_files
, *psz_sizes
;
189 int i_height
= 0, i_width
= 0;
191 p_sys
= calloc( 1, sizeof(sout_stream_sys_t
) );
195 if( !p_stream
->p_next
)
197 msg_Err( p_stream
, "cannot create chain" );
202 config_ChainParse( p_stream
, SOUT_CFG_PREFIX
, ppsz_sout_options
,
205 var_Get( p_stream
, SOUT_CFG_PREFIX
"files", &val
);
206 psz_files
= val
.psz_string
;
207 var_Get( p_stream
, SOUT_CFG_PREFIX
"sizes", &val
);
208 psz_sizes
= val
.psz_string
;
210 p_sys
->i_nb_pictures
= 0;
211 while ( psz_files
&& *psz_files
)
213 char * psz_file
= psz_files
;
214 char * psz_size
= psz_sizes
;
216 while ( *psz_files
&& *psz_files
!= ':' )
218 if ( *psz_files
== ':' )
223 while ( *psz_sizes
&& *psz_sizes
!= ':' )
225 if ( *psz_sizes
== ':' )
227 if ( sscanf( psz_size
, "%dx%d", &i_width
, &i_height
) != 2 )
229 msg_Err( p_stream
, "bad size %s for file %s", psz_size
,
236 if ( UnpackFromFile( p_stream
, psz_file
, i_width
, i_height
,
237 &p_sys
->p_pictures
[p_sys
->i_nb_pictures
] ) < 0 )
242 p_sys
->i_nb_pictures
++;
245 var_Get( p_stream
, SOUT_CFG_PREFIX
"aspect-ratio", &val
);
246 if ( val
.psz_string
)
248 char *psz_parser
= strchr( val
.psz_string
, ':' );
252 *psz_parser
++ = '\0';
253 p_sys
->i_aspect
= atoi( val
.psz_string
) * VOUT_ASPECT_FACTOR
254 / atoi( psz_parser
);
258 msg_Warn( p_stream
, "bad aspect ratio %s", val
.psz_string
);
259 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
262 free( val
.psz_string
);
266 p_sys
->i_aspect
= 4 * VOUT_ASPECT_FACTOR
/ 3;
269 var_Get( p_stream
, SOUT_CFG_PREFIX
"port", &val
);
270 p_sys
->i_fd
= net_ListenUDP1( VLC_OBJECT(p_stream
), NULL
, val
.i_int
);
271 if ( p_sys
->i_fd
< 0 )
277 var_Get( p_stream
, SOUT_CFG_PREFIX
"command", &val
);
278 p_sys
->i_cmd
= val
.i_int
;
279 p_sys
->i_old_cmd
= 0;
281 var_Get( p_stream
, SOUT_CFG_PREFIX
"gop", &val
);
282 p_sys
->i_gop
= val
.i_int
;
284 var_Get( p_stream
, SOUT_CFG_PREFIX
"qscale", &val
);
285 p_sys
->i_qscale
= val
.i_int
;
287 var_Get( p_stream
, SOUT_CFG_PREFIX
"mute-audio", &val
);
288 p_sys
->b_audio
= val
.b_bool
;
290 p_stream
->pf_add
= Add
;
291 p_stream
->pf_del
= Del
;
292 p_stream
->pf_send
= Send
;
293 p_stream
->p_sys
= p_sys
;
296 avcodec_register_all();
301 /*****************************************************************************
303 *****************************************************************************/
304 static void Close( vlc_object_t
* p_this
)
306 sout_stream_t
*p_stream
= (sout_stream_t
*)p_this
;
307 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
312 /*****************************************************************************
313 * Add: Add an input elementary stream
314 *****************************************************************************/
315 static sout_stream_id_t
*Add( sout_stream_t
*p_stream
, es_format_t
*p_fmt
)
317 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
318 sout_stream_id_t
*id
;
320 id
= calloc( 1, sizeof( sout_stream_id_t
) );
324 if( p_fmt
->i_cat
== VIDEO_ES
&& p_fmt
->i_codec
== VLC_CODEC_MPGV
)
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
|= AV_CPU_FLAG_MMX
;
367 if( !(i_cpu
& CPU_CAPABILITY_MMXEXT
) )
369 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_MMX2
;
371 if( !(i_cpu
& CPU_CAPABILITY_3DNOW
) )
373 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_3DNOW
;
375 if( !(i_cpu
& CPU_CAPABILITY_SSE
) )
377 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_SSE
;
379 if( !(i_cpu
& CPU_CAPABILITY_SSE2
) )
381 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_SSE2
;
384 id
->ff_enc_c
->sample_rate
= p_fmt
->audio
.i_rate
;
385 id
->ff_enc_c
->channels
= p_fmt
->audio
.i_channels
;
386 id
->ff_enc_c
->bit_rate
= p_fmt
->i_bitrate
;
389 if( avcodec_open( id
->ff_enc_c
, id
->ff_enc
) )
391 vlc_avcodec_unlock();
392 msg_Err( p_stream
, "cannot open encoder" );
393 av_free( id
->ff_enc_c
);
397 vlc_avcodec_unlock();
399 id
->p_buffer_out
= malloc( AVCODEC_MAX_AUDIO_FRAME_SIZE
* 2 );
400 id
->p_samples
= calloc( id
->ff_enc_c
->frame_size
* p_fmt
->audio
.i_channels
,
402 if( !id
->p_buffer_out
|| !id
->p_samples
)
405 for( i
= 0; i
< MAX_AUDIO
; i
++ )
407 if( p_sys
->pp_audio_ids
[i
] == NULL
)
409 p_sys
->pp_audio_ids
[i
] = id
;
415 msg_Err( p_stream
, "too many audio streams!" );
421 msg_Dbg( p_stream
, "do not know what to do when switching (fcc=`%4.4s')",
422 (char*)&p_fmt
->i_codec
);
426 memcpy( &id
->f_src
, p_fmt
, sizeof( es_format_t
) );
428 /* open output stream */
429 id
->id
= p_stream
->p_next
->pf_add( p_stream
->p_next
, p_fmt
);
436 avcodec_close( id
->ff_enc_c
);
437 vlc_avcodec_unlock();
438 free( id
->p_samples
);
439 free( id
->p_buffer_out
);
440 av_free( id
->ff_enc_c
);
445 /*****************************************************************************
446 * Del: Del an elementary stream
447 *****************************************************************************/
448 static int Del( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
450 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
452 if ( id
->b_switcher_audio
)
455 for ( i
= 0; i
< MAX_AUDIO
; i
++ )
457 if ( p_sys
->pp_audio_ids
[i
] == id
)
459 p_sys
->pp_audio_ids
[i
] = NULL
;
468 avcodec_close( id
->ff_enc_c
);
469 vlc_avcodec_unlock();
470 av_free( id
->ff_enc_c
);
471 av_free( id
->p_frame
);
472 free( id
->p_buffer_out
);
477 p_stream
->p_next
->pf_del( p_stream
->p_next
, id
->id
);
484 /*****************************************************************************
485 * Send: Process an input packet
486 *****************************************************************************/
487 static int Send( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
490 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
494 block_Release( p_buffer
);
498 if ( !id
->b_switcher_video
&& !id
->b_switcher_audio
)
500 return p_stream
->p_next
->pf_send( p_stream
->p_next
, id
->id
, p_buffer
);
503 block_ChainAppend( &id
->p_queued
, p_buffer
);
505 if ( id
->b_switcher_video
)
507 /* Check for commands for every video frame. */
508 NetCommand( p_stream
);
510 while ( id
->p_queued
!= NULL
)
514 if ( p_sys
->i_old_cmd
!= p_sys
->i_cmd
)
516 i_dts
= VideoCommand( p_stream
, id
);
519 i_dts
= Process( p_stream
, id
, i_dts
);
521 for ( int i
= 0; i
< MAX_AUDIO
; i
++ )
523 if ( p_sys
->pp_audio_ids
[i
] != NULL
)
524 Process( p_stream
, p_sys
->pp_audio_ids
[i
], i_dts
);
532 /*****************************************************************************
533 * Process: Process and dispatch buffers
534 *****************************************************************************/
535 static mtime_t
Process( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
538 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
540 block_t
*p_blocks
= NULL
;
541 block_t
*p_blocks_out
= NULL
;
543 /* Find out the blocks we need. */
544 while ( id
->p_queued
!= NULL
545 && (!i_max_dts
|| id
->p_queued
->i_dts
<= i_max_dts
) )
547 block_t
*p_next
= id
->p_queued
->p_next
;
548 id
->p_queued
->p_next
= NULL
;
549 i_dts
= id
->p_queued
->i_dts
;
550 block_ChainAppend( &p_blocks
, id
->p_queued
);
551 id
->p_queued
= p_next
;
554 if ( p_sys
->i_old_cmd
== 0 )
557 if ( p_blocks
!= NULL
)
558 p_stream
->p_next
->pf_send( p_stream
->p_next
, id
->id
, p_blocks
);
562 if ( p_sys
->i_old_cmd
== -1 )
564 /* No output at all */
565 while ( p_blocks
!= NULL
)
567 block_t
* p_next
= p_blocks
->p_next
;
568 block_Release( p_blocks
);
574 while ( p_blocks
!= NULL
)
576 block_t
* p_next
= p_blocks
->p_next
;
579 if ( id
->b_switcher_video
)
581 p_out
= VideoGetBuffer( p_stream
, id
, p_blocks
);
585 p_out
= AudioGetBuffer( p_stream
, id
, p_blocks
);
590 block_ChainAppend( &p_blocks_out
, p_out
);
594 if ( p_blocks_out
!= NULL
)
595 p_stream
->p_next
->pf_send( p_stream
->p_next
, id
->id
, p_blocks_out
);
599 /*****************************************************************************
600 * UnpackFromFile: Read a YUV picture and store it in our format
601 *****************************************************************************/
602 static int UnpackFromFile( sout_stream_t
*p_stream
, const char *psz_file
,
603 int i_width
, int i_height
,
607 FILE *p_file
= vlc_fopen( psz_file
, "r" );
609 if ( p_file
== NULL
)
611 msg_Err( p_stream
, "file %s not found", psz_file
);
615 if( picture_Setup( p_pic
, VLC_CODEC_I420
,
616 i_width
, i_height
, 1, 1 ) )
618 msg_Err( p_stream
, "unknown chroma" );
621 for ( i
= 0; i
< p_pic
->i_planes
; i
++ )
623 p_pic
->p
[i
].p_pixels
= malloc( p_pic
->p
[i
].i_lines
*
624 p_pic
->p
[i
].i_pitch
);
625 memset( p_pic
->p
[i
].p_pixels
, 0, p_pic
->p
[i
].i_lines
*
626 p_pic
->p
[i
].i_pitch
);
629 for ( i
= 0; i
< i_height
; i
++ )
632 uint8_t p_buffer
[i_width
* 2];
633 uint8_t *p_char
= p_buffer
;
634 uint8_t *p_y
= &p_pic
->p
[0].p_pixels
[i
* p_pic
->p
[0].i_pitch
];
635 uint8_t *p_u
= &p_pic
->p
[1].p_pixels
[i
/2 * p_pic
->p
[1].i_pitch
];
636 uint8_t *p_v
= &p_pic
->p
[2].p_pixels
[i
/2 * p_pic
->p
[2].i_pitch
];
638 if ( fread( p_buffer
, 2, i_width
, p_file
) != (size_t)i_width
)
640 msg_Err( p_stream
, "premature end of file %s", psz_file
);
642 for ( i
= 0; i
< p_pic
->i_planes
; i
++ )
644 free( p_pic
->p
[i
].p_pixels
);
650 for ( j
= 0; j
< i_width
; j
++ )
652 uint8_t **pp_chroma
= i_chroma
? &p_v
: &p_u
;
653 i_chroma
= !i_chroma
;
655 **pp_chroma
= (**pp_chroma
+ *p_char
+ 1) / 2;
657 **pp_chroma
= *p_char
;
668 /*****************************************************************************
669 * NetCommand: Get a command from the network
670 *****************************************************************************/
671 static void NetCommand( sout_stream_t
*p_stream
)
673 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
675 int i_len
= recv( p_sys
->i_fd
, psz_buffer
, sizeof( psz_buffer
) - 1, 0 );
679 psz_buffer
[i_len
] = '\0';
680 int i_cmd
= strtol( psz_buffer
, NULL
, 0 );
681 if ( i_cmd
< -1 || i_cmd
> p_sys
->i_nb_pictures
)
683 msg_Err( p_stream
, "got a wrong command (%d)", i_cmd
);
687 p_sys
->i_cmd
= i_cmd
;
689 msg_Dbg( p_stream
, "new command: %d old:%d", p_sys
->i_cmd
,
694 /*****************************************************************************
695 * VideoCommand: Create/Delete a video encoder
696 *****************************************************************************/
697 static mtime_t
VideoCommand( sout_stream_t
*p_stream
, sout_stream_id_t
*id
)
699 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
701 if ( p_sys
->i_cmd
== 0 && !(id
->p_queued
->i_flags
& BLOCK_FLAG_TYPE_I
) )
703 mtime_t i_dts
= id
->p_queued
->i_dts
;
704 block_t
*p_block
= id
->p_queued
->p_next
;
706 while ( p_block
!= NULL
)
708 if ( p_block
->i_flags
& BLOCK_FLAG_TYPE_I
)
710 i_dts
= p_block
->i_dts
;
711 p_block
= p_block
->p_next
;
717 p_sys
->i_old_cmd
= p_sys
->i_cmd
;
722 avcodec_close( id
->ff_enc_c
);
723 vlc_avcodec_unlock();
724 av_free( id
->ff_enc_c
);
725 av_free( id
->p_frame
);
726 free( id
->p_buffer_out
);
730 if ( p_sys
->i_cmd
> 0 )
732 /* Create a new encoder. */
733 int i_ff_codec
= CODEC_ID_MPEG2VIDEO
;
734 int i_aspect_num
, i_aspect_den
;
736 if( i_ff_codec
== 0 )
738 msg_Err( p_stream
, "cannot find encoder" );
742 id
->ff_enc
= avcodec_find_encoder( i_ff_codec
);
745 msg_Err( p_stream
, "cannot find encoder (avcodec)" );
749 id
->ff_enc_c
= avcodec_alloc_context();
751 /* Set CPU capabilities */
752 unsigned i_cpu
= vlc_CPU();
753 id
->ff_enc_c
->dsp_mask
= 0;
754 if( !(i_cpu
& CPU_CAPABILITY_MMX
) )
756 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_MMX
;
758 if( !(i_cpu
& CPU_CAPABILITY_MMXEXT
) )
760 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_MMX2
;
762 if( !(i_cpu
& CPU_CAPABILITY_3DNOW
) )
764 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_3DNOW
;
766 if( !(i_cpu
& CPU_CAPABILITY_SSE
) )
768 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_SSE
;
770 if( !(i_cpu
& CPU_CAPABILITY_SSE2
) )
772 id
->ff_enc_c
->dsp_mask
|= AV_CPU_FLAG_SSE2
;
775 id
->ff_enc_c
->width
= p_sys
->p_pictures
[p_sys
->i_cmd
-1].format
.i_width
;
776 id
->ff_enc_c
->height
= p_sys
->p_pictures
[p_sys
->i_cmd
-1].format
.i_height
;
777 av_reduce( &i_aspect_num
, &i_aspect_den
,
779 VOUT_ASPECT_FACTOR
, 1 << 30 /* something big */ );
780 av_reduce( &id
->ff_enc_c
->sample_aspect_ratio
.num
,
781 &id
->ff_enc_c
->sample_aspect_ratio
.den
,
782 i_aspect_num
* (int64_t)id
->ff_enc_c
->height
,
783 i_aspect_den
* (int64_t)id
->ff_enc_c
->width
, 1 << 30 );
785 #if LIBAVCODEC_BUILD >= 4754
786 id
->ff_enc_c
->time_base
.num
= 1;
787 id
->ff_enc_c
->time_base
.den
= 25; /* FIXME */
789 id
->ff_enc_c
->frame_rate
= 25; /* FIXME */
790 id
->ff_enc_c
->frame_rate_base
= 1;
793 id
->ff_enc_c
->gop_size
= 200;
794 id
->ff_enc_c
->max_b_frames
= 0;
796 id
->ff_enc_c
->flags
|= CODEC_FLAG_QSCALE
797 | CODEC_FLAG_INPUT_PRESERVED
798 | CODEC_FLAG_LOW_DELAY
;
800 id
->ff_enc_c
->mb_decision
= FF_MB_DECISION_SIMPLE
;
801 id
->ff_enc_c
->pix_fmt
= PIX_FMT_YUV420P
;
804 if( avcodec_open( id
->ff_enc_c
, id
->ff_enc
) )
806 vlc_avcodec_unlock();
807 msg_Err( p_stream
, "cannot open encoder" );
810 vlc_avcodec_unlock();
812 id
->p_buffer_out
= malloc( id
->ff_enc_c
->width
* id
->ff_enc_c
->height
* 3 );
813 id
->p_frame
= avcodec_alloc_frame();
814 id
->p_frame
->linesize
[0] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[0].i_pitch
;
815 id
->p_frame
->linesize
[1] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[1].i_pitch
;
816 id
->p_frame
->linesize
[2] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[2].i_pitch
;
817 id
->p_frame
->data
[0] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[0].p_pixels
;
818 id
->p_frame
->data
[1] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[1].p_pixels
;
819 id
->p_frame
->data
[2] = p_sys
->p_pictures
[p_sys
->i_cmd
-1].p
[2].p_pixels
;
821 id
->i_nb_pred
= p_sys
->i_gop
;
827 /*****************************************************************************
828 * VideoGetBuffer: Build an alternate video buffer
829 *****************************************************************************/
830 static block_t
*VideoGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
833 sout_stream_sys_t
*p_sys
= p_stream
->p_sys
;
837 id
->p_frame
->quality
= p_sys
->i_qscale
* powf(2.0, FF_LAMBDA_SHIFT
+ 7.0)
839 id
->p_frame
->interlaced_frame
= 0;
840 id
->p_frame
->top_field_first
= 1;
841 id
->p_frame
->pts
= p_buffer
->i_dts
;
843 if ( id
->i_nb_pred
>= p_sys
->i_gop
)
845 id
->p_frame
->pict_type
= FF_I_TYPE
;
847 id
->p_frame
->me_threshold
= 0;
848 id
->p_frame
->mb_threshold
= 0;
854 id
->p_frame
->pict_type
= FF_P_TYPE
;
856 if ( id
->p_frame
->mb_type
!= NULL
)
858 id
->p_frame
->me_threshold
= MAX_THRESHOLD
;
859 id
->p_frame
->mb_threshold
= MAX_THRESHOLD
;
865 i_out
= avcodec_encode_video( id
->ff_enc_c
, id
->p_buffer_out
,
866 id
->ff_enc_c
->width
* id
->ff_enc_c
->height
* 3,
873 if ( id
->p_frame
->mb_type
== NULL
874 && id
->ff_enc_c
->coded_frame
->pict_type
!= FF_I_TYPE
)
876 int mb_width
= (id
->ff_enc_c
->width
+ 15) / 16;
877 int mb_height
= (id
->ff_enc_c
->height
+ 15) / 16;
878 int h_chroma_shift
, v_chroma_shift
;
881 avcodec_get_chroma_sub_sample( id
->ff_enc_c
->pix_fmt
, &h_chroma_shift
,
884 id
->p_frame
->motion_subsample_log2
885 = id
->ff_enc_c
->coded_frame
->motion_subsample_log2
;
886 id
->p_frame
->mb_type
= malloc( ((mb_width
+ 1) * (mb_height
+ 1) + 1)
887 * sizeof(uint32_t) );
888 vlc_memcpy( id
->p_frame
->mb_type
, id
->ff_enc_c
->coded_frame
->mb_type
,
889 (mb_width
+ 1) * mb_height
* sizeof(id
->p_frame
->mb_type
[0]));
891 for ( i
= 0; i
< 2; i
++ )
893 int stride
= ((16 * mb_width
)
894 >> id
->ff_enc_c
->coded_frame
->motion_subsample_log2
) + 1;
895 int height
= ((16 * mb_height
)
896 >> id
->ff_enc_c
->coded_frame
->motion_subsample_log2
);
897 int b8_stride
= mb_width
* 2 + 1;
899 if ( id
->ff_enc_c
->coded_frame
->motion_val
[i
] )
901 id
->p_frame
->motion_val
[i
] = malloc( 2 * stride
* height
903 vlc_memcpy( id
->p_frame
->motion_val
[i
],
904 id
->ff_enc_c
->coded_frame
->motion_val
[i
],
905 2 * stride
* height
* sizeof(int16_t) );
907 if ( id
->ff_enc_c
->coded_frame
->ref_index
[i
] )
909 id
->p_frame
->ref_index
[i
] = malloc( b8_stride
* 2 * mb_height
911 vlc_memcpy( id
->p_frame
->ref_index
[i
],
912 id
->ff_enc_c
->coded_frame
->ref_index
[i
],
913 b8_stride
* 2 * mb_height
* sizeof(int8_t));
919 p_out
= block_New( p_stream
, i_out
);
920 vlc_memcpy( p_out
->p_buffer
, id
->p_buffer_out
, i_out
);
921 p_out
->i_length
= p_buffer
->i_length
;
922 p_out
->i_pts
= p_buffer
->i_dts
;
923 p_out
->i_dts
= p_buffer
->i_dts
;
925 switch ( id
->ff_enc_c
->coded_frame
->pict_type
)
928 p_out
->i_flags
|= BLOCK_FLAG_TYPE_I
;
931 p_out
->i_flags
|= BLOCK_FLAG_TYPE_P
;
934 p_out
->i_flags
|= BLOCK_FLAG_TYPE_B
;
940 block_Release( p_buffer
);
945 /*****************************************************************************
946 * AudioGetBuffer: Build an alternate audio buffer
947 *****************************************************************************/
948 static block_t
*AudioGetBuffer( sout_stream_t
*p_stream
, sout_stream_id_t
*id
,
955 i_out
= avcodec_encode_audio( id
->ff_enc_c
, id
->p_buffer_out
,
956 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE
,
962 p_out
= block_New( p_stream
, i_out
);
963 vlc_memcpy( p_out
->p_buffer
, id
->p_buffer_out
, i_out
);
964 p_out
->i_length
= p_buffer
->i_length
;
965 p_out
->i_pts
= p_buffer
->i_dts
;
966 p_out
->i_dts
= p_buffer
->i_dts
;
968 block_Release( p_buffer
);