r105: This commit was manufactured by cvs2svn to create tag
[cinelerra_cv/mob.git] / hvirtual / quicktime / util.c
blobba5c457b529786c605dd654913a8177a078f73a8
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;
51 if(rd && exists)
53 file->total_length = quicktime_get_file_length(path);
56 file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);
57 return 0;
60 int quicktime_file_close(quicktime_t *file)
62 /* Flush presave buffer */
63 if(file->presave_size)
65 quicktime_fseek(file, file->presave_position - file->presave_size);
66 fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
67 file->presave_size = 0;
70 if(file->stream)
72 fclose(file->stream);
74 file->stream = 0;
75 return 0;
80 int64_t quicktime_ftell(quicktime_t *file)
82 return file->ftell_position;
85 int quicktime_fseek(quicktime_t *file, int64_t offset)
87 file->ftell_position = offset;
88 if(offset > file->total_length || offset < 0) return 1;
89 if(FSEEK(file->stream, file->ftell_position, SEEK_SET))
91 // perror("quicktime_fseek FSEEK");
92 return 1;
94 return 0;
97 /* Read entire buffer from the preload buffer */
98 static int read_preload(quicktime_t *file, char *data, int64_t size)
100 int64_t selection_start = 0;
101 int64_t selection_end = 0;
102 int64_t fragment_start = 0;
103 int64_t fragment_len = 0;
105 selection_start = file->file_position;
106 selection_end = quicktime_add(file->file_position, size);
108 fragment_start = file->preload_ptr + (selection_start - file->preload_start);
109 while(fragment_start < 0) fragment_start += file->preload_size;
110 while(fragment_start >= file->preload_size) fragment_start -= file->preload_size;
112 while(selection_start < selection_end)
114 fragment_len = selection_end - selection_start;
115 if(fragment_start + fragment_len > file->preload_size)
116 fragment_len = file->preload_size - fragment_start;
118 memcpy(data, file->preload_buffer + fragment_start, fragment_len);
119 fragment_start += fragment_len;
120 data += fragment_len;
122 if(fragment_start >= file->preload_size) fragment_start = (int64_t)0;
123 selection_start += fragment_len;
125 return 0;
128 int quicktime_read_data(quicktime_t *file, char *data, int64_t size)
130 int result = 1;
132 if(!file->preload_size)
134 quicktime_fseek(file, file->file_position);
135 result = fread(data, size, 1, file->stream);
136 file->ftell_position += size;
138 else
140 /* Region requested for loading */
141 int64_t selection_start = file->file_position;
142 int64_t selection_end = file->file_position + size;
143 int64_t fragment_start, fragment_len;
145 if(selection_end - selection_start > file->preload_size)
147 /* Size is larger than preload size. Should never happen. */
148 printf("read data Size is larger than preload size. size=%llx preload_size=%llx\n",
149 selection_end - selection_start, file->preload_size);
150 quicktime_fseek(file, file->file_position);
151 result = fread(data, size, 1, file->stream);
152 file->ftell_position += size;
154 else
155 if(selection_start >= file->preload_start &&
156 selection_start < file->preload_end &&
157 selection_end <= file->preload_end &&
158 selection_end > file->preload_start)
160 /* Entire range is in buffer */
161 read_preload(file, data, size);
163 else
164 if(selection_end > file->preload_end &&
165 selection_end - file->preload_size < file->preload_end)
167 /* Range is after buffer */
168 /* Move the preload start to within one preload length of the selection_end */
169 while(selection_end - file->preload_start > file->preload_size)
171 fragment_len = selection_end - file->preload_start - file->preload_size;
172 if(file->preload_ptr + fragment_len > file->preload_size)
173 fragment_len = file->preload_size - file->preload_ptr;
174 file->preload_start += fragment_len;
175 file->preload_ptr += fragment_len;
176 if(file->preload_ptr >= file->preload_size) file->preload_ptr = 0;
179 /* Append sequential data after the preload end to the new end */
180 fragment_start = file->preload_ptr + file->preload_end - file->preload_start;
181 while(fragment_start >= file->preload_size)
182 fragment_start -= file->preload_size;
184 while(file->preload_end < selection_end)
186 fragment_len = selection_end - file->preload_end;
187 if(fragment_start + fragment_len > file->preload_size) fragment_len = file->preload_size - fragment_start;
188 quicktime_fseek(file, file->preload_end);
189 result = fread(&(file->preload_buffer[fragment_start]), fragment_len, 1, file->stream);
190 file->ftell_position += fragment_len;
191 file->preload_end += fragment_len;
192 fragment_start += fragment_len;
193 if(fragment_start >= file->preload_size) fragment_start = 0;
196 read_preload(file, data, size);
198 else
200 /* Range is before buffer or over a preload_size away from the end of the buffer. */
201 /* Replace entire preload buffer with range. */
202 quicktime_fseek(file, file->file_position);
203 result = fread(file->preload_buffer, size, 1, file->stream);
204 file->ftell_position += size;
205 file->preload_start = file->file_position;
206 file->preload_end = file->file_position + size;
207 file->preload_ptr = 0;
208 read_preload(file, data, size);
212 file->file_position += size;
213 return result;
216 int quicktime_write_data(quicktime_t *file, char *data, int size)
218 int data_offset = 0;
219 int writes_attempted = 0;
220 int writes_succeeded = 0;
221 int iterations = 0;
222 //printf("quicktime_write_data 1 %d\n", size);
224 // Flush existing buffer and seek to new position
225 if(file->file_position != file->presave_position)
227 if(file->presave_size)
229 quicktime_fseek(file, file->presave_position - file->presave_size);
230 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
231 writes_attempted += file->presave_size;
232 file->presave_size = 0;
234 file->presave_position = file->file_position;
237 // Write presave buffers until done
238 while(size > 0)
240 int fragment_size = QUICKTIME_PRESAVE;
241 if(fragment_size > size) fragment_size = size;
242 if(fragment_size + file->presave_size > QUICKTIME_PRESAVE)
243 fragment_size = QUICKTIME_PRESAVE- file->presave_size;
245 memcpy(file->presave_buffer + file->presave_size,
246 data + data_offset,
247 fragment_size);
249 file->presave_position += fragment_size;
250 file->presave_size += fragment_size;
251 data_offset += fragment_size;
252 size -= fragment_size;
254 if(file->presave_size >= QUICKTIME_PRESAVE)
256 //if(++iterations > 1) printf("quicktime_write_data 2 iterations=%d\n", iterations);
257 quicktime_fseek(file, file->presave_position - file->presave_size);
258 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
259 writes_attempted += file->presave_size;
260 file->presave_size = 0;
264 /* Adjust file position */
265 file->file_position = file->presave_position;
266 /* Adjust ftell position */
267 file->ftell_position = file->presave_position;
268 /* Adjust total length */
269 if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;
271 /* fwrite failed */
272 if(!writes_succeeded && writes_attempted)
274 return 0;
276 else
277 if(!size)
278 return 1;
279 else
280 return size;
283 int64_t quicktime_byte_position(quicktime_t *file)
285 return quicktime_position(file);
289 void quicktime_read_pascal(quicktime_t *file, char *data)
291 char len = quicktime_read_char(file);
292 quicktime_read_data(file, data, len);
293 data[len] = 0;
296 void quicktime_write_pascal(quicktime_t *file, char *data)
298 char len = strlen(data);
299 quicktime_write_data(file, &len, 1);
300 quicktime_write_data(file, data, len);
303 float quicktime_read_fixed32(quicktime_t *file)
305 unsigned long a, b, c, d;
306 unsigned char data[4];
308 quicktime_read_data(file, data, 4);
309 a = data[0];
310 b = data[1];
311 c = data[2];
312 d = data[3];
314 a = (a << 8) + b;
315 b = (c << 8) + d;
317 if(b)
318 return (float)a + (float)b / 65536;
319 else
320 return a;
323 int quicktime_write_fixed32(quicktime_t *file, float number)
325 unsigned char data[4];
326 int a, b;
328 a = number;
329 b = (number - a) * 65536;
330 data[0] = a >> 8;
331 data[1] = a & 0xff;
332 data[2] = b >> 8;
333 data[3] = b & 0xff;
335 return quicktime_write_data(file, data, 4);
338 int quicktime_write_int64(quicktime_t *file, int64_t value)
340 unsigned char data[8];
342 data[0] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
343 data[1] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
344 data[2] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
345 data[3] = (((uint64_t)value) & 0xff00000000LL) >> 32;
346 data[4] = (((uint64_t)value) & 0xff000000LL) >> 24;
347 data[5] = (((uint64_t)value) & 0xff0000LL) >> 16;
348 data[6] = (((uint64_t)value) & 0xff00LL) >> 8;
349 data[7] = ((uint64_t)value) & 0xff;
351 return quicktime_write_data(file, data, 8);
354 int quicktime_write_int64_le(quicktime_t *file, int64_t value)
356 unsigned char data[8];
358 data[7] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
359 data[6] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
360 data[5] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
361 data[4] = (((uint64_t)value) & 0xff00000000LL) >> 32;
362 data[3] = (((uint64_t)value) & 0xff000000LL) >> 24;
363 data[2] = (((uint64_t)value) & 0xff0000LL) >> 16;
364 data[1] = (((uint64_t)value) & 0xff00LL) >> 8;
365 data[0] = ((uint64_t)value) & 0xff;
367 return quicktime_write_data(file, data, 8);
370 int quicktime_write_int32(quicktime_t *file, long value)
372 unsigned char data[4];
374 data[0] = (value & 0xff000000) >> 24;
375 data[1] = (value & 0xff0000) >> 16;
376 data[2] = (value & 0xff00) >> 8;
377 data[3] = value & 0xff;
379 return quicktime_write_data(file, data, 4);
382 int quicktime_write_int32_le(quicktime_t *file, long value)
384 unsigned char data[4];
386 data[3] = (value & 0xff000000) >> 24;
387 data[2] = (value & 0xff0000) >> 16;
388 data[1] = (value & 0xff00) >> 8;
389 data[0] = value & 0xff;
391 return quicktime_write_data(file, data, 4);
394 int quicktime_write_char32(quicktime_t *file, char *string)
396 return quicktime_write_data(file, string, 4);
400 float quicktime_read_fixed16(quicktime_t *file)
402 unsigned char data[2];
404 quicktime_read_data(file, data, 2);
405 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
406 if(data[1])
407 return (float)data[0] + (float)data[1] / 256;
408 else
409 return (float)data[0];
412 int quicktime_write_fixed16(quicktime_t *file, float number)
414 unsigned char data[2];
415 int a, b;
417 a = number;
418 b = (number - a) * 256;
419 data[0] = a;
420 data[1] = b;
422 return quicktime_write_data(file, data, 2);
425 unsigned long quicktime_read_uint32(quicktime_t *file)
427 unsigned long result;
428 unsigned long a, b, c, d;
429 char data[4];
431 quicktime_read_data(file, data, 4);
432 a = (unsigned char)data[0];
433 b = (unsigned char)data[1];
434 c = (unsigned char)data[2];
435 d = (unsigned char)data[3];
437 result = (a << 24) | (b << 16) | (c << 8) | d;
438 return result;
441 long quicktime_read_int32(quicktime_t *file)
443 unsigned long result;
444 unsigned long a, b, c, d;
445 char data[4];
447 quicktime_read_data(file, data, 4);
448 a = (unsigned char)data[0];
449 b = (unsigned char)data[1];
450 c = (unsigned char)data[2];
451 d = (unsigned char)data[3];
453 result = (a << 24) | (b << 16) | (c << 8) | d;
454 return (long)result;
457 long quicktime_read_int32_le(quicktime_t *file)
459 unsigned long result;
460 unsigned long a, b, c, d;
461 char data[4];
463 quicktime_read_data(file, data, 4);
464 a = (unsigned char)data[0];
465 b = (unsigned char)data[1];
466 c = (unsigned char)data[2];
467 d = (unsigned char)data[3];
469 result = (d << 24) | (c << 16) | (b << 8) | a;
470 return (long)result;
473 int64_t quicktime_read_int64(quicktime_t *file)
475 uint64_t result, a, b, c, d, e, f, g, h;
476 char data[8];
478 quicktime_read_data(file, data, 8);
479 a = (unsigned char)data[0];
480 b = (unsigned char)data[1];
481 c = (unsigned char)data[2];
482 d = (unsigned char)data[3];
483 e = (unsigned char)data[4];
484 f = (unsigned char)data[5];
485 g = (unsigned char)data[6];
486 h = (unsigned char)data[7];
488 result = (a << 56) |
489 (b << 48) |
490 (c << 40) |
491 (d << 32) |
492 (e << 24) |
493 (f << 16) |
494 (g << 8) |
496 return (int64_t)result;
499 int64_t quicktime_read_int64_le(quicktime_t *file)
501 uint64_t result, a, b, c, d, e, f, g, h;
502 char data[8];
504 quicktime_read_data(file, data, 8);
505 a = (unsigned char)data[7];
506 b = (unsigned char)data[6];
507 c = (unsigned char)data[5];
508 d = (unsigned char)data[4];
509 e = (unsigned char)data[3];
510 f = (unsigned char)data[2];
511 g = (unsigned char)data[1];
512 h = (unsigned char)data[0];
514 result = (a << 56) |
515 (b << 48) |
516 (c << 40) |
517 (d << 32) |
518 (e << 24) |
519 (f << 16) |
520 (g << 8) |
522 return (int64_t)result;
526 long quicktime_read_int24(quicktime_t *file)
528 unsigned long result;
529 unsigned long a, b, c;
530 char data[4];
532 quicktime_read_data(file, data, 3);
533 a = (unsigned char)data[0];
534 b = (unsigned char)data[1];
535 c = (unsigned char)data[2];
537 result = (a << 16) | (b << 8) | c;
538 return (long)result;
541 int quicktime_write_int24(quicktime_t *file, long number)
543 unsigned char data[3];
544 data[0] = (number & 0xff0000) >> 16;
545 data[1] = (number & 0xff00) >> 8;
546 data[2] = (number & 0xff);
548 return quicktime_write_data(file, data, 3);
551 int quicktime_read_int16(quicktime_t *file)
553 unsigned long result;
554 unsigned long a, b;
555 char data[2];
557 quicktime_read_data(file, data, 2);
558 a = (unsigned char)data[0];
559 b = (unsigned char)data[1];
561 result = (a << 8) | b;
562 return (int)result;
565 int quicktime_read_int16_le(quicktime_t *file)
567 unsigned long result;
568 unsigned long a, b;
569 char data[2];
571 quicktime_read_data(file, data, 2);
572 a = (unsigned char)data[0];
573 b = (unsigned char)data[1];
575 result = (b << 8) | a;
576 return (int)result;
579 int quicktime_write_int16(quicktime_t *file, int number)
581 unsigned char data[2];
582 data[0] = (number & 0xff00) >> 8;
583 data[1] = (number & 0xff);
585 return quicktime_write_data(file, data, 2);
588 int quicktime_write_int16_le(quicktime_t *file, int number)
590 unsigned char data[2];
591 data[1] = (number & 0xff00) >> 8;
592 data[0] = (number & 0xff);
594 return quicktime_write_data(file, data, 2);
597 int quicktime_read_char(quicktime_t *file)
599 char output;
600 quicktime_read_data(file, &output, 1);
601 return output;
604 int quicktime_write_char(quicktime_t *file, char x)
606 return quicktime_write_data(file, &x, 1);
609 void quicktime_read_char32(quicktime_t *file, char *string)
611 quicktime_read_data(file, string, 4);
614 int64_t quicktime_position(quicktime_t *file)
616 return file->file_position;
619 int quicktime_set_position(quicktime_t *file, int64_t position)
621 file->file_position = position;
622 return 0;
625 void quicktime_copy_char32(char *output, char *input)
627 *output++ = *input++;
628 *output++ = *input++;
629 *output++ = *input++;
630 *output = *input;
634 void quicktime_print_chars(char *desc, char *input, int len)
636 int i;
637 printf("%s", desc);
638 for(i = 0; i < len; i++) printf("%c", input[i]);
639 printf("\n");
642 unsigned long quicktime_current_time(void)
644 time_t t;
645 time (&t);
646 return (t+(66*31536000)+1468800);
649 int quicktime_match_32(char *input, char *output)
651 if(input[0] == output[0] &&
652 input[1] == output[1] &&
653 input[2] == output[2] &&
654 input[3] == output[3])
655 return 1;
656 else
657 return 0;
660 int quicktime_match_24(char *input, char *output)
662 if(input[0] == output[0] &&
663 input[1] == output[1] &&
664 input[2] == output[2])
665 return 1;
666 else
667 return 0;