v4l2: Add support for setting memory:DMABuf caps
authorNicolas Dufresne <nicolas.dufresne@collabora.com>
Thu, 22 Aug 2024 20:08:03 +0000 (16:08 -0400)
committerGStreamer Marge Bot <gitlab-merge-bot@gstreamer-foundation.org>
Wed, 18 Dec 2024 23:34:08 +0000 (23:34 +0000)
This is the final step to allow negotiation of this caps features. Limiting the
features based on the io-mode shall come next.

Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/7633>

subprojects/gst-plugins-good/sys/v4l2/gstv4l2bufferpool.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2object.h
subprojects/gst-plugins-good/sys/v4l2/gstv4l2src.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2transform.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2videodec.c
subprojects/gst-plugins-good/sys/v4l2/gstv4l2videoenc.c

index f422ce7a4700c55945ac674926fcccfb64ad22f5..98c7dbe084431bd2e33e7fcb0a46e3526f127204 100644 (file)
@@ -449,7 +449,7 @@ gst_v4l2_buffer_pool_alloc_buffer (GstBufferPool * bpool, GstBuffer ** buffer,
   GstVideoInfo *info;
 
   obj = pool->obj;
-  info = &obj->info;
+  info = &obj->info.vinfo;
 
   switch (obj->mode) {
     case GST_V4L2_IO_RW:
@@ -622,8 +622,8 @@ gst_v4l2_buffer_pool_set_config (GstBufferPool * bpool, GstStructure * config)
   }
 
   /* Always update the config to ensure the configured size matches */
-  gst_buffer_pool_config_set_params (config, caps, obj->info.size, min_buffers,
-      max_buffers);
+  gst_buffer_pool_config_set_params (config, caps, obj->info.vinfo.size,
+      min_buffers, max_buffers);
 
   /* keep a GstVideoInfo with defaults for the when we need to copy */
   gst_video_info_from_caps (&pool->caps_info, caps);
@@ -1244,7 +1244,7 @@ gst_v4l2_buffer_pool_dqbuf (GstV4l2BufferPool * pool, GstBuffer ** buffer,
   GstV4l2Object *obj = pool->obj;
   GstClockTime timestamp;
   GstV4l2MemoryGroup *group;
-  const GstVideoInfo *info = &obj->info;
+  const GstVideoInfo *info = &obj->info.vinfo;
   gint i;
   gint old_buffer_state;
 
@@ -1797,7 +1797,7 @@ gst_v4l2_buffer_pool_new (GstV4l2Object * obj, GstCaps * caps)
   gst_object_ref (obj->element);
 
   config = gst_buffer_pool_get_config (GST_BUFFER_POOL_CAST (pool));
-  gst_buffer_pool_config_set_params (config, caps, obj->info.size, 0, 0);
+  gst_buffer_pool_config_set_params (config, caps, obj->info.vinfo.size, 0, 0);
   /* This will simply set a default config, but will not configure the pool
    * because min and max are not valid */
   gst_buffer_pool_set_config (GST_BUFFER_POOL_CAST (pool), config);
@@ -1827,7 +1827,7 @@ gst_v4l2_do_read (GstV4l2BufferPool * pool, GstBuffer * buf)
   GstMapInfo map;
   gint toread;
 
-  toread = obj->info.size;
+  toread = obj->info.vinfo.size;
 
   GST_LOG_OBJECT (pool, "reading %d bytes into buffer %p", toread, buf);
 
index 0b439aeddebda22abf2db8fd4919b19aba447734..4730df42ba41f00f45aa494d99a3f6f98c5d2490 100644 (file)
@@ -1443,6 +1443,31 @@ gst_v4l2_object_get_desc_from_video_format (GstVideoFormat format,
   return ret;
 }
 
+static const GstV4L2FormatDesc *
+gst_v4l2_object_get_desc_from_drm_fourcc (guint32 drm_fourcc,
+    guint64 drm_modifier, const GstV4L2FormatDesc ** fallback)
+{
+  const GstV4L2FormatDesc *ret = NULL;
+  gint i;
+
+  if (fallback)
+    *fallback = NULL;
+
+  for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
+    if (gst_v4l2_formats[i].drm_fourcc == drm_fourcc
+        && gst_v4l2_formats[i].drm_modifier == drm_modifier) {
+      if (!ret)
+        ret = &gst_v4l2_formats[i];
+      else if (fallback && !*fallback)
+        *fallback = &gst_v4l2_formats[i];
+      else
+        break;
+    }
+  }
+
+  return ret;
+}
+
 static gboolean
 gst_v4l2_object_v4l2fourcc_is_codec (guint32 fourcc)
 {
@@ -1642,7 +1667,8 @@ gst_v4l2_object_is_raw (GstV4l2Object * v4l2object)
 {
   gint i;
 
-  if (GST_VIDEO_INFO_FORMAT (&v4l2object->info) != GST_VIDEO_FORMAT_ENCODED)
+  if (GST_VIDEO_INFO_FORMAT (&v4l2object->info.vinfo) !=
+      GST_VIDEO_FORMAT_ENCODED)
     return TRUE;
 
   for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
@@ -1876,6 +1902,8 @@ gst_v4l2_object_probe_template_caps (const gchar * device, gint video_fd,
 }
 
 /* collect data for the given caps
+ * @v4l2object: the associated GstV4l2Object
+ * @info: the format information as GstVideoInfoDmaDrm
  * @caps: given input caps
  * @format: location for the v4l format
  * @w/@h: location for width and height
@@ -1884,7 +1912,7 @@ gst_v4l2_object_probe_template_caps (const gchar * device, gint video_fd,
  */
 static gboolean
 gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
-    struct v4l2_fmtdesc **format, GstVideoInfo * info)
+    struct v4l2_fmtdesc **format, GstVideoInfoDmaDrm * info)
 {
   GstStructure *structure;
   guint32 fourcc = 0, fourcc_nc = 0;
@@ -1895,13 +1923,27 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
 
   mimetype = gst_structure_get_name (structure);
 
-  if (!gst_video_info_from_caps (info, caps))
+  if (!gst_video_info_dma_drm_from_caps (info, caps) &&
+      !gst_video_info_from_caps (&info->vinfo, caps))
     goto invalid_format;
 
   if (g_str_equal (mimetype, "video/x-raw")) {
-    const GstV4L2FormatDesc *desc, *fallback_desc;
-    GstVideoFormat format = GST_VIDEO_INFO_FORMAT (info);
-    desc = gst_v4l2_object_get_desc_from_video_format (format, &fallback_desc);
+    const GstV4L2FormatDesc *desc, *fallback_desc = NULL;
+    GstVideoFormat format = GST_VIDEO_INFO_FORMAT (&info->vinfo);
+    if (format == GST_VIDEO_FORMAT_DMA_DRM) {
+      const GstStructure *s = gst_caps_get_structure (caps, 0);
+      guint64 drm_modifier;
+      guint32 drm_fourcc =
+          gst_video_dma_drm_fourcc_from_string (gst_structure_get_string (s,
+              "drm-format"), &drm_modifier);
+      /* we can't support single plane fallback with opaque DRM fourcc since we
+       * don't know how to extrapolate the missing strides and offsets. */
+      desc = gst_v4l2_object_get_desc_from_drm_fourcc (drm_fourcc, drm_modifier,
+          NULL);
+    } else {
+      desc =
+          gst_v4l2_object_get_desc_from_video_format (format, &fallback_desc);
+    }
     if (desc)
       fourcc_nc = desc->v4l2_format;
     if (fallback_desc)
@@ -3149,11 +3191,12 @@ default_frame_sizes:
 
     if (!v4l2object->skip_try_fmt_probes) {
       gint probed_w, probed_h;
-      if (v4l2object->info.width >= min_w && v4l2object->info.width <= max_w &&
-          v4l2object->info.height >= min_h
-          && v4l2object->info.height <= max_h) {
-        probed_w = v4l2object->info.width;
-        probed_h = v4l2object->info.height;
+      if (v4l2object->info.vinfo.width >= min_w &&
+          v4l2object->info.vinfo.width <= max_w &&
+          v4l2object->info.vinfo.height >= min_h
+          && v4l2object->info.vinfo.height <= max_h) {
+        probed_w = v4l2object->info.vinfo.width;
+        probed_h = v4l2object->info.vinfo.height;
       } else {
         probed_w = max_w;
         probed_h = max_h;
@@ -3430,15 +3473,15 @@ gst_v4l2_object_extrapolate_info (GstV4l2Object * v4l2object,
 static void
 gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
     struct v4l2_fmtdesc *fmtdesc, struct v4l2_format *format,
-    GstVideoInfo * info, GstVideoAlignment * align)
+    GstVideoInfoDmaDrm * info, GstVideoAlignment * align)
 {
-  const GstVideoFormatInfo *finfo = info->finfo;
+  const GstVideoFormatInfo *finfo = info->vinfo.finfo;
   gboolean standard_stride = TRUE;
   gint stride, pstride, padded_width, padded_height, i;
 
-  if (GST_VIDEO_INFO_FORMAT (info) == GST_VIDEO_FORMAT_ENCODED) {
+  if (GST_VIDEO_INFO_FORMAT (&info->vinfo) == GST_VIDEO_FORMAT_ENCODED) {
     v4l2object->n_v4l2_planes = 1;
-    info->size = format->fmt.pix.sizeimage;
+    info->vinfo.size = format->fmt.pix.sizeimage;
     goto store_info;
   }
 
@@ -3455,7 +3498,7 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
     /* pstride can be 0 for complex formats */
     GST_WARNING_OBJECT (v4l2object->dbg_obj,
         "format %s has a pstride of 0, cannot compute padded with",
-        gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (info)));
+        gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&info->vinfo)));
     padded_width = format->fmt.pix.width;
   }
 
@@ -3464,7 +3507,7 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
         "Driver bug detected, stride (%d) is too small for the width (%d)",
         padded_width, format->fmt.pix.width);
 
-  align->padding_right = padded_width - info->width - align->padding_left;
+  align->padding_right = padded_width - info->vinfo.width - align->padding_left;
 
   /* adjust bottom padding */
   padded_height = format->fmt.pix.height;
@@ -3477,8 +3520,8 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
         (padded_height + tile_height - 1) / tile_height * tile_height;
   }
 
