mirror of https://code.videolan.org/videolan/vlc
vout: spu: rework channel registration
Every registered channels need to be unregistered. The first 3 OSD channels don't need to be unregistered since they are automatically registered. sput_t now use a vector of struct spu_channel to keep its channels. This struct will contain parameters specific to a channel like the clock/delay/rate. The channel_id is now a ssize_t, -1 being invalid, 0, 1, 2 being the OSD channels, and [3; SSIZE_MAX] being registered spu channels. ES_OUT_VOUT_FLUSH_OVERLAY is renamed to ES_OUT_VOUT_DEL_OVERLAY since this control is only used to delete an overlay. Refs #22273
This commit is contained in:
parent
c08201c788
commit
9d592a58e4
|
@ -104,10 +104,9 @@ enum es_out_query_e
|
|||
|
||||
ES_OUT_VOUT_ADD_OVERLAY, /* arg1= es_out_id_t* (video es),
|
||||
* arg2= subpicture_t *,
|
||||
* arg3= int * (channel id), res= can fail */
|
||||
|
||||
ES_OUT_VOUT_FLUSH_OVERLAY, /* arg1= es_out_id_t* (video es),
|
||||
* arg2= int (channel id), res= can fail */
|
||||
* arg3= size_t * (channel id), res= can fail */
|
||||
ES_OUT_VOUT_DEL_OVERLAY, /* arg1= es_out_id_t* (video es),
|
||||
* arg2= size_t (channel id), res= can fail */
|
||||
|
||||
ES_OUT_SPU_SET_HIGHLIGHT, /* arg1= es_out_id_t* (spu es),
|
||||
arg2= const vlc_spu_highlight_t *, res=can fail */
|
||||
|
|
|
@ -50,7 +50,7 @@ struct spu_t
|
|||
spu_private_t *p;
|
||||
};
|
||||
|
||||
VLC_API spu_t * spu_Create( vlc_object_t *, vout_thread_t * );
|
||||
VLC_API spu_t * spu_Create( vlc_object_t *, vout_thread_t * );
|
||||
#define spu_Create(a,b) spu_Create(VLC_OBJECT(a),b)
|
||||
VLC_API void spu_Destroy( spu_t * );
|
||||
|
||||
|
@ -80,12 +80,13 @@ VLC_API subpicture_t * spu_Render( spu_t *, const vlc_fourcc_t *p_chroma_list,
|
|||
/**
|
||||
* It registers a new SPU channel.
|
||||
*/
|
||||
VLC_API int spu_RegisterChannel( spu_t * );
|
||||
VLC_API ssize_t spu_RegisterChannel( spu_t * );
|
||||
VLC_API void spu_UnregisterChannel( spu_t *, size_t );
|
||||
|
||||
/**
|
||||
* It clears all subpictures associated to a SPU channel.
|
||||
*/
|
||||
VLC_API void spu_ClearChannel( spu_t *, int );
|
||||
VLC_API void spu_ClearChannel( spu_t *, size_t );
|
||||
|
||||
/**
|
||||
* It changes the sub sources list
|
||||
|
|
|
@ -165,7 +165,7 @@ struct subpicture_t
|
|||
{
|
||||
/** \name Channel ID */
|
||||
/**@{*/
|
||||
int i_channel; /**< subpicture channel ID */
|
||||
ssize_t i_channel; /**< subpicture channel ID */
|
||||
/**@}*/
|
||||
|
||||
/** \name Type and flags
|
||||
|
|
|
@ -110,15 +110,16 @@ VLC_API void vout_PutPicture( vout_thread_t *, picture_t * );
|
|||
|
||||
/* Subpictures channels ID */
|
||||
#define VOUT_SPU_CHANNEL_INVALID (-1) /* Always fails in comparison */
|
||||
#define VOUT_SPU_CHANNEL_OSD 1 /* OSD channel is automatically cleared */
|
||||
#define VOUT_SPU_CHANNEL_OSD_HSLIDER 2
|
||||
#define VOUT_SPU_CHANNEL_OSD_VSLIDER 3
|
||||
#define VOUT_SPU_CHANNEL_AVAIL_FIRST 8 /* Registerable channels from this offset */
|
||||
#define VOUT_SPU_CHANNEL_OSD 0 /* OSD channel is automatically cleared */
|
||||
#define VOUT_SPU_CHANNEL_OSD_HSLIDER 1
|
||||
#define VOUT_SPU_CHANNEL_OSD_VSLIDER 2
|
||||
#define VOUT_SPU_CHANNEL_OSD_COUNT 3
|
||||
|
||||
/* */
|
||||
VLC_API void vout_PutSubpicture( vout_thread_t *, subpicture_t * );
|
||||
VLC_API int vout_RegisterSubpictureChannel( vout_thread_t * );
|
||||
VLC_API void vout_FlushSubpictureChannel( vout_thread_t *, int );
|
||||
VLC_API ssize_t vout_RegisterSubpictureChannel( vout_thread_t * );
|
||||
VLC_API void vout_UnregisterSubpictureChannel( vout_thread_t *, size_t );
|
||||
VLC_API void vout_FlushSubpictureChannel( vout_thread_t *, size_t );
|
||||
/**
|
||||
* This function will ensure that all ready/displayed pictures have at most
|
||||
* the provided date.
|
||||
|
|
|
@ -1531,7 +1531,7 @@ static int bluray_esOutControl(es_out_t *p_out, int i_query, va_list args)
|
|||
i_plane < MAX_OVERLAY &&
|
||||
esout_priv->overlay.channels[i_plane] != VOUT_SPU_CHANNEL_INVALID)
|
||||
{
|
||||
i_ret = es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_FLUSH_OVERLAY,
|
||||
i_ret = es_out_Control(esout_priv->p_dst_out, ES_OUT_VOUT_DEL_OVERLAY,
|
||||
esout_priv->overlay.p_video_es,
|
||||
esout_priv->overlay.channels[i_plane]);
|
||||
esout_priv->overlay.channels[i_plane] = VOUT_SPU_CHANNEL_INVALID;
|
||||
|
|
|
@ -166,7 +166,7 @@ static int vlclua_spu_channel_register( lua_State *L )
|
|||
if( !p_vout )
|
||||
return luaL_error( L, "Unable to find vout." );
|
||||
|
||||
int i_chan = vout_RegisterSubpictureChannel( p_vout );
|
||||
ssize_t i_chan = vout_RegisterSubpictureChannel( p_vout );
|
||||
vout_Release( p_vout );
|
||||
lua_pushinteger( L, i_chan );
|
||||
return 1;
|
||||
|
@ -174,12 +174,12 @@ static int vlclua_spu_channel_register( lua_State *L )
|
|||
|
||||
static int vlclua_spu_channel_clear( lua_State *L )
|
||||
{
|
||||
int i_chan = luaL_checkinteger( L, 1 );
|
||||
ssize_t i_chan = luaL_checkinteger( L, 1 );
|
||||
vout_thread_t *p_vout = vlclua_get_vout_internal(L);
|
||||
if( !p_vout )
|
||||
return luaL_error( L, "Unable to find vout." );
|
||||
|
||||
vout_FlushSubpictureChannel( p_vout, i_chan );
|
||||
vout_UnregisterSubpictureChannel( p_vout, i_chan );
|
||||
vout_Release(p_vout);
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ struct decoder_owner
|
|||
input_resource_t*p_resource;
|
||||
vlc_clock_t *p_clock;
|
||||
|
||||
int i_spu_channel;
|
||||
ssize_t i_spu_channel;
|
||||
int64_t i_spu_order;
|
||||
|
||||
sout_instance_t *p_sout;
|
||||
|
@ -611,8 +611,15 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
|
|||
msg_Warn( p_dec, "no vout found, dropping subpicture" );
|
||||
if( p_owner->p_vout )
|
||||
{
|
||||
vlc_mutex_lock( &p_owner->lock );
|
||||
if (p_owner->i_spu_channel != -1)
|
||||
{
|
||||
vout_UnregisterSubpictureChannel(p_owner->p_vout,
|
||||
p_owner->i_spu_channel);
|
||||
p_owner->i_spu_channel = -1;
|
||||
}
|
||||
vout_SetSubpictureClock(p_owner->p_vout, NULL);
|
||||
|
||||
vlc_mutex_lock( &p_owner->lock );
|
||||
vout_Release(p_owner->p_vout);
|
||||
p_owner->p_vout = NULL;
|
||||
vlc_mutex_unlock( &p_owner->lock );
|
||||
|
@ -622,19 +629,27 @@ static subpicture_t *spu_new_buffer( decoder_t *p_dec,
|
|||
|
||||
if( p_owner->p_vout != p_vout )
|
||||
{
|
||||
ssize_t old_spu_channel = p_owner->i_spu_channel;
|
||||
p_owner->i_spu_channel = vout_RegisterSubpictureChannel( p_vout );
|
||||
p_owner->i_spu_order = 0;
|
||||
|
||||
vlc_mutex_lock( &p_owner->lock );
|
||||
if( p_owner->p_vout )
|
||||
if (p_owner->i_spu_channel != -1)
|
||||
{
|
||||
vout_SetSubpictureClock(p_owner->p_vout, NULL);
|
||||
vout_Release(p_owner->p_vout);
|
||||
}
|
||||
p_owner->p_vout = p_vout;
|
||||
vlc_mutex_unlock( &p_owner->lock );
|
||||
if (p_owner->p_vout)
|
||||
{
|
||||
vout_SetSubpictureClock(p_owner->p_vout, NULL);
|
||||
if (old_spu_channel != -1)
|
||||
vout_UnregisterSubpictureChannel(p_owner->p_vout,
|
||||
old_spu_channel);
|
||||
}
|
||||
vlc_mutex_lock(&p_owner->lock);
|
||||
if (p_owner->p_vout)
|
||||
vout_Release(p_owner->p_vout);
|
||||
p_owner->p_vout = p_vout;
|
||||
vlc_mutex_unlock(&p_owner->lock);
|
||||
|
||||
vout_SetSubpictureClock( p_vout, p_owner->p_clock );
|
||||
vout_SetSubpictureClock(p_vout, p_owner->p_clock);
|
||||
}
|
||||
}
|
||||
else
|
||||
vout_Release(p_vout);
|
||||
|
@ -1483,7 +1498,10 @@ static void DecoderProcessFlush( decoder_t *p_dec )
|
|||
else if( p_dec->fmt_out.i_cat == SPU_ES )
|
||||
{
|
||||
if( p_owner->p_vout )
|
||||
{
|
||||
assert( p_owner->i_spu_channel >= 0 );
|
||||
vout_FlushSubpictureChannel( p_owner->p_vout, p_owner->i_spu_channel );
|
||||
}
|
||||
}
|
||||
|
||||
p_owner->i_preroll_end = (vlc_tick_t)INT64_MIN;
|
||||
|
@ -1782,7 +1800,7 @@ static decoder_t * CreateDecoder( vlc_object_t *p_parent,
|
|||
p_owner->p_resource = p_resource;
|
||||
p_owner->p_aout = NULL;
|
||||
p_owner->p_vout = NULL;
|
||||
p_owner->i_spu_channel = 0;
|
||||
p_owner->i_spu_channel = -1;
|
||||
p_owner->i_spu_order = 0;
|
||||
p_owner->p_sout = p_sout;
|
||||
p_owner->p_sout_input = NULL;
|
||||
|
@ -1969,8 +1987,9 @@ static void DeleteDecoder( decoder_t * p_dec )
|
|||
{
|
||||
if( p_owner->p_vout )
|
||||
{
|
||||
vout_FlushSubpictureChannel( p_owner->p_vout,
|
||||
p_owner->i_spu_channel );
|
||||
assert( p_owner->i_spu_channel > 0 );
|
||||
vout_UnregisterSubpictureChannel( p_owner->p_vout,
|
||||
p_owner->i_spu_channel );
|
||||
vout_SetSubpictureClock(p_owner->p_vout, NULL);
|
||||
vout_Release(p_owner->p_vout);
|
||||
}
|
||||
|
@ -2528,7 +2547,7 @@ void input_DecoderSetVoutMouseEvent( decoder_t *dec, vlc_mouse_event mouse_event
|
|||
}
|
||||
|
||||
int input_DecoderAddVoutOverlay( decoder_t *dec, subpicture_t *sub,
|
||||
int *channel )
|
||||
size_t *channel )
|
||||
{
|
||||
struct decoder_owner *owner = dec_get_owner( dec );
|
||||
assert( dec->fmt_in.i_cat == VIDEO_ES );
|
||||
|
@ -2541,8 +2560,15 @@ int input_DecoderAddVoutOverlay( decoder_t *dec, subpicture_t *sub,
|
|||
vlc_mutex_unlock( &owner->lock );
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
ssize_t channel_id =
|
||||
vout_RegisterSubpictureChannel( owner->p_vout );
|
||||
if (channel_id == -1)
|
||||
{
|
||||
vlc_mutex_unlock( &owner->lock );
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
sub->i_start = sub->i_stop = vlc_tick_now();
|
||||
sub->i_channel = *channel = vout_RegisterSubpictureChannel( owner->p_vout );
|
||||
sub->i_channel = *channel = channel_id;
|
||||
sub->i_order = 0;
|
||||
sub->b_ephemer = true;
|
||||
vout_PutSubpicture( owner->p_vout, sub );
|
||||
|
@ -2551,7 +2577,7 @@ int input_DecoderAddVoutOverlay( decoder_t *dec, subpicture_t *sub,
|
|||
return VLC_SUCCESS;
|
||||
}
|
||||
|
||||
int input_DecoderFlushVoutOverlay( decoder_t *dec, int channel )
|
||||
int input_DecoderDelVoutOverlay( decoder_t *dec, size_t channel )
|
||||
{
|
||||
struct decoder_owner *owner = dec_get_owner( dec );
|
||||
assert( dec->fmt_in.i_cat == VIDEO_ES );
|
||||
|
@ -2563,7 +2589,7 @@ int input_DecoderFlushVoutOverlay( decoder_t *dec, int channel )
|
|||
vlc_mutex_unlock( &owner->lock );
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
vout_FlushSubpictureChannel( owner->p_vout, channel );
|
||||
vout_UnregisterSubpictureChannel( owner->p_vout, channel );
|
||||
|
||||
vlc_mutex_unlock( &owner->lock );
|
||||
return VLC_SUCCESS;
|
||||
|
|
|
@ -110,7 +110,7 @@ bool input_DecoderHasFormatChanged( decoder_t *p_dec, es_format_t *p_fmt, vlc_me
|
|||
size_t input_DecoderGetFifoSize( decoder_t *p_dec );
|
||||
|
||||
void input_DecoderSetVoutMouseEvent( decoder_t *, vlc_mouse_event, void * );
|
||||
int input_DecoderAddVoutOverlay( decoder_t *, subpicture_t *, int * );
|
||||
int input_DecoderFlushVoutOverlay( decoder_t *, int );
|
||||
int input_DecoderAddVoutOverlay( decoder_t *, subpicture_t *, size_t * );
|
||||
int input_DecoderDelVoutOverlay( decoder_t *, size_t );
|
||||
|
||||
#endif
|
||||
|
|
|
@ -3131,17 +3131,17 @@ static int EsOutVaControlLocked( es_out_t *out, int i_query, va_list args )
|
|||
{
|
||||
es_out_id_t *p_es = va_arg( args, es_out_id_t * );
|
||||
subpicture_t *sub = va_arg( args, subpicture_t * );
|
||||
int *channel = va_arg( args, int * );
|
||||
size_t *channel = va_arg( args, size_t * );
|
||||
if( p_es && p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
|
||||
return input_DecoderAddVoutOverlay( p_es->p_dec, sub, channel );
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
case ES_OUT_VOUT_FLUSH_OVERLAY:
|
||||
case ES_OUT_VOUT_DEL_OVERLAY:
|
||||
{
|
||||
es_out_id_t *p_es = va_arg( args, es_out_id_t * );
|
||||
int channel = va_arg( args, int );
|
||||
size_t channel = va_arg( args, size_t );
|
||||
if( p_es && p_es->fmt.i_cat == VIDEO_ES && p_es->p_dec )
|
||||
return input_DecoderFlushVoutOverlay( p_es->p_dec, channel );
|
||||
return input_DecoderDelVoutOverlay( p_es->p_dec, channel );
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
case ES_OUT_SPU_SET_HIGHLIGHT:
|
||||
|
|
|
@ -662,15 +662,15 @@ static int ControlLocked( es_out_t *p_out, int i_query, va_list args )
|
|||
{
|
||||
es_out_id_t *p_es = va_arg( args, es_out_id_t * );
|
||||
subpicture_t *sub = va_arg( args, subpicture_t * );
|
||||
int *channel = va_arg( args, int * );
|
||||
size_t *channel = va_arg( args, size_t * );
|
||||
return es_out_Control( p_sys->p_out, ES_OUT_VOUT_ADD_OVERLAY,
|
||||
p_es->p_es, sub, channel );
|
||||
}
|
||||
case ES_OUT_VOUT_FLUSH_OVERLAY:
|
||||
case ES_OUT_VOUT_DEL_OVERLAY:
|
||||
{
|
||||
es_out_id_t *p_es = va_arg( args, es_out_id_t * );
|
||||
int channel = va_arg( args, int );
|
||||
return es_out_Control( p_sys->p_out, ES_OUT_VOUT_FLUSH_OVERLAY,
|
||||
size_t channel = va_arg( args, size_t );
|
||||
return es_out_Control( p_sys->p_out, ES_OUT_VOUT_DEL_OVERLAY,
|
||||
p_es->p_es, channel );
|
||||
}
|
||||
case ES_OUT_SPU_SET_HIGHLIGHT:
|
||||
|
|
|
@ -349,6 +349,7 @@ spu_ChangeSources
|
|||
spu_ChangeFilters
|
||||
spu_Render
|
||||
spu_RegisterChannel
|
||||
spu_UnregisterChannel
|
||||
spu_ClearChannel
|
||||
vlc_stream_directory_Attach
|
||||
vlc_stream_extractor_Attach
|
||||
|
@ -697,6 +698,7 @@ vout_GetPicture
|
|||
vout_PutPicture
|
||||
vout_PutSubpicture
|
||||
vout_RegisterSubpictureChannel
|
||||
vout_UnregisterSubpictureChannel
|
||||
vout_FlushSubpictureChannel
|
||||
vout_Flush
|
||||
vout_GetSnapshot
|
||||
|
|
|
@ -267,10 +267,10 @@ void vout_PutSubpicture( vout_thread_t *vout, subpicture_t *subpic )
|
|||
vlc_mutex_unlock(&sys->spu_lock);
|
||||
}
|
||||
|
||||
int vout_RegisterSubpictureChannel( vout_thread_t *vout )
|
||||
ssize_t vout_RegisterSubpictureChannel( vout_thread_t *vout )
|
||||
{
|
||||
assert(!vout->p->dummy);
|
||||
int channel = VOUT_SPU_CHANNEL_AVAIL_FIRST;
|
||||
ssize_t channel = VOUT_SPU_CHANNEL_INVALID;
|
||||
|
||||
vlc_mutex_lock(&vout->p->spu_lock);
|
||||
if (vout->p->spu)
|
||||
|
@ -280,6 +280,14 @@ int vout_RegisterSubpictureChannel( vout_thread_t *vout )
|
|||
return channel;
|
||||
}
|
||||
|
||||
void vout_UnregisterSubpictureChannel( vout_thread_t *vout, size_t channel )
|
||||
{
|
||||
assert(!vout->p->dummy);
|
||||
|
||||
if (vout->p->spu)
|
||||
spu_UnregisterChannel(vout->p->spu, channel);
|
||||
}
|
||||
|
||||
void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
|
||||
{
|
||||
assert(!vout->p->dummy);
|
||||
|
@ -289,7 +297,7 @@ void vout_SetSubpictureClock( vout_thread_t *vout, vlc_clock_t *clock )
|
|||
vlc_mutex_unlock(&vout->p->spu_lock);
|
||||
}
|
||||
|
||||
void vout_FlushSubpictureChannel( vout_thread_t *vout, int channel )
|
||||
void vout_FlushSubpictureChannel( vout_thread_t *vout, size_t channel )
|
||||
{
|
||||
vout_thread_sys_t *sys = vout->p;
|
||||
assert(!sys->dummy);
|
||||
|
|
|
@ -38,6 +38,7 @@
|
|||
#include <vlc_vout.h>
|
||||
#include <vlc_filter.h>
|
||||
#include <vlc_spu.h>
|
||||
#include <vlc_vector.h>
|
||||
|
||||
#include "../libvlc.h"
|
||||
#include "vout_internal.h"
|
||||
|
@ -62,10 +63,17 @@ typedef struct {
|
|||
subpicture_t *entries[VOUT_MAX_SUBPICTURES];
|
||||
} spu_heap_t;
|
||||
|
||||
struct spu_channel {
|
||||
size_t id;
|
||||
};
|
||||
|
||||
typedef struct VLC_VECTOR(struct spu_channel) spu_channel_vector;
|
||||
|
||||
struct spu_private_t {
|
||||
vlc_mutex_t lock; /* lock to protect all followings fields */
|
||||
input_thread_t *input;
|
||||
|
||||
spu_channel_vector channels;
|
||||
vlc_clock_t *clock;
|
||||
|
||||
spu_heap_t heap;
|
||||
|
@ -152,6 +160,42 @@ static void SpuHeapClean(spu_heap_t *heap)
|
|||
}
|
||||
}
|
||||
|
||||
static struct spu_channel *spu_GetChannel(spu_t *spu, size_t channel_id)
|
||||
{
|
||||
spu_private_t *sys = spu->p;
|
||||
|
||||
for (size_t i = 0; i < sys->channels.size; ++i)
|
||||
if (sys->channels.data[i].id == channel_id)
|
||||
return &sys->channels.data[i];
|
||||
|
||||
vlc_assert_unreachable();
|
||||
}
|
||||
|
||||
static ssize_t spu_GetFreeChannelId(spu_t *spu)
|
||||
{
|
||||
spu_private_t *sys = spu->p;
|
||||
|
||||
if (unlikely(sys->channels.size) > SSIZE_MAX)
|
||||
return VOUT_SPU_CHANNEL_INVALID;
|
||||
|
||||
size_t id;
|
||||
for (id = VOUT_SPU_CHANNEL_OSD_COUNT; id < sys->channels.size + 1; ++id)
|
||||
{
|
||||
bool used = false;
|
||||
for (size_t i = VOUT_SPU_CHANNEL_OSD_COUNT; i < sys->channels.size; ++i)
|
||||
{
|
||||
if (sys->channels.data[i].id == id)
|
||||
{
|
||||
used = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!used)
|
||||
return id;
|
||||
}
|
||||
return VOUT_SPU_CHANNEL_INVALID;
|
||||
}
|
||||
|
||||
static void FilterRelease(filter_t *filter)
|
||||
{
|
||||
if (filter->p_module)
|
||||
|
@ -491,6 +535,11 @@ static int IntegerCmp(int64_t i0, int64_t i1)
|
|||
{
|
||||
return i0 < i1 ? -1 : i0 > i1 ? 1 : 0;
|
||||
}
|
||||
|
||||
static int SSizeCmp(ssize_t i0, ssize_t i1)
|
||||
{
|
||||
return i0 < i1 ? -1 : i0 > i1 ? 1 : 0;
|
||||
}
|
||||
/**
|
||||
* This function compares 2 subpictures using the following properties
|
||||
* (ordered by priority)
|
||||
|
@ -514,7 +563,7 @@ static int SpuRenderCmp(const void *s0, const void *s1)
|
|||
if (!r)
|
||||
r = IntegerCmp(render_entry0->start, render_entry1->start);
|
||||
if (!r)
|
||||
r = IntegerCmp(subpic0->i_channel, subpic1->i_channel);
|
||||
r = SSizeCmp(subpic0->i_channel, subpic1->i_channel);
|
||||
if (!r)
|
||||
r = IntegerCmp(subpic0->i_order, subpic1->i_order);
|
||||
return r;
|
||||
|
@ -595,14 +644,14 @@ static void SpuSelectSubpictures(spu_t *spu,
|
|||
return;
|
||||
|
||||
/* Create a list of channels */
|
||||
int channel[VOUT_MAX_SUBPICTURES];
|
||||
int channel_count = 0;
|
||||
ssize_t channel[VOUT_MAX_SUBPICTURES];
|
||||
size_t channel_count = 0;
|
||||
|
||||
for (int index = 0; index < VOUT_MAX_SUBPICTURES; index++) {
|
||||
if (!sys->heap.entries[index])
|
||||
continue;
|
||||
const int i_channel = sys->heap.entries[index]->i_channel;
|
||||
int i;
|
||||
size_t i;
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
if (channel[i] == i_channel)
|
||||
break;
|
||||
|
@ -612,7 +661,7 @@ static void SpuSelectSubpictures(spu_t *spu,
|
|||
}
|
||||
|
||||
/* Fill up the subpicture_array arrays with relevant pictures */
|
||||
for (int i = 0; i < channel_count; i++) {
|
||||
for (size_t i = 0; i < channel_count; i++) {
|
||||
spu_render_entry_t available_entries[VOUT_MAX_SUBPICTURES];
|
||||
bool is_available_late[VOUT_MAX_SUBPICTURES];
|
||||
size_t available_count = 0;
|
||||
|
@ -1257,7 +1306,7 @@ static void UpdateSPU(spu_t *spu, const vlc_spu_highlight_t *hl)
|
|||
|
||||
static subpicture_t *sub_new_buffer(filter_t *filter)
|
||||
{
|
||||
int channel = *(int *)filter->owner.sys;
|
||||
ssize_t channel = *(ssize_t *)filter->owner.sys;
|
||||
|
||||
subpicture_t *subpicture = subpicture_New(NULL);
|
||||
if (subpicture)
|
||||
|
@ -1272,7 +1321,7 @@ static const struct filter_subpicture_callbacks sub_cbs = {
|
|||
static int SubSourceInit(filter_t *filter, void *data)
|
||||
{
|
||||
spu_t *spu = data;
|
||||
int *channel = malloc(sizeof (int));
|
||||
ssize_t *channel = malloc(sizeof (ssize_t));
|
||||
if (unlikely(channel == NULL))
|
||||
return VLC_ENOMEM;
|
||||
|
||||
|
@ -1285,7 +1334,7 @@ static int SubSourceInit(filter_t *filter, void *data)
|
|||
static int SubSourceClean(filter_t *filter, void *data)
|
||||
{
|
||||
spu_t *spu = data;
|
||||
int *channel = filter->owner.sys;
|
||||
ssize_t *channel = filter->owner.sys;
|
||||
|
||||
spu_ClearChannel(spu, *channel);
|
||||
free(channel);
|
||||
|
@ -1361,6 +1410,21 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
|
|||
/* Initialize spu fields */
|
||||
spu_private_t *sys = spu->p = (spu_private_t*)&spu[1];
|
||||
|
||||
vlc_vector_init(&sys->channels);
|
||||
if (!vlc_vector_reserve(&sys->channels, VOUT_SPU_CHANNEL_OSD_COUNT))
|
||||
{
|
||||
vlc_object_delete(spu);
|
||||
return NULL;
|
||||
}
|
||||
for (size_t i = 0; i < VOUT_SPU_CHANNEL_OSD_COUNT; ++i)
|
||||
{
|
||||
struct spu_channel channel = {
|
||||
.id = i,
|
||||
};
|
||||
bool success = vlc_vector_push(&sys->channels, channel);
|
||||
assert(success); /* already reserved */
|
||||
}
|
||||
|
||||
/* Initialize private fields */
|
||||
vlc_mutex_init(&sys->lock);
|
||||
|
||||
|
@ -1370,9 +1434,6 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
|
|||
|
||||
atomic_init(&sys->margin, var_InheritInteger(spu, "sub-margin"));
|
||||
|
||||
/* Register the default subpicture channel */
|
||||
sys->channel = VOUT_SPU_CHANNEL_AVAIL_FIRST;
|
||||
|
||||
sys->source_chain_update = NULL;
|
||||
sys->filter_chain_update = NULL;
|
||||
vlc_mutex_init(&sys->filter_chain_lock);
|
||||
|
@ -1443,6 +1504,8 @@ void spu_Destroy(spu_t *spu)
|
|||
/* Destroy all remaining subpictures */
|
||||
SpuHeapClean(&sys->heap);
|
||||
|
||||
vlc_vector_destroy(&sys->channels);
|
||||
|
||||
vlc_mutex_destroy(&sys->lock);
|
||||
|
||||
vlc_object_delete(spu);
|
||||
|
@ -1712,36 +1775,60 @@ void spu_OffsetSubtitleDate(spu_t *spu, vlc_tick_t duration)
|
|||
vlc_mutex_unlock(&sys->lock);
|
||||
}
|
||||
|
||||
int spu_RegisterChannel(spu_t *spu)
|
||||
ssize_t spu_RegisterChannel(spu_t *spu)
|
||||
{
|
||||
spu_private_t *sys = spu->p;
|
||||
|
||||
vlc_mutex_lock(&sys->lock);
|
||||
int channel = sys->channel++;
|
||||
|
||||
ssize_t channel_id = spu_GetFreeChannelId(spu);
|
||||
|
||||
if (channel_id != VOUT_SPU_CHANNEL_INVALID)
|
||||
{
|
||||
struct spu_channel channel = {
|
||||
.id = channel_id,
|
||||
};
|
||||
if (vlc_vector_push(&sys->channels, channel))
|
||||
{
|
||||
vlc_mutex_unlock(&sys->lock);
|
||||
return channel_id;
|
||||
}
|
||||
}
|
||||
|
||||
vlc_mutex_unlock(&sys->lock);
|
||||
|
||||
return channel;
|
||||
return VOUT_SPU_CHANNEL_INVALID;
|
||||
}
|
||||
|
||||
void spu_ClearChannel(spu_t *spu, int channel)
|
||||
static void spu_ClearChannelLocked(spu_t *spu, size_t channel_id)
|
||||
{
|
||||
spu_private_t *sys = spu->p;
|
||||
|
||||
vlc_mutex_lock(&sys->lock);
|
||||
|
||||
for (int i = 0; i < VOUT_MAX_SUBPICTURES; i++)
|
||||
for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
|
||||
{
|
||||
subpicture_t *subpic = sys->heap.entries[i];
|
||||
|
||||
if (!subpic)
|
||||
continue;
|
||||
if (subpic->i_channel != channel &&
|
||||
(channel != VOUT_SPU_CHANNEL_INVALID || subpic->i_channel == VOUT_SPU_CHANNEL_OSD))
|
||||
continue;
|
||||
|
||||
SpuHeapDeleteAt(&sys->heap, i);
|
||||
if (subpic && subpic->i_channel >= 0
|
||||
&& (size_t) subpic->i_channel == channel_id)
|
||||
SpuHeapDeleteAt(&sys->heap, i);
|
||||
}
|
||||
}
|
||||
|
||||
void spu_ClearChannel(spu_t *spu, size_t channel_id)
|
||||
{
|
||||
spu_private_t *sys = spu->p;
|
||||
vlc_mutex_lock(&sys->lock);
|
||||
spu_ClearChannelLocked(spu, channel_id);
|
||||
vlc_mutex_unlock(&sys->lock);
|
||||
}
|
||||
|
||||
void spu_UnregisterChannel(spu_t *spu, size_t channel_id)
|
||||
{
|
||||
spu_private_t *sys = spu->p;
|
||||
|
||||
vlc_mutex_lock(&sys->lock);
|
||||
spu_ClearChannelLocked(spu, channel_id);
|
||||
vlc_vector_remove(&sys->channels, channel_id);
|
||||
vlc_mutex_unlock(&sys->lock);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue