2 #include <linux/cdrom.h>
10 #include "funcprotos.h"
11 #include "quicktime.h"
12 #include "workarounds.h"
16 int64_t quicktime_get_file_length(char *path)
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)
28 if(rd && (file->stream = fopen(path, "rb")))
34 if(rd && !wr) sprintf(flags, "rb");
36 if(!rd && wr) sprintf(flags, "wb");
41 sprintf(flags, "rb+");
43 sprintf(flags, "wb+");
46 if(!(file->stream = fopen(path, flags)))
55 file->total_length = quicktime_get_file_length(path);
58 file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);
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;
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");
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;
130 int quicktime_read_data(quicktime_t *file, char *data, int64_t size)
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;
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=0x%jx preload_size=0x%jx\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;
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);
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);
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;
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;
232 if(value && !file->use_presave)
237 file->use_presave = value;
240 int quicktime_write_data(quicktime_t *file, char *data, int size)
243 int writes_attempted = 0;
244 int writes_succeeded = 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,
255 file->file_position += size;
256 file->ftell_position += size;
257 file->presave_position = file->file_position;
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
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,
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,
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;
315 if(!writes_succeeded && writes_attempted)
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 int len = quicktime_read_char(file);
335 quicktime_read_data(file, data, len);
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, (char*)data, 4);
361 return (float)a + (float)b / 65536;
366 int quicktime_write_fixed32(quicktime_t *file, float number)
368 unsigned char data[4];
372 b = (number - a) * 65536;
378 return quicktime_write_data(file, (char*)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, (char*)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, (char*)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, (char*)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, (char*)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, (char*)data, 2);
448 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
450 return (float)data[0] + (float)data[1] / 256;
452 return (float)data[0];
455 int quicktime_write_fixed16(quicktime_t *file, float number)
457 unsigned char data[2];
461 b = (number - a) * 256;
465 return quicktime_write_data(file, (char*)data, 2);
468 unsigned long quicktime_read_uint32(quicktime_t *file)
470 unsigned long result;
471 unsigned long a, b, c, d;
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;
484 long quicktime_read_int32(quicktime_t *file)
486 unsigned long result;
487 unsigned long a, b, c, d;
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;
500 long quicktime_read_int32_le(quicktime_t *file)
502 unsigned long result;
503 unsigned long a, b, c, d;
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;
516 int64_t quicktime_read_int64(quicktime_t *file)
518 uint64_t result, a, b, c, d, e, f, g, h;
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];
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;
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];
565 return (int64_t)result;
569 long quicktime_read_int24(quicktime_t *file)
571 unsigned long result;
572 unsigned long a, b, c;
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;
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, (char*)data, 3);
594 int quicktime_read_int16(quicktime_t *file)
596 unsigned long result;
600 quicktime_read_data(file, data, 2);
601 a = (unsigned char)data[0];
602 b = (unsigned char)data[1];
604 result = (a << 8) | b;
608 int quicktime_read_int16_le(quicktime_t *file)
610 unsigned long result;
614 quicktime_read_data(file, data, 2);
615 a = (unsigned char)data[0];
616 b = (unsigned char)data[1];
618 result = (b << 8) | a;
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, (char*)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, (char*)data, 2);
640 int quicktime_read_char(quicktime_t *file)
643 quicktime_read_data(file, &output, 1);
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 if(!file->use_presave)
667 quicktime_fseek(file, position);
668 file->presave_position = position;
673 void quicktime_copy_char32(char *output, char *input)
675 *output++ = *input++;
676 *output++ = *input++;
677 *output++ = *input++;
682 void quicktime_print_chars(char *desc, char *input, int len)
686 for(i = 0; i < len; i++) printf("%c", input[i]);
690 unsigned long quicktime_current_time(void)
694 return (t+(66*31536000)+1468800);
697 int quicktime_match_32(char *input, char *output)
699 if(input[0] == output[0] &&
700 input[1] == output[1] &&
701 input[2] == output[2] &&
702 input[3] == output[3])
708 int quicktime_match_24(char *input, char *output)
710 if(input[0] == output[0] &&
711 input[1] == output[1] &&
712 input[2] == output[2])
718 int quicktime_quantize2(int number)
720 if(number && (number % 2))
722 number += 2 - (number % 2);
727 int quicktime_quantize8(int number)
729 if(number && (number % 8))
731 number += 8 - (number % 8);
736 int quicktime_quantize16(int number)
738 if(number && (number % 16))
740 number += 16 - (number % 16);
745 int quicktime_quantize32(int number)
747 if(number && (number % 32))
749 number += 32 - (number % 32);