-  align->padding_bottom =
-      padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (info) - align->padding_top;
+  align->padding_bottom = padded_height -
+      GST_VIDEO_INFO_FIELD_HEIGHT (&info->vinfo) - align->padding_top;
 
   /* setup the strides and offset */
   if (V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type)) {
@@ -3486,33 +3529,40 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
 
     /* figure out the frame layout */
     v4l2object->n_v4l2_planes = MAX (1, pix_mp->num_planes);
-    info->size = 0;
+    info->vinfo.size = 0;
     for (i = 0; i < v4l2object->n_v4l2_planes; i++) {
       stride = pix_mp->plane_fmt[i].bytesperline;
 
-      if (info->stride[i] != stride)
+      if (info->vinfo.stride[i] != stride)
         standard_stride = FALSE;
 
-      gst_v4l2_object_set_stride (info, align, i, stride);
-      info->offset[i] = info->size;
-      info->size += pix_mp->plane_fmt[i].sizeimage;
+      gst_v4l2_object_set_stride (&info->vinfo, align, i, stride);
+      info->vinfo.offset[i] = info->vinfo.size;
+      info->vinfo.size += pix_mp->plane_fmt[i].sizeimage;
     }
 
     /* Extrapolate stride if planar format are being set in 1 v4l2 plane */
     if (v4l2object->n_v4l2_planes < finfo->n_planes) {
+      /* We should never negotiate single plane variant of formats unless the
+       * formats is mapped into libgstvideo, otherwise we don't know how to
+       * guess the missing strides and offsets. If you hit this assertion,
+       * please remove the mapping from V4L2 to DRM formats. */
+      g_assert (GST_VIDEO_INFO_FORMAT (&info->vinfo) !=
+          GST_VIDEO_FORMAT_UNKNOWN);
       stride = format->fmt.pix_mp.plane_fmt[0].bytesperline;
-      gst_v4l2_object_extrapolate_info (v4l2object, info, align, stride);
+      gst_v4l2_object_extrapolate_info (v4l2object, &info->vinfo, align,
+          stride);
     }
   } else {
     /* only one plane in non-MPLANE mode */
     v4l2object->n_v4l2_planes = 1;
-    info->size = format->fmt.pix.sizeimage;
+    info->vinfo.size = format->fmt.pix.sizeimage;
     stride = format->fmt.pix.bytesperline;
 
-    if (info->stride[0] != stride)
+    if (info->vinfo.stride[0] != stride)
       standard_stride = FALSE;
 
-    gst_v4l2_object_extrapolate_info (v4l2object, info, align, stride);
+    gst_v4l2_object_extrapolate_info (v4l2object, &info->vinfo, align, stride);
   }
 
   /* adjust the offset to take into account left and top */
@@ -3522,14 +3572,15 @@ gst_v4l2_object_save_format (GstV4l2Object * v4l2object,
           "Left and top padding is not permitted for tiled formats");
     memset (v4l2object->plane_size, 0, sizeof (v4l2object->plane_size));
   } else {
-    if (!gst_video_info_align_full (info, align, v4l2object->plane_size)) {
+    if (!gst_video_info_align_full (&info->vinfo, align,
+            v4l2object->plane_size)) {
       GST_WARNING_OBJECT (v4l2object->dbg_obj, "Failed to align video info");
     }
   }
 
 store_info:
   GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got sizeimage %" G_GSIZE_FORMAT,
-      info->size);
+      info->vinfo.size);
 
   /* to avoid copies we need video meta if there is padding */
   v4l2object->need_video_meta =
@@ -3550,10 +3601,10 @@ store_info:
   v4l2object->fmtdesc = fmtdesc;
 
   /* if we have a framerate pre-calculate duration */
