comparison Input/aac/libmp4v2/mp4util.cpp @ 16:6a86fdd4dea4 trunk

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