* modules/codec/ffmpeg/*: modified the ffmpeg video codec to use direct
authorGildas Bazin <gbazin@videolan.org>
Tue, 5 Nov 2002 10:07:56 +0000 (10:07 +0000)
committerGildas Bazin <gbazin@videolan.org>
Tue, 5 Nov 2002 10:07:56 +0000 (10:07 +0000)
   rendering when possible.
   Use BITMAPINFOHEADER from include/codecs.h + got rid of Little Endian
   translations that were already done in the demux.
* modules/demux/avi/* modules/demux/asf/*: Use BITMAPINFOHEADER from
   include/codecs.h.

modules/codec/ffmpeg/ffmpeg.c
modules/codec/ffmpeg/ffmpeg.h
modules/codec/ffmpeg/video.c
modules/codec/ffmpeg/video.h
modules/demux/asf/libasf.h
modules/demux/avi/avi.c
modules/demux/avi/libavi.c
modules/demux/avi/libavi.h

index 63005fe..725a667 100644 (file)
@@ -2,7 +2,7 @@
  * ffmpeg.c: video decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: ffmpeg.c,v 1.13 2002/10/28 22:23:23 gbazin Exp $
+ * $Id: ffmpeg.c,v 1.14 2002/11/05 10:07:56 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>                                              /* getpid() */
-#endif
-
-#include <errno.h>
 #include <string.h>
 
 #ifdef HAVE_SYS_TIMES_H
index bead0fb..d97eef6 100644 (file)
@@ -2,7 +2,7 @@
  * ffmpeg_vdec.h: video decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: ffmpeg.h,v 1.7 2002/10/28 06:26:11 fenrir Exp $
+ * $Id: ffmpeg.h,v 1.8 2002/11/05 10:07:56 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
@@ -21,6 +21,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+#include "codecs.h"                                      /* BITMAPINFOHEADER */
 
 
 #define DECODER_THREAD_COMMON \
index cb82f2a..99a2ecd 100644 (file)
@@ -2,9 +2,10 @@
  * video.c: video decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: video.c,v 1.1 2002/10/28 06:26:11 fenrir Exp $
+ * $Id: video.c,v 1.2 2002/11/05 10:07:56 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
+ *          Gildas Bazin <gbazin@netcourrier.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
 #include <vlc/decoder.h>
 #include <vlc/input.h>
 
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>                                              /* getpid() */
-#endif
-
-#include <errno.h>
 #include <string.h>
 
 #ifdef HAVE_SYS_TIMES_H
 #   include <sys/times.h>
 #endif
 
-#include "avcodec.h"                                            /* ffmpeg */
+#include "avcodec.h"                                               /* ffmpeg */
 
 #include "postprocessing/postprocessing.h"
 
 #include "ffmpeg.h"
 #include "video.h"
 
-/*
+/*****************************************************************************
  * Local prototypes
- */
-int      E_( InitThread_Video )   ( vdec_thread_t * );
-void     E_( EndThread_Video )    ( vdec_thread_t * );
-void     E_( DecodeThread_Video ) ( vdec_thread_t * );
+ *****************************************************************************/
+static void ffmpeg_CopyPicture( picture_t *, AVPicture *, vdec_thread_t * );
+static void ffmpeg_PostProcPicture( vdec_thread_t *, picture_t * );
+static int  ffmpeg_GetFrameBuf( struct AVCodecContext *, int, int, int );
 
 /* FIXME FIXME some of them are wrong */
 static int i_ffmpeg_PixFmtToChroma[] =
@@ -71,6 +67,10 @@ static int i_ffmpeg_PixFmtToChroma[] =
     VLC_FOURCC('I','4','4','4'), 0
 };
 
+/*****************************************************************************
+ * Local Functions
+ *****************************************************************************/
+
 static inline u32 ffmpeg_PixFmtToChroma( int i_ffmpegchroma )
 {
     if( ++i_ffmpegchroma > 7 )
@@ -99,47 +99,6 @@ static inline int ffmpeg_FfAspect( int i_width, int i_height, int i_ffaspect )
     }
 }
 
-
-/*****************************************************************************
- * locales Functions
- *****************************************************************************/
-
-static void ffmpeg_ParseBitMapInfoHeader( bitmapinfoheader_t *p_bh, 
-                                          u8 *p_data )
-{
-    p_bh->i_size          = GetDWLE( p_data );
-    p_bh->i_width         = GetDWLE( p_data + 4 );
-    p_bh->i_height        = GetDWLE( p_data + 8 );
-    p_bh->i_planes        = GetWLE( p_data + 12 );
-    p_bh->i_bitcount      = GetWLE( p_data + 14 );
-    p_bh->i_compression   = GetDWLE( p_data + 16 );
-    p_bh->i_sizeimage     = GetDWLE( p_data + 20 );
-    p_bh->i_xpelspermeter = GetDWLE( p_data + 24 );
-    p_bh->i_ypelspermeter = GetDWLE( p_data + 28 );
-    p_bh->i_clrused       = GetDWLE( p_data + 32 );
-    p_bh->i_clrimportant  = GetDWLE( p_data + 36 );
-
-    if( p_bh->i_size > 40 )
-    {
-        p_bh->i_data = p_bh->i_size - 40;
-        if( ( p_bh->p_data = malloc( p_bh->i_data ) ) )
-        {
-            memcpy( p_bh->p_data, p_data + 40, p_bh->i_data );
-        }
-        else
-        {
-            p_bh->i_data = 0;
-        }
-    }
-    else
-    {
-        p_bh->i_data = 0;
-        p_bh->p_data = NULL;
-    } 
-
-}
-
-
 /* Check if we have a Vout with good parameters */
 static int ffmpeg_CheckVout( vout_thread_t *p_vout,
                              int i_width,
@@ -156,7 +115,7 @@ static int ffmpeg_CheckVout( vout_thread_t *p_vout,
         /* we will try to make conversion */
         i_chroma = VLC_FOURCC('I','4','2','0');
     } 
-    
+
     if( ( p_vout->render.i_width != i_width )||
         ( p_vout->render.i_height != i_height )||
         ( p_vout->render.i_chroma != i_chroma )||
@@ -172,7 +131,6 @@ static int ffmpeg_CheckVout( vout_thread_t *p_vout,
 }
 
 /* Return a Vout */
-
 static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
                                          int i_width,
                                          int i_height,
@@ -196,7 +154,7 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
     } 
 
     i_aspect = ffmpeg_FfAspect( i_width, i_height, i_aspect );
-    
+
     /* Spawn a video output if there is none. First we look for our children,
      * then we look for any other vout that might be available. */
     p_vout = vlc_object_find( p_vdec->p_fifo, VLC_OBJECT_VOUT,
@@ -230,12 +188,12 @@ static vout_thread_t *ffmpeg_CreateVout( vdec_thread_t *p_vdec,
     if( p_vout == NULL )
     {
         msg_Dbg( p_vdec->p_fifo, "no vout present, spawning one" );
-    
+
         p_vout = vout_CreateThread( p_vdec->p_fifo,
                                     i_width, i_height,
                                     i_chroma, i_aspect );
     }
-    
+
     return( p_vout );
 }
 
@@ -251,14 +209,14 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
     u8 *p_src, *p_dst;
     u8 *p_plane[3];
     int i_plane;
-    
+
     int i_stride, i_lines;
     int i_height, i_width;
     int i_y, i_x;
-    
+
     i_height = p_vdec->p_context->height;
     i_width  = p_vdec->p_context->width;
-    
+
     p_dst = p_pic->p[0].p_pixels;
     p_src  = p_avpicture->data[0];
 
@@ -269,7 +227,7 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
         p_dst += p_pic->p[0].i_pitch;
         p_src += p_avpicture->linesize[0];
     }
-    
+
     /* process each plane in a temporary buffer */
     for( i_plane = 1; i_plane < 3; i_plane++ )
     {
@@ -290,12 +248,10 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
             }
             p_dst[2 * i_stride - 2] = p_src[i_x];
             p_dst[2 * i_stride - 1] = p_src[i_x];
-                           
+
             p_dst += 4 * i_stride; /* process the next even lines */
             p_src += i_stride;
         }
-
-
     }
 
     for( i_plane = 1; i_plane < 3; i_plane++ )
@@ -312,7 +268,7 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
             {
                 p_dst[i_x] = ( p_src[i_x] + p_src[i_x + 4*i_stride])/2;
             }
-                           
+
             p_dst += 4 * i_stride; /* process the next odd lines */
             p_src += 4 * i_stride;
         }
@@ -324,7 +280,6 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
        temporaries buffers */
     for( i_plane = 1; i_plane < 3; i_plane++ )
     {
-
         int i_size; 
         p_src  = p_plane[i_plane];
         p_dst = p_pic->p[i_plane].p_pixels;
@@ -338,75 +293,8 @@ static void ffmpeg_ConvertPictureI410toI420( picture_t *p_pic,
         }
         free( p_plane[i_plane] );
     }
-
 }
 
