|
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: S60 DataBuffer Data Source Plugin implementation |
|
15 * Version : %version: bh1mmcf#14.1.4 % |
|
16 * |
|
17 */ |
|
18 |
|
19 #include "DataBufferDataSource.h" |
|
20 #include <mmf/server/mmfdatabuffer.h> |
|
21 #include "DataBufferSourceCustomCommands.h" |
|
22 #include "SourceQueueItem.h" |
|
23 #include "SinkQueueItem.h" |
|
24 #include "DataCopyEngineAO.h" |
|
25 #include "DataBufferSourceUid.h" |
|
26 #include <MultimediaDataSourceEvents.h> |
|
27 #include "DRMConfigIntfcImpl.h" |
|
28 #include <mmfdatasink.h> |
|
29 #include <mmfdatapath.h> |
|
30 #include "tracemacros.h" |
|
31 |
|
32 const TUint KMaxHeapForBuffering = 0x40000; // 256 KB (1 MB = default controller heap size). |
|
33 |
|
34 CDataBufferSource* CDataBufferSource::NewL(TUid aType ) |
|
35 { |
|
36 EMC_TRACE1(_L("CDataBufferSource::NewL")); |
|
37 CDataBufferSource* self = new (ELeave) CDataBufferSource(aType); |
|
38 CleanupStack::PushL(self); |
|
39 self->ConstructL(); |
|
40 CleanupStack::Pop(self); |
|
41 return self; |
|
42 } |
|
43 |
|
44 CDataBufferSource::CDataBufferSource(TUid aType) |
|
45 : MDataSource(aType) |
|
46 { |
|
47 } |
|
48 |
|
49 CDataBufferSource::~CDataBufferSource(void) |
|
50 { |
|
51 } |
|
52 |
|
53 void CDataBufferSource::ConstructL (void) |
|
54 { |
|
55 } |
|
56 |
|
57 // From MDataSource begins |
|
58 TUid CDataBufferSource::DataSourceType() const |
|
59 { |
|
60 return KMmfDataBufferSource; |
|
61 } |
|
62 |
|
63 |
|
64 TFourCC CDataBufferSource::SourceDataTypeCode(TMediaId /*aMediaId*/ ) |
|
65 { |
|
66 TFourCC fourCC; |
|
67 iMultiMediaSource->GetDataTypeCode(fourCC); |
|
68 return fourCC; |
|
69 } |
|
70 |
|
71 TInt CDataBufferSource::SetSourceDataTypeCode(TFourCC aSourceFourCC, |
|
72 TMediaId /*aMediaId*/ ) |
|
73 { |
|
74 iMultiMediaSource->SetDataTypeCode(aSourceFourCC); |
|
75 return KErrNone; |
|
76 } |
|
77 |
|
78 void CDataBufferSource::FillBufferL(CMMFBuffer* aBuffer, |
|
79 MDataSink* aConsumer, |
|
80 TMediaId /*aMediaId*/ ) |
|
81 { |
|
82 User::LeaveIfError( iMultiMediaSource->ServiceFillBuffer( aBuffer, NULL, aConsumer ) ); |
|
83 } |
|
84 |
|
85 void CDataBufferSource::BufferEmptiedL(CMMFBuffer* /*aBuffer*/ ) |
|
86 { |
|
87 User::Leave(KErrUnknown); |
|
88 } |
|
89 |
|
90 TBool CDataBufferSource::CanCreateSourceBuffer() |
|
91 { |
|
92 return EFalse; |
|
93 } |
|
94 |
|
95 CMMFBuffer* CDataBufferSource::CreateSourceBufferL(TMediaId /*aMediaId*/, |
|
96 TBool &/*aReference*/ ) |
|
97 { |
|
98 /* CMMFBuffer* newBuffer = 0; //dummy |
|
99 return newBuffer; |
|
100 */ |
|
101 return NULL; |
|
102 } |
|
103 |
|
104 TInt CDataBufferSource::SourceThreadLogon( MAsyncEventHandler& /*aEventHandler*/ ) |
|
105 { |
|
106 return iMultiMediaSource->Open(); |
|
107 } |
|
108 |
|
109 void CDataBufferSource::SourceThreadLogoff() |
|
110 { |
|
111 iMultiMediaSource->Close(); |
|
112 } |
|
113 |
|
114 void CDataBufferSource::SourcePrimeL() |
|
115 { |
|
116 EMC_TRACE1(_L("CDataBufferSource::SourcePrimeL")); |
|
117 User::LeaveIfError(iMultiMediaSource->Prime()); |
|
118 } |
|
119 |
|
120 void CDataBufferSource::SourcePlayL() |
|
121 { |
|
122 EMC_TRACE1(_L("CDataBufferSource::SourcePlayL")); |
|
123 User::LeaveIfError(iMultiMediaSource->Play()); |
|
124 } |
|
125 |
|
126 void CDataBufferSource::SourceStopL() |
|
127 { |
|
128 EMC_TRACE1(_L("CDataBufferSource::SourceStopL")); |
|
129 User::LeaveIfError(iMultiMediaSource->Stop()); |
|
130 } |
|
131 |
|
132 |
|
133 void CDataBufferSource::ConstructSourceL(const TDesC8& /*aInitData*/ ) |
|
134 { |
|
135 } |
|
136 |
|
137 void CDataBufferSource::SourceCustomCommand(TMMFMessage& aMessage) |
|
138 { |
|
139 iMultiMediaSource->SourceCustomCommand(aMessage); |
|
140 } |
|
141 |
|
142 void CDataBufferSource::SetMultimediaSource(CDataBufferMultimediaSource& aMultimediaSource) |
|
143 { |
|
144 iMultiMediaSource = &aMultimediaSource; |
|
145 } |
|
146 // From MDataSource begins |
|
147 |
|
148 // From CMultimediaDataSource begins |
|
149 |
|
150 EXPORT_C CDataBufferMultimediaSource* CDataBufferMultimediaSource::NewL(MDataSource& aDataSource) |
|
151 { |
|
152 EMC_TRACE1(_L("CDataBufferMultimediaSource::NewL")); |
|
153 CDataBufferMultimediaSource* self = new (ELeave) CDataBufferMultimediaSource(aDataSource); |
|
154 CleanupStack::PushL(self); |
|
155 self->ConstructL(); |
|
156 CleanupStack::Pop(self); |
|
157 return self; |
|
158 } |
|
159 |
|
160 |
|
161 CDataBufferMultimediaSource::CDataBufferMultimediaSource(MDataSource& aDataSource) |
|
162 : iSrcItemsCount(0), |
|
163 iSnkItemsCount(0), |
|
164 iSrcBytes(0), |
|
165 iSnkBytes(0), |
|
166 iSizeBytes(0), |
|
167 iTransferRate(0), |
|
168 iBufferedDataSize(0), |
|
169 iLastBufferReceived(EFalse), |
|
170 iParentDataSource(&aDataSource) |
|
171 { |
|
172 // iState from Base |
|
173 iState = ECLOSED; |
|
174 iBufferingConfig.iType = TBufferingConfig::BUFFERINGNONE; |
|
175 iBufferingConfig.iAmount = 0; |
|
176 iMessage = NULL; |
|
177 } |
|
178 |
|
179 CDataBufferMultimediaSource::~CDataBufferMultimediaSource(void) |
|
180 { |
|
181 EMC_TRACE1(_L("CDataBufferMultimediaSource::~CDataBufferMultimediaSource")); |
|
182 |
|
183 // Cancel data copying |
|
184 if(iDataCopyEngineAO) |
|
185 { |
|
186 iDataCopyEngineAO->Cancel(); |
|
187 delete iDataCopyEngineAO; |
|
188 } |
|
189 |
|
190 iState = ECLOSED; |
|
191 // Empty source queue |
|
192 EmptySourceQueue(); |
|
193 delete iSourceQueue; |
|
194 EmptySinkQueue(); |
|
195 // Empty sink queue |
|
196 delete iSinkQueue; |
|
197 iAllowedOutputDeviceList.Close(); |
|
198 } |
|
199 |
|
200 void CDataBufferMultimediaSource::ConstructL (void) |
|
201 { |
|
202 static_cast<CDataBufferSource*>(iParentDataSource)->SetMultimediaSource(*this); |
|
203 iSourceQueue = new(ELeave) TSglQue<CSourceQueueItem>(_FOFF(CSourceQueueItem, iLink)); |
|
204 iSinkQueue = new(ELeave) TSglQue<CSinkQueueItem>(_FOFF(CSinkQueueItem, iLink)); |
|
205 iDataCopyEngineAO = CDataCopyEngineAO::NewL(iSourceQueue, iSinkQueue, *this); |
|
206 } |
|
207 |
|
208 |
|
209 TInt CDataBufferMultimediaSource::SetObserver( MMultimediaDataSourceObserver& aObserver ) |
|
210 { |
|
211 TInt status(KErrNotReady); |
|
212 switch ( iState ) |
|
213 { |
|
214 case ECLOSED: |
|
215 iObserver = &aObserver; |
|
216 status = KErrNone; |
|
217 break; |
|
218 case ESTOPPED: |
|
219 case EPRIMED: |
|
220 case EEXECUTING: |
|
221 case EBUFFERING: |
|
222 default: |
|
223 EMC_TRACE2(_L("CDataBufferMultimediaSource::SetObserver[Illegal cmd on state[%d]]"), iState ); |
|
224 break; |
|
225 }; |
|
226 return status; |
|
227 } |
|
228 |
|
229 TInt CDataBufferMultimediaSource::GetObserver( MMultimediaDataSourceObserver*& aObserver ) |
|
230 { |
|
231 aObserver = iObserver; |
|
232 return KErrNone; |
|
233 } |
|
234 |
|
235 void CDataBufferMultimediaSource::Event( TUid aEvent ) |
|
236 { |
|
237 if ( aEvent == KMultimediaDataSourceEventBitRateChanged ) |
|
238 { |
|
239 if(iMessage) |
|
240 { |
|
241 if(!iMessage->IsCompleted()) |
|
242 { |
|
243 iMessage->Complete(KErrNone); |
|
244 delete iMessage; |
|
245 iMessage = NULL; |
|
246 } |
|
247 } |
|
248 } |
|
249 } |
|
250 |
|
251 TInt CDataBufferMultimediaSource::SetDataTypeCode(TFourCC aSourceFourCC ) |
|
252 { |
|
253 TInt status(KErrNone); |
|
254 iSourceFourCC = aSourceFourCC; |
|
255 return status; |
|
256 } |
|
257 |
|
258 TInt CDataBufferMultimediaSource::GetDataTypeCode(TFourCC& aSourceFourCC ) |
|
259 { |
|
260 TInt status(KErrNone); |
|
261 aSourceFourCC = iSourceFourCC; |
|
262 return status; |
|
263 } |
|
264 |
|
265 TInt CDataBufferMultimediaSource::GetSize( TUint& aSize ) |
|
266 { |
|
267 TInt status(KErrNone); |
|
268 aSize = iSizeBytes; |
|
269 return status; |
|
270 } |
|
271 |
|
272 TInt CDataBufferMultimediaSource::Open() |
|
273 { |
|
274 TInt status(KErrNotReady); |
|
275 EMC_TRACE2(_L("CDataBufferSource::Open iState[%d]"),iState); |
|
276 switch ( iState ) |
|
277 { |
|
278 case ECLOSED: |
|
279 iState = ESTOPPED; |
|
280 status = KErrNone; |
|
281 break; |
|
282 case ESTOPPED: |
|
283 case EPRIMED: |
|
284 case EEXECUTING: |
|
285 case EBUFFERING: |
|
286 default: |
|
287 status = KErrNone; |
|
288 EMC_TRACE2(_L("CDataBufferMultimediaSource::Open[Illegal cmd on state[%d]]"), iState ); |
|
289 break; |
|
290 }; |
|
291 return status; |
|
292 } |
|
293 |
|
294 TInt CDataBufferMultimediaSource::Close() |
|
295 { |
|
296 TInt status(KErrNone); |
|
297 EMC_TRACE2(_L("CDataBufferSource::Close iState[%d]"),iState); |
|
298 iState = ECLOSED; |
|
299 // Clear app buffers |
|
300 EmptySinkQueue(); |
|
301 iSnkBytes = 0; |
|
302 // Clear observer buffers |
|
303 EmptySourceQueue(); |
|
304 iSrcBytes = 0; |
|
305 return status; |
|
306 } |
|
307 |
|
308 TInt CDataBufferMultimediaSource::Prime() |
|
309 { |
|
310 TInt status(KErrNotReady); |
|
311 EMC_TRACE2(_L("CDataBufferSource::Prime iState[%d]"),iState); |
|
312 switch ( iState ) |
|
313 { |
|
314 case ESTOPPED: |
|
315 iState = EPRIMED; |
|
316 status = KErrNone; |
|
317 break; |
|
318 case EPRIMED: |
|
319 // Clear observer buffers |
|
320 EmptySinkQueue(); |
|
321 iSnkBytes = 0; |
|
322 status = KErrNone; |
|
323 break; |
|
324 case ECLOSED: |
|
325 case EEXECUTING: |
|
326 case EBUFFERING: |
|
327 default: |
|
328 EMC_TRACE2(_L("CDataBufferMultimediaSource::Prime[Illegal cmd on state[%d]]"), iState ); |
|
329 break; |
|
330 }; |
|
331 return status; |
|
332 } |
|
333 |
|
334 TInt CDataBufferMultimediaSource::Play() |
|
335 { |
|
336 TInt status(KErrNotReady); |
|
337 EMC_TRACE2(_L("CDataBufferSource::Play iState[%d]"),iState); |
|
338 switch ( iState ) |
|
339 { |
|
340 case EPRIMED: |
|
341 iState = EEXECUTING; |
|
342 iDataCopyEngineAO->Start(); |
|
343 status = KErrNone; |
|
344 break; |
|
345 case EEXECUTING: |
|
346 case EBUFFERING: |
|
347 // No op |
|
348 status = KErrNone; |
|
349 break; |
|
350 case ECLOSED: |
|
351 case ESTOPPED: |
|
352 default: |
|
353 EMC_TRACE2(_L("CDataBufferMultimediaSource::Play[Illegal cmd on state[%d]]"), iState ); |
|
354 break; |
|
355 }; |
|
356 return status; |
|
357 } |
|
358 |
|
359 TInt CDataBufferMultimediaSource::Stop() |
|
360 { |
|
361 TInt status(KErrNotReady); |
|
362 EMC_TRACE2(_L("CDataBufferSource::Stop iState[%d]"),iState); |
|
363 switch ( iState ) |
|
364 { |
|
365 case EPRIMED: |
|
366 case EEXECUTING: |
|
367 case EBUFFERING: |
|
368 iState = ESTOPPED; |
|
369 |
|
370 // Stop data copy engine |
|
371 iDataCopyEngineAO->Stop(); |
|
372 |
|
373 // Clear observer buffers |
|
374 status = EmptySourceQueue(); |
|
375 iSrcBytes = 0; |
|
376 iLastBufferReceived = EFalse; |
|
377 |
|
378 // Clear app buffers |
|
379 status = EmptySinkQueue(); |
|
380 iSnkBytes = 0; |
|
381 |
|
382 status = KErrNone; |
|
383 break; |
|
384 case ESTOPPED: |
|
385 |
|
386 // Stop data copy engine |
|
387 iDataCopyEngineAO->Stop(); |
|
388 |
|
389 // Clear user buffers |
|
390 status = EmptySourceQueue(); |
|
391 iSrcBytes = 0; |
|
392 iLastBufferReceived = EFalse; |
|
393 break; |
|
394 case ECLOSED: |
|
395 default: |
|
396 EMC_TRACE2(_L("CDataBufferMultimediaSource::Stop[Illegal cmd on state[%d]]"), iState ); |
|
397 break; |
|
398 }; |
|
399 return status; |
|
400 } |
|
401 |
|
402 TInt CDataBufferMultimediaSource::FillBuffer( CMMFBuffer* aBuffer ) |
|
403 { |
|
404 return ServiceFillBuffer( aBuffer, iObserver, NULL ); |
|
405 } |
|
406 |
|
407 TInt CDataBufferMultimediaSource::GetInterface( |
|
408 TUid aInterfaceId, |
|
409 TVersion& aVer, |
|
410 TAny*& aInterfaceImpl ) |
|
411 { |
|
412 TInt status(KErrNotFound); |
|
413 aInterfaceImpl = NULL; |
|
414 if ( ( aInterfaceId == KDRMConfigIntfc ) && |
|
415 ( ( aVer.iMajor == KDRMConfigIntfcMajorVer1 ) && |
|
416 ( aVer.iMinor == KDRMConfigIntfcMinorVer1 ) && |
|
417 ( aVer.iBuild == KDRMConfigIntfcBuildVer1 ) ) ) |
|
418 { |
|
419 CDRMConfigIntcfImpl* temp(NULL); |
|
420 TRAP(status, temp = CDRMConfigIntcfImpl::NewL(*this)); |
|
421 if ( status == KErrNone ) |
|
422 { |
|
423 this->SetChild(*((CChildIntfc*)temp)); |
|
424 temp->SetParent(*(CParentIntfc*)this); |
|
425 aInterfaceImpl = (CDRMConfigIntfc*)temp; |
|
426 } |
|
427 } |
|
428 return status; |
|
429 } |
|
430 |
|
431 TAny* CDataBufferMultimediaSource::CustomInterface( TUid /*aInterfaceUid*/ ) |
|
432 { |
|
433 return NULL; |
|
434 } |
|
435 |
|
436 |
|
437 // From CMultimediaDataSource ends |
|
438 |
|
439 // From MDataCopyEngineObserver begins |
|
440 void CDataBufferMultimediaSource::SourceQueueItemProcessed() |
|
441 { |
|
442 iSrcItemsCount--; |
|
443 EMC_TRACE2(_L("CDataBufferMultimediaSource::SourceQueueItemProcessed[SrcItemsCount(%d)]"), iSrcItemsCount); |
|
444 |
|
445 CSourceQueueItem* srcItem = iSourceQueue->First(); |
|
446 iSourceQueue->Remove(*srcItem); |
|
447 srcItem->CompleteMessage(KErrNone); |
|
448 delete srcItem; |
|
449 } |
|
450 |
|
451 void CDataBufferMultimediaSource::SinkQueueItemProcessed() |
|
452 { |
|
453 iSnkItemsCount--; |
|
454 |
|
455 CSinkQueueItem* item = iSinkQueue->First(); |
|
456 iSinkQueue->Remove(*item); |
|
457 iSnkBytes += item->Buffer()->Data().Length(); |
|
458 EMC_TRACE3(_L("CDataBufferMultimediaSource::SinkQueueItemProcessed[Src[%d]B. Snk[%d]B]"), iSrcBytes, iSnkBytes); |
|
459 |
|
460 // If this is the last buffer being sent to the controller |
|
461 // empty the rest of the items in the sink queue |
|
462 if ( item->Buffer()->LastBuffer() ) |
|
463 { |
|
464 EMC_TRACE1(_L("CDataBufferMultimediaSource::SinkQueueItemProcessed[LASTBUFFER]")); |
|
465 CSinkQueueItem* tempItem; |
|
466 while ( !iSinkQueue->IsEmpty() ) |
|
467 { |
|
468 tempItem = iSinkQueue->First(); |
|
469 iSinkQueue->Remove(*tempItem); |
|
470 delete tempItem; |
|
471 iSnkItemsCount--; |
|
472 } |
|
473 iSnkBytes = 0; |
|
474 |
|
475 iState = ESTOPPED; |
|
476 iSrcBytes = 0; |
|
477 } |
|
478 // Signal the controller, based on which FillBuffer API was called, |
|
479 // make the appriopriate callback. |
|
480 if ( item->Observer() ) |
|
481 { |
|
482 item->Observer()->BufferFilled(item->Buffer()); |
|
483 } |
|
484 else |
|
485 { |
|
486 TRAP_IGNORE(item->Consumer()->BufferFilledL(item->Buffer())); |
|
487 } |
|
488 delete item; |
|
489 } |
|
490 // From MDataCopyEngineObserver ends |
|
491 |
|
492 // To be called by DRMConfig Interface begins |
|
493 TInt CDataBufferMultimediaSource::GetDRMType( TDRMType& aDRMType ) |
|
494 { |
|
495 TInt status(KErrNotReady); |
|
496 switch ( iState ) |
|
497 { |
|
498 case EPRIMED: |
|
499 case EEXECUTING: |
|
500 case EBUFFERING: |
|
501 aDRMType = iDRMType; |
|
502 status = KErrNone; |
|
503 break; |
|
504 case ECLOSED: |
|
505 case ESTOPPED: |
|
506 default: |
|
507 EMC_TRACE2(_L("CDataBufferMultimediaSource::GetDRMType[Illegal cmd on state[%d]]"), iState ); |
|
508 break; |
|
509 }; |
|
510 return status; |
|
511 } |
|
512 |
|
513 TInt CDataBufferMultimediaSource::GetAllowedOutputDeviceCount( TInt& aCount ) |
|
514 { |
|
515 TInt status(KErrNotReady); |
|
516 switch ( iState ) |
|
517 { |
|
518 case EPRIMED: |
|
519 case EEXECUTING: |
|
520 case EBUFFERING: |
|
521 aCount = iAllowedOutputDeviceList.Count(); |
|
522 status = KErrNone; |
|
523 break; |
|
524 case ECLOSED: |
|
525 case ESTOPPED: |
|
526 default: |
|
527 EMC_TRACE2(_L("CDataBufferMultimediaSource::GetDRMType[Illegal cmd on state[%d]]"), iState ); |
|
528 break; |
|
529 }; |
|
530 return status; |
|
531 } |
|
532 |
|
533 TInt CDataBufferMultimediaSource::GetAllowedOutputDevice( |
|
534 TInt aIndex, |
|
535 TDRMAllowedOutputDevice& aOutputDevice ) |
|
536 { |
|
537 TInt status(KErrNotReady); |
|
538 switch ( iState ) |
|
539 { |
|
540 case EPRIMED: |
|
541 case EEXECUTING: |
|
542 case EBUFFERING: |
|
543 status = KErrArgument; |
|
544 if ( (0 <= aIndex ) && ( aIndex < iAllowedOutputDeviceList.Count() ) ) |
|
545 { |
|
546 aOutputDevice = iAllowedOutputDeviceList[aIndex]; |
|
547 status = KErrNone; |
|
548 } |
|
549 break; |
|
550 case ECLOSED: |
|
551 case ESTOPPED: |
|
552 default: |
|
553 EMC_TRACE2(_L("CDataBufferMultimediaSource::GetDRMType[Illegal cmd on state[%d]]"), iState ); |
|
554 break; |
|
555 }; |
|
556 return status; |
|
557 } |
|
558 // To be called by DRMConfig Interface ends |
|
559 |
|
560 void CDataBufferMultimediaSource::SourceCustomCommand(TMMFMessage& aMessage) |
|
561 { |
|
562 TInt err(KErrNone); |
|
563 EMC_TRACE1(_L("CDataBufferMultimediaSource::SourceCustomCommand ")); |
|
564 switch ( aMessage.Function() ) |
|
565 { |
|
566 case EProcessBuffer: |
|
567 { |
|
568 CSourceQueueItem* item = NULL; |
|
569 TRAPD(err, item = CSourceQueueItem::NewL(aMessage)); |
|
570 if (err == KErrNone) |
|
571 { |
|
572 iSourceQueue->AddLast(*item); |
|
573 iSrcItemsCount++; |
|
574 iSrcBytes += item->DataSize(); |
|
575 EMC_TRACE6(_L("EProcessBuffer>State[%d] Src[%d]B Snk[%d]B] LB[%d] SeqNum[%d]"), \ |
|
576 iState, iSrcBytes, iSnkBytes, item->IsLastBuffer(), item->GetBufferSequenceNumber()); |
|
577 |
|
578 iLastBufferReceived = item->IsLastBuffer(); |
|
579 |
|
580 // If we are in EBUFFERING state, check if source can transition |
|
581 // to EEXECUTING state |
|
582 if ( ( iState == EBUFFERING ) && |
|
583 ( ( ( iSrcBytes - iSnkBytes ) >= iBufferedDataSize ) || ( iLastBufferReceived ) ) ) |
|
584 { |
|
585 iState = EEXECUTING; |
|
586 // Signal to start copy AO |
|
587 iDataCopyEngineAO->Start(); |
|
588 } |
|
589 else |
|
590 { |
|
591 iDataCopyEngineAO->SourceQueueChanged(); |
|
592 } |
|
593 |
|
594 } |
|
595 } |
|
596 break; |
|
597 |
|
598 case ECancel: |
|
599 { |
|
600 EMC_TRACE1(_L("EProcessBuffer>Cancel")); |
|
601 err = DoHandleCancel( aMessage ); |
|
602 } |
|
603 break; |
|
604 |
|
605 case ESetSize: |
|
606 { |
|
607 // Read size info |
|
608 TPckgBuf<TInt> sizePckg; |
|
609 err = aMessage.ReadData1FromClient(sizePckg); |
|
610 if ( err == KErrNone ) |
|
611 { |
|
612 iSizeBytes = sizePckg(); |
|
613 EMC_TRACE2(_L("ESetSize>SizeSet[%d] Bytes"), iSizeBytes); |
|
614 // The message is handled completely. |
|
615 aMessage.Complete(KErrNone); |
|
616 |
|
617 // Signal the observer that there is a new size changed event. |
|
618 if ( iObserver ) |
|
619 { |
|
620 iObserver->Event(KMultimediaDataSourceObserverEventSourceSizeChanged); |
|
621 } |
|
622 } |
|
623 // If we are in EBUFFERING state, re-calculate iBufferedDataSize, |
|
624 // check if source can transition to EEXECUTING state |
|
625 } |
|
626 break; |
|
627 |
|
628 case EGetCurrentBufferingConfig : |
|
629 { |
|
630 TPckgBuf<TBufferingConfig> sizePckg; |
|
631 EMC_TRACE3(_L("EGetCurrentBufferingConfig>BufType[%d] BufAmt[%d]Bytes"), \ |
|
632 iBufferingConfig.iType, iBufferingConfig.iAmount); |
|
633 sizePckg() = iBufferingConfig ; |
|
634 aMessage.WriteDataToClient(sizePckg); |
|
635 aMessage.Complete(KErrNone); |
|
636 } |
|
637 break; |
|
638 |
|
639 case ESetBufferingConfig: |
|
640 { |
|
641 // Read size info |
|
642 TPckgBuf<TBufferingConfig> sizePckg; |
|
643 err = aMessage.ReadData1FromClient(sizePckg); |
|
644 if ( err == KErrNone ) |
|
645 { |
|
646 iBufferingConfig = sizePckg(); |
|
647 EMC_TRACE3(_L("ESetBufferingConfig>BufType[%d] BufAmt[%d]Bytes"), \ |
|
648 iBufferingConfig.iType, iBufferingConfig.iAmount); |
|
649 // The message is handled completely. |
|
650 aMessage.Complete(KErrNone); |
|
651 } |
|
652 } |
|
653 break; |
|
654 |
|
655 case EGetBitRate: |
|
656 { |
|
657 TPckgBuf<TUint> bitRatePckg; |
|
658 EMC_TRACE2(_L("EGetBitRate>[%d]"), iObserverBitRate); |
|
659 bitRatePckg() = iObserverBitRate ; |
|
660 aMessage.WriteDataToClient(bitRatePckg); |
|
661 aMessage.Complete(KErrNone); |
|
662 } |
|
663 break; |
|
664 |
|
665 case EGetBufferingConfigSupported: |
|
666 { |
|
667 if(iObserverBitRate) |
|
668 { |
|
669 aMessage.Complete(KErrNone); |
|
670 } |
|
671 else |
|
672 { |
|
673 iMessage = new(ELeave) TMMFMessage(aMessage); |
|
674 } |
|
675 } |
|
676 break; |
|
677 |
|
678 case ESetDRMConfig: |
|
679 // Need to complete the message in this function |
|
680 // and return KErrNone |
|
681 err = HandleSetDRMConfig(aMessage); |
|
682 break; |
|
683 default: |
|
684 err = KErrArgument; |
|
685 break; |
|
686 }; |
|
687 |
|
688 // If any error |
|
689 if (err != KErrNone) |
|
690 { |
|
691 EMC_TRACE2(_L("CDataBufferMultimediaSource::SourceCustomCommand:Completing message with error[%d]"), err); |
|
692 aMessage.Complete(err); |
|
693 } |
|
694 } |
|
695 |
|
696 |
|
697 TInt CDataBufferMultimediaSource::ServiceFillBuffer( CMMFBuffer* aBuffer, |
|
698 MMultimediaDataSourceObserver* aObserver, |
|
699 MDataSink* aConsumer ) |
|
700 { |
|
701 TInt status(KErrNotReady); |
|
702 switch ( iState ) |
|
703 { |
|
704 case EPRIMED: |
|
705 case EBUFFERING: |
|
706 { |
|
707 status = AppendBufferToSinkQueue( aBuffer, aObserver, aConsumer ); |
|
708 } |
|
709 break; |
|
710 case EEXECUTING: |
|
711 { |
|
712 status = AppendBufferToSinkQueue( aBuffer, aObserver, aConsumer ); |
|
713 |
|
714 if ( status == KErrNone ) |
|
715 { |
|
716 // If not enough data, determine buffered data size, pause |
|
717 // data copy engine AO and move to EBUFFERING state. |
|
718 if ( !iLastBufferReceived && ( ( iSrcBytes - iSnkBytes ) < ( aBuffer->RequestSize() ) ) ) |
|
719 { |
|
720 CalculateBufferdDataSize(); |
|
721 |
|
722 if(iBufferedDataSize > 0) |
|
723 { |
|
724 iDataCopyEngineAO->Pause(); |
|
725 iState = EBUFFERING; |
|
726 } |
|
727 else |
|
728 { |
|
729 iDataCopyEngineAO->SinkQueueChanged(); |
|
730 } |
|
731 } |
|
732 else |
|
733 { |
|
734 iDataCopyEngineAO->SinkQueueChanged(); |
|
735 } |
|
736 } |
|
737 } |
|
738 break; |
|
739 |
|
740 case ECLOSED: |
|
741 case ESTOPPED: |
|
742 status = KErrNone; |
|
743 break; |
|
744 default: |
|
745 EMC_TRACE2(_L("CDataBufferMultimediaSource::ServiceFillBuffer[Illegal cmd on state[%d]]"), iState ); |
|
746 break; |
|
747 }; |
|
748 return status; |
|
749 } |
|
750 |
|
751 TInt CDataBufferMultimediaSource::AppendBufferToSinkQueue( CMMFBuffer* aBuffer, |
|
752 MMultimediaDataSourceObserver* aObserver, |
|
753 MDataSink* aConsumer ) |
|
754 { |
|
755 TInt status(KErrNone); |
|
756 // Add observer buffer to queue |
|
757 CMMFDataBuffer* dest = static_cast<CMMFDataBuffer*>( aBuffer ); |
|
758 TDes8& destBufferDes = dest->Data(); |
|
759 |
|
760 CSinkQueueItem* request(NULL); |
|
761 |
|
762 TRAP( status, request = CSinkQueueItem::NewL( aBuffer, aObserver, aConsumer ) ); |
|
763 if ( status == KErrNone ) |
|
764 { |
|
765 iSinkQueue->AddLast(*request); |
|
766 iSnkItemsCount++; |
|
767 |
|
768 EMC_TRACE5(_L("CDataBufferMultimediaSource::AppendBufferToQueue[ReqSize[%d]SrcItems[%d]SnkItems[%d]]Avail[%d]B"), \ |
|
769 aBuffer->RequestSize(), iSrcItemsCount, iSnkItemsCount, (iSrcBytes - iSnkBytes) ); |
|
770 } |
|
771 return status; |
|
772 } |
|
773 |
|
774 TInt CDataBufferMultimediaSource::EmptySourceQueue() |
|
775 { |
|
776 TInt status(KErrNone); |
|
777 // Complete and empty source queue |
|
778 EMC_TRACE2(_L("CDataBufferSource::EmptySourceQueue() iState[%d]"),iState); |
|
779 CSourceQueueItem* srcItem; |
|
780 while ( !iSourceQueue->IsEmpty() ) |
|
781 { |
|
782 srcItem = iSourceQueue->First(); |
|
783 iSourceQueue->Remove(*srcItem); |
|
784 srcItem->CompleteMessage(KErrCancel); |
|
785 delete srcItem; |
|
786 } |
|
787 iSrcItemsCount = 0; |
|
788 return status; |
|
789 } |
|
790 |
|
791 TInt CDataBufferMultimediaSource::EmptySinkQueue() |
|
792 { |
|
793 TInt status(KErrNone); |
|
794 // Empty sink queue |
|
795 EMC_TRACE2(_L("CDataBufferSource::EmptySinkQueue() iState[%d]"),iState); |
|
796 CSinkQueueItem* snkItem; |
|
797 while ( !iSinkQueue->IsEmpty() ) |
|
798 { |
|
799 snkItem = iSinkQueue->First(); |
|
800 iSinkQueue->Remove(*snkItem); |
|
801 delete snkItem; |
|
802 } |
|
803 |
|
804 iSnkItemsCount = 0; |
|
805 return status; |
|
806 } |
|
807 |
|
808 void CDataBufferMultimediaSource::CalculateBufferdDataSize() |
|
809 { |
|
810 iBufferedDataSize = 0; |
|
811 EMC_TRACE2(_L("CDataBufferSource::CalculateBufferdDataSize() iState[%d]"),iState); |
|
812 // Get the bit rate from observer |
|
813 iObserver->GetBitRate( iObserverBitRate ); |
|
814 |
|
815 // If we don't know observer bit rate |
|
816 if ((iObserverBitRate == 0 ) && (!iSinkQueue->First()) ) |
|
817 {// Just buffer until the observer buffer can be filled |
|
818 iBufferedDataSize = iSinkQueue->First()->Buffer()->RequestSize(); |
|
819 } |
|
820 else |
|
821 { |
|
822 if(iBufferingConfig.iType == TBufferingConfig::BUFFERINGNONE) |
|
823 { |
|
824 iBufferedDataSize = 0; |
|
825 } |
|
826 else if ( iBufferingConfig.iType == TBufferingConfig::FIXEDSIZE) |
|
827 { |
|
828 iBufferedDataSize = iBufferingConfig.iAmount; |
|
829 } |
|
830 else |
|
831 { |
|
832 iBufferedDataSize = (iBufferingConfig.iAmount * iObserverBitRate) / 8; |
|
833 } |
|
834 } |
|
835 |
|
836 // In case of streaming make sure this doesn't exceed the heap memory |
|
837 iBufferedDataSize = iBufferedDataSize > KMaxHeapForBuffering ? KMaxHeapForBuffering : iBufferedDataSize; |
|
838 EMC_TRACE2(_L("CDataBufferMultimediaSource::CalculateBufferdDataSize[%d]"), iBufferedDataSize ); |
|
839 } |
|
840 |
|
841 TInt CDataBufferMultimediaSource::HandleSetDRMConfig( TMMFMessage& aMessage ) |
|
842 { |
|
843 TInt status(KErrNone); |
|
844 TRAP(status, DoSetDRMConfigL( aMessage )); |
|
845 EMC_TRACE2(_L("CDataBufferMultimediaSource::HandleSetDRMConfig[%d]"), status ); |
|
846 aMessage.Complete(status); |
|
847 return status; |
|
848 } |
|
849 |
|
850 void CDataBufferMultimediaSource::DoSetDRMConfigL( TMMFMessage& aMessage ) |
|
851 { |
|
852 switch ( iState ) |
|
853 { |
|
854 case ECLOSED: |
|
855 case ESTOPPED: |
|
856 { |
|
857 // Create buffer to hold data |
|
858 HBufC8* buf = HBufC8::NewLC( aMessage.SizeOfData1FromClient() ); |
|
859 TPtr8 ptr = buf->Des(); |
|
860 |
|
861 // Read data from client. |
|
862 aMessage.ReadData1FromClientL( ptr ); |
|
863 |
|
864 RDesReadStream stream(ptr); |
|
865 CleanupClosePushL(stream); |
|
866 |
|
867 // Get DRM Type |
|
868 iDRMType = (TDRMType)stream.ReadInt32L(); |
|
869 // Get Allowed Output Device Count |
|
870 TInt count = stream.ReadInt32L(); |
|
871 // Get Allowed Output Device items |
|
872 iAllowedOutputDeviceList.Reset(); // If any |
|
873 for (TInt i=0; i<count; i++) |
|
874 { |
|
875 iAllowedOutputDeviceList.Append((TDRMAllowedOutputDevice)stream.ReadInt32L()); |
|
876 } |
|
877 CleanupStack::PopAndDestroy(&stream); |
|
878 CleanupStack::PopAndDestroy(buf); |
|
879 } |
|
880 break; |
|
881 |
|
882 case EPRIMED: |
|
883 case EEXECUTING: |
|
884 case EBUFFERING: |
|
885 default: |
|
886 EMC_TRACE2(_L("CDataBufferMultimediaSource::DoSetDRMConfigL[Illegal cmd on state[%d]]"), iState ); |
|
887 User::Leave(KErrNotReady); |
|
888 break; |
|
889 }; |
|
890 } |
|
891 |
|
892 TInt CDataBufferMultimediaSource::DoHandleCancel( TMMFMessage& aMessage ) |
|
893 { |
|
894 TInt status(KErrNone); |
|
895 TPckgBuf<TUint> bufSeqPckg; |
|
896 status = aMessage.ReadData1FromClient(bufSeqPckg); |
|
897 if ( status == KErrNone ) |
|
898 { |
|
899 CSourceQueueItem* item (NULL); |
|
900 TSglQueIter<CSourceQueueItem> itemIter(*iSourceQueue); |
|
901 while ( (item = itemIter++) != NULL ) |
|
902 { |
|
903 if ( item->GetBufferSequenceNumber() == bufSeqPckg() ) |
|
904 { // We found what we are looking for |
|
905 break; // from while ( item != NULL ) |
|
906 } |
|
907 } |
|
908 // If we have the item we are looking for |
|
909 if ( item != NULL ) |
|
910 { |
|
911 aMessage.Complete( KErrNone ); |
|
912 iSourceQueue->Remove(*item); |
|
913 item->CompleteMessage(KErrCancel); |
|
914 delete item; |
|
915 } |
|
916 else |
|
917 { |
|
918 aMessage.Complete( KErrNotFound ); |
|
919 } |
|
920 } |
|
921 return status; |
|
922 } |
|
923 |
|
924 TInt CDataBufferMultimediaSource::EvaluateIntent( ContentAccess::TIntent /*aIntent*/ ) |
|
925 { |
|
926 return KErrNone; |
|
927 } |
|
928 |
|
929 TInt CDataBufferMultimediaSource::ExecuteIntent( ContentAccess::TIntent /*aIntent*/ ) |
|
930 { |
|
931 return KErrNone; |
|
932 } |
|
933 |
|
934 // End of file |