Fixed transparent issue of RGB565
[platform/framework/native/image.git] / src / FMedia_ImageUriDataFactory.cpp
1 //
2 // Open Service Platform
3 // Copyright (c) 2012 Samsung Electronics Co., Ltd.
4 //
5 // Licensed under the Apache License, Version 2.0 (the License);
6 // you may not use this file except in compliance with the License.
7 // You may obtain a copy of the License at
8 //
9 //     http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 //
17
18 /**
19  * @file   FMedia_ImageUriDataFactory.cpp
20  * @brief  This file contains the implementation of _ImageUriDataFactory class,
21  *               required internally by Image::DecodeUrl.
22  */
23
24 //include
25 #include <cstdlib>
26 #include <new>
27 #include <pthread.h>
28 #include <unique_ptr.h>
29 #include <FBaseSysLog.h>
30 #include <FMediaIImageEventListener.h>
31
32 #include "FMedia_ImageUriData.h"
33 #include "FMedia_ImageUriDataHolder.h"
34 #include "FMedia_ImageUriDataFactory.h"
35
36 using namespace Tizen::Base;
37 using namespace Tizen::Base::Utility;
38 using namespace Tizen::Graphics;
39
40 namespace Tizen{ namespace Media{
41
42 // 3 requests in worker queue. As in 2.0.
43 static const int _MAX_IMAGE_URI_DATA_WORK = 3;
44 // 3 requests in pending queue. As in 2.0.
45 static const int _MAX_IMAGE_URI_DATA_QUEUE_COUNT = 3;
46
47 _ImageUriDataFactory* _ImageUriDataFactory::__pTheInstance = null;
48
49 void
50 _ImageUriDataFactory::InitSingleton(void)
51 {
52         std::unique_ptr<_ImageUriDataFactory> pInst(new (std::nothrow) _ImageUriDataFactory());
53
54         SysTryReturnVoidResult(NID_MEDIA, pInst, E_OUT_OF_MEMORY,
55                                                    "[%s] Memory allocation failed.",
56                                                    GetErrorMessage(E_OUT_OF_MEMORY));
57
58         result r = pInst->Construct();
59         SysTryReturnVoidResult(NID_MEDIA, r == E_SUCCESS, r,
60                                                    "[%s] Propagating.", GetErrorMessage(r));
61
62         __pTheInstance  = pInst.release();
63         std::atexit(DestroySingleton);
64 }
65
66 void
67 _ImageUriDataFactory::DestroySingleton(void)
68 {
69         delete __pTheInstance;
70 }
71
72 _ImageUriDataFactory*
73 _ImageUriDataFactory::GetInstance(void)
74 {
75         static pthread_once_t onceBlock = PTHREAD_ONCE_INIT;
76
77         if (__pTheInstance == null)
78         {
79                 ClearLastResult();
80                 pthread_once(&onceBlock, InitSingleton);
81                 result r = GetLastResult();
82                 if (IsFailed(r))
83                 {
84                         onceBlock = PTHREAD_ONCE_INIT;
85                 }
86         }
87         return __pTheInstance;
88 }
89
90 _ImageUriDataFactory::_ImageUriDataFactory(void)
91 {
92         __requestId = 0;
93 }
94
95 _ImageUriDataFactory::~_ImageUriDataFactory(void)
96 {
97         if (__pImageUriDataHolderQueue.get() != null)
98         {
99                 if (__pImageUriDataHolderQueue->GetCount() > 0)
100                 {
101                         __pImageUriDataHolderQueue->RemoveAll(true);
102                 }
103         }
104
105         if (__pImageUriDataWorkingList.get() != null)
106         {
107                 if (__pImageUriDataWorkingList->GetCount() > 0)
108                 {
109                         __pImageUriDataWorkingList->RemoveAll(true);
110                 }
111         }
112
113         __requestId = 0;
114
115 }
116
117 result
118 _ImageUriDataFactory::Construct(void)
119 {
120         result r = E_SUCCESS;
121
122         __pImageUriDataHolderQueue.reset(new (std::nothrow) Collection::Queue());
123         SysTryReturn(NID_MEDIA, __pImageUriDataHolderQueue.get() != null,
124                 E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] while creating Queue");
125
126         r = __pImageUriDataHolderQueue->Construct(_MAX_IMAGE_URI_DATA_QUEUE_COUNT);
127         SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Propagated.", GetErrorMessage(r));
128
129         __pImageUriDataWorkingList.reset(new (std::nothrow) Collection::LinkedList());
130         SysTryReturn(NID_MEDIA, __pImageUriDataWorkingList.get() != null ,
131                 E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] while creating List");
132
133         return r;
134 }
135
136 result
137 _ImageUriDataFactory::DecodeUrl(const Uri& srcImageUrl,
138         BitmapPixelFormat colorFormat, int destWidth, int destHeight,
139         RequestId &reqId, const Runtime::IEventListener& listener, long timeout)
140 {
141         result r = E_SUCCESS;
142         int index = 0;
143         reqId = -1;     // if fail it returns -1;
144
145         if (__pImageUriDataHolderQueue.get() == null)
146         {
147                 r = Construct();
148                 SysTryReturn(NID_MEDIA, r == E_SUCCESS, r, r, "[%s] Construct failed.",
149                   GetErrorMessage(r));
150         }
151
152         SysTryReturn(NID_MEDIA, GetWorkerCount() < _MAX_IMAGE_URI_DATA_WORK,
153           E_MAX_EXCEEDED, E_MAX_EXCEEDED,
154           "[E_MAX_EXCEEDED] The concurrent working limitation is exceeded.");
155
156         reqId = ++__requestId;
157
158         index = AddImageUriData(srcImageUrl, colorFormat, destWidth, destHeight, reqId, listener, timeout);
159         SysTryReturn(NID_MEDIA, index > 0, GetLastResult(), GetLastResult(),
160                 "[%s] Propagated.", GetErrorMessage(GetLastResult()));
161
162         // 0, 1, 2.. //max 3 instances
163         SysTryReturn(NID_MEDIA, GetWorkerCount() < _MAX_IMAGE_URI_DATA_WORK, E_SUCCESS,
164                 E_SUCCESS, "[E_SUCCESS] But this operation is now pending .");
165
166         r = StartDecode();
167         return r;
168 }
169
170 int
171 _ImageUriDataFactory::AddImageUriData(const Uri& srcImageUrl,
172         BitmapPixelFormat colorFormat, int destWidth, int destHeight,
173         RequestId &reqId, const Runtime::IEventListener& listener, long timeout)
174 {
175         result r = E_SUCCESS;
176         ClearLastResult();
177
178         _ImageUriDataHolder* pImageUriDataHolder = new (std::nothrow) _ImageUriDataHolder();
179         SysTryCatch(NID_MEDIA, pImageUriDataHolder != null ,
180                   r = E_OUT_OF_MEMORY, E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] while creating Image holder");
181
182         pImageUriDataHolder->SetUri(srcImageUrl);
183         pImageUriDataHolder->SetColorFormat(colorFormat);
184         pImageUriDataHolder->SetDestDim(Dimension(destWidth, destHeight));
185         pImageUriDataHolder->SetRequestId(reqId);
186         pImageUriDataHolder->SetListener(const_cast<Runtime::IEventListener*>(&listener));
187         pImageUriDataHolder->SetTimeout(timeout);
188
189         r = __pImageUriDataHolderQueue->Enqueue(*pImageUriDataHolder);
190         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated.", GetErrorMessage(r));
191
192         SetLastResult(r);
193         return GetHolderCount();
194
195 CATCH:
196         reqId = -1;
197         if (pImageUriDataHolder)
198         {
199                 delete pImageUriDataHolder;
200                 pImageUriDataHolder = null;
201         }
202         return -1;
203 }
204
205 result
206 _ImageUriDataFactory::StartDecode(void)
207 {
208         result r = E_SUCCESS;
209         Object* pObj = null;
210         _ImageUriDataHolder* pImageUriDataHolder = null;
211         IImageDecodeUrlEventListener* pImageListener = null;
212         Runtime::IEventListener* pListener = null;
213         std::unique_ptr<_ImageUriData> pImageUriData;
214         RequestId reqId = -1;
215
216         SysTryCatch(NID_MEDIA, __pImageUriDataHolderQueue.get() != null,
217           r = E_INVALID_STATE, E_INVALID_STATE, "[E_INVALID_STATE]");
218
219         pObj = __pImageUriDataHolderQueue->Dequeue();
220         SysTryCatch(NID_MEDIA, pObj != null, r = E_UNDERFLOW, E_UNDERFLOW, "[E_UNDERFLOW]");
221
222         pImageUriDataHolder = dynamic_cast<_ImageUriDataHolder*>(pObj);
223         SysTryCatch(NID_MEDIA, pImageUriDataHolder != null, r = E_INVALID_ARG,
224           E_INVALID_ARG, "[E_INVALID_ARG] : RequestId = %d",
225           pImageUriDataHolder->GetRequestId());
226
227         pListener = pImageUriDataHolder->GetListener();
228         pImageListener = dynamic_cast<IImageDecodeUrlEventListener*>(pListener);
229         SysTryCatch(NID_MEDIA, pImageListener != null, r = E_INVALID_ARG,
230           E_INVALID_ARG, "[E_INVALID_ARG] GetListener() : RequestId = %d",
231           pImageUriDataHolder->GetRequestId());
232
233         pImageUriData.reset(new (std::nothrow) _ImageUriData());
234         SysTryCatch(NID_MEDIA, pImageUriData.get() != null, r = E_OUT_OF_MEMORY,
235           E_OUT_OF_MEMORY, "[E_OUT_OF_MEMORY] : RequestId = %d",
236           pImageUriDataHolder->GetRequestId());
237
238         r = pImageUriData->Construct(*pImageListener);
239         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated : RequestId = %d.",
240           GetErrorMessage(r), pImageUriDataHolder->GetRequestId());
241
242         reqId = pImageUriDataHolder->GetRequestId();
243
244         r = pImageUriData->RequestDecode(pImageUriDataHolder->GetUri(),
245           pImageUriDataHolder->GetColorFormat(), pImageUriDataHolder->GetDestDim(),
246           reqId, pImageUriDataHolder->GetTimeout());
247         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated : RequestId = %d.",
248           GetErrorMessage(r), pImageUriDataHolder->GetRequestId());
249
250         r = __pImageUriDataWorkingList->Add(*pImageUriData.release());
251         SysTryCatch(NID_MEDIA, r == E_SUCCESS, , r, "[%s] Propagated : RequestId = %d.",
252           GetErrorMessage(r), pImageUriDataHolder->GetRequestId());
253
254         delete pImageUriDataHolder;
255
256         return r;
257
258 CATCH:
259
260         if (pImageUriDataHolder)
261         {
262                 delete pImageUriDataHolder;
263         }
264         return r;
265 }
266
267 void
268 _ImageUriDataFactory::Watchout(void)
269 {
270         result r = E_SUCCESS;
271         int heldCount = GetHolderCount();
272
273         while (0 < heldCount)
274         {
275                 r = StartDecode();
276                 if (r == E_SUCCESS)
277                 {
278                         break;
279                 }
280                 heldCount = GetHolderCount();
281         }
282 }
283
284 void
285 _ImageUriDataFactory::OnMediaSessionEnded(RequestId requestId)
286 {
287         int num = 0;
288         Object* pObj = null;
289
290         // free the memory
291         num = __pImageUriDataWorkingList->GetCount();
292         for (int i = 0; i < num; i++)
293         {
294                 pObj = __pImageUriDataWorkingList->GetAt(i);
295         if (pObj != null)
296         {
297                 _ImageUriData* pImageUriData = dynamic_cast<_ImageUriData*>(pObj);
298                 if (pImageUriData != null)
299                 {
300                                 if (requestId == pImageUriData->GetRequestId())
301                                 {
302                                         __pImageUriDataWorkingList->RemoveAt(i, true);
303                                         break;
304                                 }
305                 }
306         }
307         }
308
309         Watchout();
310 }
311
312 void
313 _ImageUriDataFactory::Remove(RequestId reqId)
314 {
315         Object* pObj = null;
316         int num = 0;
317         bool deleted = false;
318         result r = E_SUCCESS;
319
320         // Remove ImageUriData for this request id from the working list.
321         num = __pImageUriDataWorkingList->GetCount();
322         for (int i = 0; i < num; i++)
323         {
324                 pObj = __pImageUriDataWorkingList->GetAt(i);
325                 if (pObj != null)
326                 {
327                         _ImageUriData* pImageUriData = dynamic_cast<_ImageUriData*>(pObj);
328                         if (pImageUriData != null)
329                         {
330                                 if (reqId == pImageUriData->GetRequestId())
331                                 {
332                                         pImageUriData->Cancel(reqId, r);
333                                         __pImageUriDataWorkingList->RemoveAt(i, true);
334                                         deleted = true;
335                                         break;
336                                 }
337                         }
338                 }
339         }
340
341         // If ImageUriData for this request id is not present in working list,
342         // remove it from the holder queue.
343         if (deleted != true)
344         {
345                 num = __pImageUriDataHolderQueue->GetCount();
346                 for (int i = 0; i < num; i++)
347                 {
348                         // Dequeue elements one by one to check for reqId.
349                         pObj = __pImageUriDataHolderQueue->Dequeue();
350                         if (pObj != null)
351                         {
352                                 _ImageUriData* pImageUriData = dynamic_cast<_ImageUriData*>(pObj);
353                                 if (pImageUriData != null)
354                                 {
355                                         if (reqId == pImageUriData->GetRequestId())
356                                         {
357                                                 pImageUriData->Cancel(reqId, r);
358                                                 delete pImageUriData;
359                                                 deleted = true;
360                                                 break;
361                                         }
362                                         // if Dequeued data does not have the same reqId, Enqueue is again.
363                                         __pImageUriDataHolderQueue->Enqueue(*pObj);
364                                 }
365                         }
366                 }
367         }
368
369         if(deleted != true)
370         {
371                 SysLog(NID_MEDIA, "Could not find ReqId %ld in both queues!!", reqId);
372         }
373 }
374
375 int
376 _ImageUriDataFactory::GetHolderCount(void)
377 {
378         int count = __pImageUriDataHolderQueue->GetCount();
379         return count;
380 }
381
382 int
383 _ImageUriDataFactory::GetWorkerCount(void)
384 {
385         int count = __pImageUriDataWorkingList->GetCount();
386         return count;
387 }
388
389 }} // Tizen::Media