]> git.sesse.net Git - vlc/blobdiff - src/misc/filter_chain.c
mtime: Avoid overflow when using mach_absolute_time().
[vlc] / src / misc / filter_chain.c
index 87f3feed9f90e412ceed753cc9d7b5d1d2c9d3c5..cbf553e224e9f1d67240a0de64a951e77bef1ee5 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <vlc_filter.h>
 #include <vlc_osd.h>
+#include <vlc_modules.h>
 #include <libvlc.h>
 #include <assert.h>
 
@@ -45,6 +46,7 @@ typedef struct chained_filter_t
     /* Private filter chain data (shhhh!) */
     struct chained_filter_t *prev, *next;
     vlc_mouse_t *mouse;
+    picture_t *pending;
 } chained_filter_t;
 
 /* Only use this with filter objects from _this_ C module */
@@ -97,15 +99,18 @@ static int filter_chain_DeleteFilterInternal( filter_chain_t *, filter_t * );
 
 static int UpdateBufferFunctions( filter_chain_t * );
 
+static void FilterDeletePictures( filter_t *, picture_t * );
+
+#undef filter_chain_New
 /**
  * Filter chain initialisation
  */
-filter_chain_t *__filter_chain_New( vlc_object_t *p_this,
-                                    const char *psz_capability,
-                                    bool b_allow_fmt_out_change,
-                                    int  (*pf_buffer_allocation_init)( filter_t *, void * ),
-                                    void (*pf_buffer_allocation_clean)( filter_t * ),
-                                    void *p_buffer_allocation_data )
+filter_chain_t *filter_chain_New( vlc_object_t *p_this,
+                                  const char *psz_capability,
+                                  bool b_allow_fmt_out_change,
+                                  int  (*pf_buffer_allocation_init)( filter_t *, void * ),
+                                  void (*pf_buffer_allocation_clean)( filter_t * ),
+                                  void *p_buffer_allocation_data )
 {
     assert( p_this );
     assert( psz_capability );
@@ -219,19 +224,62 @@ const es_format_t *filter_chain_GetFmtOut( filter_chain_t *p_chain )
     return &p_chain->fmt_out;
 }
 
-picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
+static picture_t *FilterChainVideoFilter( chained_filter_t *f, picture_t *p_pic )
 {
-    for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
+    for( ; f != NULL; f = f->next )
     {
         filter_t *p_filter = &f->filter;
-
         p_pic = p_filter->pf_video_filter( p_filter, p_pic );
         if( !p_pic )
             break;
+        if( f->pending )
+        {
+            msg_Warn( p_filter, "dropping pictures" );
+            FilterDeletePictures( p_filter, f->pending );
+        }
+        f->pending = p_pic->p_next;
+        p_pic->p_next = NULL;
     }
     return p_pic;
 }
 
+picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
+{
+    if( p_pic )
+    {
+        p_pic = FilterChainVideoFilter( p_chain->first, p_pic );
+        if( p_pic )
+            return p_pic;
+    }
+    for( chained_filter_t *b = p_chain->last; b != NULL; b = b->prev )
+    {
+        p_pic = b->pending;
+        if( !p_pic )
+            continue;
+        b->pending = p_pic->p_next;
+        p_pic->p_next = NULL;
+
+        p_pic = FilterChainVideoFilter( b->next, p_pic );
+        if( p_pic )
+            return p_pic;
+    }
+    return NULL;
+}
+
+void filter_chain_VideoFlush( filter_chain_t *p_chain )
+{
+    for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
+    {
+        filter_t *p_filter = &f->filter;
+
+        FilterDeletePictures( p_filter, f->pending );
+        f->pending = NULL;
+
+        filter_FlushPictures( p_filter );
+    }
+}
+
+
 block_t *filter_chain_AudioFilter( filter_chain_t *p_chain, block_t *p_block )
 {
     for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
@@ -267,13 +315,13 @@ int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const
         filter_t *p_filter = &f->filter;
         vlc_mouse_t *p_mouse = f->mouse;
 
-        if( p_filter->pf_mouse && p_mouse )
+        if( p_filter->pf_video_mouse && p_mouse )
         {
             vlc_mouse_t old = *p_mouse;
             vlc_mouse_t filtered;
 
             *p_mouse = current;
-            if( p_filter->pf_mouse( p_filter, &filtered, &old, &current ) )
+            if( p_filter->pf_video_mouse( p_filter, &filtered, &old, &current ) )
                 return VLC_EGENERIC;
             current = filtered;
         }
@@ -283,6 +331,25 @@ int filter_chain_MouseFilter( filter_chain_t *p_chain, vlc_mouse_t *p_dst, const
     return VLC_SUCCESS;
 }
 
+int filter_chain_MouseEvent( filter_chain_t *p_chain,
+                             const vlc_mouse_t *p_mouse,
+                             const video_format_t *p_fmt )
+{
+    for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
+    {
+        filter_t *p_filter = &f->filter;
+
+        if( p_filter->pf_sub_mouse )
+        {
+            vlc_mouse_t old = *f->mouse;
+            *f->mouse = *p_mouse;
+            if( p_filter->pf_sub_mouse( p_filter, &old, p_mouse, p_fmt ) )
+                return VLC_EGENERIC;
+        }
+    }
+
+    return VLC_SUCCESS;
+}
 
 /* Helpers */
 static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain,
@@ -348,6 +415,7 @@ static filter_t *filter_chain_AppendFilterInternal( filter_chain_t *p_chain,
     if( p_mouse )
         vlc_mouse_Init( p_mouse );
     p_chained->mouse = p_mouse;
+    p_chained->pending = NULL;
 
     msg_Dbg( p_chain->p_this, "Filter '%s' (%p) appended to chain",
              psz_name ? psz_name : module_get_name(p_filter->p_module, false),
@@ -366,7 +434,6 @@ error:
         module_unneed( p_filter, p_filter->p_module );
     es_format_Clean( &p_filter->fmt_in );
     es_format_Clean( &p_filter->fmt_out );
-    vlc_object_detach( p_filter );
     vlc_object_release( p_filter );
     return NULL;
 }
@@ -432,13 +499,14 @@ static int filter_chain_DeleteFilterInternal( filter_chain_t *p_chain,
 
     msg_Dbg( p_chain->p_this, "Filter %p removed from chain", p_filter );
 
+    FilterDeletePictures( &p_chained->filter, p_chained->pending );
+
     /* Destroy the filter object */
     if( IsInternalVideoAllocator( p_chained ) )
         AllocatorClean( &internal_video_allocator, p_chained );
     else
         AllocatorClean( &p_chain->allocator, p_chained );
 
-    vlc_object_detach( p_filter );
     if( p_filter->p_module )
         module_unneed( p_filter, p_filter->p_module );
     free( p_chained->mouse );
@@ -449,6 +517,16 @@ static int filter_chain_DeleteFilterInternal( filter_chain_t *p_chain,
     return VLC_SUCCESS;
 }
 
+static void FilterDeletePictures( filter_t *filter, picture_t *picture )
+{
+    while( picture )
+    {
+        picture_t *next = picture->p_next;
+        filter_DeletePicture( filter, picture );
+        picture = next;
+    }
+}
+
 /**
  * Internal chain buffer handling
  */
@@ -518,20 +596,20 @@ static int InternalVideoInit( filter_t *p_filter, void *p_data )
 {
     VLC_UNUSED(p_data);
 
-    p_filter->pf_vout_buffer_new = VideoBufferNew;
-    p_filter->pf_vout_buffer_del = VideoBufferDelete;
+    p_filter->pf_video_buffer_new = VideoBufferNew;
+    p_filter->pf_video_buffer_del = VideoBufferDelete;
 
     return VLC_SUCCESS;
 }
 static void InternalVideoClean( filter_t *p_filter )
 {
-    p_filter->pf_vout_buffer_new = NULL;
-    p_filter->pf_vout_buffer_del = NULL;
+    p_filter->pf_video_buffer_new = NULL;
+    p_filter->pf_video_buffer_del = NULL;
 }
 
 static bool IsInternalVideoAllocator( chained_filter_t *p_filter )
 {
-    return p_filter->filter.pf_vout_buffer_new == VideoBufferNew;
+    return p_filter->filter.pf_video_buffer_new == VideoBufferNew;
 }
 
 /* */