|
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: TNE server |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include"HXTneserver.h" |
|
21 #include"HXTneclientservercommon.h" |
|
22 #include <flogger.h> |
|
23 #include <f32file64.h> |
|
24 static const TInt kDefaultStack = 0x4000; |
|
25 |
|
26 |
|
27 |
|
28 // PRINT macro |
|
29 #ifdef _DEBUG |
|
30 #include <e32svr.h> |
|
31 #define PRINT(x) RDebug::Print x |
|
32 #else |
|
33 #define PRINT(x) |
|
34 #endif |
|
35 |
|
36 #ifdef _DEBUG |
|
37 #define ENABLE_S60_TNE_LOGGING 1 |
|
38 #endif |
|
39 |
|
40 //implementation |
|
41 #ifdef ENABLE_S60_TNE_LOGGING |
|
42 #define FLOG FileLog |
|
43 inline static void FileLog(TRefByValue<const TDesC16> aFmt,...) |
|
44 { |
|
45 VA_LIST args; |
|
46 VA_START (args, aFmt); |
|
47 RFileLogger::WriteFormat(_L("tne"), _L("S60tne.log"), |
|
48 EFileLoggingModeAppend, aFmt, args); |
|
49 } |
|
50 |
|
51 #else // logging is disabled |
|
52 #define FLOG LogFNull |
|
53 inline static void LogFNull(TRefByValue<const TDesC16> aFmt,...){} |
|
54 |
|
55 #endif // enable logging |
|
56 |
|
57 |
|
58 |
|
59 |
|
60 const TInt KMaxPacketToDecode = 32; |
|
61 |
|
62 //////////////Server/////////////// |
|
63 |
|
64 |
|
65 CTneServer::CTneServer(CActive::TPriority aActiveObjectPriority) |
|
66 : CServer2(aActiveObjectPriority) |
|
67 { |
|
68 } |
|
69 |
|
70 |
|
71 |
|
72 CSession2* CTneServer::NewSessionL(const TVersion& /* aVersion */,const RMessage2& |
|
73 /*aMessage*/) const |
|
74 |
|
75 { |
|
76 return new (ELeave) CTneSession; |
|
77 } |
|
78 |
|
79 |
|
80 |
|
81 GLDEF_C TInt CTneServer::ThreadFunction(TAny* aName) |
|
82 { |
|
83 HBufC *pServerName = (HBufC *) aName; |
|
84 CTrapCleanup* cleanup = NULL; |
|
85 CActiveScheduler *pA = NULL; |
|
86 CTneServer *pS = NULL; |
|
87 TInt err = KErrNoMemory; |
|
88 |
|
89 FLOG(_L("CTneServer::ThreadFunction ServerName=%S"), pServerName); |
|
90 // get clean-up stack |
|
91 if (pServerName) |
|
92 { |
|
93 cleanup =CTrapCleanup::New(); |
|
94 pA = new CActiveScheduler; |
|
95 pS = new CTneServer(EPriorityStandard); |
|
96 |
|
97 } |
|
98 |
|
99 |
|
100 if (cleanup && pA && pS ) |
|
101 { |
|
102 // OK |
|
103 CActiveScheduler::Install(pA); |
|
104 // Start the server |
|
105 err = pS->Start(*pServerName); |
|
106 } |
|
107 |
|
108 RThread::Rendezvous(err); |
|
109 |
|
110 CActiveScheduler::Start(); |
|
111 |
|
112 // Tidy up... |
|
113 delete pS; |
|
114 delete pA; |
|
115 delete cleanup; |
|
116 |
|
117 |
|
118 return(err); |
|
119 } |
|
120 |
|
121 |
|
122 //global function |
|
123 |
|
124 TInt StartThread(RThread& aServerThread, HBufC *pServerName) |
|
125 { |
|
126 TInt res=KErrNone; |
|
127 |
|
128 |
|
129 res=aServerThread.Create(*pServerName, |
|
130 CTneServer::ThreadFunction, |
|
131 kDefaultStack, &User::Heap(), |
|
132 (TAny *)pServerName ); |
|
133 |
|
134 // The thread has been created OK so get it started - however |
|
135 // we need to make sure that it has started before we continue. |
|
136 if (res==KErrNone) |
|
137 { |
|
138 TRequestStatus rendezvousStatus; |
|
139 |
|
140 aServerThread.SetPriority(EPriorityNormal); |
|
141 aServerThread.Rendezvous(rendezvousStatus); |
|
142 aServerThread.Resume(); |
|
143 User::WaitForRequest(rendezvousStatus); |
|
144 res = rendezvousStatus.Int(); |
|
145 } |
|
146 |
|
147 // The thread has not been created - clearly there's been a problem. |
|
148 else |
|
149 { |
|
150 aServerThread.Close(); |
|
151 } |
|
152 |
|
153 return res; |
|
154 } |
|
155 |
|
156 |
|
157 |
|
158 |
|
159 |
|
160 ////////////////////////ServerSession////////////////////////////// |
|
161 |
|
162 |
|
163 CTneSession::CTneSession(): |
|
164 iWidth(0), |
|
165 iHeight(0) , |
|
166 iDuration(0) , |
|
167 iFrameCount(0) , |
|
168 m_LastError(KErrNone), |
|
169 m_uPacketsReceived(0) , |
|
170 m_bDone(EFalse), |
|
171 iFs(NULL), |
|
172 iYUVBuffer(NULL), |
|
173 iClientYUVBufferPtrPtr(NULL), |
|
174 m_bOpenFileLPending(EFalse), |
|
175 iGetThumbPending(EFalse), |
|
176 iCloseHandle(EFalse), |
|
177 ibOpenFilePending(EFalse), |
|
178 iThumbIndex(0), |
|
179 iUtil(NULL), |
|
180 m_State( ENotReady), |
|
181 m_bMetaDataReady(EFalse) |
|
182 { |
|
183 FLOG(_L("CTneSession::CTneSession()in this=%x"), this); |
|
184 FLOG(_L("CTneSession::CTneSession()out this=%x"), this); |
|
185 } |
|
186 |
|
187 |
|
188 |
|
189 CTneSession::~CTneSession() |
|
190 { |
|
191 FLOG(_L("CTneSession::~CTneSession()in this=%x"), this); |
|
192 if(iYUVBuffer) |
|
193 { |
|
194 User::Free(iYUVBuffer); |
|
195 iYUVBuffer = NULL; |
|
196 } |
|
197 |
|
198 if (iCloseHandle) |
|
199 { |
|
200 iFileHandle.Close(); |
|
201 } |
|
202 if (iUtil) |
|
203 { |
|
204 delete iUtil; |
|
205 iUtil = NULL; |
|
206 } |
|
207 if(iFs) |
|
208 { |
|
209 iFs->Close(); |
|
210 delete iFs; |
|
211 iFs = NULL; |
|
212 } |
|
213 CompleteRequest(KErrCancel); |
|
214 CompleteCancelRequest(); |
|
215 CActiveScheduler::Stop(); |
|
216 |
|
217 FLOG(_L("CTneSession::~CTneSession()out this=%x"), this); |
|
218 } |
|
219 |
|
220 |
|
221 /** |
|
222 Services a client request. |
|
223 */ |
|
224 void CTneSession::ServiceL(const RMessage2& aMessage) |
|
225 { |
|
226 DispatchMessageL(aMessage); |
|
227 } |
|
228 |
|
229 |
|
230 void CTneSession::DispatchMessageL(const RMessage2& aMessage) |
|
231 { |
|
232 |
|
233 TBool bCompleteRequest = EFalse; |
|
234 TInt lError = KErrNone; |
|
235 RFile* pFileHandle; |
|
236 TFileName *pFileName; |
|
237 TInt aPosition; |
|
238 TNEMetaData* pMetaData; |
|
239 TNEThumbRequest *pThumbRequestData; |
|
240 RFile64 aFilehandle; |
|
241 |
|
242 FLOG(_L("CTneSession::DispatchMessageL in type=%d"), aMessage.Function()); |
|
243 |
|
244 switch (aMessage.Function()) |
|
245 { |
|
246 case EOpenFileRFmsg: |
|
247 m_State = EStartGettingMetadata; |
|
248 bCompleteRequest = ETrue; |
|
249 iClientRequest = aMessage; |
|
250 pFileHandle = ( RFile* ) aMessage.Ptr0(); // Handle to read Message data |
|
251 aPosition = (TInt ) aMessage.Ptr1(); |
|
252 |
|
253 lError = iFileHandle.Duplicate(*pFileHandle); |
|
254 if (lError == KErrNone) |
|
255 { |
|
256 iCloseHandle = ETrue; |
|
257 lError = DoOpenFile(iFileHandle, aPosition); |
|
258 } |
|
259 |
|
260 if( m_State == EStartGettingThumbNailWithIndex) |
|
261 { |
|
262 lError = ReOpenFile(iFileHandle); |
|
263 } |
|
264 |
|
265 CompleteCancelRequest(); // it will check also if cancel needs to be done. |
|
266 |
|
267 break; |
|
268 |
|
269 //fix me - Avoid duplicate code -common func (Future Work) |
|
270 case EOpenFIleNamemsg: |
|
271 iFs = NULL; |
|
272 m_State = EStartGettingMetadata; |
|
273 iClientRequest = aMessage; |
|
274 pFileName = (TFileName* ) aMessage.Ptr0(); |
|
275 aPosition = (TInt ) aMessage.Ptr1(); |
|
276 |
|
277 iFs = new RFs; |
|
278 if(iFs == NULL) |
|
279 { |
|
280 lError = KErrNoMemory; |
|
281 bCompleteRequest = ETrue; |
|
282 } |
|
283 else if ( (lError = iFs->Connect())!= KErrNone) |
|
284 { |
|
285 bCompleteRequest = ETrue; |
|
286 } |
|
287 else if ((lError = aFilehandle.Open(*iFs,*pFileName, EFileShareReadersOnly | EFileStream | EFileRead))!= KErrNone) |
|
288 { |
|
289 bCompleteRequest = ETrue; |
|
290 } |
|
291 else if ((lError = iFileHandle.Duplicate(aFilehandle))!= KErrNone) |
|
292 { |
|
293 bCompleteRequest = ETrue; |
|
294 aFilehandle.Close(); |
|
295 |
|
296 } |
|
297 else if ( (lError = DoOpenFile(iFileHandle, aPosition)) != KErrNone ) |
|
298 { |
|
299 bCompleteRequest = ETrue; |
|
300 aFilehandle.Close(); |
|
301 iCloseHandle = ETrue; |
|
302 } |
|
303 else |
|
304 { |
|
305 bCompleteRequest = ETrue; |
|
306 aFilehandle.Close(); |
|
307 iCloseHandle = ETrue; |
|
308 } |
|
309 |
|
310 |
|
311 if( m_State == EStartGettingThumbNailWithIndex) |
|
312 { |
|
313 lError = ReOpenFile(iFileHandle); |
|
314 } |
|
315 |
|
316 CompleteCancelRequest(); // it will check also if cancel needs to be done. |
|
317 |
|
318 if (lError != KErrNone) |
|
319 { |
|
320 bCompleteRequest = ETrue; |
|
321 } |
|
322 |
|
323 break; |
|
324 case EGetMetaDatamsg: |
|
325 iClientRequest = aMessage; |
|
326 pMetaData = ( TNEMetaData* ) aMessage.Ptr0(); |
|
327 pMetaData->iWidth = iWidth; |
|
328 pMetaData->iHeight = iHeight; |
|
329 pMetaData->iFrameCount = iFrameCount; |
|
330 bCompleteRequest = ETrue; |
|
331 |
|
332 break; |
|
333 |
|
334 case EGetThumbmsg: |
|
335 |
|
336 iClientRequest = aMessage; |
|
337 pThumbRequestData = ( TNEThumbRequest * ) aMessage.Ptr0(); |
|
338 // store thumb request parameters |
|
339 iClientYUVBufferPtrPtr = &(pThumbRequestData->iYUVBuffer); |
|
340 iThumbIndex = pThumbRequestData->iIndex; |
|
341 if (iThumbIndex == KBestThumbIndex || iThumbIndex <= 1) |
|
342 { |
|
343 m_State = EStartGettingThumbNail; |
|
344 DoGetThumb(); |
|
345 } |
|
346 else |
|
347 { |
|
348 m_State = EStartGettingThumbNailWithIndex; |
|
349 if (!ibOpenFilePending) |
|
350 { |
|
351 lError = ReOpenFile(iFileHandle); |
|
352 } |
|
353 } |
|
354 break; |
|
355 case ECancelThumbmsg: |
|
356 iGetThumbPending = EFalse; |
|
357 iCancelRequest = aMessage; |
|
358 m_State = ECancelling; |
|
359 if(iUtil) |
|
360 { |
|
361 iUtil->CancelThumb(); |
|
362 } |
|
363 // cancel any pending getthumb or openfile request. |
|
364 lError = KErrCancel; |
|
365 CompleteRequest(lError); |
|
366 |
|
367 if (!ibOpenFilePending) |
|
368 { |
|
369 CompleteCancelRequest(); |
|
370 } |
|
371 break; |
|
372 |
|
373 default: |
|
374 // PanicClient(aMessage,EBadRequest); |
|
375 return; |
|
376 |
|
377 } |
|
378 |
|
379 if (bCompleteRequest) |
|
380 { |
|
381 CompleteRequest(lError); |
|
382 } |
|
383 |
|
384 FLOG(_L("CTneSession::DispatchMessageL out type=%d"), aMessage.Function()); |
|
385 } |
|
386 |
|
387 |
|
388 |
|
389 TInt CTneSession::DoOpenFile(RFile &aFileHandle, TUint uStartTime) |
|
390 { |
|
391 FLOG(_L(" CTneSession::DoOpenFile in")); |
|
392 |
|
393 MHXThumbnailUtilityImplObserver* pObserver = |
|
394 (MHXThumbnailUtilityImplObserver *) this; |
|
395 |
|
396 ibOpenFilePending = ETrue; |
|
397 TFileName aFilename; |
|
398 aFileHandle.FullName(aFilename); |
|
399 FLOG(_L("aFilename=%S"),&aFilename ); |
|
400 TRAPD(err, iUtil = CHXThumbnailUtility::NewL(*pObserver)); |
|
401 m_bDone = EFalse; |
|
402 m_uPacketsReceived = 0; |
|
403 if (err == KErrNone) |
|
404 { |
|
405 TRAP(err, iUtil->OpenFileL(aFileHandle, uStartTime)); |
|
406 } |
|
407 FLOG(_L(" CTneSession::DoOpenFile out err = %d"),err); |
|
408 ibOpenFilePending = EFalse; |
|
409 return err; |
|
410 } |
|
411 |
|
412 TInt CTneSession::ReOpenFile(RFile &aFileHandle) |
|
413 { |
|
414 iGetThumbPending = ETrue; |
|
415 TInt lError = KErrNone; |
|
416 TUint uStartingTime = 0; |
|
417 lError = GetStartingTime(uStartingTime); |
|
418 if (lError == KErrNone) |
|
419 { |
|
420 if (iUtil) |
|
421 { |
|
422 iUtil->CancelThumb(); |
|
423 delete iUtil; |
|
424 iUtil = NULL; |
|
425 } |
|
426 |
|
427 lError = DoOpenFile(aFileHandle, uStartingTime); |
|
428 } |
|
429 |
|
430 return lError; |
|
431 } |
|
432 |
|
433 |
|
434 |
|
435 void CTneSession::FetchBasicMetaData() |
|
436 { |
|
437 TUint lCount = 0; |
|
438 TUint i=0; |
|
439 TUint lFrameRateinSec = 0; |
|
440 |
|
441 iUtil->GetMetaDataCount(lCount); |
|
442 |
|
443 TBool bGotFrameSize = EFalse, bGotDuration = EFalse, bGotFrameRate = EFalse; |
|
444 |
|
445 for (i=0; i<lCount; i++) |
|
446 { |
|
447 HBufC *pDes = NULL; |
|
448 HXMetaDataKeys::EHXMetaDataId id; |
|
449 iUtil->GetMetaDataAt(i, id, pDes); |
|
450 |
|
451 if (id == HXMetaDataKeys::EHXFrameSize && pDes) |
|
452 { |
|
453 TPtr pFrameSizePtr = pDes->Des(); |
|
454 _LIT(KChar_x, "x"); |
|
455 TInt xLoc = pFrameSizePtr.Find(KChar_x); |
|
456 if (xLoc != KErrNotFound) |
|
457 { |
|
458 TLex lexWidth(pFrameSizePtr.Mid(0, xLoc)); |
|
459 TLex lexHeight(pFrameSizePtr.Mid(xLoc+1)); |
|
460 lexWidth.Val(iWidth); // Storing into local iWidth variable |
|
461 lexHeight.Val(iHeight); // Storing into local iHeight variable |
|
462 bGotFrameSize = ETrue; |
|
463 FLOG(_L(" iWidth=%d,iHeight=%d"), iWidth,iHeight); |
|
464 } |
|
465 } |
|
466 else if (id == HXMetaDataKeys::EHXDuration && pDes) |
|
467 { |
|
468 TLex lexDuration(pDes->Des()); |
|
469 lexDuration.Val(iDuration); |
|
470 bGotDuration = ETrue; |
|
471 } |
|
472 else if (id == HXMetaDataKeys::EHXFramesPerSecond && pDes) |
|
473 { |
|
474 TLex lexFramesPerSecond(pDes->Des()); |
|
475 lexFramesPerSecond.Val(lFrameRateinSec); |
|
476 bGotFrameRate = ETrue; |
|
477 } |
|
478 |
|
479 if (bGotDuration && bGotFrameRate && bGotFrameSize) |
|
480 { |
|
481 break; |
|
482 } |
|
483 |
|
484 } // end of for |
|
485 |
|
486 if (bGotDuration && bGotFrameRate) |
|
487 { |
|
488 // approximate frame count |
|
489 // iDuration is in msec. |
|
490 iFrameCount = ( (iDuration+500)/1000 ) * lFrameRateinSec; |
|
491 } |
|
492 |
|
493 else |
|
494 { |
|
495 iFrameCount = ( (iDuration+500)/1000 ) * 10; |
|
496 } |
|
497 |
|
498 |
|
499 } |
|
500 |
|
501 |
|
502 void CTneSession::DoGetThumb() |
|
503 { |
|
504 iGetThumbPending = ETrue; |
|
505 if(m_bDone) |
|
506 { |
|
507 if (m_LastError != KErrNone) |
|
508 { |
|
509 if (iYUVBuffer) |
|
510 { |
|
511 User::Free(iYUVBuffer); |
|
512 iYUVBuffer = NULL; |
|
513 } |
|
514 } |
|
515 |
|
516 NotifyIfGetThumbPending(m_LastError, iYUVBuffer); |
|
517 } |
|
518 } |
|
519 |
|
520 void CTneSession::MetaDataReady(TInt aError) |
|
521 { |
|
522 |
|
523 FLOG(_L("CTneSession::MetaDataReady in callbacks from Utility aError=%d"), aError); |
|
524 if ( m_State == EStartGettingMetadata) |
|
525 { |
|
526 // extract some minimum metadata to be used for thumbnail generation |
|
527 if (aError == KErrNone) |
|
528 { |
|
529 FetchBasicMetaData(); |
|
530 if(iYUVBuffer) |
|
531 { |
|
532 User::Free(iYUVBuffer); |
|
533 iYUVBuffer = NULL; |
|
534 } |
|
535 |
|
536 // Allocate memory for iYUVBuffer |
|
537 if( iWidth > 4 && iHeight > 4 ) // for all frame sizes |
|
538 { |
|
539 TInt length = iWidth * iHeight; |
|
540 length += (length>>1); |
|
541 iYUVBuffer = (TUint8*)User::Alloc(length); |
|
542 |
|
543 if (!iYUVBuffer) |
|
544 { |
|
545 FLOG(_L("CTneSession::MetaDataReady Error No memory for iYUVBuffer")); |
|
546 aError = KErrNoMemory; |
|
547 } |
|
548 } |
|
549 else |
|
550 { |
|
551 FLOG(_L("CTneSession::MetaDataReady Error Width/Height not found")); |
|
552 aError = KErrNotSupported; |
|
553 |
|
554 } |
|
555 } |
|
556 m_LastError = aError; |
|
557 |
|
558 // only complete the request if there is any error. If the request is not completed here then |
|
559 // it will be completed after the DoOpenFile() returns. |
|
560 if (aError != KErrNone) |
|
561 { |
|
562 CompleteRequest(aError); |
|
563 } |
|
564 |
|
565 } |
|
566 FLOG(_L("CTneSession::MetaDataReady out aError=%d"), aError); |
|
567 m_bMetaDataReady = ETrue; |
|
568 |
|
569 } |
|
570 |
|
571 |
|
572 void CTneSession::PacketReady(TInt aError, |
|
573 void *pData, TUint32 aDataSize) |
|
574 { |
|
575 FLOG(_L("CTneSession::PacketReady aError=%d m_State=%d aDataSize=%d"), aError, m_State, aDataSize); |
|
576 if(aDataSize > (iWidth*iHeight*3/2 )) |
|
577 { |
|
578 aDataSize = iWidth*iHeight*3/2 ; //restore back to values coming from header if they differ |
|
579 |
|
580 } |
|
581 if (m_State == ECancelling) |
|
582 { |
|
583 FLOG(_L("CTneSession::PacketReady no op")); |
|
584 return; |
|
585 } |
|
586 if(aDataSize < (iWidth*iHeight*3/2 )) // check to avoid getting very low size |
|
587 { |
|
588 if(m_uPacketsReceived == 0) |
|
589 { |
|
590 m_LastError = KErrNotSupported ; // if this is the first packet then only send KErrNotSupported |
|
591 } |
|
592 |
|
593 m_bDone = ETrue; |
|
594 } |
|
595 |
|
596 if (m_LastError != KErrNone || aError != KErrNone || pData == NULL) |
|
597 { |
|
598 FLOG(_L("CTneSession::PacketReady aError=%d m_State=%d pData=%x"), aError, m_State, pData); |
|
599 // MetadataReady might set m_LastError |
|
600 m_bDone = ETrue; |
|
601 |
|
602 if (m_LastError == KErrNone) |
|
603 { |
|
604 if (aError == KErrNone) |
|
605 { |
|
606 m_LastError = KErrNotSupported; |
|
607 } |
|
608 else |
|
609 { |
|
610 m_LastError = aError; |
|
611 } |
|
612 } |
|
613 } |
|
614 else |
|
615 { |
|
616 m_uPacketsReceived++; |
|
617 if ( IsGoodFrame((TUint8*)pData ) && !m_bDone ) |
|
618 { |
|
619 m_bDone = ETrue; |
|
620 m_LastError = KErrNone; |
|
621 Mem::Copy(iYUVBuffer, pData, aDataSize); |
|
622 } |
|
623 else if (m_uPacketsReceived == 1) // we copy the first packet |
|
624 { |
|
625 Mem::Copy(iYUVBuffer, pData, aDataSize); |
|
626 } |
|
627 else if (m_uPacketsReceived >= KMaxPacketToDecode) |
|
628 { |
|
629 // we decoded upto KMaxPacketToDecode and haven't found |
|
630 // a good frame yet. |
|
631 FLOG(_L("CHXTNEVideoClipInfoImp::PacketReady max count reached %d"), |
|
632 m_uPacketsReceived); |
|
633 Mem::Copy(iYUVBuffer, pData, aDataSize); // we copy and use the last frame |
|
634 m_bDone = ETrue; |
|
635 m_LastError = KErrNone; |
|
636 } |
|
637 } |
|
638 |
|
639 |
|
640 // we are done. Tell the TNUtil that no more packets are needed. |
|
641 if (m_bDone) |
|
642 { |
|
643 iUtil->CancelThumb(); |
|
644 } |
|
645 |
|
646 if (iGetThumbPending) |
|
647 { |
|
648 |
|
649 // we are done either success or failure. |
|
650 if(m_bDone) |
|
651 { |
|
652 if (m_LastError != KErrNone) |
|
653 { |
|
654 if (iYUVBuffer) |
|
655 { |
|
656 User::Free(iYUVBuffer); |
|
657 iYUVBuffer = NULL; |
|
658 } |
|
659 } |
|
660 |
|
661 NotifyIfGetThumbPending(m_LastError, iYUVBuffer); |
|
662 } |
|
663 } |
|
664 |
|
665 |
|
666 } |
|
667 |
|
668 void CTneSession::EndOfPackets() |
|
669 { |
|
670 if (!m_bDone) |
|
671 { |
|
672 if(m_uPacketsReceived >= 1) |
|
673 { |
|
674 NotifyIfGetThumbPending(KErrNone, iYUVBuffer); |
|
675 } |
|
676 else |
|
677 { |
|
678 TUint8* pYUVBuffer = NULL; |
|
679 NotifyIfGetThumbPending(KErrNotFound, pYUVBuffer); |
|
680 } |
|
681 // If end of packet has been received then thumbnailengine should be done |
|
682 m_bDone = ETrue; |
|
683 } |
|
684 |
|
685 if(!m_bMetaDataReady) |
|
686 { |
|
687 MetaDataReady(KErrCompletion); |
|
688 } |
|
689 } |
|
690 |
|
691 TBool CTneSession::IsGoodFrame(TUint8* aYUVDataPtr) |
|
692 { |
|
693 |
|
694 TInt i; |
|
695 TInt minValue = 255; |
|
696 TInt maxValue = 0; |
|
697 TBool goodFrame = ETrue; |
|
698 TInt runningSum=0; |
|
699 TInt averageValue=0; |
|
700 TInt pixelSkips = 4; |
|
701 TInt numberOfSamples=0; |
|
702 TInt minMaxDeltaThreshold = 20; |
|
703 TInt extremeRegionThreshold = 20; |
|
704 TInt ySize = iWidth*iHeight; |
|
705 |
|
706 // gather image statistics |
|
707 for(i=0, numberOfSamples=0; i<ySize; i+=pixelSkips, aYUVDataPtr+=pixelSkips, numberOfSamples++) |
|
708 { |
|
709 |
|
710 |
|
711 runningSum += *aYUVDataPtr; |
|
712 if(*aYUVDataPtr > maxValue) |
|
713 maxValue = *aYUVDataPtr; |
|
714 if(*aYUVDataPtr < minValue) |
|
715 minValue = *aYUVDataPtr; |
|
716 } |
|
717 //VDASSERT(numberOfSamples,10); |
|
718 if (numberOfSamples == 0) |
|
719 { |
|
720 FLOG(_L("CTneSession::IsGoodFrame numberOfSamples is zero")); |
|
721 } |
|
722 else |
|
723 { |
|
724 averageValue = runningSum/numberOfSamples; |
|
725 } |
|
726 |
|
727 // make decision based statistics |
|
728 if((maxValue - minValue) < minMaxDeltaThreshold) |
|
729 goodFrame = EFalse; |
|
730 else |
|
731 { |
|
732 if(averageValue < (minValue + extremeRegionThreshold) || |
|
733 averageValue > (maxValue - extremeRegionThreshold)) |
|
734 goodFrame = EFalse; |
|
735 } |
|
736 return goodFrame; |
|
737 } |
|
738 |
|
739 TInt CTneSession::GetStartingTime(TUint &uStartingTime) |
|
740 { |
|
741 TInt err = KErrNone; |
|
742 |
|
743 if (iThumbIndex <= iFrameCount) |
|
744 { |
|
745 TReal tempDuration = iDuration; |
|
746 uStartingTime = (tempDuration/iFrameCount) * iThumbIndex; |
|
747 // thumbnail beyond the clip duration. |
|
748 if (uStartingTime >= iDuration) |
|
749 { |
|
750 uStartingTime = 0; |
|
751 } |
|
752 } |
|
753 else |
|
754 { |
|
755 err = KErrNotSupported; |
|
756 } |
|
757 FLOG(_L("CTNEVideoClipInfo::GetStartingTime StartingTime=%d iDuration=%d iFrameCount=l:%d h:%d iThumbIndex=%d err=%d"), |
|
758 uStartingTime, iDuration, I64LOW(iFrameCount),I64HIGH(iFrameCount), iThumbIndex, err); |
|
759 return err; |
|
760 } |
|
761 |
|
762 |
|
763 |
|
764 void CTneSession::CompleteRequest(TInt aError) |
|
765 { |
|
766 if(!iClientRequest.IsNull()) |
|
767 { |
|
768 iClientRequest.Complete(aError); |
|
769 } |
|
770 } |
|
771 |
|
772 |
|
773 |
|
774 |
|
775 // ownership of pBitMap will be passed to Observer |
|
776 void CTneSession::NotifyIfGetThumbPending(TInt aError, TUint8 *&pYUVBuffer) |
|
777 { |
|
778 if (iGetThumbPending && !iClientRequest.IsNull()) |
|
779 { |
|
780 iGetThumbPending = EFalse; |
|
781 *iClientYUVBufferPtrPtr = pYUVBuffer; |
|
782 iClientRequest.Complete(aError); |
|
783 |
|
784 } |
|
785 } |
|
786 |
|
787 void CTneSession::CompleteCancelRequest() |
|
788 { |
|
789 |
|
790 if (!iCancelRequest.IsNull()) |
|
791 { |
|
792 |
|
793 if (iUtil) |
|
794 { |
|
795 delete iUtil; |
|
796 iUtil = NULL; |
|
797 } |
|
798 iCancelRequest.Complete(KErrNone); |
|
799 } |
|
800 } |