#include <vlc_vout.h>
#include <vlc_filter.h>
-#include <vlc_osd.h>
+#include <vlc_vout_osd.h>
#include <libvlc.h>
#include <vlc_input.h>
-#include "vout_pictures.h"
#include "vout_internal.h"
#include "interlacing.h"
#include "postprocessing.h"
+#include "display.h"
/*****************************************************************************
* Local prototypes
static int VideoFilter2Callback( vlc_object_t *, char const *,
vlc_value_t, vlc_value_t, void * );
-/* Display media title in OSD */
-static void DisplayTitleOnOSD( vout_thread_t *p_vout );
-
/* */
static void PrintVideoFormat(vout_thread_t *, const char *, const video_format_t *);
#warning "FIXME: Check RGB masks in vout_Request"
/* FIXME: check RGB masks */
- if( p_vout->fmt_render.i_chroma != vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma ) ||
- p_vout->fmt_render.i_width != p_fmt->i_width ||
- p_vout->fmt_render.i_height != p_fmt->i_height ||
+ if( p_vout->p->fmt_render.i_chroma != vlc_fourcc_GetCodec( VIDEO_ES, p_fmt->i_chroma ) ||
+ p_vout->p->fmt_render.i_width != p_fmt->i_width ||
+ p_vout->p->fmt_render.i_height != p_fmt->i_height ||
p_vout->p->b_filter_change )
{
vlc_mutex_unlock( &p_vout->p->change_lock );
#endif
if( i_sar_num > 0 && i_sar_den > 0 &&
- ( i_sar_num != p_vout->fmt_render.i_sar_num ||
- i_sar_den != p_vout->fmt_render.i_sar_den ) )
+ ( i_sar_num != p_vout->p->fmt_render.i_sar_num ||
+ i_sar_den != p_vout->p->fmt_render.i_sar_den ) )
{
- p_vout->fmt_in.i_sar_num = i_sar_num;
- p_vout->fmt_in.i_sar_den = i_sar_den;
+ p_vout->p->fmt_in.i_sar_num = i_sar_num;
+ p_vout->p->fmt_in.i_sar_den = i_sar_den;
- p_vout->fmt_render.i_sar_num = i_sar_num;
- p_vout->fmt_render.i_sar_den = i_sar_den;
+ p_vout->p->fmt_render.i_sar_num = i_sar_num;
+ p_vout->p->fmt_render.i_sar_den = i_sar_den;
p_vout->p->i_changes |= VOUT_ASPECT_CHANGE;
}
vlc_mutex_unlock( &p_vout->p->change_lock );
}
/* */
- p_vout->fmt_render = *p_fmt; /* FIXME palette */
- p_vout->fmt_in = *p_fmt; /* FIXME palette */
+ p_vout->p->fmt_render = *p_fmt; /* FIXME palette */
+ p_vout->p->fmt_in = *p_fmt; /* FIXME palette */
- p_vout->fmt_render.i_chroma =
- p_vout->fmt_in.i_chroma = i_chroma;
- video_format_FixRgb( &p_vout->fmt_render );
- video_format_FixRgb( &p_vout->fmt_in );
+ p_vout->p->fmt_render.i_chroma =
+ p_vout->p->fmt_in.i_chroma = i_chroma;
+ video_format_FixRgb( &p_vout->p->fmt_render );
+ video_format_FixRgb( &p_vout->p->fmt_in );
/* Initialize misc stuff */
+ vout_control_Init( &p_vout->p->control );
p_vout->p->i_changes = 0;
- p_vout->p->b_fullscreen = 0;
vout_chrono_Init( &p_vout->p->render, 5, 10000 ); /* Arbitrary initial time */
vout_statistic_Init( &p_vout->p->statistic );
p_vout->p->b_filter_change = 0;
p_vout->p->i_par_num =
p_vout->p->i_par_den = 1;
- p_vout->p->b_picture_empty = false;
p_vout->p->displayed.date = VLC_TS_INVALID;
p_vout->p->displayed.decoded = NULL;
p_vout->p->displayed.timestamp = VLC_TS_INVALID;
p_vout->p->displayed.qtype = QTYPE_NONE;
p_vout->p->displayed.is_interlaced = false;
- p_vout->p->step.is_requested = false;
p_vout->p->step.last = VLC_TS_INVALID;
p_vout->p->step.timestamp = VLC_TS_INVALID;
vout_snapshot_Init( &p_vout->p->snapshot );
+ p_vout->p->p_vf2_chain = filter_chain_New( p_vout, "video filter2",
+ false, video_filter_buffer_allocation_init, NULL, p_vout );
+
/* Initialize locks */
vlc_mutex_init( &p_vout->p->picture_lock );
- vlc_cond_init( &p_vout->p->picture_wait );
vlc_mutex_init( &p_vout->p->change_lock );
vlc_mutex_init( &p_vout->p->vfilter_lock );
var_CreateGetStringCommand( p_vout, "vout-filter" );
/* Apply video filter2 objects on the first vout */
- p_vout->p->psz_vf2 =
- var_CreateGetStringCommand( p_vout, "video-filter" );
-
+ var_Create( p_vout, "video-filter",
+ VLC_VAR_STRING | VLC_VAR_DOINHERIT | VLC_VAR_ISCOMMAND );
var_AddCallback( p_vout, "video-filter", VideoFilter2Callback, NULL );
- p_vout->p->p_vf2_chain = filter_chain_New( p_vout, "video filter2",
- false, video_filter_buffer_allocation_init, NULL, p_vout );
+ var_TriggerCallback( p_vout, "video-filter" );
/* Choose the video output module */
if( !p_vout->p->psz_filter_chain || !*p_vout->p->psz_filter_chain )
/* Destroy the locks */
vlc_cond_destroy( &p_vout->p->change_wait );
- vlc_cond_destroy( &p_vout->p->picture_wait );
vlc_mutex_destroy( &p_vout->p->picture_lock );
vlc_mutex_destroy( &p_vout->p->change_lock );
vlc_mutex_destroy( &p_vout->p->vfilter_lock );
+ vout_control_Clean( &p_vout->p->control );
/* */
vout_statistic_Clean( &p_vout->p->statistic );
/* */
free( p_vout->p->psz_filter_chain );
- free( p_vout->p->title.value );
config_ChainDestroy( p_vout->p->p_cfg );
}
/* */
-void vout_ChangePause( vout_thread_t *p_vout, bool b_paused, mtime_t i_date )
+void vout_ChangePause(vout_thread_t *vout, bool is_paused, mtime_t date)
{
- vlc_mutex_lock( &p_vout->p->change_lock );
+ vout_control_cmd_t cmd;
+ vout_control_cmd_Init(&cmd, VOUT_CONTROL_PAUSE);
+ cmd.u.pause.is_on = is_paused;
+ cmd.u.pause.date = date;
+ vout_control_Push(&vout->p->control, &cmd);
- assert( !p_vout->p->pause.is_on || !b_paused );
-
- vlc_mutex_lock( &p_vout->p->picture_lock );
-
- if( p_vout->p->pause.is_on )
- {
- const mtime_t i_duration = i_date - p_vout->p->pause.date;
-
- if (p_vout->p->step.timestamp > VLC_TS_INVALID)
- p_vout->p->step.timestamp += i_duration;
- if (!b_paused)
- p_vout->p->step.last = p_vout->p->step.timestamp;
- picture_fifo_OffsetDate( p_vout->p->decoder_fifo, i_duration );
- if (p_vout->p->displayed.decoded)
- p_vout->p->displayed.decoded->date += i_duration;
-
- vlc_cond_signal( &p_vout->p->picture_wait );
- vlc_mutex_unlock( &p_vout->p->picture_lock );
-
- spu_OffsetSubtitleDate( p_vout->p->p_spu, i_duration );
- }
- else
- {
- if (b_paused)
- p_vout->p->step.last = p_vout->p->step.timestamp;
- vlc_mutex_unlock( &p_vout->p->picture_lock );
- }
- p_vout->p->pause.is_on = b_paused;
- p_vout->p->pause.date = i_date;
-
- vlc_mutex_unlock( &p_vout->p->change_lock );
+ vout_control_WaitEmpty(&vout->p->control);
}
void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_lost )
pi_displayed, pi_lost );
}
-static void Flush(vout_thread_t *vout, mtime_t date, bool reset, bool below)
+void vout_Flush(vout_thread_t *vout, mtime_t date)
{
- vlc_assert_locked(&vout->p->picture_lock);
- vout->p->step.timestamp = VLC_TS_INVALID;
- vout->p->step.last = VLC_TS_INVALID;
-
- picture_t *last = vout->p->displayed.decoded;
- if (last) {
- if (reset) {
- picture_Release(last);
- vout->p->displayed.decoded = NULL;
- } else if (( below && last->date <= date) ||
- (!below && last->date >= date)) {
- vout->p->step.is_requested = true;
- }
- }
- picture_fifo_Flush( vout->p->decoder_fifo, date, below );
+ vout_control_PushTime(&vout->p->control, VOUT_CONTROL_FLUSH, date);
+ vout_control_WaitEmpty(&vout->p->control);
}
-void vout_Flush(vout_thread_t *vout, mtime_t date)
+void vout_Reset(vout_thread_t *vout)
{
- vlc_mutex_lock(&vout->p->picture_lock);
-
- Flush(vout, date, false, false);
-
- vlc_cond_signal(&vout->p->picture_wait);
- vlc_mutex_unlock(&vout->p->picture_lock);
+ vout_control_PushVoid(&vout->p->control, VOUT_CONTROL_RESET);
+ vout_control_WaitEmpty(&vout->p->control);
}
-void vout_Reset(vout_thread_t *vout)
+bool vout_IsEmpty(vout_thread_t *vout)
{
vlc_mutex_lock(&vout->p->picture_lock);
- Flush(vout, INT64_MAX, true, true);
- if (vout->p->decoder_pool)
- picture_pool_NonEmpty(vout->p->decoder_pool, true);
- vout->p->pause.is_on = false;
- vout->p->pause.date = mdate();
+ picture_t *picture = picture_fifo_Peek(vout->p->decoder_fifo);
+ if (picture)
+ picture_Release(picture);
- vlc_cond_signal( &vout->p->picture_wait );
vlc_mutex_unlock(&vout->p->picture_lock);
+
+ return !picture;
}
void vout_FixLeaks( vout_thread_t *vout )
/* */
picture_pool_NonEmpty(vout->p->decoder_pool, false);
- vlc_cond_signal(&vout->p->picture_wait);
vlc_mutex_unlock(&vout->p->picture_lock);
}
void vout_NextPicture(vout_thread_t *vout, mtime_t *duration)
{
- vlc_mutex_lock(&vout->p->picture_lock);
-
- vout->p->b_picture_empty = false;
- vout->p->step.is_requested = true;
-
- /* FIXME I highly doubt that it can works with only one cond_t FIXME */
- vlc_cond_signal(&vout->p->picture_wait);
-
- while (vout->p->step.is_requested && !vout->p->b_picture_empty)
- vlc_cond_wait(&vout->p->picture_wait, &vout->p->picture_lock);
-
- if (vout->p->step.last > VLC_TS_INVALID &&
- vout->p->step.timestamp > vout->p->step.last) {
- *duration = vout->p->step.timestamp - vout->p->step.last;
- vout->p->step.last = vout->p->step.timestamp;
- } else {
- *duration = 0;
- }
+ vout_control_cmd_t cmd;
+ vout_control_cmd_Init(&cmd, VOUT_CONTROL_STEP);
+ cmd.u.time_ptr = duration;
- /* TODO advance subpicture by the duration ... */
- vlc_mutex_unlock(&vout->p->picture_lock);
+ vout_control_Push(&vout->p->control, &cmd);
+ vout_control_WaitEmpty(&vout->p->control);
}
-void vout_DisplayTitle( vout_thread_t *p_vout, const char *psz_title )
+void vout_DisplayTitle(vout_thread_t *vout, const char *title)
{
- assert( psz_title );
-
- if( !var_InheritBool( p_vout, "osd" ) )
- return;
-
- vlc_mutex_lock( &p_vout->p->change_lock );
- free( p_vout->p->title.value );
- p_vout->p->title.value = strdup( psz_title );
- vlc_mutex_unlock( &p_vout->p->change_lock );
+ assert(title);
+ vout_control_PushString(&vout->p->control, VOUT_CONTROL_OSD_TITLE, title);
}
spu_t *vout_GetSpu( vout_thread_t *p_vout )
return p_vout->p->p_spu;
}
+/* vout_Control* are usable by anyone at anytime */
+void vout_ControlChangeFullscreen(vout_thread_t *vout, bool fullscreen)
+{
+ vout_control_PushBool(&vout->p->control, VOUT_CONTROL_FULLSCREEN,
+ fullscreen);
+}
+void vout_ControlChangeOnTop(vout_thread_t *vout, bool is_on_top)
+{
+ vout_control_PushBool(&vout->p->control, VOUT_CONTROL_ON_TOP,
+ is_on_top);
+}
+void vout_ControlChangeDisplayFilled(vout_thread_t *vout, bool is_filled)
+{
+ vout_control_PushBool(&vout->p->control, VOUT_CONTROL_DISPLAY_FILLED,
+ is_filled);
+}
+void vout_ControlChangeZoom(vout_thread_t *vout, int num, int den)
+{
+ vout_control_PushPair(&vout->p->control, VOUT_CONTROL_ZOOM,
+ num, den);
+}
+
/*****************************************************************************
* InitThread: initialize video output thread
*****************************************************************************
/* print some usefull debug info about different vout formats
*/
- PrintVideoFormat(vout, "pic render", &vout->fmt_render);
- PrintVideoFormat(vout, "pic in", &vout->fmt_in);
- PrintVideoFormat(vout, "pic out", &vout->fmt_out);
+ PrintVideoFormat(vout, "pic render", &vout->p->fmt_render);
+ PrintVideoFormat(vout, "pic in", &vout->p->fmt_in);
+ PrintVideoFormat(vout, "pic out", &vout->p->fmt_out);
- assert(vout->fmt_out.i_width == vout->fmt_render.i_width &&
- vout->fmt_out.i_height == vout->fmt_render.i_height &&
- vout->fmt_out.i_chroma == vout->fmt_render.i_chroma);
+ assert(vout->p->fmt_out.i_width == vout->p->fmt_render.i_width &&
+ vout->p->fmt_out.i_height == vout->p->fmt_render.i_height &&
+ vout->p->fmt_out.i_chroma == vout->p->fmt_render.i_chroma);
return VLC_SUCCESS;
}
-/*****************************************************************************
- * CleanThread: clean up after InitThread
- *****************************************************************************
- * This function is called after a sucessful
- * initialization. It frees all resources allocated by InitThread.
- * XXX You have to enter it with change_lock taken.
- *****************************************************************************/
-static void ThreadClean(vout_thread_t *vout)
-{
- /* Destroy translation tables */
- if (!vout->p->b_error) {
- picture_fifo_Flush(vout->p->decoder_fifo, INT64_MAX, false);
- vout_EndWrapper(vout);
- }
-}
-
static int ThreadDisplayPicture(vout_thread_t *vout,
bool now, mtime_t *deadline)
{
for (;;) {
const mtime_t date = mdate();
const bool is_paused = vout->p->pause.is_on;
- bool redisplay = is_paused && !now;
+ bool redisplay = is_paused && !now && vout->p->displayed.decoded;
bool is_forced;
/* FIXME/XXX we must redisplay the last decoded picture (because
(vout->p->decoder_pool != vout->p->display_pool || subpic)) {
picture_t *render;
if (vout->p->is_decoder_pool_slow)
- render = picture_NewFromFormat(&vout->fmt_out);
+ render = picture_NewFromFormat(&vout->p->fmt_out);
else if (vout->p->decoder_pool != vout->p->display_pool)
render = picture_pool_Get(vout->p->display_pool);
else
picture_Copy(render, filtered);
spu_RenderSubpictures(vout->p->p_spu,
- render, &vout->fmt_out,
- subpic, &vout->fmt_in, spu_render_time);
+ render, &vout->p->fmt_out,
+ subpic, &vout->p->fmt_in, spu_render_time);
}
if (vout->p->is_decoder_pool_slow) {
direct = picture_pool_Get(vout->p->display_pool);
* Take a snapshot if requested
*/
if (direct && do_snapshot)
- vout_snapshot_Set(&vout->p->snapshot, &vout->fmt_out, direct);
+ vout_snapshot_Set(&vout->p->snapshot, &vout->p->fmt_out, direct);
/* Render the direct buffer returned by vout_RenderPicture */
if (direct) {
return VLC_SUCCESS;
}
+static int ThreadManage(vout_thread_t *vout,
+ mtime_t *deadline,
+ vout_interlacing_support_t *interlacing,
+ vout_postprocessing_support_t *postprocessing)
+{
+ vlc_mutex_lock(&vout->p->picture_lock);
+
+ *deadline = VLC_TS_INVALID;
+ ThreadDisplayPicture(vout, false, deadline);
+
+ const int picture_qtype = vout->p->displayed.qtype;
+ const bool picture_interlaced = vout->p->displayed.is_interlaced;
+
+ vlc_mutex_unlock(&vout->p->picture_lock);
+
+ /* Post processing */
+ vout_SetPostProcessingState(vout, postprocessing, picture_qtype);
+
+ /* Deinterlacing */
+ vout_SetInterlacingState(vout, interlacing, picture_interlaced);
+
+ if (vout_ManageWrapper(vout)) {
+ /* A fatal error occurred, and the thread must terminate
+ * immediately, without displaying anything - setting b_error to 1
+ * causes the immediate end of the main while() loop. */
+ // FIXME pf_end
+ return VLC_EGENERIC;
+ }
+ return VLC_SUCCESS;
+}
+
+static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string)
+{
+ if (!vout->p->title.show)
+ return;
+
+ vlc_assert_locked(&vout->p->change_lock);
+
+ vout_OSDText(vout, SPU_DEFAULT_CHANNEL,
+ vout->p->title.position, INT64_C(1000) * vout->p->title.timeout,
+ string);
+}
+
+static void ThreadChangeFilters(vout_thread_t *vout, const char *filters)
+{
+ es_format_t fmt;
+ es_format_Init(&fmt, VIDEO_ES, vout->p->fmt_render.i_chroma);
+ fmt.video = vout->p->fmt_render;
+
+ vlc_mutex_lock(&vout->p->vfilter_lock);
+
+ filter_chain_Reset(vout->p->p_vf2_chain, &fmt, &fmt);
+ if (filter_chain_AppendFromString(vout->p->p_vf2_chain,
+ filters) < 0)
+ msg_Err(vout, "Video filter chain creation failed");
+
+ vlc_mutex_unlock(&vout->p->vfilter_lock);
+}
+
+static void ThreadChangePause(vout_thread_t *vout, bool is_paused, mtime_t date)
+{
+ vlc_assert_locked(&vout->p->change_lock);
+ assert(!vout->p->pause.is_on || !is_paused);
+
+ if (vout->p->pause.is_on) {
+ const mtime_t duration = date - vout->p->pause.date;
+
+ if (vout->p->step.timestamp > VLC_TS_INVALID)
+ vout->p->step.timestamp += duration;
+ if (vout->p->step.last > VLC_TS_INVALID)
+ vout->p->step.last += duration;
+ picture_fifo_OffsetDate(vout->p->decoder_fifo, duration);
+ if (vout->p->displayed.decoded)
+ vout->p->displayed.decoded->date += duration;
+
+ spu_OffsetSubtitleDate(vout->p->p_spu, duration);
+ } else {
+ vout->p->step.timestamp = VLC_TS_INVALID;
+ vout->p->step.last = VLC_TS_INVALID;
+ }
+ vout->p->pause.is_on = is_paused;
+ vout->p->pause.date = date;
+}
+
+static void ThreadFlush(vout_thread_t *vout, bool below, mtime_t date)
+{
+ vout->p->step.timestamp = VLC_TS_INVALID;
+ vout->p->step.last = VLC_TS_INVALID;
+
+ picture_t *last = vout->p->displayed.decoded;
+ if (last) {
+ if (( below && last->date <= date) ||
+ (!below && last->date >= date)) {
+ picture_Release(last);
+
+ vout->p->displayed.decoded = NULL;
+ vout->p->displayed.date = VLC_TS_INVALID;
+ vout->p->displayed.timestamp = VLC_TS_INVALID;
+ }
+ }
+ picture_fifo_Flush(vout->p->decoder_fifo, date, below);
+}
+
+static void ThreadReset(vout_thread_t *vout)
+{
+ ThreadFlush(vout, true, INT64_MAX);
+ if (vout->p->decoder_pool)
+ picture_pool_NonEmpty(vout->p->decoder_pool, true);
+ vout->p->pause.is_on = false;
+ vout->p->pause.date = mdate();
+}
+
+static void ThreadStep(vout_thread_t *vout, mtime_t *duration)
+{
+ *duration = 0;
+
+ if (vout->p->step.last <= VLC_TS_INVALID)
+ vout->p->step.last = vout->p->displayed.timestamp;
+
+ mtime_t dummy;
+ if (ThreadDisplayPicture(vout, true, &dummy))
+ return;
+
+ vout->p->step.timestamp = vout->p->displayed.timestamp;
+
+ if (vout->p->step.last > VLC_TS_INVALID &&
+ vout->p->step.timestamp > vout->p->step.last) {
+ *duration = vout->p->step.timestamp - vout->p->step.last;
+ vout->p->step.last = vout->p->step.timestamp;
+ /* TODO advance subpicture by the duration ... */
+ }
+}
+
+static void ThreadChangeFullscreen(vout_thread_t *vout, bool fullscreen)
+{
+ /* FIXME not sure setting "fullscreen" is good ... */
+ var_SetBool(vout, "fullscreen", fullscreen);
+ vout_SetDisplayFullscreen(vout->p->display.vd, fullscreen);
+}
+
+static void ThreadChangeOnTop(vout_thread_t *vout, bool is_on_top)
+{
+ vout_SetWindowState(vout->p->display.vd,
+ is_on_top ? VOUT_WINDOW_STATE_ABOVE :
+ VOUT_WINDOW_STATE_NORMAL);
+}
+
+static void ThreadChangeDisplayFilled(vout_thread_t *vout, bool is_filled)
+{
+ vout_SetDisplayFilled(vout->p->display.vd, is_filled);
+}
+
+static void ThreadChangeZoom(vout_thread_t *vout, int num, int den)
+{
+ if (num * 10 < den) {
+ num = den;
+ den *= 10;
+ } else if (num > den * 10) {
+ num = den * 10;
+ }
+
+ vout_SetDisplayZoom(vout->p->display.vd, num, den);
+}
+
+static void ThreadClean(vout_thread_t *vout)
+{
+ /* Destroy translation tables */
+ if (!vout->p->b_error) {
+ ThreadFlush(vout, true, INT64_MAX);
+ vout_EndWrapper(vout);
+ }
+}
+
/*****************************************************************************
* Thread: video output thread
*****************************************************************************
* Main loop - it is not executed if an error occurred during
* initialization
*/
+ mtime_t deadline = VLC_TS_INVALID;
while (!vout->p->b_done && !vout->p->b_error) {
- /* */
- if(vout->p->title.show && vout->p->title.value)
- DisplayTitleOnOSD(vout);
-
- vlc_mutex_lock(&vout->p->picture_lock);
+ vout_control_cmd_t cmd;
- mtime_t deadline = VLC_TS_INVALID;
- bool has_displayed = !ThreadDisplayPicture(vout, vout->p->step.is_requested, &deadline);
-
- if (has_displayed) {
- vout->p->step.timestamp = vout->p->displayed.timestamp;
- if (vout->p->step.last <= VLC_TS_INVALID)
- vout->p->step.last = vout->p->step.timestamp;
- }
- if (vout->p->step.is_requested) {
- if (!has_displayed && !vout->p->b_picture_empty) {
- picture_t *peek = picture_fifo_Peek(vout->p->decoder_fifo);
- if (peek)
- picture_Release(peek);
- if (!peek) {
- vout->p->b_picture_empty = true;
- vlc_cond_signal(&vout->p->picture_wait);
- }
- }
- if (has_displayed) {
- vout->p->step.is_requested = false;
- vlc_cond_signal(&vout->p->picture_wait);
+ vlc_mutex_unlock(&vout->p->change_lock);
+ /* FIXME remove thoses ugly timeouts
+ */
+ while (!vout_control_Pop(&vout->p->control, &cmd, deadline, 100000)) {
+ /* TODO remove the lock when possible (ie when
+ * vout->p->fmt_* are not protected by it anymore) */
+ vlc_mutex_lock(&vout->p->change_lock);
+ switch(cmd.type) {
+ case VOUT_CONTROL_OSD_TITLE:
+ ThreadDisplayOsdTitle(vout, cmd.u.string);
+ break;
+ case VOUT_CONTROL_CHANGE_FILTERS:
+ ThreadChangeFilters(vout, cmd.u.string);
+ break;
+ case VOUT_CONTROL_PAUSE:
+ ThreadChangePause(vout, cmd.u.pause.is_on, cmd.u.pause.date);
+ break;
+ case VOUT_CONTROL_FLUSH:
+ ThreadFlush(vout, false, cmd.u.time);
+ break;
+ case VOUT_CONTROL_RESET:
+ ThreadReset(vout);
+ break;
+ case VOUT_CONTROL_STEP:
+ ThreadStep(vout, cmd.u.time_ptr);
+ break;
+ case VOUT_CONTROL_FULLSCREEN:
+ ThreadChangeFullscreen(vout, cmd.u.boolean);
+ break;
+ case VOUT_CONTROL_ON_TOP:
+ ThreadChangeOnTop(vout, cmd.u.boolean);
+ break;
+ case VOUT_CONTROL_DISPLAY_FILLED:
+ ThreadChangeDisplayFilled(vout, cmd.u.boolean);
+ break;
+ case VOUT_CONTROL_ZOOM:
+ ThreadChangeZoom(vout, cmd.u.pair.a, cmd.u.pair.b);
+ break;
+ default:
+ break;
}
+ vlc_mutex_unlock(&vout->p->change_lock);
+ vout_control_cmd_Clean(&cmd);
}
+ vlc_mutex_lock(&vout->p->change_lock);
- const int picture_qtype = vout->p->displayed.qtype;
- const bool picture_interlaced = vout->p->displayed.is_interlaced;
-
- vlc_mutex_unlock(&vout->p->picture_lock);
-
- if (vout_ManageWrapper(vout)) {
- /* A fatal error occurred, and the thread must terminate
- * immediately, without displaying anything - setting b_error to 1
- * causes the immediate end of the main while() loop. */
- // FIXME pf_end
+ /* */
+ if (ThreadManage(vout, &deadline,
+ &interlacing, &postprocessing)) {
vout->p->b_error = true;
break;
}
-
- /* Post processing */
- vout_SetPostProcessingState(vout, &postprocessing, picture_qtype);
-
- /* Deinterlacing */
- vout_SetInterlacingState(vout, &interlacing, picture_interlaced);
-
- /* Check for "video filter2" changes */
- vlc_mutex_lock(&vout->p->vfilter_lock);
- if (vout->p->psz_vf2) {
- es_format_t fmt;
-
- es_format_Init(&fmt, VIDEO_ES, vout->fmt_render.i_chroma);
- fmt.video = vout->fmt_render;
- filter_chain_Reset(vout->p->p_vf2_chain, &fmt, &fmt);
-
- if (filter_chain_AppendFromString(vout->p->p_vf2_chain,
- vout->p->psz_vf2) < 0)
- msg_Err(vout, "Video filter chain creation failed");
-
- free(vout->p->psz_vf2);
- vout->p->psz_vf2 = NULL;
- }
- vlc_mutex_unlock(&vout->p->vfilter_lock);
-
- vlc_mutex_unlock(&vout->p->change_lock);
-
- if (deadline > VLC_TS_INVALID) {
- vlc_mutex_lock(&vout->p->picture_lock);
- vlc_cond_timedwait(&vout->p->picture_wait, &vout->p->picture_lock, deadline);
- vlc_mutex_unlock(&vout->p->picture_lock);
- }
-
- vlc_mutex_lock(&vout->p->change_lock);
}
/*
spu_Attach(vout->p->p_spu, VLC_OBJECT(vout), false);
vlc_object_detach(vout->p->p_spu);
- /* Destroy the video filters2 */
- filter_chain_Delete(vout->p->p_vf2_chain);
-
vlc_mutex_unlock(&vout->p->change_lock);
if (has_wrapper)
vout_CloseWrapper(vout);
+ vout_control_Dead(&vout->p->control);
+
+ /* Destroy the video filters2 */
+ filter_chain_Delete(vout->p->p_vf2_chain);
return NULL;
}
return VLC_EGENERIC;
}
- var_SetBool( p_vout, "intf-change", true );
-
/* Modify input as well because the vout might have to be restarted */
var_Create( p_input, "vout-filter", VLC_VAR_STRING );
var_SetString( p_input, "vout-filter", newval.psz_string );
/*****************************************************************************
* Video Filter2 stuff
*****************************************************************************/
-static int VideoFilter2Callback( vlc_object_t *p_this, char const *psz_cmd,
- vlc_value_t oldval, vlc_value_t newval, void *p_data )
+static int VideoFilter2Callback(vlc_object_t *object, char const *cmd,
+ vlc_value_t oldval, vlc_value_t newval,
+ void *data)
{
- vout_thread_t *p_vout = (vout_thread_t *)p_this;
- (void)psz_cmd; (void)oldval; (void)p_data;
-
- vlc_mutex_lock( &p_vout->p->vfilter_lock );
- p_vout->p->psz_vf2 = strdup( newval.psz_string );
- vlc_mutex_unlock( &p_vout->p->vfilter_lock );
+ vout_thread_t *vout = (vout_thread_t *)object;
+ (void)cmd; (void)oldval; (void)data;
+ vout_control_PushString(&vout->p->control, VOUT_CONTROL_CHANGE_FILTERS,
+ newval.psz_string);
return VLC_SUCCESS;
}
-static void DisplayTitleOnOSD( vout_thread_t *p_vout )
-{
- const mtime_t i_start = mdate();
- const mtime_t i_stop = i_start + INT64_C(1000) * p_vout->p->title.timeout;
-
- if( i_stop <= i_start )
- return;
-
- vlc_assert_locked( &p_vout->p->change_lock );
-
- vout_ShowTextAbsolute( p_vout, DEFAULT_CHAN,
- p_vout->p->title.value, NULL,
- p_vout->p->title.position,
- 30 + p_vout->fmt_in.i_width
- - p_vout->fmt_in.i_visible_width
- - p_vout->fmt_in.i_x_offset,
- 20 + p_vout->fmt_in.i_y_offset,
- i_start, i_stop );
-
- free( p_vout->p->title.value );
-
- p_vout->p->title.value = NULL;
-}
-
/* */
static void PrintVideoFormat(vout_thread_t *vout,
const char *description,