static void
gst_real_audio_dec_finalize (GObject * object)
{
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (object);

  close_library (dec, &dec->lib);

  if (dec->real_codecs_path) {
    g_free (dec->real_codecs_path);
    dec->real_codecs_path = NULL;
  }
  if (dec->racook_names) {
    g_free (dec->racook_names);
    dec->racook_names = NULL;
  }
  if (dec->raatrk_names) {
    g_free (dec->raatrk_names);
    dec->raatrk_names = NULL;
  }
  if (dec->ra14_4_names) {
    g_free (dec->ra14_4_names);
    dec->ra14_4_names = NULL;
  }
  if (dec->ra28_8_names) {
    g_free (dec->ra28_8_names);
    dec->ra28_8_names = NULL;
  }
  if (dec->rasipr_names) {
    g_free (dec->rasipr_names);
    dec->rasipr_names = NULL;
  }

  G_OBJECT_CLASS (parent_class)->finalize (object);
}
static GstStateChangeReturn
gst_real_audio_dec_change_state (GstElement * element,
    GstStateChange transition)
{
  GstStateChangeReturn ret;
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (element);

  switch (transition) {
    case GST_STATE_CHANGE_NULL_TO_READY:
      gst_real_audio_dec_probe_modules (dec);
      dec->checked_modules = TRUE;
      break;
    default:
      break;
  }

  ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);

  switch (transition) {
    case GST_STATE_CHANGE_PAUSED_TO_READY:
      close_library (dec, &dec->lib);
      break;
    case GST_STATE_CHANGE_READY_TO_NULL:
      dec->checked_modules = FALSE;
      break;
    default:
      break;
  }
  return ret;
}
Пример #3
0
static GstCaps *
gst_real_audio_dec_getcaps (GstPad * pad)
{
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (GST_PAD_PARENT (pad));
  GstCaps *res;

  if (dec->checked_modules) {
    GValue versions = { 0 };
    GValue version = { 0 };

    GST_LOG_OBJECT (dec, "constructing caps");
    res = gst_caps_new_empty ();

    g_value_init (&versions, GST_TYPE_LIST);
    g_value_init (&version, G_TYPE_INT);

    if (dec->valid_atrk) {
      g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_ATRK);
      gst_value_list_append_value (&versions, &version);
    }
    if (dec->valid_ra14_4) {
      g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_14_4);
      gst_value_list_append_value (&versions, &version);
    }
    if (dec->valid_ra28_8) {
      g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_28_8);
      gst_value_list_append_value (&versions, &version);
    }
    if (dec->valid_sipr) {
      g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_SIPR);
      gst_value_list_append_value (&versions, &version);
    }
    if (dec->valid_cook) {
      g_value_set_int (&version, GST_REAL_AUDIO_DEC_VERSION_COOK);
      gst_value_list_append_value (&versions, &version);
    }

    if (gst_value_list_get_size (&versions) > 0) {
      res = gst_caps_new_simple ("audio/x-pn-realaudio", NULL);
      gst_structure_set_value (gst_caps_get_structure (res, 0),
          "raversion", &versions);
    } else {
      res = gst_caps_new_empty ();
    }

    if (dec->valid_sipr) {
      gst_caps_append (res, gst_caps_new_simple ("audio/x-sipro", NULL));
    }
    g_value_unset (&versions);
    g_value_unset (&version);
  } else {
    GST_LOG_OBJECT (dec, "returning padtemplate caps");
    res = gst_caps_copy (gst_pad_get_pad_template_caps (pad));
  }
  GST_LOG_OBJECT (dec, "returning caps %" GST_PTR_FORMAT, res);

  return res;
}
static GstFlowReturn
gst_real_audio_dec_chain (GstPad * pad, GstBuffer * in)
{
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (GST_PAD_PARENT (pad));
  GstFlowReturn flow;
  GstClockTime timestamp;
  GstBuffer *out = NULL;
  guint16 res = 0;
  guint len;

  if (G_UNLIKELY (dec->lib.RADecode == NULL || dec->lib.module == NULL))
    goto not_negotiated;

  timestamp = GST_BUFFER_TIMESTAMP (in);

  flow = gst_pad_alloc_buffer (dec->src, GST_BUFFER_OFFSET_NONE,
      dec->width * dec->leaf_size * dec->height * 16,
      GST_PAD_CAPS (dec->src), &out);

  if (flow != GST_FLOW_OK)
    goto done;

  res = dec->lib.RADecode (dec->lib.context, GST_BUFFER_DATA (in),
      GST_BUFFER_SIZE (in), GST_BUFFER_DATA (out), &len, -1);

  if (res != 0)
    goto could_not_decode;

  GST_BUFFER_SIZE (out) = len;
  GST_BUFFER_TIMESTAMP (out) = timestamp;

  flow = gst_pad_push (dec->src, out);

done:
  gst_buffer_unref (in);
  return flow;

  /* Errors */
could_not_decode:
  {
    gst_buffer_unref (out);
    GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL),
        ("Could not decode buffer (%i).", res));
    flow = GST_FLOW_ERROR;
    goto done;
  }
