From 7ae31f20547ba81787e3e4a3453f1abfa48bfc68 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Rafa=C3=ABl=20Carr=C3=A9?= <funman@videolan.org>
Date: Mon, 2 Jun 2008 14:09:29 +0200
Subject: [PATCH] Workaround broken picture_t refcounting and destruction

Prefer huge memory leaks over segmentation faults
---
 modules/codec/fake.c                   |    8 +++++---
 modules/codec/ffmpeg/video_filter.c    |    9 ++++++---
 modules/gui/skins2/src/file_bitmap.cpp |    3 ++-
 modules/stream_out/mosaic_bridge.c     |   15 ++++++++++-----
 modules/stream_out/transcode.c         |   27 ++++++++++++++++++---------
 modules/video_filter/deinterlace.c     |   10 ++++++----
 modules/video_filter/distort.c         |    4 ++--
 modules/video_filter/logo.c            |    3 ++-
 modules/video_filter/magnify.c         |    3 ++-
 modules/video_filter/mosaic.c          |   11 +++++++----
 modules/video_filter/rss.c             |    5 +++--
 modules/video_filter/rv32.c            |    3 ++-
 modules/video_filter/scale.c           |    3 ++-
 modules/video_filter/swscale/filter.c  |    3 ++-
 src/misc/image.c                       |    5 +++--
 src/video_output/vout_intf.c           |    6 ++++--
 16 files changed, 76 insertions(+), 42 deletions(-)

diff --git a/modules/codec/fake.c b/modules/codec/fake.c
index 5d0edc4..6bc15c6 100644
--- a/modules/codec/fake.c
+++ b/modules/codec/fake.c
@@ -222,7 +222,8 @@ static int OpenDecoder( vlc_object_t *p_this )
             }
             else
             {
-                p_old->pf_release( p_old );
+                if( p_old->pf_release )
+                    p_old->pf_release( p_old );
             }
         }
     }
@@ -259,7 +260,8 @@ static int OpenDecoder( vlc_object_t *p_this )
         }
         else
         {
-            p_old->pf_release( p_old );
+            if( p_old->pf_release )
+                p_old->pf_release( p_old );
         }
     }
 
@@ -309,6 +311,6 @@ static void CloseDecoder( vlc_object_t *p_this )
     decoder_t *p_dec = (decoder_t *)p_this;
     picture_t *p_image = (picture_t *)p_dec->p_sys;
 
-    if( p_image != NULL )
+    if( p_image && p_image->pf_release )
         p_image->pf_release( p_image );
 }
diff --git a/modules/codec/ffmpeg/video_filter.c b/modules/codec/ffmpeg/video_filter.c
index df180b0..7b18b0e 100644
--- a/modules/codec/ffmpeg/video_filter.c
+++ b/modules/codec/ffmpeg/video_filter.c
@@ -424,7 +424,8 @@ static picture_t *Process( filter_t *p_filter, picture_t *p_pic )
     if( !p_pic_dst )
     {
         msg_Warn( p_filter, "can't get output picture" );
-        p_pic->pf_release( p_pic );
+        if( p_pic->pf_release )
+            p_pic->pf_release( p_pic );
         return NULL;
     }
 
@@ -600,7 +601,8 @@ static picture_t *Process( filter_t *p_filter, picture_t *p_pic )
     p_pic_dst->b_progressive = p_pic->b_progressive;
     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
 
-    p_pic->pf_release( p_pic );
+    if( p_pic->pf_release )
+        p_pic->pf_release( p_pic );
     return p_pic_dst;
 }
 
@@ -690,6 +692,7 @@ static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
     p_pic_dst->b_progressive = VLC_TRUE;
     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
 
-    p_pic->pf_release( p_pic );
+    if( p_pic->pf_release )
+        p_pic->pf_release( p_pic );
     return p_pic_dst;
 }
diff --git a/modules/gui/skins2/src/file_bitmap.cpp b/modules/gui/skins2/src/file_bitmap.cpp
index b41a796..e4cc7bd 100644
--- a/modules/gui/skins2/src/file_bitmap.cpp
+++ b/modules/gui/skins2/src/file_bitmap.cpp
@@ -73,7 +73,8 @@ FileBitmap::FileBitmap( intf_thread_t *pIntf, image_handler_t *pImageHandler,
         pSrc += pPic->p->i_pitch - m_width * 4;
     }
 
