Commit 630b0fc7 authored by Gildas Bazin's avatar Gildas Bazin

* modules/codec/ffmpeg/*: ported the ffmpeg audio and video decoders to the new api.
   Isolated the video postprocessing routines in postprocess.c

* modules/codec/ffmpeg/encoder.c, modules/codec/vorbis.c, modules/stream_out/transcode.c,
   include/vlc_block.h, include/vlc_codec.h: extracted the encoders out of transcode.c.
   transcode now uses encoder plugins (currently ffmpeg, vorbis and theora).

PS: transcoding is currently a bit broken but I'll fix that ASAP.
parent 074f7be5
dnl Autoconf settings for vlc
dnl $Id: configure.ac,v 1.98 2003/10/26 17:11:56 gbazin Exp $
dnl $Id: configure.ac,v 1.99 2003/10/27 01:04:38 gbazin Exp $
AC_INIT(vlc,0.6.3-cvs)
......@@ -1706,13 +1706,6 @@ then
AC_MSG_ERROR([cannot find ${real_ffmpeg_tree}/libavcodec/libavcodec.a, make sure you compiled libavcodec in ${with_ffmpeg_tree}])
fi
fi
ac_have_vorbis_headers=yes
AC_CHECK_HEADERS(vorbis/vorbisenc.h vorbis/codec.h,,
ac_have_vorbis_headers=no)
if test "$ac_have_vorbis_headers" = "yes"; then
AX_ADD_LDFLAGS([stream_out_transcode],[-lvorbisenc -lvorbis -logg])
fi
fi
dnl
......@@ -2020,6 +2013,9 @@ then
AC_CHECK_HEADERS(vorbis/codec.h, [
AX_ADD_PLUGINS([vorbis])
AX_ADD_LDFLAGS([vorbis],[-lvorbis -logg]) ],[])
AC_CHECK_HEADERS(vorbis/vorbisenc.h, [
AX_ADD_LDFLAGS([vorbis],[-lvorbisenc]) ],[])
fi
dnl
......
......@@ -2,7 +2,7 @@
* vlc_block.h: Data blocks management functions
*****************************************************************************
* Copyright (C) 2003 VideoLAN
* $Id: vlc_block.h,v 1.3 2003/09/30 20:23:03 gbazin Exp $
* $Id: vlc_block.h,v 1.4 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -37,6 +37,7 @@ struct block_t
vlc_bool_t b_frame_start;
mtime_t i_pts;
mtime_t i_dts;
mtime_t i_length;
vlc_bool_t b_discontinuity; /* only temporary */
......
......@@ -2,7 +2,7 @@
* vlc_codec.h: codec related structures
*****************************************************************************
* Copyright (C) 1999-2003 VideoLAN
* $Id: vlc_codec.h,v 1.1 2003/10/08 21:01:07 gbazin Exp $
* $Id: vlc_codec.h,v 1.2 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -87,6 +87,20 @@ struct encoder_t
/* Properties of the output of the encoder */
vlc_fourcc_t i_fourcc;
int i_bitrate;
int i_extra_data;
uint8_t *p_extra_data;
/* FIXME: move these to the ffmpeg encoder */
int i_frame_rate;
int i_frame_rate_base;
int i_key_int;
int i_b_frames;
int i_vtolerance;
int i_qmin;
int i_qmax;
int i_hq;
};
/**
......
......@@ -2,9 +2,9 @@ SOURCES_ffmpeg = \
ffmpeg.c \
ffmpeg.h \
video.c \
video.h \
audio.c \
audio.h \
chroma.c \
encoder.c \
postprocess.c \
$(NULL)
This diff is collapsed.
/*****************************************************************************
* audio.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: audio.h,v 1.4 2003/02/07 01:22:55 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.
*****************************************************************************/
typedef struct adec_thread_s
{
DECODER_THREAD_COMMON
// waveformatex_t format;
/*
* Output properties
*/
uint8_t * p_output;
aout_instance_t * p_aout; /* opaque */
aout_input_t * p_aout_input; /* opaque */
audio_sample_format_t output_format;
audio_date_t date;
} adec_thread_t;
/*
* Local prototypes
*/
int E_( InitThread_Audio ) ( adec_thread_t * );
void E_( EndThread_Audio ) ( adec_thread_t * );
void E_( DecodeThread_Audio ) ( adec_thread_t * );
......@@ -2,7 +2,7 @@
* chroma.c: chroma conversion using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: chroma.c,v 1.2 2003/09/26 16:10:24 gbazin Exp $
* $Id: chroma.c,v 1.3 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -38,7 +38,7 @@
#include "ffmpeg.h"
void E_(ffmpeg_InitLibavcodec) ( vlc_object_t *p_object );
void E_(InitLibavcodec) ( vlc_object_t *p_object );
static void ChromaConversion( vout_thread_t *, picture_t *, picture_t * );
/*****************************************************************************
......@@ -104,7 +104,7 @@ int E_(OpenChroma)( vlc_object_t *p_this )
case VLC_FOURCC('U','Y','V','Y'):
i_ffmpeg_chroma[i] = PIX_FMT_YUV422;
break;
/* Packed RGB formats */
case VLC_FOURCC('R','V','3','2'):
......@@ -148,7 +148,7 @@ int E_(OpenChroma)( vlc_object_t *p_this )
p_vout->chroma.p_sys->i_dst_ffmpeg_chroma = i_ffmpeg_chroma[1];
/* libavcodec needs to be initialized for some chroma conversions */
E_(ffmpeg_InitLibavcodec)(p_this);
E_(InitLibavcodec)(p_this);
return VLC_SUCCESS;
}
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
/*****************************************************************************
* postprocess.c: video postprocessing using the ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: postprocess.c,v 1.1 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
*
* 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.
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <string.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
/* ffmpeg header */
#ifdef HAVE_FFMPEG_AVCODEC_H
# include <ffmpeg/avcodec.h>
#else
# include <avcodec.h>
#endif
#include "ffmpeg.h"
#ifdef LIBAVCODEC_PP
#ifdef HAVE_POSTPROC_POSTPROCESS_H
# include <postproc/postprocess.h>
#else
# include <libpostproc/postprocess.h>
#endif
/*****************************************************************************
* video_postproc_sys_t : ffmpeg video postprocessing descriptor
*****************************************************************************/
typedef struct video_postproc_sys_t
{
pp_context_t *pp_context;
pp_mode_t *pp_mode;
int i_width;
int i_height;
} video_postproc_sys_t;
/*****************************************************************************
* OpenPostproc: probe and open the postproc
*****************************************************************************/
int E_(OpenPostproc)( decoder_t *p_dec, void **pp_data )
{
video_postproc_sys_t **pp_sys = (video_postproc_sys_t **)pp_data;
pp_mode_t *pp_mode;
vlc_value_t val;
/* ***** Load post processing if enabled ***** */
var_Create( p_dec, "ffmpeg-pp-q", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
var_Get( p_dec, "ffmpeg-pp-q", &val );
if( val.i_int > 0 )
{
int i_quality = val.i_int;
char *psz_name = config_GetPsz( p_dec, "ffmpeg-pp-name" );
if( !psz_name )
{
psz_name = strdup( "default" );
}
else if( *psz_name == '\0' )
{
free( psz_name );
psz_name = strdup( "default" );
}
pp_mode = pp_get_mode_by_name_and_quality( psz_name, i_quality );
if( !pp_mode )
{
msg_Err( p_dec, "failed geting mode for postproc" );
}
else
{
msg_Info( p_dec, "postprocessing activated" );
}
free( psz_name );
*pp_sys = malloc( sizeof(video_postproc_sys_t) );
(*pp_sys)->pp_context = NULL;
(*pp_sys)->pp_mode = NULL;
return VLC_SUCCESS;
}
else
{
msg_Dbg( p_dec, "no postprocessing enabled" );
return VLC_EGENERIC;
}
}
/*****************************************************************************
* InitPostproc:
*****************************************************************************/
int E_(InitPostproc)( decoder_t *p_dec, void *p_data,
int i_width, int i_height, int pix_fmt )
{
video_postproc_sys_t *p_sys = (video_postproc_sys_t *)p_data;
int32_t i_cpu = p_dec->p_libvlc->i_cpu;
int i_flags = 0;
if( i_cpu & CPU_CAPABILITY_MMX )
{
i_flags |= PP_CPU_CAPS_MMX;
}
if( i_cpu & CPU_CAPABILITY_MMXEXT )
{
i_flags |= PP_CPU_CAPS_MMX2;
}
if( i_cpu & CPU_CAPABILITY_3DNOW )
{
i_flags |= PP_CPU_CAPS_3DNOW;
}
switch( pix_fmt )
{
case PIX_FMT_YUV444P:
i_flags |= PP_FORMAT_444;
break;
case PIX_FMT_YUV422P:
i_flags |= PP_FORMAT_422;
break;
case PIX_FMT_YUV411P:
i_flags |= PP_FORMAT_411;
break;
default:
i_flags |= PP_FORMAT_420;
break;
}
p_sys->pp_context = pp_get_context( i_width, i_height, i_flags );
p_sys->i_width = i_width;
p_sys->i_height = i_height;
return VLC_SUCCESS;
}
/*****************************************************************************
* PostprocPict:
*****************************************************************************/
int E_(PostprocPict)( decoder_t *p_dec, void *p_data,
picture_t *p_pic, AVFrame *p_ff_pic )
{
video_postproc_sys_t *p_sys = (video_postproc_sys_t *)p_data;
uint8_t *src[3], *dst[3];
int i_plane, i_src_stride[3], i_dst_stride[3];
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
{
src[i_plane] = p_ff_pic->data[i_plane];
dst[i_plane] = p_pic->p[i_plane].p_pixels;
i_src_stride[i_plane] = p_ff_pic->linesize[i_plane];
i_dst_stride[i_plane] = p_pic->p[i_plane].i_pitch;
}
pp_postprocess( src, i_src_stride, dst, i_dst_stride,
p_sys->i_width, p_sys->i_height,
p_ff_pic->qscale_table, p_ff_pic->qstride,
p_sys->pp_mode, p_sys->pp_context,
p_ff_pic->pict_type );
return VLC_SUCCESS;
}
/*****************************************************************************
* ClosePostproc:
*****************************************************************************/
void E_(ClosePostproc)( decoder_t *p_dec, void *p_data )
{
video_postproc_sys_t *p_sys = (video_postproc_sys_t *)p_data;
if( p_sys && p_sys->pp_mode )
{
pp_free_mode( p_sys->pp_mode );
if( p_sys->pp_context ) pp_free_context( p_sys->pp_context );
}
}
#endif /* LIBAVCODEC_PP */
This diff is collapsed.
/*****************************************************************************
* video.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: video.h,v 1.11 2003/08/12 17:01:35 gbazin 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.
*****************************************************************************/
typedef struct vdec_thread_s
{
DECODER_THREAD_COMMON
AVFrame *p_ff_pic;
BITMAPINFOHEADER *p_format;
vout_thread_t *p_vout;
/* for post processing */
#ifdef LIBAVCODEC_PP
pp_context_t *pp_context;
pp_mode_t *pp_mode;
#endif
/* for frame skipping algo */
int b_hurry_up;
int i_frame_error;
int i_frame_skip;
vlc_bool_t b_has_b_frames;
int i_frame_late; /* how many decoded frames are late */
mtime_t i_frame_late_start;
/* for direct rendering */
int b_direct_rendering;
} vdec_thread_t;
int E_( InitThread_Video ) ( vdec_thread_t * );
void E_( EndThread_Video ) ( vdec_thread_t * );
void E_( DecodeThread_Video ) ( vdec_thread_t * );
......@@ -2,7 +2,7 @@
* vorbis.c: vorbis decoder module making use of libvorbis.
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: vorbis.c,v 1.19 2003/09/28 16:50:05 gbazin Exp $
* $Id: vorbis.c,v 1.20 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Gildas Bazin <gbazin@netcourrier.com>
*
......@@ -37,10 +37,21 @@
#include <vlc/input.h>
#include <ogg/ogg.h>
#ifdef MODULE_NAME_IS_tremor
#include <tremor/ivorbiscodec.h>
#else
#include <vorbis/codec.h>
/* vorbis header */
#ifdef HAVE_VORBIS_VORBISENC_H
# include <vorbis/vorbisenc.h>
# ifndef OV_ECTL_RATEMANAGE_AVG
# define OV_ECTL_RATEMANAGE_AVG 0x0
# endif
#endif
#endif
/*****************************************************************************
......@@ -121,10 +132,18 @@ static void Interleave ( int32_t *, const int32_t **, int, int );
static void Interleave ( float *, const float **, int, int );
#endif
#ifndef MODULE_NAME_IS_tremor
static int OpenEncoder ( vlc_object_t * );
static void CloseEncoder ( vlc_object_t * );
static block_t *Headers ( encoder_t * );
static block_t *Encode ( encoder_t *, aout_buffer_t * );
#endif
/*****************************************************************************
* Module descriptor
*****************************************************************************/
vlc_module_begin();
set_description( _("Vorbis audio decoder") );
#ifdef MODULE_NAME_IS_tremor
set_capability( "decoder", 90 );
......@@ -137,6 +156,14 @@ vlc_module_begin();
set_description( _("Vorbis audio packetizer") );
set_capability( "packetizer", 100 );
set_callbacks( OpenPacketizer, NULL );
#ifndef MODULE_NAME_IS_tremor
add_submodule();
set_description( _("Vorbis audio encoder") );
set_capability( "audio encoder", 100 );
set_callbacks( OpenEncoder, CloseEncoder );
#endif
vlc_module_end();
/*****************************************************************************
......@@ -576,3 +603,229 @@ static int EndDecoder( decoder_t * p_dec )
return VLC_SUCCESS;
}
#if defined(HAVE_VORBIS_VORBISENC_H) && !defined(MODULE_NAME_IS_tremor)
/*****************************************************************************
* encoder_sys_t : theora encoder descriptor
*****************************************************************************/
struct encoder_sys_t
{
/*
* Input properties
*/
int i_headers;
/*
* Vorbis properties
*/
vorbis_info vi; /* struct that stores all the static vorbis bitstream
settings */
vorbis_comment vc; /* struct that stores all the bitstream user
* comments */
vorbis_dsp_state vd; /* central working state for the packet->PCM
* decoder */
vorbis_block vb; /* local working space for packet->PCM decode */
int i_last_block_size;
int i_samples_delay;
/*
* Packetizer output properties
*/
sout_packetizer_input_t *p_sout_input;
sout_format_t sout_format;
/*
* Common properties
*/
mtime_t i_pts;
};
/*****************************************************************************
* OpenEncoder: probe the encoder and return score
*****************************************************************************/
static int OpenEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys = p_enc->p_sys;
if( p_enc->i_fourcc != VLC_FOURCC('v','o','r','b') )
{
return VLC_EGENERIC;
}
/* Allocate the memory needed to store the decoder's structure */
if( ( p_sys = (encoder_sys_t *)malloc(sizeof(encoder_sys_t)) ) == NULL )
{
msg_Err( p_enc, "out of memory" );
return VLC_EGENERIC;
}
p_enc->p_sys = p_sys;
p_enc->pf_header = Headers;
p_enc->pf_encode_audio = Encode;
p_enc->format.audio.i_format = VLC_FOURCC('f','l','3','2');
/* Initialize vorbis encoder */
vorbis_info_init( &p_sys->vi );
if( vorbis_encode_setup_managed( &p_sys->vi,
aout_FormatNbChannels( &p_enc->format.audio ),
p_enc->format.audio.i_rate, -1, p_enc->i_bitrate, -1 ) ||
vorbis_encode_ctl( &p_sys->vi, OV_ECTL_RATEMANAGE_AVG, NULL ) ||
vorbis_encode_setup_init( &p_sys->vi ) ){}
/* add a comment */
vorbis_comment_init( &p_sys->vc);
vorbis_comment_add_tag( &p_sys->vc, "ENCODER", "VLC media player");
/* set up the analysis state and auxiliary encoding storage */
vorbis_analysis_init( &p_sys->vd, &p_sys->vi );
vorbis_block_init( &p_sys->vd, &p_sys->vb );
p_sys->i_last_block_size = 0;
p_sys->i_samples_delay = 0;
p_sys->i_headers = 0;
p_sys->i_pts = 0;
return VLC_SUCCESS;
}
/****************************************************************************
* Encode: the whole thing
****************************************************************************
* This function spits out ogg packets.
****************************************************************************/
static block_t *Headers( encoder_t *p_enc )
{
encoder_sys_t *p_sys = p_enc->p_sys;
block_t *p_block, **pp_block = NULL;
/* Create theora headers */
if( !p_sys->i_headers )
{
ogg_packet header[3];
int i;
vorbis_analysis_headerout( &p_sys->vd, &p_sys->vc,
&header[0], &header[1], &header[2]);
for( i = 0; i < 3; i++ )
{
p_block = block_New( p_enc, header[i].bytes );
memcpy( p_block->p_buffer, header[i].packet, header[i].bytes );
p_block->i_dts = p_block->i_pts = p_block->i_length = 0;
block_ChainAppend( pp_block, p_block );
}
p_sys->i_headers = 3;
return *pp_block;
}
return NULL;
}
/****************************************************************************
* Encode: the whole thing
****************************************************************************
* This function spits out ogg packets.
****************************************************************************/
static block_t *Encode( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
{
encoder_sys_t *p_sys = p_enc->p_sys;
ogg_packet oggpacket;
block_t *p_block, *p_chain = NULL;
float **buffer;
int i_samples;
p_sys->i_pts = p_aout_buf->start_date -
(mtime_t)1000000 * (mtime_t)p_sys->i_samples_delay /
(mtime_t)p_enc->format.audio.i_rate;
i_samples = p_aout_buf->i_nb_samples;
p_sys->i_samples_delay += i_samples;
buffer = vorbis_analysis_buffer( &p_sys->vd, i_samples );
#if 0
if( id->ff_dec_c->channels != id->ff_enc_c->channels )
{
int i, j;
/* dumb downmixing */
for( i = 0; i < id->ff_enc_c->frame_size; i++ )
{
for( j = 0 ; j < id->f_dst.i_channels; j++ )
{
p_buffer[i*id->f_dst.i_channels+j] =
p_buffer[i*id->f_src.i_channels+j];
}
}
}
/* convert samples to float and uninterleave */
for( i = 0; i < id->f_dst.i_channels; i++ )
{
for( j = 0 ; j < i_samples ; j++ )
{
buffer[i][j]= ((float)( ((int16_t *)id->p_buffer)
[j*id->f_src.i_channels + i ] ))/ 32768.f;
}
}
#endif
vorbis_analysis_wrote( &p_sys->vd, i_samples );
while( vorbis_analysis_blockout( &p_sys->vd, &p_sys->vb ) == 1 )
{
vorbis_analysis( &p_sys->vb, NULL );
vorbis_bitrate_addblock( &p_sys->vb );
while( vorbis_bitrate_flushpacket( &p_sys->vd, &oggpacket ) )
{
int i_block_size;
p_block = block_New( p_enc, oggpacket.bytes );
memcpy( p_block->p_buffer, oggpacket.packet, oggpacket.bytes );
i_block_size = vorbis_packet_blocksize( &p_sys->vi, &oggpacket );
if( i_block_size < 0 ) i_block_size = 0;
i_samples = ( p_sys->i_last_block_size + i_block_size ) >> 2;
p_sys->i_last_block_size = i_block_size;
p_block->i_length = (mtime_t)1000000 *
(mtime_t)i_samples / (mtime_t)p_enc->format.audio.i_rate;
p_block->i_dts = p_block->i_pts = p_sys->i_pts;
p_sys->i_samples_delay -= i_samples;
/* Update pts */
p_sys->i_pts += p_block->i_length;
block_ChainAppend( &p_chain, p_block );
}
}
return p_chain;
}
/*****************************************************************************
* CloseEncoder: theora encoder destruction
*****************************************************************************/
static void CloseEncoder( vlc_object_t *p_this )
{
encoder_t *p_enc = (encoder_t *)p_this;
encoder_sys_t *p_sys = p_enc->p_sys;
vorbis_block_clear( &p_sys->vb );
vorbis_dsp_clear( &p_sys->vd );
vorbis_comment_clear( &p_sys->vc );
vorbis_info_clear( &p_sys->vi ); /* must be called last */
free( p_sys );
}
#endif /* HAVE_VORBIS_VORBISENC_H && !MODULE_NAME_IS_tremor */
This diff is collapsed.
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