⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 gsta2dpsink.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	element_class->change_state = GST_DEBUG_FUNCPTR(					gst_a2dp_sink_change_state);	g_object_class_install_property(object_class, PROP_DEVICE,			g_param_spec_string("device", "Device",			"Bluetooth remote device address",			NULL, G_PARAM_READWRITE));	g_object_class_install_property(object_class, PROP_AUTOCONNECT,			g_param_spec_boolean("auto-connect", "Auto-connect",			"Automatically attempt to connect to device",			DEFAULT_AUTOCONNECT, G_PARAM_READWRITE));	GST_DEBUG_CATEGORY_INIT(gst_a2dp_sink_debug, "a2dpsink", 0,				"A2DP sink element");}GstCaps *gst_a2dp_sink_get_device_caps(GstA2dpSink *self){	return gst_avdtp_sink_get_device_caps(self->sink);}static GstCaps *gst_a2dp_sink_get_caps(GstPad *pad){	GstCaps *caps;	GstCaps *caps_aux;	GstA2dpSink *self = GST_A2DP_SINK(GST_PAD_PARENT(pad));	if (self->sink == NULL) {		GST_DEBUG_OBJECT(self, "a2dpsink isn't initialized "			"returning template caps");		caps = gst_static_pad_template_get_caps(				&gst_a2dp_sink_factory);	} else {		GST_LOG_OBJECT(self, "Getting device caps");		caps = gst_a2dp_sink_get_device_caps(self);		if (caps == NULL)			caps = gst_static_pad_template_get_caps(                                &gst_a2dp_sink_factory);	}	caps_aux = gst_caps_copy(caps);	g_object_set(self->capsfilter, "caps", caps_aux, NULL);	gst_caps_unref(caps_aux);	return caps;}static gboolean gst_a2dp_sink_init_avdtp_sink(GstA2dpSink *self){	GstElement *sink;	/* check if we don't need a new sink */	if (self->sink_is_in_bin)		return TRUE;	if (self->sink == NULL)		sink = gst_element_factory_make("avdtpsink", "avdtpsink");	else		sink = GST_ELEMENT(self->sink);	if (sink == NULL) {		GST_ERROR_OBJECT(self, "Couldn't create avdtpsink");		return FALSE;	}	if (!gst_bin_add(GST_BIN(self), sink)) {		GST_ERROR_OBJECT(self, "failed to add avdtpsink "			"to the bin");		goto cleanup_and_fail;	}	if (gst_element_set_state(sink, GST_STATE_READY) ==			GST_STATE_CHANGE_FAILURE) {		GST_ERROR_OBJECT(self, "avdtpsink failed to go to ready");		goto remove_element_and_fail;	}	if (!gst_element_link(GST_ELEMENT(self->rtp), sink)) {		GST_ERROR_OBJECT(self, "couldn't link rtpsbcpay "			"to avdtpsink");		goto remove_element_and_fail;	}	self->sink = GST_AVDTP_SINK(sink);	self->sink_is_in_bin = TRUE;	g_object_set(G_OBJECT(self->sink), "device", self->device, NULL);	gst_element_set_state(sink, GST_STATE_PAUSED);	return TRUE;remove_element_and_fail:	gst_element_set_state (sink, GST_STATE_NULL);	gst_bin_remove(GST_BIN(self), sink);	return FALSE;cleanup_and_fail:	if (sink != NULL)		g_object_unref(G_OBJECT(sink));	return FALSE;}static gboolean gst_a2dp_sink_init_rtp_sbc_element(GstA2dpSink *self){	GstElement *rtppay;	/* if we already have a rtp, we don't need a new one */	if (self->rtp != NULL)		return TRUE;	rtppay = gst_a2dp_sink_init_element(self, "rtpsbcpay", "rtp",						self->capsfilter);	if (rtppay == NULL)		return FALSE;	self->rtp = GST_BASE_RTP_PAYLOAD(rtppay);	g_object_set(G_OBJECT(self->rtp), "min-frames", -1, NULL);	gst_element_set_state(rtppay, GST_STATE_PAUSED);	return TRUE;}static gboolean gst_a2dp_sink_init_rtp_mpeg_element(GstA2dpSink *self){	GstElement *rtppay;	/* check if we don't need a new rtp */	if (self->rtp)		return TRUE;	GST_LOG_OBJECT(self, "Initializing rtp mpeg element");	/* if capsfilter is not created then we can't have our rtp element */	if (self->capsfilter == NULL)		return FALSE;	rtppay = gst_a2dp_sink_init_element(self, "rtpmpapay", "rtp",					self->capsfilter);	if (rtppay == NULL)		return FALSE;	self->rtp = GST_BASE_RTP_PAYLOAD(rtppay);	gst_element_set_state(rtppay, GST_STATE_PAUSED);	return TRUE;}static gboolean gst_a2dp_sink_init_dynamic_elements(GstA2dpSink *self,						GstCaps *caps){	GstStructure *structure;	GstEvent *event;	GstPad *capsfilterpad;	gboolean crc;	gchar *mode = NULL;	structure = gst_caps_get_structure(caps, 0);	/* before everything we need to remove fakesink */	gst_a2dp_sink_remove_fakesink(self);	/* first, we need to create our rtp payloader */	if (gst_structure_has_name(structure, "audio/x-sbc")) {		GST_LOG_OBJECT(self, "sbc media received");		if (!gst_a2dp_sink_init_rtp_sbc_element(self))			return FALSE;	} else if (gst_structure_has_name(structure, "audio/mpeg")) {		GST_LOG_OBJECT(self, "mp3 media received");		if (!gst_a2dp_sink_init_rtp_mpeg_element(self))			return FALSE;	} else {		GST_ERROR_OBJECT(self, "Unexpected media type");		return FALSE;	}	if (!gst_a2dp_sink_init_avdtp_sink(self))		return FALSE;	/* check if we should push the taglist FIXME should we push this?	 * we can send the tags directly if needed */	if (self->taglist != NULL &&			gst_structure_has_name(structure, "audio/mpeg")) {		event = gst_event_new_tag(self->taglist);		/* send directly the crc */		if (gst_tag_list_get_boolean(self->taglist, "has-crc", &crc))			gst_avdtp_sink_set_crc(self->sink, crc);		if (gst_tag_list_get_string(self->taglist, "channel-mode",				&mode))			gst_avdtp_sink_set_channel_mode(self->sink, mode);		capsfilterpad = gst_ghost_pad_get_target(self->ghostpad);		gst_pad_send_event(capsfilterpad, event);		self->taglist = NULL;		g_free(mode);	}	if (!gst_avdtp_sink_set_device_caps(self->sink, caps))		return FALSE;	g_object_set(G_OBJECT(self->rtp), "mtu",		gst_avdtp_sink_get_link_mtu(self->sink), NULL);	/* we forward our new segment here if we have one */	if (self->newseg_event) {		gst_pad_send_event(GST_BASE_RTP_PAYLOAD_SINKPAD(self->rtp),					self->newseg_event);		self->newseg_event = NULL;	}	return TRUE;}static gboolean gst_a2dp_sink_set_caps(GstPad *pad, GstCaps *caps){	GstA2dpSink *self;	self = GST_A2DP_SINK(GST_PAD_PARENT(pad));	GST_INFO_OBJECT(self, "setting caps");	/* now we know the caps */	gst_a2dp_sink_init_dynamic_elements(self, caps);	return self->ghostpad_setcapsfunc(GST_PAD(self->ghostpad), caps);}/* used for catching newsegment events while we don't have a sink, for * later forwarding it to the sink */static gboolean gst_a2dp_sink_handle_event(GstPad *pad, GstEvent *event){	GstA2dpSink *self;	GstTagList *taglist = NULL;	GstObject *parent;	self = GST_A2DP_SINK(GST_PAD_PARENT(pad));	parent = gst_element_get_parent(GST_ELEMENT(self->sink));	if (GST_EVENT_TYPE(event) == GST_EVENT_NEWSEGMENT &&			parent != GST_OBJECT_CAST(self)) {		if (self->newseg_event != NULL)			gst_event_unref(self->newseg_event);		self->newseg_event = gst_event_ref(event);	} else if (GST_EVENT_TYPE(event) == GST_EVENT_TAG &&			parent != GST_OBJECT_CAST(self)) {		if (self->taglist == NULL)			gst_event_parse_tag(event, &self->taglist);		else {			gst_event_parse_tag(event, &taglist);			gst_tag_list_insert(self->taglist, taglist,					GST_TAG_MERGE_REPLACE);		}	}	if (parent != NULL)		gst_object_unref(GST_OBJECT(parent));	return self->ghostpad_eventfunc(GST_PAD(self->ghostpad), event);}static gboolean gst_a2dp_sink_init_caps_filter(GstA2dpSink *self){	GstElement *element;	element = gst_element_factory_make("capsfilter", "filter");	if (element == NULL)		goto failed;	if (!gst_bin_add(GST_BIN(self), element))		goto failed;	self->capsfilter = element;	return TRUE;failed:	GST_ERROR_OBJECT(self, "Failed to initialize caps filter");	return FALSE;}static gboolean gst_a2dp_sink_init_fakesink(GstA2dpSink *self){	if (self->fakesink != NULL)		return TRUE;	g_mutex_lock (self->cb_mutex);	self->fakesink = gst_a2dp_sink_init_element(self, "fakesink",			"fakesink", self->capsfilter);	g_mutex_unlock (self->cb_mutex);	if (!self->fakesink)		return FALSE;	return TRUE;}static gboolean gst_a2dp_sink_remove_fakesink(GstA2dpSink *self){	g_mutex_lock(self->cb_mutex);	if (self->fakesink != NULL) {		gst_element_set_locked_state(self->fakesink, TRUE);		gst_element_set_state(self->fakesink, GST_STATE_NULL);		gst_bin_remove(GST_BIN(self), self->fakesink);		self->fakesink = NULL;	}	g_mutex_unlock(self->cb_mutex);	return TRUE;}static void gst_a2dp_sink_init(GstA2dpSink *self,			GstA2dpSinkClass *klass){	self->sink = NULL;	self->fakesink = NULL;	self->rtp = NULL;	self->device = NULL;	self->autoconnect = DEFAULT_AUTOCONNECT;	self->capsfilter = NULL;	self->newseg_event = NULL;	self->taglist = NULL;	self->ghostpad = NULL;	self->sink_is_in_bin = FALSE;	self->cb_mutex = g_mutex_new();	/* we initialize our capsfilter */	gst_a2dp_sink_init_caps_filter(self);	g_object_set(self->capsfilter, "caps",		gst_static_pad_template_get_caps(&gst_a2dp_sink_factory),		NULL);	gst_a2dp_sink_init_fakesink(self);	gst_a2dp_sink_init_ghost_pad(self);}gboolean gst_a2dp_sink_plugin_init (GstPlugin * plugin){	return gst_element_register (plugin, "a2dpsink",			GST_RANK_PRIMARY, GST_TYPE_A2DP_SINK);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -