From bc57d09cc93c9546c7c5b655f1cccb9e8a6e384a Mon Sep 17 00:00:00 2001 From: Laurent Aimar Date: Sun, 12 May 2002 06:51:08 +0000 Subject: [PATCH] * All: simplifications. --- plugins/ffmpeg/ffmpeg.c | 314 +++++++++++++--------------------------- plugins/ffmpeg/ffmpeg.h | 11 +- 2 files changed, 106 insertions(+), 219 deletions(-) diff --git a/plugins/ffmpeg/ffmpeg.c b/plugins/ffmpeg/ffmpeg.c index 96056126cd..edaf220898 100644 --- a/plugins/ffmpeg/ffmpeg.c +++ b/plugins/ffmpeg/ffmpeg.c @@ -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 * @@ -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 ) + 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->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; -} - -static void __PACKET_NEXT( videodec_thread_t *p_vdec ) -{ + 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 ) -{ - 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; - - for( i_plane = 0; i_plane < __MIN(p_picture->i_planes, 3); i_plane++ ) + pes_packet_t *p_pes; + + p_pes = __PES_GET( p_vdec->p_fifo ); + if( p_pes->i_nb_data != 1 ) { - 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 - { - __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 ); + __GetFrame( p_vdec ); - 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; - 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; - } - - /* 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 ); - + return; + } - 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 ); - } + /* Send decoded frame to vout */ - 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 ) - { - /* 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 + for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ ) { - __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; } diff --git a/plugins/ffmpeg/ffmpeg.h b/plugins/ffmpeg/ffmpeg.h index 51c500b219..9c8d945c66 100644 --- a/plugins/ffmpeg/ffmpeg.h +++ b/plugins/ffmpeg/ffmpeg.h @@ -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 * @@ -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;