-  if (info->fps_n > 0 && info->fps_d > 0) {
-    v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND, info->fps_d,
-        info->fps_n);
-    if (GST_VIDEO_INFO_INTERLACE_MODE (info) ==
+  if (info->vinfo.fps_n > 0 && info->vinfo.fps_d > 0) {
+    v4l2object->duration = gst_util_uint64_scale_int (GST_SECOND,
+        info->vinfo.fps_d, info->vinfo.fps_n);
+    if (GST_VIDEO_INFO_INTERLACE_MODE (&info->vinfo) ==
         GST_VIDEO_INTERLACE_MODE_ALTERNATE)
       v4l2object->duration /= 2;
   } else {
@@ -3696,7 +3747,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
   enum v4l2_field field;
   guint32 pixelformat;
   struct v4l2_fmtdesc *fmtdesc;
-  GstVideoInfo info;
+  GstVideoInfoDmaDrm info;
   GstVideoAlignment align;
   gint width, height, fps_n, fps_d;
   guint pixel_bitdepth = 8;
@@ -3720,7 +3771,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
 
   is_mplane = V4L2_TYPE_IS_MULTIPLANAR (v4l2object->type);
 
-  gst_video_info_init (&info);
+  gst_video_info_dma_drm_init (&info);
   gst_video_alignment_reset (&align);
   v4l2object->transfer = GST_VIDEO_TRANSFER_UNKNOWN;
   v4l2object->matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
@@ -3729,35 +3780,43 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
     goto invalid_caps;
 
   pixelformat = fmtdesc->pixelformat;
-  width = GST_VIDEO_INFO_WIDTH (&info);
-  height = GST_VIDEO_INFO_FIELD_HEIGHT (&info);
+  width = GST_VIDEO_INFO_WIDTH (&info.vinfo);
+  height = GST_VIDEO_INFO_FIELD_HEIGHT (&info.vinfo);
   /* if caps has no width and height info, use default value */
   if (V4L2_TYPE_IS_OUTPUT (v4l2object->type) && width == 0 && height == 0) {
     width = GST_V4L2_DEFAULT_WIDTH;
     height = GST_V4L2_DEFAULT_HEIGHT;
   }
-  fps_n = GST_VIDEO_INFO_FPS_N (&info);
-  fps_d = GST_VIDEO_INFO_FPS_D (&info);
+  fps_n = GST_VIDEO_INFO_FPS_N (&info.vinfo);
+  fps_d = GST_VIDEO_INFO_FPS_D (&info.vinfo);
+
+  n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info.vinfo);
+  if (!n_v4l_planes) {
+    /* For opaque DRM format we let the driver tell us how many planes
+     * otherwise its an encoded format and we will have 1 plane */
+    if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_DMA_DRM)
+      n_v4l_planes = GST_VIDEO_MAX_PLANES;
+    else
+      n_v4l_planes = 1;
+  }
 
-  /* if encoded format (GST_VIDEO_INFO_N_PLANES return 0)
-   * or if contiguous is preferred */
-  n_v4l_planes = GST_VIDEO_INFO_N_PLANES (&info);
-  if (!n_v4l_planes || !v4l2object->prefered_non_contiguous)
+  /* If our preference is single plane, then set te number of plane to 1 */
+  if (!v4l2object->prefered_non_contiguous)
     n_v4l_planes = 1;
 
-  field = get_v4l2_field_for_info (&info);
+  field = get_v4l2_field_for_info (&info.vinfo);
   if (field != V4L2_FIELD_NONE)
     GST_DEBUG_OBJECT (v4l2object->dbg_obj, "interlaced video");
   else
     GST_DEBUG_OBJECT (v4l2object->dbg_obj, "progressive video");
 
   /* We first pick the main colorspace from the primaries */
-  switch (info.colorimetry.primaries) {
+  switch (info.vinfo.colorimetry.primaries) {
     case GST_VIDEO_COLOR_PRIMARIES_BT709:
       /* There is three colorspaces using these primaries, use the range
        * and format type to differentiate them  */
-      if (info.colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
-        if (GST_VIDEO_INFO_IS_RGB (&info))
+      if (info.vinfo.colorimetry.range == GST_VIDEO_COLOR_RANGE_16_235) {
+        if (GST_VIDEO_INFO_IS_RGB (&info.vinfo))
           colorspace = V4L2_COLORSPACE_SRGB;
         else
           colorspace = V4L2_COLORSPACE_REC709;
@@ -3788,11 +3847,11 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
 
     default:
       GST_WARNING_OBJECT (v4l2object->dbg_obj,
-          "Unknown colorimetry primaries %d", info.colorimetry.primaries);
+          "Unknown colorimetry primaries %d", info.vinfo.colorimetry.primaries);
       break;
   }
 
-  switch (info.colorimetry.range) {
+  switch (info.vinfo.colorimetry.range) {
     case GST_VIDEO_COLOR_RANGE_0_255:
       range = V4L2_QUANTIZATION_FULL_RANGE;
       break;
@@ -3804,11 +3863,11 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
       break;
     default:
       GST_WARNING_OBJECT (v4l2object->dbg_obj,
-          "Unknown colorimetry range %d", info.colorimetry.range);
+          "Unknown colorimetry range %d", info.vinfo.colorimetry.range);
       break;
   }
 
-  switch (info.colorimetry.matrix) {
+  switch (info.vinfo.colorimetry.matrix) {
     case GST_VIDEO_COLOR_MATRIX_RGB:
       /* save the matrix so we can restore it on get() call from default */
       v4l2object->matrix = GST_VIDEO_COLOR_MATRIX_RGB;
@@ -3833,11 +3892,11 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
       break;
     default:
       GST_WARNING_OBJECT (v4l2object->dbg_obj,
-          "Unknown colorimetry matrix %d", info.colorimetry.matrix);
+          "Unknown colorimetry matrix %d", info.vinfo.colorimetry.matrix);
       break;
   }
 
-  switch (info.colorimetry.transfer) {
+  switch (info.vinfo.colorimetry.transfer) {
     case GST_VIDEO_TRANSFER_GAMMA18:
     case GST_VIDEO_TRANSFER_GAMMA20:
     case GST_VIDEO_TRANSFER_GAMMA22:
@@ -3855,7 +3914,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
     case GST_VIDEO_TRANSFER_BT2020_12:
     case GST_VIDEO_TRANSFER_BT2020_10:
     case GST_VIDEO_TRANSFER_BT709:
-      v4l2object->transfer = info.colorimetry.transfer;
+      v4l2object->transfer = info.vinfo.colorimetry.transfer;
       transfer = V4L2_XFER_FUNC_709;
       break;
     case GST_VIDEO_TRANSFER_SMPTE240M:
@@ -3875,13 +3934,13 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
       break;
     default:
       GST_WARNING_OBJECT (v4l2object->dbg_obj,
-          "Unknown colorimetry transfer %d", info.colorimetry.transfer);
+          "Unknown colorimetry transfer %d", info.vinfo.colorimetry.transfer);
       break;
   }
 
   if (colorspace == 0) {
     /* Try to guess colorspace according to pixelformat and size */
-    if (GST_VIDEO_INFO_IS_YUV (&info)) {
+    if (GST_VIDEO_INFO_IS_YUV (&info.vinfo)) {
       if (range == V4L2_QUANTIZATION_FULL_RANGE
           && matrix == V4L2_YCBCR_ENC_601 && transfer == 0) {
         /* Full range BT.601 YCbCr encoding with unknown primaries and transfer
@@ -3890,12 +3949,12 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
         transfer = V4L2_XFER_FUNC_SRGB;
       } else {
         /* SD streams likely use SMPTE170M and HD streams REC709 */
-        if (width <= 720 && GST_VIDEO_INFO_HEIGHT (&info) <= 576)
+        if (width <= 720 && GST_VIDEO_INFO_HEIGHT (&info.vinfo) <= 576)
           colorspace = V4L2_COLORSPACE_SMPTE170M;
         else
           colorspace = V4L2_COLORSPACE_REC709;
       }
-    } else if (GST_VIDEO_INFO_IS_RGB (&info)) {
+    } else if (GST_VIDEO_INFO_IS_RGB (&info.vinfo)) {
       colorspace = V4L2_COLORSPACE_SRGB;
       transfer = V4L2_XFER_FUNC_NONE;
     }
@@ -3903,7 +3962,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
 
   GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Desired format %dx%d, format "
       "%" GST_FOURCC_FORMAT " stride: %d", width, height,
-      GST_FOURCC_ARGS (pixelformat), GST_VIDEO_INFO_PLANE_STRIDE (&info, 0));
+      GST_FOURCC_ARGS (pixelformat),
+      GST_VIDEO_INFO_PLANE_STRIDE (&info.vinfo, 0));
 
   s = gst_caps_get_structure (caps, 0);
 
@@ -3927,20 +3987,20 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
     /* try to ask our preferred stride but it's not a failure if not
      * accepted */
     for (i = 0; i < n_v4l_planes; i++) {
-      gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, i);
+      gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info.vinfo, i);
 
-      if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.finfo))
+      if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.vinfo.finfo))
         stride = GST_VIDEO_TILE_X_TILES (stride) *