-    pPic->pf_release( pPic );
+    if( pPic->pf_release )
+        pPic->pf_release( pPic );
     return;
 }
 
diff --git a/modules/stream_out/mosaic_bridge.c b/modules/stream_out/mosaic_bridge.c
index 0bea904..a994d7b 100644
--- a/modules/stream_out/mosaic_bridge.c
+++ b/modules/stream_out/mosaic_bridge.c
@@ -367,7 +367,8 @@ static int Del( sout_stream_t *p_stream, sout_stream_id_t *id )
     while ( p_es->p_picture )
     {
         picture_t *p_next = p_es->p_picture->p_next;
-        p_es->p_picture->pf_release( p_es->p_picture );
+        if( p_es->p_picture->pf_release )
+            p_es->p_picture->pf_release( p_es->p_picture );
         p_es->p_picture = p_next;
     }
 
@@ -473,7 +474,8 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
             if ( p_new_pic == NULL )
             {
                 msg_Err( p_stream, "image conversion failed" );
-                p_pic->pf_release( p_pic );
+                if( p_pic->pf_release )
+                    p_pic->pf_release( p_pic );
                 continue;
             }
         }
@@ -488,7 +490,8 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
                                   p_sys->p_decoder->fmt_out.video.i_aspect )
                     != VLC_SUCCESS )
             {
-                p_pic->pf_release( p_pic );
+                if( p_pic->pf_release )
+                    p_pic->pf_release( p_pic );
                 free( p_new_pic );
                 continue;
             }
@@ -503,7 +506,8 @@ static int Send( sout_stream_t *p_stream, sout_stream_id_t *id,
         p_new_pic->pf_release = ReleasePicture;
         p_new_pic->date = p_pic->date;
 
-        p_pic->pf_release( p_pic );
+        if( p_pic->pf_release )
+            p_pic->pf_release( p_pic );
         PushPicture( p_stream, p_new_pic );
     }
 
@@ -604,7 +608,8 @@ static picture_t *video_new_buffer( decoder_t *p_dec )
 
         for( i = 0; i < PICTURE_RING_SIZE; i++ )
         {
-            pp_ring[i]->pf_release( pp_ring[i] );
+            if( pp_ring[i]->pf_release )
+                pp_ring[i]->pf_release( pp_ring[i] );
             pp_ring[i] = NULL;
         }
 
diff --git a/modules/stream_out/transcode.c b/modules/stream_out/transcode.c
index b7208dd..b988339 100644
--- a/modules/stream_out/transcode.c
+++ b/modules/stream_out/transcode.c
@@ -2040,7 +2040,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
             {
                 msg_Dbg( p_stream, "late picture skipped ("I64Fd")",
                          current_date + 50000 - p_pic->date );
-                p_pic->pf_release( p_pic );
+                if( p_pic->pf_release )
+                    p_pic->pf_release( p_pic );
                 continue;
             }
         }
@@ -2071,7 +2072,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
                 msg_Dbg( p_stream, "dropping frame (%i)",
                          (int)(i_video_drift - i_master_drift) );
 #endif
-                p_pic->pf_release( p_pic );
+                if( p_pic->pf_release )
+                    p_pic->pf_release( p_pic );
                 continue;
             }
             else if( i_video_drift > i_master_drift + 50000 )
