r370: Heroine Virutal's official release 1.2.1
[cinelerra_cv/mob.git] / hvirtual / quicktime / util.c
blob5cd08288ba0a36ed219282d517f728b31600a79a
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 writes_attempted = 1;
250 writes_succeeded = fwrite(data,
251 size,
253 file->stream);
254 file->file_position += size;
255 file->ftell_position += size;
256 //printf("quicktime_write_data 2\n");
258 else
260 // Flush existing buffer and seek to new position
261 if(file->file_position != file->presave_position)
263 if(file->presave_size)
265 quicktime_fseek(file, file->presave_position - file->presave_size);
266 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
267 writes_attempted += file->presave_size;
268 file->presave_size = 0;
270 file->presave_position = file->file_position;
273 // Write presave buffers until done
274 while(size > 0)
276 int fragment_size = QUICKTIME_PRESAVE;
277 if(fragment_size > size) fragment_size = size;
278 if(fragment_size + file->presave_size > QUICKTIME_PRESAVE)
279 fragment_size = QUICKTIME_PRESAVE- file->presave_size;
281 memcpy(file->presave_buffer + file->presave_size,
282 data + data_offset,
283 fragment_size);
285 file->presave_position += fragment_size;
286 file->presave_size += fragment_size;
287 data_offset += fragment_size;
288 size -= fragment_size;
290 if(file->presave_size >= QUICKTIME_PRESAVE)
292 //if(++iterations > 1) printf("quicktime_write_data 2 iterations=%d\n", iterations);
293 quicktime_fseek(file, file->presave_position - file->presave_size);
294 writes_succeeded += fwrite(file->presave_buffer,
295 file->presave_size,
297 file->stream);
298 writes_attempted += file->presave_size;
299 file->presave_size = 0;
303 /* Adjust file position */
304 file->file_position = file->presave_position;
305 /* Adjust ftell position */
306 file->ftell_position = file->presave_position;
310 /* Adjust total length */
311 if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;
313 /* fwrite failed */
314 if(!writes_succeeded && writes_attempted)
316 return 0;
318 else
319 if(!size)
320 return 1;
321 else
322 return size;
325 int64_t quicktime_byte_position(quicktime_t *file)
327 return quicktime_position(file);
331 void quicktime_read_pascal(quicktime_t *file, char *data)
333 char len = quicktime_read_char(file);
334 quicktime_read_data(file, data, len);
335 data[len] = 0;
338 void quicktime_write_pascal(quicktime_t *file, char *data)
340 char len = strlen(data);
341 quicktime_write_data(file, &len, 1);
342 quicktime_write_data(file, data, len);
345 float quicktime_read_fixed32(quicktime_t *file)
347 unsigned long a, b, c, d;
348 unsigned char data[4];
350 quicktime_read_data(file, data, 4);
351 a = data[0];
352 b = data[1];
353 c = data[2];
354 d = data[3];
356 a = (a << 8) + b;
357 b = (c << 8) + d;
359 if(b)
360 return (float)a + (float)b / 65536;
361 else
362 return a;
365 int quicktime_write_fixed32(quicktime_t *file, float number)
367 unsigned char data[4];
368 int a, b;
370 a = number;
371 b = (number - a) * 65536;
372 data[0] = a >> 8;
373 data[1] = a & 0xff;
374 data[2] = b >> 8;
375 data[3] = b & 0xff;
377 return quicktime_write_data(file, data, 4);
380 int quicktime_write_int64(quicktime_t *file, int64_t value)
382 unsigned char data[8];
384 data[0] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
385 data[1] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
386 data[2] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
387 data[3] = (((uint64_t)value) & 0xff00000000LL) >> 32;
388 data[4] = (((uint64_t)value) & 0xff000000LL) >> 24;
389 data[5] = (((uint64_t)value) & 0xff0000LL) >> 16;
390 data[6] = (((uint64_t)value) & 0xff00LL) >> 8;
391 data[7] = ((uint64_t)value) & 0xff;
393 return quicktime_write_data(file, data, 8);
396 int quicktime_write_int64_le(quicktime_t *file, int64_t value)
398 unsigned char data[8];
400 data[7] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
401 data[6] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
402 data[5] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
403 data[4] = (((uint64_t)value) & 0xff00000000LL) >> 32;
404 data[3] = (((uint64_t)value) & 0xff000000LL) >> 24;
405 data[2] = (((uint64_t)value) & 0xff0000LL) >> 16;
406 data[1] = (((uint64_t)value) & 0xff00LL) >> 8;
407 data[0] = ((uint64_t)value) & 0xff;
409 return quicktime_write_data(file, data, 8);
412 int quicktime_write_int32(quicktime_t *file, long value)
414 unsigned char data[4];
416 data[0] = (value & 0xff000000) >> 24;
417 data[1] = (value & 0xff0000) >> 16;
418 data[2] = (value & 0xff00) >> 8;
419 data[3] = value & 0xff;
421 return quicktime_write_data(file, data, 4);
424 int quicktime_write_int32_le(quicktime_t *file, long value)
426 unsigned char data[4];
428 data[3] = (value & 0xff000000) >> 24;
429 data[2] = (value & 0xff0000) >> 16;
430 data[1] = (value & 0xff00) >> 8;
431 data[0] = value & 0xff;
433 return quicktime_write_data(file, data, 4);
436 int quicktime_write_char32(quicktime_t *file, char *string)
438 return quicktime_write_data(file, string, 4);
442 float quicktime_read_fixed16(quicktime_t *file)
444 unsigned char data[2];
446 quicktime_read_data(file, data, 2);
447 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
448 if(data[1])
449 return (float)data[0] + (float)data[1] / 256;
450 else
451 return (float)data[0];
454 int quicktime_write_fixed16(quicktime_t *file, float number)
456 unsigned char data[2];
457 int a, b;
459 a = number;
460 b = (number - a) * 256;
461 data[0] = a;
462 data[1] = b;
464 return quicktime_write_data(file, data, 2);
467 unsigned long quicktime_read_uint32(quicktime_t *file)
469 unsigned long result;
470 unsigned long a, b, c, d;
471 char data[4];
473 quicktime_read_data(file, data, 4);
474 a = (unsigned char)data[0];
475 b = (unsigned char)data[1];
476 c = (unsigned char)data[2];
477 d = (unsigned char)data[3];
479 result = (a << 24) | (b << 16) | (c << 8) | d;
480 return result;
483 long quicktime_read_int32(quicktime_t *file)
485 unsigned long result;
486 unsigned long a, b, c, d;
487 char data[4];
489 quicktime_read_data(file, data, 4);
490 a = (unsigned char)data[0];
491 b = (unsigned char)data[1];
492 c = (unsigned char)data[2];
493 d = (unsigned char)data[3];
495 result = (a << 24) | (b << 16) | (c << 8) | d;
496 return (long)result;
499 long quicktime_read_int32_le(quicktime_t *file)
501 unsigned long result;
502 unsigned long a, b, c, d;
503 char data[4];
505 quicktime_read_data(file, data, 4);
506 a = (unsigned char)data[0];
507 b = (unsigned char)data[1];
508 c = (unsigned char)data[2];
509 d = (unsigned char)data[3];
511 result = (d << 24) | (c << 16) | (b << 8) | a;
512 return (long)result;
515 int64_t quicktime_read_int64(quicktime_t *file)
517 uint64_t result, a, b, c, d, e, f, g, h;
518 char data[8];
520 quicktime_read_data(file, data, 8);
521 a = (unsigned char)data[0];
522 b = (unsigned char)data[1];
523 c = (unsigned char)data[2];
524 d = (unsigned char)data[3];
525 e = (unsigned char)data[4];
526 f = (unsigned char)data[5];
527 g = (unsigned char)data[6];
528 h = (unsigned char)data[7];
530 result = (a << 56) |
531 (b << 48) |
532 (c << 40) |
533 (d << 32) |
534 (e << 24) |
535 (f << 16) |
536 (g << 8) |
538 return (int64_t)result;
541 int64_t quicktime_read_int64_le(quicktime_t *file)
543 uint64_t result, a, b, c, d, e, f, g, h;
544 char data[8];
546 quicktime_read_data(file, data, 8);
547 a = (unsigned char)data[7];
548 b = (unsigned char)data[6];
549 c = (unsigned char)data[5];
550 d = (unsigned char)data[4];
551 e = (unsigned char)data[3];
552 f = (unsigned char)data[2];
553 g = (unsigned char)data[1];
554 h = (unsigned char)data[0];
556 result = (a << 56) |
557 (b << 48) |
558 (c << 40) |
559 (d << 32) |
560 (e << 24) |
561 (f << 16) |
562 (g << 8) |
564 return (int64_t)result;
568 long quicktime_read_int24(quicktime_t *file)
570 unsigned long result;
571 unsigned long a, b, c;
572 char data[4];
574 quicktime_read_data(file, data, 3);
575 a = (unsigned char)data[0];
576 b = (unsigned char)data[1];
577 c = (unsigned char)data[2];
579 result = (a << 16) | (b << 8) | c;
580 return (long)result;
583 int quicktime_write_int24(quicktime_t *file, long number)
585 unsigned char data[3];
586 data[0] = (number & 0xff0000) >> 16;
587 data[1] = (number & 0xff00) >> 8;
588 data[2] = (number & 0xff);
590 return quicktime_write_data(file, data, 3);
593 int quicktime_read_int16(quicktime_t *file)
595 unsigned long result;
596 unsigned long a, b;
597 char data[2];
599 quicktime_read_data(file, data, 2);
600 a = (unsigned char)data[0];
601 b = (unsigned char)data[1];
603 result = (a << 8) | b;
604 return (int)result;
607 int quicktime_read_int16_le(quicktime_t *file)
609 unsigned long result;
610 unsigned long a, b;
611 char data[2];
613 quicktime_read_data(file, data, 2);
614 a = (unsigned char)data[0];
615 b = (unsigned char)data[1];
617 result = (b << 8) | a;
618 return (int)result;
621 int quicktime_write_int16(quicktime_t *file, int number)
623 unsigned char data[2];
624 data[0] = (number & 0xff00) >> 8;
625 data[1] = (number & 0xff);
627 return quicktime_write_data(file, data, 2);
630 int quicktime_write_int16_le(quicktime_t *file, int number)
632 unsigned char data[2];
633 data[1] = (number & 0xff00) >> 8;
634 data[0] = (number & 0xff);
636 return quicktime_write_data(file, data, 2);
639 int quicktime_read_char(quicktime_t *file)
641 char output;
642 quicktime_read_data(file, &output, 1);
643 return output;
646 int quicktime_write_char(quicktime_t *file, char x)
648 return quicktime_write_data(file, &x, 1);
651 void quicktime_read_char32(quicktime_t *file, char *string)
653 quicktime_read_data(file, string, 4);
656 int64_t quicktime_position(quicktime_t *file)
658 return file->file_position;
661 int quicktime_set_position(quicktime_t *file, int64_t position)
663 file->file_position = position;
664 return 0;
667 void quicktime_copy_char32(char *output, char *input)
669 *output++ = *input++;
670 *output++ = *input++;
671 *output++ = *input++;
672 *output = *input;
676 void quicktime_print_chars(char *desc, char *input, int len)
678 int i;
679 printf("%s", desc);
680 for(i = 0; i < len; i++) printf("%c", input[i]);
681 printf("\n");
684 unsigned long quicktime_current_time(void)
686 time_t t;
687 time (&t);
688 return (t+(66*31536000)+1468800);
691 int quicktime_match_32(char *input, char *output)
693 if(input[0] == output[0] &&
694 input[1] == output[1] &&
695 input[2] == output[2] &&
696 input[3] == output[3])
697 return 1;
698 else
699 return 0;
702 int quicktime_match_24(char *input, char *output)
704 if(input[0] == output[0] &&
705 input[1] == output[1] &&
706 input[2] == output[2])
707 return 1;
708 else
709 return 0;