From: Laurent Aimar Date: Sun, 25 Apr 2010 17:28:25 +0000 (+0200) Subject: Used vout_control for various commands (vout). X-Git-Tag: 1.2.0-pre1~6880 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=2c2f3856370e3480e4a61c263ec7917ace9fb60d;p=vlc Used vout_control for various commands (vout). It also improves reactivity of seek while paused. --- diff --git a/src/video_output/control.c b/src/video_output/control.c index 6e4e3abda9..bff7a4e2d8 100644 --- a/src/video_output/control.c +++ b/src/video_output/control.c @@ -40,7 +40,8 @@ void vout_control_cmd_Clean(vout_control_cmd_t *cmd) switch (cmd->type) { //case VOUT_CONTROL_OSD_MESSAGE: case VOUT_CONTROL_OSD_TITLE: - free(cmd->u.message.string); + case VOUT_CONTROL_CHANGE_FILTERS: + free(cmd->u.string); break; #if 0 case VOUT_CONTROL_OSD_TEXT: @@ -165,6 +166,14 @@ void vout_control_PushPair(vout_control_t *ctrl, int type, int a, int b) cmd.u.pair.b = b; vout_control_Push(ctrl, &cmd); } +void vout_control_PushString(vout_control_t *ctrl, int type, const char *string) +{ + vout_control_cmd_t cmd; + + vout_control_cmd_Init(&cmd, type); + cmd.u.string = strdup(string); + vout_control_Push(ctrl, &cmd); +} int vout_control_Pop(vout_control_t *ctrl, vout_control_cmd_t *cmd, mtime_t deadline, mtime_t timeout) diff --git a/src/video_output/control.h b/src/video_output/control.h index 4949f4e30b..7abc64e11e 100644 --- a/src/video_output/control.h +++ b/src/video_output/control.h @@ -38,12 +38,6 @@ enum { VOUT_CONTROL_START, VOUT_CONTROL_STOP, - /* */ - VOUT_CONTROL_RESET, - VOUT_CONTROL_FLUSH, - VOUT_CONTROL_PAUSE, - VOUT_CONTROL_STEP, - /* Controls */ VOUT_CONTROL_FULLSCREEN, VOUT_CONTROL_DISPLAY_FILLED, @@ -62,7 +56,13 @@ enum { VOUT_CONTROL_OSD_ICON, VOUT_CONTROL_OSD_SUBPICTURE, #endif - VOUT_CONTROL_OSD_TITLE, + VOUT_CONTROL_OSD_TITLE, /* string */ + VOUT_CONTROL_CHANGE_FILTERS, /* string */ + + VOUT_CONTROL_PAUSE, + VOUT_CONTROL_RESET, + VOUT_CONTROL_FLUSH, /* time */ + VOUT_CONTROL_STEP, /* time_ptr */ }; typedef struct { @@ -71,6 +71,8 @@ typedef struct { union { bool boolean; mtime_t time; + mtime_t *time_ptr; + char *string; struct { int a; int b; @@ -149,6 +151,7 @@ void vout_control_PushBool(vout_control_t *, int type, bool boolean); void vout_control_PushTime(vout_control_t *, int type, mtime_t time); void vout_control_PushMessage(vout_control_t *, int type, int channel, const char *string); void vout_control_PushPair(vout_control_t *, int type, int a, int b); +void vout_control_PushString(vout_control_t *, int type, const char *string); void vout_control_Wake(vout_control_t *); /* control inside of the vout thread */ diff --git a/src/video_output/video_output.c b/src/video_output/video_output.c index 06533f544f..c7b248a44e 100644 --- a/src/video_output/video_output.c +++ b/src/video_output/video_output.c @@ -289,14 +289,12 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt ) 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; @@ -310,9 +308,11 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt ) 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 ); @@ -344,12 +344,10 @@ vout_thread_t * (vout_Create)( vlc_object_t *p_parent, video_format_t *p_fmt ) 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 ) @@ -465,7 +463,6 @@ static void vout_Destructor( vlc_object_t * p_this ) /* 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 ); @@ -479,7 +476,6 @@ static void vout_Destructor( vlc_object_t * p_this ) /* */ free( p_vout->p->psz_filter_chain ); - free( p_vout->p->title.value ); config_ChainDestroy( p_vout->p->p_cfg ); @@ -488,42 +484,15 @@ static void vout_Destructor( vlc_object_t * p_this ) } /* */ -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 ); - - 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_mutex_unlock( &p_vout->p->picture_lock ); - - vout_control_Wake( &p_vout->p->control ); - - 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; + 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); - 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 ) @@ -532,47 +501,16 @@ void vout_GetResetStatistic( vout_thread_t *p_vout, int *pi_displayed, int *pi_l pi_displayed, pi_lost ); } -static void Flush(vout_thread_t *vout, mtime_t date, bool reset, bool below) -{ - 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 ); -} - void vout_Flush(vout_thread_t *vout, mtime_t date) { - vlc_mutex_lock(&vout->p->picture_lock); - - Flush(vout, date, false, false); - - vlc_mutex_unlock(&vout->p->picture_lock); - vout_control_Wake(&vout->p->control); + vout_control_PushTime(&vout->p->control, VOUT_CONTROL_FLUSH, date); + vout_control_WaitEmpty(&vout->p->control); } void vout_Reset(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(); - - vlc_mutex_unlock(&vout->p->picture_lock); - vout_control_Wake(&vout->p->control); + vout_control_PushVoid(&vout->p->control, VOUT_CONTROL_RESET); + vout_control_WaitEmpty(&vout->p->control); } void vout_FixLeaks( vout_thread_t *vout ) @@ -600,46 +538,21 @@ void vout_FixLeaks( vout_thread_t *vout ) picture_pool_NonEmpty(vout->p->decoder_pool, false); vlc_mutex_unlock(&vout->p->picture_lock); - vout_control_Wake(&vout->p->control); } 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; - - vlc_mutex_unlock(&vout->p->picture_lock); - - vout_control_Wake(&vout->p->control); - - vlc_mutex_lock(&vout->p->picture_lock); - while (vout->p->step.is_requested && !vout->p->b_picture_empty) - vlc_cond_wait(&vout->p->picture_wait, &vout->p->picture_lock); + vout_control_cmd_t cmd; + vout_control_cmd_Init(&cmd, VOUT_CONTROL_STEP); + cmd.u.time_ptr = duration; - 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; - } - - /* 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 ) @@ -701,7 +614,7 @@ static int ThreadDisplayPicture(vout_thread_t *vout, 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 @@ -888,28 +801,7 @@ static int ThreadManage(vout_thread_t *vout, vlc_mutex_lock(&vout->p->picture_lock); *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); - } - } + ThreadDisplayPicture(vout, false, deadline); const int picture_qtype = vout->p->displayed.qtype; const bool picture_interlaced = vout->p->displayed.is_interlaced; @@ -932,9 +824,11 @@ static int ThreadManage(vout_thread_t *vout, return VLC_SUCCESS; } -static void ThreadDisplayOsdTitle(vout_thread_t *vout) +static void ThreadDisplayOsdTitle(vout_thread_t *vout, const char *string) { - if (!vout->p->title.show || !vout->p->title.value) + if( !var_InheritBool(vout, "osd")) + return; + if (!vout->p->title.show) return; vlc_assert_locked(&vout->p->change_lock); @@ -945,39 +839,106 @@ static void ThreadDisplayOsdTitle(vout_thread_t *vout) if (stop > start) vout_ShowTextAbsolute(vout, DEFAULT_CHAN, - vout->p->title.value, NULL, + string, NULL, vout->p->title.position, 30 + vout->fmt_in.i_width - vout->fmt_in.i_visible_width - vout->fmt_in.i_x_offset, 20 + vout->fmt_in.i_y_offset, start, stop); - - free(vout->p->title.value); - vout->p->title.value = NULL; } -static void ThreadChangeFilter(vout_thread_t *vout) +static void ThreadChangeFilters(vout_thread_t *vout, const char *filters) { - /* Check for "video filter2" changes */ + es_format_t fmt; + es_format_Init(&fmt, VIDEO_ES, vout->fmt_render.i_chroma); + fmt.video = vout->fmt_render; + 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); + 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"); - if (filter_chain_AppendFromString(vout->p->p_vf2_chain, - vout->p->psz_vf2) < 0) - msg_Err(vout, "Video filter chain creation failed"); + vlc_mutex_unlock(&vout->p->vfilter_lock); +} - free(vout->p->psz_vf2); - vout->p->psz_vf2 = NULL; +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; } - vlc_mutex_unlock(&vout->p->vfilter_lock); + 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 ... */ + } +} + + /***************************************************************************** * Thread: video output thread ***************************************************************************** @@ -1030,10 +991,32 @@ static void *Thread(void *object) /* FIXME remove thoses ugly timeouts */ while (!vout_control_Pop(&vout->p->control, &cmd, deadline, 100000)) { + /* TODO remove the lock when possible (ie when + * vout->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; default: break; } + vlc_mutex_unlock(&vout->p->change_lock); vout_control_cmd_Clean(&cmd); } vlc_mutex_lock(&vout->p->change_lock); @@ -1044,9 +1027,6 @@ static void *Thread(void *object) vout->p->b_error = true; break; } - - ThreadDisplayOsdTitle(vout); - ThreadChangeFilter(vout); } /* @@ -1066,15 +1046,15 @@ exit_thread: 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; } @@ -1113,16 +1093,15 @@ static int FilterCallback( vlc_object_t *p_this, char const *psz_cmd, /***************************************************************************** * 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; } diff --git a/src/video_output/vout_internal.h b/src/video_output/vout_internal.h index ee08763bc6..2489d285eb 100644 --- a/src/video_output/vout_internal.h +++ b/src/video_output/vout_internal.h @@ -67,8 +67,6 @@ struct vout_thread_sys_t picture_t *filtered; } display; - bool b_picture_empty; - vlc_cond_t picture_wait; struct { mtime_t date; mtime_t timestamp; @@ -78,7 +76,6 @@ struct vout_thread_sys_t } displayed; struct { - bool is_requested; mtime_t last; mtime_t timestamp; } step; @@ -88,16 +85,13 @@ struct vout_thread_sys_t mtime_t date; } pause; + /* OSD title configuration */ struct { bool show; mtime_t timeout; int position; - char *value; } title; - /* */ - vlc_mutex_t vfilter_lock; /**< video filter2 lock */ - /* */ unsigned int i_par_num; /**< monitor pixel aspect-ratio */ unsigned int i_par_den; /**< monitor pixel aspect-ratio */ @@ -111,8 +105,8 @@ struct vout_thread_sys_t bool b_filter_change; /* Video filter2 chain */ + vlc_mutex_t vfilter_lock; filter_chain_t *p_vf2_chain; - char *psz_vf2; /* Snapshot interface */ vout_snapshot_t snapshot; diff --git a/src/video_output/vout_intf.c b/src/video_output/vout_intf.c index 1f889eb2f4..3fcc04741b 100644 --- a/src/video_output/vout_intf.c +++ b/src/video_output/vout_intf.c @@ -180,8 +180,6 @@ void vout_IntfInit( vout_thread_t *p_vout ) "video-title-timeout" ); p_vout->p->title.position = var_CreateGetInteger( p_vout, "video-title-position" ); - p_vout->p->title.value = NULL; - var_AddCallback( p_vout, "video-title-show", TitleShowCallback, NULL ); var_AddCallback( p_vout, "video-title-timeout", TitleTimeoutCallback, NULL ); var_AddCallback( p_vout, "video-title-position", TitlePositionCallback, NULL );