]> git.sesse.net Git - vlc/commitdiff
* All: simplifications.
authorLaurent Aimar <fenrir@videolan.org>
Sun, 12 May 2002 06:51:08 +0000 (06:51 +0000)
committerLaurent Aimar <fenrir@videolan.org>
Sun, 12 May 2002 06:51:08 +0000 (06:51 +0000)
plugins/ffmpeg/ffmpeg.c
plugins/ffmpeg/ffmpeg.h

index 96056126cd1776009ba115f8b22fda55242040e7..edaf220898b3810e1bbcdfa951452c6b25caf4e3 100644 (file)
@@ -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 )
+    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;
 }
index 51c500b2199cdd7cdec98b35a78ac1f181cadfb9..9c8d945c669e795043ea8a18232b58b562dd7f4e 100644 (file)
@@ -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;