#define GST_V4L2_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_V4L2_BUFFER_POOL, GstV4l2BufferPool))
#define GST_V4L2_BUFFER_POOL_CAST(obj) ((GstV4l2BufferPool*)(obj))
+/* Returns true if the pool is streaming. Must be called with stream lock
+ * held. */
+#define GST_V4L2_BUFFER_POOL_IS_STREAMING(obj) (GST_V4L2_BUFFER_POOL (obj)->streaming)
+
/* This flow return is used to indicate that the last buffer has been dequeued
* during draining. This should normally only occur for mem-2-mem devices. */
#define GST_V4L2_FLOW_LAST_BUFFER GST_FLOW_CUSTOM_SUCCESS
gboolean gst_v4l2_get_output (GstV4l2Object * v4l2object, guint32 * output);
gboolean gst_v4l2_set_output (GstV4l2Object * v4l2object, guint32 output);
+/* dv timings */
+gboolean gst_v4l2_set_dv_timings (GstV4l2Object * v4l2object, struct v4l2_dv_timings *timings);
+gboolean gst_v4l2_query_dv_timings (GstV4l2Object * v4l2object, struct v4l2_dv_timings *timings);
+
/* frequency control */
gboolean gst_v4l2_get_frequency (GstV4l2Object * v4l2object, gint tunernum, gulong * frequency);
gboolean gst_v4l2_set_frequency (GstV4l2Object * v4l2object, gint tunernum, gulong frequency);
gst_v4l2src_query_preferred_dv_timings (GstV4l2Src * v4l2src,
struct PreferredCapsInfo *pref)
{
- GST_FIXME_OBJECT (v4l2src, "query dv_timings not implements");
- return NULL;
+ GstV4l2Object *obj = v4l2src->v4l2object;
+ struct v4l2_dv_timings dv_timings = { 0, };
+
+ if (!gst_v4l2_query_dv_timings (obj, &dv_timings))
+ return FALSE;
+
+ pref->width = dv_timings.bt.width;
+ pref->height = dv_timings.bt.height;
+ /* FIXME calculate frame rate */
+
+ /* If are are not streaming (e.g. we received source-change event), lock the
+ * new timing immediatly so that TRY_FMT can properly work */
+ if (!obj->pool || !GST_V4L2_BUFFER_POOL_IS_STREAMING (obj->pool))
+ gst_v4l2_set_dv_timings (obj, &dv_timings);
+
+ return TRUE;
}
static gboolean
return TRUE;
}
+
+gboolean
+gst_v4l2_set_dv_timings (GstV4l2Object * v4l2object,
+ struct v4l2_dv_timings * timings)
+{
+ gint ret;
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ ret = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_S_DV_TIMINGS, timings);
+
+ if (ret < 0) {
+ GST_ERROR_OBJECT (v4l2object->dbg_obj, "S_DV_TIMINGS failed: %s (%i)",
+ g_strerror (errno), errno);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+gst_v4l2_query_dv_timings (GstV4l2Object * v4l2object,
+ struct v4l2_dv_timings * timings)
+{
+ gint ret;
+
+ if (!GST_V4L2_IS_OPEN (v4l2object))
+ return FALSE;
+
+ ret = v4l2object->ioctl (v4l2object->video_fd, VIDIOC_QUERY_DV_TIMINGS,
+ timings);
+
+ if (ret < 0) {
+ switch (errno) {
+ case ENODATA:
+ GST_DEBUG_OBJECT (v4l2object->dbg_obj,
+ "QUERY_DV_TIMINGS not supported for this input/output");
+ break;
+ case ENOLINK:
+ GST_DEBUG_OBJECT (v4l2object->dbg_obj,
+ "No timings could be detected because no signal was found.");
+ break;
+ case ENOLCK:
+ GST_INFO_OBJECT (v4l2object->dbg_obj,
+ "The signal was unstable and the hardware could not lock on to it.");
+ break;
+ case ERANGE:
+ GST_INFO_OBJECT (v4l2object->dbg_obj,
+ "Timings were found, but they are out of range of the hardware capabilities.");
+ break;
+ default:
+ GST_ERROR_OBJECT (v4l2object->dbg_obj,
+ "QUERY_DV_TIMINGS failed: %s (%i)", g_strerror (errno), errno);
+ break;
+ }
+
+ return FALSE;
+ }
+
+ if (timings->type != V4L2_DV_BT_656_1120) {
+ GST_FIXME_OBJECT (v4l2object->dbg_obj, "Unsupported DV Timings type (%i)",
+ timings->type);
+ return FALSE;
+ }
+
+ GST_INFO_OBJECT (v4l2object->dbg_obj, "Detected DV Timings (%i x %i)",
+ timings->bt.width, timings->bt.height);
+
+ return TRUE;
+}