Commit bc57d09c authored by Laurent Aimar's avatar Laurent Aimar

* All: simplifications.

parent e3c06996
......@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.7 2002/05/10 02:04:17 fenrir Exp $
* $Id: ffmpeg.c,v 1.8 2002/05/12 06:51:08 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -81,8 +81,8 @@ MODULE_CONFIG_START
MODULE_CONFIG_STOP
MODULE_INIT_START
SET_DESCRIPTION( "ffmpeg video decoder module (MSMPEG4,MPEG4)" )
ADD_CAPABILITY( DECODER, 50 )
SET_DESCRIPTION( "ffmpeg video decoder (MSMPEG4v3,MPEG4)" )
ADD_CAPABILITY( DECODER, 70 )
ADD_SHORTCUT( "ffmpeg" )
MODULE_INIT_STOP
......@@ -119,8 +119,6 @@ static int decoder_Probe( u8 *pi_type )
{
switch( *pi_type )
{
/* case( MPEG1_VIDEO_ES ): marche pas pr le moment
case( MPEG2_VIDEO_ES ): */
case( MSMPEG4_VIDEO_ES ):
case( MPEG4_VIDEO_ES ):
return( 0 );
......@@ -197,99 +195,53 @@ static void __PES_NEXT( decoder_fifo_t *p_fifo )
vlc_mutex_unlock( &p_fifo->data_lock );
}
static void __PACKET_REINIT( videodec_thread_t *p_vdec )
static __inline__ void __GetFrame( videodec_thread_t *p_vdec )
{
pes_packet_t *p_pes;
data_packet_t *p_data;
byte_t *p_buffer;
p_pes = __PES_GET( p_vdec->p_fifo );
if( p_vdec->p_fifo->b_die )
{
return;
}
p_vdec->p_data = p_pes->p_first;
p_vdec->p_buff = p_vdec->p_data->p_payload_start;
p_vdec->i_data_size = p_vdec->p_data->p_payload_end -
p_vdec->p_data->p_payload_start;
}
p_vdec->i_pts = p_pes->i_pts;
static void __PACKET_NEXT( videodec_thread_t *p_vdec )
{
do
{
p_vdec->p_data = p_vdec->p_data->p_next;
if( !p_vdec->p_data )
while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
{
__PES_NEXT( p_vdec->p_fifo );
if( p_vdec->p_fifo->b_die )
p_pes = __PES_GET( p_vdec->p_fifo );
}
p_vdec->i_framesize = p_pes->i_pes_size;
if( p_pes->i_nb_data == 1 )
{
p_vdec->p_framedata = p_pes->p_first->p_payload_start;
return;
}
__PACKET_REINIT( p_vdec );
}
else
/* get a buffer and gather all data packet */
p_vdec->p_framedata = p_buffer = malloc( p_pes->i_pes_size );
p_data = p_pes->p_first;
do
{
p_vdec->p_buff = p_vdec->p_data->p_payload_start;
p_vdec->i_data_size = p_vdec->p_data->p_payload_end -
p_vdec->p_data->p_payload_start;
}
} while( ( p_vdec->i_data_size <= 0 )
||( p_vdec->p_data->b_discard_payload ) );
FAST_MEMCPY( p_buffer,
p_data->p_payload_start,
p_data->p_payload_end - p_data->p_payload_start );
p_buffer += p_data->p_payload_end - p_data->p_payload_start;
p_data = p_data->p_next;
} while( p_data );
}
static void __PACKET_FILL( videodec_thread_t *p_vdec )
{
if( p_vdec->i_data_size <= 0 )
{
__PACKET_NEXT( p_vdec );
}
}
/* call only two times so inline for faster */
static __inline__ void __ConvertAVPictureToPicture( AVPicture *p_avpicture,
picture_t *p_picture )
static __inline__ void __NextFrame( videodec_thread_t *p_vdec )
{
int i_plane, i_line, i_inc;
u8 *p_dest,*p_src;
pes_packet_t *p_pes;
for( i_plane = 0; i_plane < __MIN(p_picture->i_planes, 3); i_plane++ )
{
p_dest = p_picture->p[i_plane].p_pixels;
p_src = p_avpicture->data[i_plane];
if( ( !p_dest )||( !p_src ))
{
return;
}
i_inc = __MIN( p_picture->p[i_plane].i_pitch,
p_avpicture->linesize[i_plane] );
for( i_line = 0; i_line < p_picture->p[i_plane].i_lines; i_line++ )
p_pes = __PES_GET( p_vdec->p_fifo );
if( p_pes->i_nb_data != 1 )
{
FAST_MEMCPY( p_dest,
p_src,
i_inc );
p_dest += p_picture->p[i_plane].i_pitch;
p_src += p_avpicture->linesize[i_plane];
}
free( p_vdec->p_framedata ); /* FIXME keep this buffer */
}
__PES_NEXT( p_vdec->p_fifo );
}
static __inline__ u32 __FfmpegChromaToFourCC( int i_ffmpegchroma )
{
switch( i_ffmpegchroma )
{
case( PIX_FMT_YUV420P ):
case( PIX_FMT_YUV422 ):
return FOURCC_I420;
case( PIX_FMT_RGB24 ):
return FOURCC_RV24;
case( PIX_FMT_YUV422P ):
return FOURCC_Y422;
case( PIX_FMT_YUV444P ):
case( PIX_FMT_BGR24 ):
default:
return( 0 );
}
}
/*****************************************************************************
* decoder_Run: this function is called just after the thread is created
*****************************************************************************/
......@@ -355,14 +307,11 @@ static int InitThread( videodec_thread_t *p_vdec )
}
else
{
memset( &p_vdec->format, 0, sizeof( bitmapinfoheader_t ) );
intf_ErrMsg( "vdec error: cannot get informations" );
return( -1 );
}
/* some codec need to have height and width initialized (msmepg4,mpeg4) */
/* we cannot create vout because we don't know what chroma */
/*init ffmpeg */
/* TODO: add a global variable to know if init was already done
in case we use it also for audio */
if( !b_ffmpeginit )
{
avcodec_init();
......@@ -377,11 +326,6 @@ static int InitThread( videodec_thread_t *p_vdec )
switch( p_vdec->p_config->i_type)
{
case( MPEG1_VIDEO_ES ): /* marche pas pr le moment */
case( MPEG2_VIDEO_ES ):
p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MPEG1VIDEO );
p_vdec->psz_namecodec = "MPEG-1";
break;
case( MSMPEG4_VIDEO_ES):
p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4 );
p_vdec->psz_namecodec = "MS MPEG-4/divx";
......@@ -407,7 +351,7 @@ static int InitThread( videodec_thread_t *p_vdec )
p_vdec->p_context->width = p_vdec->format.i_width;
p_vdec->p_context->height = p_vdec->format.i_height;
p_vdec->p_context->pix_fmt = PIX_FMT_YUV420P;
p_vdec->p_context->pix_fmt = PIX_FMT_YUV420P; /* I420 */
if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
{
......@@ -420,7 +364,25 @@ static int InitThread( videodec_thread_t *p_vdec )
intf_WarnMsg( 1, "vdec info: ffmpeg codec (%s) started",
p_vdec->psz_namecodec );
}
/* destroy each p_vout */
/* create vout */
p_vdec->p_vout = vout_CreateThread(
NULL,
p_vdec->format.i_width,
p_vdec->format.i_height,
FOURCC_I420,
VOUT_ASPECT_FACTOR * p_vdec->format.i_width /
p_vdec->format.i_height );
if( !p_vdec->p_vout )
{
intf_ErrMsg( "vdec error: can't open vout, aborting" );
avcodec_close( p_vdec->p_context );
intf_WarnMsg(1, "vdec info: ffmpeg codec (%s) stopped",
p_vdec->psz_namecodec);
return( -1 );
}
vlc_mutex_lock( &p_vout_bank->lock );
if( p_vout_bank->i_count != 0 )
{
......@@ -428,10 +390,11 @@ static int InitThread( videodec_thread_t *p_vdec )
vout_DestroyThread( p_vout_bank->pp_vout[ 0 ], NULL );
vlc_mutex_lock( &p_vout_bank->lock );
p_vout_bank->i_count--;
p_vout_bank->pp_vout[ 0 ] = NULL;
}
p_vout_bank->i_count++;
p_vout_bank->pp_vout[0] = p_vdec->p_vout;
vlc_mutex_unlock( &p_vout_bank->lock );
__PACKET_REINIT( p_vdec );
return( 0 );
}
......@@ -472,98 +435,38 @@ static void EndThread( videodec_thread_t *p_vdec )
static void DecodeThread( videodec_thread_t *p_vdec )
{
int i_len;
int i_plane;
int i_status;
int b_gotpicture;
int b_convert;
mtime_t i_pts;
AVPicture avpicture; /* ffmpeg picture */
u32 i_chroma;
picture_t *p_picture; /* videolan picture */
picture_t *p_pic; /* videolan picture */
/* we have to get a frame stored in a pes
give it to ffmpeg decoder
and send the image to the output */
/* when we have the first image we create the video output */
i_pts = 0 ;
do
{
__PACKET_FILL( p_vdec );
if( (p_vdec->p_fifo->b_die)||(p_vdec->p_fifo->b_error) )
{
return;
}
/* save pts */
if( !i_pts ) {i_pts = __PES_GET( p_vdec->p_fifo )->i_pts;}
__GetFrame( p_vdec );
i_len = avcodec_decode_video( p_vdec->p_context,
i_status = avcodec_decode_video( p_vdec->p_context,
&avpicture,
&b_gotpicture,
p_vdec->p_buff,
p_vdec->i_data_size);
p_vdec->p_framedata,
p_vdec->i_framesize);
__NextFrame( p_vdec );
if( i_len < 0 )
if( i_status < 0 )
{
intf_WarnMsg( 3, "vdec error: cannot decode one frame (%d bytes)",
p_vdec->i_data_size );
__PES_NEXT( p_vdec->p_fifo );
__PACKET_REINIT( p_vdec );
intf_WarnMsg( 2, "vdec error: cannot decode one frame (%d bytes)",
p_vdec->i_framesize );
return;
}
p_vdec->i_data_size -= i_len;
p_vdec->p_buff += i_len;
} while( !b_gotpicture );
if( !(i_chroma =__FfmpegChromaToFourCC( p_vdec->p_context->pix_fmt ) ) )
if( !b_gotpicture )
{
b_convert = 1;
i_chroma = FOURCC_I420;
}
else
{
b_convert = 0;
return;
}
/* Send decoded frame to vout */
if( !p_vdec->p_vout )
{
/* create vout */
/* ffmpeg set it for us with some codec */
if( (!p_vdec->format.i_width )||(!p_vdec->format.i_height) )
{
p_vdec->format.i_width = p_vdec->p_context->width;
p_vdec->format.i_height = p_vdec->p_context->height;
}
/* calculate i_aspect */
p_vdec->i_aspect = VOUT_ASPECT_FACTOR * p_vdec->format.i_width /
p_vdec->format.i_height;
p_vdec->i_chroma = i_chroma;
p_vdec->p_vout = vout_CreateThread(
NULL,
p_vdec->format.i_width,
p_vdec->format.i_height,
p_vdec->i_chroma,
p_vdec->i_aspect );
if( !p_vdec->p_vout )
{
intf_ErrMsg( "vdec error: can't open vout, aborting" );
p_vdec->p_fifo->b_error = 1;
return;
}
vlc_mutex_lock( &p_vout_bank->lock );
p_vout_bank->pp_vout[ 0 ] = p_vdec->p_vout;
p_vout_bank->i_count++;
vlc_mutex_unlock( &p_vout_bank->lock );
}
while( (p_picture = vout_CreatePicture( p_vdec->p_vout,
0, /* ??? */
0, /* ??? */
0) ) /* ??? */
== NULL )
while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
{
if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
{
......@@ -572,43 +475,28 @@ static void DecodeThread( videodec_thread_t *p_vdec )
msleep( VOUT_OUTMEM_SLEEP );
}
if( b_convert )
for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
{
/* we convert in a supported format */
int i_status;
u8 *p_buff;
AVPicture avpicture_tmp;
p_buff = malloc( avpicture_get_size( PIX_FMT_YUV420P,
p_vdec->p_context->width,
p_vdec->p_context->height) );
avpicture_fill( &avpicture_tmp,
p_buff,
PIX_FMT_YUV420P,
p_vdec->p_context->width,
p_vdec->p_context->height );
i_status = img_convert( &avpicture_tmp,
PIX_FMT_YUV420P,
&avpicture,
p_vdec->p_context->pix_fmt,
p_vdec->p_context->width,
p_vdec->p_context->height );
if( i_status < 0 )
int i_size;
int i_line;
byte_t *p_dest = p_pic->p[i_plane].p_pixels;
byte_t *p_src = avpicture.data[i_plane];
if( ( !p_dest )||( !p_src ))
{
intf_ErrMsg( "vdec error: cannot convert picture in known chroma" );
return;
}
__ConvertAVPictureToPicture( &avpicture_tmp, p_picture );
free( p_buff ); /* FIXME try to alloc only one time */
break;
}
else
i_size = __MIN( p_pic->p[i_plane].i_pitch,
avpicture.linesize[i_plane] );
for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
{
__ConvertAVPictureToPicture( &avpicture, p_picture );
FAST_MEMCPY( p_dest, p_src, i_size );
p_dest += p_pic->p[i_plane].i_pitch;
p_src += avpicture.linesize[i_plane];
}
}
vout_DatePicture( p_vdec->p_vout, p_picture, i_pts );
vout_DisplayPicture( p_vdec->p_vout, p_picture );
vout_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
vout_DisplayPicture( p_vdec->p_vout, p_pic );
return;
}
......
......@@ -2,7 +2,7 @@
* ffmpeg_vdec.h: video decoder using ffmpeg library
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: ffmpeg.h,v 1.1 2002/04/23 23:44:36 fenrir Exp $
* $Id: ffmpeg.h,v 1.2 2002/05/12 06:51:08 fenrir Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
......@@ -47,11 +47,10 @@ typedef struct videodec_thread_s
AVCodecContext context, *p_context;
AVCodec *p_codec;
vout_thread_t *p_vout;
int i_aspect;
u32 i_chroma;
char *psz_namecodec;
/* private */
data_packet_t *p_data;
byte_t *p_buff;
int i_data_size;
mtime_t i_pts;
int i_framesize;
byte_t *p_framedata;
} videodec_thread_t;
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment