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; }
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; } }