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 writes_attempted
= 1;
250 writes_succeeded
= fwrite(data
,
254 file
->file_position
+= size
;
255 file
->ftell_position
+= size
;
256 //printf("quicktime_write_data 2\n");
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
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
,
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
,
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
;
314 if(!writes_succeeded
&& writes_attempted
)
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
);
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);
360 return (float)a
+ (float)b
/ 65536;
365 int quicktime_write_fixed32(quicktime_t
*file
, float number
)
367 unsigned char data
[4];
371 b
= (number
- a
) * 65536;
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]);
449 return (float)data
[0] + (float)data
[1] / 256;
451 return (float)data
[0];
454 int quicktime_write_fixed16(quicktime_t
*file
, float number
)
456 unsigned char data
[2];
460 b
= (number
- a
) * 256;
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
;
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
;
483 long quicktime_read_int32(quicktime_t
*file
)
485 unsigned long result
;
486 unsigned long a
, b
, c
, d
;
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
;
499 long quicktime_read_int32_le(quicktime_t
*file
)
501 unsigned long result
;
502 unsigned long a
, b
, c
, d
;
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
;
515 int64_t quicktime_read_int64(quicktime_t
*file
)
517 uint64_t result
, a
, b
, c
, d
, e
, f
, g
, h
;
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];
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
;
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];
564 return (int64_t)result
;
568 long quicktime_read_int24(quicktime_t
*file
)
570 unsigned long result
;
571 unsigned long a
, b
, c
;
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
;
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
;
599 quicktime_read_data(file
, data
, 2);
600 a
= (unsigned char)data
[0];
601 b
= (unsigned char)data
[1];
603 result
= (a
<< 8) | b
;
607 int quicktime_read_int16_le(quicktime_t
*file
)
609 unsigned long result
;
613 quicktime_read_data(file
, data
, 2);
614 a
= (unsigned char)data
[0];
615 b
= (unsigned char)data
[1];
617 result
= (b
<< 8) | a
;
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
)
642 quicktime_read_data(file
, &output
, 1);
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
;
667 void quicktime_copy_char32(char *output
, char *input
)
669 *output
++ = *input
++;
670 *output
++ = *input
++;
671 *output
++ = *input
++;
676 void quicktime_print_chars(char *desc
, char *input
, int len
)
680 for(i
= 0; i
< len
; i
++) printf("%c", input
[i
]);
684 unsigned long quicktime_current_time(void)
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])
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])