v4l2src: add support for mpeg formats

This commit is contained in:
Wim Taymans 2009-09-07 18:28:51 +02:00
parent c6b2dff77e
commit 796dec5920
3 changed files with 84 additions and 51 deletions

View File

@ -615,63 +615,67 @@ gst_v4l2_object_stop (GstV4l2Object * v4l2object)
/* /*
* common format / caps utilities: * common format / caps utilities:
*/ */
typedef struct
{
guint32 format;
gboolean dimensions;
} GstV4L2FormatDesc;
static const GstV4L2FormatDesc gst_v4l2_formats[] = {
static const guint32 gst_v4l2_formats[] = {
/* from Linux 2.6.15 videodev2.h */ /* from Linux 2.6.15 videodev2.h */
V4L2_PIX_FMT_RGB332, {V4L2_PIX_FMT_RGB332, TRUE},
V4L2_PIX_FMT_RGB555, {V4L2_PIX_FMT_RGB555, TRUE},
V4L2_PIX_FMT_RGB565, {V4L2_PIX_FMT_RGB565, TRUE},
V4L2_PIX_FMT_RGB555X, {V4L2_PIX_FMT_RGB555X, TRUE},
V4L2_PIX_FMT_RGB565X, {V4L2_PIX_FMT_RGB565X, TRUE},
V4L2_PIX_FMT_BGR24, {V4L2_PIX_FMT_BGR24, TRUE},
V4L2_PIX_FMT_RGB24, {V4L2_PIX_FMT_RGB24, TRUE},
V4L2_PIX_FMT_BGR32, {V4L2_PIX_FMT_BGR32, TRUE},
V4L2_PIX_FMT_RGB32, {V4L2_PIX_FMT_RGB32, TRUE},
V4L2_PIX_FMT_GREY, {V4L2_PIX_FMT_GREY, TRUE},
V4L2_PIX_FMT_YVU410, {V4L2_PIX_FMT_YVU410, TRUE},
V4L2_PIX_FMT_YVU420, {V4L2_PIX_FMT_YVU420, TRUE},
V4L2_PIX_FMT_YUYV, {V4L2_PIX_FMT_YUYV, TRUE},
V4L2_PIX_FMT_UYVY, {V4L2_PIX_FMT_UYVY, TRUE},
V4L2_PIX_FMT_YUV422P, {V4L2_PIX_FMT_YUV422P, TRUE},
V4L2_PIX_FMT_YUV411P, {V4L2_PIX_FMT_YUV411P, TRUE},
V4L2_PIX_FMT_Y41P, {V4L2_PIX_FMT_Y41P, TRUE},
/* two planes -- one Y, one Cr + Cb interleaved */ /* two planes -- one Y, one Cr + Cb interleaved */
V4L2_PIX_FMT_NV12, {V4L2_PIX_FMT_NV12, TRUE},
V4L2_PIX_FMT_NV21, {V4L2_PIX_FMT_NV21, TRUE},
/* The following formats are not defined in the V4L2 specification */ /* The following formats are not defined in the V4L2 specification */
V4L2_PIX_FMT_YUV410, {V4L2_PIX_FMT_YUV410, TRUE},
V4L2_PIX_FMT_YUV420, {V4L2_PIX_FMT_YUV420, TRUE},
V4L2_PIX_FMT_YYUV, {V4L2_PIX_FMT_YYUV, TRUE},
V4L2_PIX_FMT_HI240, {V4L2_PIX_FMT_HI240, TRUE},
/* see http://www.siliconimaging.com/RGB%20Bayer.htm */ /* see http://www.siliconimaging.com/RGB%20Bayer.htm */
#ifdef V4L2_PIX_FMT_SBGGR8 #ifdef V4L2_PIX_FMT_SBGGR8
V4L2_PIX_FMT_SBGGR8, {V4L2_PIX_FMT_SBGGR8, TRUE},
#endif #endif
/* compressed formats */ /* compressed formats */
V4L2_PIX_FMT_MJPEG, {V4L2_PIX_FMT_MJPEG, TRUE},
V4L2_PIX_FMT_JPEG, {V4L2_PIX_FMT_JPEG, TRUE},
V4L2_PIX_FMT_DV, {V4L2_PIX_FMT_DV, TRUE},
V4L2_PIX_FMT_MPEG, {V4L2_PIX_FMT_MPEG, FALSE},
/* Vendor-specific formats */ /* Vendor-specific formats */
V4L2_PIX_FMT_WNVA, {V4L2_PIX_FMT_WNVA, TRUE},
#ifdef V4L2_PIX_FMT_SN9C10X #ifdef V4L2_PIX_FMT_SN9C10X
V4L2_PIX_FMT_SN9C10X, {V4L2_PIX_FMT_SN9C10X, TRUE},
#endif #endif
#ifdef V4L2_PIX_FMT_PWC1 #ifdef V4L2_PIX_FMT_PWC1
V4L2_PIX_FMT_PWC1, {V4L2_PIX_FMT_PWC1, TRUE},
#endif #endif
#ifdef V4L2_PIX_FMT_PWC2 #ifdef V4L2_PIX_FMT_PWC2
V4L2_PIX_FMT_PWC2, {V4L2_PIX_FMT_PWC2, TRUE},
#endif #endif
#ifdef V4L2_PIX_FMT_YVYU #ifdef V4L2_PIX_FMT_YVYU
V4L2_PIX_FMT_YVYU, {V4L2_PIX_FMT_YVYU, TRUE},
#endif #endif
}; };
@ -740,6 +744,9 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
case V4L2_PIX_FMT_JPEG: case V4L2_PIX_FMT_JPEG:
rank = JPEG_BASE_RANK + 1; rank = JPEG_BASE_RANK + 1;
break; break;
case V4L2_PIX_FMT_MPEG: /* MPEG */
rank = JPEG_BASE_RANK + 2;
break;
case V4L2_PIX_FMT_RGB332: case V4L2_PIX_FMT_RGB332:
case V4L2_PIX_FMT_RGB555: case V4L2_PIX_FMT_RGB555:
@ -802,7 +809,6 @@ gst_v4l2_object_format_get_rank (const struct v4l2_fmtdesc *fmt)
rank = DV_BASE_RANK; rank = DV_BASE_RANK;
break; break;
case V4L2_PIX_FMT_MPEG: /* MPEG */
case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */ case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
rank = 0; rank = 0;
break; break;
@ -1101,7 +1107,7 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
NULL); NULL);
break; break;
case V4L2_PIX_FMT_MPEG: /* MPEG */ case V4L2_PIX_FMT_MPEG: /* MPEG */
/* someone figure out the MPEG format used... */ structure = gst_structure_new ("video/mpegts", NULL);
break; break;
case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */ case V4L2_PIX_FMT_WNVA: /* Winnov hw compres */
break; break;
@ -1148,12 +1154,15 @@ gst_v4l2_object_get_all_caps (void)
caps = gst_caps_new_empty (); caps = gst_caps_new_empty ();
for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) { for (i = 0; i < GST_V4L2_FORMAT_COUNT; i++) {
structure = gst_v4l2_object_v4l2fourcc_to_structure (gst_v4l2_formats[i]); structure =
gst_v4l2_object_v4l2fourcc_to_structure (gst_v4l2_formats[i].format);
if (structure) { if (structure) {
gst_structure_set (structure, if (gst_v4l2_formats[i].dimensions) {
"width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE, gst_structure_set (structure,
"height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE, "width", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL); "height", GST_TYPE_INT_RANGE, 1, GST_V4L2_MAX_SIZE,
"framerate", GST_TYPE_FRACTION_RANGE, 0, 1, 100, 1, NULL);
}
gst_caps_append_structure (caps, structure); gst_caps_append_structure (caps, structure);
} }
} }
@ -1187,6 +1196,16 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
structure = gst_caps_get_structure (caps, 0); structure = gst_caps_get_structure (caps, 0);
mimetype = gst_structure_get_name (structure);
if (strcmp (mimetype, "video/mpegts") == 0) {
fourcc = V4L2_PIX_FMT_MPEG;
outsize = 8192;
*fps_n = 0;
*fps_d = 1;
goto done;
}
if (!gst_structure_get_int (structure, "width", w)) if (!gst_structure_get_int (structure, "width", w))
return FALSE; return FALSE;
@ -1200,8 +1219,6 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
*fps_n = gst_value_get_fraction_numerator (framerate); *fps_n = gst_value_get_fraction_numerator (framerate);
*fps_d = gst_value_get_fraction_denominator (framerate); *fps_d = gst_value_get_fraction_denominator (framerate);
mimetype = gst_structure_get_name (structure);
if (!strcmp (mimetype, "video/x-raw-yuv")) { if (!strcmp (mimetype, "video/x-raw-yuv")) {
gst_structure_get_fourcc (structure, "format", &fourcc); gst_structure_get_fourcc (structure, "format", &fourcc);
@ -1309,6 +1326,7 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
if (fourcc == 0) if (fourcc == 0)
return FALSE; return FALSE;
done:
*format = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc); *format = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc);
*size = outsize; *size = outsize;
@ -1551,6 +1569,9 @@ gst_v4l2_object_probe_caps_for_format (GstV4l2Object * v4l2object,
GList *results = NULL; GList *results = NULL;
guint32 w, h; guint32 w, h;
if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
return gst_caps_new_simple ("video/mpegts", NULL);
memset (&size, 0, sizeof (struct v4l2_frmsizeenum)); memset (&size, 0, sizeof (struct v4l2_frmsizeenum));
size.index = 0; size.index = 0;
size.pixel_format = pixelformat; size.pixel_format = pixelformat;
@ -1842,6 +1863,9 @@ gst_v4l2_object_set_format (GstV4l2Object * v4l2object, guint32 pixelformat,
memset (&format, 0x00, sizeof (struct v4l2_format)); memset (&format, 0x00, sizeof (struct v4l2_format));
format.type = v4l2object->type; format.type = v4l2object->type;
if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
return TRUE;
if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0) if (v4l2_ioctl (fd, VIDIOC_G_FMT, &format) < 0)
goto get_fmt_failed; goto get_fmt_failed;

View File

@ -231,30 +231,31 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
v4l2object->norms = g_list_reverse (v4l2object->norms); v4l2object->norms = g_list_reverse (v4l2object->norms);
GST_DEBUG_OBJECT (e, " controls+menus"); GST_DEBUG_OBJECT (e, " controls+menus");
/* and lastly, controls+menus (if appropriate) */ /* and lastly, controls+menus (if appropriate) */
for (n = V4L2_CID_BASE;; n++) { for (n = V4L2_CID_BASE;; n++) {
struct v4l2_queryctrl control = { 0, }; struct v4l2_queryctrl control = { 0, };
GstV4l2ColorBalanceChannel *v4l2channel; GstV4l2ColorBalanceChannel *v4l2channel;
GstColorBalanceChannel *channel; GstColorBalanceChannel *channel;
/* when we reached the last official CID, continue with private CIDs */ /* when we reached the last official CID, continue with private CIDs */
if (n == V4L2_CID_LASTP1) { if (n == V4L2_CID_LASTP1) {
GST_DEBUG_OBJECT (e, "checking private CIDs"); GST_DEBUG_OBJECT (e, "checking private CIDs");
n = V4L2_CID_PRIVATE_BASE; n = V4L2_CID_PRIVATE_BASE;
/* FIXME: We are still not handling private controls. We need a new GstInterface
to export those controls */
break;
} }
GST_DEBUG_OBJECT (e, "checking control %08x", n);
control.id = n; control.id = n;
if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, &control) < 0) { if (v4l2_ioctl (v4l2object->video_fd, VIDIOC_QUERYCTRL, &control) < 0) {
if (errno == EINVAL) { if (errno == EINVAL) {
if (n < V4L2_CID_PRIVATE_BASE) if (n < V4L2_CID_PRIVATE_BASE) {
GST_DEBUG_OBJECT (e, "skipping control %08x", n);
/* continue so that we also check private controls */ /* continue so that we also check private controls */
continue; continue;
else } else {
GST_DEBUG_OBJECT (e, "controls finished");
break; break;
}
} else { } else {
GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS, GST_ELEMENT_ERROR (e, RESOURCE, SETTINGS,
(_("Failed getting controls attributes on device '%s'."), (_("Failed getting controls attributes on device '%s'."),
@ -264,8 +265,10 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
return FALSE; return FALSE;
} }
} }
if (control.flags & V4L2_CTRL_FLAG_DISABLED) if (control.flags & V4L2_CTRL_FLAG_DISABLED) {
GST_DEBUG_OBJECT (e, "skipping disabled control");
continue; continue;
}
switch (n) { switch (n) {
case V4L2_CID_BRIGHTNESS: case V4L2_CID_BRIGHTNESS:
@ -281,6 +284,9 @@ gst_v4l2_fill_lists (GstV4l2Object * v4l2object)
case V4L2_CID_EXPOSURE: case V4L2_CID_EXPOSURE:
case V4L2_CID_AUTOGAIN: case V4L2_CID_AUTOGAIN:
case V4L2_CID_GAIN: case V4L2_CID_GAIN:
#ifdef V4L2_CID_SHARPNESS
case V4L2_CID_SHARPNESS:
#endif
/* we only handle these for now (why?) */ /* we only handle these for now (why?) */
break; break;
case V4L2_CID_HFLIP: case V4L2_CID_HFLIP:

View File

@ -208,6 +208,9 @@ gst_v4l2src_set_capture (GstV4l2Src * v4l2src, guint32 pixelformat,
gint fd = v4l2src->v4l2object->video_fd; gint fd = v4l2src->v4l2object->video_fd;
struct v4l2_streamparm stream; struct v4l2_streamparm stream;
if (pixelformat == GST_MAKE_FOURCC ('M', 'P', 'E', 'G'))
return TRUE;
if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width, if (!gst_v4l2_object_set_format (v4l2src->v4l2object, pixelformat, width,
height)) { height)) {
/* error already reported */ /* error already reported */