static gboolean gst_v4l2_video_dec_stop (GstVideoDecoder * decoder) { GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder); GST_DEBUG_OBJECT (self, "Stopping"); gst_v4l2_object_unlock (self->v4l2output); gst_v4l2_object_unlock (self->v4l2capture); /* Wait for capture thread to stop */ gst_pad_stop_task (decoder->srcpad); GST_VIDEO_DECODER_STREAM_LOCK (decoder); self->output_flow = GST_FLOW_OK; GST_VIDEO_DECODER_STREAM_UNLOCK (decoder); /* Should have been flushed already */ g_assert (g_atomic_int_get (&self->active) == FALSE); g_assert (g_atomic_int_get (&self->processing) == FALSE); gst_v4l2_object_stop (self->v4l2output); gst_v4l2_object_stop (self->v4l2capture); if (self->input_state) { gst_video_codec_state_unref (self->input_state); self->input_state = NULL; } GST_DEBUG_OBJECT (self, "Stopped"); return TRUE; }
static gboolean gst_v4l2_transform_stop (GstBaseTransform * trans) { GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans); GST_DEBUG_OBJECT (self, "Stop"); gst_v4l2_object_stop (self->v4l2output); gst_v4l2_object_stop (self->v4l2capture); gst_caps_replace (&self->incaps, NULL); gst_caps_replace (&self->outcaps, NULL); return TRUE; }
static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) { GstV4l2Src *v4l2src; GstV4l2Object *obj; v4l2src = GST_V4L2SRC (src); obj = v4l2src->v4l2object; /* make sure the caps changed before doing anything */ if (gst_v4l2_object_caps_equal (obj, caps)) return TRUE; /* make sure we stop capturing and dealloc buffers */ if (!gst_v4l2_object_stop (obj)) return FALSE; g_signal_emit (v4l2src, gst_v4l2_signals[SIGNAL_PRE_SET_FORMAT], 0, v4l2src->v4l2object->video_fd, caps); if (!gst_v4l2_object_set_format (obj, caps)) /* error already posted */ return FALSE; return TRUE; }
static gboolean gst_v4l2src_set_caps (GstBaseSrc * src, GstCaps * caps) { GstV4l2Src *v4l2src; GstV4l2Object *obj; v4l2src = GST_V4L2SRC (src); obj = v4l2src->v4l2object; /* make sure the caps changed before doing anything */ if (gst_v4l2_object_caps_equal (obj, caps)) return TRUE; if (GST_V4L2_IS_ACTIVE (obj)) { /* Just check if the format is acceptable, once we know * no buffers should be outstanding we try S_FMT. * * Basesrc will do an allocation query that * should indirectly reclaim buffers, after that we can * set the format and then configure our pool */ if (gst_v4l2_object_try_format (obj, caps)) { v4l2src->renegotiation_adjust = v4l2src->offset + 1; v4l2src->pending_set_fmt = TRUE; } else return FALSE; } else { /* make sure we stop capturing and dealloc buffers */ if (!gst_v4l2_object_stop (obj)) return FALSE; return gst_v4l2src_set_format (v4l2src, caps); } return TRUE; }
static gboolean gst_v4l2sink_set_caps (GstBaseSink * bsink, GstCaps * caps) { GstV4l2Sink *v4l2sink = GST_V4L2SINK (bsink); GstV4l2Object *obj = v4l2sink->v4l2object; LOG_CAPS (v4l2sink, caps); if (!GST_V4L2_IS_OPEN (v4l2sink->v4l2object)) { GST_DEBUG_OBJECT (v4l2sink, "device is not open"); return FALSE; } /* make sure the caps changed before doing anything */ if (gst_v4l2_object_caps_equal (obj, caps)) return TRUE; if (!gst_v4l2_object_stop (obj)) goto stop_failed; if (!gst_v4l2_object_set_format (v4l2sink->v4l2object, caps)) goto invalid_format; gst_v4l2sink_sync_overlay_fields (v4l2sink); gst_v4l2sink_sync_crop_fields (v4l2sink); #ifdef HAVE_XVIDEO gst_v4l2_video_overlay_prepare_window_handle (v4l2sink->v4l2object, TRUE); #endif GST_INFO_OBJECT (v4l2sink, "outputting buffers via mmap()"); v4l2sink->video_width = GST_V4L2_WIDTH (v4l2sink->v4l2object); v4l2sink->video_height = GST_V4L2_HEIGHT (v4l2sink->v4l2object); /* TODO: videosink width/height should be scaled according to * pixel-aspect-ratio */ GST_VIDEO_SINK_WIDTH (v4l2sink) = v4l2sink->video_width; GST_VIDEO_SINK_HEIGHT (v4l2sink) = v4l2sink->video_height; return TRUE; /* ERRORS */ stop_failed: { GST_DEBUG_OBJECT (v4l2sink, "failed to stop streaming"); return FALSE; } invalid_format: { /* error already posted */ GST_DEBUG_OBJECT (v4l2sink, "can't set format"); return FALSE; } }
static GstStateChangeReturn gst_v4l2sink_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstV4l2Sink *v4l2sink = GST_V4L2SINK (element); GST_DEBUG_OBJECT (v4l2sink, "%d -> %d", GST_STATE_TRANSITION_CURRENT (transition), GST_STATE_TRANSITION_NEXT (transition)); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: /* open the device */ if (!gst_v4l2_object_open (v4l2sink->v4l2object)) return GST_STATE_CHANGE_FAILURE; break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: if (!gst_v4l2_object_stop (v4l2sink->v4l2object)) return GST_STATE_CHANGE_FAILURE; break; case GST_STATE_CHANGE_READY_TO_NULL: /* we need to call stop here too */ if (!gst_v4l2_object_stop (v4l2sink->v4l2object)) return GST_STATE_CHANGE_FAILURE; /* close the device */ if (!gst_v4l2_object_close (v4l2sink->v4l2object)) return GST_STATE_CHANGE_FAILURE; break; default: break; } return ret; }
static gboolean gst_v4l2src_stop (GstBaseSrc * src) { GstV4l2Src *v4l2src = GST_V4L2SRC (src); GstV4l2Object *obj = v4l2src->v4l2object; if (GST_V4L2_IS_ACTIVE (obj)) { if (!gst_v4l2_object_stop (obj)) return FALSE; } return TRUE; }
static gboolean gst_v4l2_transform_set_caps (GstBaseTransform * trans, GstCaps * incaps, GstCaps * outcaps) { GstV4l2Transform *self = GST_V4L2_TRANSFORM (trans); if (self->incaps && self->outcaps) { if (gst_caps_is_equal (incaps, self->incaps) && gst_caps_is_equal (outcaps, self->outcaps)) { GST_DEBUG_OBJECT (trans, "Caps did not changed"); return TRUE; } } /* TODO Add renegotiation support */ g_return_val_if_fail (!GST_V4L2_IS_ACTIVE (self->v4l2output), FALSE); g_return_val_if_fail (!GST_V4L2_IS_ACTIVE (self->v4l2capture), FALSE); gst_caps_replace (&self->incaps, incaps); gst_caps_replace (&self->outcaps, outcaps); if (!gst_v4l2_object_set_format (self->v4l2output, incaps)) goto incaps_failed; if (!gst_v4l2_object_set_format (self->v4l2capture, outcaps)) goto outcaps_failed; /* FIXME implement fallback if crop not supported */ if (!gst_v4l2_object_set_crop (self->v4l2output)) goto failed; if (!gst_v4l2_object_set_crop (self->v4l2capture)) goto failed; return TRUE; incaps_failed: { GST_ERROR_OBJECT (self, "failed to set input caps: %" GST_PTR_FORMAT, incaps); goto failed; } outcaps_failed: { gst_v4l2_object_stop (self->v4l2output); GST_ERROR_OBJECT (self, "failed to set output caps: %" GST_PTR_FORMAT, outcaps); goto failed; } failed: return FALSE; }
static GstStateChangeReturn gst_v4l2sink_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstV4l2Sink *v4l2sink = GST_V4L2SINK (element); GST_DEBUG_OBJECT (v4l2sink, "%d -> %d", GST_STATE_TRANSITION_CURRENT (transition), GST_STATE_TRANSITION_NEXT (transition)); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: /* open the device */ if (!gst_v4l2_object_start (v4l2sink->v4l2object)) return GST_STATE_CHANGE_FAILURE; break; default: break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: if (v4l2sink->state == STATE_STREAMING) { if (!gst_v4l2_object_stop_streaming (v4l2sink->v4l2object)) { return GST_STATE_CHANGE_FAILURE; } v4l2sink->state = STATE_PENDING_STREAMON; } break; case GST_STATE_CHANGE_READY_TO_NULL: if (NULL != v4l2sink->pool) gst_v4l2_buffer_pool_destroy (v4l2sink->pool); v4l2sink->pool = NULL; /* close the device */ if (!gst_v4l2_object_stop (v4l2sink->v4l2object)) return GST_STATE_CHANGE_FAILURE; v4l2sink->state = STATE_OFF; break; default: break; } return ret; }
static gboolean gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query) { GstV4l2Src *src = GST_V4L2SRC (bsrc); gboolean ret = TRUE; if (src->pending_set_fmt) { GstCaps *caps = gst_pad_get_current_caps (GST_BASE_SRC_PAD (bsrc)); if (!gst_v4l2_object_stop (src->v4l2object)) return FALSE; ret = gst_v4l2src_set_format (src, caps); gst_caps_unref (caps); src->pending_set_fmt = FALSE; } if (ret) { ret = gst_v4l2_object_decide_allocation (src->v4l2object, query); if (ret) ret = GST_BASE_SRC_CLASS (parent_class)->decide_allocation (bsrc, query); } if (ret) { if (!gst_buffer_pool_set_active (src->v4l2object->pool, TRUE)) goto activate_failed; } return ret; activate_failed: { GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (_("Failed to allocate required memory.")), ("Buffer pool activation failed")); return FALSE; } }