@@ -2088,7 +2090,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
         {
             if( transcode_video_encoder_open( p_stream, id ) != VLC_SUCCESS )
             {
-                p_pic->pf_release( p_pic );
+                if( p_pic->pf_release )
+                    p_pic->pf_release( p_pic );
                 transcode_video_close( p_stream, id );
                 id->b_transcode = VLC_FALSE;
                 return VLC_EGENERIC;
@@ -2185,7 +2188,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
                     vlc_object_detach( id->pp_filter[id->i_filter] );
                     vlc_object_destroy( id->pp_filter[id->i_filter] );
 
-                    p_pic->pf_release( p_pic );
+                    if( p_pic->pf_release )
+                        p_pic->pf_release( p_pic );
                     transcode_video_close( p_stream, id );
                     id->b_transcode = VLC_FALSE;
                     return VLC_EGENERIC;
@@ -2264,7 +2268,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
                 if( p_tmp )
                 {
                     vout_CopyPicture( p_stream, p_tmp, p_pic );
-                    p_pic->pf_release( p_pic );
+                    if( p_pic->pf_release )
+                        p_pic->pf_release( p_pic );
                     p_pic = p_tmp;
                 }
             }
@@ -2342,7 +2347,8 @@ static int transcode_video_process( sout_stream_t *p_stream,
 
         if( p_sys->i_threads == 0 )
         {
-            p_pic->pf_release( p_pic );
+            if( p_pic->pf_release )
+                p_pic->pf_release( p_pic );
         }
         else
         {
@@ -2395,7 +2401,8 @@ static int EncoderThread( sout_stream_sys_t *p_sys )
 
         vlc_mutex_unlock( &p_sys->lock_out );
 
-        p_pic->pf_release( p_pic );
+        if( p_pic->pf_release )
+            p_pic->pf_release( p_pic );
     }
 
     while( p_sys->i_last_pic != p_sys->i_first_pic )
@@ -2403,7 +2410,8 @@ static int EncoderThread( sout_stream_sys_t *p_sys )
         p_pic = p_sys->pp_pics[p_sys->i_first_pic++];
         p_sys->i_first_pic %= PICTURE_RING_SIZE;
 
-        p_pic->pf_release( p_pic );
+        if( p_pic->pf_release )
+            p_pic->pf_release( p_pic );
     }
 
     block_ChainRelease( p_sys->p_buffers );
@@ -2479,7 +2487,8 @@ static picture_t *video_new_buffer( vlc_object_t *p_this, picture_t **pp_ring,
 
         for( i = 0; i < PICTURE_RING_SIZE; i++ )
         {
-            pp_ring[i]->pf_release( pp_ring[i] );
+            if( pp_ring[i]->pf_release )
+                pp_ring[i]->pf_release( pp_ring[i] );
         }
 
         i = 0;
diff --git a/modules/video_filter/deinterlace.c b/modules/video_filter/deinterlace.c
index 68aade2..f2ce436 100644
--- a/modules/video_filter/deinterlace.c
+++ b/modules/video_filter/deinterlace.c
@@ -2137,7 +2137,8 @@ static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
             RenderDiscard( p_vout, p_pic_dst, p_pic, 0 );
 #endif
             msg_Err( p_vout, "discarding lines is not supported yet" );
-            p_pic_dst->pf_release( p_pic_dst );
+            if( p_pic_dst->pf_release )
+                p_pic_dst->pf_release( p_pic_dst );
             return p_pic;
             break;
 
@@ -2154,7 +2155,8 @@ static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
             RenderLinear( p_vout, pp_outpic[1], p_pic, 1 );
 #endif
             msg_Err( p_vout, "doubling the frame rate is not supported yet" );
-            p_pic_dst->pf_release( p_pic_dst );
+            if( p_pic_dst->pf_release )
+                p_pic_dst->pf_release( p_pic_dst );
             return p_pic;
             break;
 
@@ -2176,8 +2178,8 @@ static picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
     p_pic_dst->i_nb_fields = p_pic->i_nb_fields;
     p_pic_dst->b_progressive = VLC_TRUE;
     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
-
-    p_pic->pf_release( p_pic );
+    if( p_pic->pf_release )
+        p_pic->pf_release( p_pic );
     return p_pic_dst;
 }
 
diff --git a/modules/video_filter/distort.c b/modules/video_filter/distort.c
index 5a347bc..c65f2ac 100644
--- a/modules/video_filter/distort.c
+++ b/modules/video_filter/distort.c
@@ -1037,8 +1037,8 @@ static void DistortPsychedelic( vout_thread_t *p_vout, picture_t *p_inpic,
     copyimage( U_PLANE, 1 );
     copyimage( V_PLANE, 1 );
 #undef copyimage
-
-    p_converted->pf_release( p_converted );
+    if( p_converted->pf_release )
+        p_converted->pf_release( p_converted );
 
     p_vout->p_sys->x += p_vout->p_sys->xinc;
     p_vout->p_sys->y += p_vout->p_sys->yinc;
diff --git a/modules/video_filter/logo.c b/modules/video_filter/logo.c
index 3a2d3a0..706789c 100644
--- a/modules/video_filter/logo.c
+++ b/modules/video_filter/logo.c
@@ -268,7 +268,8 @@ void FreeLogoList( logo_list_t *p_logo_list )
         if( p_logo->psz_file ) FREE( p_logo->psz_file );
         if( p_logo->p_pic )
         {
-            p_logo->p_pic->pf_release( p_logo->p_pic );
+            if( p_logo->p_pic->pf_release )
+                p_logo->p_pic->pf_release( p_logo->p_pic );
             p_logo->p_pic = NULL;
         }
     }
diff --git a/modules/video_filter/magnify.c b/modules/video_filter/magnify.c
index 6340123..fae96cf 100644
--- a/modules/video_filter/magnify.c
+++ b/modules/video_filter/magnify.c
@@ -288,7 +288,8 @@ static void Render( vout_thread_t *p_vout, picture_t *p_pic )
         copyimage( U_PLANE );
         copyimage( V_PLANE );
     #undef copyimage
-        p_converted->pf_release( p_converted );
+        if( p_converted->pf_release )
+            p_converted->pf_release( p_converted );
 
         /* white rectangle on visualization */
         v_w = p_oyp->i_pitch*ZOOM_FACTOR/(VIS_ZOOM*o_zoom);
diff --git a/modules/video_filter/mosaic.c b/modules/video_filter/mosaic.c
index ef4a78d..ba8f74c 100644
--- a/modules/video_filter/mosaic.c
+++ b/modules/video_filter/mosaic.c
@@ -381,7 +381,7 @@ static void DestroyFilter( vlc_object_t *p_this )
     var_Destroy( p_libvlc, "mosaic-bsvt" );
     var_Destroy( p_libvlc, "mosaic-bs" );
 
-    if( p_sys->p_pic ) p_sys->p_pic->pf_release( p_sys->p_pic );
+    if( p_sys->p_pic && p_sys->p_pic->pf_release ) p_sys->p_pic->pf_release( p_sys->p_pic );
     vlc_mutex_unlock( &p_sys->lock );
     vlc_mutex_destroy( &p_sys->lock );
     free( p_sys );
@@ -394,7 +394,8 @@ static void MosaicReleasePicture( picture_t *p_picture )
 {
     picture_t *p_original_pic = (picture_t *)p_picture->p_sys;
 
-    p_original_pic->pf_release( p_original_pic );
+    if( p_original_pic->pf_release )
+        p_original_pic->pf_release( p_original_pic );
 }
 
 /*****************************************************************************
@@ -496,14 +497,16 @@ static subpicture_t *Filter( filter_t *p_filter, mtime_t date )
             if ( p_es->p_picture->p_next != NULL )
             {
                 picture_t *p_next = p_es->p_picture->p_next;
-                p_es->p_picture->pf_release( p_es->p_picture );
+                if( p_es->p_picture->pf_release )
+                    p_es->p_picture->pf_release( p_es->p_picture );
                 p_es->p_picture = p_next;
             }
             else if ( p_es->p_picture->date + p_sys->i_delay + BLANK_DELAY <
                         date )
             {
                 /* Display blank */
-                p_es->p_picture->pf_release( p_es->p_picture );
+                if( p_es->p_picture->pf_release )
+                    p_es->p_picture->pf_release( p_es->p_picture );
                 p_es->p_picture = NULL;
                 p_es->pp_last = &p_es->p_picture;
                 break;
diff --git a/modules/video_filter/rss.c b/modules/video_filter/rss.c
index 8e48053..7b582ce 100644
--- a/modules/video_filter/rss.c
+++ b/modules/video_filter/rss.c
@@ -522,7 +522,8 @@ picture_t *LoadImage( filter_t *p_filter, const char *psz_url )
         fmt_out.i_height = p_sys->p_style->i_font_size;
 
         p_pic = image_Convert( p_handler, p_orig, &fmt_in, &fmt_out );
-        p_orig->pf_release( p_orig );
+        if( p_orig->pf_release )
+            p_orig->pf_release( p_orig );
         if( !p_pic )
         {
             msg_Warn( p_filter, "Error while converting %s", psz_url );
@@ -895,7 +896,7 @@ static void FreeRSS( filter_t *p_filter)
         free( p_feed->psz_link );
         free( p_feed->psz_description );
         free( p_feed->psz_image );
-        if( p_feed->p_pic != NULL )
+        if( p_feed->p_pic && p_feed->p_pic->pf_release )
             p_feed->p_pic->pf_release( p_feed->p_pic );
     }
     free( p_sys->p_feeds );
diff --git a/modules/video_filter/rv32.c b/modules/video_filter/rv32.c
index 3d056cd..9512837 100644
--- a/modules/video_filter/rv32.c
+++ b/modules/video_filter/rv32.c
@@ -140,7 +140,8 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
     p_pic_dst->b_progressive = p_pic->b_progressive;
     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
 
-    p_pic->pf_release( p_pic );
+    if( p_pic->pf_release )
+        p_pic->pf_release( p_pic );
     return p_pic_dst;
 }
 
