/* 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: 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, PROTECTION_SYSTEM_ID_CAPS_FIELD,
              G_TYPE_STRING)) {
        const gchar *sys_id =
            gst_structure_get_string (st, 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;
}
