"Output port %u needs reconfiguration but has buffers pending",
port->index);
_buf = g_queue_pop_head (port->pending_buffers);
- g_assert (_buf != NULL);
+
ret = GST_OMX_ACQUIRE_BUFFER_OK;
goto done;
}
signalled = TRUE;
last_error = OMX_ErrorNone;
while (signalled && last_error == OMX_ErrorNone && !port->flushed
- && port->buffers->len != g_queue_get_length (port->pending_buffers)) {
+ && port->buffers->len > g_queue_get_length (port->pending_buffers)) {
signalled = g_cond_timed_wait (port->port_cond, port->port_lock, timeval);
last_error = gst_omx_component_get_last_error (comp);
/* Enqueue all buffers for the component to fill */
while ((buf = g_queue_pop_head (port->pending_buffers))) {
+ if (!buf)
+ continue;
+
g_assert (!buf->used);
/* Reset all flags, some implementations don't
signalled = TRUE;
last_error = OMX_ErrorNone;
while (signalled && last_error == OMX_ErrorNone && (port->buffers
- && port->buffers->len !=
- g_queue_get_length (port->pending_buffers))) {
+ && port->buffers->len > g_queue_get_length (port->pending_buffers))) {
signalled = g_cond_timed_wait (port->port_cond, port->port_lock, timeval);
last_error = gst_omx_component_get_last_error (comp);
}
/* Enqueue all buffers for the component to fill */
while ((buf = g_queue_pop_head (port->pending_buffers))) {
+ if (!buf)
+ continue;
+
g_assert (!buf->used);
/* Reset all flags, some implementations don't
hacks_flags |= GST_OMX_HACK_SYNCFRAME_FLAG_NOT_USED;
else if (g_str_equal (*hacks, "no-component-reconfigure"))
hacks_flags |= GST_OMX_HACK_NO_COMPONENT_RECONFIGURE;
+ else if (g_str_equal (*hacks, "no-empty-eos-buffer"))
+ hacks_flags |= GST_OMX_HACK_NO_EMPTY_EOS_BUFFER;
else
GST_WARNING ("Unknown hack: %s", *hacks);
hacks++;
return;
}
- g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK && buf != NULL);
+ g_assert (acq_return == GST_OMX_ACQUIRE_BUFFER_OK);
- GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
- buf->omx_buf->nTimeStamp);
+ if (buf) {
- /* This prevents a deadlock between the srcpad stream
- * lock and the videocodec stream lock, if ::reset()
- * is called at the wrong time
- */
- if (gst_omx_port_is_flushing (self->out_port)) {
- GST_DEBUG_OBJECT (self, "Flushing");
- gst_omx_port_release_buffer (self->out_port, buf);
- goto flushing;
- }
+ GST_DEBUG_OBJECT (self, "Handling buffer: 0x%08x %lu", buf->omx_buf->nFlags,
+ buf->omx_buf->nTimeStamp);
- GST_BASE_VIDEO_CODEC_STREAM_LOCK (self);
- frame = _find_nearest_frame (self, buf);
+ /* This prevents a deadlock between the srcpad stream
+ * lock and the videocodec stream lock, if ::reset()
+ * is called at the wrong time
+ */
+ if (gst_omx_port_is_flushing (self->out_port)) {
+ GST_DEBUG_OBJECT (self, "Flushing");
+ gst_omx_port_release_buffer (self->out_port, buf);
+ goto flushing;
+ }
- is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS);
+ GST_BASE_VIDEO_CODEC_STREAM_LOCK (self);
+ frame = _find_nearest_frame (self, buf);
- g_assert (klass->handle_output_frame);
- flow_ret = klass->handle_output_frame (self, self->out_port, buf, frame);
+ is_eos = ! !(buf->omx_buf->nFlags & OMX_BUFFERFLAG_EOS);
- if (is_eos || flow_ret == GST_FLOW_UNEXPECTED) {
- g_mutex_lock (self->drain_lock);
- if (self->draining) {
- GST_DEBUG_OBJECT (self, "Drained");
- self->draining = FALSE;
- g_cond_broadcast (self->drain_cond);
- } else if (flow_ret == GST_FLOW_OK) {
- GST_DEBUG_OBJECT (self, "Component signalled EOS");
- flow_ret = GST_FLOW_UNEXPECTED;
+ g_assert (klass->handle_output_frame);
+ flow_ret = klass->handle_output_frame (self, self->out_port, buf, frame);
+
+ if (is_eos || flow_ret == GST_FLOW_UNEXPECTED) {
+ g_mutex_lock (self->drain_lock);
+ if (self->draining) {
+ GST_DEBUG_OBJECT (self, "Drained");
+ self->draining = FALSE;
+ g_cond_broadcast (self->drain_cond);
+ } else if (flow_ret == GST_FLOW_OK) {
+ GST_DEBUG_OBJECT (self, "Component signalled EOS");
+ flow_ret = GST_FLOW_UNEXPECTED;
+ }
+ g_mutex_unlock (self->drain_lock);
+ } else {
+ GST_DEBUG_OBJECT (self, "Finished frame: %s",
+ gst_flow_get_name (flow_ret));
}
- g_mutex_unlock (self->drain_lock);
- } else {
- GST_DEBUG_OBJECT (self, "Finished frame: %s", gst_flow_get_name (flow_ret));
- }
- gst_omx_port_release_buffer (port, buf);
+ gst_omx_port_release_buffer (port, buf);
- self->downstream_flow_ret = flow_ret;
+ self->downstream_flow_ret = flow_ret;
+
+ } else {
+ g_assert ((klass->hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER));
+ flow_ret = GST_FLOW_UNEXPECTED;
+ }
if (flow_ret != GST_FLOW_OK)
goto flow_error;
gst_omx_video_enc_finish (GstBaseVideoEncoder * encoder)
{
GstOMXVideoEnc *self;
+ GstOMXVideoEncClass *klass;
GstOMXBuffer *buf;
GstOMXAcquireBufferReturn acq_ret;
self = GST_OMX_VIDEO_ENC (encoder);
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
GST_DEBUG_OBJECT (self, "Sending EOS to the component");
}
self->eos = TRUE;
+ if ((klass->hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+ GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+
+ /* Insert a NULL into the queue to signal EOS */
+ g_mutex_lock (self->out_port->port_lock);
+ g_queue_push_tail (self->out_port->pending_buffers, NULL);
+ g_cond_broadcast (self->out_port->port_cond);
+ g_mutex_unlock (self->out_port->port_lock);
+
+ return GST_BASE_VIDEO_ENCODER_FLOW_DROPPED;
+ }
+
/* Make sure to release the base class stream lock, otherwise
* _loop() can't call _finish_frame() and we might block forever
* because no input buffers are released */
static GstFlowReturn
gst_omx_video_enc_drain (GstOMXVideoEnc * self)
{
+ GstOMXVideoEncClass *klass;
GstOMXBuffer *buf;
GstOMXAcquireBufferReturn acq_ret;
GST_DEBUG_OBJECT (self, "Draining component");
+ klass = GST_OMX_VIDEO_ENC_GET_CLASS (self);
+
if (!self->started) {
GST_DEBUG_OBJECT (self, "Component not started yet");
return GST_FLOW_OK;
return GST_FLOW_OK;
}
+ if ((klass->hacks & GST_OMX_HACK_NO_EMPTY_EOS_BUFFER)) {
+ GST_WARNING_OBJECT (self, "Component does not support empty EOS buffers");
+ return GST_FLOW_OK;
+ }
+
/* Make sure to release the base class stream lock, otherwise
* _loop() can't call _finish_frame() and we might block forever
* because no input buffers are released */