Exemplo n.º 1
0
static GstFlowReturn
gst_glimage_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
  GstGLImageSink *glimage_sink = NULL;
  GstGLBuffer *gl_buffer = NULL;

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  GST_INFO ("buffer size: %d", GST_BUFFER_SIZE (buf));

  //is gl
  if (glimage_sink->is_gl) {
    //increment gl buffer ref before storage
    gl_buffer = GST_GL_BUFFER (gst_buffer_ref (buf));

    //if glimagesink has not the display yet
    if (glimage_sink->display == NULL) {
      glimage_sink->display = g_object_ref (gl_buffer->display);

      gst_gl_display_set_client_reshape_callback (glimage_sink->display,
          glimage_sink->clientReshapeCallback);

      gst_gl_display_set_client_draw_callback (glimage_sink->display,
          glimage_sink->clientDrawCallback);
    }
  }
  //is not gl
  else {
    //if glimagesink has not the display yet
    if (glimage_sink->display == NULL) {
      //create a display
      glimage_sink->display = gst_gl_display_new ();

      //init opengl context
      gst_gl_display_create_context (glimage_sink->display,
          glimage_sink->width, glimage_sink->height, 0);

      //init colorspace conversion if needed
      gst_gl_display_init_upload (glimage_sink->display, glimage_sink->format,
          glimage_sink->width, glimage_sink->height,
          glimage_sink->width, glimage_sink->height);

      gst_gl_display_set_client_reshape_callback (glimage_sink->display,
          glimage_sink->clientReshapeCallback);

      gst_gl_display_set_client_draw_callback (glimage_sink->display,
          glimage_sink->clientDrawCallback);
    }
    //blocking call
    gl_buffer = gst_gl_buffer_new (glimage_sink->display,
        glimage_sink->width, glimage_sink->height);

    //blocking call
    gst_gl_display_do_upload (glimage_sink->display, gl_buffer->texture,
        glimage_sink->width, glimage_sink->height, GST_BUFFER_DATA (buf));

    //gl_buffer is created in this block, so the gl buffer is already referenced
  }

  if (glimage_sink->window_id != glimage_sink->new_window_id) {
    glimage_sink->window_id = glimage_sink->new_window_id;
    gst_gl_display_set_window_id (glimage_sink->display,
        glimage_sink->window_id);
  }

  //the buffer is cleared when an other comes in
  if (glimage_sink->stored_buffer) {
    gst_buffer_unref (GST_BUFFER_CAST (glimage_sink->stored_buffer));
    glimage_sink->stored_buffer = NULL;
  }
  //store current buffer
  glimage_sink->stored_buffer = gl_buffer;

  //redisplay opengl scene
  if (gl_buffer->texture &&
      gst_gl_display_redisplay (glimage_sink->display,
          gl_buffer->texture, gl_buffer->width, gl_buffer->height, 
          glimage_sink->keep_aspect_ratio))
    return GST_FLOW_OK;
  else
    return GST_FLOW_UNEXPECTED;
}
Exemplo n.º 2
0
static gboolean
gst_glimage_sink_set_caps (GstBaseSink * bsink, GstCaps * caps)
{
  GstGLImageSink *glimage_sink;
  gint width;
  gint height;
  gboolean ok;
  gint fps_n, fps_d;
  gint par_n, par_d;
  gint display_par_n, display_par_d;
  guint display_ratio_num, display_ratio_den;
  GstVideoFormat format;
  GstStructure *structure;
  gboolean is_gl;

  GST_DEBUG ("set caps with %" GST_PTR_FORMAT, caps);

  glimage_sink = GST_GLIMAGE_SINK (bsink);

  structure = gst_caps_get_structure (caps, 0);
  if (gst_structure_has_name (structure, "video/x-raw-gl")) {
    is_gl = TRUE;
    format = GST_VIDEO_FORMAT_UNKNOWN;
    ok = gst_structure_get_int (structure, "width", &width);
    ok &= gst_structure_get_int (structure, "height", &height);
  } else {
    is_gl = FALSE;
    ok = gst_video_format_parse_caps (caps, &format, &width, &height);

    if (!ok)
      return FALSE;

    /* init colorspace conversion if needed */
    ok = gst_gl_display_init_upload (glimage_sink->display, format,
        width, height, width, height);

    if (!ok) {
      GST_ELEMENT_ERROR (glimage_sink, RESOURCE, NOT_FOUND,
          GST_GL_DISPLAY_ERR_MSG (glimage_sink->display), (NULL));
      return FALSE;
    }
  }

  gst_gl_display_set_client_reshape_callback (glimage_sink->display,
      glimage_sink->clientReshapeCallback);

  gst_gl_display_set_client_draw_callback (glimage_sink->display,
      glimage_sink->clientDrawCallback);

  gst_gl_display_set_client_data (glimage_sink->display,
      glimage_sink->client_data);

  ok &= gst_video_parse_caps_framerate (caps, &fps_n, &fps_d);
  ok &= gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d);

  if (!ok)
    return FALSE;

  /* get display's PAR */
  if (glimage_sink->par) {
    display_par_n = gst_value_get_fraction_numerator (glimage_sink->par);
    display_par_d = gst_value_get_fraction_denominator (glimage_sink->par);
  } else {
    display_par_n = 1;
    display_par_d = 1;
  }

  ok = gst_video_calculate_display_ratio (&display_ratio_num,
      &display_ratio_den, width, height, par_n, par_d, display_par_n,
      display_par_d);

  if (!ok)
    return FALSE;

  if (height % display_ratio_den == 0) {
    GST_DEBUG ("keeping video height");
    glimage_sink->window_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    glimage_sink->window_height = height;
  } else if (width % display_ratio_num == 0) {
    GST_DEBUG ("keeping video width");
    glimage_sink->window_width = width;
    glimage_sink->window_height = (guint)
        gst_util_uint64_scale_int (width, display_ratio_den, display_ratio_num);
  } else {
    GST_DEBUG ("approximating while keeping video height");
    glimage_sink->window_width = (guint)
        gst_util_uint64_scale_int (height, display_ratio_num,
        display_ratio_den);
    glimage_sink->window_height = height;
  }
  GST_DEBUG ("scaling to %dx%d",
      glimage_sink->window_width, glimage_sink->window_height);

  GST_VIDEO_SINK_WIDTH (glimage_sink) = width;
  GST_VIDEO_SINK_HEIGHT (glimage_sink) = height;
  glimage_sink->is_gl = is_gl;
  glimage_sink->width = width;
  glimage_sink->height = height;
  glimage_sink->fps_n = fps_n;
  glimage_sink->fps_d = fps_d;
  glimage_sink->par_n = par_n;
  glimage_sink->par_d = par_d;

  if (!glimage_sink->window_id && !glimage_sink->new_window_id)
    gst_x_overlay_prepare_xwindow_id (GST_X_OVERLAY (glimage_sink));

  return TRUE;
}