示例#1
0
static gboolean
_init_download (GstGLDownload * download)
{
  GstVideoFormat v_format;
  guint out_width, out_height;
  GstVideoInfo in_info;

  v_format = GST_VIDEO_INFO_FORMAT (&download->info);
  out_width = GST_VIDEO_INFO_WIDTH (&download->info);
  out_height = GST_VIDEO_INFO_HEIGHT (&download->info);

  if (download->initted)
    return TRUE;

  GST_TRACE ("initializing texture download for format %s",
      gst_video_format_to_string (v_format));

  if (USING_GLES2 (download->context) && !USING_GLES3 (download->context)) {
    /* GL_RGBA is the only officially supported texture format in GLES2 */
    if (v_format == GST_VIDEO_FORMAT_RGB || v_format == GST_VIDEO_FORMAT_BGR) {
      gst_gl_context_set_error (download->context, "Cannot download RGB "
          "textures in GLES2");
      return FALSE;
    }
  }

  gst_video_info_set_format (&in_info, GST_VIDEO_FORMAT_RGBA, out_width,
      out_height);

  gst_gl_color_convert_set_format (download->convert, &in_info,
      &download->info);

  return TRUE;
}
static void
gst_glimage_sink_on_close (GstGLImageSink * gl_sink)
{
  gst_gl_context_set_error (gl_sink->context, "Output window was closed");

  g_atomic_int_set (&gl_sink->to_quit, 1);
}
/* Called in the gl thread */
static void
gst_glimage_sink_thread_init_redisplay (GstGLImageSink * gl_sink)
{
  GError *error = NULL;
  gl_sink->redisplay_shader = gst_gl_shader_new (gl_sink->context);

  gst_gl_shader_set_vertex_source (gl_sink->redisplay_shader,
      redisplay_vertex_shader_str_gles2);
  gst_gl_shader_set_fragment_source (gl_sink->redisplay_shader,
      redisplay_fragment_shader_str_gles2);

  gst_gl_shader_compile (gl_sink->redisplay_shader, &error);
  if (error) {
    gst_gl_context_set_error (gl_sink->context, "%s", error->message);
    g_error_free (error);
    error = NULL;
    gst_gl_context_clear_shader (gl_sink->context);
  } else {
    gl_sink->redisplay_attr_position_loc =
        gst_gl_shader_get_attribute_location (gl_sink->redisplay_shader,
        "a_position");
    gl_sink->redisplay_attr_texture_loc =
        gst_gl_shader_get_attribute_location (gl_sink->redisplay_shader,
        "a_texCoord");
  }
}
static void
gst_gl_effects_squeeze_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLFilter *filter = GST_GL_FILTER (data);
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "squeeze0");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, (gchar *) "squeeze0", shader);

    if (USING_GLES2 (context) || USING_OPENGL3 (context)) {
      if (!gst_gl_shader_compile_with_default_v_and_check (shader,
              squeeze_fragment_source_gles2, &filter->draw_attr_position_loc,
              &filter->draw_attr_texture_loc)) {
        /* gst gl context error is already set */
        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
            ("Failed to initialize squeeze shader, %s",
                gst_gl_context_get_error ()), (NULL));
        return;
      }
    }
#if GST_GL_HAVE_OPENGL
    if (USING_OPENGL (context)) {
      if (!gst_gl_shader_compile_and_check (shader,
              squeeze_fragment_source_opengl, GST_GL_SHADER_FRAGMENT_SOURCE)) {
        gst_gl_context_set_error (context,
            "Failed to initialize squeeze shader");
        GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
            ("%s", gst_gl_context_get_error ()), (NULL));
        return;
      }
    }
#endif
  }
#if GST_GL_HAVE_OPENGL
  if (USING_OPENGL (context)) {
    gl->MatrixMode (GL_PROJECTION);
    gl->LoadIdentity ();
  }
#endif

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE0);
  if (USING_OPENGL (context))
    gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (shader, "tex", 0);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
