Add support for getcaps that probes the camera for capabilities

This commit is contained in:
Youness Alaoui 2012-10-24 10:55:52 -04:00 committed by Nicolas Dufresne
parent 4856d22b9f
commit bb83c54a87

View file

@ -141,12 +141,160 @@ gst_ahc_src_dispose (GObject * object)
G_OBJECT_CLASS (parent_class)->dispose (object);
}
static gint
_compare_formats (int f1, int f2)
{
if (f1 == f2)
return 0;
/* YV12 has priority */
if (f1 == ImageFormat_YV12)
return -1;
if (f2 == ImageFormat_YV12)
return 1;
/* Then NV21 */
if (f1 == ImageFormat_NV21)
return -1;
if (f2 == ImageFormat_NV21)
return 1;
/* Then we don't care */
return f2 - f1;
}
static gint
_compare_sizes (GstAHCSize * s1, GstAHCSize * s2)
{
return ((s2->width * s2->height) - (s1->width * s1->height));
}
static gint
_compare_ranges (int *r1, int *r2)
{
if (r1[1] == r2[1])
/* Smallest range */
return (r1[1] - r1[0]) - (r2[1] - r2[0]);
else
/* Highest fps */
return r2[1] - r1[1];
}
static GstCaps *
gst_ahc_src_getcaps (GstBaseSrc * src)
{
GstAHCSrc *self = GST_AHC_SRC (src);
return gst_caps_copy (self->caps);
if (self->camera) {
GstCaps *ret = gst_caps_new_empty ();
GstAHCParameters *params;
params = gst_ah_camera_get_parameters (self->camera);
if (params) {
GList *formats, *sizes, *ranges;
GList *i, *j, *k;
int previous_format = ImageFormat_UNKNOWN;
formats = gst_ahc_parameters_get_supported_preview_formats (params);
formats = g_list_sort (formats, (GCompareFunc) _compare_formats);
sizes = gst_ahc_parameters_get_supported_preview_sizes (params);
sizes = g_list_sort (sizes, (GCompareFunc) _compare_sizes);
ranges = gst_ahc_parameters_get_supported_preview_fps_range (params);
ranges = g_list_sort (ranges, (GCompareFunc) _compare_ranges);
GST_WARNING_OBJECT (self, "Supported preview formats:");
for (i = formats; i; i = i->next) {
int f = GPOINTER_TO_INT (i->data);
GstStructure *format = NULL;
/* Ignore duplicates */
if (f == previous_format)
continue;
/* Can't use switch/case because the values are not constants */
if (f == ImageFormat_NV16) {
GST_WARNING_OBJECT (self, " NV16 (%d)", f);
format = gst_structure_new ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '1', '6'),
NULL);
} else if (f == ImageFormat_NV21) {
GST_WARNING_OBJECT (self, " NV21 (%d)", f);
format = gst_structure_new ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '2', '1'),
NULL);
} else if (f == ImageFormat_RGB_565) {
GST_WARNING_OBJECT (self, " RGB565 (%d)", f);
format = gst_structure_new ("video/x-raw-rgb",
"bpp", G_TYPE_INT, 16,
"depth", G_TYPE_INT, 16,
"red_mask", G_TYPE_INT, 0xf800,
"green_mask", G_TYPE_INT, 0x07e0,
"blue_mask", G_TYPE_INT, 0x001f,
"endianness", G_TYPE_INT, G_LITTLE_ENDIAN, NULL);
} else if (f == ImageFormat_YUY2) {
GST_WARNING_OBJECT (self, " YUY2 (%d)", f);
format = gst_structure_new ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'U', 'Y', '2'),
NULL);
} else if (f == ImageFormat_YV12) {
GST_WARNING_OBJECT (self, " YV12 (%d)", f);
format = gst_structure_new ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('Y', 'V', '1', '2'),
NULL);
}
previous_format = f;
if (format) {
for (j = sizes; j; j = j->next) {
GstAHCSize *s = j->data;
GstStructure *size;
size = gst_structure_copy (format);
gst_structure_set (size, "width", G_TYPE_INT, s->width,
"height", G_TYPE_INT, s->height,
"interlaced", G_TYPE_BOOLEAN, FALSE,
"pixel-aspect-ratio", GST_TYPE_FRACTION, 1, 1, NULL);
for (k = ranges; k; k = k->next) {
int *range = k->data;
GstStructure *s;
s = gst_structure_copy (size);
if (range[0] == range[1]) {
gst_structure_set (s, "framerate", GST_TYPE_FRACTION,
range[0], 1000, NULL);
} else {
gst_structure_set (s, "framerate", GST_TYPE_FRACTION_RANGE,
range[0], 1000, range[1], 1000, NULL);
}
gst_caps_append_structure (ret, s);
}
gst_structure_free (size);
}
gst_structure_free (format);
}
}
GST_WARNING_OBJECT (self, "Supported preview sizes:");
for (i = sizes; i; i = i->next) {
GstAHCSize *s = i->data;
GST_WARNING_OBJECT (self, " %dx%d", s->width, s->height);
}
GST_WARNING_OBJECT (self, "Supported preview fps range:");
for (i = ranges; i; i = i->next) {
int *range = i->data;
GST_WARNING_OBJECT (self, " [%d, %d]", range[0], range[1]);
}
gst_ahc_parameters_supported_preview_formats_free (formats);
gst_ahc_parameters_supported_preview_sizes_free (sizes);
gst_ahc_parameters_supported_preview_fps_range_free (ranges);
}
gst_ahc_parameters_free (params);
return ret;
} else {
return NULL;
}
}
static void
@ -281,15 +429,19 @@ gst_ahc_src_open (GstAHCSrc * self)
self->camera = gst_ah_camera_open (0);
if (self->camera) {
GstAHCParameters *params;
JNIEnv *env = gst_dvm_get_env ();
params = gst_ah_camera_get_parameters (self->camera);
GstAHCParameters *params;
gint i;
GST_WARNING_OBJECT (self, "Opened camera");
self->texture = gst_ag_surfacetexture_new (0);
gst_ah_camera_set_preview_texture (self->camera, self->texture);
gst_ah_camera_set_error_callback (self->camera, gst_ahc_src_on_error, self);
params = gst_ah_camera_get_parameters (self->camera);
if (params) {
GstAHCSize *size;
int i;
GST_WARNING_OBJECT (self, "Params : %s",
gst_ahc_parameters_flatten (params));
@ -309,51 +461,14 @@ gst_ahc_src_open (GstAHCSrc * self)
gst_ag_imageformat_get_bits_per_pixel
(gst_ahc_parameters_get_preview_format (params)) / 8;
gst_ahc_size_free (size);
self->texture = gst_ag_surfacetexture_new (0);
gst_ah_camera_set_preview_texture (self->camera, self->texture);
gst_ah_camera_set_error_callback (self->camera, gst_ahc_src_on_error,
self);
for (i = 0; i < NUM_CALLBACK_BUFFERS; i++) {
jbyteArray array = (*env)->NewByteArray (env, self->buffer_size);
gst_ah_camera_add_callback_buffer (self->camera, array);
(*env)->DeleteLocalRef (env, array);
}
{
GList *list, *i;
list = gst_ahc_parameters_get_supported_preview_formats (params);
GST_WARNING_OBJECT (self, "Supported preview formats:");
for (i = list; i; i = i->next) {
int f = GPOINTER_TO_INT (i->data);
GST_WARNING_OBJECT (self, " %d", f);
}
gst_ahc_parameters_supported_preview_formats_free (list);
list = gst_ahc_parameters_get_supported_preview_sizes (params);
GST_WARNING_OBJECT (self, "Supported preview sizes:");
for (i = list; i; i = i->next) {
GstAHCSize *s = i->data;
GST_WARNING_OBJECT (self, " %dx%d", s->width, s->height);
}
gst_ahc_parameters_supported_preview_sizes_free (list);
list = gst_ahc_parameters_get_supported_preview_fps_range (params);
GST_WARNING_OBJECT (self, "Supported preview fps range:");
for (i = list; i; i = i->next) {
int *range = i->data;
GST_WARNING_OBJECT (self, " [%d, %d]", range[0], range[1]);
}
gst_ahc_parameters_supported_preview_fps_range_free (list);
}
gst_ahc_parameters_free (params);
}
for (i = 0; i < NUM_CALLBACK_BUFFERS; i++) {
jbyteArray array = (*env)->NewByteArray (env, self->buffer_size);
gst_ah_camera_add_callback_buffer (self->camera, array);
(*env)->DeleteLocalRef (env, array);
}
} else {
GST_ELEMENT_ERROR (self, RESOURCE, NOT_FOUND,
("Unable to open device '%d'.", 0), GST_ERROR_SYSTEM);