diff --git a/configure.ac b/configure.ac
index 29dfb38..82ea513 100644
--- a/configure.ac
+++ b/configure.ac
@@ -363,11 +363,12 @@ AG_GST_CHECK_PLUGIN(audiovisualizers)
 AG_GST_CHECK_PLUGIN(autoconvert)
 AG_GST_CHECK_PLUGIN(bayer)
 AG_GST_CHECK_PLUGIN(camerabin2)
 AG_GST_CHECK_PLUGIN(cdxaparse)
 AG_GST_CHECK_PLUGIN(coloreffects)
 AG_GST_CHECK_PLUGIN(dataurisrc)
 AG_GST_CHECK_PLUGIN(dccp)
 AG_GST_CHECK_PLUGIN(debugutils)
+AG_GST_CHECK_PLUGIN(dtcpip)
 AG_GST_CHECK_PLUGIN(dvbsuboverlay)
 AG_GST_CHECK_PLUGIN(dvdspu)
 AG_GST_CHECK_PLUGIN(faceoverlay)
@@ -2372,11 +2380,12 @@ gst/audiovisualizers/Makefile
 gst/autoconvert/Makefile
 gst/bayer/Makefile
 gst/camerabin2/Makefile
 gst/cdxaparse/Makefile
 gst/coloreffects/Makefile
 gst/dataurisrc/Makefile
 gst/dccp/Makefile
 gst/debugutils/Makefile
+gst/dtcpip/Makefile
 gst/dvbsuboverlay/Makefile
 gst/dvdspu/Makefile
 gst/faceoverlay/Makefile
