]> git.sesse.net Git - vlc/blobdiff - modules/codec/xvid.c
* modules/gui/skins/src/*: oops, forgot to add a bunch of files.
[vlc] / modules / codec / xvid.c
index fa8b798d502697f067f7595d3bfaa2d1663e5859..ff2fda6daa715eb9ef980104e9e1bd92ae8d78a0 100644 (file)
@@ -2,15 +2,15 @@
  * xvid.c: a decoder for libxvidcore, the Xvid video codec
  *****************************************************************************
  * Copyright (C) 2002 VideoLAN
- * $Id: xvid.c,v 1.1 2002/11/05 22:53:21 sam Exp $
+ * $Id: xvid.c,v 1.5 2003/02/20 01:52:45 sigmunau Exp $
  *
  * Authors: Samuel Hocevar <sam@zoy.org>
- *      
+ *
  * 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
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
- * 
+ *
  * This program is distributed in the hope that it will be useful,
  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
@@ -48,12 +48,14 @@ vlc_module_begin();
     set_description( _("Xvid video decoder") );
     set_capability( "decoder", 50 );
     set_callbacks( OpenDecoder, NULL );
+    add_bool( "xvid-direct-render", 0, NULL, "direct rendering",
+              "Use libxvidcore's direct rendering feature.", VLC_TRUE );
 vlc_module_end();
 
 /*****************************************************************************
  * OpenDecoder: probe the decoder and return score
  *****************************************************************************
- * The fourcc format for DV is "dvsd"
+ * FIXME: find fourcc formats supported by xvid
  *****************************************************************************/
 static int OpenDecoder ( vlc_object_t *p_this )
 {
@@ -87,7 +89,9 @@ static int RunDecoder ( decoder_fifo_t *p_fifo )
     uint8_t *  p_buffer, * p_image;
     int        i_ret;
     int        i_width, i_height, i_chroma, i_aspect;
-    int        i_size, i_offset;
+    int        i_size, i_offset, i_image_size;
+
+    vlc_bool_t b_direct = config_GetInt( p_fifo, "xvid-direct-render" );
 
     if( InitBitstream( &bit_stream, p_fifo, NULL, NULL ) != VLC_SUCCESS )
     {
@@ -96,20 +100,28 @@ static int RunDecoder ( decoder_fifo_t *p_fifo )
         DecoderError( p_fifo );
         return VLC_EGENERIC;
     }
+    if( ( p_format = (BITMAPINFOHEADER *)p_fifo->p_bitmapinfoheader ) == NULL )
+    {
+        i_width  = 1;
+        i_height = 1;   // avoid segfault anyway it's wrong
+    }
+    else
+    {
+        /* Guess picture properties from the BIH */
+        i_width = p_format->biWidth;
+        i_height = p_format->biHeight;
+    }
 
-    p_format = (BITMAPINFOHEADER *)p_fifo->p_demux_data;
-
-    /* Guess picture properties from the BIH */
-    i_width = p_format->biWidth;
-    i_height = p_format->biHeight;
     i_chroma = VLC_FOURCC('Y','V','1','2');
     i_aspect = VOUT_ASPECT_FACTOR * i_width / i_height;
 
     /* XXX: Completely arbitrary buffer size */
     i_size = i_width * i_height / 4;
+    i_image_size = b_direct ? 0 : i_width * i_height * 4;
     i_offset = 0;
-    p_buffer = malloc( i_size + 4 * i_width * i_height );
-    p_image = p_buffer + 4 * i_width * i_height;
+
+    p_buffer = malloc( i_size + i_image_size );
+    p_image = p_buffer + i_size;
 
     if( !p_buffer )
     {
@@ -141,58 +153,27 @@ static int RunDecoder ( decoder_fifo_t *p_fifo )
 
     /* Spawn a video output if there is none. First we look amongst our
      * children, then we look for any other vout that might be available */
-    p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_CHILD );
-    if( !p_vout ) 
-    {
-        p_vout = vlc_object_find( p_fifo, VLC_OBJECT_VOUT, FIND_ANYWHERE );
-    }
-
-    if( p_vout )
-    {
-        if( p_vout->render.i_width != i_width
-         || p_vout->render.i_height != i_height
-         || p_vout->render.i_chroma != i_chroma
-         || p_vout->render.i_aspect != i_aspect )
-        {
-            /* We are not interested in this format, close this vout */
-            vlc_object_detach( p_vout );
-            vlc_object_release( p_vout );
-            vout_DestroyThread( p_vout );
-            p_vout = NULL;
-        }
-        else
-        {
-            /* This video output is cool! Hijack it. */
-            vlc_object_detach( p_vout );
-            vlc_object_attach( p_vout, p_fifo );
-            vlc_object_release( p_vout );
-        }
-    }
+    p_vout = vout_Request( p_fifo, NULL,
+                           i_width, i_height, i_chroma, i_aspect );
 
     if( !p_vout )
     {
-        msg_Dbg( p_fifo, "no vout present, spawning one" );
-
-        p_vout = vout_CreateThread( p_fifo,
-                                    i_width, i_height,
-                                    i_chroma, i_aspect );
-        if( !p_vout )
-        {
-            msg_Err( p_fifo, "could not spawn vout" );
-            p_fifo->b_error = VLC_TRUE;
-            xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
-            free( p_buffer );
-            CloseBitstream( &bit_stream );
-            DecoderError( p_fifo );
-            return VLC_EGENERIC;
-        }
+        msg_Err( p_fifo, "could not spawn vout" );
+        p_fifo->b_error = VLC_TRUE;
+        xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );
+        free( p_buffer );
+        CloseBitstream( &bit_stream );
+        DecoderError( p_fifo );
+        return VLC_EGENERIC;
     }
 
     /* Main loop */
     while( !p_fifo->b_die && !p_fifo->b_error )
     {
         XVID_DEC_FRAME xframe;
+        XVID_DEC_PICTURE xpic;
         mtime_t i_pts = 0;
+        picture_t *p_pic;
 
         GetChunk( &bit_stream, p_buffer + i_offset, i_size - i_offset );
 
@@ -214,33 +195,41 @@ static int RunDecoder ( decoder_fifo_t *p_fifo )
             break;
         }
 
