|
1 /* |
|
2 * Copyright (c) 2006 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: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 |
|
21 |
|
22 // INCLUDE FILES |
|
23 #include "mcch263payloadformatwrite.h" |
|
24 #include "mccrtpdatasink.h" |
|
25 #include "mccinternaldef.h" |
|
26 #include "mcch263oldpayloadencoder.h" |
|
27 #include "mcch263newpayloadencoder.h" |
|
28 #include "mmcccodech263.h" |
|
29 #include "formatstatemachine.h" |
|
30 #include "mcch263formatlogs.h" |
|
31 |
|
32 #include "mmccnetworksettings.h" |
|
33 |
|
34 #ifdef VOIP_TRACE_ENABLED |
|
35 #include <voip_trace.h> |
|
36 #endif |
|
37 |
|
38 // EXTERNAL DATA STRUCTURES |
|
39 |
|
40 // EXTERNAL FUNCTION PROTOTYPES |
|
41 |
|
42 // CONSTANTS |
|
43 |
|
44 // Camera may give very big H.263 frame if there's big change in scene |
|
45 const TInt KH263DefaultPayloadSize = 12000; |
|
46 |
|
47 // MACROS |
|
48 |
|
49 // LOCAL CONSTANTS AND MACROS |
|
50 |
|
51 // MODULE DATA STRUCTURES |
|
52 |
|
53 // LOCAL FUNCTION PROTOTYPES |
|
54 |
|
55 // FORWARD DECLARATIONS |
|
56 |
|
57 // ============================= LOCAL FUNCTIONS =============================== |
|
58 |
|
59 |
|
60 // ============================ MEMBER FUNCTIONS =============================== |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // CMccH263PayloadFormatWrite::CMccH263PayloadFormatWrite |
|
64 // C++ default constructor can NOT contain any code, that |
|
65 // might leave. |
|
66 // ----------------------------------------------------------------------------- |
|
67 // |
|
68 CMccH263PayloadFormatWrite::CMccH263PayloadFormatWrite() |
|
69 { |
|
70 } |
|
71 |
|
72 // ----------------------------------------------------------------------------- |
|
73 // CMccH263PayloadFormatWrite::ConstructL |
|
74 // Symbian 2nd phase constructor can leave. |
|
75 // ----------------------------------------------------------------------------- |
|
76 // |
|
77 void CMccH263PayloadFormatWrite::ConstructL( MDataSink* aSink ) |
|
78 { |
|
79 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::ConstructL" ) |
|
80 |
|
81 iFourCC = TFourCC( KMccFourCCIdH263 ); |
|
82 |
|
83 iIsRtpSink = ( KMccRtpSinkUid == aSink->DataSinkType() ); |
|
84 iClip = aSink; |
|
85 |
|
86 iStateMachine = CFormatEncodeStateMachine::NewL( this ); |
|
87 iStateMachine->ChangeState( EEncodeIdle ); |
|
88 } |
|
89 |
|
90 // ----------------------------------------------------------------------------- |
|
91 // CMccH263PayloadFormatWrite::NewL |
|
92 // Two-phased constructor. |
|
93 // ----------------------------------------------------------------------------- |
|
94 // |
|
95 CMccH263PayloadFormatWrite* CMccH263PayloadFormatWrite::NewL( MDataSink* aSink ) |
|
96 { |
|
97 __ASSERT_ALWAYS( aSink, User::Leave( KErrArgument ) ); |
|
98 |
|
99 CMccH263PayloadFormatWrite* self = new( ELeave ) CMccH263PayloadFormatWrite; |
|
100 |
|
101 CleanupStack::PushL( self ); |
|
102 self->ConstructL( aSink ); |
|
103 CleanupStack::Pop( self ); |
|
104 |
|
105 return self; |
|
106 } |
|
107 |
|
108 CMccH263PayloadFormatWrite::~CMccH263PayloadFormatWrite() |
|
109 { |
|
110 iBuffers.ResetAndDestroy(); |
|
111 delete iSourceBuffer; |
|
112 delete iStateMachine; |
|
113 delete iPayloadEncoder; |
|
114 |
|
115 iClip = NULL; |
|
116 } |
|
117 |
|
118 |
|
119 // ----------------------------------------------------------------------------- |
|
120 // CMccH263PayloadFormatWrite::SinkThreadLogon |
|
121 // Passes the logon command to the sink clip. |
|
122 // ----------------------------------------------------------------------------- |
|
123 // |
|
124 TInt CMccH263PayloadFormatWrite::SinkThreadLogon( |
|
125 MAsyncEventHandler& aEventHandler ) |
|
126 { |
|
127 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkThreadLogon" ) |
|
128 |
|
129 iStateMachine->ChangeState( EEncodeIdle ); |
|
130 return iClip->SinkThreadLogon( aEventHandler ); |
|
131 } |
|
132 |
|
133 // ----------------------------------------------------------------------------- |
|
134 // CMccH263PayloadFormatWrite::SinkThreadLogoff |
|
135 // Passes the logoff command to the sink clip. |
|
136 // ----------------------------------------------------------------------------- |
|
137 // |
|
138 void CMccH263PayloadFormatWrite::SinkThreadLogoff() |
|
139 { |
|
140 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkThreadLogoff" ) |
|
141 |
|
142 if( iClip ) |
|
143 { |
|
144 iClip->SinkThreadLogoff(); |
|
145 } |
|
146 else |
|
147 { |
|
148 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkThreadLogoff\ |
|
149 iClip is NULL, Error!..." ) |
|
150 } |
|
151 } |
|
152 |
|
153 // ----------------------------------------------------------------------------- |
|
154 // CMccH263PayloadFormatWrite::CanCreateSinkBuffer |
|
155 // EmptyBufferL() is not used. |
|
156 // ----------------------------------------------------------------------------- |
|
157 // |
|
158 TBool CMccH263PayloadFormatWrite::CanCreateSinkBuffer() |
|
159 { |
|
160 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::CanCreateSinkBuffer" ) |
|
161 return ETrue; |
|
162 } |
|
163 |
|
164 // ----------------------------------------------------------------------------- |
|
165 // CMccH263PayloadFormatWrite::CreateSinkBufferL |
|
166 // Create a sink buffer. |
|
167 // ----------------------------------------------------------------------------- |
|
168 // |
|
169 CMMFBuffer* CMccH263PayloadFormatWrite::CreateSinkBufferL( |
|
170 TMediaId /*aMediaId*/, |
|
171 TBool& aReference ) |
|
172 { |
|
173 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::CreateSinkBufferL" ) |
|
174 |
|
175 if ( !iSourceBuffer ) |
|
176 { |
|
177 iSourceBuffer = CMMFDataBuffer::NewL( KH263DefaultPayloadSize ); |
|
178 iSourceBuffer->Data().FillZ( KH263DefaultPayloadSize ); |
|
179 iSourceBuffer->SetRequestSizeL( KH263DefaultPayloadSize ); |
|
180 } |
|
181 // the ownership of iSourceBuffer is in CMccH263PayloadFormatWrite |
|
182 aReference = ETrue; |
|
183 return iSourceBuffer; |
|
184 } |
|
185 |
|
186 |
|
187 // ----------------------------------------------------------------------------- |
|
188 // CMccH263PayloadFormatWrite::SetSinkDataTypeCode |
|
189 // Set the sink data type to the given FourCC code for the given media. |
|
190 // ----------------------------------------------------------------------------- |
|
191 // |
|
192 TInt CMccH263PayloadFormatWrite::SetSinkDataTypeCode( |
|
193 TFourCC aSinkFourCC, |
|
194 TMediaId aMediaId ) |
|
195 { |
|
196 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SetSinkDataTypeCode" ) |
|
197 |
|
198 if ( KUidMediaTypeVideo != aMediaId.iMediaType || |
|
199 iFourCC != aSinkFourCC ) |
|
200 { |
|
201 return KErrNotSupported; |
|
202 } |
|
203 else |
|
204 { |
|
205 iMediaId = aMediaId; |
|
206 return KErrNone; |
|
207 } |
|
208 } |
|
209 |
|
210 // ----------------------------------------------------------------------------- |
|
211 // CMccH263PayloadFormatWrite::SinkDataTypeCode |
|
212 // Return the sink data type (four CC code) for the given media. |
|
213 // ----------------------------------------------------------------------------- |
|
214 // |
|
215 TFourCC CMccH263PayloadFormatWrite::SinkDataTypeCode( TMediaId aMediaId ) |
|
216 { |
|
217 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkDataTypeCode" ) |
|
218 |
|
219 if ( KUidMediaTypeVideo == aMediaId.iMediaType ) |
|
220 { |
|
221 return iFourCC; |
|
222 } |
|
223 else |
|
224 { |
|
225 return TFourCC(); //defaults to 'NULL' fourCC |
|
226 } |
|
227 } |
|
228 |
|
229 |
|
230 // ----------------------------------------------------------------------------- |
|
231 // CMccH263PayloadFormatWrite::FrameTimeInterval |
|
232 // Gets audio frame size in milliseconds. |
|
233 // ----------------------------------------------------------------------------- |
|
234 // |
|
235 TTimeIntervalMicroSeconds |
|
236 CMccH263PayloadFormatWrite::FrameTimeInterval( |
|
237 TMediaId aMediaType ) const |
|
238 { |
|
239 if( KUidMediaTypeVideo != aMediaType.iMediaType ) |
|
240 { |
|
241 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::FrameTimeInterval \ |
|
242 aMediaType is not KUidMediaTypeVideo, Error!!!" ) |
|
243 } |
|
244 return TTimeIntervalMicroSeconds( TInt64( 0 ) ); |
|
245 } |
|
246 |
|
247 // ----------------------------------------------------------------------------- |
|
248 // CMccH263PayloadFormatWrite::Duration |
|
249 // Gets the duration of the sink clip for the specified media ID. |
|
250 // ----------------------------------------------------------------------------- |
|
251 // |
|
252 TTimeIntervalMicroSeconds |
|
253 CMccH263PayloadFormatWrite::Duration( TMediaId aMediaType ) const |
|
254 { |
|
255 if( KUidMediaTypeVideo != aMediaType.iMediaType ) |
|
256 { |
|
257 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::Duration \ |
|
258 aMediaType is not KUidMediaTypeVideo, Error!!!" ) |
|
259 } |
|
260 return TTimeIntervalMicroSeconds( TInt64( 0 ) ); |
|
261 } |
|
262 |
|
263 // ----------------------------------------------------------------------------- |
|
264 // CMccH263PayloadFormatWrite::BufferEmptiedL |
|
265 // Called by RTP data sink. Indicates that DTMF data is sent to the network. |
|
266 // ----------------------------------------------------------------------------- |
|
267 // |
|
268 void CMccH263PayloadFormatWrite::BufferEmptiedL( CMMFBuffer* /*aBuffer*/ ) |
|
269 { |
|
270 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::BufferEmptiedL" ) |
|
271 } |
|
272 |
|
273 // ----------------------------------------------------------------------------- |
|
274 // CMccH263PayloadFormatWrite::SinkPrimeL |
|
275 // Passes prime transition to the RTP data sink. |
|
276 // ----------------------------------------------------------------------------- |
|
277 // |
|
278 void CMccH263PayloadFormatWrite::SinkPrimeL() |
|
279 { |
|
280 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkPrimeL" ) |
|
281 __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); |
|
282 |
|
283 iClip->SinkPrimeL(); |
|
284 } |
|
285 |
|
286 // ----------------------------------------------------------------------------- |
|
287 // CMccH263PayloadFormatWrite::SinkPlayL |
|
288 // Passes play transition to the RTP data sink and resets state variables. |
|
289 // ----------------------------------------------------------------------------- |
|
290 // |
|
291 void CMccH263PayloadFormatWrite::SinkPlayL() |
|
292 { |
|
293 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkPlayL" ) |
|
294 __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); |
|
295 |
|
296 iClip->SinkPlayL(); |
|
297 } |
|
298 |
|
299 // ----------------------------------------------------------------------------- |
|
300 // CMccH263PayloadFormatWrite::SinkPauseL |
|
301 // Passes pause transition to the RTP data sink. |
|
302 // ----------------------------------------------------------------------------- |
|
303 // |
|
304 void CMccH263PayloadFormatWrite::SinkPauseL() |
|
305 { |
|
306 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkPauseL" ) |
|
307 __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); |
|
308 |
|
309 iClip->SinkPauseL(); |
|
310 } |
|
311 |
|
312 // ----------------------------------------------------------------------------- |
|
313 // CMccH263PayloadFormatWrite::SinkStopL |
|
314 // Passes stop transition to the RTP data sink. |
|
315 // ----------------------------------------------------------------------------- |
|
316 // |
|
317 void CMccH263PayloadFormatWrite::SinkStopL() |
|
318 { |
|
319 __H263FORMAT_CONTROLL( "CMccH263PayloadFormatWrite::SinkStopL" ) |
|
320 __ASSERT_ALWAYS( iClip, User::Leave( KErrArgument ) ); |
|
321 |
|
322 iClip->SinkStopL(); |
|
323 } |
|
324 |
|
325 // ----------------------------------------------------------------------------- |
|
326 // CMccH263PayloadFormatWrite::EmptyBufferL |
|
327 // Not used because DTMF payload formatter generates DTMF independently. |
|
328 // ----------------------------------------------------------------------------- |
|
329 // |
|
330 void CMccH263PayloadFormatWrite::EmptyBufferL( |
|
331 CMMFBuffer* aBuffer, |
|
332 MDataSource* aSupplier, |
|
333 TMediaId /*aMediaId*/ |
|
334 ) |
|
335 { |
|
336 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptyBufferL" ) |
|
337 __ASSERT_ALWAYS ( aBuffer, User::Leave(KErrArgument) ); |
|
338 // reference of iSourceBuffer is passed to ULdatapath |
|
339 // by calling CreateSinkBuffer |
|
340 __ASSERT_ALWAYS ( aBuffer == iSourceBuffer, User::Leave(KErrArgument) ); |
|
341 __ASSERT_ALWAYS ( aSupplier, User::Leave(KErrArgument) ); |
|
342 __ASSERT_ALWAYS ( iPayloadEncoder, User::Leave(KErrArgument) ); |
|
343 __ASSERT_ALWAYS ( iStateMachine, User::Leave(KErrArgument) ); |
|
344 |
|
345 // Save source buffer parameters and change the state. |
|
346 iDataSource = aSupplier; |
|
347 |
|
348 iBuffers.ResetAndDestroy(); |
|
349 |
|
350 CleanupStack::PushL( TCleanupItem( PayloadEncodeCleanup, this ) ); |
|
351 iPayloadEncoder->EncodeL(aBuffer, iBuffers); |
|
352 CleanupStack::Pop( ); // TCleanupItem |
|
353 |
|
354 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptyBufferL, \ |
|
355 array count ..." ) |
|
356 __H263FORMAT_MEDIA_INT1( "CMccH263PayloadFormatWrite::EmptyBufferL, \ |
|
357 array count:", iBuffers.Count()) |
|
358 |
|
359 // empty the encoded data to RtpSink |
|
360 iStateMachine->ChangeState( EEmptySourceBuffer ); |
|
361 } |
|
362 |
|
363 |
|
364 // ----------------------------------------------------------------------------- |
|
365 // CMccH263PayloadFormatWrite::ConfigurePayloadFormatL |
|
366 // Configure payload encoding parameters. |
|
367 // ----------------------------------------------------------------------------- |
|
368 // |
|
369 void CMccH263PayloadFormatWrite::ConfigurePayloadFormatL( |
|
370 const TDesC8& aConfigParams, |
|
371 CMccRtpMediaClock& /*aClock*/ ) |
|
372 |
|
373 { |
|
374 __ASSERT_ALWAYS( aConfigParams.Size() == sizeof( TMccCodecInfo ), |
|
375 User::Leave( KErrArgument ) ); |
|
376 |
|
377 TMccCodecInfoBuffer infoBuffer; |
|
378 infoBuffer.Copy( aConfigParams ); |
|
379 iCInfo = infoBuffer(); |
|
380 |
|
381 if ( !iPayloadEncoder ) |
|
382 { |
|
383 // Don't use old mode encoder for 1998 or 2000 modes, codec mode |
|
384 // old means 1998 mode in configuration parameters |
|
385 if( iCInfo.iCodecMode == KH263FormatModeOld || |
|
386 iCInfo.iCodecMode == KH263FormatModeNew ) |
|
387 { |
|
388 iPayloadEncoder = CMccH263NewPayloadEncoder::NewL(); |
|
389 } |
|
390 else |
|
391 { |
|
392 User::Leave( KErrNotSupported ); |
|
393 } |
|
394 } |
|
395 iPayloadEncoder->SetPayloadType( iCInfo.iPayloadType ); |
|
396 } |
|
397 |
|
398 |
|
399 // ----------------------------------------------------------------------------- |
|
400 // CMccH263PayloadFormatWrite::EmptySourceBufferL |
|
401 // ----------------------------------------------------------------------------- |
|
402 // |
|
403 void CMccH263PayloadFormatWrite::EmptySourceBufferL() |
|
404 { |
|
405 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptySourceBufferL \ |
|
406 from state machine" ) |
|
407 __ASSERT_ALWAYS ( iStateMachine, User::Leave(KErrArgument) ); |
|
408 __ASSERT_ALWAYS ( iClip, User::Leave(KErrArgument) ); |
|
409 |
|
410 // tell the source to give more data |
|
411 iStateMachine->ChangeState( ESourceBufferEmptied ); |
|
412 |
|
413 while ( iBuffers.Count() ) |
|
414 { |
|
415 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptySourceBufferL \ |
|
416 sending" ) |
|
417 CBufferContainer* container = iBuffers[0]; |
|
418 if ( iIsRtpSink ) |
|
419 { |
|
420 CMccRtpDataSink* rtpSink = static_cast<CMccRtpDataSink*>( iClip ); |
|
421 rtpSink->EmptyBufferL( container->iBuffer, this, iMediaId, container->iSendHeader ); |
|
422 } |
|
423 else |
|
424 { |
|
425 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptySourceBufferL copying values" ) |
|
426 container->iBuffer->SetTimeToPlay( container->iSendHeader.iTimestamp ); |
|
427 container->iBuffer->SetLastBuffer( container->iSendHeader.iMarker ); |
|
428 iClip->EmptyBufferL( container->iBuffer, this, iMediaId ); |
|
429 } |
|
430 iBuffers.Remove(0); |
|
431 delete container->iBuffer; |
|
432 container->iBuffer = NULL; |
|
433 delete container; |
|
434 container = NULL; |
|
435 } |
|
436 iBuffers.ResetAndDestroy(); |
|
437 |
|
438 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptySourceBufferL \ |
|
439 all data sent" ) |
|
440 } |
|
441 |
|
442 // ----------------------------------------------------------------------------- |
|
443 // CMccH263PayloadFormatWrite::SourceBufferEmptiedL |
|
444 // ----------------------------------------------------------------------------- |
|
445 // |
|
446 void CMccH263PayloadFormatWrite::SourceBufferEmptiedL() |
|
447 { |
|
448 __H263FORMAT_MEDIA( "CMccH263PayloadFormatWrite::EmptySourceBufferL from state machine" ) |
|
449 |
|
450 __ASSERT_ALWAYS( iDataSource, User::Leave( KErrArgument ) ); |
|
451 |
|
452 iDataSource->BufferEmptiedL( iSourceBuffer ); |
|
453 } |
|
454 |
|
455 // ----------------------------------------------------------------------------- |
|
456 // CMccH263PayloadFormatWrite::PayloadEncodeCleanup |
|
457 // ----------------------------------------------------------------------------- |
|
458 // |
|
459 void CMccH263PayloadFormatWrite::PayloadEncodeCleanup( TAny* aAny ) |
|
460 { |
|
461 // Error occured at payload encoding, cleanup and keep on asking more data |
|
462 // to be encoded. |
|
463 CMccH263PayloadFormatWrite* write = |
|
464 static_cast<CMccH263PayloadFormatWrite*>( aAny ); |
|
465 write->iBuffers.ResetAndDestroy(); |
|
466 |
|
467 write->iStateMachine->ChangeState( ESourceBufferEmptied ); |
|
468 } |
|
469 |
|
470 // ========================== OTHER EXPORTED FUNCTIONS ========================= |
|
471 |
|
472 // End of File |