XVideo optimisation patch

Shane Harper shanegh at optusnet.com.au
Sat May 12 15:50:24 CEST 2001


This patch:
 . removes a redundant memcpy of the YUV data to be displayed. (YUV data is
   now stored directly into the Shm segment which the X server will display.)
 . fixes a bug with toggling full-screen display (flag wasn't being cleared).

Unfortunately vlc will seg-fault on exit (when Xvideo module is used). I'm
not sure why. I might investigate the problem in the next few days (I don't 
have much time to work on it at the moment.)

Apart from the problem when exiting, it appears stable (I've had no other
problems with it). I hope someone will commit it into the CVS repository.


Shane.

-- Attached file included as plaintext by Listar --
-- File: vlc-xvideo-optimisation-patch

Index: include/modules.h
===================================================================
RCS file: /var/cvs/videolan/vlc/include/modules.h,v
retrieving revision 1.23
diff -u -r1.23 modules.h
--- include/modules.h	2001/05/06 04:32:02	1.23
+++ include/modules.h	2001/05/12 13:33:52
@@ -147,6 +147,10 @@
             void ( * pf_display )    ( struct vout_thread_s * );
             void ( * pf_setpalette ) ( struct vout_thread_s *, u16 *red,
                                        u16 *green, u16 *blue, u16 *transp );
+            int  ( * pf_createYUVbuf)( struct vout_thread_s *p_vout,
+                                        int i_buffer, int i_type,
+                                        int i_width, int i_height );
+                            /* pf_createYUVbuf is described in video_output.h */
         } vout;
 
         /* Motion compensation plugin */
Index: include/video_output.h
===================================================================
RCS file: /var/cvs/videolan/vlc/include/video_output.h,v
retrieving revision 1.60
diff -u -r1.60 video_output.h
--- include/video_output.h	2001/05/06 18:32:30	1.60
+++ include/video_output.h	2001/05/12 13:33:54
@@ -203,6 +203,13 @@
     void             ( *pf_display )    ( struct vout_thread_s * );
     void             ( *pf_setpalette ) ( struct vout_thread_s *, u16 *red,
                                           u16 *green, u16 *blue, u16 *transp );
+    int              ( * pf_createYUVbuf )( struct vout_thread_s *,
+                                            int i_picture, int i_type,
+                                            int i_width, int i_height );
+                    /* *pf_createYUVbuf is used to create a buffer to store the
+                     * YUV data to be displayed.  If a buffer numbered
+                     * "i_buffer" already exists, it'll be destroyed before the
+                     * new buffer is created. */
 
     /* Pictures and rendering properties */
     boolean_t           b_grayscale;           /* color or grayscale display */
@@ -233,7 +240,7 @@
     subpicture_t        p_subpicture[VOUT_MAX_PICTURES];      /* subpictures */
     int                 i_pictures;                     /* current heap size */
     vout_yuv_t          yuv;                           /* translation tables */
-    picture_t *         p_rendered_pic;  /* picture currently being rendered */
+    int                 i_pic_idx;       /* picture currently being rendered */
 
     /* Bitmap fonts */
     p_vout_font_t       p_default_font;                      /* default font */
Index: plugins/sdl/vout_sdl.c
===================================================================
RCS file: /var/cvs/videolan/vlc/plugins/sdl/vout_sdl.c,v
retrieving revision 1.51
diff -u -r1.51 vout_sdl.c
--- plugins/sdl/vout_sdl.c	2001/05/07 04:42:42	1.51
+++ plugins/sdl/vout_sdl.c	2001/05/12 13:33:59
@@ -174,8 +174,6 @@
     p_vout->p_sys->b_cursor_autohidden = 0;
     p_vout->p_sys->i_lastmoved = mdate();
 