示例#5
0
static void
_compile_shader (GstGLContext * context, GstGLShader ** shader)
{
  GError *error = NULL;

  gst_gl_shader_compile (*shader, &error);
  if (error) {
    gst_gl_context_set_error (context, "%s", error->message);
    g_error_free (error);
    error = NULL;
    gst_gl_context_clear_shader (context);
    gst_object_unref (*shader);
    *shader = NULL;
  }
}
示例#6
0
static void
gst_glimage_sink_on_close (GstGLImageSink * gl_sink)
{
  GstGLWindow *window;

  gst_gl_context_set_error (gl_sink->context, "Output window was closed");

  window = gst_gl_context_get_window (gl_sink->context);

  g_signal_handler_disconnect (window, gl_sink->key_sig_id);
  g_signal_handler_disconnect (window, gl_sink->mouse_sig_id);

  g_atomic_int_set (&gl_sink->to_quit, 1);

  gst_object_unref (window);
}
void
gst_gl_effects_xray_step_five (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "xray4");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "xray4", shader);
  }

  if (!gst_gl_shader_compile_and_check (shader,
          multiply_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_context_set_error (context, "Failed to initialize multiply shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return;
  }

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE2);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, effects->midtexture[2]);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1i (shader, "base", 2);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1f (shader, "alpha", (gfloat) 0.5f);
  gst_gl_shader_set_uniform_1i (shader, "blend", 1);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static void
