allow ffmpeg video to resample curr_pos, add bluray format
[goodguy/history.git] / cinelerra-5.0 / quicktime / util.c
1 #include <fcntl.h>
2 #include <linux/cdrom.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <string.h>
6 #include <sys/ioctl.h>
7 #include <sys/stat.h>
8 #include <time.h>
9 #include <unistd.h>
10 #include "funcprotos.h"
11 #include "quicktime.h"
12 #include "workarounds.h"
13
14 /* Disk I/O */
15
16 int64_t quicktime_get_file_length(char *path)
17 {
18         struct stat64 status;
19         if(stat64(path, &status))
20                 perror("quicktime_get_file_length stat64:");
21         return status.st_size;
22 }
23
24 int quicktime_file_open(quicktime_t *file, char *path, int rd, int wr)
25 {
26         int exists = 0;
27         char flags[10];
28         if(rd && (file->stream = fopen(path, "rb")))
29         {
30                 exists = 1;
31                 fclose(file->stream);
32         }
33
34         if(rd && !wr) sprintf(flags, "rb");
35         else
36         if(!rd && wr) sprintf(flags, "wb");
37         else
38         if(rd && wr)
39         {
40                 if(exists)
41                         sprintf(flags, "rb+");
42                 else
43                         sprintf(flags, "wb+");
44         }
45
46         if(!(file->stream = fopen(path, flags)))
47         {
48                 perror(__FUNCTION__);
49                 return 1;
50         }
51
52
53         if(rd && exists)
54         {
55                 file->total_length = quicktime_get_file_length(path);
56         }
57
58         file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);
59         return 0;
60 }
61
62 int quicktime_file_close(quicktime_t *file)
63 {
64 /* Flush presave buffer */
65         if(file->presave_size)
66         {
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;
70         }
71
72         if(file->stream)
73         {
74                 fclose(file->stream);
75         }
76         file->stream = 0;
77         return 0;
78 }
79
80
81
82 int64_t quicktime_ftell(quicktime_t *file)
83 {
84         return file->ftell_position;
85 }
86
87 int quicktime_fseek(quicktime_t *file, int64_t offset)
88 {
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))
92         {
93 //              perror("quicktime_fseek FSEEK");
94                 return 1;
95         }
96         return 0;
97 }
98
99 /* Read entire buffer from the preload buffer */
100 static int read_preload(quicktime_t *file, char *data, int64_t size)
101 {
102         int64_t selection_start = 0;
103         int64_t selection_end = 0;
104         int64_t fragment_start = 0;
105         int64_t fragment_len = 0;
106
107         selection_start = file->file_position;
108         selection_end = quicktime_add(file->file_position, size);
109
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;
113
114         while(selection_start < selection_end)
115         {
116                 fragment_len = selection_end - selection_start;
117                 if(fragment_start + fragment_len > file->preload_size)
118                         fragment_len = file->preload_size - fragment_start;
119
120                 memcpy(data, file->preload_buffer + fragment_start, fragment_len);
121                 fragment_start += fragment_len;
122                 data += fragment_len;
123
124                 if(fragment_start >= file->preload_size) fragment_start = (int64_t)0;
125                 selection_start += fragment_len;
126         }
127         return 0;
128 }
129
130 int quicktime_read_data(quicktime_t *file, char *data, int64_t size)
131 {
132         int result = 1;
133
134         if(!file->preload_size)
135         {
136                 quicktime_fseek(file, file->file_position);
137                 result = fread(data, size, 1, file->stream);
138                 file->ftell_position += size;
139         }
140         else
141         {
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;
146
147                 if(selection_end - selection_start > file->preload_size)
148                 {
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;
155                 }
156                 else
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)
161                 {
162 /* Entire range is in buffer */
163                         read_preload(file, data, size);
164                 }
165                 else
166                 if(selection_end > file->preload_end &&
167                         selection_end - file->preload_size < file->preload_end)
168                 {
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)
172                         {
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;
179                         }
180
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;
185
186                         while(file->preload_end < selection_end)
187                         {
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;
196                         }
197
198                         read_preload(file, data, size);
199                 }
200                 else
201                 {
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);
211                 }
212         }
213
214         file->file_position += size;
215         return result;
216 }
217
218 void quicktime_set_presave(quicktime_t *file, int value)
219 {
220 // Flush presave buffer
221         if(!value && file->use_presave)
222         {
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;
230         }
231         else
232         if(value && !file->use_presave)
233         {
234                 ;
235         }
236
237         file->use_presave = value;
238 }
239
240 int quicktime_write_data(quicktime_t *file, char *data, int size)
241 {
242         int data_offset = 0;
243         int writes_attempted = 0;
244         int writes_succeeded = 0;
245
246         if(!file->use_presave)
247         {
248 //printf("quicktime_write_data 1\n");
249                 quicktime_fseek(file, file->file_position);
250                 writes_attempted = 1;
251                 writes_succeeded = fwrite(data,
252                                 size,
253                                 1,
254                                 file->stream);
255                 file->file_position += size;
256                 file->ftell_position += size;
257                 file->presave_position = file->file_position;
258         }
259         else
260         {
261 // Flush existing buffer and seek to new position
262                 if(file->file_position != file->presave_position)
263                 {
264                         if(file->presave_size)
265                         {
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;
270                         }
271                         file->presave_position = file->file_position;
272                 }
273
274 // Write presave buffers until done
275                 while(size > 0)
276                 {
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;
281
282                         memcpy(file->presave_buffer + file->presave_size,
283                                 data + data_offset,
284                                 fragment_size);
285
286                         file->presave_position += fragment_size;
287                         file->presave_size += fragment_size;
288                         data_offset += fragment_size;
289                         size -= fragment_size;
290
291                         if(file->presave_size >= QUICKTIME_PRESAVE)
292                         {
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,
296                                         file->presave_size,
297                                         1,
298                                         file->stream);
299                                 writes_attempted += file->presave_size;
300                                 file->presave_size = 0;
301                         }
302                 }
303
304 /* Adjust file position */
305                 file->file_position = file->presave_position;
306 /* Adjust ftell position */
307                 file->ftell_position = file->presave_position;
308         }
309
310
311 /* Adjust total length */
312         if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;
313
314 /* fwrite failed */
315         if(!writes_succeeded && writes_attempted)
316         {
317                 return 0;
318         }
319         else
320         if(!size)
321                 return 1;
322         else
323                 return size;
324 }
325
326 int64_t quicktime_byte_position(quicktime_t *file)
327 {
328         return quicktime_position(file);
329 }
330
331
332 void quicktime_read_pascal(quicktime_t *file, char *data)
333 {
334         int len = quicktime_read_char(file);
335         quicktime_read_data(file, data, len);
336         data[len] = 0;
337 }
338
339 void quicktime_write_pascal(quicktime_t *file, char *data)
340 {
341         char len = strlen(data);
342         quicktime_write_data(file, &len, 1);
343         quicktime_write_data(file, data, len);
344 }
345
346 float quicktime_read_fixed32(quicktime_t *file)
347 {
348         unsigned long a, b, c, d;
349         unsigned char data[4];
350
351         quicktime_read_data(file, (char*)data, 4);
352         a = data[0];
353         b = data[1];
354         c = data[2];
355         d = data[3];
356
357         a = (a << 8) + b;
358         b = (c << 8) + d;
359
360         if(b)
361                 return (float)a + (float)b / 65536;
362         else
363                 return a;
364 }
365
366 int quicktime_write_fixed32(quicktime_t *file, float number)
367 {
368         unsigned char data[4];
369         int a, b;
370
371         a = number;
372         b = (number - a) * 65536;
373         data[0] = a >> 8;
374         data[1] = a & 0xff;
375         data[2] = b >> 8;
376         data[3] = b & 0xff;
377
378         return quicktime_write_data(file, (char*)data, 4);
379 }
380
381 int quicktime_write_int64(quicktime_t *file, int64_t value)
382 {
383         unsigned char data[8];
384
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;
393
394         return quicktime_write_data(file, (char*)data, 8);
395 }
396
397 int quicktime_write_int64_le(quicktime_t *file, int64_t value)
398 {
399         unsigned char data[8];
400
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;
409
410         return quicktime_write_data(file, (char*)data, 8);
411 }
412
413 int quicktime_write_int32(quicktime_t *file, long value)
414 {
415         unsigned char data[4];
416
417         data[0] = (value & 0xff000000) >> 24;
418         data[1] = (value & 0xff0000) >> 16;
419         data[2] = (value & 0xff00) >> 8;
420         data[3] = value & 0xff;
421
422         return quicktime_write_data(file, (char*)data, 4);
423 }
424
425 int quicktime_write_int32_le(quicktime_t *file, long value)
426 {
427         unsigned char data[4];
428
429         data[3] = (value & 0xff000000) >> 24;
430         data[2] = (value & 0xff0000) >> 16;
431         data[1] = (value & 0xff00) >> 8;
432         data[0] = value & 0xff;
433
434         return quicktime_write_data(file, (char*)data, 4);
435 }
436
437 int quicktime_write_char32(quicktime_t *file, char *string)
438 {
439         return quicktime_write_data(file, string, 4);
440 }
441
442
443 float quicktime_read_fixed16(quicktime_t *file)
444 {
445         unsigned char data[2];
446
447         quicktime_read_data(file, (char*)data, 2);
448 //printf("quicktime_read_fixed16 %02x%02x\n", data[0], data[1]);
449         if(data[1])
450                 return (float)data[0] + (float)data[1] / 256;
451         else
452                 return (float)data[0];
453 }
454
455 int quicktime_write_fixed16(quicktime_t *file, float number)
456 {
457         unsigned char data[2];
458         int a, b;
459
460         a = number;
461         b = (number - a) * 256;
462         data[0] = a;
463         data[1] = b;
464
465         return quicktime_write_data(file, (char*)data, 2);
466 }
467
468 unsigned long quicktime_read_uint32(quicktime_t *file)
469 {
470         unsigned long result;
471         unsigned long a, b, c, d;
472         char data[4];
473
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];
479
480         result = (a << 24) | (b << 16) | (c << 8) | d;
481         return result;
482 }
483
484 long quicktime_read_int32(quicktime_t *file)
485 {
486         unsigned long result;
487         unsigned long a, b, c, d;
488         char data[4];
489
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];
495
496         result = (a << 24) | (b << 16) | (c << 8) | d;
497         return (long)result;
498 }
499
500 long quicktime_read_int32_le(quicktime_t *file)
501 {
502         unsigned long result;
503         unsigned long a, b, c, d;
504         char data[4];
505
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];
511
512         result = (d << 24) | (c << 16) | (b << 8) | a;
513         return (long)result;
514 }
515
516 int64_t quicktime_read_int64(quicktime_t *file)
517 {
518         uint64_t result, a, b, c, d, e, f, g, h;
519         char data[8];
520
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];
530
531         result = (a << 56) |
532                 (b << 48) |
533                 (c << 40) |
534                 (d << 32) |
535                 (e << 24) |
536                 (f << 16) |
537                 (g << 8) |
538                 h;
539         return (int64_t)result;
540 }
541
542 int64_t quicktime_read_int64_le(quicktime_t *file)
543 {
544         uint64_t result, a, b, c, d, e, f, g, h;
545         char data[8];
546
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];
556
557         result = (a << 56) |
558                 (b << 48) |
559                 (c << 40) |
560                 (d << 32) |
561                 (e << 24) |
562                 (f << 16) |
563                 (g << 8) |
564                 h;
565         return (int64_t)result;
566 }
567
568
569 long quicktime_read_int24(quicktime_t *file)
570 {
571         unsigned long result;
572         unsigned long a, b, c;
573         char data[4];
574
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];
579
580         result = (a << 16) | (b << 8) | c;
581         return (long)result;
582 }
583
584 int quicktime_write_int24(quicktime_t *file, long number)
585 {
586         unsigned char data[3];
587         data[0] = (number & 0xff0000) >> 16;
588         data[1] = (number & 0xff00) >> 8;
589         data[2] = (number & 0xff);
590
591         return quicktime_write_data(file, (char*)data, 3);
592 }
593
594 int quicktime_read_int16(quicktime_t *file)
595 {
596         unsigned long result;
597         unsigned long a, b;
598         char data[2];
599
600         quicktime_read_data(file, data, 2);
601         a = (unsigned char)data[0];
602         b = (unsigned char)data[1];
603
604         result = (a << 8) | b;
605         return (int)result;
606 }
607
608 int quicktime_read_int16_le(quicktime_t *file)
609 {
610         unsigned long result;
611         unsigned long a, b;
612         char data[2];
613
614         quicktime_read_data(file, data, 2);
615         a = (unsigned char)data[0];
616         b = (unsigned char)data[1];
617
618         result = (b << 8) | a;
619         return (int)result;
620 }
621
622 int quicktime_write_int16(quicktime_t *file, int number)
623 {
624         unsigned char data[2];
625         data[0] = (number & 0xff00) >> 8;
626         data[1] = (number & 0xff);
627
628         return quicktime_write_data(file, (char*)data, 2);
629 }
630
631 int quicktime_write_int16_le(quicktime_t *file, int number)
632 {
633         unsigned char data[2];
634         data[1] = (number & 0xff00) >> 8;
635         data[0] = (number & 0xff);
636
637         return quicktime_write_data(file, (char*)data, 2);
638 }
639
640 int quicktime_read_char(quicktime_t *file)
641 {
642         char output;
643         quicktime_read_data(file, &output, 1);
644         return output;
645 }
646
647 int quicktime_write_char(quicktime_t *file, char x)
648 {
649         return quicktime_write_data(file, &x, 1);
650 }
651
652 void quicktime_read_char32(quicktime_t *file, char *string)
653 {
654         quicktime_read_data(file, string, 4);
655 }
656
657 int64_t quicktime_position(quicktime_t *file)
658 {
659         return file->file_position;
660 }
661
662 int quicktime_set_position(quicktime_t *file, int64_t position)
663 {
664         file->file_position = position;
665         if(!file->use_presave)
666         {
667                 quicktime_fseek(file, position);
668                 file->presave_position = position;
669         }
670         return 0;
671 }
672
673 void quicktime_copy_char32(char *output, char *input)
674 {
675         *output++ = *input++;
676         *output++ = *input++;
677         *output++ = *input++;
678         *output = *input;
679 }
680
681
682 void quicktime_print_chars(char *desc, char *input, int len)
683 {
684         int i;
685         printf("%s", desc);
686         for(i = 0; i < len; i++) printf("%c", input[i]);
687         printf("\n");
688 }
689
690 unsigned long quicktime_current_time(void)
691 {
692         time_t t;
693         time (&t);
694         return (t+(66*31536000)+1468800);
695 }
696
697 int quicktime_match_32(char *input, char *output)
698 {
699         if(input[0] == output[0] &&
700                 input[1] == output[1] &&
701                 input[2] == output[2] &&
702                 input[3] == output[3])
703                 return 1;
704         else
705                 return 0;
706 }
707
708 int quicktime_match_24(char *input, char *output)
709 {
710         if(input[0] == output[0] &&
711                 input[1] == output[1] &&
712                 input[2] == output[2])
713                 return 1;
714         else
715                 return 0;
716 }
717
718 int quicktime_quantize2(int number)
719 {
720         if(number && (number % 2))
721         {
722                 number += 2 - (number % 2);
723         }
724         return number;
725 }
726
727 int quicktime_quantize8(int number)
728 {
729         if(number && (number % 8))
730         {
731                 number += 8 - (number % 8);
732         }
733         return number;
734 }
735
736 int quicktime_quantize16(int number)
737 {
738         if(number && (number % 16))
739         {
740                 number += 16 - (number % 16);
741         }
742         return number;
743 }
744
745 int quicktime_quantize32(int number)
746 {
747         if(number && (number % 32))
748         {
749                 number += 32 - (number % 32);
750         }
751         return number;
752 }
753