2 #include <linux/cdrom.h>
9 #include "funcprotos.h"
10 #include "quicktime.h"
11 #include "workarounds.h"
15 int64_t quicktime_get_file_length(char *path
)
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
)
27 if(rd
&& (file
->stream
= fopen(path
, "rb")))
33 if(rd
&& !wr
) sprintf(flags
, "rb");
35 if(!rd
&& wr
) sprintf(flags
, "wb");
40 sprintf(flags
, "rb+");
42 sprintf(flags
, "wb+");
45 if(!(file
->stream
= fopen(path
, flags
)))
54 file
->total_length
= quicktime_get_file_length(path
);
57 file
->presave_buffer
= calloc(1, QUICKTIME_PRESAVE
);
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;
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");
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
;
129 int quicktime_read_data(quicktime_t
*file
, char *data
, int64_t size
)
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
;
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
;
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
);
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
);
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
;
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
;
231 if(value
&& !file
->use_presave
)
236 file
->use_presave
= value
;
239 int quicktime_write_data(quicktime_t
*file
, char *data
, int size
)
242 int writes_attempted
= 0;
243 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 char 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
, 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
, 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]);
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
, 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
, 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
, 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
)
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_quantize16(int number
)
720 if(number
&& (number
% 16))
722 number
+= 16 - (number
% 16);
727 int quicktime_quantize32(int number
)
729 if(number
&& (number
% 32))
731 number
+= 32 - (number
% 32);