-    p_vout->b_fullscreen = main_GetIntVariable( VOUT_FULLSCREEN_VAR,
-                                VOUT_FULLSCREEN_DEFAULT );
     p_vout->p_sys->b_overlay = main_GetIntVariable( VOUT_OVERLAY_VAR,
                                 VOUT_OVERLAY_DEFAULT );
     p_vout->p_sys->i_width = main_GetIntVariable( VOUT_WIDTH_VAR, 
@@ -537,17 +535,16 @@
         }
         else
         {
-            /*
-             * p_vout->p_rendered_pic->p_y/u/v contains the YUV buffers to
-             * render 
-             */
+            const picture_t *p_rendered_pic = &p_vout->p_picture[p_vout->i_pic_idx];
+                  /* p_rendered_pic->p_y/u/v contains the YUV data to display */
+
             /* TODO: support for streams other than 4:2:0 */
             /* create the overlay if necessary */
             if( p_vout->p_sys->p_overlay == NULL )
             {
                 p_vout->p_sys->p_overlay = SDL_CreateYUVOverlay( 
-                                             p_vout->p_rendered_pic->i_width, 
-                                             p_vout->p_rendered_pic->i_height,
+                                             p_rendered_pic->i_width, 
+                                             p_rendered_pic->i_height,
                                              SDL_YV12_OVERLAY, 
                                              p_vout->p_sys->p_display
                                            );
@@ -560,17 +557,17 @@
             /* copy the data into video buffers */
             /* Y first */
             memcpy(p_vout->p_sys->p_overlay->pixels[0],
-                   p_vout->p_rendered_pic->p_y,
+                   p_rendered_pic->p_y,
                    p_vout->p_sys->p_overlay->h *
                    p_vout->p_sys->p_overlay->pitches[0]);
             /* then V */
             memcpy(p_vout->p_sys->p_overlay->pixels[1],
-                   p_vout->p_rendered_pic->p_v,
+                   p_rendered_pic->p_v,
                    p_vout->p_sys->p_overlay->h *
                    p_vout->p_sys->p_overlay->pitches[1] / 2);
             /* and U */
             memcpy(p_vout->p_sys->p_overlay->pixels[2],
-                   p_vout->p_rendered_pic->p_u,
+                   p_rendered_pic->p_u,
                    p_vout->p_sys->p_overlay->h *
                    p_vout->p_sys->p_overlay->pitches[2] / 2);
 
Index: plugins/x11/vout_x11.c
===================================================================
RCS file: /var/cvs/videolan/vlc/plugins/x11/vout_x11.c,v
retrieving revision 1.24
diff -u -r1.24 vout_x11.c
--- plugins/x11/vout_x11.c	2001/05/07 03:14:09	1.24
+++ plugins/x11/vout_x11.c	2001/05/12 13:34:03
@@ -212,9 +212,6 @@
     }
     p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
 
-    p_vout->b_fullscreen
-        = main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
-
     /* Spawn base window - this window will include the video output window,
      * but also command buttons, subtitles and other indicators */
 
Index: plugins/x11/vout_xvideo.c
===================================================================
RCS file: /var/cvs/videolan/vlc/plugins/x11/vout_xvideo.c,v
retrieving revision 1.16
diff -u -r1.16 vout_xvideo.c
--- plugins/x11/vout_xvideo.c	2001/05/07 04:42:42	1.16
+++ plugins/x11/vout_xvideo.c	2001/05/12 13:34:06
@@ -85,7 +85,7 @@
 {
     /* User settings */
 #if 0
-    /* this plugin (currently) requires the SHM Ext... */
+    /* this module (currently) requires the SHM Ext... */
     boolean_t           b_shm;               /* shared memory extension flag */
 #endif
 
@@ -101,14 +101,8 @@
 
     /* Display buffers and shared memory information */
     /* Note: only 1 buffer... Xv ext does double buffering. */
-    XvImage *           p_xvimage;
-    int                 i_image_width;
-    int                 i_image_height;
-                                /* i_image_width & i_image_height reflect the
-                                 * size of the XvImage. They are used by
-                                 * vout_Display() to check if the image to be
-                                 * displayed can use the current XvImage. */
-    XShmSegmentInfo     shm_info;       /* shared memory zone information */
+    XvImage *           p_xvimage[VOUT_MAX_PICTURES];
+    XShmSegmentInfo     shm_info[VOUT_MAX_PICTURES];       /* shared memory zone information */
 
     /* X11 generic properties */
     Atom                wm_protocols;
@@ -153,10 +147,11 @@
 static int  vout_Manage    ( vout_thread_t * );
 static void vout_Display   ( vout_thread_t * );
 static void vout_SetPalette( vout_thread_t *, u16 *, u16 *, u16 *, u16 * );
+static int  vout_CreateYUVbuf( vout_thread_t *, int i_picture, int type,
+                                int width, int height);
 
 static int  XVideoCreateWindow       ( vout_thread_t * );
 static void XVideoDestroyWindow      ( vout_thread_t *p_vout );
-static int  XVideoUpdateImgSizeIfRequired( vout_thread_t *p_vout );
 static int  XVideoCreateShmImage     ( Display* dpy, int xv_port,
                                        XvImage **pp_xvimage,
                                        XShmSegmentInfo *p_shm_info,
@@ -173,7 +168,6 @@
 static void XVideoOutputCoords       ( const picture_t *, const boolean_t,
                                        const int, const int,
                                        int *, int *, int *, int * );
-static void XVideoDisplay            ( vout_thread_t * );
 
 /*****************************************************************************
  * Functions exported as capabilities. They are declared as static so that
@@ -189,6 +183,7 @@
     p_function_list->functions.vout.pf_manage     = vout_Manage;
     p_function_list->functions.vout.pf_display    = vout_Display;
     p_function_list->functions.vout.pf_setpalette = vout_SetPalette;
+    p_function_list->functions.vout.pf_createYUVbuf = vout_CreateYUVbuf;
 }
 
 /*****************************************************************************
@@ -238,9 +233,6 @@
     }
     p_vout->p_sys->i_screen = DefaultScreen( p_vout->p_sys->p_display );
 
-    p_vout->b_fullscreen
-        = main_GetIntVariable( VOUT_FULLSCREEN_VAR, VOUT_FULLSCREEN_DEFAULT );
-    
     if( !XVideoCheckForXv( p_vout->p_sys->p_display ) )
     {
         intf_ErrMsg( "vout error: no XVideo extension" );
@@ -283,26 +275,29 @@
  *****************************************************************************/
 static int vout_Init( vout_thread_t *p_vout )
 {
+    int i;
+
 #ifdef SYS_DARWIN1_3
     /* FIXME : As of 2001-03-16, XFree4 for MacOS X does not support Xshm. */
     p_vout->p_sys->b_shm = 0;
 #endif
     p_vout->b_need_render = 0;
-    p_vout->p_sys->i_image_width = p_vout->p_sys->i_image_height = 0;
+
+    for (i = 0; i<VOUT_MAX_PICTURES; ++i)
+        p_vout->p_sys->p_xvimage[i] = NULL;
 
     return( 0 );
 }
 
 /*****************************************************************************
  * vout_End: terminate XVideo video thread output method
- *****************************************************************************
- * Destroy the XvImage. It is called at the end of the thread, but also each
- * time the image is resized.
  *****************************************************************************/
 static void vout_End( vout_thread_t *p_vout )
 {
-    XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage,
-                           &p_vout->p_sys->shm_info );
+    int i;
+    for (i = 0; i<VOUT_MAX_PICTURES; ++i)
+        XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage[i],
+                               &p_vout->p_sys->shm_info[i] );
 }
 
 /*****************************************************************************
@@ -494,11 +489,11 @@
         if( xevent.type == Expose )
         {
             if( ((XExposeEvent *)&xevent)->count == 0 )
-                /* (if this is the last a collection of expose events...) */
+                /* (if this is the last of a collection of expose events...) */
                 if( p_main->p_intf->p_input )
                     if( PAUSE_S ==
                             p_main->p_intf->p_input->stream.control.i_status )
-                        XVideoDisplay( p_vout );
+                        vout_Display( p_vout );
         }
     }
         