gst_gl_effects_xray_step_two (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "xray1");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "xray1", shader);
  }

  if (!kernel_ready) {
    fill_gaussian_kernel (gauss_kernel, 7, 1.5);
    kernel_ready = TRUE;
  }

  if (!gst_gl_shader_compile_and_check (shader,
          hconv7_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_context_set_error (context, "Failed to initialize hconv7 shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return;
  }

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1i (shader, "tex", 1);
  gst_gl_shader_set_uniform_1fv (shader, "kernel", 9, gauss_kernel);
  gst_gl_shader_set_uniform_1f (shader, "width", width);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static gboolean
_2d_texture_renderer_init (GstAmc2DTextureRenderer * renderer)
{
  GstGLFuncs *gl;
  gboolean res;

  gl = renderer->context->gl_vtable;

  if (renderer->initialized)
    return TRUE;

  if (!gl->CreateProgramObject && !gl->CreateProgram) {
    gst_gl_context_set_error (renderer->context,
        "Cannot perform conversion without OpenGL shaders");
    return FALSE;
  }

  _gen_oes_texture (renderer->context, &renderer->oes_tex_id);

  res =
      gst_gl_context_gen_shader (renderer->context, vert_COPY_OES,
      frag_COPY_OES, &renderer->shader);
  if (!res)
    return FALSE;

  renderer->shader_attr_position_loc =
      gst_gl_shader_get_attribute_location (renderer->shader, "a_position");
  renderer->shader_attr_texture_loc =
      gst_gl_shader_get_attribute_location (renderer->shader, "a_texcoord");

  gst_gl_shader_use (renderer->shader);

  gst_gl_shader_set_uniform_1i (renderer->shader, "u_tex", 0);

  gst_gl_context_clear_shader (renderer->context);

  if (!_2d_texture_renderer_init_fbo (renderer))
    return FALSE;

  gl->BindTexture (GL_TEXTURE_2D, 0);

  renderer->initialized = TRUE;

  return TRUE;
}
示例#10
0
static gboolean
gst_gl_colorscale_gen_gl_resources (GstGLFilter * filter)
{
  GstGLColorscale *colorscale = GST_GL_COLORSCALE (filter);

  if (gst_gl_context_get_gl_api (filter->context) & GST_GL_API_GLES2) {
    gst_gl_context_thread_add (filter->context,
        (GstGLContextThreadFunc) _compile_identity_shader, colorscale);

    if (!colorscale->shader) {
      gst_gl_context_set_error (filter->context,
          "Failed to initialize identity shader");
      GST_ELEMENT_ERROR (colorscale, RESOURCE, NOT_FOUND, ("%s",
              gst_gl_context_get_error ()), (NULL));
      return FALSE;
    }
  }

  return TRUE;
}
示例#11
0
static void
gst_gl_effects_xray_sobel_length (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "xray_sob_len");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, (gchar *) "xray_sob_len",
        shader);
  }

  if (!gst_gl_shader_compile_and_check (shader,
          sep_sobel_length_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_context_set_error (context,
        "Failed to initialize seobel length shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return;
  }

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);
  gl->Disable (GL_TEXTURE_2D);

  gst_gl_shader_set_uniform_1i (shader, "tex", 1);
  gst_gl_shader_set_uniform_1i (shader, "invert", TRUE);
  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static void
gst_gl_effects_square_callback (gint width, gint height, guint texture,
    gpointer data)
{
  GstGLShader *shader;
  GstGLEffects *effects = GST_GL_EFFECTS (data);
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "square0");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "square0", shader);
  }

  if (!gst_gl_shader_compile_and_check (shader,
          square_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_context_set_error (context, "Failed to initialize square shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return;
  }

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_shader_use (shader);

  gl->ActiveTexture (GL_TEXTURE0);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (shader, "tex", 0);

  gst_gl_shader_set_uniform_1f (shader, "width", (gfloat) width / 2.0f);
  gst_gl_shader_set_uniform_1f (shader, "height", (gfloat) height / 2.0f);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
/* Called in the gl thread */
static gboolean
_init_upload (GstGLUpload * upload)
{
    GstGLFuncs *gl;
    GstVideoFormat v_format;
    GstVideoInfo out_info;

    gl = upload->context->gl_vtable;

    v_format = GST_VIDEO_INFO_FORMAT (&upload->in_info);

    GST_INFO ("Initializing texture upload for format:%s",
              gst_video_format_to_string (v_format));

    if (!gl->CreateProgramObject && !gl->CreateProgram) {
        gst_gl_context_set_error (upload->context,
                                  "Cannot upload YUV formats without OpenGL shaders");
        goto error;
    }

    gst_video_info_set_format (&out_info, GST_VIDEO_FORMAT_RGBA,
                               GST_VIDEO_INFO_WIDTH (&upload->in_info),
                               GST_VIDEO_INFO_HEIGHT (&upload->in_info));

    gst_gl_color_convert_set_format (upload->convert, &upload->in_info,
                                     &out_info);

    upload->out_tex = gst_gl_memory_wrapped_texture (upload->context, 0,
                      GST_VIDEO_GL_TEXTURE_TYPE_RGBA, GST_VIDEO_INFO_WIDTH (&upload->in_info),
                      GST_VIDEO_INFO_HEIGHT (&upload->in_info), NULL, NULL);

    upload->initted = TRUE;

    return TRUE;

error:
    return FALSE;
}
/* Called by the idle function in the gl thread */
void
_do_convert (GstGLContext * context, GstGLColorConvert * convert)
{
  guint in_width, in_height, out_width, out_height;
  struct ConvertInfo *c_info = &convert->priv->convert_info;
  GstMapInfo out_info[GST_VIDEO_MAX_PLANES], in_info[GST_VIDEO_MAX_PLANES];
  gboolean res = TRUE;
  gint i, j = 0;

  out_width = GST_VIDEO_INFO_WIDTH (&convert->out_info);
  out_height = GST_VIDEO_INFO_HEIGHT (&convert->out_info);
  in_width = GST_VIDEO_INFO_WIDTH (&convert->in_info);
  in_height = GST_VIDEO_INFO_HEIGHT (&convert->in_info);

  convert->outbuf = NULL;

  if (!_init_convert (convert)) {
    convert->priv->result = FALSE;
    return;
  }

  convert->outbuf = gst_buffer_new ();
  if (!gst_gl_memory_setup_buffer (convert->context, &convert->out_info,
          convert->outbuf)) {
    convert->priv->result = FALSE;
    return;
  }

  gst_buffer_add_video_meta_full (convert->outbuf, 0,
      GST_VIDEO_INFO_FORMAT (&convert->out_info),
      GST_VIDEO_INFO_WIDTH (&convert->out_info),
      GST_VIDEO_INFO_HEIGHT (&convert->out_info),
      GST_VIDEO_INFO_N_PLANES (&convert->out_info),
      convert->out_info.offset, convert->out_info.stride);

  for (i = 0; i < c_info->in_n_textures; i++) {
    convert->priv->in_tex[i] =
        (GstGLMemory *) gst_buffer_peek_memory (convert->inbuf, i);
    if (!gst_is_gl_memory ((GstMemory *) convert->priv->in_tex[i])) {
      GST_ERROR_OBJECT (convert, "input must be GstGLMemory");
      res = FALSE;
      goto out;
    }
    if (!gst_memory_map ((GstMemory *) convert->priv->in_tex[i], &in_info[i],
            GST_MAP_READ | GST_MAP_GL)) {
      GST_ERROR_OBJECT (convert, "failed to map input memory %p",
          convert->priv->in_tex[i]);
      res = FALSE;
      goto out;
    }
  }

  for (j = 0; j < c_info->out_n_textures; j++) {
    GstGLMemory *out_tex =
        (GstGLMemory *) gst_buffer_peek_memory (convert->outbuf, j);
    gint mem_width, mem_height;

    if (!gst_is_gl_memory ((GstMemory *) out_tex)) {
      GST_ERROR_OBJECT (convert, "output must be GstGLMemory");
      res = FALSE;
      goto out;
    }

    mem_width = gst_gl_memory_get_texture_width (out_tex);
    mem_height = gst_gl_memory_get_texture_height (out_tex);

    if (out_tex->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
        || out_tex->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA
        || out_width != mem_width || out_height != mem_height) {
      /* Luminance formats are not color renderable */
      /* renderering to a framebuffer only renders the intersection of all
       * the attachments i.e. the smallest attachment size */
      GstVideoInfo temp_info;

      gst_video_info_set_format (&temp_info, GST_VIDEO_FORMAT_RGBA, out_width,
          out_height);

      if (!convert->priv->out_tex[j])
        convert->priv->out_tex[j] =
            (GstGLMemory *) gst_gl_memory_alloc (context, &temp_info, 0);
    } else {
      convert->priv->out_tex[j] = out_tex;
    }

    if (!gst_memory_map ((GstMemory *) convert->priv->out_tex[j], &out_info[j],
            GST_MAP_WRITE | GST_MAP_GL)) {
      GST_ERROR_OBJECT (convert, "failed to map output memory %p",
          convert->priv->out_tex[i]);
      res = FALSE;
      goto out;
    }
  }

  GST_LOG_OBJECT (convert, "converting to textures:%p,%p,%p,%p "
      "dimensions:%ux%u, from textures:%p,%p,%p,%p dimensions:%ux%u",
      convert->priv->out_tex[0], convert->priv->out_tex[1],
      convert->priv->out_tex[2], convert->priv->out_tex[3], out_width,
      out_height, convert->priv->in_tex[0], convert->priv->in_tex[1],
      convert->priv->in_tex[2], convert->priv->in_tex[3], in_width, in_height);

  if (!_do_convert_draw (context, convert))
    res = FALSE;

out:
  for (j--; j >= 0; j--) {
    GstGLMemory *out_tex =
        (GstGLMemory *) gst_buffer_peek_memory (convert->outbuf, j);
    gint mem_width, mem_height;

    gst_memory_unmap ((GstMemory *) convert->priv->out_tex[j], &out_info[j]);

    mem_width = gst_gl_memory_get_texture_width (out_tex);
    mem_height = gst_gl_memory_get_texture_height (out_tex);

    if (out_tex->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE
        || out_tex->tex_type == GST_VIDEO_GL_TEXTURE_TYPE_LUMINANCE_ALPHA
        || out_width != mem_width || out_height != mem_height) {
      GstMapInfo to_info, from_info;

      if (!gst_memory_map ((GstMemory *) convert->priv->out_tex[j], &from_info,
              GST_MAP_READ | GST_MAP_GL)) {
        gst_gl_context_set_error (convert->context, "Failed to map "
            "intermediate memory");
        res = FALSE;
        continue;
      }
      if (!gst_memory_map ((GstMemory *) out_tex, &to_info,
              GST_MAP_WRITE | GST_MAP_GL)) {
        gst_gl_context_set_error (convert->context, "Failed to map "
            "intermediate memory");
        res = FALSE;
        continue;
      }
      gst_gl_memory_copy_into_texture (convert->priv->out_tex[j],
          out_tex->tex_id, out_tex->tex_type, mem_width, mem_height,
          GST_VIDEO_INFO_PLANE_STRIDE (&out_tex->info, out_tex->plane), FALSE);
      gst_memory_unmap ((GstMemory *) convert->priv->out_tex[j], &from_info);
      gst_memory_unmap ((GstMemory *) out_tex, &to_info);
    } else {
      convert->priv->out_tex[j] = NULL;
    }
  }

  /* YV12 the same as I420 except planes 1+2 swapped */
  if (GST_VIDEO_INFO_FORMAT (&convert->out_info) == GST_VIDEO_FORMAT_YV12) {
    GstMemory *mem1 = gst_buffer_get_memory (convert->outbuf, 1);
    GstMemory *mem2 = gst_buffer_get_memory (convert->outbuf, 2);

    gst_buffer_replace_memory (convert->outbuf, 1, mem2);
    gst_buffer_replace_memory (convert->outbuf, 2, mem1);
  }

  for (i--; i >= 0; i--) {
    gst_memory_unmap ((GstMemory *) convert->priv->in_tex[i], &in_info[i]);
  }

  if (!res) {
    gst_buffer_unref (convert->outbuf);
    convert->outbuf = NULL;
  }

  convert->priv->result = res;
  return;
}
void
gst_gl_effects_luma_to_curve (GstGLEffects * effects,
    GstGLEffectsCurve curve,
    gint curve_index, gint width, gint height, GLuint texture)
{
  GstGLShader *shader;
  GstGLFilter *filter = GST_GL_FILTER (effects);
  GstGLContext *context = filter->context;
  GstGLFuncs *gl = context->gl_vtable;

  shader = g_hash_table_lookup (effects->shaderstable, "lumamap0");

  if (!shader) {
    shader = gst_gl_shader_new (context);
    g_hash_table_insert (effects->shaderstable, "lumamap0", shader);
  }

  if (!gst_gl_shader_compile_and_check (shader,
          luma_to_curve_fragment_source, GST_GL_SHADER_FRAGMENT_SOURCE)) {
    gst_gl_context_set_error (context,
        "Failed to initialize luma to curve shader");
    GST_ELEMENT_ERROR (effects, RESOURCE, NOT_FOUND,
        ("%s", gst_gl_context_get_error ()), (NULL));
    return;
  }

  gl->MatrixMode (GL_PROJECTION);
  gl->LoadIdentity ();

  gst_gl_shader_use (shader);

  if (effects->curve[curve_index] == 0) {
    /* this parameters are needed to have a right, predictable, mapping */
    gl->GenTextures (1, &effects->curve[curve_index]);
    gl->Enable (GL_TEXTURE_1D);
    gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);
    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S, GL_CLAMP);
    gl->TexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_T, GL_CLAMP);

    gl->TexImage1D (GL_TEXTURE_1D, 0, curve.bytes_per_pixel,
        curve.width, 0, GL_RGB, GL_UNSIGNED_BYTE, curve.pixel_data);

    gl->Disable (GL_TEXTURE_1D);
  }

  gl->ActiveTexture (GL_TEXTURE2);
  gl->Enable (GL_TEXTURE_2D);
  gl->BindTexture (GL_TEXTURE_2D, texture);

  gst_gl_shader_set_uniform_1i (shader, "tex", 2);

  gl->Disable (GL_TEXTURE_2D);

  gl->ActiveTexture (GL_TEXTURE1);
  gl->Enable (GL_TEXTURE_1D);
  gl->BindTexture (GL_TEXTURE_1D, effects->curve[curve_index]);

  gst_gl_shader_set_uniform_1i (shader, "curve", 1);

  gl->Disable (GL_TEXTURE_1D);

  gst_gl_filter_draw_texture (filter, texture, width, height);
}
static gboolean
_2d_texture_renderer_init_fbo (GstAmc2DTextureRenderer * renderer)
{
  GstGLFuncs *gl;
  GLuint fake_texture = 0;
  guint out_width, out_height;

  out_width = GST_VIDEO_INFO_WIDTH (&renderer->info);
  out_height = GST_VIDEO_INFO_HEIGHT (&renderer->info);

  gl = renderer->context->gl_vtable;

  if (!gl->GenFramebuffers) {
    /* turn off the pipeline because Frame buffer object is a not present */
    gst_gl_context_set_error (renderer->context,
        "Context, EXT_framebuffer_object supported: no");
    return FALSE;
  }

  GST_INFO ("Context, EXT_framebuffer_object supported: yes");

  /* setup FBO */
  gl->GenFramebuffers (1, &renderer->fbo);
  gl->BindFramebuffer (GL_FRAMEBUFFER, renderer->fbo);

  /* setup the render buffer for depth */
  gl->GenRenderbuffers (1, &renderer->depth_buffer);
  gl->BindRenderbuffer (GL_RENDERBUFFER, renderer->depth_buffer);
  gl->RenderbufferStorage (GL_RENDERBUFFER, GL_DEPTH_COMPONENT16,
      out_width, out_height);

  /* a fake texture is attached to the render FBO (cannot init without it) */
  gl->GenTextures (1, &fake_texture);
  gl->BindTexture (GL_TEXTURE_2D, fake_texture);
  gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA8, out_width, out_height,
      0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  /* attach the texture to the FBO to renderer to */
  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
      GL_TEXTURE_2D, fake_texture, 0);

  /* attach the depth render buffer to the FBO */
  gl->FramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
      GL_RENDERBUFFER, renderer->depth_buffer);

  if (!gst_gl_context_check_framebuffer_status (renderer->context)) {
    gst_gl_context_set_error (renderer->context,
        "GL framebuffer status incomplete");
    return FALSE;
  }

  /* unbind the FBO */
  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);
  gl->DeleteTextures (1, &fake_texture);

  return TRUE;
}
示例#17
0
//Called in the gl thread
static void
gst_gl_bumper_init_resources (GstGLFilter * filter)
{
  GstGLBumper *bumper = GST_GL_BUMPER (filter);
  GstGLContext *context = filter->context;
  const GstGLFuncs *gl = context->gl_vtable;

  png_structp png_ptr;
  png_infop info_ptr;
  png_uint_32 width = 0;
  png_uint_32 height = 0;
  gint bit_depth = 0;
  gint color_type = 0;
  gint interlace_type = 0;
  png_FILE_p fp = NULL;
  guint y = 0;
  guchar *raw_data = NULL;
  guchar **rows = NULL;
  png_byte magic[8];
  gint n_read;

  if (!bumper->location) {
    gst_gl_context_set_error (context, "A filename is required");
    return;
  }

  /* BEGIN load png image file */

  if ((fp = fopen (bumper->location, "rb")) == NULL)
    LOAD_ERROR (context, "file not found");

  /* Read magic number */
  n_read = fread (magic, 1, sizeof (magic), fp);
  if (n_read != sizeof (magic)) {
    fclose (fp);
    LOAD_ERROR (context, "can't read PNG magic number");
  }

  /* Check for valid magic number */
  if (png_sig_cmp (magic, 0, sizeof (magic))) {
    fclose (fp);
    LOAD_ERROR (context, "not a valid PNG image");
  }

  png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);

  if (png_ptr == NULL) {
    fclose (fp);
    LOAD_ERROR (context, "failed to initialize the png_struct");
  }

  png_set_error_fn (png_ptr, NULL, NULL, user_warning_fn);

  info_ptr = png_create_info_struct (png_ptr);
  if (info_ptr == NULL) {
    fclose (fp);
    png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
    LOAD_ERROR (context,
        "failed to initialize the memory for image information");
  }

  png_init_io (png_ptr, fp);

  png_set_sig_bytes (png_ptr, sizeof (magic));

  png_read_info (png_ptr, info_ptr);

  png_get_IHDR (png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,
      &interlace_type, int_p_NULL, int_p_NULL);

  if (color_type != PNG_COLOR_TYPE_RGB) {
    fclose (fp);
    png_destroy_read_struct (&png_ptr, png_infopp_NULL, png_infopp_NULL);
    LOAD_ERROR (context, "color type is not rgb");
  }

  raw_data = (guchar *) malloc (sizeof (guchar) * width * height * 3);

  rows = (guchar **) malloc (sizeof (guchar *) * height);

  for (y = 0; y < height; ++y)
    rows[y] = (guchar *) (raw_data + y * width * 3);

  png_read_image (png_ptr, rows);

  free (rows);

  png_read_end (png_ptr, info_ptr);
  png_destroy_read_struct (&png_ptr, &info_ptr, png_infopp_NULL);
  fclose (fp);

  /* END load png image file */

  bumper->bumpmap_width = width;
  bumper->bumpmap_height = height;

  gl->GenTextures (1, &bumper->bumpmap);
  gl->BindTexture (GL_TEXTURE_2D, bumper->bumpmap);
  gl->TexImage2D (GL_TEXTURE_2D, 0, GL_RGBA,
      bumper->bumpmap_width, bumper->bumpmap_height, 0,
      GL_RGB, GL_UNSIGNED_BYTE, raw_data);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
  gl->TexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

  free (raw_data);
}
/* 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;
  }
}
示例#19
0
static void
_gl_mem_copy_thread (GstGLContext * context, gpointer data)
{
  const GstGLFuncs *gl;
  GstGLMemoryPBOCopyParams *copy_params;
  GstGLMemoryPBO *src;
  guint tex_id;
  guint out_tex_target;
  GLuint fboId;
  gsize out_width, out_height, out_stride;
  GLuint out_gl_format, out_gl_type;
  GLuint in_gl_format, in_gl_type;
  gsize in_size, out_size;

  copy_params = (GstGLMemoryPBOCopyParams *) data;
  src = copy_params->src;
  tex_id = copy_params->tex_id;
  out_tex_target = gst_gl_texture_target_to_gl (copy_params->tex_target);
  out_width = copy_params->out_width;
  out_height = copy_params->out_height;
  out_stride = copy_params->out_stride;

  gl = context->gl_vtable;
  out_gl_format = gst_gl_format_from_gl_texture_type (copy_params->out_format);
  out_gl_type = GL_UNSIGNED_BYTE;
  if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
    out_gl_type = GL_UNSIGNED_SHORT_5_6_5;
  in_gl_format = gst_gl_format_from_gl_texture_type (src->mem.tex_type);
  in_gl_type = GL_UNSIGNED_BYTE;
  if (src->mem.tex_type == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
    in_gl_type = GL_UNSIGNED_SHORT_5_6_5;

  if (!gl->GenFramebuffers) {
    gst_gl_context_set_error (context,
        "Context, EXT_framebuffer_object not supported");
    goto error;
  }

  in_size = GL_MEM_HEIGHT (src) * GL_MEM_STRIDE (src);
  out_size = out_height * out_stride;

  if (copy_params->respecify) {
    if (in_size != out_size) {
      GST_ERROR ("Cannot copy between textures with backing data of different"
          "sizes. input %" G_GSIZE_FORMAT " output %" G_GSIZE_FORMAT, in_size,
          out_size);
      goto error;
    }
  }

  if (!tex_id) {
    guint internal_format;
    guint out_gl_type;

    out_gl_type = GL_UNSIGNED_BYTE;
    if (copy_params->out_format == GST_VIDEO_GL_TEXTURE_TYPE_RGB16)
      out_gl_type = GL_UNSIGNED_SHORT_5_6_5;

    internal_format =
        gst_gl_sized_gl_format_from_gl_format_type (context, out_gl_format,
        out_gl_type);

    tex_id =
        _new_texture (context, out_tex_target,
        internal_format, out_gl_format, out_gl_type, copy_params->out_width,
        copy_params->out_height);
  }

  if (!tex_id) {
    GST_WARNING ("Could not create GL texture with context:%p", context);
  }

  GST_LOG ("copying memory %p, tex %u into texture %i",
      src, src->mem.tex_id, tex_id);

  /* FIXME: try and avoid creating and destroying fbo's every copy... */
  /* create a framebuffer object */
  gl->GenFramebuffers (1, &fboId);
  gl->BindFramebuffer (GL_FRAMEBUFFER, fboId);

  gl->FramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
      gst_gl_texture_target_to_gl (src->mem.tex_target), src->mem.tex_id, 0);

