Blame gst/debugutils/breakmydata.c

Packit 1f69a5
/* GStreamer
Packit 1f69a5
 * Copyright (C) 2004 Benjamin Otte <otte@gnome.org>
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-breakmydata
Packit 1f69a5
 *
Packit 1f69a5
 * This element modifies the contents of the buffer it is passed randomly
Packit 1f69a5
 * according to the parameters set.
Packit 1f69a5
 * It otherwise acts as an identity.
Packit 1f69a5
 */
Packit 1f69a5
Packit 1f69a5
#ifdef HAVE_CONFIG_H
Packit 1f69a5
#  include "config.h"
Packit 1f69a5
#endif
Packit 1f69a5
Packit 1f69a5
#include <gst/gst.h>
Packit 1f69a5
#include <gst/base/gstbasetransform.h>
Packit 1f69a5
Packit 1f69a5
GST_DEBUG_CATEGORY_STATIC (gst_break_my_data_debug);
Packit 1f69a5
#define GST_CAT_DEFAULT gst_break_my_data_debug
Packit 1f69a5
Packit 1f69a5
#define GST_TYPE_BREAK_MY_DATA \
Packit 1f69a5
  (gst_break_my_data_get_type())
Packit 1f69a5
#define GST_BREAK_MY_DATA(obj) \
Packit 1f69a5
  (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BREAK_MY_DATA,GstBreakMyData))
Packit 1f69a5
#define GST_BREAK_MY_DATA_CLASS(klass) \
Packit 1f69a5
  (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BREAK_MY_DATA,GstBreakMyDataClass))
Packit 1f69a5
#define GST_IS_BREAK_MY_DATA(obj) \
Packit 1f69a5
  (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BREAK_MY_DATA))
Packit 1f69a5
#define GST_IS_BREAK_MY_DATA_CLASS(klass) \
Packit 1f69a5
  (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BREAK_MY_DATA))