@@ -537,6 +532,7 @@
             free( p_vout->p_sys );
             return( 1 );
         }
+        p_vout->i_changes &= ~VOUT_FULLSCREEN_CHANGE;
     }
 
     
@@ -550,11 +546,8 @@
      */
     if( p_vout->i_changes & VOUT_SIZE_CHANGE )
     {
-        intf_DbgMsg( "vout: resizing window" );
         p_vout->i_changes &= ~VOUT_SIZE_CHANGE;
-        /* Nothing to do here...
-         * vout_Display() detects size changes of the image to be displayed and
-         * re-creates the XvImage.*/
+        /* Nothing to do here. (Size of images to display has changed.) */
         intf_Msg( "vout: video display resized (%dx%d)",
                   p_vout->i_width, p_vout->i_height );
     }
@@ -575,40 +568,55 @@
  *****************************************************************************
  * This function sends the currently rendered image to X11 server.
  * (The Xv extension takes care of "double-buffering".)
+ * The image is scaled to fit in the output window (and to have the correct
+ * aspect ratio).
  *****************************************************************************/
 static void vout_Display( vout_thread_t *p_vout )
 {
-    boolean_t b_draw = 1;
-    int i_size = p_vout->p_rendered_pic->i_width *
-                   p_vout->p_rendered_pic->i_height;
-
-    if( XVideoUpdateImgSizeIfRequired( p_vout ) )
-        return;
+    const picture_t *p_rendered_pic = &p_vout->p_picture[p_vout->i_pic_idx];
 
-    switch( p_vout->p_rendered_pic->i_type )
+    switch( p_rendered_pic->i_type )
     {
     case YUV_422_PICTURE:
         intf_ErrMsg( "vout error: YUV_422_PICTURE not (yet) supported" );
-        b_draw = 0;
-        break;
+        return;
 
     case YUV_444_PICTURE:
         intf_ErrMsg( "vout error: YUV_444_PICTURE not (yet) supported" );
-        b_draw = 0;
-        break;
+        return;
 
     case YUV_420_PICTURE:
-        memcpy( p_vout->p_sys->p_xvimage->data,
-                p_vout->p_rendered_pic->p_y, i_size );
-        memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ),
-                p_vout->p_rendered_pic->p_v, i_size / 4 );
-        memcpy( p_vout->p_sys->p_xvimage->data + ( i_size ) + ( i_size / 4 ),
-                p_vout->p_rendered_pic->p_u, i_size / 4 );
         break;
