/* GStreamer
 * Copyright (C) <2013> YouView TV Ltd.
 *
 * 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., 51 Franklin St, Fifth Floor,
 * Boston, MA 02110-1301, USA.
 */

/**
 * SECTION:gstprotection
 * @short_description: Functions and classes to support encrypted streams.
 *
 * The GstProtectionMeta class enables the information needed to decrypt a
 * #GstBuffer to be attached to that buffer.
 *
 * Typically, a demuxer element would attach GstProtectionMeta objects
 * to the buffers that it pushes downstream. The demuxer would parse the
 * protection information for a video/audio frame from its input data and use
 * this information to populate the #GstStructure @info field,
 * which is then encapsulated in a GstProtectionMeta object and attached to
 * the corresponding output buffer using the gst_buffer_add_protection_meta()
 * function. The information in this attached GstProtectionMeta would be
 * used by a downstream decrypter element to recover the original unencrypted
 * frame.
 *
 * Since: 1.6
 */

#include "gst_private.h"
#include "glib-compat-private.h"

#include "gstprotection.h"

#define GST_CAT_DEFAULT GST_CAT_PROTECTION

static gboolean gst_protection_meta_init (GstMeta * meta, gpointer params,
    GstBuffer * buffer);

static void gst_protection_meta_free (GstMeta * meta, GstBuffer * buffer);

static const gchar *gst_protection_factory_check (GstElementFactory * fact,
    const gchar ** system_identifiers);

GType
gst_protection_meta_api_get_type (void)
{
  static volatile GType type;
  static const gchar *tags[] = { NULL };

  if (g_once_init_enter (&type)) {
    GType _type = gst_meta_api_type_register ("GstProtectionMetaAPI", tags);
    g_once_init_leave (&type, _type);
  }
  return type;
}

static gboolean
gst_protection_meta_init (GstMeta * meta, gpointer params, GstBuffer * buffer)
{
  GstProtectionMeta *protection_meta = (GstProtectionMeta *) meta;

  protection_meta->info = NULL;

  return TRUE;
}

static void
gst_protection_meta_free (GstMeta * meta, GstBuffer * buffer)
{
  GstProtectionMeta *protection_meta = (GstProtectionMeta *) meta;

  if (protection_meta->info)
    gst_structure_free (protection_meta->info);
}

const GstMetaInfo *
gst_protection_meta_get_info (void)
{
  static const GstMetaInfo *protection_meta_info = NULL;

  if (g_once_init_enter (&protection_meta_info)) {
    const GstMetaInfo *meta =
        gst_meta_register (GST_PROTECTION_META_API_TYPE, "GstProtectionMeta",
        sizeof (GstProtectionMeta), gst_protection_meta_init,
        gst_protection_meta_free,
        (GstMetaTransformFunction) NULL);

    g_once_init_leave (&protection_meta_info, meta);
  }
  return protection_meta_info;
}

/**
 * gst_buffer_add_protection_meta:
 * @buffer: #GstBuffer holding an encrypted sample, to which protection
 *     metadata should be added.
 * @info: (transfer full): a #GstStructure holding cryptographic
 *     information relating to the sample contained in @buffer. This
 *     function takes ownership of @info.
 *
 * Attaches protection metadata to a #GstBuffer.
 *
 * Returns: (transfer none): a pointer to the added #GstProtectionMeta if successful; %NULL if
 * unsuccessful.
 *
 * Since: 1.6
 */
GstProtectionMeta *
gst_buffer_add_protection_meta (GstBuffer * buffer, GstStructure * info)
{
  GstProtectionMeta *meta;

  g_return_val_if_fail (GST_IS_BUFFER (buffer), NULL);
  g_return_val_if_fail (info != NULL, NULL);

  meta =
      (GstProtectionMeta *) gst_buffer_add_meta (buffer,
      GST_PROTECTION_META_INFO, NULL);

  meta->info = info;

  return meta;
}

/**
 * gst_protection_select_system:
 * @system_identifiers: (transfer none): A null terminated array of strings
 * that contains the UUID values of each protection system that is to be
 * checked.
 *
 * Iterates the supplied list of UUIDs and checks the GstRegistry for
 * an element that supports one of the supplied UUIDs. If more than one
 * element matches, the system ID of the highest ranked element is selected.
 *
 * Returns: (transfer none): One of the strings from @system_identifiers that
 * indicates the highest ranked element that implements the protection system
 * indicated by that system ID, or %NULL if no element has been found.
 *
 * Since: 1.6
 */
const gchar *
gst_protection_select_system (const gchar ** system_identifiers)
{
  GList *decryptors, *walk;
  const gchar *retval = NULL;

  decryptors =
      gst_element_factory_list_get_elements (GST_ELEMENT_FACTORY_TYPE_DECRYPTOR,
      GST_RANK_MARGINAL);

  for (walk = decryptors; !retval && walk; walk = g_list_next (walk)) {
    GstElementFactory *fact = (GstElementFactory *) walk->data;

    retval = gst_protection_factory_check (fact, system_identifiers);
  }

  gst_plugin_feature_list_free (decryptors);

  return retval;
}

static const gchar *
gst_protection_factory_check (GstElementFactory * fact,
    const gchar ** system_identifiers)
{
  const GList *template, *walk;
  const gchar *retval = NULL;

  template = gst_element_factory_get_static_pad_templates (fact);
  for (walk = template; walk && !retval; walk = g_list_next (walk)) {
    GstStaticPadTemplate *templ = walk->data;
    GstCaps *caps = gst_static_pad_template_get_caps (templ);
    guint leng = gst_caps_get_size (caps);

    for (guint i = 0; !retval && i < leng; ++i) {
      GstStructure *st;

      st = gst_caps_get_structure (caps, i);
      if (gst_structure_has_field_typed (st,
              GST_PROTECTION_SYSTEM_ID_CAPS_FIELD, G_TYPE_STRING)) {
        const gchar *sys_id =
            gst_structure_get_string (st, GST_PROTECTION_SYSTEM_ID_CAPS_FIELD);
        GST_DEBUG ("Found decryptor that supports protection system %s",
            sys_id);
        for (guint j = 0; !retval && system_identifiers[j]; ++j) {
          GST_TRACE ("  compare with %s", system_identifiers[j]);
          if (g_ascii_strcasecmp (system_identifiers[j], sys_id) == 0) {
            GST_DEBUG ("  Selecting %s", system_identifiers[j]);
            retval = system_identifiers[j];
          }
        }
      }
    }
    gst_caps_unref (caps);
  }

  return retval;
}
