mirror of
https://code.videolan.org/videolan/vlc
synced 2024-10-03 01:31:53 +02:00
* All: simplifications.
This commit is contained in:
parent
e3c0699664
commit
bc57d09cc9
@ -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 );
|
||||
@ -167,7 +165,7 @@ static pes_packet_t *__PES_GET( decoder_fifo_t *p_fifo )
|
||||
p_pes = p_fifo->p_first;
|
||||
|
||||
vlc_mutex_unlock( &p_fifo->data_lock );
|
||||
|
||||
|
||||
return( p_pes );
|
||||
}
|
||||
/* free the first pes and go to next */
|
||||
@ -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;
|
||||
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 )
|
||||
{
|
||||
while( ( !p_pes->i_nb_data )||( !p_pes->i_pes_size ) )
|
||||
{
|
||||
__PES_NEXT( p_vdec->p_fifo );
|
||||
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;
|
||||
}
|
||||
/* 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_data = p_vdec->p_data->p_next;
|
||||
if( !p_vdec->p_data )
|
||||
{
|
||||
__PES_NEXT( p_vdec->p_fifo );
|
||||
if( p_vdec->p_fifo->b_die )
|
||||
{
|
||||
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 ) );
|
||||
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 )
|
||||
static __inline__ void __NextFrame( videodec_thread_t *p_vdec )
|
||||
{
|
||||
if( p_vdec->i_data_size <= 0 )
|
||||
pes_packet_t *p_pes;
|
||||
|
||||
p_pes = __PES_GET( p_vdec->p_fifo );
|
||||
if( p_pes->i_nb_data != 1 )
|
||||
{
|
||||
__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;
|
||||
u8 *p_dest,*p_src;
|
||||
|
||||
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++ )
|
||||
{
|
||||
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,18 +364,37 @@ 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 )
|
||||
{
|
||||
vlc_mutex_unlock( &p_vout_bank->lock );
|
||||
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->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
|
||||
__GetFrame( p_vdec );
|
||||
|
||||
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 )
|
||||
{
|
||||
__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 ) ) )
|
||||
{
|
||||
b_convert = 1;
|
||||
i_chroma = FOURCC_I420;
|
||||
intf_WarnMsg( 2, "vdec error: cannot decode one frame (%d bytes)",
|
||||
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 )
|
||||
{
|
||||
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 )
|
||||
{
|
||||
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_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;
|
||||
|
Loading…
Reference in New Issue
Block a user