+
+    default:
+        intf_ErrMsg( "vout error: picture type %d not (yet) supported",
+                        p_rendered_pic->i_type );
+        return;
     }
+
+    {
+    int     i_dest_width, i_dest_height, i_dest_x, i_dest_y;
+
+    if( !p_vout->p_sys->p_xvimage[p_vout->i_pic_idx] ) return;
+
+    XVideoOutputCoords( p_rendered_pic, p_vout->b_scale,
+                        p_vout->p_sys->i_window_width,
+                        p_vout->p_sys->i_window_height,
+                        &i_dest_x, &i_dest_y,
+                        &i_dest_width, &i_dest_height);
+
+    XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->xv_port,
+                   p_vout->p_sys->yuv_window, p_vout->p_sys->gc,
+                   p_vout->p_sys->p_xvimage[p_vout->i_pic_idx],
+                   0 /*src_x*/, 0 /*src_y*/,
+                   p_rendered_pic->i_width,
+                   p_rendered_pic->i_height,
+                   0 /*dest_x*/, 0 /*dest_y*/, i_dest_width, i_dest_height,
+                   True );
 
-    if( b_draw )
-        XVideoDisplay( p_vout );
+     XMoveResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
+             i_dest_x, i_dest_y, i_dest_width, i_dest_height );
+    }
 }
 
 static void vout_SetPalette( p_vout_thread_t p_vout,
@@ -616,56 +624,53 @@
 {
     return;
 }
-
-/* following functions are local */
 
-/*****************************************************************************
- * XVideoUpdateImgSizeIfRequired 
- *****************************************************************************
- * This function checks to see if the image to be displayed is of a different
- * size to the last image displayed. If so, the old shm block must be
- * destroyed and a new one created.
- * Note: the "image size" is the size of the image to be passed to the Xv
- * extension (which is probably different to the size of the output window).
- *****************************************************************************/
-static int XVideoUpdateImgSizeIfRequired( vout_thread_t *p_vout )
+static int  vout_CreateYUVbuf( vout_thread_t *p_vout, int i_picture, int i_type,
+                                int i_width, int i_height )
 {
-    int i_img_width         = p_vout->p_rendered_pic->i_width;
-    int i_img_height        = p_vout->p_rendered_pic->i_height;
+    picture_t *p_pic = &p_vout->p_picture[i_picture];
 
-    if( p_vout->p_sys->i_image_width != i_img_width
-            || p_vout->p_sys->i_image_height != i_img_height )
+    if( p_vout->p_sys->p_xvimage[i_picture] )
     {
-        p_vout->p_sys->i_image_width  = i_img_width;
-        p_vout->p_sys->i_image_height = i_img_height;
-
-        /* Destroy XvImage to change its size */
-        vout_End( p_vout );
-            /* Note: vout_End does nothing if no XvImage to destroy. */
+        XVideoDestroyShmImage( p_vout, p_vout->p_sys->p_xvimage[i_picture],
+                                &p_vout->p_sys->shm_info[i_picture]);
+        p_vout->p_sys->p_xvimage[i_picture] = NULL;
+    }
 
-        /* Create XvImage using XShm extension */
-        if( XVideoCreateShmImage( p_vout->p_sys->p_display,
-                                  p_vout->p_sys->xv_port,
-                                  &p_vout->p_sys->p_xvimage,
-                                  &p_vout->p_sys->shm_info,
-                                  i_img_width, i_img_height ) )
+    switch( i_type )
+    {
+        case YUV_420_PICTURE:
         {
-            intf_ErrMsg( "vout: failed to create xvimage." );
-            p_vout->p_sys->i_image_width = 0;
-            return( 1 );
+            XVideoCreateShmImage( p_vout->p_sys->p_display,
+                                  p_vout->p_sys->xv_port,
+                                  &p_vout->p_sys->p_xvimage[i_picture],
+                                  &p_vout->p_sys->shm_info[i_picture],
+                                  i_width, i_height );
+            p_pic->p_data = p_vout->p_sys->p_xvimage[i_picture]->data;
+
+            p_pic->p_y = p_pic->p_data;
+            p_pic->p_v = p_pic->p_data +i_height*i_width;
+            p_pic->p_u = p_pic->p_data +i_height*i_width*5/4;
         }
-
+        break;
+        default:
+            intf_ErrMsg( "error: picture type %d not handled by xvideo module",
+                    i_type );
+            return 1;
+    }
+#if 0
         /* Set bytes per line and initialize buffers */
         p_vout->i_bytes_per_line =
             (p_vout->p_sys->p_xvimage->data_size) /
             (p_vout->p_sys->p_xvimage->height);
 
         /* vout_SetBuffers( p_vout, p_vout->p_sys->p_xvimage->data ); */
-    }
-
-    return( 0 );
+#endif
+    return 0;
 }
 