Packit 1f69a5
Packit 1f69a5
GType gst_break_my_data_get_type (void);
Packit 1f69a5
Packit 1f69a5
enum
Packit 1f69a5
{
Packit 1f69a5
  PROP_0,
Packit 1f69a5
  PROP_SEED,
Packit 1f69a5
  PROP_SET_TO,
Packit 1f69a5
  PROP_SKIP,
Packit 1f69a5
  PROP_PROBABILITY
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
typedef struct _GstBreakMyData GstBreakMyData;
Packit 1f69a5
typedef struct _GstBreakMyDataClass GstBreakMyDataClass;
Packit 1f69a5
Packit 1f69a5
struct _GstBreakMyData
Packit 1f69a5
{
Packit 1f69a5
  GstBaseTransform basetransform;
Packit 1f69a5
Packit 1f69a5
  GRand *rand;
Packit 1f69a5
  guint skipped;
Packit 1f69a5
Packit 1f69a5
  guint32 seed;
Packit 1f69a5
  gint set;
Packit 1f69a5
  guint skip;
Packit 1f69a5
  gdouble probability;
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
struct _GstBreakMyDataClass
Packit 1f69a5
{
Packit 1f69a5
  GstBaseTransformClass parent_class;
Packit 1f69a5
};
Packit 1f69a5
Packit 1f69a5
static void gst_break_my_data_set_property (GObject * object,
Packit 1f69a5
    guint prop_id, const GValue * value, GParamSpec * pspec);
Packit 1f69a5
static void gst_break_my_data_get_property (GObject * object,
Packit 1f69a5
    guint prop_id, GValue * value, GParamSpec * pspec);
Packit 1f69a5
Packit 1f69a5
static GstFlowReturn gst_break_my_data_transform_ip (GstBaseTransform * trans,
Packit 1f69a5
    GstBuffer * buf);
Packit 1f69a5
static gboolean gst_break_my_data_stop (GstBaseTransform * trans);
Packit 1f69a5
static gboolean gst_break_my_data_start (GstBaseTransform * trans);
Packit 1f69a5
Packit 1f69a5
GstStaticPadTemplate bmd_src_template = GST_STATIC_PAD_TEMPLATE ("src",
Packit 1f69a5
    GST_PAD_SRC,
Packit 1f69a5
    GST_PAD_ALWAYS,
Packit 1f69a5
    GST_STATIC_CAPS_ANY);
Packit 1f69a5
Packit 1f69a5
GstStaticPadTemplate bmd_sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
Packit 1f69a5
    GST_PAD_SINK,
Packit 1f69a5
    GST_PAD_ALWAYS,
Packit 1f69a5
    GST_STATIC_CAPS_ANY);
Packit 1f69a5
Packit 1f69a5
#define gst_break_my_data_parent_class parent_class
Packit 1f69a5
G_DEFINE_TYPE (GstBreakMyData, gst_break_my_data, GST_TYPE_BASE_TRANSFORM);
Packit 1f69a5
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_break_my_data_class_init (GstBreakMyDataClass * klass)
Packit 1f69a5
{
Packit 1f69a5
  GstBaseTransformClass *gstbasetrans_class;
Packit 1f69a5
  GstElementClass *gstelement_class;
Packit 1f69a5
  GObjectClass *gobject_class;
Packit 1f69a5
Packit 1f69a5
  gobject_class = G_OBJECT_CLASS (klass);
Packit 1f69a5
  gstelement_class = GST_ELEMENT_CLASS (klass);
Packit 1f69a5
  gstbasetrans_class = GST_BASE_TRANSFORM_CLASS (klass);
Packit 1f69a5
Packit 1f69a5
  GST_DEBUG_CATEGORY_INIT (gst_break_my_data_debug, "breakmydata", 0,
Packit 1f69a5
      "debugging category for breakmydata element");
Packit 1f69a5
Packit 1f69a5
  gobject_class->set_property = gst_break_my_data_set_property;
Packit 1f69a5
  gobject_class->get_property = gst_break_my_data_get_property;
Packit 1f69a5
Packit 1f69a5
  g_object_class_install_property (gobject_class, PROP_SEED,
Packit 1f69a5
      g_param_spec_uint ("seed", "seed",
Packit 1f69a5
          "seed for randomness (initialized when going from READY to PAUSED)",
Packit 1f69a5
          0, G_MAXUINT32, 0,
Packit 1f69a5
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
  g_object_class_install_property (gobject_class, PROP_SET_TO,
Packit 1f69a5
      g_param_spec_int ("set-to", "set-to",
Packit 1f69a5
          "set changed bytes to this value (-1 means random value",
Packit 1f69a5
          -1, G_MAXUINT8, -1,
Packit 1f69a5
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
  g_object_class_install_property (gobject_class, PROP_SKIP,
Packit 1f69a5
      g_param_spec_uint ("skip", "skip",
Packit 1f69a5
          "amount of bytes skipped at the beginning of stream",
Packit 1f69a5
          0, G_MAXUINT, 0,
Packit 1f69a5
          G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
  g_object_class_install_property (gobject_class, PROP_PROBABILITY,
Packit 1f69a5
      g_param_spec_double ("probability", "probability",
Packit 1f69a5
          "probability for each byte in the buffer to be changed", 0.0, 1.0,
Packit 1f69a5
          0.0, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
Packit 1f69a5
Packit 1f69a5
  gst_element_class_add_static_pad_template (gstelement_class,
Packit 1f69a5
      &bmd_sink_template);
Packit 1f69a5
  gst_element_class_add_static_pad_template (gstelement_class,
Packit 1f69a5
      &bmd_src_template);
Packit 1f69a5
Packit 1f69a5
  gst_element_class_set_static_metadata (gstelement_class, "Break my data",
Packit 1f69a5
      "Testing",
Packit 1f69a5
      "randomly change data in the stream", "Benjamin Otte <otte@gnome>");
Packit 1f69a5
Packit 1f69a5
  gstbasetrans_class->transform_ip =
Packit 1f69a5
      GST_DEBUG_FUNCPTR (gst_break_my_data_transform_ip);
Packit 1f69a5
  gstbasetrans_class->start = GST_DEBUG_FUNCPTR (gst_break_my_data_start);
Packit 1f69a5
  gstbasetrans_class->stop = GST_DEBUG_FUNCPTR (gst_break_my_data_stop);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_break_my_data_init (GstBreakMyData * bmd)
Packit 1f69a5
{
Packit 1f69a5
  gst_base_transform_set_in_place (GST_BASE_TRANSFORM (bmd), TRUE);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_break_my_data_set_property (GObject * object, guint prop_id,
Packit 1f69a5
    const GValue * value, GParamSpec * pspec)
Packit 1f69a5
{
Packit 1f69a5
  GstBreakMyData *bmd = GST_BREAK_MY_DATA (object);
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_LOCK (bmd);
Packit 1f69a5
Packit 1f69a5
  switch (prop_id) {
Packit 1f69a5
    case PROP_SEED:
Packit 1f69a5
      bmd->seed = g_value_get_uint (value);
Packit 1f69a5
      break;
Packit 1f69a5
    case PROP_SET_TO:
Packit 1f69a5
      bmd->set = g_value_get_int (value);
Packit 1f69a5
      break;
Packit 1f69a5
    case PROP_SKIP:
Packit 1f69a5
      bmd->skip = g_value_get_uint (value);
Packit 1f69a5
      break;
Packit 1f69a5
    case PROP_PROBABILITY:
Packit 1f69a5
      bmd->probability = g_value_get_double (value);
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_UNLOCK (bmd);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static void
Packit 1f69a5
gst_break_my_data_get_property (GObject * object, guint prop_id, GValue * value,
Packit 1f69a5
    GParamSpec * pspec)
Packit 1f69a5
{
Packit 1f69a5
  GstBreakMyData *bmd = GST_BREAK_MY_DATA (object);
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_LOCK (bmd);
Packit 1f69a5
Packit 1f69a5
  switch (prop_id) {
Packit 1f69a5
    case PROP_SEED:
Packit 1f69a5
      g_value_set_uint (value, bmd->seed);
Packit 1f69a5
      break;
Packit 1f69a5
    case PROP_SET_TO:
Packit 1f69a5
      g_value_set_int (value, bmd->set);
Packit 1f69a5
      break;
Packit 1f69a5
    case PROP_SKIP:
Packit 1f69a5
      g_value_set_uint (value, bmd->skip);
Packit 1f69a5
      break;
Packit 1f69a5
    case PROP_PROBABILITY:
Packit 1f69a5
      g_value_set_double (value, bmd->probability);
Packit 1f69a5
      break;
Packit 1f69a5
    default:
Packit 1f69a5
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
Packit 1f69a5
      break;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_UNLOCK (bmd);
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static GstFlowReturn
Packit 1f69a5
gst_break_my_data_transform_ip (GstBaseTransform * trans, GstBuffer * buf)
Packit 1f69a5
{
Packit 1f69a5
  GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans);
Packit 1f69a5
  GstMapInfo map;
Packit 1f69a5
  gsize i;
Packit 1f69a5
Packit 1f69a5
  g_return_val_if_fail (gst_buffer_is_writable (buf), GST_FLOW_ERROR);
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_LOCK (bmd);
Packit 1f69a5
Packit 1f69a5
  if (bmd->skipped < bmd->skip) {
Packit 1f69a5
    i = bmd->skip - bmd->skipped;
Packit 1f69a5
  } else {
Packit 1f69a5
    i = 0;
Packit 1f69a5
  }
Packit 1f69a5
Packit 1f69a5
  gst_buffer_map (buf, &map, GST_MAP_READWRITE);
Packit 1f69a5
Packit 1f69a5
  GST_LOG_OBJECT (bmd,
Packit 1f69a5
      "got buffer %p (size %" G_GSIZE_FORMAT ", timestamp %" G_GUINT64_FORMAT
Packit 1f69a5
      ", offset %" G_GUINT64_FORMAT "", buf, map.size,
Packit 1f69a5
      GST_BUFFER_TIMESTAMP (buf), GST_BUFFER_OFFSET (buf));
Packit 1f69a5
Packit 1f69a5
  for (; i < map.size; i++) {
Packit 1f69a5
    if (g_rand_double_range (bmd->rand, 0, 1.0) <= bmd->probability) {
Packit 1f69a5
      guint8 new;
Packit 1f69a5
Packit 1f69a5
      if (bmd->set < 0) {
Packit 1f69a5
        new = g_rand_int_range (bmd->rand, 0, 256);
Packit 1f69a5
      } else {
Packit 1f69a5
        new = bmd->set;
Packit 1f69a5
      }
Packit 1f69a5
      GST_INFO_OBJECT (bmd,
Packit 1f69a5
          "changing byte %" G_GSIZE_FORMAT " from 0x%02X to 0x%02X", i,
Packit 1f69a5
          (guint) GST_READ_UINT8 (map.data + i), (guint) ((guint8) new));
Packit 1f69a5
      map.data[i] = new;
Packit 1f69a5
    }
Packit 1f69a5
  }
Packit 1f69a5
  /* don't overflow */
Packit 1f69a5
  bmd->skipped += MIN (G_MAXUINT - bmd->skipped, map.size);
Packit 1f69a5
Packit 1f69a5
  gst_buffer_unmap (buf, &map);
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_UNLOCK (bmd);
Packit 1f69a5
Packit 1f69a5
  return GST_FLOW_OK;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static gboolean
Packit 1f69a5
gst_break_my_data_start (GstBaseTransform * trans)
Packit 1f69a5
{
Packit 1f69a5
  GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans);
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_LOCK (bmd);
Packit 1f69a5
  bmd->rand = g_rand_new_with_seed (bmd->seed);
Packit 1f69a5
  bmd->skipped = 0;
Packit 1f69a5
  GST_OBJECT_UNLOCK (bmd);
Packit 1f69a5
Packit 1f69a5
  return TRUE;
Packit 1f69a5
}
Packit 1f69a5
Packit 1f69a5
static gboolean
Packit 1f69a5
gst_break_my_data_stop (GstBaseTransform * trans)
Packit 1f69a5
{
Packit 1f69a5
  GstBreakMyData *bmd = GST_BREAK_MY_DATA (trans);
Packit 1f69a5
Packit 1f69a5
  GST_OBJECT_LOCK (bmd);
Packit 1f69a5
  g_rand_free (bmd->rand);
Packit 1f69a5
  bmd->rand = NULL;
Packit 1f69a5
  GST_OBJECT_UNLOCK (bmd);
Packit 1f69a5
Packit 1f69a5
  return TRUE;
Packit 1f69a5
}