not_negotiated:
  {
    GST_WARNING_OBJECT (dec, "decoder not open, probably no input caps set "
        "yet, caps on input buffer: %" GST_PTR_FORMAT, GST_BUFFER_CAPS (in));
    flow = GST_FLOW_NOT_NEGOTIATED;
    goto done;
  }
}
static void
gst_real_audio_dec_set_property (GObject * object, guint prop_id,
    const GValue * value, GParamSpec * pspec)
{
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (object);

  switch (prop_id) {
    case PROP_REAL_CODECS_PATH:
      if (dec->real_codecs_path)
        g_free (dec->real_codecs_path);
      dec->real_codecs_path = g_value_dup_string (value);
      break;
    case PROP_RACOOK_NAMES:
      if (dec->racook_names)
        g_free (dec->racook_names);
      dec->racook_names = g_value_dup_string (value);
      break;
    case PROP_RAATRK_NAMES:
      if (dec->raatrk_names)
        g_free (dec->raatrk_names);
      dec->raatrk_names = g_value_dup_string (value);
      break;
    case PROP_RA14_4_NAMES:
      if (dec->ra14_4_names)
        g_free (dec->ra14_4_names);
      dec->ra14_4_names = g_value_dup_string (value);
      break;
    case PROP_RA28_8_NAMES:
      if (dec->ra28_8_names)
        g_free (dec->ra28_8_names);
      dec->ra28_8_names = g_value_dup_string (value);
      break;
    case PROP_RASIPR_NAMES:
      if (dec->rasipr_names)
        g_free (dec->rasipr_names);
      dec->rasipr_names = g_value_dup_string (value);
      break;
    case PROP_PASSWORD:
      if (dec->pwd)
        g_free (dec->pwd);
      dec->pwd = g_value_dup_string (value);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static void
gst_real_audio_dec_get_property (GObject * object, guint prop_id,
    GValue * value, GParamSpec * pspec)
{
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (object);

  switch (prop_id) {
    case PROP_REAL_CODECS_PATH:
      g_value_set_string (value, dec->real_codecs_path ? dec->real_codecs_path
          : DEFAULT_REAL_CODECS_PATH);
      break;
    case PROP_RACOOK_NAMES:
      g_value_set_string (value, dec->racook_names ? dec->racook_names :
          DEFAULT_RACOOK_NAMES);
      break;
    case PROP_RAATRK_NAMES:
      g_value_set_string (value, dec->raatrk_names ? dec->raatrk_names :
          DEFAULT_RAATRK_NAMES);
      break;
    case PROP_RA14_4_NAMES:
      g_value_set_string (value, dec->ra14_4_names ? dec->ra14_4_names :
          DEFAULT_RA14_4_NAMES);
      break;
    case PROP_RA28_8_NAMES:
      g_value_set_string (value, dec->ra28_8_names ? dec->ra28_8_names :
          DEFAULT_RA28_8_NAMES);
      break;
    case PROP_RASIPR_NAMES:
      g_value_set_string (value, dec->rasipr_names ? dec->rasipr_names :
          DEFAULT_RASIPR_NAMES);
      break;
    case PROP_PASSWORD:
      g_value_set_string (value, dec->pwd ? dec->pwd : DEFAULT_PWD);
      break;
    default:
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
      break;
  }
}
static gboolean
gst_real_audio_dec_setcaps (GstPad * pad, GstCaps * caps)
{
  GstRealAudioDec *dec = GST_REAL_AUDIO_DEC (GST_PAD_PARENT (pad));
  GstStructure *s = gst_caps_get_structure (caps, 0);
  gint version, flavor, channels, rate, leaf_size, packet_size, width, height;
  guint16 res = 0;
  RAInit data;
  gboolean bres;
  const GValue *v;
  GstBuffer *buf = NULL;
  const gchar *name = gst_structure_get_name (s);

  if (!strcmp (name, "audio/x-sipro")) {
    version = GST_REAL_AUDIO_DEC_VERSION_SIPR;
  } else {
    if (!gst_structure_get_int (s, "raversion", &version))
      goto missing_keys;
  }

  if (!gst_structure_get_int (s, "flavor", &flavor) ||
      !gst_structure_get_int (s, "channels", &channels) ||
      !gst_structure_get_int (s, "width", &width) ||
      !gst_structure_get_int (s, "rate", &rate) ||
      !gst_structure_get_int (s, "height", &height) ||
      !gst_structure_get_int (s, "leaf_size", &leaf_size) ||
      !gst_structure_get_int (s, "packet_size", &packet_size))
    goto missing_keys;

  if ((v = gst_structure_get_value (s, "codec_data")))
    buf = g_value_peek_pointer (v);

  GST_LOG_OBJECT (dec, "opening code for version %d", version);

  /* first close existing decoder */
  close_library (dec, &dec->lib);

  if (!open_library (dec, version, &dec->lib))
    goto could_not_open;

  /* we have the module, no initialize with the caps data */
  data.samplerate = rate;
  data.width = width;
  data.channels = channels;
  data.quality = 100;
  data.leaf_size = leaf_size;
  data.packet_size = packet_size;
  data.datalen = buf ? GST_BUFFER_SIZE (buf) : 0;
  data.data = buf ? GST_BUFFER_DATA (buf) : NULL;

  if ((res = dec->lib.RAInitDecoder (dec->lib.context, &data))) {
    GST_WARNING_OBJECT (dec, "RAInitDecoder() failed");
    goto could_not_initialize;
  }

  if (dec->lib.RASetPwd) {
    dec->lib.RASetPwd (dec->lib.context, dec->pwd ? dec->pwd : DEFAULT_PWD);
  }

  if ((res = dec->lib.RASetFlavor (dec->lib.context, flavor))) {
    GST_WARNING_OBJECT (dec, "RASetFlavor(%d) failed", flavor);
    goto could_not_initialize;
  }

  caps = gst_caps_new_simple ("audio/x-raw-int",
      "endianness", G_TYPE_INT, G_BYTE_ORDER,
      "width", G_TYPE_INT, width,
      "depth", G_TYPE_INT, width,
      "rate", G_TYPE_INT, rate,
      "channels", G_TYPE_INT, channels, "signed", G_TYPE_BOOLEAN, TRUE, NULL);
  bres = gst_pad_set_caps (GST_PAD (dec->src), caps);
  gst_caps_unref (caps);
  if (!bres)
    goto could_not_set_caps;

  dec->width = width;
  dec->height = height;
  dec->leaf_size = leaf_size;

  GST_LOG_OBJECT (dec, "opened module");

  return TRUE;

missing_keys:
  {
    GST_DEBUG_OBJECT (dec, "Could not find all necessary keys in structure.");
    return FALSE;
  }
could_not_open:
  {
    GST_DEBUG_OBJECT (dec, "Could not find decoder");
    return FALSE;
  }
could_not_initialize:
  {
    close_library (dec, &dec->lib);
    GST_WARNING_OBJECT (dec, "Initialization of REAL driver failed (%i).", res);
    return FALSE;
  }
could_not_set_caps:
  {
    /* should normally not fail */
    close_library (dec, &dec->lib);
    GST_DEBUG_OBJECT (dec, "Could not convince peer to accept caps.");
    return FALSE;
  }
}