2001-12-08 13:21:23 +01:00
# define VCODEC_COPY 0
2001-12-07 00:59:46 +01:00
# define VCODEC_FRAMENO 1
# define VCODEC_DIVX4 2
2001-12-13 18:50:19 +01:00
# define VCODEC_RAW 3
2001-12-15 18:12:20 +01:00
# define VCODEC_LIBAVCODEC 4
2002-01-26 17:32:06 +01:00
# define VCODEC_NULL 5
2002-01-31 01:38:53 +01:00
# define VCODEC_RAWRGB 6
2001-12-07 00:59:46 +01:00
2001-12-08 14:30:06 +01:00
# define ACODEC_COPY 0
2001-10-31 01:25:28 +01:00
# define ACODEC_PCM 1
# define ACODEC_VBRMP3 2
2002-01-27 01:43:57 +01:00
# define ACODEC_NULL 3
2001-10-29 02:11:18 +01:00
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <signal.h>
2001-10-31 17:08:01 +01:00
# include "config.h"
2001-10-29 02:11:18 +01:00
# include "mp_msg.h"
2001-11-18 20:12:25 +01:00
# include "version.h"
2001-10-29 02:11:18 +01:00
# include "help_mp.h"
2001-11-18 20:12:25 +01:00
static char * banner_text =
" \n \n "
" MEncoder " VERSION " (C) 2000-2001 Arpad Gereoffy (see DOCS!) \n "
" \n " ;
2001-12-04 22:35:18 +01:00
# include "cpudetect.h"
2001-10-29 02:11:18 +01:00
# include "codec-cfg.h"
2002-01-25 00:02:59 +01:00
# include "cfgparser.h"
2001-10-29 02:11:18 +01:00
# include "stream.h"
# include "demuxer.h"
# include "stheader.h"
2002-01-15 00:38:49 +01:00
# include "playtree.h"
2001-10-29 02:11:18 +01:00
# include "aviwrite.h"
2001-11-14 12:16:45 +01:00
# ifdef USE_LIBVO2
# include "libvo2/libvo2.h"
# else
2001-10-29 02:11:18 +01:00
# include "libvo/video_out.h"
2001-11-14 12:16:45 +01:00
# endif
2001-10-29 02:11:18 +01:00
2001-10-30 22:55:28 +01:00
# include "dec_audio.h"
# include "dec_video.h"
2002-01-31 01:38:53 +01:00
# include "postproc/rgb2rgb.h"
2001-12-22 17:59:10 +01:00
# ifdef HAVE_DIVX4ENCORE
2001-10-29 02:11:18 +01:00
# include <encore2.h>
2001-11-03 01:44:02 +01:00
# include "divx4_vbr.h"
2001-12-22 17:59:10 +01:00
# endif
2001-10-29 02:11:18 +01:00
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
2001-10-31 17:08:01 +01:00
# include <lame/lame.h>
2001-12-06 23:27:09 +01:00
# endif
2001-10-31 01:25:28 +01:00
2001-12-22 15:32:08 +01:00
# ifdef USE_LIBAVCODEC
# ifdef USE_LIBAVCODEC_SO
# include <libffmpeg/avcodec.h>
# else
# include "libavcodec/avcodec.h"
# endif
2002-01-26 21:18:59 +01:00
extern int avcodec_inited ;
/* for video encoder */
2001-12-22 15:32:08 +01:00
static AVCodec * lavc_venc_codec = NULL ;
static AVCodecContext lavc_venc_context ;
static AVPicture lavc_venc_picture ;
2002-01-26 21:18:59 +01:00
/* video options */
2001-12-22 15:32:08 +01:00
char * lavc_param_vcodec = NULL ;
int lavc_param_vbitrate = - 1 ;
int lavc_param_vhq = 0 ; /* default is realtime encoding */
2002-01-17 02:02:41 +01:00
int lavc_param_vme = 3 ;
2002-01-29 17:27:21 +01:00
int lavc_param_vqscale = 0 ;
2001-12-22 15:32:08 +01:00
int lavc_param_keyint = - 1 ;
# endif
2001-12-16 12:37:23 +01:00
# ifdef HAVE_LIBCSS
# include "libmpdemux/dvdauth.h"
# endif
2001-12-01 02:29:25 +01:00
# include <inttypes.h>
# include "../postproc/swscale.h"
2001-12-08 14:30:06 +01:00
# include "fastmemcpy.h"
2002-01-27 19:39:53 +01:00
/**************************************************************************
Video accelerated architecture
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
vo_vaa_t vo_vaa ;
2002-02-01 12:41:38 +01:00
int vo_doublebuffering ;
2002-01-27 19:39:53 +01:00
2001-10-29 02:11:18 +01:00
//--------------------------
// cache2:
2001-11-02 02:25:13 +01:00
static int stream_cache_size = 0 ;
2001-10-29 02:11:18 +01:00
# ifdef USE_STREAM_CACHE
extern int cache_fill_status ;
# else
# define cache_fill_status 0
# endif
2001-11-02 02:25:13 +01:00
int vcd_track = 0 ;
int audio_id = - 1 ;
int video_id = - 1 ;
int dvdsub_id = - 1 ;
2002-01-26 17:32:06 +01:00
static int has_audio = 1 ;
2001-10-29 02:11:18 +01:00
char * audio_codec = NULL ; // override audio codec
char * video_codec = NULL ; // override video codec
int audio_family = - 1 ; // override audio codec family
int video_family = - 1 ; // override video codec family
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
2001-11-04 00:01:17 +01:00
int out_audio_codec = ACODEC_VBRMP3 ;
2001-12-06 23:27:09 +01:00
# else
int out_audio_codec = ACODEC_PCM ;
# endif
2001-11-04 00:01:17 +01:00
int out_video_codec = VCODEC_DIVX4 ;
2001-10-29 02:11:18 +01:00
// audio stream skip/resync functions requires only for seeking.
// (they should be implemented in the audio codec layer)
//void skip_audio_frame(sh_audio_t *sh_audio){}
//void resync_audio_stream(sh_audio_t *sh_audio){}
2001-11-02 02:25:13 +01:00
int verbose = 0 ; // must be global!
2001-10-29 02:11:18 +01:00
double video_time_usage = 0 ;
double vout_time_usage = 0 ;
static double audio_time_usage = 0 ;
static int total_time_usage_start = 0 ;
static int benchmark = 0 ;
2001-11-01 03:31:23 +01:00
// A-V sync:
int delay_corrected = 1 ;
static float default_max_pts_correction = - 1 ; //0.01f;
static float max_pts_correction = 0 ; //default_max_pts_correction;
static float c_total = 0 ;
2001-11-01 22:47:28 +01:00
float force_fps = 0 ;
float force_ofps = 0 ; // set to 24 for inverse telecine
2001-10-29 02:11:18 +01:00
2001-11-02 02:25:13 +01:00
int force_srate = 0 ;
2001-11-02 04:22:33 +01:00
char * out_filename = " test.avi " ;
char * mp3_filename = NULL ;
char * ac3_filename = NULL ;
2001-12-22 15:32:08 +01:00
char * force_fourcc = NULL ;
2001-12-22 17:59:10 +01:00
# ifdef HAVE_DIVX4ENCORE
2001-11-03 01:44:02 +01:00
static int pass = 0 ;
static char * passtmpfile = " divx2pass.log " ;
2001-12-08 02:43:02 +01:00
int pass_working = 0 ;
2001-12-22 17:59:10 +01:00
# endif
2001-11-03 01:44:02 +01:00
static int play_n_frames = - 1 ;
2001-11-04 00:01:17 +01:00
//char *out_audio_codec=NULL; // override audio codec
//char *out_video_codec=NULL; // override video codec
2001-11-02 04:22:33 +01:00
2001-10-31 17:08:01 +01:00
//#include "libmpeg2/mpeg2.h"
//#include "libmpeg2/mpeg2_internal.h"
2001-12-22 17:59:10 +01:00
# ifdef HAVE_DIVX4ENCORE
2001-11-02 04:22:33 +01:00
ENC_PARAM divx4_param ;
2001-11-03 01:44:02 +01:00
int divx4_crispness = 100 ;
2001-12-22 17:59:10 +01:00
# endif
2001-11-02 04:22:33 +01:00
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
2001-11-02 04:22:33 +01:00
int lame_param_quality = 0 ; // best
int lame_param_vbr = vbr_default ;
int lame_param_mode = - 1 ; // unset
int lame_param_padding = - 1 ; // unset
int lame_param_br = - 1 ; // unset
int lame_param_ratio = - 1 ; // unset
2001-12-06 23:27:09 +01:00
# endif
2001-11-02 04:22:33 +01:00
2001-12-01 02:29:25 +01:00
static int scale_srcW = 0 ;
static int scale_srcH = 0 ;
static int vo_w = 0 , vo_h = 0 ;
2001-11-02 02:25:13 +01:00
//-------------------------- config stuff:
2002-01-15 00:38:49 +01:00
m_config_t * mconfig ;
2001-11-02 02:25:13 +01:00
static int cfg_inc_verbose ( struct config * conf ) { + + verbose ; return 0 ; }
static int cfg_include ( struct config * conf , char * filename ) {
2002-01-15 00:38:49 +01:00
return m_config_parse_config_file ( mconfig , filename ) ;
2001-11-02 02:25:13 +01:00
}
2002-01-15 01:20:50 +01:00
static int parse_end_at ( struct config * conf , const char * param ) ;
2002-01-31 01:38:53 +01:00
static uint8_t * flip_upside_down ( uint8_t * dst , const uint8_t * src , int width , int height ) ;
2002-01-15 01:20:50 +01:00
2001-11-02 02:25:13 +01:00
# include "get_path.c"
# include "cfg-mplayer-def.h"
# include "cfg-mencoder.h"
2002-01-11 17:06:45 +01:00
# ifdef USE_DVDREAD
# include "spudec.h"
# endif
2001-10-31 17:08:01 +01:00
//---------------------------------------------------------------------------
// mini dummy libvo:
2001-10-29 02:11:18 +01:00
static unsigned char * vo_image = NULL ;
static unsigned char * vo_image_ptr = NULL ;
static uint32_t draw_slice ( uint8_t * src [ ] , int stride [ ] , int w , int h , int x0 , int y0 ) {
int y ;
2001-12-01 02:29:25 +01:00
// printf("draw_slice %dx%d %d;%d\n",w,h,x0,y0);
2002-01-26 21:18:59 +01:00
if ( scale_srcW | | scale_srcH )
2001-12-01 02:29:25 +01:00
{
uint8_t * dstPtr [ 3 ] = {
vo_image ,
vo_image + vo_w * vo_h * 5 / 4 ,
vo_image + vo_w * vo_h } ;
SwScale_YV12slice ( src , stride , y0 , h , dstPtr , vo_w , 12 , scale_srcW , scale_srcH , vo_w , vo_h ) ;
}
else
{
2001-10-29 02:11:18 +01:00
// copy Y:
for ( y = 0 ; y < h ; y + + ) {
2001-11-02 21:05:36 +01:00
unsigned char * s = src [ 0 ] + stride [ 0 ] * y ;
2001-10-29 02:11:18 +01:00
unsigned char * d = vo_image + vo_w * ( y0 + y ) + x0 ;
memcpy ( d , s , w ) ;
}
x0 > > = 1 ; y0 > > = 1 ;
w > > = 1 ; h > > = 1 ;
// copy U:
for ( y = 0 ; y < h ; y + + ) {
2001-11-02 21:05:36 +01:00
unsigned char * s = src [ 2 ] + stride [ 2 ] * y ;
2001-10-29 02:11:18 +01:00
unsigned char * d = vo_image + vo_w * vo_h + ( vo_w > > 1 ) * ( y0 + y ) + x0 ;
memcpy ( d , s , w ) ;
}
// copy V:
for ( y = 0 ; y < h ; y + + ) {
2001-11-02 21:05:36 +01:00
unsigned char * s = src [ 1 ] + stride [ 1 ] * y ;
2001-10-29 02:11:18 +01:00
unsigned char * d = vo_image + vo_w * vo_h + vo_w * vo_h / 4 + ( vo_w > > 1 ) * ( y0 + y ) + x0 ;
memcpy ( d , s , w ) ;
}
2001-12-01 02:29:25 +01:00
} // !swscaler
2002-01-26 21:18:59 +01:00
return ( 0 ) ;
2001-10-29 02:11:18 +01:00
}
static uint32_t draw_frame ( uint8_t * src [ ] ) {
// printf("This function shouldn't be called - report bug!\n");
// later: add YUY2->YV12 conversion here!
vo_image_ptr = src [ 0 ] ;
2002-01-26 21:18:59 +01:00
return ( 0 ) ;
2001-10-29 02:11:18 +01:00
}
vo_functions_t video_out ;
2001-10-31 17:08:01 +01:00
//---------------------------------------------------------------------------
2002-01-11 17:06:45 +01:00
void * vo_spudec = NULL ;
static void draw_alpha ( int x0 , int y0 , int w , int h , unsigned char * src , unsigned char * srca , int stride ) {
vo_draw_alpha_yv12 ( w , h , src , srca , stride , vo_image + vo_w * y0 + x0 , vo_w ) ;
}
static void draw_sub ( void ) {
# ifdef USE_DVDREAD
if ( vo_spudec )
spudec_draw_scaled ( vo_spudec , vo_w , vo_h , draw_alpha ) ;
# endif
}
2001-10-31 17:08:01 +01:00
int dec_audio ( sh_audio_t * sh_audio , unsigned char * buffer , int total ) {
int size = 0 ;
int eof = 0 ;
while ( size < total & & ! eof ) {
int len = total - size ;
if ( len > MAX_OUTBURST ) len = MAX_OUTBURST ;
if ( len > sh_audio - > a_buffer_size ) len = sh_audio - > a_buffer_size ;
if ( len > sh_audio - > a_buffer_len ) {
int ret = decode_audio ( sh_audio ,
& sh_audio - > a_buffer [ sh_audio - > a_buffer_len ] ,
len - sh_audio - > a_buffer_len ,
sh_audio - > a_buffer_size - sh_audio - > a_buffer_len ) ;
if ( ret > 0 ) sh_audio - > a_buffer_len + = ret ; else eof = 1 ;
}
if ( len > sh_audio - > a_buffer_len ) len = sh_audio - > a_buffer_len ;
memcpy ( buffer + size , sh_audio - > a_buffer , len ) ;
sh_audio - > a_buffer_len - = len ; size + = len ;
if ( sh_audio - > a_buffer_len > 0 )
memcpy ( sh_audio - > a_buffer , & sh_audio - > a_buffer [ len ] , sh_audio - > a_buffer_len ) ;
}
return size ;
}
//---------------------------------------------------------------------------
2001-10-29 02:11:18 +01:00
static int eof = 0 ;
2001-12-04 21:35:31 +01:00
static int interrupted = 0 ;
2001-10-29 02:11:18 +01:00
2002-01-15 01:20:50 +01:00
enum end_at_type_t { END_AT_NONE , END_AT_TIME , END_AT_SIZE } ;
static enum end_at_type_t end_at_type = END_AT_NONE ;
static int end_at ;
2001-10-29 02:11:18 +01:00
static void exit_sighandler ( int x ) {
eof = 1 ;
2001-12-04 21:35:31 +01:00
interrupted = 1 ;
2001-10-29 02:11:18 +01:00
}
2001-11-02 02:25:13 +01:00
int main ( int argc , char * argv [ ] , char * envp [ ] ) {
2001-10-29 02:11:18 +01:00
stream_t * stream = NULL ;
demuxer_t * demuxer = NULL ;
2002-01-26 23:30:02 +01:00
stream_t * stream2 = NULL ;
demuxer_t * demuxer2 = NULL ;
2001-10-29 02:11:18 +01:00
demux_stream_t * d_audio = NULL ;
demux_stream_t * d_video = NULL ;
demux_stream_t * d_dvdsub = NULL ;
sh_audio_t * sh_audio = NULL ;
sh_video_t * sh_video = NULL ;
int file_format = DEMUXER_TYPE_UNKNOWN ;
2002-02-01 09:50:45 +01:00
int i , pitches [ 3 ] ;
2001-10-29 02:11:18 +01:00
unsigned int out_fmt ;
aviwrite_t * muxer = NULL ;
aviwrite_stream_t * mux_a = NULL ;
aviwrite_stream_t * mux_v = NULL ;
FILE * muxer_f = NULL ;
2002-01-27 15:16:32 +01:00
int muxer_f_size = 0 ;
2001-10-29 02:11:18 +01:00
2001-12-22 17:59:10 +01:00
# ifdef HAVE_DIVX4ENCORE
2001-10-29 02:11:18 +01:00
ENC_FRAME enc_frame ;
ENC_RESULT enc_result ;
void * enc_handle = NULL ;
2001-12-22 17:59:10 +01:00
# endif
2001-10-29 02:11:18 +01:00
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
2001-10-31 17:08:01 +01:00
lame_global_flags * lame ;
2001-12-06 23:27:09 +01:00
# endif
2001-10-31 01:25:28 +01:00
2001-11-03 22:00:04 +01:00
float audio_preload = 0.5 ;
2001-10-31 00:17:35 +01:00
2001-11-01 22:47:28 +01:00
double v_pts_corr = 0 ;
double v_timer_corr = 0 ;
2001-11-01 03:31:23 +01:00
2002-01-15 00:38:49 +01:00
play_tree_t * playtree ;
play_tree_iter_t * playtree_iter ;
2001-11-02 02:25:13 +01:00
char * filename = NULL ;
2002-01-26 23:30:02 +01:00
char * frameno_filename = " frameno.avi " ;
2001-11-02 02:25:13 +01:00
2001-12-07 00:59:46 +01:00
int decoded_frameno = 0 ;
2002-01-26 23:30:02 +01:00
int next_frameno = - 1 ;
2001-12-07 00:59:46 +01:00
2002-01-27 19:29:33 +01:00
unsigned int timer_start ;
2001-10-29 02:11:18 +01:00
//int out_buffer_size=0x200000;
//unsigned char* out_buffer=malloc(out_buffer_size);
2001-11-02 03:08:00 +01:00
mp_msg_init ( MSGL_STATUS ) ;
2001-11-18 20:12:25 +01:00
mp_msg ( MSGT_CPLAYER , MSGL_INFO , " %s " , banner_text ) ;
2001-11-02 03:08:00 +01:00
// check codec.conf
if ( ! parse_codec_cfg ( get_path ( " codecs.conf " ) ) ) {
2001-12-25 22:59:07 +01:00
if ( ! parse_codec_cfg ( CONFDIR " /codecs.conf " ) ) {
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_HINT , MSGTR_CopyCodecsConf ) ;
exit ( 0 ) ;
}
}
2001-10-29 02:11:18 +01:00
2001-12-04 22:35:18 +01:00
/* Test for cpu capabilities (and corresponding OS support) for optimizing */
# ifdef ARCH_X86
GetCpuCaps ( & gCpuCaps ) ;
mp_msg ( MSGT_CPLAYER , MSGL_INFO , " CPUflags: Type: %d MMX: %d MMX2: %d 3DNow: %d 3DNow2: %d SSE: %d SSE2: %d \n " ,
gCpuCaps . cpuType , gCpuCaps . hasMMX , gCpuCaps . hasMMX2 ,
gCpuCaps . has3DNow , gCpuCaps . has3DNowExt ,
gCpuCaps . hasSSE , gCpuCaps . hasSSE2 ) ;
# endif
2001-12-22 17:59:10 +01:00
# ifdef HAVE_DIVX4ENCORE
2001-11-03 01:44:02 +01:00
// set some defaults, before parsing configfile/commandline:
divx4_param . min_quantizer = 2 ;
divx4_param . max_quantizer = 31 ;
divx4_param . rc_period = 2000 ;
divx4_param . rc_reaction_period = 10 ;
divx4_param . rc_reaction_ratio = 20 ;
2001-12-22 17:59:10 +01:00
# endif
2001-11-03 01:44:02 +01:00
2002-01-26 23:30:02 +01:00
// FIXME: get rid of -dvd and other tricky options and config/playtree
stream2 = open_stream ( frameno_filename , 0 , & i ) ;
if ( stream2 ) {
demuxer2 = demux_open ( stream2 , DEMUXER_TYPE_AVI , - 1 , - 1 , - 2 ) ;
if ( demuxer2 ) printf ( " Using pass3 control file: %s \n " , frameno_filename ) ;
}
2002-01-15 00:38:49 +01:00
playtree = play_tree_new ( ) ;
mconfig = m_config_new ( playtree ) ;
m_config_register_options ( mconfig , mencoder_opts ) ;
if ( m_config_parse_command_line ( mconfig , argc , argv , envp ) < 0 ) exit ( 1 ) ; // error parsing cmdline
playtree = play_tree_cleanup ( playtree ) ;
if ( playtree ) {
playtree_iter = play_tree_iter_new ( playtree , mconfig ) ;
if ( playtree_iter ) {
if ( play_tree_iter_step ( playtree_iter , 0 , 0 ) ! = PLAY_TREE_ITER_ENTRY ) {
play_tree_iter_free ( playtree_iter ) ;
playtree_iter = NULL ;
}
filename = play_tree_iter_get_file ( playtree_iter , 1 ) ;
}
}
if ( ! filename & & ! vcd_track & & ! dvd_title & & ! tv_param_on ) {
2001-11-02 02:25:13 +01:00
printf ( " \n Missing filename! \n \n " ) ;
exit ( 1 ) ;
}
2001-11-02 03:08:00 +01:00
mp_msg_init ( verbose + MSGL_STATUS ) ;
2001-10-31 23:59:56 +01:00
2001-11-02 02:25:13 +01:00
stream = open_stream ( filename , vcd_track , & file_format ) ;
2001-10-29 02:11:18 +01:00
if ( ! stream ) {
printf ( " Cannot open file/device \n " ) ;
exit ( 1 ) ;
}
printf ( " success: format: %d data: 0x%X - 0x%X \n " , file_format , ( int ) ( stream - > start_pos ) , ( int ) ( stream - > end_pos ) ) ;
2001-12-17 17:56:56 +01:00
if ( stream_cache_size ) stream_enable_cache ( stream , stream_cache_size * 1024 , 0 , 0 ) ;
2001-10-29 02:11:18 +01:00
2002-01-04 15:03:02 +01:00
# ifdef HAVE_LIBCSS
// current_module="libcss";
if ( dvdimportkey ) {
if ( dvd_import_key ( dvdimportkey ) ) {
mp_msg ( MSGT_CPLAYER , MSGL_FATAL , MSGTR_ErrorDVDkey ) ;
exit ( 1 ) ;
}
mp_msg ( MSGT_CPLAYER , MSGL_INFO , MSGTR_CmdlineDVDkey ) ;
}
if ( dvd_auth_device ) {
// if (dvd_auth(dvd_auth_device,f)) {
if ( dvd_auth ( dvd_auth_device , filename ) ) {
mp_msg ( MSGT_CPLAYER , MSGL_FATAL , " Error in DVD auth... \n " ) ;
exit ( 1 ) ;
}
mp_msg ( MSGT_CPLAYER , MSGL_INFO , MSGTR_DVDauthOk ) ;
}
# endif
2002-01-26 23:30:02 +01:00
if ( ! has_audio | | demuxer2 ) audio_id = - 2 ; /* do NOT read audio packets... */
2002-01-26 17:32:06 +01:00
2001-11-13 22:43:29 +01:00
//demuxer=demux_open(stream,file_format,video_id,audio_id,dvdsub_id);
demuxer = demux_open ( stream , file_format , audio_id , video_id , dvdsub_id ) ;
2001-10-29 02:11:18 +01:00
if ( ! demuxer ) {
printf ( " Cannot open demuxer \n " ) ;
exit ( 1 ) ;
}
2002-01-26 23:30:02 +01:00
d_audio = demuxer2 ? demuxer2 - > audio : demuxer - > audio ;
2001-10-29 02:11:18 +01:00
d_video = demuxer - > video ;
d_dvdsub = demuxer - > sub ;
sh_audio = d_audio - > sh ;
sh_video = d_video - > sh ;
if ( ! video_read_properties ( sh_video ) ) {
printf ( " Couldn't read video properties \n " ) ;
exit ( 1 ) ;
}
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_INFO , " [V] filefmt:%d fourcc:0x%X size:%dx%d fps:%5.2f ftime:=%6.4f \n " ,
2001-10-29 02:11:18 +01:00
demuxer - > file_format , sh_video - > format , sh_video - > disp_w , sh_video - > disp_h ,
sh_video - > fps , sh_video - > frametime
) ;
sh_video - > codec = NULL ;
2001-12-07 00:59:46 +01:00
if ( out_video_codec > 1 ) {
2001-11-13 23:58:14 +01:00
2001-11-02 03:08:00 +01:00
if ( video_family ! = - 1 ) mp_msg ( MSGT_MENCODER , MSGL_INFO , MSGTR_TryForceVideoFmt , video_family ) ;
2001-12-24 15:01:55 +01:00
{ /* local vars */
2001-12-23 12:58:57 +01:00
short bestprio = - 1 ;
struct codecs_st * bestcodec = NULL ;
2001-10-29 02:11:18 +01:00
while ( 1 ) {
sh_video - > codec = find_codec ( sh_video - > format ,
sh_video - > bih ? ( ( unsigned int * ) & sh_video - > bih - > biCompression ) : NULL , sh_video - > codec , 0 ) ;
if ( ! sh_video - > codec ) {
if ( video_family ! = - 1 ) {
2001-12-24 15:01:55 +01:00
//sh_video->codec=NULL; /* re-search */
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_WARN , MSGTR_CantFindVfmtFallback ) ;
2001-10-29 02:11:18 +01:00
video_family = - 1 ;
continue ;
}
2001-12-24 15:01:55 +01:00
if ( bestprio = = - 1 | | ! video_codec ) {
mp_msg ( MSGT_MENCODER , MSGL_ERR , MSGTR_CantFindVideoCodec , sh_video - > format ) ;
mp_msg ( MSGT_MENCODER , MSGL_HINT , MSGTR_TryUpgradeCodecsConfOrRTFM , get_path ( " codecs.conf " ) ) ;
exit ( 1 ) ;
}
} else {
if ( video_codec & & strcmp ( sh_video - > codec - > name , video_codec ) ) continue ;
else if ( video_family ! = - 1 & & sh_video - > codec - > driver ! = video_family ) continue ;
else if ( video_family = = - 1 & & ! video_codec & & sh_video - > codec - > priority ) {
if ( sh_video - > codec - > priority > bestprio ) {
//printf("\n\n!!! setting bestprio from %d to %d for %s!!!\n\n", bestprio, sh_video->codec->priority, sh_video->codec->name);
bestprio = sh_video - > codec - > priority ;
bestcodec = sh_video - > codec ;
}
continue ;
}
} /* sh_video->codec */
2001-10-29 02:11:18 +01:00
break ;
}
2001-12-23 12:58:57 +01:00
if ( bestprio ! = - 1 ) {
//printf("chose codec %s by priority.\n", bestcodec->name);
sh_video - > codec = bestcodec ;
}
2001-12-24 15:01:55 +01:00
} /* end local vars */
2001-10-29 02:11:18 +01:00
2001-12-23 12:58:57 +01:00
mp_msg ( MSGT_MENCODER , MSGL_INFO , " %s video codec: [%s] drv:%d prio:%d (%s) \n " , video_codec ? " Forcing " : " Detected " , sh_video - > codec - > name , sh_video - > codec - > driver , sh_video - > codec - > priority ! = - 1 ? sh_video - > codec - > priority : 0 , sh_video - > codec - > info ) ;
2001-10-29 02:11:18 +01:00
for ( i = 0 ; i < CODECS_MAX_OUTFMT ; i + + ) {
out_fmt = sh_video - > codec - > outfmt [ i ] ;
if ( out_fmt = = 0xFFFFFFFF ) continue ;
2002-01-31 01:38:53 +01:00
if ( IMGFMT_IS_RGB ( out_fmt ) ) break ;
2001-10-29 02:11:18 +01:00
if ( out_fmt = = IMGFMT_YV12 ) break ;
2002-01-31 01:38:53 +01:00
if ( out_video_codec = = VCODEC_RAWRGB ) {
if ( IMGFMT_IS_BGR ( out_fmt ) & & IMGFMT_BGR_DEPTH ( out_fmt ) = = 32 ) break ;
}
else {
if ( IMGFMT_IS_BGR ( out_fmt ) ) break ;
2001-10-29 02:11:18 +01:00
if ( out_fmt = = IMGFMT_I420 ) break ;
if ( out_fmt = = IMGFMT_IYUV ) break ;
if ( out_fmt = = IMGFMT_YUY2 ) break ;
2001-11-11 14:23:28 +01:00
if ( out_fmt = = IMGFMT_UYVY ) break ;
2002-01-31 01:38:53 +01:00
}
2001-10-29 02:11:18 +01:00
}
if ( i > = CODECS_MAX_OUTFMT ) {
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_FATAL , MSGTR_VOincompCodec ) ;
2001-10-29 02:11:18 +01:00
exit ( 1 ) ; // exit_player(MSGTR_Exit_error);
}
sh_video - > outfmtidx = i ;
2001-12-01 13:24:46 +01:00
if ( out_fmt = = IMGFMT_YV12 & & ( vo_w ! = 0 | | vo_h ! = 0 ) )
2001-12-01 02:29:25 +01:00
{
scale_srcW = sh_video - > disp_w ;
scale_srcH = sh_video - > disp_h ;
2001-12-01 13:24:46 +01:00
if ( ! vo_w ) vo_w = sh_video - > disp_w ;
if ( ! vo_h ) vo_h = sh_video - > disp_h ;
2001-12-01 02:29:25 +01:00
}
else
{
vo_w = sh_video - > disp_w ;
vo_h = sh_video - > disp_h ;
}
2001-10-29 02:11:18 +01:00
if ( out_fmt = = IMGFMT_YV12 | | out_fmt = = IMGFMT_I420 | | out_fmt = = IMGFMT_IYUV ) {
vo_image = malloc ( vo_w * vo_h * 3 / 2 ) ;
vo_image_ptr = vo_image ;
}
2001-12-15 18:12:20 +01:00
if ( IMGFMT_IS_BGR ( out_fmt ) )
vo_image_ptr = vo_image = malloc ( vo_w * vo_h * IMGFMT_BGR_DEPTH ( out_fmt ) / 8 ) ;
if ( IMGFMT_IS_RGB ( out_fmt ) )
vo_image_ptr = vo_image = malloc ( vo_w * vo_h * IMGFMT_RGB_DEPTH ( out_fmt ) / 8 ) ;
2002-02-01 09:50:45 +01:00
if ( ! init_video ( sh_video , pitches ) ) {
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_FATAL , MSGTR_CouldntInitVideoCodec ) ;
2001-10-29 02:11:18 +01:00
exit ( 1 ) ;
}
2001-11-13 23:58:14 +01:00
} // if(out_video_codec)
2001-10-31 00:17:35 +01:00
2002-01-27 02:23:23 +01:00
if ( sh_audio & & ( out_audio_codec | | ! sh_audio - > wf ) ) {
2001-10-31 00:17:35 +01:00
// Go through the codec.conf and find the best codec...
sh_audio - > codec = NULL ;
2001-11-02 03:08:00 +01:00
if ( audio_family ! = - 1 ) mp_msg ( MSGT_MENCODER , MSGL_INFO , MSGTR_TryForceAudioFmt , audio_family ) ;
2001-10-31 00:17:35 +01:00
while ( 1 ) {
sh_audio - > codec = find_codec ( sh_audio - > format , NULL , sh_audio - > codec , 1 ) ;
if ( ! sh_audio - > codec ) {
if ( audio_family ! = - 1 ) {
sh_audio - > codec = NULL ; /* re-search */
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_ERR , MSGTR_CantFindAfmtFallback ) ;
2001-10-31 00:17:35 +01:00
audio_family = - 1 ;
continue ;
}
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_ERR , MSGTR_CantFindAudioCodec , sh_audio - > format ) ;
mp_msg ( MSGT_MENCODER , MSGL_HINT , MSGTR_TryUpgradeCodecsConfOrRTFM , get_path ( " codecs.conf " ) ) ;
2001-10-31 00:17:35 +01:00
sh_audio = d_audio - > sh = NULL ;
break ;
}
if ( audio_codec & & strcmp ( sh_audio - > codec - > name , audio_codec ) ) continue ;
else if ( audio_family ! = - 1 & & sh_audio - > codec - > driver ! = audio_family ) continue ;
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_INFO , " %s audio codec: [%s] drv:%d (%s) \n " , audio_codec ? " Forcing " : " Detected " , sh_audio - > codec - > name , sh_audio - > codec - > driver , sh_audio - > codec - > info ) ;
2001-10-31 00:17:35 +01:00
break ;
}
}
2002-01-27 02:23:23 +01:00
if ( sh_audio & & ( out_audio_codec | | ! sh_audio - > wf ) ) {
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_V , " Initializing audio codec... \n " ) ;
2001-10-31 00:17:35 +01:00
if ( ! init_audio ( sh_audio ) ) {
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_ERR , MSGTR_CouldntInitAudioCodec ) ;
2001-10-31 00:17:35 +01:00
sh_audio = d_audio - > sh = NULL ;
} else {
2001-11-02 03:08:00 +01:00
mp_msg ( MSGT_MENCODER , MSGL_INFO , " AUDIO: srate=%d chans=%d bps=%d sfmt=0x%X ratio: %d->%d \n " , sh_audio - > samplerate , sh_audio - > channels , sh_audio - > samplesize ,
2001-10-31 00:17:35 +01:00
sh_audio - > sample_format , sh_audio - > i_bps , sh_audio - > o_bps ) ;
}
}
2001-10-29 02:11:18 +01:00
// set up video encoder:
2001-12-01 02:29:25 +01:00
SwScale_Init ( ) ;
2001-10-29 02:11:18 +01:00
video_out . draw_slice = draw_slice ;
video_out . draw_frame = draw_frame ;
2002-01-11 17:06:45 +01:00
# ifdef USE_DVDREAD
vo_spudec = spudec_new_scaled ( stream - > priv ? ( ( dvd_priv_t * ) ( stream - > priv ) ) - > cur_pgc - > palette : NULL ,
sh_video - > disp_w , sh_video - > disp_h ) ;
# endif
2001-10-29 02:11:18 +01:00
// set up output file:
2001-11-02 04:22:33 +01:00
muxer_f = fopen ( out_filename , " wb " ) ;
2001-11-14 00:43:33 +01:00
if ( ! muxer_f ) {
printf ( " Cannot open output file '%s' \n " , out_filename ) ;
exit ( 1 ) ;
}
2001-10-29 02:11:18 +01:00
muxer = aviwrite_new_muxer ( ) ;
2001-10-31 00:17:35 +01:00
// ============= VIDEO ===============
2001-10-29 02:11:18 +01:00
mux_v = aviwrite_new_stream ( muxer , AVIWRITE_TYPE_VIDEO ) ;
mux_v - > buffer_size = 0x200000 ;
mux_v - > buffer = malloc ( mux_v - > buffer_size ) ;
mux_v - > source = sh_video ;
mux_v - > h . dwSampleSize = 0 ; // VBR
mux_v - > h . dwScale = 10000 ;
2001-11-01 22:47:28 +01:00
mux_v - > h . dwRate = mux_v - > h . dwScale * ( force_ofps ? force_ofps : sh_video - > fps ) ;
2001-10-29 02:11:18 +01:00
2001-11-04 00:01:17 +01:00
mux_v - > codec = out_video_codec ;
2001-10-30 22:55:28 +01:00
2001-10-29 02:11:18 +01:00
switch ( mux_v - > codec ) {
2001-12-08 13:21:23 +01:00
case VCODEC_COPY :
if ( sh_video - > bih )
mux_v - > bih = sh_video - > bih ;
else
{
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
mux_v - > bih - > biWidth = sh_video - > disp_w ;
mux_v - > bih - > biHeight = sh_video - > disp_h ;
mux_v - > bih - > biCompression = sh_video - > format ;
mux_v - > bih - > biPlanes = 1 ;
mux_v - > bih - > biBitCount = 24 ; // FIXME!!!
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
}
printf ( " videocodec: framecopy (%dx%d %dbpp fourcc=%x) \n " ,
mux_v - > bih - > biWidth , mux_v - > bih - > biHeight ,
mux_v - > bih - > biBitCount , mux_v - > bih - > biCompression ) ;
2001-10-29 02:11:18 +01:00
break ;
2001-12-13 18:50:19 +01:00
case VCODEC_RAW :
if ( sh_video - > bih )
mux_v - > bih = sh_video - > bih ;
else
{
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
mux_v - > bih - > biWidth = sh_video - > disp_w ;
mux_v - > bih - > biHeight = sh_video - > disp_h ;
mux_v - > bih - > biCompression = 0 ;
mux_v - > bih - > biPlanes = 1 ;
mux_v - > bih - > biBitCount = 24 ; // FIXME!!!
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
}
mux_v - > bih - > biCompression = 0 ;
printf ( " videocodec: raw (%dx%d %dbpp fourcc=%x) \n " ,
mux_v - > bih - > biWidth , mux_v - > bih - > biHeight ,
mux_v - > bih - > biBitCount , mux_v - > bih - > biCompression ) ;
break ;
2002-01-31 01:38:53 +01:00
case VCODEC_RAWRGB :
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
mux_v - > bih - > biWidth = sh_video - > disp_w ;
mux_v - > bih - > biHeight = sh_video - > disp_h ;
mux_v - > bih - > biCompression = 0 ;
mux_v - > bih - > biPlanes = 1 ;
if ( IMGFMT_IS_RGB ( out_fmt ) )
mux_v - > bih - > biBitCount = IMGFMT_RGB_DEPTH ( out_fmt ) ;
else if ( IMGFMT_IS_BGR ( out_fmt ) )
mux_v - > bih - > biBitCount = IMGFMT_BGR_DEPTH ( out_fmt ) ;
else {
mux_v - > bih - > biBitCount = 24 ;
yuv2rgb_init ( 24 , MODE_BGR ) ;
}
if ( mux_v - > bih - > biBitCount = = 32 )
mux_v - > bih - > biBitCount = 24 ;
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
printf ( " videocodec: rawrgb (%dx%d %dbpp fourcc=%x) \n " ,
mux_v - > bih - > biWidth , mux_v - > bih - > biHeight ,
mux_v - > bih - > biBitCount , mux_v - > bih - > biCompression ) ;
break ;
2001-12-07 00:59:46 +01:00
case VCODEC_FRAMENO :
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
mux_v - > bih - > biWidth = vo_w ;
mux_v - > bih - > biHeight = vo_h ;
mux_v - > bih - > biPlanes = 1 ;
mux_v - > bih - > biBitCount = 24 ;
mux_v - > bih - > biCompression = mmioFOURCC ( ' F ' , ' r ' , ' N ' , ' o ' ) ;
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
break ;
2002-01-26 17:32:06 +01:00
case VCODEC_NULL :
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
mux_v - > bih - > biWidth = vo_w ;
mux_v - > bih - > biHeight = vo_h ;
mux_v - > bih - > biPlanes = 1 ;
mux_v - > bih - > biBitCount = 24 ;
mux_v - > bih - > biCompression = 0 ;
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
break ;
2001-10-29 02:11:18 +01:00
case VCODEC_DIVX4 :
2001-12-22 17:59:10 +01:00
# ifndef HAVE_DIVX4ENCORE
printf ( " No support for Divx4 encore compiled in \n " ) ;
return 0 ; /* FIXME */
# else
2001-10-29 02:11:18 +01:00
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
2001-12-01 02:29:25 +01:00
mux_v - > bih - > biWidth = vo_w ;
mux_v - > bih - > biHeight = vo_h ;
2001-11-02 18:43:05 +01:00
mux_v - > bih - > biPlanes = 1 ;
2001-10-29 02:11:18 +01:00
mux_v - > bih - > biBitCount = 24 ;
mux_v - > bih - > biCompression = mmioFOURCC ( ' d ' , ' i ' , ' v ' , ' x ' ) ;
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
2001-12-08 02:43:02 +01:00
if ( pass )
printf ( " Divx: 2-pass logfile: %s \n " , passtmpfile ) ;
2001-10-29 02:11:18 +01:00
break ;
2001-12-22 17:59:10 +01:00
# endif
2001-12-22 15:32:08 +01:00
case VCODEC_LIBAVCODEC :
# ifndef USE_LIBAVCODEC
printf ( " No support for FFmpeg's libavcodec compiled in \n " ) ;
2001-12-22 17:59:10 +01:00
return 0 ; /* FIXME */
2001-12-22 15:32:08 +01:00
# else
mux_v - > bih = malloc ( sizeof ( BITMAPINFOHEADER ) ) ;
mux_v - > bih - > biSize = sizeof ( BITMAPINFOHEADER ) ;
mux_v - > bih - > biWidth = vo_w ;
mux_v - > bih - > biHeight = vo_h ;
mux_v - > bih - > biPlanes = 1 ;
mux_v - > bih - > biBitCount = 24 ;
2002-01-26 21:18:59 +01:00
if ( ! lavc_param_vcodec )
{
printf ( " No libavcodec codec specified! It's requested! \n " ) ;
return 0 ; /* FIXME */
}
else
{
const char * vcodec = lavc_param_vcodec ;
if ( ! strcasecmp ( vcodec , " mpeg1video " ) )
{
mux_v - > bih - > biCompression = mmioFOURCC ( ' m ' , ' p ' , ' g ' , ' 1 ' ) ;
}
else if ( ! strcasecmp ( vcodec , " h263 " ) | | ! strcasecmp ( vcodec , " h263p " ) )
{
mux_v - > bih - > biCompression = mmioFOURCC ( ' h ' , ' 2 ' , ' 6 ' , ' 3 ' ) ;
}
else if ( ! strcasecmp ( vcodec , " rv10 " ) )
{
mux_v - > bih - > biCompression = mmioFOURCC ( ' R ' , ' V ' , ' 1 ' , ' 0 ' ) ;
}
else if ( ! strcasecmp ( vcodec , " mjpeg " ) )
{
mux_v - > bih - > biCompression = mmioFOURCC ( ' M ' , ' J ' , ' P ' , ' G ' ) ;
}
else if ( ! strcasecmp ( vcodec , " mpeg4 " ) )
{
mux_v - > bih - > biCompression = mmioFOURCC ( ' M ' , ' P ' , ' 4 ' , ' S ' ) ;
}
else if ( ! strcasecmp ( vcodec , " msmpeg4 " ) )
{
mux_v - > bih - > biCompression = mmioFOURCC ( ' d ' , ' i ' , ' v ' , ' 3 ' ) ;
}
else
mux_v - > bih - > biCompression = mmioFOURCC ( lavc_param_vcodec [ 0 ] ,
lavc_param_vcodec [ 1 ] , lavc_param_vcodec [ 2 ] , lavc_param_vcodec [ 3 ] ) ; /* FIXME!!! */
}
2001-12-22 15:32:08 +01:00
mux_v - > bih - > biSizeImage = mux_v - > bih - > biWidth * mux_v - > bih - > biHeight * ( mux_v - > bih - > biBitCount / 8 ) ;
printf ( " videocodec: libavcodec (%dx%d fourcc=%x [%.4s]) \n " ,
mux_v - > bih - > biWidth , mux_v - > bih - > biHeight , mux_v - > bih - > biCompression ,
2002-01-26 21:18:59 +01:00
( char * ) & mux_v - > bih - > biCompression ) ;
2001-12-22 15:32:08 +01:00
# endif
}
/* force output fourcc to .. */
2002-01-26 21:18:59 +01:00
if ( ( force_fourcc ! = NULL ) & & ( strlen ( force_fourcc ) > = 4 ) )
2001-12-22 15:32:08 +01:00
{
mux_v - > bih - > biCompression = mmioFOURCC ( force_fourcc [ 0 ] , force_fourcc [ 1 ] ,
force_fourcc [ 2 ] , force_fourcc [ 3 ] ) ;
printf ( " Forcing output fourcc to %x [%.4s] \n " ,
2002-01-26 21:18:59 +01:00
mux_v - > bih - > biCompression , ( char * ) & mux_v - > bih - > biCompression ) ;
2001-10-29 02:11:18 +01:00
}
2002-01-27 03:31:06 +01:00
if ( demuxer - > file_format ! = DEMUXER_TYPE_AVI ) pts_from_bps = 0 ; // it must be 0 for mpeg/asf!
2001-10-31 00:17:35 +01:00
// ============= AUDIO ===============
if ( sh_audio ) {
mux_a = aviwrite_new_stream ( muxer , AVIWRITE_TYPE_AUDIO ) ;
mux_a - > buffer_size = 0x100000 ; //16384;
mux_a - > buffer = malloc ( mux_a - > buffer_size ) ;
mux_a - > source = sh_audio ;
2001-11-04 00:01:17 +01:00
mux_a - > codec = out_audio_codec ;
2001-10-31 00:17:35 +01:00
switch ( mux_a - > codec ) {
2001-12-08 14:30:06 +01:00
case ACODEC_COPY :
2002-01-27 02:23:23 +01:00
if ( sh_audio - > wf ) {
2001-12-08 14:30:06 +01:00
mux_a - > wf = sh_audio - > wf ;
2002-01-27 03:31:06 +01:00
if ( ! sh_audio - > i_bps ) sh_audio - > i_bps = mux_a - > wf - > nAvgBytesPerSec ;
2002-01-27 02:23:23 +01:00
} else {
2001-12-08 14:30:06 +01:00
mux_a - > wf = malloc ( sizeof ( WAVEFORMATEX ) ) ;
2002-01-27 03:31:06 +01:00
mux_a - > wf - > nBlockAlign = 1 ; //mux_a->h.dwSampleSize;
2002-01-27 02:23:23 +01:00
mux_a - > wf - > wFormatTag = sh_audio - > format ;
2001-12-08 14:30:06 +01:00
mux_a - > wf - > nChannels = sh_audio - > channels ;
mux_a - > wf - > nSamplesPerSec = sh_audio - > samplerate ;
2002-01-27 02:23:23 +01:00
mux_a - > wf - > nAvgBytesPerSec = sh_audio - > i_bps ; //mux_a->h.dwSampleSize*mux_a->wf->nSamplesPerSec;
2001-12-13 18:50:19 +01:00
mux_a - > wf - > wBitsPerSample = 16 ; // FIXME
2001-12-08 14:30:06 +01:00
mux_a - > wf - > cbSize = 0 ; // FIXME for l3codeca.acm
}
2002-01-27 03:31:06 +01:00
if ( sh_audio - > audio . dwScale ) {
mux_a - > h . dwSampleSize = sh_audio - > audio . dwSampleSize ;
mux_a - > h . dwScale = sh_audio - > audio . dwScale ;
mux_a - > h . dwRate = sh_audio - > audio . dwRate ;
} else {
mux_a - > h . dwSampleSize = mux_a - > wf - > nBlockAlign ;
mux_a - > h . dwScale = mux_a - > h . dwSampleSize ;
mux_a - > h . dwRate = mux_a - > wf - > nAvgBytesPerSec ;
}
printf ( " audiocodec: framecopy (format=%x chans=%d rate=%d bits=%d bps=%d sample=%d) \n " ,
2001-12-08 14:30:06 +01:00
mux_a - > wf - > wFormatTag , mux_a - > wf - > nChannels , mux_a - > wf - > nSamplesPerSec ,
2002-01-27 03:31:06 +01:00
mux_a - > wf - > wBitsPerSample , mux_a - > wf - > nAvgBytesPerSec , mux_a - > h . dwSampleSize ) ;
2001-10-31 00:17:35 +01:00
break ;
2001-10-31 01:25:28 +01:00
case ACODEC_PCM :
printf ( " CBR PCM audio selected \n " ) ;
mux_a - > h . dwSampleSize = 2 * sh_audio - > channels ;
mux_a - > h . dwScale = 1 ;
mux_a - > h . dwRate = sh_audio - > samplerate ;
mux_a - > wf = malloc ( sizeof ( WAVEFORMATEX ) ) ;
mux_a - > wf - > nBlockAlign = mux_a - > h . dwSampleSize ;
mux_a - > wf - > wFormatTag = 0x1 ; // PCM
mux_a - > wf - > nChannels = sh_audio - > channels ;
mux_a - > wf - > nSamplesPerSec = sh_audio - > samplerate ;
mux_a - > wf - > nAvgBytesPerSec = mux_a - > h . dwSampleSize * mux_a - > wf - > nSamplesPerSec ;
mux_a - > wf - > wBitsPerSample = 16 ;
mux_a - > wf - > cbSize = 0 ; // FIXME for l3codeca.acm
break ;
2001-10-31 00:17:35 +01:00
case ACODEC_VBRMP3 :
2001-12-08 14:30:06 +01:00
printf ( " MP3 audio selected \n " ) ;
2001-10-31 00:17:35 +01:00
mux_a - > h . dwSampleSize = 0 ; // VBR
2001-11-03 22:00:04 +01:00
mux_a - > h . dwScale = 1152 ; // samples/frame
2001-10-31 00:17:35 +01:00
mux_a - > h . dwRate = sh_audio - > samplerate ;
2001-11-02 18:43:05 +01:00
if ( sizeof ( MPEGLAYER3WAVEFORMAT ) ! = 30 ) mp_msg ( MSGT_MENCODER , MSGL_WARN , " sizeof(MPEGLAYER3WAVEFORMAT)==%d!=30, maybe broken C compiler? \n " , sizeof ( MPEGLAYER3WAVEFORMAT ) ) ;
mux_a - > wf = malloc ( sizeof ( MPEGLAYER3WAVEFORMAT ) ) ; // should be 30
2001-10-31 00:17:35 +01:00
mux_a - > wf - > wFormatTag = 0x55 ; // MP3
mux_a - > wf - > nChannels = sh_audio - > channels ;
2001-11-02 21:05:36 +01:00
mux_a - > wf - > nSamplesPerSec = force_srate ? force_srate : sh_audio - > samplerate ;
2001-11-02 18:43:05 +01:00
mux_a - > wf - > nAvgBytesPerSec = 192000 / 8 ; // FIXME!
2001-11-03 22:00:04 +01:00
mux_a - > wf - > nBlockAlign = 1152 ; // requires for l3codeca.acm + WMP 6.4
2001-11-02 18:43:05 +01:00
mux_a - > wf - > wBitsPerSample = 0 ; //16;
// from NaNdub: (requires for l3codeca.acm)
mux_a - > wf - > cbSize = 12 ;
( ( MPEGLAYER3WAVEFORMAT * ) ( mux_a - > wf ) ) - > wID = 1 ;
( ( MPEGLAYER3WAVEFORMAT * ) ( mux_a - > wf ) ) - > fdwFlags = 2 ;
2001-11-03 22:00:04 +01:00
( ( MPEGLAYER3WAVEFORMAT * ) ( mux_a - > wf ) ) - > nBlockSize = 1152 ; // ???
2001-11-02 18:43:05 +01:00
( ( MPEGLAYER3WAVEFORMAT * ) ( mux_a - > wf ) ) - > nFramesPerBlock = 1 ;
( ( MPEGLAYER3WAVEFORMAT * ) ( mux_a - > wf ) ) - > nCodecDelay = 0 ;
2001-10-31 00:17:35 +01:00
break ;
}
}
2001-11-11 17:15:24 +01:00
printf ( " Writing AVI header... \n " ) ;
2001-10-29 02:11:18 +01:00
aviwrite_write_header ( muxer , muxer_f ) ;
switch ( mux_v - > codec ) {
2001-12-08 13:21:23 +01:00
case VCODEC_COPY :
2001-12-13 18:50:19 +01:00
case VCODEC_RAW :
2002-01-31 01:38:53 +01:00
case VCODEC_RAWRGB :
2002-01-26 17:32:06 +01:00
case VCODEC_NULL :
2001-10-29 02:11:18 +01:00
break ;
2001-12-07 00:59:46 +01:00
case VCODEC_FRAMENO :
decoded_frameno = 0 ;
break ;
2001-10-29 02:11:18 +01:00
case VCODEC_DIVX4 :
2001-12-22 17:59:10 +01:00
# ifndef HAVE_DIVX4ENCORE
printf ( " No support for Divx4 encore compiled in \n " ) ;
return 0 ; /* FIXME */
# else
2001-10-29 02:11:18 +01:00
// init divx4linux:
2001-12-01 02:29:25 +01:00
divx4_param . x_dim = vo_w ;
divx4_param . y_dim = vo_h ;
2001-11-02 04:22:33 +01:00
divx4_param . framerate = ( float ) mux_v - > h . dwRate / mux_v - > h . dwScale ;
if ( ! divx4_param . bitrate ) divx4_param . bitrate = 800000 ;
else if ( divx4_param . bitrate < = 16000 ) divx4_param . bitrate * = 1000 ;
if ( ! divx4_param . quality ) divx4_param . quality = 5 ; // the quality of compression ( 1 - fastest, 5 - best )
divx4_param . handle = NULL ;
encore ( NULL , ENC_OPT_INIT , & divx4_param , NULL ) ;
enc_handle = divx4_param . handle ;
2001-11-03 01:44:02 +01:00
switch ( out_fmt ) {
case IMGFMT_YV12 : enc_frame . colorspace = ENC_CSP_YV12 ; break ;
case IMGFMT_IYUV :
case IMGFMT_I420 : enc_frame . colorspace = ENC_CSP_I420 ; break ;
case IMGFMT_YUY2 : enc_frame . colorspace = ENC_CSP_YUY2 ; break ;
case IMGFMT_UYVY : enc_frame . colorspace = ENC_CSP_UYVY ; break ;
case IMGFMT_RGB24 :
case IMGFMT_BGR24 :
enc_frame . colorspace = ENC_CSP_RGB24 ; break ;
default :
2001-12-22 15:32:08 +01:00
mp_msg ( MSGT_MENCODER , MSGL_ERR , " divx4: unsupported picture format (%s)! \n " ,
vo_format_name ( out_fmt ) ) ;
2001-11-03 01:44:02 +01:00
}
switch ( pass ) {
case 1 :
2001-12-08 02:43:02 +01:00
if ( VbrControl_init_2pass_vbr_analysis ( passtmpfile , divx4_param . quality ) = = - 1 )
{
printf ( " 2pass failed: filename=%s \n " , passtmpfile ) ;
pass_working = 0 ;
}
else
pass_working = 1 ;
2001-11-03 01:44:02 +01:00
break ;
case 2 :
2001-12-08 02:43:02 +01:00
if ( VbrControl_init_2pass_vbr_encoding ( passtmpfile ,
2001-11-03 01:44:02 +01:00
divx4_param . bitrate ,
divx4_param . framerate ,
divx4_crispness ,
2001-12-08 02:43:02 +01:00
divx4_param . quality ) = = - 1 )
{
printf ( " 2pass failed: filename=%s \n " , passtmpfile ) ;
pass_working = 0 ;
}
else
pass_working = 1 ;
2001-11-03 01:44:02 +01:00
break ;
}
2001-10-29 02:11:18 +01:00
break ;
2001-12-22 17:59:10 +01:00
# endif
2001-12-22 15:32:08 +01:00
case VCODEC_LIBAVCODEC :
# ifndef USE_LIBAVCODEC
printf ( " No support for FFmpeg's libavcodec compiled in \n " ) ;
# else
if ( ! avcodec_inited )
{
avcodec_init ( ) ;
avcodec_register_all ( ) ;
avcodec_inited = 1 ;
}
2001-12-24 11:54:11 +01:00
#if 0
2001-12-22 15:32:08 +01:00
{
extern AVCodec * first_avcodec ;
AVCodec * p = first_avcodec ;
lavc_venc_codec = NULL ;
while ( p )
{
if ( p - > encode ! = NULL & & strcmp ( lavc_param_vcodec , p - > name ) = = 0 )
break ;
p = p - > next ;
}
lavc_venc_codec = p ;
}
2001-12-24 02:11:39 +01:00
# else
2001-12-22 15:32:08 +01:00
/* XXX: implement this in avcodec (i will send a patch to ffmpeglist) -- alex */
2001-12-24 02:11:39 +01:00
lavc_venc_codec = ( AVCodec * ) avcodec_find_encoder_by_name ( lavc_param_vcodec ) ;
# endif
2001-12-22 15:32:08 +01:00
if ( ! lavc_venc_codec )
{
printf ( MSGTR_MissingLAVCcodec , lavc_param_vcodec ) ;
return 0 ; /* FIXME */
}
memset ( & lavc_venc_context , 0 , sizeof ( lavc_venc_context ) ) ;
2001-12-24 02:11:39 +01:00
// lavc_venc_context.width = mux_v->bih->biWidth;
// lavc_venc_context.height = mux_v->bih->biHeight;
2001-12-24 11:54:11 +01:00
/* scaling only for YV12 (and lavc supports only YV12 ;) */
2001-12-24 02:11:39 +01:00
lavc_venc_context . width = vo_w ;
lavc_venc_context . height = vo_h ;
2001-12-22 15:32:08 +01:00
if ( lavc_param_vbitrate > = 0 ) /* != -1 */
lavc_venc_context . bit_rate = lavc_param_vbitrate ;
else
lavc_venc_context . bit_rate = 800000 ; /* default */
2001-12-24 11:54:11 +01:00
lavc_venc_context . frame_rate = ( float ) ( force_ofps ? force_ofps : sh_video - > fps ) * FRAME_RATE_BASE ;
2001-12-22 15:32:08 +01:00
/* keyframe interval */
if ( lavc_param_keyint > = 0 ) /* != -1 */
lavc_venc_context . gop_size = lavc_param_keyint ;
else
2001-12-24 02:11:39 +01:00
lavc_venc_context . gop_size = 250 ; /* default */
2001-12-24 03:11:49 +01:00
2001-12-24 02:11:39 +01:00
/* ignored by libavcodec? */
2001-12-22 15:32:08 +01:00
if ( lavc_param_vhq )
{
printf ( " High quality encoding selected (non real time)! \n " ) ;
lavc_venc_context . flags = CODEC_FLAG_HQ ;
}
else
lavc_venc_context . flags = 0 ;
2001-12-24 02:11:39 +01:00
2002-01-17 02:02:41 +01:00
/* motion estimation (0 = none ... 3 = high quality but slow) */
/* this is just an extern from libavcodec but it should be in the
encoder context - FIXME */
motion_estimation_method = lavc_param_vme ;
2001-12-24 02:11:39 +01:00
/* fixed qscale :p */
2002-01-29 17:27:21 +01:00
if ( lavc_param_vqscale )
{
printf ( " Using constant qscale = %d (VBR) \n " , lavc_param_vqscale ) ;
lavc_venc_context . flags | = CODEC_FLAG_QSCALE ;
lavc_venc_context . quality = lavc_param_vqscale ;
}
2001-12-22 15:32:08 +01:00
if ( avcodec_open ( & lavc_venc_context , lavc_venc_codec ) ! = 0 )
{
printf ( MSGTR_CantOpenCodec ) ;
return 0 ; /* FIXME */
}
if ( lavc_venc_context . codec - > encode = = NULL )
{
printf ( " avcodec init failed (ctx->codec->encode == NULL)! \n " ) ;
return 0 ;
}
2001-12-24 02:11:39 +01:00
# if 1
2001-12-26 14:32:00 +01:00
if ( out_fmt ! = IMGFMT_YV12 & & out_fmt ! = IMGFMT_I420 )
2001-12-24 02:11:39 +01:00
{
printf ( " Not supported image format! (%s) \n " ,
vo_format_name ( out_fmt ) ) ;
return 0 ; /* FIXME */
}
memset ( & lavc_venc_picture , 0 , sizeof ( lavc_venc_picture ) ) ;
{
int size = lavc_venc_context . width * lavc_venc_context . height ;
/* Y */ lavc_venc_picture . data [ 0 ] = vo_image_ptr ;
2001-12-26 14:32:00 +01:00
if ( out_fmt = = IMGFMT_YV12 )
{
/* U */ lavc_venc_picture . data [ 2 ] = lavc_venc_picture . data [ 0 ] + size ;
/* V */ lavc_venc_picture . data [ 1 ] = lavc_venc_picture . data [ 2 ] + size / 4 ;
}
else /* IMGFMT_I420 */
{
/* U */ lavc_venc_picture . data [ 1 ] = lavc_venc_picture . data [ 0 ] + size ;
/* V */ lavc_venc_picture . data [ 2 ] = lavc_venc_picture . data [ 1 ] + size / 4 ;
}
2001-12-24 02:11:39 +01:00
lavc_venc_picture . linesize [ 0 ] = lavc_venc_context . width ;
lavc_venc_picture . linesize [ 1 ] = lavc_venc_context . width / 2 ;
lavc_venc_picture . linesize [ 2 ] = lavc_venc_context . width / 2 ;
}
# else
2001-12-22 15:32:08 +01:00
switch ( out_fmt )
{
case IMGFMT_YV12 :
lavc_venc_context . pix_fmt = PIX_FMT_YUV420P ;
break ;
2001-12-24 02:11:39 +01:00
#if 0 /* it's faulting :( -- libavcodec's bug! -- alex */
case IMGFMT_YUY2 : /* or UYVY */
2001-12-22 15:32:08 +01:00
lavc_venc_context . pix_fmt = PIX_FMT_YUV422 ;
break ;
case IMGFMT_BGR24 :
lavc_venc_context . pix_fmt = PIX_FMT_BGR24 ;
break ;
case IMGFMT_RGB24 :
lavc_venc_context . pix_fmt = PIX_FMT_RGB24 ;
break ;
2001-12-22 17:59:10 +01:00
# endif
2001-12-22 15:32:08 +01:00
default :
printf ( " Not supported image format! (%s) \n " ,
vo_format_name ( out_fmt ) ) ;
return 0 ; /* FIXME */
}
printf ( " Using picture format: %s \n " , vo_format_name ( out_fmt ) ) ;
memset ( & lavc_venc_picture , 0 , sizeof ( lavc_venc_picture ) ) ;
2001-12-24 02:11:39 +01:00
printf ( " ahh: avpict_getsize=%d, vo_image_ptr=%d \n " , avpicture_get_size ( lavc_venc_context . pix_fmt ,
lavc_venc_context . width , lavc_venc_context . height ) ,
vo_h * vo_w * 3 / 2 ) ;
2001-12-22 15:32:08 +01:00
avpicture_fill ( & lavc_venc_picture , vo_image_ptr ,
lavc_venc_context . pix_fmt , lavc_venc_context . width ,
lavc_venc_context . height ) ;
{
char buf [ 1024 ] ;
avcodec_string ( ( char * ) & buf [ 0 ] , 1023 , & lavc_venc_context , 1 ) ;
2001-12-22 17:59:10 +01:00
printf ( " %s \n " , buf ) ;
2001-12-22 15:32:08 +01:00
}
# endif
2001-12-24 02:11:39 +01:00
# endif
2001-10-29 02:11:18 +01:00
}
2001-10-31 23:59:56 +01:00
if ( sh_audio )
2001-10-31 01:25:28 +01:00
switch ( mux_a - > codec ) {
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
2001-10-31 01:25:28 +01:00
case ACODEC_VBRMP3 :
lame = lame_init ( ) ;
2001-10-31 17:08:01 +01:00
lame_set_bWriteVbrTag ( lame , 0 ) ;
2001-10-31 01:25:28 +01:00
lame_set_in_samplerate ( lame , sh_audio - > samplerate ) ;
lame_set_num_channels ( lame , mux_a - > wf - > nChannels ) ;
2001-11-02 21:05:36 +01:00
lame_set_out_samplerate ( lame , mux_a - > wf - > nSamplesPerSec ) ;
2001-11-02 04:22:33 +01:00
if ( lame_param_vbr ) { // VBR:
lame_set_VBR ( lame , lame_param_vbr ) ; // vbr mode
lame_set_VBR_q ( lame , lame_param_quality + 1 ) ; // 1 = best vbr q 6=~128k
if ( lame_param_br > 0 ) lame_set_VBR_mean_bitrate_kbps ( lame , lame_param_br ) ;
} else { // CBR:
lame_set_quality ( lame , lame_param_quality ) ; // 0 = best q
if ( lame_param_br > 0 ) lame_set_brate ( lame , lame_param_br ) ;
}
if ( lame_param_mode > = 0 ) lame_set_mode ( lame , lame_param_mode ) ; // j-st
if ( lame_param_ratio > 0 ) lame_set_compression_ratio ( lame , lame_param_ratio ) ;
2001-10-31 01:25:28 +01:00
lame_init_params ( lame ) ;
2001-11-02 03:08:00 +01:00
if ( verbose ) {
2001-11-02 04:22:33 +01:00
lame_print_config ( lame ) ;
lame_print_internals ( lame ) ;
2001-11-02 03:08:00 +01:00
}
2001-12-06 23:27:09 +01:00
break ;
# endif
2001-10-31 01:25:28 +01:00
}
2001-10-29 02:11:18 +01:00
signal ( SIGINT , exit_sighandler ) ; // Interrupt from keyboard
signal ( SIGQUIT , exit_sighandler ) ; // Quit from keyboard
signal ( SIGTERM , exit_sighandler ) ; // kill
2002-01-27 19:29:33 +01:00
timer_start = GetTimerMS ( ) ;
2001-10-29 02:11:18 +01:00
while ( ! eof ) {
2001-10-30 22:22:28 +01:00
float frame_time = 0 ;
2001-10-29 02:11:18 +01:00
int blit_frame = 0 ;
float a_pts = 0 ;
float v_pts = 0 ;
2001-10-30 22:55:28 +01:00
unsigned char * start = NULL ;
int in_size ;
2001-11-01 22:47:28 +01:00
int skip_flag = 0 ; // 1=skip -1=duplicate
2001-10-29 02:11:18 +01:00
2002-01-15 01:20:50 +01:00
if ( ( end_at_type = = END_AT_SIZE & & end_at < = ftell ( muxer_f ) ) | |
( end_at_type = = END_AT_TIME & & end_at < sh_video - > timer ) )
break ;
2001-11-03 01:44:02 +01:00
if ( play_n_frames > = 0 ) {
- - play_n_frames ;
if ( play_n_frames < 0 ) break ;
}
2001-10-31 00:17:35 +01:00
if ( sh_audio ) {
// get audio:
2001-10-31 01:25:28 +01:00
while ( mux_a - > timer - audio_preload < mux_v - > timer ) {
2001-11-03 22:00:04 +01:00
int len = 0 ;
2001-10-31 00:17:35 +01:00
if ( mux_a - > h . dwSampleSize ) {
2001-11-01 03:31:23 +01:00
// CBR - copy 0.5 sec of audio
2001-10-31 01:25:28 +01:00
switch ( mux_a - > codec ) {
2001-12-08 14:30:06 +01:00
case ACODEC_COPY : // copy
2002-01-27 03:31:06 +01:00
len = mux_a - > wf - > nAvgBytesPerSec / 2 ;
2001-10-31 01:25:28 +01:00
len / = mux_a - > h . dwSampleSize ; if ( len < 1 ) len = 1 ;
len * = mux_a - > h . dwSampleSize ;
len = demux_read_data ( sh_audio - > ds , mux_a - > buffer , len ) ;
break ;
case ACODEC_PCM :
len = mux_a - > h . dwSampleSize * ( mux_a - > h . dwRate / 2 ) ;
2001-10-31 17:08:01 +01:00
len = dec_audio ( sh_audio , mux_a - > buffer , len ) ;
2001-10-31 01:25:28 +01:00
break ;
}
2001-10-31 00:17:35 +01:00
} else {
2001-11-01 03:31:23 +01:00
// VBR - encode/copy an audio frame
switch ( mux_a - > codec ) {
2001-12-08 14:30:06 +01:00
case ACODEC_COPY : // copy
2002-01-26 23:30:02 +01:00
len = ds_get_packet ( sh_audio - > ds , ( unsigned char * * ) & mux_a - > buffer ) ;
// printf("VBR audio framecopy not yet implemented!\n");
2001-11-01 03:31:23 +01:00
break ;
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
2001-11-01 03:31:23 +01:00
case ACODEC_VBRMP3 :
2001-10-31 17:08:01 +01:00
while ( mux_a - > buffer_len < 4 ) {
unsigned char tmp [ 2304 ] ;
int len = dec_audio ( sh_audio , tmp , 2304 ) ;
if ( len < = 0 ) break ; // eof
len = lame_encode_buffer_interleaved ( lame ,
tmp , len / 4 ,
mux_a - > buffer + mux_a - > buffer_len , mux_a - > buffer_size - mux_a - > buffer_len ) ;
if ( len < 0 ) break ; // error
mux_a - > buffer_len + = len ;
}
if ( mux_a - > buffer_len < 4 ) break ;
len = mp_decode_mp3_header ( mux_a - > buffer ) ;
2001-11-02 21:05:36 +01:00
//printf("%d\n",len);
2001-10-31 17:08:01 +01:00
if ( len < = 0 ) break ; // bad frame!
while ( mux_a - > buffer_len < len ) {
unsigned char tmp [ 2304 ] ;
int len = dec_audio ( sh_audio , tmp , 2304 ) ;
if ( len < = 0 ) break ; // eof
len = lame_encode_buffer_interleaved ( lame ,
tmp , len / 4 ,
mux_a - > buffer + mux_a - > buffer_len , mux_a - > buffer_size - mux_a - > buffer_len ) ;
if ( len < 0 ) break ; // error
mux_a - > buffer_len + = len ;
}
2001-11-01 03:31:23 +01:00
break ;
2001-12-06 23:27:09 +01:00
# endif
2001-11-01 03:31:23 +01:00
}
2001-10-31 00:17:35 +01:00
}
2001-10-31 01:25:28 +01:00
if ( len < = 0 ) break ; // EOF?
aviwrite_write_chunk ( muxer , mux_a , muxer_f , len , 0 ) ;
2001-11-03 22:09:21 +01:00
if ( ! mux_a - > h . dwSampleSize & & mux_a - > timer > 0 )
2001-12-06 22:50:35 +01:00
mux_a - > wf - > nAvgBytesPerSec = 0.5f + ( double ) mux_a - > size / mux_a - > timer ; // avg bps (VBR)
2001-10-31 17:08:01 +01:00
if ( mux_a - > buffer_len > = len ) {
mux_a - > buffer_len - = len ;
memcpy ( mux_a - > buffer , mux_a - > buffer + len , mux_a - > buffer_len ) ;
}
2001-10-31 00:17:35 +01:00
}
}
// get video frame!
in_size = video_read_frame ( sh_video , & frame_time , & start , force_fps ) ;
if ( in_size < 0 ) { eof = 1 ; break ; }
2001-12-07 00:59:46 +01:00
sh_video - > timer + = frame_time ; + + decoded_frameno ;
2001-11-01 22:47:28 +01:00
v_timer_corr - = frame_time - ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ;
2002-01-26 23:30:02 +01:00
if ( demuxer2 ) {
// find our frame:
while ( next_frameno < decoded_frameno ) {
int * start ;
int len = ds_get_packet ( demuxer2 - > video , ( unsigned char * * ) & start ) ;
if ( len < 0 ) { eof = 1 ; break ; }
if ( len = = 0 ) - - skip_flag ; else // duplicate
if ( len = = 4 ) next_frameno = start [ 0 ] ;
}
if ( eof ) break ;
if ( skip_flag ) printf ( " !!!!!!!!!!!! \n " ) ;
skip_flag = next_frameno - decoded_frameno ;
// find next frame:
while ( next_frameno < = decoded_frameno ) {
int * start ;
int len = ds_get_packet ( demuxer2 - > video , ( unsigned char * * ) & start ) ;
if ( len < 0 ) { eof = 1 ; break ; }
if ( len = = 0 ) - - skip_flag ; else // duplicate
if ( len = = 4 ) next_frameno = start [ 0 ] ;
}
// if(eof) break;
// printf("Current fno=%d requested=%d skip=%d \n",decoded_frameno,fno,skip_flag);
} else {
2001-11-01 22:47:28 +01:00
// check frame duplicate/drop:
if ( v_timer_corr > = ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ) {
v_timer_corr - = ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ;
+ + skip_flag ; // skip
} else
while ( v_timer_corr < = - ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ) {
v_timer_corr + = ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ;
- - skip_flag ; // dup
}
while ( ( v_pts_corr < = - ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate & & skip_flag > 0 )
| | ( v_pts_corr < = - 2 * ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ) ) {
v_pts_corr + = ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ;
- - skip_flag ; // dup
}
if ( ( v_pts_corr > = ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate & & skip_flag < 0 )
| | ( v_pts_corr > = 2 * ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ) )
if ( skip_flag < = 0 ) { // we can't skip more than 1 frame now
v_pts_corr - = ( float ) mux_v - > h . dwScale / mux_v - > h . dwRate ;
+ + skip_flag ; // skip
}
2001-10-29 02:11:18 +01:00
2002-01-26 23:30:02 +01:00
} // demuxer2
2002-01-11 17:06:45 +01:00
# ifdef USE_DVDREAD
// DVD sub:
if ( vo_spudec ) {
unsigned char * packet = NULL ;
int len ;
while ( ( len = ds_get_packet_sub ( d_dvdsub , & packet ) ) > 0 ) {
mp_msg ( MSGT_MENCODER , MSGL_V , " \r DVD sub: len=%d v_pts=%5.3f s_pts=%5.3f \n " , len , d_video - > pts , d_dvdsub - > pts ) ;
spudec_assemble ( vo_spudec , packet , len , 100 * d_dvdsub - > pts ) ;
}
spudec_heartbeat ( vo_spudec , 100 * d_video - > pts ) ;
}
# endif
2001-10-29 02:11:18 +01:00
switch ( mux_v - > codec ) {
2001-12-08 13:21:23 +01:00
case VCODEC_COPY :
2001-10-30 22:55:28 +01:00
mux_v - > buffer = start ;
2001-11-02 21:05:36 +01:00
if ( skip_flag < = 0 ) aviwrite_write_chunk ( muxer , mux_v , muxer_f , in_size , ( sh_video - > ds - > flags & 1 ) ? 0x10 : 0 ) ;
2001-10-30 22:55:28 +01:00
break ;
2002-01-31 01:38:53 +01:00
case VCODEC_RAWRGB :
{
static uint8_t * raw_rgb_buffer = NULL ;
static uint8_t * raw_rgb_buffer2 = NULL ;
if ( ! raw_rgb_buffer ) {
raw_rgb_buffer = malloc ( vo_w * vo_h * 4 ) ;
raw_rgb_buffer2 = malloc ( vo_w * vo_h * 4 ) ;
}
blit_frame = decode_video ( & video_out , sh_video , start , in_size , 0 ) ;
if ( skip_flag > 0 ) break ;
if ( ! blit_frame ) {
// empty.
aviwrite_write_chunk ( muxer , mux_v , muxer_f , 0 , 0 ) ;
break ;
}
/* Uncompressed avi files store rgb data with the top most row last so we
* have to flip the frames . */
if ( IMGFMT_IS_BGR ( out_fmt ) ) {
if ( IMGFMT_BGR_DEPTH ( out_fmt ) = = 32 ) {
rgb32to24 ( vo_image_ptr , raw_rgb_buffer , vo_w * vo_h * 4 ) ;
mux_v - > buffer = flip_upside_down ( raw_rgb_buffer , raw_rgb_buffer ,
vo_w * 3 , vo_h ) ;
}
else
mux_v - > buffer = flip_upside_down ( raw_rgb_buffer , vo_image_ptr ,
vo_w * 3 , vo_h ) ;
}
else if ( IMGFMT_IS_RGB ( out_fmt ) ) {
if ( IMGFMT_RGB_DEPTH ( out_fmt ) = = 32 ) {
rgb32tobgr32 ( vo_image_ptr , raw_rgb_buffer2 , vo_w * vo_h * 4 ) ;
rgb32to24 ( raw_rgb_buffer2 , raw_rgb_buffer , vo_w * vo_h * 4 ) ;
mux_v - > buffer = flip_upside_down ( raw_rgb_buffer , raw_rgb_buffer ,
vo_w * 3 , vo_h ) ;
}
else
mux_v - > buffer = flip_upside_down ( raw_rgb_buffer , vo_image_ptr ,
vo_w * 3 , vo_h ) ;
}
else {
yuv2rgb ( raw_rgb_buffer , vo_image_ptr , vo_image_ptr + vo_w * vo_h * 5 / 4 ,
vo_image_ptr + vo_w * vo_h , vo_w , vo_h , vo_w * 24 / 8 , vo_w , vo_w / 2 ) ;
mux_v - > buffer = flip_upside_down ( raw_rgb_buffer , raw_rgb_buffer ,
vo_w * 3 , vo_h ) ;
}
aviwrite_write_chunk ( muxer , mux_v , muxer_f , vo_w * vo_h * 3 , 0x10 ) ;
}
break ;
2001-12-13 18:50:19 +01:00
case VCODEC_RAW :
blit_frame = decode_video ( & video_out , sh_video , start , in_size , 0 ) ;
if ( skip_flag > 0 ) break ;
if ( ! blit_frame ) {
// empty.
aviwrite_write_chunk ( muxer , mux_v , muxer_f , 0 , 0 ) ;
break ;
}
mux_v - > buffer = vo_image_ptr ;
aviwrite_write_chunk ( muxer , mux_v , muxer_f , mux_v - > buffer_size , 0x10 ) ;
break ;
2002-01-26 23:30:02 +01:00
case VCODEC_FRAMENO : {
2001-12-07 00:59:46 +01:00
mux_v - > buffer = & decoded_frameno ; // tricky
2001-12-07 01:12:51 +01:00
if ( skip_flag < = 0 ) aviwrite_write_chunk ( muxer , mux_v , muxer_f , sizeof ( int ) , 0x10 ) ;
2002-01-26 23:30:02 +01:00
break ; }
2001-10-29 02:11:18 +01:00
case VCODEC_DIVX4 :
2001-12-22 17:59:10 +01:00
# ifndef HAVE_DIVX4ENCORE
printf ( " No support for Divx4 encore compiled in \n " ) ;
return 0 ; /* FIXME */
# else
2001-10-30 22:55:28 +01:00
blit_frame = decode_video ( & video_out , sh_video , start , in_size , 0 ) ;
2002-01-11 17:06:45 +01:00
draw_sub ( ) ;
2001-11-02 21:05:36 +01:00
if ( skip_flag > 0 ) break ;
2001-10-30 22:55:28 +01:00
if ( ! blit_frame ) {
// empty.
aviwrite_write_chunk ( muxer , mux_v , muxer_f , 0 , 0 ) ;
break ;
}
2001-10-29 02:11:18 +01:00
enc_frame . image = vo_image_ptr ;
enc_frame . bitstream = mux_v - > buffer ;
enc_frame . length = mux_v - > buffer_size ;
2001-11-03 01:44:02 +01:00
enc_frame . mvs = NULL ;
2001-10-29 02:11:18 +01:00
enc_frame . quant = 0 ;
enc_frame . intra = 0 ;
2001-12-08 02:43:02 +01:00
if ( pass = = 2 & & pass_working ) { // handle 2-pass:
enc_frame . quant = VbrControl_get_quant ( ) ;
2001-11-03 01:44:02 +01:00
enc_frame . intra = VbrControl_get_intra ( ) ;
encore ( enc_handle , ENC_OPT_ENCODE_VBR , & enc_frame , & enc_result ) ;
VbrControl_update_2pass_vbr_encoding ( enc_result . motion_bits ,
enc_result . texture_bits ,
enc_result . total_bits ) ;
} else {
encore ( enc_handle , ENC_OPT_ENCODE , & enc_frame , & enc_result ) ;
2001-12-08 02:43:02 +01:00
if ( pass = = 1 & & pass_working ) {
2001-11-03 01:44:02 +01:00
VbrControl_update_2pass_vbr_analysis ( enc_result . is_key_frame ,
enc_result . motion_bits ,
enc_result . texture_bits ,
enc_result . total_bits ,
enc_result . quantizer ) ;
}
}
2001-10-29 02:11:18 +01:00
// printf("encoding...\n");
// printf(" len=%d key:%d qualt:%d \n",enc_frame.length,enc_result.is_key_frame,enc_result.quantizer);
aviwrite_write_chunk ( muxer , mux_v , muxer_f , enc_frame . length , enc_result . is_key_frame ? 0x10 : 0 ) ;
break ;
2001-12-22 17:59:10 +01:00
# endif
2001-12-22 15:32:08 +01:00
case VCODEC_LIBAVCODEC :
{
# ifndef USE_LIBAVCODEC
printf ( " No support for FFmpeg's libavcodec compiled in \n " ) ;
# else
int out_size ;
blit_frame = decode_video ( & video_out , sh_video , start , in_size , 0 ) ;
if ( skip_flag > 0 ) break ;
if ( ! blit_frame ) {
// empty.
aviwrite_write_chunk ( muxer , mux_v , muxer_f , 0 , 0 ) ;
break ;
}
out_size = avcodec_encode_video ( & lavc_venc_context , mux_v - > buffer , mux_v - > buffer_size ,
& lavc_venc_picture ) ;
aviwrite_write_chunk ( muxer , mux_v , muxer_f , out_size , lavc_venc_context . key_frame ? 0x10 : 0 ) ;
# endif
}
2001-10-29 02:11:18 +01:00
}
2001-11-01 22:47:28 +01:00
if ( skip_flag < 0 ) {
2001-11-01 03:31:23 +01:00
// duplicate frame
2001-11-01 22:47:28 +01:00
printf ( " \n duplicate %d frame(s)!!! \n " , - skip_flag ) ;
while ( skip_flag < 0 ) {
aviwrite_write_chunk ( muxer , mux_v , muxer_f , 0 , 0 ) ;
+ + skip_flag ;
}
2001-11-02 21:05:36 +01:00
} else
if ( skip_flag > 0 ) {
2001-11-01 03:31:23 +01:00
// skip frame
printf ( " \n skip frame!!! \n " ) ;
2001-11-01 22:47:28 +01:00
- - skip_flag ;
2001-11-01 03:31:23 +01:00
}
2002-01-26 23:30:02 +01:00
if ( sh_audio & & ! demuxer2 ) {
2001-11-01 03:31:23 +01:00
float AV_delay , x ;
// A-V sync!
if ( pts_from_bps ) {
unsigned int samples = ( sh_audio - > audio . dwSampleSize ) ?
( ( ds_tell ( d_audio ) - sh_audio - > a_in_buffer_len ) / sh_audio - > audio . dwSampleSize ) :
( d_audio - > pack_no ) ; // <- used for VBR audio
2002-01-27 15:35:48 +01:00
// printf("samples=%d \n",samples);
2001-11-01 03:31:23 +01:00
a_pts = samples * ( float ) sh_audio - > audio . dwScale / ( float ) sh_audio - > audio . dwRate ;
delay_corrected = 1 ;
} else {
// PTS = (last timestamp) + (bytes after last timestamp)/(bytes per sec)
a_pts = d_audio - > pts ;
if ( ! delay_corrected ) if ( a_pts ) delay_corrected = 1 ;
//printf("*** %5.3f ***\n",a_pts);
a_pts + = ( ds_tell_pts ( d_audio ) - sh_audio - > a_in_buffer_len ) / ( float ) sh_audio - > i_bps ;
}
v_pts = d_video - > pts ;
// av = compensated (with out buffering delay) A-V diff
2001-11-01 22:47:28 +01:00
AV_delay = ( a_pts - v_pts ) ; AV_delay - = mux_a - > timer - ( mux_v - > timer - ( v_timer_corr + v_pts_corr ) ) ;
2001-11-01 03:31:23 +01:00
// compensate input video timer by av:
x = AV_delay * 0.1f ;
if ( x < - max_pts_correction ) x = - max_pts_correction ; else
if ( x > max_pts_correction ) x = max_pts_correction ;
if ( default_max_pts_correction > = 0 )
max_pts_correction = default_max_pts_correction ;
else
max_pts_correction = sh_video - > frametime * 0.10 ; // +-10% of time
// sh_video->timer-=x;
c_total + = x ;
2001-11-01 22:47:28 +01:00
v_pts_corr + = x ;
2001-11-01 03:31:23 +01:00
}
2002-01-27 19:29:33 +01:00
// printf("A:%6.1f V:%6.1f A-V:%7.3f oAV:%7.3f diff:%7.3f ct:%7.3f vpc:%7.3f \r",
// a_pts,v_pts,a_pts-v_pts,
// (float)(mux_a->timer-mux_v->timer),
// AV_delay, c_total, v_pts_corr );
// printf("V:%6.1f \r", d_video->pts );
2001-11-01 03:31:23 +01:00
#if 0
mp_msg ( MSGT_AVSYNC , MSGL_STATUS , " A:%6.1f V:%6.1f A-V:%7.3f ct:%7.3f %3d/%3d %2d%% %2d%% %4.1f%% %d%% \r " ,
a_pts , v_pts , a_pts - v_pts , c_total ,
( int ) sh_video - > num_frames , ( int ) sh_video - > num_frames_decoded ,
( sh_video - > timer > 0.5 ) ? ( int ) ( 100.0 * video_time_usage / ( double ) sh_video - > timer ) : 0 ,
( sh_video - > timer > 0.5 ) ? ( int ) ( 100.0 * vout_time_usage / ( double ) sh_video - > timer ) : 0 ,
( sh_video - > timer > 0.5 ) ? ( 100.0 * audio_time_usage / ( double ) sh_video - > timer ) : 0
, cache_fill_status
) ;
# endif
2002-01-27 19:29:33 +01:00
{ float t = ( GetTimerMS ( ) - timer_start ) * 0.001f ;
float len = ( demuxer - > movi_end - demuxer - > movi_start ) ;
float p = len > 1000 ? ( float ) ( demuxer - > filepos - demuxer - > movi_start ) / len : 0 ;
2002-01-27 22:37:46 +01:00
if ( ! len & & sh_audio & & sh_audio - > audio . dwLength > 100 ) {
p = ( sh_audio - > audio . dwSampleSize ? ds_tell ( sh_audio - > ds ) / sh_audio - > audio . dwSampleSize : sh_audio - > ds - > pack_no )
/ ( float ) ( sh_audio - > audio . dwLength ) ;
}
2002-01-27 21:34:31 +01:00
#if 0
mp_msg ( MSGT_AVSYNC , MSGL_STATUS , " %d < %d < %d \r " ,
( int ) demuxer - > movi_start ,
( int ) demuxer - > filepos ,
( int ) demuxer - > movi_end ) ;
# else
2002-01-27 22:46:06 +01:00
mp_msg ( MSGT_AVSYNC , MSGL_STATUS , " Pos:%6.1fs %6df (%2d%%) %3dfps Trem:%4dmin %3dmb A-V:%5.3f [%d:%d] \r " ,
2002-01-27 19:29:33 +01:00
mux_v - > timer , decoded_frameno , ( int ) ( p * 100 ) ,
( t > 1 ) ? ( int ) ( decoded_frameno / t ) : 0 ,
2002-01-27 21:34:31 +01:00
( p > 0.001 ) ? ( int ) ( ( t / p - t ) / 60 ) : 0 ,
2002-01-27 19:29:33 +01:00
( p > 0.001 ) ? ( int ) ( ftell ( muxer_f ) / p / 1024 / 1024 ) : 0 ,
2002-01-27 22:46:06 +01:00
v_pts_corr ,
( mux_v - > timer > 1 ) ? ( int ) ( mux_v - > size / mux_v - > timer / 125 ) : 0 ,
2002-01-31 01:38:53 +01:00
( mux_a & & mux_a - > timer > 1 ) ? ( int ) ( mux_a - > size / mux_a - > timer / 125 ) : 0
2002-01-27 19:29:33 +01:00
) ;
2002-01-27 21:34:31 +01:00
# endif
2002-01-27 19:29:33 +01:00
}
2001-11-01 03:31:23 +01:00
fflush ( stdout ) ;
2001-10-29 02:11:18 +01:00
} // while(!eof)
2001-12-06 23:27:09 +01:00
# ifdef HAVE_MP3LAME
// fixup CBR mp3 audio header:
2001-12-06 22:50:35 +01:00
if ( sh_audio & & mux_a - > codec = = ACODEC_VBRMP3 & & ! lame_param_vbr ) {
mux_a - > h . dwSampleSize = 1 ;
mux_a - > h . dwRate = mux_a - > wf - > nAvgBytesPerSec ;
mux_a - > h . dwScale = 1 ;
printf ( " \n \n CBR audio effective bitrate: %8.3f kbit/s (%d bytes/sec) \n " ,
mux_a - > h . dwRate * 8.0f / 1000.0f , mux_a - > h . dwRate ) ;
}
2001-12-06 23:27:09 +01:00
# endif
2001-12-06 22:50:35 +01:00
2001-12-22 17:59:10 +01:00
# ifdef USE_LIBAVCODEC
if ( mux_v - > codec = = VCODEC_LIBAVCODEC )
avcodec_close ( & lavc_venc_context ) ;
# endif
2001-11-11 17:15:24 +01:00
printf ( " \n Writing AVI index... \n " ) ;
2001-10-29 02:11:18 +01:00
aviwrite_write_index ( muxer , muxer_f ) ;
2002-01-27 15:16:32 +01:00
muxer_f_size = ftell ( muxer_f ) ;
2001-11-02 03:08:00 +01:00
printf ( " Fixup AVI header... \n " ) ;
2001-10-29 02:11:18 +01:00
fseek ( muxer_f , 0 , SEEK_SET ) ;
aviwrite_write_header ( muxer , muxer_f ) ; // update header
2002-01-27 15:16:32 +01:00
fclose ( muxer_f ) ;
2002-01-27 01:43:57 +01:00
if ( out_video_codec = = VCODEC_FRAMENO & & mux_v - > timer > 100 ) {
2002-01-27 21:34:31 +01:00
printf ( " Recommended video bitrate for 650MB CD: %d \n " , ( int ) ( ( 650 * 1024 * 1024 - muxer_f_size ) / mux_v - > timer / 125 ) ) ;
printf ( " Recommended video bitrate for 700MB CD: %d \n " , ( int ) ( ( 700 * 1024 * 1024 - muxer_f_size ) / mux_v - > timer / 125 ) ) ;
printf ( " Recommended video bitrate for 800MB CD: %d \n " , ( int ) ( ( 800 * 1024 * 1024 - muxer_f_size ) / mux_v - > timer / 125 ) ) ;
2002-01-27 01:43:57 +01:00
}
2002-01-26 17:32:06 +01:00
printf ( " \n Video stream: %8.3f kbit/s (%d bps) size: %d bytes %5.3f secs %d frames \n " ,
( float ) ( mux_v - > size / mux_v - > timer * 8.0f / 1000.0f ) , ( int ) ( mux_v - > size / mux_v - > timer ) , mux_v - > size , ( float ) mux_v - > timer , decoded_frameno ) ;
2001-12-07 00:59:46 +01:00
if ( sh_audio )
printf ( " \n Audio stream: %8.3f kbit/s (%d bps) size: %d bytes %5.3f secs \n " ,
( float ) ( mux_a - > size / mux_a - > timer * 8.0f / 1000.0f ) , ( int ) ( mux_a - > size / mux_a - > timer ) , mux_a - > size , ( float ) mux_a - > timer ) ;
2001-11-02 02:25:13 +01:00
if ( stream ) free_stream ( stream ) ; // kill cache thread
2001-12-04 21:35:31 +01:00
return interrupted ;
2001-10-29 02:11:18 +01:00
}
2002-01-15 01:20:50 +01:00
static int parse_end_at ( struct config * conf , const char * param )
{
int i ;
end_at_type = END_AT_NONE ;
/* End at size parsing */
{
char unit [ 4 ] ;
end_at_type = END_AT_SIZE ;
if ( sscanf ( param , " %d%3s " , & end_at , unit ) = = 2 ) {
if ( ! strcasecmp ( unit , " b " ) )
;
else if ( ! strcasecmp ( unit , " kb " ) )
end_at * = 1024 ;
else if ( ! strcasecmp ( unit , " mb " ) )
end_at * = 1024 * 1024 ;
else
end_at_type = END_AT_NONE ;
}
else
end_at_type = END_AT_NONE ;
}
/* End at time parsing. This has to be last because of
* sscanf ( " %f " , . . . ) below */
if ( end_at_type = = END_AT_NONE )
{
int a , b ; float d ;
end_at_type = END_AT_TIME ;
if ( sscanf ( param , " %d:%d:%f " , & a , & b , & d ) = = 3 )
end_at = 3600 * a + 60 * b + d ;
else if ( sscanf ( param , " %d:%f " , & a , & d ) = = 2 )
end_at = 60 * a + d ;
else if ( sscanf ( param , " %f " , & d ) = = 1 )
end_at = d ;
else
end_at_type = END_AT_NONE ;
}
if ( end_at_type = = END_AT_NONE )
return ERR_FUNC_ERR ;
return 1 ;
}
2002-01-31 01:38:53 +01:00
/* Flip the image in src and store the result in dst. src and dst may overlap.
width is the size of each line in bytes . */
static uint8_t * flip_upside_down ( uint8_t * dst , const uint8_t * src , int width ,
int height )
{
uint8_t * tmp = malloc ( width ) ;
int i ;
for ( i = 0 ; i < height / 2 ; i + + ) {
memcpy ( tmp , & src [ i * width ] , width ) ;
memcpy ( & dst [ i * width ] , & src [ ( height - i ) * width ] , width ) ;
memcpy ( & dst [ ( height - i ) * width ] , tmp , width ) ;
}
free ( tmp ) ;
return dst ;
}