omxaudioenc: Implement draining of the component and use it

This makes sure that all buffers are encoded and pushed downstream
before flushing the ports and losing some buffers.
This commit is contained in:
Sebastian Dröge 2011-11-01 16:46:09 +01:00
parent 8eaf25c10e
commit 1ef38751c7
2 changed files with 72 additions and 3 deletions

View file

@ -47,6 +47,8 @@ static GstFlowReturn gst_omx_audio_enc_handle_frame (GstBaseAudioEncoder *
encoder, GstBuffer * buffer);
static void gst_omx_audio_enc_flush (GstBaseAudioEncoder * encoder);
static GstFlowReturn gst_omx_audio_enc_drain (GstOMXAudioEnc * self);
enum
{
PROP_0
@ -251,6 +253,8 @@ gst_omx_audio_enc_class_init (GstOMXAudioEncClass * klass)
static void
gst_omx_audio_enc_init (GstOMXAudioEnc * self, GstOMXAudioEncClass * klass)
{
self->drain_lock = g_mutex_new ();
self->drain_cond = g_cond_new ();
}
static gboolean
@ -311,7 +315,10 @@ gst_omx_audio_enc_close (GstOMXAudioEnc * self)
static void
gst_omx_audio_enc_finalize (GObject * object)
{
/* GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (object); */
GstOMXAudioEnc *self = GST_OMX_AUDIO_ENC (object);
g_mutex_free (self->drain_lock);
g_cond_free (self->drain_cond);
G_OBJECT_CLASS (parent_class)->finalize (object);
}
@ -337,6 +344,11 @@ gst_omx_audio_enc_change_state (GstElement * element, GstStateChange transition)
if (self->out_port)
gst_omx_port_set_flushing (self->out_port, FALSE);
self->downstream_flow_ret = GST_FLOW_OK;
g_mutex_lock (self->drain_lock);
self->draining = FALSE;
g_cond_broadcast (self->drain_cond);
g_mutex_unlock (self->drain_lock);
break;
case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
break;
@ -345,6 +357,11 @@ gst_omx_audio_enc_change_state (GstElement * element, GstStateChange transition)
gst_omx_port_set_flushing (self->in_port, TRUE);
if (self->out_port)
gst_omx_port_set_flushing (self->out_port, TRUE);
g_mutex_lock (self->drain_lock);
self->draining = FALSE;
g_cond_broadcast (self->drain_cond);
g_mutex_unlock (self->drain_lock);
break;
default:
break;
@ -484,8 +501,16 @@ gst_omx_audio_enc_loop (GstOMXAudioEnc * self)
outbuf, n_samples);
}
if (flow_ret == GST_FLOW_OK && (buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS))
flow_ret = GST_FLOW_UNEXPECTED;
if (flow_ret == GST_FLOW_OK && (buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS)) {
g_mutex_lock (self->drain_lock);
if (self->draining) {
self->draining = FALSE;
g_cond_broadcast (self->drain_cond);
} else {
flow_ret = GST_FLOW_UNEXPECTED;
}
g_mutex_unlock (self->drain_lock);
}
gst_omx_port_release_buffer (port, buf);
@ -584,6 +609,12 @@ gst_omx_audio_enc_stop (GstBaseAudioEncoder * encoder)
gst_omx_component_set_state (self->component, OMX_StateIdle);
self->downstream_flow_ret = GST_FLOW_WRONG_STATE;
g_mutex_lock (self->drain_lock);
self->draining = FALSE;
g_cond_broadcast (self->drain_cond);
g_mutex_unlock (self->drain_lock);
gst_omx_port_set_flushing (self->in_port, TRUE);
gst_omx_port_set_flushing (self->out_port, TRUE);
@ -625,6 +656,7 @@ gst_omx_audio_enc_set_format (GstBaseAudioEncoder * encoder,
* format change happened we can just exit here.
*/
if (needs_disable) {
gst_omx_audio_enc_drain (self);
if (gst_omx_port_manual_reconfigure (self->in_port, TRUE) != OMX_ErrorNone)
return FALSE;
if (gst_omx_port_set_enabled (self->in_port, FALSE) != OMX_ErrorNone)
@ -762,6 +794,8 @@ gst_omx_audio_enc_flush (GstBaseAudioEncoder * encoder)
GST_DEBUG_OBJECT (self, "Resetting encoder");
if (self->started) {
gst_omx_audio_enc_drain (self);
gst_omx_port_set_flushing (self->in_port, TRUE);
gst_omx_port_set_flushing (self->out_port, TRUE);
@ -931,3 +965,32 @@ gst_omx_audio_enc_event (GstBaseAudioEncoder * encoder, GstEvent * event)
return TRUE;
}
static GstFlowReturn
gst_omx_audio_enc_drain (GstOMXAudioEnc * self)
{
GstOMXBuffer *buf;
GstOMXAcquireBufferReturn acq_ret;
GST_DEBUG_OBJECT (self, "Draining component");
/* Send an EOS buffer to the component and let the base
* class drop the EOS event. We will send it later when
* the EOS buffer arrives on the output port. */
acq_ret = gst_omx_port_acquire_buffer (self->in_port, &buf);
if (acq_ret != GST_OMX_ACQUIRE_BUFFER_OK)
return GST_FLOW_ERROR;
GST_BASE_AUDIO_ENCODER_STREAM_UNLOCK (self);
g_mutex_lock (self->drain_lock);
self->draining = TRUE;
buf->omx_buf->nFlags |= OMX_BUFFERFLAG_EOS;
gst_omx_port_release_buffer (self->in_port, buf);
GST_DEBUG_OBJECT (self, "Waiting until component is drained");
g_cond_wait (self->drain_cond, self->drain_lock);
GST_DEBUG_OBJECT (self, "Drained component");
g_mutex_unlock (self->drain_lock);
GST_BASE_AUDIO_ENCODER_STREAM_LOCK (self);
return GST_FLOW_OK;
}

View file

@ -58,6 +58,12 @@ struct _GstOMXAudioEnc
* the first buffer */
gboolean started;
/* Draining state */
GMutex *drain_lock;
GCond *drain_cond;
/* TRUE if EOS buffers shouldn't be forwarded */
gboolean draining;
GstFlowReturn downstream_flow_ret;
};