37 #include <mcedisplaysink.h> |
37 #include <mcedisplaysink.h> |
38 #include <mcespeakersink.h> |
38 #include <mcespeakersink.h> |
39 #include <mceamrcodec.h> |
39 #include <mceamrcodec.h> |
40 #include <mcevideocodec.h> |
40 #include <mcevideocodec.h> |
41 #include <DRMCommon.h> |
41 #include <DRMCommon.h> |
|
42 #include <f32file.h> |
42 |
43 |
43 |
44 |
44 // CONSTANTS |
45 // CONSTANTS |
|
46 |
|
47 const TInt64 KMicroSecondsInOneSecond = 1000000; |
45 const TInt KMusEngAmrBitRate = KMceAmrNbBitrate475; |
48 const TInt KMusEngAmrBitRate = KMceAmrNbBitrate475; |
46 const TUint KMusEngAllowedAmrBitrates = KMceAllowedAmrNbBitrate475; |
49 const TUint KMusEngAllowedAmrBitrates = KMceAllowedAmrNbBitrate475; |
47 |
50 |
48 |
51 const TInt KFastWindingFactor = 4; |
49 // ----------------------------------------------------------------------------- |
52 |
50 // |
53 // ----------------------------------------------------------------------------- |
51 // ----------------------------------------------------------------------------- |
54 // |
52 // |
55 // ----------------------------------------------------------------------------- |
53 CMusEngClipSession* CMusEngClipSession::NewL() |
56 // |
54 { |
57 EXPORT_C CMusEngClipSession* CMusEngClipSession::NewL( |
55 CMusEngClipSession* self = new( ELeave )CMusEngClipSession(); |
58 const TRect& aRect, |
|
59 MMusEngSessionObserver& aSessionObserver, |
|
60 MMusEngOutSessionObserver& aOutSessionObserver, |
|
61 MMusEngClipSessionObserver& aClipSessionObserver, |
|
62 TUint aSipProfileId ) |
|
63 { |
|
64 CMusEngClipSession* self = new( ELeave ) CMusEngClipSession( |
|
65 aSessionObserver, |
|
66 aOutSessionObserver, |
|
67 aClipSessionObserver, |
|
68 aRect ); |
56 CleanupStack::PushL( self ); |
69 CleanupStack::PushL( self ); |
57 self->ConstructL(); |
70 self->ConstructL( aSipProfileId ); |
58 CleanupStack::Pop( self ); |
71 CleanupStack::Pop( self ); |
59 return self; |
72 return self; |
60 } |
73 } |
61 |
74 |
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 |
75 |
86 // ----------------------------------------------------------------------------- |
76 // ----------------------------------------------------------------------------- |
87 // |
77 // |
88 // ----------------------------------------------------------------------------- |
78 // ----------------------------------------------------------------------------- |
89 // |
79 // |
90 CMusEngClipSession::~CMusEngClipSession() |
80 CMusEngClipSession::~CMusEngClipSession() |
91 { |
81 { |
92 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::~CMusEngClipSession()" ) |
82 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::~CMusEngClipSession()" ) |
93 |
|
94 delete iClipVideoPlayer; |
|
95 |
|
96 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::~CMusEngClipSession()" ) |
83 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::~CMusEngClipSession()" ) |
97 } |
84 } |
98 |
85 |
99 // ----------------------------------------------------------------------------- |
86 |
100 // From MLcSession |
87 // ----------------------------------------------------------------------------- |
101 // ----------------------------------------------------------------------------- |
88 // |
102 // |
89 // ----------------------------------------------------------------------------- |
103 MLcVideoPlayer* CMusEngClipSession::LocalVideoPlayer() |
90 // |
104 { |
91 EXPORT_C void CMusEngClipSession::SetClipL( const TDesC& aFileName ) |
105 return iClipVideoPlayer; |
92 { |
106 } |
93 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::SetClipL(...)" ) |
|
94 |
|
95 __ASSERT_ALWAYS( !IsProtectedFileL( aFileName ), |
|
96 User::Leave( KErrPermissionDenied ) ); |
|
97 |
|
98 if ( iSession ) |
|
99 { |
|
100 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
101 file->UpdateL( aFileName ); |
|
102 } |
|
103 |
|
104 iFileName = aFileName; |
|
105 |
|
106 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::SetClipL(...)" ) |
|
107 |
|
108 } |
|
109 |
|
110 |
|
111 // ----------------------------------------------------------------------------- |
|
112 // Since MCE does not at the moment support SetFastForwardL function, this |
|
113 // functionality is implemented by taking a timestamp when forwarding is |
|
114 // started and calculating a new position when it is ended. |
|
115 // ----------------------------------------------------------------------------- |
|
116 // |
|
117 EXPORT_C void CMusEngClipSession::FastForwardL( TBool aUseFFWD ) |
|
118 { |
|
119 MUS_LOG1( "mus: [ENGINE] -> CMusEngClipSession::FastForward(%d)", aUseFFWD ) |
|
120 |
|
121 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
122 |
|
123 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
124 |
|
125 if ( aUseFFWD ) |
|
126 { |
|
127 // Ignore if we are already fastforwarding |
|
128 if ( iFFWDStartTime.Int64() > 0 ) |
|
129 { |
|
130 return; |
|
131 } |
|
132 |
|
133 // Stop rewinding if ongoing, else just pause file source |
|
134 if ( iFRWDStartTime.Int64() > 0 ) |
|
135 { |
|
136 FastRewindL( EFalse ); |
|
137 } |
|
138 else |
|
139 { |
|
140 file->DisableL(); |
|
141 } |
|
142 |
|
143 // Get timestamp for starttime |
|
144 iFFWDStartTime.HomeTime(); |
|
145 } |
|
146 else |
|
147 { |
|
148 // Leave if we are not fastforwarding |
|
149 if ( iFFWDStartTime.Int64() == 0 ) |
|
150 { |
|
151 User::Leave( KErrAlreadyExists ); |
|
152 } |
|
153 |
|
154 // Set new position |
|
155 file->SetPositionL( PositionMicroSecondsL() ); |
|
156 MUS_LOG( " SetPositionL returned without error " ) |
|
157 |
|
158 // Reset timer |
|
159 iFFWDStartTime = TTime( 0 ); |
|
160 } |
|
161 |
|
162 MUS_LOG1( "mus: [ENGINE] <- CMusEngClipSession::FastForward(%d)", aUseFFWD ) |
|
163 } |
|
164 |
|
165 |
|
166 // ----------------------------------------------------------------------------- |
|
167 // Since MCE does not at the moment support SetFastRewindL function, this |
|
168 // functionality is implemented by taking a timestamp when rewinding is |
|
169 // started and calculating a new position when it is ended. |
|
170 // ----------------------------------------------------------------------------- |
|
171 // |
|
172 EXPORT_C void CMusEngClipSession::FastRewindL( TBool aUseFRWD ) |
|
173 { |
|
174 MUS_LOG1( "mus: [ENGINE] -> CMusEngClipSession::FastRewind(%d)", aUseFRWD ) |
|
175 |
|
176 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
177 |
|
178 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
179 |
|
180 if ( aUseFRWD ) |
|
181 { |
|
182 // Ignore if we are already fastrewinding |
|
183 if ( iFRWDStartTime.Int64() > 0 ) |
|
184 { |
|
185 return; |
|
186 } |
|
187 |
|
188 // Stop fastforwarding if ongoing, else just pause file source |
|
189 if ( iFFWDStartTime.Int64() > 0 ) |
|
190 { |
|
191 FastForwardL( EFalse ); |
|
192 } |
|
193 else |
|
194 { |
|
195 file->DisableL(); |
|
196 } |
|
197 |
|
198 // Get timestamp for starttime |
|
199 iFRWDStartTime.HomeTime(); |
|
200 } |
|
201 else |
|
202 { |
|
203 // Leave if we are not fastrewinding |
|
204 if ( iFRWDStartTime.Int64() == 0 ) |
|
205 { |
|
206 User::Leave( KErrAlreadyExists ); |
|
207 } |
|
208 |
|
209 // Set new position |
|
210 file->SetPositionL( PositionMicroSecondsL() ); |
|
211 MUS_LOG( " SetPositionL returned without error " ) |
|
212 |
|
213 // Reset timer |
|
214 iFRWDStartTime = TTime( 0 ); |
|
215 } |
|
216 |
|
217 MUS_LOG1( "mus: [ENGINE] <- CMusEngClipSession::FastRewind(%d)", aUseFRWD ) |
|
218 } |
|
219 |
|
220 |
|
221 // ----------------------------------------------------------------------------- |
|
222 // |
|
223 // ----------------------------------------------------------------------------- |
|
224 // |
|
225 EXPORT_C TTimeIntervalSeconds CMusEngClipSession::PositionL() |
|
226 { |
|
227 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::PositionL()" ) |
|
228 |
|
229 TTimeIntervalMicroSeconds currentPosition = PositionMicroSecondsL(); |
|
230 |
|
231 MUS_LOG1( "mus: [ENGINE] <- CMusEngClipSession::PositionL(), pos:%d", |
|
232 currentPosition.Int64() ) |
|
233 return TTimeIntervalSeconds( static_cast<TInt>( |
|
234 currentPosition.Int64() / KMicroSecondsInOneSecond ) ); |
|
235 } |
|
236 |
|
237 |
|
238 // ----------------------------------------------------------------------------- |
|
239 // |
|
240 // ----------------------------------------------------------------------------- |
|
241 // |
|
242 EXPORT_C TTimeIntervalSeconds CMusEngClipSession::DurationL() |
|
243 { |
|
244 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::DurationL()" ) |
|
245 |
|
246 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
247 |
|
248 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
249 |
|
250 TTimeIntervalMicroSeconds duration = file->DurationL(); |
|
251 |
|
252 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::DurationL()" ) |
|
253 return TTimeIntervalSeconds( |
|
254 static_cast<TInt>( duration.Int64() / KMicroSecondsInOneSecond ) ); |
|
255 |
|
256 } |
|
257 |
|
258 |
|
259 // ----------------------------------------------------------------------------- |
|
260 // |
|
261 // ----------------------------------------------------------------------------- |
|
262 // |
|
263 EXPORT_C void CMusEngClipSession::SetPositionL ( |
|
264 const TTimeIntervalSeconds& aPosition ) |
|
265 { |
|
266 MUS_LOG1( "mus: [ENGINE] -> CMusEngClipSession::SetPositionL (%d)", |
|
267 aPosition.Int() ) |
|
268 |
|
269 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
270 |
|
271 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
272 |
|
273 TTimeIntervalMicroSeconds position( |
|
274 KMicroSecondsInOneSecond * static_cast<TInt64>(aPosition.Int()) ); |
|
275 |
|
276 if ( position == 0 ) |
|
277 { |
|
278 iRewindedToBeginning = ETrue; |
|
279 } |
|
280 |
|
281 file->SetPositionL( position ); |
|
282 |
|
283 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::SetPositionL ()" ) |
|
284 } |
|
285 |
|
286 |
|
287 // ----------------------------------------------------------------------------- |
|
288 // |
|
289 // ----------------------------------------------------------------------------- |
|
290 // |
|
291 EXPORT_C void CMusEngClipSession::TranscodeL( const TFileName& aFileName ) |
|
292 { |
|
293 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::TranscodeL(...)" ) |
|
294 |
|
295 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
296 |
|
297 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
298 |
|
299 const RPointerArray<CMceMediaStream>& streams = iSession->Streams(); |
|
300 |
|
301 for ( TInt i = 0; i < streams.Count(); ++i ) |
|
302 { |
|
303 if ( streams[i]->State() == CMceMediaStream::ETranscodingRequired ) |
|
304 { |
|
305 if ( streams[i]->Type() == KMceAudio ) |
|
306 { |
|
307 AddAmrCodecL( static_cast<CMceAudioStream&>( *streams[i] ) ); |
|
308 } |
|
309 else |
|
310 { |
|
311 AddVideoCodecL( static_cast<CMceVideoStream&>( *streams[i] ) ); |
|
312 } |
|
313 } |
|
314 } |
|
315 |
|
316 // Set dest file already before transcoding as output file is deleted in failure case |
|
317 iTranscodingDestFileName = aFileName; |
|
318 TRAPD( err, file->TranscodeL( aFileName ) ); |
|
319 HandleTranscodingFailureL( err ); |
|
320 iTranscodingOngoing = ETrue; |
|
321 |
|
322 |
|
323 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::TranscodeL(...)" ) |
|
324 } |
|
325 |
|
326 |
|
327 // ----------------------------------------------------------------------------- |
|
328 // |
|
329 // ----------------------------------------------------------------------------- |
|
330 // |
|
331 EXPORT_C void CMusEngClipSession::CancelTranscodeL() |
|
332 { |
|
333 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::CancelTranscodeL()" ) |
|
334 |
|
335 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
336 |
|
337 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
338 |
|
339 TRAPD( err, file->CancelTranscodeL() ); |
|
340 err = err; // Silence warning in UREL build |
|
341 MUS_LOG1( "mus: [ENGINE] - cancel result %d", err ) |
|
342 // Even if cancel fails, try to delete the partial clip |
|
343 |
|
344 MUS_LOG( "mus: [ENGINE] - delete the partially converted clip" ) |
|
345 |
|
346 DeleteTranscodingDestinationFileL(); |
|
347 |
|
348 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::CancelTranscodeL()" ) |
|
349 } |
|
350 |
|
351 |
|
352 // ----------------------------------------------------------------------------- |
|
353 // |
|
354 // ----------------------------------------------------------------------------- |
|
355 // |
|
356 EXPORT_C void CMusEngClipSession::PlayL() |
|
357 { |
|
358 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::PlayL()" ) |
|
359 |
|
360 __ASSERT_ALWAYS( iSession && |
|
361 iFFWDStartTime.Int64() == 0 && |
|
362 iFRWDStartTime.Int64() == 0, |
|
363 User::Leave( KErrNotReady ) ); |
|
364 |
|
365 iPause = EFalse; |
|
366 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
367 |
|
368 if ( !file->IsEnabled() ) |
|
369 { |
|
370 file->EnableL(); |
|
371 |
|
372 iClipEnded = EFalse; |
|
373 // No need to enable audio separarely |
|
374 } |
|
375 else |
|
376 { |
|
377 MUS_LOG( "mus: [ENGINE] File is already enabled, ignore request" ) |
|
378 } |
|
379 |
|
380 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::PlayL()" ) |
|
381 } |
|
382 |
|
383 |
|
384 // ----------------------------------------------------------------------------- |
|
385 // |
|
386 // ----------------------------------------------------------------------------- |
|
387 // |
|
388 EXPORT_C void CMusEngClipSession::PauseL() |
|
389 { |
|
390 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::PauseL()" ) |
|
391 |
|
392 __ASSERT_ALWAYS( iSession && |
|
393 iFFWDStartTime.Int64() == 0 && |
|
394 iFRWDStartTime.Int64() == 0, |
|
395 User::Leave( KErrNotReady ) ); |
|
396 |
|
397 |
|
398 iPause = ETrue; |
|
399 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
400 |
|
401 if ( file->IsEnabled() ) |
|
402 { |
|
403 file->DisableL(); |
|
404 |
|
405 // No need to disable audio separarely |
|
406 } |
|
407 else |
|
408 { |
|
409 MUS_LOG( "mus: [ENGINE] File is already disabled, ignore request" ) |
|
410 } |
|
411 |
|
412 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::PauseL()" ) |
|
413 } |
|
414 |
|
415 |
|
416 // ----------------------------------------------------------------------------- |
|
417 // |
|
418 // ----------------------------------------------------------------------------- |
|
419 // |
|
420 EXPORT_C TBool CMusEngClipSession::IsPlayingL() |
|
421 { |
|
422 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
423 |
|
424 return ( MusEngMceUtils::GetFileSourceL( *iSession )->IsEnabled() ); |
|
425 } |
|
426 |
107 |
427 |
108 // ----------------------------------------------------------------------------- |
428 // ----------------------------------------------------------------------------- |
109 // |
429 // |
110 // ----------------------------------------------------------------------------- |
430 // ----------------------------------------------------------------------------- |
111 // |
431 // |
112 void CMusEngClipSession::CompleteSessionStructureL( |
432 void CMusEngClipSession::CompleteSessionStructureL( |
113 CMceStreamBundle& aLocalBundle ) |
433 CMceStreamBundle& aLocalBundle ) |
114 { |
434 { |
115 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::CompleteSessionStructureL()" ) |
435 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::CompleteSessionStructureL()" ) |
116 |
436 |
117 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
437 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
438 __ASSERT_ALWAYS( iFileName != KNullDesC(), User::Leave( KErrNotReady ) ); |
118 |
439 |
119 // Create outgoing video stream |
440 // Create outgoing video stream |
120 CMceVideoStream* videoStream = CMceVideoStream::NewLC(); |
441 CMceVideoStream* videoStream = CMceVideoStream::NewLC(); |
121 |
442 |
122 CMceRtpSink* rtpsink = CMceRtpSink::NewLC(); |
443 CMceRtpSink* rtpsink = CMceRtpSink::NewLC(); |
123 videoStream->AddSinkL( rtpsink ); |
444 videoStream->AddSinkL( rtpsink ); |
124 CleanupStack::Pop( rtpsink ); |
445 CleanupStack::Pop( rtpsink ); |
125 |
446 |
126 CMceFileSource* fileSource = |
447 CMceFileSource* fileSource = CMceFileSource::NewLC( *iManager, |
127 CMceFileSource::NewLC( *iManager, iClipVideoPlayer->LcFileName() ); |
448 iFileName ); |
128 fileSource->DisableL(); // Start session in pause mode. |
449 fileSource->DisableL(); // Start session in pause mode. |
129 videoStream->SetSourceL( fileSource ); |
450 videoStream->SetSourceL( fileSource ); |
130 CleanupStack::Pop( fileSource ); |
451 CleanupStack::Pop( fileSource ); |
131 |
452 |
132 iSession->AddStreamL( videoStream ); |
453 iSession->AddStreamL( videoStream ); |
133 CleanupStack::Pop( videoStream ); |
454 CleanupStack::Pop( videoStream ); |
134 |
455 |
135 ConstructAudioStructureL( aLocalBundle ); |
456 ConstructAudioStructureL( aLocalBundle ); |
136 |
|
137 iClipVideoPlayer->SetMceSession( iSession ); |
|
138 |
457 |
139 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::CompleteSessionStructureL()" ) |
458 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::CompleteSessionStructureL()" ) |
140 } |
459 } |
|
460 |
141 |
461 |
142 // ----------------------------------------------------------------------------- |
462 // ----------------------------------------------------------------------------- |
143 // Checks that that there is no need for transcoding before calling |
463 // Checks that that there is no need for transcoding before calling |
144 // overridden base class variant of this function. |
464 // overridden base class variant of this function. |
145 // ----------------------------------------------------------------------------- |
465 // ----------------------------------------------------------------------------- |
150 |
470 |
151 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
471 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
152 |
472 |
153 const RPointerArray<CMceMediaStream>& streams = iSession->Streams(); |
473 const RPointerArray<CMceMediaStream>& streams = iSession->Streams(); |
154 |
474 |
|
475 TBool transcodingRequired = EFalse; |
|
476 TBool transcodingRequiredDueUnknownCaps = EFalse; |
|
477 |
155 if ( iVideoCodecList ) |
478 if ( iVideoCodecList ) |
156 { |
479 { |
157 MUS_LOG_TDESC8( "iVideoCodecList: ", iVideoCodecList->Des() ) |
480 MUS_LOG_TDESC8( "iVideoCodecList: ", iVideoCodecList->Des() ) |
158 } |
481 } |
159 |
482 |
160 CMceVideoStream* videoStream = NULL; |
483 CMceVideoStream* videoStream = NULL; |
161 for ( TInt i = 0; i < streams.Count(); ++i ) |
484 for ( TInt i = 0; i < streams.Count(); ++i ) |
162 { |
485 { |
163 if ( streams[i]->State() == CMceMediaStream::ETranscodingRequired ) |
486 videoStream = static_cast<CMceVideoStream*>( streams[i] ); |
164 { |
487 |
165 User::Leave( KErrNotSupported ); |
488 if ( iTranscodingRequiredDueMissingOptions ) |
166 } |
489 { |
167 else if ( streams[i]->Type() == KMceVideo && |
490 MUS_LOG( " -> establish with current codec, remote capa unknown!!!" ) |
168 !IsH264Supported() ) |
491 TBool ignoreOptionsQueryCodecs( ETrue ); |
|
492 AddVideoCodecL( *videoStream, ignoreOptionsQueryCodecs ); |
|
493 } |
|
494 else if ( streams[i]->State() == CMceMediaStream::ETranscodingRequired ) |
|
495 { |
|
496 transcodingRequired = ETrue; |
|
497 } |
|
498 else if ( streams[i]->Type() == KMceVideo && !IsH264Supported() ) |
169 { |
499 { |
170 MUS_LOG( " -> video stream found!!!" ) |
500 MUS_LOG( " -> video stream found!!!" ) |
171 videoStream = static_cast<CMceVideoStream*>( streams[i] ); |
|
172 |
501 |
173 //transcoding of H264 is not needed only if we know explicitly |
502 //transcoding of H264 is not needed only if we know explicitly |
174 //that the peer supports it (from OPTIONS response) |
503 //that the peer supports it (from OPTIONS response) |
175 |
|
176 const RPointerArray<CMceVideoCodec>& codecs = videoStream->Codecs(); |
504 const RPointerArray<CMceVideoCodec>& codecs = videoStream->Codecs(); |
177 for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex ) |
505 for ( TInt codecIndex = 0; codecIndex < codecs.Count(); ++codecIndex ) |
178 { |
506 { |
179 if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() ) |
507 if ( codecs[codecIndex]->SdpName() == KMceSDPNameH264() ) |
180 { |
508 { |
181 User::Leave( KErrNotSupported ); |
509 transcodingRequired = ETrue; |
|
510 transcodingRequiredDueUnknownCaps = !iVideoCodecList; |
|
511 MUS_LOG( " -> Removing H264 codec from video stream" ) |
|
512 videoStream->RemoveCodecL( *codecs[codecIndex] ); |
|
513 codecIndex = 0; |
182 } |
514 } |
183 } |
515 } |
|
516 |
|
517 if ( codecs.Count() == 0) |
|
518 { |
|
519 // At least one codec should be in the stream list. |
|
520 MUS_LOG( " -> Adding codec, since codecs list is empty " ) |
|
521 AddVideoCodecL( *videoStream ); |
|
522 } |
184 } |
523 } |
185 } |
524 } |
186 |
525 |
187 CMusEngMceOutSession::EstablishSessionL(); |
526 iTranscodingRequiredDueMissingOptions = transcodingRequiredDueUnknownCaps; |
188 // Now session state is right to adjust volume |
527 |
189 SetSpeakerVolumeL( LcVolumeL() ); |
528 if ( transcodingRequired ) |
|
529 { |
|
530 iClipSessionObserver.TranscodingNeeded(iTranscodingRequiredDueMissingOptions); |
|
531 } |
|
532 else |
|
533 { |
|
534 CMusEngMceOutSession::EstablishSessionL(); |
|
535 // Now session state is right to adjust volume |
|
536 SetSpeakerVolumeL( VolumeL() ); |
|
537 } |
190 |
538 |
191 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::EstablishSessionL()" ) |
539 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::EstablishSessionL()" ) |
192 } |
540 } |
193 |
541 |
194 // ----------------------------------------------------------------------------- |
542 // ----------------------------------------------------------------------------- |
245 |
631 |
246 // ----------------------------------------------------------------------------- |
632 // ----------------------------------------------------------------------------- |
247 // |
633 // |
248 // ----------------------------------------------------------------------------- |
634 // ----------------------------------------------------------------------------- |
249 // |
635 // |
|
636 CMusEngClipSession::CMusEngClipSession( |
|
637 MMusEngSessionObserver& aSessionObserver, |
|
638 MMusEngOutSessionObserver& aOutSessionObserver, |
|
639 MMusEngClipSessionObserver& aClipSessionObserver, |
|
640 const TRect& aRect ) |
|
641 : CMusEngMceOutSession( aRect, |
|
642 aSessionObserver, |
|
643 aOutSessionObserver ), |
|
644 iClipSessionObserver( aClipSessionObserver ) |
|
645 { |
|
646 } |
|
647 |
|
648 |
|
649 // ----------------------------------------------------------------------------- |
|
650 // |
|
651 // ----------------------------------------------------------------------------- |
|
652 // |
|
653 void CMusEngClipSession::ConstructL( TUint aSipProfileId ) |
|
654 { |
|
655 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructL(...)" ) |
|
656 |
|
657 CMusEngMceOutSession::ConstructL( aSipProfileId ); |
|
658 |
|
659 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::ConstructL(...)" ) |
|
660 } |
|
661 |
|
662 |
|
663 // ----------------------------------------------------------------------------- |
|
664 // Check is file DRM protected. |
|
665 // |
|
666 // ----------------------------------------------------------------------------- |
|
667 // |
|
668 TBool CMusEngClipSession::IsProtectedFileL( const TDesC& aClipFile ) |
|
669 { |
|
670 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::IsProtectedFileL(...)" ) |
|
671 |
|
672 TBool isDRMProtected = EFalse; |
|
673 DRMCommon* drmapi = DRMCommon::NewL(); |
|
674 CleanupStack::PushL( drmapi ); |
|
675 |
|
676 User::LeaveIfError( drmapi->Connect() ); |
|
677 //Check DRM file protection |
|
678 User::LeaveIfError( drmapi->IsProtectedFile( aClipFile, isDRMProtected ) ); |
|
679 drmapi->Disconnect(); |
|
680 |
|
681 CleanupStack::PopAndDestroy( drmapi ); |
|
682 |
|
683 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::IsProtectedFileL(...)" ) |
|
684 return isDRMProtected; |
|
685 } |
|
686 |
|
687 |
|
688 // ----------------------------------------------------------------------------- |
|
689 // |
|
690 // ----------------------------------------------------------------------------- |
|
691 // |
250 void CMusEngClipSession::AddAmrCodecL( CMceAudioStream& aAudioStream ) |
692 void CMusEngClipSession::AddAmrCodecL( CMceAudioStream& aAudioStream ) |
251 { |
693 { |
252 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddAmrCodecL" ) |
694 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddAmrCodecL" ) |
253 |
695 |
254 // Remove old codecs |
696 // Remove old codecs |
|
697 |
255 while ( aAudioStream.Codecs().Count() > 0 ) |
698 while ( aAudioStream.Codecs().Count() > 0 ) |
256 { |
699 { |
257 aAudioStream.RemoveCodecL( *aAudioStream.Codecs()[0] ); |
700 aAudioStream.RemoveCodecL( *aAudioStream.Codecs()[0] ); |
258 } |
701 } |
259 |
702 |
260 // Create AMR codec instance |
703 // Create AMR codec instance |
|
704 |
261 const RPointerArray<const CMceAudioCodec>& supportedCodecs = |
705 const RPointerArray<const CMceAudioCodec>& supportedCodecs = |
262 iManager->SupportedAudioCodecs(); |
706 iManager->SupportedAudioCodecs(); |
263 |
707 |
264 CMceAudioCodec* amr = NULL; |
708 CMceAudioCodec* amr = NULL; |
265 |
709 |
266 for ( TInt i = 0; i < supportedCodecs.Count(); ++i ) |
710 for ( TInt i = 0; i < supportedCodecs.Count(); ++i ) |
267 { |
711 { |
268 if ( supportedCodecs[i]->SdpName() == KMceSDPNameAMR() ) |
712 if ( supportedCodecs[i]->SdpName() == KMceSDPNameAMR() ) |
269 { |
713 { |
270 amr = supportedCodecs[i]->CloneL(); |
714 amr = supportedCodecs[i]->CloneL(); |
271 CleanupStack::PushL( amr ); |
715 CleanupStack::PushL( amr ); |
272 User::LeaveIfError( |
716 |
273 amr->SetAllowedBitrates( KMusEngAllowedAmrBitrates ) ); |
717 User::LeaveIfError( |
|
718 amr->SetAllowedBitrates( KMusEngAllowedAmrBitrates ) ); |
274 User::LeaveIfError( amr->SetBitrate( KMusEngAmrBitRate ) ); |
719 User::LeaveIfError( amr->SetBitrate( KMusEngAmrBitRate ) ); |
275 aAudioStream.AddCodecL( amr ); |
720 aAudioStream.AddCodecL( amr ); |
|
721 |
276 CleanupStack::Pop( amr ); |
722 CleanupStack::Pop( amr ); |
277 break; // We must have only one codec |
723 break; // We must have only one codec |
278 } |
724 } |
279 } |
725 } |
280 |
726 |
281 __ASSERT_ALWAYS( amr, User::Leave( KErrNotFound ) ); |
727 __ASSERT_ALWAYS( amr, User::Leave( KErrNotFound ) ); |
282 |
728 |
283 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddAmrCodecL" ) |
729 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddAmrCodecL" ) |
284 } |
730 } |
285 |
731 |
|
732 |
286 // ----------------------------------------------------------------------------- |
733 // ----------------------------------------------------------------------------- |
287 // Create codec instance, H264 is used only if other end supports it for sure, |
734 // Create codec instance, H264 is used only if other end supports it for sure, |
288 // otherwise H263 is used. |
735 // otherwise H263 is used. |
289 // ----------------------------------------------------------------------------- |
736 // ----------------------------------------------------------------------------- |
290 // |
737 // |
291 void CMusEngClipSession::AddVideoCodecL( CMceVideoStream& aVideoStream ) |
738 void CMusEngClipSession::AddVideoCodecL( |
|
739 CMceVideoStream& aVideoStream, TBool aIgnoreNegotiated ) |
292 { |
740 { |
293 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddVideoCodecL" ) |
741 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::AddVideoCodecL" ) |
294 |
742 |
295 // Remove old codecs |
743 // Remove old codecs |
296 |
744 |
297 while ( aVideoStream.Codecs().Count() > 0 ) |
745 while ( aVideoStream.Codecs().Count() > 0 ) |
298 { |
746 { |
299 aVideoStream.RemoveCodecL( *aVideoStream.Codecs()[0] ); |
747 aVideoStream.RemoveCodecL( *aVideoStream.Codecs()[0] ); |
300 } |
748 } |
301 |
749 |
302 const RPointerArray< const CMceVideoCodec >& supportedCodecs = |
750 const RPointerArray<const CMceVideoCodec>& supportedCodecs = |
303 iManager->SupportedVideoCodecs(); |
751 iManager->SupportedVideoCodecs(); |
304 |
752 |
305 CMceVideoCodec* addedCodec = NULL; |
753 CMceVideoCodec* addedCodec = NULL; |
306 |
754 |
307 TPtrC8 addedCodecName = |
755 TPtrC8 addedCodecName = ( aIgnoreNegotiated || IsH264Supported() ) ? |
308 IsH264Supported() ? KMceSDPNameH264() : KMceSDPNameH2632000(); |
756 KMceSDPNameH264() : KMceSDPNameH2632000(); |
309 |
757 |
310 MUS_LOG_TDESC8( "mus: [ENGINE] adding codec : ", addedCodecName ); |
758 MUS_LOG_TDESC8( "mus: [ENGINE] adding codec : ", addedCodecName ); |
311 |
759 |
312 for ( TInt i = 0; i < supportedCodecs.Count(); ++i ) |
760 for ( TInt i = 0; i < supportedCodecs.Count(); ++i ) |
313 { |
761 { |
325 |
773 |
326 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddVideoCodecL" ) |
774 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::AddVideoCodecL" ) |
327 } |
775 } |
328 |
776 |
329 // ----------------------------------------------------------------------------- |
777 // ----------------------------------------------------------------------------- |
|
778 // |
|
779 // ----------------------------------------------------------------------------- |
|
780 // |
|
781 TBool CMusEngClipSession::HasClipEnded() |
|
782 { |
|
783 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::HasClipEnded()" ) |
|
784 |
|
785 TBool hasClipEnded = EFalse; |
|
786 |
|
787 if ( iSession ) |
|
788 { |
|
789 |
|
790 CMceVideoStream* videoOut = NULL; |
|
791 |
|
792 TRAPD( error, |
|
793 videoOut = MusEngMceUtils::GetVideoOutStreamL( *iSession ) ); |
|
794 if( error != KErrNone ) |
|
795 { |
|
796 MUS_LOG1( "mus: [ENGINE] Error in GetVideoOutStreamL #%d", error ) |
|
797 return hasClipEnded; |
|
798 } |
|
799 |
|
800 CMceFileSource* filesource = NULL; |
|
801 TRAP( error, filesource = MusEngMceUtils::GetFileSourceL( *iSession ) ) |
|
802 |
|
803 if ( error == KErrNone ) |
|
804 { |
|
805 TTimeIntervalMicroSeconds position; |
|
806 TTimeIntervalMicroSeconds duration; |
|
807 TRAP( error, position = filesource->PositionL() ); |
|
808 TRAPD( error1, duration = filesource->DurationL() ); |
|
809 if ( error != KErrNone || error1 != KErrNone ) |
|
810 { |
|
811 return hasClipEnded; |
|
812 } |
|
813 |
|
814 MUS_LOG2( "mus: [ENGINE] position = %Ld, duration = %Ld", |
|
815 position.Int64(), |
|
816 duration.Int64() ) |
|
817 |
|
818 TRAP( error, hasClipEnded = |
|
819 ( position.Int64() == 0 && |
|
820 !filesource->IsEnabled() && |
|
821 videoOut->State() == CMceMediaStream::EDisabled ) ) |
|
822 if( hasClipEnded ) |
|
823 { |
|
824 MUS_LOG( "mus: [ENGINE] End of clip" ) |
|
825 } |
|
826 } |
|
827 } |
|
828 |
|
829 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::HasClipEnded()" ) |
|
830 return hasClipEnded; |
|
831 } |
|
832 |
|
833 |
|
834 // ----------------------------------------------------------------------------- |
|
835 // |
|
836 // ----------------------------------------------------------------------------- |
|
837 // |
|
838 TTimeIntervalMicroSeconds CMusEngClipSession::PositionMicroSecondsL() |
|
839 { |
|
840 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
|
841 |
|
842 CMceFileSource* file = MusEngMceUtils::GetFileSourceL( *iSession ); |
|
843 |
|
844 TTimeIntervalMicroSeconds position = file->PositionL(); |
|
845 TTimeIntervalMicroSeconds duration = file->DurationL(); |
|
846 |
|
847 TTimeIntervalMicroSeconds calculatedPosition; |
|
848 |
|
849 // Adjust position if we are fastforwarding or -rewinding |
|
850 if ( iFFWDStartTime.Int64() != 0 ) |
|
851 { |
|
852 TTime now; |
|
853 now.HomeTime(); |
|
854 calculatedPosition = KFastWindingFactor * |
|
855 now.MicroSecondsFrom( iFFWDStartTime ).Int64() + |
|
856 position.Int64(); |
|
857 if ( calculatedPosition > duration ) |
|
858 { |
|
859 calculatedPosition = duration; |
|
860 } |
|
861 } |
|
862 else if ( iFRWDStartTime.Int64() != 0 ) |
|
863 { |
|
864 TTime now; |
|
865 now.HomeTime(); |
|
866 calculatedPosition = position.Int64() - |
|
867 KFastWindingFactor * |
|
868 now.MicroSecondsFrom( iFRWDStartTime ).Int64(); |
|
869 if ( calculatedPosition < 0 ) |
|
870 { |
|
871 calculatedPosition = 0; |
|
872 } |
|
873 |
|
874 if ( calculatedPosition == 0 ) |
|
875 { |
|
876 iRewindedToBeginning = ETrue; |
|
877 } |
|
878 } |
|
879 else |
|
880 { |
|
881 calculatedPosition = position; |
|
882 } |
|
883 |
|
884 return calculatedPosition; |
|
885 } |
|
886 |
|
887 |
|
888 // ----------------------------------------------------------------------------- |
330 // If member file contains audio, add appropriate amount of audio streams to |
889 // If member file contains audio, add appropriate amount of audio streams to |
331 // session structure |
890 // session structure |
332 // ----------------------------------------------------------------------------- |
891 // ----------------------------------------------------------------------------- |
333 // |
892 // |
334 void CMusEngClipSession::ConstructAudioStructureL( |
893 void CMusEngClipSession::ConstructAudioStructureL( |
335 CMceStreamBundle& aLocalBundle ) |
894 CMceStreamBundle& aLocalBundle ) |
336 { |
895 { |
337 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructAudioStructureL()" ) |
896 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::ConstructAudioStructureL()" ) |
338 |
897 |
339 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
898 __ASSERT_ALWAYS( iSession, User::Leave( KErrNotReady ) ); |
340 |
899 |
420 currentTime.MicroSecondsFrom( iBufferingStartedTime ); |
979 currentTime.MicroSecondsFrom( iBufferingStartedTime ); |
421 |
980 |
422 const TInt KMusMinimumBufferingPeriod( 500000 ); |
981 const TInt KMusMinimumBufferingPeriod( 500000 ); |
423 if ( bufferingPeriod > KMusMinimumBufferingPeriod ) |
982 if ( bufferingPeriod > KMusMinimumBufferingPeriod ) |
424 { |
983 { |
425 iClipVideoPlayer->SetBufferingPeriod( bufferingPeriod ); |
984 iBufferingPeriod = bufferingPeriod; |
426 } |
985 } |
427 |
986 |
428 MUS_LOG1( "mus: [ENGINE] current buffering period:%d", |
987 MUS_LOG1( "mus: [ENGINE] current buffering period:%d", |
429 bufferingPeriod.Int64() ) |
988 iBufferingPeriod.Int64() ) |
430 |
989 |
431 iBufferingStartedTime = 0; |
990 iBufferingStartedTime = 0; |
432 } |
991 } |
433 } |
992 } |
434 |
993 |
435 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::DetermineBufferingPeriod()" ) |
994 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::DetermineBufferingPeriod()" ) |
436 } |
995 } |
437 |
996 |
|
997 // ----------------------------------------------------------------------------- |
|
998 // |
|
999 // ----------------------------------------------------------------------------- |
|
1000 // |
|
1001 TBool CMusEngClipSession::IsH264Supported() const |
|
1002 { |
|
1003 return ( iVideoCodecList && iVideoCodecList->FindF( KMceSDPNameH264() ) >= 0 ); |
|
1004 } |
|
1005 |
|
1006 // ----------------------------------------------------------------------------- |
|
1007 // |
|
1008 // ----------------------------------------------------------------------------- |
|
1009 // |
|
1010 void CMusEngClipSession::HandleTranscodingFailureL( TInt aError ) |
|
1011 { |
|
1012 if ( aError == KErrNone ) |
|
1013 { |
|
1014 return; |
|
1015 } |
|
1016 |
|
1017 TRAP_IGNORE( DeleteTranscodingDestinationFileL() ) |
|
1018 |
|
1019 User::LeaveIfError( aError ); |
|
1020 } |
|
1021 |
|
1022 // ----------------------------------------------------------------------------- |
|
1023 // |
|
1024 // ----------------------------------------------------------------------------- |
|
1025 // |
|
1026 TInt CMusEngClipSession::DoCompleteTranscoding() |
|
1027 { |
|
1028 iTranscodingOngoing = EFalse; |
|
1029 |
|
1030 iClipSessionObserver.TranscodingCompletedInit(); |
|
1031 |
|
1032 TRAPD( error, EstablishSessionL() ) |
|
1033 iTranscodingRequiredDueMissingOptions = EFalse; |
|
1034 if ( error != KErrNone ) |
|
1035 { |
|
1036 iSessionObserver.SessionFailed(); |
|
1037 } |
|
1038 |
|
1039 // Next call does not return before session establishment |
|
1040 iClipSessionObserver.TranscodingCompletedFinalize(); |
|
1041 |
|
1042 return error; |
|
1043 } |
|
1044 |
|
1045 // ----------------------------------------------------------------------------- |
|
1046 // |
|
1047 // ----------------------------------------------------------------------------- |
|
1048 // |
|
1049 void CMusEngClipSession::DeleteTranscodingDestinationFileL() |
|
1050 { |
|
1051 RFs fs; |
|
1052 User::LeaveIfError( fs.Connect() ); |
|
1053 CleanupClosePushL( fs ); |
|
1054 |
|
1055 CFileMan* fileMan = CFileMan::NewL( fs ); |
|
1056 CleanupStack::PushL( fileMan ); |
|
1057 |
|
1058 MUS_LOG_TDESC8( "mus: [ENGINE] - deleting trascoding destination, filename", |
|
1059 iTranscodingDestFileName ) |
|
1060 TInt err = fileMan->Delete( iTranscodingDestFileName ); |
|
1061 MUS_LOG1( "mus: [ENGINE] - file delete result %d", err ) |
|
1062 |
|
1063 CleanupStack::PopAndDestroy( fileMan ); |
|
1064 CleanupStack::PopAndDestroy(); // fs |
|
1065 } |
|
1066 |
|
1067 // ----------------------------------------------------------------------------- |
|
1068 // |
|
1069 // ----------------------------------------------------------------------------- |
|
1070 // |
|
1071 TBool CMusEngClipSession::IsRewindFromEnd() |
|
1072 { |
|
1073 MUS_LOG( "mus: [ENGINE] -> CMusEngClipSession::IsRewindFromEnd()" ) |
|
1074 |
|
1075 TBool isRewindFromEnd = EFalse; |
|
1076 |
|
1077 if ( iSession ) |
|
1078 { |
|
1079 |
|
1080 CMceVideoStream* videoOut = NULL; |
|
1081 |
|
1082 TRAPD( error, |
|
1083 videoOut = MusEngMceUtils::GetVideoOutStreamL( *iSession ) ); |
|
1084 if( error != KErrNone ) |
|
1085 { |
|
1086 MUS_LOG1( "mus: [ENGINE] Error in GetVideoOutStreamL #%d", error ) |
|
1087 return isRewindFromEnd; |
|
1088 } |
|
1089 |
|
1090 CMceFileSource* filesource = NULL; |
|
1091 TRAP( error, filesource = MusEngMceUtils::GetFileSourceL( *iSession ) ) |
|
1092 |
|
1093 if ( error == KErrNone ) |
|
1094 { |
|
1095 TTimeIntervalMicroSeconds position; |
|
1096 TTimeIntervalMicroSeconds duration; |
|
1097 TRAP( error, position = filesource->PositionL() ); |
|
1098 TRAPD( error1, duration = filesource->DurationL() ); |
|
1099 if ( error != KErrNone || error1 != KErrNone ) |
|
1100 { |
|
1101 return isRewindFromEnd; |
|
1102 } |
|
1103 |
|
1104 MUS_LOG2( "mus: [ENGINE] position = %Ld, duration = %Ld", |
|
1105 position.Int64(), |
|
1106 duration.Int64() ) |
|
1107 |
|
1108 TRAP( error, isRewindFromEnd = |
|
1109 ( position.Int64() != 0 && |
|
1110 !filesource->IsEnabled() && |
|
1111 videoOut->State() == CMceMediaStream::EDisabled && |
|
1112 !iPause ) ) |
|
1113 if( isRewindFromEnd ) |
|
1114 { |
|
1115 MUS_LOG( "mus: [ENGINE] Rewind from end of clip" ) |
|
1116 } |
|
1117 } |
|
1118 } |
|
1119 |
|
1120 MUS_LOG( "mus: [ENGINE] <- CMusEngClipSession::IsRewindFromEnd()" ) |
|
1121 return isRewindFromEnd; |
|
1122 } |
438 // End of file |
1123 // End of file |
|
1124 |