[vlc-commits] vout: spu: store subpics entries into channels
Thomas Guillem
git at videolan.org
Tue Jun 11 07:58:50 CEST 2019
vlc | branch: master | Thomas Guillem <thomas at gllm.fr> | Tue Jun 4 11:52:39 2019 +0200| [2d8eb49a4387bf55a32c56993abb523e2a176632] | committer: Thomas Guillem
vout: spu: store subpics entries into channels
Refs #22273
> http://git.videolan.org/gitweb.cgi/vlc.git/?a=commit;h=2d8eb49a4387bf55a32c56993abb523e2a176632
---
src/video_output/vout_subpictures.c | 180 ++++++++++++++++--------------------
1 file changed, 82 insertions(+), 98 deletions(-)
diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index ce0340ae15..17cc6a7b77 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -59,11 +59,8 @@ typedef struct {
vlc_tick_t stop;
} spu_render_entry_t;
-typedef struct {
- subpicture_t *entries[VOUT_MAX_SUBPICTURES];
-} spu_heap_t;
-
struct spu_channel {
+ subpicture_t *entries[VOUT_MAX_SUBPICTURES];
size_t id;
};
@@ -76,8 +73,6 @@ struct spu_private_t {
spu_channel_vector channels;
vlc_clock_t *clock;
- spu_heap_t heap;
-
int channel; /**< number of subpicture channels registered */
filter_t *text; /**< text renderer module */
filter_t *scale_yuvp; /**< scaling module for YUVP */
@@ -107,57 +102,55 @@ struct spu_private_t {
vout_thread_t *vout;
};
-/*****************************************************************************
- * heap management
- *****************************************************************************/
-static void SpuHeapInit(spu_heap_t *heap)
+static void spu_channel_Init(struct spu_channel *channel, size_t id)
{
- for (int i = 0; i < VOUT_MAX_SUBPICTURES; i++)
- heap->entries[i] = NULL;
+ channel->id = id;
+
+ for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
+ channel->entries[i] = NULL;
}
-static int SpuHeapPush(spu_heap_t *heap, subpicture_t *subpic)
+static int spu_channel_Push(struct spu_channel *channel, subpicture_t *subpic)
{
- for (int i = 0; i < VOUT_MAX_SUBPICTURES; i++)
+ for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
{
- if (heap->entries[i])
+ if (channel->entries[i])
continue;
- heap->entries[i] = subpic;
+ channel->entries[i] = subpic;
return VLC_SUCCESS;
}
return VLC_EGENERIC;
}
-static void SpuHeapDeleteAt(spu_heap_t *heap, int index)
+static void spu_channel_DeleteAt(struct spu_channel *channel, size_t index)
{
- if (heap->entries[index])
+ if (channel->entries[index])
{
- subpicture_Delete(heap->entries[index]);
- heap->entries[index] = NULL;
+ subpicture_Delete(channel->entries[index]);
+ channel->entries[index] = NULL;
}
}
-static int SpuHeapDeleteSubpicture(spu_heap_t *heap, subpicture_t *subpic)
+static int spu_channel_DeleteSubpicture(struct spu_channel *channel,
+ subpicture_t *subpic)
{
for (int i = 0; i < VOUT_MAX_SUBPICTURES; i++)
{
- if (heap->entries[i] != subpic)
+ if (channel->entries[i] != subpic)
continue;
- SpuHeapDeleteAt(heap, i);
+ spu_channel_DeleteAt(channel, i);
return VLC_SUCCESS;
}
return VLC_EGENERIC;
}
-static void SpuHeapClean(spu_heap_t *heap)
+static void spu_channel_Clean(struct spu_channel *channel)
{
for (int i = 0; i < VOUT_MAX_SUBPICTURES; i++)
- {
- if (heap->entries[i])
- subpicture_Delete(heap->entries[i]);
- }
+ if (channel->entries[i])
+ subpicture_Delete(channel->entries[i]);
}
static struct spu_channel *spu_GetChannel(spu_t *spu, size_t channel_id)
@@ -569,18 +562,19 @@ static int SpuRenderCmp(const void *s0, const void *s1)
return r;
}
-static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
- spu_render_entry_t *render_entries, float rate)
+static int spu_channel_ConvertDates(struct spu_channel *channel,
+ vlc_clock_t *clock,
+ vlc_tick_t system_now,
+ spu_render_entry_t *render_entries,
+ float rate)
{
- spu_private_t *sys = spu->p;
-
/* Put every spu start and stop ts into the same array to convert them in
* one shot */
vlc_tick_t date_array[VOUT_MAX_SUBPICTURES *2];
size_t entry_count = 0;
for (size_t index = 0; index < VOUT_MAX_SUBPICTURES; index++)
{
- subpicture_t *current = sys->heap.entries[index];
+ subpicture_t *current = channel->entries[index];
if (!current)
continue;
@@ -593,8 +587,8 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
return 0;
/* Convert all spu ts */
- if (sys->clock)
- vlc_clock_ConvertArrayToSystem(sys->clock, system_now, date_array,
+ if (clock)
+ vlc_clock_ConvertArrayToSystem(clock, system_now, date_array,
entry_count * 2, rate);
/* Put back the converted ts into the output spu_render_entry_t struct */
@@ -602,7 +596,7 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
for (size_t index = 0; index < VOUT_MAX_SUBPICTURES; index++)
{
spu_render_entry_t *render_entry = &render_entries[index];
- subpicture_t *current = sys->heap.entries[index];
+ subpicture_t *current = channel->entries[index];
if (!current)
render_entry->subpicture = NULL;
@@ -618,7 +612,7 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
}
/*****************************************************************************
- * SpuSelectSubpictures: find the subpictures to display
+ * spu_SelectSubpictures: find the subpictures to display
*****************************************************************************
* This function parses all subpictures and decides which ones need to be
* displayed. If no picture has been selected, display_date will depend on
@@ -627,41 +621,28 @@ static int SpuConvertDates(spu_t *spu, vlc_tick_t system_now,
* to be removed if a newer one is available), which makes it a lot
* more difficult to guess if a subpicture has to be rendered or not.
*****************************************************************************/
-static void SpuSelectSubpictures(spu_t *spu,
- size_t *subpicture_count,
- spu_render_entry_t *subpicture_array,
- vlc_tick_t system_now,
- vlc_tick_t render_subtitle_date, float rate,
- bool ignore_osd)
+static spu_render_entry_t *
+spu_SelectSubpictures(spu_t *spu, vlc_tick_t system_now,
+ vlc_tick_t render_subtitle_date, float rate,
+ bool ignore_osd, size_t *subpicture_count)
{
spu_private_t *sys = spu->p;
+ assert(sys->channels.size >= VOUT_SPU_CHANNEL_OSD_COUNT);
+
/* */
*subpicture_count = 0;
-
- spu_render_entry_t render_entries[VOUT_MAX_SUBPICTURES];
- if (SpuConvertDates(spu, system_now, render_entries, rate) == 0)
- return;
-
- /* Create a list of channels */
- 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;
- size_t i;
- for (i = 0; i < channel_count; i++) {
- if (channel[i] == i_channel)
- break;
- }
- if (channel_count <= i)
- channel[channel_count++] = i_channel;
- }
+ spu_render_entry_t *subpicture_array =
+ vlc_alloc(sys->channels.size,
+ sizeof(spu_render_entry_t) * VOUT_MAX_SUBPICTURES);
+ if (!subpicture_array)
+ return NULL;
/* Fill up the subpicture_array arrays with relevant pictures */
- for (size_t i = 0; i < channel_count; i++) {
+ for (size_t i = 0; i < sys->channels.size; i++)
+ {
+ struct spu_channel *channel = &sys->channels.data[i];
+ spu_render_entry_t render_entries[VOUT_MAX_SUBPICTURES];
spu_render_entry_t available_entries[VOUT_MAX_SUBPICTURES];
bool is_available_late[VOUT_MAX_SUBPICTURES];
size_t available_count = 0;
@@ -672,17 +653,21 @@ static void SpuSelectSubpictures(spu_t *spu,
int64_t ephemer_subtitle_order = INT64_MIN;
int64_t ephemer_system_order = INT64_MIN;
+ if (spu_channel_ConvertDates(channel, sys->clock, system_now, render_entries,
+ rate) == 0)
+ continue;
+
/* Select available pictures */
for (int index = 0; index < VOUT_MAX_SUBPICTURES; index++) {
spu_render_entry_t *render_entry = &render_entries[index];
- subpicture_t *current = sys->heap.entries[index];
+ subpicture_t *current = channel->entries[index];
bool is_stop_valid;
bool is_late;
if (!current)
continue;
- if (current->i_channel != channel[i] ||
+ if ((current->i_channel >= 0 && (size_t) current->i_channel != channel->id) ||
(ignore_osd && !current->b_subtitle))
continue;
@@ -744,13 +729,14 @@ static void SpuSelectSubpictures(spu_t *spu,
}
if (is_rejeted)
- SpuHeapDeleteSubpicture(&sys->heap, current);
+ spu_channel_DeleteSubpicture(channel, current);
else
subpicture_array[(*subpicture_count)++] = *render_entry;
}
}
sys->last_sort_date = render_subtitle_date;
+ return subpicture_array;
}
@@ -1418,18 +1404,14 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
}
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 */
+ struct spu_channel channel;
+ spu_channel_Init(&channel, i);
+ vlc_vector_push(&sys->channels, channel);
}
/* Initialize private fields */
vlc_mutex_init(&sys->lock);
- SpuHeapInit(&sys->heap);
-
sys->clock = NULL;
atomic_init(&sys->margin, var_InheritInteger(spu, "sub-margin"));
@@ -1502,7 +1484,8 @@ void spu_Destroy(spu_t *spu)
free(sys->filter_chain_update);
/* Destroy all remaining subpictures */
- SpuHeapClean(&sys->heap);
+ for (size_t i = 0; i < sys->channels.size; ++i)
+ spu_channel_Clean(&sys->channels.data[i]);
vlc_vector_destroy(&sys->channels);
@@ -1623,8 +1606,12 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
vlc_mutex_lock(&sys->filter_chain_lock);
subpic = filter_chain_SubFilter(spu->p->filter_chain, subpic);
vlc_mutex_unlock(&sys->filter_chain_lock);
- if (!subpic)
+ if (!subpic || subpic->i_channel < 0)
+ {
+ if (subpic)
+ subpicture_Delete(subpic);
return;
+ }
/* SPU_DEFAULT_CHANNEL always reset itself */
if (subpic->i_channel == VOUT_SPU_CHANNEL_OSD)
@@ -1636,7 +1623,9 @@ void spu_PutSubpicture(spu_t *spu, subpicture_t *subpic)
/* */
vlc_mutex_lock(&sys->lock);
- if (SpuHeapPush(&sys->heap, subpic)) {
+ struct spu_channel *channel = spu_GetChannel(spu, subpic->i_channel);
+ if (spu_channel_Push(channel, subpic))
+ {
vlc_mutex_unlock(&sys->lock);
msg_Err(spu, "subpicture heap full");
subpicture_Delete(subpic);
@@ -1705,12 +1694,13 @@ subpicture_t *spu_Render(spu_t *spu,
vlc_mutex_lock(&sys->lock);
size_t subpicture_count;
- spu_render_entry_t subpicture_array[VOUT_MAX_SUBPICTURES];
/* Get an array of subpictures to render */
- SpuSelectSubpictures(spu, &subpicture_count, subpicture_array, system_now,
- render_subtitle_date, rate, ignore_osd);
- if (subpicture_count == 0) {
+ spu_render_entry_t *subpicture_array =
+ spu_SelectSubpictures(spu, system_now, render_subtitle_date, rate,
+ ignore_osd, &subpicture_count);
+ if (!subpicture_array)
+ {
vlc_mutex_unlock(&sys->lock);
return NULL;
}
@@ -1733,7 +1723,7 @@ subpicture_t *spu_Render(spu_t *spu,
subpic->b_subtitle ? render_subtitle_date : system_now);
/* Restore original dates, otherwise, the next call to
- * SpuSelectSubpictures() won't be able to select this subtitle */
+ * spu_SelectSubpictures() won't be able to select this subtitle */
subpic->i_start = i_original_start;
subpic->i_stop = i_original_stop;
}
@@ -1751,6 +1741,7 @@ subpicture_t *spu_Render(spu_t *spu,
system_now,
render_subtitle_date,
external_scale);
+ free(subpicture_array);
vlc_mutex_unlock(&sys->lock);
return render;
@@ -1766,9 +1757,8 @@ ssize_t spu_RegisterChannel(spu_t *spu)
if (channel_id != VOUT_SPU_CHANNEL_INVALID)
{
- struct spu_channel channel = {
- .id = channel_id,
- };
+ struct spu_channel channel;
+ spu_channel_Init(&channel, channel_id);
if (vlc_vector_push(&sys->channels, channel))
{
vlc_mutex_unlock(&sys->lock);
@@ -1781,25 +1771,18 @@ ssize_t spu_RegisterChannel(spu_t *spu)
return VOUT_SPU_CHANNEL_INVALID;
}
-static void spu_ClearChannelLocked(spu_t *spu, size_t channel_id)
+static void spu_channel_Clear(struct spu_channel *channel)
{
- spu_private_t *sys = spu->p;
-
for (size_t i = 0; i < VOUT_MAX_SUBPICTURES; i++)
- {
- subpicture_t *subpic = sys->heap.entries[i];
-
- if (subpic && subpic->i_channel >= 0
- && (size_t) subpic->i_channel == channel_id)
- SpuHeapDeleteAt(&sys->heap, i);
- }
+ spu_channel_DeleteAt(channel, 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);
+ struct spu_channel *channel = spu_GetChannel(spu, channel_id);
+ spu_channel_Clear(channel);
vlc_mutex_unlock(&sys->lock);
}
@@ -1808,7 +1791,8 @@ 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);
+ struct spu_channel *channel = spu_GetChannel(spu, channel_id);
+ spu_channel_Clear(channel);
vlc_vector_remove(&sys->channels, channel_id);
vlc_mutex_unlock(&sys->lock);
}
More information about the vlc-commits
mailing list