niimaqdx: don't rely on GstVideoFormat, and handle stride alignment
This commit is contained in:
parent
dd3fe6f617
commit
757e7591d4
@ -98,6 +98,7 @@ static GstFlowReturn gst_niimaqdxsrc_create (GstPushSrc * psrc,
|
|||||||
/* GstNiImaqDx methods */
|
/* GstNiImaqDx methods */
|
||||||
static GstCaps *gst_niimaqdxsrc_get_cam_caps (GstNiImaqDxSrc * src);
|
static GstCaps *gst_niimaqdxsrc_get_cam_caps (GstNiImaqDxSrc * src);
|
||||||
static gboolean gst_niimaqdxsrc_close_interface (GstNiImaqDxSrc * niimaqdxsrc);
|
static gboolean gst_niimaqdxsrc_close_interface (GstNiImaqDxSrc * niimaqdxsrc);
|
||||||
|
static void gst_niimaqdxsrc_reset (GstNiImaqDxSrc * niimaqdxsrc);
|
||||||
|
|
||||||
IMAQdxError
|
IMAQdxError
|
||||||
gst_niimaqdxsrc_report_imaq_error (IMAQdxError code)
|
gst_niimaqdxsrc_report_imaq_error (IMAQdxError code)
|
||||||
@ -150,6 +151,103 @@ gst_niimaqdxsrc_frame_done_callback (IMAQdxSession session, uInt32 bufferNumber,
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
const char *pixel_format;
|
||||||
|
const char *gst_caps_string;
|
||||||
|
int bpp;
|
||||||
|
int depth;
|
||||||
|
} ImaqDxCapsInfo;
|
||||||
|
|
||||||
|
ImaqDxCapsInfo imaq_dx_caps_infos[] = {
|
||||||
|
{
|
||||||
|
"Mono 8",
|
||||||
|
GST_VIDEO_CAPS_GRAY8, 8, 8},
|
||||||
|
{
|
||||||
|
"Mono 16",
|
||||||
|
GST_VIDEO_CAPS_GRAY16 ("BIG_ENDIAN"), 16, 16}
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
gst_niimaqdxsrc_pixel_format_to_caps_string (const char *pixel_format)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (imaq_dx_caps_infos); i++) {
|
||||||
|
if (g_strcmp0 (pixel_format, imaq_dx_caps_infos[i].pixel_format) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (i == G_N_ELEMENTS (imaq_dx_caps_infos)) {
|
||||||
|
GST_WARNING ("PixelFormat '%s' is not supported",
|
||||||
|
imaq_dx_caps_infos[i].pixel_format);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return imaq_dx_caps_infos[i].gst_caps_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *
|
||||||
|
gst_niimaqdxsrc_pixel_format_from_caps (const GstCaps * caps)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (imaq_dx_caps_infos); i++) {
|
||||||
|
GstCaps *super_caps;
|
||||||
|
super_caps = gst_caps_from_string (imaq_dx_caps_infos[i].gst_caps_string);
|
||||||
|
if (gst_caps_is_subset (caps, super_caps))
|
||||||
|
return imaq_dx_caps_infos[i].pixel_format;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gst_niimaqdxsrc_pixel_format_get_bpp (const char *pixel_format)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
for (i = 0; i < G_N_ELEMENTS (imaq_dx_caps_infos); i++) {
|
||||||
|
if (g_strcmp0 (pixel_format, imaq_dx_caps_infos[i].pixel_format) == 0) {
|
||||||
|
return imaq_dx_caps_infos[i].bpp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
gst_niimaqdxsrc_pixel_format_get_stride (const char *pixel_format, int width)
|
||||||
|
{
|
||||||
|
return width * gst_niimaqdxsrc_pixel_format_get_bpp (pixel_format) / 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GstCaps *
|
||||||
|
gst_niimaqdxsrc_new_caps_from_pixel_format (const char *pixel_format,
|
||||||
|
int width, int height,
|
||||||
|
int framerate_n, int framerate_d, int par_n, int par_d)
|
||||||
|
{
|
||||||
|
const char *caps_string;
|
||||||
|
GstCaps *caps;
|
||||||
|
GstStructure *structure;
|
||||||
|
|
||||||
|
caps_string = gst_niimaqdxsrc_pixel_format_to_caps_string (pixel_format);
|
||||||
|
if (caps_string == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
structure = gst_structure_from_string (caps_string, NULL);
|
||||||
|
gst_structure_set (structure,
|
||||||
|
"width", G_TYPE_INT, width,
|
||||||
|
"height", G_TYPE_INT, height,
|
||||||
|
"framerate", GST_TYPE_FRACTION, framerate_n, framerate_d,
|
||||||
|
"par", GST_TYPE_FRACTION, par_n, par_d, NULL);
|
||||||
|
|
||||||
|
caps = gst_caps_new_empty ();
|
||||||
|
gst_caps_append_structure (caps, structure);
|
||||||
|
|
||||||
|
return caps;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static void _____BEGIN_FUNCTIONS_____ ();
|
static void _____BEGIN_FUNCTIONS_____ ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -477,6 +575,11 @@ gst_niimaqdxsrc_init (GstNiImaqDxSrc * niimaqdxsrc,
|
|||||||
/* initialize properties */
|
/* initialize properties */
|
||||||
niimaqdxsrc->ringbuffer_count = DEFAULT_PROP_RING_BUFFER_COUNT;
|
niimaqdxsrc->ringbuffer_count = DEFAULT_PROP_RING_BUFFER_COUNT;
|
||||||
niimaqdxsrc->device_name = g_strdup (DEFAULT_PROP_DEVICE);
|
niimaqdxsrc->device_name = g_strdup (DEFAULT_PROP_DEVICE);
|
||||||
|
|
||||||
|
/* initialize pointers, then call reset to initialize the rest */
|
||||||
|
niimaqdxsrc->times = NULL;
|
||||||
|
niimaqdxsrc->temp_buffer = NULL;
|
||||||
|
gst_niimaqdxsrc_reset (niimaqdxsrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -558,7 +661,7 @@ gst_niimaqdxsrc_get_caps (GstBaseSrc * bsrc)
|
|||||||
gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
|
gst_caps_copy (gst_pad_get_pad_template_caps (GST_BASE_SRC_PAD
|
||||||
(niimaqdxsrc)));
|
(niimaqdxsrc)));
|
||||||
}
|
}
|
||||||
|
//TODO: should also call this when first opening the camera, in case format isn't supported
|
||||||
return gst_niimaqdxsrc_get_cam_caps (niimaqdxsrc);
|
return gst_niimaqdxsrc_get_cam_caps (niimaqdxsrc);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -568,14 +671,30 @@ gst_niimaqdxsrc_set_caps (GstBaseSrc * bsrc, GstCaps * caps)
|
|||||||
{
|
{
|
||||||
GstNiImaqDxSrc *niimaqdxsrc = GST_NIIMAQDXSRC (bsrc);
|
GstNiImaqDxSrc *niimaqdxsrc = GST_NIIMAQDXSRC (bsrc);
|
||||||
gboolean res = TRUE;
|
gboolean res = TRUE;
|
||||||
|
GstStructure *structure;
|
||||||
|
const char *pixel_format;
|
||||||
|
|
||||||
gst_video_format_parse_caps (caps, &niimaqdxsrc->format, &niimaqdxsrc->width,
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
&niimaqdxsrc->height);
|
|
||||||
|
gst_structure_get_int (structure, "width", &niimaqdxsrc->width);
|
||||||
|
gst_structure_get_int (structure, "height", &niimaqdxsrc->height);
|
||||||
|
|
||||||
|
pixel_format = gst_niimaqdxsrc_pixel_format_from_caps (caps);
|
||||||
|
g_assert (pixel_format);
|
||||||
|
|
||||||
|
niimaqdxsrc->dx_row_stride =
|
||||||
|
gst_niimaqdxsrc_pixel_format_get_stride (pixel_format,
|
||||||
|
niimaqdxsrc->width);
|
||||||
|
|
||||||
/* this will handle byte alignment (i.e. row multiple of 4 bytes) */
|
|
||||||
niimaqdxsrc->framesize =
|
niimaqdxsrc->framesize =
|
||||||
gst_video_format_get_size (niimaqdxsrc->format, niimaqdxsrc->width,
|
GST_ROUND_UP_4 (niimaqdxsrc->dx_row_stride) * niimaqdxsrc->height;
|
||||||
niimaqdxsrc->height);
|
|
||||||
|
if (niimaqdxsrc->temp_buffer)
|
||||||
|
g_free (niimaqdxsrc->temp_buffer);
|
||||||
|
|
||||||
|
niimaqdxsrc->temp_buffer = g_malloc (niimaqdxsrc->framesize);
|
||||||
|
|
||||||
|
GST_DEBUG ("Size %dx%d", niimaqdxsrc->width, niimaqdxsrc->height);
|
||||||
|
|
||||||
GST_LOG_OBJECT (niimaqdxsrc, "Caps set, framesize=%d",
|
GST_LOG_OBJECT (niimaqdxsrc, "Caps set, framesize=%d",
|
||||||
niimaqdxsrc->framesize);
|
niimaqdxsrc->framesize);
|
||||||
@ -594,13 +713,16 @@ gst_niimaqdxsrc_reset (GstNiImaqDxSrc * niimaqdxsrc)
|
|||||||
niimaqdxsrc->n_dropped_frames = 0;
|
niimaqdxsrc->n_dropped_frames = 0;
|
||||||
niimaqdxsrc->session = 0;
|
niimaqdxsrc->session = 0;
|
||||||
niimaqdxsrc->session_started = FALSE;
|
niimaqdxsrc->session_started = FALSE;
|
||||||
niimaqdxsrc->format = GST_VIDEO_FORMAT_UNKNOWN;
|
|
||||||
niimaqdxsrc->width = 0;
|
niimaqdxsrc->width = 0;
|
||||||
niimaqdxsrc->height = 0;
|
niimaqdxsrc->height = 0;
|
||||||
|
niimaqdxsrc->dx_row_stride = 0;
|
||||||
niimaqdxsrc->start_time = NULL;
|
niimaqdxsrc->start_time = NULL;
|
||||||
niimaqdxsrc->start_time_sent = FALSE;
|
niimaqdxsrc->start_time_sent = FALSE;
|
||||||
niimaqdxsrc->base_time = GST_CLOCK_TIME_NONE;
|
niimaqdxsrc->base_time = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
|
g_free (niimaqdxsrc->temp_buffer);
|
||||||
|
niimaqdxsrc->temp_buffer = NULL;
|
||||||
|
|
||||||
g_free (niimaqdxsrc->times);
|
g_free (niimaqdxsrc->times);
|
||||||
niimaqdxsrc->times = NULL;
|
niimaqdxsrc->times = NULL;
|
||||||
}
|
}
|
||||||
@ -684,14 +806,37 @@ gst_niimaqdxsrc_create (GstPushSrc * psrc, GstBuffer ** buffer)
|
|||||||
}
|
}
|
||||||
|
|
||||||
g_mutex_lock (niimaqdxsrc->mutex);
|
g_mutex_lock (niimaqdxsrc->mutex);
|
||||||
|
if ((niimaqdxsrc->dx_row_stride & 0x3) == 0) {
|
||||||
|
// we have properly aligned strides, copy directly to buffer
|
||||||
rval = IMAQdxGetImageData (niimaqdxsrc->session, GST_BUFFER_DATA (*buffer),
|
rval = IMAQdxGetImageData (niimaqdxsrc->session, GST_BUFFER_DATA (*buffer),
|
||||||
GST_BUFFER_SIZE (*buffer), IMAQdxBufferNumberModeBufferNumber,
|
GST_BUFFER_SIZE (*buffer), IMAQdxBufferNumberModeBufferNumber,
|
||||||
niimaqdxsrc->cumbufnum, &copied_number);
|
niimaqdxsrc->cumbufnum, &copied_number);
|
||||||
|
} else {
|
||||||
|
// we don't have aligned strides, copy to temp buffer
|
||||||
|
rval = IMAQdxGetImageData (niimaqdxsrc->session, niimaqdxsrc->temp_buffer,
|
||||||
|
GST_BUFFER_SIZE (*buffer), IMAQdxBufferNumberModeBufferNumber,
|
||||||
|
niimaqdxsrc->cumbufnum, &copied_number);
|
||||||
|
}
|
||||||
|
|
||||||
//FIXME: handle timestamps
|
//FIXME: handle timestamps
|
||||||
//timestamp = niimaqdxsrc->times[copied_index];
|
//timestamp = niimaqdxsrc->times[copied_index];
|
||||||
//niimaqdxsrc->times[copied_index] = GST_CLOCK_TIME_NONE;
|
//niimaqdxsrc->times[copied_index] = GST_CLOCK_TIME_NONE;
|
||||||
g_mutex_unlock (niimaqdxsrc->mutex);
|
g_mutex_unlock (niimaqdxsrc->mutex);
|
||||||
|
|
||||||
|
// adjust for row stride if needed (must be multiple of 4)
|
||||||
|
if ((niimaqdxsrc->dx_row_stride & 0x3) != 0) {
|
||||||
|
int i;
|
||||||
|
int dx_row_stride = niimaqdxsrc->dx_row_stride;
|
||||||
|
int gst_row_stride = GST_ROUND_UP_4 (dx_row_stride);
|
||||||
|
guint8 *src = niimaqdxsrc->temp_buffer;
|
||||||
|
guint8 *dst = GST_BUFFER_DATA (*buffer);
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (niimaqdxsrc,
|
||||||
|
"Row stride (%d) not a multiple of 4, need to copy data",
|
||||||
|
dx_row_stride);
|
||||||
|
for (i = 0; i < niimaqdxsrc->height; i++)
|
||||||
|
memcpy (dst + i * gst_row_stride, src + i * dx_row_stride, dx_row_stride);
|
||||||
|
}
|
||||||
|
|
||||||
if (rval) {
|
if (rval) {
|
||||||
gst_niimaqdxsrc_report_imaq_error (rval);
|
gst_niimaqdxsrc_report_imaq_error (rval);
|
||||||
@ -796,18 +941,6 @@ listAttributes (IMAQdxSession session)
|
|||||||
g_free (attributeInfoArray);
|
g_free (attributeInfoArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
GstVideoFormat
|
|
||||||
convert_PixelFormat_to_VideoFormat (char *pixelFormat)
|
|
||||||
{
|
|
||||||
if (g_strcmp0 (pixelFormat, "Mono 8") == 0)
|
|
||||||
return GST_VIDEO_FORMAT_GRAY8;
|
|
||||||
else if (g_strcmp0 (pixelFormat, "Mono 16") == 0)
|
|
||||||
return GST_VIDEO_FORMAT_GRAY16_BE; //TODO: always BE?
|
|
||||||
else
|
|
||||||
return GST_VIDEO_FORMAT_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* gst_niimaqdxsrc_get_cam_caps:
|
* gst_niimaqdxsrc_get_cam_caps:
|
||||||
* src: #GstNiImaqDx instance
|
* src: #GstNiImaqDx instance
|
||||||
@ -819,12 +952,11 @@ convert_PixelFormat_to_VideoFormat (char *pixelFormat)
|
|||||||
GstCaps *
|
GstCaps *
|
||||||
gst_niimaqdxsrc_get_cam_caps (GstNiImaqDxSrc * niimaqdxsrc)
|
gst_niimaqdxsrc_get_cam_caps (GstNiImaqDxSrc * niimaqdxsrc)
|
||||||
{
|
{
|
||||||
GstCaps *gcaps = NULL;
|
GstCaps *caps = NULL;
|
||||||
IMAQdxError rval;
|
IMAQdxError rval;
|
||||||
uInt32 val;
|
uInt32 val;
|
||||||
char pixelFormat[IMAQDX_MAX_API_STRING_LENGTH];
|
char pixel_format[IMAQDX_MAX_API_STRING_LENGTH];
|
||||||
gint width, height;
|
gint width, height;
|
||||||
GstVideoFormat format = GST_VIDEO_FORMAT_UNKNOWN;
|
|
||||||
|
|
||||||
if (!niimaqdxsrc->session) {
|
if (!niimaqdxsrc->session) {
|
||||||
GST_ELEMENT_ERROR (niimaqdxsrc, RESOURCE, FAILED,
|
GST_ELEMENT_ERROR (niimaqdxsrc, RESOURCE, FAILED,
|
||||||
@ -837,11 +969,8 @@ gst_niimaqdxsrc_get_cam_caps (GstNiImaqDxSrc * niimaqdxsrc)
|
|||||||
listAttributes (niimaqdxsrc->session);
|
listAttributes (niimaqdxsrc->session);
|
||||||
|
|
||||||
rval = IMAQdxGetAttribute (niimaqdxsrc->session, IMAQdxAttributePixelFormat,
|
rval = IMAQdxGetAttribute (niimaqdxsrc->session, IMAQdxAttributePixelFormat,
|
||||||
IMAQdxValueTypeString, &pixelFormat);
|
IMAQdxValueTypeString, &pixel_format);
|
||||||
gst_niimaqdxsrc_report_imaq_error (rval);
|
gst_niimaqdxsrc_report_imaq_error (rval);
|
||||||
|
|
||||||
format = convert_PixelFormat_to_VideoFormat (pixelFormat);
|
|
||||||
|
|
||||||
rval &= IMAQdxGetAttribute (niimaqdxsrc->session, IMAQdxAttributeWidth,
|
rval &= IMAQdxGetAttribute (niimaqdxsrc->session, IMAQdxAttributeWidth,
|
||||||
IMAQdxValueTypeU32, &val);
|
IMAQdxValueTypeU32, &val);
|
||||||
gst_niimaqdxsrc_report_imaq_error (rval);
|
gst_niimaqdxsrc_report_imaq_error (rval);
|
||||||
@ -857,24 +986,24 @@ gst_niimaqdxsrc_get_cam_caps (GstNiImaqDxSrc * niimaqdxsrc)
|
|||||||
("attempt to read attributes failed"));
|
("attempt to read attributes failed"));
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
//TODO: add all available caps by enumerating PixelFormat's available, and query for framerate
|
||||||
if (format == GST_VIDEO_FORMAT_UNKNOWN) {
|
caps =
|
||||||
|
gst_niimaqdxsrc_new_caps_from_pixel_format (pixel_format, width, height,
|
||||||
|
30, 1, 1, 1);
|
||||||
|
if (!caps) {
|
||||||
GST_ERROR_OBJECT (niimaqdxsrc, "PixelFormat '%s' not supported yet",
|
GST_ERROR_OBJECT (niimaqdxsrc, "PixelFormat '%s' not supported yet",
|
||||||
pixelFormat);
|
pixel_format);
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* hard code framerate and par as IMAQ doesn't tell us anything about it */
|
GST_LOG_OBJECT (caps, "are the camera caps");
|
||||||
gcaps = gst_video_format_new_caps (format, width, height, 30, 1, 1, 1);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (gcaps, "are the camera caps");
|
return caps;
|
||||||
|
|
||||||
return gcaps;
|
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
|
||||||
if (gcaps) {
|
if (caps) {
|
||||||
gst_caps_unref (gcaps);
|
gst_caps_unref (caps);
|
||||||
}
|
}
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|||||||
@ -54,10 +54,11 @@ struct _GstNiImaqDxSrc {
|
|||||||
gint ringbuffer_count;
|
gint ringbuffer_count;
|
||||||
|
|
||||||
/* image info */
|
/* image info */
|
||||||
GstVideoFormat format;
|
|
||||||
int width;
|
int width;
|
||||||
int height;
|
int height;
|
||||||
|
int dx_row_stride;
|
||||||
gint framesize;
|
gint framesize;
|
||||||
|
guint8 *temp_buffer;
|
||||||
|
|
||||||
gint64 n_frames; /* total frames sent */
|
gint64 n_frames; /* total frames sent */
|
||||||
uInt32 cumbufnum;
|
uInt32 cumbufnum;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user