1 /*
2  * The contents of this file are subject to the Mozilla Public
3  * License Version 1.1 (the "License"); you may not use this file
4  * except in compliance with the License. You may obtain a copy of
5  * the License at http://www.mozilla.org/MPL/
6  *
7  * Software distributed under the License is distributed on an "AS
8  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
9  * implied. See the License for the specific language governing
10  * rights and limitations under the License.
11  *
12  * The Original Code is MPEG4IP.
13  *
14  * The Initial Developer of the Original Code is Cisco Systems Inc.
15  * Portions created by Cisco Systems Inc. are
16  * Copyright (C) Cisco Systems Inc. 2001.  All Rights Reserved.
17  *
18  * Contributor(s):
19  *		Dave Mackie		dmackie@cisco.com
20  */
21 
22 #ifndef __MP4_UTIL_INCLUDED__
23 #define __MP4_UTIL_INCLUDED__
24 #include <assert.h>
25 
26 #ifndef ASSERT
27 #define ASSERT(expr) \
28 	if (!(expr)) { \
29 		throw new MP4Error("assert failure", __STRING((expr))); \
30 	}
31 #endif
32 #define WARNING(expr) \
33 	if (expr) { \
34 		fflush(stdout); \
35 		fprintf(stderr, "Warning (%s) in %s at line %u\n", \
36 			__STRING(expr), __FILE__, __LINE__); \
37 	}
38 
39 #define VERBOSE(exprverbosity, verbosity, expr)	\
40 	if (((exprverbosity) & (verbosity)) == (exprverbosity)) { expr; }
41 
42 #define VERBOSE_ERROR(verbosity, expr)		\
43 	VERBOSE(MP4_DETAILS_ERROR, verbosity, expr)
44 
45 #define VERBOSE_WARNING(verbosity, expr)		\
46 	VERBOSE(MP4_DETAILS_WARNING, verbosity, expr)
47 
48 #define VERBOSE_READ(verbosity, expr)		\
49 	VERBOSE(MP4_DETAILS_READ, verbosity, expr)
50 
51 #define VERBOSE_READ_TABLE(verbosity, expr)	\
52 	VERBOSE((MP4_DETAILS_READ | MP4_DETAILS_TABLE), verbosity, expr)
53 
54 #define VERBOSE_READ_SAMPLE(verbosity, expr)	\
55 	VERBOSE((MP4_DETAILS_READ | MP4_DETAILS_SAMPLE), verbosity, expr)
56 
57 #define VERBOSE_READ_HINT(verbosity, expr)	\
58 	VERBOSE((MP4_DETAILS_READ | MP4_DETAILS_HINT), verbosity, expr)
59 
60 #define VERBOSE_WRITE(verbosity, expr)		\
61 	VERBOSE(MP4_DETAILS_WRITE, verbosity, expr)
62 
63 #define VERBOSE_WRITE_TABLE(verbosity, expr)	\
64 	VERBOSE((MP4_DETAILS_WRITE | MP4_DETAILS_TABLE), verbosity, expr)
65 
66 #define VERBOSE_WRITE_SAMPLE(verbosity, expr)	\
67 	VERBOSE((MP4_DETAILS_WRITE | MP4_DETAILS_SAMPLE), verbosity, expr)
68 
69 #define VERBOSE_WRITE_HINT(verbosity, expr)	\
70 	VERBOSE((MP4_DETAILS_WRITE | MP4_DETAILS_HINT), verbosity, expr)
71 
72 #define VERBOSE_FIND(verbosity, expr)		\
73 	VERBOSE(MP4_DETAILS_FIND, verbosity, expr)
74 
75 #define VERBOSE_ISMA(verbosity, expr)		\
76 	VERBOSE(MP4_DETAILS_ISMA, verbosity, expr)
77 
78 #define VERBOSE_EDIT(verbosity, expr)		\
79 	VERBOSE(MP4_DETAILS_EDIT, verbosity, expr)
80 
Indent(FILE * pFile,u_int8_t depth)81 inline void Indent(FILE* pFile, u_int8_t depth) {
82 	fprintf(pFile, "%*c", depth, ' ');
83 }
84 
85 static inline void MP4Printf(const char* fmt, ...)
86 #ifndef _WIN32
87  __attribute__((format(__printf__, 1, 2)))
88 #endif
89 ;
90 
MP4Printf(const char * fmt,...)91 static inline void MP4Printf(const char* fmt, ...)
92 {
93 	va_list ap;
94 	va_start(ap, fmt);
95 	// TBD API call to set error_msg_func instead of just printf
96 	vprintf(fmt, ap);
97 	va_end(ap);
98 }
99 
100 class MP4Error {
101 public:
MP4Error()102 	MP4Error() {
103 		m_errno = 0;
104 		m_errstring = NULL;
105 		m_where = NULL;
106 		m_free = 0;
107 	}
~MP4Error()108 	~MP4Error() {
109 	  if (m_free != 0) {
110 	    free((void *)m_errstring);
111 	  }
112 	}
113 	MP4Error(int err, const char* where = NULL) {
114 		m_errno = err;
115 		m_errstring = NULL;
116 		m_where = where;
117 		m_free = 0;
118 	}
MP4Error(const char * format,const char * where,...)119 	MP4Error(const char *format, const char *where, ...) {
120 	  char *string;
121 	  m_errno = 0;
122 	  string = (char *)malloc(512);
123 	  m_where = where;
124 	  if (string) {
125 	    va_list ap;
126 	    va_start(ap, where);
127 	    vsnprintf(string, 512, format, ap);
128 	    va_end(ap);
129 	    m_errstring = string;
130 	    m_free = 1;
131 	  } else {
132 	    m_errstring = format;
133 	    m_free = 0;
134 	  }
135 	}
MP4Error(int err,const char * format,const char * where,...)136 	MP4Error(int err, const char* format, const char* where, ...) {
137 	  char *string;
138 	  m_errno = err;
139 	  string = (char *)malloc(512);
140 	  m_where = where;
141 	  if (string) {
142 	    va_list ap;
143 	    va_start(ap, where);
144 	    vsnprintf(string, 512, format, ap);
145 	    va_end(ap);
146 	    m_errstring = string;
147 	    m_free = 1;
148 	  } else {
149 	    m_errstring = format;
150 	    m_free = 0;
151 	  }
152 	}
153 
154 	void Print(FILE* pFile = stderr);
155 	int m_free;
156 	int m_errno;
157 	const char* m_errstring;
158 	const char* m_where;
159 };
160 
161 void MP4HexDump(
162 	u_int8_t* pBytes, u_int32_t numBytes,
163 	FILE* pFile = stdout, u_int8_t indent = 0);
164 
MP4Malloc(size_t size)165 inline void* MP4Malloc(size_t size) {
166   if (size == 0) return NULL;
167 	void* p = malloc(size);
168 	if (p == NULL && size > 0) {
169 		throw new MP4Error(errno);
170 	}
171 	return p;
172 }
173 
MP4Calloc(size_t size)174 inline void* MP4Calloc(size_t size) {
175   if (size == 0) return NULL;
176 	return memset(MP4Malloc(size), 0, size);
177 }
178 
MP4Stralloc(const char * s1)179 inline char* MP4Stralloc(const char* s1) {
180 	char* s2 = (char*)MP4Malloc(strlen(s1) + 1);
181 	strcpy(s2, s1);
182 	return s2;
183 }
184 
185 #ifdef _WIN32
MP4Stralloc(const wchar_t * s1)186 inline wchar_t* MP4Stralloc(const wchar_t* s1) {
187 	wchar_t* s2 = (wchar_t*)MP4Malloc((wcslen(s1) + 1)*sizeof(wchar_t));
188 	wcscpy(s2, s1);
189 	return s2;
190 }
191 #endif
192 
MP4Realloc(void * p,u_int32_t newSize)193 inline void* MP4Realloc(void* p, u_int32_t newSize) {
194 	// workaround library bug
195 	if (p == NULL && newSize == 0) {
196 		return NULL;
197 	}
198 	p = realloc(p, newSize);
199 	if (p == NULL && newSize > 0) {
200 		throw new MP4Error(errno);
201 	}
202 	return p;
203 }
204 
STRTOINT32(const char * s)205 inline u_int32_t STRTOINT32(const char* s) {
206   return ntohl(*(uint32_t *)s);
207 }
208 
INT32TOSTR(u_int32_t i,char * s)209 inline void INT32TOSTR(u_int32_t i, char* s) {
210   *(uint32_t *)s = htonl(i);
211   s[4] = 0;
212 }
213 
MP4GetAbsTimestamp()214 inline MP4Timestamp MP4GetAbsTimestamp() {
215 	struct timeval tv;
216 	gettimeofday(&tv, NULL);
217 	MP4Timestamp ret;
218 	ret = tv.tv_sec;
219 	ret += 2082844800;
220 	return ret;	// MP4 start date is 1/1/1904
221 	// 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
222 }
223 
224 u_int64_t MP4ConvertTime(u_int64_t t,
225 	u_int32_t oldTimeScale, u_int32_t newTimeScale);
226 
227 bool MP4NameFirstMatches(const char* s1, const char* s2);
228 
229 bool MP4NameFirstIndex(const char* s, u_int32_t* pIndex);
230 
231 char* MP4NameFirst(const char *s);
232 
233 const char* MP4NameAfterFirst(const char *s);
234 
235 char* MP4ToBase16(const u_int8_t* pData, u_int32_t dataSize);
236 
237 char* MP4ToBase64(const u_int8_t* pData, u_int32_t dataSize);
238 
239 const char* MP4NormalizeTrackType(const char* type,
240 				  uint32_t verbosity);
241 
242 #endif /* __MP4_UTIL_INCLUDED__ */
243