diff --git a/gst/dtcpip/Makefile.am b/gst/dtcpip/Makefile.am
new file mode 100644
index 0000000..80dd21a
--- /dev/null
+++ b/gst/dtcpip/Makefile.am
@@ -0,0 +1,16 @@
+plugin_LTLIBRARIES = libgstdtcpip.la
+
+libgstdtcpip_la_SOURCES = gstdtcpip.c lib_dtcpip.c
+
+libgstdtcpip_la_CFLAGS = \
+	$(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
+	-DGST_USE_UNSTABLE_API \
+	$(GST_BASE_CFLAGS) $(GST_CFLAGS)
+
+libgstdtcpip_la_LIBADD = \
+	-lgsttag-$(GST_API_VERSION) $(GST_BASE_LIBS) $(GST_LIBS)
+libgstdtcpip_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstdtcpip_la_LIBTOOLFLAGS = $(GST_PLUGIN_LIBTOOLFLAGS)
+
+noinst_HEADERS =
+
diff --git a/gst/dtcpip/gstdtcpip.c b/gst/dtcpip/gstdtcpip.c
new file mode 100644
index 0000000..7b4932d
--- /dev/null
+++ b/gst/dtcpip/gstdtcpip.c
@@ -0,0 +1,461 @@
+/*
+ * GStreamer
+ * Copyright (C) 2013 <cablelabs.com>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/**
+ * SECTION:element-dtcpip
+ *
+ * DTCP (Digital Transmission Content Protection) plugins.
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include "gstdtcpip.h"
+
+/* define to have output buffers saved to file */
+#undef DEBUG_SAVE_BUFFER_CONTENT
+
+GST_DEBUG_CATEGORY (gst_dtcpip_debug);
+#define GST_CAT_DEFAULT gst_dtcpip_debug
+
+enum
+{
+  PROP_0,
+  PROP_DTCP1HOST,
+  PROP_DTCP1PORT,
+  PROP_DTCPIP_STORAGE,
+  PROP_PASSTHRU_MODE
+};
+
+#ifdef DEBUG_SAVE_BUFFER_CONTENT
+static FILE *g_debugBufferFile = NULL;
+static gchar *g_debugBufferFileName = "buffers.txt";
+#endif
+
+/* the capabilities of the inputs and outputs.
+ *
+ * describe the real formats here.
+ */
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+    GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY"));
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+    GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS ("ANY"));
+
+#define gst_dtcpip_parent_class parent_class
+G_DEFINE_TYPE (GstDtcpIp, gst_dtcpip, GST_TYPE_ELEMENT);
+
+void gst_dtcpip_free_cleartext_data (gpointer cleartext_data);
+
+static void gst_dtcpip_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec);
+static void gst_dtcpip_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec);
+
+static GstFlowReturn gst_dtcpip_chain (GstPad * pad, GstObject * parent,
+    GstBuffer * buf);
+
+static GstStateChangeReturn gst_dtcpip_change_state (GstElement * element,
+    GstStateChange transition);
+
+/* initialize the dtcpip's class */
+static void
+gst_dtcpip_class_init (GstDtcpIpClass * klass)
+{
+  GObjectClass *gobject_class = (GObjectClass *) klass;
+  GstElementClass *gstelement_class = (GstElementClass *) klass;
+
+  gobject_class->set_property = gst_dtcpip_set_property;
+  gobject_class->get_property = gst_dtcpip_get_property;
+
+  g_object_class_install_property (gobject_class, PROP_DTCP1HOST,
+      g_param_spec_string ("dtcp1host", "dtcp1host",
+          "Host name or IP address for DTCP AKE negotiation",
+          "128.0.0.1", G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_DTCP1PORT,
+      g_param_spec_uint ("dtcp1port", "dtcp1port",
+          "Host port number for DTCP AKE negotiation", 0, 65535, 8999,
+          G_PARAM_READWRITE));
+
+  g_object_class_install_property (gobject_class, PROP_DTCPIP_STORAGE,
+      g_param_spec_string ("dtcpip-storage", "dtcpip-storage",
+          "Directory that contains client's keys",
+          "/media/truecrypt1/dll/test_keys",
+          G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_property (gobject_class, PROP_PASSTHRU_MODE,
+      g_param_spec_boolean ("passthru-mode", "Pass through mode",
+          "Pass data through without trying to decrypt",
+          FALSE, G_PARAM_READWRITE));
+
+  gst_element_class_set_metadata (gstelement_class,
+      "DTCP-IP decryption",
+      "Decrypt/DTCP",
+      "Decrypts link-encrypted DTCP-IP DLNA content",
+      "CableLabs RUIH-RI Team <ruihri@cablelabs.com>");
+
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&src_factory));
+  gst_element_class_add_pad_template (gstelement_class,
+      gst_static_pad_template_get (&sink_factory));
+
+  gstelement_class->change_state = gst_dtcpip_change_state;
+}
+
+/* initialize the new element
+ * instantiate pads and add them to element
+ * set pad calback functions
+ * initialize instance structure
+ */
+static void
+gst_dtcpip_init (GstDtcpIp * filter)
+{
+  GST_DEBUG_OBJECT (filter, "Initializing");
+
+  /* Initialize our DTCPIP library function table pointer */
+  filter->dtcpip_ftable = lib_dtcpip_get_ftable ();
+
+  /* Initialize sink pad */
+  filter->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
+  gst_pad_set_chain_function (filter->sinkpad,
+      GST_DEBUG_FUNCPTR (gst_dtcpip_chain));
+  GST_PAD_SET_PROXY_CAPS (filter->sinkpad);
+  gst_element_add_pad (GST_ELEMENT (filter), filter->sinkpad);
+
+  /* Initialize src pad */
+  filter->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
+  GST_PAD_SET_PROXY_CAPS (filter->srcpad);
+  gst_element_add_pad (GST_ELEMENT (filter), filter->srcpad);
+
+  /* Initialize element properties */
+  filter->dtcp1host = NULL;
+  filter->dtcp1port = -1;
+  filter->passthru_mode = FALSE;
+  filter->dtcp_disabled = TRUE;
+
+  /* Read env vars to storage path and key file name */
+  if (!getenv (GST_DTCP_DLL_ENV))
+    GST_INFO_OBJECT (filter,
+        "DTCP is disabled due to env var NOT set: %s", GST_DTCP_DLL_ENV);
+  else if (!getenv (GST_DTCP_KEY_STORAGE_ENV))
+    GST_INFO_OBJECT (filter,
+        "DTCP is disabled due to env var NOT set: %s",
+        GST_DTCP_KEY_STORAGE_ENV);
+  else {
+    GST_INFO_OBJECT (filter, "Initializing shared library");
+    if (!lib_dtcpip_init ())
+      GST_ERROR_OBJECT (filter,
+          "DTCP is disabled due to problems initializing shared library");
+    else {
+      filter->dtcp_disabled = FALSE;
+      GST_INFO_OBJECT (filter,
+          "Successfully initialized library, DTCP/IP enabled");
+    }
+  }
+
+  /* Initialize DTCP instance variable */
+  filter->session_handle = -1;
+
+#ifdef DEBUG_SAVE_BUFFER_CONTENT
+  g_debugBufferFile = g_fopen (g_debugBufferFileName, "wb");
+#endif
+
+}
+
+static void
+gst_dtcpip_set_property (GObject * object, guint prop_id,
+    const GValue * value, GParamSpec * pspec)
+{
+  GstDtcpIp *filter = GST_DTCPIP (object);
+
+  GST_LOG_OBJECT (filter, "Setting property: %d", prop_id);
+  switch (prop_id) {
+    case PROP_DTCP1HOST:
+      if (filter->dtcp1host) {
+        g_free (filter->dtcp1host);
+      }
+      filter->dtcp1host = g_value_dup_string (value);
+      GST_INFO_OBJECT (filter, "Host property: %s", filter->dtcp1host);
+      break;
+    case PROP_DTCP1PORT:
+      filter->dtcp1port = g_value_get_uint (value);
+      GST_INFO_OBJECT (filter, "Port property: %d", filter->dtcp1port);
+      break;
+    case PROP_PASSTHRU_MODE:
+      filter->passthru_mode = g_value_get_boolean (value);
+      GST_INFO_OBJECT (filter, "Passthru mode: %d", filter->passthru_mode);
+      break;
+    default:
+      GST_INFO_OBJECT (filter, "Unknown property id: %d", prop_id);
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+static void
+gst_dtcpip_get_property (GObject * object, guint prop_id,
+    GValue * value, GParamSpec * pspec)
+{
+  GstDtcpIp *filter = GST_DTCPIP (object);
+  GST_LOG_OBJECT (filter, "Getting property");
+
+  switch (prop_id) {
+    case PROP_DTCP1HOST:
+      g_value_set_string (value, filter->dtcp1host);
+      break;
+    case PROP_DTCP1PORT:
+      g_value_set_uint (value, filter->dtcp1port);
+      break;
+    case PROP_DTCPIP_STORAGE:
+      g_value_set_string (value, filter->dtcpip_storage);
+      break;
+    case PROP_PASSTHRU_MODE:
+      g_value_set_boolean (value, filter->passthru_mode);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+  }
+}
+
+/* Element state change
+ *
+ */
+static GstStateChangeReturn
+gst_dtcpip_change_state (GstElement * element, GstStateChange transition)
+{
+  gint ret_val = DTCPIP_SUCCESS;
+  GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+  GstDtcpIp *filter = GST_DTCPIP (element);
+  gchar dtcpip_version[1024];
+  gboolean decrypting = !filter->dtcp_disabled && !filter->passthru_mode;
+
+  GST_DEBUG_OBJECT (filter, "GST_STATE_CHANGE_%s_TO_%s",
+      gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)),
+      gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)));
+
+  switch (transition) {
+    case GST_STATE_CHANGE_NULL_TO_READY:
+      /* Allocate non-stream-specific resources (libs, mem) */
+      if (decrypting) {
+        filter->dtcpip_ftable->dtcpip_cmn_get_version (dtcpip_version,
+            sizeof (dtcpip_version));
+        GST_DEBUG_OBJECT (filter, "Got dtcpip_cmn_get_version\"=%s\"",
+            dtcpip_version);
+
+        GST_DEBUG_OBJECT (filter, "Calling dtcpip_snk_init()");
+        ret_val = filter->dtcpip_ftable->dtcpip_snk_init ();
+        if (IS_DTCPIP_FAILURE (ret_val)) {
+          GST_ERROR_OBJECT (filter,
+              "Problems in dtcpip_snk_init(\"%s\"), rc: %d",
+              filter->dtcpip_storage, ret_val);
+          return GST_STATE_CHANGE_FAILURE;
+        } else {
+          GST_DEBUG_OBJECT (filter, "Initialized dtcpip_snk_init()");
+        }
+      } else {
+        GST_INFO_OBJECT (filter, "Decrypting disabled");
+      }
+      break;
+
+    case GST_STATE_CHANGE_READY_TO_PAUSED:
+      if (decrypting) {
+        /* Allocate stream-specific resources */
+        ret_val = filter->dtcpip_ftable->dtcpip_snk_open (filter->dtcp1host,
+            filter->dtcp1port, &(filter->session_handle));
+        if (IS_DTCPIP_FAILURE (ret_val)) {
+          GST_ERROR_OBJECT (filter,
+              "Problems in dtcpip_snk_open() using host: %s, port: %d, rc: %d",
+              filter->dtcp1host, filter->dtcp1port, ret_val);
+          return GST_STATE_CHANGE_FAILURE;
+        } else {
+          GST_DEBUG_OBJECT (filter,
+              "Opened via dtcpip_snk_open(%s,%d), ret_val=%d",
+              filter->dtcp1host, filter->dtcp1port, ret_val);
+        }
+      }
+      break;
+    default:
+      break;
+  }
+
+  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+  if (ret == GST_STATE_CHANGE_FAILURE) {
+    GST_ERROR_OBJECT (filter, "Problems with parent class state change");
+    return ret;
+  }
+
+  switch (transition) {
+    case GST_STATE_CHANGE_PAUSED_TO_READY:
+      /* De-llocate stream-specific resources */
+      if (decrypting) {
+        ret_val =
+            filter->dtcpip_ftable->dtcpip_snk_close (filter->session_handle);
+        if (IS_DTCPIP_FAILURE (ret_val)) {
+          GST_ERROR_OBJECT (filter, "Problems closing");
+          /* Don't return error since closing anyways */
+        } else {
+          GST_DEBUG_OBJECT (filter,
+              "Called dtcpip_snk_close(), ret_val=%d", ret_val);
+        }
+        filter->session_handle = DTCPIP_INVALID_SESSION_HANDLE;
+      }
+      break;
+    case GST_STATE_CHANGE_READY_TO_NULL:
+      /* De-allocate non-stream-specific resources (libs, mem) */
+#ifdef DEBUG_SAVE_BUFFER_CONTENT
+      fclose (g_debugBufferFile);
+      g_debugBufferFile = NULL;
+#endif
+      break;
+    default:
+      break;
+  }
+
+  return ret;
+}
+
+/* chain function
+ * this function does the actual processing
+ */
+static GstFlowReturn            /* GST_FLOW_OK, GST_FLOW_ERROR */
+gst_dtcpip_chain (GstPad * pad, GstObject * parent, GstBuffer * buf)
+{
+  gint ret_val;
+  GstDtcpIp *filter;
+  GstMapInfo map;
+  gchar *encrypted_data;
+  gchar *cleartext_data;
+  size_t encrypted_size, cleartext_size;
+  gboolean decrypting;
+  GstFlowReturn gfr = GST_FLOW_ERROR;
+  filter = GST_DTCPIP (parent);
+
+  decrypting = !filter->dtcp_disabled && !filter->passthru_mode;
+  if (decrypting) {
+    /* 1. set our encrypted data pointer */
+    gst_buffer_map (buf, &map, GST_MAP_READ);
+    GST_LOG_OBJECT (filter, "buffer %p, %zu bytes", map.data, map.size);
+    encrypted_data = (gchar *) map.data;
+    encrypted_size = map.size;
+
+    /* 2. Call the DTCPIP decryption */
+    ret_val =
+        filter->dtcpip_ftable->dtcpip_snk_alloc_decrypt (filter->session_handle,
+        encrypted_data, encrypted_size, &cleartext_data, &cleartext_size);
+    if (IS_DTCPIP_FAILURE (ret_val)) {
+      GST_ERROR_OBJECT (filter,
+          "Failed decrypting: dtcpip_snk_alloc_decrypt(), ret_val=%d", ret_val);
+      return GST_FLOW_ERROR;
+    }
+    /* 3. Release the input buffer */
+    gst_buffer_unmap (buf, &map);
+    gst_buffer_unref (buf);
+
+    /* 4. Create a newly allocated buffer (refcount=1) 
+       and set the new buffer's data to be the decrypted data */
+    buf = gst_buffer_new_wrapped_full (0, cleartext_data, cleartext_size, 0,
+        cleartext_size, cleartext_data, gst_dtcpip_free_cleartext_data);
+  }
+  /* 5. push the data to our sink pad, and onto the downstream element
+     could be the original input buffer or the decrypted buffer... */
+  gfr = gst_pad_push (filter->srcpad, buf);
+  if (gfr < GST_FLOW_OK && gfr != GST_FLOW_FLUSHING)
+    GST_WARNING_OBJECT (filter, "Failure with flow, ret_val=%d", gfr);
+
+#ifdef DEBUG_SAVE_BUFFER_CONTENT
+  gst_buffer_map (buf, &map, GST_MAP_READ);
+  if (fwrite (map.data, map.size, 1, g_debugBufferFile) != 1) {
+    GST_WARNING_OBJECT (filter, "Failed to write %u bytes to debug file",
+        map.size);
+  }
+  gst_buffer_unmap (buf, &map);
+#endif
+
+  return gfr;
+}
+
+/**
+ * DestroyNotify method supplied when creating wrapped buffer in chain method.
+ * It is called to free the cleartext buffer that was allocated implicitly.
+ */
+void
+gst_dtcpip_free_cleartext_data (gpointer cleartext_data)
+{
+  dtcpip_typed_functions_t *dtcpip_ftable = lib_dtcpip_get_ftable ();
+  gint ret_val = dtcpip_ftable->dtcpip_snk_free (cleartext_data);
+  if (IS_DTCPIP_FAILURE (ret_val))
+    GST_ERROR ("Failure calling dtcpip_snk_free(), ret_val=%d", ret_val);
+}
+
+/* entry point to initialize the plug-in
+ * initialize the plug-in itself
+ * register the element factories and other features
+ */
+static gboolean
+dtcpip_init (GstPlugin * dtcpip)
+{
+  /* debug category for fltering log messages
+   *
+   * exchange the string 'Template ' with your description
+   */
+  GST_DEBUG_CATEGORY_INIT (gst_dtcpip_debug, "dtcpip", 0,
+      "DTCP-IP library diagnostic output");
+
+  return gst_element_register (dtcpip, "dtcpip", GST_RANK_NONE,
+      GST_TYPE_DTCPIP);
+}
+
+/* gstreamer looks for this structure to register the dtcpip plugin
+ *
+ * exchange the string 'Template dtcpip' with your dtcpip description
+ */
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+    GST_VERSION_MINOR,
+    dtcpip,
+    "DTCP (Digital Transmission Content Protection) plugin",
+    (GstPluginInitFunc) dtcpip_init,
+    VERSION, "LGPL", "CableLabs RUI-H RI", "http://www.cablelabs.com/")
diff --git a/gst/dtcpip/gstdtcpip.h b/gst/dtcpip/gstdtcpip.h
new file mode 100644
index 0000000..f9557df
--- /dev/null
+++ b/gst/dtcpip/gstdtcpip.h
@@ -0,0 +1,92 @@
+/*
+ * GStreamer
+ * Copyright (C) 2013 <cablelabs.com>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_DTCPIP_H__
+#define __GST_DTCPIP_H__
+
+#include <gst/gst.h>
+#include "lib_dtcpip.h"
+
+G_BEGIN_DECLS
+/* #defines don't like whitespacey bits */
+#define GST_TYPE_DTCPIP \
+  (gst_dtcpip_get_type())
+#define GST_DTCPIP(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DTCPIP,GstDtcpIp))
+#define GST_DTCPIP_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DTCPIP,GstDtcpIpClass))
+#define GST_IS_DTCPIP(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DTCPIP))
+#define GST_IS_DTCPIP_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DTCPIP))
+typedef struct _GstDtcpIp GstDtcpIp;
+typedef struct _GstDtcpIpClass GstDtcpIpClass;
+
+struct _GstDtcpIp
+{
+  GstElement element;
+
+  GstPad *sinkpad, *srcpad;
+
+  // Properties
+  gboolean dtcp_disabled;
+  gboolean passthru_mode;
+  gchar *dtcp1host;
+  guint dtcp1port;
+  gchar *dtcpip_storage;
+  gchar *dtcpip_library;
+
+  // DTCP Instance variables
+  gint session_handle;
+  dtcpip_typed_functions_t * dtcpip_ftable;
+};
+
+struct _GstDtcpIpClass
+{
+  GstElementClass parent_class;
+};
+
+GType gst_dtcpip_get_type (void);
+
+G_END_DECLS
+#endif /* __GST_DTCPIP_H__ */
diff --git a/gst/dtcpip/lib_dtcpip.c b/gst/dtcpip/lib_dtcpip.c
new file mode 100644
index 0000000..db965c0
--- /dev/null
+++ b/gst/dtcpip/lib_dtcpip.c
@@ -0,0 +1,304 @@
+/*
+ * GStreamer
+ * Copyright (C) 2013 <cablelabs.com>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <dlfcn.h>
+#include <glib.h>
+#include <string.h>
+
+#include "lib_dtcpip.h"
+
+GST_DEBUG_CATEGORY_EXTERN (gst_dtcpip_debug);
+#define GST_CAT_DEFAULT gst_dtcpip_debug
+
+struct dtcpip_untyped_function_entry_s
+{
+  const char *name;
+  void (*func) ();
+};
+
+typedef struct dtcpip_untyped_function_entry_s dtcpip_untyped_function_entry_t;
+
+#define DTCPIP_STUB(ret,func,...) \
+    static ret func ## _stub(__VA_ARGS__)
+
+DTCPIP_STUB (int, dtcpip_cmn_init, const char *storage_path);
+DTCPIP_STUB (void, dtcpip_cmn_get_version, char *string, size_t length);
+
+DTCPIP_STUB (int, dtcpip_src_init, unsigned short dtcp_port);
+DTCPIP_STUB (int, dtcpip_src_open, int *session_handle, int is_audio_only);
+DTCPIP_STUB (int, dtcpip_src_alloc_encrypt, int session_handle,
+    unsigned char cci,
+    char *cleartext_data, size_t cleartext_size,
+    char **encrypted_data, size_t * encrypted_size);
+DTCPIP_STUB (int, dtcpip_src_free, char *encrypted_data);
+DTCPIP_STUB (int, dtcpip_src_close, int session_handle);
+
+DTCPIP_STUB (int, dtcpip_snk_init, void);
+DTCPIP_STUB (int, dtcpip_snk_open,
+    char *ip_addr, unsigned short ip_port, int *session_handle);
+DTCPIP_STUB (int, dtcpip_snk_alloc_decrypt, int session_handle,
+    char *encrypted_data, size_t encrypted_size,
+    char **cleartext_data, size_t * cleartext_size);
+DTCPIP_STUB (int, dtcpip_snk_free, char *cleartext_data);
+DTCPIP_STUB (int, dtcpip_snk_close, int session_handle);
+
+
+
+#define DTCPIP_INIT(func) \
+    { #func, (void(*)()) func ## _stub }
+
+static dtcpip_untyped_function_entry_t untyped_functions[] = {
+  DTCPIP_INIT (dtcpip_cmn_init),
+  DTCPIP_INIT (dtcpip_cmn_get_version),
+  DTCPIP_INIT (dtcpip_src_init),
+  DTCPIP_INIT (dtcpip_src_open),
+  DTCPIP_INIT (dtcpip_src_alloc_encrypt),
+  DTCPIP_INIT (dtcpip_src_free),
+  DTCPIP_INIT (dtcpip_src_close),
+
+  DTCPIP_INIT (dtcpip_snk_init),
+  DTCPIP_INIT (dtcpip_snk_open),
+  DTCPIP_INIT (dtcpip_snk_alloc_decrypt),
+  DTCPIP_INIT (dtcpip_snk_free),
+  DTCPIP_INIT (dtcpip_snk_close)
+};
+
+dtcpip_typed_functions_t *g_dtcpip_ftable = NULL;
+
+
+DTCPIP_STUB (int, dtcpip_cmn_init, const char *storage_path)
+{
+  GST_DEBUG ("Not implemented");
+
+  return TRUE;
+}
+
+DTCPIP_STUB (void, dtcpip_cmn_get_version, char *string, size_t length)
+{
+  GST_DEBUG ("Not implemented");
+}
+
+DTCPIP_STUB (int, dtcpip_src_init, unsigned short dtcp_port)
+{
+  GST_DEBUG ("Not implemented");
+
+  return TRUE;
+}
+
+DTCPIP_STUB (int, dtcpip_src_open, int *session_handle, int is_audio_only)
+{
+  GST_DEBUG ("Not implemented");
+
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_src_alloc_encrypt, int session_handle,
+    unsigned char cci,
+    char *cleartext_data, size_t cleartext_size,
+    char **encrypted_data, size_t * encrypted_size)
+{
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_src_free, char *encrypted_data)
+{
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_src_close, int session_handle)
+{
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_snk_init, void)
+{
+  GST_DEBUG ("Not implemented");
+
+  return TRUE;
+}
+
+DTCPIP_STUB (int, dtcpip_snk_open,
+    char *ip_addr, unsigned short ip_port, int *session_handle)
+{
+  GST_DEBUG ("Not implemented");
+
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_snk_alloc_decrypt, int session_handle,
+    char *encrypted_data, size_t encrypted_size,
+    char **cleartext_data, size_t * cleartext_size)
+{
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_snk_free, char *cleartext_data)
+{
+  return -1;
+}
+
+DTCPIP_STUB (int, dtcpip_snk_close, int session_handle)
+{
+  GST_DEBUG ("Not implemented");
+
+  return -1;
+}
+
+dtcpip_typed_functions_t *
+lib_dtcpip_get_ftable (void)
+{
+  return (dtcpip_typed_functions_t *) & untyped_functions;
+}
+
+/**
+ * Initializes the DTCP/IP library. If the library cannot be
+ * located or does not have all the required functions, DTCP
+ * encryption will be disabled and local stub functions will
+ * be used instead.
+ */
+gboolean
+lib_dtcpip_init (void)
+{
+  void *dtcp_dll = NULL;
+  gboolean ret_code = TRUE;
+  const gchar *dll_path = getenv (GST_DTCP_DLL_ENV);
+
+  GST_DEBUG ("called");
+  g_dtcpip_ftable = (dtcpip_typed_functions_t *) & untyped_functions;
+
+  if (dll_path == NULL) {
+    GST_ERROR ("dtcp dll env var %s is NULL", GST_DTCP_DLL_ENV);
+    ret_code = FALSE;
+  } else {
+    if ((dtcp_dll = dlopen (dll_path, RTLD_LAZY)) != NULL) {
+      gint i = 0;
+      gint num_funcs = -1;
+      char *checkRet;
+
+      GST_INFO ("successfully opened DTCP/IP library from \"%s\".", dll_path);
+
+      /* First check that all functions defined in the structure can
+         be located in the supplied DLL.Cleaned up tab/spaces in all files */
+      num_funcs =
+          sizeof (untyped_functions) / sizeof (dtcpip_untyped_function_entry_t);
+      (void) dlerror ();
+      for (i = 0; i < num_funcs; i++) {
+        (void) dlsym (dtcp_dll, untyped_functions[i].name);
+        checkRet = dlerror ();
+
+        if (NULL != checkRet) {
+          GST_ERROR
+              ("Failed to find symbol \"%s\" [dll_handle %p].  Reason: %s",
+              untyped_functions[i].name, dtcp_dll, checkRet);
+          ret_code = FALSE;
+          break;
+        } else {
+          GST_DEBUG ("successfully located function \"%s\".",
+              untyped_functions[i].name);
+        }
+      }
+
+      /* If all symbols can be located, re-assign the function pointers. */
+      if (ret_code == TRUE) {
+        for (i = 0; i < num_funcs; i++) {
+          if (NULL == (untyped_functions[i].func =
+                  dlsym (dtcp_dll, untyped_functions[i].name))) {
+            GST_ERROR ("Failed to assign symbol \"%s\" [dll_handle %p]",
+                untyped_functions[i].name, dtcp_dll);
+            ret_code = FALSE;
+            break;
+          }
+        }
+      }
+    } else {
+      GST_ERROR ("unable to load DTCP/IP lib \"%s\": Shared Library error %d.",
+          dll_path, ret_code);
+      ret_code = FALSE;
+    }
+  }
+
+  if (ret_code == TRUE) {
+    gint result = 0;
+    gpointer dtcp_storage;
+    gsize storage_len = 0;
+    const gchar *dtcp_storage_env = getenv (GST_DTCP_KEY_STORAGE_ENV);
+
+    if (dtcp_storage_env == NULL) {
+      const gchar *last_slash = strrchr (dll_path, '/');
+      GST_INFO ("%s not defined.", GST_DTCP_KEY_STORAGE_ENV);
+
+      if (last_slash != NULL) {
+        storage_len = (int) (last_slash - dll_path);
+        dtcp_storage = g_malloc0 (storage_len + 1);
+        memcpy (dtcp_storage, dll_path, storage_len);
+      } else {
+        storage_len = 1;
+        dtcp_storage = g_malloc0 (storage_len + 1);
+        ((gchar *) dtcp_storage)[0] = '.';
+      }
+    } else {
+      storage_len = strlen (dtcp_storage_env);
+      dtcp_storage = g_malloc0 (storage_len + 1);
+      memcpy (dtcp_storage, dtcp_storage_env, storage_len);
+    }
+
+    ((gchar *) dtcp_storage)[storage_len] = '\0';
+    GST_INFO ("using \"%s\" for DTCP/IP library storage.",
+        (gchar *) dtcp_storage);
+    result = g_dtcpip_ftable->dtcpip_cmn_init (dtcp_storage);
+
+    if (result != 0) {
+      GST_ERROR ("dtcpip_cmn_init() failed with %d.", result);
+      ret_code = FALSE;
+    } else {
+      GST_INFO ("DTCP/IP enabled.");
+    }
+
+    g_free (dtcp_storage);
+
+  } else {
+    GST_WARNING ("DTCP/IP disabled.");
+  }
+
+  return ret_code;
+}
diff --git a/gst/dtcpip/lib_dtcpip.h b/gst/dtcpip/lib_dtcpip.h
new file mode 100644
index 0000000..fcd998d
--- /dev/null
+++ b/gst/dtcpip/lib_dtcpip.h
@@ -0,0 +1,100 @@
+/*
+ * GStreamer
+ * Copyright (C) 2013 <cablelabs.com>
+ * 
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ *
+ * Alternatively, the contents of this file may be used under the
+ * GNU Lesser General Public License Version 2.1 (the "LGPL"), in
+ * which case the following provisions apply instead of the ones
+ * mentioned above:
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _LIB_DTCPIP_H_
+#define _LIB_DTCPIP_H_
+
+#include <stdlib.h>             // size_t
+#include <gst/gst.h>
+
+#define DTCPIP_INVALID_SESSION_HANDLE (-1)
+#define DTCPIP_IS_SESSION_VALID(h) ((h)>0)
+
+#define DTCPIP_SUCCESS (0)
+// dtcpip (CableLabs) error code range -1 through -4
+// see Cablelabs dtcpip library functions for more detail
+
+// DTCP (Intel) error code range is below -100
+#define IS_DTCPIP_SUCCESS(ret_val) ((ret_val)>=0)
+#define IS_DTCPIP_FAILURE(ret_val) ((ret_val)<0)
+
+#define GST_DTCP_KEY_STORAGE_ENV "GST_DTCP_KEY_STORAGE"
+#define GST_DTCP_DLL_ENV "GST_DTCP_DLL"
+
+#define DTCPIP_DECL(ret,func,...) \
+    char* func ## _name; \
+    ret (*func)(__VA_ARGS__);
+
+typedef struct
+{
+  DTCPIP_DECL (int, dtcpip_cmn_init, const char *storage_path)
+  DTCPIP_DECL (void, dtcpip_cmn_get_version, char *string, size_t length)
+
+  DTCPIP_DECL (int, dtcpip_src_init, unsigned short dtcp_port)
+  DTCPIP_DECL (int, dtcpip_src_open, int *session_handle, int is_audio_only)
+   
+  DTCPIP_DECL (int, dtcpip_src_alloc_encrypt, int session_handle,
+      unsigned char cci,
+      char *cleartext_data, size_t cleartext_size,
+      char **encrypted_data, size_t * encrypted_size)
+  DTCPIP_DECL (int, dtcpip_src_free, char *encrypted_data)
+  DTCPIP_DECL (int, dtcpip_src_close, int session_handle)
+
+  DTCPIP_DECL (int, dtcpip_snk_init, void)
+   
+  DTCPIP_DECL (int, dtcpip_snk_open,
+      char *ip_addr, unsigned short ip_port, int *session_handle)
+   
+  DTCPIP_DECL (int, dtcpip_snk_alloc_decrypt, int session_handle,
+      char *encrypted_data, size_t encrypted_size,
+      char **cleartext_data, size_t * cleartext_size)
+  DTCPIP_DECL (int, dtcpip_snk_free, char *cleartext_data)
+  DTCPIP_DECL (int, dtcpip_snk_close, int session_handle)
+}
+dtcpip_typed_functions_t;
+
+dtcpip_typed_functions_t * lib_dtcpip_get_ftable (void);
+
+gboolean lib_dtcpip_init (void);
+
+#endif // _LIB_DTCPIP_H_