diff --git a/modules/video_filter/scale.c b/modules/video_filter/scale.c
index fde9f41..6381c7e 100644
--- a/modules/video_filter/scale.c
+++ b/modules/video_filter/scale.c
@@ -154,6 +154,7 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
     p_pic_dst->b_progressive = p_pic->b_progressive;
     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
 
-    p_pic->pf_release( p_pic );
+    if( p_pic->pf_release )
+        p_pic->pf_release( p_pic );
     return p_pic_dst;
 }
diff --git a/modules/video_filter/swscale/filter.c b/modules/video_filter/swscale/filter.c
index e3c50ec..120a493 100644
--- a/modules/video_filter/swscale/filter.c
+++ b/modules/video_filter/swscale/filter.c
@@ -304,7 +304,8 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
     p_pic_dst->b_progressive = p_pic->b_progressive;
     p_pic_dst->b_top_field_first = p_pic->b_top_field_first;
 
-    p_pic->pf_release( p_pic );
+    if( p_pic->pf_release )
+        p_pic->pf_release( p_pic );
     return p_pic_dst;
 }
 
diff --git a/src/misc/image.c b/src/misc/image.c
index f5a4efb..88a1389 100644
--- a/src/misc/image.c
+++ b/src/misc/image.c
@@ -130,7 +130,7 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
     while( (p_tmp = p_image->p_dec->pf_decode_video( p_image->p_dec, &p_block ))
              != NULL )
     {
-        if ( p_pic != NULL )
+        if ( p_pic && p_pic->pf_release )
             p_pic->pf_release( p_pic );
         p_pic = p_tmp;
     }