-            GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.finfo, i);
+            GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.vinfo.finfo, i);
 
       format.fmt.pix_mp.plane_fmt[i].bytesperline = stride;
     }
 
-    if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
+    if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_ENCODED)
       format.fmt.pix_mp.plane_fmt[0].sizeimage =
           calculate_max_sizeimage (v4l2object, pixel_bitdepth);
   } else {
-    gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info, 0);
+    gint stride = GST_VIDEO_INFO_PLANE_STRIDE (&info.vinfo, 0);
 
     format.type = v4l2object->type;
 
@@ -3949,14 +4009,14 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
     format.fmt.pix.pixelformat = pixelformat;
     format.fmt.pix.field = field;
 
-    if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.finfo))
+    if (GST_VIDEO_FORMAT_INFO_IS_TILED (info.vinfo.finfo))
       stride = GST_VIDEO_TILE_X_TILES (stride) *
-          GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.finfo, i);
+          GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info.vinfo.finfo, i);
 
     /* try to ask our preferred stride */
     format.fmt.pix.bytesperline = stride;
 
-    if (GST_VIDEO_INFO_FORMAT (&info) == GST_VIDEO_FORMAT_ENCODED)
+    if (GST_VIDEO_INFO_FORMAT (&info.vinfo) == GST_VIDEO_FORMAT_ENCODED)
       format.fmt.pix.sizeimage =
           calculate_max_sizeimage (v4l2object, pixel_bitdepth);
   }
@@ -4139,7 +4199,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
    * For some codecs the dimensions are *not* in the bitstream, IIRC VC1
    * in ASF mode for example, there is also not reason for a driver to
    * change the size. */
