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