r499: This commit was manufactured by cvs2svn to create tag 'r1_2_1-last'.
[cinelerra_cv.git] / hvirtual / quicktime / util.c
blobefbb5af19877da3ee9cce5f35576a0750849d588
1 #include <fcntl.h>
2 #include <linux/cdrom.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <sys/ioctl.h>
6 #include <sys/stat.h>
7 #include <time.h>
8 #include <unistd.h>
9 #include "funcprotos.h"
10 #include "quicktime.h"
11 #include "workarounds.h"
13 /* Disk I/O */
15 int64_t quicktime_get_file_length(char *path)
17 struct stat64 status;
18 if(stat64(path, &status))
19 perror("quicktime_get_file_length stat64:");
20 return status.st_size;
23 int quicktime_file_open(quicktime_t *file, char *path, int rd, int wr)
25 int exists = 0;
26 char flags[10];
27 if(rd && (file->stream = fopen(path, "rb")))
29 exists = 1;
30 fclose(file->stream);
33 if(rd && !wr) sprintf(flags, "rb");
34 else
35 if(!rd && wr) sprintf(flags, "wb");
36 else
37 if(rd && wr)
39 if(exists)
40 sprintf(flags, "rb+");
41 else
42 sprintf(flags, "wb+");
45 if(!(file->stream = fopen(path, flags)))
47 perror(__FUNCTION__);
48 return 1;
52 if(rd && exists)
54 file->total_length = quicktime_get_file_length(path);
57 file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);
58 return 0;
61 int quicktime_file_close(quicktime_t *file)
63 /* Flush presave buffer */
64 if(file->presave_size)
66 quicktime_fseek(file, file->presave_position - file->presave_size);
67 fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
68 file->presave_size = 0;
71 if(file->stream)
73 fclose(file->stream);
75 file->stream = 0;
76 return 0;
81 int64_t quicktime_ftell(quicktime_t *file)
83 return file->ftell_position;
86 int quicktime_fseek(quicktime_t *file, int64_t offset)
88 file->ftell_position = offset;
89 if(offset > file->total_length || offset < 0) return 1;
90 if(FSEEK(file->stream, file->ftell_position, SEEK_SET))
92 // perror("quicktime_fseek FSEEK");
93 return 1;
95 return 0;
98 /* Read entire buffer from the preload buffer */
99 static int read_preload(quicktime_t *file, char *data, int64_t size)
101 int64_t selection_start = 0;
102 int64_t selection_end = 0;
103 int64_t fragment_start = 0;
104 int64_t fragment_len = 0;
106 selection_start = file->file_position;
107 selection_end = quicktime_add(file->file_position, size);
109 fragment_start = file->preload_ptr + (selection_start - file->preload_start);
110 while(fragment_start < 0) fragment_start += file->preload_size;
111 while(fragment_start >= file->preload_size) fragment_start -= file->preload_size;
113 while(selection_start < selection_end)
115 fragment_len = selection_end - selection_start;
116 if(fragment_start + fragment_len > file->preload_size)
117 fragment_len = file->preload_size - fragment_start;
119 memcpy(data, file->preload_buffer + fragment_start, fragment_len);
120 fragment_start += fragment_len;
121 data += fragment_len;
123 if(fragment_start >= file->preload_size) fragment_start = (int64_t)0;
124 selection_start += fragment_len;
126 return 0;
129 int quicktime_read_data(quicktime_t *file, char *data, int64_t size)
131 int result = 1;
133 if(!file->preload_size)
135 quicktime_fseek(file, file->file_position);
136 result = fread(data, size, 1, file->stream);
137 file->ftell_position += size;
139 else
141 /* Region requested for loading */
142 int64_t selection_start = file->file_position;
143 int64_t selection_end = file->file_position + size;
144 int64_t fragment_start, fragment_len;
146 if(selection_end - selection_start > file->preload_size)
148 /* Size is larger than preload size. Should never happen. */
149 printf("read data Size is larger than preload size. size=%llx preload_size=%llx\n",
150 selection_end - selection_start, file->preload_size);
151 quicktime_fseek(file, file->file_position);
152 result = fread(data, size, 1, file->stream);
153 file->ftell_position += size;
155 else
156 if(selection_start >= file->preload_start &&
157 selection_start < file->preload_end &&
158 selection_end <= file->preload_end &&
159 selection_end > file->preload_start)
161 /* Entire range is in buffer */
162 read_preload(file, data, size);
164 else
165 if(selection_end > file->preload_end &&
166 selection_end - file->preload_size < file->preload_end)
168 /* Range is after buffer */
169 /* Move the preload start to within one preload length of the selection_end */
170 while(selection_end - file->preload_start > file->preload_size)
172 fragment_len = selection_end - file->preload_start - file->preload_size;
173 if(file->preload_ptr + fragment_len > file->preload_size)
174 fragment_len = file->preload_size - file->preload_ptr;
175 file->preload_start += fragment_len;
176 file->preload_ptr += fragment_len;
177 if(file->preload_ptr >= file->preload_size) file->preload_ptr = 0;
180 /* Append sequential data after the preload end to the new end */
181 fragment_start = file->preload_ptr + file->preload_end - file->preload_start;
182 while(fragment_start >= file->preload_size)
183 fragment_start -= file->preload_size;
185 while(file->preload_end < selection_end)
187 fragment_len = selection_end - file->preload_end;
188 if(fragment_start + fragment_len > file->preload_size) fragment_len = file->preload_size - fragment_start;
189 quicktime_fseek(file, file->preload_end);
190 result = fread(&(file->preload_buffer[fragment_start]), fragment_len, 1, file->stream);
191 file->ftell_position += fragment_len;
192 file->preload_end += fragment_len;
193 fragment_start += fragment_len;
194 if(fragment_start >= file->preload_size) fragment_start = 0;
197 read_preload(file, data, size);
199 else
201 /* Range is before buffer or over a preload_size away from the end of the buffer. */
202 /* Replace entire preload buffer with range. */
203 quicktime_fseek(file, file->file_position);
204 result = fread(file->preload_buffer, size, 1, file->stream);
205 file->ftell_position += size;
206 file->preload_start = file->file_position;
207 file->preload_end = file->file_position + size;
208 file->preload_ptr = 0;
209 read_preload(file, data, size);
213 file->file_position += size;
214 return result;
217 void quicktime_set_presave(quicktime_t *file, int value)
219 // Flush presave buffer
220 if(!value && file->use_presave)
222 quicktime_fseek(file, file->presave_position - file->presave_size);
223 fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
224 file->presave_size = 0;
225 file->file_position = file->presave_position;
226 file->ftell_position = file->presave_position;
227 if(file->total_length < file->ftell_position)
228 file->total_length = file->ftell_position;
230 else
231 if(value && !file->use_presave)
236 file->use_presave = value;
239 int quicktime_write_data(quicktime_t *file, char *data, int size)
241 int data_offset = 0;
242 int writes_attempted = 0;
243 int writes_succeeded = 0;
244 int iterations = 0;
246 if(!file->use_presave)
248 //printf("quicktime_write_data 1\n");
249 quicktime_fseek(file, file->file_position);
250 writes_attempted = 1;
251 writes_succeeded = fwrite(data,
252 size,
254 file->stream);
255 file->file_position += size;
256 file->ftell_position += size;
257 //printf("quicktime_write_data 2\n");
259 else
261 // Flush existing buffer and seek to new position
262 if(file->file_position != file->presave_position)
264 if(file->presave_size)
266 quicktime_fseek(file, file->presave_position - file->presave_size);
267 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
268 writes_attempted += file->presave_size;
269 file->presave_size = 0;
271 file->presave_position = file->file_position;
274 // Write presave buffers until done
275 while(size > 0)
277 int fragment_size = QUICKTIME_PRESAVE;
278 if(fragment_size > size) fragment_size = size;
279 if(fragment_size + file->presave_size > QUICKTIME_PRESAVE)
280 fragment_size = QUICKTIME_PRESAVE- file->presave_size;
282 memcpy(file->presave_buffer + file->presave_size,
283 data + data_offset,
284 fragment_size);
286 file->presave_position += fragment_size;
287 file->presave_size += fragment_size;
288 data_offset += fragment_size;
289 size -= fragment_size;
291 if(file->presave_size >= QUICKTIME_PRESAVE)
293 //if(++iterations > 1) printf("quicktime_write_data 2 iterations=%d\n", iterations);
294 quicktime_fseek(file, file->presave_position - file->presave_size);
295 writes_succeeded += fwrite(file->presave_buffer,
296 file->presave_size,
298 file->stream);
299 writes_attempted += file->presave_size;
300 file->presave_size = 0;
304 /* Adjust file position */
305 file->file_position = file->presave_position;
306 /* Adjust ftell position */
307 file->ftell_position = file->presave_position;
311 /* Adjust total length */
312 if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;
314 /* fwrite failed */
315 if(!writes_succeeded && writes_attempted)
317 return 0;
319 else
320 if(!size)
321 return 1;
322 else
323 return size;
326 int64_t quicktime_byte_position(quicktime_t *file)
328 return quicktime_position(file);
332 void quicktime_read_pascal(quicktime_t *file, char *data)
334 char len = quicktime_read_char(file);
335 quicktime_read_data(file, data, len);
336 data[len] = 0;
339 void quicktime_write_pascal(quicktime_t *file, char *data)
341 char len = strlen(data);
342 quicktime_write_data(file, &len, 1);
343 quicktime_write_data(file, data, len);
346 float quicktime_read_fixed32(quicktime_t *file)
348 unsigned long a, b, c, d;
349 unsigned char data[4];
351 quicktime_read_data(file, data, 4);
352 a = data[0];
353 b = data[1];
354 c = data[2];
355 d = data[3];
357 a = (a << 8) + b;
358 b = (c << 8) + d;
360 if(b)
361 return (float)a + (float)b / 65536;
362 else
363 return a;
366 int quicktime_write_fixed32(quicktime_t *file, float number)
368 unsigned char data[4];
369 int a, b;
371 a = number;
372 b = (number - a) * 65536;
373 data[0] = a >> 8;
374 data[1] = a & 0xff;
375 data[2] = b >> 8;
376 data[3] = b & 0xff;
378 return quicktime_write_data(file, data, 4);
381 int quicktime_write_int64(quicktime_t *file, int64_t value)
383 unsigned char data[8];
385 data[0] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
386 data[1] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
387 data[2] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
388 data[3] = (((uint64_t)value) & 0xff00000000LL) >> 32;
389 data[4] = (((uint64_t)value) & 0xff000000LL) >> 24;
390 data[5] = (((uint64_t)value) & 0xff0000LL) >> 16;
391 data[6] = (((uint64_t)value) & 0xff00LL) >> 8;
392 data[7] = ((uint64_t)value) & 0xff;
394 return quicktime_write_data(file, data, 8);
397 int quicktime_write_int64_le(quicktime_t *file, int64_t value)
399 unsigned char data[8];
401 data[7] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
402 data[6] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
403 data[5] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
404 data[4] = (((uint64_t)value) & 0xff00000000LL) >> 32;
405 data[3] = (((uint64_t)value) & 0xff000000LL) >> 24;
406 data[2] = (((uint64_t)value) & 0xff0000LL) >> 16;
407 data[1] = (((uint64_t)value) & 0xff00LL) >> 8;
408 data[0] = ((uint64_t)value) & 0xff;
410 return quicktime_write_data(file, data, 8);
413 int quicktime_write_int32(quicktime_t *file, long value)
415 unsigned char data[4];
417 data[0] = (value & 0xff000000) >> 24;
418 data[1] = (value & 0xff0000) >> 16;
419 data[2] = (value & 0xff00) >> 8;
420 data[3] = value & 0xff;
422 return quicktime_write_data(file, data, 4);
425 int quicktime_write_int32_le(quicktime_t *file, long value)
427 unsigned char data[4];
429 data[3] = (value & 0xff000000) >> 24;
430 data[2] = (value & 0xff0000) >> 16;
431 data[1] = (value & 0xff00) >> 8;
432 data[0] = value & 0xff;
434 return quicktime_write_data(file, data, 4);
437 int quicktime_write_char32(quicktime_t *file, char *string)
439 return quicktime_write_data(file, string, 4);
443 float quicktime_read_fixed16(quicktime_t *file)
445 unsigned char data[2];
447 quicktime_read_data(file, data, 2);
448 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
449 if(data[1])
450 return (float)data[0] + (float)data[1] / 256;
451 else
452 return (float)data[0];
455 int quicktime_write_fixed16(quicktime_t *file, float number)
457 unsigned char data[2];
458 int a, b;
460 a = number;
461 b = (number - a) * 256;
462 data[0] = a;
463 data[1] = b;
465 return quicktime_write_data(file, data, 2);
468 unsigned long quicktime_read_uint32(quicktime_t *file)
470 unsigned long result;
471 unsigned long a, b, c, d;
472 char data[4];
474 quicktime_read_data(file, data, 4);
475 a = (unsigned char)data[0];
476 b = (unsigned char)data[1];
477 c = (unsigned char)data[2];
478 d = (unsigned char)data[3];
480 result = (a << 24) | (b << 16) | (c << 8) | d;
481 return result;
484 long quicktime_read_int32(quicktime_t *file)
486 unsigned long result;
487 unsigned long a, b, c, d;
488 char data[4];
490 quicktime_read_data(file, data, 4);
491 a = (unsigned char)data[0];
492 b = (unsigned char)data[1];
493 c = (unsigned char)data[2];
494 d = (unsigned char)data[3];
496 result = (a << 24) | (b << 16) | (c << 8) | d;
497 return (long)result;
500 long quicktime_read_int32_le(quicktime_t *file)
502 unsigned long result;
503 unsigned long a, b, c, d;
504 char data[4];
506 quicktime_read_data(file, data, 4);
507 a = (unsigned char)data[0];
508 b = (unsigned char)data[1];
509 c = (unsigned char)data[2];
510 d = (unsigned char)data[3];
512 result = (d << 24) | (c << 16) | (b << 8) | a;
513 return (long)result;
516 int64_t quicktime_read_int64(quicktime_t *file)
518 uint64_t result, a, b, c, d, e, f, g, h;
519 char data[8];
521 quicktime_read_data(file, data, 8);
522 a = (unsigned char)data[0];
523 b = (unsigned char)data[1];
524 c = (unsigned char)data[2];
525 d = (unsigned char)data[3];
526 e = (unsigned char)data[4];
527 f = (unsigned char)data[5];
528 g = (unsigned char)data[6];
529 h = (unsigned char)data[7];
531 result = (a << 56) |
532 (b << 48) |
533 (c << 40) |
534 (d << 32) |
535 (e << 24) |
536 (f << 16) |
537 (g << 8) |
539 return (int64_t)result;
542 int64_t quicktime_read_int64_le(quicktime_t *file)
544 uint64_t result, a, b, c, d, e, f, g, h;
545 char data[8];
547 quicktime_read_data(file, data, 8);
548 a = (unsigned char)data[7];
549 b = (unsigned char)data[6];
550 c = (unsigned char)data[5];
551 d = (unsigned char)data[4];
552 e = (unsigned char)data[3];
553 f = (unsigned char)data[2];
554 g = (unsigned char)data[1];
555 h = (unsigned char)data[0];
557 result = (a << 56) |
558 (b << 48) |
559 (c << 40) |
560 (d << 32) |
561 (e << 24) |
562 (f << 16) |
563 (g << 8) |
565 return (int64_t)result;
569 long quicktime_read_int24(quicktime_t *file)
571 unsigned long result;
572 unsigned long a, b, c;
573 char data[4];
575 quicktime_read_data(file, data, 3);
576 a = (unsigned char)data[0];
577 b = (unsigned char)data[1];
578 c = (unsigned char)data[2];
580 result = (a << 16) | (b << 8) | c;
581 return (long)result;
584 int quicktime_write_int24(quicktime_t *file, long number)
586 unsigned char data[3];
587 data[0] = (number & 0xff0000) >> 16;
588 data[1] = (number & 0xff00) >> 8;
589 data[2] = (number & 0xff);
591 return quicktime_write_data(file, data, 3);
594 int quicktime_read_int16(quicktime_t *file)
596 unsigned long result;
597 unsigned long a, b;
598 char data[2];
600 quicktime_read_data(file, data, 2);
601 a = (unsigned char)data[0];
602 b = (unsigned char)data[1];
604 result = (a << 8) | b;
605 return (int)result;
608 int quicktime_read_int16_le(quicktime_t *file)
610 unsigned long result;
611 unsigned long a, b;
612 char data[2];
614 quicktime_read_data(file, data, 2);
615 a = (unsigned char)data[0];
616 b = (unsigned char)data[1];
618 result = (b << 8) | a;
619 return (int)result;
622 int quicktime_write_int16(quicktime_t *file, int number)
624 unsigned char data[2];
625 data[0] = (number & 0xff00) >> 8;
626 data[1] = (number & 0xff);
628 return quicktime_write_data(file, data, 2);
631 int quicktime_write_int16_le(quicktime_t *file, int number)
633 unsigned char data[2];
634 data[1] = (number & 0xff00) >> 8;
635 data[0] = (number & 0xff);
637 return quicktime_write_data(file, data, 2);
640 int quicktime_read_char(quicktime_t *file)
642 char output;
643 quicktime_read_data(file, &output, 1);
644 return output;
647 int quicktime_write_char(quicktime_t *file, char x)
649 return quicktime_write_data(file, &x, 1);
652 void quicktime_read_char32(quicktime_t *file, char *string)
654 quicktime_read_data(file, string, 4);
657 int64_t quicktime_position(quicktime_t *file)
659 return file->file_position;
662 int quicktime_set_position(quicktime_t *file, int64_t position)
664 file->file_position = position;
665 return 0;
668 void quicktime_copy_char32(char *output, char *input)
670 *output++ = *input++;
671 *output++ = *input++;
672 *output++ = *input++;
673 *output = *input;
677 void quicktime_print_chars(char *desc, char *input, int len)
679 int i;
680 printf("%s", desc);
681 for(i = 0; i < len; i++) printf("%c", input[i]);
682 printf("\n");
685 unsigned long quicktime_current_time(void)
687 time_t t;
688 time (&t);
689 return (t+(66*31536000)+1468800);
692 int quicktime_match_32(char *input, char *output)
694 if(input[0] == output[0] &&
695 input[1] == output[1] &&
696 input[2] == output[2] &&
697 input[3] == output[3])
698 return 1;
699 else
700 return 0;
703 int quicktime_match_24(char *input, char *output)
705 if(input[0] == output[0] &&
706 input[1] == output[1] &&
707 input[2] == output[2])
708 return 1;
709 else
710 return 0;