-static void ffmpeg_GetPicture( picture_t *p_pic,
-                               AVPicture *p_avpicture,
-                               vdec_thread_t   *p_vdec )
-{
-    int i_plane; 
-    int i_size;
-    int i_line;
-
-    u8  *p_dst;
-    u8  *p_src;
-    int i_src_stride;
-    int i_dst_stride;
-
-    if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
-    {
-        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
-        {
-            p_src  = p_avpicture->data[i_plane];
-            p_dst = p_pic->p[i_plane].p_pixels;
-            i_src_stride = p_avpicture->linesize[i_plane];
-            i_dst_stride = p_pic->p[i_plane].i_pitch;
-            
-            i_size = __MIN( i_src_stride, i_dst_stride );
-            for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
-            {
-                p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
-                p_src += i_src_stride;
-                p_dst += i_dst_stride;
-            }
-        }
-        if( ( p_vdec->i_pp_mode )&&
-            ( ( p_vdec->p_vout->render.i_chroma == 
-                    VLC_FOURCC( 'I','4','2','0' ) )||
-              ( p_vdec->p_vout->render.i_chroma == 
-                    VLC_FOURCC( 'Y','V','1','2' ) ) ) )
-        {
-            /* Make postproc */
-#if LIBAVCODEC_BUILD > 4313
-            p_vdec->p_pp->pf_postprocess( p_pic,
-                                          p_vdec->p_context->quant_store, 
-                                          p_vdec->p_context->qstride,
-                                          p_vdec->i_pp_mode );
-#endif
-        }
-    }
-    else
-    {
-        /* we need to convert to I420 */
-        switch( p_vdec->p_context->pix_fmt )
-        {
-#if LIBAVCODEC_BUILD >= 4615
-            case( PIX_FMT_YUV410P ):
-                ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
-                break;
-#endif            
-            default:
-                p_vdec->p_fifo->b_error = 1;
-                break;
-        }
-
-    }
-  
-}
-
-
-
 /*****************************************************************************
  *
  * Functions that initialize, decode and end the decoding process
@@ -425,26 +313,24 @@ static void ffmpeg_GetPicture( picture_t *p_pic,
  * flag are not modified inside this function.
  *
  * ffmpeg codec will be open, some memory allocated. But Vout is not yet
- *   open (done after the first decoded frame)
+ * open (done after the first decoded frame)
  *****************************************************************************/
 int E_( InitThread_Video )( vdec_thread_t *p_vdec )
 {
     int i_tmp;
-    
+
     if( p_vdec->p_fifo->p_demux_data )
     {
-        ffmpeg_ParseBitMapInfoHeader( &p_vdec->format, 
-                                      (u8*)p_vdec->p_fifo->p_demux_data );
+        p_vdec->p_format = (BITMAPINFOHEADER *)p_vdec->p_fifo->p_demux_data;
     }
     else
     {
         msg_Warn( p_vdec->p_fifo, "display informations missing" );
     }
 
-    
     /* ***** Fill p_context with init values ***** */
-    p_vdec->p_context->width  = p_vdec->format.i_width;
-    p_vdec->p_context->height = p_vdec->format.i_height;
+    p_vdec->p_context->width  = p_vdec->p_format->biWidth;
+    p_vdec->p_context->height = p_vdec->p_format->biHeight;
     
     /*  ***** Get configuration of ffmpeg plugin ***** */
 #if LIBAVCODEC_BUILD >= 4611
@@ -460,11 +346,24 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
         p_vdec->p_context->flags|= CODEC_FLAG_GRAY;
     }
 #endif
+
     p_vdec->b_hurry_up = config_GetInt(p_vdec->p_fifo, "ffmpeg-hurry-up");
-    
 
-    /* ***** Open the codec ***** */ 
-    if (avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0)
+    p_vdec->b_direct_rendering = 0;
+#if LIBAVCODEC_BUILD > 4615
+    if( (p_vdec->p_codec->capabilities & CODEC_CAP_DR1)
+        && (p_vdec->p_context->pix_fmt != PIX_FMT_YUV410P) )
+    {
+        msg_Dbg( p_vdec->p_fifo, "using direct rendering" );
+        p_vdec->b_direct_rendering = 1;
+        p_vdec->p_context->flags|= CODEC_FLAG_EMU_EDGE | CODEC_FLAG_DR1; 
+        p_vdec->p_context->get_buffer_callback = ffmpeg_GetFrameBuf;
+        p_vdec->p_context->opaque = p_vdec;
+    }
+#endif
+
+    /* ***** Open the codec ***** */
+    if( avcodec_open(p_vdec->p_context, p_vdec->p_codec) < 0 )
     {
         msg_Err( p_vdec->p_fifo, "cannot open codec (%s)",
                                  p_vdec->psz_namecodec );
@@ -477,7 +376,7 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
     }
 
     /* ***** init this codec with special data ***** */
