rotrevrep

GStreamer video sink with Gtk

Feb 9th, 2017
432
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Vala 3.68 KB | None | 0 0
  1. public abstract class ValaAbstractVideoSink : Gst.Video.Sink {
  2.     Gst.Video.Info* info;
  3.    
  4.     ~ValaAbstractVideoSink() {
  5.         Gst.Video.Info.free (info);
  6.     }
  7.    
  8.     construct {
  9.         info = Gst.Video.Info.new();
  10.         info->init();
  11.     }
  12.    
  13.     public override bool set_caps (Gst.Caps caps) {
  14.         if (info->from_caps (caps))
  15.             set_video_size (info->width, info->height);
  16.         return true;
  17.     }
  18.    
  19.     public override Gst.FlowReturn show_frame (Gst.Buffer buffer) {
  20.         Gst.Video.Frame frame;
  21.         if (Gst.Video.Frame.map (out frame, info, buffer, Gst.MapFlags.READ)) {
  22.             last_surface = new Cairo.ImageSurface.for_data (
  23.                 (uchar[])frame.data[0],
  24.                 Cairo.Format.ARGB32,
  25.                 info->width,
  26.                 info->height,
  27.                 frame.info.stride[0]);
  28.             show_surface (last_surface);
  29.         }
  30.         return Gst.FlowReturn.OK;
  31.     }
  32.    
  33.     public Cairo.Surface last_surface { get; private set; }
  34.    
  35.     public abstract void set_video_size (int width, int height);
  36.     public abstract void show_surface (Cairo.Surface surface);
  37. }
  38.  
  39. public class ValaVideoSink : ValaAbstractVideoSink {
  40.     class construct {
  41.         string format = "{ xRGB, ARGB }";
  42.         if (ByteOrder.HOST == ByteOrder.LITTLE_ENDIAN)
  43.             format = "{ BGRx, BGRA }";
  44.         string caps_str = "video/x-raw, format = (string) %s, width = (int) [ 1, max ], height = (int) [ 1, max ], framerate = (fraction) [ 0, max ]".printf (format);
  45.         Gst.StaticCaps caps = { null, caps_str };
  46.         Gst.StaticPadTemplate sink_template = {
  47.             "sink",
  48.             Gst.PadDirection.SINK,
  49.             Gst.PadPresence.ALWAYS,
  50.             caps
  51.         };
  52.         add_pad_template (sink_template.get());
  53.     }
  54.    
  55.     construct {
  56.         widget = new ValaWidget();
  57.     }
  58.    
  59.     public override void set_video_size (int width, int height) {
  60.         if (widget.video_height == 0)
  61.             widget.set_video_size (width, height);
  62.     }
  63.    
  64.     public override void show_surface (Cairo.Surface surface) {
  65.         if (widget.get_realized())
  66.             widget.queue_surface (surface);
  67.     }
  68.    
  69.     public ValaWidget widget { get; private set; }
  70. }
  71.  
  72. public class ValaWidget : Gtk.DrawingArea {
  73.     Cairo.Surface surface;
  74.    
  75.     public override bool draw (Cairo.Context context) {
  76.         if (surface == null)
  77.             return false;
  78.         Gst.Video.Rectangle src = {
  79.             0,
  80.             0,
  81.             video_width,
  82.             video_height
  83.         };
  84.         Gst.Video.Rectangle dst = {
  85.             0,
  86.             0,
  87.             get_allocated_width(),
  88.             get_allocated_height()
  89.         };
  90.         Gst.Video.Rectangle result;
  91.         Gst.Video.center_rectangle (src, dst, out result);
  92.         double dx = (double)get_allocated_width() / video_width;
  93.         double dy = (double)get_allocated_height() / video_height;
  94.         dx = double.min (dx, dy);
  95.         dy = dx;
  96.         context.translate ((double)result.x, (double)result.y);
  97.         context.scale (dx, dy);
  98.         context.rectangle (0, 0, (double)result.w, (double)result.h);
  99.         context.set_source_surface (surface, 0, 0);
  100.         context.paint();
  101.         return false;
  102.     }
  103.    
  104.     public int video_height { get; private set; }
  105.     public int video_width { get; private set; }
  106.    
  107.     internal void set_video_size (int width, int height) {
  108.         video_height = height;
  109.         video_width = width;
  110.     }
  111.    
  112.     public void queue_surface (Cairo.Surface surf) {
  113.         surface = surf;
  114.         Idle.add_full (Priority.DEFAULT, () => {
  115.             queue_draw();
  116.             return Source.REMOVE;
  117.         });
  118.     }
  119. }
  120.  
  121. public static void main (string[] args) {
  122.     Gst.init (ref args);
  123.     Gtk.init (ref args);
  124.     int index = 0;
  125.     var bin = Gst.ElementFactory.make ("playbin", "bin");
  126.     var sink = new ValaVideoSink();
  127.     bin["video-sink"] = sink;
  128.    
  129.     var window = new Gtk.Window();
  130.     var bar = new Gtk.HeaderBar();
  131.     bar.title = "test";
  132.     bar.show_close_button = true;
  133.     window.set_titlebar (bar);
  134.     window.add (sink.widget);
  135.     sink.widget.realize.connect (() => {
  136.         bin["uri"] = "http://www.w3schools.com/html/mov_bbb.mp4";
  137.         bin.set_state (Gst.State.PLAYING);
  138.     });
  139.     window.show_all();
  140.     Gtk.main();
  141. }
Add Comment
Please, Sign In to add comment