RDK Documentation (Open Sourced RDK Components)
btrMgr_streamOutGst.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_streamOutGst.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 #include <math.h>
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_streamOutGst.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 8 // Number of blocks in the internal queue
54 #define BTRMGR_INPUT_BUF_INTERVAL_THRES_CNT 4 // Number of buffer threshold based on input buffer interval
55 
56 #define GST_ELEMENT_GET_STATE_RETRY_CNT_MAX 5
57 
58 #define ENABLE_MAIN_LOOP_CONTEXT 0
59 
60 #define BTRMGR_SBC_ALLOCATION_SNR (1 << 1) // Has to match with a2dp-codecs.h
61 #define BTRMGR_SBC_ALLOCATION_LOUDNESS 1 // Need a better way to pass/map this from the upper layers
62 
63 /* Local Types & Typedefs */
64 typedef struct _stBTRMgrSOGst {
65  void* pPipeline;
66  void* pSrc;
67  void* pSink;
68  void* pAudioConv;
69  void* pAudioResample;
70  void* pAudioEnc;
71  void* pAECapsFilter;
72  void* pRtpAudioPay;
73  void* pVolume;
74 
75 #if !(ENABLE_MAIN_LOOP_CONTEXT)
76  void* pContext;
77  GMutex gMtxMainLoopRunLock;
78  GCond gCndMainLoopRun;
79  guint emptyBufPushId;
80 #endif
81 
82  void* pLoop;
83  void* pLoopThread;
84  guint busWId;
85 
86  GstClockTime gstClkTStamp;
87  guint64 inBufOffset;
88  int i32InBufMaxSize;
89  int i32InRate;
90  int i32InChannels;
91  unsigned int ui32InBitsPSample;
92  unsigned int ui32InBufIntervalms;
93  unsigned char ui8IpBufThrsCnt;
94 
95  fPtr_BTRMgr_SO_GstStatusCb fpcBSoGstStatus;
96  void* pvcBUserData;
97 
98  GMutex pipelineDataMutex;
99  gboolean bPipelineError;
100  gboolean bIsInputPaused;
101 } stBTRMgrSOGst;
102 
103 
104 /* Static Function Prototypes */
105 static GstState btrMgr_SO_validateStateWithTimeout (GstElement* element, GstState stateToValidate, guint msTimeOut);
106 static eBTRMgrSOGstRet btrMgr_SO_GstSendBuffer (stBTRMgrSOGst* pstBtrMgrSoGst, char* pcInBuf, int aiInBufSize);
107 
108 /* Local Op Threads Prototypes */
109 static gpointer btrMgr_SO_g_main_loop_Task (gpointer apstBtrMgrSoGst);
110 
111 /* Incoming Callbacks Prototypes */
112 #if !(ENABLE_MAIN_LOOP_CONTEXT)
113 static gboolean btrMgr_SO_g_main_loop_RunningCb (gpointer apstBtrMgrSoGst);
114 static gboolean btrMgr_SO_g_timeout_EmptyBufPushCb (gpointer apstBtrMgrSoGst);
115 #endif
116 static void btrMgr_SO_NeedDataCb (GstElement* appsrc, guint size, gpointer apstBtrMgrSoGst);
117 static void btrMgr_SO_EnoughDataCb (GstElement* appsrc, gpointer apstBtrMgrSoGst);
118 static gboolean btrMgr_SO_gstBusCallCb (GstBus* bus, GstMessage* msg, gpointer apstBtrMgrSoGst);
119 
120 
121 /* Static Function Definition */
122 static GstState
123 btrMgr_SO_validateStateWithTimeout (
124  GstElement* element,
125  GstState stateToValidate,
126  guint msTimeOut
127 ) {
128  GstState gst_current = GST_STATE_VOID_PENDING;
129  GstState gst_pending = GST_STATE_VOID_PENDING;
130  float timeout = BTRMGR_WAIT_TIMEOUT_MS;
131  gint gstGetStateCnt = GST_ELEMENT_GET_STATE_RETRY_CNT_MAX;
132 
133  GstStateChangeReturn gstStChangeRet = GST_STATE_CHANGE_FAILURE;
134 
135  do {
136  gstStChangeRet = gst_element_get_state(GST_ELEMENT(element), &gst_current, &gst_pending, timeout * GST_MSECOND);
137  if (((GST_STATE_CHANGE_SUCCESS == gstStChangeRet) || (GST_STATE_CHANGE_NO_PREROLL == gstStChangeRet)) && (gst_current == stateToValidate)) {
138  BTRMGRLOG_INFO("gst_element_get_state - SUCCESS : St = %d, Pend = %d StValidate = %d StChRet = %d\n", gst_current, gst_pending, stateToValidate, gstStChangeRet);
139  return gst_current;
140  }
141  usleep(msTimeOut * 1000); // Let element safely transition to required state
142  } while (((gstStChangeRet == GST_STATE_CHANGE_ASYNC) || (gst_current != stateToValidate)) && (gstGetStateCnt-- != 0)) ;
143 
144  BTRMGRLOG_ERROR("gst_element_get_state - FAILURE : St = %d, Pend = %d StValidate = %d StChRet = %d\n", gst_current, gst_pending, stateToValidate, gstStChangeRet);
145 
146  if (gst_pending == stateToValidate)
147  return gst_pending;
148  else
149  return gst_current;
150 }
151 
152 
153 /* Local Op Threads */
154 static gpointer
155 btrMgr_SO_g_main_loop_Task (
156  gpointer apstBtrMgrSoGst
157 ) {
158  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)apstBtrMgrSoGst;
159 
160  if (!pstBtrMgrSoGst || !pstBtrMgrSoGst->pLoop) {
161  BTRMGRLOG_ERROR ("GMainLoop Error - In arguments Exiting\n");
162  return NULL;
163  }
164 
165 #if !(ENABLE_MAIN_LOOP_CONTEXT)
166  GstElement* appsrc = NULL;
167  GstElement* volume = NULL;
168  GstElement* audconvert = NULL;
169  GstElement* audresample = NULL;
170  GstElement* audenc = NULL;
171  GstElement* aecapsfilter= NULL;
172  GstElement* rtpaudpay = NULL;
173  GstElement* fdsink = NULL;
174  GstElement* pipeline = NULL;
175  GstBus* bus = NULL;
176  GSource* idleSource = NULL;
177  GMainLoop* loop = NULL;
178  GMainContext* mainContext = NULL;
179  guint busWatchId;
180  guint idleSrcLoopRunningId;
181 
182 
183  if (!pstBtrMgrSoGst->pContext) {
184  BTRMGRLOG_ERROR ("GMainLoop Error - No context\n");
185  return NULL;
186  }
187 
188  mainContext = pstBtrMgrSoGst->pContext;
189  g_main_context_push_thread_default (mainContext);
190 
191  idleSource = g_idle_source_new ();
192  g_source_set_callback (idleSource, (GSourceFunc) btrMgr_SO_g_main_loop_RunningCb, pstBtrMgrSoGst, NULL);
193  idleSrcLoopRunningId = g_source_attach (idleSource, mainContext);
194  g_source_unref (idleSource);
195 
196 
197  /* Create elements */
198  appsrc = gst_element_factory_make ("appsrc", "btmgr-so-appsrc");
199  volume = gst_element_factory_make ("volume", "btmgr-so-volume");
200 #if defined(DISABLE_AUDIO_ENCODING)
201  audconvert = gst_element_factory_make ("queue", "btmgr-so-aconv");
202  audresample = gst_element_factory_make ("queue", "btmgr-so-aresample");
203  audenc = gst_element_factory_make ("queue", "btmgr-so-sbcenc");
204  aecapsfilter= gst_element_factory_make ("queue", "btmgr-so-aecapsfilter");
205  rtpaudpay = gst_element_factory_make ("queue", "btmgr-so-rtpsbcpay");
206 #else
207  /*TODO: Select the Audio Codec and RTP Audio Payloader based on input*/
208  audconvert = gst_element_factory_make ("audioconvert", "btmgr-so-aconv");
209  audresample = gst_element_factory_make ("audioresample", "btmgr-so-aresample");
210  audenc = gst_element_factory_make ("sbcenc", "btmgr-so-sbcenc");
211  aecapsfilter= gst_element_factory_make ("capsfilter", "btmgr-so-aecapsfilter");
212  rtpaudpay = gst_element_factory_make ("rtpsbcpay", "btmgr-so-rtpsbcpay");
213 #endif
214  fdsink = gst_element_factory_make ("fdsink", "btmgr-so-fdsink");
215 
216 
217  /* Create a new pipeline to hold the elements */
218  pipeline = gst_pipeline_new ("btmgr-so-pipeline");
219 
220  loop = pstBtrMgrSoGst->pLoop;
221 
222  if (!appsrc || !volume || !audenc || !aecapsfilter || !rtpaudpay || !fdsink || !loop || !pipeline) {
223  BTRMGRLOG_ERROR ("Gstreamer plugin missing for streamOut\n");
224  return NULL;
225  }
226 
227  pstBtrMgrSoGst->pPipeline = (void*)pipeline;
228  pstBtrMgrSoGst->pSrc = (void*)appsrc;
229  pstBtrMgrSoGst->pVolume = (void*)volume;
230  pstBtrMgrSoGst->pSink = (void*)fdsink;
231  pstBtrMgrSoGst->pAudioConv = (void*)audconvert;
232  pstBtrMgrSoGst->pAudioResample = (void*)audresample;
233  pstBtrMgrSoGst->pAudioEnc = (void*)audenc;
234  pstBtrMgrSoGst->pAECapsFilter = (void*)aecapsfilter;
235  pstBtrMgrSoGst->pRtpAudioPay = (void*)rtpaudpay;
236  pstBtrMgrSoGst->gstClkTStamp = 0;
237  pstBtrMgrSoGst->inBufOffset = 0;
238  pstBtrMgrSoGst->bPipelineError = FALSE;
239  pstBtrMgrSoGst->bIsInputPaused = FALSE;
240  g_mutex_init(&pstBtrMgrSoGst->pipelineDataMutex);
241 
242 
243  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
244  busWatchId = gst_bus_add_watch(bus, btrMgr_SO_gstBusCallCb, pstBtrMgrSoGst);
245  pstBtrMgrSoGst->busWId = busWatchId;
246  g_object_unref(bus);
247 
248  /* setup */
249  gst_bin_add_many (GST_BIN (pipeline), appsrc, volume, audenc, aecapsfilter, rtpaudpay, fdsink, NULL);
250  gst_element_link_many (appsrc, volume, audenc, aecapsfilter, rtpaudpay, fdsink, NULL);
251 
252  g_signal_connect (appsrc, "need-data", G_CALLBACK(btrMgr_SO_NeedDataCb), pstBtrMgrSoGst);
253  g_signal_connect (appsrc, "enough-data", G_CALLBACK(btrMgr_SO_EnoughDataCb), pstBtrMgrSoGst);
254 
255 #endif
256 
257 
258  BTRMGRLOG_INFO ("GMainLoop Running\n");
259  g_main_loop_run (pstBtrMgrSoGst->pLoop);
260 
261 
262 #if !(ENABLE_MAIN_LOOP_CONTEXT)
263  if (pstBtrMgrSoGst->emptyBufPushId) {
264  GSource *emptyBufPushSource = g_main_context_find_source_by_id(mainContext, pstBtrMgrSoGst->emptyBufPushId);
265  if (emptyBufPushSource)
266  g_source_destroy(emptyBufPushSource);
267 
268  pstBtrMgrSoGst->emptyBufPushId = 0;
269  }
270 
271  if (busWatchId) {
272  GSource *busSource = g_main_context_find_source_by_id(mainContext, busWatchId);
273  if (busSource)
274  g_source_destroy(busSource);
275 
276  busWatchId = 0;
277  pstBtrMgrSoGst->busWId = busWatchId;
278  }
279 
280  if (idleSrcLoopRunningId) {
281  GSource *idleSrcLoopRunning = g_main_context_find_source_by_id(mainContext, idleSrcLoopRunningId);
282  if (idleSrcLoopRunning)
283  g_source_destroy(idleSrcLoopRunning);
284 
285  idleSrcLoopRunningId = 0;
286  }
287 
288 
289  g_main_context_pop_thread_default (mainContext);
290 #endif
291 
292 
293  BTRMGRLOG_INFO ("GMainLoop Exiting\n");
294  return pstBtrMgrSoGst;
295 }
296 
297 
298 /* Interfaces */
299 eBTRMgrSOGstRet
301  tBTRMgrSoGstHdl* phBTRMgrSoGstHdl,
302  fPtr_BTRMgr_SO_GstStatusCb afpcBSoGstStatus,
303  void* apvUserData
304 ) {
305 #if (ENABLE_MAIN_LOOP_CONTEXT)
306  GstElement* appsrc = NULL;
307  GstElement* volume = NULL;
308  GstElement* audconvert = NULL;
309  GstElement* audresample = NULL;
310  GstElement* audenc = NULL;
311  GstElement* aecapsfilter = NULL;
312  GstElement* rtpaudpay = NULL;
313  GstElement* fdsink = NULL;
314  GstElement* pipeline = NULL;
315  GstBus* bus = NULL;
316  guint busWatchId;
317 #else
318  GMainContext* mainContext = NULL;
319 #endif
320 
321  stBTRMgrSOGst* pstBtrMgrSoGst = NULL;
322  GThread* mainLoopThread = NULL;
323  GMainLoop* loop = NULL;
324 
325 
326  if ((pstBtrMgrSoGst = (stBTRMgrSOGst*)malloc (sizeof(stBTRMgrSOGst))) == NULL) {
327  BTRMGRLOG_ERROR ("Unable to allocate memory\n");
328  return eBTRMgrSOGstFailure;
329  }
330 
331  memset((void*)pstBtrMgrSoGst, 0, sizeof(stBTRMgrSOGst));
332 
333  gst_init (NULL, NULL);
334 
335 #if (ENABLE_MAIN_LOOP_CONTEXT)
336  /* Create elements */
337  appsrc = gst_element_factory_make ("appsrc", "btmgr-so-appsrc");
338  volume = gst_element_factory_make ("volume", "btmgr-so-volume");
339 #if defined(DISABLE_AUDIO_ENCODING)
340  audconvert = gst_element_factory_make ("queue", "btmgr-so-aconv");
341  audresample = gst_element_factory_make ("queue", "btmgr-so-aresample");
342  audenc = gst_element_factory_make ("queue", "btmgr-so-sbcenc");
343  aecapsfilter= gst_element_factory_make ("queue", "btmgr-so-aecapsfilter");
344  rtpaudpay = gst_element_factory_make ("queue", "btmgr-so-rtpsbcpay");
345 #else
346  /*TODO: Select the Audio Codec and RTP Audio Payloader based on input*/
347  audconvert = gst_element_factory_make ("audioconvert", "btmgr-so-aconv");
348  audresample = gst_element_factory_make ("audioresample", "btmgr-so-aresample");
349  audenc = gst_element_factory_make ("sbcenc", "btmgr-so-sbcenc");
350  aecapsfilter= gst_element_factory_make ("capsfilter", "btmgr-so-aecapsfilter");
351  rtpaudpay = gst_element_factory_make ("rtpsbcpay", "btmgr-so-rtpsbcpay");
352 #endif
353  fdsink = gst_element_factory_make ("fdsink", "btmgr-so-fdsink");
354 
355  /* Create and event loop and feed gstreamer bus mesages to it */
356  loop = g_main_loop_new (NULL, FALSE);
357 #else
358  g_mutex_init (&pstBtrMgrSoGst->gMtxMainLoopRunLock);
359  g_cond_init (&pstBtrMgrSoGst->gCndMainLoopRun);
360 
361  mainContext = g_main_context_new();
362 
363  /* Create and event loop and feed gstreamer bus mesages to it */
364  if (mainContext) {
365  loop = g_main_loop_new (mainContext, FALSE);
366  }
367 #endif
368 
369 
370 #if (ENABLE_MAIN_LOOP_CONTEXT)
371  /* Create a new pipeline to hold the elements */
372  pipeline = gst_pipeline_new ("btmgr-so-pipeline");
373 
374  if (!appsrc || !volume || !audenc || !aecapsfilter || !rtpaudpay || !fdsink || !loop || !pipeline) {
375  BTRMGRLOG_ERROR ("Gstreamer plugin missing for streamOut\n");
376  //TODO: Call BTRMgr_SO_GstDeInit((tBTRMgrSoGstHdl)pstBtrMgrSoGst);
377  free((void*)pstBtrMgrSoGst);
378  return eBTRMgrSOGstFailure;
379  }
380 
381  pstBtrMgrSoGst->pPipeline = (void*)pipeline;
382  pstBtrMgrSoGst->pSrc = (void*)appsrc;
383  pstBtrMgrSoGst->pVolume = (void*)volume;
384  pstBtrMgrSoGst->pSink = (void*)fdsink;
385  pstBtrMgrSoGst->pAudioConv = (void*)audconvert;
386  pstBtrMgrSoGst->pAudioResample = (void*)audresample;
387  pstBtrMgrSoGst->pAudioEnc = (void*)audenc;
388  pstBtrMgrSoGst->pAECapsFilter = (void*)aecapsfilter;
389  pstBtrMgrSoGst->pRtpAudioPay = (void*)rtpaudpay;
390  pstBtrMgrSoGst->pLoop = (void*)loop;
391  pstBtrMgrSoGst->gstClkTStamp = 0;
392  pstBtrMgrSoGst->inBufOffset = 0;
393  pstBtrMgrSoGst->fpcBSoGstStatus = NULL;
394  pstBtrMgrSoGst->pvcBUserData = NULL;
395  pstBtrMgrSoGst->bPipelineError = FALSE;
396  pstBtrMgrSoGst->bIsInputPaused = FALSE;
397  g_mutex_init(&pstBtrMgrSoGst->pipelineDataMutex);
398 
399 
400  if (afpcBSoGstStatus) {
401  pstBtrMgrSoGst->fpcBSoGstStatus = afpcBSoGstStatus;
402  pstBtrMgrSoGst->pvcBUserData = apvUserData;
403  }
404 
405 
406  bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));
407  busWatchId = gst_bus_add_watch(bus, btrMgr_SO_gstBusCallCb, pstBtrMgrSoGst);
408  pstBtrMgrSoGst->busWId = busWatchId;
409  g_object_unref(bus);
410 
411  /* setup */
412  gst_bin_add_many (GST_BIN (pipeline), appsrc, volume, audenc, aecapsfilter, rtpaudpay, fdsink, NULL);
413  gst_element_link_many (appsrc, volume, audenc, aecapsfilter, rtpaudpay, fdsink, NULL);
414 
415 
416  mainLoopThread = g_thread_new("btrMgr_SO_g_main_loop_Task", btrMgr_SO_g_main_loop_Task, pstBtrMgrSoGst);
417  pstBtrMgrSoGst->pLoopThread = (void*)mainLoopThread;
418 
419  g_signal_connect (appsrc, "need-data", G_CALLBACK(btrMgr_SO_NeedDataCb), pstBtrMgrSoGst);
420  g_signal_connect (appsrc, "enough-data", G_CALLBACK(btrMgr_SO_EnoughDataCb), pstBtrMgrSoGst);
421 
422 #else
423  pstBtrMgrSoGst->pContext = (void*)mainContext;
424  pstBtrMgrSoGst->pLoop = (void*)loop;
425  pstBtrMgrSoGst->fpcBSoGstStatus = NULL;
426  pstBtrMgrSoGst->pvcBUserData = NULL;
427 
428  if (afpcBSoGstStatus) {
429  pstBtrMgrSoGst->fpcBSoGstStatus = afpcBSoGstStatus;
430  pstBtrMgrSoGst->pvcBUserData = apvUserData;
431  }
432 
433 
434  g_mutex_lock (&pstBtrMgrSoGst->gMtxMainLoopRunLock);
435  {
436  mainLoopThread = g_thread_new("btrMgr_SO_g_main_loop_Task", btrMgr_SO_g_main_loop_Task, pstBtrMgrSoGst);
437  pstBtrMgrSoGst->pLoopThread = (void*)mainLoopThread;
438 
439  //TODO: Infinite loop, break out of it gracefully in case of failures
440  while (!loop || !g_main_loop_is_running (loop)) {
441  g_cond_wait (&pstBtrMgrSoGst->gCndMainLoopRun, &pstBtrMgrSoGst->gMtxMainLoopRunLock);
442  }
443  }
444  g_mutex_unlock (&pstBtrMgrSoGst->gMtxMainLoopRunLock);
445 
446 #endif
447 
448  gst_element_set_state(GST_ELEMENT(pstBtrMgrSoGst->pPipeline), GST_STATE_NULL);
449  if (btrMgr_SO_validateStateWithTimeout(pstBtrMgrSoGst->pPipeline, GST_STATE_NULL, BTRMGR_SLEEP_TIMEOUT_MS)!= GST_STATE_NULL) {
450  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
451  BTRMgr_SO_GstDeInit((tBTRMgrSoGstHdl)pstBtrMgrSoGst);
452  return eBTRMgrSOGstFailure;
453  }
454 
455 
456  *phBTRMgrSoGstHdl = (tBTRMgrSoGstHdl)pstBtrMgrSoGst;
457 
458  return eBTRMgrSOGstSuccess;
459 }
460 
461 
462 eBTRMgrSOGstRet
464  tBTRMgrSoGstHdl hBTRMgrSoGstHdl
465 ) {
466  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
467 
468  if (!pstBtrMgrSoGst) {
469  BTRMGRLOG_ERROR ("Invalid input argument\n");
470  return eBTRMgrSOGstFailInArg;
471  }
472 
473  GstElement* pipeline = (GstElement*)pstBtrMgrSoGst->pPipeline;
474  GMainLoop* loop = (GMainLoop*)pstBtrMgrSoGst->pLoop;
475  GThread* mainLoopThread = (GThread*)pstBtrMgrSoGst->pLoopThread;
476 #if (ENABLE_MAIN_LOOP_CONTEXT)
477  guint busWatchId = pstBtrMgrSoGst->busWId;
478 #else
479  GMainContext* mainContext = (GMainContext*)pstBtrMgrSoGst->pContext;
480 #endif
481 
482  /* cleanup */
483  if (pipeline) {
484  gst_object_unref(GST_OBJECT(pipeline));
485  pipeline = NULL;
486  }
487 
488 #if (ENABLE_MAIN_LOOP_CONTEXT)
489  if (busWatchId) {
490  GSource *busSource = g_main_context_find_source_by_id(g_main_context_get_thread_default(), busWatchId);
491  if (busSource)
492  g_source_destroy(busSource);
493 
494  busWatchId = 0;
495  }
496 #endif
497 
498  if (loop) {
499  g_main_loop_quit(loop);
500  }
501 
502  if (mainLoopThread) {
503  g_thread_join(mainLoopThread);
504  mainLoopThread = NULL;
505  }
506 
507  if (loop) {
508  g_main_loop_unref(loop);
509  loop = NULL;
510  }
511 
512 #if !(ENABLE_MAIN_LOOP_CONTEXT)
513  if (mainContext) {
514  g_main_context_unref(mainContext);
515  mainContext = NULL;
516  }
517 #endif
518 
519  if (pstBtrMgrSoGst->fpcBSoGstStatus)
520  pstBtrMgrSoGst->fpcBSoGstStatus = NULL;
521 
522 
523  pstBtrMgrSoGst->bIsInputPaused = FALSE;
524 
525  g_mutex_lock(&pstBtrMgrSoGst->pipelineDataMutex);
526  pstBtrMgrSoGst->bPipelineError = FALSE;
527  g_mutex_unlock(&pstBtrMgrSoGst->pipelineDataMutex);
528 
529  g_mutex_clear(&pstBtrMgrSoGst->pipelineDataMutex);
530 
531 
532 #if !(ENABLE_MAIN_LOOP_CONTEXT)
533  g_cond_clear(&pstBtrMgrSoGst->gCndMainLoopRun);
534  g_mutex_clear(&pstBtrMgrSoGst->gMtxMainLoopRunLock);
535 #endif
536 
537 
538  memset((void*)pstBtrMgrSoGst, 0, sizeof(stBTRMgrSOGst));
539  free((void*)pstBtrMgrSoGst);
540  pstBtrMgrSoGst = NULL;
541 
542  return eBTRMgrSOGstSuccess;
543 }
544 
545 
546 eBTRMgrSOGstRet
548  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
549  int ai32InBufMaxSize,
550  const char* apcInFmt,
551  int ai32InRate,
552  int ai32InChannels,
553  int ai32OutRate,
554  int ai32OutChannels,
555  const char* apcOutChannelMode,
556  unsigned char aui8SbcAllocMethod,
557  unsigned char aui8SbcSubbands,
558  unsigned char aui8SbcBlockLength,
559  unsigned char aui8SbcMinBitpool,
560  unsigned char aui8SbcMaxBitpool,
561  int ai32BTDevFd,
562  int ai32BTDevMTU
563 ) {
564  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
565 
566  if (!pstBtrMgrSoGst || !apcInFmt) {
567  BTRMGRLOG_ERROR ("Invalid input argument\n");
568  return eBTRMgrSOGstFailInArg;
569  }
570 
571  GstElement* pipeline = (GstElement*)pstBtrMgrSoGst->pPipeline;
572  GstElement* appsrc = (GstElement*)pstBtrMgrSoGst->pSrc;
573  GstElement* volume = (GstElement*)pstBtrMgrSoGst->pVolume;
574  GstElement* fdsink = (GstElement*)pstBtrMgrSoGst->pSink;
575  GstElement* audconvert = (GstElement*)pstBtrMgrSoGst->pAudioConv;
576  GstElement* audresample = (GstElement*)pstBtrMgrSoGst->pAudioResample;
577  GstElement* audenc = (GstElement*)pstBtrMgrSoGst->pAudioEnc;
578  GstElement* aecapsfilter= (GstElement*)pstBtrMgrSoGst->pAECapsFilter;
579  GstElement* rtpaudpay = (GstElement*)pstBtrMgrSoGst->pRtpAudioPay;
580 
581  GstCaps* appsrcSrcCaps = NULL;
582  GstCaps* audEncSrcCaps = NULL;
583 
584  unsigned int lui32InBitsPSample = 0;
585  const char* lpui8StrSbcAllocMethod = NULL;
586 
587  /* Check if we are in correct state */
588  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_NULL, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_NULL) {
589  BTRMGRLOG_ERROR ("Incorrect State to perform Operation\n");
590  return eBTRMgrSOGstFailure;
591  }
592 
593  if (((ai32InRate != ai32OutRate) || (ai32InChannels != ai32OutChannels)) && audconvert && audresample) {
594  //TODO: Audio resampling from 48KHz to 44.1KHz results in some timestamp issues
595  // and discontinuties which we need to fix. Audio channel transition from
596  // Stereo to Mono
597  gst_bin_add_many(GST_BIN(pipeline), audconvert, audresample, NULL);
598  gst_element_unlink(volume, audenc);
599  gst_element_link_many (volume, audconvert, audresample, audenc, NULL);
600  }
601 
602  pstBtrMgrSoGst->gstClkTStamp = 0;
603  pstBtrMgrSoGst->inBufOffset = 0;
604 
605  if (!strcmp(apcInFmt, BTRMGR_AUDIO_SFMT_SIGNED_8BIT))
606  lui32InBitsPSample = 8;
607  else if (!strcmp(apcInFmt, BTRMGR_AUDIO_SFMT_SIGNED_LE_16BIT))
608  lui32InBitsPSample = 16;
609  else if (!strcmp(apcInFmt, BTRMGR_AUDIO_SFMT_SIGNED_LE_24BIT))
610  lui32InBitsPSample = 24;
611  else if (!strcmp(apcInFmt, BTRMGR_AUDIO_SFMT_SIGNED_LE_32BIT))
612  lui32InBitsPSample = 32;
613  else
614  lui32InBitsPSample = 16;
615 
616 
617  /*TODO: Set the caps dynamically based on input arguments to Start */
618  appsrcSrcCaps = gst_caps_new_simple ("audio/x-raw",
619  "format", G_TYPE_STRING, apcInFmt,
620  "layout", G_TYPE_STRING, "interleaved",
621  "rate", G_TYPE_INT, ai32InRate,
622  "channels", G_TYPE_INT, ai32InChannels,
623  NULL);
624 
625  if (aui8SbcAllocMethod == BTRMGR_SBC_ALLOCATION_SNR)
626  lpui8StrSbcAllocMethod = "snr";
627  else
628  lpui8StrSbcAllocMethod = "loudness";
629 
630  (void)aui8SbcMinBitpool;
631 
632  /*TODO: Set the Encoder ouput caps dynamically based on input arguments to Start */
633  audEncSrcCaps = gst_caps_new_simple ("audio/x-sbc",
634  "rate", G_TYPE_INT, ai32OutRate,
635  "channels", G_TYPE_INT, ai32OutChannels,
636  "channel-mode", G_TYPE_STRING, apcOutChannelMode,
637  "blocks", G_TYPE_INT, aui8SbcBlockLength,
638  "subbands", G_TYPE_INT, aui8SbcSubbands,
639  "allocation-method", G_TYPE_STRING, lpui8StrSbcAllocMethod,
640  "bitpool", G_TYPE_INT, aui8SbcMaxBitpool,
641  NULL);
642 
643  g_object_set (appsrc, "caps", appsrcSrcCaps, NULL);
644  g_object_set (appsrc, "blocksize", ai32InBufMaxSize, NULL);
645 
646  g_object_set (appsrc, "max-bytes", BTRMGR_MAX_INTERNAL_QUEUE_ELEMENTS * ai32InBufMaxSize, NULL);
647  g_object_set (appsrc, "is-live", 1, NULL);
648  g_object_set (appsrc, "block", 1, NULL);
649 
650 #if 0
651  g_object_set (appsrc, "do-timestamp", 1, NULL);
652 #endif
653  g_object_set (appsrc, "min-percent", 16, NULL);
654  g_object_set (appsrc, "min-latency", GST_USECOND * (ai32InBufMaxSize * 1000)/((ai32InRate/1000.0) * (lui32InBitsPSample/8) * ai32InChannels), NULL);
655  g_object_set (appsrc, "stream-type", GST_APP_STREAM_TYPE_STREAM, NULL);
656  g_object_set (appsrc, "format", GST_FORMAT_TIME, NULL);
657 
658  g_object_set (audenc, "perfect-timestamp", 1, NULL);
659 
660  g_object_set (aecapsfilter, "caps", audEncSrcCaps, NULL);
661 
662  g_object_set (rtpaudpay, "mtu", ai32BTDevMTU, NULL);
663  g_object_set (rtpaudpay, "min-frames", -1, NULL);
664  g_object_set (rtpaudpay, "perfect-rtptime", 1, NULL);
665 
666  g_object_set (fdsink, "fd", ai32BTDevFd, NULL);
667  g_object_set (fdsink, "sync", FALSE, NULL);
668 
669 
670  gst_caps_unref(audEncSrcCaps);
671  gst_caps_unref(appsrcSrcCaps);
672 
673 
674  g_mutex_lock(&pstBtrMgrSoGst->pipelineDataMutex);
675  pstBtrMgrSoGst->bPipelineError = FALSE;
676  g_mutex_unlock(&pstBtrMgrSoGst->pipelineDataMutex);
677 
678 
679  /* start play back and listed to events */
680  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
681  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_PLAYING, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PLAYING) {
682  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
683  return eBTRMgrSOGstFailure;
684  }
685 
686  pstBtrMgrSoGst->bIsInputPaused = FALSE;
687  pstBtrMgrSoGst->i32InBufMaxSize = ai32InBufMaxSize;
688  pstBtrMgrSoGst->i32InRate = ai32InRate;
689  pstBtrMgrSoGst->i32InChannels = ai32InChannels;
690  pstBtrMgrSoGst->ui32InBitsPSample = lui32InBitsPSample;
691  pstBtrMgrSoGst->ui32InBufIntervalms = round((pstBtrMgrSoGst->i32InBufMaxSize * 1000) / (pstBtrMgrSoGst->i32InRate * pstBtrMgrSoGst->i32InChannels * (pstBtrMgrSoGst->ui32InBitsPSample/8)));
692  pstBtrMgrSoGst->ui8IpBufThrsCnt = 0;
693 
694  BTRMGRLOG_WARN ("i32InRate - %d i32InChannels - %d, ui32InBitsPSample - %d, i32InBufMaxSize - %d ui32InBufIntervalms - %d\n",
695  pstBtrMgrSoGst->i32InRate, pstBtrMgrSoGst->i32InChannels, pstBtrMgrSoGst->ui32InBitsPSample, pstBtrMgrSoGst->i32InBufMaxSize, pstBtrMgrSoGst->ui32InBufIntervalms);
696 
697 #if !(ENABLE_MAIN_LOOP_CONTEXT)
698  {
699  GSource* source = g_timeout_source_new(pstBtrMgrSoGst->ui32InBufIntervalms);
700  g_source_set_priority(source, G_PRIORITY_DEFAULT);
701  g_source_set_callback(source, (GSourceFunc) btrMgr_SO_g_timeout_EmptyBufPushCb, pstBtrMgrSoGst, NULL);
702 
703  if (pstBtrMgrSoGst->emptyBufPushId) {
704  g_source_destroy(g_main_context_find_source_by_id(pstBtrMgrSoGst->pContext, pstBtrMgrSoGst->emptyBufPushId));
705  pstBtrMgrSoGst->emptyBufPushId = 0;
706  }
707 
708  if ((pstBtrMgrSoGst->emptyBufPushId = g_source_attach(source, pstBtrMgrSoGst->pContext)) != 0) {
709  BTRMGRLOG_DEBUG("Empty Buf Push Id = %d\n", pstBtrMgrSoGst->emptyBufPushId);
710  }
711 
712  g_source_unref(source);
713  }
714 #endif
715 
716  return eBTRMgrSOGstSuccess;
717 }
718 
719 
720 eBTRMgrSOGstRet
722  tBTRMgrSoGstHdl hBTRMgrSoGstHdl
723 ) {
724  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
725  GstElement* pipeline = NULL;
726 
727  if (!pstBtrMgrSoGst) {
728  BTRMGRLOG_ERROR ("Invalid input argument\n");
729  return eBTRMgrSOGstFailInArg;
730  }
731 
732  pipeline = (GstElement*)pstBtrMgrSoGst->pPipeline;
733 
734  pstBtrMgrSoGst->bIsInputPaused = FALSE;
735 
736  g_mutex_lock(&pstBtrMgrSoGst->pipelineDataMutex);
737  pstBtrMgrSoGst->bPipelineError = FALSE;
738  g_mutex_unlock(&pstBtrMgrSoGst->pipelineDataMutex);
739 
740 
741  /* stop play back */
742  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_NULL);
743  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_NULL, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_NULL) {
744  BTRMGRLOG_ERROR ("- Unable to perform Operation\n");
745  return eBTRMgrSOGstFailure;
746  }
747 
748  pstBtrMgrSoGst->gstClkTStamp = 0;
749  pstBtrMgrSoGst->inBufOffset = 0;
750 
751  pstBtrMgrSoGst->i32InBufMaxSize = 0;
752  pstBtrMgrSoGst->i32InRate = 0;
753  pstBtrMgrSoGst->i32InChannels = 0;
754  pstBtrMgrSoGst->ui32InBitsPSample = 0;
755  pstBtrMgrSoGst->ui32InBufIntervalms = 0;
756  pstBtrMgrSoGst->ui8IpBufThrsCnt = 0;
757 
758 
759  return eBTRMgrSOGstSuccess;
760 }
761 
762 
763 eBTRMgrSOGstRet
765  tBTRMgrSoGstHdl hBTRMgrSoGstHdl
766 ) {
767  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
768  GstElement* pipeline = NULL;
769 
770  if (!pstBtrMgrSoGst) {
771  BTRMGRLOG_ERROR ("Invalid input argument\n");
772  return eBTRMgrSOGstFailInArg;
773  }
774 
775  pipeline = (GstElement*)pstBtrMgrSoGst->pPipeline;
776 
777 
778  /* Check if we are in correct state */
779  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_PLAYING, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PLAYING) {
780  BTRMGRLOG_ERROR ("Incorrect State to perform Operation\n");
781  return eBTRMgrSOGstFailure;
782  }
783 
784  /* pause playback and listed to events */
785  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PAUSED);
786  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_PAUSED, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PAUSED) {
787  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
788  return eBTRMgrSOGstFailure;
789  }
790 
791  return eBTRMgrSOGstSuccess;
792 }
793 
794 
795 eBTRMgrSOGstRet
797  tBTRMgrSoGstHdl hBTRMgrSoGstHdl
798 ) {
799  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
800  GstElement* pipeline = NULL;
801 
802  if (!pstBtrMgrSoGst) {
803  BTRMGRLOG_ERROR ("Invalid input argument\n");
804  return eBTRMgrSOGstFailInArg;
805  }
806 
807  pipeline = (GstElement*)pstBtrMgrSoGst->pPipeline;
808 
809 
810  /* Check if we are in correct state */
811  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_PAUSED, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PAUSED) {
812  BTRMGRLOG_ERROR ("Incorrect State to perform Operation\n");
813  return eBTRMgrSOGstFailure;
814  }
815 
816  /* Resume playback and listed to events */
817  gst_element_set_state(GST_ELEMENT(pipeline), GST_STATE_PLAYING);
818  if (btrMgr_SO_validateStateWithTimeout(pipeline, GST_STATE_PLAYING, BTRMGR_SLEEP_TIMEOUT_MS) != GST_STATE_PLAYING) {
819  BTRMGRLOG_ERROR ("Unable to perform Operation\n");
820  return eBTRMgrSOGstFailure;
821  }
822 
823  return eBTRMgrSOGstSuccess;
824 }
825 
826 
827 eBTRMgrSOGstRet
829  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
830  unsigned char ui8InputPaused
831 ) {
832  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
833  eBTRMgrSOGstRet lenBtrMgrSoGstRet = eBTRMgrSOGstFailure;
834 
835  if (!pstBtrMgrSoGst) {
836  BTRMGRLOG_ERROR ("Invalid input argument\n");
837  return eBTRMgrSOGstFailInArg;
838  }
839 
840 #if !(ENABLE_MAIN_LOOP_CONTEXT)
841  if (ui8InputPaused) {
842  GSource* source;
843 
844  BTRMGRLOG_WARN ("SO Empty Cb i32InRate - %d\n", pstBtrMgrSoGst->i32InRate);
845  BTRMGRLOG_WARN ("SO Empty Cb i32InChannels - %d\n", pstBtrMgrSoGst->i32InChannels);
846  BTRMGRLOG_WARN ("SO Empty Cb ui32InBitsPSample - %d\n", pstBtrMgrSoGst->ui32InBitsPSample);
847  BTRMGRLOG_WARN ("SO Empty Cb i32InBufMaxSize - %d\n", pstBtrMgrSoGst->i32InBufMaxSize);
848  BTRMGRLOG_WARN ("SO Empty Cb ui32InBufIntervalms- %d\n", pstBtrMgrSoGst->ui32InBufIntervalms);
849 
850  pstBtrMgrSoGst->bIsInputPaused = TRUE;
851  pstBtrMgrSoGst->ui8IpBufThrsCnt = BTRMGR_INPUT_BUF_INTERVAL_THRES_CNT;
852  source = g_timeout_source_new(pstBtrMgrSoGst->ui32InBufIntervalms);
853  g_source_set_priority(source, G_PRIORITY_DEFAULT);
854  g_source_set_callback(source, (GSourceFunc) btrMgr_SO_g_timeout_EmptyBufPushCb, pstBtrMgrSoGst, NULL);
855 
856  if (pstBtrMgrSoGst->emptyBufPushId) {
857  g_source_destroy(g_main_context_find_source_by_id(pstBtrMgrSoGst->pContext, pstBtrMgrSoGst->emptyBufPushId));
858  pstBtrMgrSoGst->emptyBufPushId = 0;
859  }
860 
861  if ((pstBtrMgrSoGst->emptyBufPushId = g_source_attach(source, pstBtrMgrSoGst->pContext)) != 0) {
862  lenBtrMgrSoGstRet = eBTRMgrSOGstSuccess;
863  }
864 
865  g_source_unref(source);
866  }
867  else {
868  pstBtrMgrSoGst->bIsInputPaused = FALSE;
869  pstBtrMgrSoGst->ui8IpBufThrsCnt = 0;
870  if (pstBtrMgrSoGst->emptyBufPushId) {
871  BTRMGRLOG_WARN ("SO Empty Cb GSource Destroy - %d\n", pstBtrMgrSoGst->emptyBufPushId);
872  g_source_destroy(g_main_context_find_source_by_id(pstBtrMgrSoGst->pContext, pstBtrMgrSoGst->emptyBufPushId));
873  pstBtrMgrSoGst->emptyBufPushId = 0;
874  lenBtrMgrSoGstRet = eBTRMgrSOGstSuccess;
875  }
876  }
877 #endif
878 
879  return lenBtrMgrSoGstRet;
880 }
881 
882 
883 eBTRMgrSOGstRet
885  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
886  unsigned char ui8Volume
887 ) {
888  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
889  GstElement* volume = NULL;
890 
891  if (!pstBtrMgrSoGst) {
892  BTRMGRLOG_ERROR ("Invalid input argument\n");
893  return eBTRMgrSOGstFailInArg;
894  }
895 
896  volume = (GstElement*)pstBtrMgrSoGst->pVolume;
897 
898 
899  BTRMGRLOG_DEBUG("Volume at StreamOut Gst = %d, %f\n", ui8Volume, ui8Volume/255.0);
900  g_object_set (volume, "volume", (double)(ui8Volume/255.0), NULL);
901 
902  return eBTRMgrSOGstSuccess;
903 }
904 
905 
906 eBTRMgrSOGstRet
908  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
909  unsigned char* ui8Volume
910 ) {
911  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
912  GstElement* volume = NULL;
913  double dvolume = 0;
914 
915  if (!pstBtrMgrSoGst || !ui8Volume) {
916  BTRMGRLOG_ERROR ("Invalid input argument\n");
917  return eBTRMgrSOGstFailInArg;
918  }
919 
920  volume = (GstElement*)pstBtrMgrSoGst->pVolume;
921  g_object_get (volume, "volume", &dvolume, NULL);
922  *ui8Volume = (unsigned char )((dvolume) * 255) ;
923  BTRMGRLOG_DEBUG("Get Volume at StreamOut %d \n", *ui8Volume );
924 
925  return eBTRMgrSOGstSuccess;
926 }
927 
928 
929 eBTRMgrSOGstRet
931  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
932  gboolean mute
933 ) {
934  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
935  GstElement* volume = NULL;
936 
937  if (!pstBtrMgrSoGst) {
938  BTRMGRLOG_ERROR ("Invalid input argument\n");
939  return eBTRMgrSOGstFailInArg;
940  }
941 
942  volume = (GstElement*)pstBtrMgrSoGst->pVolume;
943  g_object_set (volume, "mute", mute, NULL);
944  BTRMGRLOG_DEBUG("Set mute at StreamOut %d \n", mute );
945 
946  return eBTRMgrSOGstSuccess;
947 }
948 
949 
950 eBTRMgrSOGstRet
952  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
953  gboolean * muted
954 ) {
955  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
956  gboolean mute = FALSE;
957  GstElement* volume = NULL;
958 
959  if (!pstBtrMgrSoGst || !muted) {
960  BTRMGRLOG_ERROR ("Invalid input argument\n");
961  return eBTRMgrSOGstFailInArg;
962  }
963 
964  volume = (GstElement*)pstBtrMgrSoGst->pVolume;
965  g_object_get (volume, "mute", &mute, NULL);
966  *muted = mute;
967  BTRMGRLOG_DEBUG("Get mute at StreamOut %d \n", *muted);
968 
969  return eBTRMgrSOGstSuccess;
970 }
971 
972 
973 eBTRMgrSOGstRet
975  tBTRMgrSoGstHdl hBTRMgrSoGstHdl,
976  char* pcInBuf,
977  int aiInBufSize
978 ) {
979  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
980 
981  if (!pstBtrMgrSoGst || !pcInBuf) {
982  BTRMGRLOG_ERROR ("Invalid input argument\n");
983  return eBTRMgrSOGstFailInArg;
984  }
985 
986 #if !(ENABLE_MAIN_LOOP_CONTEXT)
987  pstBtrMgrSoGst->bIsInputPaused = FALSE;
988  if (pstBtrMgrSoGst->emptyBufPushId && pstBtrMgrSoGst->pContext) {
989  BTRMGRLOG_WARN ("SO Empty Cb GSource Destroy - %d Context - %p\n", pstBtrMgrSoGst->emptyBufPushId, pstBtrMgrSoGst->pContext);
990  g_source_destroy(g_main_context_find_source_by_id(pstBtrMgrSoGst->pContext, pstBtrMgrSoGst->emptyBufPushId));
991  pstBtrMgrSoGst->emptyBufPushId = 0;
992  if (pstBtrMgrSoGst->ui8IpBufThrsCnt == BTRMGR_INPUT_BUF_INTERVAL_THRES_CNT) {
993  gst_element_send_event(GST_ELEMENT(pstBtrMgrSoGst->pPipeline), gst_event_new_flush_start());
994  gst_element_send_event(GST_ELEMENT(pstBtrMgrSoGst->pPipeline), gst_event_new_flush_stop(FALSE));
995  }
996  }
997 
998  pstBtrMgrSoGst->ui8IpBufThrsCnt = 0;
999 #endif
1000 
1001  return btrMgr_SO_GstSendBuffer(pstBtrMgrSoGst, pcInBuf, aiInBufSize);
1002 }
1003 
1004 
1005 static eBTRMgrSOGstRet
1006 btrMgr_SO_GstSendBuffer ( /* TODO: Move whole function to status function definitions section later */
1007  stBTRMgrSOGst* pstBtrMgrSoGst,
1008  char* pcInBuf,
1009  int aiInBufSize
1010 ) {
1011  int i32InBufOffset = 0;
1012  GstElement* appsrc = NULL;
1013  gboolean lbPipelineEr = FALSE;
1014 
1015  appsrc = (GstElement*)pstBtrMgrSoGst->pSrc;
1016 
1017 
1018  g_mutex_lock(&pstBtrMgrSoGst->pipelineDataMutex);
1019  lbPipelineEr = pstBtrMgrSoGst->bPipelineError;
1020  g_mutex_unlock(&pstBtrMgrSoGst->pipelineDataMutex);
1021 
1022 
1023  if (lbPipelineEr == TRUE) {
1024 #if 1
1025  return eBTRMgrSOGstSuccess;
1026 #else
1027  //TODO: This is the correct code. But we dont have
1028  // an upper layer, which can call DeInit to free the
1029  // the memory effectively without causing a deadlock
1030  // at this moment.
1031  return eBTRMgrSOGstFailure;
1032 #endif
1033  }
1034 
1035 
1036  /* push Buffers */
1037  while (aiInBufSize > pstBtrMgrSoGst->i32InBufMaxSize) {
1038  GstBuffer* gstBuf;
1039  GstMapInfo gstBufMap;
1040 
1041  gstBuf = gst_buffer_new_and_alloc (pstBtrMgrSoGst->i32InBufMaxSize);
1042  gst_buffer_set_size (gstBuf, pstBtrMgrSoGst->i32InBufMaxSize);
1043 
1044  gst_buffer_map (gstBuf, &gstBufMap, GST_MAP_WRITE);
1045 
1046  //TODO: Repalce memcpy and new_alloc if possible
1047  memcpy (gstBufMap.data, pcInBuf + i32InBufOffset, pstBtrMgrSoGst->i32InBufMaxSize);
1048 
1049  //TODO: Arrive at this vale based on Sampling rate, bits per sample, num of Channels and the
1050  // size of the incoming buffer (which represents the num of samples received at this instant)
1051  GST_BUFFER_PTS (gstBuf) = pstBtrMgrSoGst->gstClkTStamp;
1052  GST_BUFFER_DURATION (gstBuf) = GST_USECOND * (pstBtrMgrSoGst->i32InBufMaxSize * 1000)/((pstBtrMgrSoGst->i32InRate/1000.0) * (pstBtrMgrSoGst->ui32InBitsPSample/8) * pstBtrMgrSoGst->i32InChannels);
1053  pstBtrMgrSoGst->gstClkTStamp += GST_BUFFER_DURATION (gstBuf);
1054 
1055  GST_BUFFER_OFFSET (gstBuf) = pstBtrMgrSoGst->inBufOffset;
1056  pstBtrMgrSoGst->inBufOffset += pstBtrMgrSoGst->i32InBufMaxSize;
1057  GST_BUFFER_OFFSET_END (gstBuf) = pstBtrMgrSoGst->inBufOffset - 1;
1058 
1059  gst_buffer_unmap (gstBuf, &gstBufMap);
1060 
1061  //BTRMGRLOG_INFO ("PUSHING BUFFER = %d\n", pstBtrMgrSoGst->i32InBufMaxSize);
1062  gst_app_src_push_buffer (GST_APP_SRC (appsrc), gstBuf);
1063 
1064  aiInBufSize -= pstBtrMgrSoGst->i32InBufMaxSize;
1065  i32InBufOffset += pstBtrMgrSoGst->i32InBufMaxSize;
1066  }
1067 
1068 
1069  if (aiInBufSize) {
1070  GstBuffer* gstBuf;
1071  GstMapInfo gstBufMap;
1072 
1073  gstBuf = gst_buffer_new_and_alloc (aiInBufSize);
1074  gst_buffer_set_size (gstBuf, aiInBufSize);
1075 
1076  gst_buffer_map (gstBuf, &gstBufMap, GST_MAP_WRITE);
1077 
1078  //TODO: Repalce memcpy and new_alloc if possible
1079  memcpy (gstBufMap.data, pcInBuf + i32InBufOffset, aiInBufSize);
1080 
1081  //TODO: Arrive at this vale based on Sampling rate, bits per sample, num of Channels and the
1082  // size of the incoming buffer (which represents the num of samples received at this instant)
1083  GST_BUFFER_PTS (gstBuf) = pstBtrMgrSoGst->gstClkTStamp;
1084  GST_BUFFER_DURATION (gstBuf) = GST_USECOND * (aiInBufSize * 1000)/((pstBtrMgrSoGst->i32InRate/1000.0) * (pstBtrMgrSoGst->ui32InBitsPSample/8) * pstBtrMgrSoGst->i32InChannels);
1085  pstBtrMgrSoGst->gstClkTStamp += GST_BUFFER_DURATION (gstBuf);
1086 
1087  GST_BUFFER_OFFSET (gstBuf) = pstBtrMgrSoGst->inBufOffset;
1088  pstBtrMgrSoGst->inBufOffset += aiInBufSize;
1089  GST_BUFFER_OFFSET_END (gstBuf) = pstBtrMgrSoGst->inBufOffset - 1;
1090 
1091  gst_buffer_unmap (gstBuf, &gstBufMap);
1092 
1093  //BTRMGRLOG_INFO ("PUSHING BUFFER = %d\n", aiInBufSize);
1094  gst_app_src_push_buffer (GST_APP_SRC (appsrc), gstBuf);
1095  }
1096 
1097  return eBTRMgrSOGstSuccess;
1098 }
1099 
1100 
1101 eBTRMgrSOGstRet
1103  tBTRMgrSoGstHdl hBTRMgrSoGstHdl
1104 ) {
1105  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)hBTRMgrSoGstHdl;
1106  GstElement* appsrc = NULL;
1107  gboolean lbPipelineEr = FALSE;
1108 
1109  if (!pstBtrMgrSoGst) {
1110  BTRMGRLOG_ERROR ("Invalid input argument\n");
1111  return eBTRMgrSOGstFailInArg;
1112  }
1113 
1114  appsrc = (GstElement*)pstBtrMgrSoGst->pSrc;
1115 
1116 
1117  g_mutex_lock(&pstBtrMgrSoGst->pipelineDataMutex);
1118  lbPipelineEr = pstBtrMgrSoGst->bPipelineError;
1119  g_mutex_unlock(&pstBtrMgrSoGst->pipelineDataMutex);
1120 
1121 
1122  if (lbPipelineEr == TRUE) {
1123  return eBTRMgrSOGstFailure;
1124  }
1125 
1126 
1127  /* push EOS */
1128  gst_app_src_end_of_stream (GST_APP_SRC (appsrc));
1129  return eBTRMgrSOGstSuccess;
1130 }
1131 
1132 
1133 // Outgoing callbacks Registration Interfaces
1134 
1135 
1136 /* Incoming Callbacks */
1137 #if !(ENABLE_MAIN_LOOP_CONTEXT)
1138 static gboolean
1139 btrMgr_SO_g_main_loop_RunningCb (
1140  gpointer apstBtrMgrSoGst
1141 ) {
1142  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)apstBtrMgrSoGst;
1143 
1144  if (!pstBtrMgrSoGst) {
1145  BTRMGRLOG_ERROR ("GMainLoop Error - In arguments Exiting\n");
1146  return G_SOURCE_REMOVE;
1147  }
1148 
1149  BTRMGRLOG_INFO ("GMainLoop running now\n");
1150 
1151  g_mutex_lock (&pstBtrMgrSoGst->gMtxMainLoopRunLock);
1152  g_cond_signal (&pstBtrMgrSoGst->gCndMainLoopRun);
1153  g_mutex_unlock (&pstBtrMgrSoGst->gMtxMainLoopRunLock);
1154 
1155  return G_SOURCE_REMOVE;
1156 }
1157 
1158 
1159 static gboolean
1160 btrMgr_SO_g_timeout_EmptyBufPushCb (
1161  gpointer apstBtrMgrSoGst
1162 ) {
1163  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)apstBtrMgrSoGst;
1164  char* pcInBuf = NULL;
1165  if (!pstBtrMgrSoGst || !pstBtrMgrSoGst->i32InBufMaxSize) {
1166  BTRMGRLOG_ERROR ("GTimeOut Error - In arguments Exiting\n");
1167  return FALSE;
1168  }
1169 
1170  if ((pstBtrMgrSoGst->bIsInputPaused == FALSE) &&
1171  (pstBtrMgrSoGst->ui8IpBufThrsCnt >= BTRMGR_INPUT_BUF_INTERVAL_THRES_CNT)) {
1172  BTRMGRLOG_TRACE ("Not pushing Empty buffer - %d\n", pstBtrMgrSoGst->ui8IpBufThrsCnt);
1173  return TRUE;
1174  }
1175 
1176  if (pstBtrMgrSoGst->ui8IpBufThrsCnt < BTRMGR_INPUT_BUF_INTERVAL_THRES_CNT)
1177  pstBtrMgrSoGst->ui8IpBufThrsCnt++;
1178 
1179  if ((pcInBuf = malloc(pstBtrMgrSoGst->i32InBufMaxSize * sizeof(char))) == NULL) {
1180  BTRMGRLOG_ERROR ("GTimeOut Error - Unable to Alloc memory\n");
1181  return FALSE;
1182  }
1183 
1184  memset(pcInBuf, 0, pstBtrMgrSoGst->i32InBufMaxSize);
1185  if (btrMgr_SO_GstSendBuffer(pstBtrMgrSoGst, pcInBuf, pstBtrMgrSoGst->i32InBufMaxSize) != eBTRMgrSOGstSuccess) {
1186  BTRMGRLOG_WARN ("GTimeOut - Unable to Push Enpty Buffer\n");
1187  }
1188 
1189  free(pcInBuf);
1190 
1191  return TRUE;
1192 }
1193 #endif
1194 
1195 
1196 static void
1197 btrMgr_SO_NeedDataCb (
1198  GstElement* appsrc,
1199  guint size,
1200  gpointer apstBtrMgrSoGst
1201 ) {
1202  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)apstBtrMgrSoGst;
1203 
1204  //BTRMGRLOG_INFO ("NEED DATA = %d\n", size);
1205  if (pstBtrMgrSoGst && pstBtrMgrSoGst->fpcBSoGstStatus) {
1206  pstBtrMgrSoGst->fpcBSoGstStatus(eBTRMgrSOGstStUnderflow, pstBtrMgrSoGst->pvcBUserData);
1207  }
1208 }
1209 
1210 
1211 static void
1212 btrMgr_SO_EnoughDataCb (
1213  GstElement* appsrc,
1214  gpointer apstBtrMgrSoGst
1215 ) {
1216  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)apstBtrMgrSoGst;
1217 
1218  //BTRMGRLOG_INFO ("ENOUGH DATA\n");
1219  if (pstBtrMgrSoGst && pstBtrMgrSoGst->fpcBSoGstStatus) {
1220  pstBtrMgrSoGst->fpcBSoGstStatus(eBTRMgrSOGstStOverflow, pstBtrMgrSoGst->pvcBUserData);
1221  }
1222 }
1223 
1224 
1225 static gboolean
1226 btrMgr_SO_gstBusCallCb (
1227  GstBus* bus,
1228  GstMessage* msg,
1229  gpointer apstBtrMgrSoGst
1230 ) {
1231  stBTRMgrSOGst* pstBtrMgrSoGst = (stBTRMgrSOGst*)apstBtrMgrSoGst;
1232 
1233  switch (GST_MESSAGE_TYPE (msg)) {
1234 
1235  case GST_MESSAGE_EOS: {
1236  BTRMGRLOG_INFO ("End-of-stream\n");
1237  if (pstBtrMgrSoGst) {
1238  if (pstBtrMgrSoGst->pLoop) {
1239  g_main_loop_quit(pstBtrMgrSoGst->pLoop);
1240  }
1241 
1242  if (pstBtrMgrSoGst->fpcBSoGstStatus) {
1243  BTRMGRLOG_INFO ("EOS: Trigger Final Status cB\n");
1244  pstBtrMgrSoGst->fpcBSoGstStatus(pstBtrMgrSoGst->bPipelineError == TRUE ? eBTRMgrSOGstStError : eBTRMgrSOGstStCompleted,
1245  pstBtrMgrSoGst->pvcBUserData);
1246  }
1247  }
1248  break;
1249  }
1250 
1251  case GST_MESSAGE_STATE_CHANGED: {
1252  if (pstBtrMgrSoGst && (pstBtrMgrSoGst->pPipeline) && (GST_MESSAGE_SRC (msg) == GST_OBJECT (pstBtrMgrSoGst->pPipeline))) {
1253  GstState prevState, currentState;
1254 
1255  gst_message_parse_state_changed (msg, &prevState, &currentState, NULL);
1256  BTRMGRLOG_INFO ("From: %s -> To: %s\n",
1257  gst_element_state_get_name (prevState), gst_element_state_get_name (currentState));
1258  }
1259  break;
1260  }
1261 
1262  case GST_MESSAGE_ERROR: {
1263  gchar* debug;
1264  GError* err;
1265 
1266  if (pstBtrMgrSoGst) {
1267  g_mutex_lock(&pstBtrMgrSoGst->pipelineDataMutex);
1268  pstBtrMgrSoGst->bPipelineError = TRUE;
1269  g_mutex_unlock(&pstBtrMgrSoGst->pipelineDataMutex);
1270  }
1271 
1272  gst_message_parse_error (msg, &err, &debug);
1273  BTRMGRLOG_DEBUG ("Debugging info: %s\n", (debug) ? debug : "none");
1274  g_free (debug);
1275 
1276  BTRMGRLOG_ERROR ("Error: %s\n", err->message);
1277  g_error_free (err);
1278 
1279  if (pstBtrMgrSoGst) {
1280  if (pstBtrMgrSoGst->pLoop) {
1281  g_main_loop_quit(pstBtrMgrSoGst->pLoop);
1282  }
1283 
1284  if (pstBtrMgrSoGst->fpcBSoGstStatus) {
1285  BTRMGRLOG_INFO ("ERROR: Trigger Final Status cB\n");
1286  pstBtrMgrSoGst->fpcBSoGstStatus(pstBtrMgrSoGst->bPipelineError == TRUE ? eBTRMgrSOGstStError : eBTRMgrSOGstStCompleted,
1287  pstBtrMgrSoGst->pvcBUserData);
1288  }
1289  }
1290  break;
1291  }
1292 
1293  case GST_MESSAGE_WARNING:{
1294  gchar* debug;
1295  GError* warn;
1296 
1297  gst_message_parse_warning (msg, &warn, &debug);
1298  BTRMGRLOG_DEBUG ("Debugging info: %s\n", (debug) ? debug : "none");
1299  g_free (debug);
1300 
1301  BTRMGRLOG_WARN ("Warning: %s\n", warn->message);
1302  g_error_free (warn);
1303 
1304  if (pstBtrMgrSoGst && pstBtrMgrSoGst->fpcBSoGstStatus) {
1305  pstBtrMgrSoGst->fpcBSoGstStatus(eBTRMgrSOGstStWarning, pstBtrMgrSoGst->pvcBUserData);
1306  }
1307 
1308  break;
1309  }
1310 
1311  default:
1312  break;
1313 
1314  }
1315 
1316  return TRUE;
1317 }
1318 
BTRMgr_SO_GstDeInit
eBTRMgrSOGstRet BTRMgr_SO_GstDeInit(tBTRMgrSoGstHdl hBTRMgrSoGstHdl)
This API performs the cleanup operations.
Definition: btrMgr_streamOutGst.c:463
BTRMgr_SO_GstResume
eBTRMgrSOGstRet BTRMgr_SO_GstResume(tBTRMgrSoGstHdl hBTRMgrSoGstHdl)
This API resumes the current operation and listens to the events.
Definition: btrMgr_streamOutGst.c:796
BTRMgr_SO_GstSendEOS
eBTRMgrSOGstRet BTRMgr_SO_GstSendEOS(tBTRMgrSoGstHdl hBTRMgrSoGstHdl)
This API is used to push EOS(End of Stream) to the queue.
Definition: btrMgr_streamOutGst.c:1102
BTRMgr_SO_GstSetVolume
eBTRMgrSOGstRet BTRMgr_SO_GstSetVolume(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, unsigned char ui8Volume)
This API Sets the volume of current operation and listens to the events.
Definition: btrMgr_streamOutGst.c:884
BTRMgr_SO_GstGetMute
eBTRMgrSOGstRet BTRMgr_SO_GstGetMute(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, gboolean *muted)
This API Gets the Mute of current operation and listens to the events.
Definition: btrMgr_streamOutGst.c:951
BTRMgr_SO_GstSetInputPaused
eBTRMgrSOGstRet BTRMgr_SO_GstSetInputPaused(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, unsigned char ui8InputPaused)
This API Sets whether the input of current Buffers is Paused.
Definition: btrMgr_streamOutGst.c:828
BTRMgr_SO_GstInit
eBTRMgrSOGstRet BTRMgr_SO_GstInit(tBTRMgrSoGstHdl *phBTRMgrSoGstHdl, fPtr_BTRMgr_SO_GstStatusCb afpcBSoGstStatus, void *apvUserData)
This API initializes the streaming interface.
Definition: btrMgr_streamOutGst.c:300
_stBTRMgrSOGst
Definition: btrMgr_streamOutGst.c:64
btrMgr_streamOutGst.h
BTRMgr_SO_GstPause
eBTRMgrSOGstRet BTRMgr_SO_GstPause(tBTRMgrSoGstHdl hBTRMgrSoGstHdl)
This API pauses the current playback and listens to the events.
Definition: btrMgr_streamOutGst.c:764
BTRMgr_SO_GstGetVolume
eBTRMgrSOGstRet BTRMgr_SO_GstGetVolume(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, unsigned char *ui8Volume)
This API Gets the volume of current operation and listens to the events.
Definition: btrMgr_streamOutGst.c:907
BTRMgr_SO_GstStart
eBTRMgrSOGstRet BTRMgr_SO_GstStart(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, int ai32InBufMaxSize, const char *apcInFmt, int ai32InRate, int ai32InChannels, int ai32OutRate, int ai32OutChannels, const char *apcOutChannelMode, unsigned char aui8SbcAllocMethod, unsigned char aui8SbcSubbands, unsigned char aui8SbcBlockLength, unsigned char aui8SbcMinBitpool, unsigned char aui8SbcMaxBitpool, int ai32BTDevFd, int ai32BTDevMTU)
This API starts the playback and listens to the events associated with it.
Definition: btrMgr_streamOutGst.c:547
BTRMgr_SO_GstSetMute
eBTRMgrSOGstRet BTRMgr_SO_GstSetMute(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, gboolean mute)
This API Sets the Mute of current operation and listens to the events.
Definition: btrMgr_streamOutGst.c:930
BTRMgr_SO_GstStop
eBTRMgrSOGstRet BTRMgr_SO_GstStop(tBTRMgrSoGstHdl hBTRMgrSoGstHdl)
This API stops the current playback and sets the state as NULL.
Definition: btrMgr_streamOutGst.c:721
TRUE
#define TRUE
Defines for TRUE/FALSE/ENABLE flags.
Definition: wifi_common_hal.h:199
BTRMgr_SO_GstSendBuffer
eBTRMgrSOGstRet BTRMgr_SO_GstSendBuffer(tBTRMgrSoGstHdl hBTRMgrSoGstHdl, char *pcInBuf, int aiInBufSize)
This API pushes the buffer to the queue.
Definition: btrMgr_streamOutGst.c:974