Blame ext/libcaca/gstcacasink.c

Packit 1f69a5
/* GStreamer
Packit 1f69a5
 * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
Packit 1f69a5
 *
Packit 1f69a5
 * This library is free software; you can redistribute it and/or
Packit 1f69a5
 * modify it under the terms of the GNU Library General Public
Packit 1f69a5
 * License as published by the Free Software Foundation; either
Packit 1f69a5
 * version 2 of the License, or (at your option) any later version.
Packit 1f69a5
 *
Packit 1f69a5
 * This library is distributed in the hope that it will be useful,
Packit 1f69a5
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 1f69a5
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 1f69a5
 * Library General Public License for more details.
Packit 1f69a5
 *
Packit 1f69a5
 * You should have received a copy of the GNU Library General Public
Packit 1f69a5
 * License along with this library; if not, write to the
Packit 1f69a5
 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
Packit 1f69a5
 * Boston, MA 02110-1301, USA.
Packit 1f69a5
 */
Packit 1f69a5
/**
Packit 1f69a5
 * SECTION:element-cacasink
Packit 1f69a5
 * @see_also: #GstAASink
Packit 1f69a5
 *
Packit 1f69a5
 * Displays video as color ascii art.
Packit 1f69a5
 *
Packit 1f69a5
 * <refsect2>
Packit 1f69a5
 * <title>Example launch line</title>
Packit 1f69a5
 * |[
Packit 1f69a5
 * CACA_GEOMETRY=160x60 CACA_FONT=5x7 gst-launch-1.0 filesrc location=test.avi ! decodebin ! videoconvert ! cacasink
Packit 1f69a5
 * ]| This pipeline renders a video to ascii art into a separate window using a
Packit 1f69a5
 * small font and specifying the ascii resolution.
Packit 1f69a5
 * |[
Packit 1f69a5
 * CACA_DRIVER=ncurses gst-launch-1.0 filesrc location=test.avi ! decodebin ! videoconvert ! cacasink
Packit 1f69a5
 * ]| This pipeline renders a video to ascii art into the current terminal.
Packit 1f69a5
 * </refsect2>
Packit 1f69a5
 */
