gst_plugins_good/gst/alpha/gstalphacolor.c
changeset 26 69c7080681bf
parent 24 bc39b352897e
child 28 4ed5253bb6ba
equal deleted inserted replaced
24:bc39b352897e 26:69c7080681bf
     1 /* GStreamer
       
     2  * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
       
     3  *
       
     4  * This library is free software; you can redistribute it and/or
       
     5  * modify it under the terms of the GNU Library General Public
       
     6  * License as published by the Free Software Foundation; either
       
     7  * version 2 of the License, or (at your option) any later version.
       
     8  *
       
     9  * This library is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
       
    12  * Library General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU Library General Public
       
    15  * License along with this library; if not, write to the
       
    16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
       
    17  * Boston, MA 02111-1307, USA.
       
    18  */
       
    19 
       
    20 /**
       
    21  * SECTION:element-alphacolor
       
    22  *
       
    23  * The alphacolor element does memory-efficient (in-place) colourspace
       
    24  * conversion from RGBA to AYUV, preserving the alpha channel.
       
    25  */
       
    26 
       
    27 #ifdef HAVE_CONFIG_H
       
    28 #include "config.h"
       
    29 #endif
       
    30 
       
    31 #include "gstalphacolor.h"
       
    32 
       
    33 #include <gst/gst.h>
       
    34 #include <gst/video/video.h>
       
    35 
       
    36 #include <string.h>
       
    37 
       
    38 GST_DEBUG_CATEGORY_STATIC (alpha_color_debug);
       
    39 #define GST_CAT_DEFAULT alpha_color_debug
       
    40 
       
    41 /* elementfactory information */
       
    42 static const GstElementDetails gst_alpha_color_details =
       
    43 GST_ELEMENT_DETAILS ("Alpha color filter",
       
    44     "Filter/Effect/Video",
       
    45     "RGBA to AYUV colorspace conversion preserving the alpha channel",
       
    46     "Wim Taymans <wim@fluendo.com>");
       
    47 
       
    48 static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
       
    49     GST_PAD_SINK,
       
    50     GST_PAD_ALWAYS,
       
    51     GST_STATIC_CAPS (GST_VIDEO_CAPS_RGBA ";" GST_VIDEO_CAPS_BGRA)
       
    52     );
       
    53 
       
    54 static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
       
    55     GST_PAD_SRC,
       
    56     GST_PAD_ALWAYS,
       
    57     GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("AYUV"))
       
    58     );
       
    59 
       
    60 GST_BOILERPLATE (GstAlphaColor, gst_alpha_color, GstBaseTransform,
       
    61     GST_TYPE_BASE_TRANSFORM);
       
    62 
       
    63 static GstCaps *gst_alpha_color_transform_caps (GstBaseTransform * btrans,
       
    64     GstPadDirection direction, GstCaps * caps);
       
    65 static gboolean gst_alpha_color_set_caps (GstBaseTransform * btrans,
       
    66     GstCaps * incaps, GstCaps * outcaps);
       
    67 static GstFlowReturn gst_alpha_color_transform_ip (GstBaseTransform * btrans,
       
    68     GstBuffer * inbuf);
       
    69 
       
    70 static void
       
    71 gst_alpha_color_base_init (gpointer g_class)
       
    72 {
       
    73   GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
       
    74 
       
    75   gst_element_class_set_details (element_class, &gst_alpha_color_details);
       
    76 
       
    77   gst_element_class_add_pad_template (element_class,
       
    78       gst_static_pad_template_get (&sink_template));
       
    79   gst_element_class_add_pad_template (element_class,
       
    80       gst_static_pad_template_get (&src_template));
       
    81 }
       
    82 
       
    83 static void
       
    84 gst_alpha_color_class_init (GstAlphaColorClass * klass)
       
    85 {
       
    86   GstBaseTransformClass *gstbasetransform_class;
       
    87 
       
    88   gstbasetransform_class = (GstBaseTransformClass *) klass;
       
    89 
       
    90   gstbasetransform_class->transform_caps =
       
    91       GST_DEBUG_FUNCPTR (gst_alpha_color_transform_caps);
       
    92   gstbasetransform_class->set_caps =
       
    93       GST_DEBUG_FUNCPTR (gst_alpha_color_set_caps);
       
    94   gstbasetransform_class->transform_ip =
       
    95       GST_DEBUG_FUNCPTR (gst_alpha_color_transform_ip);
       
    96 
       
    97   GST_DEBUG_CATEGORY_INIT (alpha_color_debug, "alphacolor", 0,
       
    98       "RGB->YUV colorspace conversion preserving the alpha channels");
       
    99 }
       
   100 
       
   101 static void
       
   102 gst_alpha_color_init (GstAlphaColor * alpha, GstAlphaColorClass * g_class)
       
   103 {
       
   104   GstBaseTransform *btrans = NULL;
       
   105 
       
   106   btrans = GST_BASE_TRANSFORM (alpha);
       
   107 
       
   108   btrans->always_in_place = TRUE;
       
   109 }
       
   110 
       
   111 static GstCaps *
       
   112 gst_alpha_color_transform_caps (GstBaseTransform * btrans,
       
   113     GstPadDirection direction, GstCaps * caps)
       
   114 {
       
   115   const GstCaps *tmpl_caps = NULL;
       
   116   GstCaps *result = NULL, *local_caps = NULL;
       
   117   guint i;
       
   118 
       
   119   local_caps = gst_caps_copy (caps);
       
   120 
       
   121   for (i = 0; i < gst_caps_get_size (local_caps); i++) {
       
   122     GstStructure *structure = gst_caps_get_structure (local_caps, i);
       
   123 
       
   124     /* Throw away the structure name and set it to transformed format */
       
   125     if (direction == GST_PAD_SINK) {
       
   126       gst_structure_set_name (structure, "video/x-raw-yuv");
       
   127     } else if (direction == GST_PAD_SRC) {
       
   128       gst_structure_set_name (structure, "video/x-raw-rgb");
       
   129     }
       
   130     /* Remove any specific parameter from the structure */
       
   131     gst_structure_remove_field (structure, "format");
       
   132     gst_structure_remove_field (structure, "endianness");
       
   133     gst_structure_remove_field (structure, "depth");
       
   134     gst_structure_remove_field (structure, "bpp");
       
   135     gst_structure_remove_field (structure, "red_mask");
       
   136     gst_structure_remove_field (structure, "green_mask");
       
   137     gst_structure_remove_field (structure, "blue_mask");
       
   138     gst_structure_remove_field (structure, "alpha_mask");
       
   139   }
       
   140 
       
   141   /* Get the appropriate template */
       
   142   if (direction == GST_PAD_SINK) {
       
   143     tmpl_caps = gst_static_pad_template_get_caps (&src_template);
       
   144   } else if (direction == GST_PAD_SRC) {
       
   145     tmpl_caps = gst_static_pad_template_get_caps (&sink_template);
       
   146   }
       
   147 
       
   148   /* Intersect with our template caps */
       
   149   result = gst_caps_intersect (local_caps, tmpl_caps);
       
   150 
       
   151   gst_caps_unref (local_caps);
       
   152   gst_caps_do_simplify (result);
       
   153 
       
   154   GST_LOG ("transformed %" GST_PTR_FORMAT " to %" GST_PTR_FORMAT, caps, result);
       
   155 
       
   156   return result;
       
   157 }
       
   158 
       
   159 static gboolean
       
   160 gst_alpha_color_set_caps (GstBaseTransform * btrans, GstCaps * incaps,
       
   161     GstCaps * outcaps)
       
   162 {
       
   163   GstAlphaColor *alpha;
       
   164   GstStructure *structure;
       
   165   gboolean ret;
       
   166   const GValue *fps;
       
   167   gint red_mask, alpha_mask;
       
   168   gint w, h, depth, bpp;
       
   169 
       
   170   alpha = GST_ALPHA_COLOR (btrans);
       
   171   structure = gst_caps_get_structure (incaps, 0);
       
   172 
       
   173   ret = gst_structure_get_int (structure, "width", &w);
       
   174   ret &= gst_structure_get_int (structure, "height", &h);
       
   175   fps = gst_structure_get_value (structure, "framerate");
       
   176   ret &= (fps != NULL && GST_VALUE_HOLDS_FRACTION (fps));
       
   177   ret &= gst_structure_get_int (structure, "red_mask", &red_mask);
       
   178 
       
   179   /* make sure these are really full RGBA caps */
       
   180   ret &= gst_structure_get_int (structure, "alpha_mask", &alpha_mask);
       
   181   ret &= gst_structure_get_int (structure, "depth", &depth);
       
   182   ret &= gst_structure_get_int (structure, "bpp", &bpp);
       
   183 
       
   184   if (!ret || alpha_mask == 0 || red_mask == 0 || depth != 32 || bpp != 32) {
       
   185     GST_DEBUG_OBJECT (alpha, "incomplete or non-RGBA input caps!");
       
   186     return FALSE;
       
   187   }
       
   188 
       
   189   alpha->in_width = w;
       
   190   alpha->in_height = h;
       
   191   alpha->in_rgba = TRUE;
       
   192 #if (G_BYTE_ORDER == G_BIG_ENDIAN)
       
   193   if (red_mask != 0x000000ff)
       
   194 #else
       
   195   if (red_mask != 0xff000000)
       
   196 #endif
       
   197     alpha->in_rgba = FALSE;
       
   198 
       
   199   return TRUE;
       
   200 }
       
   201 
       
   202 static void
       
   203 transform_rgb (guint8 * data, gint size)
       
   204 {
       
   205   guint8 y, u, v;
       
   206 
       
   207   while (size > 0) {
       
   208     y = data[0] * 0.299 + data[1] * 0.587 + data[2] * 0.114 + 0;
       
   209     u = data[0] * -0.169 + data[1] * -0.332 + data[2] * 0.500 + 128;
       
   210     v = data[0] * 0.500 + data[1] * -0.419 + data[2] * -0.0813 + 128;
       
   211 
       
   212     data[0] = data[3];
       
   213     data[1] = y;
       
   214     data[2] = u;
       
   215     data[3] = v;
       
   216 
       
   217     data += 4;
       
   218     size -= 4;
       
   219   }
       
   220 }
       
   221 
       
   222 static void
       
   223 transform_bgr (guint8 * data, gint size)
       
   224 {
       
   225   guint8 y, u, v;
       
   226 
       
   227   while (size > 0) {
       
   228     y = data[2] * 0.299 + data[1] * 0.587 + data[0] * 0.114 + 0;
       
   229     u = data[2] * -0.169 + data[1] * -0.332 + data[0] * 0.500 + 128;
       
   230     v = data[2] * 0.500 + data[1] * -0.419 + data[0] * -0.0813 + 128;
       
   231 
       
   232     data[0] = data[3];
       
   233     data[1] = y;
       
   234     data[2] = u;
       
   235     data[3] = v;
       
   236 
       
   237     data += 4;
       
   238     size -= 4;
       
   239   }
       
   240 }
       
   241 
       
   242 static GstFlowReturn
       
   243 gst_alpha_color_transform_ip (GstBaseTransform * btrans, GstBuffer * inbuf)
       
   244 {
       
   245   GstFlowReturn ret = GST_FLOW_OK;
       
   246   GstAlphaColor *alpha;
       
   247 
       
   248   alpha = GST_ALPHA_COLOR (btrans);
       
   249 
       
   250   /* Transform in place */
       
   251   if (alpha->in_rgba)
       
   252     transform_rgb (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
       
   253   else
       
   254     transform_bgr (GST_BUFFER_DATA (inbuf), GST_BUFFER_SIZE (inbuf));
       
   255 
       
   256   return ret;
       
   257 }
       
   258 
       
   259 static gboolean
       
   260 plugin_init (GstPlugin * plugin)
       
   261 {
       
   262   return gst_element_register (plugin, "alphacolor", GST_RANK_NONE,
       
   263       GST_TYPE_ALPHA_COLOR);
       
   264 }
       
   265 
       
   266 GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
       
   267     GST_VERSION_MINOR,
       
   268     "alphacolor",
       
   269     "RGBA to AYUV colorspace conversion preserving the alpha channel",
       
   270     plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
       
   271 
       
   272 
       
   273 #ifdef __SYMBIAN32__
       
   274 EXPORT_C GstPluginDesc* _GST_PLUGIN_DESC()
       
   275 {
       
   276     return &gst_plugin_desc;
       
   277 }
       
   278 
       
   279 #endif