1 /*
2 *
3 * BlueZ - Bluetooth protocol stack for Linux
4 *
5 * Copyright (C) 2012 Collabora Ltd.
6 *
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 *
22 */
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include <unistd.h>
29 #include <stdint.h>
30 #include <string.h>
31 #include <poll.h>
32
33 #include <gst/rtp/gstrtppayloads.h>
34 #include "gstavdtpsrc.h"
35
36 GST_DEBUG_CATEGORY_STATIC (avdtpsrc_debug);
37 #define GST_CAT_DEFAULT (avdtpsrc_debug)
38
39 #define DEFAULT_VOLUME 127
40
41 enum
42 {
43 PROP_0,
44 PROP_TRANSPORT,
45 PROP_TRANSPORT_VOLUME,
46 };
47
48 #define parent_class gst_avdtp_src_parent_class
49 G_DEFINE_TYPE (GstAvdtpSrc, gst_avdtp_src, GST_TYPE_BASE_SRC);
50
51 static GstStaticPadTemplate gst_avdtp_src_template =
52 GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS,
53 GST_STATIC_CAPS ("application/x-rtp, "
54 "media = (string) \"audio\","
55 "payload = (int) "
56 GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
57 "clock-rate = (int) { 16000, 32000, "
58 "44100, 48000 }, " "encoding-name = (string) \"SBC\"; "
59 "application/x-rtp, "
60 "media = (string) \"audio\","
61 "payload = (int) "
62 GST_RTP_PAYLOAD_DYNAMIC_STRING ", "
63 "clock-rate = (int) { 8000, 11025, 12000, 16000, "
64 "22050, 2400, 32000, 44100, 48000, 64000, 88200, 96000 }, "
65 "encoding-name = (string) \"MP4A-LATM\"; "));
66
67 static void gst_avdtp_src_finalize (GObject * object);
68 static void gst_avdtp_src_get_property (GObject * object, guint prop_id,
69 GValue * value, GParamSpec * pspec);
70 static void gst_avdtp_src_set_property (GObject * object, guint prop_id,
71 const GValue * value, GParamSpec * pspec);
72
73 static GstCaps *gst_avdtp_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter);
74 static gboolean gst_avdtp_src_query (GstBaseSrc * bsrc, GstQuery * query);
75 static gboolean gst_avdtp_src_start (GstBaseSrc * bsrc);
76 static gboolean gst_avdtp_src_stop (GstBaseSrc * bsrc);
77 static GstFlowReturn gst_avdtp_src_create (GstBaseSrc * bsrc, guint64 offset,
78 guint length, GstBuffer ** outbuf);
79 static gboolean gst_avdtp_src_unlock (GstBaseSrc * bsrc);
80 static gboolean gst_avdtp_src_unlock_stop (GstBaseSrc * bsrc);
81
82 static void
gst_avdtp_src_class_init(GstAvdtpSrcClass * klass)83 gst_avdtp_src_class_init (GstAvdtpSrcClass * klass)
84 {
85 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
86 GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
87 GstBaseSrcClass *basesrc_class = GST_BASE_SRC_CLASS (klass);
88
89 parent_class = g_type_class_peek_parent (klass);
90
91 gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_avdtp_src_finalize);
92 gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_avdtp_src_set_property);
93 gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_avdtp_src_get_property);
94
95 basesrc_class->start = GST_DEBUG_FUNCPTR (gst_avdtp_src_start);
96 basesrc_class->stop = GST_DEBUG_FUNCPTR (gst_avdtp_src_stop);
97 basesrc_class->create = GST_DEBUG_FUNCPTR (gst_avdtp_src_create);
98 basesrc_class->unlock = GST_DEBUG_FUNCPTR (gst_avdtp_src_unlock);
99 basesrc_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_avdtp_src_unlock_stop);
100 basesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_avdtp_src_getcaps);
101 basesrc_class->query = GST_DEBUG_FUNCPTR (gst_avdtp_src_query);
102
103 g_object_class_install_property (gobject_class, PROP_TRANSPORT,
104 g_param_spec_string ("transport",
105 "Transport", "Use configured transport", NULL, G_PARAM_READWRITE));
106
107 g_object_class_install_property (gobject_class, PROP_TRANSPORT_VOLUME,
108 g_param_spec_uint ("transport-volume",
109 "Transport volume",
110 "Volume of the transport (only valid if transport is acquired)",
111 0, 127, DEFAULT_VOLUME, G_PARAM_READWRITE));
112
113 gst_element_class_set_static_metadata (element_class,
114 "Bluetooth AVDTP Source",
115 "Source/Audio/Network/RTP",
116 "Receives audio from an A2DP device",
117 "Arun Raghavan <arun.raghavan@collabora.co.uk>");
118
119 GST_DEBUG_CATEGORY_INIT (avdtpsrc_debug, "avdtpsrc", 0,
120 "Bluetooth AVDTP Source");
121
122 gst_element_class_add_static_pad_template (element_class,
123 &gst_avdtp_src_template);
124 }
125
126 static void
gst_avdtp_src_init(GstAvdtpSrc * avdtpsrc)127 gst_avdtp_src_init (GstAvdtpSrc * avdtpsrc)
128 {
129 avdtpsrc->poll = gst_poll_new (TRUE);
130
131 avdtpsrc->duration = GST_CLOCK_TIME_NONE;
132 avdtpsrc->transport_volume = DEFAULT_VOLUME;
133
134 gst_base_src_set_format (GST_BASE_SRC (avdtpsrc), GST_FORMAT_TIME);
135 gst_base_src_set_live (GST_BASE_SRC (avdtpsrc), TRUE);
136 gst_base_src_set_do_timestamp (GST_BASE_SRC (avdtpsrc), TRUE);
137 }
138
139 static void
gst_avdtp_src_finalize(GObject * object)140 gst_avdtp_src_finalize (GObject * object)
141 {
142 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (object);
143
144 gst_poll_free (avdtpsrc->poll);
145
146 gst_avdtp_connection_reset (&avdtpsrc->conn);
147
148 G_OBJECT_CLASS (parent_class)->finalize (object);
149 }
150
151 static void
gst_avdtp_src_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)152 gst_avdtp_src_get_property (GObject * object, guint prop_id,
153 GValue * value, GParamSpec * pspec)
154 {
155 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (object);
156
157 switch (prop_id) {
158 case PROP_TRANSPORT:
159 g_value_set_string (value, avdtpsrc->conn.transport);
160 break;
161
162 case PROP_TRANSPORT_VOLUME:
163 g_value_set_uint (value, avdtpsrc->transport_volume);
164 break;
165
166 default:
167 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
168 break;
169 }
170 }
171
172 static void
gst_avdtp_src_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)173 gst_avdtp_src_set_property (GObject * object, guint prop_id,
174 const GValue * value, GParamSpec * pspec)
175 {
176 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (object);
177
178 switch (prop_id) {
179 case PROP_TRANSPORT:
180 gst_avdtp_connection_set_transport (&avdtpsrc->conn,
181 g_value_get_string (value));
182 break;
183
184 case PROP_TRANSPORT_VOLUME:
185 avdtpsrc->transport_volume = g_value_get_uint (value);
186 break;
187
188 default:
189 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
190 break;
191 }
192 }
193
194 static gboolean
gst_avdtp_src_query(GstBaseSrc * bsrc,GstQuery * query)195 gst_avdtp_src_query (GstBaseSrc * bsrc, GstQuery * query)
196 {
197 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
198 gboolean ret = FALSE;
199
200 switch (GST_QUERY_TYPE (query)) {
201 case GST_QUERY_DURATION:{
202 GstFormat format;
203
204 if (avdtpsrc->duration != GST_CLOCK_TIME_NONE) {
205 gst_query_parse_duration (query, &format, NULL);
206
207 if (format == GST_FORMAT_TIME) {
208 gst_query_set_duration (query, format, (gint64) avdtpsrc->duration);
209 ret = TRUE;
210 }
211 }
212
213 break;
214 }
215
216 default:
217 ret = GST_BASE_SRC_CLASS (parent_class)->query (bsrc, query);
218 }
219
220 return ret;
221 }
222
223 static GstCaps *
gst_avdtp_src_getcaps(GstBaseSrc * bsrc,GstCaps * filter)224 gst_avdtp_src_getcaps (GstBaseSrc * bsrc, GstCaps * filter)
225 {
226 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
227 GstCaps *caps = NULL, *ret = NULL;
228
229 if (avdtpsrc->dev_caps) {
230 const GValue *value;
231 const char *format;
232 int rate;
233 GstStructure *structure = gst_caps_get_structure (avdtpsrc->dev_caps, 0);
234
235 format = gst_structure_get_name (structure);
236
237 if (g_str_equal (format, "audio/x-sbc")) {
238 /* FIXME: we can return a fixed payload type once we
239 * are in PLAYING */
240 caps = gst_caps_new_simple ("application/x-rtp",
241 "media", G_TYPE_STRING, "audio",
242 "payload", GST_TYPE_INT_RANGE, 96, 127,
243 "encoding-name", G_TYPE_STRING, "SBC", NULL);
244 } else if (g_str_equal (format, "audio/mpeg")) {
245 caps = gst_caps_new_simple ("application/x-rtp",
246 "media", G_TYPE_STRING, "audio",
247 "payload", GST_TYPE_INT_RANGE, 96, 127,
248 "encoding-name", G_TYPE_STRING, "MP4A-LATM", NULL);
249
250 value = gst_structure_get_value (structure, "mpegversion");
251 if (!value || !G_VALUE_HOLDS_INT (value)) {
252 GST_ERROR_OBJECT (avdtpsrc, "Failed to get mpegversion");
253 gst_caps_unref (caps);
254 return NULL;
255 }
256 gst_caps_set_simple (caps, "mpegversion", G_TYPE_INT,
257 g_value_get_int (value), NULL);
258
259 value = gst_structure_get_value (structure, "channels");
260 if (!value || !G_VALUE_HOLDS_INT (value)) {
261 GST_ERROR_OBJECT (avdtpsrc, "Failed to get channels");
262 gst_caps_unref (caps);
263 return NULL;
264 }
265 gst_caps_set_simple (caps, "channels", G_TYPE_INT,
266 g_value_get_int (value), NULL);
267
268 value = gst_structure_get_value (structure, "base-profile");
269 if (!value || !G_VALUE_HOLDS_STRING (value)) {
270 GST_ERROR_OBJECT (avdtpsrc, "Failed to get base-profile");
271 gst_caps_unref (caps);
272 return NULL;
273 }
274 gst_caps_set_simple (caps, "base-profile", G_TYPE_STRING,
275 g_value_get_string (value), NULL);
276
277 } else {
278 GST_ERROR_OBJECT (avdtpsrc,
279 "Only SBC and MPEG-2/4 are supported at the moment");
280 }
281
282 value = gst_structure_get_value (structure, "rate");
283 if (!value || !G_VALUE_HOLDS_INT (value)) {
284 GST_ERROR_OBJECT (avdtpsrc, "Failed to get sample rate");
285 gst_caps_unref (caps);
286 return NULL;
287 }
288 rate = g_value_get_int (value);
289
290 gst_caps_set_simple (caps, "clock-rate", G_TYPE_INT, rate, NULL);
291
292 if (filter) {
293 ret = gst_caps_intersect_full (filter, caps, GST_CAPS_INTERSECT_FIRST);
294 gst_caps_unref (caps);
295 } else
296 ret = caps;
297 } else {
298 GST_DEBUG_OBJECT (avdtpsrc, "device not open, using template caps");
299 ret = GST_BASE_SRC_CLASS (parent_class)->get_caps (bsrc, filter);
300 }
301
302 return ret;
303 }
304
305 static void
avrcp_metadata_cb(GstAvrcpConnection * avrcp,GstTagList * taglist,gpointer user_data)306 avrcp_metadata_cb (GstAvrcpConnection * avrcp, GstTagList * taglist,
307 gpointer user_data)
308 {
309 GstAvdtpSrc *src = GST_AVDTP_SRC (user_data);
310 guint64 duration;
311
312 if (gst_tag_list_get_uint64 (taglist, GST_TAG_DURATION, &duration)) {
313 src->duration = duration;
314 gst_element_post_message (GST_ELEMENT (src),
315 gst_message_new_duration_changed (GST_OBJECT (src)));
316 }
317
318 gst_pad_push_event (GST_BASE_SRC_PAD (src),
319 gst_event_new_tag (gst_tag_list_copy (taglist)));
320 gst_element_post_message (GST_ELEMENT (src),
321 gst_message_new_tag (GST_OBJECT (src), taglist));
322 }
323
324 static void
gst_avdtp_src_start_avrcp(GstAvdtpSrc * src)325 gst_avdtp_src_start_avrcp (GstAvdtpSrc * src)
326 {
327 gchar *path, **strv;
328 int i;
329
330 /* Strip out the /fdX in /org/bluez/dev_.../fdX */
331 strv = g_strsplit (src->conn.transport, "/", -1);
332
333 for (i = 0; strv[i]; i++);
334 g_return_if_fail (i > 0);
335
336 g_free (strv[i - 1]);
337 strv[i - 1] = NULL;
338
339 path = g_strjoinv ("/", strv);
340 g_strfreev (strv);
341
342 src->avrcp = gst_avrcp_connection_new (path, avrcp_metadata_cb, src, NULL);
343
344 g_free (path);
345 }
346
347 static void
gst_avdtp_src_stop_avrcp(GstAvdtpSrc * src)348 gst_avdtp_src_stop_avrcp (GstAvdtpSrc * src)
349 {
350 gst_avrcp_connection_free (src->avrcp);
351 }
352
353 static gboolean
gst_avdtp_src_start(GstBaseSrc * bsrc)354 gst_avdtp_src_start (GstBaseSrc * bsrc)
355 {
356 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
357
358 /* None of this can go into prepare() since we need to set up the
359 * connection to figure out what format the device is going to send us.
360 */
361
362 if (!gst_avdtp_connection_acquire (&avdtpsrc->conn, FALSE)) {
363 GST_ERROR_OBJECT (avdtpsrc, "Failed to acquire connection");
364 return FALSE;
365 }
366
367 if (!gst_avdtp_connection_get_properties (&avdtpsrc->conn)) {
368 GST_ERROR_OBJECT (avdtpsrc, "Failed to get transport properties");
369 goto fail;
370 }
371
372 if (!gst_avdtp_connection_conf_recv_stream_fd (&avdtpsrc->conn)) {
373 GST_ERROR_OBJECT (avdtpsrc, "Failed to configure stream fd");
374 goto fail;
375 }
376
377 GST_DEBUG_OBJECT (avdtpsrc, "Setting block size to link MTU (%d)",
378 avdtpsrc->conn.data.link_mtu);
379 gst_base_src_set_blocksize (GST_BASE_SRC (avdtpsrc),
380 avdtpsrc->conn.data.link_mtu);
381
382 avdtpsrc->dev_caps = gst_avdtp_connection_get_caps (&avdtpsrc->conn);
383 if (!avdtpsrc->dev_caps) {
384 GST_ERROR_OBJECT (avdtpsrc, "Failed to get device caps");
385 goto fail;
386 }
387
388 gst_poll_fd_init (&avdtpsrc->pfd);
389 avdtpsrc->pfd.fd = g_io_channel_unix_get_fd (avdtpsrc->conn.stream);
390
391 gst_poll_add_fd (avdtpsrc->poll, &avdtpsrc->pfd);
392 gst_poll_fd_ctl_read (avdtpsrc->poll, &avdtpsrc->pfd, TRUE);
393 gst_poll_set_flushing (avdtpsrc->poll, FALSE);
394
395 g_atomic_int_set (&avdtpsrc->unlocked, FALSE);
396
397 /* The life time of the connection is shorter than the src object, so we
398 * don't need to worry about memory management */
399 gst_avdtp_connection_notify_volume (&avdtpsrc->conn, G_OBJECT (avdtpsrc),
400 "transport-volume");
401
402 gst_avdtp_src_start_avrcp (avdtpsrc);
403
404 return TRUE;
405
406 fail:
407 gst_avdtp_connection_release (&avdtpsrc->conn);
408 return FALSE;
409 }
410
411 static gboolean
gst_avdtp_src_stop(GstBaseSrc * bsrc)412 gst_avdtp_src_stop (GstBaseSrc * bsrc)
413 {
414 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
415
416 gst_poll_remove_fd (avdtpsrc->poll, &avdtpsrc->pfd);
417 gst_poll_set_flushing (avdtpsrc->poll, TRUE);
418
419 gst_avdtp_src_stop_avrcp (avdtpsrc);
420 gst_avdtp_connection_release (&avdtpsrc->conn);
421
422 if (avdtpsrc->dev_caps) {
423 gst_caps_unref (avdtpsrc->dev_caps);
424 avdtpsrc->dev_caps = NULL;
425 }
426
427 return TRUE;
428 }
429
430 static GstFlowReturn
gst_avdtp_src_create(GstBaseSrc * bsrc,guint64 offset,guint length,GstBuffer ** outbuf)431 gst_avdtp_src_create (GstBaseSrc * bsrc, guint64 offset, guint length,
432 GstBuffer ** outbuf)
433 {
434 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
435 GstBuffer *buf = NULL;
436 GstMapInfo info;
437 int ret;
438
439 if (g_atomic_int_get (&avdtpsrc->unlocked))
440 return GST_FLOW_FLUSHING;
441
442 /* We don't operate in GST_FORMAT_BYTES, so offset is ignored */
443
444 while ((ret = gst_poll_wait (avdtpsrc->poll, GST_CLOCK_TIME_NONE))) {
445 if (g_atomic_int_get (&avdtpsrc->unlocked))
446 /* We're unlocked, time to gtfo */
447 return GST_FLOW_FLUSHING;
448
449 if (ret < 0)
450 /* Something went wrong */
451 goto read_error;
452
453 if (ret > 0)
454 /* Got some data */
455 break;
456 }
457
458 ret = GST_BASE_SRC_CLASS (parent_class)->alloc (bsrc, offset, length, outbuf);
459 if (G_UNLIKELY (ret != GST_FLOW_OK))
460 goto alloc_failed;
461
462 buf = *outbuf;
463
464 gst_buffer_map (buf, &info, GST_MAP_WRITE);
465
466 ret = read (avdtpsrc->pfd.fd, info.data, length);
467
468 if (ret < 0)
469 goto read_error;
470 else if (ret == 0) {
471 GST_INFO_OBJECT (avdtpsrc, "Got EOF on the transport fd");
472 goto eof;
473 }
474
475 if (ret < length)
476 gst_buffer_set_size (buf, ret);
477
478 GST_LOG_OBJECT (avdtpsrc, "Read %d bytes", ret);
479
480 gst_buffer_unmap (buf, &info);
481 *outbuf = buf;
482
483 return GST_FLOW_OK;
484
485 alloc_failed:
486 {
487 GST_DEBUG_OBJECT (bsrc, "alloc failed: %s", gst_flow_get_name (ret));
488 return ret;
489 }
490
491 read_error:
492 GST_ERROR_OBJECT (avdtpsrc, "Error while reading audio data: %s",
493 strerror (errno));
494 gst_buffer_unref (buf);
495 return GST_FLOW_ERROR;
496
497 eof:
498 gst_buffer_unref (buf);
499 return GST_FLOW_EOS;
500 }
501
502 static gboolean
gst_avdtp_src_unlock(GstBaseSrc * bsrc)503 gst_avdtp_src_unlock (GstBaseSrc * bsrc)
504 {
505 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
506
507 g_atomic_int_set (&avdtpsrc->unlocked, TRUE);
508
509 gst_poll_set_flushing (avdtpsrc->poll, TRUE);
510
511 return TRUE;
512 }
513
514 static gboolean
gst_avdtp_src_unlock_stop(GstBaseSrc * bsrc)515 gst_avdtp_src_unlock_stop (GstBaseSrc * bsrc)
516 {
517 GstAvdtpSrc *avdtpsrc = GST_AVDTP_SRC (bsrc);
518
519 g_atomic_int_set (&avdtpsrc->unlocked, FALSE);
520
521 gst_poll_set_flushing (avdtpsrc->poll, FALSE);
522
523 /* Flush out any stale data that might be buffered */
524 gst_avdtp_connection_conf_recv_stream_fd (&avdtpsrc->conn);
525
526 return TRUE;
527 }
528
529 gboolean
gst_avdtp_src_plugin_init(GstPlugin * plugin)530 gst_avdtp_src_plugin_init (GstPlugin * plugin)
531 {
532 return gst_element_register (plugin, "avdtpsrc", GST_RANK_NONE,
533 GST_TYPE_AVDTP_SRC);
534 }
535