|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: Telephony Multimedia Service |
|
15 * |
|
16 */ |
|
17 |
|
18 #include <audiopreference.h> |
|
19 #include <audiooutput.h> |
|
20 #include <mmcccodecinformation.h> |
|
21 #include <gstappsrc.h> |
|
22 #include "tmsutility.h" |
|
23 #include "gsterrorconcealmentinterface.h" |
|
24 #include "gstg711decoderinterface.h" |
|
25 #include "gstilbcdecoderinterface.h" |
|
26 #include "gstg729decoderinterface.h" |
|
27 #include "ipcallstream.h" |
|
28 |
|
29 using namespace TMS; |
|
30 |
|
31 static TMSVoIPDownlink* iSelfDn; |
|
32 #ifdef _DEBUG |
|
33 static TInt iHeap; |
|
34 #endif //_DEBUG |
|
35 GstBuffer* gstDnlBuffer; |
|
36 GstCaps* caps; |
|
37 gint requestBufLen; |
|
38 |
|
39 #ifdef __PLAY_WAV_FROM_FILE__ |
|
40 _LIT16(KTestFile1, "c:\\data\\sounds\\digital\\sample1.wav"); |
|
41 #endif |
|
42 |
|
43 // ----------------------------------------------------------------------------- |
|
44 // TMSVoIPDownlink::cb_raw_playback_handoff |
|
45 // ----------------------------------------------------------------------------- |
|
46 // |
|
47 void TMSVoIPDownlink::cb_raw_playback_handoff(GstElement* /*appsrc*/, |
|
48 guint size) |
|
49 { |
|
50 TRACE_PRN_N(_L("TMS->DNL: cb_raw_playback_handoff")); |
|
51 |
|
52 requestBufLen = size; |
|
53 |
|
54 #ifdef _DEBUG |
|
55 TInt block; |
|
56 RHeap &heap = User::Heap(); |
|
57 TInt avail = heap.Available(block); |
|
58 RDebug::Print(_L("TMS->PRINT-HEAP-DN:Size[%d], Available[%d], delta[%d]"), |
|
59 heap.Size(), avail, (iHeap - avail)); |
|
60 iHeap = avail; |
|
61 #endif //_DEBUG |
|
62 iSelfDn->BufferToBeFilled(); |
|
63 } |
|
64 |
|
65 // ----------------------------------------------------------------------------- |
|
66 // TMSVoIPDownlink::bus_call |
|
67 // ----------------------------------------------------------------------------- |
|
68 // |
|
69 gboolean TMSVoIPDownlink::bus_call(GstBus* /*bus*/, GstMessage* msg, |
|
70 gpointer /*data*/) |
|
71 { |
|
72 switch (GST_MESSAGE_TYPE(msg)) |
|
73 { |
|
74 case GST_MESSAGE_EOS: |
|
75 { |
|
76 gst_element_set_state(iSelfDn->iPipelinePlay, GST_STATE_NULL); |
|
77 gst_object_unref(GST_OBJECT(iSelfDn->iPipelinePlay)); |
|
78 break; |
|
79 } |
|
80 case GST_MESSAGE_ERROR: |
|
81 { |
|
82 gchar* debug; |
|
83 GError* err; |
|
84 gst_message_parse_error(msg, &err, &debug); |
|
85 g_free(debug); |
|
86 g_print("Error: %s\n", err->message); |
|
87 g_error_free(err); |
|
88 break; |
|
89 } |
|
90 default: |
|
91 { |
|
92 break; |
|
93 } |
|
94 } |
|
95 |
|
96 return ETrue; |
|
97 } |
|
98 |
|
99 // ----------------------------------------------------------------------------- |
|
100 // TMSVoIPDownlink::gst_initialize_play |
|
101 // ----------------------------------------------------------------------------- |
|
102 // |
|
103 gint TMSVoIPDownlink::gst_initialize_play() |
|
104 { |
|
105 TRACE_PRN_FN_ENT; |
|
106 |
|
107 gint err = KErrNone; |
|
108 |
|
109 // create elements |
|
110 iPipelinePlay = gst_pipeline_new("pipelinePlay"); |
|
111 iAppSrc = gst_element_factory_make("appsrc", "source"); |
|
112 iSink = gst_element_factory_make("devsoundsink", "sink"); |
|
113 |
|
114 if (!iAppSrc || !iSink) |
|
115 { |
|
116 err = KErrNotFound; |
|
117 TRACE_PRN_IF_ERR(err); |
|
118 return err; |
|
119 } |
|
120 |
|
121 iBusPlay = gst_pipeline_get_bus(GST_PIPELINE(iPipelinePlay)); |
|
122 gst_bus_add_watch(iBusPlay, TMSVoIPDownlink::bus_call, NULL); |
|
123 gst_object_unref(iBusPlay); |
|
124 |
|
125 iMaxBufLen = ConfigureMedia(iCodecID); |
|
126 |
|
127 g_object_set(iAppSrc, "stream-type", 0, "blocksize", iMaxBufLen, NULL); |
|
128 gst_bin_add_many(GST_BIN(iPipelinePlay), iAppSrc, iSink, NULL); |
|
129 gst_element_link(iAppSrc, iSink); |
|
130 |
|
131 caps = gst_caps_new_simple(iMediaType, |
|
132 "width", G_TYPE_INT, 16, |
|
133 "depth", G_TYPE_INT, 16, |
|
134 "signed", G_TYPE_BOOLEAN, TRUE, |
|
135 "endianness", G_TYPE_INT, G_BYTE_ORDER, |
|
136 "rate", G_TYPE_INT, 8000, |
|
137 "channels", G_TYPE_INT, 1, |
|
138 NULL); |
|
139 |
|
140 //NOTE: d/s is not ready at this time to return true maxvolume |
|
141 TInt maxvol = 10; |
|
142 #ifdef __WINSCW__ |
|
143 maxvol = 10000; |
|
144 #endif //__WINSCW__ |
|
145 g_object_set(G_OBJECT(iSink), |
|
146 "volume", maxvol, |
|
147 #ifndef __WINSCW__ |
|
148 "priority", (gint)iPriority.iPriority, |
|
149 "preference", (gint)iPriority.iPref, |
|
150 #endif |
|
151 NULL); |
|
152 |
|
153 gst_app_src_set_caps(GST_APP_SRC(iAppSrc), caps); |
|
154 gst_app_src_set_max_bytes(GST_APP_SRC(iAppSrc), iMaxBufLen); |
|
155 err = SetCodecCi(); |
|
156 //gst_element_set_state(iPipelinePlay, GST_STATE_READY); |
|
157 |
|
158 TRACE_PRN_FN_EXT; |
|
159 return err; |
|
160 } |
|
161 |
|
162 // ----------------------------------------------------------------------------- |
|
163 // TMSVoIPDownlink::gst_play_raw |
|
164 // ----------------------------------------------------------------------------- |
|
165 // |
|
166 gint TMSVoIPDownlink::gst_play_raw() |
|
167 { |
|
168 TRACE_PRN_FN_ENT; |
|
169 |
|
170 // start playback |
|
171 gst_element_set_state(iPipelinePlay, GST_STATE_PLAYING); |
|
172 |
|
173 //configure the appsrc, we will push buffer to appsrc when it needs more data |
|
174 g_signal_connect(iAppSrc, "need-data", |
|
175 G_CALLBACK (cb_raw_playback_handoff), |
|
176 NULL); |
|
177 TRACE_PRN_FN_EXT; |
|
178 return KErrNone; |
|
179 } |
|
180 |
|
181 // ----------------------------------------------------------------------------- |
|
182 // TMSVoIPDownlink::TMSVoIPDownlink |
|
183 // Standard Constructor |
|
184 // ----------------------------------------------------------------------------- |
|
185 // |
|
186 TMSVoIPDownlink::TMSVoIPDownlink() |
|
187 { |
|
188 iSelfDn = this; |
|
189 } |
|
190 |
|
191 // ----------------------------------------------------------------------------- |
|
192 // TMSVoIPDownlink::~TMSVoIPDownlink |
|
193 // Standard Constructor |
|
194 // ----------------------------------------------------------------------------- |
|
195 // |
|
196 TMSVoIPDownlink::~TMSVoIPDownlink() |
|
197 { |
|
198 TRACE_PRN_FN_ENT; |
|
199 |
|
200 Stop(); |
|
201 gst_caps_unref(caps); |
|
202 gst_object_unref(GST_OBJECT(iPipelinePlay)); |
|
203 gst_deinit(); |
|
204 |
|
205 delete iErrConcealmentIntfc; |
|
206 delete iG711DecoderIntfc; |
|
207 delete iG729DecoderIntfc; |
|
208 delete iIlbcDecoderIntfc; |
|
209 |
|
210 #ifdef __PLAY_WAV_FROM_FILE__ |
|
211 iFs.Close(); |
|
212 delete fbuf; |
|
213 #endif |
|
214 |
|
215 TRACE_PRN_FN_EXT; |
|
216 } |
|
217 |
|
218 // ----------------------------------------------------------------------------- |
|
219 // TMSVoIPDownlink::NewL |
|
220 // Symbian two-phase constructor |
|
221 // ----------------------------------------------------------------------------- |
|
222 // |
|
223 TMSVoIPDownlink* TMSVoIPDownlink::NewL(const guint32 codecID, |
|
224 const TMMFPrioritySettings priority) |
|
225 { |
|
226 TMSVoIPDownlink* self = new (ELeave) TMSVoIPDownlink(); |
|
227 CleanupStack::PushL(self); |
|
228 self->ConstructL(codecID, priority); |
|
229 CleanupStack::Pop(self); |
|
230 return self; |
|
231 } |
|
232 |
|
233 // ----------------------------------------------------------------------------- |
|
234 // TMSVoIPDownlink::ConstructL |
|
235 // Part two of Symbian two phase construction |
|
236 // ----------------------------------------------------------------------------- |
|
237 // |
|
238 void TMSVoIPDownlink::ConstructL(const guint32 codecID, |
|
239 const TMMFPrioritySettings priority) |
|
240 { |
|
241 TRACE_PRN_FN_ENT; |
|
242 |
|
243 iCodecID = codecID; |
|
244 iPriority = priority; |
|
245 // SetTime(); |
|
246 gst_init(NULL, NULL); |
|
247 // CalcLatency(); |
|
248 // SetTime(); |
|
249 |
|
250 gint err = gst_initialize_play(); |
|
251 if (err != TMS_RESULT_SUCCESS) |
|
252 { |
|
253 User::Leave(err); |
|
254 } |
|
255 |
|
256 // Client must set these before querying! |
|
257 iG711DecodeMode = TMS_G711_CODEC_MODE_ALAW; |
|
258 iILBCDecodeMode = TMS_ILBC_CODEC_MODE_20MS_FRAME; |
|
259 |
|
260 #ifdef __PLAY_WAV_FROM_FILE__ |
|
261 iReadSize = KVoIPPCM16FrameLen; |
|
262 err = iFs.Connect(); |
|
263 if (err == KErrNone) |
|
264 { |
|
265 err = iFile.Open(iFs, KTestFile1, EFileShareAny | EFileRead); |
|
266 } |
|
267 if (err == KErrNone) |
|
268 { |
|
269 iFile.Size(fsize); |
|
270 } |
|
271 fbuf = HBufC8::NewL(fsize); |
|
272 TPtr8 p = fbuf->Des(); |
|
273 iFile.Read(p, fsize); |
|
274 iFile.Close(); |
|
275 #endif |
|
276 // CalcLatency(); |
|
277 |
|
278 TRACE_PRN_FN_EXT; |
|
279 } |
|
280 |
|
281 // ----------------------------------------------------------------------------- |
|
282 // TMSVoIPDownlink::Start |
|
283 // |
|
284 // ----------------------------------------------------------------------------- |
|
285 // |
|
286 void TMSVoIPDownlink::Start() |
|
287 { |
|
288 TRACE_PRN_FN_ENT; |
|
289 |
|
290 gst_play_raw(); |
|
291 iStatus = EStreaming; |
|
292 |
|
293 TRACE_PRN_FN_EXT; |
|
294 } |
|
295 |
|
296 // ----------------------------------------------------------------------------- |
|
297 // TMSVoIPDownlink::Stop |
|
298 // |
|
299 // ----------------------------------------------------------------------------- |
|
300 // |
|
301 void TMSVoIPDownlink::Stop() |
|
302 { |
|
303 TRACE_PRN_FN_ENT; |
|
304 |
|
305 if (iStatus == EStreaming) |
|
306 { |
|
307 if (iPipelinePlay != NULL && |
|
308 iPipelinePlay->current_state == GST_STATE_PLAYING) |
|
309 { |
|
310 gst_element_set_state(iPipelinePlay, GST_STATE_NULL); |
|
311 } |
|
312 |
|
313 iStatus = EReady; |
|
314 } |
|
315 |
|
316 if (gstDnlBuffer) |
|
317 { |
|
318 gst_buffer_unref(gstDnlBuffer); |
|
319 } |
|
320 |
|
321 TRACE_PRN_FN_EXT; |
|
322 } |
|
323 |
|
324 // ----------------------------------------------------------------------------- |
|
325 // TMSVoIPDownlink::BufferToBeFilled |
|
326 // ----------------------------------------------------------------------------- |
|
327 // |
|
328 void TMSVoIPDownlink::BufferToBeFilled() |
|
329 { |
|
330 TRACE_PRN_N1(_L("TMS->DNL->BTBF: requestBufLen[%d]"), requestBufLen); |
|
331 |
|
332 #ifndef __PLAY_WAV_FROM_FILE__ |
|
333 // Create or adjust the chunk |
|
334 TInt err = DoChunk(requestBufLen, iMsgBuffer); |
|
335 |
|
336 if (err != TMS_RESULT_SUCCESS) |
|
337 { |
|
338 Stop(); |
|
339 iMsgBuffer.iStatus = err; |
|
340 } |
|
341 else |
|
342 { |
|
343 // Notify client there is buffer ready to be filled |
|
344 iMsgBuffer.iStatus = iChunk.Handle(); |
|
345 iMsgBuffer.iInt = requestBufLen; |
|
346 iStatus = EStreaming; |
|
347 // If chunk is opened, we will expect a call from the client to |
|
348 // get chunk handle. When we get a call to copy chunk handle, |
|
349 // check these variables and see if they match. This is not |
|
350 // completely secure, but will provide some level of security |
|
351 if (iMsgBuffer.iBool == TRUE) |
|
352 { |
|
353 iWriteDataXferHndlToClient = TRUE; |
|
354 iKey = iMsgBuffer.iUint32; |
|
355 } |
|
356 } |
|
357 |
|
358 iMsgBuffer.iRequest = ECmdFillBuffer; |
|
359 iMsgQueue.Send(iMsgBuffer); |
|
360 |
|
361 #else //__PLAY_WAV_FROM_FILE__ |
|
362 TInt err = KErrNone; |
|
363 BufferFilled(); |
|
364 #endif //__PLAY_WAV_FROM_FILE__ |
|
365 TRACE_PRN_IF_ERR(err); |
|
366 } |
|
367 |
|
368 // ----------------------------------------------------------------------------- |
|
369 // TMSVoIPDownlink::BufferFilled |
|
370 // |
|
371 // ----------------------------------------------------------------------------- |
|
372 // |
|
373 void TMSVoIPDownlink::BufferFilled(const guint buflen) |
|
374 { |
|
375 #ifndef __PLAY_WAV_FROM_FILE__ |
|
376 gstDnlBuffer = gst_buffer_new(); |
|
377 gst_buffer_set_caps(gstDnlBuffer, caps); |
|
378 GST_BUFFER_SIZE(gstDnlBuffer) = buflen; |
|
379 |
|
380 //TODO: what if bufLen > requestBufLen? |
|
381 |
|
382 // IMPL#1: |
|
383 // gstDnlBuffer->data pointer is set to use chunk pointer. |
|
384 // Although unlikely in the pull mode, this may potentially result |
|
385 // in data loss if chunk gets overwritten before it is consumed. |
|
386 gst_buffer_set_data(gstDnlBuffer, iChunk.Base(), buflen); |
|
387 |
|
388 // IMPL#2 |
|
389 // Alternative implementation with new buffer alloc and memcpy. |
|
390 // GStreamer will free this memory when buffer refcount becomes 0. |
|
391 //guint8* ptr = (guint8*)g_malloc(buflen); |
|
392 //GST_BUFFER_MALLOCDATA(gstDnlBuffer) = GST_BUFFER_DATA(gstDnlBuffer) = ptr; |
|
393 //memcpy(ptr, iChunk.Base(), buflen); |
|
394 |
|
395 #else //__PLAY_WAV_FROM_FILE__ |
|
396 User::After(TTimeIntervalMicroSeconds32(150000)); |
|
397 |
|
398 TPtr8 p = fbuf->Des(); |
|
399 TInt buflen = iReadSize; |
|
400 gstDnlBuffer = gst_buffer_new_and_alloc(buflen); |
|
401 gst_buffer_set_caps(gstDnlBuffer, caps); |
|
402 unsigned char* ptr = (unsigned char*)((fbuf->Ptr())+iReadBytes); |
|
403 gst_buffer_set_data(gstDnlBuffer, ptr, buflen); |
|
404 |
|
405 if ((iReadBytes + iReadSize> fsize)) |
|
406 { |
|
407 // start over from the beginning |
|
408 iReadBytes = 0; |
|
409 } |
|
410 else |
|
411 { |
|
412 iReadBytes += iReadSize; |
|
413 } |
|
414 |
|
415 #endif //__PLAY_WAV_FROM_FILE__ |
|
416 gst_app_src_push_buffer(GST_APP_SRC(iAppSrc), gstDnlBuffer); |
|
417 TRACE_PRN_N1(_L("TMS->DNL->BF: LEN[%d]"), buflen); |
|
418 } |
|
419 |
|
420 // ----------------------------------------------------------------------------- |
|
421 // TMSVoIPDownlink::SetCodecCi |
|
422 // |
|
423 // ----------------------------------------------------------------------------- |
|
424 // |
|
425 gint TMSVoIPDownlink::SetCodecCi() |
|
426 { |
|
427 TRAPD(err, SetCodecCiL()); |
|
428 return err; |
|
429 } |
|
430 |
|
431 // ----------------------------------------------------------------------------- |
|
432 // TMSVoIPDownlink::SetCodecCiL |
|
433 // |
|
434 // ----------------------------------------------------------------------------- |
|
435 // |
|
436 void TMSVoIPDownlink::SetCodecCiL() |
|
437 { |
|
438 TRACE_PRN_FN_ENT; |
|
439 |
|
440 switch (iCodecID) |
|
441 { |
|
442 case KMccFourCCIdG711: |
|
443 { |
|
444 if (!iG711DecoderIntfc) |
|
445 { |
|
446 iG711DecoderIntfc = GST_G711_DECODER_GET_IFACE(iSink); |
|
447 } |
|
448 break; |
|
449 } |
|
450 case KMccFourCCIdG729: |
|
451 { |
|
452 if (!iG729DecoderIntfc) |
|
453 { |
|
454 iG729DecoderIntfc = GST_G729_DECODER_GET_IFACE(iSink); |
|
455 } |
|
456 break; |
|
457 } |
|
458 case KMccFourCCIdILBC: |
|
459 { |
|
460 if (!iIlbcDecoderIntfc) |
|
461 { |
|
462 iIlbcDecoderIntfc = GST_ILBC_DECODER_GET_IFACE(iSink); |
|
463 } |
|
464 break; |
|
465 } |
|
466 case KMccFourCCIdAMRNB: |
|
467 case KMMFFourCCCodePCM16: |
|
468 { |
|
469 break; |
|
470 } |
|
471 default: |
|
472 { |
|
473 User::Leave(TMS_RESULT_INVALID_ARGUMENT); |
|
474 } |
|
475 } |
|
476 |
|
477 if (iCodecID == KMccFourCCIdG711 || |
|
478 iCodecID == KMccFourCCIdG729 || |
|
479 iCodecID == KMccFourCCIdILBC || |
|
480 iCodecID == KMccFourCCIdAMRNB) |
|
481 { |
|
482 if (!iErrConcealmentIntfc) |
|
483 { |
|
484 iErrConcealmentIntfc = GST_ERROR_CONCEALMENT_GET_IFACE(iSink); |
|
485 } |
|
486 } |
|
487 |
|
488 TRACE_PRN_FN_EXT; |
|
489 } |
|
490 |
|
491 // ----------------------------------------------------------------------------- |
|
492 // TMSVoIPDownlink::SetVolume |
|
493 // |
|
494 // ----------------------------------------------------------------------------- |
|
495 // |
|
496 gint TMSVoIPDownlink::SetVolume(const guint volume) |
|
497 { |
|
498 g_object_set(G_OBJECT(iSink), "volume", volume, NULL); |
|
499 TRACE_PRN_N1(_L("TMS->DNL: SetVolume [%d]"), volume); |
|
500 return TMS_RESULT_SUCCESS; |
|
501 } |
|
502 |
|
503 // ----------------------------------------------------------------------------- |
|
504 // TMSVoIPDownlink::GetVolume |
|
505 // |
|
506 // ----------------------------------------------------------------------------- |
|
507 // |
|
508 gint TMSVoIPDownlink::GetVolume(guint& volume) |
|
509 { |
|
510 g_object_get(G_OBJECT(iSink), "volume", &volume, NULL); |
|
511 TRACE_PRN_N1(_L("TMS->DNL: GetVolume [%d]"), volume); |
|
512 return TMS_RESULT_SUCCESS; |
|
513 } |
|
514 |
|
515 // ----------------------------------------------------------------------------- |
|
516 // TMSVoIPDownlink::GetMaxVolume |
|
517 // |
|
518 // ----------------------------------------------------------------------------- |
|
519 // |
|
520 gint TMSVoIPDownlink::GetMaxVolume(guint& volume) |
|
521 { |
|
522 g_object_get(G_OBJECT(iSink), "maxvolume", &volume, NULL); |
|
523 TRACE_PRN_N1(_L("TMS->DNL: MaxVolume [%d]"), volume); |
|
524 return TMS_RESULT_SUCCESS; |
|
525 } |
|
526 |
|
527 // ----------------------------------------------------------------------------- |
|
528 // TMSVoIPDownlink::GetDataXferChunkHndl |
|
529 // |
|
530 // ----------------------------------------------------------------------------- |
|
531 // |
|
532 gint TMSVoIPDownlink::GetDataXferChunkHndl(const TUint32 key, RChunk& chunk) |
|
533 { |
|
534 gint status = TMS_RESULT_DOES_NOT_EXIST; |
|
535 |
|
536 if (iChunk.Handle()) |
|
537 { |
|
538 if (iWriteDataXferHndlToClient && (iKey == key)) |
|
539 { |
|
540 chunk = iChunk; |
|
541 iWriteDataXferHndlToClient = FALSE; |
|
542 iKey = 0; |
|
543 status = TMS_RESULT_SUCCESS; |
|
544 } |
|
545 else |
|
546 { |
|
547 status = TMS_RESULT_ILLEGAL_OPERATION; |
|
548 } |
|
549 } |
|
550 |
|
551 TRACE_PRN_IF_ERR(status); |
|
552 return status; |
|
553 } |
|
554 |
|
555 // ----------------------------------------------------------------------------- |
|
556 // TMSVoIPDownlink::SetIlbcCodecMode |
|
557 // |
|
558 // ----------------------------------------------------------------------------- |
|
559 // |
|
560 gint TMSVoIPDownlink::SetIlbcCodecMode(gint mode) |
|
561 { |
|
562 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
563 |
|
564 if (iStatus == EReady) |
|
565 { |
|
566 iILBCDecodeMode = mode; |
|
567 |
|
568 if (iIlbcDecoderIntfc && iCodecID == KMccFourCCIdILBC) |
|
569 { |
|
570 if (mode == TMS_ILBC_CODEC_MODE_20MS_FRAME) |
|
571 { |
|
572 err = iIlbcDecoderIntfc->SetDecoderMode(E20msFrame); |
|
573 TRACE_PRN_N(_L("TMS->DNL: iLBC Mode Set [20ms]")); |
|
574 } |
|
575 else if (mode == TMS_ILBC_CODEC_MODE_30MS_FRAME) |
|
576 { |
|
577 err = iIlbcDecoderIntfc->SetDecoderMode(E30msFrame); |
|
578 TRACE_PRN_N(_L("TMS->DNL: iLBC Mode Set [30ms]")); |
|
579 } |
|
580 } |
|
581 } |
|
582 |
|
583 TRACE_PRN_IF_ERR(err); |
|
584 return err; |
|
585 } |
|
586 |
|
587 // ----------------------------------------------------------------------------- |
|
588 // TMSVoIPDownlink::GetIlbcCodecMode |
|
589 // |
|
590 // ----------------------------------------------------------------------------- |
|
591 // |
|
592 gint TMSVoIPDownlink::GetIlbcCodecMode(gint& mode) |
|
593 { |
|
594 // not available through CIs -> return cashed value |
|
595 mode = iILBCDecodeMode; |
|
596 TRACE_PRN_N1(_L("TMS->DNL: GetIlbcCodecMode [%d]"), mode); |
|
597 return TMS_RESULT_SUCCESS; |
|
598 } |
|
599 |
|
600 // ----------------------------------------------------------------------------- |
|
601 // TMSVoIPDownlink::SetG711CodecMode |
|
602 // |
|
603 // ----------------------------------------------------------------------------- |
|
604 // |
|
605 gint TMSVoIPDownlink::SetG711CodecMode(gint mode) |
|
606 { |
|
607 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
608 |
|
609 if (iStatus == EReady) |
|
610 { |
|
611 iG711DecodeMode = mode; |
|
612 |
|
613 if (iG711DecoderIntfc && iCodecID == KMccFourCCIdG711) |
|
614 { |
|
615 if (mode == TMS_G711_CODEC_MODE_ALAW) |
|
616 { |
|
617 err = iG711DecoderIntfc->SetDecoderMode(EDecALaw); |
|
618 TRACE_PRN_N(_L("TMS->DNL: G711 Mode Set [ALaw]")); |
|
619 } |
|
620 else if (mode == TMS_G711_CODEC_MODE_MULAW) |
|
621 { |
|
622 err = iG711DecoderIntfc->SetDecoderMode(EDecULaw); |
|
623 TRACE_PRN_N(_L("TMS->DNL: G711 Mode Set [uLaw]")); |
|
624 } |
|
625 } |
|
626 } |
|
627 |
|
628 TRACE_PRN_IF_ERR(err); |
|
629 return err; |
|
630 } |
|
631 |
|
632 // ----------------------------------------------------------------------------- |
|
633 // TMSVoIPDownlink::GetG711CodecMode |
|
634 // |
|
635 // ----------------------------------------------------------------------------- |
|
636 // |
|
637 gint TMSVoIPDownlink::GetG711CodecMode(gint& mode) |
|
638 { |
|
639 // not available through CIs -> return cached value |
|
640 mode = iG711DecodeMode; |
|
641 TRACE_PRN_N1(_L("TMS->DNL: GetG711CodecMode [%d]"), mode); |
|
642 return TMS_RESULT_SUCCESS; |
|
643 } |
|
644 |
|
645 // ----------------------------------------------------------------------------- |
|
646 // TMSVoIPDownlink::FrameModeRqrdForEC |
|
647 // |
|
648 // ----------------------------------------------------------------------------- |
|
649 // |
|
650 gint TMSVoIPDownlink::FrameModeRqrdForEC(gboolean& frmodereq) |
|
651 { |
|
652 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
653 |
|
654 if (iStatus == EReady) |
|
655 { |
|
656 if (iErrConcealmentIntfc) |
|
657 { |
|
658 err = iErrConcealmentIntfc->FrameModeRqrdForEC(&frmodereq); |
|
659 TRACE_PRN_N1(_L("TMS->DNL: FrameModeRqrdForEC [%d]"), frmodereq); |
|
660 } |
|
661 } |
|
662 |
|
663 TRACE_PRN_IF_ERR(err); |
|
664 return err; |
|
665 } |
|
666 |
|
667 // ----------------------------------------------------------------------------- |
|
668 // TMSVoIPDownlink::SetFrameMode |
|
669 // |
|
670 // ----------------------------------------------------------------------------- |
|
671 // |
|
672 gint TMSVoIPDownlink::SetFrameMode(const gboolean frmode) |
|
673 { |
|
674 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
675 |
|
676 if (iStatus == EReady) |
|
677 { |
|
678 iFrameMode = frmode; |
|
679 |
|
680 if (iErrConcealmentIntfc) |
|
681 { |
|
682 err = iErrConcealmentIntfc->SetFrameMode(frmode); |
|
683 TRACE_PRN_N1(_L("TMS->DNL: SetFrameMode [%d]"), frmode); |
|
684 } |
|
685 } |
|
686 |
|
687 TRACE_PRN_IF_ERR(err); |
|
688 return err; |
|
689 } |
|
690 |
|
691 // ----------------------------------------------------------------------------- |
|
692 // TMSVoIPDownlink::GetFrameMode |
|
693 // |
|
694 // ----------------------------------------------------------------------------- |
|
695 // |
|
696 gint TMSVoIPDownlink::GetFrameMode(gboolean& frmode) |
|
697 { |
|
698 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
699 |
|
700 if (iErrConcealmentIntfc) |
|
701 { |
|
702 // not available through CIs -> return cached value |
|
703 frmode = iFrameMode; |
|
704 TRACE_PRN_N1(_L("TMS->DNL: GetFrameMode [%d]"), frmode); |
|
705 err = TMS_RESULT_SUCCESS; |
|
706 } |
|
707 |
|
708 TRACE_PRN_IF_ERR(err); |
|
709 return err; |
|
710 } |
|
711 |
|
712 // ----------------------------------------------------------------------------- |
|
713 // TMSVoIPDownlink::ConcealErrorForNextBuffer |
|
714 // |
|
715 // ----------------------------------------------------------------------------- |
|
716 // |
|
717 gint TMSVoIPDownlink::ConcealErrorForNextBuffer() |
|
718 { |
|
719 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
720 |
|
721 if (iErrConcealmentIntfc) |
|
722 { |
|
723 err = iErrConcealmentIntfc->ConcealErrorForNextBuffer(); |
|
724 TRACE_PRN_N(_L("TMS->DNL: ConcealErrorForNextBuffer")); |
|
725 } |
|
726 |
|
727 TRACE_PRN_IF_ERR(err); |
|
728 return err; |
|
729 } |
|
730 |
|
731 // ----------------------------------------------------------------------------- |
|
732 // TMSVoIPDownlink::SetCng |
|
733 // |
|
734 // ----------------------------------------------------------------------------- |
|
735 // |
|
736 gint TMSVoIPDownlink::SetCng(const TMSFormatType fmttype, const gboolean cng) |
|
737 { |
|
738 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
739 |
|
740 if (iStatus == EReady) |
|
741 { |
|
742 if (fmttype == TMS_FORMAT_G711 && iG711DecoderIntfc) |
|
743 { |
|
744 err = iG711DecoderIntfc->SetCng(cng); |
|
745 TRACE_PRN_N1(_L("TMS->DNL: SetCng [%d]"), cng); |
|
746 } |
|
747 else if (fmttype == TMS_FORMAT_ILBC && iIlbcDecoderIntfc) |
|
748 { |
|
749 err = iIlbcDecoderIntfc->SetCng(cng); |
|
750 TRACE_PRN_N1(_L("TMS->DNL: SetCng [%d]"), cng); |
|
751 } |
|
752 } |
|
753 |
|
754 TRACE_PRN_IF_ERR(err); |
|
755 return err; |
|
756 } |
|
757 |
|
758 // ----------------------------------------------------------------------------- |
|
759 // TMSVoIPDownlink::GetCng |
|
760 // |
|
761 // ----------------------------------------------------------------------------- |
|
762 // |
|
763 gint TMSVoIPDownlink::GetCng(const TMSFormatType fmttype, gboolean& cng) |
|
764 { |
|
765 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
766 |
|
767 if (iStatus == EReady) |
|
768 { |
|
769 if (fmttype == TMS_FORMAT_G711 && iG711DecoderIntfc) |
|
770 { |
|
771 err = iG711DecoderIntfc->GetCng(&cng); |
|
772 TRACE_PRN_N1(_L("TMS->DNL: GetCng [%d]"), cng); |
|
773 } |
|
774 else if (fmttype == TMS_FORMAT_ILBC && iIlbcDecoderIntfc) |
|
775 { |
|
776 err = iIlbcDecoderIntfc->GetCng(&cng); |
|
777 TRACE_PRN_N1(_L("TMS->DNL: GetCng [%d]"), cng); |
|
778 } |
|
779 } |
|
780 |
|
781 TRACE_PRN_IF_ERR(err); |
|
782 return err; |
|
783 } |
|
784 |
|
785 // ----------------------------------------------------------------------------- |
|
786 // TMSVoIPDownlink::SetPlc |
|
787 // |
|
788 // ----------------------------------------------------------------------------- |
|
789 // |
|
790 gint TMSVoIPDownlink::SetPlc(const TMSFormatType fmttype, const gboolean plc) |
|
791 { |
|
792 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
793 |
|
794 if (iStatus == EReady) |
|
795 { |
|
796 if (fmttype == TMS_FORMAT_G711 && iG711DecoderIntfc) |
|
797 { |
|
798 iPlc = plc; |
|
799 err = iG711DecoderIntfc->SetPlc(iPlc); |
|
800 TRACE_PRN_N1(_L("TMS->DNL: SetPlc [%d]"), plc); |
|
801 } |
|
802 } |
|
803 |
|
804 TRACE_PRN_IF_ERR(err); |
|
805 return err; |
|
806 } |
|
807 |
|
808 // ----------------------------------------------------------------------------- |
|
809 // TMSVoIPDownlink::GetPlc |
|
810 // |
|
811 // ----------------------------------------------------------------------------- |
|
812 // |
|
813 gint TMSVoIPDownlink::GetPlc(const TMSFormatType fmttype, gboolean& plc) |
|
814 { |
|
815 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
816 |
|
817 if (fmttype == TMS_FORMAT_G711 && iG711DecoderIntfc) |
|
818 { |
|
819 // not available through CIs -> return cached value |
|
820 plc = iPlc; |
|
821 err = TMS_RESULT_SUCCESS; |
|
822 TRACE_PRN_N1(_L("TMS->DNL: GetPlc [%d]"), plc); |
|
823 } |
|
824 |
|
825 TRACE_PRN_IF_ERR(err); |
|
826 return err; |
|
827 } |
|
828 |
|
829 // ----------------------------------------------------------------------------- |
|
830 // TMSVoIPDownlink::BadLsfNextBuffer |
|
831 // |
|
832 // ----------------------------------------------------------------------------- |
|
833 // |
|
834 gint TMSVoIPDownlink::BadLsfNextBuffer() |
|
835 { |
|
836 gint err = TMS_RESULT_DOES_NOT_EXIST; |
|
837 |
|
838 if (iStatus == EStreaming) |
|
839 { |
|
840 if (iCodecID == KMccFourCCIdG729 && iG729DecoderIntfc) |
|
841 { |
|
842 err = iG729DecoderIntfc->BadLsfNextBuffer(); |
|
843 TRACE_PRN_N(_L("TMS->DNL: BadLsfNextBuffer")); |
|
844 } |
|
845 } |
|
846 |
|
847 TRACE_PRN_IF_ERR(err); |
|
848 return err; |
|
849 } |
|
850 |
|
851 // ----------------------------------------------------------------------------- |
|
852 // TMSVoIPDownlink::SetAudioDeviceL |
|
853 // |
|
854 // ----------------------------------------------------------------------------- |
|
855 void TMSVoIPDownlink::SetAudioDeviceL(TMSAudioOutput output) |
|
856 { |
|
857 gint outputDev; |
|
858 |
|
859 // ENoPreference=0, EAll=1, ENoOutput=2, EPrivate=3, EPublic=4 |
|
860 switch (output) |
|
861 { |
|
862 case TMS_AUDIO_OUTPUT_PRIVATE: |
|
863 case TMS_AUDIO_OUTPUT_HANDSET: |
|
864 outputDev = (gint)CAudioOutput::EPrivate; |
|
865 break; |
|
866 case TMS_AUDIO_OUTPUT_PUBLIC: |
|
867 case TMS_AUDIO_OUTPUT_LOUDSPEAKER: |
|
868 outputDev = (gint)CAudioOutput::EPublic; |
|
869 break; |
|
870 default: // Use default device routing |
|
871 outputDev = (gint)CAudioOutput::ENoPreference; |
|
872 break; |
|
873 } |
|
874 |
|
875 g_object_set(G_OBJECT(iSink), "outputdevice", outputDev, NULL); |
|
876 TRACE_PRN_N1(_L("TMS->DNL: SetAudioDeviceL [%d]"), outputDev); |
|
877 } |
|
878 |
|
879 // ----------------------------------------------------------------------------- |
|
880 // TMSVoIPDownlink::GetAudioDeviceL |
|
881 // |
|
882 // ----------------------------------------------------------------------------- |
|
883 // |
|
884 void TMSVoIPDownlink::GetAudioDeviceL(TMSAudioOutput& output) |
|
885 { |
|
886 TRACE_PRN_FN_ENT; |
|
887 |
|
888 gint outputDev; |
|
889 g_object_get(G_OBJECT(iSink), "outputdevice", &outputDev, NULL); |
|
890 TRACE_PRN_N1(_L("TMS->DNL: GetAudioDevice [%d]"), outputDev); |
|
891 |
|
892 switch (outputDev) |
|
893 { |
|
894 case CAudioOutput::ENoPreference: |
|
895 case CAudioOutput::EAll: |
|
896 case CAudioOutput::ENoOutput: |
|
897 case CAudioOutput::EPrivate: |
|
898 output = TMS_AUDIO_OUTPUT_PRIVATE; |
|
899 break; |
|
900 case CAudioOutput::EPublic: |
|
901 output = TMS_AUDIO_OUTPUT_PUBLIC; |
|
902 break; |
|
903 default: |
|
904 output = TMS_AUDIO_OUTPUT_PRIVATE; |
|
905 break; |
|
906 } |
|
907 |
|
908 TRACE_PRN_FN_EXT; |
|
909 } |
|
910 |
|
911 // End of file |