-    if( p_vdec->format.i_data )
+    if( p_vdec->p_format->biSize > sizeof(BITMAPINFOHEADER) )
     {
         AVPicture avpicture;
         int b_gotpicture;
@@ -487,8 +386,9 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
             case( CODEC_ID_MPEG4 ):
                 avcodec_decode_video( p_vdec->p_context, &avpicture, 
                                       &b_gotpicture,
-                                      p_vdec->format.p_data,
-                                      p_vdec->format.i_data );
+                                      (void *)&p_vdec->p_format[1],
+                                      p_vdec->p_format->biSize
+                                        - sizeof(BITMAPINFOHEADER) );
                 break;
             default:
                 if( p_vdec->p_fifo->i_fourcc == FOURCC_MP4S ||
@@ -496,11 +396,13 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
                     p_vdec->p_fifo->i_fourcc == FOURCC_M4S2 ||
                     p_vdec->p_fifo->i_fourcc == FOURCC_m4s2 )
                 {
-                    p_vdec->p_context->extradata_size = p_vdec->format.i_data;
-                    p_vdec->p_context->extradata = malloc( p_vdec->format.i_data );
+                    p_vdec->p_context->extradata_size =
+                        p_vdec->p_format->biSize - sizeof(BITMAPINFOHEADER);
+                    p_vdec->p_context->extradata =
+                        malloc( p_vdec->p_context->extradata_size );
                     memcpy( p_vdec->p_context->extradata,
-                            p_vdec->format.p_data,
-                            p_vdec->format.i_data );
+                            &p_vdec->p_format[1],
+                            p_vdec->p_context->extradata_size );
                 }
 
                 break;
@@ -523,7 +425,7 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
         p_vdec->i_pp_mode |= PP_DERING_Y;
     if( config_GetInt( p_vdec->p_fifo, "ffmpeg-dr-c" ) )
         p_vdec->i_pp_mode |= PP_DERING_C;
-    
+
     if( ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-q" ) > 0 )||
         ( config_GetInt( p_vdec->p_fifo, "ffmpeg-pp-auto" )  )||
         ( p_vdec->i_pp_mode != 0 ) )
@@ -543,7 +445,7 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
 //            case( CODEC_ID_H263P ): I don't use it up to now
             case( CODEC_ID_H263I ):
                 /* Ok we can make postprocessing :)) */
-               /* first try to get a postprocess module */
+                /* first try to get a postprocess module */
 #if LIBAVCODEC_BUILD > 4613
                 p_vdec->p_pp = vlc_object_create( p_vdec->p_fifo,
                                                   sizeof( postprocessing_t ) );
@@ -592,9 +494,11 @@ int E_( InitThread_Video )( vdec_thread_t *p_vdec )
     return( 0 );
 }
 