-  if (info.finfo->format != GST_VIDEO_FORMAT_ENCODED) {
+  if (GST_VIDEO_INFO_FORMAT (&info.vinfo) != GST_VIDEO_FORMAT_ENCODED) {
     /* We can crop larger images */
     if (format.fmt.pix.width < width || format.fmt.pix.height < height)
       goto invalid_dimensions;
@@ -4156,7 +4216,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
 
   /* used to check colorimetry and interlace mode fields presence */
   if (gst_v4l2_object_get_interlace_mode (format.fmt.pix.field,
-          &info.interlace_mode)) {
+          &info.vinfo.interlace_mode)) {
     if (gst_structure_has_field (s, "interlace-mode")) {
       if (format.fmt.pix.field != field)
         goto invalid_field;
@@ -4169,9 +4229,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
       gst_structure_remove_field (s, "interlace-mode");
   }
 
-  if (gst_v4l2_object_get_colorspace (v4l2object, &format, &info.colorimetry)) {
+  if (gst_v4l2_object_get_colorspace (v4l2object, &format,
+          &info.vinfo.colorimetry)) {
     if (gst_structure_has_field (s, "colorimetry")) {
-      if (!gst_v4l2_video_colorimetry_matches (&info.colorimetry, caps))
+      if (!gst_v4l2_video_colorimetry_matches (&info.vinfo.colorimetry, caps))
         goto invalid_colorimetry;
     }
   } else {
@@ -4187,10 +4248,10 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
   if (v4l2object->skip_try_fmt_probes) {
     if (!disable_interlacing && !gst_structure_has_field (s, "interlace-mode")) {
       gst_structure_set (s, "interlace-mode", G_TYPE_STRING,
-          gst_video_interlace_mode_to_string (info.interlace_mode), NULL);
+          gst_video_interlace_mode_to_string (info.vinfo.interlace_mode), NULL);
     }
     if (!disable_colorimetry && !gst_structure_has_field (s, "colorimetry")) {
-      gchar *str = gst_video_colorimetry_to_string (&info.colorimetry);
+      gchar *str = gst_video_colorimetry_to_string (&info.vinfo.colorimetry);
       gst_structure_set (s, "colorimetry", G_TYPE_STRING, str, NULL);
       g_free (str);
     }
@@ -4281,7 +4342,7 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
   if (try_only)                 /* good enough for trying only */
     return TRUE;
 
-  if (GST_VIDEO_INFO_HAS_ALPHA (&info)) {
+  if (GST_VIDEO_INFO_HAS_ALPHA (&info.vinfo)) {
     struct v4l2_control ctl = { 0, };
     ctl.id = V4L2_CID_ALPHA_COMPONENT;
     ctl.value = 0xff;
@@ -4303,9 +4364,9 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
 
   if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
       || v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
-    GST_VIDEO_INFO_FPS_N (&info) =
+    GST_VIDEO_INFO_FPS_N (&info.vinfo) =
         streamparm.parm.capture.timeperframe.denominator;
-    GST_VIDEO_INFO_FPS_D (&info) =
+    GST_VIDEO_INFO_FPS_D (&info.vinfo) =
         streamparm.parm.capture.timeperframe.numerator;
 
     GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got capture framerate: %u/%u",
@@ -4374,13 +4435,13 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
           "Reuse caps framerate %u/%u - fix v4l2 capture driver", fps_n, fps_d);
     }
 
-    GST_VIDEO_INFO_FPS_N (&info) = fps_n;
-    GST_VIDEO_INFO_FPS_D (&info) = fps_d;
+    GST_VIDEO_INFO_FPS_N (&info.vinfo) = fps_n;
+    GST_VIDEO_INFO_FPS_D (&info.vinfo) = fps_d;
   } else if (v4l2object->type == V4L2_BUF_TYPE_VIDEO_OUTPUT
       || v4l2object->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-    GST_VIDEO_INFO_FPS_N (&info) =
+    GST_VIDEO_INFO_FPS_N (&info.vinfo) =
         streamparm.parm.output.timeperframe.denominator;
-    GST_VIDEO_INFO_FPS_D (&info) =
+    GST_VIDEO_INFO_FPS_D (&info.vinfo) =
         streamparm.parm.output.timeperframe.numerator;
 
     GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Got output framerate: %u/%u",
@@ -4426,8 +4487,8 @@ gst_v4l2_object_set_format_full (GstV4l2Object * v4l2object, GstCaps * caps,
           "Reuse caps framerate %u/%u - fix v4l2 output driver", fps_n, fps_d);
     }
 
-    GST_VIDEO_INFO_FPS_N (&info) = fps_n;
-    GST_VIDEO_INFO_FPS_D (&info) = fps_d;
+    GST_VIDEO_INFO_FPS_N (&info.vinfo) = fps_n;
+    GST_VIDEO_INFO_FPS_D (&info.vinfo) = fps_d;
   }
 
 done:
@@ -4544,7 +4605,8 @@ invalid_colorimetry:
   {
     gchar *wanted_colorimetry;
 
-    wanted_colorimetry = gst_video_colorimetry_to_string (&info.colorimetry);
+    wanted_colorimetry =
+        gst_video_colorimetry_to_string (&info.vinfo.colorimetry);
 
     GST_V4L2_ERROR (error, RESOURCE, SETTINGS,
         (_("Device '%s' does not support %s colorimetry"),
@@ -4607,7 +4669,8 @@ gst_v4l2_object_try_format (GstV4l2Object * v4l2object, GstCaps * caps,
  * Returns: %TRUE on success, %FALSE on failure.
  */
 gboolean
-gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
+gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object,
+    GstVideoInfoDmaDrm * info)
 {
   struct v4l2_fmtdesc *fmtdesc;
   struct v4l2_format fmt;
@@ -4618,8 +4681,9 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
   guint width, height;
   GstVideoAlignment align;
   GstVideoInterlaceMode interlace_mode;
+  const GstV4L2FormatDesc *desc;
 
-  gst_video_info_init (info);
+  gst_video_info_dma_drm_init (info);
   gst_video_alignment_reset (&align);
   v4l2object->transfer = GST_VIDEO_TRANSFER_UNKNOWN;
   v4l2object->matrix = GST_VIDEO_COLOR_MATRIX_UNKNOWN;
@@ -4635,12 +4699,18 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
     goto unsupported_format;
 
   /* No need to care about mplane, the four first params are the same */
-  format = gst_v4l2_object_v4l2fourcc_to_video_format (fmt.fmt.pix.pixelformat);
-
-  /* fails if we do no translate the fmt.pix.pixelformat to GstVideoFormat */
-  if (format == GST_VIDEO_FORMAT_UNKNOWN)
+  desc = gst_v4l2_object_get_desc_from_v4l2fourcc (fmt.fmt.pix.pixelformat);
+  if (!desc)
     goto unsupported_format;
 
+  if (desc->gst_format == GST_VIDEO_FORMAT_UNKNOWN) {
+    if (!desc->drm_fourcc)
+      goto unsupported_format;
+    format = GST_VIDEO_FORMAT_DMA_DRM;
+  } else {
+    format = desc->gst_format;
+  }
+
   if (fmt.fmt.pix.width == 0 || fmt.fmt.pix.height == 0)
     goto invalid_dimensions;
 
@@ -4686,19 +4756,22 @@ gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info)
       goto unsupported_field;
   }
 
-  if (!gst_video_info_set_interlaced_format (info, format, interlace_mode,
-          width, height))
+  info->drm_fourcc = desc->drm_fourcc;
+  info->drm_modifier = desc->drm_modifier;
+
+  if (!gst_video_info_set_interlaced_format (&info->vinfo, format,
+          interlace_mode, width, height))
     goto invalid_dimensions;
 
-  gst_v4l2_object_get_colorspace (v4l2object, &fmt, &info->colorimetry);
-  gst_v4l2_object_get_streamparm (v4l2object, info);
-  if ((info->fps_n == 0 && v4l2object->info.fps_d != 0)
+  gst_v4l2_object_get_colorspace (v4l2object, &fmt, &info->vinfo.colorimetry);
+  gst_v4l2_object_get_streamparm (v4l2object, &info->vinfo);
+  if ((info->vinfo.fps_n == 0 && GST_V4L2_FPS_D (v4l2object) != 0)
       && (v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE
           || v4l2object->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)) {
-    info->fps_d = v4l2object->info.fps_d;
-    info->fps_n = v4l2object->info.fps_n;
+    info->vinfo.fps_d = GST_V4L2_FPS_D (v4l2object);
+    info->vinfo.fps_n = GST_V4L2_FPS_N (v4l2object);
     GST_DEBUG_OBJECT (v4l2object->dbg_obj, "Set capture fps to %d/%d",
-        info->fps_n, info->fps_d);
+        info->vinfo.fps_n, info->vinfo.fps_d);
   }
 
   gst_v4l2_object_save_format (v4l2object, fmtdesc, &fmt, info, &align);
@@ -4886,8 +4959,8 @@ gst_v4l2_object_setup_padding (GstV4l2Object * obj)
 
   rect.left = align->padding_left;
   rect.top = align->padding_top;
-  rect.width = obj->info.width;
-  rect.height = GST_VIDEO_INFO_FIELD_HEIGHT (&obj->info);
+  rect.width = GST_V4L2_WIDTH (obj);
+  rect.height = GST_V4L2_FIELD_HEIGHT (obj);
 
   if (V4L2_TYPE_IS_OUTPUT (obj->type)) {
     return gst_v4l2_object_set_crop (obj, &rect);
@@ -5309,39 +5382,40 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
     gsize offset[GST_VIDEO_MAX_PLANES], gint stride[GST_VIDEO_MAX_PLANES],
     gsize buffer_size, guint padded_height)
 {
-  guint p;
   gboolean need_fmt_update = FALSE;
+  GstVideoInfo *info = &obj->info.vinfo;
+  guint p;
 
-  if (n_planes != GST_VIDEO_INFO_N_PLANES (&obj->info)) {
+  if (n_planes != GST_V4L2_N_PLANES (obj)) {
     GST_WARNING_OBJECT (obj->dbg_obj,
         "Cannot match buffers with different number planes");
     return FALSE;
   }
 
   for (p = 0; p < n_planes; p++) {
-    if (stride[p] < obj->info.stride[p]) {
+    if (stride[p] < info->stride[p]) {
       GST_DEBUG_OBJECT (obj->dbg_obj,
           "Not matching as remote stride %i is smaller than %i on plane %u",
-          stride[p], obj->info.stride[p], p);
+          stride[p], info->stride[p], p);
       return FALSE;
-    } else if (stride[p] > obj->info.stride[p]) {
+    } else if (stride[p] > info->stride[p]) {
       GST_LOG_OBJECT (obj->dbg_obj,
           "Remote stride %i is higher than %i on plane %u",
-          stride[p], obj->info.stride[p], p);
+          stride[p], info->stride[p], p);
       need_fmt_update = TRUE;
     }
 
-    if (offset[p] < obj->info.offset[p]) {
+    if (offset[p] < info->offset[p]) {
       GST_DEBUG_OBJECT (obj->dbg_obj,
           "Not matching as offset %" G_GSIZE_FORMAT
           " is smaller than %" G_GSIZE_FORMAT " on plane %u",
-          offset[p], obj->info.offset[p], p);
+          offset[p], info->offset[p], p);
       return FALSE;
-    } else if (offset[p] > obj->info.offset[p]) {
+    } else if (offset[p] > info->offset[p]) {
       GST_LOG_OBJECT (obj->dbg_obj,
           "Remote offset %" G_GSIZE_FORMAT
           " is higher than %" G_GSIZE_FORMAT " on plane %u",
-          offset[p], obj->info.offset[p], p);
+          offset[p], info->offset[p], p);
       need_fmt_update = TRUE;
     }
   }
@@ -5372,7 +5446,7 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
       GST_DEBUG_OBJECT (obj->dbg_obj, "Padded height %u", padded_height);
 
       obj->align.padding_bottom =
-          padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (&obj->info);
+          padded_height - GST_VIDEO_INFO_FIELD_HEIGHT (info);
     } else {
       GST_WARNING_OBJECT (obj->dbg_obj,
           "Failed to compute padded height; keep the default one");
@@ -5388,9 +5462,9 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
       for (i = 0; i < obj->n_v4l2_planes; i++) {
         gint plane_stride = stride[i];
 
-        if (GST_VIDEO_FORMAT_INFO_IS_TILED (obj->info.finfo))
+        if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo))
           plane_stride = GST_VIDEO_TILE_X_TILES (plane_stride) *
-              GST_VIDEO_FORMAT_INFO_TILE_STRIDE (obj->info.finfo, i);
+              GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info->finfo, i);
 
         format.fmt.pix_mp.plane_fmt[i].bytesperline = plane_stride;
         wanted_stride[i] = plane_stride;
@@ -5403,9 +5477,9 @@ gst_v4l2_object_match_buffer_layout (GstV4l2Object * obj, guint n_planes,
 
       GST_DEBUG_OBJECT (obj->dbg_obj, "Wanted stride: %i", plane_stride);
 
-      if (GST_VIDEO_FORMAT_INFO_IS_TILED (obj->info.finfo))
+      if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo))
         plane_stride = GST_VIDEO_TILE_X_TILES (plane_stride) *
-            GST_VIDEO_FORMAT_INFO_TILE_STRIDE (obj->info.finfo, 0);
+            GST_VIDEO_FORMAT_INFO_TILE_STRIDE (info->finfo, 0);
 
       format.fmt.pix.bytesperline = plane_stride;
       format.fmt.pix.height = padded_height;
@@ -5620,13 +5694,13 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
         /* use the bigest size, when we use our own pool we can't really do any
          * other size than what the hardware gives us but for downstream pools
          * we can try */
-        size = MAX (size, obj->info.size);
+        size = MAX (size, GST_V4L2_SIZE (obj));
       } else if (can_share_own_pool) {
         /* no downstream pool, use our own then */
         GST_DEBUG_OBJECT (obj->dbg_obj,
             "read/write mode: no downstream pool, using our own");
         pool = gst_object_ref (obj_pool);
-        size = obj->info.size;
+        size = GST_V4L2_SIZE (obj);
         pushing_from_our_pool = TRUE;
       }
       break;