//  if (!gst_gl_context_check_framebuffer_status (src->mem.mem.context))
//    goto fbo_error;

  gl->BindTexture (out_tex_target, tex_id);
  if (copy_params->respecify) {
    GstMapInfo pbo_info;

    if (!gl->GenBuffers || !src->pbo) {
      gst_gl_context_set_error (context, "Cannot reinterpret texture contents "
          "without pixel buffer objects");
      gl->BindTexture (out_tex_target, 0);
      goto fbo_error;
    }

    if (gst_gl_context_get_gl_api (context) & GST_GL_API_GLES2
        && (in_gl_format != GL_RGBA || in_gl_type != GL_UNSIGNED_BYTE)) {
      gst_gl_context_set_error (context, "Cannot copy non RGBA/UNSIGNED_BYTE "
          "textures on GLES2");
      gl->BindTexture (out_tex_target, 0);
      goto fbo_error;
    }

    GST_TRACE ("copying texture data with size of %u*%u*%u",
        gst_gl_format_type_n_bytes (in_gl_format, in_gl_type),
        src->mem.tex_width, GL_MEM_HEIGHT (src));

    /* copy tex */
    _read_pixels_to_pbo (src);

    src->pbo->target = GL_PIXEL_UNPACK_BUFFER;
    if (!gst_memory_map (GST_MEMORY_CAST (src->pbo), &pbo_info,
            GST_MAP_READ | GST_MAP_GL)) {
      GST_CAT_ERROR (GST_CAT_GL_MEMORY, "Failed to map pbo for reading");
      goto fbo_error;
    }
    gl->TexSubImage2D (out_tex_target, 0, 0, 0, out_width, out_height,
        out_gl_format, out_gl_type, 0);
    gst_memory_unmap (GST_MEMORY_CAST (src->pbo), &pbo_info);
  } else {                      /* different sizes */
    gst_gl_memory_copy_teximage (GST_GL_MEMORY_CAST (src),
        tex_id, copy_params->tex_target, copy_params->out_format, out_width,
        out_height);
  }

  gl->BindTexture (out_tex_target, 0);
  gl->BindFramebuffer (GL_FRAMEBUFFER, 0);

  gl->DeleteFramebuffers (1, &fboId);

  copy_params->tex_id = tex_id;
  copy_params->result = TRUE;

  return;

/* ERRORS */
fbo_error:
  {
    gl->DeleteFramebuffers (1, &fboId);

    copy_params->tex_id = 0;
    copy_params->result = FALSE;
    return;
  }

error:
  {
    copy_params->result = FALSE;
    return;
  }
}