+/* following functions are local */
+
 /*****************************************************************************
  * XVideoCheckForXv: check for the XVideo extension
  *****************************************************************************/
@@ -930,14 +935,12 @@
 /*****************************************************************************
  * XVideoDestroyShmImage
  *****************************************************************************
- * Destroy XImage AND associated data. Detach shared memory segment from
- * server and process, then free it. If pointer is NULL, the image won't be
- * destroyed (see vout_ManageOutputMethod())
+ * Destroy XvImage. Detach shared memory segment from server and process, then
+ * free it. If pointer is NULL, the image won't be destroyed.
  *****************************************************************************/
 static void XVideoDestroyShmImage( vout_thread_t *p_vout, XvImage *p_xvimage,
                                    XShmSegmentInfo *p_shm_info )
 {
-    /* If pointer is NULL, do nothing */
     if( p_xvimage == NULL )
     {
         return;
@@ -1037,8 +1040,8 @@
     }
 }
 
-/* This based on some code in SetBufferPicture... At the moment it's only
- * used by the xvideo plugin, but others may want to use it. */
+/* This is based on some code in SetBufferPicture...
+ * XXX should be using a common function. */
 static void XVideoOutputCoords( const picture_t *p_pic, const boolean_t scale,
                                 const int win_w, const int win_h,
                                 int *dx, int *dy, int *w, int *h)
@@ -1160,40 +1163,6 @@
     return( xv_port );
 }
 
-
-/*****************************************************************************
- * XVideoDisplay: display image
- *****************************************************************************
- * This function displays the image stored in p_vout->p_sys->p_xvimage.
- * The image is scaled to fit in the output window (and to have the correct
- * aspect ratio).
- *****************************************************************************/
-static void XVideoDisplay( vout_thread_t *p_vout )
-{
-    int     i_dest_width, i_dest_height, i_dest_x, i_dest_y;
-
-    if( !p_vout->p_sys->p_xvimage ) return;
-
-    XVideoOutputCoords( p_vout->p_rendered_pic, p_vout->b_scale,
-                        p_vout->p_sys->i_window_width,
-                        p_vout->p_sys->i_window_height,
-                        &i_dest_x, &i_dest_y,
-                        &i_dest_width, &i_dest_height);
-
-    XvShmPutImage( p_vout->p_sys->p_display, p_vout->p_sys->xv_port,
-                   p_vout->p_sys->yuv_window, p_vout->p_sys->gc,
-                   p_vout->p_sys->p_xvimage,
-                   0 /*src_x*/, 0 /*src_y*/,
-                   p_vout->p_rendered_pic->i_width,
-                   p_vout->p_rendered_pic->i_height,
-                   0 /*dest_x*/, 0 /*dest_y*/, i_dest_width, i_dest_height,
-                   True );
-
-     XResizeWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
-             i_dest_width, i_dest_height );
-     XMoveWindow( p_vout->p_sys->p_display, p_vout->p_sys->yuv_window,
-             i_dest_x, i_dest_y );
-}
 
 #if 0
 /*****************************************************************************
Index: src/misc/modules.c
===================================================================
RCS file: /var/cvs/videolan/vlc/src/misc/modules.c,v
retrieving revision 1.30
diff -u -r1.30 modules.c
--- src/misc/modules.c	2001/05/07 03:14:09	1.30
+++ src/misc/modules.c	2001/05/12 13:34:13
@@ -419,6 +419,11 @@
         return( -1 );
     }
 
+    /* Initialise function ptrs to NULL. (If a function ptr is left NULL then
+     * the module is unable to supply that function and a "default" could be
+     * used instead.) */
+    memset( &p_module->p_functions, 0, sizeof(p_module_functions_t) );
+
     /* We need to fill these since they may be needed by CallSymbol() */
     p_module->is.plugin.psz_filename = psz_filename;
     p_module->is.plugin.handle = handle;
Index: src/video_output/video_output.c
===================================================================
RCS file: /var/cvs/videolan/vlc/src/video_output/video_output.c,v
retrieving revision 1.128
diff -u -r1.128 video_output.c
--- src/video_output/video_output.c	2001/05/08 20:38:25	1.128
+++ src/video_output/video_output.c	2001/05/12 13:34:15
@@ -2,7 +2,7 @@
  * video_output.c : video output thread
  * This module describes the programming interface for video output threads.
  * It includes functions allowing to open a new thread, send pictures to a
- * thread, and destroy a previously oppened video output thread.
+ * thread, and destroy a previously opened video output thread.
  *****************************************************************************
  * Copyright (C) 2000 VideoLAN
  * $Id: video_output.c,v 1.128 2001/05/08 20:38:25 sam Exp $
@@ -57,6 +57,8 @@
 /*****************************************************************************
  * Local prototypes
  *****************************************************************************/
+static int      CreateYUV_Buffer  ( vout_thread_t *, int i_picture,
+                                    int i_type, int i_width, int i_height );
 static int      BinaryLog         ( u32 i );
 static void     MaskToShift       ( int *pi_left, int *pi_right, u32 i_mask );
 static int      InitThread        ( vout_thread_t *p_vout );
@@ -152,6 +154,8 @@
     p_vout->pf_manage     = f.pf_manage;
     p_vout->pf_display    = f.pf_display;
     p_vout->pf_setpalette = f.pf_setpalette;
+    p_vout->pf_createYUVbuf = ( f.pf_createYUVbuf != NULL )
+                                ? f.pf_createYUVbuf : &CreateYUV_Buffer;
 #undef f
 
     if( p_vout->pf_setpalette == NULL )
@@ -586,6 +590,7 @@
     vlc_mutex_unlock( &p_vout->picture_lock );
 }
 
+
 /*****************************************************************************
  * vout_CreatePicture: allocate a picture in the video output heap.
  *****************************************************************************
@@ -598,9 +603,8 @@
                                int i_width, int i_height )
 {
     int         i_picture;                                  /* picture index */
-    int         i_chroma_width = 0;                          /* chroma width */
-    picture_t * p_free_picture = NULL;                 /* first free picture */
-    picture_t * p_destroyed_picture = NULL;       /* first destroyed picture */
+    int         i_free_picture = -1;
+    int         i_destroyed_picture = -1;
 
     /* Get lock */
     vlc_mutex_lock( &p_vout->picture_lock );
@@ -613,15 +617,14 @@
         if( p_vout->p_picture[i_picture].i_status == DESTROYED_PICTURE )
         {
             /* Picture is marked for destruction, but is still allocated - note
-             * that if width and type are the same for two pictures, chroma_width
-             * should also be the same */
-            if( (p_vout->p_picture[i_picture].i_type           == i_type)   &&
-                (p_vout->p_picture[i_picture].i_height         == i_height) &&
-                (p_vout->p_picture[i_picture].i_width          == i_width) )
+             * that if width and type are the same for two pictures,
+             * chroma_width should also be the same */
+            if( (p_vout->p_picture[i_picture].i_type    == i_type)   &&
+                (p_vout->p_picture[i_picture].i_height  == i_height) &&
+                (p_vout->p_picture[i_picture].i_width   == i_width) )
             {
-                /* Memory size do match : memory will not be reallocated, and function
-                 * can end immediately - this is the best possible case, since no
-                 * memory allocation needs to be done */
+                /* Memory size do match: We can reuse buffer. This is the best
+                 * possible case: No memory allocation needs to be done */
                 p_vout->p_picture[i_picture].i_status = RESERVED_PICTURE;
                 p_vout->i_pictures++;
 #ifdef TRACE_VOUT
@@ -631,67 +634,48 @@
                 vlc_mutex_unlock( &p_vout->picture_lock );
                 return( &p_vout->p_picture[i_picture] );
             }
-            else if( p_destroyed_picture == NULL )
+            else if( i_destroyed_picture == -1 )
             {
                 /* Memory size do not match, but picture index will be kept in
                  * case no other place are left */
-                p_destroyed_picture = &p_vout->p_picture[i_picture];
+                i_destroyed_picture = i_picture;
             }
         }
