Commit 3b40c174 authored by Laurent Aimar's avatar Laurent Aimar

Prepare for safe (sout)/vout/aout recycling.

parent 88a5e04e
...@@ -331,6 +331,8 @@ SOURCES_libvlc_common = \ ...@@ -331,6 +331,8 @@ SOURCES_libvlc_common = \
input/input_internal.h \ input/input_internal.h \
input/input_interface.h \ input/input_interface.h \
input/vlm_internal.h \ input/vlm_internal.h \
input/ressource.h \
input/ressource.c \
input/stream.c \ input/stream.c \
input/stream_demux.c \ input/stream_demux.c \
input/stream_filter.c \ input/stream_filter.c \
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "clock.h" #include "clock.h"
#include "decoder.h" #include "decoder.h"
#include "event.h" #include "event.h"
#include "ressource.h"
#include "../video_output/vout_control.h" #include "../video_output/vout_control.h"
...@@ -1875,7 +1876,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush ...@@ -1875,7 +1876,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL ); stats_UpdateInteger( p_dec, p_input->p->counters.p_decoded_sub, 1, NULL );
vlc_mutex_unlock( &p_input->p->counters.counters_lock ); vlc_mutex_unlock( &p_input->p->counters.counters_lock );
p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
if( p_vout && p_owner->p_spu_vout == p_vout ) if( p_vout && p_owner->p_spu_vout == p_vout )
{ {
/* Preroll does not work very well with subtitle */ /* Preroll does not work very well with subtitle */
...@@ -1900,7 +1901,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush ...@@ -1900,7 +1901,7 @@ static void DecoderProcessSpu( decoder_t *p_dec, block_t *p_block, bool b_flush
if( b_flush && p_owner->p_spu_vout ) if( b_flush && p_owner->p_spu_vout )
{ {
p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); p_vout = input_ressource_HoldVout( p_input->p->p_ressource );
if( p_vout && p_owner->p_spu_vout == p_vout ) if( p_vout && p_owner->p_spu_vout == p_vout )
spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR, spu_Control( p_vout->p_spu, SPU_CHANNEL_CLEAR,
...@@ -2029,7 +2030,8 @@ static void DeleteDecoder( decoder_t * p_dec ) ...@@ -2029,7 +2030,8 @@ static void DeleteDecoder( decoder_t * p_dec )
aout_DecDelete( p_owner->p_aout, p_owner->p_aout_input ); aout_DecDelete( p_owner->p_aout, p_owner->p_aout_input );
if( p_owner->p_aout ) if( p_owner->p_aout )
{ {
vlc_object_release( p_owner->p_aout ); input_ressource_RequestAout( p_owner->p_input->p->p_ressource,
p_owner->p_aout );
p_owner->p_aout = NULL; p_owner->p_aout = NULL;
} }
if( p_owner->p_vout ) if( p_owner->p_vout )
...@@ -2038,7 +2040,7 @@ static void DeleteDecoder( decoder_t * p_dec ) ...@@ -2038,7 +2040,7 @@ static void DeleteDecoder( decoder_t * p_dec )
vout_FixLeaks( p_owner->p_vout, true ); vout_FixLeaks( p_owner->p_vout, true );
/* We are about to die. Reattach video output to p_vlc. */ /* We are about to die. Reattach video output to p_vlc. */
vout_Request( p_dec, p_owner->p_vout, NULL ); input_ressource_RequestVout( p_owner->p_input->p->p_ressource, p_owner->p_vout, NULL );
input_SendEventVout( p_owner->p_input ); input_SendEventVout( p_owner->p_input );
} }
...@@ -2054,7 +2056,7 @@ static void DeleteDecoder( decoder_t * p_dec ) ...@@ -2054,7 +2056,7 @@ static void DeleteDecoder( decoder_t * p_dec )
{ {
vout_thread_t *p_vout; vout_thread_t *p_vout;
p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
if( p_vout ) if( p_vout )
{ {
if( p_owner->p_spu_vout == p_vout ) if( p_owner->p_spu_vout == p_vout )
...@@ -2117,7 +2119,7 @@ static vout_thread_t *aout_request_vout( void *p_private, ...@@ -2117,7 +2119,7 @@ static vout_thread_t *aout_request_vout( void *p_private,
{ {
decoder_t *p_dec = p_private; decoder_t *p_dec = p_private;
p_vout = vout_Request( p_dec, p_vout, p_fmt ); p_vout = input_ressource_RequestVout( p_dec->p_owner->p_input->p->p_ressource, p_vout, p_fmt );
input_SendEventVout( p_dec->p_owner->p_input ); input_SendEventVout( p_dec->p_owner->p_input );
return p_vout; return p_vout;
...@@ -2180,6 +2182,8 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples ) ...@@ -2180,6 +2182,8 @@ static aout_buffer_t *aout_new_buffer( decoder_t *p_dec, int i_samples )
request_vout.p_private = p_dec; request_vout.p_private = p_dec;
p_aout = p_owner->p_aout; p_aout = p_owner->p_aout;
if( !p_aout )
p_aout = input_ressource_RequestAout( p_owner->p_input->p->p_ressource, NULL );
p_aout_input = aout_DecNew( p_dec, &p_aout, p_aout_input = aout_DecNew( p_dec, &p_aout,
&format, &p_dec->fmt_out.audio_replay_gain, &request_vout ); &format, &p_dec->fmt_out.audio_replay_gain, &request_vout );
...@@ -2291,7 +2295,8 @@ static picture_t *vout_new_buffer( decoder_t *p_dec ) ...@@ -2291,7 +2295,8 @@ static picture_t *vout_new_buffer( decoder_t *p_dec )
p_owner->p_vout = NULL; p_owner->p_vout = NULL;
vlc_mutex_unlock( &p_owner->lock ); vlc_mutex_unlock( &p_owner->lock );
p_vout = vout_Request( p_dec, p_vout, &p_dec->fmt_out.video ); p_vout = input_ressource_RequestVout( p_owner->p_input->p->p_ressource,
p_vout, &p_dec->fmt_out.video );
vlc_mutex_lock( &p_owner->lock ); vlc_mutex_lock( &p_owner->lock );
p_owner->p_vout = p_vout; p_owner->p_vout = p_vout;
...@@ -2378,7 +2383,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec ) ...@@ -2378,7 +2383,7 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec )
if( p_dec->b_die || p_dec->b_error ) if( p_dec->b_die || p_dec->b_error )
break; break;
p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
if( p_vout ) if( p_vout )
break; break;
...@@ -2423,7 +2428,7 @@ static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic ) ...@@ -2423,7 +2428,7 @@ static void spu_del_buffer( decoder_t *p_dec, subpicture_t *p_subpic )
decoder_owner_sys_t *p_owner = p_dec->p_owner; decoder_owner_sys_t *p_owner = p_dec->p_owner;
vout_thread_t *p_vout = NULL; vout_thread_t *p_vout = NULL;
p_vout = vlc_object_find( p_dec, VLC_OBJECT_VOUT, FIND_ANYWHERE ); p_vout = input_ressource_HoldVout( p_owner->p_input->p->p_ressource );
if( !p_vout || p_owner->p_spu_vout != p_vout ) if( !p_vout || p_owner->p_spu_vout != p_vout )
{ {
if( p_vout ) if( p_vout )
......
...@@ -43,6 +43,7 @@ ...@@ -43,6 +43,7 @@
#include "demux.h" #include "demux.h"
#include "stream.h" #include "stream.h"
#include "item.h" #include "item.h"
#include "ressource.h"
#include <vlc_sout.h> #include <vlc_sout.h>
#include "../stream_output/stream_output.h" #include "../stream_output/stream_output.h"
...@@ -212,6 +213,10 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -212,6 +213,10 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
p_input->p->i_slave = 0; p_input->p->i_slave = 0;
p_input->p->slave = NULL; p_input->p->slave = NULL;
/* */
p_input->p->p_ressource = input_ressource_New();
input_ressource_SetInput( p_input->p->p_ressource, p_input );
/* Init control buffer */ /* Init control buffer */
vlc_mutex_init( &p_input->p->lock_control ); vlc_mutex_init( &p_input->p->lock_control );
vlc_cond_init( &p_input->p->wait_control ); vlc_cond_init( &p_input->p->wait_control );
...@@ -294,7 +299,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item, ...@@ -294,7 +299,7 @@ static input_thread_t *Create( vlc_object_t *p_parent, input_item_t *p_item,
/* */ /* */
if( p_sout ) if( p_sout )
p_input->p->p_sout = p_sout; input_ressource_RequestSout( p_input->p->p_ressource, p_sout, NULL );
memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) ); memset( &p_input->p->counters, 0, sizeof( p_input->p->counters ) );
vlc_mutex_init( &p_input->p->counters.counters_lock ); vlc_mutex_init( &p_input->p->counters.counters_lock );
...@@ -321,10 +326,10 @@ static void Destructor( input_thread_t * p_input ) ...@@ -321,10 +326,10 @@ static void Destructor( input_thread_t * p_input )
stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING ); stats_TimerDump( p_input, STATS_TIMER_INPUT_LAUNCHING );
stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING ); stats_TimerClean( p_input, STATS_TIMER_INPUT_LAUNCHING );
#ifdef ENABLE_SOUT
if( p_input->p->p_sout ) if( p_input->p->p_ressource )
sout_DeleteInstance( p_input->p->p_sout ); input_ressource_Delete( p_input->p->p_ressource );
#endif
vlc_gc_decref( p_input->p->p_item ); vlc_gc_decref( p_input->p->p_item );
vlc_mutex_destroy( &p_input->p->counters.counters_lock ); vlc_mutex_destroy( &p_input->p->counters.counters_lock );
...@@ -451,13 +456,17 @@ void input_StopThread( input_thread_t *p_input ) ...@@ -451,13 +456,17 @@ void input_StopThread( input_thread_t *p_input )
input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL ); input_ControlPush( p_input, INPUT_CONTROL_SET_DIE, NULL );
} }
sout_instance_t *input_DetachSout( input_thread_t *p_input ) input_ressource_t *input_DetachRessource( input_thread_t *p_input )
{ {
assert( p_input->b_dead ); assert( p_input->b_dead );
sout_instance_t *p_sout = p_input->p->p_sout;
vlc_object_detach( p_sout ); input_ressource_t *p_ressource = p_input->p->p_ressource;
input_ressource_SetInput( p_ressource, NULL );
p_input->p->p_ressource = NULL;
p_input->p->p_sout = NULL; p_input->p->p_sout = NULL;
return p_sout;
return p_ressource;
} }
/** /**
...@@ -843,46 +852,21 @@ static void InitStatistics( input_thread_t * p_input ) ...@@ -843,46 +852,21 @@ static void InitStatistics( input_thread_t * p_input )
#ifdef ENABLE_SOUT #ifdef ENABLE_SOUT
static int InitSout( input_thread_t * p_input ) static int InitSout( input_thread_t * p_input )
{ {
char *psz; if( p_input->b_preparsing )
return VLC_SUCCESS;
if( p_input->b_preparsing ) return VLC_SUCCESS;
/* Find a usable sout and attach it to p_input */ /* Find a usable sout and attach it to p_input */
psz = var_GetNonEmptyString( p_input, "sout" ); char *psz = var_GetNonEmptyString( p_input, "sout" );
if( psz && strncasecmp( p_input->p->p_item->psz_uri, "vlc:", 4 ) ) if( psz && strncasecmp( p_input->p->p_item->psz_uri, "vlc:", 4 ) )
{ {
/* Check the validity of the provided sout */ p_input->p->p_sout = input_ressource_RequestSout( p_input->p->p_ressource, NULL, psz );
if( p_input->p->p_sout ) if( !p_input->p->p_sout )
{ {
if( strcmp( p_input->p->p_sout->psz_sout, psz ) ) input_ChangeState( p_input, ERROR_S );
{ msg_Err( p_input, "cannot start stream output instance, " \
msg_Dbg( p_input, "destroying unusable sout" ); "aborting" );
free( psz );
sout_DeleteInstance( p_input->p->p_sout ); return VLC_EGENERIC;
p_input->p->p_sout = NULL;
}
}
if( p_input->p->p_sout )
{
/* Reuse it */
msg_Dbg( p_input, "sout keep: reusing sout" );
msg_Dbg( p_input, "sout keep: you probably want to use "
"gather stream_out" );
vlc_object_attach( p_input->p->p_sout, p_input );
}
else
{
/* Create a new one */
p_input->p->p_sout = sout_NewInstance( p_input, psz );
if( !p_input->p->p_sout )
{
input_ChangeState( p_input, ERROR_S );
msg_Err( p_input, "cannot start stream output instance, " \
"aborting" );
free( psz );
return VLC_EGENERIC;
}
} }
if( libvlc_stats( p_input ) ) if( libvlc_stats( p_input ) )
{ {
...@@ -894,12 +878,9 @@ static int InitSout( input_thread_t * p_input ) ...@@ -894,12 +878,9 @@ static int InitSout( input_thread_t * p_input )
1000000; 1000000;
} }
} }
else if( p_input->p->p_sout ) else
{ {
msg_Dbg( p_input, "destroying useless sout" ); input_ressource_RequestSout( p_input->p->p_ressource, NULL, NULL );
sout_DeleteInstance( p_input->p->p_sout );
p_input->p->p_sout = NULL;
} }
free( psz ); free( psz );
...@@ -1254,13 +1235,13 @@ error: ...@@ -1254,13 +1235,13 @@ error:
es_out_Delete( p_input->p->p_es_out ); es_out_Delete( p_input->p->p_es_out );
if( p_input->p->p_es_out_display ) if( p_input->p->p_es_out_display )
es_out_Delete( p_input->p->p_es_out_display ); es_out_Delete( p_input->p->p_es_out_display );
#ifdef ENABLE_SOUT if( p_input->p->p_ressource )
if( p_input->p->p_sout )
{ {
vlc_object_detach( p_input->p->p_sout ); if( p_input->p->p_sout )
sout_DeleteInstance( p_input->p->p_sout ); input_ressource_RequestSout( p_input->p->p_ressource,
p_input->p->p_sout, NULL );
input_ressource_SetInput( p_input->p->p_ressource, NULL );
} }
#endif
if( !p_input->b_preparsing && libvlc_stats( p_input ) ) if( !p_input->b_preparsing && libvlc_stats( p_input ) )
{ {
...@@ -1386,8 +1367,6 @@ static void End( input_thread_t * p_input ) ...@@ -1386,8 +1367,6 @@ static void End( input_thread_t * p_input )
CL_CO( sout_sent_packets ); CL_CO( sout_sent_packets );
CL_CO( sout_sent_bytes ); CL_CO( sout_sent_bytes );
CL_CO( sout_send_bitrate ); CL_CO( sout_send_bitrate );
vlc_object_detach( p_input->p->p_sout );
} }
#undef CL_CO #undef CL_CO
} }
...@@ -1399,6 +1378,11 @@ static void End( input_thread_t * p_input ) ...@@ -1399,6 +1378,11 @@ static void End( input_thread_t * p_input )
TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment ); TAB_CLEAN( p_input->p->i_attachment, p_input->p->attachment );
} }
/* */
input_ressource_RequestSout( p_input->p->p_ressource,
p_input->p->p_sout, NULL );
input_ressource_SetInput( p_input->p->p_ressource, NULL );
/* Tell we're dead */ /* Tell we're dead */
input_SendEventDead( p_input ); input_SendEventDead( p_input );
} }
......
...@@ -42,11 +42,36 @@ void input_item_SetArtFetched( input_item_t *p_i, bool b_art_fetched ); ...@@ -42,11 +42,36 @@ void input_item_SetArtFetched( input_item_t *p_i, bool b_art_fetched );
* FIXME it should NOT be defined here or not coded in misc/stats.c */ * FIXME it should NOT be defined here or not coded in misc/stats.c */
input_stats_t *stats_NewInputStats( input_thread_t *p_input ); input_stats_t *stats_NewInputStats( input_thread_t *p_input );
/**
* This defines an opaque input ressource handler.
*/
typedef struct input_ressource_t input_ressource_t;
/**
* This function releases an input_ressource_t and all associated ressources.
*/
void input_ressource_Delete( input_ressource_t * );
/**
* This function return the current sout (if any) from the ressource
* and stop tracking it.
*
* You are then responsible of its release.
*/
sout_instance_t *input_ressource_ExtractSout( input_ressource_t *p_ressource );
/* input.c */ /* input.c */
#define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d) #define input_CreateThreadExtended(a,b,c,d) __input_CreateThreadExtended(VLC_OBJECT(a),b,c,d)
input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * ); input_thread_t *__input_CreateThreadExtended ( vlc_object_t *, input_item_t *, const char *, sout_instance_t * );
sout_instance_t * input_DetachSout( input_thread_t *p_input ); /**
* This function detaches ressources from a dead input.
*
* It MUST be called on a dead input (p_input->b_dead true) otherwise
* it will assert.
* It does not support concurrent calls.
*/
input_ressource_t *input_DetachRessource( input_thread_t * );
/* */ /* */
typedef enum typedef enum
......
...@@ -123,6 +123,9 @@ struct input_thread_private_t ...@@ -123,6 +123,9 @@ struct input_thread_private_t
int i_slave; int i_slave;
input_source_t **slave; input_source_t **slave;
/* Ressources */
input_ressource_t *p_ressource;
/* Stats counters */ /* Stats counters */
struct { struct {
counter_t *p_read_packets; counter_t *p_read_packets;
......
/*****************************************************************************
* ressource.c
*****************************************************************************
* Copyright (C) 2008 Laurent Aimar
* $Id$
*
* 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
* (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.
*
* 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.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include <vlc_common.h>
#include <vlc_vout.h>
#include <vlc_aout.h>
#include <vlc_sout.h>
#include "../libvlc.h"
#include "../stream_output/stream_output.h"
#include "../audio_output/aout_internal.h"
#include "input_interface.h"
#include "ressource.h"
struct input_ressource_t
{
vlc_mutex_t lock;
input_thread_t *p_input;
sout_instance_t *p_sout;
int i_vout;
vout_thread_t **pp_vout;
vout_thread_t *p_vout_free;
aout_instance_t *p_aout;
};
/* */
static void DestroySout( input_ressource_t *p_ressource )
{
if( p_ressource->p_sout )
sout_DeleteInstance( p_ressource->p_sout );
p_ressource->p_sout = NULL;
}
static sout_instance_t *ExtractSout( input_ressource_t *p_ressource )
{
sout_instance_t *p_sout = p_ressource->p_sout;
p_ressource->p_sout = NULL;
return p_sout;
}
static sout_instance_t *RequestSout( input_ressource_t *p_ressource,
sout_instance_t *p_sout, const char *psz_sout )
{
assert( p_ressource->p_input );
assert( !p_sout || ( !p_ressource->p_sout && !psz_sout ) );
if( !p_sout && !psz_sout )
{
if( p_ressource->p_sout )
msg_Dbg( p_ressource->p_input, "destroying useless sout" );
DestroySout( p_ressource );
return NULL;
}
/* Check the validity of the sout */
if( p_ressource->p_sout &&
strcmp( p_ressource->p_sout->psz_sout, psz_sout ) )
{
msg_Dbg( p_ressource->p_input, "destroying unusable sout" );
DestroySout( p_ressource );
}
if( psz_sout )
{
if( p_ressource->p_sout )
{
/* Reuse it */
msg_Dbg( p_ressource->p_input, "reusing sout" );
msg_Dbg( p_ressource->p_input, "you probably want to use gather stream_out" );
vlc_object_attach( p_ressource->p_sout, p_ressource->p_input );
}
else
{
/* Create a new one */
p_ressource->p_sout = sout_NewInstance( p_ressource->p_input, psz_sout );
}
return ExtractSout( p_ressource );
}
else
{
vlc_object_detach( p_sout );
p_ressource->p_sout = p_sout;
return NULL;
}
}
/* */
static void DestroyVout( input_ressource_t *p_ressource )
{
assert( p_ressource->i_vout == 0 );
if( p_ressource->p_vout_free )
vout_CloseAndRelease( p_ressource->p_vout_free );
p_ressource->p_vout_free = NULL;
}
static vout_thread_t *RequestVout( input_ressource_t *p_ressource,
vout_thread_t *p_vout, video_format_t *p_fmt )
{
assert( p_ressource->p_input );
if( !p_vout && !p_fmt )
{
if( p_ressource->p_vout_free )
{
msg_Err( p_ressource->p_input, "destroying useless vout" );
vout_CloseAndRelease( p_ressource->p_vout_free );
p_ressource->p_vout_free = NULL;
}
return NULL;
}
if( p_fmt )
{
/* */
if( !p_vout && p_ressource->p_vout_free )
{
msg_Err( p_ressource->p_input, "trying to reuse free vout" );
p_vout = p_ressource->p_vout_free;
p_ressource->p_vout_free = NULL;
}
else if( p_vout )
{
assert( p_vout != p_ressource->p_vout_free );
TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
}
/* */
p_vout = vout_Request( p_ressource->p_input, p_vout, p_fmt );
if( !p_vout )
return NULL;
TAB_APPEND( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
return p_vout;
}
else
{
assert( p_vout );
TAB_REMOVE( p_ressource->i_vout, p_ressource->pp_vout, p_vout );
if( p_ressource->p_vout_free )
{
msg_Err( p_ressource->p_input, "detroying vout (already one saved)" );
vout_CloseAndRelease( p_vout );
}
else
{
msg_Err( p_ressource->p_input, "saving a free vout" );
p_ressource->p_vout_free = p_vout;
}
return NULL;
}
}
static vout_thread_t *HoldVout( input_ressource_t *p_ressource )
{
if( p_ressource->i_vout <= 0 )
return NULL;
/* TODO FIXME: p_ressource->pp_vout order is NOT stable */
vout_thread_t *p_vout = p_ressource->pp_vout[0];
vlc_object_hold( p_vout );
return p_vout;
}
/* */
static void DestroyAout( input_ressource_t *p_ressource )
{
if( p_ressource->p_aout )
vlc_object_release( p_ressource->p_aout );
p_ressource->p_aout = NULL;
}
static aout_instance_t *RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
{
assert( p_ressource->p_input );
if( p_aout )
{
msg_Err( p_ressource->p_input, "releasing aout" );
vlc_object_release( p_aout );
return NULL;
}
else
{
if( !p_ressource->p_aout )
{
msg_Err( p_ressource->p_input, "creating aout" );
p_ressource->p_aout = aout_New( p_ressource->p_input );
}
else
{
msg_Err( p_ressource->p_input, "reusing aout" );
vlc_object_attach( p_ressource->p_aout, p_ressource->p_input );
}
if( !p_ressource->p_aout )
return NULL;
vlc_object_hold( p_ressource->p_aout );
return p_ressource->p_aout;
}
}
/* */
input_ressource_t *input_ressource_New( void )
{
input_ressource_t *p_ressource = calloc( 1, sizeof(*p_ressource) );
if( !p_ressource )
return NULL;
vlc_mutex_init( &p_ressource->lock );
return p_ressource;
}
void input_ressource_Delete( input_ressource_t *p_ressource )
{
DestroySout( p_ressource );
DestroyVout( p_ressource );
DestroyAout( p_ressource );
vlc_mutex_destroy( &p_ressource->lock );
free( p_ressource );
}
void input_ressource_SetInput( input_ressource_t *p_ressource, input_thread_t *p_input )
{
vlc_mutex_lock( &p_ressource->lock );
if( p_ressource->p_input && !p_input )
{
if( p_ressource->p_aout )
vlc_object_detach( p_ressource->p_aout );
assert( p_ressource->i_vout == 0 );
if( p_ressource->p_vout_free )
vlc_object_detach( p_ressource->p_vout_free );
if( p_ressource->p_sout )
vlc_object_detach( p_ressource->p_sout );
}
/* */
p_ressource->p_input = p_input;
vlc_mutex_unlock( &p_ressource->lock );
}
vout_thread_t *input_ressource_RequestVout( input_ressource_t *p_ressource,
vout_thread_t *p_vout, video_format_t *p_fmt )
{
vlc_mutex_lock( &p_ressource->lock );
vout_thread_t *p_ret = RequestVout( p_ressource, p_vout, p_fmt );
vlc_mutex_unlock( &p_ressource->lock );
return p_ret;
}
vout_thread_t *input_ressource_HoldVout( input_ressource_t *p_ressource )
{
vlc_mutex_lock( &p_ressource->lock );
vout_thread_t *p_ret = HoldVout( p_ressource );
vlc_mutex_unlock( &p_ressource->lock );
return p_ret;
}
/* */
aout_instance_t *input_ressource_RequestAout( input_ressource_t *p_ressource, aout_instance_t *p_aout )
{
vlc_mutex_lock( &p_ressource->lock );
aout_instance_t *p_ret = RequestAout( p_ressource, p_aout );
vlc_mutex_unlock( &p_ressource->lock );
return p_ret;
}
/* */
sout_instance_t *input_ressource_RequestSout( input_ressource_t *p_ressource, sout_instance_t *p_sout, const char *psz_sout )
{
vlc_mutex_lock( &p_ressource->lock );
sout_instance_t *p_ret = RequestSout( p_ressource, p_sout, psz_sout );
vlc_mutex_unlock( &p_ressource->lock );
return p_ret;
}
sout_instance_t *input_ressource_ExtractSout( input_ressource_t *p_ressource )
{
vlc_mutex_lock( &p_ressource->lock );
sout_instance_t *p_ret = ExtractSout( p_ressource );
vlc_mutex_unlock( &p_ressource->lock );
return p_ret;
}
/*****************************************************************************
* ressource.h
*****************************************************************************
* Copyright (C) 2008 Laurent Aimar
* $Id$
*
* 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
* (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.
*
* 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.
*****************************************************************************/
#if defined(__PLUGIN__) || defined(__BUILTIN__) || !defined(__LIBVLC__)
# error This header file can only be included from LibVLC.
#endif
#ifndef _INPUT_RESSOURCE_H
#define _INPUT_RESSOURCE_H 1
#include <vlc_common.h>
/**
* This function creates an empty input_ressource_t.
*/
input_ressource_t *input_ressource_New( void );
/**
* This function set the associated input.
*/
void input_ressource_SetInput( input_ressource_t *, input_thread_t * );
/**
* This function handles sout request.
*/
sout_instance_t *input_ressource_RequestSout( input_ressource_t *, sout_instance_t *, const char *psz_sout );
/**
* This function handles aout request.
*/
aout_instance_t *input_ressource_RequestAout( input_ressource_t *, aout_instance_t * );
/**
* This function handles vout request.
*/
vout_thread_t *input_ressource_RequestVout( input_ressource_t *, vout_thread_t *, video_format_t * );
/**
* This function return the current vout if any.
*
* You must call vlc_object_release on the value returned (if non NULL).
*/
vout_thread_t *input_ressource_HoldVout( input_ressource_t * );
#endif
...@@ -764,9 +764,14 @@ static void vlm_MediaInstanceDelete( vlm_media_instance_sys_t *p_instance ) ...@@ -764,9 +764,14 @@ static void vlm_MediaInstanceDelete( vlm_media_instance_sys_t *p_instance )
input_thread_t *p_input = p_instance->p_input; input_thread_t *p_input = p_instance->p_input;
if( p_input ) if( p_input )
{ {
input_ressource_t *p_ressource;
input_StopThread( p_input ); input_StopThread( p_input );
vlc_thread_join( p_input ); vlc_thread_join( p_input );
p_instance->p_sout = input_DetachSout( p_input );
p_ressource = input_DetachRessource( p_input );
input_ressource_Delete( p_ressource );
vlc_object_release( p_input ); vlc_object_release( p_input );
} }
if( p_instance->p_sout ) if( p_instance->p_sout )
...@@ -834,6 +839,8 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char * ...@@ -834,6 +839,8 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
input_thread_t *p_input = p_instance->p_input; input_thread_t *p_input = p_instance->p_input;
if( p_input ) if( p_input )
{ {
input_ressource_t *p_ressource;
if( p_instance->i_index == i_input_index && if( p_instance->i_index == i_input_index &&
!p_input->b_eof && !p_input->b_error ) !p_input->b_eof && !p_input->b_error )
{ {
...@@ -844,13 +851,14 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char * ...@@ -844,13 +851,14 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
input_StopThread( p_input ); input_StopThread( p_input );
vlc_thread_join( p_input ); vlc_thread_join( p_input );
p_instance->p_sout = input_DetachSout( p_input );
p_ressource = input_DetachRessource( p_input );
vlc_object_release( p_input ); vlc_object_release( p_input );
if( !p_instance->b_sout_keep && p_instance->p_sout )
{ if( p_instance->b_sout_keep )
sout_DeleteInstance( p_instance->p_sout ); p_instance->p_sout = input_ressource_ExtractSout( p_ressource );
p_instance->p_sout = NULL; input_ressource_Delete( p_ressource );
}
} }
/* Start new one */ /* Start new one */
...@@ -865,6 +873,10 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char * ...@@ -865,6 +873,10 @@ static int vlm_ControlMediaInstanceStart( vlm_t *p_vlm, int64_t id, const char *
TAB_REMOVE( p_media->i_instance, p_media->instance, p_instance ); TAB_REMOVE( p_media->i_instance, p_media->instance, p_instance );
vlm_MediaInstanceDelete( p_instance ); vlm_MediaInstanceDelete( p_instance );
} }
else
{
p_instance->p_sout = NULL;
}
free( psz_log ); free( psz_log );
} }
......
...@@ -493,8 +493,12 @@ static int LoopInput( playlist_t *p_playlist ) ...@@ -493,8 +493,12 @@ static int LoopInput( playlist_t *p_playlist )
PL_DEBUG( "dead input" ); PL_DEBUG( "dead input" );
assert( p_sys->p_sout == NULL ); assert( p_sys->p_sout == NULL );
input_ressource_t *p_ressource = input_DetachRessource( p_input );
if( var_CreateGetBool( p_input, "sout-keep" ) ) if( var_CreateGetBool( p_input, "sout-keep" ) )
p_sys->p_sout = input_DetachSout( p_input ); p_sys->p_sout = input_ressource_ExtractSout( p_ressource );
input_ressource_Delete( p_ressource );
/* The DelCallback must be issued without playlist lock /* The DelCallback must be issued without playlist lock
* It is not a problem as we return VLC_EGENERIC */ * It is not a problem as we return VLC_EGENERIC */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment