1 /*****************************************************************************
2  * Copyright (C) 2013-2020 MulticoreWare, Inc
3  *
4  * Authors: Deepthi Nandakumar <deepthi@multicorewareinc.com>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111, USA.
19  *
20  * This program is also available under a commercial proprietary license.
21  * For more information, contact us at license @ x265.com.
22  *****************************************************************************/
23 
24 #include "common.h"
25 #include "slice.h"
26 #include "threading.h"
27 #include "x265.h"
28 
29 #if _WIN32
30 #include <sys/types.h>
31 #include <sys/timeb.h>
32 #include <io.h>
33 #include <fcntl.h>
34 #else
35 #include <sys/time.h>
36 #endif
37 
38 namespace X265_NS {
39 
40 #if CHECKED_BUILD || _DEBUG
41 int g_checkFailures;
42 #endif
43 
x265_mdate(void)44 int64_t x265_mdate(void)
45 {
46 #if _WIN32
47     struct timeb tb;
48     ftime(&tb);
49     return ((int64_t)tb.time * 1000 + (int64_t)tb.millitm) * 1000;
50 #else
51     struct timeval tv_date;
52     gettimeofday(&tv_date, NULL);
53     return (int64_t)tv_date.tv_sec * 1000000 + (int64_t)tv_date.tv_usec;
54 #endif
55 }
56 
57 #define X265_ALIGNBYTES 64
58 
59 #if _WIN32
60 #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR)
61 #define _aligned_malloc __mingw_aligned_malloc
62 #define _aligned_free   __mingw_aligned_free
63 #include "malloc.h"
64 #endif
65 
x265_malloc(size_t size)66 void *x265_malloc(size_t size)
67 {
68     return _aligned_malloc(size, X265_ALIGNBYTES);
69 }
70 
x265_free(void * ptr)71 void x265_free(void *ptr)
72 {
73     if (ptr) _aligned_free(ptr);
74 }
75 
76 #else // if _WIN32
x265_malloc(size_t size)77 void *x265_malloc(size_t size)
78 {
79     void *ptr;
80 
81     if (posix_memalign((void**)&ptr, X265_ALIGNBYTES, size) == 0)
82         return ptr;
83     else
84         return NULL;
85 }
86 
x265_free(void * ptr)87 void x265_free(void *ptr)
88 {
89     if (ptr) free(ptr);
90 }
91 
92 #endif // if _WIN32
93 
94 /* Not a general-purpose function; multiplies input by -1/6 to convert
95  * qp to qscale. */
x265_exp2fix8(double x)96 int x265_exp2fix8(double x)
97 {
98     int i = (int)(x * (-64.f / 6.f) + 512.5f);
99 
100     if (i < 0) return 0;
101     if (i > 1023) return 0xffff;
102     return (x265_exp2_lut[i & 63] + 256) << (i >> 6) >> 8;
103 }
104 
general_log(const x265_param * param,const char * caller,int level,const char * fmt,...)105 void general_log(const x265_param* param, const char* caller, int level, const char* fmt, ...)
106 {
107     if (param && level > param->logLevel)
108         return;
109     const int bufferSize = 4096;
110     char buffer[bufferSize];
111     int p = 0;
112     const char* log_level;
113     switch (level)
114     {
115     case X265_LOG_ERROR:
116         log_level = "error";
117         break;
118     case X265_LOG_WARNING:
119         log_level = "warning";
120         break;
121     case X265_LOG_INFO:
122         log_level = "info";
123         break;
124     case X265_LOG_DEBUG:
125         log_level = "debug";
126         break;
127     case X265_LOG_FULL:
128         log_level = "full";
129         break;
130     default:
131         log_level = "unknown";
132         break;
133     }
134 
135     if (caller)
136         p += sprintf(buffer, "%-4s [%s]: ", caller, log_level);
137     va_list arg;
138     va_start(arg, fmt);
139     vsnprintf(buffer + p, bufferSize - p, fmt, arg);
140     va_end(arg);
141     fputs(buffer, stderr);
142 }
143 
144 #if _WIN32
145 /* For Unicode filenames in Windows we convert UTF-8 strings to UTF-16 and we use _w functions.
146  * For other OS we do not make any changes. */
general_log_file(const x265_param * param,const char * caller,int level,const char * fmt,...)147 void general_log_file(const x265_param* param, const char* caller, int level, const char* fmt, ...)
148 {
149     if (param && level > param->logLevel)
150         return;
151     const int bufferSize = 4096;
152     char buffer[bufferSize];
153     int p = 0;
154     const char* log_level;
155     switch (level)
156     {
157     case X265_LOG_ERROR:
158         log_level = "error";
159         break;
160     case X265_LOG_WARNING:
161         log_level = "warning";
162         break;
163     case X265_LOG_INFO:
164         log_level = "info";
165         break;
166     case X265_LOG_DEBUG:
167         log_level = "debug";
168         break;
169     case X265_LOG_FULL:
170         log_level = "full";
171         break;
172     default:
173         log_level = "unknown";
174         break;
175     }
176 
177     if (caller)
178         p += sprintf(buffer, "%-4s [%s]: ", caller, log_level);
179     va_list arg;
180     va_start(arg, fmt);
181     vsnprintf(buffer + p, bufferSize - p, fmt, arg);
182     va_end(arg);
183 
184     HANDLE console = GetStdHandle(STD_ERROR_HANDLE);
185     DWORD mode;
186     if (GetConsoleMode(console, &mode))
187     {
188         wchar_t buf_utf16[bufferSize];
189         int length_utf16 = MultiByteToWideChar(CP_UTF8, 0, buffer, -1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)) - 1;
190         if (length_utf16 > 0)
191             WriteConsoleW(console, buf_utf16, length_utf16, &mode, NULL);
192     }
193     else
194         fputs(buffer, stderr);
195 }
196 
x265_fopen(const char * fileName,const char * mode)197 FILE* x265_fopen(const char* fileName, const char* mode)
198 {
199     wchar_t buf_utf16[MAX_PATH * 2], mode_utf16[16];
200 
201     if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)) &&
202         MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, mode, -1, mode_utf16, sizeof(mode_utf16)/sizeof(wchar_t)))
203     {
204         return _wfopen(buf_utf16, mode_utf16);
205     }
206     return NULL;
207 }
208 
x265_unlink(const char * fileName)209 int x265_unlink(const char* fileName)
210 {
211     wchar_t buf_utf16[MAX_PATH * 2];
212 
213     if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, fileName, -1, buf_utf16, sizeof(buf_utf16)/sizeof(wchar_t)))
214         return _wunlink(buf_utf16);
215 
216     return -1;
217 }
218 
x265_rename(const char * oldName,const char * newName)219 int x265_rename(const char* oldName, const char* newName)
220 {
221     wchar_t old_utf16[MAX_PATH * 2], new_utf16[MAX_PATH * 2];
222 
223     if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, oldName, -1, old_utf16, sizeof(old_utf16)/sizeof(wchar_t)) &&
224         MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, newName, -1, new_utf16, sizeof(new_utf16)/sizeof(wchar_t)))
225     {
226         return _wrename(old_utf16, new_utf16);
227     }
228     return -1;
229 }
230 #endif
231 
x265_ssim2dB(double ssim)232 double x265_ssim2dB(double ssim)
233 {
234     double inv_ssim = 1 - ssim;
235 
236     if (inv_ssim <= 0.0000000001) /* Max 100dB */
237         return 100;
238 
239     return -10.0 * log10(inv_ssim);
240 }
241 
242 /* The qscale - qp conversion is specified in the standards.
243  * Approx qscale increases by 12%  with every qp increment */
x265_qScale2qp(double qScale)244 double x265_qScale2qp(double qScale)
245 {
246     return 12.0 + 6.0 * (double)X265_LOG2(qScale / 0.85);
247 }
248 
x265_qp2qScale(double qp)249 double x265_qp2qScale(double qp)
250 {
251     return 0.85 * pow(2.0, (qp - 12.0) / 6.0);
252 }
253 
x265_picturePlaneSize(int csp,int width,int height,int plane)254 uint32_t x265_picturePlaneSize(int csp, int width, int height, int plane)
255 {
256     uint32_t size = (uint32_t)(width >> x265_cli_csps[csp].width[plane]) * (height >> x265_cli_csps[csp].height[plane]);
257 
258     return size;
259 }
260 
x265_slurp_file(const char * filename)261 char* x265_slurp_file(const char *filename)
262 {
263     if (!filename)
264         return NULL;
265 
266     int bError = 0;
267     size_t fSize;
268     char *buf = NULL;
269 
270     FILE *fh = x265_fopen(filename, "rb");
271     if (!fh)
272     {
273         x265_log_file(NULL, X265_LOG_ERROR, "unable to open file %s\n", filename);
274         return NULL;
275     }
276 
277     bError |= fseek(fh, 0, SEEK_END) < 0;
278     bError |= (fSize = ftell(fh)) <= 0;
279     bError |= fseek(fh, 0, SEEK_SET) < 0;
280     if (bError)
281         goto error;
282 
283     buf = X265_MALLOC(char, fSize + 2);
284     if (!buf)
285     {
286         x265_log(NULL, X265_LOG_ERROR, "unable to allocate memory\n");
287         goto error;
288     }
289 
290     bError |= fread(buf, 1, fSize, fh) != fSize;
291     if (buf[fSize - 1] != '\n')
292         buf[fSize++] = '\n';
293     buf[fSize] = 0;
294     fclose(fh);
295 
296     if (bError)
297     {
298         x265_log(NULL, X265_LOG_ERROR, "unable to read the file\n");
299         X265_FREE(buf);
300         buf = NULL;
301     }
302     return buf;
303 
304 error:
305     fclose(fh);
306     return NULL;
307 }
308 
309 }
310