+        while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
+        {
+            if( p_fifo->b_die || p_fifo->b_error )
+            {
+                break;
+            } 
+            msleep( VOUT_OUTMEM_SLEEP );
+        }
+
+        if( !p_pic )
+        {
+            break;
+        }
+
+        if( b_direct )
+        {
+            xpic.y = p_pic->p[0].p_pixels;
+            xpic.u = p_pic->p[1].p_pixels;
+            xpic.v = p_pic->p[2].p_pixels;
+            xpic.stride_y = p_pic->p[0].i_pitch;
+            xpic.stride_u = p_pic->p[1].i_pitch;
+            xpic.stride_v = p_pic->p[2].i_pitch;
+        }
+
         /* Decode the stuff */
         xframe.bitstream = p_buffer;
         xframe.length = i_size;
-        xframe.image = p_image;
+        xframe.image = b_direct ? (void*)&xpic : p_image;
         xframe.stride = i_width;
-        xframe.colorspace = XVID_CSP_YV12;
+        xframe.colorspace = b_direct ? XVID_CSP_EXTERN : XVID_CSP_YV12;
         i_ret = xvid_decore( p_xvid, XVID_DEC_DECODE, &xframe, NULL );
         /* FIXME: check i_ret */
 
-        if( p_vout )
+        if( !b_direct )
         {
-            picture_t *p_pic;
-
-            while( !(p_pic = vout_CreatePicture( p_vout, 0, 0, 0 ) ) )
-            {
-                if( p_fifo->b_die || p_fifo->b_error )
-                {
-                    break;
-                } 
-                msleep( VOUT_OUTMEM_SLEEP );
-            }
-
-            if( !p_pic )
-            {
-                break;
-            }
-
             /* TODO: use pf_memcpy when this is stable. */
             memcpy( p_pic->p[0].p_pixels,
                     p_image,
@@ -251,19 +240,18 @@ static int RunDecoder ( decoder_fifo_t *p_fifo )
             memcpy( p_pic->p[1].p_pixels,
                     p_image + i_width * i_height + i_width * i_height / 4,
                     i_width * i_height / 4 );
-
-            vout_DatePicture( p_vout, p_pic, i_pts );
-            vout_DisplayPicture( p_vout, p_pic );
         }
 
+        vout_DatePicture( p_vout, p_pic, i_pts );
+        vout_DisplayPicture( p_vout, p_pic );
+
         /* Move the remaining data. TODO: only do this when necessary. */
         memmove( p_buffer, p_buffer + xframe.length, i_size - xframe.length );
         i_offset = i_size - xframe.length;
     }
 
     /* Clean up everything */
-    vlc_object_detach( p_vout );
-    vout_DestroyThread( p_vout );
+    vout_Request( p_fifo, p_vout, 0, 0, 0, 0 );
 
     xvid_decore( p_xvid, XVID_DEC_DESTROY, NULL, NULL );