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