现在的位置: 首页 > 综合 > 正文

GStreamer基础教程15——继承Clutter

2018年02月23日 ⁄ 综合 ⁄ 共 4433字 ⁄ 字号 评论关闭

目标

      Clutter是一个开源的库,用来创建快速、可移植和动态的GUI。GStreamer可以通过cluttersink这个element把clutter集成进来,允许视频像纹理一样使用。本教程会展示:

      如何把GStreamer pipeline的视频输出在clutter里面作为纹理来处理


介绍

      连接GStreamer和clutter的流程实际上非常简单。我们必须使用cluttersink这个element(或者autocluttersink)并把它作为视频的sink。通过texture这个属性,这个element接受一个被GStreamer刷新的clutter的纹理。


一个3D的媒体播放器

#include <clutter-gst/clutter-gst.h>
  
/* Setup the video texture once its size is known */
void size_change (ClutterActor *texture, gint width, gint height, gpointer user_data) {
  ClutterActor *stage;
  gfloat new_x, new_y, new_width, new_height;
  gfloat stage_width, stage_height;
  ClutterAnimation *animation = NULL;
  
  stage = clutter_actor_get_stage (texture);
  if (stage == NULL)
    return;
  
  clutter_actor_get_size (stage, &stage_width, &stage_height);
  
  /* Center video on window and calculate new size preserving aspect ratio */
  new_height = (height * stage_width) / width;
  if (new_height <= stage_height) {
    new_width = stage_width;
    
    new_x = 0;
    new_y = (stage_height - new_height) / 2;
  } else {
    new_width  = (width * stage_height) / height;
    new_height = stage_height;
    
    new_x = (stage_width - new_width) / 2;
    new_y = 0;
  }
  clutter_actor_set_position (texture, new_x, new_y);
  clutter_actor_set_size (texture, new_width, new_height);
  clutter_actor_set_rotation (texture, CLUTTER_Y_AXIS, 0.0, stage_width / 2, 0, 0);
  /* Animate it */
  animation = clutter_actor_animate (texture, CLUTTER_LINEAR, 10000, "rotation-angle-y", 360.0, NULL);
  clutter_animation_set_loop (animation, TRUE);
}
  
int main(int argc, char *argv[]) {
  GstElement *pipeline, *sink;
  ClutterTimeline *timeline;
  ClutterActor *stage, *texture;
  
  /* clutter-gst takes care of initializing Clutter and GStreamer */
  if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {
    g_error ("Failed to initialize clutter\n");
    return -1;
  }
  
  stage = clutter_stage_get_default ();
  
  /* Make a timeline */
  timeline = clutter_timeline_new (1000);
  g_object_set(timeline, "loop", TRUE, NULL);
  
  /* Create new texture and disable slicing so the video is properly mapped onto it */
  texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL));
  g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL);
  
  /* Build the GStreamer pipeline */
  pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm", NULL);
  
  /* Instantiate the Clutter sink */
  sink = gst_element_factory_make ("autocluttersink", NULL);
  if (sink == NULL) {
    /* Revert to the older cluttersink, in case autocluttersink was not found */
    sink = gst_element_factory_make ("cluttersink", NULL);
  }
  if (sink == NULL) {
    g_printerr ("Unable to find a Clutter sink.\n");
    return -1;
  }
  
  /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink*/
  g_object_set (sink, "texture", texture, NULL);
  
  /* Add the Clutter sink to the pipeline */
  g_object_set (pipeline, "video-sink", sink, NULL);
  
  /* Start playing */
  gst_element_set_state (pipeline, GST_STATE_PLAYING);
  
  /* start the timeline */
  clutter_timeline_start (timeline);
  
  /* Add texture to the stage, and show it */
  clutter_group_add (CLUTTER_GROUP (stage), texture);
  clutter_actor_show_all (stage);
  
  clutter_main();
  
  /* Free resources */
  gst_element_set_state (pipeline, GST_STATE_NULL);
  gst_object_unref (pipeline);
  return 0;
}


工作流程

      这篇教程的目的不是教你如何使用clutter,而是如何把它集成到GStreamer里来。这个工作通过clutter-gst库来完成,所以它的头文件必须包含进来。

#include <clutter-gst/clutter-gst.h>

      这个库的第一件事是初始化GStreamer和Clutter,所以你调用clutter-gst-init()方法而不是自己来初始化。

  /* clutter-gst takes care of initializing Clutter and GStreamer */
  if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {
    g_error ("Failed to initialize clutter\n");
    return -1;
  }

      GStreamer视频是作为Clutter的纹理来播放,所以我们需要创建一个纹理。请记住关闭纹理的切片:

  /* Create new texture and disable slicing so the video is properly mapped onto it */
  texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL));
  g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL);

      我们注册size-change信号,这样我们一旦知道视频的尺寸之后就可以做最后的设置。

  /* Instantiate the Clutter sink */
  sink = gst_element_factory_make ("autocluttersink", NULL);
  if (sink == NULL) {
    /* Revert to the older cluttersink, in case autocluttersink was not found */
    sink = gst_element_factory_make ("cluttersink", NULL);
  }
  if (sink == NULL) {
    g_printerr ("Unable to find a Clutter sink.\n");
    return -1;
  }

      正确创建的Clutter sink element是autocluttersink,这个element工作起来或多或少的像autovideosink。然而,autocluttersink在2012.7后发布的SDK里面才有,如果找不到这个element,那么创建cluttersink来代替。

  /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink*/
  g_object_set (sink, "texture", texture, NULL);

      这个纹理是GStreamer唯一需要了解的关于Clutter的内容。

  /* Add the Clutter sink to the pipeline */
  g_object_set (pipeline, "video-sink", sink, NULL);

      最后,告诉playbin2使用我们创建的sink而不是默认的。

      然后GStreamer的pipeline和Clutter的timeline就开始工作了。一旦pipeline获得了视频的尺寸,我们在收到一个通知后更新Clutter的纹理,调用size_change的回调。这个方法会把纹理设置正确地尺寸,把它输出到窗口的中心然后开始做动画旋转(仅供演示使用),当然,这个和GStreamer就没有任何关系了。

抱歉!评论已关闭.