use tdm_dump_enable variable to check if dump needed
[platform/core/uifw/libtdm.git] / src / tdm_helper.c
1 #ifdef HAVE_CONFIG_H
2 #include "config.h"
3 #endif
4
5 #include <png.h>
6 #include <string.h>
7 #include <tbm_surface.h>
8 #include <tbm_surface_internal.h>
9 #include <string.h>
10 #include <time.h>
11
12 #include "tdm.h"
13 #include "tdm_private.h"
14
15 #define PNG_DEPTH 8
16
17 static const char *dump_prefix[2] = {"png", "yuv"};
18
19 int tdm_dump_enable;
20 static int *tdm_helper_dump_count;
21 static char *tdm_helper_dump_path;
22
23 INTERN unsigned long
24 tdm_helper_get_time_in_millis(void)
25 {
26         struct timespec tp;
27
28         if (clock_gettime(CLOCK_MONOTONIC, &tp) == 0)
29                 return (tp.tv_sec * 1000) + (tp.tv_nsec / 1000000L);
30
31         return 0;
32 }
33
34 static void
35 _tdm_helper_dump_raw(const char *file, void *data1, int size1, void *data2,
36                      int size2, void *data3, int size3)
37 {
38         unsigned int *blocks;
39         FILE *fp = fopen(file, "w+");
40         TDM_RETURN_IF_FAIL(fp != NULL);
41
42         blocks = (unsigned int *)data1;
43         fwrite(blocks, 1, size1, fp);
44
45         if (size2 > 0) {
46                 blocks = (unsigned int *)data2;
47                 fwrite(blocks, 1, size2, fp);
48         }
49
50         if (size3 > 0) {
51                 blocks = (unsigned int *)data3;
52                 fwrite(blocks, 1, size3, fp);
53         }
54
55         fclose(fp);
56 }
57
58 static void
59 _tdm_helper_dump_png(const char *file, const void *data, int width,
60                      int height)
61 {
62         FILE *fp = fopen(file, "wb");
63         TDM_RETURN_IF_FAIL(fp != NULL);
64
65         png_structp pPngStruct =
66                 png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
67         if (!pPngStruct) {
68                 fclose(fp);
69                 return;
70         }
71
72         png_infop pPngInfo = png_create_info_struct(pPngStruct);
73         if (!pPngInfo) {
74                 png_destroy_write_struct(&pPngStruct, NULL);
75                 fclose(fp);
76                 return;
77         }
78
79         png_init_io(pPngStruct, fp);
80         png_set_IHDR(pPngStruct,
81                      pPngInfo,
82                      width,
83                      height,
84                      PNG_DEPTH,
85                      PNG_COLOR_TYPE_RGBA,
86                      PNG_INTERLACE_NONE,
87                      PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
88
89         png_set_bgr(pPngStruct);
90         png_write_info(pPngStruct, pPngInfo);
91
92         const int pixel_size = 4;       // RGBA
93         png_bytep *row_pointers =
94                 png_malloc(pPngStruct, height * sizeof(png_byte *));
95
96         unsigned int *blocks = (unsigned int *)data;
97         int y = 0;
98         int x = 0;
99
100         for (; y < height; ++y) {
101                 png_bytep row =
102                         png_malloc(pPngStruct, sizeof(png_byte) * width * pixel_size);
103                 row_pointers[y] = (png_bytep)row;
104                 for (x = 0; x < width; ++x) {
105                         unsigned int curBlock = blocks[y * width + x];
106                         row[x * pixel_size] = (curBlock & 0xFF);
107                         row[1 + x * pixel_size] = (curBlock >> 8) & 0xFF;
108                         row[2 + x * pixel_size] = (curBlock >> 16) & 0xFF;
109                         row[3 + x * pixel_size] = (curBlock >> 24) & 0xFF;
110                 }
111         }
112
113         png_write_image(pPngStruct, row_pointers);
114         png_write_end(pPngStruct, pPngInfo);
115
116         for (y = 0; y < height; y++)
117                 png_free(pPngStruct, row_pointers[y]);
118         png_free(pPngStruct, row_pointers);
119
120         png_destroy_write_struct(&pPngStruct, &pPngInfo);
121
122         fclose(fp);
123 }
124
125 EXTERN void
126 tdm_helper_dump_buffer(tbm_surface_h buffer, const char *file)
127 {
128         tbm_surface_info_s info;
129         int len, ret;
130         const char *prefix;
131
132         TDM_RETURN_IF_FAIL(buffer != NULL);
133         TDM_RETURN_IF_FAIL(file != NULL);
134
135         ret = tbm_surface_map(buffer, TBM_DEVICE_CPU, &info);
136         TDM_RETURN_IF_FAIL(ret == TBM_SURFACE_ERROR_NONE);
137
138         len = strnlen(file, 1024);
139         if (info.format == TBM_FORMAT_ARGB8888 || info.format == TBM_FORMAT_XRGB8888)
140                 prefix = dump_prefix[0];
141         else
142                 prefix = dump_prefix[1];
143
144         if (strncmp(file + (len - 3), prefix, 3)) {
145                 TDM_ERR("can't dump to '%s' file", file + (len - 3));
146                 tbm_surface_unmap(buffer);
147                 return;
148         }
149
150         switch (info.format) {
151         case TBM_FORMAT_ARGB8888:
152         case TBM_FORMAT_XRGB8888:
153                 _tdm_helper_dump_png(file, info.planes[0].ptr,
154                                      info.planes[0].stride >> 2, info.height);
155                 break;
156         case TBM_FORMAT_YVU420:
157         case TBM_FORMAT_YUV420:
158                 _tdm_helper_dump_raw(file,
159                                      info.planes[0].ptr,
160                                      info.planes[0].stride * info.height,
161                                      info.planes[1].ptr,
162                                      info.planes[1].stride * (info.height >> 1),
163                                      info.planes[2].ptr,
164                                      info.planes[2].stride * (info.height >> 1));
165                 break;
166         case TBM_FORMAT_NV12:
167         case TBM_FORMAT_NV21:
168                 _tdm_helper_dump_raw(file,
169                                      info.planes[0].ptr,
170                                      info.planes[0].stride * info.height,
171                                      info.planes[1].ptr,
172                                      info.planes[1].stride * (info.height >> 1), NULL,
173                                      0);
174                 break;
175         case TBM_FORMAT_YUYV:
176         case TBM_FORMAT_UYVY:
177                 _tdm_helper_dump_raw(file,
178                                      info.planes[0].ptr,
179                                      info.planes[0].stride * info.height, NULL, 0,
180                                      NULL, 0);
181                 break;
182         default:
183                 TDM_ERR("can't dump %c%c%c%c buffer", FOURCC_STR (info.format));
184                 tbm_surface_unmap(buffer);
185                 return;
186         }
187
188         tbm_surface_unmap(buffer);
189
190         TDM_INFO("dump %s", file);
191 }
192
193 EXTERN int
194 tdm_helper_get_fd(const char *env)
195 {
196         const char *value;
197         int fd, newfd, flags, ret;
198
199         value = (const char*)getenv(env);
200         if (!value)
201                 return -1;
202
203         ret = sscanf(value, "%d", &fd);
204         if (ret < 0) {
205                 TDM_ERR("sscanf failed: %m");
206                 return -1;
207         }
208
209         flags = fcntl(fd, F_GETFD);
210         if (flags == -1) {
211                 TDM_ERR("fcntl failed: %m");
212                 return -1;
213         }
214
215         newfd = dup(fd);
216         if (newfd < 0) {
217                 TDM_ERR("dup failed: %m");
218                 return -1;
219         }
220
221         TDM_INFO("%s: fd(%d) newfd(%d)", env, fd, newfd);
222
223         fcntl(newfd, F_SETFD, flags | FD_CLOEXEC);
224
225         return newfd;
226 }
227
228 EXTERN void
229 tdm_helper_set_fd(const char *env, int fd)
230 {
231         char buf[32];
232         int ret;
233
234         snprintf(buf, sizeof(buf), "%d", fd);
235
236         ret = setenv(env, (const char*)buf, 1);
237         if (ret) {
238                 TDM_ERR("setenv failed: %m");
239                 return;
240         }
241
242         if (fd >= 0)
243                 TDM_INFO("%s: fd(%d)", env, fd);
244 }
245
246 EXTERN void
247 tdm_helper_dump_start(char *dumppath, int *count)
248 {
249         if (tdm_helper_dump_count != NULL) {
250                 TDM_DBG("tdm_helper_dump is already started.");
251                 return;
252         }
253
254         if (dumppath == NULL) {
255                 TDM_DBG("tdm_helper_dump dumppath is null.");
256                 return;
257         }
258
259         tdm_helper_dump_count = count;
260         tdm_helper_dump_path = dumppath;
261
262         tdm_dump_enable = 1;
263
264         TDM_DBG("tdm_helper_dump start.(path : %s)", tdm_helper_dump_path);
265 }
266
267 EXTERN void
268 tdm_helper_dump_stop(void)
269 {
270         tdm_helper_dump_path = NULL;
271         tdm_helper_dump_count = NULL;
272
273         tdm_dump_enable = 0;
274
275         TDM_DBG("tdm_helper_dump stop.");
276 }
277
278 INTERN int
279 tdm_helper_get_dump_count(void)
280 {
281         if ((tdm_helper_dump_count != NULL) && (tdm_helper_dump_path != NULL)) {
282                 if (*tdm_helper_dump_count == 1000)
283                         *tdm_helper_dump_count = 1;
284                 return (*tdm_helper_dump_count)++;
285         } else
286                 return 0;
287 }
288
289 INTERN char *
290 tdm_helper_get_dump_path(void)
291 {
292         return tdm_helper_dump_path;
293 }