*
* Authors: Laurent Aimar < fenrir _AT_ videolan _DOT_ 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
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; either version 2.1 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
- * GNU General Public License for more details.
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
*
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
*****************************************************************************/
/*****************************************************************************
#include <assert.h>
#include <vlc_common.h>
+#include <vlc_atomic.h>
#include <vlc_vout.h>
#include <vlc_spu.h>
#include <vlc_aout.h>
struct input_resource_t
{
- VLC_GC_MEMBERS
+ atomic_uint refs;
vlc_object_t *p_parent;
/* 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;
+ int i_vout;
- aout_instance_t *p_aout;
+ bool b_aout_busy;
+ audio_output_t *p_aout;
};
/* */
vlc_mutex_unlock( &p_resource->lock_hold );
}
-/* */
-static void DestroyAout( input_resource_t *p_resource )
-{
- if( p_resource->p_aout )
- vlc_object_release( p_resource->p_aout );
- p_resource->p_aout = NULL;
-}
-static aout_instance_t *RequestAout( input_resource_t *p_resource, aout_instance_t *p_aout )
+/* Audio output */
+audio_output_t *input_resource_GetAout( input_resource_t *p_resource )
{
- vlc_assert_locked( &p_resource->lock );
+ audio_output_t *p_aout;
- if( p_aout )
+ vlc_mutex_lock( &p_resource->lock );
+ if( p_resource->b_aout_busy )
{
- msg_Dbg( p_resource->p_parent, "releasing aout" );
- vlc_object_release( p_aout );
- return NULL;
+ vlc_mutex_unlock( &p_resource->lock );
+ msg_Dbg( p_resource->p_parent, "creating extra audio output" );
+ return aout_New( p_resource->p_parent );
}
- else
+
+ p_aout = p_resource->p_aout;
+ if( p_aout == NULL )
{
- p_aout = p_resource->p_aout;
- if( !p_aout )
- {
- msg_Dbg( p_resource->p_parent, "creating aout" );
- p_aout = aout_New( p_resource->p_parent );
+ msg_Dbg( p_resource->p_parent, "creating audio output" );
+ p_aout = aout_New( p_resource->p_parent );
+ }
+ else
+ msg_Dbg( p_resource->p_parent, "reusing audio output" );
- 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_parent, "reusing aout" );
- }
+ if( p_aout != NULL )
+ {
+ vlc_mutex_lock( &p_resource->lock_hold );
+ p_resource->p_aout = p_aout;
+ vlc_mutex_unlock( &p_resource->lock_hold );
- if( !p_aout )
- return NULL;
+ p_resource->b_aout_busy = true;
vlc_object_hold( p_aout );
- return p_aout;
}
+ vlc_mutex_unlock( &p_resource->lock );
+ return p_aout;
}
-static aout_instance_t *HoldAout( input_resource_t *p_resource )
-{
- vlc_mutex_lock( &p_resource->lock_hold );
- aout_instance_t *p_aout = p_resource->p_aout;
- if( p_aout )
- vlc_object_hold( p_aout );
+void input_resource_PutAout( input_resource_t *p_resource,
+ audio_output_t *p_aout )
+{
+ assert( p_aout != NULL );
- vlc_mutex_unlock( &p_resource->lock_hold );
+ vlc_mutex_lock( &p_resource->lock );
+ if( p_aout == p_resource->p_aout )
+ {
+ assert( p_resource->b_aout_busy );
+ p_resource->b_aout_busy = false;
+ msg_Dbg( p_resource->p_parent, "keeping audio output" );
+ vlc_object_release( p_aout );
+ p_aout = NULL;
+ }
+ else
+ msg_Dbg( p_resource->p_parent, "destroying extra audio output" );
+ vlc_mutex_unlock( &p_resource->lock );
- return p_aout;
+ if( p_aout != NULL )
+ aout_Destroy( 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;
+audio_output_t *input_resource_HoldAout( input_resource_t *p_resource )
+{
+ audio_output_t *p_aout;
+ vlc_mutex_lock( &p_resource->lock_hold );
+ p_aout = p_resource->p_aout;
+ if( p_aout )
+ vlc_object_hold( p_aout );
vlc_mutex_unlock( &p_resource->lock_hold );
- if( p_aout )
- vlc_object_release( p_aout );
+ return p_aout;
}
-static void Destructor( gc_object_t *p_gc )
+static void input_resource_TerminateAout( input_resource_t *p_resource )
{
- input_resource_t *p_resource = vlc_priv( p_gc, input_resource_t );
+ audio_output_t *p_aout;
- DestroySout( p_resource );
- DestroyVout( p_resource );
- DestroyAout( p_resource );
+ vlc_mutex_lock( &p_resource->lock );
+ vlc_mutex_lock( &p_resource->lock_hold );
+ p_aout = p_resource->p_aout;
+ p_resource->p_aout = NULL;
+ vlc_mutex_unlock( &p_resource->lock_hold );
+ p_resource->b_aout_busy = false;
+ vlc_mutex_unlock( &p_resource->lock );
- vlc_mutex_destroy( &p_resource->lock_hold );
- vlc_mutex_destroy( &p_resource->lock );
- free( p_resource );
+ if( p_aout != NULL )
+ aout_Destroy( p_aout );
}
-/* */
+/* Common */
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 );
+ atomic_init( &p_resource->refs, 1 );
p_resource->p_parent = p_parent;
vlc_mutex_init( &p_resource->lock );
vlc_mutex_init( &p_resource->lock_hold );
void input_resource_Release( input_resource_t *p_resource )
{
- vlc_gc_decref( p_resource );
+ if( atomic_fetch_sub( &p_resource->refs, 1 ) != 1 )
+ return;
+
+ DestroySout( p_resource );
+ DestroyVout( p_resource );
+ if( p_resource->p_aout != NULL )
+ aout_Destroy( p_resource->p_aout );
+
+ vlc_mutex_destroy( &p_resource->lock_hold );
+ 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 );
+ atomic_fetch_add( &p_resource->refs, 1 );
return p_resource;
}
return b_vout;
}
-/* */
-aout_instance_t *input_resource_RequestAout( input_resource_t *p_resource, aout_instance_t *p_aout )
-{
- vlc_mutex_lock( &p_resource->lock );
- aout_instance_t *p_ret = RequestAout( p_resource, p_aout );
- vlc_mutex_unlock( &p_resource->lock );
-
- return p_ret;
-}
-aout_instance_t *input_resource_HoldAout( input_resource_t *p_resource )
-{
- return HoldAout( p_resource );
-}
-
/* */
sout_instance_t *input_resource_RequestSout( input_resource_t *p_resource, sout_instance_t *p_sout, const char *psz_sout )
{
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_TerminateAout( p_resource );
input_resource_TerminateVout( p_resource );
}