gboolean gst_opencv_parse_iplimage_params_from_caps (GstCaps * caps, gint * width, gint * height, gint * ipldepth, gint * channels, GError ** err) { GstVideoInfo info; gint i, depth = 0; if (!gst_video_info_from_caps (&info, caps)) { GST_ERROR ("Failed to get the videoinfo from caps"); g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, "No width/heighti/depth/channels in caps"); return FALSE; } *width = GST_VIDEO_INFO_WIDTH (&info); *height = GST_VIDEO_INFO_HEIGHT (&info); if (GST_VIDEO_INFO_IS_RGB (&info)) *channels = 3; else if (GST_VIDEO_INFO_IS_GRAY (&info)) *channels = 1; else { g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, "Unsupported caps %s", gst_caps_to_string(caps)); return FALSE; } for (i = 0; i < GST_VIDEO_INFO_N_COMPONENTS (&info); i++) depth += GST_VIDEO_INFO_COMP_DEPTH (&info, i); if (depth / *channels == 8) { /* TODO signdness? */ *ipldepth = IPL_DEPTH_8U; } else if (depth / *channels == 16) { *ipldepth = IPL_DEPTH_16U; } else { g_set_error (err, GST_CORE_ERROR, GST_CORE_ERROR_NEGOTIATION, "Unsupported depth/channels %d/%d", depth, *channels); return FALSE; } return TRUE; }
static gboolean gst_video_crop_set_info (GstVideoFilter * vfilter, GstCaps * in, GstVideoInfo * in_info, GstCaps * out, GstVideoInfo * out_info) { GstVideoCrop *crop = GST_VIDEO_CROP (vfilter); int dx, dy; GST_OBJECT_LOCK (crop); crop->need_update = FALSE; crop->crop_left = crop->prop_left; crop->crop_right = crop->prop_right; crop->crop_top = crop->prop_top; crop->crop_bottom = crop->prop_bottom; GST_OBJECT_UNLOCK (crop); dx = GST_VIDEO_INFO_WIDTH (in_info) - GST_VIDEO_INFO_WIDTH (out_info); dy = GST_VIDEO_INFO_HEIGHT (in_info) - GST_VIDEO_INFO_HEIGHT (out_info); if (crop->crop_left == -1 && crop->crop_right == -1) { crop->crop_left = dx / 2; crop->crop_right = dx / 2 + (dx & 1); } else if (crop->crop_left == -1) { if (G_UNLIKELY (crop->crop_right > dx)) goto cropping_too_much; crop->crop_left = dx - crop->crop_right; } else if (crop->crop_right == -1) { if (G_UNLIKELY (crop->crop_left > dx)) goto cropping_too_much; crop->crop_right = dx - crop->crop_left; } if (crop->crop_top == -1 && crop->crop_bottom == -1) { crop->crop_top = dy / 2; crop->crop_bottom = dy / 2 + (dy & 1); } else if (crop->crop_top == -1) { if (G_UNLIKELY (crop->crop_bottom > dy)) goto cropping_too_much; crop->crop_top = dy - crop->crop_bottom; } else if (crop->crop_bottom == -1) { if (G_UNLIKELY (crop->crop_top > dy)) goto cropping_too_much; crop->crop_bottom = dy - crop->crop_top; } if (G_UNLIKELY ((crop->crop_left + crop->crop_right) >= GST_VIDEO_INFO_WIDTH (in_info) || (crop->crop_top + crop->crop_bottom) >= GST_VIDEO_INFO_HEIGHT (in_info))) goto cropping_too_much; if (in && out) GST_LOG_OBJECT (crop, "incaps = %" GST_PTR_FORMAT ", outcaps = %" GST_PTR_FORMAT, in, out); if ((crop->crop_left | crop->crop_right | crop->crop_top | crop-> crop_bottom) == 0) { GST_LOG_OBJECT (crop, "we are using passthrough"); gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (crop), TRUE); } else { GST_LOG_OBJECT (crop, "we are not using passthrough"); gst_base_transform_set_passthrough (GST_BASE_TRANSFORM (crop), FALSE); } if (GST_VIDEO_INFO_IS_RGB (in_info) || GST_VIDEO_INFO_IS_GRAY (in_info)) { crop->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE; } else { switch (GST_VIDEO_INFO_FORMAT (in_info)) { case GST_VIDEO_FORMAT_AYUV: crop->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_SIMPLE; break; case GST_VIDEO_FORMAT_YVYU: case GST_VIDEO_FORMAT_YUY2: case GST_VIDEO_FORMAT_UYVY: crop->packing = VIDEO_CROP_PIXEL_FORMAT_PACKED_COMPLEX; if (GST_VIDEO_INFO_FORMAT (in_info) == GST_VIDEO_FORMAT_UYVY) { /* UYVY = 4:2:2 - [U0 Y0 V0 Y1] [U2 Y2 V2 Y3] [U4 Y4 V4 Y5] */ crop->macro_y_off = 1; } else { /* YUYV = 4:2:2 - [Y0 U0 Y1 V0] [Y2 U2 Y3 V2] [Y4 U4 Y5 V4] = YUY2 */ crop->macro_y_off = 0; } break; case GST_VIDEO_FORMAT_I420: case GST_VIDEO_FORMAT_YV12: crop->packing = VIDEO_CROP_PIXEL_FORMAT_PLANAR; break; case GST_VIDEO_FORMAT_NV12: case GST_VIDEO_FORMAT_NV21: crop->packing = VIDEO_CROP_PIXEL_FORMAT_SEMI_PLANAR; break; default: goto unknown_format; } } crop->in_info = *in_info; crop->out_info = *out_info; return TRUE; /* ERROR */ cropping_too_much: { GST_WARNING_OBJECT (crop, "we are cropping too much"); return FALSE; } unknown_format: { GST_WARNING_OBJECT (crop, "Unsupported format"); return FALSE; } }
static void check_1x1_buffer (GstBuffer * buf, GstCaps * caps) { GstVideoInfo info; GstVideoFrame frame; /* the exact values we check for come from videotestsrc */ static const guint yuv_values[] = { 81, 90, 240, 255 }; static const guint rgb_values[] = { 0xff, 0, 0, 255 }; static const guint gray8_values[] = { 0x51 }; static const guint gray16_values[] = { 0x5151 }; const guint *values; guint i; const GstVideoFormatInfo *finfo; fail_unless (buf != NULL); fail_unless (caps != NULL); fail_unless (gst_video_info_from_caps (&info, caps)); fail_unless (gst_video_frame_map (&frame, &info, buf, GST_MAP_READ)); finfo = info.finfo; if (GST_VIDEO_INFO_IS_YUV (&info)) values = yuv_values; else if (GST_VIDEO_INFO_IS_GRAY (&info)) if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 8) values = gray8_values; else values = gray16_values; else values = rgb_values; GST_MEMDUMP ("buffer", GST_VIDEO_FRAME_PLANE_DATA (&frame, 0), 8); for (i = 0; i < GST_VIDEO_FRAME_N_COMPONENTS (&frame); i++) { guint8 *data = GST_VIDEO_FRAME_COMP_DATA (&frame, i); GST_DEBUG ("W: %d", GST_VIDEO_FORMAT_INFO_W_SUB (finfo, i)); GST_DEBUG ("H: %d", GST_VIDEO_FORMAT_INFO_H_SUB (finfo, i)); if (GST_VIDEO_FORMAT_INFO_W_SUB (finfo, i) >= GST_VIDEO_FRAME_WIDTH (&frame)) continue; if (GST_VIDEO_FORMAT_INFO_H_SUB (finfo, i) >= GST_VIDEO_FRAME_HEIGHT (&frame)) continue; if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 8) { fail_unless_equals_int (data[0], values[i]); } else if (GST_VIDEO_FORMAT_INFO_BITS (finfo) == 16) { guint16 pixels, val; gint depth; if (GST_VIDEO_FORMAT_INFO_IS_LE (finfo)) pixels = GST_READ_UINT16_LE (data); else pixels = GST_READ_UINT16_BE (data); depth = GST_VIDEO_FORMAT_INFO_DEPTH (finfo, i); val = pixels >> GST_VIDEO_FORMAT_INFO_SHIFT (finfo, i); val = val & ((1 << depth) - 1); GST_DEBUG ("val %08x %d : %d", pixels, i, val); if (depth <= 8) { fail_unless_equals_int (val, values[i] >> (8 - depth)); } else {
/* Called in the gl thread */ static gboolean _init_convert (GstGLColorConvert * convert) { GstGLFuncs *gl; gboolean res; struct ConvertInfo *info = &convert->priv->convert_info; gint i; gl = convert->context->gl_vtable; if (convert->initted) return TRUE; GST_INFO ("Initializing color conversion from %s to %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info))); if (!gl->CreateProgramObject && !gl->CreateProgram) { gst_gl_context_set_error (convert->context, "Cannot perform color conversion without OpenGL shaders"); goto error; } if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) { if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) { _RGB_to_RGB (convert); } } if (GST_VIDEO_INFO_IS_YUV (&convert->in_info)) { if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) { _YUV_to_RGB (convert); } } if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) { if (GST_VIDEO_INFO_IS_YUV (&convert->out_info)) { _RGB_to_YUV (convert); } } if (GST_VIDEO_INFO_IS_RGB (&convert->in_info)) { if (GST_VIDEO_INFO_IS_GRAY (&convert->out_info)) { _RGB_to_GRAY (convert); } } if (GST_VIDEO_INFO_IS_GRAY (&convert->in_info)) { if (GST_VIDEO_INFO_IS_RGB (&convert->out_info)) { _GRAY_to_RGB (convert); } } if (!info->frag_prog || info->in_n_textures == 0 || info->out_n_textures == 0) goto unhandled_format; /* multiple draw targets not supported on GLES2...yet */ if (info->out_n_textures > 1 && (!gl->DrawBuffers || USING_GLES2 (convert->context))) { g_free (info->frag_prog); GST_ERROR ("Conversion requires output to multiple draw buffers"); goto incompatible_api; } /* Requires reading from a RG/LA framebuffer... */ if (USING_GLES2 (convert->context) && (GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_YUY2 || GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_UYVY)) { g_free (info->frag_prog); GST_ERROR ("Conversion requires reading with an unsupported format"); goto incompatible_api; } res = gst_gl_context_gen_shader (convert->context, text_vertex_shader, info->frag_prog, &convert->shader); g_free (info->frag_prog); if (!res) goto error; convert->shader_attr_position_loc = gst_gl_shader_get_attribute_location (convert->shader, "a_position"); convert->shader_attr_texture_loc = gst_gl_shader_get_attribute_location (convert->shader, "a_texcoord"); gst_gl_shader_use (convert->shader); if (info->cms_offset && info->cms_coeff1 && info->cms_coeff2 && info->cms_coeff3) { gst_gl_shader_set_uniform_3fv (convert->shader, "offset", 1, info->cms_offset); gst_gl_shader_set_uniform_3fv (convert->shader, "coeff1", 1, info->cms_coeff1); gst_gl_shader_set_uniform_3fv (convert->shader, "coeff2", 1, info->cms_coeff2); gst_gl_shader_set_uniform_3fv (convert->shader, "coeff3", 1, info->cms_coeff3); } for (i = info->in_n_textures; i >= 0; i--) { if (info->shader_tex_names[i]) gst_gl_shader_set_uniform_1i (convert->shader, info->shader_tex_names[i], i); } gst_gl_shader_set_uniform_1f (convert->shader, "width", GST_VIDEO_INFO_WIDTH (&convert->in_info)); gst_gl_shader_set_uniform_1f (convert->shader, "height", GST_VIDEO_INFO_HEIGHT (&convert->in_info)); if (info->chroma_sampling[0] > 0.0f && info->chroma_sampling[1] > 0.0f) { gst_gl_shader_set_uniform_2fv (convert->shader, "chroma_sampling", 1, info->chroma_sampling); } gst_gl_context_clear_shader (convert->context); if (!_init_convert_fbo (convert)) { goto error; } gl->BindTexture (GL_TEXTURE_2D, 0); convert->initted = TRUE; return TRUE; unhandled_format: gst_gl_context_set_error (convert->context, "Don't know how to convert from %s to %s", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info))); error: return FALSE; incompatible_api: { gst_gl_context_set_error (convert->context, "Converting from %s to %s requires " "functionality that the current OpenGL setup does not support", gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->in_info)), gst_video_format_to_string (GST_VIDEO_INFO_FORMAT (&convert->out_info))); return FALSE; } }