# include "config.h"
#endif
+#include <assert.h>
+
#include <vlc_common.h>
#include <vlc_vout.h>
-#include <vlc_osd.h>
+#include <vlc_spu.h>
#include <vlc_aout.h>
#include <vlc_sout.h>
#include "../libvlc.h"
struct input_resource_t
{
+ VLC_GC_MEMBERS
+
+ vlc_object_t *p_parent;
+
/* This lock is used to serialize request and protect
* our variables */
vlc_mutex_t lock;
sout_instance_t *p_sout;
vout_thread_t *p_vout_free;
- aout_instance_t *p_aout;
/* This lock is used to protect vout resources access (for hold)
* It is a special case because of embed video (possible deadlock
- * between vout window request and vout holds in some(qt4) interface) */
- vlc_mutex_t lock_vout;
+ * between vout window request and vout holds in some(qt4) interface)
+ */
+ vlc_mutex_t lock_hold;
+
+ /* You need lock+lock_hold to write to the following variables and
+ * only lock or lock_hold to read them */
+
int i_vout;
vout_thread_t **pp_vout;
+
+ aout_instance_t *p_aout;
};
/* */
p_resource->p_sout = NULL;
}
-static sout_instance_t *DetachSout( input_resource_t *p_resource )
-{
- sout_instance_t *p_sout = p_resource->p_sout;
- p_resource->p_sout = NULL;
-
- return p_sout;
-}
-
static sout_instance_t *RequestSout( input_resource_t *p_resource,
sout_instance_t *p_sout, const char *psz_sout )
{
if( p_resource->p_sout &&
strcmp( p_resource->p_sout->psz_sout, psz_sout ) )
{
- msg_Dbg( p_resource->p_input, "destroying unusable sout" );
+ msg_Dbg( p_resource->p_parent, "destroying unusable sout" );
DestroySout( p_resource );
}
if( p_resource->p_sout )
{
/* Reuse it */
- msg_Dbg( p_resource->p_input, "reusing sout" );
- msg_Dbg( p_resource->p_input, "you probably want to use gather stream_out" );
- vlc_object_attach( p_resource->p_sout, p_resource->p_input );
+ msg_Dbg( p_resource->p_parent, "reusing sout" );
+ msg_Dbg( p_resource->p_parent, "you probably want to use gather stream_out" );
}
else
{
/* Create a new one */
- p_resource->p_sout = sout_NewInstance( p_resource->p_input, psz_sout );
+ p_resource->p_sout = sout_NewInstance( p_resource->p_parent, psz_sout );
}
p_sout = p_resource->p_sout;
}
else
{
- vlc_object_detach( p_sout );
p_resource->p_sout = p_sout;
-
return NULL;
}
#else
p_resource->p_vout_free = NULL;
}
-static vout_thread_t *DetachVout( input_resource_t *p_resource )
-{
- assert( p_resource->i_vout == 0 );
- vout_thread_t *p_vout = p_resource->p_vout_free;
- p_resource->p_vout_free = NULL;
-
- return p_vout;
-}
static void DisplayVoutTitle( input_resource_t *p_resource,
vout_thread_t *p_vout )
free( psz_nowplaying );
}
static vout_thread_t *RequestVout( input_resource_t *p_resource,
- vout_thread_t *p_vout, video_format_t *p_fmt,
+ vout_thread_t *p_vout,
+ video_format_t *p_fmt, unsigned dpb_size,
bool b_recycle )
{
+ vlc_assert_locked( &p_resource->lock );
+
if( !p_vout && !p_fmt )
{
if( p_resource->p_vout_free )
/* */
if( !p_vout && p_resource->p_vout_free )
{
- msg_Dbg( p_resource->p_input, "trying to reuse free vout" );
+ msg_Dbg( p_resource->p_parent, "trying to reuse free vout" );
p_vout = p_resource->p_vout_free;
p_resource->p_vout_free = NULL;
{
assert( p_vout != p_resource->p_vout_free );
- vlc_mutex_lock( &p_resource->lock_vout );
+ vlc_mutex_lock( &p_resource->lock_hold );
TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout );
- vlc_mutex_unlock( &p_resource->lock_vout );
+ vlc_mutex_unlock( &p_resource->lock_hold );
}
/* */
- p_vout = vout_Request( p_resource->p_input, p_vout, p_fmt );
+ vout_configuration_t cfg = {
+ .vout = p_vout,
+ .input = VLC_OBJECT(p_resource->p_input),
+ .change_fmt = true,
+ .fmt = p_fmt,
+ .dpb_size = dpb_size,
+ };
+ p_vout = vout_Request( p_resource->p_parent, &cfg );
if( !p_vout )
return NULL;
DisplayVoutTitle( p_resource, p_vout );
- vlc_mutex_lock( &p_resource->lock_vout );
+ vlc_mutex_lock( &p_resource->lock_hold );
TAB_APPEND( p_resource->i_vout, p_resource->pp_vout, p_vout );
- vlc_mutex_unlock( &p_resource->lock_vout );
+ vlc_mutex_unlock( &p_resource->lock_hold );
return p_vout;
}
{
assert( p_vout );
- vlc_mutex_lock( &p_resource->lock_vout );
+ vlc_mutex_lock( &p_resource->lock_hold );
TAB_REMOVE( p_resource->i_vout, p_resource->pp_vout, p_vout );
const int i_vout_active = p_resource->i_vout;
- vlc_mutex_unlock( &p_resource->lock_vout );
+ vlc_mutex_unlock( &p_resource->lock_hold );
if( p_resource->p_vout_free || i_vout_active > 0 || !b_recycle )
{
if( b_recycle )
- msg_Dbg( p_resource->p_input, "detroying vout (already one saved or active)" );
+ msg_Dbg( p_resource->p_parent, "detroying vout (already one saved or active)" );
vout_CloseAndRelease( p_vout );
}
else
{
- msg_Dbg( p_resource->p_input, "saving a free vout" );
+ msg_Dbg( p_resource->p_parent, "saving a free vout" );
vout_Flush( p_vout, 1 );
- spu_Control( vout_GetSpu( p_vout ), SPU_CHANNEL_CLEAR, -1 );
-
- p_resource->p_vout_free = p_vout;
+ vout_FlushSubpictureChannel( p_vout, -1 );
+
+ vout_configuration_t cfg = {
+ .vout = p_vout,
+ .input = NULL,
+ .change_fmt = false,
+ .fmt = NULL,
+ .dpb_size = 0,
+ };
+ p_resource->p_vout_free = vout_Request( p_resource->p_parent, &cfg );
}
return NULL;
}
}
static vout_thread_t *HoldVout( input_resource_t *p_resource )
{
- if( p_resource->i_vout <= 0 )
- return NULL;
-
/* TODO FIXME: p_resource->pp_vout order is NOT stable */
- vlc_mutex_lock( &p_resource->lock_vout );
-
- vout_thread_t *p_vout = p_resource->pp_vout[0];
+ vlc_mutex_lock( &p_resource->lock_hold );
- vlc_object_hold( p_vout );
+ vout_thread_t *p_vout = p_resource->i_vout > 0 ? p_resource->pp_vout[0] : NULL;
+ if( p_vout )
+ vlc_object_hold( p_vout );
- vlc_mutex_unlock( &p_resource->lock_vout );
+ vlc_mutex_unlock( &p_resource->lock_hold );
return p_vout;
}
-static void HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout, int *pi_vout )
+
+static void HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout,
+ size_t *pi_vout )
{
vout_thread_t **pp_vout;
*pi_vout = 0;
*ppp_vout = NULL;
- vlc_mutex_lock( &p_resource->lock_vout );
+ vlc_mutex_lock( &p_resource->lock_hold );
if( p_resource->i_vout <= 0 )
goto exit;
- pp_vout = calloc( p_resource->i_vout, sizeof(*pp_vout) );
+ pp_vout = malloc( p_resource->i_vout * sizeof(*pp_vout) );
if( !pp_vout )
goto exit;
}
exit:
- vlc_mutex_unlock( &p_resource->lock_vout );
+ vlc_mutex_unlock( &p_resource->lock_hold );
}
/* */
vlc_object_release( p_resource->p_aout );
p_resource->p_aout = NULL;
}
-static aout_instance_t *DetachAout( input_resource_t *p_resource )
-{
- aout_instance_t *p_aout = p_resource->p_aout;
- p_resource->p_aout = NULL;
-
- return p_aout;
-}
-
static aout_instance_t *RequestAout( input_resource_t *p_resource, aout_instance_t *p_aout )
{
+ vlc_assert_locked( &p_resource->lock );
assert( p_resource->p_input );
if( p_aout )
{
- msg_Dbg( p_resource->p_input, "releasing aout" );
+ msg_Dbg( p_resource->p_parent, "releasing aout" );
vlc_object_release( p_aout );
return NULL;
}
else
{
- if( !p_resource->p_aout )
+ p_aout = p_resource->p_aout;
+ if( !p_aout )
{
- msg_Dbg( p_resource->p_input, "creating aout" );
- p_resource->p_aout = aout_New( p_resource->p_input );
+ msg_Dbg( p_resource->p_parent, "creating aout" );
+ p_aout = aout_New( p_resource->p_parent );
+
+ vlc_mutex_lock( &p_resource->lock_hold );
+ p_resource->p_aout = p_aout;
+ vlc_mutex_unlock( &p_resource->lock_hold );
}
else
{
- msg_Dbg( p_resource->p_input, "reusing aout" );
+ msg_Dbg( p_resource->p_parent, "reusing aout" );
}
- if( !p_resource->p_aout )
+ if( !p_aout )
return NULL;
-
- vlc_object_detach( p_resource->p_aout );
- vlc_object_attach( p_resource->p_aout, p_resource->p_input );
- vlc_object_hold( p_resource->p_aout );
- return p_resource->p_aout;
+ vlc_object_hold( p_aout );
+ return p_aout;
}
}
static aout_instance_t *HoldAout( input_resource_t *p_resource )
{
- if( !p_resource->p_aout )
- return NULL;
+ vlc_mutex_lock( &p_resource->lock_hold );
aout_instance_t *p_aout = p_resource->p_aout;
+ if( p_aout )
+ vlc_object_hold( p_aout );
- vlc_object_hold( p_aout );
+ vlc_mutex_unlock( &p_resource->lock_hold );
return p_aout;
}
+static void TerminateAout( input_resource_t *p_resource )
+{
+ vlc_mutex_lock( &p_resource->lock_hold );
+
+ aout_instance_t *p_aout = p_resource->p_aout;
+ p_resource->p_aout = NULL;
+
+ vlc_mutex_unlock( &p_resource->lock_hold );
+
+ if( p_aout )
+ vlc_object_release( p_aout );
+}
+
+static void Destructor( gc_object_t *p_gc )
+{
+ input_resource_t *p_resource = vlc_priv( p_gc, input_resource_t );
+
+ DestroySout( p_resource );
+ DestroyVout( p_resource );
+ DestroyAout( p_resource );
+
+ vlc_mutex_destroy( &p_resource->lock_hold );
+ vlc_mutex_destroy( &p_resource->lock );
+ free( p_resource );
+}
/* */
-input_resource_t *input_resource_New( void )
+input_resource_t *input_resource_New( vlc_object_t *p_parent )
{
input_resource_t *p_resource = calloc( 1, sizeof(*p_resource) );
if( !p_resource )
return NULL;
+ vlc_gc_init( p_resource, Destructor );
+ p_resource->p_parent = p_parent;
vlc_mutex_init( &p_resource->lock );
- vlc_mutex_init( &p_resource->lock_vout );
+ vlc_mutex_init( &p_resource->lock_hold );
return p_resource;
}
-void input_resource_Delete( input_resource_t *p_resource )
+void input_resource_Release( input_resource_t *p_resource )
{
- DestroySout( p_resource );
- DestroyVout( p_resource );
- DestroyAout( p_resource );
+ vlc_gc_decref( p_resource );
+}
- vlc_mutex_destroy( &p_resource->lock_vout );
- vlc_mutex_destroy( &p_resource->lock );
- free( p_resource );
+input_resource_t *input_resource_Hold( input_resource_t *p_resource )
+{
+ vlc_gc_incref( p_resource );
+ return p_resource;
}
void input_resource_SetInput( input_resource_t *p_resource, input_thread_t *p_input )
vlc_mutex_lock( &p_resource->lock );
if( p_resource->p_input && !p_input )
- {
- if( p_resource->p_aout )
- vlc_object_detach( p_resource->p_aout );
-
assert( p_resource->i_vout == 0 );
- if( p_resource->p_vout_free )
- vlc_object_detach( p_resource->p_vout_free );
-
- if( p_resource->p_sout )
- vlc_object_detach( p_resource->p_sout );
- }
/* */
p_resource->p_input = p_input;
vlc_mutex_unlock( &p_resource->lock );
}
-input_resource_t *input_resource_Detach( input_resource_t *p_resource )
-{
- input_resource_t *p_ret = input_resource_New();
- if( !p_ret )
- return NULL;
-
- vlc_mutex_lock( &p_resource->lock );
- assert( !p_resource->p_input );
- p_ret->p_sout = DetachSout( p_resource );
- p_ret->p_vout_free = DetachVout( p_resource );
- p_ret->p_aout = DetachAout( p_resource );
- vlc_mutex_unlock( &p_resource->lock );
-
- return p_ret;
-}
-
vout_thread_t *input_resource_RequestVout( input_resource_t *p_resource,
- vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recycle )
+ vout_thread_t *p_vout,
+ video_format_t *p_fmt, unsigned dpb_size,
+ bool b_recycle )
{
vlc_mutex_lock( &p_resource->lock );
- vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, b_recycle );
+ vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, dpb_size, b_recycle );
vlc_mutex_unlock( &p_resource->lock );
return p_ret;
{
return HoldVout( p_resource );
}
-void input_resource_HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout, int *pi_vout )
+
+void input_resource_HoldVouts( input_resource_t *p_resource, vout_thread_t ***ppp_vout,
+ size_t *pi_vout )
{
HoldVouts( p_resource, ppp_vout, pi_vout );
}
+
void input_resource_TerminateVout( input_resource_t *p_resource )
{
- input_resource_RequestVout( p_resource, NULL, NULL, false );
+ input_resource_RequestVout( p_resource, NULL, NULL, 0, false );
}
bool input_resource_HasVout( input_resource_t *p_resource )
{
}
aout_instance_t *input_resource_HoldAout( input_resource_t *p_resource )
{
- vlc_mutex_lock( &p_resource->lock );
- aout_instance_t *p_ret = HoldAout( p_resource );
- vlc_mutex_unlock( &p_resource->lock );
-
- return p_ret;
+ return HoldAout( p_resource );
}
+
/* */
sout_instance_t *input_resource_RequestSout( input_resource_t *p_resource, sout_instance_t *p_sout, const char *psz_sout )
{
input_resource_RequestSout( p_resource, NULL, NULL );
}
+void input_resource_Terminate( input_resource_t *p_resource )
+{
+ input_resource_TerminateSout( p_resource );
+
+ vlc_mutex_lock( &p_resource->lock );
+ TerminateAout( p_resource );
+ vlc_mutex_unlock( &p_resource->lock );
+
+ input_resource_TerminateVout( p_resource );
+}
+