Commit 412d64b1 authored by Laurent Aimar's avatar Laurent Aimar

* added file needed for video transcoding with vlc.

parent 6ea48839
/*****************************************************************************
* encoder.h :
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: encoder.h,v 1.1 2003/01/22 10:41:57 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
#ifndef _ENCODER_H
#define _ENCODER_H
typedef struct encoder_sys_t encoder_sys_t;
typedef struct video_encoder_s
{
VLC_COMMON_MEMBERS
module_t * p_module;
vlc_fourcc_t i_codec; /* in */
vlc_fourcc_t i_chroma; /* in/out */
int i_width; /* in/out */
int i_height; /* in/out */
int i_aspect; /* in/out */
size_t i_buffer_size; /* in/out */
encoder_sys_t *p_sys;
int (*pf_init) ( struct video_encoder_s *p_enc );
int (*pf_encode) ( struct video_encoder_s *p_enc, picture_t *p_pic, void *p_data, size_t *pi_data );
void (*pf_end) ( struct video_encoder_s *p_enc );
} video_encoder_t;
/*
* Video decoder:
*
* = at loading a video decoder must
* * see if i_codec is supporte, if not => failling
* * modify i_width/i_height/i_chroma/i_aspect if required (for example,
* if a video codec required %8 size)
* * init/check the library
* * set pf_init, pf_encode and pf_end
* * set i_buffer_size to the max buffer size required to output a single frame
*
* = pf_init must
* * start encoding processing
* * doesn't change any parameters (i_chroma/i_width/i_height/i_aspect)
* * check for passed parameters (no one for the moment)
*
* = pf_encode must
* * encode a single frame
* * doesn't change any parameters (...)
* * doesn't look for passed paramters
*
* = pf_end must
* * end the encoding process
* * revert all that pf_init (and pf_encode) has done (memory...)
*
* = at unloading, a video decoder must revert all that was done while loading
*
* XXX: pf_init/pf_end could be called multiple time without the plugin unloaded.
* XXX: all memory allocated by video encoder MUST be unallocated by video encoder
*
*/
#endif
SOURCES_encoder_xvid = modules/encoder/xvid.c
SOURCES_encoder_ffmpeg = \
modules/encoder/ffmpeg/encoder.c \
modules/encoder/ffmpeg/video.c \
modules/encoder/ffmpeg/audio.c \
$(NULL)
/*****************************************************************************
* audio.c : audio encoder using ffmpeg library
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: audio.c,v 1.1 2003/01/22 10:41:57 fenrir Exp $
*
* Authors: Laurent Aimar
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/input.h>
#include <vlc/decoder.h>
#include <stdlib.h>
#include "codecs.h"
#include <avcodec.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
int E_( OpenEncoderAudio ) ( vlc_object_t * );
void E_( CloseEncoderAudio )( vlc_object_t * );
struct encoder_sys_t
{
void *audio_handle;
};
int E_( OpenEncoderAudio ) ( vlc_object_t *p_this )
{
return VLC_EGENERIC;
}
void E_( CloseEncoderAudio )( vlc_object_t *p_this )
{
;
}
/*****************************************************************************
* encoder.c : audio/video encoder using ffmpeg library
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: encoder.c,v 1.1 2003/01/22 10:41:57 fenrir Exp $
*
* Authors: Laurent Aimar
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/input.h>
#include <vlc/decoder.h>
#include <stdlib.h>
#include "codecs.h"
#include "encoder.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
int E_( OpenEncoderVideo )( vlc_object_t * );
void E_( CloseEncoderVideo )( vlc_object_t * );
int E_( OpenEncoderAudio ) ( vlc_object_t * );
void E_( CloseEncoderAudio )( vlc_object_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("ffmpeg encoder") );
add_shortcut( "ffmpeg" );
add_submodule();
set_capability( "video encoder", 100 );
set_callbacks( E_( OpenEncoderVideo ), E_( CloseEncoderVideo ) );
add_category_hint( "video setting", NULL );
add_integer( "encoder-ffmpeg-video-bitrate", 1000, NULL, "bitrate (kb/s)", "bitrate (kb/s)" );
add_integer( "encoder-ffmpeg-video-max-key-interval", 10, NULL, "max key interval", "maximum value of frames between two keyframes" );
add_integer( "encoder-ffmpeg-min-quantizer", 2, NULL, "min quantizer", "range 1-31" );
add_integer( "encoder-ffmpeg-max-quantizer", 31, NULL, "max quantizer", "range 1-31" );
add_submodule();
set_capability( "audio encoder", 50 );
set_callbacks( E_( OpenEncoderAudio ), E_( CloseEncoderAudio ) );
add_category_hint( "audio setting", NULL );
add_integer( "encoder-ffmpeg-audio-bitrate", 64, NULL, "bitrate (kb/s)", "bitrate (kb/s)" );
vlc_module_end();
#if 0
add_category_hint( "general setting", NULL );
add_integer( "encoder-xvid-bitrate", 1000, NULL, "bitrate (kb/s)", "bitrate (kb/s)" );
add_integer( "encoder-xvid-min-quantizer", 2, NULL, "min quantizer", "range 1-31" );
add_integer( "encoder-xvid-max-quantizer", 31, NULL, "max quantizer", "1-31" );
add_category_hint( "advanced setting", NULL );
add_integer( "encoder-xvid-reaction-delay-factor", -1, NULL, "rc reaction delay factor", "rate controler parameters");
add_integer( "encoder-xvid-averaging-period", -1, NULL, "rc averaging period", "rate controler parameters" );
add_integer( "encoder-xvid-buffer", -1, NULL, "rc buffer", "rate controler parameters" );
add_category_hint( "advanced frame setting", NULL );
add_string_from_list( "encoder-xvid-quantization", "MPEG", ppsz_xvid_quant_algo, NULL, "quantization algorithm", "" );
add_bool( "encoder-xvid-halfpel", 1, NULL, "half pixel motion estimation.", "" );
add_bool( "encoder-xvid-4mv", 0, NULL, "fourc vector per macroblock(need halfpel)", "" );
add_bool( "encoder-xvid-lumi-mask", 0, NULL, "use a lumimasking algorithm", "" );
add_bool( "encoder-xvid-adaptive-quant", 0, NULL, "perform an adaptative quantization", "" );
add_bool( "encoder-xvid-interlacing", 0, NULL, "use MPEG4 interlaced mode", "" );
add_string_from_list( "encoder-xvid-me", "", ppsz_xvid_me, NULL, "motion estimation", "" );
add_bool( "encoder-xvid-motion-advanceddiamond", 1, NULL, "motion advanceddiamond", "" );
add_bool( "encoder-xvid-motion-halfpeldiamond", 1, NULL, "motion halfpel diamond", "" );
add_bool( "encoder-xvid-motion-halfpelrefine", 1, NULL, "motion halfpelrefine", "" );
add_bool( "encoder-xvid-motion-extsearch", 1, NULL, "motion extsearch", "" );
add_bool( "encoder-xvid-motion-earlystop", 1, NULL, "motion earlystop", "" );
add_bool( "encoder-xvid-motion-quickstop", 1, NULL, "motion quickstop", "" );
add_bool( "encoder-xvid-motion-usesquares", 0, NULL, "use a square search", "" );
vlc_module_end();
#endif
/*****************************************************************************
* video.c : video encoder using ffmpeg library
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: video.c,v 1.1 2003/01/22 10:41:57 fenrir Exp $
*
* Authors: Laurent Aimar
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/input.h>
#include <vlc/decoder.h>
#include <stdlib.h>
#include "codecs.h"
#include "encoder.h"
#include <avcodec.h>
int E_( OpenEncoderVideo ) ( vlc_object_t * );
void E_( CloseEncoderVideo )( vlc_object_t * );
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Init ( video_encoder_t *p_encoder );
static int Encode ( video_encoder_t *p_encoder,
picture_t *p_pic, void *p_data, size_t *pi_data );
static void End ( video_encoder_t *p_encoder );
/*****************************************************************************
* Local definitions
*****************************************************************************/
struct encoder_sys_t
{
char *psz_codec;
AVCodecContext *p_context;
AVCodec *p_codec;
AVFrame *p_frame;
};
/*****************************************************************************
* OpenEncoderVideo:
*****************************************************************************
*
*****************************************************************************/
int E_( OpenEncoderVideo ) ( vlc_object_t *p_this )
{
video_encoder_t *p_encoder = (video_encoder_t*)p_this;
/* *** check supported codec *** */
switch( p_encoder->i_codec )
{
case VLC_FOURCC( 'm', 'p', '1', 'v' ):
case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
case VLC_FOURCC( 'm', 'p', '4', 'v' ):
break;
default:
return VLC_EGENERIC;
}
/* *** init library */
avcodec_init();
avcodec_register_all();
/* *** fix parameters *** */
/* FIXME be clever, some codec support additional chroma */
if( p_encoder->i_chroma != VLC_FOURCC( 'I', '4', '2', '0' ) )
{
p_encoder->i_chroma = VLC_FOURCC( 'I', '4', '2', '0' );
}
#if 0
p_encoder->i_width = ( p_encoder->i_width + 15 )&0xfffff8;
p_encoder->i_height = ( p_encoder->i_height + 15 )&0xfffff8;
#endif
/* *** set exported functions *** */
p_encoder->pf_init = Init;
p_encoder->pf_encode = Encode;
p_encoder->pf_end = End;
return VLC_SUCCESS;
}
/*****************************************************************************
* CloseEncoderVideo:
*****************************************************************************
*
*****************************************************************************/
void E_( CloseEncoderVideo )( vlc_object_t *p_this )
{
;
}
/*****************************************************************************
* Init:
*****************************************************************************
*
*****************************************************************************/
static int Init ( video_encoder_t *p_encoder )
{
encoder_sys_t *p_sys;
char *psz_codec;
int i_codec;
/* *** allocate memory *** */
if( !( p_encoder->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) ) ) )
{
msg_Err( p_encoder, "out of memory" );
return VLC_EGENERIC;
}
memset( p_sys, 0, sizeof( encoder_sys_t ) );
/* *** ask for the codec *** */
switch( p_encoder->i_codec )
{
case VLC_FOURCC( 'm', 'p', '1', 'v' ):
case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
psz_codec = "MPEG I";
i_codec = CODEC_ID_MPEG1VIDEO;
break;
case VLC_FOURCC( 'm', 'p', '4', 'v' ):
psz_codec = "MPEG-4";
i_codec = CODEC_ID_MPEG4;
break;
default:
return VLC_EGENERIC;
}
if( ( p_sys->p_codec = avcodec_find_encoder( i_codec ) ) == NULL )
{
msg_Err( p_encoder, "cannot find encoder for %s", p_encoder->p_sys->psz_codec );
return VLC_EGENERIC;
}
msg_Dbg( p_encoder, "encoding with %s", p_encoder->p_sys->psz_codec );
#define p_frame p_sys->p_frame
#define p_context p_sys->p_context
/* *** set context properties *** */
p_context = avcodec_alloc_context();
p_context->bit_rate = config_GetInt( p_encoder, "encoder-ffmpeg-video-bitrate" ) * 1000;
p_context->width = p_encoder->i_width;
p_context->height= p_encoder->i_height;
p_context->frame_rate = 25 * FRAME_RATE_BASE;
p_context->gop_size = config_GetInt( p_encoder, "encoder-ffmpeg-video-max-key-interval" );
p_context->qmin = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-min-quant" ), 31 ), 1 );
p_context->qmax = __MAX( __MIN( config_GetInt( p_encoder, "encoder-ffmpeg-video-max-quant" ), 31 ), 1 );
if( avcodec_open( p_context, p_encoder->p_sys->p_codec ) < 0 )
{
msg_Err( p_encoder, "failed to open %s codec", p_encoder->p_sys->psz_codec );
return VLC_EGENERIC;
}
p_frame = avcodec_alloc_frame();
switch( p_encoder->i_chroma )
{
case VLC_FOURCC( 'I', '4', '2', '0' ):
p_frame->pict_type = PIX_FMT_YUV420P;
break;
default:
return VLC_EGENERIC;
}
return VLC_SUCCESS;
#undef p_context
#undef p_frame
}
/*****************************************************************************
* Encode:
*****************************************************************************
*
*****************************************************************************/
static int Encode ( video_encoder_t *p_encoder,
picture_t *p_pic, void *p_data, size_t *pi_data )
{
#define p_frame p_encoder->p_sys->p_frame
#define p_context p_encoder->p_sys->p_context
int i;
for( i = 0; i < 3; i++ )
{
p_frame->linesize[i] = p_pic->p[i].i_pitch;
p_frame->data[i] = p_pic->p[i].p_pixels;
}
*pi_data = avcodec_encode_video( p_context, p_data, *pi_data, p_frame );
return VLC_SUCCESS;
#undef p_context
#undef p_frame
}
/*****************************************************************************
* End:
*****************************************************************************
*
*****************************************************************************/
static void End ( video_encoder_t *p_encoder )
{
avcodec_close( p_encoder->p_sys->p_context );
free( p_encoder->p_sys->p_context );
p_encoder->p_sys->p_context = NULL;
p_encoder->p_sys->p_codec = NULL;
}
/*****************************************************************************
* xvid.c: an encoder for libxvidcore, the Xvid video codec
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: xvid.c,v 1.1 2003/01/22 10:41:57 fenrir Exp $
*
* Authors: Laurent Aimar
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/input.h>
#include <vlc/decoder.h>
#include <stdlib.h>
#include "codecs.h"
#include "encoder.h"
#include <xvid.h>
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int OpenEncoder ( vlc_object_t * );
static void CloseEncoder ( vlc_object_t * );
static int Init ( video_encoder_t *p_encoder );
static int Encode ( video_encoder_t *p_encoder,
picture_t *p_pic, void *p_data, size_t *pi_data );
static void End ( video_encoder_t *p_encoder );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
static char * ppsz_xvid_quant_algo[] = { "MPEG", "H263",NULL };
static char * ppsz_xvid_me[] = { "", "zero", "logarithmic", "fullsearch", "pmvfast", "epzs", NULL };
vlc_module_begin();
set_description( _("XviD video encoder (MPEG-4)") );
set_capability( "video encoder", 50 );
set_callbacks( OpenEncoder, CloseEncoder );
add_shortcut( "xvid" );
add_category_hint( "general setting", NULL );
add_integer( "encoder-xvid-bitrate", 1000, NULL, "bitrate (kb/s)", "bitrate (kb/s)" );
add_integer( "encoder-xvid-min-quantizer", 2, NULL, "min quantizer", "range 1-31" );
add_integer( "encoder-xvid-max-quantizer", 31, NULL, "max quantizer", "1-31" );
add_integer( "encoder-xvid-max-key-interval", -1, NULL, "max key interval", "maximum value of frames between two keyframes" );
add_category_hint( "advanced setting", NULL );
add_integer( "encoder-xvid-reaction-delay-factor", -1, NULL, "rc reaction delay factor", "rate controler parameters");
add_integer( "encoder-xvid-averaging-period", -1, NULL, "rc averaging period", "rate controler parameters" );
add_integer( "encoder-xvid-buffer", -1, NULL, "rc buffer", "rate controler parameters" );
add_category_hint( "advanced frame setting", NULL );
add_string_from_list( "encoder-xvid-quantization", "MPEG", ppsz_xvid_quant_algo, NULL, "quantization algorithm", "" );
add_bool( "encoder-xvid-halfpel", 1, NULL, "half pixel motion estimation.", "" );
add_bool( "encoder-xvid-4mv", 0, NULL, "fourc vector per macroblock(need halfpel)", "" );
add_bool( "encoder-xvid-lumi-mask", 0, NULL, "use a lumimasking algorithm", "" );
add_bool( "encoder-xvid-adaptive-quant", 0, NULL, "perform an adaptative quantization", "" );
add_bool( "encoder-xvid-interlacing", 0, NULL, "use MPEG4 interlaced mode", "" );
add_string_from_list( "encoder-xvid-me", "", ppsz_xvid_me, NULL, "motion estimation", "" );
add_bool( "encoder-xvid-motion-advanceddiamond", 1, NULL, "motion advanceddiamond", "" );
add_bool( "encoder-xvid-motion-halfpeldiamond", 1, NULL, "motion halfpel diamond", "" );
add_bool( "encoder-xvid-motion-halfpelrefine", 1, NULL, "motion halfpelrefine", "" );
add_bool( "encoder-xvid-motion-extsearch", 1, NULL, "motion extsearch", "" );
add_bool( "encoder-xvid-motion-earlystop", 1, NULL, "motion earlystop", "" );
add_bool( "encoder-xvid-motion-quickstop", 1, NULL, "motion quickstop", "" );
add_bool( "encoder-xvid-motion-usesquares", 0, NULL, "use a square search", "" );
vlc_module_end();
struct encoder_sys_t
{
void *handle;
XVID_ENC_FRAME xframe;
};
/*****************************************************************************
* OpenEncoder:
*****************************************************************************
* Check the library and init it
* see if it can encode to the requested codec
*****************************************************************************/
static int OpenEncoder ( vlc_object_t *p_this )
{
video_encoder_t *p_encoder = (video_encoder_t*)p_this;
XVID_INIT_PARAM xinit;
int i_err;
if( p_encoder->i_codec != VLC_FOURCC( 'm', 'p', '4', 'v' ) )
{
/* unsupported codec */
return VLC_EGENERIC;
}
msg_Dbg( p_encoder, "XviD encoder compiled for API_VERSION:0x%x", API_VERSION );
/* init the library */
xinit.cpu_flags = 0;
if( ( i_err = xvid_init( NULL, 0, &xinit, NULL ) ) != XVID_ERR_OK )
{
msg_Err( p_encoder, "cannot init xvid library (err:0x%x)", i_err );
return VLC_EGENERIC;
}
/* check API_VERSION */
if( xinit.api_version != API_VERSION )
{
msg_Err( p_encoder, "API_VERSION version mismatch (library:0x%x)", xinit.api_version );
return VLC_EGENERIC;
}
msg_Dbg( p_encoder, "XviD api_version:0x%x core_build:0x%x cpu_flags:0x%x",
xinit.api_version,
xinit.core_build,
xinit.cpu_flags );
/* force some parameters */
if( p_encoder->i_chroma != VLC_FOURCC( 'Y', 'V', '1', '2' )&&
p_encoder->i_chroma != VLC_FOURCC( 'I', '4', '2', '0' ) )
{
p_encoder->i_chroma = VLC_FOURCC( 'I', '4', '2', '0' );
}
/* set exported functions */
p_encoder->pf_init = Init;
p_encoder->pf_encode = Encode;
p_encoder->pf_end = End;
return VLC_SUCCESS;
}
static void CloseEncoder ( vlc_object_t *p_this )
{
;
}
/*****************************************************************************
* Init:
*****************************************************************************
*
*****************************************************************************/
static int Init ( video_encoder_t *p_encoder )
{
encoder_sys_t *p_sys;
char *psz;
int i_err;
XVID_ENC_PARAM xparam;
if( !( p_encoder->p_sys = p_sys = malloc( sizeof( encoder_sys_t ) ) ) )
{
msg_Err( p_encoder, "out of memory" );
return VLC_EGENERIC;
}
memset( p_sys, 0, sizeof( encoder_sys_t ) );
/* *** open a instance of the codec *** */
xparam.width = p_encoder->i_width;
xparam.height = p_encoder->i_height;
/* framerat = xparam.fbase / xparam.fincr */
xparam.fincr = 1;
xparam.fbase = 25;
/* desired bitrate */
xparam.rc_bitrate = config_GetInt( p_encoder, "encoder-xvid-bitrate" ) * 1000;
/* setting to success in achive xparam.rc_bitrate */
xparam.rc_reaction_delay_factor = config_GetInt( p_encoder, "encoder-xvid-reaction-delay-factor" );
xparam.rc_averaging_period = config_GetInt( p_encoder, "encoder-xvid-averaging-period" );
xparam.rc_buffer = config_GetInt( p_encoder, "encoder-xvid-buffer" );
/* limit the range of allowed quantizers [1..31] */
xparam.min_quantizer = config_GetInt( p_encoder, "encoder-xvid-min-quantizer" );;
xparam.min_quantizer = __MAX( __MIN( xparam.min_quantizer, 31 ), 1 );
xparam.max_quantizer = config_GetInt( p_encoder, "encoder-xvid-max-quantizer" );
xparam.max_quantizer = __MAX( __MIN( xparam.max_quantizer, 31 ), 1 );
/* maximum value of frames between two keyframes */
xparam.max_key_interval = config_GetInt( p_encoder, "encoder-xvid-max-key-interval" );
switch( xvid_encore( NULL, XVID_ENC_CREATE, &xparam, NULL ) )
{
case XVID_ERR_OK:
msg_Dbg( p_encoder, "encoder creation successed" );
break;
case XVID_ERR_MEMORY:
msg_Err( p_encoder, "encoder creation failed, out of memory" );
return VLC_EGENERIC;
case XVID_ERR_FORMAT:
msg_Err( p_encoder, "encoder creation failed, bad format" );
return VLC_EGENERIC;
case XVID_ERR_FAIL:
default:
msg_Err( p_encoder, "encoder creation failed" );
return VLC_EGENERIC;
}
/* get the handle */
p_sys->handle = xparam.handle;
/* *** set xframe parameters *** */
#define xframe p_sys->xframe
/* set xframe.general options */
xframe.general = 0;
psz = config_GetPsz( p_encoder, "encoder-xvid-quantization" );
if( psz )
{
if( !strcmp( psz, "H263" ) )
{
xframe.general |= XVID_H263QUANT;
}
else
{
xframe.general |= XVID_MPEGQUANT;
}
free( psz );
}
if( config_GetInt( p_encoder, "encoder-xvid-halfpel" ) )
xframe.general |= XVID_HALFPEL;
if( config_GetInt( p_encoder, "encoder-xvid-4mv" ) )
xframe.general |= XVID_INTER4V;
if( config_GetInt( p_encoder, "encoder-xvid-lumi-mask" ) )
xframe.general |= XVID_LUMIMASKING;
if( config_GetInt( p_encoder, "encoder-xvid-adaptive-quant" ) )
xframe.general |= XVID_ADAPTIVEQUANT;
if( config_GetInt( p_encoder, "encoder-xvid-interlacing" ) )
xframe.general |= XVID_INTERLACING;
psz = config_GetPsz( p_encoder, "encoder-xvid-me" );
if( psz )
{
if( !strcmp( psz, "zero" ) )
{
xframe.general |= XVID_ME_ZERO;
}
else if( !strcmp( psz, "logarithmic" ) )
{
xframe.general |= XVID_ME_LOGARITHMIC;
}
else if( !strcmp( psz, "fullsearch" ) )
{
xframe.general |= XVID_ME_FULLSEARCH;
}
else if( !strcmp( psz, "pmvfast" ) )
{
xframe.general |= XVID_ME_PMVFAST;
}
else if( !strcmp( psz, "epzs" ) )
{
xframe.general |= XVID_ME_EPZS;
}
free( psz );
}
xframe.motion = 0;
if( config_GetInt( p_encoder, "encoder-xvid-motion-advanceddiamond" ) )
xframe.motion |= PMV_ADVANCEDDIAMOND16 | PMV_ADVANCEDDIAMOND8;
if( config_GetInt( p_encoder, "encoder-xvid-motion-halfpeldiamond" ) )
xframe.motion |= PMV_HALFPELDIAMOND16 | PMV_HALFPELDIAMOND8;
if( config_GetInt( p_encoder, "encoder-xvid-motion-halfpelrefine") )
xframe.motion |= PMV_HALFPELREFINE16 | PMV_HALFPELREFINE8;
if( config_GetInt( p_encoder, "encoder-xvid-motion-extsearch" ) )
xframe.motion |= PMV_EXTSEARCH16 | PMV_EXTSEARCH8;
if( config_GetInt( p_encoder, "encoder-xvid-motion-earlystop") )
xframe.motion |= PMV_EARLYSTOP16 | PMV_EARLYSTOP8;
if( config_GetInt( p_encoder, "encoder-xvid-motion-quickstop" ) )
xframe.motion |= PMV_QUICKSTOP16 | PMV_QUICKSTOP8;
if( config_GetInt( p_encoder, "encoder-xvid-motion-usesquares" ) )
xframe.motion |= PMV_USESQUARES16 | PMV_USESQUARES8;
/* no user quant matrix */
xframe.quant_intra_matrix = NULL;
xframe.quant_inter_matrix = NULL;
switch( p_encoder->i_chroma )
{
case VLC_FOURCC( 'Y', 'V', '1', '2' ):
xframe.colorspace = XVID_CSP_YV12;
case VLC_FOURCC( 'I', '4', '2', '0' ):
xframe.colorspace = XVID_CSP_I420;
}
/* != 0 -> force quant */
xframe.quant = 0;
#undef xframe
return VLC_SUCCESS;
}
/*****************************************************************************
* Encode: encode a single frame
*****************************************************************************
*
*****************************************************************************/
static int Encode ( video_encoder_t *p_encoder,
picture_t *p_pic, void *p_data, size_t *pi_data )
{
int i_err;
#define xframe p_encoder->p_sys->xframe
xframe.image = p_pic->p->p_pixels;
xframe.bitstream = p_data;
xframe.length = -1;
/* let codec decided between I-frame and P-frame */
xframe.intra = -1;
i_err = xvid_encore( p_encoder->p_sys->handle, XVID_ENC_ENCODE, &xframe, NULL );
*pi_data = xframe.length;
#undef xframe
return VLC_SUCCESS;
}
/*****************************************************************************
* End
*****************************************************************************
*
*****************************************************************************/
static void End ( video_encoder_t *p_encoder )
{
int i_err;
/* *** close the codec */
i_err = xvid_encore(p_encoder->p_sys->handle, XVID_ENC_DESTROY, NULL, NULL);
/* *** free memory */
free( p_encoder->p_sys );
msg_Dbg( p_encoder, "closing encoder (err:0x%x)", i_err );
return;
}
/*****************************************************************************
* encoder.c : encoder wrapper plugin for vlc
*****************************************************************************
* Copyright (C) 2002 VideoLAN
* $Id: encoder.c,v 1.1 2003/01/22 10:41:57 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/input.h>
#include "encoder.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static int Create ( vlc_object_t * );
static void Destroy ( vlc_object_t * );
static int Init ( vout_thread_t * );
static void End ( vout_thread_t * );
static int Manage ( vout_thread_t * );
static void Render ( vout_thread_t *, picture_t * );
static void Display ( vout_thread_t *, picture_t * );
static void SetPalette( vout_thread_t *, uint16_t *, uint16_t *, uint16_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Encoder wrapper module") );
set_capability( "video output", 0 );
set_callbacks( Create, Destroy );
add_shortcut( "encoder" );
vlc_module_end();
/*****************************************************************************
* vout_sys_t: video output descriptor
*****************************************************************************
* This structure is part of the video output thread descriptor.
* It describes the SVGAlib specific properties of an output thread.
*****************************************************************************/
struct vout_sys_t
{
vlc_fourcc_t i_codec;
video_encoder_t *p_encoder;
int i_buffer;
void *p_buffer;
input_thread_t *p_input;
es_descriptor_t *p_es;
};
/*****************************************************************************
* Create: allocates video thread
*****************************************************************************
* This function allocates and initializes a vout method.
*****************************************************************************/
static int Create( vlc_object_t *p_this )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
char *psz_sout;
char *psz_sout_vcodec;
vlc_fourcc_t i_codec;
psz_sout = config_GetPsz( p_vout, "sout" );
if( !psz_sout || !*psz_sout )
{
/* avoid bad infinite loop */
msg_Err( p_vout, "encoder video output should be used only in sout mode" );
if( psz_sout ) free( psz_sout );
return VLC_EGENERIC;
}
free( psz_sout );
psz_sout_vcodec = config_GetPsz( p_vout, "sout-vcodec" );
if( !psz_sout_vcodec || !*psz_sout_vcodec )
{
msg_Err( p_vout, "you have to specify a video codec using sout-vcodec" );
if( psz_sout_vcodec ) free( psz_sout_vcodec );
return VLC_EGENERIC;
}
if( !strcmp( psz_sout_vcodec, "mpeg4" ) )
{
i_codec = VLC_FOURCC( 'm', 'p', '4', 'v' );
}
else if( !strcmp( psz_sout_vcodec, "mpeg2" ) )
{
i_codec = VLC_FOURCC( 'm', 'p', '2', 'v' );
}
else if( !strcmp( psz_sout_vcodec, "mpeg1" ) )
{
i_codec = VLC_FOURCC( 'm', 'p', '1', 'v' );
}
else
{
int i;
int c[4];
msg_Warn( p_vout, "unknown codec %s used as a fourcc", psz_sout_vcodec );
for( i = 0; i < 4; i++ )
{
if( psz_sout_vcodec[i] )
c[i] = psz_sout_vcodec[i];
else
c[i] = ' ';
}
i_codec = VLC_FOURCC( c[0], c[1], c[2], c[3] );
}
free( psz_sout_vcodec );
/* Allocate instance and initialize some members */
if( !( p_vout->p_sys = malloc( sizeof( vout_sys_t ) ) ) )
{
return VLC_ENOMEM;
}
memset( p_vout->p_sys, 0, sizeof( vout_sys_t ) );
/* *** save parameters *** */
p_vout->p_sys->i_codec = i_codec;
/* *** set exported functions *** */
p_vout->pf_init = Init;
p_vout->pf_end = End;
p_vout->pf_render = Render;
p_vout->pf_manage = Manage;
p_vout->pf_display = Display;
return VLC_SUCCESS;
}
/*****************************************************************************
* Init: initialize video thread
*****************************************************************************/
static int Init( vout_thread_t *p_vout )
{
vout_sys_t *p_sys = p_vout->p_sys;
video_encoder_t *p_encoder = p_vout->p_sys->p_encoder;
char *psz_sout_vcodec;
int i_index;
picture_t *p_pic;
/* *** create a video encoder object *** */
p_vout->p_sys->p_encoder =
p_encoder = vlc_object_create( p_vout, sizeof( video_encoder_t ) );
/* *** set wanted input format *** */
p_encoder->i_codec = p_vout->p_sys->i_codec;
/* *** set prefered properties *** */
/* encoder can modify all these values except i_codec */
p_encoder->i_chroma = p_vout->render.i_chroma;
p_encoder->i_width = p_vout->render.i_width;
p_encoder->i_height = p_vout->render.i_height;
p_encoder->i_aspect = p_vout->render.i_aspect;
p_encoder->i_buffer_size = 0;
/* *** requuest this module *** */
p_encoder->p_module = module_Need( p_encoder,
"video encoder",
"$video-encoder" );
if( !p_encoder->p_module )
{
msg_Warn( p_vout,
"no suitable encoder to %4.4s",
(char*)&p_encoder->i_codec );
vlc_object_destroy( p_encoder );
return VLC_EGENERIC;
}
/* *** init the codec *** */
if( p_encoder->pf_init( p_encoder ) )
{
msg_Err( p_vout, "failed to initialize video encoder plugin" );
vlc_object_destroy( p_encoder );
return VLC_EGENERIC;
}
/* *** alloacted buffer *** */
if( p_encoder->i_buffer_size <= 0 )
{
p_encoder->i_buffer_size = 10 * p_encoder->i_width * p_encoder->i_height;
}
p_sys->i_buffer = p_encoder->i_buffer_size;
if( !( p_sys->p_buffer = malloc( p_encoder->i_buffer_size ) ) )
{
msg_Err( p_vout, "out of memory" );
return VLC_ENOMEM;
}
/* *** create a new standalone ES *** */
/* find a p_input */
p_sys->p_input = vlc_object_find( p_vout, VLC_OBJECT_INPUT, FIND_ANYWHERE );
if( !p_sys->p_input )
{
msg_Err( p_vout, "cannot find p_input" );
return VLC_EGENERIC;
}
vlc_mutex_lock( &p_sys->p_input->stream.stream_lock );
/* avoid bad loop (else output will also be reencoded until it segfault :p*/
/* XXX do it after the lock (if we have multiple video stream...) */
psz_sout_vcodec = config_GetPsz( p_vout, "sout-vcodec" );
config_PutPsz( p_vout, "sout-vcodec", NULL );
/* add a new stream */
p_sys->p_es = input_AddES( p_sys->p_input,
NULL, /* we aren't attached to a program */
12, /* es_id */
0 ); /* no extra data */
if( !p_sys->p_es )
{
msg_Err( p_vout, "cannot create es" );
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
return VLC_EGENERIC;
}
p_sys->p_es->i_stream_id = 1;
p_sys->p_es->i_fourcc = p_encoder->i_codec;
p_sys->p_es->i_cat = VIDEO_ES;
if( input_SelectES( p_sys->p_input, p_sys->p_es ) )
{
input_DelES( p_sys->p_input, p_sys->p_es );
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
msg_Err( p_vout, "cannot select es" );
return VLC_EGENERIC;
}
/* restore value as we could have multiple video stream (have you a 42*12 GHz ?) */
config_PutPsz( p_vout, "sout-vcodec", psz_sout_vcodec );
vlc_mutex_unlock( &p_sys->p_input->stream.stream_lock );
I_OUTPUTPICTURES = 0;
p_vout->output.pf_setpalette = SetPalette;
/* remember that this value could have been modified by encoder */
p_vout->output.i_chroma = p_vout->p_sys->p_encoder->i_chroma;
p_vout->output.i_width = p_vout->p_sys->p_encoder->i_width;
p_vout->output.i_height = p_vout->p_sys->p_encoder->i_height;
p_vout->output.i_aspect = p_vout->p_sys->p_encoder->i_aspect;
/* Try to initialize 1 direct buffer */
p_pic = NULL;
/* Find an empty picture slot */
for( i_index = 0 ; i_index < VOUT_MAX_PICTURES ; i_index++ )
{
if( p_vout->p_picture[ i_index ].i_status == FREE_PICTURE )
{
p_pic = p_vout->p_picture + i_index;
break;
}
}
/* Allocate the picture */
if( p_pic == NULL )
{
return VLC_SUCCESS;
}
vout_AllocatePicture( p_vout, p_pic, p_vout->output.i_width,
p_vout->output.i_height,
p_vout->output.i_chroma );
if( p_pic->i_planes == 0 )
{
return VLC_SUCCESS;
}
p_pic->i_status = DESTROYED_PICTURE;
p_pic->i_type = DIRECT_PICTURE;
PP_OUTPUTPICTURE[ I_OUTPUTPICTURES ] = p_pic;
I_OUTPUTPICTURES++;
return VLC_SUCCESS;
}
/*****************************************************************************
* End: terminate video thread
*****************************************************************************/
static void End( vout_thread_t *p_vout )
{
vout_sys_t *p_sys = p_vout->p_sys;
video_encoder_t *p_encoder = p_vout->p_sys->p_encoder;
/* *** stop encoder *** */
p_encoder->pf_end( p_encoder );
vlc_object_release( p_sys->p_input );
/* *** unload encoder plugin *** */
module_Unneed( p_encoder,
p_encoder->p_module );
vlc_object_destroy( p_encoder );
free( p_sys->p_buffer );
}
/*****************************************************************************
* Destroy: destroy video thread
*****************************************************************************
* Terminate an output method created by Create
*****************************************************************************/
static void Destroy( vlc_object_t *p_this )
{
vout_thread_t *p_vout = (vout_thread_t *)p_this;
/* Destroy structure */
free( p_vout->p_sys );
p_vout->p_sys = NULL;
}
/*****************************************************************************
* Manage: handle events
*****************************************************************************
* This function should be called regularly by video output thread. It manages
* console events. It returns a non null value on error.
*****************************************************************************/
static int Manage( vout_thread_t *p_vout )
{
return VLC_SUCCESS;
}
/*****************************************************************************
* Render:
*****************************************************************************
*
*****************************************************************************/
static void Render( vout_thread_t *p_vout, picture_t *p_pic )
{
}
/*****************************************************************************
* Display: displays previously rendered output
*****************************************************************************
* This function sends the currently rendered image to the VGA card.
*****************************************************************************/
static void Display( vout_thread_t *p_vout, picture_t *p_pic )
{
vout_sys_t *p_sys = p_vout->p_sys;
video_encoder_t *p_encoder = p_vout->p_sys->p_encoder;
int i_err;
size_t i_data;
i_data = p_sys->i_buffer;
i_err = p_encoder->pf_encode( p_encoder,
p_pic,
p_sys->p_buffer,
&i_data );
if( i_err )
{
msg_Err( p_vout, "failed to encode a frame (err:0x%x)", i_err );
return;
}
if( i_data > 0 && p_sys->p_es->p_decoder_fifo )
{
pes_packet_t *p_pes;
data_packet_t *p_data;
if( !( p_pes = input_NewPES( p_sys->p_input->p_method_data ) ) )
{
msg_Err( p_vout, "cannot allocate new PES" );
return;
}
if( !( p_data = input_NewPacket( p_sys->p_input->p_method_data, i_data ) ) )
{
msg_Err( p_vout, "cannot allocate new data_packet" );
return;
}
p_pes->i_dts = p_pic->date;
p_pes->i_pts = p_pic->date;
p_pes->p_first = p_pes->p_last = p_data;
p_pes->i_nb_data = 1;
p_pes->i_pes_size = i_data;
p_vout->p_vlc->pf_memcpy( p_data->p_payload_start,
p_sys->p_buffer,
i_data );
input_DecodePES( p_sys->p_es->p_decoder_fifo, p_pes );
}
}
/*****************************************************************************
* SetPalette: set a 8bpp palette
*****************************************************************************
* TODO: support 8 bits clut (for Mach32 cards and others).
*****************************************************************************/
static void SetPalette( vout_thread_t *p_vout, uint16_t *red, uint16_t *green, uint16_t *blue )
{
;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment