Use ftello/fseeko instead of ftell/fseek
[L-SMASH.git] / utils.c
blobb99bcc61c05d8c709451520a6ec1ee83a3cada8c
1 /*****************************************************************************
2 * utils.c:
3 *****************************************************************************
4 * Copyright (C) 2010-2012 L-SMASH project
6 * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted, provided that the above
10 * copyright notice and this permission notice appear in all copies.
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
13 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
15 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
16 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
17 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
18 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 *****************************************************************************/
21 /* This file is available under an ISC license. */
23 #include "internal.h" /* must be placed first */
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdarg.h>
29 #include "utils.h"
31 uint64_t lsmash_bs_get_pos( lsmash_bs_t *bs )
33 return bs->pos;
36 void lsmash_bs_empty( lsmash_bs_t *bs )
38 if( !bs )
39 return;
40 memset( bs->data, 0, bs->alloc );
41 bs->store = 0;
42 bs->pos = 0;
45 void lsmash_bs_free( lsmash_bs_t *bs )
47 if( bs->data )
48 free( bs->data );
49 bs->data = NULL;
50 bs->alloc = 0;
51 bs->store = 0;
52 bs->pos = 0;
55 void lsmash_bs_alloc( lsmash_bs_t *bs, uint64_t size )
57 if( (bs->alloc >= size) || bs->error )
58 return;
59 uint64_t alloc = size + (1<<16);
60 uint8_t *data;
61 if( !bs->data )
62 data = malloc( alloc );
63 else
64 data = realloc( bs->data, alloc );
65 if( !data )
67 lsmash_bs_free( bs );
68 bs->error = 1;
69 return;
71 bs->data = data;
72 bs->alloc = alloc;
75 /*---- bitstream writer ----*/
76 void lsmash_bs_put_byte( lsmash_bs_t *bs, uint8_t value )
78 lsmash_bs_alloc( bs, bs->store + 1 );
79 if( bs->error )
80 return;
81 bs->data[bs->store ++] = value;
84 void lsmash_bs_put_bytes( lsmash_bs_t *bs, uint32_t size, void *value )
86 if( !size || !value )
87 return;
88 lsmash_bs_alloc( bs, bs->store + size );
89 if( bs->error )
90 return;
91 memcpy( bs->data + bs->store, value, size );
92 bs->store += size;
95 void lsmash_bs_put_be16( lsmash_bs_t *bs, uint16_t value )
97 lsmash_bs_put_byte( bs, (uint8_t)((value>>8)&0xff) );
98 lsmash_bs_put_byte( bs, (uint8_t)(value&0xff) );
101 void lsmash_bs_put_be24( lsmash_bs_t *bs, uint32_t value )
103 lsmash_bs_put_byte( bs, (uint8_t)((value>>16)&0xff) );
104 lsmash_bs_put_be16( bs, (uint16_t)(value&0xffff) );
107 void lsmash_bs_put_be32( lsmash_bs_t *bs, uint32_t value )
109 lsmash_bs_put_be16( bs, (uint16_t)((value>>16)&0xffff) );
110 lsmash_bs_put_be16( bs, (uint16_t)(value&0xffff) );
113 void lsmash_bs_put_be64( lsmash_bs_t *bs, uint64_t value )
115 lsmash_bs_put_be32( bs, (uint32_t)((value>>32)&0xffffffff) );
116 lsmash_bs_put_be32( bs, (uint32_t)(value&0xffffffff) );
119 void lsmash_bs_put_byte_from_64( lsmash_bs_t *bs, uint64_t value )
121 lsmash_bs_put_byte( bs, (uint8_t)(value&0xff) );
124 void lsmash_bs_put_be16_from_64( lsmash_bs_t *bs, uint64_t value )
126 lsmash_bs_put_be16( bs, (uint16_t)(value&0xffff) );
129 void lsmash_bs_put_be24_from_64( lsmash_bs_t *bs, uint64_t value )
131 lsmash_bs_put_be24( bs, (uint32_t)(value&0xffffff) );
134 void lsmash_bs_put_be32_from_64( lsmash_bs_t *bs, uint64_t value )
136 lsmash_bs_put_be32( bs, (uint32_t)(value&0xffffffff) );
139 int lsmash_bs_write_data( lsmash_bs_t *bs )
141 if( !bs )
142 return -1;
143 if( !bs->store || !bs->data )
144 return 0;
145 if( bs->error || !bs->stream || fwrite( bs->data, 1, bs->store, bs->stream ) != bs->store )
147 lsmash_bs_free( bs );
148 bs->error = 1;
149 return -1;
151 bs->written += bs->store;
152 bs->store = 0;
153 return 0;
156 lsmash_bs_t* lsmash_bs_create( char* filename )
158 lsmash_bs_t* bs = lsmash_malloc_zero( sizeof(lsmash_bs_t) );
159 if( !bs )
160 return NULL;
161 if( filename && (bs->stream = fopen( filename, "wb" )) == NULL )
163 free( bs );
164 return NULL;
166 return bs;
169 void lsmash_bs_cleanup( lsmash_bs_t *bs )
171 if( !bs )
172 return;
173 if( bs->stream )
174 fclose( bs->stream );
175 lsmash_bs_free( bs );
176 free( bs );
179 void* lsmash_bs_export_data( lsmash_bs_t *bs, uint32_t* length )
181 if( !bs || !bs->data || bs->store == 0 || bs->error )
182 return NULL;
183 void *buf = lsmash_memdup( bs->data, bs->store );
184 if( !buf )
185 return NULL;
186 if( length )
187 *length = bs->store;
188 return buf;
190 /*---- ----*/
192 /*---- bitstream reader ----*/
193 uint8_t lsmash_bs_show_byte( lsmash_bs_t *bs, uint32_t offset )
195 if( bs->error || !bs->data )
196 return 0;
197 if( bs->pos + offset > bs->store )
199 lsmash_bs_free( bs );
200 bs->error = 1;
201 return 0;
203 return bs->data[bs->pos + offset];
206 uint8_t lsmash_bs_get_byte( lsmash_bs_t *bs )
208 if( bs->error || !bs->data )
209 return 0;
210 if( bs->pos + 1 > bs->store )
212 lsmash_bs_free( bs );
213 bs->error = 1;
214 return 0;
216 return bs->data[bs->pos ++];
219 uint8_t *lsmash_bs_get_bytes( lsmash_bs_t *bs, uint32_t size )
221 if( bs->error || !size )
222 return NULL;
223 if( bs->pos + size > bs->store )
225 lsmash_bs_free( bs );
226 bs->error = 1;
227 return NULL;
229 uint8_t *value = lsmash_memdup( bs->data + bs->pos, size );
230 if( !value )
232 lsmash_bs_free( bs );
233 bs->error = 1;
234 return NULL;
236 bs->pos += size;
237 return value;
240 uint16_t lsmash_bs_get_be16( lsmash_bs_t *bs )
242 uint16_t value = lsmash_bs_get_byte( bs );
243 return (value<<8) | lsmash_bs_get_byte( bs );
246 uint32_t lsmash_bs_get_be24( lsmash_bs_t *bs )
248 uint32_t value = lsmash_bs_get_byte( bs );
249 return (value<<16) | lsmash_bs_get_be16( bs );
252 uint32_t lsmash_bs_get_be32( lsmash_bs_t *bs )
254 uint32_t value = lsmash_bs_get_be16( bs );
255 return (value<<16) | lsmash_bs_get_be16( bs );
258 uint64_t lsmash_bs_get_be64( lsmash_bs_t *bs )
260 uint64_t value = lsmash_bs_get_be32( bs );
261 return (value<<32) | lsmash_bs_get_be32( bs );
264 uint64_t lsmash_bs_get_byte_to_64( lsmash_bs_t *bs )
266 return lsmash_bs_get_byte( bs );
269 uint64_t lsmash_bs_get_be16_to_64( lsmash_bs_t *bs )
271 return lsmash_bs_get_be16( bs );
274 uint64_t lsmash_bs_get_be24_to_64( lsmash_bs_t *bs )
276 return lsmash_bs_get_be24( bs );
279 uint64_t lsmash_bs_get_be32_to_64( lsmash_bs_t *bs )
281 return lsmash_bs_get_be32( bs );
284 int lsmash_bs_read_data( lsmash_bs_t *bs, uint32_t size )
286 if( !bs )
287 return -1;
288 if( !size )
289 return 0;
290 lsmash_bs_alloc( bs, bs->store + size );
291 if( bs->error || !bs->stream )
293 lsmash_bs_free( bs );
294 bs->error = 1;
295 return -1;
297 uint64_t read_size = fread( bs->data + bs->store, 1, size, bs->stream );
298 if( read_size != size && !feof( bs->stream ) )
300 bs->error = 1;
301 return -1;
303 bs->store += read_size;
304 return 0;
307 int lsmash_bs_import_data( lsmash_bs_t *bs, void* data, uint32_t length )
309 if( !bs || bs->error || !data || length == 0 )
310 return -1;
311 lsmash_bs_alloc( bs, bs->store + length );
312 if( bs->error || !bs->data ) /* means, failed to alloc. */
314 lsmash_bs_free( bs );
315 return -1;
317 memcpy( bs->data + bs->store, data, length );
318 bs->store += length;
319 return 0;
321 /*---- ----*/
323 /*---- bitstream ----*/
324 void lsmash_bits_init( lsmash_bits_t *bits, lsmash_bs_t *bs )
326 debug_if( !bits || !bs )
327 return;
328 bits->bs = bs;
329 bits->store = 0;
330 bits->cache = 0;
333 lsmash_bits_t *lsmash_bits_create( lsmash_bs_t *bs )
335 debug_if( !bs )
336 return NULL;
337 lsmash_bits_t *bits = (lsmash_bits_t *)malloc( sizeof(lsmash_bits_t) );
338 if( !bits )
339 return NULL;
340 lsmash_bits_init( bits, bs );
341 return bits;
344 void lsmash_bits_empty( lsmash_bits_t *bits )
346 debug_if( !bits )
347 return;
348 lsmash_bs_empty( bits->bs );
349 bits->store = 0;
350 bits->cache = 0;
353 #define BITS_IN_BYTE 8
354 void lsmash_bits_put_align( lsmash_bits_t *bits )
356 debug_if( !bits )
357 return;
358 if( !bits->store )
359 return;
360 lsmash_bs_put_byte( bits->bs, bits->cache << ( BITS_IN_BYTE - bits->store ) );
363 void lsmash_bits_get_align( lsmash_bits_t *bits )
365 debug_if( !bits )
366 return;
367 bits->store = 0;
368 bits->cache = 0;
371 /* Must be used ONLY for bits struct created with isom_create_bits.
372 Otherwise, just free() the bits struct. */
373 void lsmash_bits_cleanup( lsmash_bits_t *bits )
375 debug_if( !bits )
376 return;
377 free( bits );
380 /* we can change value's type to unsigned int for 64-bit operation if needed. */
381 static inline uint8_t lsmash_bits_mask_lsb8( uint32_t value, uint32_t width )
383 return (uint8_t)( value & ~( ~0U << width ) );
386 /* We can change value's type to unsigned int for 64-bit operation if needed. */
387 void lsmash_bits_put( lsmash_bits_t *bits, uint32_t width, uint32_t value )
389 debug_if( !bits || !width )
390 return;
391 if( bits->store )
393 if( bits->store + width < BITS_IN_BYTE )
395 /* cache can contain all of value's bits. */
396 bits->cache <<= width;
397 bits->cache |= lsmash_bits_mask_lsb8( value, width );
398 bits->store += width;
399 return;
401 /* flush cache with value's some leading bits. */
402 uint32_t free_bits = BITS_IN_BYTE - bits->store;
403 bits->cache <<= free_bits;
404 bits->cache |= lsmash_bits_mask_lsb8( value >> (width -= free_bits), free_bits );
405 lsmash_bs_put_byte( bits->bs, bits->cache );
406 bits->store = 0;
407 bits->cache = 0;
409 /* cache is empty here. */
410 /* byte unit operation. */
411 while( width > BITS_IN_BYTE )
412 lsmash_bs_put_byte( bits->bs, (uint8_t)(value >> (width -= BITS_IN_BYTE)) );
413 /* bit unit operation for residual. */
414 if( width )
416 bits->cache = lsmash_bits_mask_lsb8( value, width );
417 bits->store = width;
421 /* We can change value's type to unsigned int for 64-bit operation if needed. */
422 uint32_t lsmash_bits_get( lsmash_bits_t *bits, uint32_t width )
424 debug_if( !bits || !width )
425 return 0;
426 uint32_t value = 0;
427 if( bits->store )
429 if( bits->store >= width )
431 /* cache contains all of bits required. */
432 bits->store -= width;
433 return lsmash_bits_mask_lsb8( bits->cache >> bits->store, width );
435 /* fill value's leading bits with cache's residual. */
436 value = lsmash_bits_mask_lsb8( bits->cache, bits->store );
437 width -= bits->store;
438 bits->store = 0;
439 bits->cache = 0;
441 /* cache is empty here. */
442 /* byte unit operation. */
443 while( width > BITS_IN_BYTE )
445 value <<= BITS_IN_BYTE;
446 width -= BITS_IN_BYTE;
447 value |= lsmash_bs_get_byte( bits->bs );
449 /* bit unit operation for residual. */
450 if( width )
452 bits->cache = lsmash_bs_get_byte( bits->bs );
453 bits->store = BITS_IN_BYTE - width;
454 value <<= width;
455 value |= lsmash_bits_mask_lsb8( bits->cache >> bits->store, width );
457 return value;
460 /****
461 bitstream with bytestream for adhoc operation
462 ****/
464 lsmash_bits_t* lsmash_bits_adhoc_create()
466 lsmash_bs_t* bs = lsmash_bs_create( NULL ); /* no file writing */
467 if( !bs )
468 return NULL;
469 lsmash_bits_t* bits = lsmash_bits_create( bs );
470 if( !bits )
472 lsmash_bs_cleanup( bs );
473 return NULL;
475 return bits;
478 void lsmash_bits_adhoc_cleanup( lsmash_bits_t* bits )
480 if( !bits )
481 return;
482 lsmash_bs_cleanup( bits->bs );
483 lsmash_bits_cleanup( bits );
486 void* lsmash_bits_export_data( lsmash_bits_t* bits, uint32_t* length )
488 lsmash_bits_put_align( bits );
489 return lsmash_bs_export_data( bits->bs, length );
492 int lsmash_bits_import_data( lsmash_bits_t* bits, void* data, uint32_t length )
494 return lsmash_bs_import_data( bits->bs, data, length );
496 /*---- ----*/
498 /*---- list ----*/
499 void lsmash_init_entry_list( lsmash_entry_list_t *list )
501 list->head = NULL;
502 list->tail = NULL;
503 list->last_accessed_entry = NULL;
504 list->last_accessed_number = 0;
505 list->entry_count = 0;
508 lsmash_entry_list_t *lsmash_create_entry_list( void )
510 lsmash_entry_list_t *list = malloc( sizeof(lsmash_entry_list_t) );
511 if( !list )
512 return NULL;
513 lsmash_init_entry_list( list );
514 return list;
517 int lsmash_add_entry( lsmash_entry_list_t *list, void *data )
519 if( !list )
520 return -1;
521 lsmash_entry_t *entry = malloc( sizeof(lsmash_entry_t) );
522 if( !entry )
523 return -1;
524 entry->next = NULL;
525 entry->prev = list->tail;
526 entry->data = data;
527 if( list->head )
528 list->tail->next = entry;
529 else
530 list->head = entry;
531 list->tail = entry;
532 list->entry_count += 1;
533 return 0;
536 int lsmash_remove_entry_direct( lsmash_entry_list_t *list, lsmash_entry_t *entry, void* eliminator )
538 if( !entry )
539 return -1;
540 if( !eliminator )
541 eliminator = free;
542 lsmash_entry_t *next = entry->next;
543 lsmash_entry_t *prev = entry->prev;
544 if( entry == list->head )
545 list->head = next;
546 else
547 prev->next = next;
548 if( entry == list->tail )
549 list->tail = prev;
550 else
551 next->prev = prev;
552 if( entry->data )
553 ((lsmash_entry_data_eliminator)eliminator)( entry->data );
554 if( entry == list->last_accessed_entry )
556 if( next )
557 list->last_accessed_entry = next;
558 else if( prev )
560 list->last_accessed_entry = prev;
561 list->last_accessed_number -= 1;
563 else
565 list->last_accessed_entry = NULL;
566 list->last_accessed_number = 0;
569 else
571 /* We can't know the current entry number immediately,
572 * so discard the last accessed entry info because time is wasted to know it. */
573 list->last_accessed_entry = NULL;
574 list->last_accessed_number = 0;
576 free( entry );
577 list->entry_count -= 1;
578 return 0;
581 int lsmash_remove_entry( lsmash_entry_list_t *list, uint32_t entry_number, void* eliminator )
583 lsmash_entry_t *entry = lsmash_get_entry( list, entry_number );
584 return lsmash_remove_entry_direct( list, entry, eliminator );
587 void lsmash_remove_entries( lsmash_entry_list_t *list, void* eliminator )
589 if( !list )
590 return;
591 if( !eliminator )
592 eliminator = free;
593 for( lsmash_entry_t *entry = list->head; entry; )
595 lsmash_entry_t *next = entry->next;
596 if( entry->data )
597 ((lsmash_entry_data_eliminator)eliminator)( entry->data );
598 free( entry );
599 entry = next;
601 lsmash_init_entry_list( list );
604 void lsmash_remove_list( lsmash_entry_list_t *list, void* eliminator )
606 if( !list )
607 return;
608 lsmash_remove_entries( list, eliminator );
609 free( list );
612 lsmash_entry_t *lsmash_get_entry( lsmash_entry_list_t *list, uint32_t entry_number )
614 if( !list || !entry_number || entry_number > list->entry_count )
615 return NULL;
616 int shortcut = 1;
617 lsmash_entry_t *entry = NULL;
618 if( list->last_accessed_entry )
620 if( entry_number == list->last_accessed_number )
621 entry = list->last_accessed_entry;
622 else if( entry_number == list->last_accessed_number + 1 )
623 entry = list->last_accessed_entry->next;
624 else if( entry_number == list->last_accessed_number - 1 )
625 entry = list->last_accessed_entry->prev;
626 else
627 shortcut = 0;
629 else
630 shortcut = 0;
631 if( !shortcut )
633 if( entry_number <= (list->entry_count >> 1) )
635 /* Look for from the head. */
636 uint32_t distance_plus_one = entry_number;
637 for( entry = list->head; entry && --distance_plus_one; entry = entry->next );
639 else
641 /* Look for from the tail. */
642 uint32_t distance = list->entry_count - entry_number;
643 for( entry = list->tail; entry && distance--; entry = entry->prev );
646 if( entry )
648 list->last_accessed_entry = entry;
649 list->last_accessed_number = entry_number;
651 return entry;
654 void *lsmash_get_entry_data( lsmash_entry_list_t *list, uint32_t entry_number )
656 lsmash_entry_t *entry = lsmash_get_entry( list, entry_number );
657 return entry ? entry->data : NULL;
659 /*---- ----*/
661 /*---- type ----*/
662 double lsmash_fixed2double( uint64_t value, int frac_width )
664 return value / (double)(1ULL << frac_width);
667 float lsmash_int2float32( uint32_t value )
669 return (union {uint32_t i; float f;}){value}.f;
672 double lsmash_int2float64( uint64_t value )
674 return (union {uint64_t i; double d;}){value}.d;
676 /*---- ----*/
678 /*---- allocator ----*/
679 void *lsmash_malloc_zero( size_t size )
681 if( !size )
682 return NULL;
683 void *p = malloc( size );
684 if( !p )
685 return NULL;
686 memset( p, 0, size );
687 return p;
690 void *lsmash_memdup( void *src, size_t size )
692 if( !size )
693 return NULL;
694 void *dst = malloc( size );
695 if( !dst )
696 return NULL;
697 memcpy( dst, src, size );
698 return dst;
701 lsmash_multiple_buffers_t *lsmash_create_multiple_buffers( uint32_t number_of_buffers, uint32_t buffer_size )
703 if( (uint64_t)number_of_buffers * buffer_size > UINT32_MAX )
704 return NULL;
705 lsmash_multiple_buffers_t *multiple_buffer = malloc( sizeof(lsmash_multiple_buffers_t) );
706 if( !multiple_buffer )
707 return NULL;
708 multiple_buffer->buffers = malloc( number_of_buffers * buffer_size );
709 if( !multiple_buffer->buffers )
711 free( multiple_buffer );
712 return NULL;
714 multiple_buffer->number_of_buffers = number_of_buffers;
715 multiple_buffer->buffer_size = buffer_size;
716 return multiple_buffer;
719 void *lsmash_withdraw_buffer( lsmash_multiple_buffers_t *multiple_buffer, uint32_t buffer_number )
721 if( !multiple_buffer || !buffer_number || buffer_number > multiple_buffer->number_of_buffers )
722 return NULL;
723 return multiple_buffer->buffers + (buffer_number - 1) * multiple_buffer->buffer_size;
726 lsmash_multiple_buffers_t *lsmash_resize_multiple_buffers( lsmash_multiple_buffers_t *multiple_buffer, uint32_t buffer_size )
728 if( !multiple_buffer )
729 return NULL;
730 if( buffer_size == multiple_buffer->buffer_size )
731 return multiple_buffer;
732 if( (uint64_t)multiple_buffer->number_of_buffers * buffer_size > UINT32_MAX )
733 return NULL;
734 void *temp;
735 if( buffer_size > multiple_buffer->buffer_size )
737 temp = realloc( multiple_buffer->buffers, multiple_buffer->number_of_buffers * buffer_size );
738 if( !temp )
739 return NULL;
740 for( uint32_t i = multiple_buffer->number_of_buffers - 1; i ; i-- )
741 memmove( temp + buffer_size, temp + i * multiple_buffer->buffer_size, multiple_buffer->buffer_size );
743 else
745 for( uint32_t i = 1; i < multiple_buffer->number_of_buffers; i++ )
746 memmove( multiple_buffer->buffers + buffer_size, multiple_buffer->buffers + i * multiple_buffer->buffer_size, multiple_buffer->buffer_size );
747 temp = realloc( multiple_buffer->buffers, multiple_buffer->number_of_buffers * buffer_size );
748 if( !temp )
749 return NULL;
751 multiple_buffer->buffers = temp;
752 multiple_buffer->buffer_size = buffer_size;
753 return multiple_buffer;
756 void lsmash_destroy_multiple_buffers( lsmash_multiple_buffers_t *multiple_buffer )
758 if( !multiple_buffer )
759 return;
760 if( multiple_buffer->buffers )
761 free( multiple_buffer->buffers );
762 free( multiple_buffer );
764 /*---- ----*/
766 /*---- others ----*/
767 void lsmash_log( lsmash_log_level level, const char* message, ... )
769 char *prefix;
770 va_list args;
772 va_start( args, message );
773 switch( level )
775 case LSMASH_LOG_ERROR:
776 prefix = "Error";
777 break;
778 case LSMASH_LOG_WARNING:
779 prefix = "Warning";
780 break;
781 case LSMASH_LOG_INFO:
782 prefix = "Info";
783 break;
784 default:
785 prefix = "Unknown";
786 break;
789 fprintf( stderr, "[%s]: ", prefix );
790 vfprintf( stderr, message, args );
791 va_end( args );
794 uint32_t lsmash_count_bits( uint32_t bits )
796 bits = (bits & 0x55555555) + ((bits >> 1) & 0x55555555);
797 bits = (bits & 0x33333333) + ((bits >> 2) & 0x33333333);
798 bits = (bits & 0x0f0f0f0f) + ((bits >> 4) & 0x0f0f0f0f);
799 bits = (bits & 0x00ff00ff) + ((bits >> 8) & 0x00ff00ff);
800 return (bits & 0x0000ffff) + ((bits >> 16) & 0x0000ffff);
803 /* for qsort function */
804 int lsmash_compare_dts( const lsmash_media_ts_t *a, const lsmash_media_ts_t *b )
806 int64_t diff = (int64_t)(a->dts - b->dts);
807 return diff > 0 ? 1 : (diff == 0 ? 0 : -1);
810 int lsmash_compare_cts( const lsmash_media_ts_t *a, const lsmash_media_ts_t *b )
812 int64_t diff = (int64_t)(a->cts - b->cts);
813 return diff > 0 ? 1 : (diff == 0 ? 0 : -1);