Commit 5318004e authored by Steve Lhomme's avatar Steve Lhomme
Browse files

video_filter: add the possibility to full draining support

This type of draining is usually done before flushing (discontinuity) or before
closing a filter modules.

For now only the "in-line" draining is used.

Ref #12155
parent 07dbfe81
......@@ -110,8 +110,12 @@ struct vlc_filter_operations
/** Drain (audio filter) */
block_t *(*drain_audio)(filter_t *);
/** Video Drain (formerly video filter(NULL)) */
picture_t *(*drain_video)(filter_t *);
/**
* Video Drain (formerly video filter(NULL))
* \param fully No input will be received, output all possible remaining
* pictures.
*/
picture_t *(*drain_video)(filter_t *, bool fully);
};
/** Flush
......@@ -275,10 +279,10 @@ static inline picture_t *filter_NewPicture( filter_t *p_filter )
/**
* This function will drain, then flush a video filter.
*/
static inline picture_t *filter_DrainVideo( filter_t *p_filter )
static inline picture_t *filter_DrainVideo( filter_t *p_filter, bool fully )
{
if( p_filter->ops->drain_video )
return p_filter->ops->drain_video( p_filter );
return p_filter->ops->drain_video( p_filter, fully );
return NULL;
}
......@@ -612,10 +616,11 @@ VLC_API picture_t *filter_chain_VideoFilter(filter_chain_t *chain,
* Drain the filter chain of remaining processed pictures.
*
* \param chain pointer to filter chain
* \param fully drain everything, no input pictures will be provided
* \return modified picture after applying all video filters or NULL if there is
* nothing left to drain
*/
VLC_API picture_t *filter_chain_VideoDrain(filter_chain_t *chain) VLC_USED;
VLC_API picture_t *filter_chain_VideoDrain(filter_chain_t *chain, bool fully) VLC_USED;
/**
* Flush a video filter chain.
......
......@@ -174,12 +174,12 @@ static picture_t *Deinterlace(filter_t *p_filter, picture_t *p_pic)
return res;
}
static picture_t *Drain(filter_t *p_filter)
static picture_t *Drain(filter_t *p_filter, bool fully)
{
filter_sys_t *p_sys = p_filter->p_sys;
d3d11_device_lock( p_sys->d3d_dev );
picture_t *res = DoDraining( p_filter, &p_sys->context );
picture_t *res = DoDraining( p_filter, &p_sys->context, fully );
d3d11_device_unlock( p_sys->d3d_dev );
return res;
......
......@@ -268,10 +268,10 @@ static picture_t *Deinterlace(filter_t *p_filter, picture_t *p_pic)
return DoDeinterlacing( p_filter, &p_sys->context, p_pic );
}
static picture_t *Drain(filter_t *p_filter)
static picture_t *Drain(filter_t *p_filter, bool fully)
{
filter_sys_t *p_sys = p_filter->p_sys;
return DoDraining( p_filter, &p_sys->context );
return DoDraining( p_filter, &p_sys->context, fully );
}
static const struct filter_mode_t *GetFilterMode(const char *mode)
......
......@@ -298,8 +298,9 @@ fail:
return NULL;
}
static picture_t *drain(filter_t * p_filter)
static picture_t *drain(filter_t * p_filter, bool fully)
{
// TODO handle draining ?
filter_sys_t * const sys = p_filter->p_sys;
MMAL_BUFFER_HEADER_T * out_buf;
out_buf = seq_delta(sys->seq_in, sys->seq_out) >= 5 ? mmal_queue_timedwait(sys->out_q, 1000) : mmal_queue_get(sys->out_q);
......
......@@ -883,8 +883,9 @@ error:
return NULL;
}
static picture_t *DrainX2(filter_t *filter)
static picture_t *DrainX2(filter_t *filter, bool fully)
{
// TODO handle draining ?
filter_sys_t *const filter_sys = filter->p_sys;
struct deint_data *const p_deint_data = filter_sys->p_data;
const video_format_t * fmt = &filter->fmt_out.video;
......
......@@ -64,8 +64,9 @@ static picture_t *Deinterlace(filter_t *filter, picture_t *src)
return src;
}
static picture_t *Drain(filter_t *filter)
static picture_t *Drain(filter_t *filter, bool fully)
{
// TODO handle draining ?
filter_sys_t *sys = filter->p_sys;
if (sys->last_pic == NULL) // second drain call
return NULL;
......
......@@ -597,13 +597,13 @@ static void decoder_queue_video( decoder_t *p_dec, picture_t *p_pic )
if( p_sys->p_vf2 )
{
/* push the picture in the mosaic-struct structure */
p_new_pic = filter_chain_VideoDrain( p_sys->p_vf2 );
p_new_pic = filter_chain_VideoDrain( p_sys->p_vf2, false );
while ( p_new_pic != NULL )
{
vlc_global_lock( VLC_MOSAIC_MUTEX );
vlc_picture_chain_Append( &p_es->pictures, p_new_pic );
vlc_global_unlock( VLC_MOSAIC_MUTEX );
p_new_pic = filter_chain_VideoDrain( p_sys->p_vf2 );
p_new_pic = filter_chain_VideoDrain( p_sys->p_vf2, false );
}
}
}
......
......@@ -589,11 +589,11 @@ void VideoDecodedStream::Output(picture_t *p_pic)
outputbuffer->Enqueue(p_pic);
if(p_filters_chain)
{
p_pic = filter_chain_VideoDrain(p_filters_chain);
p_pic = filter_chain_VideoDrain(p_filters_chain, false);
while (p_pic)
{
outputbuffer->Enqueue(p_pic);
p_pic = filter_chain_VideoDrain(p_filters_chain);
p_pic = filter_chain_VideoDrain(p_filters_chain, false);
}
}
}
......
......@@ -585,7 +585,7 @@ int transcode_video_process( sout_stream_t *p_stream, sout_stream_id_sys_t *id,
if ( p_in )
p_in = filter_chain_VideoFilter( chains[i], p_in );
else
p_in = filter_chain_VideoDrain( chains[i] );
p_in = filter_chain_VideoDrain( chains[i], false );
}
if( !p_in )
......
......@@ -53,7 +53,7 @@ vlc_module_end ()
*****************************************************************************/
static picture_t *Chain ( filter_t *, picture_t * );
static void Flush ( filter_t * );
static picture_t *Drain ( filter_t * );
static picture_t *Drain ( filter_t *, bool );
static int BuildTransformChain( filter_t *p_filter );
static int BuildChromaResize( filter_t * );
......@@ -280,10 +280,10 @@ static void Flush( filter_t *p_filter )
filter_chain_VideoFlush( p_sys->p_chain );
}
static picture_t *Drain( filter_t *p_filter )
static picture_t *Drain( filter_t *p_filter, bool fully )
{
filter_sys_t *p_sys = p_filter->p_sys;
return filter_chain_VideoDrain( p_sys->p_chain );
return filter_chain_VideoDrain( p_sys->p_chain, fully );
}
/*****************************************************************************
......
......@@ -508,10 +508,10 @@ chain_CVPX_Filter(filter_t *filter, picture_t *pic)
return filter_chain_VideoFilter(chain, pic);
}
static picture_t * chain_CVPX_Drain(filter_t *filter)
static picture_t * chain_CVPX_Drain(filter_t *filter, bool fully)
{
filter_chain_t *chain = filter->p_sys;
return filter_chain_VideoDrain(chain);
return filter_chain_VideoDrain(chain, fully);
}
static void
......
......@@ -42,7 +42,7 @@ static int Activate( filter_t * );
static void Destroy( filter_t * );
static picture_t *Filter( filter_t *, picture_t * );
static void Flush( filter_t * );
static picture_t *Drain( filter_t * );
static picture_t *Drain( filter_t *, bool );
/* This module effectively implements a form of picture-in-picture.
* - The outer picture is called the canvas.
......@@ -408,8 +408,8 @@ static void Flush( filter_t *p_filter )
filter_chain_VideoFlush( p_sys->p_chain );
}
static picture_t *Drain( filter_t *p_filter )
static picture_t *Drain( filter_t *p_filter, bool fully )
{
filter_sys_t *p_sys = p_filter->p_sys;
return filter_chain_VideoDrain( p_sys->p_chain );
return filter_chain_VideoDrain( p_sys->p_chain, fully );
}
......@@ -353,7 +353,8 @@ exit:
#endif
}
picture_t *DoDraining( filter_t *p_filter, struct deinterlace_ctx *p_context )
picture_t *DoDraining( filter_t *p_filter, struct deinterlace_ctx *p_context, bool fully )
{
// TODO
return DoDeinterlacing( p_filter, p_context, NULL );
}
......@@ -120,7 +120,7 @@ void GetDeinterlacingOutput( const struct deinterlace_ctx *,
* @return The deinterlaced picture or NULL if it failed
*/
picture_t *DoDeinterlacing( filter_t *, struct deinterlace_ctx *, picture_t * );
picture_t *DoDraining( filter_t *, struct deinterlace_ctx * );
picture_t *DoDraining( filter_t *, struct deinterlace_ctx *, bool fully );
/**
* @brief Flush the deinterlacer context
......
......@@ -444,10 +444,10 @@ picture_t *Deinterlace( filter_t *p_filter, picture_t *p_pic )
return DoDeinterlacing( p_filter, &p_sys->context, p_pic );
}
static picture_t *Drain(filter_t *p_filter )
static picture_t *Drain(filter_t *p_filter, bool fully )
{
filter_sys_t *p_sys = p_filter->p_sys;
return DoDraining( p_filter, &p_sys->context );
return DoDraining( p_filter, &p_sys->context, fully );
}
/*****************************************************************************
......
......@@ -49,7 +49,7 @@ static int Open( filter_t * );
static void Close( filter_t * );
static picture_t *new_frame( filter_t * );
static picture_t *Filter( filter_t *, picture_t * );
static picture_t *Drain( filter_t * );
static picture_t *Drain( filter_t *, bool );
static uint8_t sobel( const uint8_t *, const int, const int, int, int);
/* Kernel for X axis */
......@@ -198,10 +198,10 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_pic )
return FilterFromFiltered( p_filter, &p_pic->format, p_filtered_frame );
}
static picture_t *Drain( filter_t *p_filter )
static picture_t *Drain( filter_t *p_filter, bool fully )
{
filter_chain_t *p_sys = p_filter->p_sys;
picture_t *p_drained = filter_chain_VideoDrain( p_sys );
picture_t *p_drained = filter_chain_VideoDrain( p_sys, fully );
if (!p_drained)
return NULL;
return FilterFromFiltered( p_filter, &p_filter->fmt_out.video, p_drained );
......
......@@ -72,8 +72,9 @@ static picture_t *Filter(filter_t *p_filter, picture_t *p_pic)
return p_pic;
}
static picture_t *Drain(filter_t *p_filter)
static picture_t *Drain(filter_t *p_filter, bool fully)
{
VLC_UNUSED(fully);
filter_sys_t *p_sys = p_filter->p_sys;
if ( p_sys->src_pic == NULL )
return NULL;
......
......@@ -111,8 +111,9 @@ static picture_t *Filter( filter_t *p_filter, picture_t *p_picture)
return SetOutputDate( p_sys, p_picture );
}
static picture_t *Drain( filter_t *p_filter )
static picture_t *Drain( filter_t *p_filter, bool fully )
{
// TODO handle fully ?
filter_sys_t *p_sys = p_filter->p_sys;
if ( p_sys->p_previous_pic == NULL )
......
......@@ -437,14 +437,14 @@ picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
assert( p_pic != NULL );
for( chained_filter_t *f = p_chain->first; f != NULL; f = f->next )
{
picture_t *pending = filter_DrainVideo( &f->filter );
picture_t *pending = filter_DrainVideo( &f->filter, false );
if (pending)
{
msg_Warn( &f->filter, "dropping pictures" );
do
{
picture_Release( pending );
pending = filter_DrainVideo( &f->filter );
pending = filter_DrainVideo( &f->filter, false );
} while (pending);
}
}
......@@ -452,11 +452,11 @@ picture_t *filter_chain_VideoFilter( filter_chain_t *p_chain, picture_t *p_pic )
return filter_chained( p_chain->first, p_pic );
}
picture_t *filter_chain_VideoDrain( filter_chain_t *p_chain )
picture_t *filter_chain_VideoDrain( filter_chain_t *p_chain, bool fully )
{
for( chained_filter_t *b = p_chain->last; b != NULL; )
{
picture_t *p_pic = filter_DrainVideo( &b->filter );
picture_t *p_pic = filter_DrainVideo( &b->filter, fully );
if ( p_pic )
{
// we have a picture, feed it down the chain
......
......@@ -1108,7 +1108,7 @@ static picture_t *ThreadGetPrerenderedLocked(vout_thread_sys_t *vout, bool reuse
picture_t *picture = NULL;
while (!picture) {
picture = filter_chain_VideoDrain(sys->filter.chain_static);
picture = filter_chain_VideoDrain(sys->filter.chain_static, false);
if (picture && DropLate(vout, picture, can_drop_late, paused))
{
picture = NULL;
......@@ -1230,7 +1230,7 @@ static int ThreadDisplayRenderPicture(vout_thread_sys_t *vout, bool render_now)
vout_chrono_Start(&sys->render);
vlc_mutex_lock(&sys->filter.lock);
picture_t *filtered = filter_chain_VideoDrain(sys->filter.chain_interactive);
picture_t *filtered = filter_chain_VideoDrain(sys->filter.chain_interactive, false);
vlc_mutex_unlock(&sys->filter.lock);
if (filtered == NULL)
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment