static void
_RGB_to_YUV (GstGLColorConvert * convert)
{
  struct ConvertInfo *info = &convert->priv->convert_info;
  GstVideoFormat in_format = GST_VIDEO_INFO_FORMAT (&convert->in_info);
  const gchar *in_format_str = gst_video_format_to_string (in_format);
  GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
  gchar *pixel_order = _RGB_pixel_order (in_format_str, "rgba");
  const gchar *alpha;

  info->frag_prog = NULL;
  info->in_n_textures = 1;

  info->shader_tex_names[0] = "tex";

  switch (out_format) {
    case GST_VIDEO_FORMAT_AYUV:
      alpha = _is_RGBx (in_format) ? "1.0" : "texel.a";
      info->frag_prog = g_strdup_printf (frag_RGB_to_AYUV, pixel_order[0],
          pixel_order[1], pixel_order[2], pixel_order[3], alpha);
      info->out_n_textures = 1;
      break;
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_YV12:
    case GST_VIDEO_FORMAT_Y444:
    case GST_VIDEO_FORMAT_Y42B:
    case GST_VIDEO_FORMAT_Y41B:
      info->frag_prog = g_strdup_printf (frag_RGB_to_PLANAR_YUV,
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
      info->out_n_textures = 3;
      if (out_format == GST_VIDEO_FORMAT_Y444) {
        info->chroma_sampling[0] = info->chroma_sampling[1] = 1.0f;
      } else if (out_format == GST_VIDEO_FORMAT_Y42B) {
        info->chroma_sampling[0] = 2.0f;
        info->chroma_sampling[1] = 1.0f;
      } else if (out_format == GST_VIDEO_FORMAT_Y41B) {
        info->chroma_sampling[0] = 4.0f;
        info->chroma_sampling[1] = 1.0f;
      } else {
        info->chroma_sampling[0] = info->chroma_sampling[1] = 2.0f;
      }
      break;
    case GST_VIDEO_FORMAT_YUY2:
      info->frag_prog = g_strdup_printf (frag_RGB_to_YUY2_UYVY,
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
          "y", "u", "y", "v");
      info->out_n_textures = 1;
      break;
    case GST_VIDEO_FORMAT_UYVY:
      info->frag_prog = g_strdup_printf (frag_RGB_to_YUY2_UYVY,
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3],
          "u", "y", "v", "y");
      info->out_n_textures = 1;
      break;
    default:
      break;
  }

  if (gst_video_colorimetry_matches (&convert->in_info.colorimetry,
          GST_VIDEO_COLORIMETRY_BT709)) {
    info->cms_offset = (gfloat *) from_rgb_bt709_offset;
    info->cms_coeff1 = (gfloat *) from_rgb_bt709_ycoeff;
    info->cms_coeff2 = (gfloat *) from_rgb_bt709_ucoeff;
    info->cms_coeff3 = (gfloat *) from_rgb_bt709_vcoeff;
  } else {
    /* defaults/bt601 */
    info->cms_offset = (gfloat *) from_rgb_bt601_offset;
    info->cms_coeff1 = (gfloat *) from_rgb_bt601_ycoeff;
    info->cms_coeff2 = (gfloat *) from_rgb_bt601_ucoeff;
    info->cms_coeff3 = (gfloat *) from_rgb_bt601_vcoeff;
  }

  g_free (pixel_order);
}
static gboolean
gst_rtp_vraw_pay_setcaps (GstRTPBasePayload * payload, GstCaps * caps)
{
  GstRtpVRawPay *rtpvrawpay;
  gboolean res;
  gint pgroup, xinc, yinc;
  const gchar *depthstr, *samplingstr, *colorimetrystr;
  gchar *wstr, *hstr;
  GstVideoInfo info;

  rtpvrawpay = GST_RTP_VRAW_PAY (payload);

  if (!gst_video_info_from_caps (&info, caps))
    goto invalid_caps;

  rtpvrawpay->vinfo = info;

  if (gst_video_colorimetry_matches (&info.colorimetry,
          GST_VIDEO_COLORIMETRY_BT601)) {
    colorimetrystr = "BT601-5";
  } else if (gst_video_colorimetry_matches (&info.colorimetry,
          GST_VIDEO_COLORIMETRY_BT709)) {
    colorimetrystr = "BT709-2";
  } else if (gst_video_colorimetry_matches (&info.colorimetry,
          GST_VIDEO_COLORIMETRY_SMPTE240M)) {
    colorimetrystr = "SMPTE240M";
  } else {
    colorimetrystr = "SMPTE240M";
  }

  xinc = yinc = 1;

  /* these values are the only thing we can do */
  depthstr = "8";

  switch (GST_VIDEO_INFO_FORMAT (&info)) {
    case GST_VIDEO_FORMAT_RGBA:
      samplingstr = "RGBA";
      pgroup = 4;
      break;
    case GST_VIDEO_FORMAT_BGRA:
      samplingstr = "BGRA";
      pgroup = 4;
      break;
    case GST_VIDEO_FORMAT_RGB:
      samplingstr = "RGB";
      pgroup = 3;
      break;
    case GST_VIDEO_FORMAT_BGR:
      samplingstr = "BGR";
      pgroup = 3;
      break;
    case GST_VIDEO_FORMAT_AYUV:
      samplingstr = "YCbCr-4:4:4";
      pgroup = 3;
      break;
    case GST_VIDEO_FORMAT_UYVY:
      samplingstr = "YCbCr-4:2:2";
      pgroup = 4;
      xinc = 2;
      break;
    case GST_VIDEO_FORMAT_Y41B:
      samplingstr = "YCbCr-4:1:1";
      pgroup = 6;
      xinc = 4;
      break;
    case GST_VIDEO_FORMAT_I420:
      samplingstr = "YCbCr-4:2:0";
      pgroup = 6;
      xinc = yinc = 2;
      break;
    case GST_VIDEO_FORMAT_UYVP:
      samplingstr = "YCbCr-4:2:2";
      pgroup = 5;
      xinc = 2;
      depthstr = "10";
      break;
    default:
      goto unknown_format;
      break;
  }

  if (GST_VIDEO_INFO_IS_INTERLACED (&info)) {
    yinc *= 2;
  }

  rtpvrawpay->pgroup = pgroup;
  rtpvrawpay->xinc = xinc;
  rtpvrawpay->yinc = yinc;

  GST_DEBUG_OBJECT (payload, "width %d, height %d, sampling %s",
      GST_VIDEO_INFO_WIDTH (&info), GST_VIDEO_INFO_HEIGHT (&info), samplingstr);
  GST_DEBUG_OBJECT (payload, "xinc %d, yinc %d, pgroup %d", xinc, yinc, pgroup);

  wstr = g_strdup_printf ("%d", GST_VIDEO_INFO_WIDTH (&info));
  hstr = g_strdup_printf ("%d", GST_VIDEO_INFO_HEIGHT (&info));

  gst_rtp_base_payload_set_options (payload, "video", TRUE, "RAW", 90000);
  if (GST_VIDEO_INFO_IS_INTERLACED (&info)) {
    res = gst_rtp_base_payload_set_outcaps (payload, "sampling", G_TYPE_STRING,
        samplingstr, "depth", G_TYPE_STRING, depthstr, "width", G_TYPE_STRING,
        wstr, "height", G_TYPE_STRING, hstr, "colorimetry", G_TYPE_STRING,
        colorimetrystr, "interlace", G_TYPE_STRING, "true", NULL);
  } else {
    res = gst_rtp_base_payload_set_outcaps (payload, "sampling", G_TYPE_STRING,
        samplingstr, "depth", G_TYPE_STRING, depthstr, "width", G_TYPE_STRING,
        wstr, "height", G_TYPE_STRING, hstr, "colorimetry", G_TYPE_STRING,
        colorimetrystr, NULL);
  }
  g_free (wstr);
  g_free (hstr);

  return res;

  /* ERRORS */
invalid_caps:
  {
    GST_ERROR_OBJECT (payload, "could not parse caps");
    return FALSE;
  }
unknown_format:
  {
    GST_ERROR_OBJECT (payload, "unknown caps format");
    return FALSE;
  }
}
static void
_YUV_to_RGB (GstGLColorConvert * convert)
{
  struct ConvertInfo *info = &convert->priv->convert_info;
  GstVideoFormat out_format = GST_VIDEO_INFO_FORMAT (&convert->out_info);
  const gchar *out_format_str = gst_video_format_to_string (out_format);
  gchar *pixel_order = _RGB_pixel_order ("rgba", out_format_str);
#if GST_GL_HAVE_PLATFORM_EAGL
  gboolean texture_rg = FALSE;
#else
  gboolean texture_rg =
      gst_gl_context_check_feature (convert->context, "GL_EXT_texture_rg")
      || gst_gl_context_check_feature (convert->context, "GL_ARB_texture_rg");
#endif

  info->out_n_textures = 1;

  switch (GST_VIDEO_INFO_FORMAT (&convert->in_info)) {
    case GST_VIDEO_FORMAT_AYUV:
      info->frag_prog = g_strdup_printf (frag_AYUV_to_RGB, pixel_order[0],
          pixel_order[1], pixel_order[2], pixel_order[3]);
      info->in_n_textures = 1;
      info->shader_tex_names[0] = "tex";
      break;
    case GST_VIDEO_FORMAT_I420:
    case GST_VIDEO_FORMAT_Y444:
    case GST_VIDEO_FORMAT_Y42B:
    case GST_VIDEO_FORMAT_Y41B:
      info->frag_prog = g_strdup_printf (frag_PLANAR_YUV_to_RGB, pixel_order[0],
          pixel_order[1], pixel_order[2], pixel_order[3]);
      info->in_n_textures = 3;
      info->shader_tex_names[0] = "Ytex";
      info->shader_tex_names[1] = "Utex";
      info->shader_tex_names[2] = "Vtex";
      break;
    case GST_VIDEO_FORMAT_YV12:
      info->frag_prog = g_strdup_printf (frag_PLANAR_YUV_to_RGB, pixel_order[0],
          pixel_order[1], pixel_order[2], pixel_order[3]);
      info->in_n_textures = 3;
      info->shader_tex_names[0] = "Ytex";
      info->shader_tex_names[1] = "Vtex";
      info->shader_tex_names[2] = "Utex";
      break;
    case GST_VIDEO_FORMAT_YUY2:
    {
      char uv_val = texture_rg ? 'g' : 'a';
      info->frag_prog = g_strdup_printf (frag_YUY2_UYVY_to_RGB, 'r', uv_val,
          uv_val, 'g', 'a', pixel_order[0], pixel_order[1], pixel_order[2],
          pixel_order[3]);
      info->in_n_textures = 1;
      info->shader_tex_names[0] = "Ytex";
      break;
    }
    case GST_VIDEO_FORMAT_NV12:
    {
      char val2 = texture_rg ? 'g' : 'a';
      info->frag_prog = g_strdup_printf (frag_NV12_NV21_to_RGB, 'r', val2,
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
      info->in_n_textures = 2;
      info->shader_tex_names[0] = "Ytex";
      info->shader_tex_names[1] = "UVtex";
      break;
    }
    case GST_VIDEO_FORMAT_NV21:
    {
      char val2 = texture_rg ? 'g' : 'a';
      info->frag_prog = g_strdup_printf (frag_NV12_NV21_to_RGB, val2, 'r',
          pixel_order[0], pixel_order[1], pixel_order[2], pixel_order[3]);
      info->in_n_textures = 2;
      info->shader_tex_names[0] = "Ytex";
      info->shader_tex_names[1] = "UVtex";
      break;
    }
    case GST_VIDEO_FORMAT_UYVY:
    {
      char y_val = texture_rg ? 'g' : 'a';
      info->frag_prog = g_strdup_printf (frag_YUY2_UYVY_to_RGB, y_val, 'g',
          'g', 'r', 'b', pixel_order[0], pixel_order[1], pixel_order[2],
          pixel_order[3]);
      info->in_n_textures = 1;
      info->shader_tex_names[0] = "Ytex";
      break;
    }
    default:
      break;
  }

  if (gst_video_colorimetry_matches (&convert->in_info.colorimetry,
          GST_VIDEO_COLORIMETRY_BT709)) {
    info->cms_offset = (gfloat *) from_yuv_bt709_offset;
    info->cms_coeff1 = (gfloat *) from_yuv_bt709_rcoeff;
    info->cms_coeff2 = (gfloat *) from_yuv_bt709_gcoeff;
    info->cms_coeff3 = (gfloat *) from_yuv_bt709_bcoeff;
  } else {
    /* defaults/bt601 */
    info->cms_offset = (gfloat *) from_yuv_bt601_offset;
    info->cms_coeff1 = (gfloat *) from_yuv_bt601_rcoeff;
    info->cms_coeff2 = (gfloat *) from_yuv_bt601_gcoeff;
    info->cms_coeff3 = (gfloat *) from_yuv_bt601_bcoeff;
  }

  g_free (pixel_order);
}