|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 /** |
|
20 @file |
|
21 @internalComponent |
|
22 */ |
|
23 |
|
24 #include "omxthreadrequest.h" |
|
25 |
|
26 COmxThreadRequest* COmxThreadRequest::NewL() |
|
27 { |
|
28 COmxThreadRequest* self = new (ELeave) COmxThreadRequest(); |
|
29 CleanupStack::PushL(self); |
|
30 self->ConstructL(); |
|
31 CleanupStack::Pop(self); |
|
32 return self; |
|
33 } |
|
34 |
|
35 COmxThreadRequest::COmxThreadRequest() |
|
36 { |
|
37 } |
|
38 |
|
39 void COmxThreadRequest::ConstructL() |
|
40 { |
|
41 //Parameters to send to the sub thread |
|
42 TThreadParam param; |
|
43 param.iThreadRequestObj = this; |
|
44 |
|
45 //Get a reference to this thread's heap |
|
46 RHeap& thisHeap = User::Heap(); |
|
47 |
|
48 //Get the id of this thread |
|
49 RThread thisThread; |
|
50 TThreadId thisThreadId = thisThread.Id(); |
|
51 param.iMainThreadId = thisThreadId; |
|
52 |
|
53 //Get a request to signal for setup completion |
|
54 TRequestStatus setupComplete = KRequestPending; |
|
55 param.iSetupComplete = &setupComplete; |
|
56 |
|
57 //current time and the "this" pointer for a unique key |
|
58 _LIT(KFormatString,"%S.%020Lu.%08X"); |
|
59 TName threadName; |
|
60 TTime now; |
|
61 now.UniversalTime(); |
|
62 threadName.Format(KFormatString, &KXMLClientOMXThreadName, now.Int64(), reinterpret_cast<TUint>(this)); |
|
63 |
|
64 //Create a new thread using the same heap as this thread |
|
65 TInt result = iRequestThread.Create(threadName, |
|
66 ThreadCreateFunction, |
|
67 KDefaultStackSize, |
|
68 &thisHeap, |
|
69 ¶m); |
|
70 User::LeaveIfError(result); |
|
71 |
|
72 //Run the thread under high priority |
|
73 iRequestThread.SetPriority(EPriorityNormal); |
|
74 |
|
75 //Wait for thread startup to complete |
|
76 TRequestStatus threadStatus = KRequestPending; |
|
77 iRequestThread.Logon(threadStatus); |
|
78 |
|
79 //Start the thread |
|
80 iRequestThread.Resume(); |
|
81 User::WaitForRequest(threadStatus, setupComplete); |
|
82 if(threadStatus != KRequestPending) |
|
83 { |
|
84 //Thread creation failed |
|
85 TInt reason = iRequestThread.ExitReason(); |
|
86 User::Leave(reason); |
|
87 } |
|
88 |
|
89 // Thread creation was successfull |
|
90 TInt error = iRequestThread.LogonCancel(threadStatus); |
|
91 User::LeaveIfError(error); // There is no outstanding request |
|
92 User::WaitForRequest(threadStatus); // Consume the signal |
|
93 |
|
94 iThreadCreated = ETrue; |
|
95 User::LeaveIfError(setupComplete.Int()); |
|
96 } |
|
97 |
|
98 /** |
|
99 Main thread entry point for the omx sub-thread. |
|
100 Create a cleanup stack for the thread and process the commands |
|
101 inside a trap for cleanup behaviour. |
|
102 @internalComponent |
|
103 |
|
104 @param aPtr Parameters to be used for creating the thread. |
|
105 @return The error code for thread termination. |
|
106 */ |
|
107 TInt COmxThreadRequest::ThreadCreateFunction(TAny* aPtr) |
|
108 { |
|
109 TInt error = KErrNone; |
|
110 |
|
111 // Create a cleanup stack for the thread |
|
112 CTrapCleanup* cleanupStack = CTrapCleanup::New(); |
|
113 if (cleanupStack) |
|
114 { |
|
115 if(error == KErrNone) |
|
116 { |
|
117 TRAP(error, ThreadTrapFunctionL(aPtr)); |
|
118 } |
|
119 } |
|
120 else |
|
121 { |
|
122 error = KErrNoMemory; |
|
123 } |
|
124 |
|
125 delete cleanupStack; |
|
126 return error; |
|
127 } |
|
128 |
|
129 /** |
|
130 Function for thread execution. If the thread is successfully created signal |
|
131 the main thread that the thread creation was successfull. Then enter OMX |
|
132 request loop. |
|
133 |
|
134 @internalComponent |
|
135 |
|
136 @param aPtr A pointer to a TThreadParam object containing the startup parameters |
|
137 for the thread. |
|
138 */ |
|
139 void COmxThreadRequest::ThreadTrapFunctionL(TAny* aPtr) |
|
140 { |
|
141 TThreadParam* param = static_cast<TThreadParam*>(aPtr); |
|
142 COmxThreadRequest* iThreadRequestObj = param->iThreadRequestObj; |
|
143 |
|
144 // tell main thread that setup is complete |
|
145 RThread mainThread; |
|
146 mainThread.Open(param->iMainThreadId); |
|
147 mainThread.RequestComplete(param->iSetupComplete, KErrNone); |
|
148 mainThread.Close(); |
|
149 |
|
150 // loop to execute OMX commands in own thread |
|
151 while(iThreadRequestObj->iFunction != EOMXFunctionCodeTerminate) |
|
152 { |
|
153 iThreadRequestObj->iRequestThreadStatus = KRequestPending; |
|
154 |
|
155 // block until client request is made |
|
156 User::WaitForRequest(iThreadRequestObj->iRequestThreadStatus); |
|
157 switch(iThreadRequestObj->iFunction) |
|
158 { |
|
159 case EOMXFunctionCodeGetHandle: |
|
160 iThreadRequestObj->iErrorType = OMX_GetHandle( |
|
161 iThreadRequestObj->ipHandle, |
|
162 iThreadRequestObj->icComponentName, |
|
163 iThreadRequestObj->ipAppData, |
|
164 iThreadRequestObj->ipCallBacks); |
|
165 break; |
|
166 |
|
167 case EOMXFunctionCodeFreeHandle: |
|
168 iThreadRequestObj->iErrorType = OMX_FreeHandle( |
|
169 iThreadRequestObj->ihComponent); |
|
170 break; |
|
171 |
|
172 case EOMXFunctionCodeTerminate: |
|
173 break; |
|
174 |
|
175 default: |
|
176 // should never be reached |
|
177 User::Panic(_L("COmxThreadRequest"), KErrNotSupported); |
|
178 } |
|
179 |
|
180 // complete client request |
|
181 TRequestStatus *status = iThreadRequestObj->iCallingStatus; |
|
182 RThread callingThread; |
|
183 callingThread.Open(iThreadRequestObj->iCallingThreadId); |
|
184 callingThread.RequestComplete(status, KErrNone); |
|
185 callingThread.Close(); |
|
186 } |
|
187 } |
|
188 |
|
189 COmxThreadRequest::~COmxThreadRequest() |
|
190 { |
|
191 if(iThreadCreated) |
|
192 { |
|
193 TRequestStatus status; |
|
194 // Logon to ensure thread has completely terminated, not just broken out of message handling loop. |
|
195 // In particular this ensures the cleanup stack is destroyed before the heap marks are inspected. |
|
196 iRequestThread.Logon(status); |
|
197 Terminate(); |
|
198 User::WaitForRequest(status); |
|
199 iThreadCreated = EFalse; |
|
200 iRequestThread.Close(); |
|
201 } |
|
202 } |
|
203 |
|
204 OMX_ERRORTYPE COmxThreadRequest::GetHandle( |
|
205 OMX_OUT OMX_HANDLETYPE* pHandle, |
|
206 OMX_IN OMX_STRING cComponentName, |
|
207 OMX_IN OMX_PTR pAppData, |
|
208 OMX_IN OMX_CALLBACKTYPE* pCallBacks) |
|
209 { |
|
210 ipHandle = pHandle; |
|
211 icComponentName = cComponentName; |
|
212 ipAppData = pAppData; |
|
213 ipCallBacks = pCallBacks; |
|
214 |
|
215 iFunction = EOMXFunctionCodeGetHandle; |
|
216 DoRequest(); |
|
217 |
|
218 return iErrorType; |
|
219 } |
|
220 |
|
221 OMX_ERRORTYPE COmxThreadRequest::FreeHandle( |
|
222 OMX_IN OMX_HANDLETYPE hComponent) |
|
223 { |
|
224 ihComponent = hComponent; |
|
225 |
|
226 iFunction = EOMXFunctionCodeFreeHandle; |
|
227 DoRequest(); |
|
228 |
|
229 return iErrorType; |
|
230 } |
|
231 |
|
232 void COmxThreadRequest::Terminate() |
|
233 { |
|
234 iFunction = EOMXFunctionCodeTerminate; |
|
235 DoRequest(); |
|
236 } |
|
237 |
|
238 void COmxThreadRequest::DoRequest() |
|
239 { |
|
240 RThread me; |
|
241 iCallingThreadId = me.Id(); |
|
242 |
|
243 TRequestStatus callingRequestStatus = KRequestPending; |
|
244 iCallingStatus = &callingRequestStatus; |
|
245 |
|
246 // send request to request thread |
|
247 RThread requestThread; |
|
248 requestThread.Open(iRequestThread.Id()); |
|
249 TRequestStatus* requestStatus = &iRequestThreadStatus; |
|
250 requestThread.RequestComplete(requestStatus, KErrNone); |
|
251 requestThread.Close(); |
|
252 |
|
253 // block calling request until OMX request completes |
|
254 User::WaitForRequest(callingRequestStatus); |
|
255 } |