1 /*****************************************************************************
2  * utils.h
3  *****************************************************************************
4  * Copyright (C) 2010-2017 L-SMASH project
5  *
6  * Authors: Yusuke Nakamura <muken.the.vfrmaniac@gmail.com>
7  *
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.
11  *
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  *****************************************************************************/
20 
21 /* This file is available under an ISC license. */
22 
23 #ifndef LSMASH_UTIL_H
24 #define LSMASH_UTIL_H
25 
26 #define debug_if(x) if(x)
27 
28 #define LSMASH_MAX( a, b ) ((a) > (b) ? (a) : (b))
29 #define LSMASH_MIN( a, b ) ((a) < (b) ? (a) : (b))
30 
31 #define EXPAND_VA_ARGS( ... ) __VA_ARGS__
32 
33 /* default arguments
34  * Use only CALL_FUNC_DEFAULT_ARGS().
35  * The defined macros can't be passed a macro argument requiring the empty parameter list.
36  *
37  * The following is an example.
38  *   #define TEMPLATE_A( ... ) CALL_FUNC_DEFAULT_ARGS( TEMPLATE_A, __VA_ARGS__ )
39  *   #define TEMPLATE_A_1( _1 )     _1( 1 )
40  *   #define TEMPLATE_B( ... ) CALL_FUNC_DEFAULT_ARGS( TEMPLATE_B, __VA_ARGS__ )
41  *   #define TEMPLATE_B_2( _1, _2 ) ((_1) + (_2))
42  *   #define TEMPLATE_B_1( _1 )     TEMPLATE_B_2( _1, 0 )
43  *   #define TEMPLATE_B_0()
44  *   int main( void )
45  *   {
46  *      TEMPLATE_A( TEMPLATE_B_1 ); // OK
47  *      TEMPLATE_A( TEMPLATE_B );   // NG
48  *      TEMPLATE_B( 1, 2 );         // OK
49  *      TEMPLATE_B();               // NG
50  *      return 0;
51  *   }
52  * */
53 #define NUM_ARGS( _0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, ... ) _12
54 #ifdef _MSC_VER
55 #define COUNT_NUM_ARGS( ... ) EXPAND_VA_ARGS( NUM_ARGS( __VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 ) )
56 #else
57 #define COUNT_NUM_ARGS( ... ) NUM_ARGS( __VA_ARGS__, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0, 0 )
58 #endif
59 #define GET_FUNC_BY_NUM_ARGS_EXN( func_name, N )   func_name ## _ ## N
60 #define GET_FUNC_BY_NUM_ARGS_EX0( func_name, N )   GET_FUNC_BY_NUM_ARGS_EXN( func_name, N )
61 #define GET_FUNC_BY_NUM_ARGS_EX1( func_name, ... ) GET_FUNC_BY_NUM_ARGS_EX0( func_name, COUNT_NUM_ARGS( __VA_ARGS__ ) )
62 #define CALL_FUNC_DEFAULT_ARGS( func_name, ... )   GET_FUNC_BY_NUM_ARGS_EX1( func_name, __VA_ARGS__ ) ( __VA_ARGS__ )
63 
64 /*---- class ----*/
65 typedef struct
66 {
67     char  *name;
68     size_t log_level_offset;    /* offset in the struct where 'log_level' is placed
69                                  * If set to 0, 'log_level' is unavailable and implicitly set to LSMASH_LOG_INFO. */
70 } lsmash_class_t;
71 
72 /*---- type ----*/
73 double lsmash_fixed2double( uint64_t value, int frac_width );
74 float lsmash_int2float32( uint32_t value );
75 double lsmash_int2float64( uint64_t value );
76 
77 /*---- others ----*/
78 typedef enum
79 {
80     LSMASH_LOG_QUIET = 0,
81     LSMASH_LOG_ERROR,
82     LSMASH_LOG_WARNING,
83     LSMASH_LOG_INFO,
84 } lsmash_log_level;
85 
86 typedef struct
87 {
88     uint64_t n;
89     uint64_t d;
90 } lsmash_rational_u64_t;
91 
92 typedef struct
93 {
94     int64_t  n;
95     uint64_t d;
96 } lsmash_rational_s64_t;
97 
98 void lsmash_log
99 (
100     const void      *class,
101     lsmash_log_level level,
102     const char      *message,
103     ...
104 );
105 
106 void lsmash_log_refresh_line
107 (
108     const void *class
109 );
110 
111 uint32_t lsmash_count_bits
112 (
113     uint32_t bits
114 );
115 
116 void lsmash_ifprintf
117 (
118     FILE       *fp,
119     int         indent,
120     const char *format, ...
121 );
122 
123 int lsmash_ceil_log2
124 (
125     uint64_t value
126 );
127 
128 int lsmash_compare_dts
129 (
130     const lsmash_media_ts_t *a,
131     const lsmash_media_ts_t *b
132 );
133 
134 int lsmash_compare_cts
135 (
136     const lsmash_media_ts_t *a,
137     const lsmash_media_ts_t *b
138 );
139 
lsmash_get_gcd(uint64_t a,uint64_t b)140 static inline uint64_t lsmash_get_gcd
141 (
142     uint64_t a,
143     uint64_t b
144 )
145 {
146     if( !b )
147         return a;
148     while( 1 )
149     {
150         uint64_t c = a % b;
151         if( !c )
152             return b;
153         a = b;
154         b = c;
155     }
156 }
157 
lsmash_get_lcm(uint64_t a,uint64_t b)158 static inline uint64_t lsmash_get_lcm
159 (
160     uint64_t a,
161     uint64_t b
162 )
163 {
164     if( !a )
165         return 0;
166     return (a / lsmash_get_gcd( a, b )) * b;
167 }
168 
lsmash_reduce_fraction(uint64_t * a,uint64_t * b)169 static inline void lsmash_reduce_fraction
170 (
171     uint64_t *a,
172     uint64_t *b
173 )
174 {
175     if( !a || !b )
176         return;
177     uint64_t gcd = lsmash_get_gcd( *a, *b );
178     if( gcd )
179     {
180         *a /= gcd;
181         *b /= gcd;
182     }
183 }
184 
lsmash_reduce_fraction_su(int64_t * a,uint64_t * b)185 static inline void lsmash_reduce_fraction_su
186 (
187     int64_t  *a,
188     uint64_t *b
189 )
190 {
191     if( !a || !b )
192         return;
193     uint64_t c = *a > 0 ? *a : -(*a);
194     uint64_t gcd = lsmash_get_gcd( c, *b );
195     if( gcd )
196     {
197         c /= gcd;
198         *b /= gcd;
199         *a = *a > 0 ? (signed)c : -(signed)c;
200     }
201 }
202 
203 #endif
204