• 【GStreamer开发】GStreamer基础教程15——继承Clutter


    目标

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

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


    介绍

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


    一个3D的媒体播放器

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:14px;">#include <clutter-gst/clutter-gst.h>  
    2.     
    3. /* Setup the video texture once its size is known */  
    4. void size_change (ClutterActor *texture, gint width, gint height, gpointer user_data) {  
    5.   ClutterActor *stage;  
    6.   gfloat new_x, new_y, new_width, new_height;  
    7.   gfloat stage_width, stage_height;  
    8.   ClutterAnimation *animation = NULL;  
    9.     
    10.   stage = clutter_actor_get_stage (texture);  
    11.   if (stage == NULL)  
    12.     return;  
    13.     
    14.   clutter_actor_get_size (stage, &stage_width, &stage_height);  
    15.     
    16.   /* Center video on window and calculate new size preserving aspect ratio */  
    17.   new_height = (height * stage_width) / width;  
    18.   if (new_height <= stage_height) {  
    19.     new_width = stage_width;  
    20.       
    21.     new_x = 0;  
    22.     new_y = (stage_height - new_height) / 2;  
    23.   } else {  
    24.     new_width  = (width * stage_height) / height;  
    25.     new_height = stage_height;  
    26.       
    27.     new_x = (stage_width - new_width) / 2;  
    28.     new_y = 0;  
    29.   }  
    30.   clutter_actor_set_position (texture, new_x, new_y);  
    31.   clutter_actor_set_size (texture, new_width, new_height);  
    32.   clutter_actor_set_rotation (texture, CLUTTER_Y_AXIS, 0.0, stage_width / 200);  
    33.   /* Animate it */  
    34.   animation = clutter_actor_animate (texture, CLUTTER_LINEAR, 10000"rotation-angle-y"360.0NULL);  
    35.   clutter_animation_set_loop (animation, TRUE);  
    36. }  
    37.     
    38. int main(int argc, charchar *argv[]) {  
    39.   GstElement *pipeline, *sink;  
    40.   ClutterTimeline *timeline;  
    41.   ClutterActor *stage, *texture;  
    42.     
    43.   /* clutter-gst takes care of initializing Clutter and GStreamer */  
    44.   if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {  
    45.     g_error ("Failed to initialize clutter ");  
    46.     return -1;  
    47.   }  
    48.     
    49.   stage = clutter_stage_get_default ();  
    50.     
    51.   /* Make a timeline */  
    52.   timeline = clutter_timeline_new (1000);  
    53.   g_object_set(timeline, "loop", TRUE, NULL);  
    54.     
    55.   /* Create new texture and disable slicing so the video is properly mapped onto it */  
    56.   texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL));  
    57.   g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL);  
    58.     
    59.   /* Build the GStreamer pipeline */  
    60.   pipeline = gst_parse_launch ("playbin2 uri=http://docs.gstreamer.com/media/sintel_trailer-480p.webm"NULL);  
    61.     
    62.   /* Instantiate the Clutter sink */  
    63.   sink = gst_element_factory_make ("autocluttersink"NULL);  
    64.   if (sink == NULL) {  
    65.     /* Revert to the older cluttersink, in case autocluttersink was not found */  
    66.     sink = gst_element_factory_make ("cluttersink"NULL);  
    67.   }  
    68.   if (sink == NULL) {  
    69.     g_printerr ("Unable to find a Clutter sink. ");  
    70.     return -1;  
    71.   }  
    72.     
    73.   /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink*/  
    74.   g_object_set (sink, "texture", texture, NULL);  
    75.     
    76.   /* Add the Clutter sink to the pipeline */  
    77.   g_object_set (pipeline, "video-sink", sink, NULL);  
    78.     
    79.   /* Start playing */  
    80.   gst_element_set_state (pipeline, GST_STATE_PLAYING);  
    81.     
    82.   /* start the timeline */  
    83.   clutter_timeline_start (timeline);  
    84.     
    85.   /* Add texture to the stage, and show it */  
    86.   clutter_group_add (CLUTTER_GROUP (stage), texture);  
    87.   clutter_actor_show_all (stage);  
    88.     
    89.   clutter_main();  
    90.     
    91.   /* Free resources */  
    92.   gst_element_set_state (pipeline, GST_STATE_NULL);  
    93.   gst_object_unref (pipeline);  
    94.   return 0;  
    95. }  
    96. </span>  


    工作流程

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. <span style="font-size:14px;">#include <clutter-gst/clutter-gst.h></span>  

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* clutter-gst takes care of initializing Clutter and GStreamer */  
    2. if (clutter_gst_init (&argc, &argv) != CLUTTER_INIT_SUCCESS) {  
    3.   g_error ("Failed to initialize clutter ");  
    4.   return -1;  
    5. }  

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Create new texture and disable slicing so the video is properly mapped onto it */  
    2. texture = CLUTTER_ACTOR (g_object_new (CLUTTER_TYPE_TEXTURE, "disable-slicing", TRUE, NULL));  
    3. g_signal_connect (texture, "size-change", G_CALLBACK (size_change), NULL);  

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Instantiate the Clutter sink */  
    2. sink = gst_element_factory_make ("autocluttersink"NULL);  
    3. if (sink == NULL) {  
    4.   /* Revert to the older cluttersink, in case autocluttersink was not found */  
    5.   sink = gst_element_factory_make ("cluttersink"NULL);  
    6. }  
    7. if (sink == NULL) {  
    8.   g_printerr ("Unable to find a Clutter sink. ");  
    9.   return -1;  
    10. }  

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Link GStreamer with Clutter by passing the Clutter texture to the Clutter sink*/  
    2. g_object_set (sink, "texture", texture, NULL);  

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

    [objc] view plain copy
     在CODE上查看代码片派生到我的代码片
    1. /* Add the Clutter sink to the pipeline */  
    2. g_object_set (pipeline, "video-sink", sink, NULL);  

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

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

  • 相关阅读:
    vue : 无法加载文件 C:UsersxxxAppDataRoaming pmvue.ps1,因为在此系统上禁止运行脚本
    VSCode搭建简单的Vue前端项目
    Ant Design和Ant Design Pro
    React、Vue、AngularJS、Bootstrap、EasyUI 、AntDesign、Element理解
    CTF-flag在index里 80
    Web安全之XSS漏洞专题和Web安全之命令执行漏洞专题—第五天
    CTF-web4 80
    Sqli-labs-第五关详解
    Web安全之文件上传漏洞专题--第四天.
    Sqli_labs第1-4关&&sqlmap.py的初步使用
  • 原文地址:https://www.cnblogs.com/huty/p/8517303.html
Copyright © 2020-2023  润新知