It properly fixes #3526.
/* Number of planes in a picture */
#define VOUT_MAX_PLANES 5
-/* Video heap size - remember that a decompressed picture is big
- * (~1 Mbyte) before using huge values */
-#define VOUT_MAX_PICTURES 20
-
/*
* Time settings
*/
vout_thread_t *vout;
vlc_object_t *input;
const video_format_t *fmt;
+ unsigned dpb_size;
} vout_configuration_t;
/**
aout_instance_t *p_aout = p_private;
VLC_UNUSED(b_recycle);
vout_configuration_t cfg = {
- .vout = p_vout,
- .input = NULL,
- .fmt = p_fmt,
+ .vout = p_vout,
+ .input = NULL,
+ .fmt = p_fmt,
+ .dpb_size = 1,
};
return vout_Request( p_aout, &cfg );
}
vout_Reset( p_owner->p_vout );
/* */
- input_resource_RequestVout( p_owner->p_input->p->p_resource, p_owner->p_vout, NULL, true );
+ input_resource_RequestVout( p_owner->p_input->p->p_resource, p_owner->p_vout, NULL, 0, true );
input_SendEventVout( p_owner->p_input );
}
decoder_t *p_dec = p_private;
input_thread_t *p_input = p_dec->p_owner->p_input;
- p_vout = input_resource_RequestVout( p_input->p->p_resource, p_vout, p_fmt, b_recyle );
+ p_vout = input_resource_RequestVout( p_input->p->p_resource, p_vout, p_fmt, 1, b_recyle );
input_SendEventVout( p_input );
return p_vout;
p_owner->p_vout = NULL;
vlc_mutex_unlock( &p_owner->lock );
+ unsigned dpb_size;
+ switch( p_dec->fmt_in.i_codec )
+ {
+ case VLC_CODEC_H264:
+ case VLC_CODEC_DIRAC: /* FIXME valid ? */
+ dpb_size = 18;
+ break;
+ case VLC_CODEC_VP5:
+ case VLC_CODEC_VP6:
+ case VLC_CODEC_VP6F:
+ case VLC_CODEC_VP8:
+ dpb_size = 3;
+ break;
+ default:
+ dpb_size = 2;
+ break;
+ }
p_vout = input_resource_RequestVout( p_owner->p_input->p->p_resource,
- p_vout, &p_dec->fmt_out.video, true );
-
+ p_vout, &p_dec->fmt_out.video,
+ dpb_size + 1 + DECODER_MAX_BUFFERING_COUNT,
+ true );
vlc_mutex_lock( &p_owner->lock );
p_owner->p_vout = p_vout;
free( psz_nowplaying );
}
static vout_thread_t *RequestVout( input_resource_t *p_resource,
- vout_thread_t *p_vout, video_format_t *p_fmt,
+ vout_thread_t *p_vout,
+ video_format_t *p_fmt, unsigned dpb_size,
bool b_recycle )
{
vlc_assert_locked( &p_resource->lock );
/* */
vout_configuration_t cfg = {
- .vout = p_vout,
- .input = VLC_OBJECT(p_resource->p_input),
- .fmt = p_fmt,
+ .vout = p_vout,
+ .input = VLC_OBJECT(p_resource->p_input),
+ .fmt = p_fmt,
+ .dpb_size = dpb_size,
};
p_vout = vout_Request( p_resource->p_input, &cfg );
if( !p_vout )
vout_FlushSubpictureChannel( p_vout, -1 );
vout_configuration_t cfg = {
- .vout = p_vout,
- .input = NULL,
- .fmt = p_fmt,
+ .vout = p_vout,
+ .input = NULL,
+ .fmt = p_fmt,
+ .dpb_size = 0,
};
p_resource->p_vout_free = vout_Request( p_resource->p_input, &cfg );
}
}
vout_thread_t *input_resource_RequestVout( input_resource_t *p_resource,
- vout_thread_t *p_vout, video_format_t *p_fmt, bool b_recycle )
+ vout_thread_t *p_vout,
+ video_format_t *p_fmt, unsigned dpb_size,
+ bool b_recycle )
{
vlc_mutex_lock( &p_resource->lock );
- vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, b_recycle );
+ vout_thread_t *p_ret = RequestVout( p_resource, p_vout, p_fmt, dpb_size, b_recycle );
vlc_mutex_unlock( &p_resource->lock );
return p_ret;
void input_resource_TerminateVout( input_resource_t *p_resource )
{
- input_resource_RequestVout( p_resource, NULL, NULL, false );
+ input_resource_RequestVout( p_resource, NULL, NULL, 0, false );
}
bool input_resource_HasVout( input_resource_t *p_resource )
{
/**
* This function handles vout request.
*/
-vout_thread_t *input_resource_RequestVout( input_resource_t *, vout_thread_t *, video_format_t *, bool b_recycle );
+vout_thread_t *input_resource_RequestVout( input_resource_t *, vout_thread_t *, video_format_t *, unsigned dpb_size, bool b_recycle );
/**
* This function return one of the current vout if any.
vout->p = (vout_thread_sys_t*)&vout[1];
vout->p->original = original;
+ vout->p->dpb_size = cfg->dpb_size;
vout_control_Init(&vout->p->control);
vout_control_PushVoid(&vout->p->control, VOUT_CONTROL_INIT);
ThreadClean(vout);
return VLC_EGENERIC;
}
- if (video_format_IsSimilar(&original, &vout->p->original))
- return VLC_SUCCESS;
+ if (video_format_IsSimilar(&original, &vout->p->original)) {
+ if (cfg->dpb_size <= vout->p->dpb_size)
+ return VLC_SUCCESS;
+ msg_Warn(vout, "DPB need to be increased");
+ }
vout_display_state_t state;
memset(&state, 0, sizeof(state));
* and I am not sure what to do */
vout->p->original = original;
+ vout->p->dpb_size = cfg->dpb_size;
if (ThreadStart(vout, &state)) {
ThreadClean(vout);
return VLC_EGENERIC;
#include "statistic.h"
#include "chrono.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.
+ *
+ * It can be made lower at compilation time if needed, but performance
+ * may be degraded.
+ */
+#define VOUT_MAX_PICTURES (20)
+
/* */
struct vout_thread_sys_t
{
/* */
video_format_t original; /* Original format ie coming from the decoder */
+ unsigned dpb_size;
/* Snapshot interface */
vout_snapshot_t snapshot;
#include "vout_internal.h"
#include "display.h"
-/* Minimum number of direct pictures the video output will accept without
- * creating additional pictures in system memory */
-#ifdef OPTIMIZE_MEMORY
-# define VOUT_MIN_DIRECT_PICTURES (VOUT_MAX_PICTURES/2)
-#else
-# define VOUT_MIN_DIRECT_PICTURES (3*VOUT_MAX_PICTURES/4)
-#endif
-
/*****************************************************************************
* Local prototypes
*****************************************************************************/
vout_display_t *vd = sys->display.vd;
video_format_t source = vd->source;
- /* XXX For non dr case, the current vout implementation force us to
- * create at most 1 direct picture (otherwise the buffers will be kept
- * referenced even through the Init/End.
- */
sys->display.use_dr = !vout_IsDisplayFiltered(vd);
const bool allow_dr = !vd->info.has_pictures_invalid && sys->display.use_dr;
-
- picture_pool_t *display_pool = vout_display_Pool(vd, allow_dr ? VOUT_MAX_PICTURES : 3);
- if (allow_dr && picture_pool_GetSize(display_pool) >= VOUT_MIN_DIRECT_PICTURES) {
+ const unsigned private_picture = 3; /* XXX 2 for filter, 1 for SPU */
+ const unsigned display_picture = 1; /* Minimum number of display picture */
+ const unsigned decoder_picture = 1 + sys->dpb_size;
+ const unsigned kept_picture = 1; /* last displayed picture */
+ const unsigned reserved_picture = display_picture +
+ private_picture +
+ kept_picture;
+ picture_pool_t *display_pool =
+ vout_display_Pool(vd, allow_dr ? __MAX(VOUT_MAX_PICTURES,
+ reserved_picture + decoder_picture) : 3);
+ if (allow_dr &&
+ picture_pool_GetSize(display_pool) >= reserved_picture + decoder_picture) {
+ sys->dpb_size = picture_pool_GetSize(display_pool) - reserved_picture - kept_picture;
sys->decoder_pool = display_pool;
sys->display_pool = display_pool;
sys->is_decoder_pool_slow = vd->info.is_slow;
} else if (!sys->decoder_pool) {
- sys->decoder_pool = picture_pool_NewFromFormat(&source, VOUT_MAX_PICTURES);
+ sys->decoder_pool =
+ picture_pool_NewFromFormat(&source,
+ __MAX(VOUT_MAX_PICTURES,
+ private_picture + kept_picture + decoder_picture));
+ if (allow_dr) {
+ msg_Warn(vout, "Not enough direct buffers, using system memory");
+ sys->dpb_size = 0;
+ } else {
+ sys->dpb_size = picture_pool_GetSize(display_pool) - private_picture - kept_picture;
+ }
if (sys->display.use_dr)
sys->display_pool = display_pool;
else
- sys->display_pool = picture_pool_Reserve(sys->decoder_pool, 1);;
+ sys->display_pool = picture_pool_Reserve(sys->decoder_pool, display_picture);
sys->is_decoder_pool_slow = false;
}
- sys->private_pool = picture_pool_Reserve(sys->decoder_pool, 3); /* XXX 2 for filter, 1 for SPU */
+ sys->private_pool = picture_pool_Reserve(sys->decoder_pool, private_picture);
sys->display.filtered = NULL;
return VLC_SUCCESS;
}