-
 /*****************************************************************************
  * DecodeThread: Called for decode one frame
+ *****************************************************************************
+ * We have to get a frame stored in a pes, give it to ffmpeg decoder and send
+ * the image to the output.
  *****************************************************************************/
 void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
 {
@@ -603,16 +507,12 @@ void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
     int     i_status;
     int     b_drawpicture;
     int     b_gotpicture;
-    AVPicture avpicture;  /* ffmpeg 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 */ 
+    AVPicture avpicture;                                   /* ffmpeg picture */
+    picture_t *p_pic;                                    /* videolan picture */
 
     /* TODO implement it in a better way */
     /* A good idea could be to decode all I pictures and see for the other */
-    if( ( p_vdec->b_hurry_up )&&
-        ( p_vdec->i_frame_late > 4 ) )
+    if( ( p_vdec->b_hurry_up )&& ( p_vdec->i_frame_late > 4 ) )
     {
 #if LIBAVCODEC_BUILD > 4603
         b_drawpicture = 0;
@@ -683,7 +583,6 @@ void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
                                      p_vdec->p_buffer,
                                      i_frame_size );
 
-
     if( i_status < 0 )
     {
         msg_Warn( p_vdec->p_fifo, "cannot decode one frame (%d bytes)",
@@ -702,44 +601,55 @@ void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
         p_vdec->i_frame_late = 0;
     }
 
-    if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture)
+    if( !b_gotpicture || avpicture.linesize[0] == 0 || !b_drawpicture )
     {
         return;
     }
-    
-    /* Check our vout */
-    if( !ffmpeg_CheckVout( p_vdec->p_vout,
+
+    if( !p_vdec->b_direct_rendering )
+    {
+        /* Check our vout */
+        if( !ffmpeg_CheckVout( p_vdec->p_vout,
                            p_vdec->p_context->width,
                            p_vdec->p_context->height,
                            p_vdec->p_context->aspect_ratio_info,
                            ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
-    {
-        p_vdec->p_vout = 
-          ffmpeg_CreateVout( p_vdec,
-                             p_vdec->p_context->width,
-                             p_vdec->p_context->height,
-                             p_vdec->p_context->aspect_ratio_info,
-                             ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt));
-        if( !p_vdec->p_vout )
         {
-            msg_Err( p_vdec->p_fifo, "cannot create vout" );
-            p_vdec->p_fifo->b_error = 1; /* abort */
-            return;
+            p_vdec->p_vout = ffmpeg_CreateVout( p_vdec,
+                           p_vdec->p_context->width,
+                           p_vdec->p_context->height,
+                           p_vdec->p_context->aspect_ratio_info,
+                           ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt) );
+            if( !p_vdec->p_vout )
+            {
+                msg_Err( p_vdec->p_fifo, "cannot create vout" );
+                p_vdec->p_fifo->b_error = 1; /* abort */
+                return;
+            }
         }
-    }
 
-    /* Get a new picture */
-    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 )
+        /* Get a new picture */
+        while( !(p_pic = vout_CreatePicture( p_vdec->p_vout, 0, 0, 0 ) ) )
         {
-            return;
+            if( p_vdec->p_fifo->b_die || p_vdec->p_fifo->b_error )
+            {
+                return;
+            }
+            msleep( VOUT_OUTMEM_SLEEP );
         }
-        msleep( VOUT_OUTMEM_SLEEP );
+
+        /* fill p_picture_t from avpicture, do I410->I420 if needed */
+        ffmpeg_CopyPicture( p_pic, &avpicture, p_vdec );
     }
-    /* fill p_picture_t from avpicture, do I410->I420 if needed
-       and do post-processing if requested */    
-    ffmpeg_GetPicture( p_pic, &avpicture, p_vdec );
+    else
+    {
+#if LIBAVCODEC_BUILD > 4615
+        p_pic = (picture_t *)p_vdec->p_context->dr_opaque_frame;
+#endif
+    }
+
+    /* Do post-processing if requested */
+    ffmpeg_PostProcPicture( p_vdec, p_pic );
 
     /* FIXME correct avi and use i_dts */
 
@@ -750,7 +660,6 @@ void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
     return;
 }
 
-
 /*****************************************************************************
  * EndThread: thread destruction
  *****************************************************************************
@@ -759,7 +668,6 @@ void  E_( DecodeThread_Video )( vdec_thread_t *p_vdec )
  *****************************************************************************/
 void E_( EndThread_Video )( vdec_thread_t *p_vdec )
 {
-    
     if( p_vdec->p_pp )
     {
         /* release postprocessing module */
@@ -774,7 +682,142 @@ void E_( EndThread_Video )( vdec_thread_t *p_vdec )
         vlc_object_detach( p_vdec->p_vout );
         vlc_object_attach( p_vdec->p_vout, p_vdec->p_fifo->p_vlc );
     }
+}
+
+/*****************************************************************************
+ * ffmpeg_CopyPicture: copy a picture from ffmpeg internal buffers to a
+ *                     picture_t structure (when not in direct rendering mode).
+ *****************************************************************************/
+static void ffmpeg_CopyPicture( picture_t *p_pic, AVPicture *p_avpicture,
+                                vdec_thread_t *p_vdec )
+{
+    int i_plane; 
+    int i_size;
+    int i_line;
+
+    u8  *p_dst;
+    u8  *p_src;
+    int i_src_stride;
+    int i_dst_stride;
+
+    if( ffmpeg_PixFmtToChroma( p_vdec->p_context->pix_fmt ) )
+    {
+        for( i_plane = 0; i_plane < p_pic->i_planes; i_plane++ )
+        {
+            p_src  = p_avpicture->data[i_plane];
+            p_dst = p_pic->p[i_plane].p_pixels;
+            i_src_stride = p_avpicture->linesize[i_plane];
+            i_dst_stride = p_pic->p[i_plane].i_pitch;
+
+            i_size = __MIN( i_src_stride, i_dst_stride );
+            for( i_line = 0; i_line < p_pic->p[i_plane].i_lines; i_line++ )
+            {
+                p_vdec->p_fifo->p_vlc->pf_memcpy( p_dst, p_src, i_size );
+                p_src += i_src_stride;
+                p_dst += i_dst_stride;
+            }
+        }
+    }
+    else
+    {
+        /* we need to convert to I420 */
+        switch( p_vdec->p_context->pix_fmt )
+        {
+#if LIBAVCODEC_BUILD >= 4615
+            case( PIX_FMT_YUV410P ):
+                ffmpeg_ConvertPictureI410toI420( p_pic, p_avpicture, p_vdec );
+                break;
+#endif            
+            default:
+                p_vdec->p_fifo->b_error = 1;
+                break;
+        }
+    }
+}
 
-    FREE( p_vdec->format.p_data );
+/*****************************************************************************
+ * ffmpeg_PostProcPicture: Postprocessing is done here.
+ *****************************************************************************/
+static void ffmpeg_PostProcPicture( vdec_thread_t *p_vdec, picture_t *p_pic )
+{
+#if LIBAVCODEC_BUILD > 4313
+    if( ( p_vdec->i_pp_mode )&&
+        ( ( p_vdec->p_vout->render.i_chroma == 
+            VLC_FOURCC( 'I','4','2','0' ) )||
+          ( p_vdec->p_vout->render.i_chroma == 
+            VLC_FOURCC( 'Y','V','1','2' ) ) ) )
+    {
+        /* Make postproc */
+        p_vdec->p_pp->pf_postprocess( p_pic,
+                                      p_vdec->p_context->quant_store, 
+                                      p_vdec->p_context->qstride,
+                                      p_vdec->i_pp_mode );
+    }
+#endif
 }
 
+/*****************************************************************************
+ * ffmpeg_GetFrameBuf: callback used by ffmpeg to get a frame buffer.
+ *                     (used for direct rendering)
+ *****************************************************************************/
+static int ffmpeg_GetFrameBuf( struct AVCodecContext *avctx, int width,
+                               int height, int pict_type )
+{
+#if LIBAVCODEC_BUILD > 4615
+    vdec_thread_t *p_vdec = (vdec_thread_t *)avctx->opaque;
+    picture_t *p_pic;
+
+    /* Check our vout */
+    if( !ffmpeg_CheckVout( p_vdec->p_vout,
+                           p_vdec->p_context->width,
+                           p_vdec->p_context->height,
+                           p_vdec->p_context->aspect_ratio_info,
+                           ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt)) )
+    {
+        p_vdec->p_vout = ffmpeg_CreateVout( p_vdec,
+                           p_vdec->p_context->width,
+                           p_vdec->p_context->height,
+                           p_vdec->p_context->aspect_ratio_info,
+                           ffmpeg_PixFmtToChroma(p_vdec->p_context->pix_fmt) );
+        if( !p_vdec->p_vout )
+        {
+            msg_Err( p_vdec->p_fifo, "cannot create vout" );
+            p_vdec->p_fifo->b_error = 1; /* abort */
+            return -1;
+        }
+    }
+
+    /* Get a new picture */
+    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 )
+        {
+            return -1;
+        }
+        msleep( VOUT_OUTMEM_SLEEP );
+    }
+
+    /* FIXME: we may have to use link/unlinkPicture to fully support streams
+     * with B FRAMES */
+
+    avctx->draw_horiz_band= NULL;
+    avctx->dr_buffer[0]= p_pic->p[0].p_pixels;
+    avctx->dr_buffer[1]= p_pic->p[1].p_pixels;
+    avctx->dr_buffer[2]= p_pic->p[2].p_pixels;
+
+    avctx->dr_stride   = p_pic->p[0].i_pitch;
+    avctx->dr_uvstride = p_pic->p[1].i_pitch;
+
+    avctx->dr_opaque_frame = p_pic;
+
+    /* FIXME: this variable is used to determine if a macro-block to be written
+     * can be skipped. The idea behind this is that if a macro-block hasn't
+     * changed and all the frame-buffers already have the value of this
+     * macro-block, then we can skip the writting.
+     * But currently we cannot ensure this is the case, so we decide to write
+     * everything. */
+    avctx->dr_ip_buffer_count = 999;
+
+    return 0;
+#endif
+}
index a46f610..bd1bdbc 100644 (file)
@@ -2,7 +2,7 @@
  * video.h: video decoder using ffmpeg library
  *****************************************************************************
  * Copyright (C) 1999-2001 VideoLAN
- * $Id: video.h,v 1.1 2002/10/28 06:26:11 fenrir Exp $
+ * $Id: video.h,v 1.2 2002/11/05 10:07:56 gbazin Exp $
  *
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  *
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
-
-/* for a video stream */
-typedef struct bitmapinfoheader_s
-{
-    u32 i_size; /* size of header */
-    u32 i_width;
-    u32 i_height;
-    u16 i_planes;
-    u16 i_bitcount;
-    u32 i_compression;
-    u32 i_sizeimage;
-    u32 i_xpelspermeter;
-    u32 i_ypelspermeter;
-    u32 i_clrused;
-    u32 i_clrimportant;
-
-    int i_data;
-    u8  *p_data;
-} bitmapinfoheader_t;
-
 typedef struct vdec_thread_s
 {
     DECODER_THREAD_COMMON
 
-    bitmapinfoheader_t  format;
+    BITMAPINFOHEADER    *p_format;
 
     vout_thread_t       *p_vout; 
 
@@ -53,14 +33,14 @@ typedef struct vdec_thread_s
     u32                 i_pp_mode; /* valid only with I420 and YV12 */
     postprocessing_t    *p_pp;
 
-
     /* for frame skipping algo */
-//    statistic_s statistic;
-
     int b_hurry_up;
     int i_frame_error;
     int i_frame_skip;
-    int i_frame_late;  /* how may frame decoded are in late */
+    int i_frame_late;  /* how many decoded frames are late */
+
+    /* for direct rendering */
+    int b_direct_rendering;
 
 } vdec_thread_t;
 
