omxvideoenc: implement decide_allocation

Increase the number of output buffers by the number of buffers requested
downstream.
Prevent buffers starvation if downstream is going to use dynamic buffer
mode on its input.

https://bugzilla.gnome.org/show_bug.cgi?id=795746
This commit is contained in:
Guillaume Desmottes 2018-04-26 12:30:47 +02:00
parent 431eac07bf
commit c8969b0dbe
5 changed files with 53 additions and 12 deletions

View file

@ -2552,17 +2552,19 @@ done:
* less buffers than the worst case in such scenarios.
*/
gboolean
gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port)
gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra)
{
OMX_PARAM_PORTDEFINITIONTYPE port_def;
guint nb;
gst_omx_port_get_port_definition (port, &port_def);
if (port_def.nBufferCountActual != port_def.nBufferCountMin) {
port_def.nBufferCountActual = port_def.nBufferCountMin;
nb = port_def.nBufferCountMin + extra;
if (port_def.nBufferCountActual != nb) {
port_def.nBufferCountActual = nb;
GST_DEBUG_OBJECT (port->comp->parent,
"set port %d nBufferCountActual to %d",
(guint) port->index, (guint) port_def.nBufferCountActual);
"set port %d nBufferCountActual to %d", (guint) port->index, nb);
if (gst_omx_port_update_port_definition (port, &port_def) != OMX_ErrorNone)
return FALSE;

View file

@ -455,7 +455,7 @@ OMX_ERRORTYPE gst_omx_port_mark_reconfigured (GstOMXPort * port);
OMX_ERRORTYPE gst_omx_port_set_enabled (GstOMXPort * port, gboolean enabled);
OMX_ERRORTYPE gst_omx_port_wait_enabled (GstOMXPort * port, GstClockTime timeout);
gboolean gst_omx_port_is_enabled (GstOMXPort * port);
gboolean gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port);
gboolean gst_omx_port_ensure_buffer_count_actual (GstOMXPort * port, guint extra);
/* OMX 1.2.0 dynamic allocation mode */
gboolean gst_omx_is_dynamic_allocation_supported (void);

View file

@ -2335,7 +2335,7 @@ gst_omx_video_dec_ensure_nb_in_buffers (GstOMXVideoDec * self)
GstOMXVideoDecClass *klass = GST_OMX_VIDEO_DEC_GET_CLASS (self);
if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
if (!gst_omx_port_ensure_buffer_count_actual (self->dec_in_port))
if (!gst_omx_port_ensure_buffer_count_actual (self->dec_in_port, 0))
return FALSE;
}

View file

@ -226,6 +226,8 @@ static gboolean gst_omx_video_enc_propose_allocation (GstVideoEncoder * encoder,
GstQuery * query);
static GstCaps *gst_omx_video_enc_getcaps (GstVideoEncoder * encoder,
GstCaps * filter);
static gboolean gst_omx_video_enc_decide_allocation (GstVideoEncoder * encoder,
GstQuery * query);
static GstFlowReturn gst_omx_video_enc_drain (GstOMXVideoEnc * self);
@ -481,6 +483,8 @@ gst_omx_video_enc_class_init (GstOMXVideoEncClass * klass)
video_encoder_class->propose_allocation =
GST_DEBUG_FUNCPTR (gst_omx_video_enc_propose_allocation);
video_encoder_class->getcaps = GST_DEBUG_FUNCPTR (gst_omx_video_enc_getcaps);
video_encoder_class->decide_allocation =
GST_DEBUG_FUNCPTR (gst_omx_video_enc_decide_allocation);
klass->cdata.type = GST_OMX_COMPONENT_TYPE_FILTER;
klass->cdata.default_sink_template_caps = "video/x-raw, "
@ -1372,11 +1376,18 @@ static gboolean
gst_omx_video_enc_ensure_nb_out_buffers (GstOMXVideoEnc * self)
{
GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
guint extra = 0;
if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
if (!gst_omx_port_ensure_buffer_count_actual (self->enc_out_port))
return FALSE;
}
if (!(klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL))
return TRUE;
/* If dowstream tell us how many buffers it needs allocate as many extra buffers so we won't starve
* if it keeps them downstream (like when using dynamic mode). */
if (self->nb_downstream_buffers)
extra = self->nb_downstream_buffers;
if (!gst_omx_port_ensure_buffer_count_actual (self->enc_out_port, extra))
return FALSE;
return TRUE;
}
@ -1641,6 +1652,7 @@ gst_omx_video_enc_start (GstVideoEncoder * encoder)
self->last_upstream_ts = 0;
self->downstream_flow_ret = GST_FLOW_OK;
self->nb_downstream_buffers = 0;
return TRUE;
}
@ -1883,7 +1895,7 @@ gst_omx_video_enc_ensure_nb_in_buffers (GstOMXVideoEnc * self)
GstOMXVideoEncClass *klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
if ((klass->cdata.hacks & GST_OMX_HACK_ENSURE_BUFFER_COUNT_ACTUAL)) {
if (!gst_omx_port_ensure_buffer_count_actual (self->enc_in_port))
if (!gst_omx_port_ensure_buffer_count_actual (self->enc_in_port, 0))
return FALSE;
}
@ -3030,3 +3042,28 @@ gst_omx_video_enc_getcaps (GstVideoEncoder * encoder, GstCaps * filter)
return ret;
}
static gboolean
gst_omx_video_enc_decide_allocation (GstVideoEncoder * encoder,
GstQuery * query)
{
GstOMXVideoEnc *self = GST_OMX_VIDEO_ENC (encoder);
guint min = 1;
if (!GST_VIDEO_ENCODER_CLASS
(gst_omx_video_enc_parent_class)->decide_allocation (encoder, query))
return FALSE;
if (gst_query_get_n_allocation_pools (query)) {
gst_query_parse_nth_allocation_pool (query, 0, NULL, NULL, &min, NULL);
GST_DEBUG_OBJECT (self,
"Downstream requested %d buffers, adjust number of output buffers accordingly",
min);
} else {
GST_DEBUG_OBJECT (self, "Downstream didn't set any allocation pool info");
}
self->nb_downstream_buffers = min;
return TRUE;
}

View file

@ -101,6 +101,8 @@ struct _GstOMXVideoEnc
GstOMXBufferAllocation input_allocation;
/* TRUE if encoder is passing dmabuf's fd directly to the OMX component */
gboolean input_dmabuf;
/* Number of buffers requested downstream */
guint nb_downstream_buffers;
#ifdef USE_OMX_TARGET_ZYNQ_USCALE_PLUS
GEnumClass *alg_roi_quality_enum_class;