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