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

📄 gstavdtpsink.c

📁 这是Linux环境下的蓝牙源代码
💻 C
📖 第 1 页 / 共 3 页
字号:
	GST_DEBUG_OBJECT(self, "stream start packet sent");	io_error = gst_avdtp_sink_audioservice_expect(self,			&rsp->rsp_h.msg_h, BT_STREAMSTART_RSP);	if (io_error != G_IO_ERROR_NONE) {		GST_ERROR_OBJECT(self, "Error while stream "			"start confirmation");		return FALSE;	}	if (rsp->rsp_h.posix_errno != 0) {		GST_ERROR_OBJECT(self, "BT_STREAMSTART_RSP failed : %s(%d)",					strerror(rsp->rsp_h.posix_errno),					rsp->rsp_h.posix_errno);		return FALSE;	}	GST_DEBUG_OBJECT(self, "stream started");	io_error = gst_avdtp_sink_audioservice_expect(self, &ind->h,			BT_STREAMFD_IND);	if (io_error != G_IO_ERROR_NONE) {		GST_ERROR_OBJECT(self, "Error while receiving "			"stream filedescriptor");		return FALSE;	}	if (!gst_avdtp_sink_conf_recv_stream_fd(self))		return FALSE;	return TRUE;}static gboolean gst_avdtp_sink_init_mp3_pkt_conf(		GstAvdtpSink *self, GstCaps *caps,		mpeg_capabilities_t *pkt){	const GValue *value = NULL;	gint rate, layer;	const gchar* name;	GstStructure *structure = gst_caps_get_structure(caps, 0);	name = gst_structure_get_name(structure);	if (!(IS_MPEG_AUDIO(name))) {		GST_ERROR_OBJECT(self, "Unexpected format %s, "				"was expecting mp3", name);		return FALSE;	}	/* layer */	value = gst_structure_get_value(structure, "layer");	layer = g_value_get_int(value);	if (layer == 1)		pkt->layer = BT_MPEG_LAYER_1;	else if (layer == 2)		pkt->layer = BT_MPEG_LAYER_2;	else if (layer == 3)		pkt->layer = BT_MPEG_LAYER_3;	else {		GST_ERROR_OBJECT(self, "Unexpected layer: %d", layer);		return FALSE;	}	/* crc */	if (self->mp3_using_crc != -1)		pkt->crc = self->mp3_using_crc;	else {		GST_ERROR_OBJECT(self, "No info about crc was received, "				" can't proceed");		return FALSE;	}	/* channel mode */	if (self->channel_mode != -1)		pkt->channel_mode = self->channel_mode;	else {		GST_ERROR_OBJECT(self, "No info about channel mode "				"received, can't proceed");		return FALSE;	}	/* mpf - we will only use the mandatory one */	pkt->mpf = 0;	value = gst_structure_get_value(structure, "rate");	rate = g_value_get_int(value);	if (rate == 44100)		pkt->frequency = BT_MPEG_SAMPLING_FREQ_44100;	else if (rate == 48000)		pkt->frequency = BT_MPEG_SAMPLING_FREQ_48000;	else if (rate == 32000)		pkt->frequency = BT_MPEG_SAMPLING_FREQ_32000;	else if (rate == 24000)		pkt->frequency = BT_MPEG_SAMPLING_FREQ_24000;	else if (rate == 22050)		pkt->frequency = BT_MPEG_SAMPLING_FREQ_22050;	else if (rate == 16000)		pkt->frequency = BT_MPEG_SAMPLING_FREQ_16000;	else {		GST_ERROR_OBJECT(self, "Invalid rate while setting caps");		return FALSE;	}	/* vbr - we always say its vbr, we don't have how to know it */	pkt->bitrate = 0x8000;	return TRUE;}static gboolean gst_avdtp_sink_configure(GstAvdtpSink *self,			GstCaps *caps){	gchar buf[BT_AUDIO_IPC_PACKET_SIZE];	struct bt_setconfiguration_req *req = (void *) buf;	struct bt_setconfiguration_rsp *rsp = (void *) buf;	gboolean ret;	GIOError io_error;	gchar *temp;	GstStructure *structure;	temp = gst_caps_to_string(caps);	GST_DEBUG_OBJECT(self, "configuring device with caps: %s", temp);	g_free(temp);	memset (req, 0, sizeof(buf));	req->h.msg_type = BT_SETCONFIGURATION_REQ;	req->access_mode = BT_CAPABILITIES_ACCESS_MODE_WRITE;	strncpy(req->device, self->device, 18);	structure = gst_caps_get_structure(caps, 0);	if (gst_structure_has_name(structure, "audio/x-sbc"))		ret = gst_avdtp_sink_init_sbc_pkt_conf(self, caps,				&req->sbc_capabilities);	else if (gst_structure_has_name(structure, "audio/mpeg"))		ret = gst_avdtp_sink_init_mp3_pkt_conf(self, caps,				&req->mpeg_capabilities);	else		ret = FALSE;	if (!ret) {		GST_ERROR_OBJECT(self, "Couldn't parse caps "				"to packet configuration");		return FALSE;	}	io_error = gst_avdtp_sink_audioservice_send(self, &req->h);	if (io_error != G_IO_ERROR_NONE) {		GST_ERROR_OBJECT(self, "Error ocurred while sending "					"configurarion packet");		return FALSE;	}	GST_DEBUG_OBJECT(self, "configuration packet sent");	io_error = gst_avdtp_sink_audioservice_expect(self,			&rsp->rsp_h.msg_h, BT_SETCONFIGURATION_RSP);	if (io_error != G_IO_ERROR_NONE) {		GST_ERROR_OBJECT(self, "Error while receiving device "					"confirmation");		return FALSE;	}	if (rsp->rsp_h.posix_errno != 0) {		GST_ERROR_OBJECT(self, "BT_SETCONFIGURATION_RSP failed : "					"%s(%d)",					strerror(rsp->rsp_h.posix_errno),					rsp->rsp_h.posix_errno);		return FALSE;	}	self->data->link_mtu = rsp->link_mtu;	GST_DEBUG_OBJECT(self, "configuration set");	return TRUE;}static GstFlowReturn gst_avdtp_sink_preroll(GstBaseSink *basesink,					GstBuffer *buffer){	GstAvdtpSink *sink = GST_AVDTP_SINK(basesink);	gboolean ret;	GST_AVDTP_SINK_MUTEX_LOCK(sink);	ret = gst_avdtp_sink_stream_start(sink);	GST_AVDTP_SINK_MUTEX_UNLOCK(sink);	if (!ret)		return GST_FLOW_ERROR;	return GST_FLOW_OK;}static GstFlowReturn gst_avdtp_sink_render(GstBaseSink *basesink,					GstBuffer *buffer){	GstAvdtpSink *self = GST_AVDTP_SINK(basesink);	gsize ret;	GIOError err;	err = g_io_channel_write(self->stream, (gchar*)GST_BUFFER_DATA(buffer),			 (gsize)(GST_BUFFER_SIZE(buffer)), &ret);	if (err != G_IO_ERROR_NONE) {		GST_ERROR_OBJECT(self, "Error while writting to socket: %d %s",				errno, strerror(errno));		return GST_FLOW_ERROR;	}	return GST_FLOW_OK;}static gboolean gst_avdtp_sink_unlock(GstBaseSink *basesink){	GstAvdtpSink *self = GST_AVDTP_SINK(basesink);	if (self->stream != NULL)		g_io_channel_flush (self->stream, NULL);	return TRUE;}static GstFlowReturn gst_avdtp_sink_buffer_alloc(GstBaseSink *basesink,				guint64 offset, guint size, GstCaps* caps,				GstBuffer **buf){	GstAvdtpSink *self = GST_AVDTP_SINK(basesink);	*buf = gst_buffer_new_and_alloc(size);	if (!(*buf)) {		GST_ERROR_OBJECT(self, "buffer allocation failed");		return GST_FLOW_ERROR;	}	gst_buffer_set_caps(*buf, caps);	GST_BUFFER_OFFSET(*buf) = offset;	return GST_FLOW_OK;}static void gst_avdtp_sink_class_init(GstAvdtpSinkClass *klass){	GObjectClass *object_class = G_OBJECT_CLASS(klass);	GstBaseSinkClass *basesink_class = GST_BASE_SINK_CLASS(klass);	parent_class = g_type_class_peek_parent(klass);	object_class->finalize = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_finalize);	object_class->set_property = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_set_property);	object_class->get_property = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_get_property);	basesink_class->start = GST_DEBUG_FUNCPTR(gst_avdtp_sink_start);	basesink_class->stop = GST_DEBUG_FUNCPTR(gst_avdtp_sink_stop);	basesink_class->render = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_render);	basesink_class->preroll = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_preroll);	basesink_class->unlock = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_unlock);	basesink_class->event = GST_DEBUG_FUNCPTR(					gst_avdtp_sink_event);	basesink_class->buffer_alloc =		GST_DEBUG_FUNCPTR(gst_avdtp_sink_buffer_alloc);	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(avdtp_sink_debug, "avdtpsink", 0,				"A2DP headset sink element");}static void gst_avdtp_sink_init(GstAvdtpSink *self,			GstAvdtpSinkClass *klass){	self->device = NULL;	self->data = NULL;	self->stream = NULL;	self->dev_caps = NULL;	self->autoconnect = DEFAULT_AUTOCONNECT;	self->sink_lock = g_mutex_new();	/* FIXME this is for not synchronizing with clock, should be tested	 * with devices to see the behaviour	gst_base_sink_set_sync(GST_BASE_SINK(self), FALSE);	*/}static GIOError gst_avdtp_sink_audioservice_send(					GstAvdtpSink *self,					const bt_audio_msg_header_t *msg){	GIOError error;	gsize written;	error = g_io_channel_write(self->server, (const gchar*) msg,			BT_AUDIO_IPC_PACKET_SIZE, &written);	if (error != G_IO_ERROR_NONE)		GST_ERROR_OBJECT(self, "Error sending data to audio service:"			" %s(%d)", strerror(errno), errno);	return error;}static GIOError gst_avdtp_sink_audioservice_recv(					GstAvdtpSink *self,					bt_audio_msg_header_t *inmsg){	GIOError status;	gsize bytes_read;	const char *type;	status = g_io_channel_read(self->server, (gchar*) inmsg,			BT_AUDIO_IPC_PACKET_SIZE, &bytes_read);	if (status != G_IO_ERROR_NONE) {		GST_ERROR_OBJECT(self, "Error receiving data from "				"audio service");		return status;	}	type = bt_audio_strmsg(inmsg->msg_type);	if (!type) {		status = G_IO_ERROR_INVAL;		GST_ERROR_OBJECT(self, "Bogus message type %d "				"received from audio service",				inmsg->msg_type);	}	return status;}static GIOError gst_avdtp_sink_audioservice_expect(			GstAvdtpSink *self, bt_audio_msg_header_t *outmsg,			int expected_type){	GIOError status;	status = gst_avdtp_sink_audioservice_recv(self, outmsg);	if (status != G_IO_ERROR_NONE)		return status;	if (outmsg->msg_type != expected_type)		status = G_IO_ERROR_INVAL;	return status;}gboolean gst_avdtp_sink_plugin_init (GstPlugin * plugin){	return gst_element_register (plugin, "avdtpsink",			GST_RANK_NONE, GST_TYPE_AVDTP_SINK);}/* public functions */GstCaps *gst_avdtp_sink_get_device_caps(GstAvdtpSink *sink){	if (sink->dev_caps == NULL)		return NULL;	return gst_caps_copy(sink->dev_caps);}gboolean gst_avdtp_sink_set_device_caps(GstAvdtpSink *self,			GstCaps *caps){	gboolean ret;	GST_DEBUG_OBJECT(self, "setting device caps");	GST_AVDTP_SINK_MUTEX_LOCK(self);	ret = gst_avdtp_sink_configure(self, caps);	if (self->stream_caps)		gst_caps_unref(self->stream_caps);	self->stream_caps = gst_caps_ref(caps);	GST_AVDTP_SINK_MUTEX_UNLOCK(self);	return ret;}guint gst_avdtp_sink_get_link_mtu(GstAvdtpSink *sink){	return sink->data->link_mtu;}void gst_avdtp_sink_set_device(GstAvdtpSink *self, const gchar* dev){	if (self->device != NULL)		g_free(self->device);	GST_LOG_OBJECT(self, "Setting device: %s", dev);	self->device = g_strdup(dev);}gchar *gst_avdtp_sink_get_device(GstAvdtpSink *self){	return g_strdup(self->device);}void gst_avdtp_sink_set_crc(GstAvdtpSink *self, gboolean crc){	gint new_crc;	new_crc = crc ? CRC_PROTECTED : CRC_UNPROTECTED;	/* test if we already received a different crc */	if (self->mp3_using_crc != -1 && new_crc != self->mp3_using_crc) {		GST_WARNING_OBJECT(self, "crc changed during stream");		return;	}	self->mp3_using_crc = new_crc;}void gst_avdtp_sink_set_channel_mode(GstAvdtpSink *self,			const gchar *mode){	gint new_mode;	new_mode = gst_avdtp_sink_get_channel_mode(mode);	if (self->channel_mode != -1 && new_mode != self->channel_mode) {		GST_WARNING_OBJECT(self, "channel mode changed during stream");		return;	}	self->channel_mode = new_mode;	if (self->channel_mode == -1)		GST_WARNING_OBJECT(self, "Received invalid channel "				"mode: %s", mode);}

⌨️ 快捷键说明

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