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)
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
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
* 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>
*
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 */
* 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>
*
/* 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;
+
};
/**
ffmpeg.c \
ffmpeg.h \
video.c \
- video.h \
audio.c \
- audio.h \
chroma.c \
+ encoder.c \
+ postprocess.c \
$(NULL)
/*****************************************************************************
* audio.c: audio decoder using ffmpeg library
*****************************************************************************
- * Copyright (C) 1999-2001 VideoLAN
- * $Id: audio.c,v 1.19 2003/07/10 01:33:41 fenrir Exp $
+ * Copyright (C) 1999-2003 VideoLAN
+ * $Id: audio.c,v 1.20 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
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <unistd.h> /* getpid() */
#endif
-#include <errno.h>
-#include <string.h>
-
#ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
#endif
+
#include "codecs.h"
#include "aout_internal.h"
# include <avcodec.h>
#endif
-//#include "postprocessing/postprocessing.h"
#include "ffmpeg.h"
#include "audio.h"
-/*
- * Local prototypes
- */
-int E_( InitThread_Audio ) ( adec_thread_t * );
-void E_( EndThread_Audio ) ( adec_thread_t * );
-void E_( DecodeThread_Audio ) ( adec_thread_t * );
-
static unsigned int pi_channels_maps[6] =
{
0,
AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
- AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT,
+ AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
+ | AOUT_CHAN_REARRIGHT,
AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
| AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
};
/*****************************************************************************
- * locales Functions
- *****************************************************************************/
-
-/*****************************************************************************
- *
- * Functions that initialize, decode and end the decoding process
- *
- * Functions exported for ffmpeg.c
- * * E_( InitThread_Audio )
- * * E_( DecodeThread_Audio )
- * * E_( EndThread_Video_Audio )
+ * decoder_sys_t : decoder descriptor
*****************************************************************************/
+struct decoder_sys_t
+{
+ /* Common part between video and audio decoder */
+ int i_cat;
+ int i_codec_id;
+ char *psz_namecodec;
+ AVCodecContext *p_context;
+ AVCodec *p_codec;
+
+ /* Temporary buffer for libavcodec */
+ uint8_t *p_output;
+
+ /*
+ * Output properties
+ */
+ aout_instance_t *p_aout;
+ aout_input_t *p_aout_input;
+ audio_sample_format_t aout_format;
+ audio_date_t end_date;
+};
/*****************************************************************************
- * InitThread: initialize vdec output thread
+ * InitAudioDec: initialize audio decoder
*****************************************************************************
- * This function is called from decoder_Run and performs the second step
- * of the initialization. It returns 0 on success. Note that the thread's
- * flag are not modified inside this function.
- *
- * ffmpeg codec will be open, some memory allocated.
+ * The ffmpeg codec will be opened, some memory allocated.
*****************************************************************************/
-int E_( InitThread_Audio )( adec_thread_t *p_adec )
+int E_(InitAudioDec)( decoder_t *p_dec, AVCodecContext *p_context,
+ AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
{
+ decoder_sys_t *p_sys;
WAVEFORMATEX wf, *p_wf;
- if( ( p_wf = p_adec->p_fifo->p_waveformatex ) == NULL )
+ /* Allocate the memory needed to store the decoder's structure */
+ if( ( p_dec->p_sys = p_sys =
+ (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
{
- msg_Warn( p_adec->p_fifo, "audio informations missing" );
+ msg_Err( p_dec, "out of memory" );
+ return VLC_EGENERIC;
+ }
+
+ p_dec->p_sys->p_context = p_context;
+ p_dec->p_sys->p_codec = p_codec;
+ p_dec->p_sys->i_codec_id = i_codec_id;
+ p_dec->p_sys->psz_namecodec = psz_namecodec;
+
+ if( ( p_wf = p_dec->p_fifo->p_waveformatex ) == NULL )
+ {
+ msg_Warn( p_dec, "audio informations missing" );
p_wf = &wf;
memset( p_wf, 0, sizeof( WAVEFORMATEX ) );
}
/* ***** Fill p_context with init values ***** */
- p_adec->p_context->sample_rate = p_wf->nSamplesPerSec;
- p_adec->p_context->channels = p_wf->nChannels;
- p_adec->p_context->block_align = p_wf->nBlockAlign;
- p_adec->p_context->bit_rate = p_wf->nAvgBytesPerSec * 8;
+ p_sys->p_context->sample_rate = p_wf->nSamplesPerSec;
+ p_sys->p_context->channels = p_wf->nChannels;
+ p_sys->p_context->block_align = p_wf->nBlockAlign;
+ p_sys->p_context->bit_rate = p_wf->nAvgBytesPerSec * 8;
- if( ( p_adec->p_context->extradata_size = p_wf->cbSize ) > 0 )
+ if( ( p_sys->p_context->extradata_size = p_wf->cbSize ) > 0 )
{
- p_adec->p_context->extradata = malloc( p_wf->cbSize + FF_INPUT_BUFFER_PADDING_SIZE );
-
- memcpy( p_adec->p_context->extradata, &p_wf[1], p_wf->cbSize);
- memset( &((uint8_t*)p_adec->p_context->extradata)[p_wf->cbSize], 0, FF_INPUT_BUFFER_PADDING_SIZE );
+ p_sys->p_context->extradata =
+ malloc( p_wf->cbSize + FF_INPUT_BUFFER_PADDING_SIZE );
+ memcpy( p_sys->p_context->extradata, &p_wf[1], p_wf->cbSize);
+ memset( &((uint8_t*)p_sys->p_context->extradata)[p_wf->cbSize], 0,
+ FF_INPUT_BUFFER_PADDING_SIZE );
}
/* ***** Open the codec ***** */
- if (avcodec_open(p_adec->p_context, p_adec->p_codec) < 0)
+ if (avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0)
{
- msg_Err( p_adec->p_fifo,
- "cannot open codec (%s)",
- p_adec->psz_namecodec );
- return( -1 );
+ msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
+ return VLC_EGENERIC;
}
else
{
- msg_Dbg( p_adec->p_fifo,
- "ffmpeg codec (%s) started",
- p_adec->psz_namecodec );
+ msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
}
- p_adec->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
-
+ p_sys->p_output = malloc( 3 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
- p_adec->output_format.i_format = AOUT_FMT_S16_NE;
- p_adec->output_format.i_rate = p_wf->nSamplesPerSec;
- p_adec->output_format.i_physical_channels
- = p_adec->output_format.i_original_channels
- = pi_channels_maps[p_wf->nChannels];
+ p_sys->p_aout = NULL;
+ p_sys->p_aout_input = NULL;
- p_adec->p_aout = NULL;
- p_adec->p_aout_input = NULL;
+ aout_DateSet( &p_sys->end_date, 0 );
- return( 0 );
+ return VLC_SUCCESS;
}
-
/*****************************************************************************
- * DecodeThread: Called for decode one frame
+ * DecodeAudio: Called to decode one frame
*****************************************************************************/
-void E_( DecodeThread_Audio )( adec_thread_t *p_adec )
+int E_( DecodeAudio )( decoder_t *p_dec, block_t *p_block )
{
- pes_packet_t *p_pes;
- aout_buffer_t *p_aout_buffer;
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ aout_buffer_t *p_aout_buffer;
+ mtime_t i_pts;
- int i_samplesperchannel;
- int i_output_size;
- int i_frame_size;
- int i_used;
+ uint8_t *p_buffer, *p_samples;
+ int i_buffer, i_samples;
- uint8_t *p;
+ if( !aout_DateGet( &p_sys->end_date ) && !p_block->i_pts )
+ {
+ /* We've just started the stream, wait for the first PTS. */
+ block_Release( p_block );
+ return VLC_SUCCESS;
+ }
- do
+ i_pts = p_block->i_pts;
+ i_buffer = p_block->i_buffer;
+ p_buffer = p_block->p_buffer;
+
+ while( i_buffer )
{
- input_ExtractPES( p_adec->p_fifo, &p_pes );
- if( !p_pes )
+ int i_used, i_output;
+
+ i_used = avcodec_decode_audio( p_sys->p_context,
+ (int16_t*)p_sys->p_output, &i_output,
+ p_buffer, i_buffer );
+ if( i_used < 0 )
{
- p_adec->p_fifo->b_error = 1;
- return;
+ msg_Warn( p_dec, "cannot decode one frame (%d bytes)", i_buffer );
+ break;
}
- p_adec->pts = p_pes->i_pts;
- i_frame_size = p_pes->i_pes_size;
- if( i_frame_size > 0 )
- {
- int i_need;
+ i_buffer -= i_used;
+ p_buffer += i_used;
+ if( p_sys->p_context->channels <= 0 || p_sys->p_context->channels > 6 )
+ {
+ msg_Warn( p_dec, "invalid channels count %d",
+ p_sys->p_context->channels );
+ break;
+ }
- i_need = i_frame_size + FF_INPUT_BUFFER_PADDING_SIZE + p_adec->i_buffer;
- if( p_adec->i_buffer_size < i_need )
+ /* **** First check if we have a valid output **** */
+ if( p_sys->p_aout_input == NULL ||
+ p_sys->aout_format.i_original_channels !=
+ pi_channels_maps[p_sys->p_context->channels] )
+ {
+ if( p_sys->p_aout_input != NULL )
{
- uint8_t *p_last = p_adec->p_buffer;
-
- p_adec->p_buffer = malloc( i_need );
- p_adec->i_buffer_size = i_need;
- if( p_adec->i_buffer > 0 )
- {
- memcpy( p_adec->p_buffer, p_last, p_adec->i_buffer );
- }
- FREE( p_last );
+ /* **** Delete the old **** */
+ aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
}
- i_frame_size =
- E_( GetPESData )( p_adec->p_buffer + p_adec->i_buffer,
- i_frame_size,
- p_pes );
- /* make ffmpeg happier but I'm not sure it's needed for audio */
- memset( p_adec->p_buffer + p_adec->i_buffer + i_frame_size, 0, FF_INPUT_BUFFER_PADDING_SIZE );
- }
- input_DeletePES( p_adec->p_fifo->p_packets_mgt, p_pes );
- } while( i_frame_size <= 0 );
-
- i_frame_size += p_adec->i_buffer;
+ /* **** Create a new audio output **** */
+ p_sys->aout_format.i_format = AOUT_FMT_S16_NE;
+ p_sys->aout_format.i_rate = p_sys->p_context->sample_rate;
+ p_sys->aout_format.i_physical_channels =
+ p_sys->aout_format.i_original_channels =
+ pi_channels_maps[p_sys->p_context->channels];
-usenextdata:
- i_used = avcodec_decode_audio( p_adec->p_context,
- (int16_t*)p_adec->p_output,
- &i_output_size,
- p_adec->p_buffer,
- i_frame_size );
- if( i_used < 0 )
- {
- msg_Warn( p_adec->p_fifo,
- "cannot decode one frame (%d bytes)",
- i_frame_size );
- p_adec->i_buffer = 0;
- return;
- }
- else if( i_used < i_frame_size )
- {
- memmove( p_adec->p_buffer,
- p_adec->p_buffer + i_used,
- p_adec->i_buffer_size - i_used );
-
- p_adec->i_buffer = i_frame_size - i_used;
- }
- else
- {
- p_adec->i_buffer = 0;
- }
-
- i_frame_size -= i_used;
-
- //msg_Dbg( p_adec->p_fifo, "frame size:%d buffer used:%d", i_frame_size, i_used );
- if( i_output_size <= 0 )
- {
- msg_Warn( p_adec->p_fifo,
- "decoded %d samples bytes",
- i_output_size );
- }
-
- if( p_adec->p_context->channels <= 0 ||
- p_adec->p_context->channels > 5 )
- {
- msg_Warn( p_adec->p_fifo,
- "invalid channels count %d",
- p_adec->p_context->channels );
- }
+ aout_DateInit( &p_sys->end_date, p_sys->aout_format.i_rate );
+ p_sys->p_aout_input = aout_DecNew( p_dec, &p_sys->p_aout,
+ &p_sys->aout_format );
+ }
- /* **** First check if we have a valid output **** */
- if( ( p_adec->p_aout_input == NULL )||
- ( p_adec->output_format.i_original_channels !=
- pi_channels_maps[p_adec->p_context->channels] ) )
- {
- if( p_adec->p_aout_input != NULL )
+ if( !p_sys->p_aout_input )
{
- /* **** Delete the old **** */
- aout_DecDelete( p_adec->p_aout, p_adec->p_aout_input );
+ msg_Err( p_dec, "cannot create audio output" );
+ block_Release( p_block );
+ return VLC_EGENERIC;
}
- /* **** Create a new audio output **** */
- p_adec->output_format.i_physical_channels =
- p_adec->output_format.i_original_channels =
- pi_channels_maps[p_adec->p_context->channels];
-
- aout_DateInit( &p_adec->date, p_adec->output_format.i_rate );
- p_adec->p_aout_input = aout_DecNew( p_adec->p_fifo,
- &p_adec->p_aout,
- &p_adec->output_format );
- }
-
- if( !p_adec->p_aout_input )
- {
- msg_Err( p_adec->p_fifo, "cannot create aout" );
- return;
- }
-
- if( p_adec->pts != 0 && p_adec->pts != aout_DateGet( &p_adec->date ) )
- {
- aout_DateSet( &p_adec->date, p_adec->pts );
- }
- else if( !aout_DateGet( &p_adec->date ) )
- {
- return;
- }
-
- /* **** Now we can output these samples **** */
- i_samplesperchannel = i_output_size / 2
- / aout_FormatNbChannels( &p_adec->output_format );
-
- p = &p_adec->p_output[0];
- while( i_samplesperchannel > 0 )
- {
- int i_samples;
+ if( i_pts != 0 && i_pts != aout_DateGet( &p_sys->end_date ) )
+ {
+ aout_DateSet( &p_sys->end_date, i_pts );
+ i_pts = 0;
+ }
- i_samples = __MIN( 8000, i_samplesperchannel );
+ /* **** Now we can output these samples **** */
+ i_samples = i_output / 2 / p_sys->p_context->channels;
- p_aout_buffer = aout_DecNewBuffer( p_adec->p_aout,
- p_adec->p_aout_input,
- i_samples );
- if( !p_aout_buffer )
+ p_samples = p_sys->p_output;
+ while( i_samples > 0 )
{
- msg_Err( p_adec->p_fifo, "cannot get aout buffer" );
- p_adec->p_fifo->b_error = 1;
- return;
- }
+ int i_smaller_samples;
- p_aout_buffer->start_date = aout_DateGet( &p_adec->date );
- p_aout_buffer->end_date = aout_DateIncrement( &p_adec->date,
- i_samples );
- memcpy( p_aout_buffer->p_buffer,
- p,
- p_aout_buffer->i_nb_bytes );
+ i_smaller_samples = __MIN( 8000, i_samples );
- aout_DecPlay( p_adec->p_aout, p_adec->p_aout_input, p_aout_buffer );
+ p_aout_buffer = aout_DecNewBuffer( p_sys->p_aout,
+ p_sys->p_aout_input,
+ i_smaller_samples );
+ if( !p_aout_buffer )
+ {
+ msg_Err( p_dec, "cannot get aout buffer" );
+ block_Release( p_block );
+ return VLC_EGENERIC;
+ }
- p += i_samples * 2 * aout_FormatNbChannels( &p_adec->output_format );
- i_samplesperchannel -= i_samples;
+ p_aout_buffer->start_date = aout_DateGet( &p_sys->end_date );
+ p_aout_buffer->end_date = aout_DateIncrement( &p_sys->end_date,
+ i_smaller_samples );
+ memcpy( p_aout_buffer->p_buffer, p_samples,
+ p_aout_buffer->i_nb_bytes );
- }
+ aout_DecPlay( p_sys->p_aout, p_sys->p_aout_input, p_aout_buffer );
- if( i_frame_size > 0 )
- {
- goto usenextdata;
+ p_samples += i_smaller_samples * 2 * p_sys->p_context->channels;
+ i_samples -= i_smaller_samples;
+ }
}
- return;
+ block_Release( p_block );
+ return VLC_SUCCESS;
}
-
/*****************************************************************************
- * EndThread: thread destruction
- *****************************************************************************
- * This function is called when the thread ends after a sucessful
- * initialization.
+ * EndAudioDec: audio decoder destruction
*****************************************************************************/
-void E_( EndThread_Audio )( adec_thread_t *p_adec )
+void E_(EndAudioDec)( decoder_t *p_dec )
{
-// FREE( p_adec->format.p_data );
- FREE( p_adec->p_output );
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ if( p_sys->p_output ) free( p_sys->p_output );
- if( p_adec->p_aout_input )
+ if( p_sys->p_aout_input )
{
- aout_DecDelete( p_adec->p_aout, p_adec->p_aout_input );
+ aout_DecDelete( p_sys->p_aout, p_sys->p_aout_input );
}
-
}
-
+++ /dev/null
-/*****************************************************************************
- * 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 * );
-
* 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>
*
#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 * );
/*****************************************************************************
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'):
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;
}
--- /dev/null
+/*****************************************************************************
+ * encoder.c: video and audio encoder using the ffmpeg library
+ *****************************************************************************
+ * Copyright (C) 1999-2001 VideoLAN
+ * $Id: encoder.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.
+ *****************************************************************************/
+
+/*****************************************************************************
+ * Preamble
+ *****************************************************************************/
+#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
+
+#include <vlc/vlc.h>
+#include <vlc/vout.h>
+#include <vlc/aout.h>
+#include <vlc/decoder.h>
+#include <vlc/input.h>
+#include <vlc/sout.h>
+
+#include "aout_internal.h"
+
+/* ffmpeg header */
+#ifdef HAVE_FFMPEG_AVCODEC_H
+# include <ffmpeg/avcodec.h>
+#else
+# include <avcodec.h>
+#endif
+
+#include "ffmpeg.h"
+
+#define AVCODEC_MAX_VIDEO_FRAME_SIZE (3*1024*1024)
+
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
+int E_(OpenVideoEncoder) ( vlc_object_t * );
+void E_(CloseVideoEncoder)( vlc_object_t * );
+
+int E_(OpenAudioEncoder) ( vlc_object_t * );
+void E_(CloseAudioEncoder)( vlc_object_t * );
+
+static block_t *EncodeVideo( encoder_t *, picture_t * );
+static block_t *EncodeAudio( encoder_t *, aout_buffer_t * );
+
+/*****************************************************************************
+ * encoder_sys_t : ffmpeg encoder descriptor
+ *****************************************************************************/
+struct encoder_sys_t
+{
+ /*
+ * Ffmpeg properties
+ */
+ AVCodec *p_codec;
+ AVCodecContext *p_context;
+
+ /*
+ * Packetizer output properties
+ */
+ sout_packetizer_input_t *p_sout_input;
+ sout_format_t sout_format;
+
+ /*
+ * Common properties
+ */
+ int i_last_block_size;
+ int i_samples_delay;
+ mtime_t i_pts;
+
+ mtime_t i_last_ref_pts;
+ mtime_t i_buggy_pts_detect;
+
+ int i_frame_size;
+
+ char *p_buffer;
+ char *p_buffer_out;
+};
+
+/*****************************************************************************
+ * OpenVideoEncoder: probe the encoder
+ *****************************************************************************/
+int E_(OpenVideoEncoder)( vlc_object_t *p_this )
+{
+ encoder_t *p_enc = (encoder_t *)p_this;
+ encoder_sys_t *p_sys = p_enc->p_sys;
+ AVCodecContext *p_context;
+ AVCodec *p_codec;
+ int i_ff_codec;
+
+ /* find encoder */
+ i_ff_codec = E_(GetFfmpegCodec)( p_enc->i_fourcc, 0, 0, 0 );
+ if( !i_ff_codec )
+ {
+ return VLC_EGENERIC;
+ }
+
+ p_codec = avcodec_find_encoder( i_ff_codec );
+ if( !p_codec )
+ {
+ return VLC_EGENERIC;
+ }
+
+ /* libavcodec needs to be initialized */
+ E_(InitLibavcodec)(p_this);
+
+ /* 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_sys->p_codec = p_codec;
+
+ p_enc->pf_header = NULL;
+ p_enc->pf_encode_video = EncodeVideo;
+ p_enc->format.video.i_chroma = VLC_FOURCC('I','4','2','0');
+
+ if( p_enc->i_fourcc == VLC_FOURCC( 'm','p','1','v' ) ||
+ p_enc->i_fourcc == VLC_FOURCC( 'm','p','2','v' ) )
+ {
+ p_enc->i_fourcc = VLC_FOURCC( 'm','p','g','v' );
+ }
+
+ p_sys->p_context = p_context = avcodec_alloc_context();
+ p_context->width = p_enc->format.video.i_width;
+ p_context->height = p_enc->format.video.i_height;
+ p_context->bit_rate = p_enc->i_bitrate;
+
+ p_context->frame_rate = p_enc->i_frame_rate;
+ p_context->frame_rate_base= p_enc->i_frame_rate_base;
+
+ p_context->gop_size = p_enc->i_key_int >= 0 ? p_enc->i_key_int : 50;
+ p_context->max_b_frames =
+ __MIN( p_enc->i_b_frames, FF_MAX_B_FRAMES );
+ p_context->b_frame_strategy = 0;
+ p_context->b_quant_factor = 2.0;
+
+ if( p_enc->i_vtolerance >= 0 )
+ {
+ p_context->bit_rate_tolerance = p_enc->i_vtolerance;
+ }
+ p_context->qmin = p_enc->i_qmin;
+ p_context->qmax = p_enc->i_qmax;
+
+#if LIBAVCODEC_BUILD >= 4673
+ p_context->mb_decision = p_enc->i_hq;
+#else
+ if( p_enc->i_hq )
+ {
+ p_context->flags |= CODEC_FLAG_HQ;
+ }
+#endif
+
+ if( i_ff_codec == CODEC_ID_RAWVIDEO )
+ {
+ p_context->pix_fmt = E_(GetFfmpegChroma)( p_enc->i_fourcc );
+ }
+
+ /* Make sure we get extradata filled by the encoder */
+ p_context->extradata_size = 0;
+ p_context->extradata = NULL;
+ p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+ if( avcodec_open( p_context, p_sys->p_codec ) )
+ {
+ msg_Err( p_enc, "cannot open encoder" );
+ return VLC_EGENERIC;
+ }
+
+ p_enc->i_extra_data = p_context->extradata_size;
+ p_enc->p_extra_data = p_context->extradata;
+ p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
+
+ p_sys->p_buffer_out = malloc( AVCODEC_MAX_VIDEO_FRAME_SIZE );
+ p_sys->i_last_ref_pts = 0;
+ p_sys->i_buggy_pts_detect = 0;
+
+ return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * EncodeVideo: the whole thing
+ ****************************************************************************/
+static block_t *EncodeVideo( encoder_t *p_enc, picture_t *p_pict )
+{
+ encoder_sys_t *p_sys = p_enc->p_sys;
+ AVFrame frame;
+ int i_out, i_plane;
+
+ for( i_plane = 0; i_plane < p_pict->i_planes; i_plane++ )
+ {
+ frame.data[i_plane] = p_pict->p[i_plane].p_pixels;
+ frame.linesize[i_plane] = p_pict->p[i_plane].i_pitch;
+ }
+
+ frame.pts = p_pict->date;
+
+ /* Let ffmpeg select the frame type */
+ frame.pict_type = 0;
+
+ i_out = avcodec_encode_video( p_sys->p_context, p_sys->p_buffer_out,
+ AVCODEC_MAX_VIDEO_FRAME_SIZE, &frame );
+ if( i_out > 0 )
+ {
+ block_t *p_block = block_New( p_enc, i_out );
+ memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
+
+ if( p_sys->p_context->coded_frame->pts != 0 &&
+ p_sys->i_buggy_pts_detect != p_sys->p_context->coded_frame->pts )
+ {
+ p_sys->i_buggy_pts_detect = p_sys->p_context->coded_frame->pts;
+
+ /* FIXME, 3-2 pulldown is not handled correctly */
+ p_block->i_length = 0;//in->i_length;
+ p_block->i_pts = p_sys->p_context->coded_frame->pts;
+
+ if( !p_sys->p_context->delay ||
+ ( p_sys->p_context->coded_frame->pict_type != FF_I_TYPE &&
+ p_sys->p_context->coded_frame->pict_type != FF_P_TYPE ) )
+ {
+ p_block->i_dts = p_block->i_pts;
+ }
+ else
+ {
+ if( p_sys->i_last_ref_pts )
+ {
+ p_block->i_dts = p_sys->i_last_ref_pts;
+ }
+ else
+ {
+ /* Let's put something sensible */
+ p_block->i_dts = p_block->i_pts;
+ }
+
+ p_sys->i_last_ref_pts = p_block->i_pts;
+ }
+ }
+ else
+ {
+ /* Buggy libavcodec which doesn't update coded_frame->pts
+ * correctly */
+ p_block->i_length = 0;//in->i_length;
+ p_block->i_dts = p_block->i_pts = p_pict->date;
+ }
+
+ return p_block;
+ }
+
+ return NULL;
+}
+
+/*****************************************************************************
+ * CloseVideoEncoder: ffmpeg video encoder destruction
+ *****************************************************************************/
+void E_(CloseVideoEncoder)( vlc_object_t *p_this )
+{
+ encoder_t *p_enc = (encoder_t *)p_this;
+ encoder_sys_t *p_sys = p_enc->p_sys;
+
+ avcodec_close( p_sys->p_context );
+ free( p_sys->p_context );
+ free( p_sys->p_buffer_out );
+ free( p_sys );
+}
+
+/*****************************************************************************
+ * OpenAudioEncoder: probe the encoder
+ *****************************************************************************/
+int E_(OpenAudioEncoder)( vlc_object_t *p_this )
+{
+ encoder_t *p_enc = (encoder_t *)p_this;
+ encoder_sys_t *p_sys = p_enc->p_sys;
+ AVCodecContext *p_context;
+ AVCodec *p_codec;
+ int i_ff_codec;
+
+ i_ff_codec = E_(GetFfmpegCodec)( p_enc->i_fourcc, 0, 0, 0 );
+ if( i_ff_codec == 0 )
+ {
+ msg_Err( p_enc, "cannot find encoder id" );
+ return VLC_EGENERIC;
+ }
+
+ p_codec = avcodec_find_encoder( i_ff_codec );
+ if( !p_codec )
+ {
+ msg_Err( p_enc, "cannot find encoder (avcodec)" );
+ return VLC_EGENERIC;
+ }
+
+ /* libavcodec needs to be initialized */
+ E_(InitLibavcodec)(p_this);
+
+ /* 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_sys->p_codec = p_codec;
+
+ p_enc->pf_header = NULL;
+ p_enc->pf_encode_audio = EncodeAudio;
+ p_enc->format.audio.i_format = VLC_FOURCC('s','1','6','n');
+
+ p_sys->p_context = p_context = avcodec_alloc_context();
+ p_context->bit_rate = p_enc->i_bitrate;
+ p_context->sample_rate = p_enc->format.audio.i_rate;
+ p_context->channels =
+ aout_FormatNbChannels( &p_enc->format.audio );
+
+ /* Make sure we get extradata filled by the encoder */
+ p_context->extradata_size = 0;
+ p_context->extradata = NULL;
+ p_context->flags |= CODEC_FLAG_GLOBAL_HEADER;
+
+ p_sys->i_samples_delay = 0;
+ p_sys->i_last_block_size = 0;
+ p_sys->i_pts = 0;
+
+ if( avcodec_open( p_context, p_sys->p_codec ) )
+ {
+#if 0
+ if( p_context->channels > 2 )
+ {
+ p_context->channels = 2;
+ id->f_dst.i_channels = 2;
+ if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
+ {
+ msg_Err( p_enc, "cannot open encoder" );
+ return VLC_EGENERIC;
+ }
+ msg_Warn( p_enc, "stereo mode selected (codec limitation)" );
+ }
+ else
+ {
+ msg_Err( p_enc, "cannot open encoder" );
+ return VLC_EGENERIC;
+ }
+#endif
+ }
+
+ p_enc->i_extra_data = p_context->extradata_size;
+ p_enc->p_extra_data = p_context->extradata;
+ p_context->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
+
+ p_sys->p_buffer = malloc( p_context->frame_size * 2 *
+ p_context->channels * 2 );
+
+ p_sys->p_buffer_out = malloc( 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE );
+
+ p_sys->i_frame_size = p_sys->p_context->frame_size * 2 *
+ p_context->channels;
+
+ /* Hack for mp3 transcoding support */
+ if( p_enc->i_fourcc == VLC_FOURCC( 'm','p','3',' ' ) )
+ {
+ p_enc->i_fourcc = VLC_FOURCC( 'm','p','g','a' );
+ }
+
+ return VLC_SUCCESS;
+}
+
+/****************************************************************************
+ * EncodeAudio: the whole thing
+ ****************************************************************************/
+static block_t *EncodeAudio( encoder_t *p_enc, aout_buffer_t *p_aout_buf )
+{
+ encoder_sys_t *p_sys = p_enc->p_sys;
+ block_t *p_block, *p_chain = NULL;
+ char *p_buffer = p_aout_buf->p_buffer;
+ int i_samples = p_aout_buf->i_nb_samples;
+ int i_samples_delay = p_sys->i_samples_delay;
+
+ 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;
+
+ p_sys->i_samples_delay += i_samples;
+
+ while( p_sys->i_samples_delay >= p_sys->p_context->frame_size )
+ {
+ int16_t *p_samples;
+ int i_out;
+
+ if( i_samples_delay )
+ {
+ /* Take care of the left-over from last time */
+ int i_delay_size = i_samples_delay * 2 *
+ p_sys->p_context->channels;
+ int i_size = p_sys->i_frame_size - i_delay_size;
+
+ p_samples = (int16_t *)p_sys->p_buffer;
+ memcpy( p_sys->p_buffer + i_delay_size, p_buffer, i_size );
+ p_buffer -= i_delay_size;
+ i_samples += i_samples_delay;
+ i_samples_delay = 0;
+ }
+ else
+ {
+ p_samples = (int16_t *)p_buffer;
+ }
+
+ i_out = avcodec_encode_audio( p_sys->p_context, p_sys->p_buffer_out,
+ 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE,
+ p_samples );
+ if( i_out <= 0 )
+ {
+ break;
+ }
+
+ p_buffer += p_sys->i_frame_size;
+ p_sys->i_samples_delay -= p_sys->p_context->frame_size;
+ i_samples = p_sys->p_context->frame_size;
+
+ p_block = block_New( p_enc, i_out );
+ memcpy( p_block->p_buffer, p_sys->p_buffer_out, i_out );
+
+ p_block->i_length = (mtime_t)1000000 *
+ (mtime_t)p_sys->p_context->frame_size /
+ (mtime_t)p_sys->p_context->sample_rate;
+
+ p_block->i_dts = p_block->i_pts = p_sys->i_pts;
+
+ /* Update pts */
+ p_sys->i_pts += p_block->i_length;
+ block_ChainAppend( &p_chain, p_block );
+ }
+
+ /* Backup the remaining raw samples */
+ if( p_sys->i_samples_delay > 0 )
+ {
+ memcpy( p_sys->p_buffer, p_buffer + i_samples_delay,
+ i_samples * 2 * p_sys->p_context->channels );
+ }
+
+ return p_chain;
+}
+
+/*****************************************************************************
+ * CloseAudioEncoder: ffmpeg audio encoder destruction
+ *****************************************************************************/
+void E_(CloseAudioEncoder)( vlc_object_t *p_this )
+{
+ encoder_t *p_enc = (encoder_t *)p_this;
+ encoder_sys_t *p_sys = p_enc->p_sys;
+
+ avcodec_close( p_sys->p_context );
+ free( p_sys->p_context );
+ free( p_sys->p_buffer );
+ free( p_sys->p_buffer_out );
+ free( p_sys );
+}
* ffmpeg.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: ffmpeg.c,v 1.54 2003/10/25 00:49:13 sam Exp $
+ * $Id: ffmpeg.c,v 1.55 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
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
-#include <string.h>
-
#ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
#endif
# error You must have a libavcodec >= 4655 (get CVS)
#endif
-
#include "ffmpeg.h"
#ifdef LIBAVCODEC_PP
# endif
#endif
-#include "video.h" // video ffmpeg specific
-#include "audio.h" // audio ffmpeg specific
-
-/*
- * Local prototypes
- */
-int E_(OpenChroma) ( vlc_object_t * );
-void E_(ffmpeg_InitLibavcodec) ( vlc_object_t *p_object );
-
-static int OpenDecoder ( vlc_object_t * );
-static int RunDecoder ( decoder_fifo_t * );
+/*****************************************************************************
+ * decoder_sys_t: decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+ /* Common part between video and audio decoder */
+ int i_cat;
+ int i_codec_id;
+ char *psz_namecodec;
-static int InitThread ( generic_thread_t * );
-static void EndThread ( generic_thread_t * );
+ AVCodecContext *p_context;
+ AVCodec *p_codec;
+};
-static int b_ffmpeginit = 0;
+/****************************************************************************
+ * Local prototypes
+ ****************************************************************************/
+static int OpenDecoder( vlc_object_t * );
+static int InitDecoder( decoder_t * );
+static int EndDecoder( decoder_t * );
-static int ffmpeg_GetFfmpegCodec( vlc_fourcc_t, int *, int *, char ** );
+static int b_ffmpeginit = 0;
/*****************************************************************************
* Module descriptor
*****************************************************************************/
-#define DR_TEXT N_("Direct rendering")
-
-#define ERROR_TEXT N_("Error resilience")
-#define ERROR_LONGTEXT N_( \
- "ffmpeg can make errors resiliences. \n" \
- "Nevertheless, with a buggy encoder (like ISO MPEG-4 encoder from M$) " \
- "this will produce a lot of errors.\n" \
- "Valid range is -1 to 99 (-1 disables all errors resiliences).")
-
-#define BUGS_TEXT N_("Workaround bugs")
-#define BUGS_LONGTEXT N_( \
- "Try to fix some bugs\n" \
- "1 autodetect\n" \
- "2 old msmpeg4\n" \
- "4 xvid interlaced\n" \
- "8 ump4 \n" \
- "16 no padding\n" \
- "32 ac vlc\n" \
- "64 Qpel chroma")
-
-#define HURRYUP_TEXT N_("Hurry up")
-#define HURRYUP_LONGTEXT N_( \
- "Allow the decoder to partially decode or skip frame(s) " \
- "when there is not enough time. It's useful with low CPU power " \
- "but it can produce distorted pictures.")
-
-#define TRUNC_TEXT N_("Truncated stream")
-#define TRUNC_LONGTEXT N_("truncated stream -1:auto,0:disable,:1:enable")
-
-#define PP_Q_TEXT N_("Post processing quality")
-#define PP_Q_LONGTEXT N_( \
- "Quality of post processing. Valid range is 0 to 6\n" \
- "Higher levels require considerable more CPU power, but produce " \
- "better looking pictures." )
-
-#define LIBAVCODEC_PP_TEXT N_("Ffmpeg postproc filter chains")
-/* FIXME (cut/past from ffmpeg */
-#define LIBAVCODEC_PP_LONGTEXT \
-"<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n" \
-"long form example:\n" \
-"vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n" \
-"short form example:\n" \
-"vb:a/hb:a/lb de,-vb\n" \
-"more examples:\n" \
-"tn:64:128:256\n" \
-"Filters Options\n" \
-"short long name short long option Description\n" \
-"* * a autoq cpu power dependant enabler\n" \
-" c chrom chrominance filtring enabled\n" \
-" y nochrom chrominance filtring disabled\n" \
-"hb hdeblock (2 Threshold) horizontal deblocking filter\n" \
-" 1. difference factor: default=64, higher -> more deblocking\n" \
-" 2. flatness threshold: default=40, lower -> more deblocking\n" \
-" the h & v deblocking filters share these\n" \
-" so u cant set different thresholds for h / v\n" \
-"vb vdeblock (2 Threshold) vertical deblocking filter\n" \
-"h1 x1hdeblock Experimental h deblock filter 1\n" \
-"v1 x1vdeblock Experimental v deblock filter 1\n" \
-"dr dering Deringing filter\n" \
-"al autolevels automatic brightness / contrast\n" \
-" f fullyrange stretch luminance to (0..255)\n" \
-"lb linblenddeint linear blend deinterlacer\n" \
-"li linipoldeint linear interpolating deinterlace\n" \
-"ci cubicipoldeint cubic interpolating deinterlacer\n" \
-"md mediandeint median deinterlacer\n" \
-"fd ffmpegdeint ffmpeg deinterlacer\n" \
-"de default hb:a,vb:a,dr:a,al\n" \
-"fa fast h1:a,v1:a,dr:a,al\n" \
-"tn tmpnoise (3 Thresholds) Temporal Noise Reducer\n" \
-" 1. <= 2. <= 3. larger -> stronger filtering\n" \
-"fq forceQuant <quantizer> Force quantizer\n"
-
vlc_module_begin();
+
+ /* decoder main module */
add_category_hint( N_("ffmpeg"), NULL, VLC_FALSE );
set_capability( "decoder", 70 );
set_callbacks( OpenDecoder, NULL );
set_description( _("ffmpeg audio/video decoder((MS)MPEG4,SVQ1,H263,WMV,WMA)") );
add_bool( "ffmpeg-dr", 1, NULL, DR_TEXT, DR_TEXT, VLC_TRUE );
- add_integer ( "ffmpeg-error-resilience", -1, NULL, ERROR_TEXT, ERROR_LONGTEXT, VLC_TRUE );
- add_integer ( "ffmpeg-workaround-bugs", 1, NULL, BUGS_TEXT, BUGS_LONGTEXT, VLC_FALSE );
- add_bool( "ffmpeg-hurry-up", 0, NULL, HURRYUP_TEXT, HURRYUP_LONGTEXT, VLC_FALSE );
- add_integer( "ffmpeg-truncated", -1, NULL, TRUNC_TEXT, TRUNC_LONGTEXT, VLC_FALSE );
+ add_integer ( "ffmpeg-error-resilience", -1, NULL, ERROR_TEXT,
+ ERROR_LONGTEXT, VLC_TRUE );
+ add_integer ( "ffmpeg-workaround-bugs", 1, NULL, BUGS_TEXT, BUGS_LONGTEXT,
+ VLC_FALSE );
+ add_bool( "ffmpeg-hurry-up", 0, NULL, HURRYUP_TEXT, HURRYUP_LONGTEXT,
+ VLC_FALSE );
+ add_integer( "ffmpeg-truncated", 0, NULL, TRUNC_TEXT, TRUNC_LONGTEXT,
+ VLC_FALSE );
- add_category_hint( N_("Post processing"), NULL, VLC_FALSE );
-
- add_integer( "ffmpeg-pp-q", 0, NULL, PP_Q_TEXT, PP_Q_LONGTEXT, VLC_FALSE );
#ifdef LIBAVCODEC_PP
- add_string( "ffmpeg-pp-name", "default", NULL, LIBAVCODEC_PP_TEXT, LIBAVCODEC_PP_LONGTEXT, VLC_TRUE );
+ add_integer( "ffmpeg-pp-q", 0, NULL, PP_Q_TEXT, PP_Q_LONGTEXT, VLC_FALSE );
+ add_string( "ffmpeg-pp-name", "default", NULL, LIBAVCODEC_PP_TEXT,
+ LIBAVCODEC_PP_LONGTEXT, VLC_TRUE );
#endif
/* chroma conversion submodule */
set_callbacks( E_(OpenChroma), NULL );
set_description( _("ffmpeg chroma conversion") );
+ /* video encoder submodule */
+ add_submodule();
+ set_description( _("ffmpeg video encoder") );
+ set_capability( "video encoder", 100 );
+ set_callbacks( E_(OpenVideoEncoder), E_(CloseVideoEncoder) );
+
+ /* audio encoder submodule */
+ add_submodule();
+ set_description( _("ffmpeg audio encoder") );
+ set_capability( "audio encoder", 10 );
+ set_callbacks( E_(OpenAudioEncoder), E_(CloseAudioEncoder) );
+
var_Create( p_module->p_libvlc, "avcodec", VLC_VAR_MUTEX );
vlc_module_end();
/*****************************************************************************
* OpenDecoder: probe the decoder and return score
- *****************************************************************************
- * Tries to launch a decoder and return score so that the interface is able
- * to chose.
*****************************************************************************/
static int OpenDecoder( vlc_object_t *p_this )
{
decoder_t *p_dec = (decoder_t*) p_this;
+ int i_cat;
- if( !ffmpeg_GetFfmpegCodec( p_dec->p_fifo->i_fourcc, NULL, NULL, NULL ) )
+ if( !E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc, &i_cat, NULL, NULL ) )
{
return VLC_EGENERIC;
}
- p_dec->pf_run = RunDecoder;
+ p_dec->pf_init = InitDecoder;
+ p_dec->pf_decode = (i_cat == VIDEO_ES) ? E_(DecodeVideo) : E_(DecodeAudio);
+ p_dec->pf_end = EndDecoder;
return VLC_SUCCESS;
}
-typedef union decoder_thread_u
-{
- generic_thread_t gen;
- adec_thread_t audio;
- vdec_thread_t video;
-
-} decoder_thread_t;
-
/*****************************************************************************
- * RunDecoder: this function is called just after the thread is created
+ * InitDecoder: Initalize the decoder
*****************************************************************************/
-static int RunDecoder( decoder_fifo_t *p_fifo )
-{
- generic_thread_t *p_decoder;
- int b_error;
-
- if ( !(p_decoder = malloc( sizeof( decoder_thread_t ) ) ) )
- {
- msg_Err( p_fifo, "out of memory" );
- DecoderError( p_fifo );
- return( -1 );
- }
- memset( p_decoder, 0, sizeof( decoder_thread_t ) );
-
- p_decoder->p_fifo = p_fifo;
-
- if( InitThread( p_decoder ) != 0 )
- {
- msg_Err( p_fifo, "initialization failed" );
- DecoderError( p_fifo );
- return( -1 );
- }
-
- while( (!p_decoder->p_fifo->b_die) && (!p_decoder->p_fifo->b_error) )
- {
- switch( p_decoder->i_cat )
- {
- case VIDEO_ES:
- E_( DecodeThread_Video )( (vdec_thread_t*)p_decoder );
- break;
- case AUDIO_ES:
- E_( DecodeThread_Audio )( (adec_thread_t*)p_decoder );
- break;
- }
- }
-
- if( ( b_error = p_decoder->p_fifo->b_error ) )
- {
- DecoderError( p_decoder->p_fifo );
- }
-
- EndThread( p_decoder );
-
- if( b_error )
- {
- return( -1 );
- }
-
- return( 0 );
-}
-
-/*****************************************************************************
- *
- * Functions that initialize, decode and end the decoding process
- *
- *****************************************************************************/
-
-/*****************************************************************************
- * InitThread: initialize vdec output thread
- *****************************************************************************
- * This function is called from decoder_Run and performs the second step
- * of the initialization. It returns 0 on success. Note that the thread's
- * flag are not modified inside this function.
- *
- * ffmpeg codec will be open, some memory allocated. But Vout is not yet
- * open (done after the first decoded frame)
- *****************************************************************************/
-
-static int InitThread( generic_thread_t *p_decoder )
+static int InitDecoder( decoder_t *p_dec )
{
- int i_result;
+ int i_cat, i_codec_id, i_result;
+ char *psz_namecodec;
+ AVCodecContext *p_context;
+ AVCodec *p_codec;
- E_(ffmpeg_InitLibavcodec)(VLC_OBJECT(p_decoder->p_fifo));
+ E_(InitLibavcodec)( VLC_OBJECT(p_dec->p_fifo) );
/* *** determine codec type *** */
- ffmpeg_GetFfmpegCodec( p_decoder->p_fifo->i_fourcc,
- &p_decoder->i_cat,
- &p_decoder->i_codec_id,
- &p_decoder->psz_namecodec );
+ E_(GetFfmpegCodec)( p_dec->p_fifo->i_fourcc,
+ &i_cat, &i_codec_id, &psz_namecodec );
/* *** ask ffmpeg for a decoder *** */
- if( !( p_decoder->p_codec =
- avcodec_find_decoder( p_decoder->i_codec_id ) ) )
+ if( !( p_codec = avcodec_find_decoder( i_codec_id ) ) )
{
- msg_Err( p_decoder->p_fifo,
- "codec not found (%s)",
- p_decoder->psz_namecodec );
- return( -1 );
+ msg_Err( p_dec, "codec not found (%s)", psz_namecodec );
+ return VLC_EGENERIC;
}
- /* *** Get a p_context *** */
- p_decoder->p_context = avcodec_alloc_context();
+ /* *** get a p_context *** */
+ p_context = avcodec_alloc_context();
- switch( p_decoder->i_cat )
+ switch( i_cat )
{
- case VIDEO_ES:
- i_result = E_( InitThread_Video )( (vdec_thread_t*)p_decoder );
- break;
- case AUDIO_ES:
- i_result = E_( InitThread_Audio )( (adec_thread_t*)p_decoder );
- break;
- default:
- i_result = -1;
+ case VIDEO_ES:
+ i_result = E_( InitVideoDec )( p_dec, p_context, p_codec,
+ i_codec_id, psz_namecodec );
+ p_dec->pf_decode = E_(DecodeVideo);
+ break;
+ case AUDIO_ES:
+ i_result = E_( InitAudioDec )( p_dec, p_context, p_codec,
+ i_codec_id, psz_namecodec );
+ p_dec->pf_decode = E_(DecodeAudio);
+ break;
+ default:
+ i_result = VLC_EGENERIC;
}
- p_decoder->pts = 0;
- p_decoder->p_buffer = NULL;
- p_decoder->i_buffer = 0;
- p_decoder->i_buffer_size = 0;
+ p_dec->p_sys->i_cat = i_cat;
- return( i_result );
+ return i_result;
}
-
+
/*****************************************************************************
- * EndThread: thread destruction
- *****************************************************************************
- * This function is called when the thread ends after a sucessful
- * initialization.
+ * EndDecoder: decoder destruction
*****************************************************************************/
-static void EndThread( generic_thread_t *p_decoder )
+static int EndDecoder( decoder_t *p_dec )
{
+ decoder_sys_t *p_sys = p_dec->p_sys;
- if( !p_decoder )
+ if( !p_sys->p_context )
{
- return;
- }
+ if( p_sys->p_context->extradata )
+ free( p_sys->p_context->extradata );
- if( p_decoder->p_context != NULL)
- {
- FREE( p_decoder->p_context->extradata );
- avcodec_close( p_decoder->p_context );
- msg_Dbg( p_decoder->p_fifo,
- "ffmpeg codec (%s) stopped",
- p_decoder->psz_namecodec );
- free( p_decoder->p_context );
+ avcodec_close( p_sys->p_context );
+ msg_Dbg( p_dec, "ffmpeg codec (%s) stopped", p_sys->psz_namecodec );
+ free( p_sys->p_context );
}
- FREE( p_decoder->p_buffer );
-
- switch( p_decoder->i_cat )
+ switch( p_sys->i_cat )
{
- case AUDIO_ES:
- E_( EndThread_Audio )( (adec_thread_t*)p_decoder );
- break;
- case VIDEO_ES:
- E_( EndThread_Video )( (vdec_thread_t*)p_decoder );
- break;
+ case AUDIO_ES:
+ E_( EndAudioDec )( p_dec );
+ break;
+ case VIDEO_ES:
+ E_( EndVideoDec )( p_dec );
+ break;
}
- free( p_decoder );
+ free( p_sys );
+ return VLC_SUCCESS;
}
-
+
/*****************************************************************************
- * locales Functions
+ * local Functions
*****************************************************************************/
-
-int E_( GetPESData )( uint8_t *p_buf, int i_max, pes_packet_t *p_pes )
-{
- int i_copy;
- int i_count;
-
- data_packet_t *p_data;
-
- i_count = 0;
- p_data = p_pes->p_first;
- while( p_data != NULL && i_count < i_max )
- {
-
- i_copy = __MIN( p_data->p_payload_end - p_data->p_payload_start,
- i_max - i_count );
-
- if( i_copy > 0 )
- {
- memcpy( p_buf,
- p_data->p_payload_start,
- i_copy );
- }
-
- p_data = p_data->p_next;
- i_count += i_copy;
- p_buf += i_copy;
- }
-
- if( i_count < i_max )
- {
- memset( p_buf, 0, i_max - i_count );
- }
- return( i_count );
-}
-
-
-static int ffmpeg_GetFfmpegCodec( vlc_fourcc_t i_fourcc,
- int *pi_cat,
- int *pi_ffmpeg_codec,
- char **ppsz_name )
+int E_(GetFfmpegCodec)( vlc_fourcc_t i_fourcc, int *pi_cat,
+ int *pi_ffmpeg_codec, char **ppsz_name )
{
int i_cat;
int i_codec;
switch( i_fourcc )
{
- case FOURCC_mpgv:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MPEG1VIDEO;
- psz_name = "MPEG-1/2 Video";
- break;
-
- case FOURCC_DIV1:
- case FOURCC_div1:
- case FOURCC_MPG4:
- case FOURCC_mpg4:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MSMPEG4V1;
- psz_name = "MS MPEG-4 v1";
- break;
-
- case FOURCC_DIV2:
- case FOURCC_div2:
- case FOURCC_MP42:
- case FOURCC_mp42:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MSMPEG4V2;
- psz_name = "MS MPEG-4 v2";
- break;
-
- case FOURCC_MPG3:
- case FOURCC_mpg3:
- case FOURCC_div3:
- case FOURCC_MP43:
- case FOURCC_mp43:
- case FOURCC_DIV3:
- case FOURCC_DIV4:
- case FOURCC_div4:
- case FOURCC_DIV5:
- case FOURCC_div5:
- case FOURCC_DIV6:
- case FOURCC_div6:
- case FOURCC_AP41:
- case FOURCC_3VID:
- case FOURCC_3vid:
- case FOURCC_3IVD:
- case FOURCC_3ivd:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MSMPEG4V3;
- psz_name = "MS MPEG-4 v3";
- break;
-
- case FOURCC_SVQ1:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_SVQ1;
- psz_name = "SVQ-1 (Sorenson Video v1)";
- break;
-#if LIBAVCODEC_BUILD >= 4666
- case FOURCC_SVQ3:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_SVQ3;
- psz_name = "SVQ-3 (Sorenson Video v3)";
- break;
-#endif
- case FOURCC_DIVX:
- case FOURCC_divx:
- case FOURCC_MP4S:
- case FOURCC_mp4s:
- case FOURCC_M4S2:
- case FOURCC_m4s2:
- case FOURCC_xvid:
- case FOURCC_XVID:
- case FOURCC_XviD:
- case FOURCC_DX50:
- case FOURCC_mp4v:
- case FOURCC_4:
- case FOURCC_m4cc:
- case FOURCC_M4CC:
- /* 3iv1 is unsupported by ffmpeg
- putting it here gives extreme distorted images
- case FOURCC_3IV1:
- case FOURCC_3iv1:
- */
- case FOURCC_3IV2:
- case FOURCC_3iv2:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MPEG4;
- psz_name = "MPEG-4";
- break;
+ /*
+ * Video Codecs
+ */
+
+ /* MPEG-1 Video */
+ case VLC_FOURCC('m','p','1','v'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MPEG1VIDEO;
+ psz_name = "MPEG-1/2 Video";
+ break;
+
+ /* MPEG-2 Video */
+ case VLC_FOURCC('m','p','2','v'):
+ case VLC_FOURCC('m','p','g','v'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MPEG2VIDEO;
+ psz_name = "MPEG-2 Video";
+ break;
+
+ /* MPEG-4 Video */
+ case VLC_FOURCC('D','I','V','X'):
+ case VLC_FOURCC('d','i','v','x'):
+ case VLC_FOURCC('M','P','4','S'):
+ case VLC_FOURCC('m','p','4','s'):
+ case VLC_FOURCC('M','4','S','2'):
+ case VLC_FOURCC('m','4','s','2'):
+ case VLC_FOURCC('x','v','i','d'):
+ case VLC_FOURCC('X','V','I','D'):
+ case VLC_FOURCC('X','v','i','D'):
+ case VLC_FOURCC('D','X','5','0'):
+ case VLC_FOURCC('m','p','4','v'):
+ case VLC_FOURCC( 4, 0, 0, 0 ):
+ case VLC_FOURCC('m','4','c','c'):
+ case VLC_FOURCC('M','4','C','C'):
+ /* 3ivx delta 3.5 Unsupported
+ * putting it here gives extreme distorted images
+ case VLC_FOURCC('3','I','V','1'):
+ case VLC_FOURCC('3','i','v','1'): */
+ /* 3ivx delta 4 */
+ case VLC_FOURCC('3','I','V','2'):
+ case VLC_FOURCC('3','i','v','2'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MPEG4;
+ psz_name = "MPEG-4";
+ break;
+
+ /* MSMPEG4 v1 */
+ case VLC_FOURCC('D','I','V','1'):
+ case VLC_FOURCC('d','i','v','1'):
+ case VLC_FOURCC('M','P','G','4'):
+ case VLC_FOURCC('m','p','g','4'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MSMPEG4V1;
+ psz_name = "MS MPEG-4 v1";
+ break;
+
+ /* MSMPEG4 v2 */
+ case VLC_FOURCC('D','I','V','2'):
+ case VLC_FOURCC('d','i','v','2'):
+ case VLC_FOURCC('M','P','4','2'):
+ case VLC_FOURCC('m','p','4','2'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MSMPEG4V2;
+ psz_name = "MS MPEG-4 v2";
+ break;
+
+ /* MSMPEG4 v3 / M$ mpeg4 v3 */
+ case VLC_FOURCC('M','P','G','3'):
+ case VLC_FOURCC('m','p','g','3'):
+ case VLC_FOURCC('d','i','v','3'):
+ case VLC_FOURCC('M','P','4','3'):
+ case VLC_FOURCC('m','p','4','3'):
+ /* DivX 3.20 */
+ case VLC_FOURCC('D','I','V','3'):
+ case VLC_FOURCC('D','I','V','4'):
+ case VLC_FOURCC('d','i','v','4'):
+ case VLC_FOURCC('D','I','V','5'):
+ case VLC_FOURCC('d','i','v','5'):
+ case VLC_FOURCC('D','I','V','6'):
+ case VLC_FOURCC('d','i','v','6'):
+ /* AngelPotion stuff */
+ case VLC_FOURCC('A','P','4','1'):
+ /* 3ivx doctered divx files */
+ case VLC_FOURCC('3','I','V','D'):
+ case VLC_FOURCC('3','i','v','d'):
+ /* who knows? */
+ case VLC_FOURCC('3','V','I','D'):
+ case VLC_FOURCC('3','v','i','d'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MSMPEG4V3;
+ psz_name = "MS MPEG-4 v3";
+ break;
+
+ /* Sorenson v1 */
+ case VLC_FOURCC('S','V','Q','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_SVQ1;
+ psz_name = "SVQ-1 (Sorenson Video v1)";
+ break;
+
+ /* Sorenson v3 */
+ case VLC_FOURCC('S','V','Q','3'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_SVQ3;
+ psz_name = "SVQ-3 (Sorenson Video v3)";
+ break;
+
+/* H263 and H263i */
+/* H263(+) is also known as Real Video 1.0 */
/* FIXME FOURCC_H263P exist but what fourcc ? */
- case FOURCC_H263:
- case FOURCC_h263:
- case FOURCC_U263:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_H263;
- psz_name = "H263";
- break;
-
- case FOURCC_I263:
- case FOURCC_i263:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_H263I;
- psz_name = "I263.I";
- break;
- case FOURCC_WMV1:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_WMV1;
- psz_name ="Windows Media Video 1";
- break;
- case FOURCC_WMV2:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_WMV2;
- psz_name ="Windows Media Video 2";
- break;
- case FOURCC_MJPG:
- case FOURCC_mjpg:
- case FOURCC_mjpa:
- case FOURCC_jpeg:
- case FOURCC_JPEG:
- case FOURCC_JFIF:
- case FOURCC_JPGL:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MJPEG;
- psz_name = "Motion JPEG";
- break;
- case FOURCC_mjpb:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MJPEGB;
- psz_name = "Motion JPEG B";
- break;
- case FOURCC_dvsl:
- case FOURCC_dvsd:
- case FOURCC_DVSD:
- case FOURCC_dvhd:
- case FOURCC_dvc:
- case FOURCC_dvp:
- case FOURCC_CDVC:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_DVVIDEO;
- psz_name = "DV video";
- break;
-
- case FOURCC_MAC3:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_MACE3;
- psz_name = "MACE-3 audio";
- break;
- case FOURCC_MAC6:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_MACE6;
- psz_name = "MACE-6 audio";
- break;
- case FOURCC_dvau:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_DVAUDIO;
- psz_name = "DV audio";
- break;
-
- case FOURCC_WMA1:
- case FOURCC_wma1:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_WMAV1;
- psz_name ="Windows Media Audio 1";
- break;
- case FOURCC_WMA2:
- case FOURCC_wma2:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_WMAV2;
- psz_name ="Windows Media Audio 2";
- break;
-
- case FOURCC_HFYU:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_HUFFYUV;
- psz_name ="Huff YUV";
- break;
-
- case FOURCC_CYUV:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_CYUV;
- psz_name ="Creative YUV";
- break;
+ /* H263 */
+ case VLC_FOURCC('H','2','6','3'):
+ case VLC_FOURCC('h','2','6','3'):
+ case VLC_FOURCC('U','2','6','3'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_H263;
+ psz_name = "H263";
+ break;
+
+ /* H263i */
+ case VLC_FOURCC('I','2','6','3'):
+ case VLC_FOURCC('i','2','6','3'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_H263I;
+ psz_name = "I263.I";
+ break;
+
+#if LIBAVCODEC_BUILD >= 4669
+ /* Flash (H263) variant */
+ case VLC_FOURCC('F','L','V','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_FLV1;
+ psz_name = "Flash Video";
+ break;
+#endif
+
+ /* MJPEG */
+ case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
+ case VLC_FOURCC( 'm', 'j', 'p', 'g' ):
+ case VLC_FOURCC( 'm', 'j', 'p', 'a' ): /* for mov file */
+ case VLC_FOURCC( 'j', 'p', 'e', 'g' ):
+ case VLC_FOURCC( 'J', 'P', 'E', 'G' ):
+ case VLC_FOURCC( 'J', 'F', 'I', 'F' ):
+ case VLC_FOURCC( 'J', 'P', 'G', 'L' ):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MJPEG;
+ psz_name = "Motion JPEG";
+ break;
+ case VLC_FOURCC( 'm', 'j', 'p', 'b' ): /* for mov file */
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MJPEGB;
+ psz_name = "Motion JPEG B";
+ break;
+
+ /* DV */
+ case VLC_FOURCC('d','v','s','l'):
+ case VLC_FOURCC('d','v','s','d'):
+ case VLC_FOURCC('D','V','S','D'):
+ case VLC_FOURCC('d','v','h','d'):
+ case VLC_FOURCC('d','v','c',' '):
+ case VLC_FOURCC('d','v','p',' '):
+ case VLC_FOURCC('C','D','V','C'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_DVVIDEO;
+ psz_name = "DV video";
+ break;
+
+ /* Windows Media Video */
+ case VLC_FOURCC('W','M','V','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_WMV1;
+ psz_name ="Windows Media Video 1";
+ break;
+ case VLC_FOURCC('W','M','V','2'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_WMV2;
+ psz_name ="Windows Media Video 2";
+ break;
+
+#if LIBAVCODEC_BUILD >= 4683
+ /* Microsoft Video 1 */
+ case VLC_FOURCC('M','S','V','C'):
+ case VLC_FOURCC('m','s','v','c'):
+ case VLC_FOURCC('C','R','A','M'):
+ case VLC_FOURCC('c','r','a','m'):
+ case VLC_FOURCC('W','H','A','M'):
+ case VLC_FOURCC('w','h','a','m'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MSVIDEO1;
+ psz_name = "Microsoft Video 1";
+ break;
+
+ /* Microsoft RLE */
+ case VLC_FOURCC('m','r','l','e'):
+ case VLC_FOURCC(0x1,0x0,0x0,0x0):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_MSRLE;
+ psz_name = "Microsoft RLE";
+ break;
+#endif
#if( ( LIBAVCODEC_BUILD >= 4663 ) && ( !defined( WORDS_BIGENDIAN ) ) )
- /* Quality of this decoder on ppc is not good */
- case FOURCC_IV31:
- case FOURCC_iv31:
- case FOURCC_IV32:
- case FOURCC_iv32:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_INDEO3;
- psz_name = "Indeo v3";
- break;
+ /* Indeo Video Codecs (Quality of this decoder on ppc is not good) */
+ case VLC_FOURCC('I','V','3','1'):
+ case VLC_FOURCC('i','v','3','1'):
+ case VLC_FOURCC('I','V','3','2'):
+ case VLC_FOURCC('i','v','3','2'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_INDEO3;
+ psz_name = "Indeo v3";
+ break;
#endif
+ /* Huff YUV */
+ case VLC_FOURCC('H','F','Y','U'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_HUFFYUV;
+ psz_name ="Huff YUV";
+ break;
+
+ /* Creative YUV */
+ case VLC_FOURCC('C','Y','U','V'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_CYUV;
+ psz_name ="Creative YUV";
+ break;
+
#if LIBAVCODEC_BUILD >= 4668
-/* Sorta works */
- case FOURCC_vp31:
- case FOURCC_VP31:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_VP3;
- psz_name = "On2's VP3 Video";
- break;
+ /* On2 VP3 Video Codecs */
+ case VLC_FOURCC('V','P','3','1'):
+ case VLC_FOURCC('v','p','3','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_VP3;
+ psz_name = "On2's VP3 Video";
+ break;
+#endif
#if ( !defined( WORDS_BIGENDIAN ) )
-/* Another thing that doesn't work */
- case FOURCC_ASV1:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_ASV1;
- psz_name = "Asus V1";
- break;
+#if LIBAVCODEC_BUILD >= 4668
+ /* Asus Video (Another thing that doesn't work on PPC) */
+ case VLC_FOURCC('A','S','V','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_ASV1;
+ psz_name = "Asus V1";
+ break;
+#endif
+#if LIBAVCODEC_BUILD >= 4677
+ case VLC_FOURCC('A','S','V','2'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_ASV2;
+ psz_name = "Asus V2";
+ break;
+#endif
#endif
- case FOURCC_FFV1:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_FFV1;
- psz_name = "FFMpeg Video 1";
- break;
-
- case FOURCC_RA10:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_RA_144;
- psz_name = "RealAudio 1.0";
- break;
-
- case FOURCC_RA20:
- i_cat = AUDIO_ES;
- i_codec = CODEC_ID_RA_288;
- psz_name = "RealAudio 2.0";
- break;
+#if LIBAVCODEC_BUILD >= 4668
+ /* FFMPEG Video 1 (lossless codec) */
+ case VLC_FOURCC('F','F','V','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_FFV1;
+ psz_name = "FFMpeg Video 1";
+ break;
#endif
#if LIBAVCODEC_BUILD >= 4669
- case FOURCC_FLV1:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_FLV1;
- psz_name = "Flash Video";
- break;
-
- case FOURCC_VCR1:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_VCR1;
- psz_name = "ATI VCR1";
- break;
-
+ /* ATI VCR1 */
+ case VLC_FOURCC('V','C','R','1'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_VCR1;
+ psz_name = "ATI VCR1";
+ break;
#endif
#if LIBAVCODEC_BUILD >= 4672
- case FOURCC_CLJR:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_CLJR;
- psz_name = "Creative Logic AccuPak";
- break;
+ /* Cirrus Logic AccuPak */
+ case VLC_FOURCC('C','L','J','R'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_CLJR;
+ psz_name = "Creative Logic AccuPak";
+ break;
#endif
-#if LIBAVCODEC_BUILD >= 4677
- case FOURCC_ASV2:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_ASV2;
- psz_name = "Asus V2";
- break;
+#if LIBAVCODEC_BUILD >= 4683
+ /* Apple Video */
+ case VLC_FOURCC('r','p','z','a'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_RPZA;
+ psz_name = "Apple Video";
+ break;
#endif
#if LIBAVCODEC_BUILD >= 4683
- case FOURCC_rpza:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_RPZA;
- psz_name = "Apple Video";
- break;
-
- case FOURCC_cvid:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_CINEPAK;
- psz_name = "Cinepak";
- break;
-
- case FOURCC_mrle:
- case FOURCC_1000:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MSRLE;
- psz_name = "Microsoft RLE";
- break;
-
- case FOURCC_cram:
- case FOURCC_CRAM:
- case FOURCC_msvc:
- case FOURCC_MSVC:
- case FOURCC_wham:
- case FOURCC_WHAM:
- i_cat = VIDEO_ES;
- i_codec = CODEC_ID_MSVIDEO1;
- psz_name = "Microsoft Video 1";
- break;
+ /* Cinepak */
+ case VLC_FOURCC('c','v','i','d'):
+ i_cat = VIDEO_ES;
+ i_codec = CODEC_ID_CINEPAK;
+ psz_name = "Cinepak";
+ break;
+#endif
+
+ /*
+ * Audio Codecs
+ */
+
+ /* Windows Media Audio 1 */
+ case VLC_FOURCC('W','M','A','1'):
+ case VLC_FOURCC('w','m','a','1'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_WMAV1;
+ psz_name ="Windows Media Audio 1";
+ break;
+
+ /* Windows Media Audio 2 */
+ case VLC_FOURCC('W','M','A','2'):
+ case VLC_FOURCC('w','m','a','2'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_WMAV2;
+ psz_name ="Windows Media Audio 2";
+ break;
+
+ /* DV Audio */
+ case VLC_FOURCC('d','v','a','u'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_DVAUDIO;
+ psz_name = "DV audio";
+ break;
+
+ /* MACE-3 Audio */
+ case VLC_FOURCC('M','A','C','3'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_MACE3;
+ psz_name = "MACE-3 audio";
+ break;
+
+ /* MACE-6 Audio */
+ case VLC_FOURCC('M','A','C','6'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_MACE6;
+ psz_name = "MACE-6 audio";
+ break;
+
+#if LIBAVCODEC_BUILD >= 4668
+ /* RealAudio 1.0 */
+ case VLC_FOURCC('1','4','_','4'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_RA_144;
+ psz_name = "RealAudio 1.0";
+ break;
+
+ /* RealAudio 2.0 */
+ case VLC_FOURCC('2','8','_','8'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_RA_288;
+ psz_name = "RealAudio 2.0";
+ break;
#endif
- default:
- i_cat = UNKNOWN_ES;
- i_codec = CODEC_ID_NONE;
- psz_name = NULL;
- break;
+
+ /* MPEG Audio layer 1/2/3 */
+ case VLC_FOURCC('m','p','g','a'):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_MP2;
+ psz_name = "MPEG Audio layer 1/2";
+ break;
+ case VLC_FOURCC('m','p','3',' '):
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_MP3;
+ psz_name = "MPEG Audio layer 1/2/3";
+ break;
+
+ /* A52 Audio (aka AC3) */
+ case VLC_FOURCC('a','5','2',' '):
+ case VLC_FOURCC('a','5','2','b'): /* VLC specific hack */
+ i_cat = AUDIO_ES;
+ i_codec = CODEC_ID_AC3;
+ psz_name = "A52 Audio (aka AC3)";
+ break;
+
+ default:
+ i_cat = UNKNOWN_ES;
+ i_codec = CODEC_ID_NONE;
+ psz_name = NULL;
+ break;
}
if( i_codec != CODEC_ID_NONE )
return( VLC_FALSE );
}
-void E_ (ffmpeg_InitLibavcodec) ( vlc_object_t *p_object )
+int E_(GetFfmpegChroma)( vlc_fourcc_t i_chroma )
+{
+ switch( i_chroma )
+ {
+ case VLC_FOURCC( 'I', '4', '2', '0' ):
+ return PIX_FMT_YUV420P;
+ case VLC_FOURCC( 'I', '4', '2', '2' ):
+ return PIX_FMT_YUV422P;
+ case VLC_FOURCC( 'I', '4', '4', '4' ):
+ return PIX_FMT_YUV444P;
+ case VLC_FOURCC( 'R', 'V', '1', '5' ):
+ return PIX_FMT_RGB555;
+ case VLC_FOURCC( 'R', 'V', '1', '6' ):
+ return PIX_FMT_RGB565;
+ case VLC_FOURCC( 'R', 'V', '2', '4' ):
+ return PIX_FMT_RGB24;
+ case VLC_FOURCC( 'R', 'V', '3', '2' ):
+ return PIX_FMT_RGBA32;
+ case VLC_FOURCC( 'G', 'R', 'E', 'Y' ):
+ return PIX_FMT_GRAY8;
+ case VLC_FOURCC( 'Y', 'U', 'Y', '2' ):
+ return PIX_FMT_YUV422;
+ default:
+ return 0;
+ }
+}
+
+void E_(InitLibavcodec)( vlc_object_t *p_object )
{
vlc_value_t lockval;
/*****************************************************************************
- * ffmpeg_vdec.h: video decoder using ffmpeg library
+ * ffmpeg.h: decoder using the ffmpeg library
*****************************************************************************
* Copyright (C) 2001 VideoLAN
- * $Id: ffmpeg.h,v 1.26 2003/10/25 00:49:13 sam Exp $
+ * $Id: ffmpeg.h,v 1.27 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
#include "codecs.h" /* BITMAPINFOHEADER */
-
-#define DECODER_THREAD_COMMON \
- decoder_fifo_t *p_fifo; \
- \
- int i_cat; /* AUDIO_ES, VIDEO_ES */ \
- int i_codec_id; \
- char *psz_namecodec; \
- \
- AVCodecContext *p_context; \
- AVCodec *p_codec; \
- mtime_t input_pts_previous; \
- mtime_t input_pts; \
- mtime_t pts; \
- \
- /* Private stuff for frame gathering */ \
- uint8_t *p_buffer; /* buffer for gather pes */ \
- int i_buffer_size; /* size of allocated p_buffer */ \
- int i_buffer; /* bytes already present in p_buffer */
-
-
-typedef struct generic_thread_s
-{
- DECODER_THREAD_COMMON
-
-} generic_thread_t;
-
#if LIBAVCODEC_BUILD >= 4663
# define LIBAVCODEC_PP
#else
# undef LIBAVCODEC_PP
#endif
-#define FREE( p ) if( p ) free( p ); p = NULL
+struct picture_t;
+struct AVFrame;
+struct AVCodecContext;
+struct AVCodec;
-int E_( GetPESData )( uint8_t *p_buf, int i_max, pes_packet_t *p_pes );
+void E_(InitLibavcodec)( vlc_object_t * );
+int E_(GetFfmpegCodec)( vlc_fourcc_t, int *, int *, char ** );
+int E_(GetFfmpegChroma)( vlc_fourcc_t );
-/*****************************************************************************
- * Video codec fourcc
- *****************************************************************************/
+/* Video decoder module */
+int E_( InitVideoDec )( decoder_t *, AVCodecContext *, AVCodec *,
+ int, char * );
+void E_( EndVideoDec ) ( decoder_t * );
+int E_( DecodeVideo ) ( decoder_t *, block_t * );
-/* MPEG 1/2 video */
-#define FOURCC_mpgv VLC_FOURCC('m','p','g','v')
-
-/* MPEG4 video */
-#define FOURCC_DIVX VLC_FOURCC('D','I','V','X')
-#define FOURCC_divx VLC_FOURCC('d','i','v','x')
-#define FOURCC_DIV1 VLC_FOURCC('D','I','V','1')
-#define FOURCC_div1 VLC_FOURCC('d','i','v','1')
-#define FOURCC_MP4S VLC_FOURCC('M','P','4','S')
-#define FOURCC_mp4s VLC_FOURCC('m','p','4','s')
-#define FOURCC_M4S2 VLC_FOURCC('M','4','S','2')
-#define FOURCC_m4s2 VLC_FOURCC('m','4','s','2')
-#define FOURCC_xvid VLC_FOURCC('x','v','i','d')
-#define FOURCC_XVID VLC_FOURCC('X','V','I','D')
-#define FOURCC_XviD VLC_FOURCC('X','v','i','D')
-#define FOURCC_DX50 VLC_FOURCC('D','X','5','0')
-#define FOURCC_mp4v VLC_FOURCC('m','p','4','v')
-#define FOURCC_4 VLC_FOURCC( 4, 0, 0, 0 )
-#define FOURCC_m4cc VLC_FOURCC('m','4','c','c')
-#define FOURCC_M4CC VLC_FOURCC('M','4','C','C')
-
-/* MSMPEG4 v2 */
-#define FOURCC_MPG4 VLC_FOURCC('M','P','G','4')
-#define FOURCC_mpg4 VLC_FOURCC('m','p','g','4')
-#define FOURCC_DIV2 VLC_FOURCC('D','I','V','2')
-#define FOURCC_div2 VLC_FOURCC('d','i','v','2')
-#define FOURCC_MP42 VLC_FOURCC('M','P','4','2')
-#define FOURCC_mp42 VLC_FOURCC('m','p','4','2')
-
-/* MSMPEG4 v3 / M$ mpeg4 v3 */
-#define FOURCC_MPG3 VLC_FOURCC('M','P','G','3')
-#define FOURCC_mpg3 VLC_FOURCC('m','p','g','3')
-#define FOURCC_div3 VLC_FOURCC('d','i','v','3')
-#define FOURCC_MP43 VLC_FOURCC('M','P','4','3')
-#define FOURCC_mp43 VLC_FOURCC('m','p','4','3')
-
-/* DivX 3.20 */
-#define FOURCC_DIV3 VLC_FOURCC('D','I','V','3')
-#define FOURCC_DIV4 VLC_FOURCC('D','I','V','4')
-#define FOURCC_div4 VLC_FOURCC('d','i','v','4')
-#define FOURCC_DIV5 VLC_FOURCC('D','I','V','5')
-#define FOURCC_div5 VLC_FOURCC('d','i','v','5')
-#define FOURCC_DIV6 VLC_FOURCC('D','I','V','6')
-#define FOURCC_div6 VLC_FOURCC('d','i','v','6')
-
-/* AngelPotion stuff */
-#define FOURCC_AP41 VLC_FOURCC('A','P','4','1')
-
-/* 3ivx doctered divx files */
-#define FOURCC_3IVD VLC_FOURCC('3','I','V','D')
-#define FOURCC_3ivd VLC_FOURCC('3','i','v','d')
-
-/* 3ivx delta 3.5 Unsupported */
-#define FOURCC_3IV1 VLC_FOURCC('3','I','V','1')
-#define FOURCC_3iv1 VLC_FOURCC('3','i','v','1')
-
-/* 3ivx delta 4 */
-#define FOURCC_3IV2 VLC_FOURCC('3','I','V','2')
-#define FOURCC_3iv2 VLC_FOURCC('3','i','v','2')
-
-/* who knows? */
-#define FOURCC_3VID VLC_FOURCC('3','V','I','D')
-#define FOURCC_3vid VLC_FOURCC('3','v','i','d')
-
-/* H263 and H263i */
-/* H263(+) is also known as Real Video 1.0 */
-#define FOURCC_H263 VLC_FOURCC('H','2','6','3')
-#define FOURCC_h263 VLC_FOURCC('h','2','6','3')
-#define FOURCC_U263 VLC_FOURCC('U','2','6','3')
-#define FOURCC_I263 VLC_FOURCC('I','2','6','3')
-#define FOURCC_i263 VLC_FOURCC('i','2','6','3')
-/* Flash (H263) variant */
-#define FOURCC_FLV1 VLC_FOURCC('F','L','V','1')
-
-
-/* Sorenson v1/3 */
-#define FOURCC_SVQ1 VLC_FOURCC('S','V','Q','1')
-#define FOURCC_SVQ3 VLC_FOURCC('S','V','Q','3')
-
-/* mjpeg */
-#define FOURCC_MJPG VLC_FOURCC( 'M', 'J', 'P', 'G' )
-#define FOURCC_mjpg VLC_FOURCC( 'm', 'j', 'p', 'g' )
- /* for mov file */
-#define FOURCC_mjpa VLC_FOURCC( 'm', 'j', 'p', 'a' )
- /* for mov file XXX: untested */
-#define FOURCC_mjpb VLC_FOURCC( 'm', 'j', 'p', 'b' )
-
-#define FOURCC_jpeg VLC_FOURCC( 'j', 'p', 'e', 'g' )
-#define FOURCC_JPEG VLC_FOURCC( 'J', 'P', 'E', 'G' )
-#define FOURCC_JFIF VLC_FOURCC( 'J', 'F', 'I', 'F' )
-#define FOURCC_JPGL VLC_FOURCC( 'J', 'P', 'G', 'L' )
-
-/* Microsoft Video 1 */
-#define FOURCC_MSVC VLC_FOURCC('M','S','V','C')
-#define FOURCC_msvc VLC_FOURCC('m','s','v','c')
-#define FOURCC_CRAM VLC_FOURCC('C','R','A','M')
-#define FOURCC_cram VLC_FOURCC('c','r','a','m')
-#define FOURCC_WHAM VLC_FOURCC('W','H','A','M')
-#define FOURCC_wham VLC_FOURCC('w','h','a','m')
-
-/* Windows Screen Video */
-#define FOURCC_MSS1 VLC_FOURCC('M','S','S','1')
-
-/* Microsoft RLE */
-#define FOURCC_mrle VLC_FOURCC('m','r','l','e')
-#define FOURCC_1000 VLC_FOURCC(0x1,0x0,0x0,0x0)
-
-/* Windows Media Video */
-#define FOURCC_WMV1 VLC_FOURCC('W','M','V','1')
-#define FOURCC_WMV2 VLC_FOURCC('W','M','V','2')
-
-/* DV */
-#define FOURCC_dvsl VLC_FOURCC('d','v','s','l')
-#define FOURCC_dvsd VLC_FOURCC('d','v','s','d')
-#define FOURCC_DVSD VLC_FOURCC('D','V','S','D')
-#define FOURCC_dvhd VLC_FOURCC('d','v','h','d')
-#define FOURCC_dvc VLC_FOURCC('d','v','c',' ')
-#define FOURCC_dvp VLC_FOURCC('d','v','p',' ')
-#define FOURCC_CDVC VLC_FOURCC('C','D','V','C')
-
-/* Indeo Video Codecs */
-#define FOURCC_IV31 VLC_FOURCC('I','V','3','1')
-#define FOURCC_iv31 VLC_FOURCC('i','v','3','1')
-#define FOURCC_IV32 VLC_FOURCC('I','V','3','2')
-#define FOURCC_iv32 VLC_FOURCC('i','v','3','2')
-
-/* On2 VP3 Video Codecs */
-#define FOURCC_VP31 VLC_FOURCC('V','P','3','1')
-#define FOURCC_vp31 VLC_FOURCC('v','p','3','1')
-
-/* Asus Video */
-#define FOURCC_ASV1 VLC_FOURCC('A','S','V','1')
-#define FOURCC_ASV2 VLC_FOURCC('A','S','V','2')
-
-/* ATI VCR1 */
-#define FOURCC_VCR1 VLC_FOURCC('V','C','R','1')
-
-/* FFMPEG Video 1 (lossless codec) */
-#define FOURCC_FFV1 VLC_FOURCC('F','F','V','1')
-
-/* Cirrus Logic AccuPak */
-#define FOURCC_CLJR VLC_FOURCC('C','L','J','R')
-
-/* Creative YUV */
-#define FOURCC_CYUV VLC_FOURCC('C','Y','U','V')
-
-/* Huff YUV */
-#define FOURCC_HFYU VLC_FOURCC('H','F','Y','U')
-
-/* Apple Video */
-#define FOURCC_rpza VLC_FOURCC('r','p','z','a')
-
-/* Cinepak */
-#define FOURCC_cvid VLC_FOURCC('c','v','i','d')
+/* Audio decoder module */
+int E_( InitAudioDec )( decoder_t *, AVCodecContext *, AVCodec *,
+ int, char * );
+void E_( EndAudioDec ) ( decoder_t * );
+int E_( DecodeAudio ) ( decoder_t *, block_t * );
+/* Chroma conversion module */
+int E_(OpenChroma)( vlc_object_t * );
-/*****************************************************************************
- * Audio codec fourcc
- *****************************************************************************/
-#define FOURCC_WMA1 VLC_FOURCC('W','M','A','1')
-#define FOURCC_wma1 VLC_FOURCC('w','m','a','1')
-#define FOURCC_WMA2 VLC_FOURCC('W','M','A','2')
-#define FOURCC_wma2 VLC_FOURCC('w','m','a','2')
-#define FOURCC_dvau VLC_FOURCC('d','v','a','u')
+/* Video encoder module */
+int E_(OpenVideoEncoder) ( vlc_object_t * );
+void E_(CloseVideoEncoder)( vlc_object_t * );
-#define FOURCC_MAC3 VLC_FOURCC('M','A','C','3')
-#define FOURCC_MAC6 VLC_FOURCC('M','A','C','6')
+/* Audio encoder module */
+int E_(OpenAudioEncoder) ( vlc_object_t * );
+void E_(CloseAudioEncoder)( vlc_object_t * );
-#define FOURCC_RA10 VLC_FOURCC('1','4','_','4')
-#define FOURCC_RA20 VLC_FOURCC('2','8','_','8')
+/* Postprocessing module */
+int E_(OpenPostproc)( decoder_t *, void ** );
+int E_(InitPostproc)( decoder_t *, void *, int, int, int );
+int E_(PostprocPict)( decoder_t *, void *, picture_t *, AVFrame * );
+void E_(ClosePostproc)( decoder_t *, void * );
+/*****************************************************************************
+ * Module descriptor help strings
+ *****************************************************************************/
+#define DR_TEXT N_("Direct rendering")
+
+#define ERROR_TEXT N_("Error resilience")
+#define ERROR_LONGTEXT N_( \
+ "ffmpeg can make errors resiliences. \n" \
+ "Nevertheless, with a buggy encoder (like ISO MPEG-4 encoder from M$) " \
+ "this will produce a lot of errors.\n" \
+ "Valid range is -1 to 99 (-1 disables all errors resiliences).")
+
+#define BUGS_TEXT N_("Workaround bugs")
+#define BUGS_LONGTEXT N_( \
+ "Try to fix some bugs\n" \
+ "1 autodetect\n" \
+ "2 old msmpeg4\n" \
+ "4 xvid interlaced\n" \
+ "8 ump4 \n" \
+ "16 no padding\n" \
+ "32 ac vlc\n" \
+ "64 Qpel chroma")
+
+#define HURRYUP_TEXT N_("Hurry up")
+#define HURRYUP_LONGTEXT N_( \
+ "Allow the decoder to partially decode or skip frame(s) " \
+ "when there is not enough time. It's useful with low CPU power " \
+ "but it can produce distorted pictures.")
+
+#define TRUNC_TEXT N_("Truncated stream")
+#define TRUNC_LONGTEXT N_("truncated stream -1:auto,0:disable,:1:enable")
+
+#define PP_Q_TEXT N_("Post processing quality")
+#define PP_Q_LONGTEXT N_( \
+ "Quality of post processing. Valid range is 0 to 6\n" \
+ "Higher levels require considerable more CPU power, but produce " \
+ "better looking pictures." )
+
+#define LIBAVCODEC_PP_TEXT N_("Ffmpeg postproc filter chains")
+/* FIXME (cut/past from ffmpeg */
+#define LIBAVCODEC_PP_LONGTEXT \
+"<filterName>[:<option>[:<option>...]][[,|/][-]<filterName>[:<option>...]]...\n" \
+"long form example:\n" \
+"vdeblock:autoq/hdeblock:autoq/linblenddeint default,-vdeblock\n" \
+"short form example:\n" \
+"vb:a/hb:a/lb de,-vb\n" \
+"more examples:\n" \
+"tn:64:128:256\n" \
+"Filters Options\n" \
+"short long name short long option Description\n" \
+"* * a autoq cpu power dependant enabler\n" \
+" c chrom chrominance filtring enabled\n" \
+" y nochrom chrominance filtring disabled\n" \
+"hb hdeblock (2 Threshold) horizontal deblocking filter\n" \
+" 1. difference factor: default=64, higher -> more deblocking\n" \
+" 2. flatness threshold: default=40, lower -> more deblocking\n" \
+" the h & v deblocking filters share these\n" \
+" so u cant set different thresholds for h / v\n" \
+"vb vdeblock (2 Threshold) vertical deblocking filter\n" \
+"h1 x1hdeblock Experimental h deblock filter 1\n" \
+"v1 x1vdeblock Experimental v deblock filter 1\n" \
+"dr dering Deringing filter\n" \
+"al autolevels automatic brightness / contrast\n" \
+" f fullyrange stretch luminance to (0..255)\n" \
+"lb linblenddeint linear blend deinterlacer\n" \
+"li linipoldeint linear interpolating deinterlace\n" \
+"ci cubicipoldeint cubic interpolating deinterlacer\n" \
+"md mediandeint median deinterlacer\n" \
+"fd ffmpegdeint ffmpeg deinterlacer\n" \
+"de default hb:a,vb:a,dr:a,al\n" \
+"fa fast h1:a,v1:a,dr:a,al\n" \
+"tn tmpnoise (3 Thresholds) Temporal Noise Reducer\n" \
+" 1. <= 2. <= 3. larger -> stronger filtering\n" \
+"fq forceQuant <quantizer> Force quantizer\n"
--- /dev/null
+/*****************************************************************************
+ * 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 */
/*****************************************************************************
- * video.c: video decoder using ffmpeg library
+ * video.c: video decoder using the ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: video.c,v 1.41 2003/10/21 18:33:53 gbazin Exp $
+ * $Id: video.c,v 1.42 2003/10/27 01:04:38 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin@netcourrier.com>
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
+#include <string.h>
#include <vlc/vlc.h>
#include <vlc/vout.h>
-#include <vlc/aout.h>
#include <vlc/decoder.h>
#include <vlc/input.h>
-#include <string.h>
-
#ifdef HAVE_SYS_TIMES_H
# include <sys/times.h>
#endif
#include "ffmpeg.h"
-#ifdef LIBAVCODEC_PP
-# ifdef HAVE_POSTPROC_POSTPROCESS_H
-# include <postproc/postprocess.h>
-# else
-# include <libpostproc/postprocess.h>
-# endif
-#else
-# include "postprocessing/postprocessing.h"
-#endif
+/*****************************************************************************
+ * decoder_sys_t : decoder descriptor
+ *****************************************************************************/
+struct decoder_sys_t
+{
+ /* Common part between video and audio decoder */
+ int i_cat;
+ int i_codec_id;
+ char *psz_namecodec;
+
+ AVCodecContext *p_context;
+ AVCodec *p_codec;
+
+ /* Video decoder specific part */
+ mtime_t input_pts;
+ mtime_t i_pts;
+
+ AVFrame *p_ff_pic;
+ BITMAPINFOHEADER *p_format;
-#include "video.h"
+ vout_thread_t *p_vout;
+ /* for frame skipping algo */
+ int b_hurry_up;
+ int i_frame_error;
+ int i_frame_skip;
+
+ /* how many decoded frames are late */
+ int i_late_frames;
+ mtime_t i_late_frames_start;
+
+ /* for direct rendering */
+ int b_direct_rendering;
+
+ vlc_bool_t b_has_b_frames;
+
+ int i_buffer;
+ char *p_buffer;
+
+ /* Postprocessing handle */
+ void *p_pp;
+};
/*****************************************************************************
* Local prototypes
*****************************************************************************/
-static void ffmpeg_CopyPicture( picture_t *, AVFrame *, vdec_thread_t * );
-
-static int ffmpeg_GetFrameBuf ( struct AVCodecContext *, AVFrame * );
-static void ffmpeg_ReleaseFrameBuf ( struct AVCodecContext *, AVFrame * );
+static void ffmpeg_CopyPicture ( decoder_t *, picture_t *, AVFrame * );
+static int ffmpeg_GetFrameBuf ( struct AVCodecContext *, AVFrame * );
+static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *, AVFrame * );
/*****************************************************************************
* Local Functions
/* FIXME FIXME some of them are wrong */
switch( i_ff_chroma )
{
- case PIX_FMT_YUV420P:
- case PIX_FMT_YUV422:
- return( VLC_FOURCC('I','4','2','0') );
- case PIX_FMT_RGB24:
- return( VLC_FOURCC('R','V','2','4') );
-
- case PIX_FMT_YUV422P:
- return( VLC_FOURCC('I','4','2','2') );
- case PIX_FMT_YUV444P:
- return( VLC_FOURCC('I','4','4','4') );
- case PIX_FMT_YUV410P:
- case PIX_FMT_YUV411P:
- case PIX_FMT_BGR24:
- default:
- return( 0 );
+ case PIX_FMT_YUV420P:
+ case PIX_FMT_YUV422:
+ return( VLC_FOURCC('I','4','2','0') );
+ case PIX_FMT_RGB24:
+ return( VLC_FOURCC('R','V','2','4') );
+ case PIX_FMT_YUV422P:
+ return( VLC_FOURCC('I','4','2','2') );
+ case PIX_FMT_YUV444P:
+ return( VLC_FOURCC('I','4','4','4') );
+ case PIX_FMT_YUV410P:
+ case PIX_FMT_YUV411P:
+ case PIX_FMT_BGR24:
+ default:
+ return 0;
}
}
/* Return a Vout */
-static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
+static vout_thread_t *ffmpeg_CreateVout( decoder_t *p_dec,
AVCodecContext *p_context )
{
vout_thread_t *p_vout;
/* Spawn a video output if there is none. First we look for our children,
* then we look for any other vout that might be available. */
- p_vout = vout_Request( p_vdec->p_fifo, p_vdec->p_vout,
+ p_vout = vout_Request( p_dec, p_dec->p_sys->p_vout,
i_width, i_height, i_chroma, i_aspect );
-#ifdef LIBAVCODEC_PP
- if( p_vdec->pp_mode && !p_vdec->pp_context )
- {
- int32_t i_cpu = p_vdec->p_fifo->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( p_context->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_vdec->pp_context = pp_get_context( i_width, i_height, i_flags );
- }
+#ifdef LIBAVCODEC_PP
+ if( p_dec->p_sys->p_pp )
+ E_(InitPostproc)( p_dec, p_dec->p_sys->p_pp, i_width, i_height,
+ p_context->pix_fmt );
#endif
return p_vout;
}
/*****************************************************************************
- *
- * Functions that initialize, decode and end the decoding process
- *
- * Functions exported for ffmpeg.c
- * * E_( InitThread_Video )
- * * E_( DecodeThread )
- * * E_( EndThread_Video )
- *****************************************************************************/
-
-/*****************************************************************************
- * InitThread: initialize vdec output thread
+ * InitVideo: initialize the video decoder
*****************************************************************************
- * This function is called from decoder_Run and performs the second step
- * of the initialization. It returns 0 on success. Note that the thread's
- * flag are not modified inside this function.
- *
- * ffmpeg codec will be open, some memory allocated. But Vout is not yet
- * open (done after the first decoded frame)
+ * the ffmpeg codec will be opened, some memory allocated. The vout is not yet
+ * opened (done after the first decoded frame).
*****************************************************************************/
-static inline void SetDWBE( void *data, uint32_t dw )
-{
- uint8_t *p = data;
-
- p[0] = (dw >> 24 )&0xff;
- p[1] = (dw >> 16 )&0xff;
- p[2] = (dw >> 8 )&0xff;
- p[3] = (dw )&0xff;
-}
-
-int E_( InitThread_Video )( vdec_thread_t *p_vdec )
+int E_(InitVideoDec)( decoder_t *p_dec, AVCodecContext *p_context,
+ AVCodec *p_codec, int i_codec_id, char *psz_namecodec )
{
+ decoder_sys_t *p_sys;
+ vlc_value_t val;
int i_tmp;
- int i_truncated;
- p_vdec->p_ff_pic = avcodec_alloc_frame();
+ /* Allocate the memory needed to store the decoder's structure */
+ if( ( p_dec->p_sys = p_sys =
+ (decoder_sys_t *)malloc(sizeof(decoder_sys_t)) ) == NULL )
+ {
+ msg_Err( p_dec, "out of memory" );
+ return VLC_EGENERIC;
+ }
+
+ p_dec->p_sys->p_context = p_context;
+ p_dec->p_sys->p_codec = p_codec;
+ p_dec->p_sys->i_codec_id = i_codec_id;
+ p_dec->p_sys->psz_namecodec = psz_namecodec;
+ p_sys->p_ff_pic = avcodec_alloc_frame();
- if( ( p_vdec->p_format =
- (BITMAPINFOHEADER *)p_vdec->p_fifo->p_bitmapinfoheader ) != NULL )
+ if( ( p_sys->p_format =
+ (BITMAPINFOHEADER *)p_dec->p_fifo->p_bitmapinfoheader ) != NULL )
{
/* ***** Fill p_context with init values ***** */
- p_vdec->p_context->width = p_vdec->p_format->biWidth;
- p_vdec->p_context->height = p_vdec->p_format->biHeight;
+ p_sys->p_context->width = p_sys->p_format->biWidth;
+ p_sys->p_context->height = p_sys->p_format->biHeight;
}
else
{
- msg_Warn( p_vdec->p_fifo, "display informations missing" );
- p_vdec->p_format = NULL;
+ msg_Warn( p_dec, "display informations missing" );
+ p_sys->p_format = NULL;
}
/* ***** Get configuration of ffmpeg plugin ***** */
- i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-workaround-bugs" );
- p_vdec->p_context->workaround_bugs = __MAX( __MIN( i_tmp, 99 ), 0 );
+ i_tmp = config_GetInt( p_dec, "ffmpeg-workaround-bugs" );
+ p_sys->p_context->workaround_bugs = __MAX( __MIN( i_tmp, 99 ), 0 );
- i_tmp = config_GetInt( p_vdec->p_fifo, "ffmpeg-error-resilience" );
- p_vdec->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
+ i_tmp = config_GetInt( p_dec, "ffmpeg-error-resilience" );
+ p_sys->p_context->error_resilience = __MAX( __MIN( i_tmp, 99 ), -1 );
- if( config_GetInt( p_vdec->p_fifo, "grayscale" ) )
- {
- p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
- }
-
- p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
+ var_Create( p_dec, "grayscale", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+ var_Get( p_dec, "grayscale", &val );
+ if( val.b_bool ) p_sys->p_context->flags |= CODEC_FLAG_GRAY;
- /* CODEC_FLAG_TRUNCATED */
-
- /* FIXME search real LIBAVCODEC_BUILD */
+ /* Decide if we set CODEC_FLAG_TRUNCATED */
#if LIBAVCODEC_BUILD >= 4662
- i_truncated = config_GetInt( p_vdec->p_fifo, "ffmpeg-truncated" );
- if( i_truncated == 1 )
-#if 0
- ||
- ( i_truncated == -1 && ( p_vdec->p_context->width == 0 || p_vdec->p_context->height == 0 ) ) )
-#endif
- {
- p_vdec->p_context->flags |= CODEC_FLAG_TRUNCATED;
- }
+ var_Create( p_dec, "ffmpeg-truncated", VLC_VAR_INTEGER|VLC_VAR_DOINHERIT );
+ var_Get( p_dec, "ffmpeg-truncated", &val );
+ if( val.i_int > 0 ) p_sys->p_context->flags |= CODEC_FLAG_TRUNCATED;
#endif
/* ***** Open the codec ***** */
- if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
+ if( avcodec_open( p_sys->p_context, p_sys->p_codec ) < 0 )
{
- msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
- p_vdec->psz_namecodec );
- return( VLC_EGENERIC );
+ msg_Err( p_dec, "cannot open codec (%s)", p_sys->psz_namecodec );
+ return VLC_EGENERIC;
}
else
{
- msg_Dbg( p_vdec->p_fifo, "ffmpeg codec (%s) started",
- p_vdec->psz_namecodec );
+ msg_Dbg( p_dec, "ffmpeg codec (%s) started", p_sys->psz_namecodec );
}
- p_vdec->b_direct_rendering = 0;
- if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr" ) &&
- p_vdec->p_codec->capabilities & CODEC_CAP_DR1 &&
- ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) &&
+ /* ***** ffmpeg frame skipping ***** */
+ var_Create( p_dec, "ffmpeg-hurry-up", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+ var_Get( p_dec, "ffmpeg-hurry-up", &val );
+ p_sys->b_hurry_up = val.b_bool;
+
+ /* ***** ffmpeg direct rendering ***** */
+ p_sys->b_direct_rendering = 0;
+ var_Create( p_dec, "ffmpeg-dr", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+ var_Get( p_dec, "ffmpeg-dr", &val );
+ if( val.b_bool && (p_sys->p_codec->capabilities & CODEC_CAP_DR1) &&
+ ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) &&
/* Apparently direct rendering doesn't work with YUV422P */
- p_vdec->p_context->pix_fmt != PIX_FMT_YUV422P &&
- !(p_vdec->p_context->width % 16) && !(p_vdec->p_context->height % 16) )
+ p_sys->p_context->pix_fmt != PIX_FMT_YUV422P &&
+ !(p_sys->p_context->width % 16) && !(p_sys->p_context->height % 16) )
{
/* Some codecs set pix_fmt only after the 1st frame has been decoded,
* so we need to do another check in ffmpeg_GetFrameBuf() */
- p_vdec->b_direct_rendering = 1;
+ p_sys->b_direct_rendering = 1;
}
- /* ***** Load post processing ***** */
#ifdef LIBAVCODEC_PP
- p_vdec->pp_context = NULL;
- p_vdec->pp_mode = NULL;
-
- if( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )
+ if( E_(OpenPostproc)( p_dec, &p_sys->p_pp ) == VLC_SUCCESS )
{
- int i_quality = config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" );
- char *psz_name = config_GetPsz( p_vdec->p_fifo, "ffmpeg-pp-name" );
-
- if( !psz_name )
- {
- psz_name = strdup( "default" );
- }
- else if( *psz_name == '\0' )
- {
- free( psz_name );
- psz_name = strdup( "default" );
- }
-
- p_vdec->pp_mode =
- pp_get_mode_by_name_and_quality( psz_name, i_quality );
-
- if( !p_vdec->pp_mode )
- {
- msg_Err( p_vdec->p_fifo, "failed geting mode for postproc" );
- }
- else
- {
- msg_Info( p_vdec->p_fifo, "postproc activated" );
- }
- free( psz_name );
-
/* for now we cannot do postproc and dr */
- p_vdec->b_direct_rendering = 0;
- }
- else
- {
- msg_Dbg( p_vdec->p_fifo, "no postproc" );
+ p_sys->b_direct_rendering = 0;
}
#endif
/* ffmpeg doesn't properly release old pictures when frames are skipped */
- if( p_vdec->b_hurry_up ) p_vdec->b_direct_rendering = 0;
+ if( p_sys->b_hurry_up ) p_sys->b_direct_rendering = 0;
+ if( p_sys->b_direct_rendering )
+ {
+ msg_Dbg( p_dec, "using direct rendering" );
+ p_sys->p_context->flags |= CODEC_FLAG_EMU_EDGE;
+ }
/* Always use our get_buffer wrapper so we can calculate the
* PTS correctly */
- p_vdec->p_context->get_buffer = ffmpeg_GetFrameBuf;
- p_vdec->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
- p_vdec->p_context->opaque = p_vdec;
-
- if( p_vdec->b_direct_rendering )
- {
- msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
- p_vdec->p_context->flags |= CODEC_FLAG_EMU_EDGE;
- }
+ p_sys->p_context->get_buffer = ffmpeg_GetFrameBuf;
+ p_sys->p_context->release_buffer = ffmpeg_ReleaseFrameBuf;
+ p_sys->p_context->opaque = p_dec;
/* ***** init this codec with special data ***** */
- if( p_vdec->p_format &&
- p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
+ if( p_sys->p_format && p_sys->p_format->biSize > sizeof(BITMAPINFOHEADER) )
{
int b_gotpicture;
- int i_size = p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
+ int i_size = p_sys->p_format->biSize - sizeof(BITMAPINFOHEADER);
- if( p_vdec->i_codec_id == CODEC_ID_MPEG4 )
+ if( p_sys->i_codec_id == CODEC_ID_MPEG4 )
{
uint8_t *p_vol = malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
- memcpy( p_vol, &p_vdec->p_format[1], i_size );
+ memcpy( p_vol, &p_sys->p_format[1], i_size );
memset( &p_vol[i_size], 0, FF_INPUT_BUFFER_PADDING_SIZE );
- avcodec_decode_video( p_vdec->p_context, p_vdec->p_ff_pic,
- &b_gotpicture,
- p_vol,
- i_size );
+ avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
+ &b_gotpicture, p_vol, i_size );
free( p_vol );
}
#if LIBAVCODEC_BUILD >= 4666
- else if( p_vdec->i_codec_id == CODEC_ID_SVQ3 )
+ else if( p_sys->i_codec_id == CODEC_ID_SVQ3 )
{
uint8_t *p;
- p_vdec->p_context->extradata_size = i_size + 12;
- p = p_vdec->p_context->extradata =
- malloc( p_vdec->p_context->extradata_size );
+ p_sys->p_context->extradata_size = i_size + 12;
+ p = p_sys->p_context->extradata =
+ malloc( p_sys->p_context->extradata_size );
memcpy( &p[0], "SVQ3", 4 );
memset( &p[4], 0, 8 );
- memcpy( &p[12], &p_vdec->p_format[1], i_size );
+ memcpy( &p[12], &p_sys->p_format[1], i_size );
}
#endif
else
{
- p_vdec->p_context->extradata_size = i_size;
- p_vdec->p_context->extradata =
+ p_sys->p_context->extradata_size = i_size;
+ p_sys->p_context->extradata =
malloc( i_size + FF_INPUT_BUFFER_PADDING_SIZE );
- memcpy( p_vdec->p_context->extradata,
- &p_vdec->p_format[1], i_size );
- memset( &((uint8_t*)p_vdec->p_context->extradata)[i_size],
+ memcpy( p_sys->p_context->extradata,
+ &p_sys->p_format[1], i_size );
+ memset( &((uint8_t*)p_sys->p_context->extradata)[i_size],
0, FF_INPUT_BUFFER_PADDING_SIZE );
}
}
- p_vdec->p_vout = NULL;
-
- p_vdec->input_pts_previous = 0;
- p_vdec->input_pts = 0;
- p_vdec->b_has_b_frames = VLC_FALSE;
+ /* ***** misc init ***** */
+ p_sys->p_vout = NULL;
+ p_sys->input_pts = 0;
+ p_sys->i_pts = 0;
+ p_sys->b_has_b_frames = VLC_FALSE;
+ p_sys->i_late_frames = 0;
+ p_sys->i_buffer = 1;
+ p_sys->p_buffer = malloc( p_sys->i_buffer );
+ p_sys->p_pp = NULL;
- return( VLC_SUCCESS );
+ return VLC_SUCCESS;
}
/*****************************************************************************
- * DecodeThread: Called to decode one frame
- *****************************************************************************
- * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
- * the image to the output.
+ * DecodeVideo: Called to decode one or more frames
*****************************************************************************/
-void E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
+int E_(DecodeVideo)( decoder_t *p_dec, block_t *p_block )
{
- pes_packet_t *p_pes;
- int i_frame_size;
- int i_used;
- int b_drawpicture;
- int b_gotpicture;
- picture_t *p_pic; /* vlc picture */
+ decoder_sys_t *p_sys = p_dec->p_sys;
+ int i_buffer, b_drawpicture;
+ char *p_buffer;
+
+ if( p_block->i_pts > 0 )
+ {
+ p_sys->input_pts = p_block->i_pts;
+ }
/* TODO implement it in a better way */
/* A good idea could be to decode all I pictures and see for the other */
- if( p_vdec->b_hurry_up && p_vdec->i_frame_late > 4 )
+ if( p_sys->b_hurry_up && p_sys->i_late_frames > 4 )
{
b_drawpicture = 0;
- if( p_vdec->i_frame_late < 8 )
+ if( p_sys->i_late_frames < 8 )
{
- p_vdec->p_context->hurry_up = 2;
+ p_sys->p_context->hurry_up = 2;
}
else
{
- /* too much late picture, won't decode
- but break picture until a new I, and for mpeg4 ...*/
- p_vdec->i_frame_late--; /* needed else it will never be decrease */
- input_ExtractPES( p_vdec->p_fifo, NULL );
- return;
+ /* picture too late, won't decode
+ * but break picture until a new I, and for mpeg4 ...*/
+
+ p_sys->i_late_frames--; /* needed else it will never be decrease */
+ block_Release( p_block );
+ return VLC_SUCCESS;
}
}
else
{
b_drawpicture = 1;
- p_vdec->p_context->hurry_up = 0;
+ p_sys->p_context->hurry_up = 0;
}
- if( p_vdec->i_frame_late > 0 &&
- mdate() - p_vdec->i_frame_late_start > (mtime_t)5000000 )
+ if( p_sys->i_late_frames > 0 &&
+ mdate() - p_sys->i_late_frames_start > I64C(5000000) )
{
- msg_Err( p_vdec->p_fifo, "more than 5 seconds of late video -> "
- "dropping (to slow computer ?)" );
- do
- {
- input_ExtractPES( p_vdec->p_fifo, &p_pes );
- if( !p_pes )
- {
- p_vdec->p_fifo->b_error = 1;
- return;
- }
-
- if( p_pes->i_pts > 0 )
- {
- p_vdec->input_pts_previous = p_vdec->input_pts;
- p_vdec->input_pts = p_pes->i_pts;
- }
- input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
+ msg_Err( p_dec, "more than 5 seconds of late video -> "
+ "dropping frame (computer too slow ?)" );
+ block_Release( p_block );
+ p_sys->i_pts = 0; /* To make sure we recover properly */
+ p_sys->i_late_frames--;
+ return VLC_SUCCESS;
+ }
- } while( p_vdec->input_pts <= 0 || p_vdec->input_pts < mdate() );
+ if( !p_sys->p_context->width || !p_sys->p_context->height )
+ {
+ p_sys->p_context->hurry_up = 5;
}
- if( !p_vdec->p_context->width || !p_vdec->p_context->height )
+ /*
+ * Do the actual decoding now
+ */
+
+ /* Don't forget that ffmpeg requires a little more bytes
+ * that the real frame size */
+ i_buffer = p_block->i_buffer;
+ if( i_buffer + FF_INPUT_BUFFER_PADDING_SIZE > p_sys->i_buffer )
{
- p_vdec->p_context->hurry_up = 5;
+ free( p_sys->p_buffer );
+ p_sys->p_buffer = malloc( i_buffer + FF_INPUT_BUFFER_PADDING_SIZE );
}
+ p_buffer = p_sys->p_buffer;
+ p_dec->p_vlc->pf_memcpy( p_buffer, p_block->p_buffer, p_block->i_buffer );
+ memset( p_buffer + i_buffer, 0, FF_INPUT_BUFFER_PADDING_SIZE );
- do
+ while( i_buffer )
{
- input_ExtractPES( p_vdec->p_fifo, &p_pes );
- if( !p_pes )
+ int i_used, b_gotpicture;
+ picture_t *p_pic;
+
+ i_used = avcodec_decode_video( p_sys->p_context, p_sys->p_ff_pic,
+ &b_gotpicture,
+ p_buffer, i_buffer );
+ if( i_used < 0 )
{
- p_vdec->p_fifo->b_error = 1;
- return;
+ msg_Warn( p_dec, "cannot decode one frame (%d bytes)", i_buffer );
+ p_sys->i_frame_error++;
+ block_Release( p_block );
+ return VLC_SUCCESS;
}
- if( p_pes->i_pts > 0 )
+ /* Consumed bytes */
+ i_buffer -= i_used;
+ p_buffer += i_used;
+
+ /* Nothing to display */
+ if( !b_gotpicture ) continue;
+
+ /* Update frame late count*/
+ if( p_sys->i_pts && p_sys->i_pts <= mdate() )
+ {
+ p_sys->i_late_frames++;
+ if( p_sys->i_late_frames == 1 )
+ p_sys->i_late_frames_start = mdate();
+ }
+ else
{
- p_vdec->input_pts_previous = p_vdec->input_pts;
- p_vdec->input_pts = p_pes->i_pts;
+ p_sys->i_late_frames = 0;
}
- i_frame_size = p_pes->i_pes_size;
+ if( !b_drawpicture || p_sys->p_ff_pic->linesize[0] == 0 )
+ {
+ /* Do not display the picture */
+ continue;
+ }
- if( i_frame_size > 0 )
+ if( !p_sys->b_direct_rendering )
{
- uint8_t *p_last;
- int i_need;
- /* XXX Don't forget that ffmpeg required a little more bytes
- * that the real frame size */
- i_need = i_frame_size + FF_INPUT_BUFFER_PADDING_SIZE + p_vdec->i_buffer;
- if( p_vdec->i_buffer_size < i_need)
+ p_sys->p_vout = ffmpeg_CreateVout( p_dec, p_sys->p_context );
+ if( !p_sys->p_vout )
+ {
+ msg_Err( p_dec, "cannot create vout" );
+ block_Release( p_block );
+ return VLC_EGENERIC;
+ }
+
+ /* Get a new picture */
+ while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
{
- p_last = p_vdec->p_buffer;
- p_vdec->p_buffer = malloc( i_need );
- p_vdec->i_buffer_size = i_need;
- if( p_vdec->i_buffer > 0 )
+ if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
{
- memcpy( p_vdec->p_buffer, p_last, p_vdec->i_buffer );
+ block_Release( p_block );
+ return VLC_EGENERIC;
}
- FREE( p_last );
+ msleep( VOUT_OUTMEM_SLEEP );
}
- i_frame_size =
- E_( GetPESData )( p_vdec->p_buffer + p_vdec->i_buffer,
- i_frame_size , p_pes );
- memset( p_vdec->p_buffer + p_vdec->i_buffer + i_frame_size,
- 0, FF_INPUT_BUFFER_PADDING_SIZE );
- }
-
- input_DeletePES( p_vdec->p_fifo->p_packets_mgt, p_pes );
-
- } while( i_frame_size <= 0 );
-
- i_frame_size += p_vdec->i_buffer;
-
-usenextdata:
- i_used = avcodec_decode_video( p_vdec->p_context,
- p_vdec->p_ff_pic,
- &b_gotpicture,
- p_vdec->p_buffer,
- i_frame_size );
-
- if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error ) return;
-
-#if 0
- msg_Dbg( p_vdec->p_fifo,
- "used:%d framesize:%d (%s picture)",
- i_used, i_frame_size, b_gotpicture ? "got":"no got" );
-#endif
- if( i_used < 0 )
- {
- msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
- i_frame_size );
- p_vdec->i_frame_error++;
- p_vdec->i_buffer = 0;
- return;
- }
- else if( i_used < i_frame_size )
- {
- memmove( p_vdec->p_buffer,
- p_vdec->p_buffer + i_used,
- p_vdec->i_buffer_size - i_used );
- p_vdec->i_buffer = i_frame_size - i_used;
- }
- else
- {
- p_vdec->i_buffer = 0;
- }
-
- /* consumed bytes */
- i_frame_size -= i_used;
-
- /* Update frame late count*/
- if( p_vdec->pts <= mdate() )
- {
- p_vdec->i_frame_late++;
- if( p_vdec->i_frame_late == 1 )
+ /* Fill p_picture_t from AVVideoFrame and do chroma conversion
+ * if needed */
+ ffmpeg_CopyPicture( p_dec, p_pic, p_sys->p_ff_pic );
+ }
+ else
{
- p_vdec->i_frame_late_start = mdate();
+ p_pic = (picture_t *)p_sys->p_ff_pic->opaque;
}
- }
- else
- {
- p_vdec->i_frame_late = 0;
- }
-
- if( !b_gotpicture || p_vdec->p_ff_pic->linesize[0] == 0 || !b_drawpicture )
- {
- return;
- }
- if( !p_vdec->b_direct_rendering )
- {
- p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
- if( !p_vdec->p_vout )
+ /* Set the PTS
+ * There is an ugly hack here because some demuxers pass us a dts
+ * instead of a pts so this screw up things for streams with
+ * B frames. */
+ if( p_sys->p_ff_pic->pict_type == FF_B_TYPE )
+ p_sys->b_has_b_frames = VLC_TRUE;
+ if( p_sys->p_ff_pic->pts &&
+ ( !p_sys->p_context->has_b_frames || !p_sys->b_has_b_frames ||
+ p_sys->p_ff_pic->pict_type == FF_B_TYPE ) )
{
- msg_Err( p_vdec->p_fifo, "cannot create vout" );
- p_vdec->p_fifo->b_error = 1; /* abort */
- return;
+ p_sys->i_pts = p_sys->p_ff_pic->pts;
}
- /* Get a new picture */
- while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
+ /* Send decoded frame to vout */
+ if( p_sys->i_pts )
{
- if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
+ vout_DatePicture( p_sys->p_vout, p_pic, p_sys->i_pts );
+ vout_DisplayPicture( p_sys->p_vout, p_pic );
+
+ /* interpolate the next PTS */
+ if( p_sys->p_context->frame_rate > 0 )
{
- return;
+ p_sys->i_pts += I64C(1000000) *
+ (2 + p_sys->p_ff_pic->repeat_pict) *
+ p_sys->p_context->frame_rate_base /
+ (2 * p_sys->p_context->frame_rate);
}
- msleep( VOUT_OUTMEM_SLEEP );
}
-
- /* fill p_picture_t from AVVideoFrame and do chroma conversion
- * if needed */
- ffmpeg_CopyPicture( p_pic, p_vdec->p_ff_pic, p_vdec );
- }
- else
- {
- p_pic = (picture_t *)p_vdec->p_ff_pic->opaque;
}
- /* Set the PTS
- * There is an ugly hack here because some demuxers pass us a dts instead
- * of a pts so this screw up things for streams with B frames. */
- if( p_vdec->p_ff_pic->pict_type == FF_B_TYPE )
- p_vdec->b_has_b_frames = VLC_TRUE;
- if( p_vdec->p_ff_pic->pts &&
- ( !p_vdec->p_context->has_b_frames || !p_vdec->b_has_b_frames ||
- p_vdec->p_ff_pic->pict_type == FF_B_TYPE ) )
- {
- p_vdec->pts = p_vdec->p_ff_pic->pts;
- }
-
- if( p_vdec->pts <= 0 )
- {
- p_vdec->pts = mdate() + DEFAULT_PTS_DELAY; // FIXME
- }
-
- /* Send decoded frame to vout */
- vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->pts );
- vout_DisplayPicture( p_vdec->p_vout, p_pic );
-
- /* interpolate the next PTS */
- if( p_vdec->p_context->frame_rate > 0 )
- {
- p_vdec->pts += I64C(1000000) * (2 + p_vdec->p_ff_pic->repeat_pict) *
- p_vdec->p_context->frame_rate_base /
- (2 * p_vdec->p_context->frame_rate);
- }
-
- if( i_frame_size > 0 )
- {
- goto usenextdata; /* try to use all data */
- }
+ block_Release( p_block );
+ return VLC_SUCCESS;
}
/*****************************************************************************
- * EndThread: thread destruction
+ * EndVideo: decoder destruction
*****************************************************************************
* This function is called when the thread ends after a sucessful
* initialization.
*****************************************************************************/
-void E_( EndThread_Video )( vdec_thread_t *p_vdec )
+void E_(EndVideoDec)( decoder_t *p_dec )
{
+ decoder_sys_t *p_sys = p_dec->p_sys;
+
+ if( p_sys->p_ff_pic ) free( p_sys->p_ff_pic );
#ifdef LIBAVCODEC_PP
- if( p_vdec->pp_mode )
- {
- pp_free_mode( p_vdec->pp_mode );
- if( p_vdec->pp_context )
- {
- pp_free_context( p_vdec->pp_context );
- }
- }
+ E_(ClosePostproc)( p_dec, p_sys->p_pp );
#endif
- if( p_vdec->p_ff_pic )
- {
- free( p_vdec->p_ff_pic );
- }
+ free( p_sys->p_buffer );
/* We are about to die. Reattach video output to p_vlc. */
- vout_Request( p_vdec->p_fifo, p_vdec->p_vout, 0, 0, 0, 0 );
+ vout_Request( p_dec, p_sys->p_vout, 0, 0, 0, 0 );
}
/*****************************************************************************
* ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
* picture_t structure (when not in direct rendering mode).
*****************************************************************************/
-static void ffmpeg_CopyPicture( picture_t *p_pic,
- AVFrame *p_ff_pic,
- vdec_thread_t *p_vdec )
+static void ffmpeg_CopyPicture( decoder_t *p_dec,
+ picture_t *p_pic, AVFrame *p_ff_pic )
{
- int i_plane;
- int i_size;
- int i_line;
-
- uint8_t *p_dst;
- uint8_t *p_src;
- int i_src_stride;
- int i_dst_stride;
+ decoder_sys_t *p_sys = p_dec->p_sys;
- if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
+ if( ffmpeg_PixFmtToChroma( p_sys->p_context->pix_fmt ) )
{
#ifdef LIBAVCODEC_PP
- if( p_vdec->pp_mode && p_vdec->pp_context )
- {
- uint8_t *src[3], *dst[3];
- int 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;
+ if( p_sys->p_pp )
+ E_(PostprocPict)( p_dec, p_sys->p_pp, p_pic, p_ff_pic );
+#else
+ int i_plane, i_size, i_line;
+ uint8_t *p_dst, *p_src;
+ int i_src_stride, i_dst_stride;
- 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_vdec->p_context->width,
- p_vdec->p_context->height,
- p_ff_pic->qscale_table, p_ff_pic->qstride,
- p_vdec->pp_mode, p_vdec->pp_context,
- p_ff_pic->pict_type );
- }
- else
+ for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
{
-#endif
- for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
- {
- p_src = p_ff_pic->data[i_plane];
- p_dst = p_pic->p[i_plane].p_pixels;
- i_src_stride = p_ff_pic->linesize[i_plane];
- i_dst_stride = p_pic->p[i_plane].i_pitch;
+ p_src = p_ff_pic->data[i_plane];
+ p_dst = p_pic->p[i_plane].p_pixels;
+ i_src_stride = p_ff_pic->linesize[i_plane];
+ i_dst_stride = p_pic->p[i_plane].i_pitch;
- i_size = __MIN( i_src_stride, i_dst_stride );
- for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
- {
- p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
- p_src += i_src_stride;
- p_dst += i_dst_stride;
- }
+ i_size = __MIN( i_src_stride, i_dst_stride );
+ for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
+ {
+ p_dec->p_vlc->pf_memcpy( p_dst, p_src, i_size );
+ p_src += i_src_stride;
+ p_dst += i_dst_stride;
}
-#ifdef LIBAVCODEC_PP
}
#endif
}
else
{
+ AVPicture dest_pic;
+ int i;
+
/* we need to convert to I420 */
- switch( p_vdec->p_context->pix_fmt )
+ switch( p_sys->p_context->pix_fmt )
{
- AVPicture dest_pic;
- int i;
-
- case( PIX_FMT_YUV410P ):
- case( PIX_FMT_YUV411P ):
- for( i = 0; i < p_pic->i_planes; i++ )
- {
- dest_pic.data[i] = p_pic->p[i].p_pixels;
- dest_pic.linesize[i] = p_pic->p[i].i_pitch;
- }
- img_convert( &dest_pic, PIX_FMT_YUV420P,
- (AVPicture *)p_ff_pic,
- p_vdec->p_context->pix_fmt,
- p_vdec->p_context->width,
- p_vdec->p_context->height );
- break;
- default:
- msg_Err( p_vdec->p_fifo, "don't know how to convert chroma %i",
- p_vdec->p_context->pix_fmt );
- p_vdec->p_fifo->b_error = 1;
- break;
+ case( PIX_FMT_YUV410P ):
+ case( PIX_FMT_YUV411P ):
+ for( i = 0; i < p_pic->i_planes; i++ )
+ {
+ dest_pic.data[i] = p_pic->p[i].p_pixels;
+ dest_pic.linesize[i] = p_pic->p[i].i_pitch;
+ }
+ img_convert( &dest_pic, PIX_FMT_YUV420P,
+ (AVPicture *)p_ff_pic,
+ p_sys->p_context->pix_fmt,
+ p_sys->p_context->width,
+ p_sys->p_context->height );
+ break;
+ default:
+ msg_Err( p_dec, "don't know how to convert chroma %i",
+ p_sys->p_context->pix_fmt );
+ p_dec->p_fifo->b_error = 1;
+ break;
}
}
}
static int ffmpeg_GetFrameBuf( struct AVCodecContext *p_context,
AVFrame *p_ff_pic )
{
- vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
+ decoder_t *p_dec = (decoder_t *)p_context->opaque;
+ decoder_sys_t *p_sys = p_dec->p_sys;
picture_t *p_pic;
/* Set picture PTS */
- if( p_context->flags & CODEC_FLAG_TRUNCATED )
- {
- p_ff_pic->pts = p_vdec->input_pts_previous;
- p_vdec->input_pts_previous = 0;
- }
- else
- {
- p_ff_pic->pts = p_vdec->input_pts;
- p_vdec->input_pts = 0;
- }
+ p_ff_pic->pts = p_sys->input_pts;
+ p_sys->input_pts = 0;
/* Not much to do in indirect rendering mode */
- if( !p_vdec->b_direct_rendering )
+ if( !p_sys->b_direct_rendering )
{
return avcodec_default_get_buffer( p_context, p_ff_pic );
}
/* Some codecs set pix_fmt only after the 1st frame has been decoded,
* so this check is necessary. */
if( !ffmpeg_PixFmtToChroma( p_context->pix_fmt ) ||
- p_vdec->p_context->width % 16 || p_vdec->p_context->height % 16 )
+ p_sys->p_context->width % 16 || p_sys->p_context->height % 16 )
{
- msg_Dbg( p_vdec->p_fifo, "disabling direct rendering" );
- p_vdec->b_direct_rendering = 0;
+ msg_Dbg( p_dec, "disabling direct rendering" );
+ p_sys->b_direct_rendering = 0;
return avcodec_default_get_buffer( p_context, p_ff_pic );
}
/* Check and (re)create our vout if needed */
- p_vdec->p_vout = ffmpeg_CreateVout( p_vdec, p_vdec->p_context );
- if( !p_vdec->p_vout )
+ p_sys->p_vout = ffmpeg_CreateVout( p_dec, p_sys->p_context );
+ if( !p_sys->p_vout )
{
- msg_Err( p_vdec->p_fifo, "cannot create vout" );
- p_vdec->p_fifo->b_error = 1; /* abort */
- p_vdec->b_direct_rendering = 0;
+ msg_Err( p_dec, "cannot create vout" );
+ p_dec->p_fifo->b_error = 1; /* abort */
+ p_sys->b_direct_rendering = 0;
return avcodec_default_get_buffer( p_context, p_ff_pic );
}
- p_vdec->p_vout->render.b_allow_modify_pics = 0;
+ p_sys->p_vout->render.b_allow_modify_pics = 0;
/* Get a new picture */
- while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
+ while( !(p_pic = vout_CreatePicture( p_sys->p_vout, 0, 0, 0 ) ) )
{
- if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
+ if( p_dec->p_fifo->b_die || p_dec->p_fifo->b_error )
{
- p_vdec->b_direct_rendering = 0;
+ p_sys->b_direct_rendering = 0;
return avcodec_default_get_buffer( p_context, p_ff_pic );
}
msleep( VOUT_OUTMEM_SLEEP );
}
- p_vdec->p_context->draw_horiz_band = NULL;
+ p_sys->p_context->draw_horiz_band = NULL;
p_ff_pic->opaque = (void*)p_pic;
p_ff_pic->type = FF_BUFFER_TYPE_USER;
if( p_ff_pic->reference != 0 )
{
- vout_LinkPicture( p_vdec->p_vout, p_pic );
+ vout_LinkPicture( p_sys->p_vout, p_pic );
}
+
/* FIXME what is that, should give good value */
p_ff_pic->age = 256*256*256*64; // FIXME FIXME from ffmpeg
static void ffmpeg_ReleaseFrameBuf( struct AVCodecContext *p_context,
AVFrame *p_ff_pic )
{
- vdec_thread_t *p_vdec = (vdec_thread_t *)p_context->opaque;
+ decoder_t *p_dec = (decoder_t *)p_context->opaque;
+ decoder_sys_t *p_sys = p_dec->p_sys;
picture_t *p_pic;
if( p_ff_pic->type != FF_BUFFER_TYPE_USER )
if( p_ff_pic->reference != 0 )
{
- vout_UnlinkPicture( p_vdec->p_vout, p_pic );
+ vout_UnlinkPicture( p_sys->p_vout, p_pic );
}
}
+++ /dev/null
-/*****************************************************************************
- * 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 * );
* 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>
*
#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
/*****************************************************************************
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 );
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();
/*****************************************************************************
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 */
* transcode.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: transcode.c,v 1.43 2003/10/24 21:27:06 gbazin Exp $
+ * $Id: transcode.c,v 1.44 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
# include <avcodec.h>
#endif
-/* vorbis header */
-#ifdef HAVE_VORBIS_VORBISENC_H
-# include <vorbis/vorbisenc.h>
-# ifndef OV_ECTL_RATEMANAGE_AVG
-# define OV_ECTL_RATEMANAGE_AVG 0x0
-# endif
-#endif
-
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
static int transcode_video_ffmpeg_getframebuf( struct AVCodecContext *, AVFrame *);
+static int pi_channels_maps[6] =
+{
+ 0,
+ AOUT_CHAN_CENTER, AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
+ AOUT_CHAN_CENTER | AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT,
+ AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_REARLEFT
+ | AOUT_CHAN_REARRIGHT,
+ AOUT_CHAN_LEFT | AOUT_CHAN_RIGHT | AOUT_CHAN_CENTER
+ | AOUT_CHAN_REARLEFT | AOUT_CHAN_REARRIGHT
+};
+
/*****************************************************************************
* Module descriptor
*****************************************************************************/
mtime_t i_input_pts;
mtime_t i_output_pts;
- mtime_t i_last_ref_pts;
-
- mtime_t i_buggy_pts_detect;
};
/*****************************************************************************
/*****************************************************************************
* Close:
*****************************************************************************/
-
static void Close( vlc_object_t * p_this )
{
sout_stream_t *p_stream = (sout_stream_t*)p_this;
void *id;
/* Encoder */
- encoder_t *p_encoder;
+ encoder_t *p_encoder;
+ vlc_fourcc_t b_enc_inited;
/* ffmpeg part */
AVCodec *ff_dec;
AVCodecContext *ff_dec_c;
-
- vlc_fourcc_t b_enc_inited;
- AVCodec *ff_enc;
- AVCodecContext *ff_enc_c;
-
mtime_t i_dts;
mtime_t i_length;
int i_buffer_pos;
uint8_t *p_buffer;
- int i_buffer_out;
- int i_buffer_out_pos;
- uint8_t *p_buffer_out;
-
AVFrame *p_ff_pic;
AVFrame *p_ff_pic_tmp0; /* to do deinterlace */
AVFrame *p_ff_pic_tmp1; /* to do pix conversion */
AVFrame *p_ff_pic_tmp2; /* to do resample */
ImgReSampleContext *p_vresample;
-
-#ifdef HAVE_VORBIS_VORBISENC_H
-
- /* Vorbis part */
- vorbis_info *p_vi;
- vorbis_dsp_state *p_vd;
- vorbis_block *p_vb;
- vorbis_comment *p_vc;
- int i_last_block_size;
- int i_samples_delay;
- vlc_bool_t b_headers_sent;
-#endif
};
}
}
- /* find encoder */
id->i_buffer_in = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
id->i_buffer_in_pos = 0;
id->p_buffer_in = malloc( id->i_buffer_in );
id->i_buffer_pos = 0;
id->p_buffer = malloc( id->i_buffer );
- id->i_buffer_out = 2 * AVCODEC_MAX_AUDIO_FRAME_SIZE;
- id->i_buffer_out_pos = 0;
- id->p_buffer_out = malloc( id->i_buffer_out );
-
/* Sanity check for audio channels */
id->f_dst.i_channels = __MIN( id->f_dst.i_channels, id->f_src.i_channels );
-#ifdef HAVE_VORBIS_VORBISENC_H
- if( id->f_dst.i_fourcc == VLC_FOURCC('v','o','r','b') )
- {
- id->p_vi = (vorbis_info *)malloc( sizeof(vorbis_info) );
- id->p_vd = (vorbis_dsp_state *)malloc( sizeof(vorbis_dsp_state) );
- id->p_vb = (vorbis_block *)malloc( sizeof(vorbis_block) );
- id->p_vc = (vorbis_comment *)malloc( sizeof(vorbis_comment) );
-
- vorbis_info_init( id->p_vi );
-
- if( vorbis_encode_setup_managed( id->p_vi, id->f_dst.i_channels,
- id->f_dst.i_sample_rate, -1, id->f_dst.i_bitrate, -1 ) ||
- vorbis_encode_ctl( id->p_vi, OV_ECTL_RATEMANAGE_AVG, NULL ) ||
- vorbis_encode_setup_init( id->p_vi ) ){}
-
- /* add a comment */
- vorbis_comment_init( id->p_vc);
- vorbis_comment_add_tag( id->p_vc, "ENCODER", "VLC media player");
-
- /* set up the analysis state and auxiliary encoding storage */
- vorbis_analysis_init( id->p_vd, id->p_vi );
- vorbis_block_init( id->p_vd, id->p_vb );
-
- id->b_headers_sent = VLC_FALSE;
- id->i_last_block_size = 0;
- id->i_samples_delay = 0;
-
- return VLC_SUCCESS;
- }
-#endif
-
- i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
- if( i_ff_codec == 0 )
- {
- msg_Err( p_stream, "cannot find encoder id" );
- return VLC_EGENERIC;
- }
-
- id->ff_enc = avcodec_find_encoder( i_ff_codec );
- if( !id->ff_enc )
- {
- msg_Err( p_stream, "cannot find encoder (avcodec)" );
- return VLC_EGENERIC;
- }
-
- /* Hack for mp3 transcoding support */
- if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','3',' ' ) )
+ /* find encoder */
+ id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
+ id->p_encoder->i_fourcc = id->f_dst.i_fourcc;
+ id->p_encoder->format.audio.i_format = AOUT_FMT_S16_NE;
+ id->p_encoder->format.audio.i_rate = id->f_dst.i_sample_rate;
+ id->p_encoder->format.audio.i_physical_channels =
+ id->p_encoder->format.audio.i_original_channels =
+ pi_channels_maps[id->f_dst.i_channels];
+ id->p_encoder->i_bitrate = id->f_dst.i_bitrate;
+ id->p_encoder->i_extra_data = 0;
+ id->p_encoder->p_extra_data = NULL;
+
+ id->p_encoder->p_module =
+ module_Need( id->p_encoder, "audio encoder", NULL );
+ if( !id->p_encoder->p_module )
{
- id->f_dst.i_fourcc = VLC_FOURCC( 'm','p','g','a' );
+ vlc_object_destroy( id->p_encoder );
+ id->p_encoder = NULL;
}
- id->ff_enc_c = avcodec_alloc_context();
- id->ff_enc_c->bit_rate = id->f_dst.i_bitrate;
- id->ff_enc_c->sample_rate = id->f_dst.i_sample_rate;
- id->ff_enc_c->channels = id->f_dst.i_channels;
+ id->b_enc_inited = VLC_FALSE;
- /* Make sure we get extradata filled by the encoder */
- id->ff_enc_c->extradata_size = 0;
- id->ff_enc_c->extradata = NULL;
- id->ff_enc_c->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
- if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
- {
- if( id->ff_enc_c->channels > 2 )
- {
- id->ff_enc_c->channels = 2;
- id->f_dst.i_channels = 2;
- if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
- {
- msg_Err( p_stream, "cannot open encoder" );
- return VLC_EGENERIC;
- }
- msg_Warn( p_stream, "stereo mode selected (codec limitation)" );
- }
- else
- {
- msg_Err( p_stream, "cannot open encoder" );
- return VLC_EGENERIC;
- }
- }
-
- id->f_dst.i_extra_data = id->ff_enc_c->extradata_size;
- id->f_dst.p_extra_data = id->ff_enc_c->extradata;
- id->ff_enc_c->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
+ id->f_dst.i_extra_data = id->p_encoder->i_extra_data;
+ id->f_dst.p_extra_data = id->p_encoder->p_extra_data;
return VLC_SUCCESS;
}
if( id->ff_dec )
{
avcodec_close( id->ff_dec_c );
+ free( id->ff_dec_c );
}
-#ifdef HAVE_VORBIS_VORBISENC_H
- if( id->f_dst.i_fourcc == VLC_FOURCC('v','o','r','b') )
- {
- vorbis_block_clear( id->p_vb );
- vorbis_dsp_clear( id->p_vd );
- vorbis_comment_clear( id->p_vc );
- vorbis_info_clear( id->p_vi ); /* must be called last */
-
- free( id->p_vi );
- free( id->p_vd );
- free( id->p_vb );
- free( id->p_vc );
- }
- else
-#endif
- avcodec_close( id->ff_enc_c );
-
- free( id->ff_dec_c );
- if( id->f_dst.i_fourcc != VLC_FOURCC('v','o','r','b') )
- free( id->ff_enc_c );
+ module_Unneed( id->p_encoder, id->p_encoder->p_module );
+ vlc_object_destroy( id->p_encoder );
free( id->p_buffer_in );
free( id->p_buffer );
- free( id->p_buffer_out );
}
static int transcode_audio_ffmpeg_process( sout_stream_t *p_stream,
sout_buffer_t **out )
{
vlc_bool_t b_again = VLC_FALSE;
-
+ aout_buffer_t aout_buf;
+ block_t *p_block;
*out = NULL;
/* gather data into p_buffer_in */
-#ifdef HAVE_VORBIS_VORBISENC_H
- if( id->f_dst.i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
- id->i_dts = in->i_dts -
- (mtime_t)1000000 * (mtime_t)id->i_samples_delay /
- (mtime_t)id->f_dst.i_sample_rate;
- else
-#endif
id->i_dts = in->i_dts -
(mtime_t)1000000 *
(mtime_t)(id->i_buffer_pos / 2 / id->ff_dec_c->channels )/
do
{
- int i_buffer_pos;
-
/* decode as much data as possible */
if( id->ff_dec )
{
int i_buffer_size;
int i_used;
- i_buffer_size = id->i_buffer - id->i_buffer_pos;
-
i_used = avcodec_decode_audio( id->ff_dec_c,
- (int16_t*)&id->p_buffer[id->i_buffer_pos],
+ (int16_t*)&id->p_buffer,
&i_buffer_size, id->p_buffer_in,
id->i_buffer_in_pos );
- /* msg_Warn( p_stream, "avcodec_decode_audio: %d used",
- i_used ); */
+#if 0
+ msg_Warn( p_stream, "avcodec_decode_audio: %d used on %d",
+ i_used, id->i_buffer_in_pos );
+#endif
+
id->i_buffer_pos += i_buffer_size;
if( i_used < 0 )
{
- msg_Warn( p_stream, "error");
+ msg_Warn( p_stream, "error audio decoding");
id->i_buffer_in_pos = 0;
break;
}
id->i_buffer_in_pos -= i_used;
}
- i_buffer_pos = id->i_buffer_pos;
-
- /* encode as much data as possible */
-
-#ifdef HAVE_VORBIS_VORBISENC_H
- if( id->i_buffer_pos == 0 );
- else if( id->f_dst.i_fourcc == VLC_FOURCC( 'v', 'o', 'r', 'b' ) )
- {
- float **buffer;
- int i, j, i_samples;
- sout_buffer_t *p_out;
- ogg_packet op;
-
- if( !id->b_headers_sent )
- {
- ogg_packet header[3];
- vorbis_analysis_headerout( id->p_vd, id->p_vc,
- &header[0], &header[1], &header[2]);
- for( i = 0; i < 3; i++ )
- {
- p_out = sout_BufferNew( p_stream->p_sout, header[i].bytes);
- memcpy( p_out->p_buffer, header[i].packet,
- header[i].bytes );
-
- p_out->i_size = header[i].bytes;
- p_out->i_length = 0;
-
- p_out->i_dts = p_out->i_pts = id->i_dts;
-
- sout_BufferChain( out, p_out );
- }
- id->b_headers_sent = VLC_TRUE;
- }
-
- i_samples = id->i_buffer_pos / id->f_src.i_channels / 2;
- id->i_samples_delay += i_samples;
- id->i_buffer_pos = 0;
-
- buffer = vorbis_analysis_buffer( id->p_vd, i_samples );
-
- /* 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;
- }
- }
-
- vorbis_analysis_wrote( id->p_vd, i_samples );
-
- while( vorbis_analysis_blockout( id->p_vd, id->p_vb ) == 1 )
- {
- vorbis_analysis( id->p_vb, NULL );
- vorbis_bitrate_addblock( id->p_vb );
-
- while( vorbis_bitrate_flushpacket( id->p_vd, &op ) )
- {
- int i_block_size;
- p_out = sout_BufferNew( p_stream->p_sout, op.bytes );
- memcpy( p_out->p_buffer, op.packet, op.bytes );
-
- i_block_size = vorbis_packet_blocksize( id->p_vi, &op );
-
- if( i_block_size < 0 ) i_block_size = 0;
- i_samples = ( id->i_last_block_size +
- i_block_size ) >> 2;
- id->i_last_block_size = i_block_size;
-
- p_out->i_size = op.bytes;
- p_out->i_length = (mtime_t)1000000 *
- (mtime_t)i_samples /
- (mtime_t)id->f_dst.i_sample_rate;
-
- //msg_Err( p_stream, "i_dts: %lld", id->i_dts );
-
- /* FIXME */
- p_out->i_dts = id->i_dts;
- p_out->i_pts = id->i_dts;
-
- id->i_samples_delay -= i_samples;
-
- /* update dts */
- id->i_dts += p_out->i_length;
- sout_BufferChain( out, p_out );
-
- }
- }
- }
- else
-#endif
-
- for( ;; )
- {
- int i_frame_size = id->ff_enc_c->frame_size * 2 *
- id->ff_dec_c->channels;
- int i_out_size, i, j;
- sout_buffer_t *p_out;
- int16_t *p_buffer = (int16_t *)(id->p_buffer + i_buffer_pos -
- id->i_buffer_pos);
-
- if( id->i_buffer_pos < i_frame_size )
- {
- break;
- }
-
- if( id->ff_dec_c->channels != id->ff_enc_c->channels )
- {
- /* 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];
- }
- }
- }
-
- /* msg_Warn( p_stream, "avcodec_encode_audio: frame size%d",
- i_frame_size); */
- i_out_size = avcodec_encode_audio( id->ff_enc_c,
- id->p_buffer_out, id->i_buffer_out, p_buffer );
+ if( id->i_buffer_pos == 0 ) continue;
- if( i_out_size <= 0 )
+ /* Encode as much data as possible */
+ if( id->b_enc_inited )
+ {
+ while( id->p_encoder->pf_header &&
+ (p_block = id->p_encoder->pf_header( id->p_encoder )) )
{
- break;
+ sout_buffer_t *p_out;
+ p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
+ memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
+ p_out->i_dts = in->i_dts;
+ p_out->i_pts = in->i_dts;
+ sout_BufferChain( out, p_out );
}
- id->i_buffer_pos -= i_frame_size;
-
- p_out = sout_BufferNew( p_stream->p_sout, i_out_size );
- memcpy( p_out->p_buffer, id->p_buffer_out, i_out_size );
- p_out->i_size = i_out_size;
- p_out->i_length = (mtime_t)1000000 *
- (mtime_t)id->ff_enc_c->frame_size /
- (mtime_t)id->ff_enc_c->sample_rate;
-
- /* FIXME */
- p_out->i_dts = id->i_dts;
- p_out->i_pts = id->i_dts;
-
- /* update dts */
- id->i_dts += p_out->i_length;
-
- /* msg_Warn( p_stream, "frame dts=%lld len %lld out=%d",
- p_out->i_dts, p_out->i_length, i_out_size ); */
-
- sout_BufferChain( out, p_out );
- }
-
- /* Copy the remaining raw samples */
- if( id->i_buffer_pos != 0 )
- {
- memmove( id->p_buffer,
- &id->p_buffer[i_buffer_pos - id->i_buffer_pos],
- id->i_buffer_pos );
- }
+ id->b_enc_inited = VLC_TRUE;
+ }
+
+ aout_buf.p_buffer = id->p_buffer;
+ aout_buf.i_nb_bytes = id->i_buffer_pos;
+ aout_buf.i_nb_samples = id->i_buffer_pos / 2 / id->ff_dec_c->channels;
+ aout_buf.start_date = id->i_dts;
+ aout_buf.end_date = id->i_dts;
+
+ p_block = id->p_encoder->pf_encode_audio( id->p_encoder, &aout_buf );
+ while( p_block )
+ {
+ sout_buffer_t *p_out;
+ block_t *p_prev_block = p_block;
+
+ p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
+ memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
+ p_out->i_dts = p_block->i_dts;
+ p_out->i_pts = p_block->i_pts;
+ p_out->i_length = p_block->i_length;
+ sout_BufferChain( out, p_out );
+
+ p_block = p_block->p_next;
+ block_Release( p_prev_block );
+ }
+ id->i_buffer_pos = 0;
} while( b_again );
int i_ff_codec;
+ /* Open decoder */
if( id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '0' ) ||
id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '2', '2' ) ||
id->f_src.i_fourcc == VLC_FOURCC( 'I', '4', '4', '4' ) ||
id->f_src.i_fourcc == VLC_FOURCC( 'R', 'V', '3', '2' ) ||
id->f_src.i_fourcc == VLC_FOURCC( 'G', 'R', 'E', 'Y' ) )
{
- id->ff_dec = NULL;
+ id->ff_dec = NULL;
id->ff_dec_c = avcodec_alloc_context();
id->ff_dec_c->width = id->f_src.i_width;
id->ff_dec_c->height = id->f_src.i_height;
}
}
-
- /* find encoder */
- id->ff_enc = id->ff_enc_c = NULL;
- i_ff_codec = get_ff_codec( id->f_dst.i_fourcc );
- if( i_ff_codec != 0 )
- {
- id->ff_enc = avcodec_find_encoder( i_ff_codec );
- }
-
- /* Hack for external encoders */
- if( !id->ff_enc )
+ /* Open encoder */
+ id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
+ id->p_encoder->i_fourcc = id->f_dst.i_fourcc;
+ id->p_encoder->format.video.i_width = p_sys->i_width;
+ id->p_encoder->format.video.i_height = p_sys->i_height;
+ id->p_encoder->i_bitrate = p_sys->i_vbitrate;
+
+ id->p_encoder->i_vtolerance = p_sys->i_vtolerance;
+ id->p_encoder->i_key_int = p_sys->i_key_int;
+ id->p_encoder->i_b_frames = p_sys->i_b_frames;
+ id->p_encoder->i_qmin = p_sys->i_qmin;
+ id->p_encoder->i_qmax = p_sys->i_qmax;
+ id->p_encoder->i_hq = p_sys->i_hq;
+
+ if( id->p_encoder->format.video.i_width <= 0 )
{
- id->p_encoder = vlc_object_create( p_stream, VLC_OBJECT_ENCODER );
- id->p_encoder->i_fourcc = id->f_dst.i_fourcc;
- id->p_encoder->format.video.i_width = p_sys->i_width;
- id->p_encoder->format.video.i_height = p_sys->i_height;
- id->p_encoder->i_bitrate = p_sys->i_vbitrate;
-
- if( id->p_encoder->format.video.i_width <= 0 )
- {
- id->p_encoder->format.video.i_width = id->f_dst.i_width =
- id->ff_dec_c->width - p_sys->i_crop_left -
- p_sys->i_crop_right;
- }
- if( id->p_encoder->format.video.i_height <= 0 )
- {
- id->p_encoder->format.video.i_height = id->f_dst.i_height =
- id->ff_dec_c->height - p_sys->i_crop_top -
- p_sys->i_crop_bottom;
- }
-
- id->p_encoder->p_module =
- module_Need( id->p_encoder, "video encoder", NULL );
-
- if( !id->p_encoder->p_module )
- {
- free( id->p_encoder );
- id->p_encoder = NULL;
- }
+ id->p_encoder->format.video.i_width = id->f_dst.i_width =
+ id->ff_dec_c->width - p_sys->i_crop_left - p_sys->i_crop_right;
}
- /* End hack for external encoders */
-
- if( !id->ff_enc && !id->p_encoder )
+ if( id->p_encoder->format.video.i_height <= 0 )
{
- msg_Err( p_stream, "cannot find encoder" );
- return VLC_EGENERIC;
+ id->p_encoder->format.video.i_height = id->f_dst.i_height =
+ id->ff_dec_c->height - p_sys->i_crop_top - p_sys->i_crop_bottom;
}
- /* XXX open it only when we have the first frame */
- id->b_enc_inited = VLC_FALSE;
- id->i_buffer_in = 0;
- id->i_buffer_in_pos = 0;
- id->p_buffer_in = NULL;
-
- id->i_buffer = 3*1024*1024;
- id->i_buffer_pos = 0;
- id->p_buffer = malloc( id->i_buffer );
-
- id->i_buffer_out = 0;
- id->i_buffer_out_pos = 0;
- id->p_buffer_out = NULL;
-
id->p_ff_pic = avcodec_alloc_frame();
id->p_ff_pic_tmp0 = NULL;
id->p_ff_pic_tmp1 = NULL;
id->p_ff_pic_tmp2 = NULL;
id->p_vresample = NULL;
- p_sys->i_last_ref_pts = 0;
- p_sys->i_buggy_pts_detect = 0;
-
- /* This is enough for external encoders */
- if( id->p_encoder && id->p_encoder->p_module ) return VLC_SUCCESS;
-
- if( id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','1','v' )||
- id->f_dst.i_fourcc == VLC_FOURCC( 'm','p','2','v' ) )
- {
- id->f_dst.i_fourcc = VLC_FOURCC( 'm','p','g','v' );
- }
-
- id->ff_enc_c = avcodec_alloc_context();
- id->ff_enc_c->width = id->f_dst.i_width;
- id->ff_enc_c->height = id->f_dst.i_height;
- id->ff_enc_c->bit_rate = id->f_dst.i_bitrate;
-
if( id->ff_dec )
{
- id->ff_enc_c->frame_rate = id->ff_dec_c->frame_rate;
+ id->p_encoder->i_frame_rate = id->ff_dec_c->frame_rate;
#if LIBAVCODEC_BUILD >= 4662
- id->ff_enc_c->frame_rate_base= id->ff_dec_c->frame_rate_base;
+ id->p_encoder->i_frame_rate_base= id->ff_dec_c->frame_rate_base;
#endif
}
else
{
#if LIBAVCODEC_BUILD >= 4662
- id->ff_enc_c->frame_rate = 25 ; /* FIXME as it break mpeg */
- id->ff_enc_c->frame_rate_base= 1;
+ id->p_encoder->i_frame_rate = 25 ; /* FIXME as it break mpeg */
+ id->p_encoder->i_frame_rate_base= 1;
#else
- id->ff_enc_c->frame_rate = 25 * FRAME_RATE_BASE;
+ id->p_encoder->i_frame_rate = 25 * FRAME_RATE_BASE;
#endif
}
- id->ff_enc_c->gop_size = p_sys->i_key_int >= 0 ? p_sys->i_key_int : 50;
- id->ff_enc_c->max_b_frames = __MIN( p_sys->i_b_frames, FF_MAX_B_FRAMES );
- id->ff_enc_c->b_frame_strategy = 0;
- id->ff_enc_c->b_quant_factor = 2.0;
+ id->p_encoder->p_module =
+ module_Need( id->p_encoder, "video encoder", NULL );
- if( p_sys->i_vtolerance >= 0 )
+ if( !id->p_encoder->p_module )
{
- id->ff_enc_c->bit_rate_tolerance = p_sys->i_vtolerance;
+ vlc_object_destroy( id->p_encoder );
+ msg_Err( p_stream, "cannot find encoder" );
+ return VLC_EGENERIC;
}
- id->ff_enc_c->qmin = p_sys->i_qmin;
- id->ff_enc_c->qmax = p_sys->i_qmax;
-#if LIBAVCODEC_BUILD >= 4673
- id->ff_enc_c->mb_decision = p_sys->i_hq;
-#else
- if( p_sys->i_hq )
- {
- id->ff_enc_c->flags |= CODEC_FLAG_HQ;
- }
-#endif
+ /* Close the encoder.
+ * We'll open it only when we have the first frame */
+ module_Unneed( id->p_encoder, id->p_encoder->p_module );
- if( i_ff_codec == CODEC_ID_RAWVIDEO )
- {
- id->ff_enc_c->pix_fmt = get_ff_chroma( id->f_dst.i_fourcc );
- }
+ id->b_enc_inited = VLC_FALSE;
return VLC_SUCCESS;
}
-static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream, sout_stream_id_t *id )
+static void transcode_video_ffmpeg_close ( sout_stream_t *p_stream,
+ sout_stream_id_t *id )
{
+ /* Close decoder */
if( id->ff_dec )
{
avcodec_close( id->ff_dec_c );
- }
- if( id->p_encoder )
- {
- /* External encoding */
- module_Unneed( id->p_encoder, id->p_encoder->p_module );
- vlc_object_destroy( id->p_encoder->p_module );
- }
- else if( id->b_enc_inited )
- {
- avcodec_close( id->ff_enc_c );
+ free( id->ff_dec_c );
}
+ /* Close encoder */
+ module_Unneed( id->p_encoder, id->p_encoder->p_module );
+ vlc_object_destroy( id->p_encoder );
+
+ /* Misc cleanup */
if( id->p_ff_pic)
{
free( id->p_ff_pic );
{
free( id->p_vresample );
}
-
- free( id->ff_dec_c );
- if( id->ff_enc_c ) free( id->ff_enc_c );
- free( id->p_buffer );
}
static int transcode_video_ffmpeg_process( sout_stream_t *p_stream,
{
sout_stream_sys_t *p_sys = p_stream->p_sys;
int i_used;
- int i_out;
int b_gotpicture;
AVFrame *frame;
p_sys->i_output_pts = frame->pts;
}
- if( !id->b_enc_inited && id->p_encoder )
+ if( !id->b_enc_inited )
{
block_t *p_block;
/* XXX hack because of copy packetizer and mpeg4video that can fail
* detecting size */
-#if 0
- if( id->p_encoder->i_width <= 0 )
+ if( id->p_encoder->format.video.i_width <= 0 )
{
- id->p_encoder->i_width = id->f_dst.i_width =
+ id->p_encoder->format.video.i_width = id->f_dst.i_width =
id->ff_dec_c->width - p_sys->i_crop_left -
p_sys->i_crop_right;
}
- if( id->p_encoder->i_height <= 0 )
+ if( id->p_encoder->format.video.i_height <= 0 )
{
- id->p_encoder->i_height = id->f_dst.i_height =
+ id->p_encoder->format.video.i_height = id->f_dst.i_height =
id->ff_dec_c->height - p_sys->i_crop_top -
p_sys->i_crop_bottom;
}
-#endif
id->p_encoder->i_bitrate = p_sys->i_vbitrate;
- if( !( id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out, &id->f_dst ) ) )
+ id->p_encoder->i_extra_data = 0;
+ id->p_encoder->p_extra_data = NULL;
+
+ id->p_encoder->p_module =
+ module_Need( id->p_encoder, "video encoder", NULL );
+ if( !id->p_encoder->p_module )
+ {
+ vlc_object_destroy( id->p_encoder );
+ msg_Err( p_stream, "cannot find encoder" );
+ return VLC_EGENERIC;
+ }
+
+ id->f_dst.i_extra_data = id->p_encoder->i_extra_data;
+ id->f_dst.p_extra_data = id->p_encoder->p_extra_data;
+
+ if( !( id->id =
+ p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out,
+ &id->f_dst ) ) )
{
msg_Err( p_stream, "cannot add this stream" );
+ transcode_video_ffmpeg_close( p_stream, id );
id->b_transcode = VLC_FALSE;
return VLC_EGENERIC;
}
- while( (p_block = id->p_encoder->pf_header( id->p_encoder )) )
+ while( id->p_encoder->pf_header &&
+ (p_block = id->p_encoder->pf_header( id->p_encoder )) )
{
sout_buffer_t *p_out;
p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
id->b_enc_inited = VLC_TRUE;
}
- else if( !id->b_enc_inited )
- {
- /* XXX hack because of copy packetizer and mpeg4video that can fail
- * detecting size */
- if( id->ff_enc_c->width <= 0 )
- {
- id->ff_enc_c->width =
- id->f_dst.i_width = id->ff_dec_c->width - p_sys->i_crop_left - p_sys->i_crop_right;
- }
- if( id->ff_enc_c->height <= 0 )
- {
- id->ff_enc_c->height =
- id->f_dst.i_height = id->ff_dec_c->height - p_sys->i_crop_top - p_sys->i_crop_bottom;
- }
-
- /* Make sure we get extradata filled by the encoder */
- id->ff_enc_c->extradata_size = 0;
- id->ff_enc_c->extradata = NULL;
- id->ff_enc_c->flags |= CODEC_FLAG_GLOBAL_HEADER;
-
- if( avcodec_open( id->ff_enc_c, id->ff_enc ) )
- {
- msg_Err( p_stream, "cannot open encoder" );
- return VLC_EGENERIC;
- }
-
- id->f_dst.i_extra_data = id->ff_enc_c->extradata_size;
- id->f_dst.p_extra_data = id->ff_enc_c->extradata;
- id->ff_enc_c->flags &= ~CODEC_FLAG_GLOBAL_HEADER;
-
- if( !( id->id = p_stream->p_sys->p_out->pf_add( p_stream->p_sys->p_out, &id->f_dst ) ) )
- {
- msg_Err( p_stream, "cannot add this stream" );
- transcode_video_ffmpeg_close( p_stream, id );
- id->b_transcode = VLC_FALSE;
- return VLC_EGENERIC;
- }
-
- id->i_inter_pixfmt = id->ff_enc_c->pix_fmt;
-
- id->b_enc_inited = VLC_TRUE;
- }
-
/* deinterlace */
if( p_stream->p_sys->b_deinterlace )
id->ff_dec_c->frame_rate_base / (2 * id->ff_dec_c->frame_rate);
}
- if( id->p_encoder )
- {
- /* External encoding */
- block_t *p_block;
- picture_t pic;
- int i_plane;
-
- vout_InitPicture( VLC_OBJECT(p_stream), &pic,
- id->p_encoder->format.video.i_chroma,
- id->f_dst.i_width, id->f_dst.i_height,
- id->f_dst.i_width * VOUT_ASPECT_FACTOR /
- id->f_dst.i_height );
-
- for( i_plane = 0; i_plane < pic.i_planes; i_plane++ )
- {
- pic.p[i_plane].p_pixels = frame->data[i_plane];
- pic.p[i_plane].i_pitch = frame->linesize[i_plane];
- }
-
- pic.date = frame->pts;
-
- p_block = id->p_encoder->pf_encode_video( id->p_encoder, &pic );
- if( p_block )
- {
- sout_buffer_t *p_out;
- p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
- memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
- p_out->i_dts = p_block->i_dts;
- p_out->i_pts = p_block->i_pts;
- sout_BufferChain( out, p_out );
- block_Release( p_block );
- }
-
- return VLC_SUCCESS;
- }
-
- /* Let ffmpeg select the frame type */
- frame->pict_type = 0;
-
- i_out = avcodec_encode_video( id->ff_enc_c, id->p_buffer,
- id->i_buffer, frame );
- if( i_out > 0 )
- {
- sout_buffer_t *p_out;
- p_out = sout_BufferNew( p_stream->p_sout, i_out );
-
- memcpy( p_out->p_buffer, id->p_buffer, i_out );
-
- p_out->i_size = i_out;
-
- if( id->ff_enc_c->coded_frame->pts != 0 &&
- p_sys->i_buggy_pts_detect != id->ff_enc_c->coded_frame->pts )
- {
- p_sys->i_buggy_pts_detect = id->ff_enc_c->coded_frame->pts;
-
- /* FIXME, 3-2 pulldown is not handled correctly */
- p_out->i_length = in->i_length;
- p_out->i_pts = id->ff_enc_c->coded_frame->pts;
-
- if( !id->ff_enc_c->delay ||
- ( id->ff_enc_c->coded_frame->pict_type != FF_I_TYPE &&
- id->ff_enc_c->coded_frame->pict_type != FF_P_TYPE ) )
- {
- p_out->i_dts = p_out->i_pts;
- }
- else
- {
- if( p_sys->i_last_ref_pts )
- {
- p_out->i_dts = p_sys->i_last_ref_pts;
- }
- else
- {
- /* Let's put something sensible */
- p_out->i_dts = p_out->i_pts;
- }
-
- p_sys->i_last_ref_pts = p_out->i_pts;
- }
- }
- else
- {
- /* Buggy libavcodec which doesn't update coded_frame->pts
- * correctly */
- p_out->i_length = in->i_length;
- p_out->i_dts = in->i_dts;
- p_out->i_pts = in->i_dts;
- }
-
- sout_BufferChain( out, p_out );
- }
+ /* Encoding */
+ block_t *p_block;
+ picture_t pic;
+ int i_plane;
+
+ vout_InitPicture( VLC_OBJECT(p_stream), &pic,
+ id->p_encoder->format.video.i_chroma,
+ id->f_dst.i_width, id->f_dst.i_height,
+ id->f_dst.i_width * VOUT_ASPECT_FACTOR /
+ id->f_dst.i_height );
+
+ for( i_plane = 0; i_plane < pic.i_planes; i_plane++ )
+ {
+ pic.p[i_plane].p_pixels = frame->data[i_plane];
+ pic.p[i_plane].i_pitch = frame->linesize[i_plane];
+ }
+
+ pic.date = frame->pts;
+
+ p_block = id->p_encoder->pf_encode_video( id->p_encoder, &pic );
+ while( p_block )
+ {
+ sout_buffer_t *p_out;
+ block_t *p_prev_block = p_block;
+
+ p_out = sout_BufferNew( p_stream->p_sout, p_block->i_buffer );
+ memcpy( p_out->p_buffer, p_block->p_buffer, p_block->i_buffer);
+ p_out->i_dts = p_block->i_dts;
+ p_out->i_pts = p_block->i_pts;
+ p_out->i_length = p_block->i_length;
+ sout_BufferChain( out, p_out );
+
+ p_block = p_block->p_next;
+ block_Release( p_prev_block );
+ }
if( i_data <= 0 )
{