[vlc-devel] [PATCH 06/18] vout: spu: use vlc_clock_t
Thomas Guillem
thomas at gllm.fr
Thu Mar 7 15:25:28 CET 2019
The clock is not mandatory. If there is no clock (the transcode case for
example), spu ts won't be converted.
---
src/video_output/vout_internal.h | 4 +
src/video_output/vout_subpictures.c | 163 +++++++++++++++++++++-------
2 files changed, 128 insertions(+), 39 deletions(-)
diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h
index 4b67be606e..59da8d95cd 100644
--- a/src/video_output/vout_internal.h
+++ b/src/video_output/vout_internal.h
@@ -30,6 +30,7 @@
#include "vout_wrapper.h"
#include "statistic.h"
#include "chrono.h"
+#include "../clock/clock.h"
/* It should be high enough to absorbe jitter due to difficult picture(s)
* to decode but not too high as memory is not that cheap.
@@ -243,6 +244,9 @@ void vout_CloseWrapper(vout_thread_t *);
int spu_ProcessMouse(spu_t *, const vlc_mouse_t *, const video_format_t *);
void spu_Attach( spu_t *, input_thread_t *input );
void spu_Detach( spu_t * );
+void spu_clock_Set(spu_t *, vlc_clock_t *);
+void spu_clock_Reset(spu_t *);
+void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay);
void spu_ChangeMargin(spu_t *, int);
void spu_SetHighlight(spu_t *, const vlc_spu_highlight_t*);
diff --git a/src/video_output/vout_subpictures.c b/src/video_output/vout_subpictures.c
index 6d77d94f27..f32a5bd267 100644
--- a/src/video_output/vout_subpictures.c
+++ b/src/video_output/vout_subpictures.c
@@ -1,7 +1,7 @@
/*****************************************************************************
* vout_subpictures.c : subpicture management functions
*****************************************************************************
- * Copyright (C) 2000-2007 VLC authors and VideoLAN
+ * Copyright (C) 2000-2019 VLC authors, VideoLAN and Videolabs SAS
*
* Authors: Vincent Seguin <seguin at via.ecp.fr>
* Samuel Hocevar <sam at zoy.org>
@@ -52,7 +52,13 @@
/* Number of simultaneous subpictures */
#define VOUT_MAX_SUBPICTURES (__MAX(VOUT_MAX_PICTURES, SPU_MAX_PREPARE_TIME/5000))
-/* */
+/* Hold of subpicture with converted ts */
+typedef struct {
+ subpicture_t *subpicture;
+ vlc_tick_t start;
+ vlc_tick_t stop;
+} spu_render_entry_t;
+
typedef struct {
subpicture_t *subpicture;
bool reject;
@@ -66,6 +72,8 @@ struct spu_private_t {
vlc_mutex_t lock; /* lock to protect all followings fields */
input_thread_t *input;
+ vlc_clock_t *clock;
+
spu_heap_t heap;
int channel; /**< number of subpicture channels registered */
@@ -502,15 +510,17 @@ static int IntegerCmp(int64_t i0, int64_t i1)
*
* XXX spu_RenderSubpictures depends heavily on this order.
*/
-static int SubpictureCmp(const void *s0, const void *s1)
+static int SpuRenderCmp(const void *s0, const void *s1)
{
- subpicture_t *subpic0 = *(subpicture_t**)s0;
- subpicture_t *subpic1 = *(subpicture_t**)s1;
+ const spu_render_entry_t *render_entry0 = s0;
+ const spu_render_entry_t *render_entry1 = s1;
+ subpicture_t *subpic0 = render_entry0->subpicture;
+ subpicture_t *subpic1 = render_entry1->subpicture;
int r;
r = IntegerCmp(!subpic0->b_absolute, !subpic1->b_absolute);
if (!r)
- r = IntegerCmp(subpic0->i_start, subpic1->i_start);
+ r = IntegerCmp(render_entry0->start, render_entry1->start);
if (!r)
r = IntegerCmp(subpic0->i_channel, subpic1->i_channel);
if (!r)
@@ -518,6 +528,56 @@ static int SubpictureCmp(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)
+{
+ 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++)
+ {
+ spu_heap_entry_t *entry = &sys->heap.entry[index];
+ subpicture_t *current = entry->subpicture;
+
+ if (!current)
+ continue;
+
+ date_array[entry_count * 2] = current->i_start;
+ date_array[entry_count * 2 + 1] = current->i_stop;
+ entry_count++;
+ }
+ if (entry_count == 0)
+ return 0;
+
+ /* Convert all spu ts */
+ if (sys->clock)
+ vlc_clock_ConvertArrayToSystem(sys->clock, system_now, date_array,
+ entry_count * 2, rate);
+
+ /* Put back the converted ts into the output spu_render_entry_t struct */
+ entry_count = 0;
+ for (size_t index = 0; index < VOUT_MAX_SUBPICTURES; index++)
+ {
+ spu_render_entry_t *render_entry = &render_entries[index];
+ spu_heap_entry_t *entry = &sys->heap.entry[index];
+ subpicture_t *current = entry->subpicture;
+
+ if (!current)
+ render_entry->subpicture = NULL;
+ else
+ {
+ render_entry->subpicture = current;
+ render_entry->start = date_array[entry_count * 2];
+ render_entry->stop = date_array[entry_count * 2 + 1];
+ entry_count++;
+ }
+ }
+ return entry_count;
+}
+
/*****************************************************************************
* SpuSelectSubpictures: find the subpictures to display
*****************************************************************************
@@ -530,9 +590,9 @@ static int SubpictureCmp(const void *s0, const void *s1)
*****************************************************************************/
static void SpuSelectSubpictures(spu_t *spu,
size_t *subpicture_count,
- subpicture_t **subpicture_array,
+ spu_render_entry_t *subpicture_array,
vlc_tick_t system_now,
- vlc_tick_t render_subtitle_date,
+ vlc_tick_t render_subtitle_date, float rate,
bool ignore_osd)
{
spu_private_t *sys = spu->p;
@@ -540,6 +600,10 @@ static void SpuSelectSubpictures(spu_t *spu,
/* */
*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 */
int channel[VOUT_MAX_SUBPICTURES];
int channel_count = 0;
@@ -564,7 +628,7 @@ static void SpuSelectSubpictures(spu_t *spu,
/* Fill up the subpicture_array arrays with relevant pictures */
for (int i = 0; i < channel_count; i++) {
- subpicture_t *available_subpic[VOUT_MAX_SUBPICTURES];
+ spu_render_entry_t available_entries[VOUT_MAX_SUBPICTURES];
bool is_available_late[VOUT_MAX_SUBPICTURES];
size_t available_count = 0;
@@ -577,6 +641,7 @@ static void SpuSelectSubpictures(spu_t *spu,
/* Select available pictures */
for (int index = 0; index < VOUT_MAX_SUBPICTURES; index++) {
spu_heap_entry_t *entry = &sys->heap.entry[index];
+ spu_render_entry_t *render_entry = &render_entries[index];
subpicture_t *current = entry->subpicture;
bool is_stop_valid;
bool is_late;
@@ -593,31 +658,31 @@ static void SpuSelectSubpictures(spu_t *spu,
const vlc_tick_t render_date = current->b_subtitle ? render_subtitle_date : system_now;
if (render_date &&
- render_date < current->i_start) {
+ render_date < render_entry->start) {
/* Too early, come back next monday */
continue;
}
vlc_tick_t *ephemer_date_ptr = current->b_subtitle ? &ephemer_subtitle_date : &ephemer_osd_date;
int64_t *ephemer_order_ptr = current->b_subtitle ? &ephemer_subtitle_order : &ephemer_system_order;
- if (current->i_start >= *ephemer_date_ptr) {
- *ephemer_date_ptr = current->i_start;
+ if (render_entry->start >= *ephemer_date_ptr) {
+ *ephemer_date_ptr = render_entry->start;
if (current->i_order > *ephemer_order_ptr)
*ephemer_order_ptr = current->i_order;
}
- is_stop_valid = !current->b_ephemer || current->i_stop > current->i_start;
+ is_stop_valid = !current->b_ephemer || render_entry->stop > render_entry->start;
- is_late = is_stop_valid && current->i_stop <= render_date;
+ is_late = is_stop_valid && render_entry->stop <= render_date;
/* start_date will be used for correct automatic overlap support
* in case picture that should not be displayed anymore (display_time)
- * overlap with a picture to be displayed (current->i_start) */
+ * overlap with a picture to be displayed (render_entry->start) */
if (current->b_subtitle && !is_late && !current->b_ephemer)
- start_date = current->i_start;
+ start_date = render_entry->start;
/* */
- available_subpic[available_count] = current;
+ available_entries[available_count] = *render_entry;
is_available_late[available_count] = is_late;
available_count++;
}
@@ -630,7 +695,8 @@ static void SpuSelectSubpictures(spu_t *spu,
/* Select pictures to be displayed */
for (size_t index = 0; index < available_count; index++) {
- subpicture_t *current = available_subpic[index];
+ spu_render_entry_t *render_entry = &available_entries[index];
+ subpicture_t *current = render_entry->subpicture;
bool is_late = is_available_late[index];
const vlc_tick_t stop_date = current->b_subtitle ? __MAX(start_date, sys->last_sort_date) : system_now;
@@ -638,11 +704,11 @@ static void SpuSelectSubpictures(spu_t *spu,
const int64_t ephemer_order = current->b_subtitle ? ephemer_subtitle_order : ephemer_system_order;
/* Destroy late and obsolete ephemer subpictures */
- bool is_rejeted = is_late && current->i_stop <= stop_date;
+ bool is_rejeted = is_late && render_entry->stop <= stop_date;
if (current->b_ephemer) {
- if (current->i_start < ephemer_date)
+ if (render_entry->start < ephemer_date)
is_rejeted = true;
- else if (current->i_start == ephemer_date &&
+ else if (render_entry->start == ephemer_date &&
current->i_order < ephemer_order)
is_rejeted = true;
}
@@ -650,7 +716,7 @@ static void SpuSelectSubpictures(spu_t *spu,
if (is_rejeted)
SpuHeapDeleteSubpicture(&sys->heap, current);
else
- subpicture_array[(*subpicture_count)++] = current;
+ subpicture_array[(*subpicture_count)++] = *render_entry;
}
}
@@ -664,13 +730,14 @@ static void SpuSelectSubpictures(spu_t *spu,
*/
static void SpuRenderRegion(spu_t *spu,
subpicture_region_t **dst_ptr, spu_area_t *dst_area,
- subpicture_t *subpic, subpicture_region_t *region,
+ const spu_render_entry_t *entry, subpicture_region_t *region,
const spu_scale_t scale_size,
const vlc_fourcc_t *chroma_list,
const video_format_t *fmt,
const spu_area_t *subtitle_area, int subtitle_area_count,
vlc_tick_t render_date)
{
+ subpicture_t *subpic = entry->subpicture;
spu_private_t *sys = spu->p;
video_format_t fmt_original = region->fmt;
@@ -689,7 +756,7 @@ static void SpuRenderRegion(spu_t *spu,
if (region->fmt.i_chroma == VLC_CODEC_TEXT) {
SpuRenderText(spu, &restore_text, region,
chroma_list,
- render_date - subpic->i_start);
+ render_date - entry->start);
/* Check if the rendering has failed ... */
if (region->fmt.i_chroma == VLC_CODEC_TEXT)
@@ -971,11 +1038,11 @@ static void SpuRenderRegion(spu_t *spu,
dst->p_picture = picture_Hold(region_picture);
int fade_alpha = 255;
if (subpic->b_fade) {
- vlc_tick_t fade_start = subpic->i_start + 3 * (subpic->i_stop - subpic->i_start) / 4;
+ vlc_tick_t fade_start = entry->start + 3 * (entry->stop - entry->start) / 4;
- if (fade_start <= render_date && fade_start < subpic->i_stop)
- fade_alpha = 255 * (subpic->i_stop - render_date) /
- (subpic->i_stop - fade_start);
+ if (fade_start <= render_date && fade_start < entry->stop)
+ fade_alpha = 255 * (entry->stop - render_date) /
+ (entry->stop - fade_start);
}
dst->i_alpha = fade_alpha * subpic->i_alpha * region->i_alpha / 65025;
}
@@ -1004,7 +1071,7 @@ exit:
*/
static subpicture_t *SpuRenderSubpictures(spu_t *spu,
size_t i_subpicture,
- subpicture_t **pp_subpicture,
+ const spu_render_entry_t *p_entries,
const vlc_fourcc_t *chroma_list,
const video_format_t *fmt_dst,
const video_format_t *fmt_src,
@@ -1018,7 +1085,7 @@ static subpicture_t *SpuRenderSubpictures(spu_t *spu,
unsigned int subtitle_region_count = 0;
unsigned int region_count = 0;
for (unsigned i = 0; i < i_subpicture; i++) {
- const subpicture_t *subpic = pp_subpicture[i];
+ const subpicture_t *subpic = p_entries[i].subpicture;
unsigned count = 0;
for (subpicture_region_t *r = subpic->p_region; r != NULL; r = r->p_next)
@@ -1035,7 +1102,7 @@ static subpicture_t *SpuRenderSubpictures(spu_t *spu,
subpicture_t *output = subpicture_New(NULL);
if (!output)
return NULL;
- output->i_order = pp_subpicture[i_subpicture - 1]->i_order;
+ output->i_order = p_entries[i_subpicture - 1].subpicture->i_order;
output->i_original_picture_width = fmt_dst->i_visible_width;
output->i_original_picture_height = fmt_dst->i_visible_height;
subpicture_region_t **output_last_ptr = &output->p_region;
@@ -1051,8 +1118,9 @@ static subpicture_t *SpuRenderSubpictures(spu_t *spu,
subtitle_area = calloc(subtitle_region_count, sizeof(*subtitle_area));
/* Process all subpictures and regions (in the right order) */
- for (unsigned int index = 0; index < i_subpicture; index++) {
- subpicture_t *subpic = pp_subpicture[index];
+ for (size_t index = 0; index < i_subpicture; index++) {
+ const spu_render_entry_t *entry = &p_entries[index];
+ subpicture_t *subpic = entry->subpicture;
subpicture_region_t *region;
if (!subpic->p_region)
@@ -1119,7 +1187,7 @@ static subpicture_t *SpuRenderSubpictures(spu_t *spu,
/* */
SpuRenderRegion(spu, output_last_ptr, &area,
- subpic, region, virtual_scale,
+ entry, region, virtual_scale,
chroma_list, fmt_dst,
subtitle_area, subtitle_area_count,
subpic->b_subtitle ? render_subtitle_date : system_now);
@@ -1312,6 +1380,7 @@ spu_t *spu_Create(vlc_object_t *object, vout_thread_t *vout)
SpuHeapInit(&sys->heap);
+ sys->clock = NULL;
sys->text = NULL;
sys->scale = NULL;
sys->scale_yuvp = NULL;
@@ -1418,6 +1487,23 @@ void spu_Detach(spu_t *spu)
vlc_mutex_unlock(&spu->p->lock);
}
+void spu_clock_Set(spu_t *spu, vlc_clock_t *clock)
+{
+ spu->p->clock = clock;
+}
+
+void spu_clock_Reset(spu_t *spu)
+{
+ if (spu->p->clock)
+ vlc_clock_Reset(spu->p->clock);
+}
+
+void spu_clock_SetDelay(spu_t *spu, vlc_tick_t delay)
+{
+ if (spu->p->clock)
+ vlc_clock_SetDelay(spu->p->clock, delay);
+}
+
/**
* Inform the SPU filters of mouse event
*/
@@ -1585,11 +1671,11 @@ subpicture_t *spu_Render(spu_t *spu,
vlc_mutex_lock(&sys->lock);
size_t subpicture_count;
- subpicture_t *subpicture_array[VOUT_MAX_SUBPICTURES];
+ 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, ignore_osd);
+ render_subtitle_date, rate, ignore_osd);
if (subpicture_count == 0) {
vlc_mutex_unlock(&sys->lock);
return NULL;
@@ -1597,7 +1683,7 @@ subpicture_t *spu_Render(spu_t *spu,
/* Updates the subpictures */
for (size_t i = 0; i < subpicture_count; i++) {
- subpicture_t *subpic = subpicture_array[i];
+ subpicture_t *subpic = subpicture_array[i].subpicture;
subpicture_Update(subpic,
fmt_src, fmt_dst,
subpic->b_subtitle ? render_subtitle_date : system_now);
@@ -1605,7 +1691,7 @@ subpicture_t *spu_Render(spu_t *spu,
/* Now order the subpicture array
* XXX The order is *really* important for overlap subtitles positionning */
- qsort(subpicture_array, subpicture_count, sizeof(*subpicture_array), SubpictureCmp);
+ qsort(subpicture_array, subpicture_count, sizeof(*subpicture_array), SpuRenderCmp);
/* Render the subpictures */
subpicture_t *render = SpuRenderSubpictures(spu,
@@ -1619,7 +1705,6 @@ subpicture_t *spu_Render(spu_t *spu,
vlc_mutex_unlock(&sys->lock);
return render;
- (void) rate;
}
void spu_OffsetSubtitleDate(spu_t *spu, vlc_tick_t duration)
--
2.20.1
More information about the vlc-devel
mailing list