@@ -179,7 +179,8 @@ static picture_t *ImageRead( image_handler_t *p_image, block_t *p_block,
 
             if( !p_image->p_filter )
             {
-                p_pic->pf_release( p_pic );
+                if( p_pic->pf_release )
+                    p_pic->pf_release( p_pic );
                 return NULL;
             }
         }
diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c
index 2eb4dac..7369673 100644
--- a/src/video_output/vout_intf.c
+++ b/src/video_output/vout_intf.c
@@ -704,7 +704,8 @@ int vout_Snapshot( vout_thread_t *p_vout, picture_t *p_pic )
         p_subpic = spu_CreateSubpicture( p_vout->p_spu );
         if( p_subpic == NULL )
         {
-             p_pif->pf_release( p_pif );
+             if( p_pif->pf_release )
+                 p_pif->pf_release( p_pif );
              return VLC_EGENERIC;
         }
 
@@ -719,7 +720,8 @@ int vout_Snapshot( vout_thread_t *p_vout, picture_t *p_pic )
         p_subpic->p_region = spu_CreateRegion( p_vout->p_spu, &fmt_out );
         vout_CopyPicture( p_image->p_parent, &p_subpic->p_region->picture,
                           p_pif );
-        p_pif->pf_release( p_pif );
+        if( p_pif->pf_release )
+            p_pif->pf_release( p_pif );
 
         spu_DisplaySubpicture( p_vout->p_spu, p_subpic );
     }
-- 
1.5.4.3

