|
1 /* |
|
2 * Copyright (c) 2005 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 // USER |
|
20 #include "musengclipsession.h" |
|
21 #include "musengmceoutsession.h" |
|
22 #include "musenglivesession.h" |
|
23 #include "musengmceutils.h" |
|
24 #include "musenglogger.h" |
|
25 #include "musengclipvideoplayer.h" |
|
26 |
|
27 // SYSTEM |
|
28 #include <lcsessionobserver.h> |
|
29 #include <mcemanager.h> |
|
30 #include <mcesession.h> |
|
31 #include <mcestreambundle.h> |
|
32 #include <mcefilesource.h> |
|
33 #include <mcemediastream.h> |
|
34 #include <mcevideostream.h> |
|
35 #include <mceaudiostream.h> |
|
36 #include <mcertpsink.h> |
|
37 #include <mcedisplaysink.h> |
|
38 #include <mcespeakersink.h> |
|
39 #include <mceamrcodec.h> |
|
40 #include <mcevideocodec.h> |
|
41 #include <DRMCommon.h> |
|
42 |
|
43 |
|
44 // CONSTANTS |
|
45 const TInt KMusEngAmrBitRate = KMceAmrNbBitrate475; |
|
46 const TUint KMusEngAllowedAmrBitrates = KMceAllowedAmrNbBitrate475; |
|
47 |
|
48 |
|
49 // ----------------------------------------------------------------------------- |
|
50 // |
|
51 // ----------------------------------------------------------------------------- |
|
52 // |
|
53 CMusEngClipSession* CMusEngClipSession::NewL() |
|
54 { |
|
55 CMusEngClipSession* self = new( ELeave )CMusEngClipSession(); |
|
56 CleanupStack::PushL( self ); |
|
57 self->ConstructL(); |
|
58 CleanupStack::Pop( self ); |
|
59 return self; |
|
60 } |
|
61 |
|
62 // ----------------------------------------------------------------------------- |
|
63 // |
|
64 // ----------------------------------------------------------------------------- |
|
65 // |
|
66 CMusEngClipSession::CMusEngClipSession() |
|
67 : CMusEngMceOutSession() |
|
68 { |
|
69 } |
|
70 |
|
71 // ----------------------------------------------------------------------------- |
|
72 // |
|
73 // ----------------------------------------------------------------------------- |
|
74 // |
|
75 void CMusEngClipSession::ConstructL() |
|
76 { |
|
77 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructL(...)" ) |
|
78 |
|
79 CMusEngMceOutSession::ConstructL(); |
|
80 |
|
81 iClipVideoPlayer = CMusEngClipVideoPlayer::NewL( *this, *this ); |
|
82 |
|
83 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructL(...)" ) |
|
84 } |
|
85 |
|
86 // ----------------------------------------------------------------------------- |
|
87 // |
|
88 // ----------------------------------------------------------------------------- |
|
89 // |
|
90 CMusEngClipSession::~CMusEngClipSession() |
|
91 { |
|
92 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::~CMusEngClipSession()" ) |
|
93 |
|
94 delete iClipVideoPlayer; |
|
95 |
|
96 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::~CMusEngClipSession()" ) |
|
97 } |
|
98 |
|
99 // ----------------------------------------------------------------------------- |
|
100 // From MLcSession |
|
101 // ----------------------------------------------------------------------------- |
|
102 // |
|
103 MLcVideoPlayer* CMusEngClipSession::LocalVideoPlayer() |
|
104 { |
|
105 return iClipVideoPlayer; |
|
106 } |
|
107 |
|
108 // ----------------------------------------------------------------------------- |
|
109 // |
|
110 // ----------------------------------------------------------------------------- |
|
111 // |
|
112 void CMusEngClipSession::CompleteSessionStructureL( |
|
113 CMceStreamBundle& aLocalBundle ) |
|
114 { |
|
115 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::CompleteSessionStructureL()" ) |
|
116 |
|
117 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
118 |
|
119 // Create outgoing video stream |
|
120 CMceVideoStream* videoStream = CMceVideoStream::NewLC(); |
|
121 |
|
122 CMceRtpSink* rtpsink = CMceRtpSink::NewLC(); |
|
123 videoStream->AddSinkL( rtpsink ); |
|
124 CleanupStack::Pop( rtpsink ); |
|
125 |
|
126 CMceFileSource* fileSource = |
|
127 CMceFileSource::NewLC( *iManager, iClipVideoPlayer->LcFileName() ); |
|
128 fileSource->DisableL(); // Start session in pause mode. |
|
129 videoStream->SetSourceL( fileSource ); |
|
130 CleanupStack::Pop( fileSource ); |
|
131 |
|
132 iSession->AddStreamL( videoStream ); |
|
133 CleanupStack::Pop( videoStream ); |
|
134 |
|
135 ConstructAudioStructureL( aLocalBundle ); |
|
136 |
|
137 iClipVideoPlayer->SetMceSession( iSession ); |
|
138 |
|
139 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::CompleteSessionStructureL()" ) |
|
140 } |
|
141 |
|
142 // ----------------------------------------------------------------------------- |
|
143 // Checks that that there is no need for transcoding before calling |
|
144 // overridden base class variant of this function. |
|
145 // ----------------------------------------------------------------------------- |
|
146 // |
|
147 void CMusEngClipSession::EstablishSessionL() |
|
148 { |
|
149 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::EstablishSessionL()" ) |
|
150 |
|
151 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
152 |
|
153 const RPointerArray<CMceMediaStream>& streams = iSession->Streams(); |
|
154 |
|
155 if ( iVideoCodecList ) |
|
156 { |
|
157 MUS_LOG_TDESC8( "iVideoCodecList: ", iVideoCodecList->Des() ) |
|
158 } |
|
159 |
|
160 CMceVideoStream* videoStream = NULL; |
|
161 for ( TInt i = 0; i < streams.Count(); ++i ) |
|
162 { |
|
163 if ( streams[i]->State() == CMceMediaStream::ETranscodingRequired ) |
|
164 { |
|
165 User::Leave( KErrNotSupported ); |
|
166 } |
|
167 else if ( streams[i]->Type() == KMceVideo && |
|
168 !IsH264Supported() ) |
|
169 { |
|
170 MUS_LOG( " -> video stream found!!!" ) |
|
171 videoStream = static_cast<CMceVideoStream*>( streams[i] ); |
|
172 |
|
173 //transcoding of H264 is not needed only if we know explicitly |
|
174 //that the peer supports it (from OPTIONS response) |
|
175 |
|
176 const RPointerArray<CMceVideoCodec>& codecs = videoStream->Codecs(); |
|
177 for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex ) |
|
178 { |
|
179 if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() ) |
|
180 { |
|
181 User::Leave( KErrNotSupported ); |
|
182 } |
|
183 } |
|
184 } |
|
185 } |
|
186 |
|
187 CMusEngMceOutSession::EstablishSessionL(); |
|
188 // Now session state is right to adjust volume |
|
189 SetSpeakerVolumeL( LcVolumeL() ); |
|
190 |
|
191 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::EstablishSessionL()" ) |
|
192 } |
|
193 |
|
194 // ----------------------------------------------------------------------------- |
|
195 // Implemented for MMceStreamObserver |
|
196 // ----------------------------------------------------------------------------- |
|
197 // |
|
198 void CMusEngClipSession::StreamStateChanged( CMceMediaStream& aStream ) |
|
199 { |
|
200 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::StreamStateChanged()" ) |
|
201 |
|
202 if ( !iSession ) |
|
203 { |
|
204 return; |
|
205 } |
|
206 |
|
207 DetermineBufferingPeriod( aStream ); |
|
208 |
|
209 CMusEngMceSession::StreamStateChanged( aStream ); |
|
210 |
|
211 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::StreamStateChanged()" ) |
|
212 } |
|
213 |
|
214 // ----------------------------------------------------------------------------- |
|
215 // Implemented for MMceStreamObserver |
|
216 // ----------------------------------------------------------------------------- |
|
217 // |
|
218 void CMusEngClipSession::StreamStateChanged( CMceMediaStream& aStream, |
|
219 CMceMediaSource& aSource ) |
|
220 { |
|
221 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::StreamStateChanged( src )" ) |
|
222 |
|
223 if ( !iSession ) |
|
224 { |
|
225 return; |
|
226 } |
|
227 |
|
228 MUS_ENG_LOG_STREAM_STATE( aStream ) |
|
229 |
|
230 DetermineBufferingPeriod( aStream ); |
|
231 |
|
232 if ( iClipVideoPlayer->HasClipEnded() ) |
|
233 { |
|
234 MUS_LOG( "mus: [ENGINE] Clip ended." ) |
|
235 InformObserverAboutPlayerStateChange( iClipVideoPlayer ); |
|
236 } |
|
237 else |
|
238 { |
|
239 // Cannot handle, forward to the ancestor class |
|
240 CMusEngMceSession::StreamStateChanged( aStream, aSource ); |
|
241 } |
|
242 |
|
243 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::StreamStateChanged( src )" ) |
|
244 } |
|
245 |
|
246 // ----------------------------------------------------------------------------- |
|
247 // |
|
248 // ----------------------------------------------------------------------------- |
|
249 // |
|
250 void CMusEngClipSession::AddAmrCodecL( CMceAudioStream& aAudioStream ) |
|
251 { |
|
252 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddAmrCodecL" ) |
|
253 |
|
254 // Remove old codecs |
|
255 while ( aAudioStream.Codecs().Count() > 0 ) |
|
256 { |
|
257 aAudioStream.RemoveCodecL( *aAudioStream.Codecs()[0] ); |
|
258 } |
|
259 |
|
260 // Create AMR codec instance |
|
261 const RPointerArray<const CMceAudioCodec>& supportedCodecs = |
|
262 iManager->SupportedAudioCodecs(); |
|
263 |
|
264 CMceAudioCodec* amr = NULL; |
|
265 |
|
266 for ( TInt i = 0; i < supportedCodecs.Count(); ++i ) |
|
267 { |
|
268 if ( supportedCodecs[i]->SdpName() == KMceSDPNameAMR() ) |
|
269 { |
|
270 amr = supportedCodecs[i]->CloneL(); |
|
271 CleanupStack::PushL( amr ); |
|
272 User::LeaveIfError( |
|
273 amr->SetAllowedBitrates( KMusEngAllowedAmrBitrates ) ); |
|
274 User::LeaveIfError( amr->SetBitrate( KMusEngAmrBitRate ) ); |
|
275 aAudioStream.AddCodecL( amr ); |
|
276 CleanupStack::Pop( amr ); |
|
277 break; // We must have only one codec |
|
278 } |
|
279 } |
|
280 |
|
281 __ASSERT_ALWAYS( amr, User::Leave( KErrNotFound ) ); |
|
282 |
|
283 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddAmrCodecL" ) |
|
284 } |
|
285 |
|
286 // ----------------------------------------------------------------------------- |
|
287 // Create codec instance, H264 is used only if other end supports it for sure, |
|
288 // otherwise H263 is used. |
|
289 // ----------------------------------------------------------------------------- |
|
290 // |
|
291 void CMusEngClipSession::AddVideoCodecL( CMceVideoStream& aVideoStream ) |
|
292 { |
|
293 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddVideoCodecL" ) |
|
294 |
|
295 // Remove old codecs |
|
296 |
|
297 while ( aVideoStream.Codecs().Count() > 0 ) |
|
298 { |
|
299 aVideoStream.RemoveCodecL( *aVideoStream.Codecs()[0] ); |
|
300 } |
|
301 |
|
302 const RPointerArray< const CMceVideoCodec >& supportedCodecs = |
|
303 iManager->SupportedVideoCodecs(); |
|
304 |
|
305 CMceVideoCodec* addedCodec = NULL; |
|
306 |
|
307 TPtrC8 addedCodecName = |
|
308 IsH264Supported() ? KMceSDPNameH264() : KMceSDPNameH2632000(); |
|
309 |
|
310 MUS_LOG_TDESC8( "mus: [ENGINE] adding codec : ", addedCodecName ); |
|
311 |
|
312 for ( TInt i = 0; i < supportedCodecs.Count(); ++i ) |
|
313 { |
|
314 if ( supportedCodecs[i]->SdpName() == addedCodecName ) |
|
315 { |
|
316 addedCodec = supportedCodecs[i]->CloneL(); |
|
317 CleanupStack::PushL( addedCodec ); |
|
318 aVideoStream.AddCodecL( addedCodec ); |
|
319 CleanupStack::Pop( addedCodec ); |
|
320 break; // We must have only one codec |
|
321 } |
|
322 } |
|
323 |
|
324 __ASSERT_ALWAYS( addedCodec, User::Leave( KErrNotFound ) ); |
|
325 |
|
326 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddVideoCodecL" ) |
|
327 } |
|
328 |
|
329 // ----------------------------------------------------------------------------- |
|
330 // If member file contains audio, add appropriate amount of audio streams to |
|
331 // session structure |
|
332 // ----------------------------------------------------------------------------- |
|
333 // |
|
334 void CMusEngClipSession::ConstructAudioStructureL( |
|
335 CMceStreamBundle& aLocalBundle ) |
|
336 { |
|
337 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructAudioStructureL()" ) |
|
338 |
|
339 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
340 |
|
341 // There is no clip audio present in operator variant |
|
342 if ( iOperatorVariant ) |
|
343 { |
|
344 MUS_LOG( " Operator variant, no audio constructed" ) |
|
345 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructAudioStructureL()" ) |
|
346 return; |
|
347 } |
|
348 |
|
349 CMceFileSource* fileSource = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
350 |
|
351 TInt audioElementCount = fileSource->MediaElementCountL( KMceAudio ); |
|
352 |
|
353 MUS_LOG1( "mus: [ENGINE] File contains %d audio elements", |
|
354 audioElementCount ) |
|
355 |
|
356 for ( TInt i = 0; i < audioElementCount; ++i ) |
|
357 { |
|
358 fileSource->SetCurrentMediaElementL( KMceAudio, i ); |
|
359 |
|
360 MUS_LOG1( "mus: [ENGINE] Current audio element set to : %d ", i ) |
|
361 |
|
362 // Set up an audio outstream. |
|
363 CMceAudioStream* audioOut = CMceAudioStream::NewLC(); |
|
364 |
|
365 CMceRtpSink* rtpSink = CMceRtpSink::NewLC(); |
|
366 audioOut->AddSinkL( rtpSink ); |
|
367 CleanupStack::Pop( rtpSink ); |
|
368 |
|
369 audioOut->SetSourceL( fileSource ); |
|
370 |
|
371 iSession->AddStreamL( audioOut ); |
|
372 CleanupStack::Pop( audioOut ); |
|
373 |
|
374 MUS_LOG( "mus: [ENGINE] Audio outstream created" ) |
|
375 |
|
376 // Set up an audio stream to local speaker |
|
377 audioOut = CMceAudioStream::NewLC(); |
|
378 |
|
379 MusEngMceUtils::AddSpeakerL( *audioOut ); |
|
380 |
|
381 audioOut->SetSourceL( fileSource ); |
|
382 |
|
383 iSession->AddStreamL( audioOut ); |
|
384 CleanupStack::Pop( audioOut ); |
|
385 |
|
386 MUS_LOG( "mus: [ENGINE] Local audio stream created" ) |
|
387 |
|
388 aLocalBundle.AddStreamL( *audioOut ); |
|
389 |
|
390 MUS_LOG( "mus: [ENGINE] Local audio stream added to bundle" ) |
|
391 } |
|
392 |
|
393 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructAudioStructureL()" ) |
|
394 } |
|
395 |
|
396 // ----------------------------------------------------------------------------- |
|
397 // Calculates how long MCE buffers based on time between buffering and streaming |
|
398 // events. |
|
399 // ----------------------------------------------------------------------------- |
|
400 // |
|
401 void CMusEngClipSession::DetermineBufferingPeriod( CMceMediaStream& aStream ) |
|
402 { |
|
403 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::DetermineBufferingPeriod()" ) |
|
404 |
|
405 // Determine file position modifier from time difference between buffering |
|
406 // and streaming events |
|
407 if ( aStream.State() == CMceMediaStream::EBuffering ) |
|
408 { |
|
409 iBufferingStartedTime.HomeTime(); |
|
410 } |
|
411 |
|
412 if ( aStream.State() == CMceMediaStream::EStreaming ) |
|
413 { |
|
414 if ( iBufferingStartedTime.Int64() != 0 ) |
|
415 { |
|
416 TTime currentTime; |
|
417 currentTime.HomeTime(); |
|
418 |
|
419 TTimeIntervalMicroSeconds bufferingPeriod = |
|
420 currentTime.MicroSecondsFrom( iBufferingStartedTime ); |
|
421 |
|
422 const TInt KMusMinimumBufferingPeriod( 500000 ); |
|
423 if ( bufferingPeriod > KMusMinimumBufferingPeriod ) |
|
424 { |
|
425 iClipVideoPlayer->SetBufferingPeriod( bufferingPeriod ); |
|
426 } |
|
427 |
|
428 MUS_LOG1( "mus: [ENGINE] current buffering period:%d", |
|
429 bufferingPeriod.Int64() ) |
|
430 |
|
431 iBufferingStartedTime = 0; |
|
432 } |
|
433 } |
|
434 |
|
435 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::DetermineBufferingPeriod()" ) |
|
436 } |
|
437 |
|
438 // End of file |