|
1 /* |
|
2 * Copyright (c) 2004-2008 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: Payload format component capable to write RTP payload |
|
15 * containing G711 audio. |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 // INCLUDE FILES |
|
23 #include "rtpheader.h" |
|
24 #include "g711payloadformatwrite.h" |
|
25 #include "mccrtpdatasink.h" |
|
26 #include "g711payloadformatdefs.h" |
|
27 #include "mccuids.hrh" |
|
28 #include "mccdef.h" |
|
29 #include "mccrtpmediaclock.h" |
|
30 #include "mccredpayloadwrite.h" |
|
31 #include "mccinternaldef.h" |
|
32 |
|
33 // ============================= LOCAL FUNCTIONS =============================== |
|
34 |
|
35 // ============================ MEMBER FUNCTIONS =============================== |
|
36 |
|
37 // ----------------------------------------------------------------------------- |
|
38 // CG711PayloadFormatRead::CG711PayloadFormatRead |
|
39 // C++ default constructor can NOT contain any code, that |
|
40 // might leave. |
|
41 // ----------------------------------------------------------------------------- |
|
42 // |
|
43 CG711PayloadFormatWrite::CG711PayloadFormatWrite() |
|
44 { |
|
45 } |
|
46 |
|
47 // ----------------------------------------------------------------------------- |
|
48 // CG711PayloadFormatWrite::ConstructL |
|
49 // Symbian 2nd phase constructor can leave. |
|
50 // ----------------------------------------------------------------------------- |
|
51 // |
|
52 void CG711PayloadFormatWrite::ConstructL ( MDataSink* aSink ) |
|
53 { |
|
54 DP_G711_WRITE( "CG711PayloadFormatWrite::ConstructL()" ); |
|
55 |
|
56 __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) ); |
|
57 |
|
58 // Set default values |
|
59 iFourCC.Set( KMccFourCCIdG711 ); |
|
60 |
|
61 iIsRtpSink = ( KMccRtpSinkUid == aSink->DataSinkType() ); |
|
62 TBool isRedEncoder |
|
63 = ( TUid::Uid( KImplUidRedPayloadFormatEncode ) == aSink->DataSinkType() ); |
|
64 |
|
65 if ( iIsRtpSink ) |
|
66 { |
|
67 CMccRtpDataSink* tmp = static_cast<CMccRtpDataSink*>( aSink ); |
|
68 iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp ); |
|
69 } |
|
70 else if ( isRedEncoder ) |
|
71 { |
|
72 CMccRedPayloadWrite* tmp = static_cast<CMccRedPayloadWrite*>( aSink ); |
|
73 iRtpDataSink = static_cast<MMccRtpDataSink*>( tmp ); |
|
74 iIsRtpSink = ETrue; |
|
75 } |
|
76 else |
|
77 { |
|
78 DP_G711_WRITE( "CG711PayloadFormatWrite::ConstructL, sink not RTP one" ); |
|
79 } |
|
80 |
|
81 iClip = aSink; |
|
82 |
|
83 // Initialize state machine |
|
84 iStateMachine = CFormatEncodeStateMachine::NewL( this ); |
|
85 iStateMachine->ChangeState( EEncodeIdle ); |
|
86 } |
|
87 |
|
88 // ----------------------------------------------------------------------------- |
|
89 // CG711PayloadFormatWrite::NewL |
|
90 // Two-phased constructor. |
|
91 // ----------------------------------------------------------------------------- |
|
92 // |
|
93 CG711PayloadFormatWrite* CG711PayloadFormatWrite::NewL ( MDataSink* aSink ) |
|
94 { |
|
95 DP_G711_WRITE( "CG711PayloadFormatWrite::NewL()" ); |
|
96 |
|
97 __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) ); |
|
98 |
|
99 CG711PayloadFormatWrite* self = new (ELeave) CG711PayloadFormatWrite; |
|
100 CleanupStack::PushL( self ); |
|
101 self->ConstructL( aSink ); |
|
102 CleanupStack::Pop( self ); |
|
103 return self; |
|
104 } |
|
105 |
|
106 // Destructor |
|
107 CG711PayloadFormatWrite::~CG711PayloadFormatWrite () |
|
108 { |
|
109 DP_G711_WRITE( "CG711PayloadFormatWrite::~CG711PayloadFormatWrite()" ); |
|
110 if ( iStateMachine ) |
|
111 { |
|
112 iStateMachine->Cancel(); |
|
113 } |
|
114 |
|
115 // Media clock is not owned |
|
116 if ( iRtpMediaClock ) |
|
117 { |
|
118 iRtpMediaClock->UnregisterMediaFormat( iKey ); |
|
119 } |
|
120 |
|
121 delete iSourceBuffer; |
|
122 delete iSinkBuffer; |
|
123 delete iStateMachine; |
|
124 } |
|
125 |
|
126 // ----------------------------------------------------------------------------- |
|
127 // CG711PayloadFormatWrite::SinkThreadLogon |
|
128 // Passes the logon command to the sink clip |
|
129 // ----------------------------------------------------------------------------- |
|
130 // |
|
131 TInt CG711PayloadFormatWrite::SinkThreadLogon(MAsyncEventHandler& aEventHandler) |
|
132 { |
|
133 iClip->SinkThreadLogon( aEventHandler ); |
|
134 return KErrNone; |
|
135 } |
|
136 |
|
137 // ----------------------------------------------------------------------------- |
|
138 // CG711PayloadFormatWrite::SinkThreadLogoff |
|
139 // Passes the logoff command to the sink clip |
|
140 // ----------------------------------------------------------------------------- |
|
141 void CG711PayloadFormatWrite::SinkThreadLogoff() |
|
142 { |
|
143 iClip->SinkThreadLogoff(); |
|
144 } |
|
145 |
|
146 // ----------------------------------------------------------------------------- |
|
147 // CG711PayloadFormatWrite::CreateSinkBufferL |
|
148 // Create a sink buffer |
|
149 // ----------------------------------------------------------------------------- |
|
150 // |
|
151 CMMFBuffer* CG711PayloadFormatWrite::CreateSinkBufferL( TMediaId aMediaId, |
|
152 TBool &aReference ) |
|
153 { |
|
154 DP_G711_WRITE( "CG711PayloadFormatWrite::CreateSinkBufferL()" ); |
|
155 |
|
156 if ( KUidMediaTypeAudio != aMediaId.iMediaType ) |
|
157 { |
|
158 User::Leave( KErrNotSupported ); |
|
159 } |
|
160 |
|
161 aReference = ETrue; |
|
162 |
|
163 // Create buffer for data transfer between ULDataPath and FormatWrite |
|
164 return CreateSinkBufferOfSizeL( iCInfo.iFrameSize + KVoIPHeaderLength ); |
|
165 } |
|
166 |
|
167 // ----------------------------------------------------------------------------- |
|
168 // CG711PayloadFormatWrite::CreateSinkBufferOfSizeL |
|
169 // Create a sink buffer of the given size. |
|
170 // ----------------------------------------------------------------------------- |
|
171 // |
|
172 CMMFDataBuffer* CG711PayloadFormatWrite::CreateSinkBufferOfSizeL( TUint aSize ) |
|
173 { |
|
174 DP_G711_WRITE( "CG711PayloadFormatWrite::CreateSinkBufferOfSizeL()" ); |
|
175 |
|
176 // Needs to create source buffer |
|
177 if ( !iSourceBuffer ) |
|
178 { |
|
179 iSourceBuffer = CMMFDataBuffer::NewL( aSize ); |
|
180 iSourceBuffer->Data().FillZ( aSize ); |
|
181 iSourceBuffer->SetRequestSizeL( aSize ); |
|
182 } |
|
183 |
|
184 return iSourceBuffer; |
|
185 } |
|
186 |
|
187 // ----------------------------------------------------------------------------- |
|
188 // CG711PayloadFormatWrite::EmptyBufferL |
|
189 // Empty the given source buffer |
|
190 // ----------------------------------------------------------------------------- |
|
191 // |
|
192 void CG711PayloadFormatWrite::EmptyBufferL( CMMFBuffer* aBuffer, |
|
193 MDataSource* aSupplier, |
|
194 TMediaId aMediaId ) |
|
195 { |
|
196 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptyBufferL()" ); |
|
197 |
|
198 __ASSERT_ALWAYS( aBuffer, User::Leave( KErrArgument ) ); |
|
199 __ASSERT_ALWAYS( aBuffer == iSourceBuffer, User::Leave( KErrArgument ) ); |
|
200 __ASSERT_ALWAYS( aSupplier, User::Leave( KErrArgument ) ); |
|
201 __ASSERT_ALWAYS( KUidMediaTypeAudio == aMediaId.iMediaType, |
|
202 User::Leave( KErrNotSupported ) ); |
|
203 |
|
204 // Save source buffer parameters and change the state. |
|
205 iDataPath = aSupplier; |
|
206 iSourceBuffer = static_cast<CMMFDataBuffer*>( aBuffer ); |
|
207 |
|
208 if ( !iSinkBuffer ) |
|
209 { |
|
210 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptyBufferL, sink not ready!" ); |
|
211 |
|
212 iStateMachine->ChangeState( ESourceBufferEmptied ); |
|
213 return; |
|
214 } |
|
215 |
|
216 // Check if hw has sent different length buffer compared to last time. |
|
217 // This means that we need to update the media clock. This allows G.711 |
|
218 // codec to change dynamically the buffer size. |
|
219 const TInt dataLen( iSourceBuffer->Data().Length() - KVoIPHeaderLength ); |
|
220 const TInt audioLen( dataLen / KBitsPerByte ); |
|
221 if ( audioLen != iCInfo.iHwFrameTime ) |
|
222 { |
|
223 // Re-register to RTP clock. |
|
224 iCInfo.iHwFrameTime = audioLen; |
|
225 iRtpMediaClock->UnregisterMediaFormat( iKey ); |
|
226 iKey = iRtpMediaClock->RegisterMediaFormat( KDefaultSampleRate, iCInfo.iHwFrameTime ); |
|
227 } |
|
228 |
|
229 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptyBufferL, SetTimeToPlay" ); |
|
230 |
|
231 TUint32 ts = 0; |
|
232 User::LeaveIfError( iRtpMediaClock->GetTimeStamp( iKey, ts ) ); |
|
233 |
|
234 if ( iRtpMediaClock->TimeBasedIncrement() ) |
|
235 { |
|
236 DP_G711_WRITE( |
|
237 "CG711PayloadFormatWrite::EmptyBufferL(), New stream begins" ); |
|
238 iFirstPacketFinished = EFalse; |
|
239 } |
|
240 |
|
241 if ( !iSinkBuffer->Data().Length() ) |
|
242 { |
|
243 iSinkBuffer->SetTimeToPlay( TInt64( ts ) ); |
|
244 iSinkBuffer->SetFrameNumber( aBuffer->FrameNumber() ); |
|
245 } |
|
246 else |
|
247 { |
|
248 iSourceBuffer->SetTimeToPlay( TInt64( ts ) ); |
|
249 } |
|
250 |
|
251 iStateMachine->ChangeState( EEmptySourceBuffer ); |
|
252 } |
|
253 |
|
254 // ----------------------------------------------------------------------------- |
|
255 // CG711PayloadFormatWrite::SetSinkDataTypeCode |
|
256 // Set the sink data type to the given four CC code for the given media |
|
257 // ----------------------------------------------------------------------------- |
|
258 // |
|
259 TInt CG711PayloadFormatWrite::SetSinkDataTypeCode( TFourCC aSinkFourCC, |
|
260 TMediaId aMediaId ) |
|
261 { |
|
262 DP_G711_WRITE( "CG711PayloadFormatWrite::SetSinkDataTypeCode()" ); |
|
263 |
|
264 if ( KUidMediaTypeAudio != aMediaId.iMediaType ) |
|
265 { |
|
266 return KErrNotSupported; |
|
267 } |
|
268 |
|
269 iFourCC = aSinkFourCC; |
|
270 |
|
271 return KErrNone; |
|
272 } |
|
273 |
|
274 // ----------------------------------------------------------------------------- |
|
275 // CG711PayloadFormatWrite::SinkDataTypeCode |
|
276 // Return the sink data type (four CC code) for the given media ID |
|
277 // ----------------------------------------------------------------------------- |
|
278 // |
|
279 TFourCC CG711PayloadFormatWrite::SinkDataTypeCode( TMediaId aMediaId ) |
|
280 { |
|
281 if ( KUidMediaTypeAudio == aMediaId.iMediaType ) |
|
282 { |
|
283 return iFourCC; |
|
284 } |
|
285 else |
|
286 { |
|
287 return TFourCC(); //defaults to 'NULL' fourCC |
|
288 } |
|
289 } |
|
290 |
|
291 // ----------------------------------------------------------------------------- |
|
292 // CG711PayloadFormatWrite::BufferEmptiedL |
|
293 // Called after payload buffer is completely emptied by RtpDataSink. |
|
294 // ----------------------------------------------------------------------------- |
|
295 // |
|
296 void CG711PayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ ) |
|
297 { |
|
298 |
|
299 } |
|
300 |
|
301 // ----------------------------------------------------------------------------- |
|
302 // CG711PayloadFormatWrite::NumChannels |
|
303 // Returns number of channels |
|
304 // ----------------------------------------------------------------------------- |
|
305 // |
|
306 TUint CG711PayloadFormatWrite::NumChannels() |
|
307 { |
|
308 return KMono; |
|
309 } |
|
310 |
|
311 // ----------------------------------------------------------------------------- |
|
312 // CG711PayloadFormatWrite::SampleRate |
|
313 // Returns SampleRate |
|
314 // ----------------------------------------------------------------------------- |
|
315 // |
|
316 TUint CG711PayloadFormatWrite::SampleRate() |
|
317 { |
|
318 return KDefaultSampleRate; |
|
319 } |
|
320 |
|
321 // ----------------------------------------------------------------------------- |
|
322 // CG711PayloadFormatWrite::SetSampleRate |
|
323 // Set SampleRate |
|
324 // ----------------------------------------------------------------------------- |
|
325 // |
|
326 TInt CG711PayloadFormatWrite::SetSampleRate( TUint aSampleRate ) |
|
327 { |
|
328 if ( KDefaultSampleRate != aSampleRate ) |
|
329 { |
|
330 return KErrNotSupported; |
|
331 } |
|
332 else |
|
333 { |
|
334 return KErrNone; |
|
335 } |
|
336 } |
|
337 |
|
338 // ----------------------------------------------------------------------------- |
|
339 // CG711PayloadFormatWrite::FrameTimeInterval |
|
340 // Return the frame time interval for the given media |
|
341 // ----------------------------------------------------------------------------- |
|
342 // |
|
343 TTimeIntervalMicroSeconds |
|
344 CG711PayloadFormatWrite::FrameTimeInterval( TMediaId aMediaId ) const |
|
345 { |
|
346 if ( KUidMediaTypeAudio == aMediaId.iMediaType ) |
|
347 { |
|
348 return TTimeIntervalMicroSeconds( TInt64( 0 ) ); |
|
349 } |
|
350 else |
|
351 { |
|
352 return TTimeIntervalMicroSeconds( TInt64( 0 ) ); |
|
353 } |
|
354 } |
|
355 |
|
356 // ----------------------------------------------------------------------------- |
|
357 // CG711PayloadFormatWrite::Duration |
|
358 // Return the frame time interval for the given media |
|
359 // NOT SUPPORTED |
|
360 // ----------------------------------------------------------------------------- |
|
361 // |
|
362 TTimeIntervalMicroSeconds |
|
363 CG711PayloadFormatWrite::Duration( TMediaId /*aMediaType*/ ) const |
|
364 { |
|
365 return TTimeIntervalMicroSeconds( TInt64( 0 ) ); |
|
366 } |
|
367 |
|
368 // ----------------------------------------------------------------------------- |
|
369 // CG711PayloadFormatWrite::EmptySourceBufferL |
|
370 // Empty the given sourcebuffer |
|
371 // Sourcebuffer is given in iSourceBuffer |
|
372 // Called by statemachine |
|
373 // ----------------------------------------------------------------------------- |
|
374 // |
|
375 void CG711PayloadFormatWrite::EmptySourceBufferL() |
|
376 { |
|
377 const TDesC8& srcDes( iSourceBuffer->Data() ); |
|
378 |
|
379 DP_G711_WRITE2( "CG711PayloadFormatWrite::EmptySourceBufferL - SRC BUF SIZE: %d", srcDes.Size() ); |
|
380 DP_G711_WRITE2( "CG711PayloadFormatWrite::EmptySourceBufferL - AUDIO SIZE: %d", srcDes.Size() - KVoIPHeaderLength ); |
|
381 |
|
382 TPtrC8 audioFrame( srcDes.Mid( KVoIPHeaderLength ) ); |
|
383 TPtrC8 frameHeader( srcDes.Left( KVoIPHeaderLength ) ); |
|
384 TDes8& destDes( iSinkBuffer->Data() ); |
|
385 |
|
386 if ( audioFrame.Size() > destDes.MaxSize() - destDes.Size() || !frameHeader.Length() ) |
|
387 { |
|
388 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL WARNING SRCBUF LARGER THAN SINKBUF" ); |
|
389 } |
|
390 else |
|
391 { |
|
392 const TUint8 frmHdrByte( frameHeader[0] ); |
|
393 if ( KVoIPAudioFrame == frmHdrByte ) |
|
394 { |
|
395 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL - AUDIO FRAME" ); |
|
396 if ( iCNModeON ) |
|
397 { |
|
398 iCNModeON = EFalse; |
|
399 iFirstPacketFinished = EFalse; |
|
400 } |
|
401 |
|
402 destDes.Append( audioFrame ); |
|
403 } |
|
404 else if ( KVoIPCNFrame == frmHdrByte ) |
|
405 { |
|
406 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL - CNOISE FRAME" ); |
|
407 if ( destDes.Length() ) |
|
408 { |
|
409 // Send audio frames first |
|
410 DeliverPacketL( *iSinkBuffer ); |
|
411 iSinkBuffer->SetTimeToPlay( iSourceBuffer->TimeToPlay() ); |
|
412 } |
|
413 |
|
414 iCNModeON = ETrue; |
|
415 destDes.Append( audioFrame ); |
|
416 } |
|
417 else |
|
418 { |
|
419 DP_G711_WRITE( "CG711PayloadFormatWrite::EmptySourceBufferL - UNVOICED NON-SID FRAME" ); |
|
420 } |
|
421 } |
|
422 |
|
423 // If we have filled the buffer enough or the frame is a CN packet |
|
424 // then send it. |
|
425 const TInt sendBytes( iCInfo.iPtime * KBitsPerByte ); |
|
426 if ( sendBytes == destDes.Size() || iCNModeON ) |
|
427 { |
|
428 this->DeliverPacketL( *iSinkBuffer ); |
|
429 } |
|
430 |
|
431 iStateMachine->ChangeState( ESourceBufferEmptied ); |
|
432 } |
|
433 |
|
434 // ----------------------------------------------------------------------------- |
|
435 // CG711PayloadFormatWrite::DeliverPacketL |
|
436 // Prepare the packet header and deliver the packet to the datasink. |
|
437 // ----------------------------------------------------------------------------- |
|
438 // |
|
439 void CG711PayloadFormatWrite::DeliverPacketL( CMMFDataBuffer& aPayload ) |
|
440 { |
|
441 DP_G711_WRITE2( "CG711PayloadFormatWrite::DeliverPacketL - TSTAMP: %u", |
|
442 static_cast<TUint32>( aPayload.TimeToPlay().Int64() ) ); |
|
443 |
|
444 if ( !iClip ) |
|
445 { |
|
446 DP_G711_WRITE( "CG711PayloadFormatWrite::DeliverPacketL NO DATASINK!" ); |
|
447 |
|
448 User::Leave( KErrNotReady ); |
|
449 } |
|
450 |
|
451 // Construct RTP header. Note that CN frames must not have the marker bit |
|
452 // set, only first audioframe after silence period. |
|
453 TRtpSendHeader sendHdr; |
|
454 if ( !iFirstPacketFinished && !iCNModeON ) |
|
455 { |
|
456 sendHdr.iMarker = 1; |
|
457 iFirstPacketFinished = ETrue; |
|
458 } |
|
459 else |
|
460 { |
|
461 sendHdr.iMarker = 0; |
|
462 } |
|
463 |
|
464 sendHdr.iTimestamp |
|
465 = static_cast<TUint32>( aPayload.TimeToPlay().Int64() ); |
|
466 |
|
467 const TMediaId mediaId( KUidMediaTypeAudio ); |
|
468 const TInt dataSize( aPayload.Data().Size() ); |
|
469 if ( iCNModeON ) |
|
470 { |
|
471 if ( iCInfo.iComfortNoiseGenerationPt != KPayloadTypeUndefined ) |
|
472 { |
|
473 sendHdr.iPayloadType = iCInfo.iComfortNoiseGenerationPt; |
|
474 if ( dataSize ) |
|
475 { |
|
476 if ( iIsRtpSink ) |
|
477 { |
|
478 iRtpDataSink->EmptyBufferL( &aPayload, this, mediaId, sendHdr ); |
|
479 } |
|
480 else |
|
481 { |
|
482 aPayload.SetLastBuffer( sendHdr.iMarker ); |
|
483 iClip->EmptyBufferL( &aPayload, this, mediaId ); |
|
484 } |
|
485 } |
|
486 } |
|
487 } |
|
488 else |
|
489 { |
|
490 sendHdr.iPayloadType = iCInfo.iPayloadType; |
|
491 |
|
492 if ( dataSize ) |
|
493 { |
|
494 if ( iIsRtpSink ) |
|
495 { |
|
496 iRtpDataSink->EmptyBufferL( &aPayload, this, mediaId, sendHdr ); |
|
497 } |
|
498 else |
|
499 { |
|
500 aPayload.SetLastBuffer( sendHdr.iMarker ); |
|
501 iClip->EmptyBufferL( &aPayload, this, mediaId ); |
|
502 } |
|
503 } |
|
504 } |
|
505 |
|
506 // Reset the payload buffer -- only if previous EmptyBufferL() is a |
|
507 // synchronous call. |
|
508 aPayload.Data().Zero(); |
|
509 } |
|
510 |
|
511 // ----------------------------------------------------------------------------- |
|
512 // CG711PayloadFormatWrite::SourceBufferEmptiedL |
|
513 // Handle the event that sourcebuffer has been emptied. |
|
514 // Sourcebuffer is given in "iSourceBuffer". |
|
515 // Called by the statemachine. |
|
516 // ----------------------------------------------------------------------------- |
|
517 // |
|
518 void CG711PayloadFormatWrite::SourceBufferEmptiedL() |
|
519 { |
|
520 DP_G711_WRITE( "CG711PayloadFormatWrite::SourceBufferEmptiedL()" ); |
|
521 iDataPath->BufferEmptiedL( iSourceBuffer ); |
|
522 } |
|
523 |
|
524 // ----------------------------------------------------------------------------- |
|
525 // CG711PayloadFormatWrite::SinkPrimeL |
|
526 // Prime sink |
|
527 // ----------------------------------------------------------------------------- |
|
528 // |
|
529 void CG711PayloadFormatWrite::SinkPrimeL() |
|
530 { |
|
531 DP_G711_WRITE( "CG711PayloadFormatWrite::SinkPrimeL()" ); |
|
532 iClip->SinkPrimeL(); |
|
533 } |
|
534 |
|
535 // ----------------------------------------------------------------------------- |
|
536 // CG711PayloadFormatWrite::SinkPlayL |
|
537 // Start playing. |
|
538 // ----------------------------------------------------------------------------- |
|
539 // |
|
540 void CG711PayloadFormatWrite::SinkPlayL() |
|
541 { |
|
542 DP_G711_WRITE( "CG711PayloadFormatWrite::SinkPlayL()" ); |
|
543 // Allocate buffer for data transfer between |
|
544 // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder |
|
545 delete iSinkBuffer; |
|
546 iSinkBuffer = NULL; |
|
547 iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iPtime * KBitsPerByte ); |
|
548 |
|
549 // Start state machine |
|
550 iStateMachine->ChangeState( EEncodeIdle ); |
|
551 iFirstPacketFinished = EFalse; |
|
552 |
|
553 // Start a new cycle of frame collecting |
|
554 if ( iSinkBuffer ) |
|
555 { |
|
556 iSinkBuffer->SetLastBuffer( EFalse ); |
|
557 } |
|
558 |
|
559 iClip->SinkPlayL(); |
|
560 } |
|
561 |
|
562 // ----------------------------------------------------------------------------- |
|
563 // CG711PayloadFormatWrite::SinkPauseL |
|
564 // Pause sink |
|
565 // ----------------------------------------------------------------------------- |
|
566 // |
|
567 void CG711PayloadFormatWrite::SinkPauseL() |
|
568 { |
|
569 DP_G711_WRITE( "CG711PayloadFormatWrite::SinkPauseL()" ); |
|
570 iStateMachine->Cancel(); |
|
571 iStateMachine->ChangeState( EEncodeIdle ); |
|
572 |
|
573 iClip->SinkPauseL(); |
|
574 } |
|
575 |
|
576 // ----------------------------------------------------------------------------- |
|
577 // CG711PayloadFormatWrite::SinkStopL |
|
578 // Stop sink |
|
579 // ----------------------------------------------------------------------------- |
|
580 // |
|
581 void CG711PayloadFormatWrite::SinkStopL() |
|
582 { |
|
583 DP_G711_WRITE( "CG711PayloadFormatWrite::SinkStopL" ); |
|
584 |
|
585 // Stop state machine |
|
586 iStateMachine->Cancel(); |
|
587 iStateMachine->ChangeState( EEncodeIdle ); |
|
588 |
|
589 iClip->SinkStopL(); |
|
590 } |
|
591 |
|
592 // --------------------------------------------------------------------------- |
|
593 // CG711PayloadFormatWrite::ConfigurePayloadFormatL |
|
594 // Configure payload encoding parameters |
|
595 // --------------------------------------------------------------------------- |
|
596 // |
|
597 void CG711PayloadFormatWrite::ConfigurePayloadFormatL( const TDesC8& aConfigParams, |
|
598 CMccRtpMediaClock& aClock ) |
|
599 { |
|
600 DP_G711_WRITE( "CG711PayloadFormatWrite::ConfigurePayloadFormatL" ); |
|
601 |
|
602 __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ), |
|
603 User::Leave( KErrArgument ) ); |
|
604 |
|
605 TMccCodecInfoBuffer infoBuffer; |
|
606 infoBuffer.Copy( aConfigParams ); |
|
607 |
|
608 if ( !infoBuffer().iIsUpdate ) |
|
609 { |
|
610 iCInfo = infoBuffer(); |
|
611 iRtpMediaClock = &aClock; |
|
612 iKey = iRtpMediaClock->RegisterMediaFormat( KDefaultSampleRate, iCInfo.iHwFrameTime ); |
|
613 |
|
614 if( iCInfo.iHwFrameTime ) |
|
615 { |
|
616 iCInfo.iFrameSize = TUint( iCInfo.iHwFrameTime * KDefaultSampleRateInkHz ); |
|
617 } |
|
618 else |
|
619 { |
|
620 DP_G711_WRITE( "CG711PayloadFormatWrite::ConfigurePayloadFormatL KErrArgument" ); |
|
621 User::Leave( KErrArgument ); |
|
622 } |
|
623 |
|
624 DP_G711_WRITE2( "CG711PayloadFormatWrite::ConfigurePayloadFormatL FrameSize: %d", iCInfo.iFrameSize ); |
|
625 |
|
626 if ( EGenRedUsed == iCInfo.iAlgoUsed ) |
|
627 { |
|
628 DP_G711_WRITE2( "CG711PayloadFormatWrite::ConfigurePayloadFormatL, RED LEVEL: %d", |
|
629 iCInfo.iRedundancyCount ); |
|
630 |
|
631 CPayloadFormatWrite* redEncoder |
|
632 = static_cast<CMccRedPayloadWrite*>( iClip ); |
|
633 |
|
634 TMccRedPayloadWriteConfig config; |
|
635 config.iRedBlockCount = iCInfo.iRedundancyCount; |
|
636 config.iMaxPayloadSize = iCInfo.iPtime * KBitsPerByte; |
|
637 config.iNumOfEncodings = 1; |
|
638 config.iRedPayloadType = iCInfo.iRedundantPayload; |
|
639 config.InitPayloadTypes(); |
|
640 config.iEncPayloadTypes[0] = iCInfo.iPayloadType; |
|
641 TMccRedPayloadWritePckg pckg( config ); |
|
642 redEncoder->ConfigurePayloadFormatL( pckg, *iRtpMediaClock ); |
|
643 } |
|
644 } |
|
645 else |
|
646 { |
|
647 UpdateConfigurationL( infoBuffer() ); |
|
648 } |
|
649 } |
|
650 |
|
651 // ----------------------------------------------------------------------------- |
|
652 // CG711PayloadFormatWrite::UpdateConfigurationL |
|
653 // Update payload encoding parameters |
|
654 // ----------------------------------------------------------------------------- |
|
655 // |
|
656 void CG711PayloadFormatWrite::UpdateConfigurationL( TMccCodecInfo& aCodecInfo ) |
|
657 { |
|
658 DP_G711_WRITE( "CG711PayloadFormatWrite::UpdateConfigurationL" ); |
|
659 |
|
660 iCInfo.iPtime = aCodecInfo.iPtime; |
|
661 iCInfo.iPayloadType = aCodecInfo.iPayloadType; |
|
662 iCInfo.iComfortNoiseGenerationPt = aCodecInfo.iComfortNoiseGenerationPt; |
|
663 |
|
664 // Allocate buffer for data transfer between |
|
665 // FormatWrite - MDataSink AND FormatWrite - redundancy payload encoder |
|
666 delete iSinkBuffer; |
|
667 iSinkBuffer = NULL; |
|
668 iSinkBuffer = CMMFDataBuffer::NewL( iCInfo.iPtime * KBitsPerByte ); |
|
669 |
|
670 DP_G711_WRITE( "CG711PayloadFormatWrite::UpdateConfigurationL, exit" ); |
|
671 } |
|
672 |
|
673 // ========================== OTHER EXPORTED FUNCTIONS ========================= |
|
674 |
|
675 // End of File |