1 /*******************************************************************************
2 util.c
3
4 libquicktime - A library for reading and writing quicktime/avi/mp4 files.
5 http://libquicktime.sourceforge.net
6
7 Copyright (C) 2002 Heroine Virtual Ltd.
8 Copyright (C) 2002-2011 Members of the libquicktime project.
9
10 This library is free software; you can redistribute it and/or modify it under
11 the terms of the GNU Lesser General Public License as published by the Free
12 Software Foundation; either version 2.1 of the License, or (at your option)
13 any later version.
14
15 This library is distributed in the hope that it will be useful, but WITHOUT
16 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
18 details.
19
20 You should have received a copy of the GNU Lesser General Public License along
21 with this library; if not, write to the Free Software Foundation, Inc., 51
22 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 *******************************************************************************/
24
25 #include "lqt_private.h"
26 #include "lqt_fseek.h"
27 #include "workarounds.h"
28 #include <sys/stat.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <time.h>
34 #include <math.h>
35
36 #ifndef HAVE_LRINT
37 #define lrint(x) ((long int)(x))
38 #endif
39
40 /* Disk I/O */
41
quicktime_get_file_length(const char * path)42 int64_t quicktime_get_file_length(const char *path)
43 {
44 struct stat status;
45 if(stat(path, &status))
46 perror("quicktime_get_file_length stat:");
47 return status.st_size;
48 }
49
quicktime_file_open(quicktime_t * file,const char * path,int rd,int wr)50 int quicktime_file_open(quicktime_t *file, const char *path, int rd, int wr)
51 {
52 int exists = 0;
53 char flags[10];
54 if(rd && (file->stream = fopen(path, "rb")))
55 {
56 exists = 1;
57 fclose(file->stream);
58 }
59
60 if(rd && !wr) sprintf(flags, "rb");
61 else
62 if(!rd && wr) sprintf(flags, "wb");
63 else
64 if(rd && wr)
65 {
66 if(exists)
67 sprintf(flags, "rb+");
68 else
69 sprintf(flags, "wb+");
70 }
71
72 if(!(file->stream = fopen(path, flags)))
73 {
74 return 1;
75 }
76
77 if(rd && exists)
78 {
79 file->total_length = quicktime_get_file_length(path);
80 }
81 if(wr)
82 file->presave_buffer = calloc(1, QUICKTIME_PRESAVE);
83 return 0;
84 }
85
quicktime_file_close(quicktime_t * file)86 int quicktime_file_close(quicktime_t *file)
87 {
88 /* Flush presave buffer */
89 if(file->presave_size)
90 {
91 quicktime_fseek(file, file->presave_position - file->presave_size);
92 fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
93 file->presave_size = 0;
94 }
95
96 if(file->stream)
97 {
98 fclose(file->stream);
99 }
100 file->stream = 0;
101 return 0;
102 }
103
quicktime_ftell(quicktime_t * file)104 int64_t quicktime_ftell(quicktime_t *file)
105 {
106 return file->ftell_position;
107 }
108
quicktime_fseek(quicktime_t * file,int64_t offset)109 int quicktime_fseek(quicktime_t *file, int64_t offset)
110 {
111 file->ftell_position = offset;
112 if(offset > file->total_length || offset < 0) return 1;
113 if(fseeko(file->stream, file->ftell_position, SEEK_SET))
114 {
115 // perror("quicktime_fseek fseeko");
116 return 1;
117 }
118 return 0;
119 }
120
121 /* Read entire buffer from the preload buffer */
read_preload(quicktime_t * file,uint8_t * data,int64_t size)122 static int read_preload(quicktime_t *file, uint8_t *data, int64_t size)
123 {
124 int64_t selection_start = 0;
125 int64_t selection_end = 0;
126 int64_t fragment_start = 0;
127 int64_t fragment_len = 0;
128
129 selection_start = file->file_position;
130 selection_end = quicktime_add(file->file_position, size);
131
132 fragment_start = file->preload_ptr + (selection_start - file->preload_start);
133 while(fragment_start < 0) fragment_start += file->preload_size;
134 while(fragment_start >= file->preload_size) fragment_start -= file->preload_size;
135
136 while(selection_start < selection_end)
137 {
138 fragment_len = selection_end - selection_start;
139 if(fragment_start + fragment_len > file->preload_size)
140 fragment_len = file->preload_size - fragment_start;
141
142 memcpy(data, file->preload_buffer + fragment_start, fragment_len);
143 fragment_start += fragment_len;
144 data += fragment_len;
145
146 if(fragment_start >= file->preload_size) fragment_start = (int64_t)0;
147 selection_start += fragment_len;
148 }
149 return 0;
150 }
151
quicktime_read_data(quicktime_t * file,uint8_t * data,int64_t size)152 int quicktime_read_data(quicktime_t *file, uint8_t *data, int64_t size)
153 {
154 int result = 1;
155
156 /* Return if we had an error before */
157 if(file->io_error || file->io_eof)
158 return 0;
159
160 if(!file->preload_size)
161 {
162 quicktime_fseek(file, file->file_position);
163 result = fread(data, 1, size, file->stream);
164 if(result < size)
165 {
166 file->io_error = ferror(file->stream);
167 file->io_eof = feof(file->stream);
168 }
169 file->ftell_position += size;
170 }
171 else
172 {
173 /* Region requested for loading */
174 int64_t selection_start = file->file_position;
175 int64_t selection_end = file->file_position + size;
176 int64_t fragment_start, fragment_len;
177
178 if(selection_end - selection_start > file->preload_size)
179 {
180 /* Size is larger than preload size. Should never happen. */
181 quicktime_fseek(file, file->file_position);
182 result = fread(data, 1, size, file->stream);
183 if(result < size)
184 {
185 file->io_error = ferror(file->stream);
186 file->io_eof = feof(file->stream);
187 }
188 file->ftell_position += size;
189 }
190 else if(selection_start >= file->preload_start &&
191 selection_start < file->preload_end &&
192 selection_end <= file->preload_end &&
193 selection_end > file->preload_start)
194 {
195 /* Entire range is in buffer */
196 read_preload(file, data, size);
197 result = size;
198 }
199 else if(selection_end > file->preload_end &&
200 selection_end - file->preload_size < file->preload_end)
201 {
202 /* Range is after buffer */
203 /* Move the preload start to within one preload length of the selection_end */
204 while(selection_end - file->preload_start > file->preload_size)
205 {
206 fragment_len = selection_end - file->preload_start - file->preload_size;
207 if(file->preload_ptr + fragment_len > file->preload_size)
208 fragment_len = file->preload_size - file->preload_ptr;
209 file->preload_start += fragment_len;
210 file->preload_ptr += fragment_len;
211 if(file->preload_ptr >= file->preload_size) file->preload_ptr = 0;
212 }
213
214 /* Append sequential data after the preload end to the new end */
215 fragment_start = file->preload_ptr + file->preload_end - file->preload_start;
216 while(fragment_start >= file->preload_size)
217 fragment_start -= file->preload_size;
218
219 while(file->preload_end < selection_end)
220 {
221 fragment_len = selection_end - file->preload_end;
222 if(fragment_start + fragment_len > file->preload_size)
223 fragment_len = file->preload_size - fragment_start;
224 quicktime_fseek(file, file->preload_end);
225 result = fread(&file->preload_buffer[fragment_start],
226 fragment_len, 1, file->stream);
227
228 if(result < fragment_len)
229 {
230 file->io_error = ferror(file->stream);
231 file->io_eof = feof(file->stream);
232 }
233 file->ftell_position += fragment_len;
234 file->preload_end += fragment_len;
235 fragment_start += fragment_len;
236 if(fragment_start >= file->preload_size)
237 fragment_start = 0;
238 }
239
240 read_preload(file, data, size);
241 result = size;
242 }
243 else
244 {
245 /* Range is before buffer or over a preload_size away from the end of the buffer. */
246 /* Replace entire preload buffer with range. */
247 quicktime_fseek(file, file->file_position);
248 result = fread(file->preload_buffer, 1, size, file->stream);
249 if(result < size)
250 {
251 file->io_error = ferror(file->stream);
252 file->io_eof = feof(file->stream);
253 }
254 file->ftell_position += size;
255 file->preload_start = file->file_position;
256 file->preload_end = file->file_position + size;
257 file->preload_ptr = 0;
258 read_preload(file, data, size);
259
260
261 }
262 }
263 file->file_position += size;
264 return result;
265 }
266
quicktime_write_data(quicktime_t * file,const uint8_t * data,int size)267 int quicktime_write_data(quicktime_t *file, const uint8_t *data, int size)
268 {
269 int data_offset = 0;
270 int writes_attempted = 0;
271 int writes_succeeded = 0;
272
273 if(file->io_error)
274 return 0;
275
276 // Flush existing buffer and seek to new position
277 if(file->file_position != file->presave_position)
278 {
279 if(file->presave_size)
280 {
281 quicktime_fseek(file, file->presave_position - file->presave_size);
282 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
283 writes_attempted += file->presave_size;
284 file->presave_size = 0;
285 }
286 file->presave_position = file->file_position;
287 }
288
289 // Write presave buffers until done
290 while(size > 0)
291 {
292 int fragment_size = QUICKTIME_PRESAVE;
293 if(fragment_size > size) fragment_size = size;
294 if(fragment_size + file->presave_size > QUICKTIME_PRESAVE)
295 fragment_size = QUICKTIME_PRESAVE- file->presave_size;
296
297 memcpy(file->presave_buffer + file->presave_size,
298 data + data_offset,
299 fragment_size);
300
301 file->presave_position += fragment_size;
302 file->presave_size += fragment_size;
303 data_offset += fragment_size;
304 size -= fragment_size;
305
306 if(file->presave_size >= QUICKTIME_PRESAVE)
307 {
308 quicktime_fseek(file, file->presave_position - file->presave_size);
309 writes_succeeded += fwrite(file->presave_buffer, 1, file->presave_size, file->stream);
310 writes_attempted += file->presave_size;
311 file->presave_size = 0;
312 }
313 }
314
315 /* Adjust file position */
316 file->file_position = file->presave_position;
317 /* Adjust ftell position */
318 file->ftell_position = file->presave_position;
319 /* Adjust total length */
320 if(file->total_length < file->ftell_position) file->total_length = file->ftell_position;
321
322 /* fwrite failed */
323 if(!writes_succeeded && writes_attempted)
324 {
325 file->io_error = ferror(file->stream);
326 return 0;
327 }
328 else
329 if(!size)
330 return 1;
331 else
332 return size;
333 }
334
quicktime_byte_position(quicktime_t * file)335 int64_t quicktime_byte_position(quicktime_t *file)
336 {
337 return quicktime_position(file);
338 }
339
340
quicktime_read_pascal(quicktime_t * file,char * data)341 void quicktime_read_pascal(quicktime_t *file, char *data)
342 {
343 char len = quicktime_read_char(file);
344 quicktime_read_data(file, (uint8_t*)data, len);
345 data[(int)len] = 0;
346 }
347
quicktime_write_pascal(quicktime_t * file,char * data)348 void quicktime_write_pascal(quicktime_t *file, char *data)
349 {
350 uint8_t len = strlen(data);
351 quicktime_write_data(file, &len, 1);
352 quicktime_write_data(file, (uint8_t*)data, len);
353 }
354
quicktime_read_fixed32(quicktime_t * file)355 float quicktime_read_fixed32(quicktime_t *file)
356 {
357 unsigned long a, b, c, d;
358 uint8_t data[4];
359
360 quicktime_read_data(file, data, 4);
361 a = data[0];
362 b = data[1];
363 c = data[2];
364 d = data[3];
365
366 a = (a << 8) + b;
367 b = (c << 8) + d;
368
369 if(b)
370 return (float)a + (float)b / 65536;
371 else
372 return a;
373 }
374
375
quicktime_write_fixed32(quicktime_t * file,float number)376 int quicktime_write_fixed32(quicktime_t *file, float number)
377 {
378 unsigned char data[4];
379 int a, b;
380
381 a = number;
382 b = (number - a) * 65536;
383 data[0] = a >> 8;
384 data[1] = a & 0xff;
385 data[2] = b >> 8;
386
387 data[3] = b & 0xff;
388
389 return quicktime_write_data(file, data, 4);
390 }
391
392 static float
float32_be_read(unsigned char * cptr)393 float32_be_read (unsigned char *cptr)
394 { int exponent, mantissa, negative ;
395 float fvalue ;
396
397 negative = cptr [0] & 0x80 ;
398 exponent = ((cptr [0] & 0x7F) << 1) | ((cptr [1] & 0x80) ? 1 : 0) ;
399 mantissa = ((cptr [1] & 0x7F) << 16) | (cptr [2] << 8) | (cptr [3]) ;
400
401 if (! (exponent || mantissa))
402 return 0.0 ;
403
404 mantissa |= 0x800000 ;
405 exponent = exponent ? exponent - 127 : 0 ;
406
407 fvalue = mantissa ? ((float) mantissa) / ((float) 0x800000) : 0.0 ;
408
409 if (negative)
410 fvalue *= -1 ;
411
412 if (exponent > 0)
413 fvalue *= (1 << exponent) ;
414 else if (exponent < 0)
415 fvalue /= (1 << abs (exponent)) ;
416
417 return fvalue ;
418 } /* float32_be_read */
419
420 static double
double64_be_read(unsigned char * cptr)421 double64_be_read (unsigned char *cptr)
422 { int exponent, negative ;
423 double dvalue ;
424
425 negative = (cptr [0] & 0x80) ? 1 : 0 ;
426 exponent = ((cptr [0] & 0x7F) << 4) | ((cptr [1] >> 4) & 0xF) ;
427
428 /* Might not have a 64 bit long, so load the mantissa into a double. */
429 dvalue = (((cptr [1] & 0xF) << 24) | (cptr [2] << 16) | (cptr [3] << 8) | cptr [4]) ;
430 dvalue += ((cptr [5] << 16) | (cptr [6] << 8) | cptr [7]) / ((double) 0x1000000) ;
431
432 if (exponent == 0 && dvalue == 0.0)
433 return 0.0 ;
434
435 dvalue += 0x10000000 ;
436
437 exponent = exponent - 0x3FF ;
438
439 dvalue = dvalue / ((double) 0x10000000) ;
440
441 if (negative)
442 dvalue *= -1 ;
443
444 if (exponent > 0)
445 dvalue *= (1 << exponent) ;
446 else if (exponent < 0)
447 dvalue /= (1 << abs (exponent)) ;
448
449 return dvalue ;
450 } /* double64_be_read */
451
452 static void
float32_be_write(float in,unsigned char * out)453 float32_be_write (float in, unsigned char *out)
454 { int exponent, mantissa, negative = 0 ;
455
456 memset (out, 0, sizeof (int)) ;
457
458 if (in == 0.0)
459 return ;
460
461 if (in < 0.0)
462 { in *= -1.0 ;
463 negative = 1 ;
464 } ;
465
466 in = frexp (in, &exponent) ;
467
468 exponent += 126 ;
469
470 in *= (float) 0x1000000 ;
471 mantissa = (((int) in) & 0x7FFFFF) ;
472
473 if (negative)
474 out [0] |= 0x80 ;
475
476 if (exponent & 0x01)
477 out [1] |= 0x80 ;
478
479 out [3] = mantissa & 0xFF ;
480 out [2] = (mantissa >> 8) & 0xFF ;
481 out [1] |= (mantissa >> 16) & 0x7F ;
482 out [0] |= (exponent >> 1) & 0x7F ;
483
484 return ;
485 } /* float32_be_write */
486
487
488 static void
double64_be_write(double in,unsigned char * out)489 double64_be_write (double in, unsigned char *out)
490 { int exponent, mantissa ;
491
492 memset (out, 0, sizeof (double)) ;
493
494 if (in == 0.0)
495 return ;
496
497 if (in < 0.0)
498 { in *= -1.0 ;
499 out [0] |= 0x80 ;
500 } ;
501
502 in = frexp (in, &exponent) ;
503
504 exponent += 1022 ;
505
506 out [0] |= (exponent >> 4) & 0x7F ;
507 out [1] |= (exponent << 4) & 0xF0 ;
508
509 in *= 0x20000000 ;
510 mantissa = lrint (floor (in)) ;
511
512 out [1] |= (mantissa >> 24) & 0xF ;
513 out [2] = (mantissa >> 16) & 0xFF ;
514 out [3] = (mantissa >> 8) & 0xFF ;
515 out [4] = mantissa & 0xFF ;
516
517 in = fmod (in, 1.0) ;
518 in *= 0x1000000 ;
519 mantissa = lrint (floor (in)) ;
520
521 out [5] = (mantissa >> 16) & 0xFF ;
522 out [6] = (mantissa >> 8) & 0xFF ;
523 out [7] = mantissa & 0xFF ;
524
525 return ;
526 } /* double64_be_write */
527
528
quicktime_read_float32(quicktime_t * file)529 float quicktime_read_float32(quicktime_t *file)
530 {
531 unsigned char b[4];
532 quicktime_read_data(file, b, 4);
533 return float32_be_read(b);
534 }
535
quicktime_read_double64(quicktime_t * file)536 double quicktime_read_double64(quicktime_t *file)
537 {
538 unsigned char b[8];
539 quicktime_read_data(file, b, 8);
540 return double64_be_read(b);
541 }
542
543
quicktime_write_float32(quicktime_t * file,float value)544 int quicktime_write_float32(quicktime_t *file, float value)
545 {
546 unsigned char b[4];
547 float32_be_write(value, b);
548 return quicktime_write_data(file, b, 4);
549 }
550
quicktime_write_double64(quicktime_t * file,double value)551 int quicktime_write_double64(quicktime_t *file, double value)
552 {
553 unsigned char b[8];
554 double64_be_write(value, b);
555 return quicktime_write_data(file, b, 8);
556 }
557
quicktime_write_int64(quicktime_t * file,int64_t value)558 int quicktime_write_int64(quicktime_t *file, int64_t value)
559 {
560 unsigned char data[8];
561
562 data[0] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
563 data[1] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
564 data[2] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
565 data[3] = (((uint64_t)value) & 0xff00000000LL) >> 32;
566 data[4] = (((uint64_t)value) & 0xff000000LL) >> 24;
567 data[5] = (((uint64_t)value) & 0xff0000LL) >> 16;
568 data[6] = (((uint64_t)value) & 0xff00LL) >> 8;
569 data[7] = ((uint64_t)value) & 0xff;
570
571 return quicktime_write_data(file, data, 8);
572 }
573
quicktime_write_int64_le(quicktime_t * file,int64_t value)574 int quicktime_write_int64_le(quicktime_t *file, int64_t value)
575 {
576 unsigned char data[8];
577
578 data[7] = (((uint64_t)value) & 0xff00000000000000LL) >> 56;
579 data[6] = (((uint64_t)value) & 0xff000000000000LL) >> 48;
580 data[5] = (((uint64_t)value) & 0xff0000000000LL) >> 40;
581 data[4] = (((uint64_t)value) & 0xff00000000LL) >> 32;
582 data[3] = (((uint64_t)value) & 0xff000000LL) >> 24;
583 data[2] = (((uint64_t)value) & 0xff0000LL) >> 16;
584 data[1] = (((uint64_t)value) & 0xff00LL) >> 8;
585 data[0] = ((uint64_t)value) & 0xff;
586
587 return quicktime_write_data(file, data, 8);
588 }
589
590
quicktime_write_int32(quicktime_t * file,long value)591 int quicktime_write_int32(quicktime_t *file, long value)
592 {
593 unsigned char data[4];
594
595 data[0] = (value & 0xff000000) >> 24;
596 data[1] = (value & 0xff0000) >> 16;
597 data[2] = (value & 0xff00) >> 8;
598 data[3] = value & 0xff;
599
600 return quicktime_write_data(file, data, 4);
601 }
602
quicktime_write_int32_le(quicktime_t * file,long value)603 int quicktime_write_int32_le(quicktime_t *file, long value)
604 {
605 unsigned char data[4];
606
607 data[3] = (value & 0xff000000) >> 24;
608 data[2] = (value & 0xff0000) >> 16;
609 data[1] = (value & 0xff00) >> 8;
610 data[0] = value & 0xff;
611
612 return quicktime_write_data(file, data, 4);
613 }
614
quicktime_write_char32(quicktime_t * file,char * string)615 int quicktime_write_char32(quicktime_t *file, char *string)
616 {
617 return quicktime_write_data(file, (uint8_t*)string, 4);
618 }
619
620
quicktime_read_fixed16(quicktime_t * file)621 float quicktime_read_fixed16(quicktime_t *file)
622 {
623 unsigned char data[2];
624
625 quicktime_read_data(file, data, 2);
626 if(data[1])
627 return (float)data[0] + (float)data[1] / 256;
628 else
629 return (float)data[0];
630 }
631
quicktime_write_fixed16(quicktime_t * file,float number)632 int quicktime_write_fixed16(quicktime_t *file, float number)
633 {
634 unsigned char data[2];
635 int a, b;
636
637 a = number;
638 b = (number - a) * 256;
639 data[0] = a;
640 data[1] = b;
641
642 return quicktime_write_data(file, data, 2);
643 }
644
quicktime_read_uint32(quicktime_t * file)645 unsigned long quicktime_read_uint32(quicktime_t *file)
646 {
647 unsigned long result;
648 unsigned long a, b, c, d;
649 uint8_t data[4];
650
651 quicktime_read_data(file, data, 4);
652 a = data[0];
653 b = data[1];
654 c = data[2];
655 d = data[3];
656
657 result = (a << 24) | (b << 16) | (c << 8) | d;
658 return result;
659 }
660
quicktime_read_int32(quicktime_t * file)661 long quicktime_read_int32(quicktime_t *file)
662 {
663 unsigned long result;
664 unsigned long a, b, c, d;
665 uint8_t data[4];
666
667 quicktime_read_data(file, data, 4);
668 a = data[0];
669 b = data[1];
670 c = data[2];
671 d = data[3];
672
673 result = (a << 24) | (b << 16) | (c << 8) | d;
674 return (long)result;
675 }
676
quicktime_read_int32_le(quicktime_t * file)677 long quicktime_read_int32_le(quicktime_t *file)
678 {
679 unsigned long result;
680 unsigned long a, b, c, d;
681 uint8_t data[4];
682
683 quicktime_read_data(file, data, 4);
684 a = data[0];
685 b = data[1];
686 c = data[2];
687 d = data[3];
688
689 result = (d << 24) | (c << 16) | (b << 8) | a;
690 return (long)result;
691 }
692
quicktime_read_int64(quicktime_t * file)693 int64_t quicktime_read_int64(quicktime_t *file)
694 {
695 uint64_t result, a, b, c, d, e, f, g, h;
696 uint8_t data[8];
697
698 quicktime_read_data(file, data, 8);
699 a = data[0];
700 b = data[1];
701 c = data[2];
702 d = data[3];
703 e = data[4];
704 f = data[5];
705 g = data[6];
706 h = data[7];
707
708 result = (a << 56) |
709 (b << 48) |
710 (c << 40) |
711 (d << 32) |
712 (e << 24) |
713 (f << 16) |
714 (g << 8) |
715 h;
716 return (int64_t)result;
717 }
718
719
quicktime_read_int64_le(quicktime_t * file)720 int64_t quicktime_read_int64_le(quicktime_t *file)
721 {
722 uint64_t result, a, b, c, d, e, f, g, h;
723 uint8_t data[8];
724
725 quicktime_read_data(file, data, 8);
726 a = data[7];
727 b = data[6];
728 c = data[5];
729 d = data[4];
730 e = data[3];
731 f = data[2];
732 g = data[1];
733 h = data[0];
734
735 result = (a << 56) |
736 (b << 48) |
737 (c << 40) |
738 (d << 32) |
739 (e << 24) |
740 (f << 16) |
741 (g << 8) |
742 h;
743 return (int64_t)result;
744 }
745
746
quicktime_read_int24(quicktime_t * file)747 long quicktime_read_int24(quicktime_t *file)
748 {
749 unsigned long result;
750 unsigned long a, b, c;
751 uint8_t data[4];
752
753 quicktime_read_data(file, data, 3);
754 a = data[0];
755 b = data[1];
756 c = data[2];
757
758 result = (a << 16) | (b << 8) | c;
759 return (long)result;
760 }
761
quicktime_write_int24(quicktime_t * file,long number)762 int quicktime_write_int24(quicktime_t *file, long number)
763 {
764 unsigned char data[3];
765 data[0] = (number & 0xff0000) >> 16;
766 data[1] = (number & 0xff00) >> 8;
767 data[2] = (number & 0xff);
768
769 return quicktime_write_data(file, data, 3);
770 }
771
quicktime_read_int16(quicktime_t * file)772 int quicktime_read_int16(quicktime_t *file)
773 {
774 unsigned long result;
775 unsigned long a, b;
776 uint8_t data[2];
777
778 quicktime_read_data(file, data, 2);
779 a = data[0];
780 b = data[1];
781
782 result = (a << 8) | b;
783 return (int)result;
784 }
785
quicktime_read_int16_le(quicktime_t * file)786 int quicktime_read_int16_le(quicktime_t *file)
787 {
788 unsigned long result;
789 unsigned long a, b;
790 uint8_t data[2];
791
792 quicktime_read_data(file, data, 2);
793 a = data[0];
794 b = data[1];
795
796 result = (b << 8) | a;
797 return (int)result;
798 }
799
quicktime_write_int16(quicktime_t * file,int number)800 int quicktime_write_int16(quicktime_t *file, int number)
801 {
802 unsigned char data[2];
803 data[0] = (number & 0xff00) >> 8;
804 data[1] = (number & 0xff);
805
806 return quicktime_write_data(file, data, 2);
807 }
808
quicktime_write_int16_le(quicktime_t * file,int number)809 int quicktime_write_int16_le(quicktime_t *file, int number)
810 {
811 unsigned char data[2];
812 data[1] = (number & 0xff00) >> 8;
813 data[0] = (number & 0xff);
814
815 return quicktime_write_data(file, data, 2);
816 }
817
quicktime_read_char(quicktime_t * file)818 int quicktime_read_char(quicktime_t *file)
819 {
820 char output;
821 quicktime_read_data(file, (uint8_t*)(&output), 1);
822 return output;
823 }
824
quicktime_write_char(quicktime_t * file,char x)825 int quicktime_write_char(quicktime_t *file, char x)
826 {
827 return quicktime_write_data(file, (uint8_t*)(&x), 1);
828 }
829
quicktime_read_char32(quicktime_t * file,char * string)830 void quicktime_read_char32(quicktime_t *file, char *string)
831 {
832 quicktime_read_data(file, (uint8_t*)string, 4);
833 }
834
quicktime_position(quicktime_t * file)835 int64_t quicktime_position(quicktime_t *file)
836 {
837 return file->file_position;
838 }
839
quicktime_set_position(quicktime_t * file,int64_t position)840 int quicktime_set_position(quicktime_t *file, int64_t position)
841 {
842 file->file_position = position;
843 return 0;
844 }
845
quicktime_copy_char32(char * output,char * input)846 void quicktime_copy_char32(char *output, char *input)
847 {
848 *output++ = *input++;
849 *output++ = *input++;
850 *output++ = *input++;
851 *output = *input;
852 }
853
854
quicktime_print_chars(char * desc,uint8_t * input,int len)855 void quicktime_print_chars(char *desc, uint8_t *input, int len)
856 {
857 int i;
858 lqt_dump("%s", desc);
859 for(i = 0; i < len; i++) lqt_dump("%02x ", input[i]);
860 lqt_dump("\n");
861 }
862
quicktime_current_time(void)863 unsigned long quicktime_current_time(void)
864 {
865 time_t t;
866 time (&t);
867 return (t+(66*31536000)+1468800);
868 }
869
quicktime_match_32(void * _input,void * _output)870 int quicktime_match_32(void *_input, void *_output)
871 {
872 uint8_t * input = (uint8_t*)_input;
873 uint8_t * output = (uint8_t*)_output;
874 if(input[0] == output[0] &&
875 input[1] == output[1] &&
876 input[2] == output[2] &&
877 input[3] == output[3])
878 return 1;
879 else
880 return 0;
881 }
882
quicktime_match_24(char * input,char * output)883 int quicktime_match_24(char *input, char *output)
884 {
885 if(input[0] == output[0] &&
886 input[1] == output[1] &&
887 input[2] == output[2])
888 return 1;
889 else
890 return 0;
891 }
892
do_hexdump(uint8_t * data,int len,int linebreak,FILE * f)893 static void do_hexdump(uint8_t * data, int len, int linebreak, FILE * f)
894 {
895 int i;
896 int bytes_written = 0;
897 int imax;
898
899 while(bytes_written < len)
900 {
901 imax = (bytes_written + linebreak > len) ? len - bytes_written : linebreak;
902 for(i = 0; i < imax; i++)
903 fprintf(f, "%02x ", data[bytes_written + i]);
904 for(i = imax; i < linebreak; i++)
905 fprintf(f, " ");
906 for(i = 0; i < imax; i++)
907 {
908 if(!(data[bytes_written + i] & 0x80) && (data[bytes_written + i] >= 32))
909 fprintf(f, "%c", data[bytes_written + i]);
910 else
911 fprintf(f, ".");
912 }
913 bytes_written += imax;
914 fprintf(f, "\n");
915 }
916 }
917
lqt_hexdump(uint8_t * data,int len,int linebreak)918 void lqt_hexdump(uint8_t * data, int len, int linebreak)
919 {
920 do_hexdump(data, len, linebreak, stderr);
921 }
922
lqt_hexdump_stdout(uint8_t * data,int len,int linebreak)923 void lqt_hexdump_stdout(uint8_t * data, int len, int linebreak)
924 {
925 do_hexdump(data, len, linebreak, stdout);
926 }
927
lqt_dump_time(uint64_t t)928 void lqt_dump_time(uint64_t t)
929 {
930 time_t ti;
931 struct tm tm;
932 /* 2082844800 = seconds between 1/1/04 and 1/1/70 */
933 ti = t - 2082844800;
934 localtime_r(&ti, &tm);
935 tm.tm_mon++;
936 printf("%04d-%02d-%02d %02d:%02d:%02d (%"PRId64")",
937 tm.tm_year+1900, tm.tm_mon, tm.tm_mday,
938 tm.tm_hour, tm.tm_min, tm.tm_sec, t);
939 }
940