static GstFlowReturn
gst_opencv_video_filter_transform_ip (GstBaseTransform * trans,
    GstBuffer * buffer)
{
  GstOpencvVideoFilter *transform;
  GstOpencvVideoFilterClass *fclass;
  GstFlowReturn ret;

  transform = GST_OPENCV_VIDEO_FILTER (trans);
  fclass = GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);

  g_return_val_if_fail (fclass->cv_trans_ip_func != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (transform->cvImage != NULL, GST_FLOW_ERROR);

  /* TODO this is not always needed and should be solved at BaseTransform
   * level */
  buffer = gst_buffer_make_writable (buffer);

  transform->cvImage->imageData = (char *) gst_buffer_map (buffer,
      NULL, NULL, GST_MAP_READWRITE);

  /* FIXME how to release buffer? */
  ret = fclass->cv_trans_ip_func (transform, buffer, transform->cvImage);

  gst_buffer_unmap (buffer, transform->cvImage->imageData, -1);

  return ret;
}
static GstFlowReturn
gst_opencv_video_filter_transform_ip (GstBaseTransform * trans,
    GstBuffer * buffer)
{
  GstOpencvVideoFilter *transform;
  GstOpencvVideoFilterClass *fclass;
  GstMapInfo info;
  GstFlowReturn ret;

  transform = GST_OPENCV_VIDEO_FILTER (trans);
  fclass = GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);

  g_return_val_if_fail (fclass->cv_trans_ip_func != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (transform->cvImage != NULL, GST_FLOW_ERROR);

  if (!gst_buffer_map (buffer, &info, GST_MAP_READWRITE))
    goto map_failed;

  transform->cvImage->imageData = (char *) info.data;

  ret = fclass->cv_trans_ip_func (transform, buffer, transform->cvImage);

  gst_buffer_unmap (buffer, &info);

  return ret;

map_failed:
  GST_ELEMENT_ERROR (transform, RESOURCE, WRITE,
      ("Failed to map buffer for reading and writing"), (NULL));
  return GST_FLOW_ERROR;
}
static GstFlowReturn
gst_opencv_video_filter_transform (GstBaseTransform * trans,
    GstBuffer * inbuf, GstBuffer * outbuf)
{
  GstOpencvVideoFilter *transform;
  GstOpencvVideoFilterClass *fclass;
  GstFlowReturn ret;

  transform = GST_OPENCV_VIDEO_FILTER (trans);
  fclass = GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);

  g_return_val_if_fail (fclass->cv_trans_func != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (transform->cvImage != NULL, GST_FLOW_ERROR);
  g_return_val_if_fail (transform->out_cvImage != NULL, GST_FLOW_ERROR);

  transform->cvImage->imageData = (char *) gst_buffer_map (inbuf,
      NULL, NULL, GST_MAP_READ);
  transform->out_cvImage->imageData = (char *) gst_buffer_map (outbuf,
      NULL, NULL, GST_MAP_WRITE);

  ret = fclass->cv_trans_func (transform, inbuf, transform->cvImage, outbuf,
      transform->out_cvImage);

  gst_buffer_unmap (inbuf, transform->cvImage->imageData, -1);
  gst_buffer_unmap (outbuf, transform->out_cvImage->imageData, -1);

  return ret;
}
static gboolean
gst_opencv_video_filter_set_caps (GstBaseTransform * trans, GstCaps * incaps,
    GstCaps * outcaps)
{
  GstOpencvVideoFilter *transform = GST_OPENCV_VIDEO_FILTER (trans);
  GstOpencvVideoFilterClass *klass =
      GST_OPENCV_VIDEO_FILTER_GET_CLASS (transform);
  gint in_width, in_height;
  gint in_depth, in_channels;
  gint out_width, out_height;
  gint out_depth, out_channels;
  GError *in_err = NULL;
  GError *out_err = NULL;

  if (!gst_opencv_parse_iplimage_params_from_caps (incaps, &in_width,
          &in_height, &in_depth, &in_channels, &in_err)) {
    GST_WARNING_OBJECT (transform, "Failed to parse input caps: %s",
        in_err->message);
    g_error_free (in_err);
    return FALSE;
  }

  if (!gst_opencv_parse_iplimage_params_from_caps (outcaps, &out_width,
          &out_height, &out_depth, &out_channels, &out_err)) {
    GST_WARNING_OBJECT (transform, "Failed to parse output caps: %s",
        out_err->message);
    g_error_free (out_err);
    return FALSE;
  }

  if (klass->cv_set_caps) {
    if (!klass->cv_set_caps (transform, in_width, in_height, in_depth,
            in_channels, out_width, out_height, out_depth, out_channels))
      return FALSE;
  }

  if (transform->cvImage) {
    cvReleaseImage (&transform->cvImage);
  }
  if (transform->out_cvImage) {
    cvReleaseImage (&transform->out_cvImage);
  }

  transform->cvImage =
      cvCreateImageHeader (cvSize (in_width, in_height), in_depth, in_channels);
  transform->out_cvImage =
      cvCreateImageHeader (cvSize (out_width, out_height), out_depth,
      out_channels);

  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (transform),
      transform->in_place);
  return TRUE;
}