@@ -68,5 +48,3 @@ typedef struct vdec_thread_s
 int      E_( InitThread_Video )   ( vdec_thread_t * );
 void     E_( EndThread_Video )    ( vdec_thread_t * );
 void     E_( DecodeThread_Video ) ( vdec_thread_t * );
-
-
index a68c81f..6cca0d7 100644 (file)
@@ -2,7 +2,7 @@
  * libasf.h : 
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libasf.h,v 1.2 2002/10/21 09:18:37 fenrir Exp $
+ * $Id: libasf.h,v 1.3 2002/11/05 10:07:56 gbazin Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+#include "codecs.h"                        /* BITMAPINFOHEADER, WAVEFORMATEX */
+
 /*****************************************************************************
  * Structure needed for decoder
  *****************************************************************************/
-typedef struct bitmapinfoheader_s
-{
-    u32 i_size; /* size of header 40 + size of data follwoing this header */
-    u32 i_width;
-    u32 i_height;
-    u16 i_planes;
-    u16 i_bitcount;
-    u32 i_compression;
-    u32 i_sizeimage;
-    u32 i_xpelspermeter;
-    u32 i_ypelspermeter;
-    u32 i_clrused;
-    u32 i_clrimportant;
-} bitmapinfoheader_t;
-
-typedef struct waveformatex_s
-{
-    u16 i_format;
-    u16 i_channels;
-    u32 i_samplepersec;
-    u32 i_avgbytespersec;
-    u16 i_blockalign;
-    u16 i_bitspersample;
-    u16 i_size;          /* This give size of data 
-                            imediatly following this header. */
-} waveformatex_t;
-
 typedef struct guid_s
 {
     u32 v1; /* le */
index d2fcf8a..96fcebe 100644 (file)
@@ -2,7 +2,7 @@
  * avi.c : AVI file Stream input module for vlc
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: avi.c,v 1.8 2002/10/28 01:51:37 fenrir Exp $
+ * $Id: avi.c,v 1.9 2002/11/05 10:07:56 gbazin Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -937,17 +937,17 @@ static int AVIInit( vlc_object_t * p_this )
                 /* XXX quick hack for playing ffmpeg video, I don't know 
                     who is doing something wrong */
                 p_info->i_samplesize = 0;
-                p_info->i_fourcc = p_avi_strf_vids->i_compression;
+                p_info->i_fourcc = p_avi_strf_vids->p_bih->biCompression;
                 p_info->i_codec = 
                     AVI_FourccGetCodec( VIDEO_ES, p_info->i_fourcc );
                 i_init_size = p_avi_strf_vids->i_chunk_size;
                 p_init_data = p_avi_strf_vids->p_bih;
                 msg_Dbg( p_input, "stream[%d] video(%4.4s) %dx%d %dbpp %ffps",
                         i,
-                         (char*)&p_avi_strf_vids->i_compression,
-                         p_avi_strf_vids->i_width,
-                         p_avi_strf_vids->i_height,
-                         p_avi_strf_vids->i_bitcount,
+                         (char*)&p_avi_strf_vids->p_bih->biCompression,
+                         p_avi_strf_vids->p_bih->biWidth,
+                         p_avi_strf_vids->p_bih->biHeight,
+                         p_avi_strf_vids->p_bih->biBitCount,
                          (float)p_info->i_rate /
                              (float)p_info->i_scale );
                 break;
index b3eaa02..b9f01bc 100644 (file)
@@ -2,7 +2,7 @@
  * libavi.c : 
  *****************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libavi.c,v 1.3 2002/10/27 15:37:16 fenrir Exp $
+ * $Id: libavi.c,v 1.4 2002/11/05 10:07:56 gbazin Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -539,29 +539,29 @@ static int AVI_ChunkRead_strf( input_thread_t *p_input,
             break;
         case( AVIFOURCC_vids ):
             p_strh->strh.i_samplesize = 0; // XXX for ffmpeg avi file
-            AVI_READ4BYTES( p_chk->strf.vids.i_size );
-            AVI_READ4BYTES( p_chk->strf.vids.i_width );
-            AVI_READ4BYTES( p_chk->strf.vids.i_height );
-            AVI_READ2BYTES( p_chk->strf.vids.i_planes );
-            AVI_READ2BYTES( p_chk->strf.vids.i_bitcount );
-            AVI_READFOURCC( p_chk->strf.vids.i_compression );
-            AVI_READ4BYTES( p_chk->strf.vids.i_sizeimage );
-            AVI_READ4BYTES( p_chk->strf.vids.i_xpelspermeter );
-            AVI_READ4BYTES( p_chk->strf.vids.i_ypelspermeter );
-            AVI_READ4BYTES( p_chk->strf.vids.i_clrused );
-            AVI_READ4BYTES( p_chk->strf.vids.i_clrimportant );
             p_chk->strf.vids.p_bih = malloc( p_chk->common.i_chunk_size );
-            memcpy( p_chk->strf.vids.p_bih, 
-                    p_buff + 8, 
-                    p_chk->common.i_chunk_size );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSize );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biWidth );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biHeight );
+            AVI_READ2BYTES( p_chk->strf.vids.p_bih->biPlanes );
+            AVI_READ2BYTES( p_chk->strf.vids.p_bih->biBitCount );
+            AVI_READFOURCC( p_chk->strf.vids.p_bih->biCompression );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biSizeImage );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biXPelsPerMeter );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biYPelsPerMeter );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrUsed );
+            AVI_READ4BYTES( p_chk->strf.vids.p_bih->biClrImportant );
+            memcpy( &p_chk->strf.vids.p_bih[1],
+                    p_buff + sizeof(BITMAPINFOHEADER),
+                    p_chk->common.i_chunk_size - sizeof(BITMAPINFOHEADER) );
 #ifdef AVI_DEBUG
             msg_Dbg( p_input,
                      "strf: video:%c%c%c%c %dx%d planes:%d %dbpp",
-                     AVIFOURCC_PRINT( p_chk->strf.vids.i_compression ),
-                     p_chk->strf.vids.i_width,
-                     p_chk->strf.vids.i_height,
-                     p_chk->strf.vids.i_planes,
-                     p_chk->strf.vids.i_bitcount );
+                     AVIFOURCC_PRINT( p_chk->strf.vids.p_bih->biCompression ),
+                     p_chk->strf.vids.p_bih->biWidth,
+                     p_chk->strf.vids.p_bih->biHeight,
+                     p_chk->strf.vids.p_bih->biPlanes,
+                     p_chk->strf.vids.p_bih->biBitCount );
 #endif
             break;
         default:
