v4l2src: port to new video formats

This commit is contained in:
Wim Taymans 2011-07-08 14:34:40 +02:00
parent 734ec56617
commit b8640c8cd9
2 changed files with 133 additions and 143 deletions

View file

@ -41,6 +41,8 @@
#include "gst/gst-i18n-plugin.h"
#include <gst/video/video.h>
/* videodev2.h is not versioned and we can't easily check for the presence
* of enum values at compile time, but the V4L2_CAP_VIDEO_OUTPUT_OVERLAY define
* was added in the same commit as V4L2_FIELD_INTERLACED_{TB,BT} (b2787845) */
@ -1147,89 +1149,6 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
case V4L2_PIX_FMT_JPEG: /* JFIF JPEG */
structure = gst_structure_new ("image/jpeg", NULL);
break;
case V4L2_PIX_FMT_RGB332:
case V4L2_PIX_FMT_RGB555:
case V4L2_PIX_FMT_RGB555X:
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_RGB565X:
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
case V4L2_PIX_FMT_RGB32:
case V4L2_PIX_FMT_BGR32:{
guint depth = 0, bpp = 0;
gint endianness = 0;
guint32 r_mask = 0, b_mask = 0, g_mask = 0;
switch (fourcc) {
case V4L2_PIX_FMT_RGB332:
bpp = depth = 8;
endianness = G_BYTE_ORDER; /* 'like, whatever' */
r_mask = 0xe0;
g_mask = 0x1c;
b_mask = 0x03;
break;
case V4L2_PIX_FMT_RGB555:
case V4L2_PIX_FMT_RGB555X:
bpp = 16;
depth = 15;
endianness =
fourcc == V4L2_PIX_FMT_RGB555X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
r_mask = 0x7c00;
g_mask = 0x03e0;
b_mask = 0x001f;
break;
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_RGB565X:
bpp = depth = 16;
endianness =
fourcc == V4L2_PIX_FMT_RGB565X ? G_BIG_ENDIAN : G_LITTLE_ENDIAN;
r_mask = 0xf800;
g_mask = 0x07e0;
b_mask = 0x001f;
break;
case V4L2_PIX_FMT_RGB24:
bpp = depth = 24;
endianness = G_BIG_ENDIAN;
r_mask = 0xff0000;
g_mask = 0x00ff00;
b_mask = 0x0000ff;
break;
case V4L2_PIX_FMT_BGR24:
bpp = depth = 24;
endianness = G_BIG_ENDIAN;
r_mask = 0x0000ff;
g_mask = 0x00ff00;
b_mask = 0xff0000;
break;
case V4L2_PIX_FMT_RGB32:
bpp = depth = 32;
endianness = G_BIG_ENDIAN;
r_mask = 0xff000000;
g_mask = 0x00ff0000;
b_mask = 0x0000ff00;
break;
case V4L2_PIX_FMT_BGR32:
bpp = depth = 32;
endianness = G_BIG_ENDIAN;
r_mask = 0x000000ff;
g_mask = 0x0000ff00;
b_mask = 0x00ff0000;
break;
default:
g_assert_not_reached ();
break;
}
structure = gst_structure_new ("video/x-raw-rgb",
"bpp", G_TYPE_INT, bpp,
"depth", G_TYPE_INT, depth,
"red_mask", G_TYPE_INT, r_mask,
"green_mask", G_TYPE_INT, g_mask,
"blue_mask", G_TYPE_INT, b_mask,
"endianness", G_TYPE_INT, endianness, NULL);
break;
}
case V4L2_PIX_FMT_GREY: /* 8 Greyscale */
structure = gst_structure_new ("video/x-raw-gray",
"bpp", G_TYPE_INT, 8, NULL);
@ -1238,6 +1157,17 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
case V4L2_PIX_FMT_HI240: /* 8 8-bit color */
/* FIXME: get correct fourccs here */
break;
case V4L2_PIX_FMT_RGB332:
case V4L2_PIX_FMT_RGB555X:
case V4L2_PIX_FMT_RGB565X:
/* FIXME: get correct fourccs here */
break;
case V4L2_PIX_FMT_RGB555:
case V4L2_PIX_FMT_RGB565:
case V4L2_PIX_FMT_RGB24:
case V4L2_PIX_FMT_BGR24:
case V4L2_PIX_FMT_RGB32:
case V4L2_PIX_FMT_BGR32:
case V4L2_PIX_FMT_NV12: /* 12 Y/CbCr 4:2:0 */
case V4L2_PIX_FMT_NV21: /* 12 Y/CrCb 4:2:0 */
case V4L2_PIX_FMT_YVU410:
@ -1246,59 +1176,81 @@ gst_v4l2_object_v4l2fourcc_to_structure (guint32 fourcc)
case V4L2_PIX_FMT_YUYV:
case V4L2_PIX_FMT_YVU420:
case V4L2_PIX_FMT_UYVY:
#if 0
case V4L2_PIX_FMT_Y41P:
#endif
case V4L2_PIX_FMT_YUV422P:
#ifdef V4L2_PIX_FMT_YVYU
case V4L2_PIX_FMT_YVYU:
#endif
case V4L2_PIX_FMT_YUV411P:{
guint32 fcc = 0;
GstVideoFormat format;
switch (fourcc) {
case V4L2_PIX_FMT_RGB555:
format = GST_VIDEO_FORMAT_RGB15;
break;
case V4L2_PIX_FMT_RGB565:
format = GST_VIDEO_FORMAT_RGB16;
break;
case V4L2_PIX_FMT_RGB24:
format = GST_VIDEO_FORMAT_RGB;
break;
case V4L2_PIX_FMT_BGR24:
format = GST_VIDEO_FORMAT_BGR;
break;
case V4L2_PIX_FMT_RGB32:
format = GST_VIDEO_FORMAT_RGBx;
break;
case V4L2_PIX_FMT_BGR32:
format = GST_VIDEO_FORMAT_BGRx;
break;
case V4L2_PIX_FMT_NV12:
fcc = GST_MAKE_FOURCC ('N', 'V', '1', '2');
format = GST_VIDEO_FORMAT_NV12;
break;
case V4L2_PIX_FMT_NV21:
fcc = GST_MAKE_FOURCC ('N', 'V', '2', '1');
format = GST_VIDEO_FORMAT_NV21;
break;
case V4L2_PIX_FMT_YVU410:
fcc = GST_MAKE_FOURCC ('Y', 'V', 'U', '9');
format = GST_VIDEO_FORMAT_YVU9;
break;
case V4L2_PIX_FMT_YUV410:
fcc = GST_MAKE_FOURCC ('Y', 'U', 'V', '9');
format = GST_VIDEO_FORMAT_YUV9;
break;
case V4L2_PIX_FMT_YUV420:
fcc = GST_MAKE_FOURCC ('I', '4', '2', '0');
format = GST_VIDEO_FORMAT_I420;
break;
case V4L2_PIX_FMT_YUYV:
fcc = GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
format = GST_VIDEO_FORMAT_YUY2;
break;
case V4L2_PIX_FMT_YVU420:
fcc = GST_MAKE_FOURCC ('Y', 'V', '1', '2');
format = GST_VIDEO_FORMAT_YV12;
break;
case V4L2_PIX_FMT_UYVY:
fcc = GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
format = GST_VIDEO_FORMAT_UYVY;
break;
#if 0
case V4L2_PIX_FMT_Y41P:
fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'P');
format = GST_VIDEO_FORMAT_Y41P;
break;
#endif
case V4L2_PIX_FMT_YUV411P:
fcc = GST_MAKE_FOURCC ('Y', '4', '1', 'B');
format = GST_VIDEO_FORMAT_Y41B;
break;
case V4L2_PIX_FMT_YUV422P:
fcc = GST_MAKE_FOURCC ('Y', '4', '2', 'B');
format = GST_VIDEO_FORMAT_Y42B;
break;
#ifdef V4L2_PIX_FMT_YVYU
case V4L2_PIX_FMT_YVYU:
fcc = GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U');
format = GST_VIDEO_FORMAT_YVYU;
break;
#endif
default:
g_assert_not_reached ();
break;
}
structure = gst_structure_new ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, fcc, NULL);
structure = gst_structure_new ("video/x-raw",
"format", G_TYPE_STRING, gst_video_format_to_string (format), NULL);
break;
}
case V4L2_PIX_FMT_DV:
@ -1406,99 +1358,99 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
}
if (!gst_structure_get_int (structure, "width", w))
return FALSE;
goto no_width;
if (!gst_structure_get_int (structure, "height", h))
return FALSE;
goto no_height;
if (!gst_structure_get_boolean (structure, "interlaced", interlaced))
*interlaced = FALSE;
framerate = gst_structure_get_value (structure, "framerate");
if (!framerate)
return FALSE;
goto no_framerate;
*fps_n = gst_value_get_fraction_numerator (framerate);
*fps_d = gst_value_get_fraction_denominator (framerate);
if (!strcmp (mimetype, "video/x-raw-yuv")) {
gst_structure_get_fourcc (structure, "format", &fourcc);
if (!strcmp (mimetype, "video/x-raw")) {
GstVideoInfo info;
switch (fourcc) {
case GST_MAKE_FOURCC ('I', '4', '2', '0'):
case GST_MAKE_FOURCC ('I', 'Y', 'U', 'V'):
if (!gst_video_info_from_caps (&info, caps))
goto invalid_format;
switch (GST_VIDEO_INFO_FORMAT (&info)) {
case GST_VIDEO_FORMAT_I420:
fourcc = V4L2_PIX_FMT_YUV420;
outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
break;
case GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'):
case GST_VIDEO_FORMAT_YUY2:
fourcc = V4L2_PIX_FMT_YUYV;
outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
break;
case GST_MAKE_FOURCC ('Y', '4', '1', 'P'):
#if 0
case GST_VIDEO_FORMAT_Y41P:
fourcc = V4L2_PIX_FMT_Y41P;
outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
break;
case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
#endif
case GST_VIDEO_FORMAT_UYVY:
fourcc = V4L2_PIX_FMT_UYVY;
outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
break;
case GST_MAKE_FOURCC ('Y', 'V', '1', '2'):
case GST_VIDEO_FORMAT_YV12:
fourcc = V4L2_PIX_FMT_YVU420;
outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * (GST_ROUND_UP_2 (*h) / 2));
break;
case GST_MAKE_FOURCC ('Y', '4', '1', 'B'):
case GST_VIDEO_FORMAT_Y41B:
fourcc = V4L2_PIX_FMT_YUV411P;
outsize = GST_ROUND_UP_4 (*w) * *h;
outsize += 2 * ((GST_ROUND_UP_8 (*w) / 4) * *h);
break;
case GST_MAKE_FOURCC ('Y', '4', '2', 'B'):
case GST_VIDEO_FORMAT_Y42B:
fourcc = V4L2_PIX_FMT_YUV422P;
outsize = GST_ROUND_UP_4 (*w) * *h;
outsize += 2 * ((GST_ROUND_UP_8 (*w) / 2) * *h);
break;
case GST_MAKE_FOURCC ('N', 'V', '1', '2'):
case GST_VIDEO_FORMAT_NV12:
fourcc = V4L2_PIX_FMT_NV12;
outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
break;
case GST_MAKE_FOURCC ('N', 'V', '2', '1'):
case GST_VIDEO_FORMAT_NV21:
fourcc = V4L2_PIX_FMT_NV21;
outsize = GST_ROUND_UP_4 (*w) * GST_ROUND_UP_2 (*h);
outsize += (GST_ROUND_UP_4 (*w) * *h) / 2;
break;
#ifdef V4L2_PIX_FMT_YVYU
case GST_MAKE_FOURCC ('Y', 'V', 'Y', 'U'):
case GST_VIDEO_FORMAT_YVYU:
fourcc = V4L2_PIX_FMT_YVYU;
outsize = (GST_ROUND_UP_2 (*w) * 2) * *h;
break;
#endif
}
} else if (!strcmp (mimetype, "video/x-raw-rgb")) {
gint depth, endianness, r_mask;
gst_structure_get_int (structure, "depth", &depth);
gst_structure_get_int (structure, "endianness", &endianness);
gst_structure_get_int (structure, "red_mask", &r_mask);
switch (depth) {
case 8:
fourcc = V4L2_PIX_FMT_RGB332;
case GST_VIDEO_FORMAT_RGB15:
fourcc = V4L2_PIX_FMT_RGB555;
break;
case 15:
fourcc = (endianness == G_LITTLE_ENDIAN) ?
V4L2_PIX_FMT_RGB555 : V4L2_PIX_FMT_RGB555X;
case GST_VIDEO_FORMAT_RGB16:
fourcc = V4L2_PIX_FMT_RGB565;
break;
case 16:
fourcc = (endianness == G_LITTLE_ENDIAN) ?
V4L2_PIX_FMT_RGB565 : V4L2_PIX_FMT_RGB565X;
case GST_VIDEO_FORMAT_RGB:
fourcc = V4L2_PIX_FMT_RGB24;
break;
case 24:
fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR24 : V4L2_PIX_FMT_RGB24;
case GST_VIDEO_FORMAT_BGR:
fourcc = V4L2_PIX_FMT_BGR24;
break;
case 32:
fourcc = (r_mask == 0xFF) ? V4L2_PIX_FMT_BGR32 : V4L2_PIX_FMT_RGB32;
case GST_VIDEO_FORMAT_RGBx:
case GST_VIDEO_FORMAT_RGBA:
fourcc = V4L2_PIX_FMT_RGB32;
break;
case GST_VIDEO_FORMAT_BGRx:
case GST_VIDEO_FORMAT_BGRA:
fourcc = V4L2_PIX_FMT_BGR32;
break;
default:
break;
}
} else if (strcmp (mimetype, "video/x-dv") == 0) {
@ -1526,13 +1478,40 @@ gst_v4l2_object_get_caps_info (GstV4l2Object * v4l2object, GstCaps * caps,
}
if (fourcc == 0)
return FALSE;
goto unhandled_format;
done:
*format = gst_v4l2_object_get_format_from_fourcc (v4l2object, fourcc);
*size = outsize;
return TRUE;
/* ERRORS */
no_width:
{
GST_DEBUG_OBJECT (v4l2object, "no width");
return FALSE;
}
no_height:
{
GST_DEBUG_OBJECT (v4l2object, "no height");
return FALSE;
}
no_framerate:
{
GST_DEBUG_OBJECT (v4l2object, "no framerate");
return FALSE;
}
invalid_format:
{
GST_DEBUG_OBJECT (v4l2object, "invalid format");
return FALSE;
}
unhandled_format:
{
GST_DEBUG_OBJECT (v4l2object, "unhandled format");
return FALSE;
}
}

View file

@ -330,13 +330,13 @@ gst_v4l2src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
G_MAXINT, 1);
v = gst_structure_get_value (structure, "format");
if (v && G_VALUE_TYPE (v) != GST_TYPE_FOURCC) {
guint32 fourcc;
if (v && G_VALUE_TYPE (v) != G_TYPE_STRING) {
const gchar *format;
g_return_if_fail (G_VALUE_TYPE (v) == GST_TYPE_LIST);
fourcc = gst_value_get_fourcc (gst_value_list_get_value (v, 0));
gst_structure_set (structure, "format", GST_TYPE_FOURCC, fourcc, NULL);
format = g_value_get_string (gst_value_list_get_value (v, 0));
gst_structure_set (structure, "format", G_TYPE_STRING, format, NULL);
}
}
@ -451,8 +451,9 @@ gst_v4l2src_negotiate (GstBaseSrc * basesrc)
result = TRUE;
} else if (gst_caps_is_fixed (caps)) {
/* yay, fixed caps, use those then */
if (gst_pad_set_caps (GST_BASE_SRC_PAD (basesrc), caps))
result = TRUE;
gst_pad_push_event (GST_BASE_SRC_PAD (basesrc),
gst_event_new_caps (caps));
result = gst_v4l2src_set_caps (basesrc, caps);
}
}
gst_caps_unref (caps);
@ -864,6 +865,9 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
int i;
GstFlowReturn ret;
if (v4l2src->get_frame == NULL)
goto not_negotiated;
for (i = 0; i < v4l2src->decimate - 1; i++) {
ret = v4l2src->get_frame (v4l2src, buf);
if (ret != GST_FLOW_OK) {
@ -927,6 +931,13 @@ gst_v4l2src_create (GstPushSrc * src, GstBuffer ** buf)
GST_BUFFER_DURATION (*buf) = v4l2src->duration;
}
return ret;
/* ERRORS */
not_negotiated:
{
GST_DEBUG_OBJECT (src, "we are not negotiated");
return GST_FLOW_NOT_NEGOTIATED;
}
}