@@ -5642,7 +5716,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
       other_pool = pool;
       gst_object_unref (pool);
       pool = gst_object_ref (obj_pool);
-      size = obj->info.size;
+      size = GST_V4L2_SIZE (obj);
       break;
 
     case GST_V4L2_IO_MMAP:
@@ -5653,7 +5727,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
         if (pool)
           gst_object_unref (pool);
         pool = gst_object_ref (obj_pool);
-        size = obj->info.size;
+        size = GST_V4L2_SIZE (obj);
         GST_DEBUG_OBJECT (obj->dbg_obj,
             "streaming mode: using our own pool %" GST_PTR_FORMAT, pool);
         pushing_from_our_pool = TRUE;
@@ -5664,7 +5738,7 @@ gst_v4l2_object_decide_allocation (GstV4l2Object * obj, GstQuery * query)
       } else {
         GST_DEBUG_OBJECT (obj->dbg_obj,
             "streaming mode: no usable pool, copying to generic pool");
-        size = MAX (size, obj->info.size);
+        size = MAX (size, GST_V4L2_SIZE (obj));
       }
       break;
     case GST_V4L2_IO_AUTO:
@@ -5851,7 +5925,7 @@ gst_v4l2_object_propose_allocation (GstV4l2Object * obj, GstQuery * query)
   GstStructure *allocation_meta = NULL;
 
   /* Set defaults allocation parameters */
-  size = obj->info.size;
+  size = GST_V4L2_SIZE (obj);
   min = GST_V4L2_MIN_BUFFERS (obj);
   max = VIDEO_MAX_FRAME;
 
index 1127139e10a84b97606cc3bcbe3527a41ea8f9f6..4b14b7e625a869b28a64c2053f75e46a1b9d9898 100644 (file)
@@ -44,7 +44,7 @@ typedef struct _GstV4l2ObjectClassHelper GstV4l2ObjectClassHelper;
 
 /* size of v4l2 buffer pool in streaming case, obj->info needs to be valid */
 #define GST_V4L2_MIN_BUFFERS(obj) \
