Mercurial > audlegacy
annotate Plugins/Input/aac/libmp4v2/mp4util.cpp @ 199:0a2ad94e8607 trunk
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
author | chainsaw |
---|---|
date | Wed, 16 Nov 2005 16:21:11 -0800 |
parents | fa848bd484d8 |
children | f2dc045d2327 |
rev | line source |
---|---|
61 | 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 | |
199
0a2ad94e8607
[svn] Synced with bmp-mp4. Build system is fragile, but should work now.
chainsaw
parents:
61
diff
changeset
|
16 * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. |
61 | 17 * |
18 * Contributor(s): | |
19 * Dave Mackie dmackie@cisco.com | |
20 */ | |
21 | |
22 #include "mp4common.h" | |
23 | |
24 void MP4Error::Print(FILE* pFile) | |
25 { | |
26 fprintf(pFile, "MP4ERROR: "); | |
27 if (m_where) { | |
28 fprintf(pFile, "%s", m_where); | |
29 } | |
30 if (m_errstring) { | |
31 if (m_where) { | |
32 fprintf(pFile, ": "); | |
33 } | |
34 fprintf(pFile, "%s", m_errstring); | |
35 } | |
36 if (m_errno) { | |
37 if (m_where || m_errstring) { | |
38 fprintf(pFile, ": "); | |
39 } | |
40 fprintf(pFile, "%s", strerror(m_errno)); | |
41 } | |
42 fprintf(pFile, "\n"); | |
43 } | |
44 | |
45 void MP4HexDump( | |
46 u_int8_t* pBytes, u_int32_t numBytes, | |
47 FILE* pFile, u_int8_t indent) | |
48 { | |
49 if (pFile == NULL) { | |
50 pFile = stdout; | |
51 } | |
52 Indent(pFile, indent); | |
53 fprintf(pFile, "<%u bytes> ", numBytes); | |
54 for (u_int32_t i = 0; i < numBytes; i++) { | |
55 if ((i % 16) == 0 && numBytes > 16) { | |
56 fprintf(pFile, "\n"); | |
57 Indent(pFile, indent); | |
58 } | |
59 fprintf(pFile, "%02x ", pBytes[i]); | |
60 } | |
61 fprintf(pFile, "\n"); | |
62 } | |
63 | |
64 bool MP4NameFirstMatches(const char* s1, const char* s2) | |
65 { | |
66 if (s1 == NULL || *s1 == '\0' || s2 == NULL || *s2 == '\0') { | |
67 return false; | |
68 } | |
69 | |
70 if (*s2 == '*') { | |
71 return true; | |
72 } | |
73 | |
74 while (*s1 != '\0') { | |
75 if (*s2 == '\0' || strchr("[.", *s2)) { | |
76 break; | |
77 } | |
78 if (tolower(*s1) != tolower(*s2)) { | |
79 return false; | |
80 } | |
81 s1++; | |
82 s2++; | |
83 } | |
84 return true; | |
85 } | |
86 | |
87 bool MP4NameFirstIndex(const char* s, u_int32_t* pIndex) | |
88 { | |
89 if (s == NULL) { | |
90 return false; | |
91 } | |
92 | |
93 while (*s != '\0' && *s != '.') { | |
94 if (*s == '[') { | |
95 s++; | |
96 ASSERT(pIndex); | |
97 if (sscanf(s, "%u", pIndex) != 1) { | |
98 return false; | |
99 } | |
100 return true; | |
101 } | |
102 s++; | |
103 } | |
104 return false; | |
105 } | |
106 | |
107 char* MP4NameFirst(const char *s) | |
108 { | |
109 if (s == NULL) { | |
110 return NULL; | |
111 } | |
112 | |
113 const char* end = s; | |
114 | |
115 while (*end != '\0' && *end != '.') { | |
116 end++; | |
117 } | |
118 | |
119 char* first = (char*)MP4Calloc((end - s) + 1); | |
120 | |
121 if (first) { | |
122 strncpy(first, s, end - s); | |
123 } | |
124 | |
125 return first; | |
126 } | |
127 | |
128 const char* MP4NameAfterFirst(const char *s) | |
129 { | |
130 if (s == NULL) { | |
131 return NULL; | |
132 } | |
133 | |
134 while (*s != '\0') { | |
135 if (*s == '.') { | |
136 s++; | |
137 if (*s == '\0') { | |
138 return NULL; | |
139 } | |
140 return s; | |
141 } | |
142 s++; | |
143 } | |
144 return NULL; | |
145 } | |
146 | |
147 char* MP4ToBase16(const u_int8_t* pData, u_int32_t dataSize) | |
148 { | |
149 if (dataSize) { | |
150 ASSERT(pData); | |
151 } | |
152 | |
153 char* s = (char*)MP4Calloc((2 * dataSize) + 1); | |
154 | |
155 u_int32_t i, j; | |
156 for (i = 0, j = 0; i < dataSize; i++) { | |
157 sprintf(&s[j], "%02x", pData[i]); | |
158 j += 2; | |
159 } | |
160 | |
161 return s; /* N.B. caller is responsible for free'ing s */ | |
162 } | |
163 | |
164 char* MP4ToBase64(const u_int8_t* pData, u_int32_t dataSize) | |
165 { | |
166 if (dataSize) { | |
167 ASSERT(pData); | |
168 } | |
169 | |
170 static const char encoding[64] = { | |
171 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P', | |
172 'Q','R','S','T','U','V','W','X','Y','Z','a','b','c','d','e','f', | |
173 'g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v', | |
174 'w','x','y','z','0','1','2','3','4','5','6','7','8','9','+','/' | |
175 }; | |
176 | |
177 char* s = (char*)MP4Calloc((((dataSize + 2) * 4) / 3) + 1); | |
178 | |
179 const u_int8_t* src = pData; | |
180 char* dest = s; | |
181 u_int32_t numGroups = dataSize / 3; | |
182 | |
183 for (u_int32_t i = 0; i < numGroups; i++) { | |
184 *dest++ = encoding[src[0] >> 2]; | |
185 *dest++ = encoding[((src[0] & 0x03) << 4) | (src[1] >> 4)]; | |
186 *dest++ = encoding[((src[1] & 0x0F) << 2) | (src[2] >> 6)]; | |
187 *dest++ = encoding[src[2] & 0x3F]; | |
188 src += 3; | |
189 } | |
190 | |
191 if (dataSize % 3 == 1) { | |
192 *dest++ = encoding[src[0] >> 2]; | |
193 *dest++ = encoding[((src[0] & 0x03) << 4)]; | |
194 *dest++ = '='; | |
195 *dest++ = '='; | |
196 } else if (dataSize % 3 == 2) { | |
197 *dest++ = encoding[src[0] >> 2]; | |
198 *dest++ = encoding[((src[0] & 0x03) << 4) | (src[1] >> 4)]; | |
199 *dest++ = encoding[((src[1] & 0x0F) << 2)]; | |
200 *dest++ = '='; | |
201 } | |
202 *dest = '\0'; | |
203 return s; /* N.B. caller is responsible for free'ing s */ | |
204 } | |
205 | |
206 static bool convertBase64 (const char data, uint8_t *value) | |
207 { | |
208 static const uint8_t decodingarr64[128] = { | |
209 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
210 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
211 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
212 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
213 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
214 0xff, 0xff, 0xff, 0x3e, 0xff, 0xff, 0xff, 0x3f, | |
215 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, | |
216 0x3c, 0x3d, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, | |
217 0xff, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, | |
218 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, | |
219 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, | |
220 0x17, 0x18, 0x19, 0xff, 0xff, 0xff, 0xff, 0xff, | |
221 0xff, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, | |
222 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27, 0x28, | |
223 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f, 0x30, | |
224 0x31, 0x32, 0x33, 0xff, 0xff, 0xff, 0xff, 0xff, | |
225 }; | |
226 uint8_t index = (uint8_t)data; | |
227 if ((index & 0x80) != 0) return false; | |
228 | |
229 if (decodingarr64[index] == 0xff) return false; | |
230 *value = decodingarr64[index]; | |
231 return true; | |
232 } | |
233 | |
234 uint8_t *Base64ToBinary (const char *pData, uint32_t decodeSize, uint32_t *pDataSize) | |
235 { | |
236 uint8_t *ret; | |
237 uint32_t size, ix, groups; | |
238 if (pData == NULL || decodeSize == 0 || pDataSize == NULL) | |
239 return NULL; | |
240 | |
241 if ((decodeSize % 4) != 0) { | |
242 // must be multiples of 4 characters | |
243 return NULL; | |
244 } | |
245 size = (decodeSize * 3) / 4; | |
246 groups = decodeSize / 4; | |
247 ret = (uint8_t *)MP4Calloc(size); | |
248 for (ix = 0; ix < groups; ix++) { | |
249 uint8_t value[4]; | |
250 for (uint8_t jx = 0; jx < 4; jx++) { | |
251 if (pData[jx] == '=') { | |
252 if (ix != (groups - 1)) { | |
253 free(ret); | |
254 return NULL; | |
255 } | |
256 size--; | |
257 value[jx] = 0; | |
258 } else if (convertBase64(pData[jx], &value[jx]) == false) { | |
259 free(ret); | |
260 return NULL; | |
261 } | |
262 } | |
263 ret[(ix * 3)] = value[0] << 2 | ((value[1] >> 4) & 0x3); | |
264 ret[(ix * 3) + 1] = (value[1] << 4) | (value[2] >> 2 & 0xf); | |
265 ret[(ix * 3) + 2] = ((value[2] & 0x3) << 6) | value[3]; | |
266 pData += 4; | |
267 } | |
268 *pDataSize = size; | |
269 return ret; | |
270 } | |
271 | |
272 // log2 of value, rounded up | |
273 static u_int8_t ilog2(u_int64_t value) | |
274 { | |
275 u_int64_t powerOf2 = 1; | |
276 for (u_int8_t i = 0; i < 64; i++) { | |
277 if (value <= powerOf2) { | |
278 return i; | |
279 } | |
280 powerOf2 <<= 1; | |
281 } | |
282 return 64; | |
283 } | |
284 | |
285 u_int64_t MP4ConvertTime(u_int64_t t, | |
286 u_int32_t oldTimeScale, u_int32_t newTimeScale) | |
287 { | |
288 // avoid float point exception | |
289 if (oldTimeScale == 0) { | |
290 throw new MP4Error("division by zero", "MP4ConvertTime"); | |
291 } | |
292 | |
293 // check if we can safely use integer operations | |
294 if (ilog2(t) + ilog2(newTimeScale) <= 64) { | |
295 return (t * newTimeScale) / oldTimeScale; | |
296 } | |
297 | |
298 // final resort is to use floating point | |
299 double d = ((double)newTimeScale / (double)oldTimeScale) + 0.5; | |
300 d *= UINT64_TO_DOUBLE(t); | |
301 | |
302 return (u_int64_t)d; | |
303 } | |
304 | |
305 const char* MP4NormalizeTrackType (const char* type, | |
306 uint32_t verbosity) | |
307 { | |
308 if (!strcasecmp(type, "vide") | |
309 || !strcasecmp(type, "video") | |
310 || !strcasecmp(type, "mp4v") | |
311 || !strcasecmp(type, "avc1") | |
312 || !strcasecmp(type, "s263") // 3GPP H.263 | |
313 || !strcasecmp(type, "encv")) { | |
314 return MP4_VIDEO_TRACK_TYPE; | |
315 } | |
316 | |
317 if (!strcasecmp(type, "soun") | |
318 || !strcasecmp(type, "sound") | |
319 || !strcasecmp(type, "audio") | |
320 || !strcasecmp(type, "enca") | |
321 || !strcasecmp(type, "samr") // 3GPP AMR | |
322 || !strcasecmp(type, "sawb") // 3GPP AMR/WB | |
323 || !strcasecmp(type, "mp4a")) { | |
324 return MP4_AUDIO_TRACK_TYPE; | |
325 } | |
326 | |
327 if (!strcasecmp(type, "sdsm") | |
328 || !strcasecmp(type, "scene") | |
329 || !strcasecmp(type, "bifs")) { | |
330 return MP4_SCENE_TRACK_TYPE; | |
331 } | |
332 | |
333 if (!strcasecmp(type, "odsm") | |
334 || !strcasecmp(type, "od")) { | |
335 return MP4_OD_TRACK_TYPE; | |
336 } | |
337 VERBOSE_WARNING(verbosity, | |
338 printf("Attempt to normalize %s did not match\n", | |
339 type)); | |
340 return type; | |
341 } |