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