1 #include <stdio.h>
2 #include <signal.h>
3 #include <string.h>
4 #include "lib_ccx.h"
5 #include "ccx_common_option.h"
6 #include "activity.h"
7 #include "utility.h"
8 
9 int temp_debug = 0; // This is a convenience variable used to enable/disable debug on variable conditions. Find references to understand.
10 volatile sig_atomic_t change_filename_requested = 0;
11 
12 
13 static uint32_t crc32_table [] = {
14     0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9,
15     0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005,
16     0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
17     0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd,
18     0x4c11db70, 0x48d0c6c7, 0x4593e01e, 0x4152fda9,
19     0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75,
20     0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011,
21     0x791d4014, 0x7ddc5da3, 0x709f7b7a, 0x745e66cd,
22     0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039,
23     0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5,
24     0xbe2b5b58, 0xbaea46ef, 0xb7a96036, 0xb3687d81,
25     0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d,
26     0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49,
27     0xc7361b4c, 0xc3f706fb, 0xceb42022, 0xca753d95,
28     0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1,
29     0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d,
30     0x34867077, 0x30476dc0, 0x3d044b19, 0x39c556ae,
31     0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072,
32     0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16,
33     0x018aeb13, 0x054bf6a4, 0x0808d07d, 0x0cc9cdca,
34     0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde,
35     0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02,
36     0x5e9f46bf, 0x5a5e5b08, 0x571d7dd1, 0x53dc6066,
37     0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba,
38     0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e,
39     0xbfa1b04b, 0xbb60adfc, 0xb6238b25, 0xb2e29692,
40     0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6,
41     0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a,
42     0xe0b41de7, 0xe4750050, 0xe9362689, 0xedf73b3e,
43     0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2,
44     0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686,
45     0xd5b88683, 0xd1799b34, 0xdc3abded, 0xd8fba05a,
46     0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637,
47     0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb,
48     0x4f040d56, 0x4bc510e1, 0x46863638, 0x42472b8f,
49     0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53,
50     0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47,
51     0x36194d42, 0x32d850f5, 0x3f9b762c, 0x3b5a6b9b,
52     0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff,
53     0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623,
54     0xf12f560e, 0xf5ee4bb9, 0xf8ad6d60, 0xfc6c70d7,
55     0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b,
56     0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f,
57     0xc423cd6a, 0xc0e2d0dd, 0xcda1f604, 0xc960ebb3,
58     0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7,
59     0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b,
60     0x9b3660c6, 0x9ff77d71, 0x92b45ba8, 0x9675461f,
61     0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3,
62     0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640,
63     0x4e8ee645, 0x4a4ffbf2, 0x470cdd2b, 0x43cdc09c,
64     0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8,
65     0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24,
66     0x119b4be9, 0x155a565e, 0x18197087, 0x1cd86d30,
67     0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec,
68     0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088,
69     0x2497d08d, 0x2056cd3a, 0x2d15ebe3, 0x29d4f654,
70     0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0,
71     0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c,
72     0xe3a1cbc1, 0xe760d676, 0xea23f0af, 0xeee2ed18,
73     0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4,
74     0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0,
75     0x9abc8bd5, 0x9e7d9662, 0x933eb0bb, 0x97ffad0c,
76     0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668,
77     0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4
78 };
79 
verify_crc32(uint8_t * buf,int len)80 int verify_crc32(uint8_t *buf, int len)
81 {
82 	int i = 0;
83 	int32_t crc = -1;
84 	for (i = 0; i < len; i++)
85 		crc = (crc << 8) ^ crc32_table[((crc >> 24) ^ (buf[i] & 0xff)) & 0xff];
86 	return crc?CCX_FALSE:CCX_TRUE;
87 }
stringztoms(const char * s,struct ccx_boundary_time * bt)88 int stringztoms (const char *s, struct ccx_boundary_time *bt)
89 {
90 	unsigned ss=0, mm=0, hh=0;
91 	int value=-1;
92 	int colons=0;
93 	const char *c=s;
94 	while (*c)
95 	{
96 		if (*c==':')
97 		{
98 			if (value==-1) // : at the start, or ::, etc
99 				return -1;
100 			colons++;
101 			if (colons>2) // Max 2, for HH:MM:SS
102 				return -1;
103 			hh=mm;
104 			mm=ss;
105 			ss=value;
106 			value=-1;
107 		}
108 		else
109 		{
110 			if (!isdigit (*c)) // Only : or digits, so error
111 				return -1;
112 			if (value==-1)
113 				value=*c-'0';
114 			else
115 				value=value*10+*c-'0';
116 		}
117 		c++;
118 	}
119 	hh = mm;
120 	mm = ss;
121 	ss = value;
122 	if (mm > 59 || ss > 59)
123 		return -1;
124 	bt->set = 1;
125 	bt->hh = hh;
126 	bt->mm = mm;
127 	bt->ss = ss;
128 	LLONG secs = (hh * 3600 + mm * 60 + ss);
129 	bt->time_in_ms = secs*1000;
130 	return 0;
131 }
timestamp_to_srttime(uint64_t timestamp,char * buffer)132 void timestamp_to_srttime(uint64_t timestamp, char *buffer)
133 {
134 	uint64_t p = timestamp;
135 	uint8_t h = (uint8_t) (p / 3600000);
136 	uint8_t m = (uint8_t) (p / 60000 - 60 * h);
137 	uint8_t s = (uint8_t) (p / 1000 - 3600 * h - 60 * m);
138 	uint16_t u = (uint16_t) (p - 3600000 * h - 60000 * m - 1000 * s);
139 	sprintf(buffer, "%02"PRIu8":%02"PRIu8":%02"PRIu8",%03"PRIu16, h, m, s, u);
140 }
141 
timestamp_to_smptetttime(uint64_t timestamp,char * buffer)142 void timestamp_to_smptetttime(uint64_t timestamp, char *buffer)
143 {
144 	uint64_t p = timestamp;
145 	uint8_t h = (uint8_t) (p / 3600000);
146 	uint8_t m = (uint8_t) (p / 60000 - 60 * h);
147 	uint8_t s = (uint8_t) (p / 1000 - 3600 * h - 60 * m);
148 	uint16_t u = (uint16_t) (p - 3600000 * h - 60000 * m - 1000 * s);
149 	sprintf(buffer, "%02"PRIu8":%02"PRIu8":%02"PRIu8".%03"PRIu16, h, m, s, u);
150 }
151 
152 #define MIN3(a, b, c) ((a) < (b) ? ((a) < (c) ? (a) : (c)) : ((b) < (c) ? (b) : (c)))
153 
levenshtein_dist(const uint64_t * s1,const uint64_t * s2,unsigned s1len,unsigned s2len)154 int levenshtein_dist (const uint64_t *s1, const uint64_t *s2, unsigned s1len, unsigned s2len)
155 {
156 	unsigned int x, y, v, lastdiag, olddiag;
157 	unsigned int *column = (unsigned *) malloc ((s1len+1)*sizeof (unsigned int));
158 	for (y = 1; y <= s1len; y++)
159 		column[y] = y;
160 	for (x = 1; x <= s2len; x++)
161 	{
162 		column[0] = x;
163 		for (y = 1, lastdiag = x-1; y <= s1len; y++)
164 		{
165 			olddiag = column[y];
166 			column[y] = MIN3(column[y] + 1, column[y-1] + 1, lastdiag + (s1[y-1] == s2[x-1] ? 0 : 1));
167 			lastdiag = olddiag;
168 		}
169 	}
170 	v = column[s1len];
171 	free (column);
172 	return v;
173 }
174 
levenshtein_dist_char(const char * s1,const char * s2,unsigned s1len,unsigned s2len)175 int levenshtein_dist_char (const char *s1, const char *s2, unsigned s1len, unsigned s2len)
176 {
177 	unsigned int x, y, v, lastdiag, olddiag;
178 	unsigned int *column = (unsigned *) malloc ((s1len+1)*sizeof (unsigned int));
179 	for (y = 1; y <= s1len; y++)
180 		column[y] = y;
181 	for (x = 1; x <= s2len; x++)
182 	{
183 		column[0] = x;
184 		for (y = 1, lastdiag = x-1; y <= s1len; y++)
185 		{
186 			olddiag = column[y];
187 			column[y] = MIN3(column[y] + 1, column[y-1] + 1, lastdiag + (s1[y-1] == s2[x-1] ? 0 : 1));
188 			lastdiag = olddiag;
189 		}
190 	}
191 	v = column[s1len];
192 	free (column);
193 	return v;
194 }
195 
millis_to_date(uint64_t timestamp,char * buffer,enum ccx_output_date_format date_format,char millis_separator)196 void millis_to_date (uint64_t timestamp, char *buffer, enum ccx_output_date_format date_format, char millis_separator)
197 {
198 	time_t secs;
199 	unsigned int millis;
200 	char c_temp[80];
201 	struct tm *time_struct=NULL;
202 	switch (date_format)
203 	{
204 		case ODF_NONE:
205 			buffer[0] = 0;
206 			break;
207 		case ODF_HHMMSS:
208 			timestamp_to_srttime (timestamp, buffer);
209 			buffer[8] = 0;
210 			break;
211 		case ODF_HHMMSSMS:
212 			timestamp_to_srttime (timestamp, buffer);
213 			break;
214 		case ODF_SECONDS:
215 			secs = (time_t) (timestamp/1000);
216 			millis = (time_t) (timestamp%1000);
217 			sprintf (buffer, "%lu%c%03u", (unsigned long) secs,
218 					millis_separator, (unsigned) millis);
219 			break;
220 		case ODF_DATE:
221 			secs = (time_t) (timestamp/1000);
222 			millis = (unsigned int) (timestamp%1000);
223 			time_struct = gmtime(&secs);
224 			strftime(c_temp, sizeof(c_temp), "%Y%m%d%H%M%S", time_struct);
225 			sprintf (buffer, "%s%c%03u", c_temp, millis_separator, millis);
226 			break;
227 
228 		default:
229 			fatal(CCX_COMMON_EXIT_BUG_BUG, "Invalid value for date_format in millis_to_date()\n");
230 	}
231 }
232 
in_array(uint16_t * array,uint16_t length,uint16_t element)233 bool_t in_array(uint16_t *array, uint16_t length, uint16_t element)
234 {
235 	bool_t r = NO;
236 	for (uint16_t i = 0; i < length; i++)
237 		if (array[i] == element)
238 		{
239 			r = YES;
240 			break;
241 		}
242 	return r;
243 }
244 
print_error(int mode,const char * fmt,...)245 void print_error (int mode, const char *fmt, ...)
246 {
247 	va_list args;
248 	va_start(args, fmt);
249 	if (mode)
250 		fprintf(stderr,"###MESSAGE#");
251 	else
252 		fprintf(stderr, "\rError: ");
253 	vfprintf(stderr, fmt, args);
254 	fprintf(stderr, "\n");
255 	va_end(args);
256 }
257 /* Write formatted message to stderr and then exit. */
fatal(int exit_code,const char * fmt,...)258 void fatal(int exit_code, const char *fmt, ...)
259 {
260 	va_list args;
261 	va_start(args, fmt);
262 	if (ccx_options.gui_mode_reports)
263 		fprintf(stderr,"###MESSAGE#");
264 	else
265 		fprintf(stderr, "\rError: ");
266 	vfprintf(stderr, fmt, args);
267 	fprintf(stderr, "\n");
268 	va_end(args);
269 	exit(exit_code);
270 }
271 
272 /* General output, replacement for printf so we can control globally where messages go.
273    mprint => Message print */
mprint(const char * fmt,...)274 void mprint (const char *fmt, ...)
275 {
276 	va_list args;
277 	if (!ccx_options.messages_target)
278 		return;
279 	activity_header(); // Brag about writing it :-)
280 	va_start(args, fmt);
281 	if (ccx_options.messages_target==CCX_MESSAGES_STDOUT)
282 	{
283 		vfprintf(stdout, fmt, args);
284 		fflush (stdout);
285 	}
286 	else
287 	{
288 		vfprintf(stderr, fmt, args);
289 		fflush (stderr);
290 	}
291 	va_end(args);
292 }
293 
294 /* Shorten some debug output code. */
dbg_print(LLONG mask,const char * fmt,...)295 void dbg_print(LLONG mask, const char *fmt, ...)
296 {
297 	va_list args;
298 	LLONG t;
299 	if (!ccx_options.messages_target)
300 		return;
301 	t = temp_debug ? (ccx_options.debug_mask_on_debug | ccx_options.debug_mask) : ccx_options.debug_mask; // Mask override?
302 
303 	if(mask & t)
304 	{
305 		va_start(args, fmt);
306 		if (ccx_options.messages_target==CCX_MESSAGES_STDOUT)
307 		{
308 			vfprintf(stdout, fmt, args);
309 			fflush (stdout);
310 		}
311 		else
312 		{
313 			vfprintf(stderr, fmt, args);
314 			fflush (stderr);
315 		}
316 		va_end(args);
317 	}
318 }
319 
dump(LLONG mask,unsigned char * start,int l,unsigned long abs_start,unsigned clear_high_bit)320 void dump (LLONG mask, unsigned char *start, int l, unsigned long abs_start, unsigned clear_high_bit)
321 {
322 	LLONG t=temp_debug ? (ccx_options.debug_mask_on_debug | ccx_options.debug_mask) : ccx_options.debug_mask; // Mask override?
323 	if(! (mask & t))
324 		return;
325 
326 	for (int x=0; x<l; x=x+16)
327 	{
328 		mprint ("%08ld | ",x+abs_start);
329 		for (int j=0; j<16; j++)
330 		{
331 			if (x+j<l)
332 				mprint ("%02X ",start[x+j]);
333 			else
334 				mprint ("   ");
335 		}
336 		mprint (" | ");
337 		for (int j=0; j<16; j++)
338 		{
339 			if (x+j<l && start[x+j]>=' ')
340 				mprint ("%c", start[x+j] & (clear_high_bit ? 0x7F : 0xFF)); // 0x7F < remove high bit, convenient for visual CC inspection
341 			else
342 				mprint (" ");
343 		}
344 		mprint ("\n");
345 	}
346 }
347 
init_boundary_time(struct ccx_boundary_time * bt)348 void init_boundary_time (struct ccx_boundary_time *bt)
349 {
350 	bt->hh = 0;
351 	bt->mm = 0;
352 	bt->ss = 0;
353 	bt->set = 0;
354 	bt->time_in_ms = 0;
355 }
356 
357 
sleep_secs(int secs)358 void sleep_secs (int secs)
359 {
360 #ifdef _WIN32
361 	Sleep(secs * 1000);
362 #else
363 	sleep(secs);
364 #endif
365 }
366 
hex_to_int(char high,char low)367 int hex_to_int (char high, char low)
368 {
369 	unsigned char h,l;
370 	if (high >= '0' && high <= '9')
371 		h = high-'0';
372 	else if (high >= 'a' && high <= 'f')
373 		h = high-'a'+10;
374 	else
375 		return -1;
376 	if (low >= '0' && low <= '9')
377 		l = low - '0';
378 	else if (low >= 'a' && low <= 'f')
379 		l = low - 'a'+10;
380 	else
381 		return -1;
382 	return h * 16+l;
383 }
hex_string_to_int(char * string,int len)384 int hex_string_to_int(char* string, int len)
385 {
386   int total_return = 0;
387   while(*string && len-- > 0 && total_return >= 0){
388     unsigned char c = *string;
389     if(c >= '0' && c <= '9')
390       total_return = total_return * 16 + (c - '0');
391     else if(*string >= 'a' && *string <= 'f')
392       total_return = total_return * 16 + (c - 'a' + 10);
393     else
394       total_return = -1;
395     string++;
396   }
397   return total_return;
398 }
399 
400 #ifndef _WIN32
m_signal(int sig,void (* func)(int))401 void m_signal(int sig, void (*func)(int))
402 {
403 	struct sigaction act;
404 	act.sa_handler = func;
405 	sigemptyset(&act.sa_mask);
406 	act.sa_flags = 0;
407 
408 	if (sigaction(sig, &act, NULL))
409 		perror("sigaction() error");
410 
411 	return;
412 }
413 
create_signal(int sigtype)414 void create_signal(int sigtype)
415 {
416 	if (signal(sigtype, signal_handler) == SIG_ERR)
417 		mprint("Can't catch signal %d.\n", sigtype);
418 }
419 
signal_handler(int sig_type)420 void signal_handler(int sig_type)
421 {
422 	int ret;
423 
424         if (sig_type == SIGUSR1)
425         {
426         	mprint("Caught SIGUSR1. Filename Change Requested\n");
427         	change_filename_requested = 1;
428         }
429 }
430 #endif
431 
change_filename(struct encoder_ctx * enc_ctx)432 struct encoder_ctx *change_filename(struct encoder_ctx *enc_ctx)
433 {
434 	if(change_filename_requested == 0)
435 	{
436 		return enc_ctx;
437 	}
438 	struct encoder_ctx *temp_encoder = malloc(sizeof(struct encoder_ctx));
439 	*temp_encoder = *enc_ctx;
440 	if (enc_ctx->out->fh != -1)
441 	{
442 		if (enc_ctx->out->fh > 0)
443 			close(enc_ctx->out->fh);
444 		enc_ctx->out->fh=-1;
445 		int iter;
446 		char str_number[15];
447 		char *current_name = malloc(sizeof(char)*(strlen(enc_ctx->out->filename)+10));
448 		strcpy(current_name,enc_ctx->out->filename);
449 		mprint ("Creating %s\n", enc_ctx->out->filename);
450 		if(enc_ctx->out->renaming_extension)
451 		{
452 			strcat(current_name,".");
453 			sprintf(str_number, "%d", enc_ctx->out->renaming_extension);
454 			strcat(current_name,str_number);
455 		}
456 		enc_ctx->out->renaming_extension++;
457 		for (iter = enc_ctx->out->renaming_extension; iter >= 1; iter--)
458 		{
459 			int ret;
460 			char new_extension[6];
461 			sprintf(new_extension, ".%d", iter);
462 			char *newname = malloc(sizeof(char)*(strlen(enc_ctx->out->filename)+10));
463 			strcpy(newname,enc_ctx->out->filename);
464 			strcat(newname,new_extension);
465 			ret = rename(current_name, newname);
466 			if(ret)
467 			{
468 				mprint("Failed to rename the file\n");
469 
470 			}
471 			mprint ("Creating %s\n", newname);
472 			strcpy(current_name,enc_ctx->out->filename);
473 
474 			if(iter-2>0)
475 			{
476 				strcat(current_name,".");
477 				sprintf(str_number, "%d", iter-2);
478 				strcat(current_name,str_number);
479 			}
480 			free(newname);
481 
482 		}
483 
484 		enc_ctx->out->fh = open(enc_ctx->out->filename, O_RDWR | O_CREAT | O_TRUNC | O_BINARY, S_IREAD | S_IWRITE);
485 		free(current_name);
486 		if (enc_ctx->out->fh == -1)
487 		{
488 			mprint("Failed to create a new rotation file\n");
489 			return temp_encoder;
490 		}
491 		free(temp_encoder);
492 		change_filename_requested = 0;
493 		return enc_ctx;
494 
495 	}
496 	return temp_encoder;
497 }
get_basename(char * filename)498 char *get_basename(char *filename)
499 {
500 	char *c;
501 	int len;
502 	char *basefilename;
503 
504 	if(!filename)
505 		return NULL;
506 
507 	len = strlen(filename);
508 	basefilename = (char *) malloc(len+1);
509 	if (basefilename == NULL)
510 	{
511 		return NULL;
512 	}
513 
514 	strcpy (basefilename, filename);
515 
516 	for (c = basefilename + len; c > basefilename && *c != '.'; c--)
517 	{;} // Get last .
518 	if (*c == '.')
519 		*c = 0;
520 
521 	return basefilename;
522 }
523 
get_file_extension(enum ccx_output_format write_format)524 char *get_file_extension(enum ccx_output_format write_format)
525 {
526 	switch (write_format)
527 	{
528 		case CCX_OF_RAW:
529 			return strdup(".raw");
530 		case CCX_OF_SRT:
531 			return strdup(".srt");
532 		case CCX_OF_SSA:
533 			return strdup(".ass");
534 		case CCX_OF_WEBVTT:
535 			return strdup (".vtt");
536 		case CCX_OF_SAMI:
537 			return strdup(".smi");
538 		case CCX_OF_SMPTETT:
539 			return strdup(".ttml");
540 		case CCX_OF_TRANSCRIPT:
541 			return strdup(".txt");
542 		case CCX_OF_RCWT:
543 			return strdup(".bin");
544 		case CCX_OF_SPUPNG:
545 			return strdup(".xml");
546 		case CCX_OF_DVDRAW:
547 			return strdup(".dvdraw");
548 		case CCX_OF_SIMPLE_XML:
549 			return strdup(".xml");
550 		case CCX_OF_G608:
551 			return strdup(".g608");
552 		case CCX_OF_NULL:
553 			return NULL;
554 		case CCX_OF_CURL:
555 			return NULL;
556 		default:
557 			fatal (CCX_COMMON_EXIT_BUG_BUG, "write_format doesn't have any legal value, this is a bug.\n");
558 			errno = EINVAL;
559 			return NULL;
560 	}
561 	return 0;
562 }
563 
create_outfilename(const char * basename,const char * suffix,const char * extension)564 char *create_outfilename(const char *basename, const char *suffix, const char *extension)
565 {
566 	char *ptr = NULL;
567 	size_t blen, slen, elen;
568 
569 	if(basename)
570 		blen = strlen(basename);
571 	else
572 		blen = 0;
573 
574 	if(suffix)
575 		slen = strlen(suffix);
576 	else
577 		slen = 0;
578 
579 	if(extension)
580 		elen = strlen(extension);
581 	else
582 		elen = 0;
583 	if ( (elen + slen + blen) <= 0)
584 		return NULL;
585 
586 	ptr = malloc(elen + slen + blen + 1);
587 	if(!ptr)
588 		return NULL;
589 
590 	ptr[0] = '\0';
591 
592 	if(basename)
593 		strcat(ptr, basename);
594 	if(suffix)
595 		strcat(ptr, suffix);
596 	if(extension)
597 		strcat(ptr, extension);
598 
599 	return ptr;
600 }
601 
utf16_to_utf8(unsigned short utf16_char,unsigned char * out)602 size_t utf16_to_utf8(unsigned short utf16_char, unsigned char *out)
603 {
604 	if (utf16_char < 0x80) {
605 		out[0] = (unsigned char)((utf16_char >> 0 & 0x7F) | 0x00);
606 		return 1;
607 	} else if (utf16_char < 0x0800) {
608 		out[0] = (unsigned char)((utf16_char >> 6 & 0x1F) | 0xC0);
609 		out[1] = (unsigned char)((utf16_char >> 0 & 0x3F) | 0x80);
610 		return 2;
611 	} else if (utf16_char < 0x010000) {
612 		out[0] = (unsigned char)((utf16_char >> 12 & 0x0F) | 0xE0);
613 		out[1] = (unsigned char)((utf16_char >> 6 & 0x3F) | 0x80);
614 		out[2] = (unsigned char)((utf16_char >> 0 & 0x3F) | 0x80);
615 		return 3;
616 	} else if (utf16_char < 0x110000) {
617 		out[0] = (unsigned char)((utf16_char >> 18 & 0x07) | 0xF0);
618 		out[1] = (unsigned char)((utf16_char >> 12 & 0x3F) | 0x80);
619 		out[2] = (unsigned char)((utf16_char >> 6 & 0x3F) | 0x80);
620 		out[3] = (unsigned char)((utf16_char >> 0 & 0x3F) | 0x80);
621 		return 4;
622 	}
623 	return 0;
624 }
625 
change_timebase(LLONG val,struct ccx_rational cur_tb,struct ccx_rational dest_tb)626 LLONG change_timebase(LLONG val, struct ccx_rational cur_tb, struct ccx_rational dest_tb)
627 {
628 	/* val = (value * current timebase) / destination timebase */
629 	val = val * cur_tb.num * dest_tb.den;
630 	val = val / ( cur_tb.den * dest_tb.num);
631 	return val;
632 }
633 
str_reallocncat(char * dst,char * src)634 char *str_reallocncat(char *dst, char *src)
635 {
636 	int nl = dst==NULL? (strlen (src)+1) : (strlen(dst) + strlen(src) + 1);
637 	char *orig = dst;
638 	dst = (char *)realloc(dst, nl);
639 	if (!dst)
640 		return NULL;
641 	if (orig == NULL)
642 		strcpy(dst, src);
643 	else
644 		strcat(dst, src);
645 	return dst;
646 }
647 
648 #ifdef _WIN32
strndup(const char * s,size_t n)649 char *strndup(const char *s, size_t n)
650 {
651 	char *p;
652 
653 	p = (char *)malloc(n + 1);
654 	if (p == NULL)
655 		return NULL;
656 	memcpy(p, s, n);
657 	p[n] = '\0';
658 	return p;
659 }
strtok_r(char * str,const char * delim,char ** saveptr)660 char *strtok_r(char *str, const char *delim, char **saveptr)
661 {
662 	return strtok_s(str, delim, saveptr);
663 }
664 #endif //_WIN32
665