Commit bc57d09c authored by Laurent Aimar's avatar Laurent Aimar

* All: simplifications.

parent e3c06996
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library * ffmpeg.c: video decoder using ffmpeg library
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * 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> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -81,8 +81,8 @@ MODULE_CONFIG_START ...@@ -81,8 +81,8 @@ MODULE_CONFIG_START
MODULE_CONFIG_STOP MODULE_CONFIG_STOP
MODULE_INIT_START MODULE_INIT_START
SET_DESCRIPTION( "ffmpeg video decoder module (MSMPEG4,MPEG4)" ) SET_DESCRIPTION( "ffmpeg video decoder (MSMPEG4v3,MPEG4)" )
ADD_CAPABILITY( DECODER, 50 ) ADD_CAPABILITY( DECODER, 70 )
ADD_SHORTCUT( "ffmpeg" ) ADD_SHORTCUT( "ffmpeg" )
MODULE_INIT_STOP MODULE_INIT_STOP
...@@ -119,8 +119,6 @@ static int decoder_Probe( u8 *pi_type ) ...@@ -119,8 +119,6 @@ static int decoder_Probe( u8 *pi_type )
{ {
switch( *pi_type ) switch( *pi_type )
{ {
/* case( MPEG1_VIDEO_ES ): marche pas pr le moment
case( MPEG2_VIDEO_ES ): */
case( MSMPEG4_VIDEO_ES ): case( MSMPEG4_VIDEO_ES ):
case( MPEG4_VIDEO_ES ): case( MPEG4_VIDEO_ES ):
return( 0 ); return( 0 );
...@@ -167,7 +165,7 @@ static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo ) ...@@ -167,7 +165,7 @@ static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
p_pes = p_fifo->p_first; p_pes = p_fifo->p_first;
vlc_mutex_unlock( &p_fifo->data_lock ); vlc_mutex_unlock( &p_fifo->data_lock );
return( p_pes ); return( p_pes );
} }
/* free the first pes and go to next */ /* free the first pes and go to next */
...@@ -197,99 +195,53 @@ static void __PES_NEXT( decoder_fifo_t *p_fifo ) ...@@ -197,99 +195,53 @@ static void __PES_NEXT( decoder_fifo_t *p_fifo )
vlc_mutex_unlock( &p_fifo->data_lock ); 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; pes_packet_t *p_pes;
data_packet_t *p_data;
byte_t *p_buffer;
p_pes = __PES_GET( p_vdec->p_fifo ); p_pes = __PES_GET( p_vdec->p_fifo );
if( p_vdec->p_fifo->b_die ) p_vdec->i_pts = p_pes->i_pts;
while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
{ {
return; __PES_NEXT( p_vdec->p_fifo );
p_pes = __PES_GET( p_vdec->p_fifo );
} }
p_vdec->p_data = p_pes->p_first; p_vdec->i_framesize = p_pes->i_pes_size;
p_vdec->p_buff = p_vdec->p_data->p_payload_start; if( p_pes->i_nb_data == 1 )
p_vdec->i_data_size = p_vdec->p_data->p_payload_end - {
p_vdec->p_data->p_payload_start; p_vdec->p_framedata = p_pes->p_first->p_payload_start;
} return;
}
static void __PACKET_NEXT( videodec_thread_t *p_vdec ) /* 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 do
{ {
p_vdec->p_data = p_vdec->p_data->p_next; FAST_MEMCPY( p_buffer,
if( !p_vdec->p_data ) p_data->p_payload_start,
{ p_data->p_payload_end - p_data->p_payload_start );
__PES_NEXT( p_vdec->p_fifo ); p_buffer += p_data->p_payload_end - p_data->p_payload_start;
if( p_vdec->p_fifo->b_die ) p_data = p_data->p_next;
{ } while( p_data );
return;
}
__PACKET_REINIT( p_vdec );
}
else
{
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 ) );
} }
static void __PACKET_FILL( videodec_thread_t *p_vdec ) static __inline__ void __NextFrame( 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 )
{ {
int i_plane, i_line, i_inc; pes_packet_t *p_pes;
u8 *p_dest,*p_src;
p_pes = __PES_GET( p_vdec->p_fifo );
for( i_plane = 0; i_plane < __MIN(p_picture->i_planes, 3); i_plane++ ) if( p_pes->i_nb_data != 1 )
{ {
p_dest = p_picture->p[i_plane].p_pixels; free( p_vdec->p_framedata ); /* FIXME keep this buffer */
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++ )
{
FAST_MEMCPY( p_dest,
p_src,
i_inc );
p_dest += p_picture->p[i_plane].i_pitch;
p_src += p_avpicture->linesize[i_plane];
}
} }
__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 * decoder_Run: this function is called just after the thread is created
*****************************************************************************/ *****************************************************************************/
...@@ -355,14 +307,11 @@ static int InitThread( videodec_thread_t *p_vdec ) ...@@ -355,14 +307,11 @@ static int InitThread( videodec_thread_t *p_vdec )
} }
else 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 */ /*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 ) if( !b_ffmpeginit )
{ {
avcodec_init(); avcodec_init();
...@@ -377,11 +326,6 @@ static int InitThread( videodec_thread_t *p_vdec ) ...@@ -377,11 +326,6 @@ static int InitThread( videodec_thread_t *p_vdec )
switch( p_vdec->p_config->i_type) 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): case( MSMPEG4_VIDEO_ES):
p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4 ); p_vdec->p_codec = avcodec_find_decoder( CODEC_ID_MSMPEG4 );
p_vdec->psz_namecodec = "MS MPEG-4/divx"; p_vdec->psz_namecodec = "MS MPEG-4/divx";
...@@ -407,7 +351,7 @@ static int InitThread( videodec_thread_t *p_vdec ) ...@@ -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->width = p_vdec->format.i_width;
p_vdec->p_context->height = p_vdec->format.i_height; 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) if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
{ {
...@@ -420,18 +364,37 @@ static int InitThread( videodec_thread_t *p_vdec ) ...@@ -420,18 +364,37 @@ static int InitThread( videodec_thread_t *p_vdec )
intf_WarnMsg( 1, "vdec info: ffmpeg codec (%s) started", intf_WarnMsg( 1, "vdec info: ffmpeg codec (%s) started",
p_vdec->psz_namecodec ); 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 ); vlc_mutex_lock( &p_vout_bank->lock );
if( p_vout_bank->i_count != 0 ) if( p_vout_bank->i_count != 0 )
{ {
vlc_mutex_unlock( &p_vout_bank->lock ); vlc_mutex_unlock( &p_vout_bank->lock );
vout_DestroyThread( p_vout_bank->pp_vout[ 0 ], NULL ); vout_DestroyThread( p_vout_bank->pp_vout[ 0 ], NULL );
vlc_mutex_lock( &p_vout_bank->lock ); vlc_mutex_lock( &p_vout_bank->lock );
p_vout_bank->i_count--; 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 ); vlc_mutex_unlock( &p_vout_bank->lock );
__PACKET_REINIT( p_vdec );
return( 0 ); return( 0 );
} }
...@@ -472,98 +435,38 @@ static void EndThread( videodec_thread_t *p_vdec ) ...@@ -472,98 +435,38 @@ static void EndThread( videodec_thread_t *p_vdec )
static void DecodeThread( 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_gotpicture;
int b_convert;
mtime_t i_pts;
AVPicture avpicture; /* ffmpeg picture */ AVPicture avpicture; /* ffmpeg picture */
u32 i_chroma; picture_t *p_pic; /* videolan picture */
picture_t *p_picture; /* videolan picture */
/* we have to get a frame stored in a pes /* we have to get a frame stored in a pes
give it to ffmpeg decoder give it to ffmpeg decoder
and send the image to the output */ and send the image to the output */
/* when we have the first image we create the video output */
i_pts = 0 ; __GetFrame( p_vdec );
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;}
i_len = avcodec_decode_video( p_vdec->p_context,
&avpicture,
&b_gotpicture,
p_vdec->p_buff,
p_vdec->i_data_size);
if( i_len < 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 );
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 ) ) ) i_status = avcodec_decode_video( p_vdec->p_context,
&avpicture,
&b_gotpicture,
p_vdec->p_framedata,
p_vdec->i_framesize);
__NextFrame( p_vdec );
if( i_status < 0 )
{ {
b_convert = 1; intf_WarnMsg( 2, "vdec error: cannot decode one frame (%d bytes)",
i_chroma = FOURCC_I420; p_vdec->i_framesize );
return;
} }
else if( !b_gotpicture )
{ {
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 ) /* Send decoded frame to 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, while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
0, /* ??? */
0, /* ??? */
0) ) /* ??? */
== NULL )
{ {
if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error ) 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 ) ...@@ -572,43 +475,28 @@ static void DecodeThread( videodec_thread_t *p_vdec )
msleep( VOUT_OUTMEM_SLEEP ); 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 )
{
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 */
}
else
{ {
__ConvertAVPictureToPicture( &avpicture, p_picture ); 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 ))
{
break;
}
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++ )
{
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_DatePicture( p_vdec->p_vout, p_pic, p_vdec->i_pts);
vout_DisplayPicture( p_vdec->p_vout, p_picture ); vout_DisplayPicture( p_vdec->p_vout, p_pic );
return; return;
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ffmpeg_vdec.h: video decoder using ffmpeg library * ffmpeg_vdec.h: video decoder using ffmpeg library
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * 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> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -47,11 +47,10 @@ typedef struct videodec_thread_s ...@@ -47,11 +47,10 @@ typedef struct videodec_thread_s
AVCodecContext context, *p_context; AVCodecContext context, *p_context;
AVCodec *p_codec; AVCodec *p_codec;
vout_thread_t *p_vout; vout_thread_t *p_vout;
int i_aspect;
u32 i_chroma;
char *psz_namecodec; char *psz_namecodec;
/* private */ /* private */
data_packet_t *p_data; mtime_t i_pts;
byte_t *p_buff; int i_framesize;
int i_data_size; byte_t *p_framedata;
} videodec_thread_t; } 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