mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-18 15:51:11 +00:00
bluez: Fix gstreamer plugin to reflect the ipc changes.
This commit is contained in:
parent
4fd14e4113
commit
b03faa59d1
1 changed files with 92 additions and 62 deletions
|
@ -63,7 +63,7 @@ GST_DEBUG_CATEGORY_STATIC (avdtp_sink_debug);
|
|||
|
||||
struct bluetooth_data
|
||||
{
|
||||
struct bt_getcapabilities_rsp caps; /* Bluetooth device caps */
|
||||
struct bt_get_capabilities_rsp *caps; /* Bluetooth device caps */
|
||||
guint link_mtu;
|
||||
|
||||
gchar buffer[BUFFER_SIZE]; /* Codec transfer buffer */
|
||||
|
@ -110,7 +110,7 @@ static GstStaticPadTemplate avdtp_sink_factory =
|
|||
static GIOError gst_avdtp_sink_audioservice_send (GstAvdtpSink * self,
|
||||
const bt_audio_msg_header_t * msg);
|
||||
static GIOError gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self,
|
||||
bt_audio_msg_header_t * outmsg, int expected_type);
|
||||
bt_audio_msg_header_t * outmsg, guint8 expected_name);
|
||||
|
||||
|
||||
static void
|
||||
|
@ -245,16 +245,38 @@ gst_avdtp_sink_bluetooth_recvmsg_fd (GstAvdtpSink * sink)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static codec_capabilities_t *
|
||||
gst_avdtp_find_caps (GstAvdtpSink * sink, uint8_t codec_type)
|
||||
{
|
||||
struct bt_get_capabilities_rsp *rsp = sink->data->caps;
|
||||
codec_capabilities_t *codec = (void *) rsp->data;
|
||||
int bytes_left = rsp->h.length - sizeof (*rsp);
|
||||
|
||||
while (bytes_left > 0) {
|
||||
if (codec->type == codec_type)
|
||||
break;
|
||||
|
||||
bytes_left -= codec->length;
|
||||
codec = (void *) codec + codec->length;
|
||||
}
|
||||
|
||||
if (bytes_left <= 0)
|
||||
return NULL;
|
||||
|
||||
return codec;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_avdtp_sink_init_sbc_pkt_conf (GstAvdtpSink * sink,
|
||||
GstCaps * caps, sbc_capabilities_t * pkt)
|
||||
{
|
||||
sbc_capabilities_t *cfg = &sink->data->caps.sbc_capabilities;
|
||||
sbc_capabilities_t *cfg;
|
||||
const GValue *value = NULL;
|
||||
const char *pref, *name;
|
||||
gint rate, subbands, blocks;
|
||||
GstStructure *structure = gst_caps_get_structure (caps, 0);
|
||||
|
||||
cfg = (void *) gst_avdtp_find_caps (sink, BT_A2DP_CODEC_SBC);
|
||||
name = gst_structure_get_name (structure);
|
||||
|
||||
if (!(IS_SBC (name))) {
|
||||
|
@ -589,6 +611,9 @@ gst_avdtp_sink_parse_mpeg_caps (GstAvdtpSink * self, mpeg_capabilities_t * mpeg)
|
|||
gboolean valid_layer = FALSE;
|
||||
gboolean mono, stereo;
|
||||
|
||||
if (!mpeg)
|
||||
return NULL;
|
||||
|
||||
GST_LOG_OBJECT (self, "parsing mpeg caps");
|
||||
|
||||
structure = gst_structure_empty_new ("audio/mpeg");
|
||||
|
@ -702,14 +727,17 @@ gst_avdtp_sink_parse_mpeg_caps (GstAvdtpSink * self, mpeg_capabilities_t * mpeg)
|
|||
static gboolean
|
||||
gst_avdtp_sink_update_caps (GstAvdtpSink * self)
|
||||
{
|
||||
sbc_capabilities_t *sbc = &self->data->caps.sbc_capabilities;
|
||||
mpeg_capabilities_t *mpeg = &self->data->caps.mpeg_capabilities;
|
||||
sbc_capabilities_t *sbc;
|
||||
mpeg_capabilities_t *mpeg;
|
||||
GstStructure *sbc_structure;
|
||||
GstStructure *mpeg_structure;
|
||||
gchar *tmp;
|
||||
|
||||
GST_LOG_OBJECT (self, "updating device caps");
|
||||
|
||||
sbc = (void *) gst_avdtp_find_caps (self, BT_A2DP_CODEC_SBC);
|
||||
mpeg = (void *) gst_avdtp_find_caps (self, BT_A2DP_CODEC_MPEG12);
|
||||
|
||||
sbc_structure = gst_avdtp_sink_parse_sbc_caps (self, sbc);
|
||||
mpeg_structure = gst_avdtp_sink_parse_mpeg_caps (self, mpeg);
|
||||
|
||||
|
@ -729,14 +757,17 @@ gst_avdtp_sink_update_caps (GstAvdtpSink * self)
|
|||
static gboolean
|
||||
gst_avdtp_sink_get_capabilities (GstAvdtpSink * self)
|
||||
{
|
||||
gchar *buf[BT_AUDIO_IPC_PACKET_SIZE];
|
||||
struct bt_getcapabilities_req *req = (void *) buf;
|
||||
struct bt_getcapabilities_rsp *rsp = (void *) buf;
|
||||
gchar *buf[BT_SUGGESTED_BUFFER_SIZE];
|
||||
struct bt_get_capabilities_req *req = (void *) buf;
|
||||
struct bt_get_capabilities_rsp *rsp = (void *) buf;
|
||||
GIOError io_error;
|
||||
|
||||
memset (req, 0, BT_AUDIO_IPC_PACKET_SIZE);
|
||||
memset (req, 0, BT_SUGGESTED_BUFFER_SIZE);
|
||||
|
||||
req->h.type = BT_REQUEST;
|
||||
req->h.name = BT_GET_CAPABILITIES;
|
||||
req->h.length = sizeof (*req);
|
||||
|
||||
req->h.msg_type = BT_GETCAPABILITIES_REQ;
|
||||
if (self->device == NULL)
|
||||
return FALSE;
|
||||
strncpy (req->device, self->device, 18);
|
||||
|
@ -750,19 +781,14 @@ gst_avdtp_sink_get_capabilities (GstAvdtpSink * self)
|
|||
}
|
||||
|
||||
io_error = gst_avdtp_sink_audioservice_expect (self,
|
||||
&rsp->rsp_h.msg_h, BT_GETCAPABILITIES_RSP);
|
||||
&rsp->h, BT_GET_CAPABILITIES);
|
||||
if (io_error != G_IO_ERROR_NONE) {
|
||||
GST_ERROR_OBJECT (self, "Error while getting device caps");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
if (rsp->rsp_h.posix_errno != 0) {
|
||||
GST_ERROR_OBJECT (self, "BT_GETCAPABILITIES failed : %s(%d)",
|
||||
strerror (rsp->rsp_h.posix_errno), rsp->rsp_h.posix_errno);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
memcpy (&self->data->caps, rsp, sizeof (*rsp));
|
||||
self->data->caps = g_malloc0 (rsp->h.length);
|
||||
memcpy (self->data->caps, rsp, rsp->h.length);
|
||||
if (!gst_avdtp_sink_update_caps (self)) {
|
||||
GST_WARNING_OBJECT (self, "failed to update capabilities");
|
||||
return FALSE;
|
||||
|
@ -882,16 +908,16 @@ failed:
|
|||
static gboolean
|
||||
gst_avdtp_sink_stream_start (GstAvdtpSink * self)
|
||||
{
|
||||
gchar buf[BT_AUDIO_IPC_PACKET_SIZE];
|
||||
struct bt_streamstart_req *req = (void *) buf;
|
||||
struct bt_streamstart_rsp *rsp = (void *) buf;
|
||||
struct bt_streamfd_ind *ind = (void *) buf;
|
||||
gchar buf[BT_SUGGESTED_BUFFER_SIZE];
|
||||
struct bt_start_stream_req *req = (void *) buf;
|
||||
struct bt_start_stream_rsp *rsp = (void *) buf;
|
||||
struct bt_new_stream_ind *ind = (void *) buf;
|
||||
GIOError io_error;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "stream start");
|
||||
|
||||
memset (req, 0, sizeof (buf));
|
||||
req->h.msg_type = BT_STREAMSTART_REQ;
|
||||
req->h.type = BT_REQUEST;
|
||||
req->h.name = BT_START_STREAM;
|
||||
req->h.length = sizeof (*req);
|
||||
|
||||
io_error = gst_avdtp_sink_audioservice_send (self, &req->h);
|
||||
if (io_error != G_IO_ERROR_NONE) {
|
||||
|
@ -899,25 +925,14 @@ gst_avdtp_sink_stream_start (GstAvdtpSink * self)
|
|||
return FALSE;
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "stream start packet sent");
|
||||
|
||||
io_error = gst_avdtp_sink_audioservice_expect (self,
|
||||
&rsp->rsp_h.msg_h, BT_STREAMSTART_RSP);
|
||||
&rsp->h, BT_START_STREAM);
|
||||
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);
|
||||
io_error = gst_avdtp_sink_audioservice_expect (self, &ind->h, BT_NEW_STREAM);
|
||||
if (io_error != G_IO_ERROR_NONE) {
|
||||
GST_ERROR_OBJECT (self, "Error while receiving " "stream filedescriptor");
|
||||
return FALSE;
|
||||
|
@ -1008,9 +1023,9 @@ gst_avdtp_sink_init_mp3_pkt_conf (GstAvdtpSink * self, GstCaps * caps,
|
|||
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;
|
||||
gchar buf[BT_SUGGESTED_BUFFER_SIZE];
|
||||
struct bt_set_configuration_req *req = (void *) buf;
|
||||
struct bt_set_configuration_rsp *rsp = (void *) buf;
|
||||
gboolean ret;
|
||||
GIOError io_error;
|
||||
gchar *temp;
|
||||
|
@ -1021,16 +1036,18 @@ gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps)
|
|||
g_free (temp);
|
||||
|
||||
memset (req, 0, sizeof (buf));
|
||||
req->h.msg_type = BT_SETCONFIGURATION_REQ;
|
||||
req->h.type = BT_REQUEST;
|
||||
req->h.name = BT_SET_CONFIGURATION;
|
||||
req->h.length = sizeof (*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);
|
||||
ret = gst_avdtp_sink_init_sbc_pkt_conf (self, caps, (void *) &req->codec);
|
||||
else if (gst_structure_has_name (structure, "audio/mpeg"))
|
||||
ret = gst_avdtp_sink_init_mp3_pkt_conf (self, caps,
|
||||
&req->mpeg_capabilities);
|
||||
ret = gst_avdtp_sink_init_mp3_pkt_conf (self, caps, (void *) &req->codec);
|
||||
else
|
||||
ret = FALSE;
|
||||
|
||||
|
@ -1046,23 +1063,14 @@ gst_avdtp_sink_configure (GstAvdtpSink * self, GstCaps * caps)
|
|||
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);
|
||||
&rsp->h, BT_SET_CONFIGURATION);
|
||||
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;
|
||||
}
|
||||
|
@ -1196,13 +1204,19 @@ gst_avdtp_sink_audioservice_send (GstAvdtpSink * self,
|
|||
{
|
||||
GIOError error;
|
||||
gsize written;
|
||||
const char *type, *name;
|
||||
|
||||
error = g_io_channel_write (self->server, (const gchar *) msg,
|
||||
BT_AUDIO_IPC_PACKET_SIZE, &written);
|
||||
BT_SUGGESTED_BUFFER_SIZE, &written);
|
||||
if (error != G_IO_ERROR_NONE)
|
||||
GST_ERROR_OBJECT (self, "Error sending data to audio service:"
|
||||
" %s(%d)", strerror (errno), errno);
|
||||
|
||||
type = bt_audio_strtype (msg->type);
|
||||
name = bt_audio_strname (msg->name);
|
||||
|
||||
GST_DEBUG_OBJECT (self, "sent: %s -> %s", type, name);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1212,28 +1226,44 @@ gst_avdtp_sink_audioservice_recv (GstAvdtpSink * self,
|
|||
{
|
||||
GIOError status;
|
||||
gsize bytes_read;
|
||||
const char *type;
|
||||
const char *type, *name;
|
||||
|
||||
status = g_io_channel_read (self->server, (gchar *) inmsg,
|
||||
BT_AUDIO_IPC_PACKET_SIZE, &bytes_read);
|
||||
BT_SUGGESTED_BUFFER_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);
|
||||
type = bt_audio_strtype (inmsg->type);
|
||||
if (!type) {
|
||||
status = G_IO_ERROR_INVAL;
|
||||
GST_ERROR_OBJECT (self, "Bogus message type %d "
|
||||
"received from audio service", inmsg->msg_type);
|
||||
"received from audio service", inmsg->type);
|
||||
}
|
||||
|
||||
name = bt_audio_strname (inmsg->name);
|
||||
if (!name) {
|
||||
status = G_IO_ERROR_INVAL;
|
||||
GST_ERROR_OBJECT (self, "Bogus message name %d "
|
||||
"received from audio service", inmsg->name);
|
||||
}
|
||||
|
||||
if (inmsg->type == BT_ERROR) {
|
||||
bt_audio_error_t *err = (void *) inmsg;
|
||||
status = G_IO_ERROR_INVAL;
|
||||
GST_ERROR_OBJECT (self, "%s failed : "
|
||||
"%s(%d)", name, strerror (err->posix_errno), err->posix_errno);
|
||||
}
|
||||
|
||||
GST_DEBUG_OBJECT (self, "received: %s <- %s", type, name);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static GIOError
|
||||
gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self,
|
||||
bt_audio_msg_header_t * outmsg, int expected_type)
|
||||
bt_audio_msg_header_t * outmsg, guint8 expected_name)
|
||||
{
|
||||
GIOError status;
|
||||
|
||||
|
@ -1241,7 +1271,7 @@ gst_avdtp_sink_audioservice_expect (GstAvdtpSink * self,
|
|||
if (status != G_IO_ERROR_NONE)
|
||||
return status;
|
||||
|
||||
if (outmsg->msg_type != expected_type)
|
||||
if (outmsg->name != expected_name)
|
||||
status = G_IO_ERROR_INVAL;
|
||||
|
||||
return status;
|
||||
|
|
Loading…
Reference in a new issue