Packit 1f69a5
Packit 1f69a5
#ifdef HAVE_CONFIG_H
Packit 1f69a5
#include "config.h"
Packit 1f69a5
#endif
Packit 1f69a5
Packit 1f69a5
#include <string.h>
Packit 1f69a5
#include "gstcacasink.h"
Packit 1f69a5
Packit 1f69a5
Packit 1f69a5
//#define GST_CACA_DEFAULT_RED_MASK R_MASK_32_REVERSE_INT
Packit 1f69a5
//#define GST_CACA_DEFAULT_GREEN_MASK G_MASK_32_REVERSE_INT
Packit 1f69a5
//#define GST_CACA_DEFAULT_BLUE_MASK B_MASK_32_REVERSE_INT
Packit 1f69a5
Packit 1f69a5
/* cacasink signals and args */
Packit 1f69a5
enum
Packit 1f69a5
{
Packit 1f69a5
  LAST_SIGNAL
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
#define GST_CACA_DEFAULT_SCREEN_WIDTH 80
Packit 1f69a5
#define GST_CACA_DEFAULT_SCREEN_HEIGHT 25
Packit 1f69a5
#define GST_CACA_DEFAULT_DITHER CACA_DITHERING_NONE
Packit 1f69a5
#define GST_CACA_DEFAULT_ANTIALIASING TRUE
Packit 1f69a5
Packit 1f69a5
enum
Packit 1f69a5
{
Packit 1f69a5
  PROP_0,
Packit 1f69a5
  PROP_SCREEN_WIDTH,
Packit 1f69a5
  PROP_SCREEN_HEIGHT,
Packit 1f69a5
  PROP_DITHER,
Packit 1f69a5
  PROP_ANTIALIASING
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
Packit 1f69a5
    GST_PAD_SINK,
Packit 1f69a5
    GST_PAD_ALWAYS,
Packit 1f69a5
    GST_STATIC_CAPS (GST_VIDEO_CAPS_MAKE
Packit 1f69a5
        ("{ RGB, BGR, RGBx, xRGB, BGRx, xBGR, RGB16, RGB15 }"))
Packit 1f69a5
    );
Packit 1f69a5
Packit 1f69a5
static gboolean gst_cacasink_setcaps (GstBaseSink * pad, GstCaps * caps);
Packit 1f69a5
static void gst_cacasink_get_times (GstBaseSink * sink, GstBuffer * buffer,
Packit 1f69a5
    GstClockTime * start, GstClockTime * end);
Packit 1f69a5
static GstFlowReturn gst_cacasink_render (GstBaseSink * basesink,
Packit 1f69a5
    GstBuffer * buffer);
Packit 1f69a5
Packit 1f69a5
static void gst_cacasink_set_property (GObject * object, guint prop_id,
Packit 1f69a5
    const GValue * value, GParamSpec * pspec);
Packit 1f69a5
static void gst_cacasink_get_property (GObject * object, guint prop_id,
Packit 1f69a5
    GValue * value, GParamSpec * pspec);
Packit 1f69a5
Packit 1f69a5
static GstStateChangeReturn gst_cacasink_change_state (GstElement * element,
Packit 1f69a5
    GstStateChange transition);
Packit 1f69a5
Packit 1f69a5
#define gst_cacasink_parent_class parent_class
Packit 1f69a5
G_DEFINE_TYPE (GstCACASink, gst_cacasink, GST_TYPE_BASE_SINK);
Packit 1f69a5
Packit 1f69a5
#define GST_TYPE_CACADITHER (gst_cacasink_dither_get_type())
Packit 1f69a5
static GType
Packit 1f69a5
gst_cacasink_dither_get_type (void)
Packit 1f69a5
{
Packit 1f69a5
  static GType dither_type = 0;
Packit 1f69a5
Packit 1f69a5
  static const GEnumValue dither_types[] = {
Packit 1f69a5
    {CACA_DITHERING_NONE, "No dithering", "none"},
Packit 1f69a5
    {CACA_DITHERING_ORDERED2, "Ordered 2x2 Bayer dithering", "2x2"},
Packit 1f69a5
    {CACA_DITHERING_ORDERED4, "Ordered 4x4 Bayer dithering", "4x4"},
Packit 1f69a5
    {CACA_DITHERING_ORDERED8, "Ordered 8x8 Bayer dithering", "8x8"},
Packit 1f69a5
    {CACA_DITHERING_RANDOM, "Random dithering", "random"},
Packit 1f69a5
    {0, NULL, NULL},
Packit 1f69a5
  };
Packit 1f69a5
Packit 1f69a5
  if (!dither_type) {
Packit 1f69a5
    dither_type = g_enum_register_static ("GstCACASinkDithering", dither_types);
Packit 1f69a5
  }
Packit 1f69a5
  return dither_type;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_cacasink_class_init (GstCACASinkClass * klass)
Packit 1f69a5
{
Packit 1f69a5
  GObjectClass *gobject_class;
Packit 1f69a5
  GstElementClass *gstelement_class;
Packit 1f69a5
  GstBaseSinkClass *gstbasesink_class;
Packit 1f69a5
Packit 1f69a5
  gobject_class = (GObjectClass *) klass;
Packit 1f69a5
  gstelement_class = (GstElementClass *) klass;
Packit 1f69a5
  gstbasesink_class = (GstBaseSinkClass *) klass;
Packit 1f69a5
Packit 1f69a5
  parent_class = g_type_class_peek_parent (klass);
Packit 1f69a5
Packit 1f69a5
  gobject_class->set_property = gst_cacasink_set_property;
Packit 1f69a5
  gobject_class->get_property = gst_cacasink_get_property;
Packit 1f69a5
Packit 1f69a5
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SCREEN_WIDTH,
Packit 1f69a5
      g_param_spec_int ("screen-width", "Screen Width",
Packit 1f69a5
          "The width of the screen", 0, G_MAXINT, GST_CACA_DEFAULT_SCREEN_WIDTH,
Packit 1f69a5
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_SCREEN_HEIGHT,
Packit 1f69a5
      g_param_spec_int ("screen-height", "Screen Height",
Packit 1f69a5
          "The height of the screen", 0, G_MAXINT,
Packit 1f69a5
          GST_CACA_DEFAULT_SCREEN_HEIGHT,
Packit 1f69a5
          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_DITHER,
Packit 1f69a5
      g_param_spec_enum ("dither", "Dither Type", "Set type of Dither",
Packit 1f69a5
          GST_TYPE_CACADITHER, GST_CACA_DEFAULT_DITHER,
Packit 1f69a5
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
  g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_ANTIALIASING,
Packit 1f69a5
      g_param_spec_boolean ("anti-aliasing", "Anti Aliasing",
Packit 1f69a5
          "Enables Anti-Aliasing", GST_CACA_DEFAULT_ANTIALIASING,
Packit 1f69a5
          G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
Packit 1f69a5
  gstelement_class->change_state = gst_cacasink_change_state;
Packit 1f69a5
Packit 1f69a5
  gst_element_class_set_static_metadata (gstelement_class,
Packit 1f69a5
      "A colored ASCII art video sink", "Sink/Video",
Packit 1f69a5
      "A colored ASCII art videosink", "Zeeshan Ali <zak147@yahoo.com>");
Packit 1f69a5
  gst_element_class_add_static_pad_template (gstelement_class, &sink_template);
Packit 1f69a5
Packit 1f69a5
  gstbasesink_class->set_caps = GST_DEBUG_FUNCPTR (gst_cacasink_setcaps);
Packit 1f69a5
  gstbasesink_class->get_times = GST_DEBUG_FUNCPTR (gst_cacasink_get_times);
Packit 1f69a5
  gstbasesink_class->preroll = GST_DEBUG_FUNCPTR (gst_cacasink_render);
Packit 1f69a5
  gstbasesink_class->render = GST_DEBUG_FUNCPTR (gst_cacasink_render);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_cacasink_get_times (GstBaseSink * sink, GstBuffer * buffer,
Packit 1f69a5
    GstClockTime * start, GstClockTime * end)
Packit 1f69a5
{
Packit 1f69a5
  *start = GST_BUFFER_TIMESTAMP (buffer);
Packit 1f69a5
  *end = *start + GST_BUFFER_DURATION (buffer);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static gboolean
Packit 1f69a5
gst_cacasink_setcaps (GstBaseSink * basesink, GstCaps * caps)
Packit 1f69a5
{
Packit 1f69a5
  GstCACASink *cacasink;
Packit 1f69a5
  GstVideoInfo info;
Packit 1f69a5
  guint bpp, red_mask, green_mask, blue_mask;
Packit 1f69a5
Packit 1f69a5
  cacasink = GST_CACASINK (basesink);
Packit 1f69a5
Packit 1f69a5
  if (!gst_video_info_from_caps (&info, caps))
Packit 1f69a5
    goto caps_error;
Packit 1f69a5
Packit 1f69a5
  switch (GST_VIDEO_INFO_FORMAT (&info)) {
Packit 1f69a5
    case GST_VIDEO_FORMAT_RGB:
Packit 1f69a5
    case GST_VIDEO_FORMAT_BGR:
Packit 1f69a5
    case GST_VIDEO_FORMAT_RGBx:
Packit 1f69a5
    case GST_VIDEO_FORMAT_xRGB:
Packit 1f69a5
    case GST_VIDEO_FORMAT_BGRx:
Packit 1f69a5
    case GST_VIDEO_FORMAT_xBGR:
Packit 1f69a5
      bpp = 8 * info.finfo->pixel_stride[0];
Packit 1f69a5
      red_mask = 0xff << (8 * info.finfo->poffset[GST_VIDEO_COMP_R]);
Packit 1f69a5
      green_mask = 0xff << (8 * info.finfo->poffset[GST_VIDEO_COMP_G]);
Packit 1f69a5
      blue_mask = 0xff << (8 * info.finfo->poffset[GST_VIDEO_COMP_B]);
Packit 1f69a5
      break;
Packit 1f69a5
    case GST_VIDEO_FORMAT_RGB16:
Packit 1f69a5
      bpp = 16;
Packit 1f69a5
      red_mask = 0xf800;
Packit 1f69a5
      green_mask = 0x07e0;
Packit 1f69a5
      blue_mask = 0x001f;
Packit 1f69a5
      break;
Packit 1f69a5
    case GST_VIDEO_FORMAT_RGB15:
Packit 1f69a5
      bpp = 16;
Packit 1f69a5
      red_mask = 0x7c00;
Packit 1f69a5
      green_mask = 0x03e0;
Packit 1f69a5
      blue_mask = 0x001f;
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      goto invalid_format;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  if (cacasink->bitmap) {
Packit 1f69a5
    caca_free_bitmap (cacasink->bitmap);
Packit 1f69a5
  }
Packit 1f69a5
  cacasink->bitmap = caca_create_bitmap (bpp,
Packit 1f69a5
      GST_VIDEO_INFO_WIDTH (&info),
Packit 1f69a5
      GST_VIDEO_INFO_HEIGHT (&info),
Packit 1f69a5
      GST_ROUND_UP_4 (GST_VIDEO_INFO_WIDTH (&info) * bpp / 8),
Packit 1f69a5
      red_mask, green_mask, blue_mask, 0);
Packit 1f69a5
  if (!cacasink->bitmap)
Packit 1f69a5
    goto no_bitmap;
Packit 1f69a5
Packit 1f69a5
  cacasink->info = info;
Packit 1f69a5
Packit 1f69a5
  return TRUE;
Packit 1f69a5
Packit 1f69a5
  /* ERROS */
Packit 1f69a5
caps_error:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ERROR_OBJECT (cacasink, "error parsing caps");
Packit 1f69a5
    return FALSE;
Packit 1f69a5
  }
Packit 1f69a5
invalid_format:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ERROR_OBJECT (cacasink, "invalid format");
Packit 1f69a5
    return FALSE;
Packit 1f69a5
  }
Packit 1f69a5
no_bitmap:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ERROR_OBJECT (cacasink, "could not create bitmap");
Packit 1f69a5
    return FALSE;
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_cacasink_init (GstCACASink * cacasink)
Packit 1f69a5
{
Packit 1f69a5
  cacasink->screen_width = GST_CACA_DEFAULT_SCREEN_WIDTH;
Packit 1f69a5
  cacasink->screen_height = GST_CACA_DEFAULT_SCREEN_HEIGHT;
Packit 1f69a5
Packit 1f69a5
  cacasink->dither = GST_CACA_DEFAULT_DITHER;
Packit 1f69a5
  cacasink->antialiasing = GST_CACA_DEFAULT_ANTIALIASING;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static GstFlowReturn
Packit 1f69a5
gst_cacasink_render (GstBaseSink * basesink, GstBuffer * buffer)
Packit 1f69a5
{
Packit 1f69a5
  GstCACASink *cacasink = GST_CACASINK (basesink);
Packit 1f69a5
  GstVideoFrame frame;
Packit 1f69a5
Packit 1f69a5
  GST_DEBUG ("render");
Packit 1f69a5
Packit 1f69a5
  if (!gst_video_frame_map (&frame, &cacasink->info, buffer, GST_MAP_READ))
Packit 1f69a5
    goto invalid_frame;
Packit 1f69a5
Packit 1f69a5
  caca_clear ();
Packit 1f69a5
  caca_draw_bitmap (0, 0, cacasink->screen_width - 1,
Packit 1f69a5
      cacasink->screen_height - 1, cacasink->bitmap,
Packit 1f69a5
      GST_VIDEO_FRAME_PLANE_DATA (&frame, 0));
Packit 1f69a5
  caca_refresh ();
Packit 1f69a5
Packit 1f69a5
  gst_video_frame_unmap (&frame);
Packit 1f69a5
Packit 1f69a5
  return GST_FLOW_OK;
Packit 1f69a5
Packit 1f69a5
  /* ERRORS */
Packit 1f69a5
invalid_frame:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ERROR_OBJECT (cacasink, "invalid frame received");
Packit 1f69a5
    return GST_FLOW_ERROR;
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_cacasink_set_property (GObject * object, guint prop_id,
Packit 1f69a5
    const GValue * value, GParamSpec * pspec)
Packit 1f69a5
{
Packit 1f69a5
  GstCACASink *cacasink;
Packit 1f69a5
Packit 1f69a5
  g_return_if_fail (GST_IS_CACASINK (object));
Packit 1f69a5
Packit 1f69a5
  cacasink = GST_CACASINK (object);
Packit 1f69a5
Packit 1f69a5
  switch (prop_id) {
Packit 1f69a5
    case PROP_DITHER:{
Packit 1f69a5
      cacasink->dither = g_value_get_enum (value);
Packit 1f69a5
      caca_set_dithering (cacasink->dither + CACA_DITHERING_NONE);
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
    case PROP_ANTIALIASING:{
Packit 1f69a5
      cacasink->antialiasing = g_value_get_boolean (value);
Packit 1f69a5
      if (cacasink->antialiasing) {
Packit 1f69a5
        caca_set_feature (CACA_ANTIALIASING_MAX);
Packit 1f69a5
      } else {
Packit 1f69a5
        caca_set_feature (CACA_ANTIALIASING_MIN);
Packit 1f69a5
      }
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
    default:
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_cacasink_get_property (GObject * object, guint prop_id, GValue * value,
Packit 1f69a5
    GParamSpec * pspec)
Packit 1f69a5
{
Packit 1f69a5
  GstCACASink *cacasink;
Packit 1f69a5
Packit 1f69a5
  cacasink = GST_CACASINK (object);
Packit 1f69a5
Packit 1f69a5
  switch (prop_id) {
Packit 1f69a5
    case PROP_SCREEN_WIDTH:{
Packit 1f69a5
      g_value_set_int (value, cacasink->screen_width);
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
    case PROP_SCREEN_HEIGHT:{
Packit 1f69a5
      g_value_set_int (value, cacasink->screen_height);
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
    case PROP_DITHER:{
Packit 1f69a5
      g_value_set_enum (value, cacasink->dither);
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
    case PROP_ANTIALIASING:{
Packit 1f69a5
      g_value_set_boolean (value, cacasink->antialiasing);
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
    default:{
Packit 1f69a5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 1f69a5
      break;
Packit 1f69a5
    }
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static gboolean
Packit 1f69a5
gst_cacasink_open (GstCACASink * cacasink)
Packit 1f69a5
{
Packit 1f69a5
  cacasink->bitmap = NULL;
Packit 1f69a5
Packit 1f69a5
  if (caca_init () < 0)
Packit 1f69a5
    goto init_failed;
Packit 1f69a5
Packit 1f69a5
  cacasink->screen_width = caca_get_width ();
Packit 1f69a5
  cacasink->screen_height = caca_get_height ();
Packit 1f69a5
  cacasink->antialiasing = TRUE;
Packit 1f69a5
  caca_set_feature (CACA_ANTIALIASING_MAX);
Packit 1f69a5
  cacasink->dither = 0;
Packit 1f69a5
  caca_set_dithering (CACA_DITHERING_NONE);
Packit 1f69a5
Packit 1f69a5
  return TRUE;
Packit 1f69a5
Packit 1f69a5
  /* ERRORS */
Packit 1f69a5
init_failed:
Packit 1f69a5
  {
Packit 1f69a5
    GST_ELEMENT_ERROR (cacasink, RESOURCE, OPEN_WRITE, (NULL),
Packit 1f69a5
        ("caca_init() failed"));
Packit 1f69a5
    return FALSE;
Packit 1f69a5
  }
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_cacasink_close (GstCACASink * cacasink)
Packit 1f69a5
{
Packit 1f69a5
  if (cacasink->bitmap) {
Packit 1f69a5
    caca_free_bitmap (cacasink->bitmap);
Packit 1f69a5
    cacasink->bitmap = NULL;
Packit 1f69a5
  }
Packit 1f69a5
  caca_end ();
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static GstStateChangeReturn
Packit 1f69a5
gst_cacasink_change_state (GstElement * element, GstStateChange transition)
Packit 1f69a5
{
Packit 1f69a5
  GstStateChangeReturn ret;
Packit 1f69a5
Packit 1f69a5
  switch (transition) {
Packit 1f69a5
    case GST_STATE_CHANGE_READY_TO_PAUSED:
Packit 1f69a5
      if (!gst_cacasink_open (GST_CACASINK (element)))
Packit 1f69a5
        return GST_STATE_CHANGE_FAILURE;
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
Packit 1f69a5
Packit 1f69a5
  switch (transition) {
Packit 1f69a5
    case GST_STATE_CHANGE_PAUSED_TO_READY:
Packit 1f69a5
      gst_cacasink_close (GST_CACASINK (element));
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
  return ret;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static gboolean
Packit 1f69a5
plugin_init (GstPlugin * plugin)
Packit 1f69a5
{
Packit 1f69a5
  if (!gst_element_register (plugin, "cacasink", GST_RANK_NONE,
Packit 1f69a5
          GST_TYPE_CACASINK))
Packit 1f69a5
    return FALSE;
Packit 1f69a5
Packit 1f69a5
  return TRUE;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
Packit 1f69a5
    GST_VERSION_MINOR,
Packit 1f69a5
    cacasink,
Packit 1f69a5
    "Colored ASCII Art video sink",
Packit 1f69a5
    plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)