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=%llx preload_size=%llx\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;
247 if(!file
->use_presave
)
249 //printf("quicktime_write_data 1\n");
250 quicktime_fseek(file
, file
->file_position
);
251 writes_attempted
= 1;
252 writes_succeeded
= fwrite(data
,
256 file
->file_position
+= size
;
257 file
->ftell_position
+= size
;
258 file
->presave_position
= file
->file_position
;
262 // Flush existing buffer and seek to new position
263 if(file
->file_position
!= file
->presave_position
)
265 if(file
->presave_size
)
267 quicktime_fseek(file
, file
->presave_position
- file
->presave_size
);
268 writes_succeeded
+= fwrite(file
->presave_buffer
, 1, file
->presave_size
, file
->stream
);
269 writes_attempted
+= file
->presave_size
;
270 file
->presave_size
= 0;
272 file
->presave_position
= file
->file_position
;
275 // Write presave buffers until done
278 int fragment_size
= QUICKTIME_PRESAVE
;
279 if(fragment_size
> size
) fragment_size
= size
;
280 if(fragment_size
+ file
->presave_size
> QUICKTIME_PRESAVE
)
281 fragment_size
= QUICKTIME_PRESAVE
- file
->presave_size
;
283 memcpy(file
->presave_buffer
+ file
->presave_size
,
287 file
->presave_position
+= fragment_size
;
288 file
->presave_size
+= fragment_size
;
289 data_offset
+= fragment_size
;
290 size
-= fragment_size
;
292 if(file
->presave_size
>= QUICKTIME_PRESAVE
)
294 //if(++iterations > 1) printf("quicktime_write_data 2 iterations=%d\n", iterations);
295 quicktime_fseek(file
, file
->presave_position
- file
->presave_size
);
296 writes_succeeded
+= fwrite(file
->presave_buffer
,
300 writes_attempted
+= file
->presave_size
;
301 file
->presave_size
= 0;
305 /* Adjust file position */
306 file
->file_position
= file
->presave_position
;
307 /* Adjust ftell position */
308 file
->ftell_position
= file
->presave_position
;
312 /* Adjust total length */
313 if(file
->total_length
< file
->ftell_position
) file
->total_length
= file
->ftell_position
;
316 if(!writes_succeeded
&& writes_attempted
)
327 int64_t quicktime_byte_position(quicktime_t
*file
)
329 return quicktime_position(file
);
333 void quicktime_read_pascal(quicktime_t
*file
, char *data
)
335 char len
= quicktime_read_char(file
);
336 quicktime_read_data(file
, data
, len
);
340 void quicktime_write_pascal(quicktime_t
*file
, char *data
)
342 char len
= strlen(data
);
343 quicktime_write_data(file
, &len
, 1);
344 quicktime_write_data(file
, data
, len
);
347 float quicktime_read_fixed32(quicktime_t
*file
)
349 unsigned long a
, b
, c
, d
;
350 unsigned char data
[4];
352 quicktime_read_data(file
, data
, 4);
362 return (float)a
+ (float)b
/ 65536;
367 int quicktime_write_fixed32(quicktime_t
*file
, float number
)
369 unsigned char data
[4];
373 b
= (number
- a
) * 65536;
379 return quicktime_write_data(file
, data
, 4);
382 int quicktime_write_int64(quicktime_t
*file
, int64_t value
)
384 unsigned char data
[8];
386 data
[0] = (((uint64_t)value
) & 0xff00000000000000LL
) >> 56;
387 data
[1] = (((uint64_t)value
) & 0xff000000000000LL
) >> 48;
388 data
[2] = (((uint64_t)value
) & 0xff0000000000LL
) >> 40;
389 data
[3] = (((uint64_t)value
) & 0xff00000000LL
) >> 32;
390 data
[4] = (((uint64_t)value
) & 0xff000000LL
) >> 24;
391 data
[5] = (((uint64_t)value
) & 0xff0000LL
) >> 16;
392 data
[6] = (((uint64_t)value
) & 0xff00LL
) >> 8;
393 data
[7] = ((uint64_t)value
) & 0xff;
395 return quicktime_write_data(file
, data
, 8);
398 int quicktime_write_int64_le(quicktime_t
*file
, int64_t value
)
400 unsigned char data
[8];
402 data
[7] = (((uint64_t)value
) & 0xff00000000000000LL
) >> 56;
403 data
[6] = (((uint64_t)value
) & 0xff000000000000LL
) >> 48;
404 data
[5] = (((uint64_t)value
) & 0xff0000000000LL
) >> 40;
405 data
[4] = (((uint64_t)value
) & 0xff00000000LL
) >> 32;
406 data
[3] = (((uint64_t)value
) & 0xff000000LL
) >> 24;
407 data
[2] = (((uint64_t)value
) & 0xff0000LL
) >> 16;
408 data
[1] = (((uint64_t)value
) & 0xff00LL
) >> 8;
409 data
[0] = ((uint64_t)value
) & 0xff;
411 return quicktime_write_data(file
, data
, 8);
414 int quicktime_write_int32(quicktime_t
*file
, long value
)
416 unsigned char data
[4];
418 data
[0] = (value
& 0xff000000) >> 24;
419 data
[1] = (value
& 0xff0000) >> 16;
420 data
[2] = (value
& 0xff00) >> 8;
421 data
[3] = value
& 0xff;
423 return quicktime_write_data(file
, data
, 4);
426 int quicktime_write_int32_le(quicktime_t
*file
, long value
)
428 unsigned char data
[4];
430 data
[3] = (value
& 0xff000000) >> 24;
431 data
[2] = (value
& 0xff0000) >> 16;
432 data
[1] = (value
& 0xff00) >> 8;
433 data
[0] = value
& 0xff;
435 return quicktime_write_data(file
, data
, 4);
438 int quicktime_write_char32(quicktime_t
*file
, char *string
)
440 return quicktime_write_data(file
, string
, 4);
444 float quicktime_read_fixed16(quicktime_t
*file
)
446 unsigned char data
[2];
448 quicktime_read_data(file
, data
, 2);
449 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
451 return (float)data
[0] + (float)data
[1] / 256;
453 return (float)data
[0];
456 int quicktime_write_fixed16(quicktime_t
*file
, float number
)
458 unsigned char data
[2];
462 b
= (number
- a
) * 256;
466 return quicktime_write_data(file
, data
, 2);
469 unsigned long quicktime_read_uint32(quicktime_t
*file
)
471 unsigned long result
;
472 unsigned long a
, b
, c
, d
;
475 quicktime_read_data(file
, data
, 4);
476 a
= (unsigned char)data
[0];
477 b
= (unsigned char)data
[1];
478 c
= (unsigned char)data
[2];
479 d
= (unsigned char)data
[3];
481 result
= (a
<< 24) | (b
<< 16) | (c
<< 8) | d
;
485 long quicktime_read_int32(quicktime_t
*file
)
487 unsigned long result
;
488 unsigned long a
, b
, c
, d
;
491 quicktime_read_data(file
, data
, 4);
492 a
= (unsigned char)data
[0];
493 b
= (unsigned char)data
[1];
494 c
= (unsigned char)data
[2];
495 d
= (unsigned char)data
[3];
497 result
= (a
<< 24) | (b
<< 16) | (c
<< 8) | d
;
501 long quicktime_read_int32_le(quicktime_t
*file
)
503 unsigned long result
;
504 unsigned long a
, b
, c
, d
;
507 quicktime_read_data(file
, data
, 4);
508 a
= (unsigned char)data
[0];
509 b
= (unsigned char)data
[1];
510 c
= (unsigned char)data
[2];
511 d
= (unsigned char)data
[3];
513 result
= (d
<< 24) | (c
<< 16) | (b
<< 8) | a
;
517 int64_t quicktime_read_int64(quicktime_t
*file
)
519 uint64_t result
, a
, b
, c
, d
, e
, f
, g
, h
;
522 quicktime_read_data(file
, data
, 8);
523 a
= (unsigned char)data
[0];
524 b
= (unsigned char)data
[1];
525 c
= (unsigned char)data
[2];
526 d
= (unsigned char)data
[3];
527 e
= (unsigned char)data
[4];
528 f
= (unsigned char)data
[5];
529 g
= (unsigned char)data
[6];
530 h
= (unsigned char)data
[7];
540 return (int64_t)result
;
543 int64_t quicktime_read_int64_le(quicktime_t
*file
)
545 uint64_t result
, a
, b
, c
, d
, e
, f
, g
, h
;
548 quicktime_read_data(file
, data
, 8);
549 a
= (unsigned char)data
[7];
550 b
= (unsigned char)data
[6];
551 c
= (unsigned char)data
[5];
552 d
= (unsigned char)data
[4];
553 e
= (unsigned char)data
[3];
554 f
= (unsigned char)data
[2];
555 g
= (unsigned char)data
[1];
556 h
= (unsigned char)data
[0];
566 return (int64_t)result
;
570 long quicktime_read_int24(quicktime_t
*file
)
572 unsigned long result
;
573 unsigned long a
, b
, c
;
576 quicktime_read_data(file
, data
, 3);
577 a
= (unsigned char)data
[0];
578 b
= (unsigned char)data
[1];
579 c
= (unsigned char)data
[2];
581 result
= (a
<< 16) | (b
<< 8) | c
;
585 int quicktime_write_int24(quicktime_t
*file
, long number
)
587 unsigned char data
[3];
588 data
[0] = (number
& 0xff0000) >> 16;
589 data
[1] = (number
& 0xff00) >> 8;
590 data
[2] = (number
& 0xff);
592 return quicktime_write_data(file
, data
, 3);
595 int quicktime_read_int16(quicktime_t
*file
)
597 unsigned long result
;
601 quicktime_read_data(file
, data
, 2);
602 a
= (unsigned char)data
[0];
603 b
= (unsigned char)data
[1];
605 result
= (a
<< 8) | b
;
609 int quicktime_read_int16_le(quicktime_t
*file
)
611 unsigned long result
;
615 quicktime_read_data(file
, data
, 2);
616 a
= (unsigned char)data
[0];
617 b
= (unsigned char)data
[1];
619 result
= (b
<< 8) | a
;
623 int quicktime_write_int16(quicktime_t
*file
, int number
)
625 unsigned char data
[2];
626 data
[0] = (number
& 0xff00) >> 8;
627 data
[1] = (number
& 0xff);
629 return quicktime_write_data(file
, data
, 2);
632 int quicktime_write_int16_le(quicktime_t
*file
, int number
)
634 unsigned char data
[2];
635 data
[1] = (number
& 0xff00) >> 8;
636 data
[0] = (number
& 0xff);
638 return quicktime_write_data(file
, data
, 2);
641 int quicktime_read_char(quicktime_t
*file
)
644 quicktime_read_data(file
, &output
, 1);
648 int quicktime_write_char(quicktime_t
*file
, char x
)
650 return quicktime_write_data(file
, &x
, 1);
653 void quicktime_read_char32(quicktime_t
*file
, char *string
)
655 quicktime_read_data(file
, string
, 4);
658 int64_t quicktime_position(quicktime_t
*file
)
660 return file
->file_position
;
663 int quicktime_set_position(quicktime_t
*file
, int64_t position
)
665 file
->file_position
= position
;
666 if(!file
->use_presave
)
668 quicktime_fseek(file
, position
);
669 file
->presave_position
= position
;
674 void quicktime_copy_char32(char *output
, char *input
)
676 *output
++ = *input
++;
677 *output
++ = *input
++;
678 *output
++ = *input
++;
683 void quicktime_print_chars(char *desc
, char *input
, int len
)
687 for(i
= 0; i
< len
; i
++) printf("%c", input
[i
]);
691 unsigned long quicktime_current_time(void)
695 return (t
+(66*31536000)+1468800);
698 int quicktime_match_32(char *input
, char *output
)
700 if(input
[0] == output
[0] &&
701 input
[1] == output
[1] &&
702 input
[2] == output
[2] &&
703 input
[3] == output
[3])
709 int quicktime_match_24(char *input
, char *output
)
711 if(input
[0] == output
[0] &&
712 input
[1] == output
[1] &&
713 input
[2] == output
[2])
719 int quicktime_quantize16(int number
)
721 if(number
&& (number
% 16))
723 number
+= 16 - (number
% 16);
728 int quicktime_quantize32(int number
)
730 if(number
&& (number
% 32))
732 number
+= 32 - (number
% 32);