-    ((GST_VIDEO_INFO_INTERLACE_MODE (&obj->info) == \
+    ((GST_VIDEO_INFO_INTERLACE_MODE (&obj->info.vinfo) == \
       GST_VIDEO_INTERLACE_MODE_ALTERNATE) ? \
       /* 2x buffers needed with each field in its own buffer */ \
       4 : 2)
@@ -82,11 +82,14 @@ typedef int ioctl_req_t;
 typedef gulong ioctl_req_t;
 #endif
 
-#define GST_V4L2_WIDTH(o)        (GST_VIDEO_INFO_WIDTH (&(o)->info))
-#define GST_V4L2_HEIGHT(o)       (GST_VIDEO_INFO_HEIGHT (&(o)->info))
+#define GST_V4L2_WIDTH(o)        (GST_VIDEO_INFO_WIDTH (&(o)->info.vinfo))
+#define GST_V4L2_HEIGHT(o)       (GST_VIDEO_INFO_HEIGHT (&(o)->info.vinfo))
+#define GST_V4L2_FIELD_HEIGHT(o) (GST_VIDEO_INFO_FIELD_HEIGHT (&(o)->info.vinfo))
 #define GST_V4L2_PIXELFORMAT(o)  ((o)->fmtdesc->pixelformat)
-#define GST_V4L2_FPS_N(o)        (GST_VIDEO_INFO_FPS_N (&(o)->info))
-#define GST_V4L2_FPS_D(o)        (GST_VIDEO_INFO_FPS_D (&(o)->info))
+#define GST_V4L2_FPS_N(o)        (GST_VIDEO_INFO_FPS_N (&(o)->info.vinfo))
+#define GST_V4L2_FPS_D(o)        (GST_VIDEO_INFO_FPS_D (&(o)->info.vinfo))
+#define GST_V4L2_SIZE(o)         (GST_VIDEO_INFO_SIZE (&(o)->info.vinfo))
+#define GST_V4L2_N_PLANES(o)     (GST_VIDEO_INFO_N_PLANES (&(o)->info.vinfo))
 
 /* simple check whether the device is open */
 #define GST_V4L2_IS_OPEN(o)      ((o)->video_fd > 0)
@@ -145,7 +148,7 @@ struct _GstV4l2Object {
   /* the current format */
   struct v4l2_fmtdesc *fmtdesc;
   struct v4l2_format format;
-  GstVideoInfo info;
+  GstVideoInfoDmaDrm info;
   GstVideoAlignment align;
   GstVideoTransferFunction transfer;
   gsize plane_size[GST_VIDEO_MAX_PLANES];
@@ -229,7 +232,7 @@ struct _GstV4l2Object {
    * on slow USB firmwares. When this is set, gst_v4l2_set_format() will modify
    * the caps to reflect what was negotiated during fixation */
   gboolean skip_try_fmt_probes;
-  
+
   guint max_width;
   guint max_height;
 };
@@ -315,7 +318,7 @@ gboolean     gst_v4l2_object_stop        (GstV4l2Object * v4l2object);
 GstCaps *    gst_v4l2_object_probe_caps  (GstV4l2Object * v4l2object, GstCaps * filter);
 GstCaps *    gst_v4l2_object_get_caps    (GstV4l2Object * v4l2object, GstCaps * filter);
 
-gboolean     gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfo * info);
+gboolean     gst_v4l2_object_acquire_format (GstV4l2Object * v4l2object, GstVideoInfoDmaDrm * info);
 
 gboolean     gst_v4l2_object_setup_padding (GstV4l2Object * obj);
 
index 0a65b2c7d30057b559a241320a2faee8cfb5709b..cc1bbbf842db2a9d43553cf117bc375e1397ce02 100644 (file)
@@ -922,10 +922,10 @@ gst_v4l2src_decide_allocation (GstBaseSrc * bsrc, GstQuery * query)
 
     if (gst_query_get_n_allocation_pools (query))
       gst_query_set_nth_allocation_pool (query, 0, pool,
-          src->v4l2object->info.size, 1, 0);
+          src->v4l2object->info.vinfo.size, 1, 0);
     else
-      gst_query_add_allocation_pool (query, pool, src->v4l2object->info.size, 1,
-          0);
+      gst_query_add_allocation_pool (query, pool,
+          src->v4l2object->info.vinfo.size, 1, 0);
 
     if (pool)
       gst_object_unref (pool);
@@ -998,7 +998,7 @@ gst_v4l2src_query (GstBaseSrc * bsrc, GstQuery * query)
 
       /* min latency is the time to capture one frame/field */
       min_latency = gst_util_uint64_scale_int (GST_SECOND, fps_d, fps_n);
-      if (GST_VIDEO_INFO_INTERLACE_MODE (&obj->info) ==
+      if (GST_VIDEO_INFO_INTERLACE_MODE (&obj->info.vinfo) ==
           GST_VIDEO_INTERLACE_MODE_ALTERNATE)
         min_latency /= 2;
 
@@ -1160,7 +1160,7 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
 
   do {
     ret = GST_BASE_SRC_CLASS (parent_class)->alloc (GST_BASE_SRC (src), 0,
-        obj->info.size, buf);
+        obj->info.vinfo.size, buf);
 
     if (G_UNLIKELY (ret != GST_FLOW_OK)) {
       if (ret == GST_V4L2_FLOW_RESOLUTION_CHANGE) {
index 38805489df1fae8838691e813b02c14f488e8aec..97688fd299520ac71a701eb7a0cb9ac8ec54029c 100644 (file)
@@ -29,6 +29,8 @@
 #include <unistd.h>
 #include <string.h>
 
+#include <gst/allocators/allocators.h>
+
 #include "gstv4l2object.h"
 #include "gstv4l2transform.h"
 
@@ -373,23 +375,45 @@ gst_v4l2_transform_caps_remove_format_info (GstCaps * caps)
 
   n = gst_caps_get_size (caps);
   for (i = 0; i < n; i++) {
-    st = gst_caps_get_structure (caps, i);
-    f = gst_caps_get_features (caps, i);
+    GstCapsFeatures *alt_f = NULL;
 
-    /* If this is already expressed by the existing caps
-     * skip this structure */
-    if (i > 0 && gst_caps_is_subset_structure_full (res, st, f))
-      continue;
+    st = gst_structure_copy (gst_caps_get_structure (caps, i));
+    f = gst_caps_get_features (caps, i);
+    alt_f = gst_caps_features_copy (f);
+
+    /* remove all the features we support, if anything is left it means we
+     * cannot convert */
+    if (!gst_caps_features_is_any (f)) {
+      gst_caps_features_remove (alt_f, GST_CAPS_FEATURE_MEMORY_SYSTEM_MEMORY);
+      gst_caps_features_remove (alt_f, GST_CAPS_FEATURE_MEMORY_DMABUF);
+      gst_caps_features_remove (alt_f, GST_CAPS_FEATURE_FORMAT_INTERLACED);
+    }
 
-    st = gst_structure_copy (st);
     /* Only remove format info for the cases when we can actually convert */
     if (!gst_caps_features_is_any (f)
-        && gst_caps_features_is_equal (f,
-            GST_CAPS_FEATURES_MEMORY_SYSTEM_MEMORY))
-      gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
-          "width", "height", "pixel-aspect-ratio", NULL);
+        && (gst_caps_features_get_size (alt_f) == 0)) {
+      gst_structure_remove_fields (st, "format", "drm-format", "colorimetry",
+          "chroma-site", "width", "height", "pixel-aspect-ratio", NULL);
+
+      /* create an alternate feature, so that we allow converting between system
+       * memory and dmabuf */
+      if (gst_caps_features_contains (f, GST_CAPS_FEATURE_FORMAT_INTERLACED))
+        gst_caps_features_add (alt_f, GST_CAPS_FEATURE_FORMAT_INTERLACED);
+      if (!gst_caps_features_contains (f, GST_CAPS_FEATURE_MEMORY_DMABUF))
+        gst_caps_features_add (alt_f, GST_CAPS_FEATURE_MEMORY_DMABUF);
+    }
 
-    gst_caps_append_structure_full (res, st, gst_caps_features_copy (f));
+    /* If this is already expressed by the existing caps
+     * skip this structure */
+    if (!gst_caps_is_subset_structure_full (res, st, f))
+      gst_caps_append_structure_full (res, gst_structure_copy (st),
+          gst_caps_features_copy (f));
+    if (!gst_caps_is_subset_structure_full (res, st, alt_f))
+      gst_caps_append_structure_full (res, gst_structure_copy (st),
+          gst_caps_features_copy (alt_f));
+
+    gst_structure_free (st);
+    gst_caps_features_free (alt_f);
   }
 
   return res;
@@ -920,7 +944,7 @@ gst_v4l2_transform_prepare_output_buffer (GstBaseTransform * trans,
     }
 
     gst_buffer_pool_config_set_params (config, self->incaps,
-        self->v4l2output->info.size, min, min);
+        self->v4l2output->info.vinfo.size, min, min);
 
     /* There is no reason to refuse this config */
     if (!gst_buffer_pool_set_config (pool, config))
index 5c137cf7dae947249888dd284ba04246d9557f01..dc91c90dbf6cf328016b782955c3931239bd5056 100644 (file)
@@ -364,7 +364,7 @@ gst_v4l2_video_remove_padding (GstCapsFeatures * features,
 {
   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (user_data);
   GstVideoAlignment *align = &self->v4l2capture->align;
-  GstVideoInfo *info = &self->v4l2capture->info;
+  GstVideoInfo *info = &self->v4l2capture->info.vinfo;
   int width, height;
 
   if (!gst_structure_get_int (structure, "width", &width))
@@ -397,13 +397,14 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
 {
   GstV4l2VideoDec *self = GST_V4L2_VIDEO_DEC (decoder);
   GstV4l2Error error = GST_V4L2_ERROR_INIT;
-  GstVideoInfo info;
+  GstVideoInfoDmaDrm info;
   GstVideoCodecState *output_state;
-  GstCaps *acquired_caps, *fixation_caps, *available_caps, *caps, *filter;
-  GstStructure *st;
+  GstCaps *acquired_caps, *acquired_drm_caps;
+  GstCaps *fixation_caps, *available_caps, *caps, *filter;
   gboolean active;
   GstBufferPool *cpool;
   gboolean ret;
+  gint i;
 
   /* We don't allow renegotiation without careful disabling the pool */
   cpool = gst_v4l2_object_get_buffer_pool (self->v4l2capture);
@@ -415,8 +416,8 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
   }
 
   /* init capture fps according to output */
-  self->v4l2capture->info.fps_d = self->v4l2output->info.fps_d;
-  self->v4l2capture->info.fps_n = self->v4l2output->info.fps_n;
+  GST_V4L2_FPS_D (self->v4l2capture) = GST_V4L2_FPS_D (self->v4l2output);
+  GST_V4L2_FPS_N (self->v4l2capture) = GST_V4L2_FPS_N (self->v4l2output);
 
   /* For decoders G_FMT returns coded size, G_SELECTION returns visible size
    * in the compose rectangle. gst_v4l2_object_acquire_format() checks both
@@ -426,19 +427,34 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
     goto not_negotiated;
 
   /* gst_v4l2_object_acquire_format() does not set fps, copy from sink */
-  info.fps_n = self->v4l2output->info.fps_n;
-  info.fps_d = self->v4l2output->info.fps_d;
+  info.vinfo.fps_n = GST_V4L2_FPS_N (self->v4l2output);
+  info.vinfo.fps_d = GST_V4L2_FPS_D (self->v4l2output);
 
   gst_caps_replace (&self->probed_srccaps, NULL);
   self->probed_srccaps = gst_v4l2_object_probe_caps (self->v4l2capture,
       gst_v4l2_object_get_raw_caps ());
-  /* Create caps from the acquired format, remove the format field */
-  acquired_caps = gst_video_info_to_caps (&info);
-  GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
-  fixation_caps = gst_caps_copy (acquired_caps);
-  st = gst_caps_get_structure (fixation_caps, 0);
-  gst_structure_remove_fields (st, "format", "colorimetry", "chroma-site",
-      NULL);
+
+  /* Create caps from the acquired format, removing the format fields */
+  fixation_caps = gst_caps_new_empty ();
+
+  acquired_drm_caps = gst_video_info_dma_drm_to_caps (&info);
+  if (acquired_drm_caps) {
+    GST_DEBUG_OBJECT (self, "Acquired DRM caps: %" GST_PTR_FORMAT,
+        acquired_drm_caps);
+    gst_caps_append (fixation_caps, gst_caps_copy (acquired_drm_caps));
+  }
+
+  acquired_caps = gst_video_info_to_caps (&info.vinfo);
+  if (acquired_caps) {
+    GST_DEBUG_OBJECT (self, "Acquired caps: %" GST_PTR_FORMAT, acquired_caps);
+    gst_caps_append (fixation_caps, gst_caps_copy (acquired_drm_caps));
+  }
+
+  for (i = 0; i < gst_caps_get_size (fixation_caps); i++) {
+    GstStructure *st = gst_caps_get_structure (fixation_caps, i);
+    gst_structure_remove_fields (st, "format", "drm-format", "colorimetry",
+        "chroma-site", NULL);
+  }
 
   /* Probe currently available pixel formats */
   available_caps = gst_caps_copy (self->probed_srccaps);
@@ -465,6 +481,16 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
   /* Prefer the acquired caps over anything suggested downstream, this ensure
    * that we preserves the bit depth, as we don't have any fancy fixation
    * process */
+  if (acquired_drm_caps) {
+    if (gst_caps_is_subset (acquired_drm_caps, caps)) {
+      gst_caps_replace (&acquired_caps, acquired_drm_caps);
+      acquired_drm_caps = NULL;
+      goto use_acquired_caps;
+    }
+
+    gst_clear_caps (&acquired_drm_caps);
+  }
+
   if (gst_caps_is_subset (acquired_caps, caps))
     goto use_acquired_caps;
 
@@ -475,12 +501,11 @@ gst_v4l2_video_dec_negotiate (GstVideoDecoder * decoder)
 
   /* Try to set negotiated format, on success replace acquired format */
   if (gst_v4l2_object_set_format (self->v4l2capture, caps, &error))
-    gst_video_info_from_caps (&info, caps);
+    info = self->v4l2capture->info;
   else
     gst_v4l2_clear_error (&error);
 
 use_acquired_caps:
-  gst_caps_unref (acquired_caps);
   gst_caps_unref (caps);
 
   /* catch possible bogus driver that don't enumerate the format it actually
@@ -488,12 +513,13 @@ use_acquired_caps:
   if (!self->v4l2capture->fmtdesc)
     goto not_negotiated;
 
-  output_state = gst_video_decoder_set_output_state (decoder,
-      info.finfo->format, info.width, info.height, self->input_state);
+  output_state = gst_video_decoder_set_interlaced_output_state (decoder,
+      info.vinfo.finfo->format, info.vinfo.interlace_mode, info.vinfo.width,
+      info.vinfo.height, self->input_state);
 
   /* Copy the rest of the information, there might be more in the future */
-  output_state->info.interlace_mode = info.interlace_mode;
-  output_state->info.colorimetry = info.colorimetry;
+  output_state->info.colorimetry = info.vinfo.colorimetry;
+  output_state->caps = acquired_caps;
   gst_video_codec_state_unref (output_state);
 
   ret = GST_VIDEO_DECODER_CLASS (parent_class)->negotiate (decoder);
@@ -945,14 +971,15 @@ gst_v4l2_video_dec_handle_frame (GstVideoDecoder * decoder,
     /* Ensure input internal pool is active */
 
     gst_buffer_pool_config_set_params (config, self->input_state->caps,
-        self->v4l2output->info.size, min, max);
+        self->v4l2output->info.vinfo.size, min, max);
 
     /* There is no reason to refuse this config */
     if (!gst_buffer_pool_set_config (pool, config)) {
       config = gst_buffer_pool_get_config (pool);
 
       if (!gst_buffer_pool_config_validate_params (config,
-              self->input_state->caps, self->v4l2output->info.size, min, max)) {
+              self->input_state->caps,
+              self->v4l2output->info.vinfo.size, min, max)) {
         gst_structure_free (config);
         goto activate_failed;
       }
index ac382fbc941ca416934e5e457c1bf57ce54ac436..e1f98a0515167b17986e29666f63375c602d0998 100644 (file)
@@ -779,14 +779,14 @@ gst_v4l2_video_enc_handle_frame (GstVideoEncoder * encoder,
           GST_V4L2_MIN_BUFFERS (self->v4l2output));
 
       gst_buffer_pool_config_set_params (config, self->input_state->caps,
-          self->v4l2output->info.size, min, min);
+          self->v4l2output->info.vinfo.size, min, min);
 
       /* There is no reason to refuse this config */
       if (!gst_buffer_pool_set_config (opool, config)) {
         config = gst_buffer_pool_get_config (opool);
 
         if (gst_buffer_pool_config_validate_params (config,
-                self->input_state->caps, self->v4l2output->info.size, min,
+                self->input_state->caps, self->v4l2output->info.vinfo.size, min,
                 min)) {
           gst_structure_free (config);
           if (opool)