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  * 3GPP features implementation is based on 3GPP's TS26.234-v5.60,
19  * and was contributed by Ximpo Group Ltd.
20  *
21  * Portions created by Ximpo Group Ltd. are
22  * Copyright (C) Ximpo Group Ltd. 2003, 2004.  All Rights Reserved.
23  *
24  * Contributor(s):
25  *		Dave Mackie			dmackie@cisco.com
26  *		Alix Marchandise-Franquet	alix@cisco.com
27  *              Ximpo Group Ltd.                mp4v2@ximpo.com
28  *              Bill May                        wmay@cisco.com
29  */
30 
31 /*
32  * MP4 library API functions
33  *
34  * These are wrapper functions that provide C linkage conventions
35  * to the library, and catch any internal errors, ensuring that
36  * a proper return value is given.
37  */
38 
39 #include "mp4common.h"
40 
41 #define PRINT_ERROR(e) \
42 	VERBOSE_ERROR(((MP4File*)hFile)->GetVerbosity(), e->Print());
43 
44 /* file operations */
45 // benski>
MP4ReadEx(const char * fileName,void * user,struct Virtual_IO * virtual_IO,u_int32_t verbosity)46  extern "C" MP4FileHandle MP4ReadEx (const char* fileName,
47 				     void *user,
48 				     struct Virtual_IO *virtual_IO,
49 				     u_int32_t verbosity)
50 {
51   MP4File* pFile = NULL;
52   try {
53     pFile = new MP4File(verbosity);
54 
55     pFile->ReadEx(fileName, user, virtual_IO);
56     return (MP4FileHandle)pFile;
57   } catch (MP4Error* e) {
58     VERBOSE_ERROR(verbosity, e->Print());
59     delete e;
60     delete pFile;
61     return MP4_INVALID_FILE_HANDLE;
62   }
63 }
64 
MP4Read(const char * fileName,u_int32_t verbosity)65 extern "C" MP4FileHandle MP4Read(const char* fileName, u_int32_t verbosity)
66 {
67 	MP4File* pFile = NULL;
68 	try {
69 		pFile = new MP4File(verbosity);
70 		pFile->Read(fileName);
71 		return (MP4FileHandle)pFile;
72 	}
73 	catch (MP4Error* e) {
74 		VERBOSE_ERROR(verbosity, e->Print());
75 		delete e;
76 		delete pFile;
77 		return MP4_INVALID_FILE_HANDLE;
78 	}
79 }
80 
MP4Create(const char * fileName,u_int32_t verbosity,u_int32_t flags)81 extern "C" MP4FileHandle MP4Create (const char* fileName,
82 				    u_int32_t verbosity,
83 				    u_int32_t  flags)
84 {
85   return MP4CreateEx(fileName, verbosity, flags);
86 }
87 
MP4CreateEx(const char * fileName,u_int32_t verbosity,u_int32_t flags,int add_ftyp,int add_iods,char * majorBrand,u_int32_t minorVersion,char ** supportedBrands,u_int32_t supportedBrandsCount)88 extern "C" MP4FileHandle MP4CreateEx (const char* fileName,
89 				      u_int32_t verbosity,
90 				      u_int32_t  flags,
91 				      int add_ftyp,
92 				      int add_iods,
93 				      char* majorBrand,
94 				      u_int32_t minorVersion,
95 				      char** supportedBrands,
96 				      u_int32_t supportedBrandsCount)
97 {
98 	MP4File* pFile = NULL;
99 	try {
100 		pFile = new MP4File(verbosity);
101 		// LATER useExtensibleFormat, moov first, then mvex's
102 		pFile->Create(fileName, flags, add_ftyp, add_iods,
103 			      majorBrand, minorVersion,
104 			      supportedBrands, supportedBrandsCount);
105 		return (MP4FileHandle)pFile;
106 	}
107 	catch (MP4Error* e) {
108 		VERBOSE_ERROR(verbosity, e->Print());
109 		delete e;
110 		delete pFile;
111 		return MP4_INVALID_FILE_HANDLE;
112 	}
113 }
114 
MP4Modify(const char * fileName,u_int32_t verbosity,u_int32_t flags)115 extern "C" MP4FileHandle MP4Modify(const char* fileName,
116 	u_int32_t verbosity, u_int32_t flags)
117 {
118 	MP4File* pFile = NULL;
119 	try {
120 		pFile = new MP4File(verbosity);
121 		// LATER useExtensibleFormat, moov first, then mvex's
122 		if (pFile->Modify(fileName))
123 		return (MP4FileHandle)pFile;
124 	}
125 	catch (MP4Error* e) {
126 		VERBOSE_ERROR(verbosity, e->Print());
127 		delete e;
128 	}
129 
130 	if (pFile) delete pFile;
131 	return MP4_INVALID_FILE_HANDLE;
132 }
133 
MP4Optimize(const char * existingFileName,const char * newFileName,u_int32_t verbosity)134 extern "C" bool MP4Optimize(const char* existingFileName,
135 	const char* newFileName,
136 	u_int32_t verbosity)
137 {
138 	try {
139 		MP4File* pFile = new MP4File(verbosity);
140 		pFile->Optimize(existingFileName, newFileName);
141 		delete pFile;
142 		return true;
143 	}
144 	catch (MP4Error* e) {
145 		VERBOSE_ERROR(verbosity, e->Print());
146 		delete e;
147 	}
148 	return false;
149 }
150 
MP4Close(MP4FileHandle hFile)151 extern "C" void MP4Close(MP4FileHandle hFile)
152 {
153 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
154 		try {
155 			((MP4File*)hFile)->Close();
156 			delete (MP4File*)hFile;
157 			return;
158 		}
159 		catch (MP4Error* e) {
160 			PRINT_ERROR(e);
161 			delete e;
162 		}
163 	}
164 	return ;
165 }
166 
MP4Dump(MP4FileHandle hFile,FILE * pDumpFile,bool dumpImplicits)167 extern "C" bool MP4Dump(
168 	MP4FileHandle hFile,
169 	FILE* pDumpFile,
170 	bool dumpImplicits)
171 {
172 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
173 		try {
174 			((MP4File*)hFile)->Dump(pDumpFile, dumpImplicits);
175 			return true;
176 		}
177 		catch (MP4Error* e) {
178 			PRINT_ERROR(e);
179 			delete e;
180 		}
181 	}
182 	return false;
183 }
184 
185 
186 /* specific file properties */
187 
MP4GetVerbosity(MP4FileHandle hFile)188 extern "C" u_int32_t MP4GetVerbosity(MP4FileHandle hFile)
189 {
190 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
191 		try {
192 			return ((MP4File*)hFile)->GetVerbosity();
193 		}
194 		catch (MP4Error* e) {
195 			PRINT_ERROR(e);
196 			delete e;
197 		}
198 	}
199 	return 0;
200 }
201 
MP4SetVerbosity(MP4FileHandle hFile,u_int32_t verbosity)202 extern "C" void MP4SetVerbosity(MP4FileHandle hFile, u_int32_t verbosity)
203 {
204 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
205 		try {
206 			((MP4File*)hFile)->SetVerbosity(verbosity);
207 			return;
208 		}
209 		catch (MP4Error* e) {
210 			PRINT_ERROR(e);
211 			delete e;
212 		}
213 	}
214 	return;
215 }
216 
MP4GetDuration(MP4FileHandle hFile)217 extern "C" MP4Duration MP4GetDuration(MP4FileHandle hFile)
218 {
219 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
220 		try {
221 			return ((MP4File*)hFile)->GetDuration();
222 		}
223 		catch (MP4Error* e) {
224 			PRINT_ERROR(e);
225 			delete e;
226 		}
227 	}
228 	return MP4_INVALID_DURATION;
229 }
230 
MP4GetTimeScale(MP4FileHandle hFile)231 extern "C" u_int32_t MP4GetTimeScale(MP4FileHandle hFile)
232 {
233 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
234 		try {
235 			return ((MP4File*)hFile)->GetTimeScale();
236 		}
237 		catch (MP4Error* e) {
238 			PRINT_ERROR(e);
239 			delete e;
240 		}
241 	}
242 	return 0;
243 }
244 
MP4SetTimeScale(MP4FileHandle hFile,u_int32_t value)245 extern "C" bool MP4SetTimeScale(MP4FileHandle hFile, u_int32_t value)
246 {
247 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
248 		try {
249 			((MP4File*)hFile)->SetTimeScale(value);
250 			return true;
251 		}
252 		catch (MP4Error* e) {
253 			PRINT_ERROR(e);
254 			delete e;
255 		}
256 	}
257 	return false;
258 }
259 
MP4GetODProfileLevel(MP4FileHandle hFile)260 extern "C" u_int8_t MP4GetODProfileLevel(MP4FileHandle hFile)
261 {
262 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
263 		try {
264 			return ((MP4File*)hFile)->GetODProfileLevel();
265 		}
266 		catch (MP4Error* e) {
267 			PRINT_ERROR(e);
268 			delete e;
269 		}
270 	}
271 	return 0;
272 }
273 
MP4SetODProfileLevel(MP4FileHandle hFile,u_int8_t value)274 extern "C" bool MP4SetODProfileLevel(MP4FileHandle hFile, u_int8_t value)
275 {
276 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
277 		try {
278 			((MP4File*)hFile)->SetODProfileLevel(value);
279 			return true;
280 		}
281 		catch (MP4Error* e) {
282 			PRINT_ERROR(e);
283 			delete e;
284 		}
285 	}
286 	return false;
287 }
288 
MP4GetSceneProfileLevel(MP4FileHandle hFile)289 extern "C" u_int8_t MP4GetSceneProfileLevel(MP4FileHandle hFile)
290 {
291 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
292 		try {
293 			return ((MP4File*)hFile)->GetSceneProfileLevel();
294 		}
295 		catch (MP4Error* e) {
296 			PRINT_ERROR(e);
297 			delete e;
298 		}
299 	}
300 	return 0;
301 }
302 
MP4SetSceneProfileLevel(MP4FileHandle hFile,u_int8_t value)303 extern "C" bool MP4SetSceneProfileLevel(MP4FileHandle hFile, u_int8_t value)
304 {
305 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
306 		try {
307 			((MP4File*)hFile)->SetSceneProfileLevel(value);
308 			return true;
309 		}
310 		catch (MP4Error* e) {
311 			PRINT_ERROR(e);
312 			delete e;
313 		}
314 	}
315 	return false;
316 }
317 
MP4GetVideoProfileLevel(MP4FileHandle hFile,MP4TrackId trackId)318 extern "C" u_int8_t MP4GetVideoProfileLevel(MP4FileHandle hFile,
319 					    MP4TrackId trackId)
320 {
321 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
322 		try {
323 			return ((MP4File*)hFile)->GetVideoProfileLevel();
324 		}
325 		catch (MP4Error* e) {
326 			PRINT_ERROR(e);
327 			delete e;
328 		}
329 		if (MP4_IS_VALID_TRACK_ID(trackId)) {
330 		  uint8_t *foo;
331 		  uint32_t bufsize;
332 		  uint8_t type;
333 		  // for mpeg4 video tracks, try to look for the VOSH header,
334 		  // which has this info.
335 		  type = MP4GetTrackEsdsObjectTypeId(hFile, trackId);
336 		  if (type == MP4_MPEG4_VIDEO_TYPE) {
337 		    if (MP4GetTrackESConfiguration(hFile,
338 						   trackId,
339 						   &foo,
340 						   &bufsize)) {
341 		      uint8_t *ptr = foo;
342 		      while (bufsize > 0) {
343 			if (htonl(*(uint32_t *)ptr) == 0x1b0) {
344 			  uint8_t ret = ptr[4];
345 			  free(foo);
346 			  return ret;
347 			}
348 			ptr++;
349 			bufsize--;
350 		      }
351 		      free(foo);
352 		    }
353 		  }
354 		}
355 
356 	}
357 	return 0;
358 }
359 
MP4SetVideoProfileLevel(MP4FileHandle hFile,u_int8_t value)360 extern "C" void MP4SetVideoProfileLevel(MP4FileHandle hFile, u_int8_t value)
361 {
362 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
363 		try {
364 			((MP4File*)hFile)->SetVideoProfileLevel(value);
365 			return ;
366 		}
367 		catch (MP4Error* e) {
368 			PRINT_ERROR(e);
369 			delete e;
370 		}
371 	}
372 	return ;
373 }
374 
MP4GetAudioProfileLevel(MP4FileHandle hFile)375 extern "C" u_int8_t MP4GetAudioProfileLevel(MP4FileHandle hFile)
376 {
377 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
378 		try {
379 			return ((MP4File*)hFile)->GetAudioProfileLevel();
380 		}
381 		catch (MP4Error* e) {
382 			PRINT_ERROR(e);
383 			delete e;
384 		}
385 	}
386 	return 0;
387 }
388 
MP4SetAudioProfileLevel(MP4FileHandle hFile,u_int8_t value)389 extern "C" void MP4SetAudioProfileLevel(MP4FileHandle hFile, u_int8_t value)
390 {
391 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
392 		try {
393 			((MP4File*)hFile)->SetAudioProfileLevel(value);
394 		}
395 		catch (MP4Error* e) {
396 			PRINT_ERROR(e);
397 			delete e;
398 		}
399 	}
400 }
401 
MP4GetGraphicsProfileLevel(MP4FileHandle hFile)402 extern "C" u_int8_t MP4GetGraphicsProfileLevel(MP4FileHandle hFile)
403 {
404 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
405 		try {
406 			return ((MP4File*)hFile)->GetGraphicsProfileLevel();
407 		}
408 		catch (MP4Error* e) {
409 			PRINT_ERROR(e);
410 			delete e;
411 		}
412 	}
413 	return 0;
414 }
415 
MP4SetGraphicsProfileLevel(MP4FileHandle hFile,u_int8_t value)416 extern "C" bool MP4SetGraphicsProfileLevel(MP4FileHandle hFile, u_int8_t value)
417 {
418 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
419 		try {
420 			((MP4File*)hFile)->SetGraphicsProfileLevel(value);
421 			return true;
422 		}
423 		catch (MP4Error* e) {
424 			PRINT_ERROR(e);
425 			delete e;
426 		}
427 	}
428 	return false;
429 }
430 
431 /* generic file properties */
432 
MP4HaveAtom(MP4FileHandle hFile,const char * atomName)433 extern "C" bool MP4HaveAtom (MP4FileHandle hFile, const char *atomName)
434 {
435   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
436     try {
437       return ((MP4File *)hFile)->FindAtom(atomName) != NULL;
438     } catch (MP4Error *e) {
439       PRINT_ERROR(e);
440       delete e;
441     }
442   }
443   return false;
444 }
445 
MP4GetIntegerProperty(MP4FileHandle hFile,const char * propName,u_int64_t * retvalue)446 extern "C" bool MP4GetIntegerProperty(
447 	MP4FileHandle hFile, const char* propName, u_int64_t *retvalue)
448 {
449 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
450 		try {
451 			*retvalue = ((MP4File*)hFile)->GetIntegerProperty(propName);
452 			return true;
453 		}
454 		catch (MP4Error* e) {
455 			PRINT_ERROR(e);
456 			delete e;
457 		}
458 	}
459 	return false;
460 }
461 
MP4GetFloatProperty(MP4FileHandle hFile,const char * propName,float * retvalue)462 extern "C" bool MP4GetFloatProperty(
463 	MP4FileHandle hFile, const char* propName, float *retvalue)
464 {
465 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
466 		try {
467 			*retvalue = ((MP4File*)hFile)->GetFloatProperty(propName);
468 			return true;
469 		}
470 		catch (MP4Error* e) {
471 			PRINT_ERROR(e);
472 			delete e;
473 		}
474 	}
475 	return false;
476 }
477 
MP4GetStringProperty(MP4FileHandle hFile,const char * propName,const char ** retvalue)478 extern "C" bool MP4GetStringProperty(
479 	MP4FileHandle hFile, const char* propName,
480 	const char **retvalue)
481 {
482 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
483 		try {
484 			*retvalue =  ((MP4File*)hFile)->GetStringProperty(propName);
485 			return true;
486 		}
487 		catch (MP4Error* e) {
488 			PRINT_ERROR(e);
489 			delete e;
490 		}
491 	}
492 	return false;
493 }
494 
MP4GetBytesProperty(MP4FileHandle hFile,const char * propName,u_int8_t ** ppValue,u_int32_t * pValueSize)495 extern "C" bool MP4GetBytesProperty(
496 	MP4FileHandle hFile, const char* propName,
497 	u_int8_t** ppValue, u_int32_t* pValueSize)
498 {
499 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
500 		try {
501 			((MP4File*)hFile)->GetBytesProperty(propName, ppValue, pValueSize);
502 			return true;
503 		}
504 		catch (MP4Error* e) {
505 			PRINT_ERROR(e);
506 			delete e;
507 		}
508 	}
509 	*ppValue = NULL;
510 	*pValueSize = 0;
511 	return false;
512 }
513 
MP4SetIntegerProperty(MP4FileHandle hFile,const char * propName,int64_t value)514 extern "C" bool MP4SetIntegerProperty(
515 	MP4FileHandle hFile, const char* propName, int64_t value)
516 {
517 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
518 		try {
519 			((MP4File*)hFile)->SetIntegerProperty(propName, value);
520 			return true;
521 		}
522 		catch (MP4Error* e) {
523 			PRINT_ERROR(e);
524 			delete e;
525 		}
526 	}
527 	return false;
528 }
529 
MP4SetFloatProperty(MP4FileHandle hFile,const char * propName,float value)530 extern "C" bool MP4SetFloatProperty(
531 	MP4FileHandle hFile, const char* propName, float value)
532 {
533 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
534 		try {
535 			((MP4File*)hFile)->SetFloatProperty(propName, value);
536 			return true;
537 		}
538 		catch (MP4Error* e) {
539 			PRINT_ERROR(e);
540 			delete e;
541 		}
542 	}
543 	return false;
544 }
545 
MP4SetStringProperty(MP4FileHandle hFile,const char * propName,const char * value)546 extern "C" bool MP4SetStringProperty(
547 	MP4FileHandle hFile, const char* propName, const char* value)
548 {
549 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
550 		try {
551 			((MP4File*)hFile)->SetStringProperty(propName, value);
552 			return true;
553 		}
554 		catch (MP4Error* e) {
555 			PRINT_ERROR(e);
556 			delete e;
557 		}
558 	}
559 	return false;
560 }
561 
MP4SetBytesProperty(MP4FileHandle hFile,const char * propName,const u_int8_t * pValue,u_int32_t valueSize)562 extern "C" bool MP4SetBytesProperty(
563 	MP4FileHandle hFile, const char* propName,
564 	const u_int8_t* pValue, u_int32_t valueSize)
565 {
566 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
567 		try {
568 			((MP4File*)hFile)->SetBytesProperty(propName, pValue, valueSize);
569 			return true;
570 		}
571 		catch (MP4Error* e) {
572 			PRINT_ERROR(e);
573 			delete e;
574 		}
575 	}
576 	return false;
577 }
578 
579 /* track operations */
580 
MP4AddTrack(MP4FileHandle hFile,const char * type)581 extern "C" MP4TrackId MP4AddTrack(
582 	MP4FileHandle hFile, const char* type)
583 {
584 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
585 		try {
586 			return ((MP4File*)hFile)->AddSystemsTrack(type);
587 		}
588 		catch (MP4Error* e) {
589 			PRINT_ERROR(e);
590 			delete e;
591 		}
592 	}
593 	return MP4_INVALID_TRACK_ID;
594 }
595 
MP4AddSystemsTrack(MP4FileHandle hFile,const char * type)596 extern "C" MP4TrackId MP4AddSystemsTrack(
597 	MP4FileHandle hFile, const char* type)
598 {
599 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
600 		try {
601 			return ((MP4File*)hFile)->AddSystemsTrack(type);
602 		}
603 		catch (MP4Error* e) {
604 			PRINT_ERROR(e);
605 			delete e;
606 		}
607 	}
608 	return MP4_INVALID_TRACK_ID;
609 }
610 
MP4AddODTrack(MP4FileHandle hFile)611 extern "C" MP4TrackId MP4AddODTrack(MP4FileHandle hFile)
612 {
613 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
614 		try {
615 			return ((MP4File*)hFile)->AddODTrack();
616 		}
617 		catch (MP4Error* e) {
618 			PRINT_ERROR(e);
619 			delete e;
620 		}
621 	}
622 	return MP4_INVALID_TRACK_ID;
623 }
624 
MP4AddSceneTrack(MP4FileHandle hFile)625 extern "C" MP4TrackId MP4AddSceneTrack(MP4FileHandle hFile)
626 {
627 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
628 		try {
629 			return ((MP4File*)hFile)->AddSceneTrack();
630 		}
631 		catch (MP4Error* e) {
632 			PRINT_ERROR(e);
633 			delete e;
634 		}
635 	}
636 	return MP4_INVALID_TRACK_ID;
637 }
638 
MP4AddAudioTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,u_int8_t audioType)639 extern "C" MP4TrackId MP4AddAudioTrack(
640 	MP4FileHandle hFile,
641 	u_int32_t timeScale,
642 	MP4Duration sampleDuration,
643 	u_int8_t audioType)
644 {
645 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
646 		try {
647 			return ((MP4File*)hFile)->
648 				AddAudioTrack(timeScale, sampleDuration, audioType);
649 		}
650 		catch (MP4Error* e) {
651 			PRINT_ERROR(e);
652 			delete e;
653 		}
654 	}
655 	return MP4_INVALID_TRACK_ID;
656 }
657 
658 //
659 // API to initialize ismacryp properties to sensible defaults.
660 // if the input pointer is null then an ismacryp params is malloc'd.
661 // caller must see to it that it is properly disposed of.
662 //
MP4DefaultISMACrypParams(mp4v2_ismacrypParams * ptr)663 extern "C" mp4v2_ismacrypParams *MP4DefaultISMACrypParams(mp4v2_ismacrypParams *ptr)
664 {
665     try
666     {
667         if (ptr == NULL) {
668             ptr = (mp4v2_ismacrypParams *)MP4Malloc(sizeof(mp4v2_ismacrypParams));
669         }
670         memset(ptr, 0, sizeof(*ptr));
671         return ptr;
672     }
673 
674     catch (...) {
675       return MP4_INVALID_TRACK_ID;
676     }
677 }
678 
679 
MP4AddEncAudioTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,mp4v2_ismacrypParams * icPp,u_int8_t audioType)680 extern "C" MP4TrackId MP4AddEncAudioTrack(MP4FileHandle hFile,
681 					  u_int32_t timeScale,
682 					  MP4Duration sampleDuration,
683                                           mp4v2_ismacrypParams *icPp,
684 					  u_int8_t audioType)
685 {
686   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
687     try {
688       if (icPp == NULL) {
689 	return ((MP4File*)hFile)->
690 	  AddEncAudioTrack(timeScale, sampleDuration, audioType,
691 			   0, 0,
692 			   0, 0,
693 			   false, NULL, false);
694       } else {
695 	return ((MP4File*)hFile)->
696 	  AddEncAudioTrack(timeScale, sampleDuration, audioType,
697 			   icPp->scheme_type, icPp->scheme_version,
698 			   icPp->key_ind_len, icPp->iv_len,
699 			   icPp->selective_enc, icPp->kms_uri, true);
700       }
701     } catch (MP4Error* e) {
702       PRINT_ERROR(e);
703       delete e;
704     }
705   }
706   return MP4_INVALID_TRACK_ID;
707 }
MP4AddAmrAudioTrack(MP4FileHandle hFile,u_int32_t timeScale,u_int16_t modeSet,u_int8_t modeChangePeriod,u_int8_t framesPerSample,bool isAmrWB)708 extern "C" MP4TrackId MP4AddAmrAudioTrack(
709 		MP4FileHandle hFile,
710 		u_int32_t timeScale,
711 		u_int16_t modeSet,
712 		u_int8_t modeChangePeriod,
713 		u_int8_t framesPerSample,
714 		bool isAmrWB)
715 {
716 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
717 		try {
718 			return ((MP4File*)hFile)->
719 				AddAmrAudioTrack(timeScale, modeSet, modeChangePeriod, framesPerSample, isAmrWB);
720 		}
721 		catch (MP4Error* e) {
722 			PRINT_ERROR(e);
723 			delete e;
724 		}
725 	}
726 	return MP4_INVALID_TRACK_ID;
727 }
728 
MP4SetAmrVendor(MP4FileHandle hFile,MP4TrackId trackId,u_int32_t vendor)729 extern "C" void MP4SetAmrVendor(
730 		MP4FileHandle hFile,
731 		MP4TrackId trackId,
732 		u_int32_t vendor)
733 {
734 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
735 		try {
736 			((MP4File*)hFile)->
737 				SetAmrVendor(trackId, vendor);
738 		}
739 		catch (MP4Error* e) {
740 			PRINT_ERROR(e);
741 			delete e;
742 		}
743 	}
744 }
745 
MP4SetAmrDecoderVersion(MP4FileHandle hFile,MP4TrackId trackId,u_int8_t decoderVersion)746 extern "C" void MP4SetAmrDecoderVersion(
747 		MP4FileHandle hFile,
748 		MP4TrackId trackId,
749 		u_int8_t decoderVersion)
750 {
751 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
752 		try {
753 			((MP4File*)hFile)->
754 				SetAmrDecoderVersion(trackId, decoderVersion);
755 		}
756 		catch (MP4Error* e) {
757 			PRINT_ERROR(e);
758 			delete e;
759 		}
760 	}
761 }
762 
MP4SetAmrModeSet(MP4FileHandle hFile,MP4TrackId trackId,u_int16_t modeSet)763 extern "C" void MP4SetAmrModeSet(
764 		MP4FileHandle hFile,
765 		MP4TrackId trackId,
766 		u_int16_t modeSet)
767 {
768 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
769 		try {
770 			((MP4File*)hFile)->
771 				SetAmrModeSet(trackId, modeSet);
772 		}
773 		catch (MP4Error* e) {
774 			PRINT_ERROR(e);
775 			delete e;
776 		}
777 	}
778 }
779 
MP4GetAmrModeSet(MP4FileHandle hFile,MP4TrackId trackId)780 extern "C" uint16_t MP4GetAmrModeSet(
781 				     MP4FileHandle hFile,
782 				     MP4TrackId trackId)
783 {
784 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
785 		try {
786 		  return ((MP4File*)hFile)->
787 				GetAmrModeSet(trackId);
788 		}
789 		catch (MP4Error* e) {
790 			PRINT_ERROR(e);
791 			delete e;
792 		}
793 	}
794 	return 0;
795 }
796 
MP4AddHrefTrack(MP4FileHandle hFile,uint32_t timeScale,MP4Duration sampleDuration,const char * base_url)797 extern "C" MP4TrackId MP4AddHrefTrack (MP4FileHandle hFile,
798 				       uint32_t timeScale,
799 				       MP4Duration sampleDuration,
800 				       const char *base_url)
801 {
802   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
803     try {
804       MP4File *pFile = (MP4File *)hFile;
805 
806       return pFile->AddHrefTrack(timeScale,
807 				 sampleDuration,
808 				 base_url);
809     }
810     catch (MP4Error* e) {
811       PRINT_ERROR(e);
812       delete e;
813     }
814   }
815   return MP4_INVALID_TRACK_ID;
816 }
817 
MP4GetHrefTrackBaseUrl(MP4FileHandle hFile,MP4TrackId trackId)818 extern "C" const char *MP4GetHrefTrackBaseUrl (MP4FileHandle hFile,
819 					       MP4TrackId trackId)
820 {
821   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
822     try {
823       return ((MP4File*)hFile)->GetTrackStringProperty(trackId,
824 						       "mdia.minf.stbl.stsd.href.burl.base_url");
825     }
826     catch (MP4Error* e) {
827       PRINT_ERROR(e);
828       delete e;
829     }
830   }
831   return NULL;
832 }
833 
MP4AddVideoTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,u_int16_t width,u_int16_t height,u_int8_t videoType)834 extern "C" MP4TrackId MP4AddVideoTrack(
835 	MP4FileHandle hFile,
836 	u_int32_t timeScale,
837 	MP4Duration sampleDuration,
838 	u_int16_t width,
839 	u_int16_t height,
840 	u_int8_t videoType)
841 {
842   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
843     try {
844       MP4File *pFile = (MP4File *)hFile;
845 
846       return pFile->AddMP4VideoTrack(timeScale,
847 				     sampleDuration,
848 				     width,
849 				     height,
850 				     videoType);
851     }
852     catch (MP4Error* e) {
853       PRINT_ERROR(e);
854       delete e;
855     }
856   }
857   return MP4_INVALID_TRACK_ID;
858 }
859 
MP4AddEncVideoTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,u_int16_t width,u_int16_t height,mp4v2_ismacrypParams * icPp,u_int8_t videoType,const char * oFormat)860 extern "C" MP4TrackId MP4AddEncVideoTrack(MP4FileHandle hFile,
861 					  u_int32_t timeScale,
862 					  MP4Duration sampleDuration,
863 					  u_int16_t width,
864 					  u_int16_t height,
865                                           mp4v2_ismacrypParams *icPp,
866 					  u_int8_t videoType,
867 					  const char *oFormat)
868 {
869   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
870     try {
871 
872  	  // test for valid ismacrypt session descriptor
873       if (icPp == NULL) {
874 		return MP4_INVALID_TRACK_ID;
875       }
876       MP4File *pFile = (MP4File *)hFile;
877 
878 	return pFile->AddEncVideoTrack(timeScale,
879 			sampleDuration,
880 			width,
881 			height,
882 			videoType,
883 			icPp,
884 			oFormat);
885 
886     } catch (MP4Error* e) {
887       PRINT_ERROR(e);
888       delete e;
889     }
890   }
891   return MP4_INVALID_TRACK_ID;
892 }
893 
894 
MP4AddH264VideoTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,u_int16_t width,u_int16_t height,uint8_t AVCProfileIndication,uint8_t profile_compat,uint8_t AVCLevelIndication,uint8_t sampleLenFieldSizeMinusOne)895 extern "C" MP4TrackId MP4AddH264VideoTrack(MP4FileHandle hFile,
896 					   u_int32_t timeScale,
897 					   MP4Duration sampleDuration,
898 					   u_int16_t width,
899 					   u_int16_t height,
900 					   uint8_t AVCProfileIndication,
901 					   uint8_t profile_compat,
902 					   uint8_t AVCLevelIndication,
903 					   uint8_t sampleLenFieldSizeMinusOne)
904 {
905   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
906     try {
907       MP4File *pFile = (MP4File *)hFile;
908 
909       return pFile->AddH264VideoTrack(timeScale,
910 				      sampleDuration,
911 				      width,
912 				      height,
913 				      AVCProfileIndication,
914 				      profile_compat,
915 				      AVCLevelIndication,
916 				      sampleLenFieldSizeMinusOne);
917     }
918     catch (MP4Error* e) {
919       PRINT_ERROR(e);
920       delete e;
921     }
922   }
923   return MP4_INVALID_TRACK_ID;
924 }
925 
MP4AddEncH264VideoTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,u_int16_t width,u_int16_t height,MP4FileHandle srcFile,MP4TrackId srcTrackId,mp4v2_ismacrypParams * icPp)926 extern "C" MP4TrackId MP4AddEncH264VideoTrack(
927 	MP4FileHandle hFile,
928 	u_int32_t timeScale,
929 	MP4Duration sampleDuration,
930 	u_int16_t width,
931 	u_int16_t height,
932 	MP4FileHandle srcFile,
933 	MP4TrackId srcTrackId,
934     mp4v2_ismacrypParams *icPp
935 )
936 
937 {
938   MP4Atom *srcAtom;
939   MP4File *pFile;
940 
941   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
942     try {
943 
944 	pFile = (MP4File *)srcFile;
945 	srcAtom = pFile->FindTrackAtom(srcTrackId, "mdia.minf.stbl.stsd.avc1.avcC");
946 	if (srcAtom == NULL)
947 		return MP4_INVALID_TRACK_ID;
948 
949 	pFile = (MP4File *)hFile;
950 
951 	return pFile->AddEncH264VideoTrack(timeScale,
952 			 sampleDuration,
953 			 width,
954 			 height,
955 			 srcAtom,
956 			 icPp);
957     }
958     catch (MP4Error* e) {
959       PRINT_ERROR(e);
960       delete e;
961     }
962   }
963   return MP4_INVALID_TRACK_ID;
964 }
965 
MP4AddH264SequenceParameterSet(MP4FileHandle hFile,MP4TrackId trackId,const uint8_t * pSequence,uint16_t sequenceLen)966 extern "C" void MP4AddH264SequenceParameterSet (MP4FileHandle hFile,
967 						MP4TrackId trackId,
968 						const uint8_t *pSequence,
969 						uint16_t sequenceLen)
970 {
971   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
972     try {
973       MP4File *pFile = (MP4File *)hFile;
974 
975       pFile->AddH264SequenceParameterSet(trackId,
976 					 pSequence,
977 					 sequenceLen);
978       return;
979     }
980     catch (MP4Error* e) {
981       PRINT_ERROR(e);
982       delete e;
983     }
984   }
985     return;
986 }
MP4AddH264PictureParameterSet(MP4FileHandle hFile,MP4TrackId trackId,const uint8_t * pPict,uint16_t pictLen)987 extern "C" void MP4AddH264PictureParameterSet (MP4FileHandle hFile,
988 					       MP4TrackId trackId,
989 					       const uint8_t *pPict,
990 					       uint16_t pictLen)
991 {
992   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
993     try {
994       MP4File *pFile = (MP4File *)hFile;
995 
996       pFile->AddH264PictureParameterSet(trackId,
997 					pPict,
998 					pictLen);
999       return;
1000     }
1001     catch (MP4Error* e) {
1002       PRINT_ERROR(e);
1003       delete e;
1004     }
1005   }
1006     return;
1007 }
1008 
MP4AddH263VideoTrack(MP4FileHandle hFile,u_int32_t timeScale,MP4Duration sampleDuration,u_int16_t width,u_int16_t height,u_int8_t h263Level,u_int8_t h263Profile,u_int32_t avgBitrate,u_int32_t maxBitrate)1009 extern "C" MP4TrackId MP4AddH263VideoTrack(
1010 		MP4FileHandle hFile,
1011 		u_int32_t timeScale,
1012 		MP4Duration sampleDuration,
1013 		u_int16_t width,
1014 		u_int16_t height,
1015 		u_int8_t h263Level,
1016 		u_int8_t h263Profile,
1017 		u_int32_t avgBitrate,
1018 		u_int32_t maxBitrate)
1019 {
1020 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1021 		try {
1022 			return ((MP4File*)hFile)->
1023 				AddH263VideoTrack(timeScale, sampleDuration, width, height, h263Level, h263Profile, avgBitrate, maxBitrate);
1024 		}
1025 		catch (MP4Error* e) {
1026 			PRINT_ERROR(e);
1027 			delete e;
1028 		}
1029 	}
1030 
1031 	return MP4_INVALID_TRACK_ID;
1032 }
1033 
MP4SetH263Vendor(MP4FileHandle hFile,MP4TrackId trackId,u_int32_t vendor)1034 extern "C" void MP4SetH263Vendor(
1035 		MP4FileHandle hFile,
1036 		MP4TrackId trackId,
1037 		u_int32_t vendor)
1038 {
1039 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1040 		try {
1041 			((MP4File*)hFile)->
1042 				SetH263Vendor(trackId, vendor);
1043 		}
1044 		catch (MP4Error* e) {
1045 			PRINT_ERROR(e);
1046 			delete e;
1047 		}
1048 	}
1049 }
1050 
MP4SetH263DecoderVersion(MP4FileHandle hFile,MP4TrackId trackId,u_int8_t decoderVersion)1051 extern "C" void MP4SetH263DecoderVersion(
1052 		MP4FileHandle hFile,
1053 		MP4TrackId trackId,
1054 		u_int8_t decoderVersion)
1055 {
1056 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1057 
1058 		try {
1059 			((MP4File*)hFile)->
1060 				SetH263DecoderVersion(trackId, decoderVersion);
1061 		}
1062 		catch (MP4Error* e) {
1063 			PRINT_ERROR(e);
1064 			delete e;
1065 		}
1066 	}
1067 }
1068 
MP4SetH263Bitrates(MP4FileHandle hFile,MP4TrackId trackId,u_int32_t avgBitrate,u_int32_t maxBitrate)1069 extern "C" void MP4SetH263Bitrates(
1070 		MP4FileHandle hFile,
1071 		MP4TrackId trackId,
1072 		u_int32_t avgBitrate,
1073 		u_int32_t maxBitrate)
1074 {
1075 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1076 
1077 		try {
1078 			((MP4File*)hFile)->
1079 				SetH263Bitrates(trackId, avgBitrate, maxBitrate);
1080 		}
1081 		catch (MP4Error* e) {
1082 			PRINT_ERROR(e);
1083 			delete e;
1084 		}
1085 	}
1086 }
1087 
MP4AddHintTrack(MP4FileHandle hFile,MP4TrackId refTrackId)1088 extern "C" MP4TrackId MP4AddHintTrack(
1089 	MP4FileHandle hFile, MP4TrackId refTrackId)
1090 {
1091 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1092 		try {
1093 			return ((MP4File*)hFile)->AddHintTrack(refTrackId);
1094 		}
1095 		catch (MP4Error* e) {
1096 			PRINT_ERROR(e);
1097 			delete e;
1098 		}
1099 	}
1100 	return MP4_INVALID_TRACK_ID;
1101 }
1102 
MP4AddTextTrack(MP4FileHandle hFile,MP4TrackId refTrackId)1103 extern "C" MP4TrackId MP4AddTextTrack(
1104 	MP4FileHandle hFile, MP4TrackId refTrackId)
1105 {
1106 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1107 		try {
1108 			return ((MP4File*)hFile)->AddTextTrack(refTrackId);
1109 		}
1110 		catch (MP4Error* e) {
1111 			PRINT_ERROR(e);
1112 			delete e;
1113 		}
1114 	}
1115 	return MP4_INVALID_TRACK_ID;
1116 }
1117 
MP4AddChapterTextTrack(MP4FileHandle hFile,MP4TrackId refTrackId)1118 extern "C" MP4TrackId MP4AddChapterTextTrack(
1119 	MP4FileHandle hFile, MP4TrackId refTrackId)
1120 {
1121 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1122 		try {
1123 			return ((MP4File*)hFile)->AddChapterTextTrack(refTrackId);
1124 		}
1125 		catch (MP4Error* e) {
1126 			PRINT_ERROR(e);
1127 			delete e;
1128 		}
1129 	}
1130 	return MP4_INVALID_TRACK_ID;
1131 }
1132 
1133 
MP4CloneTrack(MP4FileHandle srcFile,MP4TrackId srcTrackId,MP4FileHandle dstFile,MP4TrackId dstHintTrackReferenceTrack)1134 extern "C" MP4TrackId MP4CloneTrack (MP4FileHandle srcFile,
1135 				     MP4TrackId srcTrackId,
1136 				     MP4FileHandle dstFile,
1137 				     MP4TrackId dstHintTrackReferenceTrack)
1138 {
1139   MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
1140 
1141   if (dstFile == NULL) {
1142     dstFile = srcFile;
1143   }
1144 
1145   const char* trackType =
1146     MP4GetTrackType(srcFile, srcTrackId);
1147 
1148   if (!trackType) {
1149     return dstTrackId;
1150   }
1151 
1152   const char *media_data_name =
1153     MP4GetTrackMediaDataName(srcFile, srcTrackId);
1154   if (media_data_name == NULL) return dstTrackId;
1155 
1156   if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
1157     if (ATOMID(media_data_name) == ATOMID("mp4v")) {
1158       MP4SetVideoProfileLevel(dstFile,
1159 			      MP4GetVideoProfileLevel(srcFile));
1160       dstTrackId = MP4AddVideoTrack(
1161 				    dstFile,
1162 				    MP4GetTrackTimeScale(srcFile,
1163 							 srcTrackId),
1164 				    MP4GetTrackFixedSampleDuration(srcFile,
1165 								   srcTrackId),
1166 				    MP4GetTrackVideoWidth(srcFile,
1167 							  srcTrackId),
1168 				    MP4GetTrackVideoHeight(srcFile,
1169 							   srcTrackId),
1170 				    MP4GetTrackEsdsObjectTypeId(srcFile,
1171 								srcTrackId));
1172     } else if (ATOMID(media_data_name) == ATOMID("avc1")) {
1173       uint8_t AVCProfileIndication;
1174       uint8_t profile_compat;
1175       uint8_t AVCLevelIndication;
1176       uint32_t sampleLenFieldSizeMinusOne;
1177       uint64_t temp;
1178 
1179       if (MP4GetTrackH264ProfileLevel(srcFile, srcTrackId,
1180 				      &AVCProfileIndication,
1181 				      &AVCLevelIndication) == false) {
1182 	return dstTrackId;
1183       }
1184       if (MP4GetTrackH264LengthSize(srcFile, srcTrackId,
1185 				    &sampleLenFieldSizeMinusOne) == false) {
1186 	return dstTrackId;
1187       }
1188       sampleLenFieldSizeMinusOne--;
1189       if (MP4GetTrackIntegerProperty(srcFile, srcTrackId,
1190 				     "mdia.minf.stbl.stsd.*[0].avcC.profile_compatibility",
1191 				     &temp) == false) return dstTrackId;
1192       profile_compat = temp & 0xff;
1193 
1194       dstTrackId = MP4AddH264VideoTrack(dstFile,
1195 					MP4GetTrackTimeScale(srcFile,
1196 							     srcTrackId),
1197 					MP4GetTrackFixedSampleDuration(srcFile,
1198 								       srcTrackId),
1199 					MP4GetTrackVideoWidth(srcFile,
1200 							      srcTrackId),
1201 					MP4GetTrackVideoHeight(srcFile,
1202 							       srcTrackId),
1203 					AVCProfileIndication,
1204 					profile_compat,
1205 					AVCLevelIndication,
1206 					sampleLenFieldSizeMinusOne);
1207         uint8_t **seqheader, **pictheader;
1208 	uint32_t *pictheadersize, *seqheadersize;
1209 	uint32_t ix;
1210 	MP4GetTrackH264SeqPictHeaders(srcFile, srcTrackId,
1211 				      &seqheader, &seqheadersize,
1212 				      &pictheader, &pictheadersize);
1213 	for (ix = 0; seqheadersize[ix] != 0; ix++) {
1214 	  MP4AddH264SequenceParameterSet(dstFile, dstTrackId,
1215 					 seqheader[ix], seqheadersize[ix]);
1216 	  free(seqheader[ix]);
1217 	}
1218 	free(seqheader);
1219 	free(seqheadersize);
1220 	for (ix = 0; pictheadersize[ix] != 0; ix++) {
1221 	  MP4AddH264PictureParameterSet(dstFile, dstTrackId,
1222 					pictheader[ix], pictheadersize[ix]);
1223 	  free(pictheader[ix]);
1224 	}
1225 	free(pictheader);
1226 	free(pictheadersize);
1227     } else
1228       return dstTrackId;
1229   } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
1230     if (ATOMID(media_data_name) != ATOMID("mp4a")) return dstTrackId;
1231     MP4SetAudioProfileLevel(dstFile,
1232 			    MP4GetAudioProfileLevel(srcFile));
1233     dstTrackId = MP4AddAudioTrack(
1234 				  dstFile,
1235 				  MP4GetTrackTimeScale(srcFile, srcTrackId),
1236 				  MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
1237 				  MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId));
1238 
1239   } else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
1240     dstTrackId = MP4AddODTrack(dstFile);
1241 
1242   } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
1243     dstTrackId = MP4AddSceneTrack(dstFile);
1244 
1245   } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
1246     if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) {
1247       dstTrackId = MP4_INVALID_TRACK_ID;
1248     } else {
1249       dstTrackId = MP4AddHintTrack(
1250 				   dstFile,
1251 				   dstHintTrackReferenceTrack);
1252     }
1253 
1254   } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
1255     dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
1256 
1257   } else {
1258     dstTrackId = MP4AddTrack(dstFile, trackType);
1259   }
1260 
1261   if (dstTrackId == MP4_INVALID_TRACK_ID) {
1262     return dstTrackId;
1263   }
1264 
1265   MP4SetTrackTimeScale(
1266 		       dstFile,
1267 		       dstTrackId,
1268 		       MP4GetTrackTimeScale(srcFile, srcTrackId));
1269 
1270   if (MP4_IS_AUDIO_TRACK_TYPE(trackType)
1271       || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
1272     // copy track ES configuration
1273     u_int8_t* pConfig = NULL;
1274     u_int32_t configSize = 0;
1275     uint32_t verb = MP4GetVerbosity(srcFile);
1276     MP4SetVerbosity(srcFile, verb & ~(MP4_DETAILS_ERROR));
1277     bool haveEs = MP4GetTrackESConfiguration(srcFile,
1278 					     srcTrackId,
1279 					     &pConfig,
1280 					     &configSize);
1281     MP4SetVerbosity(srcFile, verb);
1282     if (haveEs &&
1283 	pConfig != NULL && configSize != 0) {
1284       if (!MP4SetTrackESConfiguration(
1285 				      dstFile,
1286 				      dstTrackId,
1287 				      pConfig,
1288 				      configSize)) {
1289 	free(pConfig);
1290 	MP4DeleteTrack(dstFile, dstTrackId);
1291 	return MP4_INVALID_TRACK_ID;
1292       }
1293 
1294       free(pConfig);
1295     }
1296   }
1297 
1298   if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
1299     // probably not exactly what is wanted
1300     // but caller can adjust later to fit their desires
1301 
1302     char* payloadName = NULL;
1303     char *encodingParms = NULL;
1304     u_int8_t payloadNumber;
1305     u_int16_t maxPayloadSize;
1306 
1307     if (MP4GetHintTrackRtpPayload(
1308 			      srcFile,
1309 			      srcTrackId,
1310 			      &payloadName,
1311 			      &payloadNumber,
1312 			      &maxPayloadSize,
1313 			      &encodingParms)) {
1314 
1315       if (MP4SetHintTrackRtpPayload(
1316 				    dstFile,
1317 				    dstTrackId,
1318 				    payloadName,
1319 				    &payloadNumber,
1320 				    maxPayloadSize,
1321 				    encodingParms) == false) {
1322 	MP4DeleteTrack(dstFile, dstTrackId);
1323 	return MP4_INVALID_TRACK_ID;
1324       }
1325     }
1326 #if 0
1327     MP4SetHintTrackSdp(
1328 		       dstFile,
1329 		       dstTrackId,
1330 		       MP4GetHintTrackSdp(srcFile, srcTrackId));
1331 #endif
1332   }
1333 
1334   return dstTrackId;
1335 }
1336 
1337 // Given a track, make an encrypted clone of it in the dest. file
MP4EncAndCloneTrack(MP4FileHandle srcFile,MP4TrackId srcTrackId,mp4v2_ismacrypParams * icPp,MP4FileHandle dstFile,MP4TrackId dstHintTrackReferenceTrack)1338 extern "C" MP4TrackId MP4EncAndCloneTrack(MP4FileHandle srcFile,
1339                                           MP4TrackId srcTrackId,
1340                                           mp4v2_ismacrypParams *icPp,
1341 					  MP4FileHandle dstFile,
1342 					  MP4TrackId dstHintTrackReferenceTrack
1343                                           )
1344 {
1345   const char *oFormat;
1346 
1347   MP4TrackId dstTrackId = MP4_INVALID_TRACK_ID;
1348 
1349   if (dstFile == NULL) {
1350     dstFile = srcFile;
1351   }
1352 
1353   const char* trackType = MP4GetTrackType(srcFile, srcTrackId);
1354 
1355   if (!trackType) {
1356     return dstTrackId;
1357   }
1358 
1359   if (MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
1360 
1361     // test source file format for avc1
1362     oFormat = MP4GetTrackMediaDataName(srcFile, srcTrackId);
1363     if (!strcasecmp(oFormat, "avc1"))
1364     {
1365         dstTrackId = MP4AddEncH264VideoTrack(dstFile,
1366 				MP4GetTrackTimeScale(srcFile, srcTrackId),
1367 				MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
1368 				MP4GetTrackVideoWidth(srcFile, srcTrackId),
1369 				MP4GetTrackVideoHeight(srcFile, srcTrackId),
1370 				srcFile,
1371 				srcTrackId,
1372 				icPp
1373                      );
1374     }
1375     else
1376     {
1377     MP4SetVideoProfileLevel(dstFile, MP4GetVideoProfileLevel(srcFile));
1378     dstTrackId = MP4AddEncVideoTrack(dstFile,
1379 				     MP4GetTrackTimeScale(srcFile, srcTrackId),
1380 				MP4GetTrackFixedSampleDuration(srcFile, srcTrackId),
1381 				     MP4GetTrackVideoWidth(srcFile, srcTrackId),
1382 				     MP4GetTrackVideoHeight(srcFile, srcTrackId),
1383                                      icPp,
1384 				MP4GetTrackEsdsObjectTypeId(srcFile, srcTrackId),
1385 				oFormat
1386                                      );
1387     }
1388 
1389   } else if (MP4_IS_AUDIO_TRACK_TYPE(trackType)) {
1390     MP4SetAudioProfileLevel(dstFile, MP4GetAudioProfileLevel(srcFile));
1391     dstTrackId = MP4AddEncAudioTrack(dstFile,
1392 				     MP4GetTrackTimeScale(srcFile, srcTrackId),
1393 				     MP4GetTrackFixedSampleDuration(srcFile,
1394 								    srcTrackId),
1395                                      icPp,
1396 				     MP4GetTrackEsdsObjectTypeId(srcFile,
1397 								 srcTrackId)
1398                                      );
1399 
1400   } else if (MP4_IS_OD_TRACK_TYPE(trackType)) {
1401     dstTrackId = MP4AddODTrack(dstFile);
1402 
1403   } else if (MP4_IS_SCENE_TRACK_TYPE(trackType)) {
1404     dstTrackId = MP4AddSceneTrack(dstFile);
1405 
1406   } else if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
1407      if (dstHintTrackReferenceTrack == MP4_INVALID_TRACK_ID) {
1408          dstTrackId = MP4_INVALID_TRACK_ID;
1409     } else {
1410          dstTrackId = MP4AddHintTrack(dstFile,
1411 				 MP4GetHintTrackReferenceTrackId(srcFile,
1412 								 srcTrackId));
1413     }
1414   } else if (MP4_IS_SYSTEMS_TRACK_TYPE(trackType)) {
1415     dstTrackId = MP4AddSystemsTrack(dstFile, trackType);
1416 
1417   } else {
1418     dstTrackId = MP4AddTrack(dstFile, trackType);
1419   }
1420 
1421   if (dstTrackId == MP4_INVALID_TRACK_ID) {
1422     return dstTrackId;
1423   }
1424 
1425   MP4SetTrackTimeScale(dstFile,
1426 		       dstTrackId,
1427 		       MP4GetTrackTimeScale(srcFile, srcTrackId));
1428 
1429   if (MP4_IS_AUDIO_TRACK_TYPE(trackType)
1430    || MP4_IS_VIDEO_TRACK_TYPE(trackType)) {
1431     // copy track ES configuration
1432     u_int8_t* pConfig = NULL;
1433     u_int32_t configSize = 0;
1434     if (MP4GetTrackESConfiguration(srcFile, srcTrackId,
1435 				   &pConfig, &configSize)) {
1436 
1437       if (pConfig != NULL) {
1438 	MP4SetTrackESConfiguration(dstFile, dstTrackId,
1439 				   pConfig, configSize);
1440       }
1441     }
1442     if (pConfig != NULL)
1443       free(pConfig);
1444     }
1445 
1446   // Bill's change to MP4CloneTrack
1447   if (MP4_IS_HINT_TRACK_TYPE(trackType)) {
1448     // probably not exactly what is wanted
1449     // but caller can adjust later to fit their desires
1450 
1451     char* payloadName = NULL;
1452     char *encodingParms = NULL;
1453     u_int8_t payloadNumber;
1454     u_int16_t maxPayloadSize;
1455 
1456     if (MP4GetHintTrackRtpPayload(
1457 				  srcFile,
1458 				  srcTrackId,
1459 				  &payloadName,
1460 				  &payloadNumber,
1461 				  &maxPayloadSize,
1462 				  &encodingParms)) {
1463 
1464       (void)MP4SetHintTrackRtpPayload(
1465 		                 dstFile,
1466 			         dstTrackId,
1467 			         payloadName,
1468 			         &payloadNumber,
1469 			         maxPayloadSize,
1470 			         encodingParms);
1471     }
1472 #if 0
1473       MP4SetHintTrackSdp(
1474                          dstFile,
1475                          dstTrackId,
1476                          MP4GetHintTrackSdp(srcFile, srcTrackId));
1477 #endif
1478    }
1479 
1480   return dstTrackId;
1481 }
1482 
MP4CopyTrack(MP4FileHandle srcFile,MP4TrackId srcTrackId,MP4FileHandle dstFile,bool applyEdits,MP4TrackId dstHintTrackReferenceTrack)1483 extern "C" MP4TrackId MP4CopyTrack(MP4FileHandle srcFile,
1484 				   MP4TrackId srcTrackId,
1485 				   MP4FileHandle dstFile,
1486 				   bool applyEdits,
1487 				   MP4TrackId dstHintTrackReferenceTrack)
1488 {
1489   bool copySamples = true;	// LATER allow false => reference samples
1490 
1491   MP4TrackId dstTrackId =
1492     MP4CloneTrack(srcFile, srcTrackId, dstFile, dstHintTrackReferenceTrack);
1493 
1494   if (dstTrackId == MP4_INVALID_TRACK_ID) {
1495     return dstTrackId;
1496   }
1497 
1498   bool viaEdits =
1499     applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
1500 
1501   MP4SampleId sampleId = 0;
1502   MP4SampleId numSamples =
1503     MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
1504 
1505   MP4Timestamp when = 0;
1506   MP4Duration editsDuration =
1507     MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
1508 
1509   while (true) {
1510     MP4Duration sampleDuration = MP4_INVALID_DURATION;
1511 
1512     if (viaEdits) {
1513       sampleId = MP4GetSampleIdFromEditTime(
1514 					    srcFile,
1515 					    srcTrackId,
1516 					    when,
1517 					    NULL,
1518 					    &sampleDuration);
1519 
1520       // in theory, this shouldn't happen
1521       if (sampleId == MP4_INVALID_SAMPLE_ID) {
1522 	MP4DeleteTrack(dstFile, dstTrackId);
1523 	return MP4_INVALID_TRACK_ID;
1524       }
1525 
1526       when += sampleDuration;
1527 
1528       if (when >= editsDuration) {
1529 	break;
1530       }
1531     } else {
1532       sampleId++;
1533       if (sampleId > numSamples) {
1534 	break;
1535       }
1536     }
1537 
1538     bool rc = false;
1539 
1540     if (copySamples) {
1541       rc = MP4CopySample(
1542 			 srcFile,
1543 			 srcTrackId,
1544 			 sampleId,
1545 			 dstFile,
1546 			 dstTrackId,
1547 			 sampleDuration);
1548 
1549     } else {
1550       rc = MP4ReferenceSample(
1551 			      srcFile,
1552 			      srcTrackId,
1553 			      sampleId,
1554 			      dstFile,
1555 			      dstTrackId,
1556 			      sampleDuration);
1557     }
1558 
1559     if (!rc) {
1560       MP4DeleteTrack(dstFile, dstTrackId);
1561       return MP4_INVALID_TRACK_ID;
1562     }
1563   }
1564 
1565   return dstTrackId;
1566 }
1567 
1568 // Given a source track in a source file, make an encrypted copy of
1569 // the track in the destination file, including sample encryption
MP4EncAndCopyTrack(MP4FileHandle srcFile,MP4TrackId srcTrackId,mp4v2_ismacrypParams * icPp,encryptFunc_t encfcnp,u_int32_t encfcnparam1,MP4FileHandle dstFile,bool applyEdits,MP4TrackId dstHintTrackReferenceTrack)1570 extern "C" MP4TrackId MP4EncAndCopyTrack(MP4FileHandle srcFile,
1571 					 MP4TrackId srcTrackId,
1572                                          mp4v2_ismacrypParams *icPp,
1573                                          encryptFunc_t encfcnp,
1574                                          u_int32_t encfcnparam1,
1575 					 MP4FileHandle dstFile,
1576 					 bool applyEdits,
1577 					 MP4TrackId dstHintTrackReferenceTrack
1578                                          )
1579 {
1580   bool copySamples = true;	// LATER allow false => reference samples
1581 
1582   MP4TrackId dstTrackId =
1583      MP4EncAndCloneTrack(srcFile, srcTrackId,
1584                         icPp,
1585                         dstFile, dstHintTrackReferenceTrack);
1586 
1587   if (dstTrackId == MP4_INVALID_TRACK_ID) {
1588     return dstTrackId;
1589   }
1590 
1591   bool viaEdits =
1592     applyEdits && MP4GetTrackNumberOfEdits(srcFile, srcTrackId);
1593 
1594   MP4SampleId sampleId = 0;
1595   MP4SampleId numSamples =
1596     MP4GetTrackNumberOfSamples(srcFile, srcTrackId);
1597 
1598   MP4Timestamp when = 0;
1599   MP4Duration editsDuration =
1600     MP4GetTrackEditTotalDuration(srcFile, srcTrackId);
1601 
1602   while (true) {
1603     MP4Duration sampleDuration = MP4_INVALID_DURATION;
1604 
1605     if (viaEdits) {
1606       sampleId = MP4GetSampleIdFromEditTime(srcFile,
1607 					    srcTrackId,
1608 					    when,
1609 					    NULL,
1610 					    &sampleDuration);
1611 
1612       // in theory, this shouldn't happen
1613       if (sampleId == MP4_INVALID_SAMPLE_ID) {
1614 	MP4DeleteTrack(dstFile, dstTrackId);
1615 	return MP4_INVALID_TRACK_ID;
1616       }
1617 
1618       when += sampleDuration;
1619 
1620       if (when >= editsDuration) {
1621 	break;
1622       }
1623     } else {
1624       sampleId++;
1625       if (sampleId > numSamples) {
1626 	break;
1627       }
1628     }
1629 
1630     bool rc = false;
1631 
1632     if (copySamples) {
1633       // encrypt and copy
1634       rc = MP4EncAndCopySample(srcFile,
1635 			 srcTrackId,
1636 			 sampleId,
1637 			 encfcnp,
1638                          encfcnparam1,
1639 			 dstFile,
1640 			 dstTrackId,
1641 			 sampleDuration);
1642 
1643     } else {
1644       // not sure what these are - encrypt?
1645       rc = MP4ReferenceSample(srcFile,
1646 			      srcTrackId,
1647 			      sampleId,
1648 			      dstFile,
1649 			      dstTrackId,
1650 			      sampleDuration);
1651     }
1652 
1653     if (!rc) {
1654       MP4DeleteTrack(dstFile, dstTrackId);
1655       return MP4_INVALID_TRACK_ID;
1656     }
1657   }
1658 
1659   return dstTrackId;
1660 }
1661 
MP4DeleteTrack(MP4FileHandle hFile,MP4TrackId trackId)1662 extern "C" void MP4DeleteTrack(
1663 	MP4FileHandle hFile,
1664 	MP4TrackId trackId)
1665 {
1666 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1667 		try {
1668 			((MP4File*)hFile)->DeleteTrack(trackId);
1669 			return ;
1670 		}
1671 		catch (MP4Error* e) {
1672 			PRINT_ERROR(e);
1673 			delete e;
1674 		}
1675 	}
1676 	return;
1677 }
1678 
MP4GetNumberOfTracks(MP4FileHandle hFile,const char * type,u_int8_t subType)1679 extern "C" u_int32_t MP4GetNumberOfTracks(
1680 	MP4FileHandle hFile,
1681 	const char* type,
1682 	u_int8_t subType)
1683 {
1684 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1685 		try {
1686 			return ((MP4File*)hFile)->GetNumberOfTracks(type, subType);
1687 		}
1688 		catch (MP4Error* e) {
1689 			PRINT_ERROR(e);
1690 			delete e;
1691 		}
1692 	}
1693 	return 0;
1694 }
1695 
MP4FindTrackId(MP4FileHandle hFile,u_int16_t index,const char * type,u_int8_t subType)1696 extern "C" MP4TrackId MP4FindTrackId(
1697 	MP4FileHandle hFile,
1698 	u_int16_t index,
1699 	const char* type,
1700 	u_int8_t subType)
1701 {
1702 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1703 		try {
1704 			return ((MP4File*)hFile)->FindTrackId(index, type, subType);
1705 		}
1706 		catch (MP4Error* e) {
1707 			PRINT_ERROR(e);
1708 			delete e;
1709 		}
1710 	}
1711 	return MP4_INVALID_TRACK_ID;
1712 }
1713 
MP4FindTrackIndex(MP4FileHandle hFile,MP4TrackId trackId)1714 extern "C" u_int16_t MP4FindTrackIndex(
1715 	MP4FileHandle hFile, MP4TrackId trackId)
1716 {
1717 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1718 		try {
1719 			return ((MP4File*)hFile)->FindTrackIndex(trackId);
1720 		}
1721 		catch (MP4Error* e) {
1722 			PRINT_ERROR(e);
1723 			delete e;
1724 		}
1725 	}
1726 	return (u_int16_t)-1;
1727 }
1728 
1729 /* specific track properties */
1730 
MP4GetTrackType(MP4FileHandle hFile,MP4TrackId trackId)1731 extern "C" const char* MP4GetTrackType(
1732 	MP4FileHandle hFile, MP4TrackId trackId)
1733 {
1734 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1735 		try {
1736 			return ((MP4File*)hFile)->GetTrackType(trackId);
1737 		}
1738 		catch (MP4Error* e) {
1739 			PRINT_ERROR(e);
1740 			delete e;
1741 		}
1742 	}
1743 	return NULL;
1744 }
MP4GetTrackMediaDataName(MP4FileHandle hFile,MP4TrackId trackId)1745 extern "C" const char* MP4GetTrackMediaDataName(
1746 	MP4FileHandle hFile, MP4TrackId trackId)
1747 {
1748 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1749 		try {
1750 			return ((MP4File*)hFile)->GetTrackMediaDataName(trackId);
1751 		}
1752 		catch (MP4Error* e) {
1753 			PRINT_ERROR(e);
1754 			delete e;
1755 		}
1756 	}
1757 	return NULL;
1758 }
1759 
MP4GetTrackMediaDataOriginalFormat(MP4FileHandle hFile,MP4TrackId trackId,char * originalFormat,u_int32_t buflen)1760 extern "C" bool MP4GetTrackMediaDataOriginalFormat(
1761 	MP4FileHandle hFile, MP4TrackId trackId, char *originalFormat,
1762 	u_int32_t buflen)
1763 {
1764 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1765 		try {
1766 
1767 			return ((MP4File*)hFile)->GetTrackMediaDataOriginalFormat(trackId,
1768 				originalFormat, buflen);
1769 		}
1770 		catch (MP4Error* e) {
1771 			PRINT_ERROR(e);
1772 			delete e;
1773 		}
1774 	}
1775 	return false;
1776 }
1777 
MP4GetTrackDuration(MP4FileHandle hFile,MP4TrackId trackId)1778 extern "C" MP4Duration MP4GetTrackDuration(
1779 	MP4FileHandle hFile, MP4TrackId trackId)
1780 {
1781 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1782 		try {
1783 			return ((MP4File*)hFile)->GetTrackDuration(trackId);
1784 		}
1785 		catch (MP4Error* e) {
1786 			PRINT_ERROR(e);
1787 			delete e;
1788 		}
1789 	}
1790 	return MP4_INVALID_DURATION;
1791 }
1792 
MP4GetTrackTimeScale(MP4FileHandle hFile,MP4TrackId trackId)1793 extern "C" u_int32_t MP4GetTrackTimeScale(
1794 	MP4FileHandle hFile, MP4TrackId trackId)
1795 {
1796 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1797 		try {
1798 			return ((MP4File*)hFile)->GetTrackTimeScale(trackId);
1799 		}
1800 		catch (MP4Error* e) {
1801 			PRINT_ERROR(e);
1802 			delete e;
1803 		}
1804 	}
1805 	return 0;
1806 }
1807 
MP4SetTrackTimeScale(MP4FileHandle hFile,MP4TrackId trackId,u_int32_t value)1808 extern "C" void MP4SetTrackTimeScale(
1809 	MP4FileHandle hFile, MP4TrackId trackId, u_int32_t value)
1810 {
1811 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1812 		try {
1813 			((MP4File*)hFile)->SetTrackTimeScale(trackId, value);
1814 			return;
1815 		}
1816 		catch (MP4Error* e) {
1817 			PRINT_ERROR(e);
1818 			delete e;
1819 		}
1820 	}
1821 	return;
1822 }
1823 
MP4GetTrackAudioMpeg4Type(MP4FileHandle hFile,MP4TrackId trackId)1824 extern "C" u_int8_t MP4GetTrackAudioMpeg4Type(
1825 	MP4FileHandle hFile, MP4TrackId trackId)
1826 {
1827 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1828 		try {
1829 			return ((MP4File*)hFile)->GetTrackAudioMpeg4Type(trackId);
1830 		}
1831 		catch (MP4Error* e) {
1832 			PRINT_ERROR(e);
1833 			delete e;
1834 		}
1835 	}
1836 	return MP4_MPEG4_INVALID_AUDIO_TYPE;
1837 }
1838 
1839 
1840 
1841 // Replacement to MP4GetTrackVideoType and MP4GetTrackAudioType
1842 // Basically does the same thing but with a more self-explanatory name
MP4GetTrackEsdsObjectTypeId(MP4FileHandle hFile,MP4TrackId trackId)1843 extern "C" u_int8_t MP4GetTrackEsdsObjectTypeId(
1844      MP4FileHandle hFile, MP4TrackId trackId)
1845 {
1846   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1847     try {
1848 
1849       return ((MP4File*)hFile)->GetTrackEsdsObjectTypeId(trackId);
1850     }
1851     catch (MP4Error* e) {
1852       PRINT_ERROR(e);
1853       delete e;
1854     }
1855   }
1856   return MP4_INVALID_AUDIO_TYPE;
1857 }
1858 
MP4GetTrackFixedSampleDuration(MP4FileHandle hFile,MP4TrackId trackId)1859 extern "C" MP4Duration MP4GetTrackFixedSampleDuration(
1860 	MP4FileHandle hFile, MP4TrackId trackId)
1861 {
1862 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1863 		try {
1864 			return ((MP4File*)hFile)->GetTrackFixedSampleDuration(trackId);
1865 		}
1866 		catch (MP4Error* e) {
1867 			PRINT_ERROR(e);
1868 			delete e;
1869 		}
1870 	}
1871 	return MP4_INVALID_DURATION;
1872 }
1873 
MP4GetTrackBitRate(MP4FileHandle hFile,MP4TrackId trackId)1874 extern "C" u_int32_t MP4GetTrackBitRate(
1875 	MP4FileHandle hFile, MP4TrackId trackId)
1876 {
1877 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1878 	  MP4File *pFile = (MP4File *)hFile;
1879 		try {
1880 		  return pFile->GetTrackIntegerProperty(trackId,
1881 				"mdia.minf.stbl.stsd.*.esds.decConfigDescr.avgBitrate");
1882 		}
1883 		catch (MP4Error* e) {
1884 		  //PRINT_ERROR(e);  we don't really need to print this.
1885 			delete e;
1886 		}
1887 		// if we're here, we can't get the bitrate from above -
1888 		// lets calculate it
1889 		try {
1890 		  MP4Duration trackDur;
1891 		  trackDur = MP4GetTrackDuration(hFile, trackId);
1892 		  uint64_t msDuration =
1893 		    pFile->ConvertFromTrackDuration(trackId, trackDur,
1894 						    MP4_MSECS_TIME_SCALE);
1895 		  if (msDuration == 0) return 0;
1896 
1897 		  MP4Track *pTrack = pFile->GetTrack(trackId);
1898 		  uint64_t bytes = pTrack->GetTotalOfSampleSizes();
1899 		  bytes *= TO_U64(8 * 1000);
1900 		  bytes /= msDuration;
1901 		  return (uint32_t)bytes;
1902 		}
1903 		catch (MP4Error* e) {
1904 		  PRINT_ERROR(e); // print this one.
1905 			delete e;
1906 		}
1907 
1908 	}
1909 	return 0;
1910 }
1911 
MP4GetTrackESConfiguration(MP4FileHandle hFile,MP4TrackId trackId,u_int8_t ** ppConfig,u_int32_t * pConfigSize)1912 extern "C" bool MP4GetTrackESConfiguration(
1913 	MP4FileHandle hFile, MP4TrackId trackId,
1914 	u_int8_t** ppConfig, u_int32_t* pConfigSize)
1915 {
1916 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1917 		try {
1918 			((MP4File*)hFile)->GetTrackESConfiguration(
1919 				trackId, ppConfig, pConfigSize);
1920 			return true;
1921 		}
1922 		catch (MP4Error* e) {
1923 			PRINT_ERROR(e);
1924 			delete e;
1925 		}
1926 	}
1927 	*ppConfig = NULL;
1928 	*pConfigSize = 0;
1929 	return false;
1930 }
MP4GetTrackVideoMetadata(MP4FileHandle hFile,MP4TrackId trackId,u_int8_t ** ppConfig,u_int32_t * pConfigSize)1931 extern "C" bool MP4GetTrackVideoMetadata(
1932 	MP4FileHandle hFile, MP4TrackId trackId,
1933 	u_int8_t** ppConfig, u_int32_t* pConfigSize)
1934 {
1935 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1936 		try {
1937 			((MP4File*)hFile)->GetTrackVideoMetadata(
1938 				trackId, ppConfig, pConfigSize);
1939 			return true;
1940 		}
1941 		catch (MP4Error* e) {
1942 			PRINT_ERROR(e);
1943 			delete e;
1944 		}
1945 	}
1946 	*ppConfig = NULL;
1947 	*pConfigSize = 0;
1948 	return false;
1949 }
1950 
MP4SetTrackESConfiguration(MP4FileHandle hFile,MP4TrackId trackId,const u_int8_t * pConfig,u_int32_t configSize)1951 extern "C" bool MP4SetTrackESConfiguration(
1952 	MP4FileHandle hFile, MP4TrackId trackId,
1953 	const u_int8_t* pConfig, u_int32_t configSize)
1954 {
1955 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1956 		try {
1957 			((MP4File*)hFile)->SetTrackESConfiguration(
1958 				trackId, pConfig, configSize);
1959 			return true;
1960 		}
1961 		catch (MP4Error* e) {
1962 			PRINT_ERROR(e);
1963 			delete e;
1964 		}
1965 	}
1966 	return false;
1967 }
1968 
MP4GetTrackH264ProfileLevel(MP4FileHandle hFile,MP4TrackId trackId,uint8_t * pProfile,uint8_t * pLevel)1969 extern "C" bool MP4GetTrackH264ProfileLevel (MP4FileHandle hFile,
1970 					     MP4TrackId trackId,
1971 					     uint8_t *pProfile,
1972 					     uint8_t *pLevel)
1973 {
1974   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
1975     try {
1976       *pProfile =
1977 	((MP4File *)hFile)->GetTrackIntegerProperty(trackId,
1978 						    "mdia.minf.stbl.stsd.*[0].avcC.AVCProfileIndication");
1979       *pLevel =
1980 	((MP4File *)hFile)->GetTrackIntegerProperty(trackId,
1981 						    "mdia.minf.stbl.stsd.*[0].avcC.AVCLevelIndication");
1982 
1983       return true;
1984     }
1985     catch (MP4Error* e) {
1986       PRINT_ERROR(e);
1987       delete e;
1988     }
1989   }
1990   return false;
1991 }
MP4GetTrackH264SeqPictHeaders(MP4FileHandle hFile,MP4TrackId trackId,uint8_t *** pSeqHeader,uint32_t ** pSeqHeaderSize,uint8_t *** pPictHeader,uint32_t ** pPictHeaderSize)1992 extern "C" void MP4GetTrackH264SeqPictHeaders (MP4FileHandle hFile,
1993 					       MP4TrackId trackId,
1994 					       uint8_t ***pSeqHeader,
1995 					       uint32_t **pSeqHeaderSize,
1996 					       uint8_t ***pPictHeader,
1997 					       uint32_t **pPictHeaderSize)
1998 {
1999   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2000     try {
2001       ((MP4File*)hFile)->GetTrackH264SeqPictHeaders(trackId,
2002 						    pSeqHeader,
2003 						    pSeqHeaderSize,
2004 						    pPictHeader,
2005 						    pPictHeaderSize);
2006       return;
2007     }
2008     catch (MP4Error* e) {
2009       PRINT_ERROR(e);
2010       delete e;
2011     }
2012   }
2013   return;
2014 }
MP4GetTrackH264LengthSize(MP4FileHandle hFile,MP4TrackId trackId,uint32_t * pLength)2015 extern "C" bool MP4GetTrackH264LengthSize (MP4FileHandle hFile,
2016 					   MP4TrackId trackId,
2017 					   uint32_t *pLength)
2018 {
2019   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2020     try {
2021       *pLength = 1 +
2022 	((MP4File*) hFile)->GetTrackIntegerProperty(trackId,
2023 						   "mdia.minf.stbl.stsd.*[0].avcC.lengthSizeMinusOne");
2024       return true;
2025     }
2026     catch (MP4Error* e) {
2027       PRINT_ERROR(e);
2028       delete e;
2029     }
2030   }
2031   return false;
2032 }
2033 
MP4GetTrackNumberOfSamples(MP4FileHandle hFile,MP4TrackId trackId)2034 extern "C" MP4SampleId MP4GetTrackNumberOfSamples(
2035 	MP4FileHandle hFile, MP4TrackId trackId)
2036 {
2037 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2038 		try {
2039 			return ((MP4File*)hFile)->GetTrackNumberOfSamples(trackId);
2040 		}
2041 		catch (MP4Error* e) {
2042 			PRINT_ERROR(e);
2043 			delete e;
2044 		}
2045 	}
2046 	return 0;
2047 }
2048 
MP4GetTrackVideoWidth(MP4FileHandle hFile,MP4TrackId trackId)2049 extern "C" u_int16_t MP4GetTrackVideoWidth(
2050 	MP4FileHandle hFile, MP4TrackId trackId)
2051 {
2052 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2053 		try {
2054 		       return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
2055 				"mdia.minf.stbl.stsd.*.width");
2056 		}
2057 		catch (MP4Error* e) {
2058 			PRINT_ERROR(e);
2059 			delete e;
2060 		}
2061 	}
2062 	return 0;
2063 }
2064 
MP4GetTrackVideoHeight(MP4FileHandle hFile,MP4TrackId trackId)2065 extern "C" u_int16_t MP4GetTrackVideoHeight(
2066 	MP4FileHandle hFile, MP4TrackId trackId)
2067 {
2068 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2069 		try {
2070 			return ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
2071 				"mdia.minf.stbl.stsd.*.height");
2072 		}
2073 		catch (MP4Error* e) {
2074 			PRINT_ERROR(e);
2075 			delete e;
2076 		}
2077 	}
2078 	return 0;
2079 }
2080 
MP4GetTrackVideoFrameRate(MP4FileHandle hFile,MP4TrackId trackId)2081 extern "C" double MP4GetTrackVideoFrameRate(
2082 	MP4FileHandle hFile, MP4TrackId trackId)
2083 {
2084 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2085 		try {
2086 			return ((MP4File*)hFile)->GetTrackVideoFrameRate(trackId);
2087 		}
2088 		catch (MP4Error* e) {
2089 			PRINT_ERROR(e);
2090 			delete e;
2091 		}
2092 	}
2093 	return 0.0;
2094 }
2095 
MP4GetTrackAudioChannels(MP4FileHandle hFile,MP4TrackId trackId)2096 extern "C" int MP4GetTrackAudioChannels (MP4FileHandle hFile,
2097 					      MP4TrackId trackId)
2098 {
2099 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2100 		try {
2101 			return ((MP4File*)hFile)->GetTrackAudioChannels(trackId);
2102 		}
2103 		catch (MP4Error* e) {
2104 			PRINT_ERROR(e);
2105 			delete e;
2106 		}
2107 	}
2108 	return -1;
2109 }
2110 
2111 // returns true if the track is a media track encrypted according to ismacryp
MP4IsIsmaCrypMediaTrack(MP4FileHandle hFile,MP4TrackId trackId)2112 extern "C" bool MP4IsIsmaCrypMediaTrack(
2113 	MP4FileHandle hFile, MP4TrackId trackId)
2114 {
2115   bool retval = false;
2116   uint32_t verb = MP4GetVerbosity(hFile);
2117   MP4SetVerbosity(hFile, verb & ~(MP4_DETAILS_ERROR));
2118 
2119         if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2120                try {
2121 		 retval = ((MP4File*)hFile)->IsIsmaCrypMediaTrack(trackId);
2122 	       }
2123                catch (MP4Error* e) {
2124                        PRINT_ERROR(e);
2125                        delete e;
2126                }
2127         }
2128 	MP4SetVerbosity(hFile, verb);
2129         return retval;
2130 }
2131 
2132 
2133 /* generic track properties */
2134 
MP4HaveTrackAtom(MP4FileHandle hFile,MP4TrackId trackId,const char * atomName)2135 extern "C" bool MP4HaveTrackAtom (MP4FileHandle hFile,
2136 				  MP4TrackId trackId,
2137 				  const char *atomName)
2138 {
2139   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2140     try {
2141       return ((MP4File*)hFile)->FindTrackAtom(trackId, atomName) != NULL;
2142     }
2143     catch (MP4Error* e) {
2144       PRINT_ERROR(e);
2145       delete e;
2146     }
2147   }
2148   return false;
2149 }
2150 
MP4GetTrackIntegerProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,u_int64_t * retvalue)2151 extern "C" bool MP4GetTrackIntegerProperty (
2152 	MP4FileHandle hFile, MP4TrackId trackId,
2153 	const char* propName,
2154 	u_int64_t *retvalue)
2155 {
2156 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2157 		try {
2158 			*retvalue = ((MP4File*)hFile)->GetTrackIntegerProperty(trackId,
2159 				propName);
2160 			return true;
2161 		}
2162 		catch (MP4Error* e) {
2163 			PRINT_ERROR(e);
2164 			delete e;
2165 		}
2166 	}
2167 	return false;
2168 }
2169 
MP4GetTrackFloatProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,float * retvalue)2170 extern "C" bool MP4GetTrackFloatProperty(
2171 	MP4FileHandle hFile, MP4TrackId trackId,
2172 	const char* propName,
2173 	float *retvalue)
2174 {
2175 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2176 		try {
2177 			*retvalue = ((MP4File*)hFile)->GetTrackFloatProperty(trackId, propName);
2178 			return true;
2179 		}
2180 		catch (MP4Error* e) {
2181 			PRINT_ERROR(e);
2182 			delete e;
2183 		}
2184 	}
2185 	return false;
2186 }
2187 
MP4GetTrackStringProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,const char ** retvalue)2188 extern "C" bool MP4GetTrackStringProperty(
2189 	MP4FileHandle hFile, MP4TrackId trackId,
2190 	const char* propName,
2191 	const char **retvalue)
2192 {
2193 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2194 		try {
2195 			*retvalue = ((MP4File*)hFile)->GetTrackStringProperty(trackId, propName);
2196 			return true;
2197 		}
2198 		catch (MP4Error* e) {
2199 			PRINT_ERROR(e);
2200 			delete e;
2201 		}
2202 	}
2203 	return false;
2204 }
2205 
MP4GetTrackBytesProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,u_int8_t ** ppValue,u_int32_t * pValueSize)2206 extern "C" bool MP4GetTrackBytesProperty(
2207 	MP4FileHandle hFile, MP4TrackId trackId, const char* propName,
2208 	u_int8_t** ppValue, u_int32_t* pValueSize)
2209 {
2210 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2211 		try {
2212 			((MP4File*)hFile)->GetTrackBytesProperty(
2213 				trackId, propName, ppValue, pValueSize);
2214 			return true;
2215 		}
2216 		catch (MP4Error* e) {
2217 			PRINT_ERROR(e);
2218 			delete e;
2219 		}
2220 	}
2221 	*ppValue = NULL;
2222 	*pValueSize = 0;
2223 	return false;
2224 }
2225 
MP4SetTrackIntegerProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,int64_t value)2226 extern "C" bool MP4SetTrackIntegerProperty(
2227 	MP4FileHandle hFile, MP4TrackId trackId,
2228 	const char* propName, int64_t value)
2229 {
2230 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2231 		try {
2232 			((MP4File*)hFile)->SetTrackIntegerProperty(trackId,
2233 				propName, value);
2234 			return true;
2235 		}
2236 		catch (MP4Error* e) {
2237 			PRINT_ERROR(e);
2238 			delete e;
2239 		}
2240 	}
2241 	return false;
2242 }
2243 
MP4SetTrackFloatProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,float value)2244 extern "C" bool MP4SetTrackFloatProperty(
2245 	MP4FileHandle hFile, MP4TrackId trackId,
2246 	const char* propName, float value)
2247 {
2248 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2249 		try {
2250 			((MP4File*)hFile)->SetTrackFloatProperty(trackId, propName, value);
2251 			return true;
2252 		}
2253 		catch (MP4Error* e) {
2254 			PRINT_ERROR(e);
2255 			delete e;
2256 		}
2257 	}
2258 	return false;
2259 }
2260 
MP4SetTrackStringProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,const char * value)2261 extern "C" bool MP4SetTrackStringProperty(
2262 	MP4FileHandle hFile, MP4TrackId trackId,
2263 	const char* propName, const char* value)
2264 {
2265 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2266 		try {
2267 			((MP4File*)hFile)->SetTrackStringProperty(trackId, propName, value);
2268 			return true;
2269 		}
2270 		catch (MP4Error* e) {
2271 			PRINT_ERROR(e);
2272 			delete e;
2273 		}
2274 	}
2275 	return false;
2276 }
2277 
MP4SetTrackBytesProperty(MP4FileHandle hFile,MP4TrackId trackId,const char * propName,const u_int8_t * pValue,u_int32_t valueSize)2278 extern "C" bool MP4SetTrackBytesProperty(
2279 	MP4FileHandle hFile, MP4TrackId trackId,
2280 	const char* propName, const u_int8_t* pValue, u_int32_t valueSize)
2281 {
2282 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2283 		try {
2284 			((MP4File*)hFile)->SetTrackBytesProperty(
2285 				trackId, propName, pValue, valueSize);
2286 			return true;
2287 		}
2288 		catch (MP4Error* e) {
2289 			PRINT_ERROR(e);
2290 			delete e;
2291 		}
2292 	}
2293 	return false;
2294 }
2295 
2296 /* sample operations */
2297 
MP4ReadSample(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId,u_int8_t ** ppBytes,u_int32_t * pNumBytes,MP4Timestamp * pStartTime,MP4Duration * pDuration,MP4Duration * pRenderingOffset,bool * pIsSyncSample)2298 extern "C" bool MP4ReadSample(
2299 	/* input parameters */
2300 	MP4FileHandle hFile,
2301 	MP4TrackId trackId,
2302 	MP4SampleId sampleId,
2303 	/* output parameters */
2304 	u_int8_t** ppBytes,
2305 	u_int32_t* pNumBytes,
2306 	MP4Timestamp* pStartTime,
2307 	MP4Duration* pDuration,
2308 	MP4Duration* pRenderingOffset,
2309 	bool* pIsSyncSample)
2310 {
2311 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2312 		try {
2313 			((MP4File*)hFile)->ReadSample(
2314 				trackId,
2315 				sampleId,
2316 				ppBytes,
2317 				pNumBytes,
2318 				pStartTime,
2319 				pDuration,
2320 				pRenderingOffset,
2321 				pIsSyncSample);
2322 			return true;
2323 		}
2324 		catch (MP4Error* e) {
2325 			PRINT_ERROR(e);
2326 			delete e;
2327 		}
2328 	}
2329 	*pNumBytes = 0;
2330 	return false;
2331 }
2332 
MP4ReadSampleFromTime(MP4FileHandle hFile,MP4TrackId trackId,MP4Timestamp when,u_int8_t ** ppBytes,u_int32_t * pNumBytes,MP4Timestamp * pStartTime,MP4Duration * pDuration,MP4Duration * pRenderingOffset,bool * pIsSyncSample)2333 extern "C" bool MP4ReadSampleFromTime(
2334 	/* input parameters */
2335 	MP4FileHandle hFile,
2336 	MP4TrackId trackId,
2337 	MP4Timestamp when,
2338 	/* output parameters */
2339 	u_int8_t** ppBytes,
2340 	u_int32_t* pNumBytes,
2341 	MP4Timestamp* pStartTime,
2342 	MP4Duration* pDuration,
2343 	MP4Duration* pRenderingOffset,
2344 	bool* pIsSyncSample)
2345 {
2346 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2347 		try {
2348 			MP4SampleId sampleId =
2349 				((MP4File*)hFile)->GetSampleIdFromTime(
2350 					trackId, when, false);
2351 
2352 			((MP4File*)hFile)->ReadSample(
2353 				trackId,
2354 				sampleId,
2355 				ppBytes,
2356 				pNumBytes,
2357 				pStartTime,
2358 				pDuration,
2359 				pRenderingOffset,
2360 				pIsSyncSample);
2361 
2362 			return true;
2363 		}
2364 		catch (MP4Error* e) {
2365 			PRINT_ERROR(e);
2366 			delete e;
2367 		}
2368 	}
2369 	*pNumBytes = 0;
2370 	return false;
2371 }
2372 
MP4WriteSample(MP4FileHandle hFile,MP4TrackId trackId,const u_int8_t * pBytes,u_int32_t numBytes,MP4Duration duration,MP4Duration renderingOffset,bool isSyncSample)2373 extern "C" bool MP4WriteSample(
2374 	MP4FileHandle hFile,
2375 	MP4TrackId trackId,
2376 	const u_int8_t* pBytes,
2377 	u_int32_t numBytes,
2378 	MP4Duration duration,
2379 	MP4Duration renderingOffset,
2380 	bool isSyncSample)
2381 {
2382 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2383 		try {
2384 			((MP4File*)hFile)->WriteSample(
2385 				trackId,
2386 				pBytes,
2387 				numBytes,
2388 				duration,
2389 				renderingOffset,
2390 				isSyncSample);
2391 			return true;
2392 		}
2393 		catch (MP4Error* e) {
2394 			PRINT_ERROR(e);
2395 			delete e;
2396 		}
2397 	}
2398 	return false;
2399 }
2400 
MP4CopySample(MP4FileHandle srcFile,MP4TrackId srcTrackId,MP4SampleId srcSampleId,MP4FileHandle dstFile,MP4TrackId dstTrackId,MP4Duration dstSampleDuration)2401 extern "C" bool MP4CopySample(
2402 	MP4FileHandle srcFile,
2403 	MP4TrackId srcTrackId,
2404 	MP4SampleId srcSampleId,
2405 	MP4FileHandle dstFile,
2406 	MP4TrackId dstTrackId,
2407 	MP4Duration dstSampleDuration)
2408 {
2409 	bool rc;
2410 	u_int8_t* pBytes = NULL;
2411 	u_int32_t numBytes = 0;
2412 	MP4Duration sampleDuration;
2413 	MP4Duration renderingOffset;
2414 	bool isSyncSample;
2415 
2416 	// Note: we leave it up to the caller to ensure that the
2417 	// source and destination tracks are compatible.
2418 	// i.e. copying audio samples into a video track
2419 	// is unlikely to do anything useful
2420 
2421 	rc = MP4ReadSample(
2422 		srcFile,
2423 		srcTrackId,
2424 		srcSampleId,
2425 		&pBytes,
2426 		&numBytes,
2427 		NULL,
2428 		&sampleDuration,
2429 		&renderingOffset,
2430 		&isSyncSample);
2431 
2432 	if (!rc) {
2433 		return false;
2434 	}
2435 
2436 	if (dstFile == MP4_INVALID_FILE_HANDLE) {
2437 		dstFile = srcFile;
2438 	}
2439 	if (dstTrackId == MP4_INVALID_TRACK_ID) {
2440 		dstTrackId = srcTrackId;
2441 	}
2442 	if (dstSampleDuration != MP4_INVALID_DURATION) {
2443 		sampleDuration = dstSampleDuration;
2444 	}
2445 
2446 	rc = MP4WriteSample(
2447 		dstFile,
2448 		dstTrackId,
2449 		pBytes,
2450 		numBytes,
2451 		sampleDuration,
2452 		renderingOffset,
2453 		isSyncSample);
2454 
2455 	free(pBytes);
2456 
2457 	return rc;
2458 }
2459 
MP4EncAndCopySample(MP4FileHandle srcFile,MP4TrackId srcTrackId,MP4SampleId srcSampleId,encryptFunc_t encfcnp,u_int32_t encfcnparam1,MP4FileHandle dstFile,MP4TrackId dstTrackId,MP4Duration dstSampleDuration)2460 extern "C" bool MP4EncAndCopySample(
2461 	MP4FileHandle srcFile,
2462 	MP4TrackId srcTrackId,
2463 	MP4SampleId srcSampleId,
2464         encryptFunc_t encfcnp,
2465         u_int32_t encfcnparam1,
2466 	MP4FileHandle dstFile,
2467 	MP4TrackId dstTrackId,
2468 	MP4Duration dstSampleDuration)
2469 {
2470 	bool rc;
2471 	u_int8_t* pBytes = NULL;
2472 	u_int32_t numBytes = 0;
2473 	u_int8_t* encSampleData = NULL;
2474 	u_int32_t encSampleLength = 0;
2475 	MP4Duration sampleDuration;
2476 	MP4Duration renderingOffset;
2477 	bool isSyncSample;
2478 
2479 	// Note: we leave it up to the caller to ensure that the
2480 	// source and destination tracks are compatible.
2481 	// i.e. copying audio samples into a video track
2482 	// is unlikely to do anything useful
2483 
2484 	rc = MP4ReadSample(
2485 		srcFile,
2486 		srcTrackId,
2487 		srcSampleId,
2488 		&pBytes,
2489 		&numBytes,
2490 		NULL,
2491 		&sampleDuration,
2492 		&renderingOffset,
2493 		&isSyncSample);
2494 
2495 	if (!rc) {
2496 		return false;
2497 	}
2498 
2499 	if (dstFile == MP4_INVALID_FILE_HANDLE) {
2500 		dstFile = srcFile;
2501 	}
2502 	if (dstTrackId == MP4_INVALID_TRACK_ID) {
2503 		dstTrackId = srcTrackId;
2504 	}
2505 	if (dstSampleDuration != MP4_INVALID_DURATION) {
2506 		sampleDuration = dstSampleDuration;
2507 	}
2508 
2509         //if (ismacrypEncryptSampleAddHeader(ismaCryptSId, numBytes, pBytes,
2510         //                        &encSampleLength, &encSampleData) != 0) {
2511         if (encfcnp(encfcnparam1, numBytes, pBytes,
2512 				&encSampleLength, &encSampleData) != 0) {
2513 		fprintf(stderr,
2514 			"Can't encrypt the sample and add its header %u\n",
2515 			srcSampleId);
2516 	}
2517 
2518 	rc = MP4WriteSample(
2519 		dstFile,
2520                 dstTrackId,
2521                 encSampleData,
2522                 encSampleLength,
2523                 sampleDuration,
2524                 renderingOffset,
2525                 isSyncSample);
2526 
2527 	free(pBytes);
2528 
2529 	if (encSampleData != NULL) {
2530 	          free(encSampleData);
2531         }
2532 
2533 	return rc;
2534 }
2535 
MP4ReferenceSample(MP4FileHandle srcFile,MP4TrackId srcTrackId,MP4SampleId srcSampleId,MP4FileHandle dstFile,MP4TrackId dstTrackId,MP4Duration dstSampleDuration)2536 extern "C" bool MP4ReferenceSample(
2537 	MP4FileHandle srcFile,
2538 	MP4TrackId srcTrackId,
2539 	MP4SampleId srcSampleId,
2540 	MP4FileHandle dstFile,
2541 	MP4TrackId dstTrackId,
2542 	MP4Duration dstSampleDuration)
2543 {
2544 	// LATER Not yet implemented
2545 	return false;
2546 }
2547 
MP4GetSampleSize(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId)2548 extern "C" u_int32_t MP4GetSampleSize(
2549 	MP4FileHandle hFile,
2550 	MP4TrackId trackId,
2551 	MP4SampleId sampleId)
2552 {
2553 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2554 		try {
2555 			return ((MP4File*)hFile)->GetSampleSize(
2556 				trackId, sampleId);
2557 		}
2558 		catch (MP4Error* e) {
2559 			PRINT_ERROR(e);
2560 			delete e;
2561 		}
2562 	}
2563 	return 0;
2564 }
2565 
MP4GetTrackMaxSampleSize(MP4FileHandle hFile,MP4TrackId trackId)2566 extern "C" u_int32_t MP4GetTrackMaxSampleSize(
2567 	MP4FileHandle hFile,
2568 	MP4TrackId trackId)
2569 {
2570 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2571 		try {
2572 			return ((MP4File*)hFile)->GetTrackMaxSampleSize(trackId);
2573 		}
2574 		catch (MP4Error* e) {
2575 			PRINT_ERROR(e);
2576 			delete e;
2577 		}
2578 	}
2579 	return 0;
2580 }
2581 
MP4GetSampleIdFromTime(MP4FileHandle hFile,MP4TrackId trackId,MP4Timestamp when,bool wantSyncSample)2582 extern "C" MP4SampleId MP4GetSampleIdFromTime(
2583 	MP4FileHandle hFile,
2584 	MP4TrackId trackId,
2585 	MP4Timestamp when,
2586 	bool wantSyncSample)
2587 {
2588 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2589 		try {
2590 			return ((MP4File*)hFile)->GetSampleIdFromTime(
2591 				trackId, when, wantSyncSample);
2592 		}
2593 		catch (MP4Error* e) {
2594 			PRINT_ERROR(e);
2595 			delete e;
2596 		}
2597 	}
2598 	return MP4_INVALID_SAMPLE_ID;
2599 }
2600 
MP4GetSampleTime(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId)2601 extern "C" MP4Timestamp MP4GetSampleTime(
2602 	MP4FileHandle hFile,
2603 	MP4TrackId trackId,
2604 	MP4SampleId sampleId)
2605 {
2606 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2607 		try {
2608 			return ((MP4File*)hFile)->GetSampleTime(
2609 				trackId, sampleId);
2610 		}
2611 		catch (MP4Error* e) {
2612 			PRINT_ERROR(e);
2613 			delete e;
2614 		}
2615 	}
2616 	return MP4_INVALID_TIMESTAMP;
2617 }
2618 
MP4GetSampleDuration(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId)2619 extern "C" MP4Duration MP4GetSampleDuration(
2620 	MP4FileHandle hFile,
2621 	MP4TrackId trackId,
2622 	MP4SampleId sampleId)
2623 {
2624 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2625 		try {
2626 			return ((MP4File*)hFile)->GetSampleDuration(
2627 				trackId, sampleId);
2628 		}
2629 		catch (MP4Error* e) {
2630 			PRINT_ERROR(e);
2631 			delete e;
2632 		}
2633 	}
2634 	return MP4_INVALID_DURATION;
2635 }
2636 
MP4GetSampleRenderingOffset(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId)2637 extern "C" MP4Duration MP4GetSampleRenderingOffset(
2638 	MP4FileHandle hFile,
2639 	MP4TrackId trackId,
2640 	MP4SampleId sampleId)
2641 {
2642 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2643 		try {
2644 			return ((MP4File*)hFile)->GetSampleRenderingOffset(
2645 				trackId, sampleId);
2646 		}
2647 		catch (MP4Error* e) {
2648 			PRINT_ERROR(e);
2649 			delete e;
2650 		}
2651 	}
2652 	return MP4_INVALID_DURATION;
2653 }
2654 
MP4SetSampleRenderingOffset(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId,MP4Duration renderingOffset)2655 extern "C" bool MP4SetSampleRenderingOffset(
2656 	MP4FileHandle hFile,
2657 	MP4TrackId trackId,
2658 	MP4SampleId sampleId,
2659 	MP4Duration renderingOffset)
2660 {
2661 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2662 		try {
2663 			((MP4File*)hFile)->SetSampleRenderingOffset(
2664 				trackId, sampleId, renderingOffset);
2665 			return true;
2666 		}
2667 		catch (MP4Error* e) {
2668 			PRINT_ERROR(e);
2669 			delete e;
2670 		}
2671 	}
2672 	return false;
2673 }
2674 
MP4GetSampleSync(MP4FileHandle hFile,MP4TrackId trackId,MP4SampleId sampleId)2675 extern "C" int8_t MP4GetSampleSync(
2676 	MP4FileHandle hFile,
2677 	MP4TrackId trackId,
2678 	MP4SampleId sampleId)
2679 {
2680 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2681 		try {
2682 			return ((MP4File*)hFile)->GetSampleSync(
2683 				trackId, sampleId);
2684 		}
2685 		catch (MP4Error* e) {
2686 			PRINT_ERROR(e);
2687 			delete e;
2688 		}
2689 	}
2690 	return -1;
2691 }
2692 
2693 
MP4ConvertFromMovieDuration(MP4FileHandle hFile,MP4Duration duration,u_int32_t timeScale)2694 extern "C" u_int64_t MP4ConvertFromMovieDuration(
2695 	MP4FileHandle hFile,
2696 	MP4Duration duration,
2697 	u_int32_t timeScale)
2698 {
2699 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2700 		try {
2701 			return ((MP4File*)hFile)->ConvertFromMovieDuration(
2702 				duration, timeScale);
2703 		}
2704 		catch (MP4Error* e) {
2705 			PRINT_ERROR(e);
2706 			delete e;
2707 		}
2708 	}
2709 	return (u_int64_t)MP4_INVALID_DURATION;
2710 }
2711 
MP4ConvertFromTrackTimestamp(MP4FileHandle hFile,MP4TrackId trackId,MP4Timestamp timeStamp,u_int32_t timeScale)2712 extern "C" u_int64_t MP4ConvertFromTrackTimestamp(
2713 	MP4FileHandle hFile,
2714 	MP4TrackId trackId,
2715 	MP4Timestamp timeStamp,
2716 	u_int32_t timeScale)
2717 {
2718 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2719 		try {
2720 			return ((MP4File*)hFile)->ConvertFromTrackTimestamp(
2721 				trackId, timeStamp, timeScale);
2722 		}
2723 		catch (MP4Error* e) {
2724 			PRINT_ERROR(e);
2725 			delete e;
2726 		}
2727 	}
2728 	return (u_int64_t)MP4_INVALID_TIMESTAMP;
2729 }
2730 
MP4ConvertToTrackTimestamp(MP4FileHandle hFile,MP4TrackId trackId,u_int64_t timeStamp,u_int32_t timeScale)2731 extern "C" MP4Timestamp MP4ConvertToTrackTimestamp(
2732 	MP4FileHandle hFile,
2733 	MP4TrackId trackId,
2734 	u_int64_t timeStamp,
2735 	u_int32_t timeScale)
2736 {
2737 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2738 		try {
2739 			return ((MP4File*)hFile)->ConvertToTrackTimestamp(
2740 				trackId, timeStamp, timeScale);
2741 		}
2742 		catch (MP4Error* e) {
2743 			PRINT_ERROR(e);
2744 			delete e;
2745 		}
2746 	}
2747 	return MP4_INVALID_TIMESTAMP;
2748 }
2749 
MP4ConvertFromTrackDuration(MP4FileHandle hFile,MP4TrackId trackId,MP4Duration duration,u_int32_t timeScale)2750 extern "C" u_int64_t MP4ConvertFromTrackDuration(
2751 	MP4FileHandle hFile,
2752 	MP4TrackId trackId,
2753 	MP4Duration duration,
2754 	u_int32_t timeScale)
2755 {
2756 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2757 		try {
2758 			return ((MP4File*)hFile)->ConvertFromTrackDuration(
2759 				trackId, duration, timeScale);
2760 		}
2761 		catch (MP4Error* e) {
2762 			PRINT_ERROR(e);
2763 			delete e;
2764 		}
2765 	}
2766 	return (u_int64_t)MP4_INVALID_DURATION;
2767 }
2768 
MP4ConvertToTrackDuration(MP4FileHandle hFile,MP4TrackId trackId,u_int64_t duration,u_int32_t timeScale)2769 extern "C" MP4Duration MP4ConvertToTrackDuration(
2770 	MP4FileHandle hFile,
2771 	MP4TrackId trackId,
2772 	u_int64_t duration,
2773 	u_int32_t timeScale)
2774 {
2775 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2776 		try {
2777 			return ((MP4File*)hFile)->ConvertToTrackDuration(
2778 				trackId, duration, timeScale);
2779 		}
2780 		catch (MP4Error* e) {
2781 			PRINT_ERROR(e);
2782 			delete e;
2783 		}
2784 	}
2785 	return MP4_INVALID_DURATION;
2786 }
2787 
MP4GetHintTrackRtpPayload(MP4FileHandle hFile,MP4TrackId hintTrackId,char ** ppPayloadName,u_int8_t * pPayloadNumber,u_int16_t * pMaxPayloadSize,char ** ppEncodingParams)2788 extern "C" bool MP4GetHintTrackRtpPayload(
2789 	MP4FileHandle hFile,
2790 	MP4TrackId hintTrackId,
2791 	char** ppPayloadName,
2792 	u_int8_t* pPayloadNumber,
2793 	u_int16_t* pMaxPayloadSize,
2794 	char **ppEncodingParams)
2795 {
2796 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2797 		try {
2798 			((MP4File*)hFile)->GetHintTrackRtpPayload(
2799 				hintTrackId, ppPayloadName, pPayloadNumber, pMaxPayloadSize,
2800 				ppEncodingParams);
2801 			return true;
2802 		}
2803 		catch (MP4Error* e) {
2804 			PRINT_ERROR(e);
2805 			delete e;
2806 		}
2807 	}
2808 	return false;
2809 }
2810 
MP4SetHintTrackRtpPayload(MP4FileHandle hFile,MP4TrackId hintTrackId,const char * pPayloadName,u_int8_t * pPayloadNumber,u_int16_t maxPayloadSize,const char * encode_params,bool include_rtp_map,bool include_mpeg4_esid)2811 extern "C" bool MP4SetHintTrackRtpPayload(
2812 	MP4FileHandle hFile,
2813 	MP4TrackId hintTrackId,
2814 	const char* pPayloadName,
2815 	u_int8_t* pPayloadNumber,
2816 	u_int16_t maxPayloadSize,
2817 	const char *encode_params,
2818 	bool include_rtp_map,
2819 	bool include_mpeg4_esid)
2820 {
2821 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2822 		try {
2823 			((MP4File*)hFile)->SetHintTrackRtpPayload(
2824 				hintTrackId, pPayloadName, pPayloadNumber, maxPayloadSize, encode_params,
2825 				include_rtp_map, include_mpeg4_esid);
2826 			return true;
2827 		}
2828 		catch (MP4Error* e) {
2829 			PRINT_ERROR(e);
2830 			delete e;
2831 		}
2832 	}
2833 	return false;
2834 }
2835 
MP4GetSessionSdp(MP4FileHandle hFile)2836 extern "C" const char* MP4GetSessionSdp(
2837 	MP4FileHandle hFile)
2838 {
2839 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2840 		try {
2841 			return ((MP4File*)hFile)->GetSessionSdp();
2842 		}
2843 		catch (MP4Error* e) {
2844 			PRINT_ERROR(e);
2845 			delete e;
2846 		}
2847 	}
2848 	return NULL;
2849 }
2850 
MP4SetSessionSdp(MP4FileHandle hFile,const char * sdpString)2851 extern "C" bool MP4SetSessionSdp(
2852 	MP4FileHandle hFile,
2853 	const char* sdpString)
2854 {
2855 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2856 		try {
2857 			((MP4File*)hFile)->SetSessionSdp(sdpString);
2858 			return true;
2859 		}
2860 		catch (MP4Error* e) {
2861 			PRINT_ERROR(e);
2862 			delete e;
2863 		}
2864 	}
2865 	return false;
2866 }
2867 
MP4AppendSessionSdp(MP4FileHandle hFile,const char * sdpString)2868 extern "C" bool MP4AppendSessionSdp(
2869 	MP4FileHandle hFile,
2870 	const char* sdpString)
2871 {
2872 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2873 		try {
2874 			((MP4File*)hFile)->AppendSessionSdp(sdpString);
2875 			return true;
2876 		}
2877 		catch (MP4Error* e) {
2878 			PRINT_ERROR(e);
2879 			delete e;
2880 		}
2881 	}
2882 	return false;
2883 }
2884 
MP4GetHintTrackSdp(MP4FileHandle hFile,MP4TrackId hintTrackId)2885 extern "C" const char* MP4GetHintTrackSdp(
2886 	MP4FileHandle hFile,
2887 	MP4TrackId hintTrackId)
2888 {
2889 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2890 		try {
2891 			return ((MP4File*)hFile)->GetHintTrackSdp(hintTrackId);
2892 		}
2893 		catch (MP4Error* e) {
2894 			PRINT_ERROR(e);
2895 			delete e;
2896 		}
2897 	}
2898 	return NULL;
2899 }
2900 
MP4SetHintTrackSdp(MP4FileHandle hFile,MP4TrackId hintTrackId,const char * sdpString)2901 extern "C" bool MP4SetHintTrackSdp(
2902 	MP4FileHandle hFile,
2903 	MP4TrackId hintTrackId,
2904 	const char* sdpString)
2905 {
2906 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2907 		try {
2908 			((MP4File*)hFile)->SetHintTrackSdp(hintTrackId, sdpString);
2909 			return true;
2910 		}
2911 		catch (MP4Error* e) {
2912 			PRINT_ERROR(e);
2913 			delete e;
2914 		}
2915 	}
2916 	return false;
2917 }
2918 
MP4AppendHintTrackSdp(MP4FileHandle hFile,MP4TrackId hintTrackId,const char * sdpString)2919 extern "C" bool MP4AppendHintTrackSdp(
2920 	MP4FileHandle hFile,
2921 	MP4TrackId hintTrackId,
2922 	const char* sdpString)
2923 {
2924 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2925 		try {
2926 			((MP4File*)hFile)->AppendHintTrackSdp(hintTrackId, sdpString);
2927 			return true;
2928 		}
2929 		catch (MP4Error* e) {
2930 			PRINT_ERROR(e);
2931 			delete e;
2932 		}
2933 	}
2934 	return false;
2935 }
2936 
MP4GetHintTrackReferenceTrackId(MP4FileHandle hFile,MP4TrackId hintTrackId)2937 extern "C" MP4TrackId MP4GetHintTrackReferenceTrackId(
2938 	MP4FileHandle hFile,
2939 	MP4TrackId hintTrackId)
2940 {
2941 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2942 		try {
2943 			return ((MP4File*)hFile)->
2944 				GetHintTrackReferenceTrackId(hintTrackId);
2945 		}
2946 		catch (MP4Error* e) {
2947 			PRINT_ERROR(e);
2948 			delete e;
2949 		}
2950 	}
2951 	return MP4_INVALID_TRACK_ID;
2952 }
2953 
MP4ReadRtpHint(MP4FileHandle hFile,MP4TrackId hintTrackId,MP4SampleId hintSampleId,u_int16_t * pNumPackets)2954 extern "C" bool MP4ReadRtpHint(
2955 	MP4FileHandle hFile,
2956 	MP4TrackId hintTrackId,
2957 	MP4SampleId hintSampleId,
2958 	u_int16_t* pNumPackets)
2959 {
2960 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2961 		try {
2962 			((MP4File*)hFile)->ReadRtpHint(
2963 				hintTrackId, hintSampleId, pNumPackets);
2964 			return true;
2965 		}
2966 		catch (MP4Error* e) {
2967 			PRINT_ERROR(e);
2968 			delete e;
2969 		}
2970 	}
2971 	return false;
2972 }
2973 
MP4GetRtpHintNumberOfPackets(MP4FileHandle hFile,MP4TrackId hintTrackId)2974 extern "C" u_int16_t MP4GetRtpHintNumberOfPackets(
2975 	MP4FileHandle hFile,
2976 	MP4TrackId hintTrackId)
2977 {
2978 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2979 		try {
2980 			return ((MP4File*)hFile)->GetRtpHintNumberOfPackets(hintTrackId);
2981 		}
2982 		catch (MP4Error* e) {
2983 			PRINT_ERROR(e);
2984 			delete e;
2985 		}
2986 	}
2987 	return 0;
2988 }
2989 
MP4GetRtpPacketBFrame(MP4FileHandle hFile,MP4TrackId hintTrackId,u_int16_t packetIndex)2990 extern "C" int8_t MP4GetRtpPacketBFrame(
2991 	MP4FileHandle hFile,
2992 	MP4TrackId hintTrackId,
2993 	u_int16_t packetIndex)
2994 {
2995 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
2996 		try {
2997 			return ((MP4File*)hFile)->
2998 				GetRtpPacketBFrame(hintTrackId, packetIndex);
2999 		}
3000 		catch (MP4Error* e) {
3001 			PRINT_ERROR(e);
3002 			delete e;
3003 		}
3004 	}
3005 	return -1;
3006 }
3007 
MP4GetRtpPacketTransmitOffset(MP4FileHandle hFile,MP4TrackId hintTrackId,u_int16_t packetIndex)3008 extern "C" int32_t MP4GetRtpPacketTransmitOffset(
3009 	MP4FileHandle hFile,
3010 	MP4TrackId hintTrackId,
3011 	u_int16_t packetIndex)
3012 {
3013 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3014 		try {
3015 			return ((MP4File*)hFile)->
3016 				GetRtpPacketTransmitOffset(hintTrackId, packetIndex);
3017 		}
3018 		catch (MP4Error* e) {
3019 			PRINT_ERROR(e);
3020 			delete e;
3021 		}
3022 	}
3023 	return 0;
3024 }
3025 
MP4ReadRtpPacket(MP4FileHandle hFile,MP4TrackId hintTrackId,u_int16_t packetIndex,u_int8_t ** ppBytes,u_int32_t * pNumBytes,u_int32_t ssrc,bool includeHeader,bool includePayload)3026 extern "C" bool MP4ReadRtpPacket(
3027 	MP4FileHandle hFile,
3028 	MP4TrackId hintTrackId,
3029 	u_int16_t packetIndex,
3030 	u_int8_t** ppBytes,
3031 	u_int32_t* pNumBytes,
3032 	u_int32_t ssrc,
3033 	bool includeHeader,
3034 	bool includePayload)
3035 {
3036 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3037 		try {
3038 			((MP4File*)hFile)->ReadRtpPacket(
3039 				hintTrackId, packetIndex,
3040 				ppBytes, pNumBytes,
3041 				ssrc, includeHeader, includePayload);
3042 			return true;
3043 		}
3044 		catch (MP4Error* e) {
3045 			PRINT_ERROR(e);
3046 			delete e;
3047 		}
3048 	}
3049 	return false;
3050 }
3051 
MP4GetRtpTimestampStart(MP4FileHandle hFile,MP4TrackId hintTrackId)3052 extern "C" MP4Timestamp MP4GetRtpTimestampStart(
3053 	MP4FileHandle hFile,
3054 	MP4TrackId hintTrackId)
3055 {
3056 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3057 		try {
3058 			return ((MP4File*)hFile)->GetRtpTimestampStart(hintTrackId);
3059 		}
3060 		catch (MP4Error* e) {
3061 			PRINT_ERROR(e);
3062 			delete e;
3063 		}
3064 	}
3065 	return MP4_INVALID_TIMESTAMP;
3066 }
3067 
MP4SetRtpTimestampStart(MP4FileHandle hFile,MP4TrackId hintTrackId,MP4Timestamp rtpStart)3068 extern "C" bool MP4SetRtpTimestampStart(
3069 	MP4FileHandle hFile,
3070 	MP4TrackId hintTrackId,
3071 	MP4Timestamp rtpStart)
3072 {
3073 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3074 		try {
3075 			((MP4File*)hFile)->SetRtpTimestampStart(
3076 				hintTrackId, rtpStart);
3077 			return true;
3078 		}
3079 		catch (MP4Error* e) {
3080 			PRINT_ERROR(e);
3081 			delete e;
3082 		}
3083 	}
3084 	return false;
3085 }
3086 
MP4AddRtpHint(MP4FileHandle hFile,MP4TrackId hintTrackId)3087 extern "C" bool MP4AddRtpHint(
3088 	MP4FileHandle hFile,
3089 	MP4TrackId hintTrackId)
3090 {
3091 	return MP4AddRtpVideoHint(hFile, hintTrackId, false, 0);
3092 }
3093 
MP4AddRtpVideoHint(MP4FileHandle hFile,MP4TrackId hintTrackId,bool isBframe,u_int32_t timestampOffset)3094 extern "C" bool MP4AddRtpVideoHint(
3095 	MP4FileHandle hFile,
3096 	MP4TrackId hintTrackId,
3097 	bool isBframe,
3098 	u_int32_t timestampOffset)
3099 {
3100 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3101 		try {
3102 			((MP4File*)hFile)->AddRtpHint(hintTrackId,
3103 				isBframe, timestampOffset);
3104 			return true;
3105 		}
3106 		catch (MP4Error* e) {
3107 			PRINT_ERROR(e);
3108 			delete e;
3109 		}
3110 	}
3111 	return false;
3112 }
3113 
MP4AddRtpPacket(MP4FileHandle hFile,MP4TrackId hintTrackId,bool setMbit,int32_t transmitOffset)3114 extern "C" bool MP4AddRtpPacket(
3115 	MP4FileHandle hFile,
3116 	MP4TrackId hintTrackId,
3117 	bool setMbit,
3118 	int32_t transmitOffset)
3119 {
3120 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3121 		try {
3122 			((MP4File*)hFile)->AddRtpPacket(
3123 				hintTrackId, setMbit, transmitOffset);
3124 			return true;
3125 		}
3126 		catch (MP4Error* e) {
3127 			PRINT_ERROR(e);
3128 			delete e;
3129 		}
3130 	}
3131 	return false;
3132 }
3133 
MP4AddRtpImmediateData(MP4FileHandle hFile,MP4TrackId hintTrackId,const u_int8_t * pBytes,u_int32_t numBytes)3134 extern "C" bool MP4AddRtpImmediateData(
3135 	MP4FileHandle hFile,
3136 	MP4TrackId hintTrackId,
3137 	const u_int8_t* pBytes,
3138 	u_int32_t numBytes)
3139 {
3140 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3141 		try {
3142 			((MP4File*)hFile)->AddRtpImmediateData(hintTrackId,
3143 				pBytes, numBytes);
3144 			return true;
3145 		}
3146 		catch (MP4Error* e) {
3147 			PRINT_ERROR(e);
3148 			delete e;
3149 		}
3150 	}
3151 	return false;
3152 }
3153 
MP4AddRtpSampleData(MP4FileHandle hFile,MP4TrackId hintTrackId,MP4SampleId sampleId,u_int32_t dataOffset,u_int32_t dataLength)3154 extern "C" bool MP4AddRtpSampleData(
3155 	MP4FileHandle hFile,
3156 	MP4TrackId hintTrackId,
3157 	MP4SampleId sampleId,
3158 	u_int32_t dataOffset,
3159 	u_int32_t dataLength)
3160 {
3161 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3162 		try {
3163 			((MP4File*)hFile)->AddRtpSampleData(
3164 				hintTrackId, sampleId, dataOffset, dataLength);
3165 			return true;
3166 		}
3167 		catch (MP4Error* e) {
3168 			PRINT_ERROR(e);
3169 			delete e;
3170 		}
3171 	}
3172 	return false;
3173 }
3174 
MP4AddRtpESConfigurationPacket(MP4FileHandle hFile,MP4TrackId hintTrackId)3175 extern "C" bool MP4AddRtpESConfigurationPacket(
3176 	MP4FileHandle hFile,
3177 	MP4TrackId hintTrackId)
3178 {
3179 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3180 		try {
3181 			((MP4File*)hFile)->AddRtpESConfigurationPacket(hintTrackId);
3182 			return true;
3183 		}
3184 		catch (MP4Error* e) {
3185 			PRINT_ERROR(e);
3186 			delete e;
3187 		}
3188 	}
3189 	return false;
3190 }
3191 
MP4WriteRtpHint(MP4FileHandle hFile,MP4TrackId hintTrackId,MP4Duration duration,bool isSyncSample)3192 extern "C" bool MP4WriteRtpHint(
3193 	MP4FileHandle hFile,
3194 	MP4TrackId hintTrackId,
3195 	MP4Duration duration,
3196 	bool isSyncSample)
3197 {
3198 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3199 		try {
3200 			((MP4File*)hFile)->WriteRtpHint(
3201 				hintTrackId, duration, isSyncSample);
3202 			return true;
3203 		}
3204 		catch (MP4Error* e) {
3205 			PRINT_ERROR(e);
3206 			delete e;
3207 		}
3208 	}
3209 	return false;
3210 }
3211 /* 3GPP specific operations */
3212 
MP4Make3GPCompliant(const char * fileName,u_int32_t verbosity,char * majorBrand,u_int32_t minorVersion,char ** supportedBrands,u_int32_t supportedBrandsCount,bool deleteIodsAtom)3213 extern "C" bool MP4Make3GPCompliant(
3214 	const char* fileName,
3215 	u_int32_t verbosity,
3216 	char* majorBrand,
3217 	u_int32_t minorVersion,
3218 	char** supportedBrands,
3219 	u_int32_t supportedBrandsCount,
3220 	bool deleteIodsAtom)
3221 {
3222 	MP4File* pFile;
3223 	pFile = NULL;
3224 
3225 	try {
3226 		pFile = new MP4File(verbosity);
3227 		pFile->Modify(fileName);
3228 		pFile->Make3GPCompliant(fileName, majorBrand, minorVersion, supportedBrands, supportedBrandsCount, deleteIodsAtom);
3229 		pFile->Close();
3230 		delete pFile;
3231 		return true;
3232 	}
3233 	catch (MP4Error* e) {
3234 		VERBOSE_ERROR(verbosity, e->Print());
3235 		delete e;
3236 	}
3237 	delete pFile;
3238 	return false;
3239 }
3240 
3241 /* ISMA specific operations */
3242 
MP4MakeIsmaCompliant(const char * fileName,u_int32_t verbosity,bool addIsmaComplianceSdp)3243 extern "C" bool MP4MakeIsmaCompliant(
3244 	const char* fileName,
3245 	u_int32_t verbosity,
3246 	bool addIsmaComplianceSdp)
3247 {
3248 	MP4File* pFile;
3249 	pFile = NULL;
3250 
3251 	try {
3252 		pFile = new MP4File(verbosity);
3253 		pFile->Modify(fileName);
3254 		pFile->MakeIsmaCompliant(addIsmaComplianceSdp);
3255 		pFile->Close();
3256 		delete pFile;
3257 		return true;
3258 	}
3259 	catch (MP4Error* e) {
3260 		VERBOSE_ERROR(verbosity, e->Print());
3261 		delete e;
3262 	}
3263 	delete pFile;
3264 	return false;
3265 }
3266 
MP4MakeIsmaSdpIod(u_int8_t videoProfile,u_int32_t videoBitrate,u_int8_t * videoConfig,u_int32_t videoConfigLength,u_int8_t audioProfile,u_int32_t audioBitrate,u_int8_t * audioConfig,u_int32_t audioConfigLength,u_int32_t verbosity)3267 extern "C" char* MP4MakeIsmaSdpIod(
3268 	u_int8_t videoProfile,
3269 	u_int32_t videoBitrate,
3270 	u_int8_t* videoConfig,
3271 	u_int32_t videoConfigLength,
3272 	u_int8_t audioProfile,
3273 	u_int32_t audioBitrate,
3274 	u_int8_t* audioConfig,
3275 	u_int32_t audioConfigLength,
3276 	u_int32_t verbosity)
3277 {
3278 	MP4File* pFile = NULL;
3279 
3280 	try {
3281 		pFile = new MP4File(verbosity);
3282 
3283 		u_int8_t* pBytes = NULL;
3284 		u_int64_t numBytes = 0;
3285 
3286 		pFile->CreateIsmaIodFromParams(
3287 			videoProfile,
3288 			videoBitrate,
3289 			videoConfig,
3290 			videoConfigLength,
3291 			audioProfile,
3292 			audioBitrate,
3293 			audioConfig,
3294 			audioConfigLength,
3295 			&pBytes,
3296 			&numBytes);
3297 
3298 		char* iodBase64 =
3299 			MP4ToBase64(pBytes, numBytes);
3300 		MP4Free(pBytes);
3301 
3302 		char* sdpIod =
3303 			(char*)MP4Malloc(strlen(iodBase64) + 64);
3304 		snprintf(sdpIod, strlen(iodBase64) + 64,
3305 			"a=mpeg4-iod: \042data:application/mpeg4-iod;base64,%s\042",
3306 			iodBase64);
3307 		MP4Free(iodBase64);
3308 
3309 		delete pFile;
3310 
3311 		return sdpIod;
3312 	}
3313 	catch (MP4Error* e) {
3314 		VERBOSE_ERROR(verbosity, e->Print());
3315 		delete e;
3316 	}
3317 	return NULL;
3318 }
3319 
3320 /* Edit list */
3321 
MP4AddTrackEdit(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId,MP4Timestamp startTime,MP4Duration duration,bool dwell)3322 extern "C" MP4EditId MP4AddTrackEdit(
3323 	MP4FileHandle hFile,
3324 	MP4TrackId trackId,
3325 	MP4EditId editId,
3326 	MP4Timestamp startTime,
3327 	MP4Duration duration,
3328 	bool dwell)
3329 {
3330 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3331 		try {
3332 			MP4EditId newEditId =
3333 				((MP4File*)hFile)->AddTrackEdit(trackId, editId);
3334 
3335 			if (newEditId != MP4_INVALID_EDIT_ID) {
3336 				((MP4File*)hFile)->SetTrackEditMediaStart(
3337 					trackId, newEditId, startTime);
3338 				((MP4File*)hFile)->SetTrackEditDuration(
3339 					trackId, newEditId, duration);
3340 				((MP4File*)hFile)->SetTrackEditDwell(
3341 					trackId, newEditId, dwell);
3342 			}
3343 
3344 			return newEditId;
3345 		}
3346 		catch (MP4Error* e) {
3347 			PRINT_ERROR(e);
3348 			delete e;
3349 		}
3350 	}
3351 	return MP4_INVALID_EDIT_ID;
3352 }
3353 
MP4DeleteTrackEdit(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId)3354 extern "C" bool MP4DeleteTrackEdit(
3355 	MP4FileHandle hFile,
3356 	MP4TrackId trackId,
3357 	MP4EditId editId)
3358 {
3359 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3360 		try {
3361 			((MP4File*)hFile)->DeleteTrackEdit(trackId, editId);
3362 			return true;
3363 		}
3364 		catch (MP4Error* e) {
3365 			PRINT_ERROR(e);
3366 			delete e;
3367 		}
3368 	}
3369 	return false;
3370 }
3371 
MP4GetTrackNumberOfEdits(MP4FileHandle hFile,MP4TrackId trackId)3372 extern "C" u_int32_t MP4GetTrackNumberOfEdits(
3373 	MP4FileHandle hFile,
3374 	MP4TrackId trackId)
3375 {
3376 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3377 		try {
3378 			return ((MP4File*)hFile)->GetTrackNumberOfEdits(trackId);
3379 		}
3380 		catch (MP4Error* e) {
3381 			//PRINT_ERROR(e);
3382 			delete e;
3383 		}
3384 	}
3385 	return 0;
3386 }
3387 
MP4GetTrackEditMediaStart(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId)3388 extern "C" MP4Timestamp MP4GetTrackEditMediaStart(
3389 	MP4FileHandle hFile,
3390 	MP4TrackId trackId,
3391 	MP4EditId editId)
3392 {
3393 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3394 		try {
3395 			return ((MP4File*)hFile)->GetTrackEditMediaStart(
3396 				trackId, editId);
3397 		}
3398 		catch (MP4Error* e) {
3399 			PRINT_ERROR(e);
3400 			delete e;
3401 		}
3402 	}
3403 	return MP4_INVALID_TIMESTAMP;
3404 }
3405 
MP4GetTrackEditTotalDuration(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId)3406 extern "C" MP4Duration MP4GetTrackEditTotalDuration(
3407 	MP4FileHandle hFile,
3408 	MP4TrackId trackId,
3409 	MP4EditId editId)
3410 {
3411 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3412 		try {
3413 			return ((MP4File*)hFile)->GetTrackEditTotalDuration(
3414 				trackId, editId);
3415 		}
3416 		catch (MP4Error* e) {
3417 			PRINT_ERROR(e);
3418 			delete e;
3419 		}
3420 	}
3421 	return MP4_INVALID_DURATION;
3422 }
3423 
MP4SetTrackEditMediaStart(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId,MP4Timestamp startTime)3424 extern "C" bool MP4SetTrackEditMediaStart(
3425 	MP4FileHandle hFile,
3426 	MP4TrackId trackId,
3427 	MP4EditId editId,
3428 	MP4Timestamp startTime)
3429 {
3430 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3431 		try {
3432 			((MP4File*)hFile)->SetTrackEditMediaStart(
3433 				trackId, editId, startTime);
3434 			return true;
3435 		}
3436 		catch (MP4Error* e) {
3437 			PRINT_ERROR(e);
3438 			delete e;
3439 		}
3440 	}
3441 	return false;
3442 }
3443 
MP4GetTrackEditDuration(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId)3444 extern "C" MP4Duration MP4GetTrackEditDuration(
3445 	MP4FileHandle hFile,
3446 	MP4TrackId trackId,
3447 	MP4EditId editId)
3448 {
3449 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3450 		try {
3451 			return ((MP4File*)hFile)->GetTrackEditDuration(trackId, editId);
3452 		}
3453 		catch (MP4Error* e) {
3454 			PRINT_ERROR(e);
3455 			delete e;
3456 		}
3457 	}
3458 	return MP4_INVALID_DURATION;
3459 }
3460 
MP4SetTrackEditDuration(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId,MP4Duration duration)3461 extern "C" bool MP4SetTrackEditDuration(
3462 	MP4FileHandle hFile,
3463 	MP4TrackId trackId,
3464 	MP4EditId editId,
3465 	MP4Duration duration)
3466 {
3467 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3468 		try {
3469 			((MP4File*)hFile)->SetTrackEditDuration(trackId, editId, duration);
3470 			return true;
3471 		}
3472 		catch (MP4Error* e) {
3473 			PRINT_ERROR(e);
3474 			delete e;
3475 		}
3476 	}
3477 	return false;
3478 }
3479 
MP4GetTrackEditDwell(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId)3480 extern "C" int8_t MP4GetTrackEditDwell(
3481 	MP4FileHandle hFile,
3482 	MP4TrackId trackId,
3483 	MP4EditId editId)
3484 {
3485 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3486 		try {
3487 			return ((MP4File*)hFile)->GetTrackEditDwell(trackId, editId);
3488 		}
3489 		catch (MP4Error* e) {
3490 			PRINT_ERROR(e);
3491 			delete e;
3492 		}
3493 	}
3494 	return -1;
3495 }
3496 
MP4SetTrackEditDwell(MP4FileHandle hFile,MP4TrackId trackId,MP4EditId editId,bool dwell)3497 extern "C" bool MP4SetTrackEditDwell(
3498 	MP4FileHandle hFile,
3499 	MP4TrackId trackId,
3500 	MP4EditId editId,
3501 	bool dwell)
3502 {
3503 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3504 		try {
3505 			((MP4File*)hFile)->SetTrackEditDwell(trackId, editId, dwell);
3506 			return true;
3507 		}
3508 		catch (MP4Error* e) {
3509 			PRINT_ERROR(e);
3510 			delete e;
3511 		}
3512 	}
3513 	return false;
3514 }
3515 
MP4ReadSampleFromEditTime(MP4FileHandle hFile,MP4TrackId trackId,MP4Timestamp when,u_int8_t ** ppBytes,u_int32_t * pNumBytes,MP4Timestamp * pStartTime,MP4Duration * pDuration,MP4Duration * pRenderingOffset,bool * pIsSyncSample)3516 extern "C" bool MP4ReadSampleFromEditTime(
3517 	/* input parameters */
3518 	MP4FileHandle hFile,
3519 	MP4TrackId trackId,
3520 	MP4Timestamp when,
3521 	/* output parameters */
3522 	u_int8_t** ppBytes,
3523 	u_int32_t* pNumBytes,
3524 	MP4Timestamp* pStartTime,
3525 	MP4Duration* pDuration,
3526 	MP4Duration* pRenderingOffset,
3527 	bool* pIsSyncSample)
3528 {
3529 	MP4SampleId sampleId =
3530 		MP4GetSampleIdFromEditTime(
3531 			hFile,
3532 			trackId,
3533 			when,
3534 			pStartTime,
3535 			pDuration);
3536 
3537 	return MP4ReadSample(
3538 		hFile,
3539 		trackId,
3540 		sampleId,
3541 		ppBytes,
3542 		pNumBytes,
3543 		NULL,
3544 		NULL,
3545 		pRenderingOffset,
3546 		pIsSyncSample);
3547 }
3548 
MP4GetSampleIdFromEditTime(MP4FileHandle hFile,MP4TrackId trackId,MP4Timestamp when,MP4Timestamp * pStartTime,MP4Duration * pDuration)3549 extern "C" MP4SampleId MP4GetSampleIdFromEditTime(
3550 	MP4FileHandle hFile,
3551 	MP4TrackId trackId,
3552 	MP4Timestamp when,
3553 	MP4Timestamp* pStartTime,
3554 	MP4Duration* pDuration)
3555 {
3556 	if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3557 		try {
3558 			return ((MP4File*)hFile)->GetSampleIdFromEditTime(
3559 				trackId, when, pStartTime, pDuration);
3560 		}
3561 		catch (MP4Error* e) {
3562 			PRINT_ERROR(e);
3563 			delete e;
3564 		}
3565 	}
3566 	return MP4_INVALID_SAMPLE_ID;
3567 }
3568 
3569 /* Utlities */
3570 
MP4BinaryToBase16(const u_int8_t * pData,u_int32_t dataSize)3571 extern "C" char* MP4BinaryToBase16(
3572 	const u_int8_t* pData,
3573 	u_int32_t dataSize)
3574 {
3575 	if (pData || dataSize == 0) {
3576 		try {
3577 			return MP4ToBase16(pData, dataSize);
3578 		}
3579 		catch (MP4Error* e) {
3580 			delete e;
3581 		}
3582 	}
3583 	return NULL;
3584 }
3585 
MP4BinaryToBase64(const u_int8_t * pData,u_int32_t dataSize)3586 extern "C" char* MP4BinaryToBase64(
3587 	const u_int8_t* pData,
3588 	u_int32_t dataSize)
3589 {
3590 	if (pData || dataSize == 0) {
3591 		try {
3592 			return MP4ToBase64(pData, dataSize);
3593 		}
3594 		catch (MP4Error* e) {
3595 			delete e;
3596 		}
3597 	}
3598 	return NULL;
3599 }
3600 
3601 /* iTunes meta data handling */
MP4GetMetadataByIndex(MP4FileHandle hFile,u_int32_t index,char ** ppName,u_int8_t ** ppValue,u_int32_t * pValueSize)3602 extern "C" bool MP4GetMetadataByIndex(MP4FileHandle hFile, u_int32_t index,
3603 				      char** ppName,
3604 				      u_int8_t** ppValue, u_int32_t* pValueSize)
3605 {
3606   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3607     try {
3608       return ((MP4File*)hFile)->GetMetadataByIndex(
3609 						   index, ppName, ppValue, pValueSize);
3610     }
3611     catch (MP4Error* e) {
3612       PRINT_ERROR(e);
3613       delete e;
3614     }
3615   }
3616   return false;
3617 }
3618 
MP4MetadataDelete(MP4FileHandle hFile)3619 extern "C" bool MP4MetadataDelete(MP4FileHandle hFile)
3620 {
3621   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3622     try {
3623       return ((MP4File*)hFile)->MetadataDelete();
3624     }
3625     catch (MP4Error* e) {
3626       PRINT_ERROR(e);
3627       delete e;
3628     }
3629   }
3630   return false;
3631 }
3632 
MP4SetMetadataName(MP4FileHandle hFile,const char * value)3633 extern "C" bool MP4SetMetadataName(MP4FileHandle hFile,
3634                                    const char* value)
3635 {
3636   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3637     try {
3638       return ((MP4File*)hFile)->SetMetadataString("\251nam", value);
3639     }
3640     catch (MP4Error* e) {
3641       PRINT_ERROR(e);
3642       delete e;
3643     }
3644   }
3645   return false;
3646 }
3647 
MP4GetMetadataName(MP4FileHandle hFile,char ** value)3648 extern "C" bool MP4GetMetadataName(MP4FileHandle hFile,
3649 				   char** value)
3650 {
3651   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3652     try {
3653       return ((MP4File*)hFile)->GetMetadataString("\251nam", value);
3654     }
3655     catch (MP4Error* e) {
3656       PRINT_ERROR(e);
3657       delete e;
3658     }
3659   }
3660   return false;
3661 }
3662 
MP4DeleteMetadataName(MP4FileHandle hFile)3663 extern "C" bool MP4DeleteMetadataName(MP4FileHandle hFile)
3664 {
3665   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3666     try {
3667       return ((MP4File*)hFile)->DeleteMetadataAtom("\251nam");
3668     }
3669     catch (MP4Error* e) {
3670       PRINT_ERROR(e);
3671       delete e;
3672     }
3673   }
3674   return false;
3675 }
3676 
MP4SetMetadataWriter(MP4FileHandle hFile,const char * value)3677 extern "C" bool MP4SetMetadataWriter(MP4FileHandle hFile,
3678 				     const char* value)
3679 {
3680   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3681     try {
3682       return ((MP4File*)hFile)->SetMetadataString("\251wrt", value);
3683     }
3684     catch (MP4Error* e) {
3685       PRINT_ERROR(e);
3686       delete e;
3687     }
3688   }
3689   return false;
3690 }
3691 
MP4GetMetadataWriter(MP4FileHandle hFile,char ** value)3692 extern "C" bool MP4GetMetadataWriter(MP4FileHandle hFile,
3693 				     char** value)
3694 {
3695   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3696     try {
3697       return ((MP4File*)hFile)->GetMetadataString("\251wrt", value);
3698     }
3699     catch (MP4Error* e) {
3700       PRINT_ERROR(e);
3701       delete e;
3702     }
3703   }
3704   return false;
3705 }
3706 
MP4DeleteMetadataWriter(MP4FileHandle hFile)3707 extern "C" bool MP4DeleteMetadataWriter(MP4FileHandle hFile)
3708 {
3709   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3710     try {
3711       return ((MP4File*)hFile)->DeleteMetadataAtom("\251wrt");
3712     }
3713     catch (MP4Error* e) {
3714       PRINT_ERROR(e);
3715       delete e;
3716     }
3717   }
3718   return false;
3719 }
3720 
MP4SetMetadataAlbum(MP4FileHandle hFile,const char * value)3721 extern "C" bool MP4SetMetadataAlbum(MP4FileHandle hFile,
3722 				    const char* value)
3723 {
3724   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3725     try {
3726       return ((MP4File*)hFile)->SetMetadataString("\251alb", value);
3727     }
3728     catch (MP4Error* e) {
3729       PRINT_ERROR(e);
3730       delete e;
3731     }
3732   }
3733   return false;
3734 }
3735 
MP4GetMetadataAlbum(MP4FileHandle hFile,char ** value)3736 extern "C" bool MP4GetMetadataAlbum(MP4FileHandle hFile,
3737 				    char** value)
3738 {
3739   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3740     try {
3741       return ((MP4File*)hFile)->GetMetadataString("\251alb", value);
3742     }
3743     catch (MP4Error* e) {
3744       PRINT_ERROR(e);
3745       delete e;
3746     }
3747   }
3748   return false;
3749 }
3750 
MP4DeleteMetadataAlbum(MP4FileHandle hFile)3751 extern "C" bool MP4DeleteMetadataAlbum(MP4FileHandle hFile)
3752 {
3753   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3754     try {
3755       return ((MP4File*)hFile)->DeleteMetadataAtom("\251alb");
3756     }
3757     catch (MP4Error* e) {
3758       PRINT_ERROR(e);
3759       delete e;
3760     }
3761   }
3762   return false;
3763 }
3764 
MP4SetMetadataArtist(MP4FileHandle hFile,const char * value)3765 extern "C" bool MP4SetMetadataArtist(MP4FileHandle hFile,
3766 				     const char* value)
3767 {
3768   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3769     try {
3770       return ((MP4File*)hFile)->SetMetadataString("\251ART", value);
3771     }
3772     catch (MP4Error* e) {
3773       PRINT_ERROR(e);
3774       delete e;
3775     }
3776   }
3777   return false;
3778 }
3779 
MP4GetMetadataArtist(MP4FileHandle hFile,char ** value)3780 extern "C" bool MP4GetMetadataArtist(MP4FileHandle hFile,
3781 				     char** value)
3782 {
3783   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3784     try {
3785       return ((MP4File*)hFile)->GetMetadataString("\251ART", value);
3786     }
3787     catch (MP4Error* e) {
3788       PRINT_ERROR(e);
3789       delete e;
3790     }
3791   }
3792   return false;
3793 }
3794 
MP4DeleteMetadataArtist(MP4FileHandle hFile)3795 extern "C" bool MP4DeleteMetadataArtist(MP4FileHandle hFile)
3796 {
3797   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3798     try {
3799       return ((MP4File*)hFile)->DeleteMetadataAtom("\251ART");
3800     }
3801     catch (MP4Error* e) {
3802       PRINT_ERROR(e);
3803       delete e;
3804     }
3805   }
3806   return false;
3807 }
3808 
MP4SetMetadataTool(MP4FileHandle hFile,const char * value)3809 extern "C" bool MP4SetMetadataTool(MP4FileHandle hFile,
3810 				   const char* value)
3811 {
3812   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3813     try {
3814       return ((MP4File*)hFile)->SetMetadataString("\251too", value);
3815     }
3816     catch (MP4Error* e) {
3817       PRINT_ERROR(e);
3818       delete e;
3819     }
3820   }
3821   return false;
3822 }
3823 
MP4GetMetadataTool(MP4FileHandle hFile,char ** value)3824 extern "C" bool MP4GetMetadataTool(MP4FileHandle hFile,
3825 				   char** value)
3826 {
3827   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3828     try {
3829       return ((MP4File*)hFile)->GetMetadataString("\251too", value);
3830     }
3831     catch (MP4Error* e) {
3832       PRINT_ERROR(e);
3833       delete e;
3834     }
3835   }
3836   return false;
3837 }
3838 
MP4DeleteMetadataTool(MP4FileHandle hFile)3839 extern "C" bool MP4DeleteMetadataTool(MP4FileHandle hFile)
3840 {
3841   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3842     try {
3843       return ((MP4File*)hFile)->DeleteMetadataAtom("\251too");
3844     }
3845     catch (MP4Error* e) {
3846       PRINT_ERROR(e);
3847       delete e;
3848     }
3849   }
3850   return false;
3851 }
3852 
MP4SetMetadataComment(MP4FileHandle hFile,const char * value)3853 extern "C" bool MP4SetMetadataComment(MP4FileHandle hFile,
3854 				      const char* value)
3855 {
3856   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3857     try {
3858       return ((MP4File*)hFile)->SetMetadataString("\251cmt", value);
3859     }
3860     catch (MP4Error* e) {
3861       PRINT_ERROR(e);
3862       delete e;
3863     }
3864   }
3865   return false;
3866 }
3867 
MP4GetMetadataComment(MP4FileHandle hFile,char ** value)3868 extern "C" bool MP4GetMetadataComment(MP4FileHandle hFile,
3869 				      char** value)
3870 {
3871   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3872     try {
3873       return ((MP4File*)hFile)->GetMetadataString("\251cmt", value);
3874     }
3875     catch (MP4Error* e) {
3876       PRINT_ERROR(e);
3877       delete e;
3878     }
3879   }
3880   return false;
3881 }
3882 
MP4DeleteMetadataComment(MP4FileHandle hFile)3883 extern "C" bool MP4DeleteMetadataComment(MP4FileHandle hFile)
3884 {
3885   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3886     try {
3887       return ((MP4File*)hFile)->DeleteMetadataAtom("\251cmt");
3888     }
3889     catch (MP4Error* e) {
3890       PRINT_ERROR(e);
3891       delete e;
3892     }
3893   }
3894   return false;
3895 }
3896 
MP4SetMetadataYear(MP4FileHandle hFile,const char * value)3897 extern "C" bool MP4SetMetadataYear(MP4FileHandle hFile,
3898 				   const char* value)
3899 {
3900   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3901     try {
3902       return ((MP4File*)hFile)->SetMetadataString("\251day", value);
3903     }
3904     catch (MP4Error* e) {
3905       PRINT_ERROR(e);
3906       delete e;
3907     }
3908   }
3909   return false;
3910 }
3911 
MP4GetMetadataYear(MP4FileHandle hFile,char ** value)3912 extern "C" bool MP4GetMetadataYear(MP4FileHandle hFile,
3913 				   char** value)
3914 {
3915   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3916     try {
3917       return ((MP4File*)hFile)->GetMetadataString("\251day", value);
3918     }
3919     catch (MP4Error* e) {
3920       PRINT_ERROR(e);
3921       delete e;
3922     }
3923   }
3924   return false;
3925 }
3926 
MP4DeleteMetadataYear(MP4FileHandle hFile)3927 extern "C" bool MP4DeleteMetadataYear(MP4FileHandle hFile)
3928 {
3929   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3930     try {
3931       return ((MP4File*)hFile)->DeleteMetadataAtom("\251day");
3932     }
3933     catch (MP4Error* e) {
3934       PRINT_ERROR(e);
3935       delete e;
3936     }
3937   }
3938   return false;
3939 }
3940 
MP4SetMetadataTrack(MP4FileHandle hFile,u_int16_t track,u_int16_t totalTracks)3941 extern "C" bool MP4SetMetadataTrack(MP4FileHandle hFile,
3942 				    u_int16_t track, u_int16_t totalTracks)
3943 {
3944   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3945     try {
3946       return ((MP4File*)hFile)->SetMetadataTrack(track, totalTracks);
3947     }
3948     catch (MP4Error* e) {
3949       PRINT_ERROR(e);
3950       delete e;
3951     }
3952   }
3953   return false;
3954 }
3955 
MP4GetMetadataTrack(MP4FileHandle hFile,u_int16_t * track,u_int16_t * totalTracks)3956 extern "C" bool MP4GetMetadataTrack(MP4FileHandle hFile,
3957 				    u_int16_t* track, u_int16_t* totalTracks)
3958 {
3959   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3960     try {
3961       return ((MP4File*)hFile)->GetMetadataTrack(track, totalTracks);
3962     }
3963     catch (MP4Error* e) {
3964       PRINT_ERROR(e);
3965       delete e;
3966     }
3967   }
3968   return false;
3969 }
3970 
MP4DeleteMetadataTrack(MP4FileHandle hFile)3971 extern "C" bool MP4DeleteMetadataTrack(MP4FileHandle hFile)
3972 {
3973   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3974     try {
3975       return ((MP4File*)hFile)->DeleteMetadataAtom("trkn");
3976     }
3977     catch (MP4Error* e) {
3978       PRINT_ERROR(e);
3979       delete e;
3980     }
3981   }
3982   return false;
3983 }
3984 
MP4SetMetadataDisk(MP4FileHandle hFile,u_int16_t disk,u_int16_t totalDisks)3985 extern "C" bool MP4SetMetadataDisk(MP4FileHandle hFile,
3986 				   u_int16_t disk, u_int16_t totalDisks)
3987 {
3988   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
3989     try {
3990       return ((MP4File*)hFile)->SetMetadataDisk(disk, totalDisks);
3991     }
3992     catch (MP4Error* e) {
3993       PRINT_ERROR(e);
3994       delete e;
3995     }
3996   }
3997   return false;
3998 }
3999 
MP4GetMetadataDisk(MP4FileHandle hFile,u_int16_t * disk,u_int16_t * totalDisks)4000 extern "C" bool MP4GetMetadataDisk(MP4FileHandle hFile,
4001 				   u_int16_t* disk, u_int16_t* totalDisks)
4002 {
4003   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4004     try {
4005       return ((MP4File*)hFile)->GetMetadataDisk(disk, totalDisks);
4006     }
4007     catch (MP4Error* e) {
4008       PRINT_ERROR(e);
4009       delete e;
4010     }
4011   }
4012   return false;
4013 }
4014 
MP4DeleteMetadataDisk(MP4FileHandle hFile)4015 extern "C" bool MP4DeleteMetadataDisk(MP4FileHandle hFile)
4016 {
4017   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4018     try {
4019       return ((MP4File*)hFile)->DeleteMetadataAtom("disk");
4020     }
4021     catch (MP4Error* e) {
4022       PRINT_ERROR(e);
4023       delete e;
4024     }
4025   }
4026   return false;
4027 }
4028 
MP4SetMetadataGenre(MP4FileHandle hFile,const char * genre)4029 extern "C" bool MP4SetMetadataGenre(MP4FileHandle hFile, const char *genre)
4030 {
4031   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4032     try {
4033       return ((MP4File*)hFile)->SetMetadataGenre(genre);
4034     }
4035     catch (MP4Error* e) {
4036       PRINT_ERROR(e);
4037       delete e;
4038     }
4039   }
4040   return false;
4041 }
4042 
MP4GetMetadataGenre(MP4FileHandle hFile,char ** genre)4043 extern "C" bool MP4GetMetadataGenre(MP4FileHandle hFile, char **genre)
4044 {
4045   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4046     try {
4047       return ((MP4File*)hFile)->GetMetadataGenre(genre);
4048     }
4049     catch (MP4Error* e) {
4050       PRINT_ERROR(e);
4051       delete e;
4052     }
4053   }
4054   return false;
4055 }
4056 
MP4DeleteMetadataGenre(MP4FileHandle hFile)4057 extern "C" bool MP4DeleteMetadataGenre(MP4FileHandle hFile)
4058 {
4059   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4060     try {
4061       return ((MP4File*)hFile)->DeleteMetadataGenre();
4062     }
4063     catch (MP4Error* e) {
4064       PRINT_ERROR(e);
4065       delete e;
4066     }
4067   }
4068   return false;
4069 }
4070 
MP4SetMetadataGrouping(MP4FileHandle hFile,const char * grouping)4071 extern "C" bool MP4SetMetadataGrouping(MP4FileHandle hFile, const char *grouping)
4072 {
4073   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4074     try {
4075       return ((MP4File*)hFile)->SetMetadataString("\251grp", grouping);
4076     }
4077     catch (MP4Error* e) {
4078       PRINT_ERROR(e);
4079       delete e;
4080     }
4081   }
4082   return false;
4083 }
4084 
MP4GetMetadataGrouping(MP4FileHandle hFile,char ** grouping)4085 extern "C" bool MP4GetMetadataGrouping(MP4FileHandle hFile, char **grouping)
4086 {
4087   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4088     try {
4089       return ((MP4File*)hFile)->GetMetadataString("\251grp", grouping);
4090     }
4091     catch (MP4Error* e) {
4092       PRINT_ERROR(e);
4093       delete e;
4094     }
4095   }
4096   return false;
4097 }
4098 
MP4DeleteMetadataGrouping(MP4FileHandle hFile)4099 extern "C" bool MP4DeleteMetadataGrouping(MP4FileHandle hFile)
4100 {
4101   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4102     try {
4103       return ((MP4File*)hFile)->DeleteMetadataAtom("\251grp");
4104     }
4105     catch (MP4Error* e) {
4106       PRINT_ERROR(e);
4107       delete e;
4108     }
4109   }
4110   return false;
4111 }
4112 
MP4SetMetadataTempo(MP4FileHandle hFile,u_int16_t tempo)4113 extern "C" bool MP4SetMetadataTempo(MP4FileHandle hFile, u_int16_t tempo)
4114 {
4115   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4116     try {
4117       return ((MP4File*)hFile)->SetMetadataTempo(tempo);
4118     }
4119     catch (MP4Error* e) {
4120       PRINT_ERROR(e);
4121       delete e;
4122     }
4123   }
4124   return false;
4125 }
4126 
MP4GetMetadataTempo(MP4FileHandle hFile,u_int16_t * tempo)4127 extern "C" bool MP4GetMetadataTempo(MP4FileHandle hFile, u_int16_t* tempo)
4128 {
4129   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4130     try {
4131       return ((MP4File*)hFile)->GetMetadataTempo(tempo);
4132     }
4133     catch (MP4Error* e) {
4134       PRINT_ERROR(e);
4135       delete e;
4136     }
4137   }
4138   return false;
4139 }
4140 
MP4DeleteMetadataTempo(MP4FileHandle hFile)4141 extern "C" bool MP4DeleteMetadataTempo(MP4FileHandle hFile)
4142 {
4143   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4144     try {
4145       return ((MP4File*)hFile)->DeleteMetadataAtom("tmpo");
4146     }
4147     catch (MP4Error* e) {
4148       PRINT_ERROR(e);
4149       delete e;
4150     }
4151   }
4152   return false;
4153 }
4154 
MP4SetMetadataCompilation(MP4FileHandle hFile,u_int8_t cpl)4155 extern "C" bool MP4SetMetadataCompilation(MP4FileHandle hFile, u_int8_t cpl)
4156 {
4157   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4158     try {
4159       return ((MP4File*)hFile)->SetMetadataUint8("cpil", cpl & 0x1);
4160     }
4161     catch (MP4Error* e) {
4162       PRINT_ERROR(e);
4163       delete e;
4164     }
4165   }
4166   return false;
4167 }
4168 
MP4GetMetadataCompilation(MP4FileHandle hFile,u_int8_t * cpl)4169 extern "C" bool MP4GetMetadataCompilation(MP4FileHandle hFile, u_int8_t* cpl)
4170 {
4171   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4172     try {
4173       return ((MP4File*)hFile)->GetMetadataUint8("cpil", cpl);
4174     }
4175     catch (MP4Error* e) {
4176       PRINT_ERROR(e);
4177       delete e;
4178     }
4179   }
4180   return false;
4181 }
4182 
MP4DeleteMetadataCompilation(MP4FileHandle hFile)4183 extern "C" bool MP4DeleteMetadataCompilation(MP4FileHandle hFile)
4184 {
4185   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4186     try {
4187       return ((MP4File*)hFile)->DeleteMetadataAtom("cpil");
4188     }
4189     catch (MP4Error* e) {
4190       PRINT_ERROR(e);
4191       delete e;
4192     }
4193   }
4194   return false;
4195 }
4196 
MP4SetMetadataPartOfGaplessAlbum(MP4FileHandle hFile,u_int8_t pgap)4197 extern "C" bool MP4SetMetadataPartOfGaplessAlbum (MP4FileHandle hFile,
4198 						  u_int8_t pgap)
4199 {
4200   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4201     try {
4202       return ((MP4File*)hFile)->SetMetadataUint8("pgap", pgap & 0x1);
4203     }
4204     catch (MP4Error* e) {
4205       PRINT_ERROR(e);
4206       delete e;
4207     }
4208   }
4209   return false;
4210 }
4211 
MP4GetMetadataPartOfGaplessAlbum(MP4FileHandle hFile,u_int8_t * pgap)4212 extern "C" bool MP4GetMetadataPartOfGaplessAlbum (MP4FileHandle hFile,
4213 						  u_int8_t* pgap)
4214 {
4215   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4216     try {
4217       return ((MP4File*)hFile)->GetMetadataUint8("pgap", pgap);
4218     }
4219     catch (MP4Error* e) {
4220       PRINT_ERROR(e);
4221       delete e;
4222     }
4223   }
4224   return false;
4225 }
4226 
MP4DeleteMetadataPartOfGaplessAlbum(MP4FileHandle hFile)4227 extern "C" bool MP4DeleteMetadataPartOfGaplessAlbum (MP4FileHandle hFile)
4228 {
4229   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4230     try {
4231       return ((MP4File*)hFile)->DeleteMetadataAtom("pgap");
4232     }
4233     catch (MP4Error* e) {
4234       PRINT_ERROR(e);
4235       delete e;
4236     }
4237   }
4238   return false;
4239 }
4240 
MP4SetMetadataCoverArt(MP4FileHandle hFile,u_int8_t * coverArt,u_int32_t size)4241 extern "C" bool MP4SetMetadataCoverArt(MP4FileHandle hFile,
4242 				       u_int8_t *coverArt, u_int32_t size)
4243 {
4244   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4245     try {
4246       return ((MP4File*)hFile)->SetMetadataCoverArt(coverArt, size);
4247     }
4248     catch (MP4Error* e) {
4249       PRINT_ERROR(e);
4250       delete e;
4251     }
4252   }
4253   return false;
4254 }
4255 
MP4GetMetadataCoverArt(MP4FileHandle hFile,u_int8_t ** coverArt,u_int32_t * size,uint32_t index)4256 extern "C" bool MP4GetMetadataCoverArt(MP4FileHandle hFile,
4257 				       u_int8_t **coverArt, u_int32_t* size,
4258 				       uint32_t index)
4259 {
4260   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4261     try {
4262       return ((MP4File*)hFile)->GetMetadataCoverArt(coverArt, size, index);
4263     }
4264     catch (MP4Error* e) {
4265       PRINT_ERROR(e);
4266       delete e;
4267     }
4268   }
4269   return false;
4270 }
4271 
MP4GetMetadataCoverArtCount(MP4FileHandle hFile)4272 extern "C" u_int32_t MP4GetMetadataCoverArtCount(MP4FileHandle hFile)
4273 {
4274   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4275     try {
4276       return ((MP4File*)hFile)->GetMetadataCoverArtCount();
4277     }
4278     catch (MP4Error* e) {
4279       PRINT_ERROR(e);
4280       delete e;
4281     }
4282   }
4283   return false;
4284 }
4285 
MP4DeleteMetadataCoverArt(MP4FileHandle hFile)4286 extern "C" bool MP4DeleteMetadataCoverArt(MP4FileHandle hFile)
4287 {
4288   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4289     try {
4290       return ((MP4File*)hFile)->DeleteMetadataAtom("covr");
4291     }
4292     catch (MP4Error* e) {
4293       PRINT_ERROR(e);
4294       delete e;
4295     }
4296   }
4297   return false;
4298 }
MP4SetMetadataAlbumArtist(MP4FileHandle hFile,const char * value)4299 extern "C" bool MP4SetMetadataAlbumArtist (MP4FileHandle hFile,
4300 					   const char* value)
4301 {
4302  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4303    try {
4304      return ((MP4File*)hFile)->SetMetadataString("aART", value);
4305    }
4306    catch (MP4Error* e) {
4307      PRINT_ERROR(e);
4308      delete e;
4309    }
4310  }
4311  return false;
4312 }
4313 
MP4GetMetadataAlbumArtist(MP4FileHandle hFile,char ** value)4314 extern "C" bool MP4GetMetadataAlbumArtist (MP4FileHandle hFile,
4315 					   char** value)
4316 {
4317  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4318    try {
4319      return ((MP4File*)hFile)->GetMetadataString("aART", value);
4320    }
4321    catch (MP4Error* e) {
4322      PRINT_ERROR(e);
4323      delete e;
4324    }
4325  }
4326  return false;
4327 }
4328 
MP4DeleteMetadataAlbumArtist(MP4FileHandle hFile)4329 extern "C" bool MP4DeleteMetadataAlbumArtist (MP4FileHandle hFile)
4330 {
4331  if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4332    try {
4333      return ((MP4File*)hFile)->DeleteMetadataAtom("aART");
4334    }
4335    catch (MP4Error* e) {
4336      PRINT_ERROR(e);
4337      delete e;
4338    }
4339  }
4340  return false;
4341 }
4342 
MP4SetMetadataFreeForm(MP4FileHandle hFile,const char * name,const u_int8_t * pValue,u_int32_t valueSize,const char * owner)4343 extern "C" bool MP4SetMetadataFreeForm(MP4FileHandle hFile,
4344 				       const char *name,
4345 				       const u_int8_t* pValue,
4346 				       u_int32_t valueSize,
4347 							 const char *owner)
4348 {
4349   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4350     try {
4351       return ((MP4File*)hFile)->SetMetadataFreeForm(name, pValue, valueSize, owner);
4352     }
4353     catch (MP4Error* e) {
4354       PRINT_ERROR(e);
4355       delete e;
4356     }
4357   }
4358   return false;
4359 }
4360 
MP4GetMetadataFreeForm(MP4FileHandle hFile,const char * name,u_int8_t ** pValue,u_int32_t * valueSize,const char * owner)4361 extern "C" bool MP4GetMetadataFreeForm(MP4FileHandle hFile, const char *name,
4362 				       u_int8_t** pValue, u_int32_t* valueSize, const char *owner)
4363 {
4364   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4365     try {
4366       return ((MP4File*)hFile)->GetMetadataFreeForm(name, pValue, valueSize, owner);
4367     }
4368     catch (MP4Error* e) {
4369       PRINT_ERROR(e);
4370       delete e;
4371     }
4372   }
4373   return false;
4374 }
4375 
MP4DeleteMetadataFreeForm(MP4FileHandle hFile,const char * name,const char * owner)4376 extern "C" bool MP4DeleteMetadataFreeForm(MP4FileHandle hFile, const char *name, const char *owner)
4377 {
4378   if (MP4_IS_VALID_FILE_HANDLE(hFile)) {
4379     try {
4380       return ((MP4File*)hFile)->DeleteMetadataFreeForm(name, owner);
4381     }
4382     catch (MP4Error* e) {
4383       PRINT_ERROR(e);
4384       delete e;
4385     }
4386   }
4387   return false;
4388 }
4389 
4390 
MP4Free(void * p)4391 extern "C" void MP4Free (void *p)
4392 {
4393   if (p != NULL)
4394     free(p);
4395 }
4396