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; }
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; }