RDK Documentation (Open Sourced RDK Components)
btrMgr_streamInGst.c
Go to the documentation of this file.
1 /*
2  * If not stated otherwise in this file or this component's Licenses.txt file the
3  * following copyright and licenses apply:
4  *
5  * Copyright 2016 RDK Management
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  * http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18 */
19 /**
20  * @file btrMgr_streamInGst.c
21  *
22  * @description This file implements bluetooth manager's GStreamer streaming interface to external BT devices
23  *
24  */
25 
26 #ifdef HAVE_CONFIG_H
27 #include <config.h>
28 #endif
29 
30 
31 /* System Headers */
32 #include <stdlib.h>
33 #include <string.h>
34 #include <unistd.h>
35 
36 
37 /* Ext lib Headers */
38 #include <gst/gst.h>
39 #include <gst/audio/audio.h>
40 #include <gst/app/gstappsrc.h>
41 
42 
43 /* Interface lib Headers */
44 #include "btrMgr_logger.h" //for rdklogger
45 
46 /* Local Headers */
47 #include "btrMgr_streamInGst.h"
48 
49 
50 /* Local defines */
51 #define BTRMGR_SLEEP_TIMEOUT_MS 1 // Suspend execution of thread. Keep as minimal as possible
52 #define BTRMGR_WAIT_TIMEOUT_MS 2 // Use for blocking operations
53 #define BTRMGR_MAX_INTERNAL_QUEUE_ELEMENTS 16 // Number of blocks in the internal queue
54 
55 #define GST_ELEMENT_GET_STATE_RETRY_CNT_MAX 5
56 
57 #define ENABLE_MAIN_LOOP_CONTEXT 0
58 
59 
60 /* Local Types & Typedefs */
61 typedef struct _stBTRMgrSIGst {
62  void* pPipeline;
63  void* pSrc;
64  void* pSrcCapsFilter;
65  void* pAudioDec;
66  void* pAudioParse;
67  void* psbcdecCapsFilter;
68  void* pRtpAudioDePay;
69  void* pVolume;
70  void* pSink;
71 
72 #if !(ENABLE_MAIN_LOOP_CONTEXT)
73  void* pContext;
74  GMutex gMtxMainLoopRunLock;
75  GCond gCndMainLoopRun;
76 #endif
77 
78  void* pLoop;
79  void* pLoopThread;
80  guint busWId;
81 
82  GstClockTime gstClkTStamp;
83  guint64 inBufOffset;
84 
85  fPtr_BTRMgr_SI_GstStatusCb fpcBSiGstStatus;
86  void* pvcBUserData;
87 
89 
90 
91 /* Static Function Prototypes */
92 static GstState btrMgr_SI_validateStateWithTimeout (GstElement* element, GstState stateToValidate, guint msTimeOut);
93 
94 /* Local Op Threads Prototypes */
95 static gpointer btrMgr_SI_g_main_loop_Task (gpointer apstBtrMgrSiGst);
96 
97 /* Incoming Callbacks Prototypes */
98 #if !(ENABLE_MAIN_LOOP_CONTEXT)
99 static gboolean btrMgr_SI_g_main_loop_RunningCb (gpointer apstBtrMgrSiGst);
100 #endif
101 static gboolean btrMgr_SI_gstBusCallCb (GstBus* bus, GstMessage* msg, gpointer apstBtrMgrSiGst);
102 
103 
104 /* Static Function Definition */
105 static GstState
106 btrMgr_SI_validateStateWithTimeout (
107  GstElement* element,
108  GstState stateToValidate,
109  guint msTimeOut
110 ) {
111  GstState gst_current = GST_STATE_VOID_PENDING;
112  GstState gst_pending = GST_STATE_VOID_PENDING;
113  float timeout = BTRMGR_WAIT_TIMEOUT_MS;
114  gint gstGetStateCnt = GST_ELEMENT_GET_STATE_RETRY_CNT_MAX;
115 
116  GstStateChangeReturn gstStChangeRet = GST_STATE_CHANGE_FAILURE;
117 
118  do {
119  gstStChangeRet = gst_element_get_state(GST_ELEMENT(element), &gst_current, &gst_pending, timeout * GST_MSECOND);
120  if (((GST_STATE_CHANGE_SUCCESS == gstStChangeRet) || (GST_STATE_CHANGE_NO_PREROLL == gstStChangeRet)) && (gst_current == stateToValidate)) {
121  BTRMGRLOG_INFO("gst_element_get_state - SUCCESS : St = %d Pend = %d StValidate = %d StChRet = %d\n", gst_current, gst_pending, stateToValidate, gstStChangeRet);
122  return gst_current;
123  }
124  usleep(msTimeOut * 1000); // Let element safely transition to required state
125  } while (((gstStChangeRet == GST_STATE_CHANGE_ASYNC) || (gst_current != stateToValidate)) && (gstGetStateCnt-- != 0)) ;
126 
127  BTRMGRLOG_ERROR("gst_element_get_state - FAILURE : St = %d Pend = %d StValidate = %d StChRet = %d\n", gst_current, gst_pending, stateToValidate, gstStChangeRet);
128 
129  if (gst_pending == stateToValidate)
130  return gst_pending;
131  else
132  return gst_current;
133 }
134 
135 
136 /* Local Op Threads */
137 static gpointer
138 btrMgr_SI_g_main_loop_Task (
139  gpointer apstBtrMgrSiGst
140 ) {
141  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)apstBtrMgrSiGst;
142 
143  if (!pstBtrMgrSiGst || !pstBtrMgrSiGst->pLoop) {
144  BTRMGRLOG_ERROR ("GMainLoop Error - In arguments Exiting\n");
145  return NULL;
146  }
147 
148 #if !(ENABLE_MAIN_LOOP_CONTEXT)
149  GstElement* fdsrc = NULL;
150  GstElement* rtpcapsfilter = NULL;
151  GstElement* rtpauddepay = NULL;
152  GstElement* audparse = NULL;
153  GstElement* auddec = NULL;
154  GstElement* volume = NULL;
155  GstElement* fdsink = NULL;
156  GstElement* pipeline = NULL;
157  GstBus* bus = NULL;
158  GSource* idleSource = NULL;
159  GMainLoop* loop = NULL;
160  GMainContext* mainContext = NULL;
161  guint busWatchId;
162 
163 
164  if (!pstBtrMgrSiGst->pContext) {
165  BTRMGRLOG_ERROR ("GMainLoop Error - No context\n");
166  return NULL;
167  }
168 
169 
170  mainContext = pstBtrMgrSiGst->pContext;
171  g_main_context_push_thread_default (mainContext);
172 
173  idleSource = g_idle_source_new ();
174  g_source_set_callback (idleSource, (GSourceFunc) btrMgr_SI_g_main_loop_RunningCb, pstBtrMgrSiGst, NULL);
175  g_source_attach (idleSource, mainContext);
176  g_source_unref (idleSource);
177 
178 
179  /* Create elements */
180  fdsrc = gst_element_factory_make ("fdsrc", "btmgr-si-fdsrc");
181 
182  /*TODO: Select the Audio Codec and RTP Audio DePayloader based on input format*/
183  rtpcapsfilter = gst_element_factory_make ("capsfilter", "btmgr-si-rtpcapsfilter");
184  rtpauddepay = gst_element_factory_make ("rtpsbcdepay", "btmgr-si-rtpsbcdepay");
185  audparse = gst_element_factory_make ("sbcparse", "btmgr-si-rtpsbcparse");
186  auddec = gst_element_factory_make ("sbcdec", "btmgr-si-sbcdec");
187  volume = gst_element_factory_make ("volume", "btmgr-si-volume");
188 
189 #if defined BUILD_FOR_BRCM
190  // make fdsink a filesink, so you can write pcm data to file or pipe, or alternatively, send it to the brcmpcmsink
191  fdsink = gst_element_factory_make ("brcmpcmsink", "btmgr-si-pcmsink");
192 #else
193  /* Use generic sink element */
194  fdsink = gst_element_factory_make ("autoaudiosink", "btmgr-si-pcmsink");
195 #endif
196 
197  /* Create a new pipeline to hold the elements */
198  pipeline = gst_pipeline_new ("btmgr-si-pipeline");
199 
200  loop = pstBtrMgrSiGst->pLoop;
201 
202  if (!fdsrc || !rtpcapsfilter || !rtpauddepay || !audparse || !auddec || !volume || !fdsink || !loop || !pipeline) {
203  BTRMGRLOG_ERROR ("Gstreamer plugin missing for streamIn\n");
204  return NULL;
205  }
206 
207  pstBtrMgrSiGst->pPipeline = (void*)pipeline;
208  pstBtrMgrSiGst->pSrc = (void*)fdsrc;
209  pstBtrMgrSiGst->pSrcCapsFilter = (void*)rtpcapsfilter;
210  pstBtrMgrSiGst->pRtpAudioDePay = (void*)rtpauddepay;
211  pstBtrMgrSiGst->pAudioParse = (void*)audparse;
212  pstBtrMgrSiGst->pAudioDec = (void*)auddec;
213  pstBtrMgrSiGst->pVolume = (void*)volume;
214  pstBtrMgrSiGst->pSink = (void*)fdsink;
215  pstBtrMgrSiGst->pLoop = (void*)loop;
216  pstBtrMgrSiGst->gstClkTStamp = 0;
217  pstBtrMgrSiGst->inBufOffset = 0;
218 
219 
220  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
221  busWatchId = gst_bus_add_watch (bus, btrMgr_SI_gstBusCallCb, pstBtrMgrSiGst);
222  pstBtrMgrSiGst->busWId = busWatchId;
223  g_object_unref (bus);
224 
225  /* setup */
226  gst_bin_add_many (GST_BIN (pipeline), fdsrc, rtpcapsfilter, rtpauddepay, audparse, auddec, volume, fdsink, NULL);
227  gst_element_link_many (fdsrc, rtpcapsfilter, rtpauddepay, audparse, auddec, volume, fdsink, NULL);
228 
229 #endif
230 
231 
232  BTRMGRLOG_INFO ("GMainLoop Running\n");
233  g_main_loop_run (pstBtrMgrSiGst->pLoop);
234 
235 
236 #if !(ENABLE_MAIN_LOOP_CONTEXT)
237  if (busWatchId) {
238  GSource *busSource = g_main_context_find_source_by_id(mainContext, busWatchId);
239  if (busSource)
240  g_source_destroy(busSource);
241 
242  busWatchId = 0;
243  pstBtrMgrSiGst->busWId = busWatchId;
244  }
245 
246 
247  g_main_context_pop_thread_default (mainContext);
248 #endif
249 
250  BTRMGRLOG_INFO ("GMainLoop Exiting\n");
251  return pstBtrMgrSiGst;
252 }
253 
254 
255 /* Interfaces */
256 eBTRMgrSIGstRet
258  tBTRMgrSiGstHdl* phBTRMgrSiGstHdl,
259  fPtr_BTRMgr_SI_GstStatusCb afpcBSiGstStatus,
260  void* apvUserData
261 ) {
262 #if (ENABLE_MAIN_LOOP_CONTEXT)
263  GstElement* fdsrc = NULL;
264  GstElement* rtpcapsfilter = NULL;
265  GstElement* rtpauddepay = NULL;
266  GstElement* audparse = NULL;
267  GstElement* auddec = NULL;
268  GstElement* volume = NULL;
269  GstElement* fdsink = NULL;
270  GstElement* pipeline = NULL;
271  GstBus* bus = NULL;
272  guint busWatchId;
273 #else
274  GMainContext* mainContext = NULL;
275 #endif
276 
277  stBTRMgrSIGst* pstBtrMgrSiGst = NULL;
278  GThread* mainLoopThread = NULL;
279  GMainLoop* loop = NULL;
280 
281 
282  if ((pstBtrMgrSiGst = (stBTRMgrSIGst*)malloc (sizeof(stBTRMgrSIGst))) == NULL) {
283  BTRMGRLOG_ERROR ("Unable to allocate memory\n");
284  return eBTRMgrSIGstFailure;
285  }
286 
287  memset((void*)pstBtrMgrSiGst, 0, sizeof(stBTRMgrSIGst));
288 
289  gst_init (NULL, NULL);
290 
291 #if (ENABLE_MAIN_LOOP_CONTEXT)
292  /* Create elements */
293  fdsrc = gst_element_factory_make ("fdsrc", "btmgr-si-fdsrc");
294 
295  /*TODO: Select the Audio Codec and RTP Audio DePayloader based on input format*/
296  rtpcapsfilter = gst_element_factory_make ("capsfilter", "btmgr-si-rtpcapsfilter");
297  rtpauddepay = gst_element_factory_make ("rtpsbcdepay", "btmgr-si-rtpsbcdepay");
298  audparse = gst_element_factory_make ("sbcparse", "btmgr-si-rtpsbcparse");
299  auddec = gst_element_factory_make ("sbcdec", "btmgr-si-sbcdec");
300  volume = gst_element_factory_make ("volume", "btmgr-si-volume");
301 
302 #if defined BUILD_FOR_BRCM
303  // make fdsink a filesink, so you can write pcm data to file or pipe, or alternatively, send it to the brcmpcmsink
304  fdsink = gst_element_factory_make ("brcmpcmsink", "btmgr-si-pcmsink");
305 #else
306  /* Use generic sink element */
307  fdsink = gst_element_factory_make ("autoaudiosink", "btmgr-si-pcmsink");
308 #endif
309 
310  /* Create an event loop and feed gstreamer bus mesages to it */
311  loop = g_main_loop_new (NULL, FALSE);
312 #else
313  g_mutex_init (&pstBtrMgrSiGst->gMtxMainLoopRunLock);
314  g_cond_init (&pstBtrMgrSiGst->gCndMainLoopRun);
315 
316  mainContext = g_main_context_new();
317 
318  /* Create and event loop and feed gstreamer bus mesages to it */
319  if (mainContext) {
320  loop = g_main_loop_new (mainContext, FALSE);
321  }
322 #endif
323 
324 
325 #if (ENABLE_MAIN_LOOP_CONTEXT)
326  /* Create a new pipeline to hold the elements */
327  pipeline = gst_pipeline_new ("btmgr-si-pipeline");
328 
329  if (!fdsrc || !rtpcapsfilter || !rtpauddepay || !audparse || !auddec || !volume || !fdsink || !loop || !pipeline) {
330  BTRMGRLOG_ERROR ("Gstreamer plugin missing for streamIn\n");
331  //TODO: Call BTRMgr_SI_GstDeInit((tBTRMgrSiGstHdl)pstBtrMgrSiGst);
332  return eBTRMgrSIGstFailure;
333  }
334 
335  pstBtrMgrSiGst->pPipeline = (void*)pipeline;
336  pstBtrMgrSiGst->pSrc = (void*)fdsrc;
337  pstBtrMgrSiGst->pSrcCapsFilter = (void*)rtpcapsfilter;
338  pstBtrMgrSiGst->pRtpAudioDePay = (void*)rtpauddepay;
339  pstBtrMgrSiGst->pAudioParse = (void*)audparse;
340  pstBtrMgrSiGst->pAudioDec = (void*)auddec;
341  pstBtrMgrSiGst->pVolume = (void*)volume;
342  pstBtrMgrSiGst->pSink = (void*)fdsink;
343  pstBtrMgrSiGst->pLoop = (void*)loop;
344  pstBtrMgrSiGst->gstClkTStamp = 0;
345  pstBtrMgrSiGst->inBufOffset = 0;
346  pstBtrMgrSiGst->fpcBSiGstStatus = NULL;
347  pstBtrMgrSiGst->pvcBUserData = NULL;
348 
349 
350  if (afpcBSiGstStatus) {
351  pstBtrMgrSiGst->fpcBSiGstStatus = afpcBSiGstStatus;
352  pstBtrMgrSiGst->pvcBUserData = apvUserData;
353  }
354 
355 
356  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
357  busWatchId = gst_bus_add_watch (bus, btrMgr_SI_gstBusCallCb, pstBtrMgrSiGst);
358  pstBtrMgrSiGst->busWId = busWatchId;
359  g_object_unref (bus);
360 
361  /* setup */
362  gst_bin_add_many (GST_BIN (pipeline), fdsrc, rtpcapsfilter, rtpauddepay, audparse, auddec, volume, fdsink, NULL);
363  gst_element_link_many (fdsrc, rtpcapsfilter, rtpauddepay, audparse, auddec, volume, fdsink, NULL);
364 
365 
366  mainLoopThread = g_thread_new("btrMgr_SI_g_main_loop_Task", btrMgr_SI_g_main_loop_Task, pstBtrMgrSiGst);
367  pstBtrMgrSiGst->pLoopThread = (void*)mainLoopThread;
368 
369 #else
370  pstBtrMgrSiGst->pContext = (void*)mainContext;
371  pstBtrMgrSiGst->pLoop = (void*)loop;
372  pstBtrMgrSiGst->fpcBSiGstStatus = NULL;
373  pstBtrMgrSiGst->pvcBUserData = NULL;
374 
375  if (afpcBSiGstStatus) {
376  pstBtrMgrSiGst->fpcBSiGstStatus = afpcBSiGstStatus;
377  pstBtrMgrSiGst->pvcBUserData = apvUserData;
378  }
379 
380 
381  g_mutex_lock (&pstBtrMgrSiGst->gMtxMainLoopRunLock);
382  {
383  mainLoopThread = g_thread_new("btrMgr_SI_g_main_loop_Task", btrMgr_SI_g_main_loop_Task, pstBtrMgrSiGst);
384  pstBtrMgrSiGst->pLoopThread = (void*)mainLoopThread;
385 
386  //TODO: Infinite loop, break out of it gracefully in case of failures
387  while (!loop || !g_main_loop_is_running (loop)) {
388  g_cond_wait (&pstBtrMgrSiGst->gCndMainLoopRun, &pstBtrMgrSiGst->gMtxMainLoopRunLock);
389  }
390  }
391  g_mutex_unlock (&pstBtrMgrSiGst->gMtxMainLoopRunLock);
392 
393 #endif
394 
395  gst_element_set_state(GST_ELEMENT(pstBtrMgrSiGst->pPipeline), GST_STATE_NULL);
396  if (btrMgr_SI_validateStateWithTimeout(pstBtrMgrSiGst->pPipeline, GST_STATE_NULL, BTRMGR_SLEEP_TIMEOUT_MS)!= GST_STATE_NULL) {
397  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
398  BTRMgr_SI_GstDeInit((tBTRMgrSiGstHdl)pstBtrMgrSiGst);
399  return eBTRMgrSIGstFailure;
400  }
401 
402 
403  *phBTRMgrSiGstHdl = (tBTRMgrSiGstHdl)pstBtrMgrSiGst;
404 
405  return eBTRMgrSIGstSuccess;
406 }
407 
408 
409 eBTRMgrSIGstRet
411  tBTRMgrSiGstHdl hBTRMgrSiGstHdl
412 ) {
413  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
414 
415  if (!pstBtrMgrSiGst) {
416  BTRMGRLOG_ERROR ("Invalid input argument\n");
417  return eBTRMgrSIGstFailInArg;
418  }
419 
420  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
421  GMainLoop* loop = (GMainLoop*)pstBtrMgrSiGst->pLoop;
422  GThread* mainLoopThread = (GThread*)pstBtrMgrSiGst->pLoopThread;
423 #if (ENABLE_MAIN_LOOP_CONTEXT)
424  guint busWatchId = pstBtrMgrSiGst->busWId;
425 #else
426  GMainContext* mainContext = (GMainContext*)pstBtrMgrSiGst->pContext;
427 #endif
428 
429  /* cleanup */
430  if (pipeline) {
431  gst_object_unref(GST_OBJECT(pipeline));
432  pipeline = NULL;
433  }
434 
435 #if (ENABLE_MAIN_LOOP_CONTEXT)
436  if (busWatchId) {
437  GSource *busSource = g_main_context_find_source_by_id(g_main_context_get_thread_default(), busWatchId);
438  if (busSource)
439  g_source_destroy(busSource);
440 
441  busWatchId = 0;
442  }
443 #endif
444 
445  if (loop) {
446  g_main_loop_quit(loop);
447  }
448 
449  if (mainLoopThread) {
450  g_thread_join(mainLoopThread);
451  mainLoopThread = NULL;
452  }
453 
454  if (loop) {
455  g_main_loop_unref(loop);
456  loop = NULL;
457  }
458 
459 #if !(ENABLE_MAIN_LOOP_CONTEXT)
460  if (mainContext) {
461  g_main_context_unref(mainContext);
462  mainContext = NULL;
463  }
464 #endif
465 
466  if (pstBtrMgrSiGst->fpcBSiGstStatus)
467  pstBtrMgrSiGst->fpcBSiGstStatus = NULL;
468 
469 
470 #if !(ENABLE_MAIN_LOOP_CONTEXT)
471  g_cond_clear(&pstBtrMgrSiGst->gCndMainLoopRun);
472  g_mutex_clear(&pstBtrMgrSiGst->gMtxMainLoopRunLock);
473 #endif
474 
475 
476  memset((void*)pstBtrMgrSiGst, 0, sizeof(stBTRMgrSIGst));
477  free((void*)pstBtrMgrSiGst);
478  pstBtrMgrSiGst = NULL;
479 
480  return eBTRMgrSIGstSuccess;
481 }
482 
483 
484 eBTRMgrSIGstRet
486  tBTRMgrSiGstHdl hBTRMgrSiGstHdl,
487  int aiInBufMaxSize,
488  int aiBTDevFd,
489  int aiBTDevMTU,
490  unsigned int aiBTDevSFreq,
491  const char* apcAudioInType
492 ) {
493  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
494 
495  if (!pstBtrMgrSiGst || !apcAudioInType) {
496  BTRMGRLOG_ERROR ("Invalid input argument\n");
497  return eBTRMgrSIGstFailInArg;
498  }
499 
500  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
501  GstElement* fdsrc = (GstElement*)pstBtrMgrSiGst->pSrc;
502  GstElement* rtpcapsfilter = (GstElement*)pstBtrMgrSiGst->pSrcCapsFilter;
503  GstElement* auddec = (GstElement*)pstBtrMgrSiGst->pAudioDec;
504  GstElement* fdsink = (GstElement*)pstBtrMgrSiGst->pSink;
505 
506  guint busWatchId = pstBtrMgrSiGst->busWId;
507  gint rtpPaylodVal= 0;
508 
509  GstCaps* fdsrcSrcCaps = NULL;
510 
511  (void)pipeline;
512  (void)fdsrc;
513  (void)auddec;
514  (void)busWatchId;
515 
516  /* Check if we are in correct state */
517  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_NULL, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_NULL) {
518  BTRMGRLOG_ERROR ("Incorrect State to perform Operation\n");
519  return eBTRMgrSIGstFailure;
520  }
521 
522  pstBtrMgrSiGst->gstClkTStamp = 0;
523  pstBtrMgrSiGst->inBufOffset = 0;
524 
525 
526  if (!strncmp(apcAudioInType, BTRMGR_AUDIO_INPUT_TYPE_SBC, strlen(BTRMGR_AUDIO_INPUT_TYPE_SBC))) {
527  rtpPaylodVal = 96;
528  }
529  else if (!strncmp(apcAudioInType, BTRMGR_AUDIO_INPUT_TYPE_AAC, strlen(BTRMGR_AUDIO_INPUT_TYPE_AAC))) {
530  rtpPaylodVal = 96;
531  }
532 
533 
534  fdsrcSrcCaps = gst_caps_new_simple ("application/x-rtp",
535  "media", G_TYPE_STRING, "audio",
536  "encoding-name", G_TYPE_STRING, apcAudioInType,
537  "clock-rate", G_TYPE_INT, aiBTDevSFreq,
538  "payload", G_TYPE_INT, rtpPaylodVal,
539  NULL);
540 
541  g_object_set (fdsrc, "fd", aiBTDevFd, NULL);
542  g_object_set (fdsrc, "blocksize", aiBTDevMTU, NULL);
543  g_object_set (fdsrc, "do-timestamp",TRUE, NULL);
544  g_object_set (rtpcapsfilter, "caps",fdsrcSrcCaps, NULL);
545  g_object_set (fdsink, "sync", FALSE, NULL);
546 
547 
548  gst_caps_unref(fdsrcSrcCaps);
549 
550  /* start play back and listed to events */
551  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
552  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_PLAYING, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PLAYING) {
553  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
554  return eBTRMgrSIGstFailure;
555  }
556 
557  return eBTRMgrSIGstSuccess;
558 }
559 
560 
561 eBTRMgrSIGstRet
563  tBTRMgrSiGstHdl hBTRMgrSiGstHdl
564 ) {
565  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
566 
567  if (!pstBtrMgrSiGst) {
568  BTRMGRLOG_ERROR ("Invalid input argument\n");
569  return eBTRMgrSIGstFailInArg;
570  }
571 
572  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
573  GstElement* fdsrc = (GstElement*)pstBtrMgrSiGst->pSrc;
574  GMainLoop* loop = (GMainLoop*)pstBtrMgrSiGst->pLoop;
575  guint busWatchId = pstBtrMgrSiGst->busWId;
576 
577  (void)pipeline;
578  (void)fdsrc;
579  (void)loop;
580  (void)busWatchId;
581 
582  /* stop play back */
583  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
584  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_NULL, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_NULL) {
585  BTRMGRLOG_ERROR ("- Unable to perform Operation\n");
586  return eBTRMgrSIGstFailure;
587  }
588 
589  pstBtrMgrSiGst->gstClkTStamp = 0;
590  pstBtrMgrSiGst->inBufOffset = 0;
591 
592  return eBTRMgrSIGstSuccess;
593 }
594 
595 
596 eBTRMgrSIGstRet
598  tBTRMgrSiGstHdl hBTRMgrSiGstHdl
599 ) {
600  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
601 
602  if (!pstBtrMgrSiGst) {
603  BTRMGRLOG_ERROR ("Invalid input argument\n");
604  return eBTRMgrSIGstFailInArg;
605  }
606 
607  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
608  GstElement* fdsrc = (GstElement*)pstBtrMgrSiGst->pSrc;
609  GMainLoop* loop = (GMainLoop*)pstBtrMgrSiGst->pLoop;
610  guint busWatchId = pstBtrMgrSiGst->busWId;
611 
612  (void)pipeline;
613  (void)fdsrc;
614  (void)loop;
615  (void)busWatchId;
616 
617  /* Check if we are in correct state */
618  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_PLAYING, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PLAYING) {
619  BTRMGRLOG_ERROR ("Incorrect State to perform Operation\n");
620  return eBTRMgrSIGstFailure;
621  }
622 
623  /* pause playback and listed to events */
624  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PAUSED);
625  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_PAUSED, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PAUSED) {
626  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
627  return eBTRMgrSIGstFailure;
628  }
629 
630  return eBTRMgrSIGstSuccess;
631 }
632 
633 
634 eBTRMgrSIGstRet
636  tBTRMgrSiGstHdl hBTRMgrSiGstHdl
637 ) {
638  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
639 
640  if (!pstBtrMgrSiGst) {
641  BTRMGRLOG_ERROR ("Invalid input argument\n");
642  return eBTRMgrSIGstFailInArg;
643  }
644 
645  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
646  GstElement* fdsrc = (GstElement*)pstBtrMgrSiGst->pSrc;
647  GMainLoop* loop = (GMainLoop*)pstBtrMgrSiGst->pLoop;
648  guint busWatchId = pstBtrMgrSiGst->busWId;
649 
650  (void)pipeline;
651  (void)fdsrc;
652  (void)loop;
653  (void)busWatchId;
654 
655  /* Check if we are in correct state */
656  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_PAUSED, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PAUSED) {
657  BTRMGRLOG_ERROR ("Incorrect State to perform Operation\n");
658  return eBTRMgrSIGstFailure;
659  }
660 
661  /* Resume playback and listed to events */
662  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
663  if (btrMgr_SI_validateStateWithTimeout(pipeline, GST_STATE_PLAYING, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PLAYING) {
664  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
665  return eBTRMgrSIGstFailure;
666  }
667 
668  return eBTRMgrSIGstSuccess;
669 }
670 
671 
672 eBTRMgrSIGstRet
674  tBTRMgrSiGstHdl hBTRMgrSiGstHdl,
675  unsigned char ui8Volume
676 ) {
677  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
678 
679  if (!pstBtrMgrSiGst) {
680  BTRMGRLOG_ERROR ("Invalid input argument\n");
681  return eBTRMgrSIGstFailInArg;
682  }
683 
684  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
685  GstElement* volume = (GstElement*)pstBtrMgrSiGst->pVolume;
686 
687  (void)pipeline;
688 
689 
690  BTRMGRLOG_DEBUG("Volume at StreamIn Gst = %d, %f\n", ui8Volume, ui8Volume/100.0);
691  g_object_set (volume, "volume", (double)(ui8Volume/100.0), NULL);
692 
693  return eBTRMgrSIGstSuccess;
694 }
695 
696 
697 eBTRMgrSIGstRet
699  tBTRMgrSiGstHdl hBTRMgrSiGstHdl,
700  char* pcInBuf,
701  int aiInBufSize
702 ) {
703  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
704 
705  if (!pstBtrMgrSiGst) {
706  BTRMGRLOG_ERROR ("Invalid input argument\n");
707  return eBTRMgrSIGstFailInArg;
708  }
709 
710  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
711  GstElement* fdsrc = (GstElement*)pstBtrMgrSiGst->pSrc;
712  GMainLoop* loop = (GMainLoop*)pstBtrMgrSiGst->pLoop;
713  guint busWatchId = pstBtrMgrSiGst->busWId;
714 
715  (void)pipeline;
716  (void)fdsrc;
717  (void)loop;
718  (void)busWatchId;
719 
720  /* push Buffers */
721  {
722  GstBuffer *gstBuf;
723  GstMapInfo gstBufMap;
724 
725  gstBuf = gst_buffer_new_and_alloc (aiInBufSize);
726  gst_buffer_map (gstBuf, &gstBufMap, GST_MAP_WRITE);
727 
728  //TODO: Repalce memcpy and new_alloc if possible
729  memcpy (gstBufMap.data, pcInBuf, aiInBufSize);
730 
731  //TODO: Arrive at this vale based on Sampling rate, bits per sample, num of Channels and the
732  // size of the incoming buffer (which represents the num of samples received at this instant)
733  GST_BUFFER_PTS (gstBuf) = pstBtrMgrSiGst->gstClkTStamp;
734  GST_BUFFER_DURATION (gstBuf) = GST_USECOND * (aiInBufSize * 1000)/(48 * (16/8) * 2);
735  pstBtrMgrSiGst->gstClkTStamp += GST_BUFFER_DURATION (gstBuf);
736 
737  GST_BUFFER_OFFSET (gstBuf) = pstBtrMgrSiGst->inBufOffset;
738  pstBtrMgrSiGst->inBufOffset += aiInBufSize;
739  GST_BUFFER_OFFSET_END (gstBuf) = pstBtrMgrSiGst->inBufOffset - 1;
740 
741  gst_app_src_push_buffer (GST_APP_SRC (fdsrc), gstBuf);
742 
743  gst_buffer_unmap (gstBuf, &gstBufMap);
744  }
745 
746  return eBTRMgrSIGstSuccess;
747 }
748 
749 
750 eBTRMgrSIGstRet
752  tBTRMgrSiGstHdl hBTRMgrSiGstHdl
753 ) {
754  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)hBTRMgrSiGstHdl;
755 
756  if (!pstBtrMgrSiGst) {
757  BTRMGRLOG_ERROR ("Invalid input argument\n");
758  return eBTRMgrSIGstFailInArg;
759  }
760 
761  GstElement* pipeline = (GstElement*)pstBtrMgrSiGst->pPipeline;
762  GstElement* fdsrc = (GstElement*)pstBtrMgrSiGst->pSrc;
763  GMainLoop* loop = (GMainLoop*)pstBtrMgrSiGst->pLoop;
764  guint busWatchId = pstBtrMgrSiGst->busWId;
765 
766  (void)pipeline;
767  (void)fdsrc;
768  (void)loop;
769  (void)busWatchId;
770 
771  /* push EOS */
772  gst_element_send_event (pipeline, gst_event_new_eos ());
773 
774  return eBTRMgrSIGstSuccess;
775 }
776 
777 // Outgoing callbacks Registration Interfaces
778 
779 
780 /* Incoming Callbacks */
781 #if !(ENABLE_MAIN_LOOP_CONTEXT)
782 static gboolean
783 btrMgr_SI_g_main_loop_RunningCb (
784  gpointer apstBtrMgrSiGst
785 ) {
786  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)apstBtrMgrSiGst;
787 
788  if (!pstBtrMgrSiGst) {
789  BTRMGRLOG_ERROR ("GMainLoop Error - In arguments Exiting\n");
790  return G_SOURCE_REMOVE;
791  }
792 
793  BTRMGRLOG_INFO ("GMainLoop running now");
794 
795  g_mutex_lock (&pstBtrMgrSiGst->gMtxMainLoopRunLock);
796  g_cond_signal (&pstBtrMgrSiGst->gCndMainLoopRun);
797  g_mutex_unlock (&pstBtrMgrSiGst->gMtxMainLoopRunLock);
798 
799  return G_SOURCE_REMOVE;
800 }
801 #endif
802 
803 static gboolean
804 btrMgr_SI_gstBusCallCb (
805  GstBus* bus,
806  GstMessage* msg,
807  gpointer apstBtrMgrSiGst
808 ) {
809  stBTRMgrSIGst* pstBtrMgrSiGst = (stBTRMgrSIGst*)apstBtrMgrSiGst;
810 
811  switch (GST_MESSAGE_TYPE (msg)) {
812 
813  case GST_MESSAGE_EOS: {
814 
815  BTRMGRLOG_INFO ("End-of-stream\n");
816  if (pstBtrMgrSiGst) {
817  if (pstBtrMgrSiGst->pLoop) {
818  g_main_loop_quit(pstBtrMgrSiGst->pLoop);
819  }
820  }
821  break;
822  }
823 
824 
825  case GST_MESSAGE_STATE_CHANGED: {
826  if (pstBtrMgrSiGst && (pstBtrMgrSiGst->pPipeline) && (GST_MESSAGE_SRC (msg) == GST_OBJECT (pstBtrMgrSiGst->pPipeline))) {
827  GstState prevState, currentState;
828 
829  gst_message_parse_state_changed (msg, &prevState, &currentState, NULL);
830  BTRMGRLOG_INFO ("From: %s -> To: %s\n",
831  gst_element_state_get_name (prevState), gst_element_state_get_name (currentState));
832  }
833  break;
834  }
835 
836 
837  case GST_MESSAGE_ERROR: {
838  gchar* debug;
839  GError* err;
840 
841  gst_message_parse_error (msg, &err, &debug);
842  BTRMGRLOG_DEBUG ("Debugging info: %s\n", (debug) ? debug : "none");
843  g_free (debug);
844 
845  BTRMGRLOG_ERROR ("Error: %s\n", err->message);
846  g_error_free (err);
847 
848  if (pstBtrMgrSiGst) {
849  if (pstBtrMgrSiGst->pLoop) {
850  g_main_loop_quit(pstBtrMgrSiGst->pLoop);
851  }
852  }
853  break;
854  }
855 
856  case GST_MESSAGE_WARNING:{
857  gchar* debug;
858  GError* warn;
859 
860  gst_message_parse_warning (msg, &warn, &debug);
861  BTRMGRLOG_DEBUG ("Debugging info: %s\n", (debug) ? debug : "none");
862  g_free (debug);
863 
864  BTRMGRLOG_WARN ("Warning: %s\n", warn->message);
865  g_error_free (warn);
866  break;
867  }
868 
869  default:
870  break;
871 
872  }
873 
874  return TRUE;
875 }
876 
BTRMgr_SI_GstInit
eBTRMgrSIGstRet BTRMgr_SI_GstInit(tBTRMgrSiGstHdl *phBTRMgrSiGstHdl, fPtr_BTRMgr_SI_GstStatusCb afpcBSiGstStatus, void *apvUserData)
This API initializes the streaming interface.
Definition: btrMgr_streamInGst.c:257
BTRMgr_SI_GstStart
eBTRMgrSIGstRet BTRMgr_SI_GstStart(tBTRMgrSiGstHdl hBTRMgrSiGstHdl, int aiInBufMaxSize, int aiBTDevFd, int aiBTDevMTU, unsigned int aiBTDevSFreq, const char *apcAudioInType)
This API starts the playback and listens to the events associated with it.
Definition: btrMgr_streamInGst.c:485
_stBTRMgrSIGst
Definition: btrMgr_streamInGst.c:61
BTRMgr_SI_GstSetVolume
eBTRMgrSIGstRet BTRMgr_SI_GstSetVolume(tBTRMgrSiGstHdl hBTRMgrSiGstHdl, unsigned char ui8Volume)
This API resumes the current operation and listens to the events.
Definition: btrMgr_streamInGst.c:673
BTRMgr_SI_GstSendBuffer
eBTRMgrSIGstRet BTRMgr_SI_GstSendBuffer(tBTRMgrSiGstHdl hBTRMgrSiGstHdl, char *pcInBuf, int aiInBufSize)
This API pushes the buffer to the queue.
Definition: btrMgr_streamInGst.c:698
BTRMgr_SI_GstDeInit
eBTRMgrSIGstRet BTRMgr_SI_GstDeInit(tBTRMgrSiGstHdl hBTRMgrSiGstHdl)
This API performs the cleanup operations.
Definition: btrMgr_streamInGst.c:410
BTRMgr_SI_GstSendEOS
eBTRMgrSIGstRet BTRMgr_SI_GstSendEOS(tBTRMgrSiGstHdl hBTRMgrSiGstHdl)
This API is used to push EOS(End of Stream) to the queue.
Definition: btrMgr_streamInGst.c:751
BTRMgr_SI_GstStop
eBTRMgrSIGstRet BTRMgr_SI_GstStop(tBTRMgrSiGstHdl hBTRMgrSiGstHdl)
This API stops the current playback and sets the state as NULL.
Definition: btrMgr_streamInGst.c:562
BTRMgr_SI_GstResume
eBTRMgrSIGstRet BTRMgr_SI_GstResume(tBTRMgrSiGstHdl hBTRMgrSiGstHdl)
This API resumes the current operation and listens to the events.
Definition: btrMgr_streamInGst.c:635
BTRMgr_SI_GstPause
eBTRMgrSIGstRet BTRMgr_SI_GstPause(tBTRMgrSiGstHdl hBTRMgrSiGstHdl)
This API pauses the current playback and listens to the events.
Definition: btrMgr_streamInGst.c:597
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
btrMgr_streamInGst.h