r955: Fix the Diffkey icon.
[cinelerra_cv.git] / quicktime / util.c
blob79f06bd4ad31001f6c7e87544d02eb27b5a2342d
1 #include <fcntl.h>
2 #include <linux/cdrom.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/ioctl.h>
7 #include <sys/stat.h>
8 #include <time.h>
9 #include <unistd.h>
10 #include "funcprotos.h"
11 #include "quicktime.h"
12 #include "workarounds.h"
14 /* Disk I/O */
16 int64_t quicktime_get_file_length(char *path)
18 struct stat64 status;
19 if(stat64(path, &status))
20 perror("quicktime_get_file_length stat64:");
21 return status.st_size;
24 int quicktime_file_open(quicktime_t *file, char *path, int rd, int wr)
26 int exists = 0;
27 char flags[10];
28 if(rd && (file->stream = fopen(path, "rb")))
30 exists = 1;
31 fclose(file->stream);
34 if(rd && !wr) sprintf(flags, "rb");
35 else
36 if(!rd && wr) sprintf(flags, "wb");
37 else
38 if(rd && wr)
40 if(exists)
41 sprintf(flags, "rb+");
42 else
43 sprintf(flags, "wb+");
46 if(!(file->stream = fopen(path, flags)))
48 perror(__FUNCTION__);
49 return 1;
53 if(rd && exists)
55 file->total_length = quicktime_get_file_length(path);
58 file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);
59 return 0;
62 int quicktime_file_close(quicktime_t *file)
64 /* Flush presave buffer */
65 if(file->presave_size)
67 quicktime_fseek(file, file->presave_position - file->presave_size);
68 fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
69 file->presave_size = 0;
72 if(file->stream)
74 fclose(file->stream);
76 file->stream = 0;
77 return 0;
82 int64_t quicktime_ftell(quicktime_t *file)
84 return file->ftell_position;
87 int quicktime_fseek(quicktime_t *file, int64_t offset)
89 file->ftell_position = offset;
90 if(offset > file->total_length || offset < 0) return 1;
91 if(FSEEK(file->stream, file->ftell_position, SEEK_SET))
93 // perror("quicktime_fseek FSEEK");
94 return 1;
96 return 0;
99 /* Read entire buffer from the preload buffer */
100 static int read_preload(quicktime_t *file, char *data, int64_t size)
102 int64_t selection_start = 0;
103 int64_t selection_end = 0;
104 int64_t fragment_start = 0;
105 int64_t fragment_len = 0;
107 selection_start = file->file_position;
108 selection_end = quicktime_add(file->file_position, size);
110 fragment_start = file->preload_ptr + (selection_start - file->preload_start);
111 while(fragment_start < 0) fragment_start += file->preload_size;
112 while(fragment_start >= file->preload_size) fragment_start -= file->preload_size;
114 while(selection_start < selection_end)
116 fragment_len = selection_end - selection_start;
117 if(fragment_start + fragment_len > file->preload_size)
118 fragment_len = file->preload_size - fragment_start;
120 memcpy(data, file->preload_buffer + fragment_start, fragment_len);
121 fragment_start += fragment_len;
122 data += fragment_len;
124 if(fragment_start >= file->preload_size) fragment_start = (int64_t)0;
125 selection_start += fragment_len;
127 return 0;
130 int quicktime_read_data(quicktime_t *file, char *data, int64_t size)
132 int result = 1;
134 if(!file->preload_size)
136 quicktime_fseek(file, file->file_position);
137 result = fread(data, size, 1, file->stream);
138 file->ftell_position += size;
140 else
142 /* Region requested for loading */
143 int64_t selection_start = file->file_position;
144 int64_t selection_end = file->file_position + size;
145 int64_t fragment_start, fragment_len;
147 if(selection_end - selection_start > file->preload_size)
149 /* Size is larger than preload size. Should never happen. */
150 printf("read data Size is larger than preload size. size=%llx preload_size=%llx\n",
151 selection_end - selection_start, file->preload_size);
152 quicktime_fseek(file, file->file_position);
153 result = fread(data, size, 1, file->stream);
154 file->ftell_position += size;
156 else
157 if(selection_start >= file->preload_start &&
158 selection_start < file->preload_end &&
159 selection_end <= file->preload_end &&
160 selection_end > file->preload_start)
162 /* Entire range is in buffer */
163 read_preload(file, data, size);
165 else
166 if(selection_end > file->preload_end &&
167 selection_end - file->preload_size < file->preload_end)
169 /* Range is after buffer */
170 /* Move the preload start to within one preload length of the selection_end */
171 while(selection_end - file->preload_start > file->preload_size)
173 fragment_len = selection_end - file->preload_start - file->preload_size;
174 if(file->preload_ptr + fragment_len > file->preload_size)
175 fragment_len = file->preload_size - file->preload_ptr;
176 file->preload_start += fragment_len;
177 file->preload_ptr += fragment_len;
178 if(file->preload_ptr >= file->preload_size) file->preload_ptr = 0;
181 /* Append sequential data after the preload end to the new end */
182 fragment_start = file->preload_ptr + file->preload_end - file->preload_start;
183 while(fragment_start >= file->preload_size)
184 fragment_start -= file->preload_size;
186 while(file->preload_end < selection_end)
188 fragment_len = selection_end - file->preload_end;
189 if(fragment_start + fragment_len > file->preload_size) fragment_len = file->preload_size - fragment_start;
190 quicktime_fseek(file, file->preload_end);
191 result = fread(&(file->preload_buffer[fragment_start]), fragment_len, 1, file->stream);
192 file->ftell_position += fragment_len;
193 file->preload_end += fragment_len;
194 fragment_start += fragment_len;
195 if(fragment_start >= file->preload_size) fragment_start = 0;
198 read_preload(file, data, size);
200 else
202 /* Range is before buffer or over a preload_size away from the end of the buffer. */
203 /* Replace entire preload buffer with range. */
204 quicktime_fseek(file, file->file_position);
205 result = fread(file->preload_buffer, size, 1, file->stream);
206 file->ftell_position += size;
207 file->preload_start = file->file_position;
208 file->preload_end = file->file_position + size;
209 file->preload_ptr = 0;
210 read_preload(file, data, size);
214 file->file_position += size;
215 return result;
218 void quicktime_set_presave(quicktime_t *file, int value)
220 // Flush presave buffer
221 if(!value && file->use_presave)
223 quicktime_fseek(file, file->presave_position - file->presave_size);
224 fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
225 file->presave_size = 0;
226 file->file_position = file->presave_position;
227 file->ftell_position = file->presave_position;
228 if(file->total_length < file->ftell_position)
229 file->total_length = file->ftell_position;
231 else
232 if(value && !file->use_presave)
237 file->use_presave = value;
240 int quicktime_write_data(quicktime_t *file, char *data, int size)
242 int data_offset = 0;
243 int writes_attempted = 0;
244 int writes_succeeded = 0;
245 int iterations = 0;
247 if(!file->use_presave)
249 //printf("quicktime_write_data 1\n");
250 quicktime_fseek(file, file->file_position);
251 writes_attempted = 1;
252 writes_succeeded = fwrite(data,
253 size,
255 file->stream);
256 file->file_position += size;
257 file->ftell_position += size;
258 file->presave_position = file->file_position;
260 else
262 // Flush existing buffer and seek to new position
263 if(file->file_position != file->presave_position)
265 if(file->presave_size)
267 quicktime_fseek(file, file->presave_position - file->presave_size);
268 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
269 writes_attempted += file->presave_size;
270 file->presave_size = 0;
272 file->presave_position = file->file_position;
275 // Write presave buffers until done
276 while(size > 0)
278 int fragment_size = QUICKTIME_PRESAVE;
279 if(fragment_size > size) fragment_size = size;
280 if(fragment_size + file->presave_size > QUICKTIME_PRESAVE)
281 fragment_size = QUICKTIME_PRESAVE- file->presave_size;
283 memcpy(file->presave_buffer + file->presave_size,
284 data + data_offset,
285 fragment_size);
287 file->presave_position += fragment_size;
288 file->presave_size += fragment_size;
289 data_offset += fragment_size;
290 size -= fragment_size;
292 if(file->presave_size >= QUICKTIME_PRESAVE)
294 //if(++iterations > 1) printf("quicktime_write_data 2 iterations=%d\n", iterations);
295 quicktime_fseek(file, file->presave_position - file->presave_size);
296 writes_succeeded += fwrite(file->presave_buffer,
297 file->presave_size,
299 file->stream);
300 writes_attempted += file->presave_size;
301 file->presave_size = 0;
305 /* Adjust file position */
306 file->file_position = file->presave_position;
307 /* Adjust ftell position */
308 file->ftell_position = file->presave_position;
312 /* Adjust total length */
313 if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;
315 /* fwrite failed */
316 if(!writes_succeeded && writes_attempted)
318 return 0;
320 else
321 if(!size)
322 return 1;
323 else
324 return size;
327 int64_t quicktime_byte_position(quicktime_t *file)
329 return quicktime_position(file);
333 void quicktime_read_pascal(quicktime_t *file, char *data)
335 char len = quicktime_read_char(file);
336 quicktime_read_data(file, data, len);
337 data[len] = 0;
340 void quicktime_write_pascal(quicktime_t *file, char *data)
342 char len = strlen(data);
343 quicktime_write_data(file, &len, 1);
344 quicktime_write_data(file, data, len);
347 float quicktime_read_fixed32(quicktime_t *file)
349 unsigned long a, b, c, d;
350 unsigned char data[4];
352 quicktime_read_data(file, data, 4);
353 a = data[0];
354 b = data[1];
355 c = data[2];
356 d = data[3];
358 a = (a << 8) + b;
359 b = (c << 8) + d;
361 if(b)
362 return (float)a + (float)b / 65536;
363 else
364 return a;
367 int quicktime_write_fixed32(quicktime_t *file, float number)
369 unsigned char data[4];
370 int a, b;
372 a = number;
373 b = (number - a) * 65536;
374 data[0] = a >> 8;
375 data[1] = a & 0xff;
376 data[2] = b >> 8;
377 data[3] = b & 0xff;
379 return quicktime_write_data(file, data, 4);
382 int quicktime_write_int64(quicktime_t *file, int64_t value)
384 unsigned char data[8];
386 data[0] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
387 data[1] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
388 data[2] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
389 data[3] = (((uint64_t)value) & 0xff00000000LL) >> 32;
390 data[4] = (((uint64_t)value) & 0xff000000LL) >> 24;
391 data[5] = (((uint64_t)value) & 0xff0000LL) >> 16;
392 data[6] = (((uint64_t)value) & 0xff00LL) >> 8;
393 data[7] = ((uint64_t)value) & 0xff;
395 return quicktime_write_data(file, data, 8);
398 int quicktime_write_int64_le(quicktime_t *file, int64_t value)
400 unsigned char data[8];
402 data[7] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
403 data[6] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
404 data[5] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
405 data[4] = (((uint64_t)value) & 0xff00000000LL) >> 32;
406 data[3] = (((uint64_t)value) & 0xff000000LL) >> 24;
407 data[2] = (((uint64_t)value) & 0xff0000LL) >> 16;
408 data[1] = (((uint64_t)value) & 0xff00LL) >> 8;
409 data[0] = ((uint64_t)value) & 0xff;
411 return quicktime_write_data(file, data, 8);
414 int quicktime_write_int32(quicktime_t *file, long value)
416 unsigned char data[4];
418 data[0] = (value & 0xff000000) >> 24;
419 data[1] = (value & 0xff0000) >> 16;
420 data[2] = (value & 0xff00) >> 8;
421 data[3] = value & 0xff;
423 return quicktime_write_data(file, data, 4);
426 int quicktime_write_int32_le(quicktime_t *file, long value)
428 unsigned char data[4];
430 data[3] = (value & 0xff000000) >> 24;
431 data[2] = (value & 0xff0000) >> 16;
432 data[1] = (value & 0xff00) >> 8;
433 data[0] = value & 0xff;
435 return quicktime_write_data(file, data, 4);
438 int quicktime_write_char32(quicktime_t *file, char *string)
440 return quicktime_write_data(file, string, 4);
444 float quicktime_read_fixed16(quicktime_t *file)
446 unsigned char data[2];
448 quicktime_read_data(file, data, 2);
449 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
450 if(data[1])
451 return (float)data[0] + (float)data[1] / 256;
452 else
453 return (float)data[0];
456 int quicktime_write_fixed16(quicktime_t *file, float number)
458 unsigned char data[2];
459 int a, b;
461 a = number;
462 b = (number - a) * 256;
463 data[0] = a;
464 data[1] = b;
466 return quicktime_write_data(file, data, 2);
469 unsigned long quicktime_read_uint32(quicktime_t *file)
471 unsigned long result;
472 unsigned long a, b, c, d;
473 char data[4];
475 quicktime_read_data(file, data, 4);
476 a = (unsigned char)data[0];
477 b = (unsigned char)data[1];
478 c = (unsigned char)data[2];
479 d = (unsigned char)data[3];
481 result = (a << 24) | (b << 16) | (c << 8) | d;
482 return result;
485 long quicktime_read_int32(quicktime_t *file)
487 unsigned long result;
488 unsigned long a, b, c, d;
489 char data[4];
491 quicktime_read_data(file, data, 4);
492 a = (unsigned char)data[0];
493 b = (unsigned char)data[1];
494 c = (unsigned char)data[2];
495 d = (unsigned char)data[3];
497 result = (a << 24) | (b << 16) | (c << 8) | d;
498 return (long)result;
501 long quicktime_read_int32_le(quicktime_t *file)
503 unsigned long result;
504 unsigned long a, b, c, d;
505 char data[4];
507 quicktime_read_data(file, data, 4);
508 a = (unsigned char)data[0];
509 b = (unsigned char)data[1];
510 c = (unsigned char)data[2];
511 d = (unsigned char)data[3];
513 result = (d << 24) | (c << 16) | (b << 8) | a;
514 return (long)result;
517 int64_t quicktime_read_int64(quicktime_t *file)
519 uint64_t result, a, b, c, d, e, f, g, h;
520 char data[8];
522 quicktime_read_data(file, data, 8);
523 a = (unsigned char)data[0];
524 b = (unsigned char)data[1];
525 c = (unsigned char)data[2];
526 d = (unsigned char)data[3];
527 e = (unsigned char)data[4];
528 f = (unsigned char)data[5];
529 g = (unsigned char)data[6];
530 h = (unsigned char)data[7];
532 result = (a << 56) |
533 (b << 48) |
534 (c << 40) |
535 (d << 32) |
536 (e << 24) |
537 (f << 16) |
538 (g << 8) |
540 return (int64_t)result;
543 int64_t quicktime_read_int64_le(quicktime_t *file)
545 uint64_t result, a, b, c, d, e, f, g, h;
546 char data[8];
548 quicktime_read_data(file, data, 8);
549 a = (unsigned char)data[7];
550 b = (unsigned char)data[6];
551 c = (unsigned char)data[5];
552 d = (unsigned char)data[4];
553 e = (unsigned char)data[3];
554 f = (unsigned char)data[2];
555 g = (unsigned char)data[1];
556 h = (unsigned char)data[0];
558 result = (a << 56) |
559 (b << 48) |
560 (c << 40) |
561 (d << 32) |
562 (e << 24) |
563 (f << 16) |
564 (g << 8) |
566 return (int64_t)result;
570 long quicktime_read_int24(quicktime_t *file)
572 unsigned long result;
573 unsigned long a, b, c;
574 char data[4];
576 quicktime_read_data(file, data, 3);
577 a = (unsigned char)data[0];
578 b = (unsigned char)data[1];
579 c = (unsigned char)data[2];
581 result = (a << 16) | (b << 8) | c;
582 return (long)result;
585 int quicktime_write_int24(quicktime_t *file, long number)
587 unsigned char data[3];
588 data[0] = (number & 0xff0000) >> 16;
589 data[1] = (number & 0xff00) >> 8;
590 data[2] = (number & 0xff);
592 return quicktime_write_data(file, data, 3);
595 int quicktime_read_int16(quicktime_t *file)
597 unsigned long result;
598 unsigned long a, b;
599 char data[2];
601 quicktime_read_data(file, data, 2);
602 a = (unsigned char)data[0];
603 b = (unsigned char)data[1];
605 result = (a << 8) | b;
606 return (int)result;
609 int quicktime_read_int16_le(quicktime_t *file)
611 unsigned long result;
612 unsigned long a, b;
613 char data[2];
615 quicktime_read_data(file, data, 2);
616 a = (unsigned char)data[0];
617 b = (unsigned char)data[1];
619 result = (b << 8) | a;
620 return (int)result;
623 int quicktime_write_int16(quicktime_t *file, int number)
625 unsigned char data[2];
626 data[0] = (number & 0xff00) >> 8;
627 data[1] = (number & 0xff);
629 return quicktime_write_data(file, data, 2);
632 int quicktime_write_int16_le(quicktime_t *file, int number)
634 unsigned char data[2];
635 data[1] = (number & 0xff00) >> 8;
636 data[0] = (number & 0xff);
638 return quicktime_write_data(file, data, 2);
641 int quicktime_read_char(quicktime_t *file)
643 char output;
644 quicktime_read_data(file, &output, 1);
645 return output;
648 int quicktime_write_char(quicktime_t *file, char x)
650 return quicktime_write_data(file, &x, 1);
653 void quicktime_read_char32(quicktime_t *file, char *string)
655 quicktime_read_data(file, string, 4);
658 int64_t quicktime_position(quicktime_t *file)
660 return file->file_position;
663 int quicktime_set_position(quicktime_t *file, int64_t position)
665 file->file_position = position;
666 if(!file->use_presave)
668 quicktime_fseek(file, position);
669 file->presave_position = position;
671 return 0;
674 void quicktime_copy_char32(char *output, char *input)
676 *output++ = *input++;
677 *output++ = *input++;
678 *output++ = *input++;
679 *output = *input;
683 void quicktime_print_chars(char *desc, char *input, int len)
685 int i;
686 printf("%s", desc);
687 for(i = 0; i < len; i++) printf("%c", input[i]);
688 printf("\n");
691 unsigned long quicktime_current_time(void)
693 time_t t;
694 time (&t);
695 return (t+(66*31536000)+1468800);
698 int quicktime_match_32(char *input, char *output)
700 if(input[0] == output[0] &&
701 input[1] == output[1] &&
702 input[2] == output[2] &&
703 input[3] == output[3])
704 return 1;
705 else
706 return 0;
709 int quicktime_match_24(char *input, char *output)
711 if(input[0] == output[0] &&
712 input[1] == output[1] &&
713 input[2] == output[2])
714 return 1;
715 else
716 return 0;
719 int quicktime_quantize16(int number)
721 if(number && (number % 16))
723 number += 16 - (number % 16);
725 return number;
728 int quicktime_quantize32(int number)
730 if(number && (number % 32))
732 number += 32 - (number % 32);
734 return number;