index 4f5d62e..6ca10ed 100644 (file)
@@ -2,7 +2,7 @@
  * libavi.h : LibAVI library 
  ******************************************************************************
  * Copyright (C) 2001 VideoLAN
- * $Id: libavi.h,v 1.1 2002/10/15 00:56:43 fenrir Exp $
+ * $Id: libavi.h,v 1.2 2002/11/05 10:07:56 gbazin Exp $
  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  * 
  * This program is free software; you can redistribute it and/or modify
@@ -20,6 +20,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  *****************************************************************************/
 
+#include "codecs.h"                                      /* BITMAPINFOHEADER */
 
 /* flags for use in <dwFlags> in AVIFileHdr */
 #define AVIF_HASINDEX       0x00000010  /* Index at end of file? */
@@ -255,18 +256,7 @@ typedef struct avi_chunk_strf_auds_s
 typedef struct avi_chunk_strf_vids_s
 {
     AVI_CHUNK_COMMON
-    void *p_bih;    // bitmapinfoheader_t loaded from file
-    u32 i_size; /* size of header */
-    u32 i_width;
-    u32 i_height;
-    u16 i_planes;
-    u16 i_bitcount;
-    u32 i_compression;
-    u32 i_sizeimage;
-    u32 i_xpelspermeter;
-    u32 i_ypelspermeter;
-    u32 i_clrused;
-    u32 i_clrimportant;
+    BITMAPINFOHEADER *p_bih;
 } avi_chunk_strf_vids_t;
 
 typedef union avi_chunk_strf_u