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
)))
53 file
->total_length
= quicktime_get_file_length(path
);
56 file
->presave_buffer
= calloc(1, QUICKTIME_PRESAVE
);
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;
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");
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
;
128 int quicktime_read_data(quicktime_t
*file
, char *data
, int64_t size
)
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
;
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
;
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
);
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
);
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
;
216 int quicktime_write_data(quicktime_t
*file
, char *data
, int size
)
219 int writes_attempted
= 0;
220 int writes_succeeded
= 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
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
,
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
;
272 if(!writes_succeeded
&& writes_attempted
)
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
);
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);
318 return (float)a
+ (float)b
/ 65536;
323 int quicktime_write_fixed32(quicktime_t
*file
, float number
)
325 unsigned char data
[4];
329 b
= (number
- a
) * 65536;
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]);
407 return (float)data
[0] + (float)data
[1] / 256;
409 return (float)data
[0];
412 int quicktime_write_fixed16(quicktime_t
*file
, float number
)
414 unsigned char data
[2];
418 b
= (number
- a
) * 256;
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
;
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
;
441 long quicktime_read_int32(quicktime_t
*file
)
443 unsigned long result
;
444 unsigned long a
, b
, c
, d
;
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
;
457 long quicktime_read_int32_le(quicktime_t
*file
)
459 unsigned long result
;
460 unsigned long a
, b
, c
, d
;
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
;
473 int64_t quicktime_read_int64(quicktime_t
*file
)
475 uint64_t result
, a
, b
, c
, d
, e
, f
, g
, h
;
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];
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
;
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];
522 return (int64_t)result
;
526 long quicktime_read_int24(quicktime_t
*file
)
528 unsigned long result
;
529 unsigned long a
, b
, c
;
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
;
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
;
557 quicktime_read_data(file
, data
, 2);
558 a
= (unsigned char)data
[0];
559 b
= (unsigned char)data
[1];
561 result
= (a
<< 8) | b
;
565 int quicktime_read_int16_le(quicktime_t
*file
)
567 unsigned long result
;
571 quicktime_read_data(file
, data
, 2);
572 a
= (unsigned char)data
[0];
573 b
= (unsigned char)data
[1];
575 result
= (b
<< 8) | a
;
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
)
600 quicktime_read_data(file
, &output
, 1);
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
;
625 void quicktime_copy_char32(char *output
, char *input
)
627 *output
++ = *input
++;
628 *output
++ = *input
++;
629 *output
++ = *input
++;
634 void quicktime_print_chars(char *desc
, char *input
, int len
)
638 for(i
= 0; i
< len
; i
++) printf("%c", input
[i
]);
642 unsigned long quicktime_current_time(void)
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])
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])