-        else if( (p_free_picture == NULL) &&
+        else if( (i_free_picture == -1) &&
                  (p_vout->p_picture[i_picture].i_status == FREE_PICTURE ))
         {
             /* Picture is empty and ready for allocation */
-            p_free_picture = &p_vout->p_picture[i_picture];
+            i_free_picture = i_picture;
         }
     }
 
-    /* If no free picture is available, use a destroyed picture */
-    if( (p_free_picture == NULL) && (p_destroyed_picture != NULL ) )
-    {
-        /* No free picture or matching destroyed picture has been found, but
-         * a destroyed picture is still avalaible */
-        free( p_destroyed_picture->p_data );
-        p_free_picture = p_destroyed_picture;
-    }
+    i_picture = i_free_picture != -1 ? i_free_picture
+        :( i_destroyed_picture != -1 ? i_destroyed_picture : -1 );
 
     /*
      * Prepare picture
      */
-    if( p_free_picture != NULL )
+    if( i_picture != -1 )
     {
-        /* Allocate memory */
+        picture_t * p_free_picture = &p_vout->p_picture[i_picture];
+
+        /* set p_free_picture->i_chroma_width */
         switch( i_type )
         {
-        case YUV_420_PICTURE:        /* YUV 420: 1,1/4,1/4 samples per pixel */
-            i_chroma_width = i_width / 2;
-            p_free_picture->p_data = malloc( i_height * i_chroma_width * 3 * sizeof( yuv_data_t ) );
-            p_free_picture->p_y = (yuv_data_t *)p_free_picture->p_data;
-            p_free_picture->p_u = (yuv_data_t *)p_free_picture->p_data +i_height*i_chroma_width*4/2;
-            p_free_picture->p_v = (yuv_data_t *)p_free_picture->p_data +i_height*i_chroma_width*5/2;
-            break;
-        case YUV_422_PICTURE:        /* YUV 422: 1,1/2,1/2 samples per pixel */
-            i_chroma_width = i_width / 2;
-            p_free_picture->p_data = malloc( i_height * i_chroma_width * 4 * sizeof( yuv_data_t ) );
-            p_free_picture->p_y = (yuv_data_t *)p_free_picture->p_data;
-            p_free_picture->p_u = (yuv_data_t *)p_free_picture->p_data +i_height*i_chroma_width*2;
-            p_free_picture->p_v = (yuv_data_t *)p_free_picture->p_data +i_height*i_chroma_width*3;
-            break;
-        case YUV_444_PICTURE:            /* YUV 444: 1,1,1 samples per pixel */
-            i_chroma_width = i_width;
-            p_free_picture->p_data = malloc( i_height * i_chroma_width * 3 * sizeof( yuv_data_t ) );
-            p_free_picture->p_y = (yuv_data_t *)p_free_picture->p_data;
-            p_free_picture->p_u = (yuv_data_t *)p_free_picture->p_data +i_height*i_chroma_width;
-            p_free_picture->p_v = (yuv_data_t *)p_free_picture->p_data +i_height*i_chroma_width*2;
-            break;
-#ifdef DEBUG
-        default:
-            intf_ErrMsg("error: unknown picture type %d", i_type );
-            p_free_picture->p_data   =  NULL;
-            break;
-#endif
+            case YUV_420_PICTURE:
+            case YUV_422_PICTURE:
+                p_free_picture->i_chroma_width = i_width / 2;
+                break;
+            case YUV_444_PICTURE:
+                p_free_picture->i_chroma_width = i_width;
+                break;
+            default:
+                p_free_picture->i_chroma_width = 0;
         }
 
+        (p_vout->pf_createYUVbuf)( p_vout, i_picture, i_type,
+                                    i_width, i_height );
+
         if( p_free_picture->p_data != NULL )
         {
             /* Copy picture information, set some default values */
@@ -700,9 +684,8 @@
             p_free_picture->i_matrix_coefficients       = 1;
             p_free_picture->i_width                     = i_width;
             p_free_picture->i_height                    = i_height;
-            p_free_picture->i_chroma_width              = i_chroma_width;
             p_free_picture->i_size                      = i_width * i_height;
-            p_free_picture->i_chroma_size               = i_chroma_width
+            p_free_picture->i_chroma_size               = p_free_picture->i_chroma_width
                                                             * i_height;
             p_free_picture->i_display_horizontal_offset = 0;
             p_free_picture->i_display_vertical_offset   = 0;
@@ -717,7 +700,7 @@
             /* Memory allocation failed : set picture as empty */
             p_free_picture->i_type   =  EMPTY_PICTURE;
             p_free_picture->i_status =  FREE_PICTURE;
-            p_free_picture =            NULL;
+            /*p_free_picture =            NULL;*/
             intf_ErrMsg( "vout error: picture allocation returned %s",
                          strerror( ENOMEM ) );
         }
@@ -869,6 +852,50 @@
 /* following functions are local */
 
 /*****************************************************************************
+ * CreateYUV_Buffer : allocate a buffer to store YUV data
+ *****************************************************************************
+ * If there is an existing buffer it is freed before the new buffer is created.
+ *****************************************************************************/
+static int  CreateYUV_Buffer( vout_thread_t *p_vout, int i_picture, int i_type,
+                                int i_width, int i_height )
+{
+    picture_t *p_pic = &p_vout->p_picture[i_picture];
+    const int i_chroma_width = p_pic->i_chroma_width;
+
+    if( p_pic->i_status != FREE_PICTURE )
+        free( p_pic->p_data );
+
+    switch( i_type )
+    {
+    case YUV_420_PICTURE:        /* YUV 420: 1,1/4,1/4 samples per pixel */
+        p_pic->p_data = malloc( i_height * i_chroma_width * 3 * sizeof( yuv_data_t ) );
+        p_pic->p_y = (yuv_data_t *)p_pic->p_data;
+        p_pic->p_u = (yuv_data_t *)p_pic->p_data +i_height*i_chroma_width*4/2;
+        p_pic->p_v = (yuv_data_t *)p_pic->p_data +i_height*i_chroma_width*5/2;
+        break;
+    case YUV_422_PICTURE:        /* YUV 422: 1,1/2,1/2 samples per pixel */
+        p_pic->p_data = malloc( i_height * i_chroma_width * 4 * sizeof( yuv_data_t ) );
+        p_pic->p_y = (yuv_data_t *)p_pic->p_data;
+        p_pic->p_u = (yuv_data_t *)p_pic->p_data +i_height*i_chroma_width*2;
+        p_pic->p_v = (yuv_data_t *)p_pic->p_data +i_height*i_chroma_width*3;
+        break;
+    case YUV_444_PICTURE:            /* YUV 444: 1,1,1 samples per pixel */
+        p_pic->p_data = malloc( i_height * i_chroma_width * 3 * sizeof( yuv_data_t ) );
+        p_pic->p_y = (yuv_data_t *)p_pic->p_data;
+        p_pic->p_u = (yuv_data_t *)p_pic->p_data +i_height*i_chroma_width;
+        p_pic->p_v = (yuv_data_t *)p_pic->p_data +i_height*i_chroma_width*2;
+        break;
+    default:
+#ifdef DEBUG
+        intf_ErrMsg("error: unknown picture type %d", i_type );
+        p_pic->p_data   =  NULL;
+#endif
+        return 1;
+    }
+    return 0;
+}
+
+/*****************************************************************************
  * BinaryLog: computes the base 2 log of a binary value
  *****************************************************************************
  * This functions is used by MaskToShift, to get a bit index from a binary
@@ -984,6 +1011,7 @@
     boolean_t       b_display;                               /* display flag */
 
     picture_t *     p_pic;                                /* picture pointer */
+    int             i_pic_index;
 
     subpicture_t *  p_subpic;                          /* subpicture pointer */
     subpicture_t *  p_ephemer;        /* youngest ephemer subpicture pointer */
@@ -1007,6 +1035,7 @@
     {
         /* Initialize loop variables */
         p_pic =         NULL;
+        i_pic_index =   -1;
         p_subpic =      NULL;
         p_ephemer =     NULL;
         ephemer_date =  0;
@@ -1032,6 +1061,7 @@
               (p_vout->p_picture[i_index].date < display_date) ) )
             {
                 p_pic = &p_vout->p_picture[i_index];
+                i_pic_index = i_index;
                 display_date = p_pic->date;
             }
         }
@@ -1179,7 +1209,7 @@
         {
             b_display = p_vout->b_active;
             p_vout->last_display_date = display_date;
-            p_vout->p_rendered_pic = p_pic;
+            p_vout->i_pic_idx = i_pic_index;
 
             /* Set picture dimensions and clear buffer */
             SetBufferPicture( p_vout, p_pic );





More information about the vlc-devel mailing list