|
1 // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // |
|
15 |
|
16 #include <3gplibrary/mp4config.h> |
|
17 #include <3gplibrary/mp4lib.h> |
|
18 #include "mp4atom.h" |
|
19 #include "mp4memwrap.h" |
|
20 #include "mp4file.h" |
|
21 #include "mp4endian.h" |
|
22 #include "mp4compose.h" |
|
23 #include "mp4currenttime.h" |
|
24 #include "mp4utils.h" |
|
25 |
|
26 #define MP4_INT_MAX KMaxTInt32 |
|
27 #define MDAT_HEADER_SIZE 16 |
|
28 |
|
29 // MACROS |
|
30 // Debug print macro |
|
31 #ifdef _DEBUG |
|
32 #include <e32svr.h> |
|
33 #define PRINT(x) |
|
34 #else |
|
35 #define PRINT(x) |
|
36 #endif |
|
37 |
|
38 |
|
39 inline void updateChunkOffset(sampleTable *st, mp4_i32 index, mp4_i64 value) |
|
40 { |
|
41 if (value > MP4_INT_MAX) |
|
42 st->stcoNeed64Bits = ETrue; |
|
43 |
|
44 st->stcoChunkOffset[index] = value; |
|
45 } |
|
46 |
|
47 /* must be called after determineAudioTrakMetaDataSize and determineVideoTrakMetaDataSize */ |
|
48 size_t mvhdAtomSize(MP4HandleImp handle) |
|
49 { |
|
50 if (handle->videoDuration > MP4_INT_MAX || handle->audioDuration > MP4_INT_MAX) |
|
51 { |
|
52 return 120; |
|
53 } |
|
54 else |
|
55 { |
|
56 return 108; |
|
57 } |
|
58 } |
|
59 |
|
60 |
|
61 |
|
62 /* helper functions */ |
|
63 mp4_i32 formatMdatHeader(mp4_u8 *buffer, mp4_i64 size); |
|
64 |
|
65 /* |
|
66 * Function: |
|
67 * |
|
68 * mp4_i32 updateVideoMetaData(MP4HandleImp handle, |
|
69 * mp4_u32 size, |
|
70 * mp4_u32 duration) |
|
71 * |
|
72 * Description: |
|
73 * |
|
74 * This function updates sample table atom data. |
|
75 * |
|
76 * One call of this function will generate one chunk in the MP4 file. |
|
77 * |
|
78 * Parameters: |
|
79 * |
|
80 * handle MP4 library handle |
|
81 * size Size of video frame to insert |
|
82 * duration Duration of the video frame (in media timescale) |
|
83 * |
|
84 * Return value: |
|
85 * |
|
86 * 0 Success |
|
87 * -1 Error |
|
88 * |
|
89 */ |
|
90 mp4_i32 updateVideoMetaData(MP4HandleImp handle, mp4_u32 size, mp4_u32 duration, mp4_bool keyframe) |
|
91 { |
|
92 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
93 { |
|
94 if (handle->metaDataBlocks == BLOCK_LIMIT) |
|
95 { |
|
96 /* Write metadata to temporary files */ |
|
97 |
|
98 if (writeMetaDataTmp(handle) < 0) |
|
99 return -1; |
|
100 } |
|
101 |
|
102 handle->metaDataBlocks++; |
|
103 } |
|
104 |
|
105 handle->videoSampleTable->currentChunk++; |
|
106 |
|
107 if (updateDecodingTimeToSample(handle, handle->videoSampleTable, duration) < 0) |
|
108 return -1; |
|
109 |
|
110 if (updateSampleSize(handle, handle->videoSampleTable, size) < 0) |
|
111 return -1; |
|
112 |
|
113 if (updateSampleToChunk(handle->videoSampleTable) < 0) |
|
114 return -1; |
|
115 |
|
116 if (updateChunkOffset(handle, handle->videoSampleTable) < 0) |
|
117 return -1; |
|
118 |
|
119 if (keyframe) |
|
120 if (updateSyncSample(handle, handle->videoSampleTable) < 0) |
|
121 return -1; |
|
122 |
|
123 return 0; |
|
124 } |
|
125 |
|
126 |
|
127 /* |
|
128 * Function: |
|
129 * |
|
130 * mp4_i32 updateAudioMetaData(MP4HandleImp handle, |
|
131 * mp4_u32 size, |
|
132 * mp4_u32 numberofframes) |
|
133 * |
|
134 * Description: |
|
135 * |
|
136 * This function updates sample table atom data. |
|
137 * |
|
138 * One call of this function will generate one chunk in the MP4 file. |
|
139 * |
|
140 * Parameters: |
|
141 * |
|
142 * handle MP4 library handle |
|
143 * size Size of video frame to insert |
|
144 * duration Duration of audio frames (in timescale, |
|
145 * see MP4ComposeAddAudioDescription) |
|
146 * |
|
147 * Return value: |
|
148 * |
|
149 * 0 Success |
|
150 * -1 Error |
|
151 * |
|
152 */ |
|
153 mp4_i32 updateAudioMetaData(MP4HandleImp handle, mp4_u32 size, mp4_u32 duration) |
|
154 { |
|
155 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
156 { |
|
157 if (handle->metaDataBlocks == BLOCK_LIMIT) |
|
158 { |
|
159 /* Write metadata to temporary files */ |
|
160 |
|
161 if (writeMetaDataTmp(handle) < 0) |
|
162 return -1; |
|
163 } |
|
164 |
|
165 handle->metaDataBlocks++; |
|
166 } |
|
167 |
|
168 handle->audioSampleTable->currentChunk++; |
|
169 |
|
170 if (updateDecodingTimeToSample(handle, handle->audioSampleTable, duration) < 0) |
|
171 return -1; |
|
172 |
|
173 if (updateSampleSize(handle, handle->audioSampleTable, size) < 0) |
|
174 return -1; |
|
175 |
|
176 if (updateSampleToChunk(handle->audioSampleTable) < 0) |
|
177 return -1; |
|
178 |
|
179 if (updateChunkOffset(handle, handle->audioSampleTable) < 0) |
|
180 return -1; |
|
181 |
|
182 return 0; |
|
183 } |
|
184 |
|
185 |
|
186 /* |
|
187 * Function: |
|
188 * |
|
189 * mp4_i32 writeFTYPAndMDATToFile(MP4HandleImp handle) |
|
190 * |
|
191 * Description: |
|
192 * |
|
193 * This function writes FTYP box to a file. In addition, it writes MDAT box |
|
194 * size and type to a file. The function is used when meta data is put to |
|
195 * the end of file. |
|
196 * |
|
197 * Parameters: |
|
198 * |
|
199 * handle MP4 library handle |
|
200 * |
|
201 * Return value: |
|
202 * |
|
203 * 0 Success |
|
204 * -1 Error |
|
205 * |
|
206 */ |
|
207 mp4_i32 writeFTYPAndMDATToFile(MP4HandleImp handle) |
|
208 { |
|
209 mp4_u8 buf[32]; |
|
210 mp4_u32 i = 0; |
|
211 |
|
212 |
|
213 if (writeFTYP(handle) < 0) |
|
214 return -1; |
|
215 |
|
216 handle->ftypWritten = MP4TRUE; |
|
217 |
|
218 |
|
219 i = formatMdatHeader(buf, (mp4_u32)0); |
|
220 if (writeFile(handle, buf, i) < 0) |
|
221 return -1; |
|
222 |
|
223 return 0; |
|
224 } |
|
225 |
|
226 |
|
227 /* |
|
228 * Function: |
|
229 * |
|
230 * mp4_i32 writeDataToFile(MP4HandleImp handle) |
|
231 * |
|
232 * Description: |
|
233 * |
|
234 * This function writes meta and media data to a file. |
|
235 * |
|
236 * Parameters: |
|
237 * |
|
238 * handle MP4 library handle |
|
239 * |
|
240 * Return value: |
|
241 * |
|
242 * 0 Success |
|
243 * -1 Error |
|
244 * |
|
245 */ |
|
246 mp4_i32 writeDataToFile(MP4HandleImp handle) |
|
247 { |
|
248 PRINT((_L("e_writedatatofile 1"))); |
|
249 mp4_u32 metaDataSize = 0; |
|
250 trakSize *audioTrackSize; |
|
251 trakSize *videoTrackSize; |
|
252 mp4_bool haveAudio = MP4FALSE; |
|
253 mp4_bool haveVideo = MP4FALSE; |
|
254 mp4_u8 ftypdelta = 0; |
|
255 |
|
256 |
|
257 if ((handle->type & MP4_TYPE_AMR_NB) || |
|
258 (handle->type & MP4_TYPE_AMR_WB) || |
|
259 (handle->type & MP4_TYPE_QCELP_13K) || |
|
260 (handle->type & MP4_TYPE_MPEG4_AUDIO)) |
|
261 haveAudio = MP4TRUE; |
|
262 |
|
263 if ((handle->type & MP4_TYPE_H263_PROFILE_0) || |
|
264 (handle->type & MP4_TYPE_H263_PROFILE_3) || |
|
265 (handle->type & MP4_TYPE_MPEG4_VIDEO) || |
|
266 containsAvcVideo( handle->type ) ) |
|
267 haveVideo = MP4TRUE; |
|
268 |
|
269 if ((handle->generate3G2 && !(handle->type & MP4_TYPE_QCELP_13K)) || |
|
270 (!handle->generate3G2 && !(handle->type & MP4_TYPE_AMR_WB))) |
|
271 ftypdelta = 4; /* one more additional compatible brand */ |
|
272 else |
|
273 ftypdelta = 0; |
|
274 |
|
275 if( containsAvcVideo( handle->type ) ) |
|
276 { |
|
277 ftypdelta += 4; |
|
278 } |
|
279 |
|
280 PRINT((_L("e_writedatatofile_alloc_audiotrk 1"))); |
|
281 audioTrackSize = (trakSize *)mp4malloc(sizeof(trakSize)); |
|
282 if (audioTrackSize == NULL) |
|
283 return -1; |
|
284 PRINT((_L("e_writedatatofile_alloc_audiotrk 0"))); |
|
285 |
|
286 PRINT((_L("e_writedatatofile_alloc_videotrk 1"))); |
|
287 videoTrackSize = (trakSize *)mp4malloc(sizeof(trakSize)); |
|
288 if (videoTrackSize == NULL) |
|
289 { |
|
290 mp4free(audioTrackSize); |
|
291 |
|
292 return -1; |
|
293 } |
|
294 PRINT((_L("e_writedatatofile_alloc_videotrk 0"))); |
|
295 |
|
296 if (haveAudio) |
|
297 { |
|
298 PRINT((_L("e_writedatatofile_deter_audiotrk_metadatasize 1"))); |
|
299 if (determineAudioTrakMetaDataSize(handle, handle->audioSampleTable, audioTrackSize) < 0) |
|
300 { |
|
301 mp4free(audioTrackSize); |
|
302 mp4free(videoTrackSize); |
|
303 return -1; |
|
304 } |
|
305 PRINT((_L("e_writedatatofile_deter_audiotrk_metadatasize 0"))); |
|
306 } |
|
307 |
|
308 if (haveVideo) |
|
309 { |
|
310 PRINT((_L("e_writedatatofile_deter_videotrk_metadatasize 1"))); |
|
311 if (determineVideoTrakMetaDataSize(handle, handle->videoSampleTable, videoTrackSize) < 0) |
|
312 { |
|
313 mp4free(audioTrackSize); |
|
314 mp4free(videoTrackSize); |
|
315 return -1; |
|
316 } |
|
317 PRINT((_L("e_writedatatofile_deter_videotrk_metadatasize 0"))); |
|
318 } |
|
319 |
|
320 if (handle->flags & MP4_FLAG_METADATALAST) |
|
321 { |
|
322 metaDataSize += (FTYP_SIZE + ftypdelta); /* ftyp */ |
|
323 handle->metaDataSize = metaDataSize; |
|
324 } |
|
325 else |
|
326 { |
|
327 metaDataSize += (FTYP_SIZE + ftypdelta); /* ftyp */ |
|
328 metaDataSize += 8; /* moov atomheader */ |
|
329 metaDataSize += mvhdAtomSize(handle); /* mvhd */ |
|
330 if (handle->moovUDTA) |
|
331 { |
|
332 metaDataSize += 8 + (mp4_u32)handle->moovUDTA->atomcontentsize; |
|
333 } |
|
334 metaDataSize += audioTrackSize->trak; /* Audio trak */ |
|
335 metaDataSize += videoTrackSize->trak; /* Video trak */ |
|
336 |
|
337 handle->metaDataSize = metaDataSize; |
|
338 } |
|
339 |
|
340 |
|
341 if (!(handle->flags & MP4_FLAG_LONGCLIP)) |
|
342 { |
|
343 /* Update metadata pointers only if metadata is in memory */ |
|
344 |
|
345 if (haveAudio) |
|
346 { |
|
347 PRINT((_L("e_writedatatofile_reupdata_audiometadata 1"))); |
|
348 if (reUpdateAudioMetaData(handle->audioSampleTable, metaDataSize) < 0) |
|
349 { |
|
350 mp4free(audioTrackSize); |
|
351 mp4free(videoTrackSize); |
|
352 |
|
353 return -1; |
|
354 } |
|
355 PRINT((_L("e_writedatatofile_reupdata_audiometadata 0"))); |
|
356 } |
|
357 |
|
358 if (haveVideo) |
|
359 { |
|
360 PRINT((_L("e_writedatatofile_reupdata_videometadata 1"))); |
|
361 if (reUpdateVideoMetaData(handle->videoSampleTable, metaDataSize) < 0) |
|
362 { |
|
363 mp4free(audioTrackSize); |
|
364 mp4free(videoTrackSize); |
|
365 |
|
366 return -1; |
|
367 } |
|
368 PRINT((_L("e_writedatatofile_reupdata_videometadata 0"))); |
|
369 } |
|
370 } |
|
371 else |
|
372 { |
|
373 /* Write the rest of metadata to temporary files */ |
|
374 PRINT((_L("e_writedatatofile_write_metadatablocks 1"))); |
|
375 if (handle->metaDataBlocks) |
|
376 if (writeMetaDataTmp(handle) < 0) |
|
377 { |
|
378 mp4free(audioTrackSize); |
|
379 mp4free(videoTrackSize); |
|
380 return -1; |
|
381 } |
|
382 PRINT((_L("e_writedatatofile_write_metadatablocks 0"))); |
|
383 } |
|
384 |
|
385 |
|
386 if (handle->flags & MP4_FLAG_METADATALAST) |
|
387 { |
|
388 mp4_u8 buf[16]; |
|
389 mp4_u32 moovSize = 0; |
|
390 |
|
391 moovSize += 8; /* moov atomheader */ |
|
392 moovSize += mvhdAtomSize(handle); /* mvhd */ |
|
393 moovSize += audioTrackSize->trak; /* Audio trak */ |
|
394 moovSize += videoTrackSize->trak; /* Video trak */ |
|
395 if (handle->moovUDTA) |
|
396 { |
|
397 moovSize += 8 + handle->moovUDTA->atomcontentsize; |
|
398 } |
|
399 |
|
400 PRINT((_L("e_writedatatofile_write_moov 1"))); |
|
401 if (writeMOOV(handle, moovSize, haveAudio, haveVideo, audioTrackSize, videoTrackSize) < 0) |
|
402 { |
|
403 mp4free(audioTrackSize); |
|
404 mp4free(videoTrackSize); |
|
405 |
|
406 return -1; |
|
407 } |
|
408 PRINT((_L("e_writedatatofile_write_moov 0"))); |
|
409 |
|
410 /* Overwrite media data size */ |
|
411 PRINT((_L("e_writedatatofile_update_moov_media_size 1"))); |
|
412 if(!handle->bufferWrite) |
|
413 { |
|
414 if (seekFileAbsWrite(handle, (FTYP_SIZE + ftypdelta)) != 0) |
|
415 { |
|
416 mp4free(audioTrackSize); |
|
417 mp4free(videoTrackSize); |
|
418 return -1; |
|
419 } |
|
420 } |
|
421 |
|
422 //make sure the buf is large enough to hold the mdat header |
|
423 TInt i; |
|
424 i = formatMdatHeader(buf, handle->mediaDataBytes); |
|
425 if (writeFileUnbuffered(handle, buf, i) < 0) |
|
426 { |
|
427 mp4free(audioTrackSize); |
|
428 mp4free(videoTrackSize); |
|
429 return -1; |
|
430 } |
|
431 PRINT((_L("e_writedatatofile_update_moov_media_size 0"))); |
|
432 } |
|
433 else |
|
434 { |
|
435 PRINT((_L("e_writedatatofile_write_ftyp 1"))); |
|
436 if (writeFTYP(handle) < 0) |
|
437 { |
|
438 mp4free(audioTrackSize); |
|
439 mp4free(videoTrackSize); |
|
440 |
|
441 return -1; |
|
442 } |
|
443 PRINT((_L("e_writedatatofile_write_ftyp 0"))); |
|
444 |
|
445 PRINT((_L("e_writedatatofile_write_new_moov 1"))); |
|
446 if (writeMOOV(handle, metaDataSize - (FTYP_SIZE + ftypdelta), haveAudio, haveVideo, audioTrackSize, videoTrackSize) < 0) |
|
447 { |
|
448 mp4free(audioTrackSize); |
|
449 mp4free(videoTrackSize); |
|
450 |
|
451 return -1; |
|
452 } |
|
453 PRINT((_L("e_writedatatofile_write_new_moov 0"))); |
|
454 |
|
455 PRINT((_L("e_writedatatofile_write_new_mdia 1"))); |
|
456 if (writeMediaData(handle) < 0) |
|
457 { |
|
458 mp4free(audioTrackSize); |
|
459 mp4free(videoTrackSize); |
|
460 |
|
461 return -1; |
|
462 } |
|
463 PRINT((_L("e_writedatatofile_write_new_mdia 0"))); |
|
464 } |
|
465 |
|
466 PRINT((_L("e_writedatatofile_free_audioandvideotrks 1"))); |
|
467 mp4free(audioTrackSize); |
|
468 mp4free(videoTrackSize); |
|
469 PRINT((_L("e_writedatatofile_free_audioandvideotrks 0"))); |
|
470 PRINT((_L("e_writedatatofile 0"))); |
|
471 return 0; |
|
472 } |
|
473 |
|
474 |
|
475 /* |
|
476 * Function: |
|
477 * |
|
478 * mp4_i32 updateDecodingTimeToSample(MP4HandleImp handle, |
|
479 * sampleTable *st, |
|
480 * mp4_u32 duration) |
|
481 * |
|
482 * Description: |
|
483 * |
|
484 * This function updates stts atom data. |
|
485 * |
|
486 * Parameters: |
|
487 * |
|
488 * handle MP4 library handle |
|
489 * st sampleTable |
|
490 * duration Duration of sample to insert (in media timescale) |
|
491 * |
|
492 * Return value: |
|
493 * |
|
494 * 0 Success |
|
495 * -1 Error |
|
496 * |
|
497 */ |
|
498 mp4_i32 updateDecodingTimeToSample(MP4HandleImp handle, sampleTable *st, mp4_u32 duration) |
|
499 { |
|
500 if (!handle) |
|
501 return -1; |
|
502 |
|
503 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
504 { |
|
505 if (st->sttsCurrentEntryCount == 0) |
|
506 { |
|
507 st->sttsSampleCount[st->sttsCurrentEntryCount] = 1; |
|
508 st->sttsSampleDelta[st->sttsCurrentEntryCount] = duration; |
|
509 |
|
510 st->sttsCurrentEntryCount++; |
|
511 st->sttsEntryCount++; |
|
512 |
|
513 return 0; |
|
514 } |
|
515 |
|
516 if (st->sttsCurrentEntryCount == st->sttsMaxEntryCount) |
|
517 { |
|
518 void *p; |
|
519 |
|
520 p = mp4realloc(st->sttsSampleCount, |
|
521 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, |
|
522 sizeof(mp4_u32) * st->sttsMaxEntryCount); |
|
523 if (p == NULL) |
|
524 return -1; |
|
525 |
|
526 st->sttsSampleCount = (mp4_u32 *)p; |
|
527 |
|
528 p = mp4realloc(st->sttsSampleDelta, |
|
529 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, |
|
530 sizeof(mp4_u32) * st->sttsMaxEntryCount); |
|
531 if (p == NULL) |
|
532 return -1; |
|
533 |
|
534 st->sttsSampleDelta = (mp4_u32 *)p; |
|
535 |
|
536 st->sttsMaxEntryCount *= 2; |
|
537 } |
|
538 |
|
539 if (st->sttsSampleDelta[st->sttsCurrentEntryCount - 1] == duration) |
|
540 { |
|
541 st->sttsSampleCount[st->sttsCurrentEntryCount - 1]++; |
|
542 } |
|
543 else |
|
544 { |
|
545 st->sttsSampleCount[st->sttsCurrentEntryCount] = 1; |
|
546 st->sttsSampleDelta[st->sttsCurrentEntryCount] = duration; |
|
547 |
|
548 st->sttsCurrentEntryCount++; |
|
549 st->sttsEntryCount++; |
|
550 } |
|
551 } |
|
552 else |
|
553 { |
|
554 if (st->sttsEntryCount == 0) |
|
555 { |
|
556 st->sttsSampleCount[st->sttsEntryCount]++; |
|
557 st->sttsSampleDelta[st->sttsEntryCount] = duration; |
|
558 |
|
559 st->sttsEntryCount++; |
|
560 |
|
561 return 0; |
|
562 } |
|
563 |
|
564 if (st->sttsEntryCount == st->sttsMaxEntryCount) |
|
565 { |
|
566 void *p; |
|
567 |
|
568 p = mp4realloc(st->sttsSampleCount, |
|
569 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, |
|
570 sizeof(mp4_u32) * st->sttsMaxEntryCount); |
|
571 if (p == NULL) |
|
572 return -1; |
|
573 |
|
574 st->sttsSampleCount = (mp4_u32 *)p; |
|
575 |
|
576 p = mp4realloc(st->sttsSampleDelta, |
|
577 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, |
|
578 sizeof(mp4_u32) * st->sttsMaxEntryCount); |
|
579 if (p == NULL) |
|
580 return -1; |
|
581 |
|
582 st->sttsSampleDelta = (mp4_u32 *)p; |
|
583 |
|
584 st->sttsMaxEntryCount *= 2; |
|
585 } |
|
586 |
|
587 if (st->sttsSampleDelta[st->sttsEntryCount - 1] == duration) |
|
588 { |
|
589 st->sttsSampleCount[st->sttsEntryCount - 1]++; |
|
590 } |
|
591 else |
|
592 { |
|
593 st->sttsSampleCount[st->sttsEntryCount] = 1; |
|
594 st->sttsSampleDelta[st->sttsEntryCount] = duration; |
|
595 |
|
596 st->sttsEntryCount++; |
|
597 } |
|
598 } |
|
599 |
|
600 |
|
601 return 0; |
|
602 } |
|
603 |
|
604 |
|
605 /* |
|
606 * Function: |
|
607 * |
|
608 * mp4_i32 updateSampleSize(MP4HandleImp handle, |
|
609 * sampleTable *st, |
|
610 * mp4_u32 size) |
|
611 * |
|
612 * Description: |
|
613 * |
|
614 * This function updates stsz atom data. |
|
615 * |
|
616 * Parameters: |
|
617 * |
|
618 * handle MP4 library handle |
|
619 * st sampleTable |
|
620 * size Size of sample in bytes |
|
621 * |
|
622 * Return value: |
|
623 * |
|
624 * 0 Success |
|
625 * -1 Error |
|
626 * |
|
627 */ |
|
628 mp4_i32 updateSampleSize(MP4HandleImp handle, sampleTable *st, mp4_u32 size) |
|
629 { |
|
630 if (!handle) |
|
631 return -1; |
|
632 |
|
633 if (size == 0) |
|
634 return -1; |
|
635 |
|
636 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
637 { |
|
638 if (st->stszCurrentSampleCount == st->stszMaxSampleCount) |
|
639 { |
|
640 void *p; |
|
641 |
|
642 p = mp4realloc(st->stszEntrySize, |
|
643 2 * sizeof(mp4_u32) * st->stszMaxSampleCount, |
|
644 sizeof(mp4_u32) * st->stszMaxSampleCount); |
|
645 if (p == NULL) |
|
646 return -1; |
|
647 |
|
648 st->stszEntrySize = (mp4_u32 *)p; |
|
649 |
|
650 st->stszMaxSampleCount *= 2; |
|
651 } |
|
652 |
|
653 st->stszEntrySize[st->stszCurrentSampleCount] = size; |
|
654 |
|
655 st->stszCurrentSampleCount++; |
|
656 st->stszSampleCount++; |
|
657 } |
|
658 else |
|
659 { |
|
660 if (st->stszSampleCount == st->stszMaxSampleCount) |
|
661 { |
|
662 void *p; |
|
663 |
|
664 p = mp4realloc(st->stszEntrySize, |
|
665 2 * sizeof(mp4_u32) * st->stszMaxSampleCount, |
|
666 sizeof(mp4_u32) * st->stszMaxSampleCount); |
|
667 if (p == NULL) |
|
668 return -1; |
|
669 |
|
670 st->stszEntrySize = (mp4_u32 *)p; |
|
671 |
|
672 st->stszMaxSampleCount *= 2; |
|
673 } |
|
674 |
|
675 st->stszEntrySize[st->stszSampleCount] = size; |
|
676 |
|
677 st->stszSampleCount++; |
|
678 } |
|
679 |
|
680 |
|
681 return 0; |
|
682 } |
|
683 |
|
684 |
|
685 /* |
|
686 * Function: |
|
687 * |
|
688 * mp4_i32 updateSampleToChunk(sampleTable *st) |
|
689 * |
|
690 * Description: |
|
691 * |
|
692 * This function updates stsc atom data. |
|
693 * |
|
694 * Parameters: |
|
695 * |
|
696 * st sampleTable |
|
697 * |
|
698 * Return value: |
|
699 * |
|
700 * 0 Success |
|
701 * -1 Error |
|
702 * |
|
703 */ |
|
704 mp4_i32 updateSampleToChunk(sampleTable *st) |
|
705 { |
|
706 if (st->stscEntryCount != 0) |
|
707 return 0; |
|
708 |
|
709 |
|
710 st->stscFirstChunk[st->stscEntryCount] = st->currentChunk; |
|
711 st->stscSamplesPerChunk[st->stscEntryCount] = 1; |
|
712 st->stscSampleDescriptionIndex[st->stscEntryCount] = 1; /* Note: Need to update here for multiple sample entry support */ |
|
713 st->stscEntryCount++; |
|
714 |
|
715 return 0; |
|
716 } |
|
717 |
|
718 |
|
719 /* |
|
720 * Function: |
|
721 * |
|
722 * mp4_i32 updateChunkOffset(MP4HandleImp handle, |
|
723 * sampleTable *st) |
|
724 * |
|
725 * Description: |
|
726 * |
|
727 * This function updates stco atom data. |
|
728 * |
|
729 * Parameters: |
|
730 * |
|
731 * handle MP4 library handle |
|
732 * st sampleTable |
|
733 * |
|
734 * Return value: |
|
735 * |
|
736 * 0 Success |
|
737 * -1 Error |
|
738 * |
|
739 */ |
|
740 mp4_i32 updateChunkOffset(MP4HandleImp handle, sampleTable *st) |
|
741 { |
|
742 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
743 { |
|
744 if (st->stcoCurrentEntryCount == st->stcoMaxEntryCount) |
|
745 { |
|
746 void *p; |
|
747 |
|
748 p = mp4realloc(st->stcoChunkOffset, |
|
749 2 * sizeof(mp4_u64) * st->stcoMaxEntryCount, |
|
750 sizeof(mp4_u64) * st->stcoMaxEntryCount); |
|
751 if (p == NULL) |
|
752 return -1; |
|
753 |
|
754 st->stcoChunkOffset = (mp4_u64*)p; |
|
755 |
|
756 st->stcoMaxEntryCount *= 2; |
|
757 } |
|
758 |
|
759 if (handle->flags & MP4_FLAG_METADATALAST) |
|
760 updateChunkOffset(st, st->stcoCurrentEntryCount, handle->mediaDataBytes); |
|
761 else |
|
762 updateChunkOffset(st, st->stcoCurrentEntryCount, handle->bytesInTmpFile); |
|
763 |
|
764 st->stcoCurrentEntryCount++; |
|
765 st->stcoEntryCount++; |
|
766 } |
|
767 else |
|
768 { |
|
769 if (st->stcoEntryCount == st->stcoMaxEntryCount) |
|
770 { |
|
771 void *p; |
|
772 |
|
773 p = mp4realloc(st->stcoChunkOffset, |
|
774 2 * sizeof(mp4_u64) * st->stcoMaxEntryCount, |
|
775 sizeof(mp4_u64) * st->stcoMaxEntryCount); |
|
776 if (p == NULL) |
|
777 return -1; |
|
778 |
|
779 st->stcoChunkOffset = (mp4_u64 *)p; |
|
780 |
|
781 st->stcoMaxEntryCount *= 2; |
|
782 } |
|
783 |
|
784 if (handle->flags & MP4_FLAG_METADATALAST) |
|
785 updateChunkOffset(st, st->stcoEntryCount, handle->mediaDataBytes); |
|
786 else |
|
787 updateChunkOffset(st, st->stcoEntryCount, handle->bytesInTmpFile); |
|
788 |
|
789 st->stcoEntryCount++; |
|
790 } |
|
791 |
|
792 |
|
793 return 0; |
|
794 } |
|
795 |
|
796 |
|
797 /* |
|
798 * Function: |
|
799 * |
|
800 * mp4_i32 updateSyncSample(MP4HandleImp handle, |
|
801 * sampleTable *st) |
|
802 * |
|
803 * Description: |
|
804 * |
|
805 * This function updates stss atom data. |
|
806 * |
|
807 * Parameters: |
|
808 * |
|
809 * handle MP4 library handle |
|
810 * st sampleTable |
|
811 * |
|
812 * Return value: |
|
813 * |
|
814 * 0 Success |
|
815 * -1 Error |
|
816 * |
|
817 */ |
|
818 mp4_i32 updateSyncSample(MP4HandleImp handle, sampleTable *st) |
|
819 { |
|
820 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
821 { |
|
822 if (st->stssCurrentEntryCount == st->stssMaxEntryCount) |
|
823 { |
|
824 void *p; |
|
825 |
|
826 p = mp4realloc(st->stssSampleNumber, |
|
827 2 * sizeof(mp4_u32) * st->stssMaxEntryCount, |
|
828 sizeof(mp4_u32) * st->stssMaxEntryCount); |
|
829 if (p == NULL) |
|
830 return -1; |
|
831 |
|
832 st->stssSampleNumber = (mp4_u32 *)p; |
|
833 |
|
834 st->stssMaxEntryCount *= 2; |
|
835 } |
|
836 |
|
837 st->stssSampleNumber[st->stssCurrentEntryCount] = handle->videoSampleNum; |
|
838 st->stssCurrentEntryCount++; |
|
839 st->stssEntryCount++; |
|
840 } |
|
841 else |
|
842 { |
|
843 if (st->stssEntryCount == st->stssMaxEntryCount) |
|
844 { |
|
845 void *p; |
|
846 |
|
847 p = mp4realloc(st->stssSampleNumber, |
|
848 2 * sizeof(mp4_u32) * st->stssMaxEntryCount, |
|
849 sizeof(mp4_u32) * st->stssMaxEntryCount); |
|
850 if (p == NULL) |
|
851 return -1; |
|
852 |
|
853 st->stssSampleNumber = (mp4_u32 *)p; |
|
854 |
|
855 st->stssMaxEntryCount *= 2; |
|
856 } |
|
857 |
|
858 st->stssSampleNumber[st->stssEntryCount] = handle->videoSampleNum; |
|
859 st->stssEntryCount++; |
|
860 } |
|
861 |
|
862 |
|
863 return 0; |
|
864 } |
|
865 |
|
866 |
|
867 /* |
|
868 * Function: |
|
869 * |
|
870 * mp4_i32 determineAudioTrakMetaDataSize(MP4HandleImp handle, |
|
871 * sampleTable *st, |
|
872 * trakSize *ts) |
|
873 * |
|
874 * Description: |
|
875 * |
|
876 * This function calculates the audio track meta data size. |
|
877 * |
|
878 * Parameters: |
|
879 * |
|
880 * handle MP4 library handle |
|
881 * st Sample table data |
|
882 * ts Atom sizes are returned here |
|
883 * |
|
884 * Return value: |
|
885 * |
|
886 * 0 Success |
|
887 * |
|
888 */ |
|
889 mp4_i32 determineAudioTrakMetaDataSize(MP4HandleImp handle, sampleTable *st, trakSize *ts) |
|
890 { |
|
891 if (handle->type & MP4_TYPE_AMR_NB) /* AMR-NB */ |
|
892 { |
|
893 ts->damr = 17; |
|
894 ts->samr = 36 + ts->damr; |
|
895 ts->stsd = 16 + ts->samr; |
|
896 } |
|
897 else if (handle->type & MP4_TYPE_AMR_WB) /* AMR-WB */ |
|
898 { |
|
899 ts->damr = 17; |
|
900 ts->sawb = 36 + ts->damr; |
|
901 ts->stsd = 16 + ts->sawb; |
|
902 } |
|
903 else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) /* QCELP 13K stored in QCELPSampleEntry */ |
|
904 { |
|
905 ts->dqcp = 14; |
|
906 ts->sqcp = 36 + ts->dqcp; |
|
907 ts->stsd = 16 + ts->sqcp; |
|
908 } |
|
909 else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) /* QCELP 13K stored in MP4AudioDescription */ |
|
910 { |
|
911 calculateES_DescriptorSize(handle, MP4_TYPE_QCELP_13K); |
|
912 ts->esds = 12 + handle->ES_DescriptorSize; /*37 + handle->audioDecSpecificInfoSize;*/ |
|
913 ts->mp4a = 36 + ts->esds; |
|
914 ts->stsd = 16 + ts->mp4a; |
|
915 } |
|
916 else /* MPEG audio */ |
|
917 { |
|
918 calculateES_DescriptorSize(handle, MP4_TYPE_MPEG4_AUDIO); |
|
919 ts->esds = 12 + handle->ES_DescriptorSize; /*37 + handle->audioDecSpecificInfoSize;*/ |
|
920 ts->mp4a = 36 + ts->esds; |
|
921 ts->stsd = 16 + ts->mp4a; |
|
922 } |
|
923 ts->stts = 16 + st->sttsEntryCount * 8; |
|
924 ts->stsc = 16 + st->stscEntryCount * 12; |
|
925 if (st->stszSampleSize != 0) |
|
926 ts->stsz = 20; |
|
927 else |
|
928 ts->stsz = 20 + st->stszSampleCount * 4; |
|
929 ts->stco = 16 + st->stcoEntryCount * (st->stcoNeed64Bits ? 8 : 4); |
|
930 ts->stbl = 8 + ts->stsd + ts->stts + ts->stsc + ts->stsz + ts->stco; |
|
931 ts->dref = 28; |
|
932 ts->dinf = 8 + ts->dref; |
|
933 ts->smhd = 16; |
|
934 ts->minf = 8 + ts->smhd + ts->dinf + ts->stbl; |
|
935 ts->hdlr = 33; |
|
936 |
|
937 if (handle->audioDuration > MP4_INT_MAX) |
|
938 { |
|
939 ts->mdhd = 44; |
|
940 ts->tkhd = 104; |
|
941 } |
|
942 else |
|
943 { |
|
944 ts->mdhd = 32; |
|
945 ts->tkhd = 92; |
|
946 } |
|
947 |
|
948 ts->mdia = 8 + ts->mdhd + ts->hdlr + ts->minf; |
|
949 if ( handle->audioUDTA ) |
|
950 { |
|
951 ts->udta = 8 + handle->audioUDTA->atomcontentsize; |
|
952 } |
|
953 ts->trak = 8 + ts->tkhd + ts->mdia + ts->udta; |
|
954 |
|
955 return 0; |
|
956 } |
|
957 |
|
958 |
|
959 /* |
|
960 * Function: |
|
961 * |
|
962 * mp4_i32 determineVideoTrakMetaDataSize(MP4HandleImp handle, |
|
963 * sampleTable *st, |
|
964 * trakSize *ts) |
|
965 * |
|
966 * Description: |
|
967 * |
|
968 * This function calculates the video track meta data size. |
|
969 * |
|
970 * Parameters: |
|
971 * |
|
972 * handle MP4 library handle |
|
973 * st Sample table data |
|
974 * ts Atom sizes are returned here |
|
975 * |
|
976 * Return value: |
|
977 * |
|
978 * 0 Success |
|
979 * |
|
980 */ |
|
981 mp4_i32 determineVideoTrakMetaDataSize(MP4HandleImp handle, sampleTable *st, trakSize *ts) |
|
982 { |
|
983 /* Note: This functions assumes single sample entry per media track. |
|
984 If necessary, modify to support multiple sample entries in the future. */ |
|
985 if ((handle->type & MP4_TYPE_H263_PROFILE_0) || (handle->type & MP4_TYPE_H263_PROFILE_3)) |
|
986 { |
|
987 ts->d263 = 15; |
|
988 ts->s263 = 86 + ts->d263; |
|
989 ts->stsd = 16 + ts->s263; |
|
990 } |
|
991 else /* MPEG-4 */ |
|
992 if ((handle->type & MP4_TYPE_MPEG4_VIDEO)) |
|
993 { |
|
994 ts->esds = 37 + handle->videoDecSpecificInfoSize; |
|
995 ts->mp4v = 86 + ts->esds; |
|
996 ts->stsd = 16 + ts->mp4v; |
|
997 } |
|
998 else /* AVC */ |
|
999 if ( containsAvcVideo( handle->type ) ) |
|
1000 { |
|
1001 /* Note: If necessary, add btrt and m4ds boxes here in the future. */ |
|
1002 ts->avcc = 8 + handle->videoDecSpecificInfoSize; /*handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize;*/ |
|
1003 ts->avc1 = 86 + ts->avcc; |
|
1004 ts->stsd = 16 + ts->avc1; |
|
1005 } |
|
1006 else |
|
1007 { |
|
1008 } |
|
1009 |
|
1010 ts->stts = 16 + st->sttsEntryCount * 8; |
|
1011 ts->stsc = 16 + st->stscEntryCount * 12; |
|
1012 if (st->stszSampleSize != 0) |
|
1013 ts->stsz = 20; |
|
1014 else |
|
1015 ts->stsz = 20 + st->stszSampleCount * 4; |
|
1016 ts->stco = 16 + st->stcoEntryCount * (st->stcoNeed64Bits ? 8 : 4); |
|
1017 ts->stss = 16 + st->stssEntryCount * 4; |
|
1018 if( handle->videoSampleTable->sdtpEntryCount ) |
|
1019 ts->sdtp = 4 + 4 + 1 + 3 + handle->videoSampleTable->sdtpEntryCount; //size + 'SDTP' + ver + flags + dependencies |
|
1020 else |
|
1021 ts->sdtp = 0; |
|
1022 |
|
1023 ts->stbl = 8 + ts->stsd + ts->stts + ts->stsc + ts->stsz + ts->stco + ts->stss + ts->sdtp; |
|
1024 ts->dref = 28; |
|
1025 ts->dinf = 8 + ts->dref; |
|
1026 ts->vmhd = 20; |
|
1027 ts->minf = 8 + ts->vmhd + ts->dinf + ts->stbl; |
|
1028 ts->hdlr = 33; |
|
1029 |
|
1030 if (handle->videoDuration > MP4_INT_MAX) |
|
1031 { |
|
1032 ts->mdhd = 44; |
|
1033 ts->tkhd = 104; |
|
1034 } |
|
1035 else |
|
1036 { |
|
1037 ts->mdhd = 32; |
|
1038 ts->tkhd = 92; |
|
1039 } |
|
1040 |
|
1041 ts->mdia = 8 + ts->mdhd + ts->hdlr + ts->minf; |
|
1042 if ( handle->videoUDTA ) |
|
1043 { |
|
1044 ts->udta = 8 + handle->videoUDTA->atomcontentsize; |
|
1045 } |
|
1046 ts->trak = 8 + ts->tkhd + ts->mdia + ts->udta; |
|
1047 |
|
1048 return 0; |
|
1049 } |
|
1050 |
|
1051 |
|
1052 /* |
|
1053 * Function: |
|
1054 * |
|
1055 * mp4_i32 reUpdateAudioMetaData(sampleTable *st, |
|
1056 * mp4_u32 metaDataSize) |
|
1057 * |
|
1058 * Description: |
|
1059 * |
|
1060 * This function updates the chunk offsets in the meta data to point to |
|
1061 * correct places. |
|
1062 * |
|
1063 * Parameters: |
|
1064 * |
|
1065 * st Sample table data |
|
1066 * metaDataSize Meta data size |
|
1067 * |
|
1068 * Return value: |
|
1069 * |
|
1070 * 0 Success |
|
1071 * |
|
1072 */ |
|
1073 mp4_i32 reUpdateAudioMetaData(sampleTable *st, mp4_u32 metaDataSize) |
|
1074 { |
|
1075 mp4_u32 i; |
|
1076 |
|
1077 |
|
1078 for (i = 0; i < st->stcoEntryCount; i++) |
|
1079 updateChunkOffset(st, i, st->stcoChunkOffset[i] + metaDataSize + MDAT_HEADER_SIZE); |
|
1080 |
|
1081 return 0; |
|
1082 } |
|
1083 |
|
1084 |
|
1085 /* |
|
1086 * Function: |
|
1087 * |
|
1088 * mp4_i32 reUpdateVideoMetaData(sampleTable *st, |
|
1089 * mp4_u32 metaDataSize) |
|
1090 * |
|
1091 * Description: |
|
1092 * |
|
1093 * This function updates the chunk offsets in the meta data to point to |
|
1094 * correct places. |
|
1095 * |
|
1096 * Parameters: |
|
1097 * |
|
1098 * st Sample table data |
|
1099 * metaDataSize Meta data size |
|
1100 * |
|
1101 * Return value: |
|
1102 * |
|
1103 * 0 Success |
|
1104 * |
|
1105 */ |
|
1106 mp4_i32 reUpdateVideoMetaData(sampleTable *st, mp4_u32 metaDataSize) |
|
1107 { |
|
1108 mp4_u32 i; |
|
1109 |
|
1110 |
|
1111 for (i = 0; i < st->stcoEntryCount; i++) |
|
1112 updateChunkOffset(st, i, st->stcoChunkOffset[i] + metaDataSize + MDAT_HEADER_SIZE); |
|
1113 |
|
1114 return 0; |
|
1115 } |
|
1116 |
|
1117 |
|
1118 /* |
|
1119 * Function: |
|
1120 * |
|
1121 * mp4_i32 writeFTYP(MP4HandleImp handle) |
|
1122 * |
|
1123 * Description: |
|
1124 * |
|
1125 * Write FTYP atom. |
|
1126 * |
|
1127 * Parameters: |
|
1128 * |
|
1129 * handle MP4 library handle |
|
1130 * |
|
1131 * Return value: |
|
1132 * |
|
1133 * 0 Success |
|
1134 * -1 Error |
|
1135 * |
|
1136 */ |
|
1137 mp4_i32 writeFTYP(MP4HandleImp handle) |
|
1138 { |
|
1139 mp4_u8 *buf; |
|
1140 mp4_u32 i = 0; |
|
1141 mp4_u8 ftypdelta = 0; |
|
1142 |
|
1143 if ((handle->generate3G2 && !(handle->type & MP4_TYPE_QCELP_13K)) || |
|
1144 (!handle->generate3G2 && !(handle->type & MP4_TYPE_AMR_WB))) |
|
1145 ftypdelta = 4; /* one more additional compatible brand */ |
|
1146 else |
|
1147 ftypdelta = 0; |
|
1148 |
|
1149 if( containsAvcVideo( handle->type ) ) |
|
1150 { |
|
1151 ftypdelta += 4; |
|
1152 } |
|
1153 if(handle->bufferWrite) |
|
1154 handle->ftypdelta=ftypdelta; |
|
1155 |
|
1156 buf = (mp4_u8 *)mp4malloc(FTYP_SIZE + ftypdelta); |
|
1157 if (buf == NULL) |
|
1158 return -1; |
|
1159 |
|
1160 /* Size */ |
|
1161 insertu32(buf+i, (mp4_u32)(FTYP_SIZE + ftypdelta)); |
|
1162 i += 4; |
|
1163 |
|
1164 /* Atom type */ |
|
1165 insertu32(buf+i, (mp4_u32)ATOMTYPE_FTYP); |
|
1166 i += 4; |
|
1167 |
|
1168 if ( containsAvcVideo( handle->type ) ) |
|
1169 { |
|
1170 if(handle->generateMP4) |
|
1171 { |
|
1172 /* MPEG-4 Major brand */ |
|
1173 buf[i++] = 'm'; |
|
1174 buf[i++] = 'p'; |
|
1175 buf[i++] = '4'; |
|
1176 buf[i++] = '2'; |
|
1177 } |
|
1178 |
|
1179 else |
|
1180 { |
|
1181 /* AVC is included for 3GPP Release 6 and beyond */ |
|
1182 /* Major brand */ |
|
1183 buf[i++] = '3'; |
|
1184 buf[i++] = 'g'; |
|
1185 buf[i++] = 'p'; |
|
1186 buf[i++] = '6'; |
|
1187 } |
|
1188 } |
|
1189 else |
|
1190 { |
|
1191 if(handle->generateMP4) |
|
1192 { |
|
1193 /* MPEG-4 Major brand */ |
|
1194 buf[i++] = 'm'; |
|
1195 buf[i++] = 'p'; |
|
1196 buf[i++] = '4'; |
|
1197 buf[i++] = '2'; |
|
1198 } |
|
1199 else if(handle->generate3G2) |
|
1200 { |
|
1201 /* 3GPP2 Major brand */ |
|
1202 buf[i++] = '3'; |
|
1203 buf[i++] = 'g'; |
|
1204 buf[i++] = '2'; |
|
1205 buf[i++] = 'a'; |
|
1206 } |
|
1207 else |
|
1208 { |
|
1209 /* 3GPP Major brand */ |
|
1210 buf[i++] = '3'; |
|
1211 buf[i++] = 'g'; |
|
1212 buf[i++] = 'p'; |
|
1213 buf[i++] = '4'; |
|
1214 } |
|
1215 } |
|
1216 |
|
1217 /* Minor version */ |
|
1218 if(handle->generateMP4) |
|
1219 { /* MPEG-4 Minor Version */ |
|
1220 insertu32(buf+i, (mp4_u32)(0)); /* 0 */ |
|
1221 i += 4; |
|
1222 } |
|
1223 else if(handle->generate3G2) |
|
1224 { /* 3GPP2 Minor Version */ |
|
1225 if( containsAvcVideo( handle->type ) ) |
|
1226 { |
|
1227 insertu32(buf+i, (mp4_u32)(2*256*256)); /* VB.0.0 */ |
|
1228 i += 4; |
|
1229 } |
|
1230 else |
|
1231 { |
|
1232 insertu32(buf+i, (mp4_u32)(1*256*256)); /* VA.0.0 */ |
|
1233 i += 4; |
|
1234 } |
|
1235 } |
|
1236 else |
|
1237 { /* 3GPP Minor Version */ |
|
1238 if( containsAvcVideo( handle->type ) ) |
|
1239 { |
|
1240 insertu32(buf+i, (mp4_u32)2*256); /* V6.3.0 */ |
|
1241 i += 4; |
|
1242 } |
|
1243 else |
|
1244 { |
|
1245 insertu32(buf+i, (mp4_u32)4*256); /* V4.4.0 */ |
|
1246 i += 4; |
|
1247 } |
|
1248 } |
|
1249 |
|
1250 /* Compatible brands */ |
|
1251 if(handle->generateMP4) |
|
1252 {/* MPEG-4 Compatible Brands */ |
|
1253 buf[i++] = 'm'; |
|
1254 buf[i++] = 'p'; |
|
1255 buf[i++] = '4'; |
|
1256 buf[i++] = '2'; |
|
1257 |
|
1258 buf[i++] = '3'; |
|
1259 buf[i++] = 'g'; |
|
1260 buf[i++] = 'p'; |
|
1261 buf[i++] = '4'; |
|
1262 |
|
1263 buf[i++] = 'i'; |
|
1264 buf[i++] = 's'; |
|
1265 buf[i++] = 'o'; |
|
1266 buf[i++] = 'm'; |
|
1267 if ( containsAvcVideo( handle->type ) ) |
|
1268 { |
|
1269 /* AVC is included for 3GPP Release 6 and beyond */ |
|
1270 buf[i++] = 'a'; |
|
1271 buf[i++] = 'v'; |
|
1272 buf[i++] = 'c'; |
|
1273 buf[i++] = '1'; |
|
1274 } |
|
1275 } |
|
1276 else if(handle->generate3G2) |
|
1277 {/* 3GPP2 Compatible Brands */ |
|
1278 if( containsAvcVideo( handle->type ) ) |
|
1279 { |
|
1280 buf[i++] = '3'; |
|
1281 buf[i++] = 'g'; |
|
1282 buf[i++] = '2'; |
|
1283 buf[i++] = 'b'; |
|
1284 if (!(handle->type & MP4_TYPE_QCELP_13K)) |
|
1285 { // If 3GPP codecs are used, then put 3GP6 in compatible brands |
|
1286 buf[i++] = '3'; |
|
1287 buf[i++] = 'g'; |
|
1288 buf[i++] = 'p'; |
|
1289 buf[i++] = '6'; |
|
1290 } |
|
1291 } |
|
1292 else |
|
1293 { |
|
1294 buf[i++] = '3'; |
|
1295 buf[i++] = 'g'; |
|
1296 buf[i++] = '2'; |
|
1297 buf[i++] = 'a'; |
|
1298 if (!(handle->type & MP4_TYPE_QCELP_13K)) |
|
1299 { // If 3GPP codecs are used, then put 3GP4 in compatible brands |
|
1300 buf[i++] = '3'; |
|
1301 buf[i++] = 'g'; |
|
1302 buf[i++] = 'p'; |
|
1303 buf[i++] = '4'; |
|
1304 } |
|
1305 } |
|
1306 if ( containsAvcVideo( handle->type ) ) |
|
1307 { |
|
1308 /* AVC is included for 3GPP Release 6 and beyond */ |
|
1309 buf[i++] = 'a'; |
|
1310 buf[i++] = 'v'; |
|
1311 buf[i++] = 'c'; |
|
1312 buf[i++] = '1'; |
|
1313 } |
|
1314 |
|
1315 buf[i++] = 'i'; |
|
1316 buf[i++] = 's'; |
|
1317 buf[i++] = 'o'; |
|
1318 buf[i++] = 'm'; |
|
1319 } |
|
1320 else |
|
1321 {/* 3GPP Compatible Brands */ |
|
1322 if ( containsAvcVideo( handle->type ) ) |
|
1323 { |
|
1324 buf[i++] = '3'; |
|
1325 buf[i++] = 'g'; |
|
1326 buf[i++] = 'p'; |
|
1327 buf[i++] = '6'; |
|
1328 } |
|
1329 else |
|
1330 { |
|
1331 buf[i++] = '3'; |
|
1332 buf[i++] = 'g'; |
|
1333 buf[i++] = 'p'; |
|
1334 buf[i++] = '4'; |
|
1335 } |
|
1336 |
|
1337 if (!(handle->type & MP4_TYPE_AMR_WB)) |
|
1338 { // If 3GPP2 codecs are used, then put 3G2A in compatible brands |
|
1339 buf[i++] = '3'; |
|
1340 buf[i++] = 'g'; |
|
1341 buf[i++] = '2'; |
|
1342 buf[i++] = 'a'; |
|
1343 } |
|
1344 |
|
1345 buf[i++] = 'i'; |
|
1346 buf[i++] = 's'; |
|
1347 buf[i++] = 'o'; |
|
1348 buf[i++] = 'm'; |
|
1349 |
|
1350 if ( containsAvcVideo( handle->type ) ) |
|
1351 { |
|
1352 /* AVC is included for 3GPP Release 6 and beyond */ |
|
1353 buf[i++] = 'a'; |
|
1354 buf[i++] = 'v'; |
|
1355 buf[i++] = 'c'; |
|
1356 buf[i++] = '1'; |
|
1357 } |
|
1358 |
|
1359 } |
|
1360 if (writeFile(handle, buf, (FTYP_SIZE + ftypdelta)) < 0) |
|
1361 { |
|
1362 mp4free(buf); |
|
1363 |
|
1364 return -1; |
|
1365 } |
|
1366 |
|
1367 mp4free(buf); |
|
1368 |
|
1369 return 0; |
|
1370 } |
|
1371 |
|
1372 |
|
1373 /* |
|
1374 * Function: |
|
1375 * |
|
1376 * mp4_i32 writeMOOV(MP4HandleImp handle, |
|
1377 * mp4_u32 moovSize, |
|
1378 * mp4_bool haveAudio, |
|
1379 * mp4_bool haveVideo, |
|
1380 * trakSize *audioTrackSize, |
|
1381 * trakSize *videoTrackSize) |
|
1382 * |
|
1383 * Description: |
|
1384 * |
|
1385 * Write MOOV atom. |
|
1386 * |
|
1387 * Parameters: |
|
1388 * |
|
1389 * handle MP4 library handle |
|
1390 * moovSize Size of MOOV atom in bytes |
|
1391 * haveAudio Flag to indicate whether audio exists or not |
|
1392 * haveVideo Flag to indicate whether video exists or not |
|
1393 * audioTrackSize Size of audio track in bytes |
|
1394 * videoTrackSize Size of video track in bytes |
|
1395 * |
|
1396 * Return value: |
|
1397 * |
|
1398 * 0 Success |
|
1399 * -1 Error |
|
1400 * |
|
1401 */ |
|
1402 mp4_i32 writeMOOV(MP4HandleImp handle, mp4_u32 moovSize, mp4_bool haveAudio, mp4_bool haveVideo, trakSize *audioTrackSize, trakSize *videoTrackSize) |
|
1403 { |
|
1404 PRINT((_L("e_writemoov 1"))); |
|
1405 mp4_u8 buf[8]; |
|
1406 mp4_u32 i = 0; |
|
1407 |
|
1408 |
|
1409 /* Size */ |
|
1410 insertu32(buf+i, moovSize); |
|
1411 i += 4; |
|
1412 |
|
1413 /* Atom type */ |
|
1414 insertu32(buf+i, (mp4_u32)ATOMTYPE_MOOV); |
|
1415 i += 4; |
|
1416 |
|
1417 PRINT((_L("e_writemoov_header 1"))); |
|
1418 if (writeFile(handle, buf, 8) < 0) |
|
1419 return -1; |
|
1420 PRINT((_L("e_writemoov_header 0"))); |
|
1421 |
|
1422 PRINT((_L("e_writemoov_mvhd 1"))); |
|
1423 if (writeMVHD(handle) < 0) |
|
1424 return -1; |
|
1425 PRINT((_L("e_writemoov_mvhd 0"))); |
|
1426 |
|
1427 PRINT((_L("e_writemoov_video 1"))); |
|
1428 if (haveVideo) |
|
1429 if (writeVideoTrak(handle, videoTrackSize) < 0) |
|
1430 return -1; |
|
1431 PRINT((_L("e_writemoov_video 0"))); |
|
1432 |
|
1433 PRINT((_L("e_writemoov_audio 1"))); |
|
1434 if (haveAudio) |
|
1435 if (writeAudioTrak(handle, audioTrackSize) < 0) |
|
1436 return -1; |
|
1437 PRINT((_L("e_writemoov_audio 0"))); |
|
1438 |
|
1439 PRINT((_L("e_writemoov_udta 1"))); |
|
1440 if (handle->moovUDTA) |
|
1441 { |
|
1442 if (writeUDTA(handle, handle->moovUDTA) < 0) |
|
1443 { |
|
1444 return -1; |
|
1445 } |
|
1446 } |
|
1447 PRINT((_L("e_writemoov_udta 0"))); |
|
1448 PRINT((_L("e_writemoov 0"))); |
|
1449 return 0; |
|
1450 } |
|
1451 |
|
1452 |
|
1453 /* |
|
1454 * Function: |
|
1455 * |
|
1456 * mp4_i32 writeMVHD(MP4HandleImp handle) |
|
1457 * |
|
1458 * Description: |
|
1459 * |
|
1460 * Write MVHD atom. |
|
1461 * |
|
1462 * Parameters: |
|
1463 * |
|
1464 * handle MP4 library handle |
|
1465 * |
|
1466 * Return value: |
|
1467 * |
|
1468 * 0 Success |
|
1469 * -1 Error |
|
1470 * |
|
1471 */ |
|
1472 mp4_i32 writeMVHD(MP4HandleImp handle) |
|
1473 { |
|
1474 mp4_u8 *buf; |
|
1475 mp4_u32 i = 0; |
|
1476 mp4_u32 u32; |
|
1477 |
|
1478 size_t mvhdSize = mvhdAtomSize(handle); |
|
1479 |
|
1480 buf = (mp4_u8 *)mp4malloc(mvhdSize); |
|
1481 if (buf == NULL) |
|
1482 return -1; |
|
1483 |
|
1484 /* Size */ |
|
1485 insertu32(buf+i, (mp4_u32)mvhdSize); |
|
1486 i += 4; |
|
1487 |
|
1488 /* Atom type */ |
|
1489 insertu32(buf+i, (mp4_u32)ATOMTYPE_MVHD); |
|
1490 i += 4; |
|
1491 |
|
1492 |
|
1493 if (handle->videoDuration > MP4_INT_MAX || handle->audioDuration > MP4_INT_MAX) |
|
1494 { |
|
1495 /* Version and flags */ |
|
1496 insertu32(buf+i, (mp4_u32)0x01000000); //its going to be a version 1 atom |
|
1497 i += 4; |
|
1498 |
|
1499 /* Creation time */ |
|
1500 if (getCurrentTime(&u32) < 0) |
|
1501 u32 = 0; |
|
1502 insertu64(buf+i, (mp4_u64)u32); |
|
1503 i += 8; |
|
1504 |
|
1505 /* Modification time */ |
|
1506 if (getCurrentTime(&u32) < 0) |
|
1507 u32 = 0; |
|
1508 insertu64(buf+i, (mp4_u64)u32); |
|
1509 i += 8; |
|
1510 |
|
1511 /* Timescale */ |
|
1512 insertu32(buf+i, (mp4_u32)MVHD_TIMESCALE); |
|
1513 i += 4; |
|
1514 |
|
1515 /* Duration */ |
|
1516 { |
|
1517 mp4_u64 u64; |
|
1518 mp4_u64 videoDuration = 0; |
|
1519 mp4_u64 audioDuration = 0; |
|
1520 |
|
1521 |
|
1522 if (handle->videoTimeScale) |
|
1523 videoDuration = (mp4_u64)((mp4_double)MVHD_TIMESCALE * |
|
1524 (mp4_double)handle->videoDuration / |
|
1525 (mp4_double)handle->videoTimeScale + |
|
1526 (mp4_double)0.5); |
|
1527 if (handle->audioTimeScale) |
|
1528 audioDuration = (mp4_u64)((mp4_double)MVHD_TIMESCALE * |
|
1529 (mp4_double)handle->audioDuration / |
|
1530 (mp4_double)handle->audioTimeScale + |
|
1531 (mp4_double)0.5); |
|
1532 |
|
1533 if (audioDuration > videoDuration) |
|
1534 u64 = audioDuration; |
|
1535 else |
|
1536 u64 = videoDuration; |
|
1537 |
|
1538 insertu64(buf+i, u64); |
|
1539 i += 8; |
|
1540 } |
|
1541 |
|
1542 } |
|
1543 else |
|
1544 { |
|
1545 /* Version and flags */ |
|
1546 insertu32(buf+i, (mp4_u32)0); |
|
1547 i += 4; |
|
1548 |
|
1549 /* Creation time */ |
|
1550 if (getCurrentTime(&u32) < 0) |
|
1551 u32 = 0; |
|
1552 insertu32(buf+i, (mp4_u32)u32); |
|
1553 i += 4; |
|
1554 |
|
1555 /* Modification time */ |
|
1556 if (getCurrentTime(&u32) < 0) |
|
1557 u32 = 0; |
|
1558 insertu32(buf+i, (mp4_u32)u32); |
|
1559 i += 4; |
|
1560 |
|
1561 /* Timescale */ |
|
1562 insertu32(buf+i, (mp4_u32)MVHD_TIMESCALE); |
|
1563 i += 4; |
|
1564 |
|
1565 /* Duration */ |
|
1566 { |
|
1567 mp4_u32 videoDuration = 0; |
|
1568 mp4_u32 audioDuration = 0; |
|
1569 |
|
1570 |
|
1571 if (handle->videoTimeScale) |
|
1572 videoDuration = (mp4_u32)((mp4_double)MVHD_TIMESCALE * |
|
1573 (mp4_double)handle->videoDuration / |
|
1574 (mp4_double)handle->videoTimeScale + |
|
1575 (mp4_double)0.5); |
|
1576 if (handle->audioTimeScale) |
|
1577 audioDuration = (mp4_u32)((mp4_double)MVHD_TIMESCALE * |
|
1578 (mp4_double)handle->audioDuration / |
|
1579 (mp4_double)handle->audioTimeScale + |
|
1580 (mp4_double)0.5); |
|
1581 |
|
1582 if (audioDuration > videoDuration) |
|
1583 u32 = audioDuration; |
|
1584 else |
|
1585 u32 = videoDuration; |
|
1586 |
|
1587 insertu32(buf+i, u32); |
|
1588 i += 4; |
|
1589 } |
|
1590 } |
|
1591 /* Reserved */ |
|
1592 insertu32(buf+i, (mp4_u32)0x00010000); |
|
1593 i += 4; |
|
1594 |
|
1595 insertu16(buf+i, (mp4_u16)0x0100); |
|
1596 i += 2; |
|
1597 |
|
1598 insertu16(buf+i, (mp4_u16)0x0000); |
|
1599 i += 2; |
|
1600 |
|
1601 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1602 i += 4; |
|
1603 |
|
1604 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1605 i += 4; |
|
1606 |
|
1607 insertu32(buf+i, (mp4_u32)0x00010000); |
|
1608 i += 4; |
|
1609 |
|
1610 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1611 i += 4; |
|
1612 |
|
1613 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1614 i += 4; |
|
1615 |
|
1616 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1617 i += 4; |
|
1618 |
|
1619 insertu32(buf+i, (mp4_u32)0x00010000); |
|
1620 i += 4; |
|
1621 |
|
1622 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1623 i += 4; |
|
1624 |
|
1625 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1626 i += 4; |
|
1627 |
|
1628 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1629 i += 4; |
|
1630 |
|
1631 insertu32(buf+i, (mp4_u32)0x40000000); |
|
1632 i += 4; |
|
1633 |
|
1634 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1635 i += 4; |
|
1636 |
|
1637 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1638 i += 4; |
|
1639 |
|
1640 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1641 i += 4; |
|
1642 |
|
1643 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1644 i += 4; |
|
1645 |
|
1646 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1647 i += 4; |
|
1648 |
|
1649 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1650 i += 4; |
|
1651 |
|
1652 insertu32(buf+i, (mp4_u32)0x00010000); |
|
1653 i += 4; |
|
1654 |
|
1655 if (writeFile(handle, buf, mvhdSize) < 0) |
|
1656 { |
|
1657 mp4free(buf); |
|
1658 |
|
1659 return -1; |
|
1660 } |
|
1661 |
|
1662 mp4free(buf); |
|
1663 |
|
1664 return 0; |
|
1665 } |
|
1666 |
|
1667 |
|
1668 /* |
|
1669 * Function: |
|
1670 * |
|
1671 * mp4_i32 writeVideoTrak(MP4HandleImp handle, |
|
1672 * trakSize *ts) |
|
1673 * |
|
1674 * Description: |
|
1675 * |
|
1676 * Write video track atom. |
|
1677 * |
|
1678 * Parameters: |
|
1679 * |
|
1680 * handle MP4 library handle |
|
1681 * ts Atom sizes |
|
1682 * |
|
1683 * Return value: |
|
1684 * |
|
1685 * 0 Success |
|
1686 * -1 Error |
|
1687 * |
|
1688 */ |
|
1689 mp4_i32 writeVideoTrak(MP4HandleImp handle, trakSize *ts) |
|
1690 { |
|
1691 mp4_u8 buf[8]; |
|
1692 mp4_u32 i = 0; |
|
1693 |
|
1694 |
|
1695 /* Size */ |
|
1696 insertu32(buf+i, (mp4_u32)ts->trak); |
|
1697 i += 4; |
|
1698 |
|
1699 /* Atom type */ |
|
1700 insertu32(buf+i, (mp4_u32)ATOMTYPE_TRAK); |
|
1701 i += 4; |
|
1702 |
|
1703 if (writeFile(handle, buf, 8) < 0) |
|
1704 return -1; |
|
1705 |
|
1706 if (writeVideoTKHD(handle, ts) < 0) |
|
1707 return -1; |
|
1708 |
|
1709 if (writeVideoMDIA(handle, ts) < 0) |
|
1710 return -1; |
|
1711 |
|
1712 if (handle->videoUDTA) |
|
1713 { |
|
1714 if (writeUDTA(handle, handle->videoUDTA) < 0) |
|
1715 return -1; |
|
1716 } |
|
1717 |
|
1718 return 0; |
|
1719 } |
|
1720 |
|
1721 |
|
1722 /* |
|
1723 * Function: |
|
1724 * |
|
1725 * mp4_i32 writeVideoTKHD(MP4HandleImp handle, |
|
1726 * trakSize *ts) |
|
1727 * |
|
1728 * Description: |
|
1729 * |
|
1730 * Write TKHD atom. |
|
1731 * |
|
1732 * Parameters: |
|
1733 * |
|
1734 * handle MP4 library handle |
|
1735 * ts Atom sizes |
|
1736 * |
|
1737 * Return value: |
|
1738 * |
|
1739 * 0 Success |
|
1740 * -1 Error |
|
1741 * |
|
1742 */ |
|
1743 mp4_i32 writeVideoTKHD(MP4HandleImp handle, trakSize *ts) |
|
1744 { |
|
1745 mp4_u8 *buf; |
|
1746 mp4_u32 i = 0; |
|
1747 mp4_u32 u32; |
|
1748 mp4_double ud; |
|
1749 |
|
1750 |
|
1751 buf = (mp4_u8 *)mp4malloc(ts->tkhd); |
|
1752 if (buf == NULL) |
|
1753 return -1; |
|
1754 |
|
1755 /* Size */ |
|
1756 insertu32(buf+i, (mp4_u32)ts->tkhd); |
|
1757 i += 4; |
|
1758 |
|
1759 /* Atom type */ |
|
1760 insertu32(buf+i, (mp4_u32)ATOMTYPE_TKHD); |
|
1761 i += 4; |
|
1762 |
|
1763 |
|
1764 if (handle->videoDuration > MP4_INT_MAX) |
|
1765 { |
|
1766 mp4_u64 u64; |
|
1767 /* Version and flags */ |
|
1768 buf[i++] = 1; //make this a version 1 atom |
|
1769 buf[i++] = 0; |
|
1770 buf[i++] = 0; |
|
1771 buf[i++] = 7; /* Track enabled, used in movie and preview */ |
|
1772 |
|
1773 /* Creation time */ |
|
1774 if (getCurrentTime(&u32) < 0) |
|
1775 u32 = 0; |
|
1776 insertu64(buf+i, (mp4_u64)u32); |
|
1777 i += 8; |
|
1778 |
|
1779 /* Modification time */ |
|
1780 if (getCurrentTime(&u32) < 0) |
|
1781 u32 = 0; |
|
1782 insertu64(buf+i, (mp4_u64)u32); |
|
1783 i += 8; |
|
1784 |
|
1785 /* Track ID */ |
|
1786 insertu32(buf+i, (mp4_u32)1); |
|
1787 i += 4; |
|
1788 |
|
1789 /* Reserved */ |
|
1790 insertu32(buf+i, (mp4_u32)0); |
|
1791 i += 4; |
|
1792 |
|
1793 /* Duration */ |
|
1794 if ( (handle->videoDuration == 0) || (handle->videoTimeScale == 0) ) |
|
1795 { |
|
1796 ud = 0; |
|
1797 } |
|
1798 else |
|
1799 { |
|
1800 ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->videoDuration / (mp4_double)handle->videoTimeScale + (mp4_double)0.5; |
|
1801 } |
|
1802 |
|
1803 u64 = (mp4_u64)ud; |
|
1804 insertu64(buf+i, u64); |
|
1805 i += 8; |
|
1806 } |
|
1807 else |
|
1808 { |
|
1809 /* Version and flags */ |
|
1810 buf[i++] = 0; |
|
1811 buf[i++] = 0; |
|
1812 buf[i++] = 0; |
|
1813 buf[i++] = 7; /* Track enabled, used in movie and preview */ |
|
1814 |
|
1815 /* Creation time */ |
|
1816 if (getCurrentTime(&u32) < 0) |
|
1817 u32 = 0; |
|
1818 insertu32(buf+i, (mp4_u32)u32); |
|
1819 i += 4; |
|
1820 |
|
1821 /* Modification time */ |
|
1822 if (getCurrentTime(&u32) < 0) |
|
1823 u32 = 0; |
|
1824 insertu32(buf+i, (mp4_u32)u32); |
|
1825 i += 4; |
|
1826 |
|
1827 /* Track ID */ |
|
1828 insertu32(buf+i, (mp4_u32)1); |
|
1829 i += 4; |
|
1830 |
|
1831 /* Reserved */ |
|
1832 insertu32(buf+i, (mp4_u32)0); |
|
1833 i += 4; |
|
1834 |
|
1835 /* Duration */ |
|
1836 if ( (handle->videoDuration == 0) || (handle->videoTimeScale == 0) ) |
|
1837 { |
|
1838 ud = 0; |
|
1839 } |
|
1840 else |
|
1841 { |
|
1842 ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->videoDuration / (mp4_double)handle->videoTimeScale + (mp4_double)0.5; |
|
1843 } |
|
1844 |
|
1845 u32 = (mp4_u32)ud; |
|
1846 insertu32(buf+i, u32); |
|
1847 i += 4; |
|
1848 } |
|
1849 /* Reserved */ |
|
1850 insertu32(buf+i, (mp4_u32)0); |
|
1851 i += 4; |
|
1852 |
|
1853 insertu32(buf+i, (mp4_u32)0); |
|
1854 i += 4; |
|
1855 |
|
1856 insertu32(buf+i, (mp4_u32)0); |
|
1857 i += 4; |
|
1858 |
|
1859 insertu16(buf+i, (mp4_u16)0); /* Visual track */ |
|
1860 i += 2; |
|
1861 |
|
1862 insertu16(buf+i, (mp4_u16)0); |
|
1863 i += 2; |
|
1864 |
|
1865 insertu32(buf+i, (mp4_u32)0x00010000); |
|
1866 i += 4; |
|
1867 |
|
1868 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1869 i += 4; |
|
1870 |
|
1871 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1872 i += 4; |
|
1873 |
|
1874 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1875 i += 4; |
|
1876 |
|
1877 insertu32(buf+i, (mp4_u32)0x00010000); |
|
1878 i += 4; |
|
1879 |
|
1880 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1881 i += 4; |
|
1882 |
|
1883 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1884 i += 4; |
|
1885 |
|
1886 insertu32(buf+i, (mp4_u32)0x00000000); |
|
1887 i += 4; |
|
1888 |
|
1889 insertu32(buf+i, (mp4_u32)0x40000000); |
|
1890 i += 4; |
|
1891 |
|
1892 insertu16(buf+i, (mp4_u16)handle->videoWidth); /* Width */ |
|
1893 i += 2; |
|
1894 |
|
1895 insertu16(buf+i, (mp4_u16)0); |
|
1896 i += 2; |
|
1897 |
|
1898 insertu16(buf+i, (mp4_u16)handle->videoHeight); /* Height */ |
|
1899 i += 2; |
|
1900 |
|
1901 insertu16(buf+i, (mp4_u16)0); |
|
1902 i += 2; |
|
1903 |
|
1904 if (writeFile(handle, buf, ts->tkhd) < 0) |
|
1905 { |
|
1906 mp4free(buf); |
|
1907 |
|
1908 return -1; |
|
1909 } |
|
1910 |
|
1911 mp4free(buf); |
|
1912 |
|
1913 return 0; |
|
1914 } |
|
1915 |
|
1916 |
|
1917 /* |
|
1918 * Function: |
|
1919 * |
|
1920 * mp4_i32 writeVideoMDIA(MP4HandleImp handle, |
|
1921 * trakSize *ts) |
|
1922 * |
|
1923 * Description: |
|
1924 * |
|
1925 * Write video MDIA atom. |
|
1926 * |
|
1927 * Parameters: |
|
1928 * |
|
1929 * handle MP4 library handle |
|
1930 * ts Atom sizes |
|
1931 * |
|
1932 * Return value: |
|
1933 * |
|
1934 * 0 Success |
|
1935 * -1 Error |
|
1936 * |
|
1937 */ |
|
1938 mp4_i32 writeVideoMDIA(MP4HandleImp handle, trakSize *ts) |
|
1939 { |
|
1940 mp4_u8 buf[8]; |
|
1941 mp4_u32 i = 0; |
|
1942 |
|
1943 |
|
1944 /* Size */ |
|
1945 insertu32(buf+i, (mp4_u32)ts->mdia); |
|
1946 i += 4; |
|
1947 |
|
1948 /* Atom type */ |
|
1949 insertu32(buf+i, (mp4_u32)ATOMTYPE_MDIA); |
|
1950 i += 4; |
|
1951 |
|
1952 if (writeFile(handle, buf, 8) < 0) |
|
1953 return -1; |
|
1954 |
|
1955 if (writeVideoMDHD(handle, ts) < 0) |
|
1956 return -1; |
|
1957 |
|
1958 if (writeVideoHDLR(handle, ts) < 0) |
|
1959 return -1; |
|
1960 |
|
1961 if (writeVideoMINF(handle, ts) < 0) |
|
1962 return -1; |
|
1963 |
|
1964 return 0; |
|
1965 } |
|
1966 |
|
1967 |
|
1968 /* |
|
1969 * Function: |
|
1970 * |
|
1971 * mp4_i32 writeVideoMDHD(MP4HandleImp handle, |
|
1972 * trakSize *ts) |
|
1973 * |
|
1974 * Description: |
|
1975 * |
|
1976 * Write video MDHD atom. |
|
1977 * |
|
1978 * Parameters: |
|
1979 * |
|
1980 * handle MP4 library handle |
|
1981 * ts Atom sizes |
|
1982 * |
|
1983 * Return value: |
|
1984 * |
|
1985 * 0 Success |
|
1986 * -1 Error |
|
1987 * |
|
1988 */ |
|
1989 mp4_i32 writeVideoMDHD(MP4HandleImp handle, trakSize *ts) |
|
1990 { |
|
1991 mp4_u8 *buf; |
|
1992 mp4_u32 i = 0; |
|
1993 mp4_u32 u32; |
|
1994 |
|
1995 |
|
1996 buf = (mp4_u8 *)mp4malloc(ts->mdhd); |
|
1997 if (buf == NULL) |
|
1998 return -1; |
|
1999 |
|
2000 /* Size */ |
|
2001 insertu32(buf+i, (mp4_u32)ts->mdhd); |
|
2002 i += 4; |
|
2003 |
|
2004 /* Atom type */ |
|
2005 insertu32(buf+i, (mp4_u32)ATOMTYPE_MDHD); |
|
2006 i += 4; |
|
2007 |
|
2008 if (handle->videoDuration > MP4_INT_MAX) |
|
2009 { |
|
2010 /* Version and flags */ |
|
2011 insertu32(buf+i, (mp4_u32)0x01000000); //version 1 atom |
|
2012 i += 4; |
|
2013 |
|
2014 /* Creation time */ |
|
2015 if (getCurrentTime(&u32) < 0) |
|
2016 u32 = 0; |
|
2017 insertu64(buf+i, (mp4_u64)u32); |
|
2018 i += 8; |
|
2019 |
|
2020 /* Modification time */ |
|
2021 if (getCurrentTime(&u32) < 0) |
|
2022 u32 = 0; |
|
2023 insertu64(buf+i, (mp4_u64)u32); |
|
2024 i += 8; |
|
2025 |
|
2026 /* Timescale */ |
|
2027 insertu32(buf+i, (mp4_u32)handle->videoTimeScale); |
|
2028 i += 4; |
|
2029 |
|
2030 /* Duration */ |
|
2031 insertu64(buf+i, handle->videoDuration); |
|
2032 i += 8; |
|
2033 } |
|
2034 else |
|
2035 { |
|
2036 /* Version and flags */ |
|
2037 insertu32(buf+i, (mp4_u32)0); |
|
2038 i += 4; |
|
2039 |
|
2040 /* Creation time */ |
|
2041 if (getCurrentTime(&u32) < 0) |
|
2042 u32 = 0; |
|
2043 insertu32(buf+i, (mp4_u32)u32); |
|
2044 i += 4; |
|
2045 |
|
2046 /* Modification time */ |
|
2047 if (getCurrentTime(&u32) < 0) |
|
2048 u32 = 0; |
|
2049 insertu32(buf+i, (mp4_u32)u32); |
|
2050 i += 4; |
|
2051 |
|
2052 /* Timescale */ |
|
2053 insertu32(buf+i, (mp4_u32)handle->videoTimeScale); |
|
2054 i += 4; |
|
2055 |
|
2056 /* Duration */ |
|
2057 insertu32(buf+i, (mp4_u32)handle->videoDuration); |
|
2058 i += 4; |
|
2059 } |
|
2060 |
|
2061 /* Language */ |
|
2062 insertu16(buf+i, (mp4_u16)0x55c4); /* 'und' */ |
|
2063 i += 2; |
|
2064 |
|
2065 /* Reserved */ |
|
2066 insertu16(buf+i, (mp4_u16)0x0000); |
|
2067 i += 2; |
|
2068 |
|
2069 if (writeFile(handle, buf, ts->mdhd) < 0) |
|
2070 { |
|
2071 mp4free(buf); |
|
2072 |
|
2073 return -1; |
|
2074 } |
|
2075 |
|
2076 mp4free(buf); |
|
2077 |
|
2078 return 0; |
|
2079 } |
|
2080 |
|
2081 |
|
2082 /* |
|
2083 * Function: |
|
2084 * |
|
2085 * mp4_i32 writeVideoHDLR(MP4HandleImp handle, |
|
2086 * trakSize *ts) |
|
2087 * |
|
2088 * Description: |
|
2089 * |
|
2090 * Write video HDLR atom. |
|
2091 * |
|
2092 * Parameters: |
|
2093 * |
|
2094 * handle MP4 library handle |
|
2095 * ts Atom sizes |
|
2096 * |
|
2097 * Return value: |
|
2098 * |
|
2099 * 0 Success |
|
2100 * -1 Error |
|
2101 * |
|
2102 */ |
|
2103 mp4_i32 writeVideoHDLR(MP4HandleImp handle, trakSize *ts) |
|
2104 { |
|
2105 mp4_u8 *buf; |
|
2106 mp4_u32 i = 0; |
|
2107 |
|
2108 |
|
2109 buf = (mp4_u8 *)mp4malloc(ts->hdlr); |
|
2110 if (buf == NULL) |
|
2111 return -1; |
|
2112 |
|
2113 /* Size */ |
|
2114 insertu32(buf+i, (mp4_u32)ts->hdlr); |
|
2115 i += 4; |
|
2116 |
|
2117 /* Atom type */ |
|
2118 insertu32(buf+i, (mp4_u32)ATOMTYPE_HDLR); |
|
2119 i += 4; |
|
2120 |
|
2121 /* Version and flags */ |
|
2122 insertu32(buf+i, (mp4_u32)0); |
|
2123 i += 4; |
|
2124 |
|
2125 /* Reserved */ |
|
2126 insertu32(buf+i, (mp4_u32)0); |
|
2127 i += 4; |
|
2128 |
|
2129 /* Handler type */ |
|
2130 buf[i++] = 'v'; |
|
2131 buf[i++] = 'i'; |
|
2132 buf[i++] = 'd'; |
|
2133 buf[i++] = 'e'; |
|
2134 |
|
2135 /* Reserved */ |
|
2136 insertu32(buf+i, (mp4_u32)0); |
|
2137 i += 4; |
|
2138 |
|
2139 /* Reserved */ |
|
2140 insertu32(buf+i, (mp4_u32)0); |
|
2141 i += 4; |
|
2142 |
|
2143 /* Reserved */ |
|
2144 insertu32(buf+i, (mp4_u32)0); |
|
2145 i += 4; |
|
2146 |
|
2147 /* Empty string */ |
|
2148 buf[i++] = 0; |
|
2149 |
|
2150 if (writeFile(handle, buf, ts->hdlr) < 0) |
|
2151 { |
|
2152 mp4free(buf); |
|
2153 |
|
2154 return -1; |
|
2155 } |
|
2156 |
|
2157 mp4free(buf); |
|
2158 |
|
2159 return 0; |
|
2160 } |
|
2161 |
|
2162 |
|
2163 /* |
|
2164 * Function: |
|
2165 * |
|
2166 * mp4_i32 writeVideoMINF(MP4HandleImp handle, |
|
2167 * trakSize *ts) |
|
2168 * |
|
2169 * Description: |
|
2170 * |
|
2171 * Write video MINF atom. |
|
2172 * |
|
2173 * Parameters: |
|
2174 * |
|
2175 * handle MP4 library handle |
|
2176 * ts Atom sizes |
|
2177 * |
|
2178 * Return value: |
|
2179 * |
|
2180 * 0 Success |
|
2181 * -1 Error |
|
2182 * |
|
2183 */ |
|
2184 mp4_i32 writeVideoMINF(MP4HandleImp handle, trakSize *ts) |
|
2185 { |
|
2186 mp4_u8 buf[8]; |
|
2187 mp4_u32 i = 0; |
|
2188 |
|
2189 |
|
2190 /* Size */ |
|
2191 insertu32(buf+i, (mp4_u32)ts->minf); |
|
2192 i += 4; |
|
2193 |
|
2194 /* Atom type */ |
|
2195 insertu32(buf+i, (mp4_u32)ATOMTYPE_MINF); |
|
2196 i += 4; |
|
2197 |
|
2198 if (writeFile(handle, buf, 8) < 0) |
|
2199 return -1; |
|
2200 |
|
2201 if (writeVMHD(handle, ts) < 0) |
|
2202 return -1; |
|
2203 |
|
2204 if (writeDINF(handle, ts) < 0) |
|
2205 return -1; |
|
2206 |
|
2207 if (writeVideoSTBL(handle, ts) < 0) |
|
2208 return -1; |
|
2209 |
|
2210 return 0; |
|
2211 } |
|
2212 |
|
2213 |
|
2214 /* |
|
2215 * Function: |
|
2216 * |
|
2217 * mp4_i32 writeVMHD(MP4HandleImp handle, |
|
2218 * trakSize *ts) |
|
2219 * |
|
2220 * Description: |
|
2221 * |
|
2222 * Write VMHD atom. |
|
2223 * |
|
2224 * Parameters: |
|
2225 * |
|
2226 * handle MP4 library handle |
|
2227 * ts Atom sizes |
|
2228 * |
|
2229 * Return value: |
|
2230 * |
|
2231 * 0 Success |
|
2232 * -1 Error |
|
2233 * |
|
2234 */ |
|
2235 mp4_i32 writeVMHD(MP4HandleImp handle, trakSize *ts) |
|
2236 { |
|
2237 mp4_u8 *buf; |
|
2238 mp4_u32 i = 0; |
|
2239 |
|
2240 |
|
2241 buf = (mp4_u8 *)mp4malloc(ts->vmhd); |
|
2242 if (buf == NULL) |
|
2243 return -1; |
|
2244 |
|
2245 /* Size */ |
|
2246 insertu32(buf+i, (mp4_u32)ts->vmhd); |
|
2247 i += 4; |
|
2248 |
|
2249 /* Atom type */ |
|
2250 insertu32(buf+i, (mp4_u32)ATOMTYPE_VMHD); |
|
2251 i += 4; |
|
2252 |
|
2253 /* Version and flags */ |
|
2254 insertu32(buf+i, (mp4_u32)0x00000001); |
|
2255 i += 4; |
|
2256 |
|
2257 /* Reserved */ |
|
2258 insertu32(buf+i, (mp4_u32)0); |
|
2259 i += 4; |
|
2260 |
|
2261 insertu32(buf+i, (mp4_u32)0); |
|
2262 i += 4; |
|
2263 |
|
2264 if (writeFile(handle, buf, ts->vmhd) < 0) |
|
2265 { |
|
2266 mp4free(buf); |
|
2267 |
|
2268 return -1; |
|
2269 } |
|
2270 |
|
2271 mp4free(buf); |
|
2272 |
|
2273 return 0; |
|
2274 } |
|
2275 |
|
2276 |
|
2277 /* |
|
2278 * Function: |
|
2279 * |
|
2280 * mp4_i32 writeDINF(MP4HandleImp handle, |
|
2281 * trakSize *ts) |
|
2282 * |
|
2283 * Description: |
|
2284 * |
|
2285 * Write DINF atom. |
|
2286 * |
|
2287 * Parameters: |
|
2288 * |
|
2289 * handle MP4 library handle |
|
2290 * ts Atom sizes |
|
2291 * |
|
2292 * Return value: |
|
2293 * |
|
2294 * 0 Success |
|
2295 * -1 Error |
|
2296 * |
|
2297 */ |
|
2298 mp4_i32 writeDINF(MP4HandleImp handle, trakSize *ts) |
|
2299 { |
|
2300 mp4_u8 buf[8]; |
|
2301 mp4_u32 i = 0; |
|
2302 |
|
2303 |
|
2304 /* Size */ |
|
2305 insertu32(buf+i, (mp4_u32)ts->dinf); |
|
2306 i += 4; |
|
2307 |
|
2308 /* Atom type */ |
|
2309 insertu32(buf+i, (mp4_u32)ATOMTYPE_DINF); |
|
2310 i += 4; |
|
2311 |
|
2312 if (writeFile(handle, buf, 8) < 0) |
|
2313 return -1; |
|
2314 |
|
2315 if (writeDREF(handle, ts) < 0) |
|
2316 return -1; |
|
2317 |
|
2318 return 0; |
|
2319 } |
|
2320 |
|
2321 |
|
2322 /* |
|
2323 * Function: |
|
2324 * |
|
2325 * mp4_i32 writeDREF(MP4HandleImp handle, |
|
2326 * trakSize *ts) |
|
2327 * |
|
2328 * Description: |
|
2329 * |
|
2330 * Write DREF atom. |
|
2331 * |
|
2332 * Parameters: |
|
2333 * |
|
2334 * handle MP4 library handle |
|
2335 * ts Atom sizes |
|
2336 * |
|
2337 * Return value: |
|
2338 * |
|
2339 * 0 Success |
|
2340 * -1 Error |
|
2341 * |
|
2342 */ |
|
2343 mp4_i32 writeDREF(MP4HandleImp handle, trakSize *ts) |
|
2344 { |
|
2345 mp4_u8 *buf; |
|
2346 mp4_u32 i = 0; |
|
2347 |
|
2348 |
|
2349 buf = (mp4_u8 *)mp4malloc(ts->dref); |
|
2350 if (buf == NULL) |
|
2351 return -1; |
|
2352 |
|
2353 /* Size */ |
|
2354 insertu32(buf+i, (mp4_u32)ts->dref); |
|
2355 i += 4; |
|
2356 |
|
2357 /* Atom type */ |
|
2358 insertu32(buf+i, (mp4_u32)ATOMTYPE_DREF); |
|
2359 i += 4; |
|
2360 |
|
2361 /* Version and flags */ |
|
2362 insertu32(buf+i, (mp4_u32)0); |
|
2363 i += 4; |
|
2364 |
|
2365 /* Entry count */ |
|
2366 insertu32(buf+i, (mp4_u32)1); |
|
2367 i += 4; |
|
2368 |
|
2369 /* URL atom */ |
|
2370 |
|
2371 /* Size */ |
|
2372 insertu32(buf+i, (mp4_u32)12); |
|
2373 i += 4; |
|
2374 |
|
2375 /* Type */ |
|
2376 insertu32(buf+i, (mp4_u32)ATOMTYPE_URL); |
|
2377 i += 4; |
|
2378 |
|
2379 /* Version and flags */ |
|
2380 insertu32(buf+i, (mp4_u32)0x00000001); |
|
2381 i += 4; |
|
2382 |
|
2383 if (writeFile(handle, buf, ts->dref) < 0) |
|
2384 { |
|
2385 mp4free(buf); |
|
2386 |
|
2387 return -1; |
|
2388 } |
|
2389 |
|
2390 mp4free(buf); |
|
2391 |
|
2392 return 0; |
|
2393 } |
|
2394 |
|
2395 |
|
2396 /* |
|
2397 * Function: |
|
2398 * |
|
2399 * mp4_i32 writeVideoSTBL(MP4HandleImp handle, |
|
2400 * trakSize *ts) |
|
2401 * |
|
2402 * Description: |
|
2403 * |
|
2404 * Write video STBL atom. |
|
2405 * |
|
2406 * Parameters: |
|
2407 * |
|
2408 * handle MP4 library handle |
|
2409 * ts Atom sizes |
|
2410 * |
|
2411 * Return value: |
|
2412 * |
|
2413 * 0 Success |
|
2414 * -1 Error |
|
2415 * |
|
2416 */ |
|
2417 mp4_i32 writeVideoSTBL(MP4HandleImp handle, trakSize *ts) |
|
2418 { |
|
2419 mp4_u8 buf[8]; |
|
2420 mp4_u32 i = 0; |
|
2421 |
|
2422 |
|
2423 /* Size */ |
|
2424 insertu32(buf+i, (mp4_u32)ts->stbl); |
|
2425 i += 4; |
|
2426 |
|
2427 /* Atom type */ |
|
2428 insertu32(buf+i, (mp4_u32)ATOMTYPE_STBL); |
|
2429 i += 4; |
|
2430 |
|
2431 if (writeFile(handle, buf, 8) < 0) |
|
2432 return -1; |
|
2433 |
|
2434 if (writeVideoSTSD(handle, ts) < 0) |
|
2435 return -1; |
|
2436 |
|
2437 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
2438 { |
|
2439 if (writeVideoSTTSLongClip(handle, ts) < 0) |
|
2440 return -1; |
|
2441 } |
|
2442 else |
|
2443 { |
|
2444 if (writeVideoSTTS(handle, ts) < 0) |
|
2445 return -1; |
|
2446 } |
|
2447 |
|
2448 if (writeVideoSTSC(handle, ts) < 0) |
|
2449 return -1; |
|
2450 |
|
2451 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
2452 { |
|
2453 if (writeVideoSTSZLongClip(handle, ts) < 0) |
|
2454 return -1; |
|
2455 |
|
2456 if (handle->videoSampleTable->stcoNeed64Bits) |
|
2457 { |
|
2458 if (writeVideoCO64LongClip(handle, ts) < 0) |
|
2459 return -1; |
|
2460 } |
|
2461 else |
|
2462 { |
|
2463 if (writeVideoSTCOLongClip(handle, ts) < 0) |
|
2464 return -1; |
|
2465 } |
|
2466 |
|
2467 if (writeVideoSTSSLongClip(handle, ts) < 0) |
|
2468 return -1; |
|
2469 |
|
2470 if(ts->sdtp && writeVideoSDTPLongClip(handle, ts) < 0) |
|
2471 return -1; |
|
2472 } |
|
2473 else |
|
2474 { |
|
2475 if (writeVideoSTSZ(handle, ts) < 0) |
|
2476 return -1; |
|
2477 |
|
2478 if (handle->videoSampleTable->stcoNeed64Bits) |
|
2479 { |
|
2480 if (writeVideoCO64(handle, ts) < 0) |
|
2481 return -1; |
|
2482 } |
|
2483 else |
|
2484 { |
|
2485 if (writeVideoSTCO(handle, ts) < 0) |
|
2486 return -1; |
|
2487 } |
|
2488 |
|
2489 if (writeVideoSTSS(handle, ts) < 0) |
|
2490 return -1; |
|
2491 |
|
2492 if(ts->sdtp && writeVideoSDTP(handle, ts) < 0) |
|
2493 return -1; |
|
2494 } |
|
2495 return 0; |
|
2496 } |
|
2497 |
|
2498 |
|
2499 /* |
|
2500 * Function: |
|
2501 * |
|
2502 * mp4_i32 writeVideoSTSD(MP4HandleImp handle, |
|
2503 * trakSize *ts) |
|
2504 * |
|
2505 * Description: |
|
2506 * |
|
2507 * Write video STSD atom. |
|
2508 * |
|
2509 * Parameters: |
|
2510 * |
|
2511 * handle MP4 library handle |
|
2512 * ts Atom sizes |
|
2513 * |
|
2514 * Return value: |
|
2515 * |
|
2516 * 0 Success |
|
2517 * -1 Error |
|
2518 * |
|
2519 */ |
|
2520 mp4_i32 writeVideoSTSD(MP4HandleImp handle, trakSize *ts) |
|
2521 { |
|
2522 mp4_u8 buf[16]; |
|
2523 mp4_u32 i = 0; |
|
2524 |
|
2525 |
|
2526 /* Size */ |
|
2527 insertu32(buf+i, (mp4_u32)ts->stsd); |
|
2528 i += 4; |
|
2529 |
|
2530 /* Atom type */ |
|
2531 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSD); |
|
2532 i += 4; |
|
2533 |
|
2534 /* Version and flags */ |
|
2535 insertu32(buf+i, (mp4_u32)0); |
|
2536 i += 4; |
|
2537 |
|
2538 /* Entry count */ |
|
2539 insertu32(buf+i, (mp4_u32)1); |
|
2540 i += 4; |
|
2541 |
|
2542 if (writeFile(handle, buf, 16) < 0) |
|
2543 return -1; |
|
2544 |
|
2545 if (handle->type & MP4_TYPE_MPEG4_VIDEO) |
|
2546 { |
|
2547 if (writeMP4V(handle, ts) < 0) |
|
2548 return -1; |
|
2549 } |
|
2550 else if ((handle->type & MP4_TYPE_H263_PROFILE_0) || |
|
2551 (handle->type & MP4_TYPE_H263_PROFILE_3)) |
|
2552 { |
|
2553 if (writeS263(handle, ts) < 0) |
|
2554 return -1; |
|
2555 } |
|
2556 else if ( containsAvcVideo( handle->type ) ) |
|
2557 { |
|
2558 if (writeAVC1(handle, ts) < 0) |
|
2559 return -1; |
|
2560 } |
|
2561 else |
|
2562 { |
|
2563 } |
|
2564 |
|
2565 return 0; |
|
2566 } |
|
2567 |
|
2568 |
|
2569 /* |
|
2570 * Function: |
|
2571 * |
|
2572 * mp4_i32 writeMP4V(MP4HandleImp handle, |
|
2573 * trakSize *ts) |
|
2574 * |
|
2575 * Description: |
|
2576 * |
|
2577 * Write MP4V atom. |
|
2578 * |
|
2579 * Parameters: |
|
2580 * |
|
2581 * handle MP4 library handle |
|
2582 * ts Atom sizes |
|
2583 * |
|
2584 * Return value: |
|
2585 * |
|
2586 * 0 Success |
|
2587 * -1 Error |
|
2588 * |
|
2589 */ |
|
2590 mp4_i32 writeMP4V(MP4HandleImp handle, trakSize *ts) |
|
2591 { |
|
2592 mp4_u8 *buf; |
|
2593 mp4_u32 i = 0; |
|
2594 |
|
2595 |
|
2596 buf = (mp4_u8 *)mp4malloc(86); |
|
2597 if (buf == NULL) |
|
2598 return -1; |
|
2599 |
|
2600 /* Size */ |
|
2601 insertu32(buf+i, (mp4_u32)ts->mp4v); |
|
2602 i += 4; |
|
2603 |
|
2604 /* Atom type */ |
|
2605 insertu32(buf+i, (mp4_u32)ATOMTYPE_MP4V); |
|
2606 i += 4; |
|
2607 |
|
2608 /* Reserved */ |
|
2609 buf[i++] = 0; |
|
2610 buf[i++] = 0; |
|
2611 buf[i++] = 0; |
|
2612 buf[i++] = 0; |
|
2613 buf[i++] = 0; |
|
2614 buf[i++] = 0; |
|
2615 |
|
2616 /* Data reference index */ |
|
2617 insertu16(buf+i, (mp4_u16)1); |
|
2618 i += 2; |
|
2619 |
|
2620 /* Reserved */ |
|
2621 insertu32(buf+i, (mp4_u32)0); |
|
2622 i += 4; |
|
2623 |
|
2624 insertu32(buf+i, (mp4_u32)0); |
|
2625 i += 4; |
|
2626 |
|
2627 insertu32(buf+i, (mp4_u32)0); |
|
2628 i += 4; |
|
2629 |
|
2630 insertu32(buf+i, (mp4_u32)0); |
|
2631 i += 4; |
|
2632 |
|
2633 /* Width */ |
|
2634 insertu16(buf+i, (mp4_u16)handle->videoWidth); |
|
2635 i += 2; |
|
2636 |
|
2637 /* Height */ |
|
2638 insertu16(buf+i, (mp4_u16)handle->videoHeight); |
|
2639 i += 2; |
|
2640 |
|
2641 /* Reserved */ |
|
2642 insertu32(buf+i, (mp4_u32)0x00480000); |
|
2643 i += 4; |
|
2644 |
|
2645 insertu32(buf+i, (mp4_u32)0x00480000); |
|
2646 i += 4; |
|
2647 |
|
2648 insertu32(buf+i, (mp4_u32)0); |
|
2649 i += 4; |
|
2650 |
|
2651 insertu16(buf+i, (mp4_u16)1); |
|
2652 i += 2; |
|
2653 |
|
2654 insertu32(buf+i, (mp4_u32)0); |
|
2655 i += 4; |
|
2656 |
|
2657 insertu32(buf+i, (mp4_u32)0); |
|
2658 i += 4; |
|
2659 |
|
2660 insertu32(buf+i, (mp4_u32)0); |
|
2661 i += 4; |
|
2662 |
|
2663 insertu32(buf+i, (mp4_u32)0); |
|
2664 i += 4; |
|
2665 |
|
2666 insertu32(buf+i, (mp4_u32)0); |
|
2667 i += 4; |
|
2668 |
|
2669 insertu32(buf+i, (mp4_u32)0); |
|
2670 i += 4; |
|
2671 |
|
2672 insertu32(buf+i, (mp4_u32)0); |
|
2673 i += 4; |
|
2674 |
|
2675 insertu32(buf+i, (mp4_u32)0); |
|
2676 i += 4; |
|
2677 |
|
2678 insertu16(buf+i, (mp4_u16)24); |
|
2679 i += 2; |
|
2680 |
|
2681 insertu16(buf+i, (mp4_u16)0xffff); |
|
2682 i += 2; |
|
2683 |
|
2684 if (writeFile(handle, buf, 86) < 0) |
|
2685 { |
|
2686 mp4free(buf); |
|
2687 |
|
2688 return -1; |
|
2689 } |
|
2690 |
|
2691 if (writeVideoESD(handle, ts) < 0) |
|
2692 { |
|
2693 mp4free(buf); |
|
2694 |
|
2695 return -1; |
|
2696 } |
|
2697 |
|
2698 mp4free(buf); |
|
2699 |
|
2700 return 0; |
|
2701 } |
|
2702 |
|
2703 |
|
2704 /* |
|
2705 * Function: |
|
2706 * |
|
2707 * mp4_i32 writeVideoESD(MP4HandleImp handle, |
|
2708 * trakSize *ts) |
|
2709 * |
|
2710 * Description: |
|
2711 * |
|
2712 * Write video ESD atom. |
|
2713 * |
|
2714 * Parameters: |
|
2715 * |
|
2716 * handle MP4 library handle |
|
2717 * ts Atom sizes |
|
2718 * |
|
2719 * Return value: |
|
2720 * |
|
2721 * 0 Success |
|
2722 * -1 Error |
|
2723 * |
|
2724 */ |
|
2725 mp4_i32 writeVideoESD(MP4HandleImp handle, trakSize *ts) |
|
2726 { |
|
2727 mp4_u8 *buf; |
|
2728 mp4_u32 i = 0; |
|
2729 |
|
2730 |
|
2731 buf = (mp4_u8 *)mp4malloc(ts->esds); |
|
2732 if (buf == NULL) |
|
2733 return -1; |
|
2734 |
|
2735 /* Size */ |
|
2736 insertu32(buf+i, (mp4_u32)ts->esds); |
|
2737 i += 4; |
|
2738 |
|
2739 /* Atom type */ |
|
2740 insertu32(buf+i, (mp4_u32)ATOMTYPE_ESD); |
|
2741 i += 4; |
|
2742 |
|
2743 /* Version and flags */ |
|
2744 insertu32(buf+i, (mp4_u32)0); |
|
2745 i += 4; |
|
2746 |
|
2747 /* ES_DescrTag */ |
|
2748 buf[i++] = 0x03; |
|
2749 |
|
2750 /* Size */ |
|
2751 buf[i++] = (mp4_u8)(23 + handle->videoDecSpecificInfoSize); |
|
2752 |
|
2753 /* ES_ID */ |
|
2754 insertu16(buf+i, (mp4_u16)0); |
|
2755 i += 2; |
|
2756 |
|
2757 /* Flags */ |
|
2758 buf[i++] = 0; |
|
2759 |
|
2760 /* DecoderConfigDescrTag */ |
|
2761 buf[i++] = 0x04; |
|
2762 |
|
2763 /* Size */ |
|
2764 buf[i++] = (mp4_u8)(15 + handle->videoDecSpecificInfoSize); |
|
2765 |
|
2766 /* ObjectTypeIndication */ |
|
2767 buf[i++] = 0x20; |
|
2768 |
|
2769 /* Flags */ |
|
2770 buf[i++] = 0x11; |
|
2771 |
|
2772 /* BufferSizeDB */ |
|
2773 buf[i++] = 0x00; |
|
2774 buf[i++] = 0x50; |
|
2775 buf[i++] = 0x00; |
|
2776 |
|
2777 /* MaxBitrate */ |
|
2778 insertu32(buf+i, (mp4_u32)handle->videoMaxBitrate); |
|
2779 i += 4; |
|
2780 |
|
2781 /* AvgBitrate */ |
|
2782 insertu32(buf+i, (mp4_u32)handle->videoAvgBitrate); |
|
2783 i += 4; |
|
2784 |
|
2785 /* DecSpecificInfoTag */ |
|
2786 buf[i++] = 0x05; |
|
2787 |
|
2788 /* Size */ |
|
2789 buf[i++] = (mp4_u8)handle->videoDecSpecificInfoSize; |
|
2790 |
|
2791 /* DecoderSpecificInfo */ |
|
2792 mp4memcpy(buf+i, handle->videoDecSpecificInfo, handle->videoDecSpecificInfoSize); |
|
2793 i += handle->videoDecSpecificInfoSize; |
|
2794 |
|
2795 /* SLConfigDescrTag */ |
|
2796 buf[i++] = 0x06; |
|
2797 |
|
2798 /* Size */ |
|
2799 buf[i++] = 1; |
|
2800 |
|
2801 /* */ |
|
2802 buf[i++] = 2; |
|
2803 |
|
2804 if (writeFile(handle, buf, ts->esds) < 0) |
|
2805 { |
|
2806 mp4free(buf); |
|
2807 |
|
2808 return -1; |
|
2809 } |
|
2810 |
|
2811 mp4free(buf); |
|
2812 |
|
2813 return 0; |
|
2814 } |
|
2815 |
|
2816 |
|
2817 /* |
|
2818 * Function: |
|
2819 * |
|
2820 * mp4_i32 writeS263(MP4HandleImp handle, |
|
2821 * trakSize *ts) |
|
2822 * |
|
2823 * Description: |
|
2824 * |
|
2825 * Write S263 atom. |
|
2826 * |
|
2827 * Parameters: |
|
2828 * |
|
2829 * handle MP4 library handle |
|
2830 * ts Atom sizes |
|
2831 * |
|
2832 * Return value: |
|
2833 * |
|
2834 * 0 Success |
|
2835 * -1 Error |
|
2836 * |
|
2837 */ |
|
2838 mp4_i32 writeS263(MP4HandleImp handle, trakSize *ts) |
|
2839 { |
|
2840 mp4_u8 *buf; |
|
2841 mp4_u32 i = 0; |
|
2842 |
|
2843 |
|
2844 buf = (mp4_u8 *)mp4malloc(86); |
|
2845 if (buf == NULL) |
|
2846 return -1; |
|
2847 |
|
2848 /* Size */ |
|
2849 insertu32(buf+i, (mp4_u32)ts->s263); |
|
2850 i += 4; |
|
2851 |
|
2852 /* Atom type */ |
|
2853 insertu32(buf+i, (mp4_u32)ATOMTYPE_S263); |
|
2854 i += 4; |
|
2855 |
|
2856 /* Reserved */ |
|
2857 buf[i++] = 0; |
|
2858 buf[i++] = 0; |
|
2859 buf[i++] = 0; |
|
2860 buf[i++] = 0; |
|
2861 buf[i++] = 0; |
|
2862 buf[i++] = 0; |
|
2863 |
|
2864 /* Data reference index */ |
|
2865 insertu16(buf+i, (mp4_u16)1); |
|
2866 i += 2; |
|
2867 |
|
2868 /* Reserved */ |
|
2869 insertu32(buf+i, (mp4_u32)0); |
|
2870 i += 4; |
|
2871 |
|
2872 insertu32(buf+i, (mp4_u32)0); |
|
2873 i += 4; |
|
2874 |
|
2875 insertu32(buf+i, (mp4_u32)0); |
|
2876 i += 4; |
|
2877 |
|
2878 insertu32(buf+i, (mp4_u32)0); |
|
2879 i += 4; |
|
2880 |
|
2881 /* Width */ |
|
2882 insertu16(buf+i, (mp4_u16)handle->videoWidth); |
|
2883 i += 2; |
|
2884 |
|
2885 /* Height */ |
|
2886 insertu16(buf+i, (mp4_u16)handle->videoHeight); |
|
2887 i += 2; |
|
2888 |
|
2889 /* Reserved */ |
|
2890 insertu32(buf+i, (mp4_u32)0x00480000); |
|
2891 i += 4; |
|
2892 |
|
2893 insertu32(buf+i, (mp4_u32)0x00480000); |
|
2894 i += 4; |
|
2895 |
|
2896 insertu32(buf+i, (mp4_u32)0); |
|
2897 i += 4; |
|
2898 |
|
2899 insertu16(buf+i, (mp4_u16)1); |
|
2900 i += 2; |
|
2901 |
|
2902 insertu32(buf+i, (mp4_u32)0); |
|
2903 i += 4; |
|
2904 |
|
2905 insertu32(buf+i, (mp4_u32)0); |
|
2906 i += 4; |
|
2907 |
|
2908 insertu32(buf+i, (mp4_u32)0); |
|
2909 i += 4; |
|
2910 |
|
2911 insertu32(buf+i, (mp4_u32)0); |
|
2912 i += 4; |
|
2913 |
|
2914 insertu32(buf+i, (mp4_u32)0); |
|
2915 i += 4; |
|
2916 |
|
2917 insertu32(buf+i, (mp4_u32)0); |
|
2918 i += 4; |
|
2919 |
|
2920 insertu32(buf+i, (mp4_u32)0); |
|
2921 i += 4; |
|
2922 |
|
2923 insertu32(buf+i, (mp4_u32)0); |
|
2924 i += 4; |
|
2925 |
|
2926 insertu16(buf+i, (mp4_u16)24); |
|
2927 i += 2; |
|
2928 |
|
2929 insertu16(buf+i, (mp4_u16)0xffff); |
|
2930 i += 2; |
|
2931 |
|
2932 if (writeFile(handle, buf, 86) < 0) |
|
2933 { |
|
2934 mp4free(buf); |
|
2935 |
|
2936 return -1; |
|
2937 } |
|
2938 |
|
2939 if (writeD263(handle, ts) < 0) |
|
2940 { |
|
2941 mp4free(buf); |
|
2942 |
|
2943 return -1; |
|
2944 } |
|
2945 |
|
2946 mp4free(buf); |
|
2947 |
|
2948 return 0; |
|
2949 } |
|
2950 |
|
2951 |
|
2952 /* |
|
2953 * Function: |
|
2954 * |
|
2955 * mp4_i32 writeD263(MP4HandleImp handle, |
|
2956 * trakSize *ts) |
|
2957 * |
|
2958 * Description: |
|
2959 * |
|
2960 * Write D263 atom. |
|
2961 * |
|
2962 * Parameters: |
|
2963 * |
|
2964 * handle MP4 library handle |
|
2965 * ts Atom sizes |
|
2966 * |
|
2967 * Return value: |
|
2968 * |
|
2969 * 0 Success |
|
2970 * -1 Error |
|
2971 * |
|
2972 */ |
|
2973 mp4_i32 writeD263(MP4HandleImp handle, trakSize *ts) |
|
2974 { |
|
2975 mp4_u8 buf[15]; |
|
2976 mp4_u32 i = 0; |
|
2977 |
|
2978 |
|
2979 /* Size */ |
|
2980 insertu32(buf+i, (mp4_u32)ts->d263); |
|
2981 i += 4; |
|
2982 |
|
2983 /* Atom type */ |
|
2984 insertu32(buf+i, (mp4_u32)ATOMTYPE_D263); |
|
2985 i += 4; |
|
2986 |
|
2987 /* Vendor */ |
|
2988 buf[i++] = 'S'; |
|
2989 buf[i++] = '6'; |
|
2990 buf[i++] = '0'; |
|
2991 buf[i++] = ' '; |
|
2992 |
|
2993 /* Decoder version */ |
|
2994 buf[i++] = 0; |
|
2995 |
|
2996 /* H263_Level */ |
|
2997 buf[i++] = handle->videoLevel; |
|
2998 |
|
2999 /* H263_Profile */ |
|
3000 if (handle->type & MP4_TYPE_H263_PROFILE_0) |
|
3001 buf[i++] = 0; |
|
3002 else if (handle->type & MP4_TYPE_H263_PROFILE_3) |
|
3003 buf[i++] = 3; |
|
3004 else |
|
3005 return -1; |
|
3006 |
|
3007 if (writeFile(handle, buf, 15) < 0) |
|
3008 return -1; |
|
3009 |
|
3010 return 0; |
|
3011 } |
|
3012 |
|
3013 /* |
|
3014 * Function: |
|
3015 * |
|
3016 * mp4_i32 writeAVC1(MP4HandleImp handle, |
|
3017 * trakSize *ts) |
|
3018 * |
|
3019 * Description: |
|
3020 * |
|
3021 * Write AVC1 atom. |
|
3022 * |
|
3023 * Parameters: |
|
3024 * |
|
3025 * handle MP4 library handle |
|
3026 * ts Atom sizes |
|
3027 * |
|
3028 * Return value: |
|
3029 * |
|
3030 * 0 Success |
|
3031 * -1 Error |
|
3032 * |
|
3033 */ |
|
3034 mp4_i32 writeAVC1(MP4HandleImp handle, trakSize *ts) |
|
3035 { |
|
3036 mp4_u8 *buf; |
|
3037 mp4_u32 i = 0; |
|
3038 |
|
3039 |
|
3040 buf = (mp4_u8 *)mp4malloc(86); |
|
3041 if (buf == NULL) |
|
3042 return -1; |
|
3043 |
|
3044 /* Size */ |
|
3045 insertu32(buf+i, (mp4_u32)ts->avc1); |
|
3046 i += 4; |
|
3047 |
|
3048 /* Atom type */ |
|
3049 insertu32(buf+i, (mp4_u32)ATOMTYPE_AVC1); |
|
3050 i += 4; |
|
3051 |
|
3052 /* Reserved */ |
|
3053 buf[i++] = 0; |
|
3054 buf[i++] = 0; |
|
3055 buf[i++] = 0; |
|
3056 buf[i++] = 0; |
|
3057 buf[i++] = 0; |
|
3058 buf[i++] = 0; |
|
3059 |
|
3060 /* Data reference index */ |
|
3061 insertu16(buf+i, (mp4_u16)1); |
|
3062 i += 2; |
|
3063 |
|
3064 /* Reserved */ |
|
3065 insertu32(buf+i, (mp4_u32)0); |
|
3066 i += 4; |
|
3067 |
|
3068 insertu32(buf+i, (mp4_u32)0); |
|
3069 i += 4; |
|
3070 |
|
3071 insertu32(buf+i, (mp4_u32)0); |
|
3072 i += 4; |
|
3073 |
|
3074 insertu32(buf+i, (mp4_u32)0); |
|
3075 i += 4; |
|
3076 |
|
3077 /* Width */ |
|
3078 insertu16(buf+i, (mp4_u16)handle->videoWidth); |
|
3079 i += 2; |
|
3080 |
|
3081 /* Height */ |
|
3082 insertu16(buf+i, (mp4_u16)handle->videoHeight); |
|
3083 i += 2; |
|
3084 |
|
3085 /* H-res (default is 72dpi = 0x00480000) */ |
|
3086 insertu32(buf+i, (mp4_u32)0x00480000); |
|
3087 i += 4; |
|
3088 |
|
3089 /* V-res (default is 72dpi = 0x00480000) */ |
|
3090 insertu32(buf+i, (mp4_u32)0x00480000); |
|
3091 i += 4; |
|
3092 |
|
3093 /* Reserved */ |
|
3094 insertu32(buf+i, (mp4_u32)0); |
|
3095 i += 4; |
|
3096 |
|
3097 /* Frame count (default is 1) */ |
|
3098 insertu16(buf+i, (mp4_u16)1); |
|
3099 i += 2; |
|
3100 |
|
3101 /* Compressor name (32 byte string) */ |
|
3102 // The spec *recommends* inserting "\012AVC Coding" here |
|
3103 // but we just have a string of nulls. |
|
3104 insertu32(buf+i, (mp4_u32)0); |
|
3105 i += 4; |
|
3106 |
|
3107 insertu32(buf+i, (mp4_u32)0); |
|
3108 i += 4; |
|
3109 |
|
3110 insertu32(buf+i, (mp4_u32)0); |
|
3111 i += 4; |
|
3112 |
|
3113 insertu32(buf+i, (mp4_u32)0); |
|
3114 i += 4; |
|
3115 |
|
3116 insertu32(buf+i, (mp4_u32)0); |
|
3117 i += 4; |
|
3118 |
|
3119 insertu32(buf+i, (mp4_u32)0); |
|
3120 i += 4; |
|
3121 |
|
3122 insertu32(buf+i, (mp4_u32)0); |
|
3123 i += 4; |
|
3124 |
|
3125 insertu32(buf+i, (mp4_u32)0); |
|
3126 i += 4; |
|
3127 |
|
3128 /* Depth (default is 0x0018 which indicates colour images with no alpha) */ |
|
3129 insertu16(buf+i, (mp4_u16)24); |
|
3130 i += 2; |
|
3131 |
|
3132 /* Pre-defined (-1) */ |
|
3133 insertu16(buf+i, (mp4_u16)0xffff); |
|
3134 i += 2; |
|
3135 |
|
3136 if (writeFile(handle, buf, 86) < 0) |
|
3137 { |
|
3138 mp4free(buf); |
|
3139 |
|
3140 return -1; |
|
3141 } |
|
3142 |
|
3143 if (writeAVCC(handle, ts) < 0) |
|
3144 { |
|
3145 mp4free(buf); |
|
3146 |
|
3147 return -1; |
|
3148 } |
|
3149 |
|
3150 /* Note: If necessary, include writing of btrt and m4ds atoms. */ |
|
3151 |
|
3152 mp4free(buf); |
|
3153 |
|
3154 return 0; |
|
3155 } |
|
3156 |
|
3157 /* |
|
3158 * Function: |
|
3159 * |
|
3160 * mp4_i32 writeAVCC(MP4HandleImp handle, |
|
3161 * trakSize *ts) |
|
3162 * |
|
3163 * Description: |
|
3164 * |
|
3165 * Write AVCC atom. |
|
3166 * |
|
3167 * Parameters: |
|
3168 * |
|
3169 * handle MP4 library handle |
|
3170 * ts Atom sizes |
|
3171 * |
|
3172 * Return value: |
|
3173 * |
|
3174 * 0 Success |
|
3175 * -1 Error |
|
3176 * |
|
3177 */ |
|
3178 mp4_i32 writeAVCC(MP4HandleImp handle, trakSize *ts) |
|
3179 { |
|
3180 mp4_u8 *buf; |
|
3181 mp4_u32 i = 0; |
|
3182 |
|
3183 |
|
3184 buf = (mp4_u8 *)mp4malloc(ts->avcc); |
|
3185 if (buf == NULL) |
|
3186 return -1; |
|
3187 |
|
3188 /* Size */ |
|
3189 insertu32(buf+i, (mp4_u32)ts->avcc); |
|
3190 i += 4; |
|
3191 |
|
3192 /* Atom type */ |
|
3193 insertu32(buf+i, (mp4_u32)ATOMTYPE_AVCC); |
|
3194 i += 4; |
|
3195 |
|
3196 /*mp4memcpy(buf+i, handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig, |
|
3197 handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize);*/ |
|
3198 |
|
3199 mp4memcpy(buf+i, handle->videoDecSpecificInfo, handle->videoDecSpecificInfoSize); |
|
3200 |
|
3201 /*i += handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize;*/ |
|
3202 |
|
3203 i += handle->videoDecSpecificInfoSize; |
|
3204 |
|
3205 if (writeFile(handle, buf, ts->avcc) < 0) |
|
3206 { |
|
3207 mp4free(buf); |
|
3208 |
|
3209 return -1; |
|
3210 } |
|
3211 |
|
3212 mp4free(buf); |
|
3213 |
|
3214 return 0; |
|
3215 } |
|
3216 |
|
3217 |
|
3218 /* |
|
3219 * Function: |
|
3220 * |
|
3221 * mp4_i32 writeVideoSTTS(MP4HandleImp handle, |
|
3222 * trakSize *ts) |
|
3223 * |
|
3224 * Description: |
|
3225 * |
|
3226 * Write video STTS atom. |
|
3227 * |
|
3228 * Parameters: |
|
3229 * |
|
3230 * handle MP4 library handle |
|
3231 * ts Atom sizes |
|
3232 * |
|
3233 * Return value: |
|
3234 * |
|
3235 * 0 Success |
|
3236 * -1 Error |
|
3237 * |
|
3238 */ |
|
3239 mp4_i32 writeVideoSTTS(MP4HandleImp handle, trakSize *ts) |
|
3240 { |
|
3241 mp4_u8 *buf; |
|
3242 mp4_u32 i = 0; |
|
3243 mp4_u32 j; |
|
3244 |
|
3245 |
|
3246 buf = (mp4_u8 *)mp4malloc(ts->stts); |
|
3247 if (buf == NULL) |
|
3248 return -1; |
|
3249 |
|
3250 /* Size */ |
|
3251 insertu32(buf+i, (mp4_u32)ts->stts); |
|
3252 i += 4; |
|
3253 |
|
3254 /* Atom type */ |
|
3255 insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); |
|
3256 i += 4; |
|
3257 |
|
3258 /* Version and flags */ |
|
3259 insertu32(buf+i, (mp4_u32)0); |
|
3260 i += 4; |
|
3261 |
|
3262 /* Entry count */ |
|
3263 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsEntryCount); |
|
3264 i += 4; |
|
3265 |
|
3266 /* Sample count and sample delta */ |
|
3267 for (j = 0; j < handle->videoSampleTable->sttsEntryCount; j++) |
|
3268 { |
|
3269 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsSampleCount[j]); |
|
3270 i += 4; |
|
3271 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsSampleDelta[j]); |
|
3272 i += 4; |
|
3273 } |
|
3274 |
|
3275 if (writeFile(handle, buf, ts->stts) < 0) |
|
3276 { |
|
3277 mp4free(buf); |
|
3278 |
|
3279 return -1; |
|
3280 } |
|
3281 |
|
3282 mp4free(buf); |
|
3283 |
|
3284 return 0; |
|
3285 } |
|
3286 |
|
3287 |
|
3288 /* |
|
3289 * Function: |
|
3290 * |
|
3291 * mp4_i32 writeVideoSTTSLongClip(MP4HandleImp handle, |
|
3292 * trakSize *ts) |
|
3293 * |
|
3294 * Description: |
|
3295 * |
|
3296 * Write video STTS atom. |
|
3297 * |
|
3298 * Parameters: |
|
3299 * |
|
3300 * handle MP4 library handle |
|
3301 * ts Atom sizes |
|
3302 * |
|
3303 * Return value: |
|
3304 * |
|
3305 * 0 Success |
|
3306 * -1 Error |
|
3307 * |
|
3308 */ |
|
3309 mp4_i32 writeVideoSTTSLongClip(MP4HandleImp handle, trakSize *ts) |
|
3310 { |
|
3311 mp4_u8 *buf; |
|
3312 mp4_u8 *buf2; |
|
3313 mp4_u32 i = 0; |
|
3314 mp4_u32 j; |
|
3315 mp4_u32 left; |
|
3316 mp4_u32 bytestoread; |
|
3317 |
|
3318 |
|
3319 buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
3320 if (buf == NULL) |
|
3321 return -1; |
|
3322 |
|
3323 buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2); |
|
3324 if (buf2 == NULL) |
|
3325 { |
|
3326 mp4free(buf); |
|
3327 return -1; |
|
3328 } |
|
3329 |
|
3330 /* Size */ |
|
3331 insertu32(buf+i, (mp4_u32)ts->stts); |
|
3332 i += 4; |
|
3333 |
|
3334 /* Atom type */ |
|
3335 insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); |
|
3336 i += 4; |
|
3337 |
|
3338 /* Version and flags */ |
|
3339 insertu32(buf+i, (mp4_u32)0); |
|
3340 i += 4; |
|
3341 |
|
3342 /* Entry count */ |
|
3343 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsEntryCount); |
|
3344 i += 4; |
|
3345 |
|
3346 if (writeFile(handle, buf, i) < 0) |
|
3347 { |
|
3348 mp4free(buf); |
|
3349 mp4free(buf2); |
|
3350 |
|
3351 return -1; |
|
3352 } |
|
3353 |
|
3354 /* Sample count and delta */ |
|
3355 |
|
3356 /* Seek to the beginning of temporary files */ |
|
3357 |
|
3358 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0) |
|
3359 { |
|
3360 mp4free(buf); |
|
3361 mp4free(buf2); |
|
3362 return -1; |
|
3363 } |
|
3364 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0) |
|
3365 { |
|
3366 mp4free(buf); |
|
3367 mp4free(buf2); |
|
3368 return -1; |
|
3369 } |
|
3370 |
|
3371 left = handle->videoSampleTable->sttsEntryCount * 4; /* Bytes left in each file */ |
|
3372 |
|
3373 while (left) |
|
3374 { |
|
3375 if (left > METADATA_COPY_BUFFERSIZE / 2) |
|
3376 bytestoread = METADATA_COPY_BUFFERSIZE / 2; |
|
3377 else |
|
3378 bytestoread = left; |
|
3379 |
|
3380 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0) |
|
3381 { |
|
3382 mp4free(buf); |
|
3383 mp4free(buf2); |
|
3384 |
|
3385 return -1; |
|
3386 } |
|
3387 |
|
3388 for (j = 0; j < bytestoread; j += 4) |
|
3389 { |
|
3390 insertu32(buf + 2*j, ((mp4_u32 *)buf2)[j / 4]); |
|
3391 } |
|
3392 |
|
3393 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0) |
|
3394 { |
|
3395 mp4free(buf); |
|
3396 mp4free(buf2); |
|
3397 |
|
3398 return -1; |
|
3399 } |
|
3400 |
|
3401 for (j = 0; j < bytestoread; j += 4) |
|
3402 { |
|
3403 insertu32(buf + 2*j + 4, ((mp4_u32 *)buf2)[j / 4]); |
|
3404 } |
|
3405 |
|
3406 if (writeFile(handle, buf, 2 * bytestoread) < 0) |
|
3407 { |
|
3408 mp4free(buf); |
|
3409 mp4free(buf2); |
|
3410 |
|
3411 return -1; |
|
3412 } |
|
3413 |
|
3414 left -= bytestoread; |
|
3415 } |
|
3416 |
|
3417 mp4free(buf); |
|
3418 mp4free(buf2); |
|
3419 |
|
3420 |
|
3421 return 0; |
|
3422 } |
|
3423 |
|
3424 |
|
3425 /* |
|
3426 * Function: |
|
3427 * |
|
3428 * mp4_i32 writeVideoSTSC(MP4HandleImp handle, |
|
3429 * trakSize *ts) |
|
3430 * |
|
3431 * Description: |
|
3432 * |
|
3433 * Write video STSC atom. |
|
3434 * |
|
3435 * Parameters: |
|
3436 * |
|
3437 * handle MP4 library handle |
|
3438 * ts Atom sizes |
|
3439 * |
|
3440 * Return value: |
|
3441 * |
|
3442 * 0 Success |
|
3443 * -1 Error |
|
3444 * |
|
3445 */ |
|
3446 mp4_i32 writeVideoSTSC(MP4HandleImp handle, trakSize *ts) |
|
3447 { |
|
3448 mp4_u8 *buf; |
|
3449 mp4_u32 i = 0; |
|
3450 mp4_u32 j; |
|
3451 |
|
3452 |
|
3453 buf = (mp4_u8 *)mp4malloc(ts->stsc); |
|
3454 if (buf == NULL) |
|
3455 return -1; |
|
3456 |
|
3457 /* Size */ |
|
3458 insertu32(buf+i, (mp4_u32)ts->stsc); |
|
3459 i += 4; |
|
3460 |
|
3461 /* Atom type */ |
|
3462 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSC); |
|
3463 i += 4; |
|
3464 |
|
3465 /* Version and flags */ |
|
3466 insertu32(buf+i, (mp4_u32)0); |
|
3467 i += 4; |
|
3468 |
|
3469 /* Entry count */ |
|
3470 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscEntryCount); |
|
3471 i += 4; |
|
3472 |
|
3473 /* First chunk, samples per chunk and sample description index */ |
|
3474 for (j = 0; j < handle->videoSampleTable->stscEntryCount; j++) |
|
3475 { |
|
3476 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscFirstChunk[j]); |
|
3477 i += 4; |
|
3478 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscSamplesPerChunk[j]); |
|
3479 i += 4; |
|
3480 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscSampleDescriptionIndex[j]); |
|
3481 i += 4; |
|
3482 } |
|
3483 |
|
3484 if (writeFile(handle, buf, ts->stsc) < 0) |
|
3485 { |
|
3486 mp4free(buf); |
|
3487 |
|
3488 return -1; |
|
3489 } |
|
3490 |
|
3491 mp4free(buf); |
|
3492 |
|
3493 return 0; |
|
3494 } |
|
3495 |
|
3496 |
|
3497 /* |
|
3498 * Function: |
|
3499 * |
|
3500 * mp4_i32 writeVideoSTSZ(MP4HandleImp handle, |
|
3501 * trakSize *ts) |
|
3502 * |
|
3503 * Description: |
|
3504 * |
|
3505 * Write video STSZ atom. |
|
3506 * |
|
3507 * Parameters: |
|
3508 * |
|
3509 * handle MP4 library handle |
|
3510 * ts Atom sizes |
|
3511 * |
|
3512 * Return value: |
|
3513 * |
|
3514 * 0 Success |
|
3515 * -1 Error |
|
3516 * |
|
3517 */ |
|
3518 mp4_i32 writeVideoSTSZ(MP4HandleImp handle, trakSize *ts) |
|
3519 { |
|
3520 mp4_u8 *buf; |
|
3521 mp4_u32 i = 0; |
|
3522 mp4_u32 j; |
|
3523 |
|
3524 |
|
3525 buf = (mp4_u8 *)mp4malloc(ts->stsz); |
|
3526 if (buf == NULL) |
|
3527 return -1; |
|
3528 |
|
3529 /* Size */ |
|
3530 insertu32(buf+i, (mp4_u32)ts->stsz); |
|
3531 i += 4; |
|
3532 |
|
3533 /* Atom type */ |
|
3534 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); |
|
3535 i += 4; |
|
3536 |
|
3537 /* Version and flags */ |
|
3538 insertu32(buf+i, (mp4_u32)0); |
|
3539 i += 4; |
|
3540 |
|
3541 /* Sample size */ |
|
3542 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleSize); |
|
3543 i += 4; |
|
3544 |
|
3545 /* Sample count */ |
|
3546 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleCount); |
|
3547 i += 4; |
|
3548 |
|
3549 /* Entry sizes */ |
|
3550 if (handle->videoSampleTable->stszSampleSize == 0) |
|
3551 { |
|
3552 for (j = 0; j < handle->videoSampleTable->stszSampleCount; j++) |
|
3553 { |
|
3554 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszEntrySize[j]); |
|
3555 i += 4; |
|
3556 } |
|
3557 } |
|
3558 |
|
3559 if (writeFile(handle, buf, ts->stsz) < 0) |
|
3560 { |
|
3561 mp4free(buf); |
|
3562 |
|
3563 return -1; |
|
3564 } |
|
3565 |
|
3566 mp4free(buf); |
|
3567 |
|
3568 return 0; |
|
3569 } |
|
3570 |
|
3571 |
|
3572 /* |
|
3573 * Function: |
|
3574 * |
|
3575 * mp4_i32 writeVideoSTSZLongClip(MP4HandleImp handle, |
|
3576 * trakSize *ts) |
|
3577 * |
|
3578 * Description: |
|
3579 * |
|
3580 * Write video STSZ atom. |
|
3581 * |
|
3582 * Parameters: |
|
3583 * |
|
3584 * handle MP4 library handle |
|
3585 * ts Atom sizes |
|
3586 * |
|
3587 * Return value: |
|
3588 * |
|
3589 * 0 Success |
|
3590 * -1 Error |
|
3591 * |
|
3592 */ |
|
3593 mp4_i32 writeVideoSTSZLongClip(MP4HandleImp handle, trakSize *ts) |
|
3594 { |
|
3595 mp4_u8 *buf; |
|
3596 mp4_u8 *buf2; |
|
3597 mp4_u32 i = 0; |
|
3598 mp4_u32 j; |
|
3599 mp4_u32 left; |
|
3600 mp4_u32 bytestoread; |
|
3601 |
|
3602 |
|
3603 buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
3604 if (buf == NULL) |
|
3605 return -1; |
|
3606 |
|
3607 buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
3608 if (buf2 == NULL) |
|
3609 { |
|
3610 mp4free(buf); |
|
3611 return -1; |
|
3612 } |
|
3613 |
|
3614 /* Size */ |
|
3615 insertu32(buf+i, (mp4_u32)ts->stsz); |
|
3616 i += 4; |
|
3617 |
|
3618 /* Atom type */ |
|
3619 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); |
|
3620 i += 4; |
|
3621 |
|
3622 /* Version and flags */ |
|
3623 insertu32(buf+i, (mp4_u32)0); |
|
3624 i += 4; |
|
3625 |
|
3626 /* Sample size */ |
|
3627 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleSize); |
|
3628 i += 4; |
|
3629 |
|
3630 /* Sample count */ |
|
3631 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleCount); |
|
3632 i += 4; |
|
3633 |
|
3634 if (writeFile(handle, buf, i) < 0) |
|
3635 { |
|
3636 mp4free(buf); |
|
3637 mp4free(buf2); |
|
3638 |
|
3639 return -1; |
|
3640 } |
|
3641 |
|
3642 /* Entry sizes */ |
|
3643 |
|
3644 if (handle->videoSampleTable->stszSampleSize == 0) |
|
3645 { |
|
3646 /* Seek to the beginning of temporary file */ |
|
3647 |
|
3648 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0) |
|
3649 { |
|
3650 mp4free(buf); |
|
3651 mp4free(buf2); |
|
3652 return -1; |
|
3653 } |
|
3654 |
|
3655 left = handle->videoSampleTable->stszSampleCount * 4; /* Bytes left in the file */ |
|
3656 |
|
3657 while (left) |
|
3658 { |
|
3659 if (left > METADATA_COPY_BUFFERSIZE) |
|
3660 bytestoread = METADATA_COPY_BUFFERSIZE; |
|
3661 else |
|
3662 bytestoread = left; |
|
3663 |
|
3664 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0) |
|
3665 { |
|
3666 mp4free(buf); |
|
3667 mp4free(buf2); |
|
3668 |
|
3669 return -1; |
|
3670 } |
|
3671 |
|
3672 for (j = 0; j < bytestoread; j += 4) |
|
3673 { |
|
3674 insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]); |
|
3675 } |
|
3676 |
|
3677 if (writeFile(handle, buf, bytestoread) < 0) |
|
3678 { |
|
3679 mp4free(buf); |
|
3680 mp4free(buf2); |
|
3681 |
|
3682 return -1; |
|
3683 } |
|
3684 |
|
3685 left -= bytestoread; |
|
3686 } |
|
3687 } |
|
3688 |
|
3689 mp4free(buf); |
|
3690 mp4free(buf2); |
|
3691 |
|
3692 |
|
3693 return 0; |
|
3694 } |
|
3695 |
|
3696 |
|
3697 /* |
|
3698 * Function: |
|
3699 * |
|
3700 * mp4_i32 writeVideoSTCO(MP4HandleImp handle, |
|
3701 * trakSize *ts) |
|
3702 * |
|
3703 * Description: |
|
3704 * |
|
3705 * Write video STCO atom. |
|
3706 * |
|
3707 * Parameters: |
|
3708 * |
|
3709 * handle MP4 library handle |
|
3710 * ts Atom sizes |
|
3711 * |
|
3712 * Return value: |
|
3713 * |
|
3714 * 0 Success |
|
3715 * -1 Error |
|
3716 * |
|
3717 */ |
|
3718 mp4_i32 writeVideoSTCO(MP4HandleImp handle, trakSize *ts) |
|
3719 { |
|
3720 mp4_u8 *buf; |
|
3721 mp4_u32 i = 0; |
|
3722 mp4_u32 j; |
|
3723 |
|
3724 |
|
3725 buf = (mp4_u8 *)mp4malloc(ts->stco); |
|
3726 if (buf == NULL) |
|
3727 return -1; |
|
3728 |
|
3729 /* Size */ |
|
3730 insertu32(buf+i, (mp4_u32)ts->stco); |
|
3731 i += 4; |
|
3732 |
|
3733 /* Atom type */ |
|
3734 insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); |
|
3735 i += 4; |
|
3736 |
|
3737 /* Version and flags */ |
|
3738 insertu32(buf+i, (mp4_u32)0); |
|
3739 i += 4; |
|
3740 |
|
3741 /* Entry count */ |
|
3742 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); |
|
3743 i += 4; |
|
3744 |
|
3745 /* Chunk offsets */ |
|
3746 for (j = 0; j < handle->videoSampleTable->stcoEntryCount; j++) |
|
3747 { |
|
3748 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoChunkOffset[j]); |
|
3749 i += 4; |
|
3750 } |
|
3751 |
|
3752 if (writeFile(handle, buf, ts->stco) < 0) |
|
3753 { |
|
3754 mp4free(buf); |
|
3755 |
|
3756 return -1; |
|
3757 } |
|
3758 |
|
3759 mp4free(buf); |
|
3760 |
|
3761 return 0; |
|
3762 } |
|
3763 |
|
3764 /* |
|
3765 * Function: |
|
3766 * |
|
3767 * mp4_i32 writeVideoCO64(MP4HandleImp handle, |
|
3768 * trakSize *ts) |
|
3769 * |
|
3770 * Description: |
|
3771 * |
|
3772 * Write video CO64 atom. |
|
3773 * |
|
3774 * Parameters: |
|
3775 * |
|
3776 * handle MP4 library handle |
|
3777 * ts Atom sizes |
|
3778 * |
|
3779 * Return value: |
|
3780 * |
|
3781 * 0 Success |
|
3782 * -1 Error |
|
3783 * |
|
3784 */ |
|
3785 mp4_i32 writeVideoCO64(MP4HandleImp handle, trakSize *ts) |
|
3786 { |
|
3787 mp4_u8 *buf; |
|
3788 mp4_u32 i = 0; |
|
3789 mp4_u32 j; |
|
3790 |
|
3791 |
|
3792 buf = (mp4_u8 *)mp4malloc(ts->stco); |
|
3793 if (buf == NULL) |
|
3794 return -1; |
|
3795 |
|
3796 /* Size */ |
|
3797 insertu32(buf+i, (mp4_u32)ts->stco); |
|
3798 i += 4; |
|
3799 |
|
3800 /* Atom type */ |
|
3801 insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); |
|
3802 i += 4; |
|
3803 |
|
3804 /* Version and flags */ |
|
3805 insertu32(buf+i, (mp4_u32)0); |
|
3806 i += 4; |
|
3807 |
|
3808 /* Entry count */ |
|
3809 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); |
|
3810 i += 4; |
|
3811 |
|
3812 /* Chunk offsets */ |
|
3813 for (j = 0; j < handle->videoSampleTable->stcoEntryCount; j++) |
|
3814 { |
|
3815 insertu64(buf+i, (mp4_u64)handle->videoSampleTable->stcoChunkOffset[j]); |
|
3816 i += 8; |
|
3817 } |
|
3818 |
|
3819 if (writeFile(handle, buf, ts->stco) < 0) |
|
3820 { |
|
3821 mp4free(buf); |
|
3822 |
|
3823 return -1; |
|
3824 } |
|
3825 |
|
3826 mp4free(buf); |
|
3827 |
|
3828 return 0; |
|
3829 } |
|
3830 |
|
3831 /* |
|
3832 * Function: |
|
3833 * |
|
3834 * mp4_i32 writeVideoSTCOLongClip(MP4HandleImp handle, |
|
3835 * trakSize *ts) |
|
3836 * |
|
3837 * Description: |
|
3838 * |
|
3839 * Write video STCO atom. |
|
3840 * |
|
3841 * Parameters: |
|
3842 * |
|
3843 * handle MP4 library handle |
|
3844 * ts Atom sizes |
|
3845 * |
|
3846 * Return value: |
|
3847 * |
|
3848 * 0 Success |
|
3849 * -1 Error |
|
3850 * |
|
3851 */ |
|
3852 mp4_i32 writeVideoSTCOLongClip(MP4HandleImp handle, trakSize *ts) |
|
3853 { |
|
3854 mp4_u8 *buf; |
|
3855 mp4_u8 *buf2; |
|
3856 mp4_u32 i = 0; |
|
3857 mp4_u32 j; |
|
3858 mp4_u32 left; |
|
3859 mp4_u32 bytestoread; |
|
3860 mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 |
|
3861 //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 |
|
3862 |
|
3863 buf = (mp4_u8 *)mp4malloc(bufferSize); |
|
3864 if (buf == NULL) |
|
3865 return -1; |
|
3866 |
|
3867 buf2 = (mp4_u8 *)mp4malloc(bufferSize); |
|
3868 if (buf2 == NULL) |
|
3869 { |
|
3870 mp4free(buf); |
|
3871 return -1; |
|
3872 } |
|
3873 |
|
3874 /* Size */ |
|
3875 insertu32(buf+i, (mp4_u32)ts->stco); |
|
3876 i += 4; |
|
3877 |
|
3878 /* Atom type */ |
|
3879 insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); |
|
3880 i += 4; |
|
3881 |
|
3882 /* Version and flags */ |
|
3883 insertu32(buf+i, (mp4_u32)0); |
|
3884 i += 4; |
|
3885 |
|
3886 /* Entry count */ |
|
3887 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); |
|
3888 i += 4; |
|
3889 |
|
3890 if (writeFile(handle, buf, i) < 0) |
|
3891 { |
|
3892 mp4free(buf); |
|
3893 mp4free(buf2); |
|
3894 |
|
3895 return -1; |
|
3896 } |
|
3897 |
|
3898 /* Chunk offsets */ |
|
3899 |
|
3900 /* Seek to the beginning of temporary file */ |
|
3901 |
|
3902 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) |
|
3903 { |
|
3904 mp4free(buf); |
|
3905 mp4free(buf2); |
|
3906 return -1; |
|
3907 } |
|
3908 |
|
3909 left = handle->videoSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ |
|
3910 |
|
3911 while (left) |
|
3912 { |
|
3913 if (left > bufferSize) |
|
3914 bytestoread = bufferSize; |
|
3915 else |
|
3916 bytestoread = left; |
|
3917 |
|
3918 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) |
|
3919 { |
|
3920 mp4free(buf); |
|
3921 mp4free(buf2); |
|
3922 |
|
3923 return -1; |
|
3924 } |
|
3925 |
|
3926 for (j = 0; j < bytestoread; j += 8) |
|
3927 { |
|
3928 ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ |
|
3929 insertu32(buf + j/2, ((mp4_u64 *)buf2)[j / 8]); |
|
3930 } |
|
3931 |
|
3932 if (writeFile(handle, buf, bytestoread/2) < 0) |
|
3933 { |
|
3934 mp4free(buf); |
|
3935 mp4free(buf2); |
|
3936 |
|
3937 return -1; |
|
3938 } |
|
3939 |
|
3940 left -= bytestoread; |
|
3941 } |
|
3942 |
|
3943 mp4free(buf); |
|
3944 mp4free(buf2); |
|
3945 |
|
3946 |
|
3947 return 0; |
|
3948 } |
|
3949 |
|
3950 /* |
|
3951 * Function: |
|
3952 * |
|
3953 * mp4_i32 writeVideoCO64LongClip(MP4HandleImp handle, |
|
3954 * trakSize *ts) |
|
3955 * |
|
3956 * Description: |
|
3957 * |
|
3958 * Write video CO64 atom. |
|
3959 * |
|
3960 * Parameters: |
|
3961 * |
|
3962 * handle MP4 library handle |
|
3963 * ts Atom sizes |
|
3964 * |
|
3965 * Return value: |
|
3966 * |
|
3967 * 0 Success |
|
3968 * -1 Error |
|
3969 * |
|
3970 */ |
|
3971 mp4_i32 writeVideoCO64LongClip(MP4HandleImp handle, trakSize *ts) |
|
3972 { |
|
3973 mp4_u8 *buf; |
|
3974 mp4_u8 *buf2; |
|
3975 mp4_u32 i = 0; |
|
3976 mp4_u32 j; |
|
3977 mp4_u32 left; |
|
3978 mp4_u32 bytestoread; |
|
3979 mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 |
|
3980 //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 |
|
3981 |
|
3982 buf = (mp4_u8 *)mp4malloc(bufferSize); |
|
3983 if (buf == NULL) |
|
3984 return -1; |
|
3985 |
|
3986 buf2 = (mp4_u8 *)mp4malloc(bufferSize); |
|
3987 if (buf2 == NULL) |
|
3988 { |
|
3989 mp4free(buf); |
|
3990 return -1; |
|
3991 } |
|
3992 |
|
3993 /* Size */ |
|
3994 insertu32(buf+i, (mp4_u32)ts->stco); |
|
3995 i += 4; |
|
3996 |
|
3997 /* Atom type */ |
|
3998 insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); |
|
3999 i += 4; |
|
4000 |
|
4001 /* Version and flags */ |
|
4002 insertu32(buf+i, (mp4_u32)0); |
|
4003 i += 4; |
|
4004 |
|
4005 /* Entry count */ |
|
4006 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); |
|
4007 i += 4; |
|
4008 |
|
4009 if (writeFile(handle, buf, i) < 0) |
|
4010 { |
|
4011 mp4free(buf); |
|
4012 mp4free(buf2); |
|
4013 |
|
4014 return -1; |
|
4015 } |
|
4016 |
|
4017 /* Chunk offsets */ |
|
4018 |
|
4019 /* Seek to the beginning of temporary file */ |
|
4020 |
|
4021 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) |
|
4022 { |
|
4023 mp4free(buf); |
|
4024 mp4free(buf2); |
|
4025 return -1; |
|
4026 } |
|
4027 |
|
4028 left = handle->videoSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ |
|
4029 |
|
4030 while (left) |
|
4031 { |
|
4032 if (left > bufferSize) |
|
4033 bytestoread = bufferSize; |
|
4034 else |
|
4035 bytestoread = left; |
|
4036 |
|
4037 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) |
|
4038 { |
|
4039 mp4free(buf); |
|
4040 mp4free(buf2); |
|
4041 |
|
4042 return -1; |
|
4043 } |
|
4044 |
|
4045 for (j = 0; j < bytestoread; j += 8) |
|
4046 { |
|
4047 ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ |
|
4048 insertu64(buf + j, ((mp4_u64 *)buf2)[j / 8]); |
|
4049 } |
|
4050 |
|
4051 if (writeFile(handle, buf, bytestoread) < 0) |
|
4052 { |
|
4053 mp4free(buf); |
|
4054 mp4free(buf2); |
|
4055 |
|
4056 return -1; |
|
4057 } |
|
4058 |
|
4059 left -= bytestoread; |
|
4060 } |
|
4061 |
|
4062 mp4free(buf); |
|
4063 mp4free(buf2); |
|
4064 |
|
4065 |
|
4066 return 0; |
|
4067 } |
|
4068 |
|
4069 /* |
|
4070 * Function: |
|
4071 * |
|
4072 * mp4_i32 writeVideoSTSS(MP4HandleImp handle, |
|
4073 * trakSize *ts) |
|
4074 * |
|
4075 * Description: |
|
4076 * |
|
4077 * Write video STSS atom. |
|
4078 * |
|
4079 * Parameters: |
|
4080 * |
|
4081 * handle MP4 library handle |
|
4082 * ts Atom sizes |
|
4083 * |
|
4084 * Return value: |
|
4085 * |
|
4086 * 0 Success |
|
4087 * -1 Error |
|
4088 * |
|
4089 */ |
|
4090 mp4_i32 writeVideoSTSS(MP4HandleImp handle, trakSize *ts) |
|
4091 { |
|
4092 mp4_u8 *buf; |
|
4093 mp4_u32 i = 0; |
|
4094 mp4_u32 j; |
|
4095 |
|
4096 |
|
4097 buf = (mp4_u8 *)mp4malloc(ts->stss); |
|
4098 if (buf == NULL) |
|
4099 return -1; |
|
4100 |
|
4101 /* Size */ |
|
4102 insertu32(buf+i, (mp4_u32)ts->stss); |
|
4103 i += 4; |
|
4104 |
|
4105 /* Atom type */ |
|
4106 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSS); |
|
4107 i += 4; |
|
4108 |
|
4109 /* Version and flags */ |
|
4110 insertu32(buf+i, (mp4_u32)0); |
|
4111 i += 4; |
|
4112 |
|
4113 /* Entry count */ |
|
4114 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssEntryCount); |
|
4115 i += 4; |
|
4116 |
|
4117 /* Sample numbers */ |
|
4118 for (j = 0; j < handle->videoSampleTable->stssEntryCount; j++) |
|
4119 { |
|
4120 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssSampleNumber[j]); |
|
4121 i += 4; |
|
4122 } |
|
4123 |
|
4124 if (writeFile(handle, buf, ts->stss) < 0) |
|
4125 { |
|
4126 mp4free(buf); |
|
4127 |
|
4128 return -1; |
|
4129 } |
|
4130 |
|
4131 mp4free(buf); |
|
4132 |
|
4133 return 0; |
|
4134 } |
|
4135 |
|
4136 |
|
4137 /* |
|
4138 * Function: |
|
4139 * |
|
4140 * mp4_i32 writeVideoSTSSLongClip(MP4HandleImp handle, |
|
4141 * trakSize *ts) |
|
4142 * |
|
4143 * Description: |
|
4144 * |
|
4145 * Write video STSS atom. |
|
4146 * |
|
4147 * Parameters: |
|
4148 * |
|
4149 * handle MP4 library handle |
|
4150 * ts Atom sizes |
|
4151 * |
|
4152 * Return value: |
|
4153 * |
|
4154 * 0 Success |
|
4155 * -1 Error |
|
4156 * |
|
4157 */ |
|
4158 mp4_i32 writeVideoSTSSLongClip(MP4HandleImp handle, trakSize *ts) |
|
4159 { |
|
4160 mp4_u8 *buf; |
|
4161 mp4_u8 *buf2; |
|
4162 mp4_u32 i = 0; |
|
4163 mp4_u32 j; |
|
4164 mp4_u32 left; |
|
4165 mp4_u32 bytestoread; |
|
4166 |
|
4167 |
|
4168 buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
4169 if (buf == NULL) |
|
4170 return -1; |
|
4171 |
|
4172 buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
4173 if (buf2 == NULL) |
|
4174 { |
|
4175 mp4free(buf); |
|
4176 return -1; |
|
4177 } |
|
4178 |
|
4179 /* Size */ |
|
4180 insertu32(buf+i, (mp4_u32)ts->stss); |
|
4181 i += 4; |
|
4182 |
|
4183 /* Atom type */ |
|
4184 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSS); |
|
4185 i += 4; |
|
4186 |
|
4187 /* Version and flags */ |
|
4188 insertu32(buf+i, (mp4_u32)0); |
|
4189 i += 4; |
|
4190 |
|
4191 /* Entry count */ |
|
4192 insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssEntryCount); |
|
4193 i += 4; |
|
4194 |
|
4195 if (writeFile(handle, buf, i) < 0) |
|
4196 { |
|
4197 mp4free(buf); |
|
4198 mp4free(buf2); |
|
4199 |
|
4200 return -1; |
|
4201 } |
|
4202 |
|
4203 /* Sample numbers */ |
|
4204 |
|
4205 /* Seek to the beginning of temporary file */ |
|
4206 |
|
4207 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0) |
|
4208 { |
|
4209 mp4free(buf); |
|
4210 mp4free(buf2); |
|
4211 return -1; |
|
4212 } |
|
4213 |
|
4214 left = handle->videoSampleTable->stssEntryCount * 4; /* Bytes left in the file */ |
|
4215 |
|
4216 while (left) |
|
4217 { |
|
4218 if (left > METADATA_COPY_BUFFERSIZE) |
|
4219 bytestoread = METADATA_COPY_BUFFERSIZE; |
|
4220 else |
|
4221 bytestoread = left; |
|
4222 |
|
4223 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0) |
|
4224 { |
|
4225 mp4free(buf); |
|
4226 mp4free(buf2); |
|
4227 |
|
4228 return -1; |
|
4229 } |
|
4230 |
|
4231 for (j = 0; j < bytestoread; j += 4) |
|
4232 { |
|
4233 insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]); |
|
4234 } |
|
4235 |
|
4236 if (writeFile(handle, buf, bytestoread) < 0) |
|
4237 { |
|
4238 mp4free(buf); |
|
4239 mp4free(buf2); |
|
4240 |
|
4241 return -1; |
|
4242 } |
|
4243 |
|
4244 left -= bytestoread; |
|
4245 } |
|
4246 |
|
4247 mp4free(buf); |
|
4248 mp4free(buf2); |
|
4249 |
|
4250 |
|
4251 return 0; |
|
4252 } |
|
4253 |
|
4254 |
|
4255 /* |
|
4256 * Function: |
|
4257 * |
|
4258 * mp4_i32 writeAudioTrak(MP4HandleImp handle, |
|
4259 * trakSize *ts) |
|
4260 * |
|
4261 * Description: |
|
4262 * |
|
4263 * Write audio track atom. |
|
4264 * |
|
4265 * Parameters: |
|
4266 * |
|
4267 * handle MP4 library handle |
|
4268 * ts Atom sizes |
|
4269 * |
|
4270 * Return value: |
|
4271 * |
|
4272 * 0 Success |
|
4273 * -1 Error |
|
4274 * |
|
4275 */ |
|
4276 mp4_i32 writeAudioTrak(MP4HandleImp handle, trakSize *ts) |
|
4277 { |
|
4278 mp4_u8 buf[8]; |
|
4279 mp4_u32 i = 0; |
|
4280 |
|
4281 |
|
4282 /* Size */ |
|
4283 insertu32(buf+i, (mp4_u32)ts->trak); |
|
4284 i += 4; |
|
4285 |
|
4286 /* Atom type */ |
|
4287 insertu32(buf+i, (mp4_u32)ATOMTYPE_TRAK); |
|
4288 i += 4; |
|
4289 |
|
4290 if (writeFile(handle, buf, 8) < 0) |
|
4291 return -1; |
|
4292 |
|
4293 if (writeAudioTKHD(handle, ts) < 0) |
|
4294 return -1; |
|
4295 |
|
4296 if (writeAudioMDIA(handle, ts) < 0) |
|
4297 return -1; |
|
4298 |
|
4299 if (handle->audioUDTA) |
|
4300 { |
|
4301 if (writeUDTA(handle, handle->audioUDTA) < 0) |
|
4302 return -1; |
|
4303 } |
|
4304 |
|
4305 return 0; |
|
4306 } |
|
4307 |
|
4308 |
|
4309 /* |
|
4310 * Function: |
|
4311 * |
|
4312 * mp4_i32 writeAudioTKHD(MP4HandleImp handle, |
|
4313 * trakSize *ts) |
|
4314 * |
|
4315 * Description: |
|
4316 * |
|
4317 * Write audio TKHD atom. |
|
4318 * |
|
4319 * Parameters: |
|
4320 * |
|
4321 * handle MP4 library handle |
|
4322 * ts Atom sizes |
|
4323 * |
|
4324 * Return value: |
|
4325 * |
|
4326 * 0 Success |
|
4327 * -1 Error |
|
4328 * |
|
4329 */ |
|
4330 mp4_i32 writeAudioTKHD(MP4HandleImp handle, trakSize *ts) |
|
4331 { |
|
4332 mp4_u8 *buf; |
|
4333 mp4_u32 i = 0; |
|
4334 mp4_u32 u32; |
|
4335 mp4_double ud; |
|
4336 |
|
4337 |
|
4338 buf = (mp4_u8 *)mp4malloc(ts->tkhd); |
|
4339 if (buf == NULL) |
|
4340 return -1; |
|
4341 |
|
4342 /* Size */ |
|
4343 insertu32(buf+i, (mp4_u32)ts->tkhd); |
|
4344 i += 4; |
|
4345 |
|
4346 /* Atom type */ |
|
4347 insertu32(buf+i, (mp4_u32)ATOMTYPE_TKHD); |
|
4348 i += 4; |
|
4349 |
|
4350 |
|
4351 if (handle->audioDuration > MP4_INT_MAX) |
|
4352 { |
|
4353 mp4_u64 u64; |
|
4354 /* Version and flags */ |
|
4355 buf[i++] = 1; |
|
4356 buf[i++] = 0; |
|
4357 buf[i++] = 0; |
|
4358 buf[i++] = 7; /* Track enabled, used in movie and preview */ |
|
4359 |
|
4360 /* Creation time */ |
|
4361 if (getCurrentTime(&u32) < 0) |
|
4362 u32 = 0; |
|
4363 insertu64(buf+i, (mp4_u64)u32); |
|
4364 i += 8; |
|
4365 |
|
4366 /* Modification time */ |
|
4367 if (getCurrentTime(&u32) < 0) |
|
4368 u32 = 0; |
|
4369 insertu64(buf+i, (mp4_u64)u32); |
|
4370 i += 8; |
|
4371 |
|
4372 /* Track ID */ |
|
4373 insertu32(buf+i, (mp4_u32)2); |
|
4374 i += 4; |
|
4375 |
|
4376 /* Reserved */ |
|
4377 insertu32(buf+i, (mp4_u32)0); |
|
4378 i += 4; |
|
4379 |
|
4380 /* Duration */ |
|
4381 if ( ( handle->audioTimeScale == 0 ) || ( handle->audioDuration == 0 ) ) |
|
4382 { |
|
4383 ud = 0; |
|
4384 } |
|
4385 else |
|
4386 { |
|
4387 ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->audioDuration / (mp4_double)handle->audioTimeScale + (mp4_double)0.5; |
|
4388 } |
|
4389 u64 = (mp4_u64)ud; |
|
4390 insertu64(buf+i, u64); |
|
4391 i += 8; |
|
4392 |
|
4393 } |
|
4394 else |
|
4395 { |
|
4396 /* Version and flags */ |
|
4397 buf[i++] = 0; |
|
4398 buf[i++] = 0; |
|
4399 buf[i++] = 0; |
|
4400 buf[i++] = 7; /* Track enabled, used in movie and preview */ |
|
4401 |
|
4402 /* Creation time */ |
|
4403 if (getCurrentTime(&u32) < 0) |
|
4404 u32 = 0; |
|
4405 insertu32(buf+i, (mp4_u32)u32); |
|
4406 i += 4; |
|
4407 |
|
4408 /* Modification time */ |
|
4409 if (getCurrentTime(&u32) < 0) |
|
4410 u32 = 0; |
|
4411 insertu32(buf+i, (mp4_u32)u32); |
|
4412 i += 4; |
|
4413 |
|
4414 /* Track ID */ |
|
4415 insertu32(buf+i, (mp4_u32)2); |
|
4416 i += 4; |
|
4417 |
|
4418 /* Reserved */ |
|
4419 insertu32(buf+i, (mp4_u32)0); |
|
4420 i += 4; |
|
4421 |
|
4422 /* Duration */ |
|
4423 if ( ( handle->audioTimeScale == 0 ) || ( handle->audioDuration == 0 ) ) |
|
4424 { |
|
4425 ud = 0; |
|
4426 } |
|
4427 else |
|
4428 { |
|
4429 ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->audioDuration / (mp4_double)handle->audioTimeScale + (mp4_double)0.5; |
|
4430 } |
|
4431 u32 = (mp4_u32)ud; |
|
4432 insertu32(buf+i, u32); |
|
4433 i += 4; |
|
4434 } |
|
4435 /* Reserved */ |
|
4436 insertu32(buf+i, (mp4_u32)0); |
|
4437 i += 4; |
|
4438 |
|
4439 insertu32(buf+i, (mp4_u32)0); |
|
4440 i += 4; |
|
4441 |
|
4442 insertu32(buf+i, (mp4_u32)0); |
|
4443 i += 4; |
|
4444 |
|
4445 insertu16(buf+i, (mp4_u16)0x0100); /* Audio track */ |
|
4446 i += 2; |
|
4447 |
|
4448 insertu16(buf+i, (mp4_u16)0); |
|
4449 i += 2; |
|
4450 |
|
4451 insertu32(buf+i, (mp4_u32)0x00010000); |
|
4452 i += 4; |
|
4453 |
|
4454 insertu32(buf+i, (mp4_u32)0x00000000); |
|
4455 i += 4; |
|
4456 |
|
4457 insertu32(buf+i, (mp4_u32)0x00000000); |
|
4458 i += 4; |
|
4459 |
|
4460 insertu32(buf+i, (mp4_u32)0x00000000); |
|
4461 i += 4; |
|
4462 |
|
4463 insertu32(buf+i, (mp4_u32)0x00010000); |
|
4464 i += 4; |
|
4465 |
|
4466 insertu32(buf+i, (mp4_u32)0x00000000); |
|
4467 i += 4; |
|
4468 |
|
4469 insertu32(buf+i, (mp4_u32)0x00000000); |
|
4470 i += 4; |
|
4471 |
|
4472 insertu32(buf+i, (mp4_u32)0x00000000); |
|
4473 i += 4; |
|
4474 |
|
4475 insertu32(buf+i, (mp4_u32)0x40000000); |
|
4476 i += 4; |
|
4477 |
|
4478 insertu32(buf+i, (mp4_u32)0); /* Audio track */ |
|
4479 i += 4; |
|
4480 |
|
4481 insertu32(buf+i, (mp4_u32)0); /* Audio track */ |
|
4482 i += 4; |
|
4483 |
|
4484 if (writeFile(handle, buf, ts->tkhd) < 0) |
|
4485 { |
|
4486 mp4free(buf); |
|
4487 |
|
4488 return -1; |
|
4489 } |
|
4490 |
|
4491 mp4free(buf); |
|
4492 |
|
4493 return 0; |
|
4494 } |
|
4495 |
|
4496 |
|
4497 /* |
|
4498 * Function: |
|
4499 * |
|
4500 * mp4_i32 writeAudioMDIA(MP4HandleImp handle, |
|
4501 * trakSize *ts) |
|
4502 * |
|
4503 * Description: |
|
4504 * |
|
4505 * Write audio MDIA atom. |
|
4506 * |
|
4507 * Parameters: |
|
4508 * |
|
4509 * handle MP4 library handle |
|
4510 * ts Atom sizes |
|
4511 * |
|
4512 * Return value: |
|
4513 * |
|
4514 * 0 Success |
|
4515 * -1 Error |
|
4516 * |
|
4517 */ |
|
4518 mp4_i32 writeAudioMDIA(MP4HandleImp handle, trakSize *ts) |
|
4519 { |
|
4520 mp4_u8 buf[8]; |
|
4521 mp4_u32 i = 0; |
|
4522 |
|
4523 |
|
4524 /* Size */ |
|
4525 insertu32(buf+i, (mp4_u32)ts->mdia); |
|
4526 i += 4; |
|
4527 |
|
4528 /* Atom type */ |
|
4529 insertu32(buf+i, (mp4_u32)ATOMTYPE_MDIA); |
|
4530 i += 4; |
|
4531 |
|
4532 if (writeFile(handle, buf, 8) < 0) |
|
4533 return -1; |
|
4534 |
|
4535 if (writeAudioMDHD(handle, ts) < 0) |
|
4536 return -1; |
|
4537 |
|
4538 if (writeAudioHDLR(handle, ts) < 0) |
|
4539 return -1; |
|
4540 |
|
4541 if (writeAudioMINF(handle, ts) < 0) |
|
4542 return -1; |
|
4543 |
|
4544 return 0; |
|
4545 } |
|
4546 |
|
4547 |
|
4548 /* |
|
4549 * Function: |
|
4550 * |
|
4551 * mp4_i32 writeAudioMDHD(MP4HandleImp handle, |
|
4552 * trakSize *ts) |
|
4553 * |
|
4554 * Description: |
|
4555 * |
|
4556 * Write audio MDHD atom. |
|
4557 * |
|
4558 * Parameters: |
|
4559 * |
|
4560 * handle MP4 library handle |
|
4561 * ts Atom sizes |
|
4562 * |
|
4563 * Return value: |
|
4564 * |
|
4565 * 0 Success |
|
4566 * -1 Error |
|
4567 * |
|
4568 */ |
|
4569 mp4_i32 writeAudioMDHD(MP4HandleImp handle, trakSize *ts) |
|
4570 { |
|
4571 mp4_u8 *buf; |
|
4572 mp4_u32 i = 0; |
|
4573 mp4_u32 u32; |
|
4574 |
|
4575 |
|
4576 buf = (mp4_u8 *)mp4malloc(ts->mdhd); |
|
4577 if (buf == NULL) |
|
4578 return -1; |
|
4579 |
|
4580 /* Size */ |
|
4581 insertu32(buf+i, (mp4_u32)ts->mdhd); |
|
4582 i += 4; |
|
4583 |
|
4584 /* Atom type */ |
|
4585 insertu32(buf+i, (mp4_u32)ATOMTYPE_MDHD); |
|
4586 i += 4; |
|
4587 |
|
4588 if (handle->audioDuration > MP4_INT_MAX) |
|
4589 { |
|
4590 /* Version and flags */ |
|
4591 insertu32(buf+i, (mp4_u32)0x1000000); //version 1 atom |
|
4592 i += 4; |
|
4593 |
|
4594 /* Creation time */ |
|
4595 if (getCurrentTime(&u32) < 0) |
|
4596 u32 = 0; |
|
4597 insertu64(buf+i, (mp4_u64)u32); |
|
4598 i += 8; |
|
4599 |
|
4600 /* Modification time */ |
|
4601 if (getCurrentTime(&u32) < 0) |
|
4602 u32 = 0; |
|
4603 insertu64(buf+i, (mp4_u64)u32); |
|
4604 i += 8; |
|
4605 |
|
4606 /* Timescale */ |
|
4607 insertu32(buf+i, (mp4_u32)handle->audioTimeScale); |
|
4608 i += 4; |
|
4609 |
|
4610 /* Duration */ |
|
4611 insertu64(buf+i, handle->audioDuration); |
|
4612 i += 8; |
|
4613 |
|
4614 } |
|
4615 else |
|
4616 { |
|
4617 /* Version and flags */ |
|
4618 insertu32(buf+i, (mp4_u32)0); |
|
4619 i += 4; |
|
4620 |
|
4621 /* Creation time */ |
|
4622 if (getCurrentTime(&u32) < 0) |
|
4623 u32 = 0; |
|
4624 insertu32(buf+i, (mp4_u32)u32); |
|
4625 i += 4; |
|
4626 |
|
4627 /* Modification time */ |
|
4628 if (getCurrentTime(&u32) < 0) |
|
4629 u32 = 0; |
|
4630 insertu32(buf+i, (mp4_u32)u32); |
|
4631 i += 4; |
|
4632 |
|
4633 /* Timescale */ |
|
4634 insertu32(buf+i, (mp4_u32)handle->audioTimeScale); |
|
4635 i += 4; |
|
4636 |
|
4637 /* Duration */ |
|
4638 insertu32(buf+i, (mp4_u32)handle->audioDuration); |
|
4639 i += 4; |
|
4640 } |
|
4641 |
|
4642 /* Language */ |
|
4643 insertu16(buf+i, (mp4_u16)0x55c4); /* 'und' */ |
|
4644 i += 2; |
|
4645 |
|
4646 /* Reserved */ |
|
4647 insertu16(buf+i, (mp4_u16)0x0000); |
|
4648 i += 2; |
|
4649 |
|
4650 if (writeFile(handle, buf, ts->mdhd) < 0) |
|
4651 { |
|
4652 mp4free(buf); |
|
4653 |
|
4654 return -1; |
|
4655 } |
|
4656 |
|
4657 mp4free(buf); |
|
4658 |
|
4659 return 0; |
|
4660 } |
|
4661 |
|
4662 |
|
4663 /* |
|
4664 * Function: |
|
4665 * |
|
4666 * mp4_i32 writeAudioHDLR(MP4HandleImp handle, |
|
4667 * trakSize *ts) |
|
4668 * |
|
4669 * Description: |
|
4670 * |
|
4671 * Write audio HDLR atom. |
|
4672 * |
|
4673 * Parameters: |
|
4674 * |
|
4675 * handle MP4 library handle |
|
4676 * ts Atom sizes |
|
4677 * |
|
4678 * Return value: |
|
4679 * |
|
4680 * 0 Success |
|
4681 * -1 Error |
|
4682 * |
|
4683 */ |
|
4684 mp4_i32 writeAudioHDLR(MP4HandleImp handle, trakSize *ts) |
|
4685 { |
|
4686 mp4_u8 *buf; |
|
4687 mp4_u32 i = 0; |
|
4688 |
|
4689 |
|
4690 buf = (mp4_u8 *)mp4malloc(ts->hdlr); |
|
4691 if (buf == NULL) |
|
4692 return -1; |
|
4693 |
|
4694 /* Size */ |
|
4695 insertu32(buf+i, (mp4_u32)ts->hdlr); |
|
4696 i += 4; |
|
4697 |
|
4698 /* Atom type */ |
|
4699 insertu32(buf+i, (mp4_u32)ATOMTYPE_HDLR); |
|
4700 i += 4; |
|
4701 |
|
4702 /* Version and flags */ |
|
4703 insertu32(buf+i, (mp4_u32)0); |
|
4704 i += 4; |
|
4705 |
|
4706 /* Reserved */ |
|
4707 insertu32(buf+i, (mp4_u32)0); |
|
4708 i += 4; |
|
4709 |
|
4710 /* Handler type */ |
|
4711 buf[i++] = 's'; |
|
4712 buf[i++] = 'o'; |
|
4713 buf[i++] = 'u'; |
|
4714 buf[i++] = 'n'; |
|
4715 |
|
4716 /* Reserved */ |
|
4717 insertu32(buf+i, (mp4_u32)0); |
|
4718 i += 4; |
|
4719 |
|
4720 /* Reserved */ |
|
4721 insertu32(buf+i, (mp4_u32)0); |
|
4722 i += 4; |
|
4723 |
|
4724 /* Reserved */ |
|
4725 insertu32(buf+i, (mp4_u32)0); |
|
4726 i += 4; |
|
4727 |
|
4728 /* Empty string */ |
|
4729 buf[i++] = 0; |
|
4730 |
|
4731 if (writeFile(handle, buf, ts->hdlr) < 0) |
|
4732 { |
|
4733 mp4free(buf); |
|
4734 |
|
4735 return -1; |
|
4736 } |
|
4737 |
|
4738 mp4free(buf); |
|
4739 |
|
4740 return 0; |
|
4741 } |
|
4742 |
|
4743 |
|
4744 /* |
|
4745 * Function: |
|
4746 * |
|
4747 * mp4_i32 writeAudioMINF(MP4HandleImp handle, |
|
4748 * trakSize *ts) |
|
4749 * |
|
4750 * Description: |
|
4751 * |
|
4752 * Write audio MINF atom. |
|
4753 * |
|
4754 * Parameters: |
|
4755 * |
|
4756 * handle MP4 library handle |
|
4757 * ts Atom sizes |
|
4758 * |
|
4759 * Return value: |
|
4760 * |
|
4761 * 0 Success |
|
4762 * -1 Error |
|
4763 * |
|
4764 */ |
|
4765 mp4_i32 writeAudioMINF(MP4HandleImp handle, trakSize *ts) |
|
4766 { |
|
4767 mp4_u8 buf[8]; |
|
4768 mp4_u32 i = 0; |
|
4769 |
|
4770 |
|
4771 /* Size */ |
|
4772 insertu32(buf+i, (mp4_u32)ts->minf); |
|
4773 i += 4; |
|
4774 |
|
4775 /* Atom type */ |
|
4776 insertu32(buf+i, (mp4_u32)ATOMTYPE_MINF); |
|
4777 i += 4; |
|
4778 |
|
4779 if (writeFile(handle, buf, 8) < 0) |
|
4780 return -1; |
|
4781 |
|
4782 if (writeSMHD(handle, ts) < 0) |
|
4783 return -1; |
|
4784 |
|
4785 if (writeDINF(handle, ts) < 0) |
|
4786 return -1; |
|
4787 |
|
4788 if (writeAudioSTBL(handle, ts) < 0) |
|
4789 return -1; |
|
4790 |
|
4791 return 0; |
|
4792 } |
|
4793 |
|
4794 |
|
4795 /* |
|
4796 * Function: |
|
4797 * |
|
4798 * mp4_i32 writeSMHD(MP4HandleImp handle, |
|
4799 * trakSize *ts) |
|
4800 * |
|
4801 * Description: |
|
4802 * |
|
4803 * Write SMHD atom. |
|
4804 * |
|
4805 * Parameters: |
|
4806 * |
|
4807 * handle MP4 library handle |
|
4808 * ts Atom sizes |
|
4809 * |
|
4810 * Return value: |
|
4811 * |
|
4812 * 0 Success |
|
4813 * -1 Error |
|
4814 * |
|
4815 */ |
|
4816 mp4_i32 writeSMHD(MP4HandleImp handle, trakSize *ts) |
|
4817 { |
|
4818 mp4_u8 *buf; |
|
4819 mp4_u32 i = 0; |
|
4820 |
|
4821 |
|
4822 buf = (mp4_u8 *)mp4malloc(ts->smhd); |
|
4823 if (buf == NULL) |
|
4824 return -1; |
|
4825 |
|
4826 /* Size */ |
|
4827 insertu32(buf+i, (mp4_u32)ts->smhd); |
|
4828 i += 4; |
|
4829 |
|
4830 /* Atom type */ |
|
4831 insertu32(buf+i, (mp4_u32)ATOMTYPE_SMHD); |
|
4832 i += 4; |
|
4833 |
|
4834 /* Version and flags */ |
|
4835 insertu32(buf+i, (mp4_u32)0); |
|
4836 i += 4; |
|
4837 |
|
4838 /* Reserved */ |
|
4839 insertu32(buf+i, (mp4_u32)0); |
|
4840 i += 4; |
|
4841 |
|
4842 if (writeFile(handle, buf, ts->smhd) < 0) |
|
4843 { |
|
4844 mp4free(buf); |
|
4845 |
|
4846 return -1; |
|
4847 } |
|
4848 |
|
4849 mp4free(buf); |
|
4850 |
|
4851 return 0; |
|
4852 } |
|
4853 |
|
4854 |
|
4855 /* |
|
4856 * Function: |
|
4857 * |
|
4858 * mp4_i32 writeAudioSTBL(MP4HandleImp handle, |
|
4859 * trakSize *ts) |
|
4860 * |
|
4861 * Description: |
|
4862 * |
|
4863 * Write audio STBL atom. |
|
4864 * |
|
4865 * Parameters: |
|
4866 * |
|
4867 * handle MP4 library handle |
|
4868 * ts Atom sizes |
|
4869 * |
|
4870 * Return value: |
|
4871 * |
|
4872 * 0 Success |
|
4873 * -1 Error |
|
4874 * |
|
4875 */ |
|
4876 mp4_i32 writeAudioSTBL(MP4HandleImp handle, trakSize *ts) |
|
4877 { |
|
4878 mp4_u8 buf[8]; |
|
4879 mp4_u32 i = 0; |
|
4880 |
|
4881 |
|
4882 /* Size */ |
|
4883 insertu32(buf+i, (mp4_u32)ts->stbl); |
|
4884 i += 4; |
|
4885 |
|
4886 /* Atom type */ |
|
4887 insertu32(buf+i, (mp4_u32)ATOMTYPE_STBL); |
|
4888 i += 4; |
|
4889 |
|
4890 if (writeFile(handle, buf, 8) < 0) |
|
4891 return -1; |
|
4892 |
|
4893 if (writeAudioSTSD(handle, ts) < 0) |
|
4894 return -1; |
|
4895 |
|
4896 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
4897 { |
|
4898 if (writeAudioSTTSLongClip(handle, ts) < 0) |
|
4899 return -1; |
|
4900 } |
|
4901 else |
|
4902 { |
|
4903 if (writeAudioSTTS(handle, ts) < 0) |
|
4904 return -1; |
|
4905 } |
|
4906 |
|
4907 if (writeAudioSTSC(handle, ts) < 0) |
|
4908 return -1; |
|
4909 |
|
4910 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
4911 { |
|
4912 if (writeAudioSTSZLongClip(handle, ts) < 0) |
|
4913 return -1; |
|
4914 |
|
4915 if (handle->audioSampleTable->stcoNeed64Bits) |
|
4916 { |
|
4917 if (writeAudioCO64LongClip(handle, ts) < 0) |
|
4918 return -1; |
|
4919 } |
|
4920 else |
|
4921 { |
|
4922 if (writeAudioSTCOLongClip(handle, ts) < 0) |
|
4923 return -1; |
|
4924 } |
|
4925 } |
|
4926 else |
|
4927 { |
|
4928 if (writeAudioSTSZ(handle, ts) < 0) |
|
4929 return -1; |
|
4930 |
|
4931 if (handle->audioSampleTable->stcoNeed64Bits) |
|
4932 { |
|
4933 if (writeAudioCO64(handle, ts) < 0) |
|
4934 return -1; |
|
4935 } |
|
4936 else |
|
4937 { |
|
4938 if (writeAudioSTCO(handle, ts) < 0) |
|
4939 return -1; |
|
4940 } |
|
4941 } |
|
4942 |
|
4943 |
|
4944 return 0; |
|
4945 } |
|
4946 |
|
4947 |
|
4948 /* |
|
4949 * Function: |
|
4950 * |
|
4951 * mp4_i32 writeAudioSTSD(MP4HandleImp handle, |
|
4952 * trakSize *ts) |
|
4953 * |
|
4954 * Description: |
|
4955 * |
|
4956 * Write audio STSD atom. |
|
4957 * |
|
4958 * Parameters: |
|
4959 * |
|
4960 * handle MP4 library handle |
|
4961 * ts Atom sizes |
|
4962 * |
|
4963 * Return value: |
|
4964 * |
|
4965 * 0 Success |
|
4966 * -1 Error |
|
4967 * |
|
4968 */ |
|
4969 mp4_i32 writeAudioSTSD(MP4HandleImp handle, trakSize *ts) |
|
4970 { |
|
4971 mp4_u8 buf[16]; |
|
4972 mp4_u32 i = 0; |
|
4973 |
|
4974 |
|
4975 /* Size */ |
|
4976 insertu32(buf+i, (mp4_u32)ts->stsd); |
|
4977 i += 4; |
|
4978 |
|
4979 /* Atom type */ |
|
4980 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSD); |
|
4981 i += 4; |
|
4982 |
|
4983 /* Version and flags */ |
|
4984 insertu32(buf+i, (mp4_u32)0); |
|
4985 i += 4; |
|
4986 |
|
4987 /* Entry count */ |
|
4988 insertu32(buf+i, (mp4_u32)1); |
|
4989 i += 4; |
|
4990 |
|
4991 if (writeFile(handle, buf, 16) < 0) |
|
4992 return -1; |
|
4993 |
|
4994 if (handle->type & MP4_TYPE_MPEG4_AUDIO) |
|
4995 { |
|
4996 if (writeMP4A(handle, ts) < 0) |
|
4997 return -1; |
|
4998 } |
|
4999 else if (handle->type & MP4_TYPE_AMR_NB) |
|
5000 { |
|
5001 if (writeSAMR(handle, ts) < 0) |
|
5002 return -1; |
|
5003 } |
|
5004 else if (handle->type & MP4_TYPE_AMR_WB) |
|
5005 { |
|
5006 if (writeSAWB(handle, ts) < 0) |
|
5007 return -1; |
|
5008 } |
|
5009 else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) |
|
5010 { |
|
5011 if (writeSQCP(handle, ts) < 0) |
|
5012 return -1; |
|
5013 } |
|
5014 else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) |
|
5015 { |
|
5016 if (writeMP4A(handle, ts) < 0) |
|
5017 return -1; |
|
5018 } |
|
5019 else |
|
5020 { |
|
5021 } |
|
5022 |
|
5023 return 0; |
|
5024 } |
|
5025 |
|
5026 |
|
5027 /* |
|
5028 * Function: |
|
5029 * |
|
5030 * mp4_i32 writeMP4A(MP4HandleImp handle, |
|
5031 * trakSize *ts) |
|
5032 * |
|
5033 * Description: |
|
5034 * |
|
5035 * Write MP4A atom. |
|
5036 * |
|
5037 * Parameters: |
|
5038 * |
|
5039 * handle MP4 library handle |
|
5040 * ts Atom sizes |
|
5041 * |
|
5042 * Return value: |
|
5043 * |
|
5044 * 0 Success |
|
5045 * -1 Error |
|
5046 * |
|
5047 */ |
|
5048 mp4_i32 writeMP4A(MP4HandleImp handle, trakSize *ts) |
|
5049 { |
|
5050 mp4_u8 *buf; |
|
5051 mp4_u32 i = 0; |
|
5052 |
|
5053 |
|
5054 buf = (mp4_u8 *)mp4malloc(36); |
|
5055 if (buf == NULL) |
|
5056 return -1; |
|
5057 |
|
5058 /* Size */ |
|
5059 insertu32(buf+i, (mp4_u32)ts->mp4a); |
|
5060 i += 4; |
|
5061 |
|
5062 /* Atom type */ |
|
5063 insertu32(buf+i, (mp4_u32)ATOMTYPE_MP4A); |
|
5064 i += 4; |
|
5065 |
|
5066 /* Reserved */ |
|
5067 buf[i++] = 0; |
|
5068 buf[i++] = 0; |
|
5069 buf[i++] = 0; |
|
5070 buf[i++] = 0; |
|
5071 buf[i++] = 0; |
|
5072 buf[i++] = 0; |
|
5073 |
|
5074 /* Data reference index */ |
|
5075 insertu16(buf+i, (mp4_u16)1); |
|
5076 i += 2; |
|
5077 |
|
5078 /* Reserved */ |
|
5079 insertu32(buf+i, (mp4_u32)0); |
|
5080 i += 4; |
|
5081 |
|
5082 insertu32(buf+i, (mp4_u32)0); |
|
5083 i += 4; |
|
5084 |
|
5085 insertu16(buf+i, (mp4_u16)2); |
|
5086 i += 2; |
|
5087 |
|
5088 insertu16(buf+i, (mp4_u16)16); |
|
5089 i += 2; |
|
5090 |
|
5091 insertu32(buf+i, (mp4_u32)0); |
|
5092 i += 4; |
|
5093 |
|
5094 /* Timescale */ |
|
5095 insertu16(buf+i, (mp4_u16)handle->audioTimeScale); |
|
5096 i += 2; |
|
5097 |
|
5098 /* Reserved */ |
|
5099 insertu16(buf+i, (mp4_u16)0); |
|
5100 i += 2; |
|
5101 |
|
5102 if (writeFile(handle, buf, 36) < 0) |
|
5103 { |
|
5104 mp4free(buf); |
|
5105 |
|
5106 return -1; |
|
5107 } |
|
5108 |
|
5109 if (writeAudioESD(handle, ts) < 0) |
|
5110 { |
|
5111 mp4free(buf); |
|
5112 |
|
5113 return -1; |
|
5114 } |
|
5115 |
|
5116 mp4free(buf); |
|
5117 |
|
5118 return 0; |
|
5119 } |
|
5120 |
|
5121 |
|
5122 /* |
|
5123 * Function: |
|
5124 * |
|
5125 * mp4_i32 writeAudioESD(MP4HandleImp handle, |
|
5126 * trakSize *ts) |
|
5127 * |
|
5128 * Description: |
|
5129 * |
|
5130 * Write audio ESD atom. |
|
5131 * |
|
5132 * Parameters: |
|
5133 * |
|
5134 * handle MP4 library handle |
|
5135 * ts Atom sizes |
|
5136 * |
|
5137 * Return value: |
|
5138 * |
|
5139 * 0 Success |
|
5140 * -1 Error |
|
5141 * |
|
5142 */ |
|
5143 mp4_i32 writeAudioESD(MP4HandleImp handle, trakSize *ts) |
|
5144 { |
|
5145 mp4_u8 *buf; |
|
5146 mp4_u32 i = 0; |
|
5147 mp4_u32 bitrate = 0; |
|
5148 mp4_u32 num_of_bytes = 0; |
|
5149 mp4_u32 size = 0; |
|
5150 mp4_u32 index = 0; |
|
5151 mp4_u32 tempnum = 0; |
|
5152 |
|
5153 mp4_u32 size1, size2; |
|
5154 mp4_u32 numofsizebytes1, numofsizebytes2; |
|
5155 |
|
5156 buf = (mp4_u8 *)mp4malloc(ts->esds); |
|
5157 if (buf == NULL) |
|
5158 return -1; |
|
5159 |
|
5160 /* Calculate the necessary size information */ |
|
5161 size1 = handle->audioDecSpecificInfoSize; |
|
5162 if (size1 < 128) |
|
5163 numofsizebytes1 = 1; |
|
5164 else |
|
5165 { |
|
5166 numofsizebytes1 = 1; |
|
5167 while ( size1 >= 128 ) |
|
5168 { |
|
5169 size1 = size1 >> 7; |
|
5170 numofsizebytes1++; |
|
5171 } |
|
5172 } |
|
5173 |
|
5174 size2 = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize; |
|
5175 if (size2 < 128) |
|
5176 numofsizebytes2 = 1; |
|
5177 else |
|
5178 { |
|
5179 numofsizebytes2 = 1; |
|
5180 while ( size2 >= 128 ) |
|
5181 { |
|
5182 size2 = size2 >> 7; |
|
5183 numofsizebytes2++; |
|
5184 } |
|
5185 } |
|
5186 /* End of size calculations */ |
|
5187 |
|
5188 /* Size */ |
|
5189 insertu32(buf+i, (mp4_u32)ts->esds); |
|
5190 i += 4; |
|
5191 |
|
5192 /* Atom type */ |
|
5193 insertu32(buf+i, (mp4_u32)ATOMTYPE_ESD); |
|
5194 i += 4; |
|
5195 |
|
5196 /* Version and flags */ |
|
5197 insertu32(buf+i, (mp4_u32)0); |
|
5198 i += 4; |
|
5199 |
|
5200 /* ES_DescrTag */ |
|
5201 buf[i++] = 0x03; |
|
5202 |
|
5203 /* Size */ |
|
5204 size = 21 + numofsizebytes1 + numofsizebytes2 + handle->audioDecSpecificInfoSize; |
|
5205 if (size < 128) |
|
5206 buf[i++] = (mp4_u8)(size); |
|
5207 else |
|
5208 { |
|
5209 num_of_bytes = 0; |
|
5210 while ( size >= 128 ) |
|
5211 { |
|
5212 size = size >> 7; |
|
5213 num_of_bytes++; |
|
5214 } |
|
5215 size = 21 + numofsizebytes1 + numofsizebytes2 + handle->audioDecSpecificInfoSize; |
|
5216 for(index = num_of_bytes; index > 0; index--) |
|
5217 { |
|
5218 tempnum = size >> (7 * index); |
|
5219 buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum); |
|
5220 size -= (tempnum << (7 * index)); |
|
5221 } |
|
5222 buf[i++] = (mp4_u8)size; |
|
5223 } |
|
5224 |
|
5225 /* ES_ID */ |
|
5226 insertu16(buf+i, (mp4_u16)0); |
|
5227 i += 2; |
|
5228 |
|
5229 /* Flags */ |
|
5230 buf[i++] = 0; |
|
5231 |
|
5232 /* DecoderConfigDescrTag */ |
|
5233 buf[i++] = 0x04; |
|
5234 |
|
5235 /* Size */ |
|
5236 size = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize; |
|
5237 if (size < 128) |
|
5238 buf[i++] = (mp4_u8)(size); |
|
5239 else |
|
5240 { |
|
5241 num_of_bytes = 0; |
|
5242 while ( size >= 128 ) |
|
5243 { |
|
5244 size = size >> 7; |
|
5245 num_of_bytes++; |
|
5246 } |
|
5247 size = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize; |
|
5248 for(index = num_of_bytes; index > 0; index--) |
|
5249 { |
|
5250 tempnum = size >> (7 * index); |
|
5251 buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum); |
|
5252 size -= (tempnum << (7 * index)); |
|
5253 } |
|
5254 buf[i++] = (mp4_u8)size; |
|
5255 } |
|
5256 |
|
5257 /* ObjectTypeIndication */ |
|
5258 if (handle->type & MP4_TYPE_MPEG4_AUDIO) |
|
5259 buf[i++] = 0x40; |
|
5260 else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) |
|
5261 buf[i++] = 0xE1; |
|
5262 else |
|
5263 { |
|
5264 } |
|
5265 |
|
5266 /* Flags */ |
|
5267 buf[i++] = 0x15; |
|
5268 |
|
5269 /* BufferSizeDB */ |
|
5270 if (handle->type & MP4_TYPE_MPEG4_AUDIO) |
|
5271 { |
|
5272 buf[i++] = 0x00; |
|
5273 buf[i++] = 0x00; |
|
5274 buf[i++] = 0x00; |
|
5275 } |
|
5276 else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) |
|
5277 { /* 4096 for QCELP 13K */ |
|
5278 buf[i++] = 0x00; |
|
5279 buf[i++] = 0x10; |
|
5280 buf[i++] = 0x00; |
|
5281 } |
|
5282 else |
|
5283 { |
|
5284 } |
|
5285 |
|
5286 |
|
5287 if ((handle->audioDuration != 0) && (handle->audioTimeScale != 0)) |
|
5288 bitrate = (mp4_u32)((mp4_double)8 * |
|
5289 (mp4_double)handle->audioMediaDataSize / |
|
5290 ((mp4_double)handle->audioDuration / |
|
5291 (mp4_double)handle->audioTimeScale)); |
|
5292 else |
|
5293 bitrate = 0; |
|
5294 |
|
5295 /* MaxBitrate */ |
|
5296 insertu32(buf+i, (mp4_u32)bitrate); /*0x00010000*/ |
|
5297 i += 4; |
|
5298 |
|
5299 /* AvgBitrate */ |
|
5300 insertu32(buf+i, (mp4_u32)bitrate);/*0x00008000*/ |
|
5301 i += 4; |
|
5302 |
|
5303 /* DecSpecificInfoTag */ |
|
5304 buf[i++] = 0x05; |
|
5305 |
|
5306 /* Size */ |
|
5307 size = handle->audioDecSpecificInfoSize; |
|
5308 if (size < 128) |
|
5309 buf[i++] = (mp4_u8)(size); |
|
5310 else |
|
5311 { |
|
5312 num_of_bytes = 0; |
|
5313 while ( size >= 128 ) |
|
5314 { |
|
5315 size = size >> 7; |
|
5316 num_of_bytes++; |
|
5317 } |
|
5318 size = handle->audioDecSpecificInfoSize; |
|
5319 for(index = num_of_bytes; index > 0; index--) |
|
5320 { |
|
5321 tempnum = size >> (7 * index); |
|
5322 buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum); |
|
5323 size -= (tempnum << (7 * index)); |
|
5324 } |
|
5325 buf[i++] = (mp4_u8)size; |
|
5326 } |
|
5327 |
|
5328 /* DecoderSpecificInfo */ |
|
5329 mp4memcpy(buf+i, handle->audioDecSpecificInfo, handle->audioDecSpecificInfoSize); |
|
5330 i += handle->audioDecSpecificInfoSize; |
|
5331 |
|
5332 /* SLConfigDescrTag */ |
|
5333 buf[i++] = 0x06; |
|
5334 |
|
5335 /* Size */ |
|
5336 buf[i++] = 1; |
|
5337 |
|
5338 /* */ |
|
5339 buf[i++] = 2; |
|
5340 |
|
5341 if (writeFile(handle, buf, ts->esds) < 0) |
|
5342 { |
|
5343 mp4free(buf); |
|
5344 |
|
5345 return -1; |
|
5346 } |
|
5347 |
|
5348 mp4free(buf); |
|
5349 |
|
5350 return 0; |
|
5351 } |
|
5352 |
|
5353 |
|
5354 /* |
|
5355 * Function: |
|
5356 * |
|
5357 * mp4_i32 writeSAMR(MP4HandleImp handle, |
|
5358 * trakSize *ts) |
|
5359 * |
|
5360 * Description: |
|
5361 * |
|
5362 * Write SAMR atom. |
|
5363 * |
|
5364 * Parameters: |
|
5365 * |
|
5366 * handle MP4 library handle |
|
5367 * ts Atom sizes |
|
5368 * |
|
5369 * Return value: |
|
5370 * |
|
5371 * 0 Success |
|
5372 * -1 Error |
|
5373 * |
|
5374 */ |
|
5375 mp4_i32 writeSAMR(MP4HandleImp handle, trakSize *ts) |
|
5376 { |
|
5377 mp4_u8 *buf; |
|
5378 mp4_u32 i = 0; |
|
5379 |
|
5380 |
|
5381 buf = (mp4_u8 *)mp4malloc(36); |
|
5382 if (buf == NULL) |
|
5383 return -1; |
|
5384 |
|
5385 /* Size */ |
|
5386 insertu32(buf+i, (mp4_u32)ts->samr); |
|
5387 i += 4; |
|
5388 |
|
5389 /* Atom type */ |
|
5390 insertu32(buf+i, (mp4_u32)ATOMTYPE_SAMR); |
|
5391 i += 4; |
|
5392 |
|
5393 /* Reserved */ |
|
5394 buf[i++] = 0; |
|
5395 buf[i++] = 0; |
|
5396 buf[i++] = 0; |
|
5397 buf[i++] = 0; |
|
5398 buf[i++] = 0; |
|
5399 buf[i++] = 0; |
|
5400 |
|
5401 /* Data reference index */ |
|
5402 insertu16(buf+i, (mp4_u16)1); |
|
5403 i += 2; |
|
5404 |
|
5405 /* Reserved */ |
|
5406 insertu32(buf+i, (mp4_u32)0); |
|
5407 i += 4; |
|
5408 |
|
5409 insertu32(buf+i, (mp4_u32)0); |
|
5410 i += 4; |
|
5411 |
|
5412 insertu16(buf+i, (mp4_u16)2); |
|
5413 i += 2; |
|
5414 |
|
5415 insertu16(buf+i, (mp4_u16)16); |
|
5416 i += 2; |
|
5417 |
|
5418 insertu32(buf+i, (mp4_u32)0); |
|
5419 i += 4; |
|
5420 |
|
5421 /* Timescale */ |
|
5422 insertu16(buf+i, (mp4_u16)handle->audioTimeScale); |
|
5423 i += 2; |
|
5424 |
|
5425 /* Reserved */ |
|
5426 insertu16(buf+i, (mp4_u16)0); |
|
5427 i += 2; |
|
5428 |
|
5429 if (writeFile(handle, buf, 36) < 0) |
|
5430 { |
|
5431 mp4free(buf); |
|
5432 |
|
5433 return -1; |
|
5434 } |
|
5435 |
|
5436 if (writeDAMR(handle, ts) < 0) |
|
5437 { |
|
5438 mp4free(buf); |
|
5439 |
|
5440 return -1; |
|
5441 } |
|
5442 |
|
5443 mp4free(buf); |
|
5444 |
|
5445 return 0; |
|
5446 } |
|
5447 |
|
5448 |
|
5449 /* |
|
5450 * Function: |
|
5451 * |
|
5452 * mp4_i32 writeSAWB(MP4HandleImp handle, |
|
5453 * trakSize *ts) |
|
5454 * |
|
5455 * Description: |
|
5456 * |
|
5457 * Write SAWB atom. |
|
5458 * |
|
5459 * Parameters: |
|
5460 * |
|
5461 * handle MP4 library handle |
|
5462 * ts Atom sizes |
|
5463 * |
|
5464 * Return value: |
|
5465 * |
|
5466 * 0 Success |
|
5467 * -1 Error |
|
5468 * |
|
5469 */ |
|
5470 mp4_i32 writeSAWB(MP4HandleImp handle, trakSize *ts) |
|
5471 { |
|
5472 mp4_u8 *buf; |
|
5473 mp4_u32 i = 0; |
|
5474 |
|
5475 |
|
5476 buf = (mp4_u8 *)mp4malloc(36); |
|
5477 if (buf == NULL) |
|
5478 return -1; |
|
5479 |
|
5480 /* Size */ |
|
5481 insertu32(buf+i, (mp4_u32)ts->sawb); |
|
5482 i += 4; |
|
5483 |
|
5484 /* Atom type */ |
|
5485 insertu32(buf+i, (mp4_u32)ATOMTYPE_SAWB); |
|
5486 i += 4; |
|
5487 |
|
5488 /* Reserved */ |
|
5489 buf[i++] = 0; |
|
5490 buf[i++] = 0; |
|
5491 buf[i++] = 0; |
|
5492 buf[i++] = 0; |
|
5493 buf[i++] = 0; |
|
5494 buf[i++] = 0; |
|
5495 |
|
5496 /* Data reference index */ |
|
5497 insertu16(buf+i, (mp4_u16)1); |
|
5498 i += 2; |
|
5499 |
|
5500 /* Reserved */ |
|
5501 insertu32(buf+i, (mp4_u32)0); |
|
5502 i += 4; |
|
5503 |
|
5504 insertu32(buf+i, (mp4_u32)0); |
|
5505 i += 4; |
|
5506 |
|
5507 insertu16(buf+i, (mp4_u16)2); |
|
5508 i += 2; |
|
5509 |
|
5510 insertu16(buf+i, (mp4_u16)16); |
|
5511 i += 2; |
|
5512 |
|
5513 insertu32(buf+i, (mp4_u32)0); |
|
5514 i += 4; |
|
5515 |
|
5516 /* Timescale */ |
|
5517 insertu16(buf+i, (mp4_u16)handle->audioTimeScale); |
|
5518 i += 2; |
|
5519 |
|
5520 /* Reserved */ |
|
5521 insertu16(buf+i, (mp4_u16)0); |
|
5522 i += 2; |
|
5523 |
|
5524 if (writeFile(handle, buf, 36) < 0) |
|
5525 { |
|
5526 mp4free(buf); |
|
5527 |
|
5528 return -1; |
|
5529 } |
|
5530 |
|
5531 if (writeDAMR(handle, ts) < 0) |
|
5532 { |
|
5533 mp4free(buf); |
|
5534 |
|
5535 return -1; |
|
5536 } |
|
5537 |
|
5538 mp4free(buf); |
|
5539 |
|
5540 return 0; |
|
5541 } |
|
5542 |
|
5543 |
|
5544 /* |
|
5545 * Function: |
|
5546 * |
|
5547 * mp4_i32 writeDAMR(MP4HandleImp handle, |
|
5548 * trakSize *ts) |
|
5549 * |
|
5550 * Description: |
|
5551 * |
|
5552 * Write DAMR atom. |
|
5553 * |
|
5554 * Parameters: |
|
5555 * |
|
5556 * handle MP4 library handle |
|
5557 * ts Atom sizes |
|
5558 * |
|
5559 * Return value: |
|
5560 * |
|
5561 * 0 Success |
|
5562 * -1 Error |
|
5563 * |
|
5564 */ |
|
5565 mp4_i32 writeDAMR(MP4HandleImp handle, trakSize *ts) |
|
5566 { |
|
5567 mp4_u8 buf[17]; |
|
5568 mp4_u32 i = 0; |
|
5569 |
|
5570 |
|
5571 /* Size */ |
|
5572 insertu32(buf+i, (mp4_u32)ts->damr); |
|
5573 i += 4; |
|
5574 |
|
5575 /* Atom type */ |
|
5576 insertu32(buf+i, (mp4_u32)ATOMTYPE_DAMR); |
|
5577 i += 4; |
|
5578 |
|
5579 /* Vendor */ |
|
5580 buf[i++] = 'S'; |
|
5581 buf[i++] = '6'; |
|
5582 buf[i++] = '0'; |
|
5583 buf[i++] = ' '; |
|
5584 |
|
5585 /* Decoder version */ |
|
5586 buf[i++] = 0; |
|
5587 |
|
5588 /* Mode set */ |
|
5589 insertu16(buf+i, (mp4_u16)handle->audioModeSet); |
|
5590 i += 2; |
|
5591 |
|
5592 /* Mode change period */ |
|
5593 buf[i++] = 0; |
|
5594 |
|
5595 /* Frames per sample */ |
|
5596 buf[i++] = handle->audioFramesPerSample; |
|
5597 |
|
5598 if (writeFile(handle, buf, 17) < 0) |
|
5599 return -1; |
|
5600 |
|
5601 return 0; |
|
5602 } |
|
5603 |
|
5604 |
|
5605 /* |
|
5606 * Function: |
|
5607 * |
|
5608 * mp4_i32 writeAudioSTTS(MP4HandleImp handle, |
|
5609 * trakSize *ts) |
|
5610 * |
|
5611 * Description: |
|
5612 * |
|
5613 * Write audio STTS atom. |
|
5614 * |
|
5615 * Parameters: |
|
5616 * |
|
5617 * handle MP4 library handle |
|
5618 * ts Atom sizes |
|
5619 * |
|
5620 * Return value: |
|
5621 * |
|
5622 * 0 Success |
|
5623 * -1 Error |
|
5624 * |
|
5625 */ |
|
5626 mp4_i32 writeAudioSTTS(MP4HandleImp handle, trakSize *ts) |
|
5627 { |
|
5628 mp4_u8 *buf; |
|
5629 mp4_u32 i = 0; |
|
5630 mp4_u32 j; |
|
5631 |
|
5632 |
|
5633 buf = (mp4_u8 *)mp4malloc(ts->stts); |
|
5634 if (buf == NULL) |
|
5635 return -1; |
|
5636 |
|
5637 /* Size */ |
|
5638 insertu32(buf+i, (mp4_u32)ts->stts); |
|
5639 i += 4; |
|
5640 |
|
5641 /* Atom type */ |
|
5642 insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); |
|
5643 i += 4; |
|
5644 |
|
5645 /* Version and flags */ |
|
5646 insertu32(buf+i, (mp4_u32)0); |
|
5647 i += 4; |
|
5648 |
|
5649 /* Entry count */ |
|
5650 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsEntryCount); |
|
5651 i += 4; |
|
5652 |
|
5653 /* Sample count and sample delta */ |
|
5654 for (j = 0; j < handle->audioSampleTable->sttsEntryCount; j++) |
|
5655 { |
|
5656 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsSampleCount[j]); |
|
5657 i += 4; |
|
5658 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsSampleDelta[j]); |
|
5659 i += 4; |
|
5660 } |
|
5661 |
|
5662 if (writeFile(handle, buf, ts->stts) < 0) |
|
5663 { |
|
5664 mp4free(buf); |
|
5665 |
|
5666 return -1; |
|
5667 } |
|
5668 |
|
5669 mp4free(buf); |
|
5670 |
|
5671 return 0; |
|
5672 } |
|
5673 |
|
5674 |
|
5675 /* |
|
5676 * Function: |
|
5677 * |
|
5678 * mp4_i32 writeAudioSTTSLongClip(MP4HandleImp handle, |
|
5679 * trakSize *ts) |
|
5680 * |
|
5681 * Description: |
|
5682 * |
|
5683 * Write audio STTS atom. |
|
5684 * |
|
5685 * Parameters: |
|
5686 * |
|
5687 * handle MP4 library handle |
|
5688 * ts Atom sizes |
|
5689 * |
|
5690 * Return value: |
|
5691 * |
|
5692 * 0 Success |
|
5693 * -1 Error |
|
5694 * |
|
5695 */ |
|
5696 mp4_i32 writeAudioSTTSLongClip(MP4HandleImp handle, trakSize *ts) |
|
5697 { |
|
5698 mp4_u8 *buf; |
|
5699 mp4_u8 *buf2; |
|
5700 mp4_u32 i = 0; |
|
5701 mp4_u32 j; |
|
5702 mp4_u32 left; |
|
5703 mp4_u32 bytestoread; |
|
5704 |
|
5705 |
|
5706 buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
5707 if (buf == NULL) |
|
5708 return -1; |
|
5709 |
|
5710 buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2); |
|
5711 if (buf2 == NULL) |
|
5712 { |
|
5713 mp4free(buf); |
|
5714 return -1; |
|
5715 } |
|
5716 |
|
5717 /* Size */ |
|
5718 insertu32(buf+i, (mp4_u32)ts->stts); |
|
5719 i += 4; |
|
5720 |
|
5721 /* Atom type */ |
|
5722 insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); |
|
5723 i += 4; |
|
5724 |
|
5725 /* Version and flags */ |
|
5726 insertu32(buf+i, (mp4_u32)0); |
|
5727 i += 4; |
|
5728 |
|
5729 /* Entry count */ |
|
5730 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsEntryCount); |
|
5731 i += 4; |
|
5732 |
|
5733 if (writeFile(handle, buf, i) < 0) |
|
5734 { |
|
5735 mp4free(buf); |
|
5736 mp4free(buf2); |
|
5737 |
|
5738 return -1; |
|
5739 } |
|
5740 |
|
5741 /* Sample count and delta */ |
|
5742 |
|
5743 /* Seek to the beginning of temporary files */ |
|
5744 |
|
5745 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0) |
|
5746 { |
|
5747 mp4free(buf); |
|
5748 mp4free(buf2); |
|
5749 return -1; |
|
5750 } |
|
5751 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0) |
|
5752 { |
|
5753 mp4free(buf); |
|
5754 mp4free(buf2); |
|
5755 return -1; |
|
5756 } |
|
5757 |
|
5758 left = handle->audioSampleTable->sttsEntryCount * 4; /* Bytes left in each file */ |
|
5759 |
|
5760 while (left) |
|
5761 { |
|
5762 if (left > METADATA_COPY_BUFFERSIZE / 2) |
|
5763 bytestoread = METADATA_COPY_BUFFERSIZE / 2; |
|
5764 else |
|
5765 bytestoread = left; |
|
5766 |
|
5767 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0) |
|
5768 { |
|
5769 mp4free(buf); |
|
5770 mp4free(buf2); |
|
5771 |
|
5772 return -1; |
|
5773 } |
|
5774 |
|
5775 for (j = 0; j < bytestoread; j += 4) |
|
5776 { |
|
5777 insertu32(buf + 2*j, ((mp4_u32 *)buf2)[j / 4]); |
|
5778 } |
|
5779 |
|
5780 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0) |
|
5781 { |
|
5782 mp4free(buf); |
|
5783 mp4free(buf2); |
|
5784 |
|
5785 return -1; |
|
5786 } |
|
5787 |
|
5788 for (j = 0; j < bytestoread; j += 4) |
|
5789 { |
|
5790 insertu32(buf + 2*j + 4, ((mp4_u32 *)buf2)[j / 4]); |
|
5791 } |
|
5792 |
|
5793 if (writeFile(handle, buf, 2 * bytestoread) < 0) |
|
5794 { |
|
5795 mp4free(buf); |
|
5796 mp4free(buf2); |
|
5797 |
|
5798 return -1; |
|
5799 } |
|
5800 |
|
5801 left -= bytestoread; |
|
5802 } |
|
5803 |
|
5804 mp4free(buf); |
|
5805 mp4free(buf2); |
|
5806 |
|
5807 |
|
5808 return 0; |
|
5809 } |
|
5810 |
|
5811 |
|
5812 /* |
|
5813 * Function: |
|
5814 * |
|
5815 * mp4_i32 writeAudioSTSC(MP4HandleImp handle, |
|
5816 * trakSize *ts) |
|
5817 * |
|
5818 * Description: |
|
5819 * |
|
5820 * Write audio STSC atom. |
|
5821 * |
|
5822 * Parameters: |
|
5823 * |
|
5824 * handle MP4 library handle |
|
5825 * ts Atom sizes |
|
5826 * |
|
5827 * Return value: |
|
5828 * |
|
5829 * 0 Success |
|
5830 * -1 Error |
|
5831 * |
|
5832 */ |
|
5833 mp4_i32 writeAudioSTSC(MP4HandleImp handle, trakSize *ts) |
|
5834 { |
|
5835 mp4_u8 *buf; |
|
5836 mp4_u32 i = 0; |
|
5837 mp4_u32 j; |
|
5838 |
|
5839 |
|
5840 buf = (mp4_u8 *)mp4malloc(ts->stsc); |
|
5841 if (buf == NULL) |
|
5842 return -1; |
|
5843 |
|
5844 /* Size */ |
|
5845 insertu32(buf+i, (mp4_u32)ts->stsc); |
|
5846 i += 4; |
|
5847 |
|
5848 /* Atom type */ |
|
5849 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSC); |
|
5850 i += 4; |
|
5851 |
|
5852 /* Version and flags */ |
|
5853 insertu32(buf+i, (mp4_u32)0); |
|
5854 i += 4; |
|
5855 |
|
5856 /* Entry count */ |
|
5857 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscEntryCount); |
|
5858 i += 4; |
|
5859 |
|
5860 /* First chunk, samples per chunk and sample description index */ |
|
5861 for (j = 0; j < handle->audioSampleTable->stscEntryCount; j++) |
|
5862 { |
|
5863 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscFirstChunk[j]); |
|
5864 i += 4; |
|
5865 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscSamplesPerChunk[j]); |
|
5866 i += 4; |
|
5867 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscSampleDescriptionIndex[j]); |
|
5868 i += 4; |
|
5869 } |
|
5870 |
|
5871 if (writeFile(handle, buf, ts->stsc) < 0) |
|
5872 { |
|
5873 mp4free(buf); |
|
5874 |
|
5875 return -1; |
|
5876 } |
|
5877 |
|
5878 mp4free(buf); |
|
5879 |
|
5880 return 0; |
|
5881 } |
|
5882 |
|
5883 |
|
5884 /* |
|
5885 * Function: |
|
5886 * |
|
5887 * mp4_i32 writeAudioSTSZ(MP4HandleImp handle, |
|
5888 * trakSize *ts) |
|
5889 * |
|
5890 * Description: |
|
5891 * |
|
5892 * Write audio STSZ atom. |
|
5893 * |
|
5894 * Parameters: |
|
5895 * |
|
5896 * handle MP4 library handle |
|
5897 * ts Atom sizes |
|
5898 * |
|
5899 * Return value: |
|
5900 * |
|
5901 * 0 Success |
|
5902 * -1 Error |
|
5903 * |
|
5904 */ |
|
5905 mp4_i32 writeAudioSTSZ(MP4HandleImp handle, trakSize *ts) |
|
5906 { |
|
5907 mp4_u8 *buf; |
|
5908 mp4_u32 i = 0; |
|
5909 mp4_u32 j; |
|
5910 |
|
5911 |
|
5912 buf = (mp4_u8 *)mp4malloc(ts->stsz); |
|
5913 if (buf == NULL) |
|
5914 return -1; |
|
5915 |
|
5916 /* Size */ |
|
5917 insertu32(buf+i, (mp4_u32)ts->stsz); |
|
5918 i += 4; |
|
5919 |
|
5920 /* Atom type */ |
|
5921 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); |
|
5922 i += 4; |
|
5923 |
|
5924 /* Version and flags */ |
|
5925 insertu32(buf+i, (mp4_u32)0); |
|
5926 i += 4; |
|
5927 |
|
5928 /* Sample size */ |
|
5929 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleSize); |
|
5930 i += 4; |
|
5931 |
|
5932 /* Sample count */ |
|
5933 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleCount); |
|
5934 i += 4; |
|
5935 |
|
5936 /* Entry sizes */ |
|
5937 if (handle->audioSampleTable->stszSampleSize == 0) |
|
5938 { |
|
5939 for (j = 0; j < handle->audioSampleTable->stszSampleCount; j++) |
|
5940 { |
|
5941 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszEntrySize[j]); |
|
5942 i += 4; |
|
5943 } |
|
5944 } |
|
5945 |
|
5946 if (writeFile(handle, buf, ts->stsz) < 0) |
|
5947 { |
|
5948 mp4free(buf); |
|
5949 |
|
5950 return -1; |
|
5951 } |
|
5952 |
|
5953 mp4free(buf); |
|
5954 |
|
5955 return 0; |
|
5956 } |
|
5957 |
|
5958 |
|
5959 /* |
|
5960 * Function: |
|
5961 * |
|
5962 * mp4_i32 writeAudioSTSZLongClip(MP4HandleImp handle, |
|
5963 * trakSize *ts) |
|
5964 * |
|
5965 * Description: |
|
5966 * |
|
5967 * Write audio STSZ atom. |
|
5968 * |
|
5969 * Parameters: |
|
5970 * |
|
5971 * handle MP4 library handle |
|
5972 * ts Atom sizes |
|
5973 * |
|
5974 * Return value: |
|
5975 * |
|
5976 * 0 Success |
|
5977 * -1 Error |
|
5978 * |
|
5979 */ |
|
5980 mp4_i32 writeAudioSTSZLongClip(MP4HandleImp handle, trakSize *ts) |
|
5981 { |
|
5982 mp4_u8 *buf; |
|
5983 mp4_u8 *buf2; |
|
5984 mp4_u32 i = 0; |
|
5985 mp4_u32 j; |
|
5986 mp4_u32 left; |
|
5987 mp4_u32 bytestoread; |
|
5988 |
|
5989 |
|
5990 buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
5991 if (buf == NULL) |
|
5992 return -1; |
|
5993 |
|
5994 buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
5995 if (buf2 == NULL) |
|
5996 { |
|
5997 mp4free(buf); |
|
5998 return -1; |
|
5999 } |
|
6000 |
|
6001 /* Size */ |
|
6002 insertu32(buf+i, (mp4_u32)ts->stsz); |
|
6003 i += 4; |
|
6004 |
|
6005 /* Atom type */ |
|
6006 insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); |
|
6007 i += 4; |
|
6008 |
|
6009 /* Version and flags */ |
|
6010 insertu32(buf+i, (mp4_u32)0); |
|
6011 i += 4; |
|
6012 |
|
6013 /* Sample size */ |
|
6014 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleSize); |
|
6015 i += 4; |
|
6016 |
|
6017 /* Sample count */ |
|
6018 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleCount); |
|
6019 i += 4; |
|
6020 |
|
6021 if (writeFile(handle, buf, i) < 0) |
|
6022 { |
|
6023 mp4free(buf); |
|
6024 mp4free(buf2); |
|
6025 |
|
6026 return -1; |
|
6027 } |
|
6028 |
|
6029 /* Entry sizes */ |
|
6030 |
|
6031 if (handle->audioSampleTable->stszSampleSize == 0) |
|
6032 { |
|
6033 /* Seek to the beginning of temporary file */ |
|
6034 |
|
6035 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0) |
|
6036 { |
|
6037 mp4free(buf); |
|
6038 mp4free(buf2); |
|
6039 return -1; |
|
6040 } |
|
6041 |
|
6042 left = handle->audioSampleTable->stszSampleCount * 4; /* Bytes left in the file */ |
|
6043 |
|
6044 while (left) |
|
6045 { |
|
6046 if (left > METADATA_COPY_BUFFERSIZE) |
|
6047 bytestoread = METADATA_COPY_BUFFERSIZE; |
|
6048 else |
|
6049 bytestoread = left; |
|
6050 |
|
6051 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0) |
|
6052 { |
|
6053 mp4free(buf); |
|
6054 mp4free(buf2); |
|
6055 |
|
6056 return -1; |
|
6057 } |
|
6058 |
|
6059 for (j = 0; j < bytestoread; j += 4) |
|
6060 { |
|
6061 insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]); |
|
6062 } |
|
6063 |
|
6064 if (writeFile(handle, buf, bytestoread) < 0) |
|
6065 { |
|
6066 mp4free(buf); |
|
6067 mp4free(buf2); |
|
6068 |
|
6069 return -1; |
|
6070 } |
|
6071 |
|
6072 left -= bytestoread; |
|
6073 } |
|
6074 } |
|
6075 |
|
6076 mp4free(buf); |
|
6077 mp4free(buf2); |
|
6078 |
|
6079 |
|
6080 return 0; |
|
6081 } |
|
6082 |
|
6083 |
|
6084 /* |
|
6085 * Function: |
|
6086 * |
|
6087 * mp4_i32 writeAudioSTCO(MP4HandleImp handle, |
|
6088 * trakSize *ts) |
|
6089 * |
|
6090 * Description: |
|
6091 * |
|
6092 * Write audio STCO atom. |
|
6093 * |
|
6094 * Parameters: |
|
6095 * |
|
6096 * handle MP4 library handle |
|
6097 * ts Atom sizes |
|
6098 * |
|
6099 * Return value: |
|
6100 * |
|
6101 * 0 Success |
|
6102 * -1 Error |
|
6103 * |
|
6104 */ |
|
6105 mp4_i32 writeAudioSTCO(MP4HandleImp handle, trakSize *ts) |
|
6106 { |
|
6107 mp4_u8 *buf; |
|
6108 mp4_u32 i = 0; |
|
6109 mp4_u32 j; |
|
6110 |
|
6111 |
|
6112 buf = (mp4_u8 *)mp4malloc(ts->stco); |
|
6113 if (buf == NULL) |
|
6114 return -1; |
|
6115 |
|
6116 /* Size */ |
|
6117 insertu32(buf+i, (mp4_u32)ts->stco); |
|
6118 i += 4; |
|
6119 |
|
6120 /* Atom type */ |
|
6121 insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); |
|
6122 i += 4; |
|
6123 |
|
6124 /* Version and flags */ |
|
6125 insertu32(buf+i, (mp4_u32)0); |
|
6126 i += 4; |
|
6127 |
|
6128 /* Entry count */ |
|
6129 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); |
|
6130 i += 4; |
|
6131 |
|
6132 /* Chunk offsets */ |
|
6133 for (j = 0; j < handle->audioSampleTable->stcoEntryCount; j++) |
|
6134 { |
|
6135 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoChunkOffset[j]); |
|
6136 i += 4; |
|
6137 } |
|
6138 |
|
6139 if (writeFile(handle, buf, ts->stco) < 0) |
|
6140 { |
|
6141 mp4free(buf); |
|
6142 |
|
6143 return -1; |
|
6144 } |
|
6145 |
|
6146 mp4free(buf); |
|
6147 |
|
6148 return 0; |
|
6149 } |
|
6150 |
|
6151 /* |
|
6152 * Function: |
|
6153 * |
|
6154 * mp4_i32 writeAudioCO64(MP4HandleImp handle, |
|
6155 * trakSize *ts) |
|
6156 * |
|
6157 * Description: |
|
6158 * |
|
6159 * Write audio CO64 atom. |
|
6160 * |
|
6161 * Parameters: |
|
6162 * |
|
6163 * handle MP4 library handle |
|
6164 * ts Atom sizes |
|
6165 * |
|
6166 * Return value: |
|
6167 * |
|
6168 * 0 Success |
|
6169 * -1 Error |
|
6170 * |
|
6171 */ |
|
6172 mp4_i32 writeAudioCO64(MP4HandleImp handle, trakSize *ts) |
|
6173 { |
|
6174 mp4_u8 *buf; |
|
6175 mp4_u32 i = 0; |
|
6176 mp4_u32 j; |
|
6177 |
|
6178 |
|
6179 buf = (mp4_u8 *)mp4malloc(ts->stco); |
|
6180 if (buf == NULL) |
|
6181 return -1; |
|
6182 |
|
6183 /* Size */ |
|
6184 insertu32(buf+i, (mp4_u32)ts->stco); |
|
6185 i += 4; |
|
6186 |
|
6187 /* Atom type */ |
|
6188 insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); |
|
6189 i += 4; |
|
6190 |
|
6191 /* Version and flags */ |
|
6192 insertu32(buf+i, (mp4_u32)0); |
|
6193 i += 4; |
|
6194 |
|
6195 /* Entry count */ |
|
6196 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); |
|
6197 i += 4; |
|
6198 |
|
6199 /* Chunk offsets */ |
|
6200 for (j = 0; j < handle->audioSampleTable->stcoEntryCount; j++) |
|
6201 { |
|
6202 insertu64(buf+j, (mp4_u64)handle->audioSampleTable->stcoChunkOffset[j]); |
|
6203 } |
|
6204 |
|
6205 if (writeFile(handle, buf, ts->stco) < 0) |
|
6206 { |
|
6207 mp4free(buf); |
|
6208 |
|
6209 return -1; |
|
6210 } |
|
6211 |
|
6212 mp4free(buf); |
|
6213 |
|
6214 return 0; |
|
6215 } |
|
6216 |
|
6217 /* |
|
6218 * Function: |
|
6219 * |
|
6220 * mp4_i32 writeAudioSTCOLongClip(MP4HandleImp handle, |
|
6221 * trakSize *ts) |
|
6222 * |
|
6223 * Description: |
|
6224 * |
|
6225 * Write audio STCO atom. |
|
6226 * |
|
6227 * Parameters: |
|
6228 * |
|
6229 * handle MP4 library handle |
|
6230 * ts Atom sizes |
|
6231 * |
|
6232 * Return value: |
|
6233 * |
|
6234 * 0 Success |
|
6235 * -1 Error |
|
6236 * |
|
6237 */ |
|
6238 mp4_i32 writeAudioSTCOLongClip(MP4HandleImp handle, trakSize *ts) |
|
6239 { |
|
6240 mp4_u8 *buf; |
|
6241 mp4_u8 *buf2; |
|
6242 mp4_u32 i = 0; |
|
6243 mp4_u32 j; |
|
6244 mp4_u32 left; |
|
6245 mp4_u32 bytestoread; |
|
6246 mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 |
|
6247 //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 |
|
6248 |
|
6249 |
|
6250 buf = (mp4_u8 *)mp4malloc(bufferSize); |
|
6251 if (buf == NULL) |
|
6252 return -1; |
|
6253 |
|
6254 buf2 = (mp4_u8 *)mp4malloc(bufferSize); |
|
6255 if (buf2 == NULL) |
|
6256 { |
|
6257 mp4free(buf); |
|
6258 return -1; |
|
6259 } |
|
6260 |
|
6261 /* Size */ |
|
6262 insertu32(buf+i, (mp4_u32)ts->stco); |
|
6263 i += 4; |
|
6264 |
|
6265 /* Atom type */ |
|
6266 insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); |
|
6267 i += 4; |
|
6268 |
|
6269 /* Version and flags */ |
|
6270 insertu32(buf+i, (mp4_u32)0); |
|
6271 i += 4; |
|
6272 |
|
6273 /* Entry count */ |
|
6274 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); |
|
6275 i += 4; |
|
6276 |
|
6277 if (writeFile(handle, buf, i) < 0) |
|
6278 { |
|
6279 mp4free(buf); |
|
6280 mp4free(buf2); |
|
6281 |
|
6282 return -1; |
|
6283 } |
|
6284 |
|
6285 /* Chunk offsets */ |
|
6286 |
|
6287 /* Seek to the beginning of temporary file */ |
|
6288 |
|
6289 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) |
|
6290 { |
|
6291 mp4free(buf); |
|
6292 mp4free(buf2); |
|
6293 return -1; |
|
6294 } |
|
6295 |
|
6296 left = handle->audioSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ |
|
6297 |
|
6298 while (left) |
|
6299 { |
|
6300 if (left > bufferSize) |
|
6301 bytestoread = bufferSize; |
|
6302 else |
|
6303 bytestoread = left; |
|
6304 |
|
6305 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) |
|
6306 { |
|
6307 mp4free(buf); |
|
6308 mp4free(buf2); |
|
6309 |
|
6310 return -1; |
|
6311 } |
|
6312 |
|
6313 for (j = 0; j < bytestoread; j += 8) |
|
6314 { |
|
6315 ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ |
|
6316 insertu32(buf + j/2, ((mp4_u64 *)buf2)[j / 8]); |
|
6317 } |
|
6318 |
|
6319 if (writeFile(handle, buf, bytestoread/2) < 0) |
|
6320 { |
|
6321 mp4free(buf); |
|
6322 mp4free(buf2); |
|
6323 |
|
6324 return -1; |
|
6325 } |
|
6326 |
|
6327 left -= bytestoread; |
|
6328 } |
|
6329 |
|
6330 mp4free(buf); |
|
6331 mp4free(buf2); |
|
6332 |
|
6333 |
|
6334 return 0; |
|
6335 } |
|
6336 |
|
6337 /* |
|
6338 * Function: |
|
6339 * |
|
6340 * mp4_i32 writeAudioCO64LongClip(MP4HandleImp handle, |
|
6341 * trakSize *ts) |
|
6342 * |
|
6343 * Description: |
|
6344 * |
|
6345 * Write audio CO64 atom. |
|
6346 * |
|
6347 * Parameters: |
|
6348 * |
|
6349 * handle MP4 library handle |
|
6350 * ts Atom sizes |
|
6351 * |
|
6352 * Return value: |
|
6353 * |
|
6354 * 0 Success |
|
6355 * -1 Error |
|
6356 * |
|
6357 */ |
|
6358 mp4_i32 writeAudioCO64LongClip(MP4HandleImp handle, trakSize *ts) |
|
6359 { |
|
6360 mp4_u8 *buf; |
|
6361 mp4_u8 *buf2; |
|
6362 mp4_u32 i = 0; |
|
6363 mp4_u32 j; |
|
6364 mp4_u32 left; |
|
6365 mp4_u32 bytestoread; |
|
6366 mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 |
|
6367 //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 |
|
6368 |
|
6369 |
|
6370 buf = (mp4_u8 *)mp4malloc(bufferSize); |
|
6371 if (buf == NULL) |
|
6372 return -1; |
|
6373 |
|
6374 buf2 = (mp4_u8 *)mp4malloc(bufferSize); |
|
6375 if (buf2 == NULL) |
|
6376 { |
|
6377 mp4free(buf); |
|
6378 return -1; |
|
6379 } |
|
6380 |
|
6381 /* Size */ |
|
6382 insertu32(buf+i, (mp4_u32)ts->stco); |
|
6383 i += 4; |
|
6384 |
|
6385 /* Atom type */ |
|
6386 insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); |
|
6387 i += 4; |
|
6388 |
|
6389 /* Version and flags */ |
|
6390 insertu32(buf+i, (mp4_u32)0); |
|
6391 i += 4; |
|
6392 |
|
6393 /* Entry count */ |
|
6394 insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); |
|
6395 i += 4; |
|
6396 |
|
6397 if (writeFile(handle, buf, i) < 0) |
|
6398 { |
|
6399 mp4free(buf); |
|
6400 mp4free(buf2); |
|
6401 |
|
6402 return -1; |
|
6403 } |
|
6404 |
|
6405 /* Chunk offsets */ |
|
6406 |
|
6407 /* Seek to the beginning of temporary file */ |
|
6408 |
|
6409 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) |
|
6410 { |
|
6411 mp4free(buf); |
|
6412 mp4free(buf2); |
|
6413 return -1; |
|
6414 } |
|
6415 |
|
6416 left = handle->audioSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ |
|
6417 |
|
6418 while (left) |
|
6419 { |
|
6420 if (left > bufferSize) |
|
6421 bytestoread = bufferSize; |
|
6422 else |
|
6423 bytestoread = left; |
|
6424 |
|
6425 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) |
|
6426 { |
|
6427 mp4free(buf); |
|
6428 mp4free(buf2); |
|
6429 |
|
6430 return -1; |
|
6431 } |
|
6432 |
|
6433 for (j = 0; j < bytestoread; j += 8) |
|
6434 { |
|
6435 ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ |
|
6436 insertu64(buf + j, ((mp4_u64 *)buf2)[j / 8]); |
|
6437 } |
|
6438 |
|
6439 if (writeFile(handle, buf, bytestoread) < 0) |
|
6440 { |
|
6441 mp4free(buf); |
|
6442 mp4free(buf2); |
|
6443 |
|
6444 return -1; |
|
6445 } |
|
6446 |
|
6447 left -= bytestoread; |
|
6448 } |
|
6449 |
|
6450 mp4free(buf); |
|
6451 mp4free(buf2); |
|
6452 |
|
6453 |
|
6454 return 0; |
|
6455 } |
|
6456 |
|
6457 |
|
6458 /* |
|
6459 * Function: |
|
6460 * |
|
6461 * mp4_i32 writeMediaData(MP4HandleImp handle) |
|
6462 * |
|
6463 * Description: |
|
6464 * |
|
6465 * This function writes media data to the output file. |
|
6466 * |
|
6467 * Before writing media data to the output file, meta data has |
|
6468 * been written to the file. Media data that is in tmpfile is |
|
6469 * read from there and written to the end of the output file. |
|
6470 * |
|
6471 * Parameters: |
|
6472 * |
|
6473 * handle MP4 library handle |
|
6474 * |
|
6475 * Return value: |
|
6476 * |
|
6477 * 0 Success |
|
6478 * -1 Error |
|
6479 * |
|
6480 */ |
|
6481 mp4_i32 writeMediaData(MP4HandleImp handle) |
|
6482 { |
|
6483 mp4_u8 *buf; |
|
6484 mp4_u32 i = 0; |
|
6485 mp4_u64 left; |
|
6486 mp4_u32 bytestoread; |
|
6487 |
|
6488 |
|
6489 buf = (mp4_u8 *)mp4malloc(1024); |
|
6490 if (buf == NULL) |
|
6491 return -1; |
|
6492 |
|
6493 |
|
6494 i = formatMdatHeader(buf, handle->bytesInTmpFile); |
|
6495 if (writeFile(handle, buf, i) < 0) |
|
6496 { |
|
6497 mp4free(buf); |
|
6498 |
|
6499 return -1; |
|
6500 } |
|
6501 |
|
6502 /* Seek to the beginning of tmpfile */ |
|
6503 if (seekTmpFileAbs(handle, 0) < 0) |
|
6504 { |
|
6505 mp4free(buf); |
|
6506 return -1; |
|
6507 } |
|
6508 |
|
6509 left = handle->bytesInTmpFile; |
|
6510 |
|
6511 while (left) |
|
6512 { |
|
6513 if (left > 1024) |
|
6514 bytestoread = 1024; |
|
6515 else |
|
6516 bytestoread = left; |
|
6517 |
|
6518 if (readTmpFile(handle, buf, bytestoread) < 0) |
|
6519 { |
|
6520 mp4free(buf); |
|
6521 |
|
6522 return -1; |
|
6523 } |
|
6524 |
|
6525 if (writeFile(handle, buf, bytestoread) < 0) |
|
6526 { |
|
6527 mp4free(buf); |
|
6528 |
|
6529 return -1; |
|
6530 } |
|
6531 |
|
6532 left -= bytestoread; |
|
6533 } |
|
6534 |
|
6535 mp4free(buf); |
|
6536 |
|
6537 return 0; |
|
6538 } |
|
6539 |
|
6540 /* |
|
6541 * Function: |
|
6542 * |
|
6543 * mp4_i32 insertu64(mp4_u8 *buf, |
|
6544 * mp4_u64 value) |
|
6545 * |
|
6546 * Description: |
|
6547 * |
|
6548 * This function writes value into buf taking into account the endianism |
|
6549 * of the current computer. |
|
6550 * |
|
6551 * It is assumed that the caller of the function has allocated enough |
|
6552 * space for buf. |
|
6553 * |
|
6554 * Parameters: |
|
6555 * |
|
6556 * buf Buffer to write to |
|
6557 * value Value to write to buf |
|
6558 * |
|
6559 * Return value: |
|
6560 * |
|
6561 * 0 Success |
|
6562 * |
|
6563 */ |
|
6564 mp4_i32 insertu64(mp4_u8 *buf, mp4_u64 value) |
|
6565 { |
|
6566 mp4_u64 u64; |
|
6567 |
|
6568 |
|
6569 u64 = u64endian(value); |
|
6570 mp4memcpy(buf, &u64, sizeof(mp4_u64)); |
|
6571 |
|
6572 return 0; |
|
6573 } |
|
6574 |
|
6575 |
|
6576 /* |
|
6577 * Function: |
|
6578 * |
|
6579 * mp4_i32 insertu32(mp4_u8 *buf, |
|
6580 * mp4_u32 value) |
|
6581 * |
|
6582 * Description: |
|
6583 * |
|
6584 * This function writes value into buf taking into account the endianism |
|
6585 * of the current computer. |
|
6586 * |
|
6587 * It is assumed that the caller of the function has allocated enough |
|
6588 * space for buf. |
|
6589 * |
|
6590 * Parameters: |
|
6591 * |
|
6592 * buf Buffer to write to |
|
6593 * value Value to write to buf |
|
6594 * |
|
6595 * Return value: |
|
6596 * |
|
6597 * 0 Success |
|
6598 * |
|
6599 */ |
|
6600 mp4_i32 insertu32(mp4_u8 *buf, mp4_u32 value) |
|
6601 { |
|
6602 mp4_u32 u32; |
|
6603 |
|
6604 |
|
6605 u32 = u32endian(value); |
|
6606 mp4memcpy(buf, &u32, 4); |
|
6607 |
|
6608 return 0; |
|
6609 } |
|
6610 |
|
6611 |
|
6612 /* |
|
6613 * Function: |
|
6614 * |
|
6615 * mp4_i32 insertu16(mp4_u8 *buf, |
|
6616 * mp4_u16 value) |
|
6617 * |
|
6618 * Description: |
|
6619 * |
|
6620 * This function writes value into buf taking into account the endianism |
|
6621 * of the current computer. |
|
6622 * |
|
6623 * It is assumed that the caller of the function has allocated enough |
|
6624 * space for buf. |
|
6625 * |
|
6626 * Parameters: |
|
6627 * |
|
6628 * buf Buffer to write to |
|
6629 * value Value to write to buf |
|
6630 * |
|
6631 * Return value: |
|
6632 * |
|
6633 * 0 Success |
|
6634 * |
|
6635 */ |
|
6636 mp4_i32 insertu16(mp4_u8 *buf, mp4_u16 value) |
|
6637 { |
|
6638 mp4_u16 u16; |
|
6639 |
|
6640 |
|
6641 u16 = u16endian(value); |
|
6642 mp4memcpy(buf, &u16, 2); |
|
6643 |
|
6644 return 0; |
|
6645 } |
|
6646 |
|
6647 |
|
6648 /* |
|
6649 * Function: |
|
6650 * |
|
6651 * mp4_i32 writeMetaDataTmp(MP4HandleImp handle) |
|
6652 * |
|
6653 * Description: |
|
6654 * |
|
6655 * This function writes metadata accumulated in memory to the disk. |
|
6656 * |
|
6657 * Parameters: |
|
6658 * |
|
6659 * handle MP4 library handle |
|
6660 * |
|
6661 * Return value: |
|
6662 * |
|
6663 * 0 Success |
|
6664 * -1 Error |
|
6665 * |
|
6666 */ |
|
6667 mp4_i32 writeMetaDataTmp(MP4HandleImp handle) |
|
6668 { |
|
6669 PRINT((_L("e_writemetadatatmp 1"))); |
|
6670 if (handle->videoSampleTable) |
|
6671 { |
|
6672 PRINT((_L("e_writemetadatatmp_writemetadata_video 1"))); |
|
6673 if (writeMetaDataFileNum(handle, |
|
6674 (mp4_u8 *)handle->videoSampleTable->sttsSampleCount, |
|
6675 handle->videoSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), |
|
6676 METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0) |
|
6677 return -1; |
|
6678 |
|
6679 if (writeMetaDataFileNum(handle, |
|
6680 (mp4_u8 *)handle->videoSampleTable->sttsSampleDelta, |
|
6681 handle->videoSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), |
|
6682 METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0) |
|
6683 return -1; |
|
6684 |
|
6685 if (writeMetaDataFileNum(handle, |
|
6686 (mp4_u8 *)handle->videoSampleTable->stszEntrySize, |
|
6687 handle->videoSampleTable->stszCurrentSampleCount * sizeof(mp4_u32), |
|
6688 METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0) |
|
6689 return -1; |
|
6690 |
|
6691 if (writeMetaDataFileNum(handle, |
|
6692 (mp4_u8 *)handle->videoSampleTable->stcoChunkOffset, |
|
6693 handle->videoSampleTable->stcoCurrentEntryCount * sizeof(mp4_u64), |
|
6694 METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) |
|
6695 return -1; |
|
6696 |
|
6697 if (writeMetaDataFileNum(handle, |
|
6698 (mp4_u8 *)handle->videoSampleTable->stssSampleNumber, |
|
6699 handle->videoSampleTable->stssCurrentEntryCount * sizeof(mp4_u32), |
|
6700 METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0) |
|
6701 return -1; |
|
6702 |
|
6703 if (writeMetaDataFileNum(handle, |
|
6704 (mp4_u8 *)handle->videoSampleTable->sdtpSampleDependency, |
|
6705 handle->videoSampleTable->sdtpCurrentEntryCount * sizeof(mp4_u8), |
|
6706 METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0) |
|
6707 return -1; |
|
6708 PRINT((_L("e_writemetadatatmp_writemetadata_video 0"))); |
|
6709 } |
|
6710 |
|
6711 if (handle->audioSampleTable) |
|
6712 { |
|
6713 PRINT((_L("e_writemetadatatmp_writemetadata_audio 1"))); |
|
6714 if (writeMetaDataFileNum(handle, |
|
6715 (mp4_u8 *)handle->audioSampleTable->sttsSampleCount, |
|
6716 handle->audioSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), |
|
6717 METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0) |
|
6718 return -1; |
|
6719 |
|
6720 if (writeMetaDataFileNum(handle, |
|
6721 (mp4_u8 *)handle->audioSampleTable->sttsSampleDelta, |
|
6722 handle->audioSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), |
|
6723 METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0) |
|
6724 return -1; |
|
6725 |
|
6726 if (writeMetaDataFileNum(handle, |
|
6727 (mp4_u8 *)handle->audioSampleTable->stszEntrySize, |
|
6728 handle->audioSampleTable->stszCurrentSampleCount * sizeof(mp4_u32), |
|
6729 METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0) |
|
6730 return -1; |
|
6731 |
|
6732 if (writeMetaDataFileNum(handle, |
|
6733 (mp4_u8 *)handle->audioSampleTable->stcoChunkOffset, |
|
6734 handle->audioSampleTable->stcoCurrentEntryCount * sizeof(mp4_u64), |
|
6735 METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) |
|
6736 return -1; |
|
6737 PRINT((_L("e_writemetadatatmp_writemetadata_audio 0"))); |
|
6738 } |
|
6739 |
|
6740 if (handle->videoSampleTable) |
|
6741 { |
|
6742 handle->videoSampleTable->sttsCurrentEntryCount = 0; |
|
6743 handle->videoSampleTable->stszCurrentSampleCount = 0; |
|
6744 handle->videoSampleTable->stcoCurrentEntryCount = 0; |
|
6745 handle->videoSampleTable->stssCurrentEntryCount = 0; |
|
6746 handle->videoSampleTable->sdtpCurrentEntryCount = 0; |
|
6747 } |
|
6748 |
|
6749 if (handle->audioSampleTable) |
|
6750 { |
|
6751 handle->audioSampleTable->sttsCurrentEntryCount = 0; |
|
6752 handle->audioSampleTable->stszCurrentSampleCount = 0; |
|
6753 handle->audioSampleTable->stcoCurrentEntryCount = 0; |
|
6754 } |
|
6755 |
|
6756 handle->metaDataBlocks = 0; |
|
6757 handle->metaDataOnDisk = MP4TRUE; |
|
6758 |
|
6759 PRINT((_L("e_writemetadatatmp 0"))); |
|
6760 return 0; |
|
6761 } |
|
6762 |
|
6763 /* |
|
6764 * Function: |
|
6765 * |
|
6766 * mp4_i32 writeSQCP(MP4HandleImp handle, |
|
6767 * trakSize *ts) |
|
6768 * |
|
6769 * Description: |
|
6770 * |
|
6771 * Write SQCP atom. |
|
6772 * |
|
6773 * Parameters: |
|
6774 * |
|
6775 * handle MP4 library handle |
|
6776 * ts Atom sizes |
|
6777 * |
|
6778 * Return value: |
|
6779 * |
|
6780 * 0 Success |
|
6781 * -1 Error |
|
6782 * |
|
6783 */ |
|
6784 mp4_i32 writeSQCP(MP4HandleImp handle, trakSize *ts) |
|
6785 { |
|
6786 mp4_u8 *buf; |
|
6787 mp4_u32 i = 0; |
|
6788 |
|
6789 |
|
6790 buf = (mp4_u8 *)mp4malloc(36); |
|
6791 if (buf == NULL) |
|
6792 return -1; |
|
6793 |
|
6794 /* Size */ |
|
6795 insertu32(buf+i, (mp4_u32)ts->sqcp); |
|
6796 i += 4; |
|
6797 |
|
6798 /* Atom type */ |
|
6799 insertu32(buf+i, (mp4_u32)ATOMTYPE_SQCP); |
|
6800 i += 4; |
|
6801 |
|
6802 /* Reserved */ |
|
6803 buf[i++] = 0; |
|
6804 buf[i++] = 0; |
|
6805 buf[i++] = 0; |
|
6806 buf[i++] = 0; |
|
6807 buf[i++] = 0; |
|
6808 buf[i++] = 0; |
|
6809 |
|
6810 /* Data reference index */ |
|
6811 insertu16(buf+i, (mp4_u16)1); |
|
6812 i += 2; |
|
6813 |
|
6814 /* Reserved */ |
|
6815 insertu32(buf+i, (mp4_u32)0); |
|
6816 i += 4; |
|
6817 |
|
6818 insertu32(buf+i, (mp4_u32)0); |
|
6819 i += 4; |
|
6820 |
|
6821 insertu16(buf+i, (mp4_u16)2); |
|
6822 i += 2; |
|
6823 |
|
6824 insertu16(buf+i, (mp4_u16)16); |
|
6825 i += 2; |
|
6826 |
|
6827 insertu32(buf+i, (mp4_u32)0); |
|
6828 i += 4; |
|
6829 |
|
6830 /* Timescale */ |
|
6831 insertu16(buf+i, (mp4_u16)handle->audioTimeScale); |
|
6832 i += 2; |
|
6833 |
|
6834 /* Reserved */ |
|
6835 insertu16(buf+i, (mp4_u16)0); |
|
6836 i += 2; |
|
6837 |
|
6838 if (writeFile(handle, buf, 36) < 0) |
|
6839 { |
|
6840 mp4free(buf); |
|
6841 |
|
6842 return -1; |
|
6843 } |
|
6844 |
|
6845 if (writeDQCP(handle, ts) < 0) |
|
6846 { |
|
6847 mp4free(buf); |
|
6848 |
|
6849 return -1; |
|
6850 } |
|
6851 |
|
6852 mp4free(buf); |
|
6853 |
|
6854 return 0; |
|
6855 } |
|
6856 |
|
6857 /* |
|
6858 * Function: |
|
6859 * |
|
6860 * mp4_i32 writeDQCP(MP4HandleImp handle, |
|
6861 * trakSize *ts) |
|
6862 * |
|
6863 * Description: |
|
6864 * |
|
6865 * Write DQCP atom. |
|
6866 * |
|
6867 * Parameters: |
|
6868 * |
|
6869 * handle MP4 library handle |
|
6870 * ts Atom sizes |
|
6871 * |
|
6872 * Return value: |
|
6873 * |
|
6874 * 0 Success |
|
6875 * -1 Error |
|
6876 * |
|
6877 */ |
|
6878 mp4_i32 writeDQCP(MP4HandleImp handle, trakSize *ts) |
|
6879 { |
|
6880 mp4_u8 buf[14]; |
|
6881 mp4_u32 i = 0; |
|
6882 |
|
6883 |
|
6884 /* Size */ |
|
6885 insertu32(buf+i, (mp4_u32)ts->dqcp); |
|
6886 i += 4; |
|
6887 |
|
6888 /* Atom type */ |
|
6889 insertu32(buf+i, (mp4_u32)ATOMTYPE_DQCP); |
|
6890 i += 4; |
|
6891 |
|
6892 /* Vendor */ |
|
6893 buf[i++] = 'n'; |
|
6894 buf[i++] = 'o'; |
|
6895 buf[i++] = 'k'; |
|
6896 buf[i++] = 'i'; |
|
6897 |
|
6898 /* Decoder version */ |
|
6899 buf[i++] = 0; |
|
6900 |
|
6901 /* Mode set */ |
|
6902 // insertu16(buf+i, (mp4_u16)handle->audioModeSet); |
|
6903 // i += 2; |
|
6904 |
|
6905 /* Mode change period */ |
|
6906 // buf[i++] = 0; |
|
6907 |
|
6908 /* Frames per sample */ |
|
6909 buf[i++] = handle->audioFramesPerSample; |
|
6910 |
|
6911 if (writeFile(handle, buf, 14) < 0) |
|
6912 return -1; |
|
6913 |
|
6914 return 0; |
|
6915 } |
|
6916 |
|
6917 /* |
|
6918 * Function: |
|
6919 * |
|
6920 * mp4_i32 calculateES_DescriptorSize(mp4_u32 type) |
|
6921 * |
|
6922 * Description: |
|
6923 * |
|
6924 * Calculated the ES_Descriptor size inside the ESDS box. |
|
6925 * Updates handle->ES_DescriptorSize; |
|
6926 * |
|
6927 * Parameters: |
|
6928 * |
|
6929 * handle MP4 library handle |
|
6930 * type the media type: |
|
6931 * MP4_TYPE_QCELP_13K |
|
6932 * MP4_TYPE_MPEG_AUDIO |
|
6933 * MP4_TYPE_MPEG4_VIDEO |
|
6934 * |
|
6935 * Return value: |
|
6936 * |
|
6937 * 0 Success |
|
6938 * |
|
6939 */ |
|
6940 mp4_i32 calculateES_DescriptorSize(MP4HandleImp handle, mp4_u32 type) |
|
6941 { |
|
6942 mp4_u32 size1, size2, size3; |
|
6943 mp4_u32 numofsizebytes1, numofsizebytes2, numofsizebytes3; |
|
6944 mp4_u32 decspecinfosize = 0; |
|
6945 |
|
6946 if (((type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) || |
|
6947 (type & MP4_TYPE_MPEG4_AUDIO)) |
|
6948 decspecinfosize = handle->audioDecSpecificInfoSize; |
|
6949 else /* MPEG video case */ |
|
6950 decspecinfosize = handle->videoDecSpecificInfoSize; |
|
6951 |
|
6952 size1 = decspecinfosize; |
|
6953 if (size1 < 128) |
|
6954 numofsizebytes1 = 1; |
|
6955 else |
|
6956 { |
|
6957 numofsizebytes1 = 1; |
|
6958 while ( size1 >= 128 ) |
|
6959 { |
|
6960 size1 = size1 >> 7; |
|
6961 numofsizebytes1++; |
|
6962 } |
|
6963 } |
|
6964 |
|
6965 size2 = 14 + numofsizebytes1 + decspecinfosize; |
|
6966 if (size2 < 128) |
|
6967 numofsizebytes2 = 1; |
|
6968 else |
|
6969 { |
|
6970 numofsizebytes2 = 1; |
|
6971 while ( size2 >= 128 ) |
|
6972 { |
|
6973 size2 = size2 >> 7; |
|
6974 numofsizebytes2++; |
|
6975 } |
|
6976 } |
|
6977 |
|
6978 size3 = 21 + numofsizebytes1 + numofsizebytes2 + decspecinfosize; |
|
6979 if (size3 < 128) |
|
6980 numofsizebytes3 = 1; |
|
6981 else |
|
6982 { |
|
6983 numofsizebytes3 = 1; |
|
6984 while ( size3 >= 128 ) |
|
6985 { |
|
6986 size3 = size3 >> 7; |
|
6987 numofsizebytes3++; |
|
6988 } |
|
6989 } |
|
6990 |
|
6991 /* ES_DescriptorSize contains the size of the ES_Descriptor Field, including the 0x03 (ES_ID Tag) */ |
|
6992 handle->ES_DescriptorSize = 21 + numofsizebytes1 + numofsizebytes2 + decspecinfosize + numofsizebytes3 + 1; |
|
6993 return 0; |
|
6994 } |
|
6995 |
|
6996 /* |
|
6997 * Function: |
|
6998 * |
|
6999 * mp4_i32 writeUDTA(MP4HandleImp handle, |
|
7000 * userDataAtom *udta) |
|
7001 * |
|
7002 * Description: |
|
7003 * |
|
7004 * Write UDTA atom. |
|
7005 * |
|
7006 * Parameters: |
|
7007 * |
|
7008 * handle MP4 library handle |
|
7009 * ts Atom sizes |
|
7010 * |
|
7011 * Return value: |
|
7012 * |
|
7013 * 0 Success |
|
7014 * -1 Error |
|
7015 * |
|
7016 */ |
|
7017 mp4_i32 writeUDTA(MP4HandleImp handle, userDataAtom *udta) |
|
7018 { |
|
7019 mp4_u8 buf[8]; |
|
7020 mp4_u32 i = 0; |
|
7021 |
|
7022 |
|
7023 /* Size */ |
|
7024 insertu32(buf+i, 8 + (mp4_u32)udta->atomcontentsize); |
|
7025 i += 4; |
|
7026 |
|
7027 /* Atom type */ |
|
7028 insertu32(buf+i, (mp4_u32)ATOMTYPE_UDTA); |
|
7029 i += 4; |
|
7030 |
|
7031 if (writeFile(handle, buf, 8) < 0) |
|
7032 return -1; |
|
7033 |
|
7034 if (writeFile(handle, udta->contentdata, udta->atomcontentsize) < 0) |
|
7035 return -1; |
|
7036 |
|
7037 return 0; |
|
7038 } |
|
7039 |
|
7040 /* |
|
7041 * Function: |
|
7042 * |
|
7043 * mp4_i32 updateVideoDependencyMetaData(MP4HandleImp handle, |
|
7044 * mp4_u8 aDependsOn, |
|
7045 * mp4_u8 aIsDependentOn, |
|
7046 * mp4_u8 aHasRedundancy) |
|
7047 * |
|
7048 * Description: |
|
7049 * |
|
7050 * Updates SDTP video dependency data |
|
7051 * |
|
7052 * Parameters: |
|
7053 * |
|
7054 * handle MP4 library handle |
|
7055 * aDependsOn This frame's dependency on other frames |
|
7056 * aIsDependentOn Other frames's dependency on this frame |
|
7057 * aHasRedundancy Whether there is redundant coding in this frame |
|
7058 * |
|
7059 * Return value: |
|
7060 * |
|
7061 * 0 Success |
|
7062 * -1 Error |
|
7063 * |
|
7064 */ |
|
7065 mp4_i32 updateVideoDependencyMetaData(MP4HandleImp handle, mp4_u8 aDependsOn, mp4_u8 aIsDependentOn, mp4_u8 aHasRedundancy) |
|
7066 { |
|
7067 if (handle->flags & MP4_FLAG_LONGCLIP) |
|
7068 { |
|
7069 if (handle->videoSampleTable->sdtpCurrentEntryCount == handle->videoSampleTable->sdtpMaxEntryCount) |
|
7070 { |
|
7071 void *p; |
|
7072 |
|
7073 p = mp4realloc(handle->videoSampleTable->sdtpSampleDependency, |
|
7074 2 * sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount, |
|
7075 sizeof(mp4_u8) * handle->videoSampleTable->stssMaxEntryCount); |
|
7076 if (p == NULL) |
|
7077 return -1; |
|
7078 |
|
7079 handle->videoSampleTable->sdtpSampleDependency = (mp4_u8 *)p; |
|
7080 |
|
7081 handle->videoSampleTable->sdtpMaxEntryCount *= 2; |
|
7082 } |
|
7083 |
|
7084 handle->videoSampleTable->sdtpSampleDependency[handle->videoSampleTable->sdtpCurrentEntryCount] = (aDependsOn << 4) | (aIsDependentOn << 2) | (aHasRedundancy); |
|
7085 handle->videoSampleTable->sdtpCurrentEntryCount++; |
|
7086 handle->videoSampleTable->sdtpEntryCount++; |
|
7087 } |
|
7088 else |
|
7089 { |
|
7090 if (handle->videoSampleTable->sdtpEntryCount == handle->videoSampleTable->sdtpMaxEntryCount) |
|
7091 { |
|
7092 void *p; |
|
7093 |
|
7094 p = mp4realloc(handle->videoSampleTable->sdtpSampleDependency, |
|
7095 2 * sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount, |
|
7096 sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount); |
|
7097 if (p == NULL) |
|
7098 return -1; |
|
7099 |
|
7100 handle->videoSampleTable->sdtpSampleDependency = (mp4_u8 *)p; |
|
7101 |
|
7102 handle->videoSampleTable->sdtpMaxEntryCount *= 2; |
|
7103 } |
|
7104 |
|
7105 handle->videoSampleTable->sdtpSampleDependency[handle->videoSampleTable->sdtpEntryCount] = (aDependsOn << 4) | (aIsDependentOn << 2) | (aHasRedundancy); |
|
7106 handle->videoSampleTable->sdtpEntryCount++; |
|
7107 } |
|
7108 |
|
7109 return 0; |
|
7110 } |
|
7111 |
|
7112 /* |
|
7113 * Function: |
|
7114 * |
|
7115 * mp4_i32 writeVideoSDTP(MP4HandleImp handle, |
|
7116 * trakSize *ts) |
|
7117 * |
|
7118 * Description: |
|
7119 * |
|
7120 * Write video SDTP atom. |
|
7121 * |
|
7122 * Parameters: |
|
7123 * |
|
7124 * handle MP4 library handle |
|
7125 * ts Atom sizes |
|
7126 * |
|
7127 * Return value: |
|
7128 * |
|
7129 * 0 Success |
|
7130 * -1 Error |
|
7131 * |
|
7132 */ |
|
7133 mp4_i32 writeVideoSDTP(MP4HandleImp handle, trakSize *ts) |
|
7134 { |
|
7135 mp4_u8 *buf; |
|
7136 mp4_u32 i = 0; |
|
7137 mp4_u32 j; |
|
7138 |
|
7139 buf = (mp4_u8 *)mp4malloc(ts->sdtp); |
|
7140 if (buf == NULL) |
|
7141 return -1; |
|
7142 |
|
7143 /* Size */ |
|
7144 insertu32(buf+i, (mp4_u32)ts->sdtp); |
|
7145 i += 4; |
|
7146 |
|
7147 /* Atom type */ |
|
7148 insertu32(buf+i, (mp4_u32)ATOMTYPE_SDTP); |
|
7149 i += 4; |
|
7150 |
|
7151 /* Version and flags */ |
|
7152 insertu32(buf+i, (mp4_u32)0); |
|
7153 i += 4; |
|
7154 |
|
7155 /* Sample dependencies */ |
|
7156 for (j = 0; j < handle->videoSampleTable->sdtpEntryCount; j++) |
|
7157 { |
|
7158 buf[i++] = (mp4_u8)handle->videoSampleTable->sdtpSampleDependency[j]; |
|
7159 } |
|
7160 |
|
7161 if (writeFile(handle, buf, ts->sdtp) < 0) |
|
7162 { |
|
7163 mp4free(buf); |
|
7164 |
|
7165 return -1; |
|
7166 } |
|
7167 |
|
7168 mp4free(buf); |
|
7169 |
|
7170 return 0; |
|
7171 } |
|
7172 |
|
7173 /* |
|
7174 * Function: |
|
7175 * |
|
7176 * mp4_i32 writeVideoSDTPLongClip(MP4HandleImp handle, |
|
7177 * trakSize *ts) |
|
7178 * |
|
7179 * Description: |
|
7180 * |
|
7181 * Write video SDTP atom. |
|
7182 * |
|
7183 * Parameters: |
|
7184 * |
|
7185 * handle MP4 library handle |
|
7186 * ts Atom sizes |
|
7187 * |
|
7188 * Return value: |
|
7189 * |
|
7190 * 0 Success |
|
7191 * -1 Error |
|
7192 * |
|
7193 */ |
|
7194 mp4_i32 writeVideoSDTPLongClip(MP4HandleImp handle, trakSize *ts) |
|
7195 { |
|
7196 mp4_u8 *buf; |
|
7197 mp4_u8 *buf2; |
|
7198 mp4_u32 i = 0; |
|
7199 mp4_u32 left; |
|
7200 mp4_u32 bytestoread; |
|
7201 |
|
7202 |
|
7203 buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); |
|
7204 if (buf == NULL) |
|
7205 return -1; |
|
7206 |
|
7207 buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2); |
|
7208 if (buf2 == NULL) |
|
7209 { |
|
7210 mp4free(buf); |
|
7211 return -1; |
|
7212 } |
|
7213 |
|
7214 /* Size */ |
|
7215 insertu32(buf+i, (mp4_u32)ts->sdtp); |
|
7216 i += 4; |
|
7217 |
|
7218 /* Atom type */ |
|
7219 insertu32(buf+i, (mp4_u32)ATOMTYPE_SDTP); |
|
7220 i += 4; |
|
7221 |
|
7222 /* Version and flags */ |
|
7223 insertu32(buf+i, (mp4_u32)0); |
|
7224 i += 4; |
|
7225 |
|
7226 if (writeFile(handle, buf, i) < 0) |
|
7227 { |
|
7228 mp4free(buf); |
|
7229 mp4free(buf2); |
|
7230 |
|
7231 return -1; |
|
7232 } |
|
7233 |
|
7234 /* Sample count and delta */ |
|
7235 |
|
7236 /* Seek to the beginning of temporary files */ |
|
7237 |
|
7238 if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0) |
|
7239 { |
|
7240 mp4free(buf); |
|
7241 mp4free(buf2); |
|
7242 return -1; |
|
7243 } |
|
7244 |
|
7245 left = handle->videoSampleTable->sdtpEntryCount; /* Bytes left in each file */ |
|
7246 |
|
7247 while (left) |
|
7248 { |
|
7249 if (left > METADATA_COPY_BUFFERSIZE / 2) |
|
7250 bytestoread = METADATA_COPY_BUFFERSIZE / 2; |
|
7251 else |
|
7252 bytestoread = left; |
|
7253 |
|
7254 if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0) |
|
7255 { |
|
7256 mp4free(buf); |
|
7257 mp4free(buf2); |
|
7258 |
|
7259 return -1; |
|
7260 } |
|
7261 |
|
7262 if (writeFile(handle, buf2, bytestoread) < 0) |
|
7263 { |
|
7264 mp4free(buf); |
|
7265 mp4free(buf2); |
|
7266 |
|
7267 return -1; |
|
7268 } |
|
7269 |
|
7270 left -= bytestoread; |
|
7271 } |
|
7272 |
|
7273 mp4free(buf); |
|
7274 mp4free(buf2); |
|
7275 |
|
7276 |
|
7277 return 0; |
|
7278 } |
|
7279 |
|
7280 /* |
|
7281 * Function: |
|
7282 * |
|
7283 * mp4_i32 writeAVCP(MP4HandleImp handle, |
|
7284 * trakSize *ts) |
|
7285 * |
|
7286 * Description: |
|
7287 * |
|
7288 * Write AVCP atom. |
|
7289 * |
|
7290 * Parameters: |
|
7291 * |
|
7292 * handle MP4 library handle |
|
7293 * ts Atom sizes |
|
7294 * |
|
7295 * Return value: |
|
7296 * |
|
7297 * 0 Success |
|
7298 * -1 Error |
|
7299 * |
|
7300 */ |
|
7301 mp4_i32 writeAVCP(MP4HandleImp handle, trakSize *ts) |
|
7302 { |
|
7303 mp4_u8 *buf; |
|
7304 mp4_u32 i = 0; |
|
7305 |
|
7306 |
|
7307 buf = (mp4_u8 *)mp4malloc(86+7); // 86 = size of VisualSampleEntry, 7 = size of AVCDecoderConfigurationRecord |
|
7308 // with PPS and SPS sizes set to 0 |
|
7309 if (buf == NULL) |
|
7310 return -1; |
|
7311 |
|
7312 /* Size */ |
|
7313 insertu32(buf+i, (mp4_u32)ts->avcp); |
|
7314 i += 4; |
|
7315 |
|
7316 /* Atom type */ |
|
7317 insertu32(buf+i, (mp4_u32)ATOMTYPE_AVCP); |
|
7318 i += 4; |
|
7319 |
|
7320 /* Reserved */ |
|
7321 buf[i++] = 0; |
|
7322 buf[i++] = 0; |
|
7323 buf[i++] = 0; |
|
7324 buf[i++] = 0; |
|
7325 buf[i++] = 0; |
|
7326 buf[i++] = 0; |
|
7327 |
|
7328 /* Data reference index */ |
|
7329 insertu16(buf+i, (mp4_u16)1); |
|
7330 i += 2; |
|
7331 |
|
7332 /* Reserved */ |
|
7333 insertu32(buf+i, (mp4_u32)0); |
|
7334 i += 4; |
|
7335 |
|
7336 insertu32(buf+i, (mp4_u32)0); |
|
7337 i += 4; |
|
7338 |
|
7339 insertu32(buf+i, (mp4_u32)0); |
|
7340 i += 4; |
|
7341 |
|
7342 insertu32(buf+i, (mp4_u32)0); |
|
7343 i += 4; |
|
7344 |
|
7345 /* Width */ |
|
7346 insertu16(buf+i, (mp4_u16)handle->videoWidth); |
|
7347 i += 2; |
|
7348 |
|
7349 /* Height */ |
|
7350 insertu16(buf+i, (mp4_u16)handle->videoHeight); |
|
7351 i += 2; |
|
7352 |
|
7353 /* Reserved */ |
|
7354 insertu32(buf+i, (mp4_u32)0x00480000); |
|
7355 i += 4; |
|
7356 |
|
7357 insertu32(buf+i, (mp4_u32)0x00480000); |
|
7358 i += 4; |
|
7359 |
|
7360 insertu32(buf+i, (mp4_u32)0); |
|
7361 i += 4; |
|
7362 |
|
7363 insertu16(buf+i, (mp4_u16)1); |
|
7364 i += 2; |
|
7365 |
|
7366 // Compressorname |
|
7367 buf[i++] = 14; |
|
7368 insertu32(buf+i, (mp4_u32)0x41564320); // "AVC " |
|
7369 i += 4; |
|
7370 insertu32(buf+i, (mp4_u32)0x70617261); // "para" |
|
7371 i += 4; |
|
7372 insertu32(buf+i, (mp4_u32)0x6d657465); // "mete" |
|
7373 i += 4; |
|
7374 insertu16(buf+i, (mp4_u16)0x7273); // "rs" |
|
7375 i += 2; |
|
7376 buf[i++] = 0; |
|
7377 insertu32(buf+i, (mp4_u32)0); |
|
7378 i += 4; |
|
7379 insertu32(buf+i, (mp4_u32)0); |
|
7380 i += 4; |
|
7381 insertu32(buf+i, (mp4_u32)0); |
|
7382 i += 4; |
|
7383 insertu32(buf+i, (mp4_u32)0); |
|
7384 i += 4; |
|
7385 |
|
7386 insertu16(buf+i, (mp4_u16)24); |
|
7387 i += 2; |
|
7388 |
|
7389 insertu16(buf+i, (mp4_u16)0xffff); |
|
7390 i += 2; |
|
7391 |
|
7392 // AVCC without picparams & seqparams |
|
7393 mp4memcpy(buf+i, handle->videoDecSpecificInfo, 5); // 5 = configurationVersion + AVCProfileIndication + |
|
7394 // profile_compatibility + AVCLevelIndication + |
|
7395 // '111111' + lengthSizeMinusOne (2 bits) |
|
7396 i += 5; |
|
7397 buf[i++] = 0xE0 | 0; // '111' + numOfSequenceParameterSets (5 bits) |
|
7398 buf[i++] = 0; // numOfPictureParameterSets |
|
7399 |
|
7400 if (writeFile(handle, buf, 86+7) < 0) |
|
7401 { |
|
7402 mp4free(buf); |
|
7403 |
|
7404 return -1; |
|
7405 } |
|
7406 |
|
7407 mp4free(buf); |
|
7408 |
|
7409 return 0; |
|
7410 } |
|
7411 |
|
7412 /* |
|
7413 * Function: |
|
7414 * |
|
7415 * mp4_i32 formatMdatHeader(mp4_u8 *buffer, |
|
7416 * mp4_u64 size) |
|
7417 * |
|
7418 * Description: |
|
7419 * |
|
7420 * Formats the MDAT header into buffer |
|
7421 * |
|
7422 * Parameters: |
|
7423 * |
|
7424 * buffer buffer to write the MDAT header into |
|
7425 * size Size of the media data (excluding the MDAT header) |
|
7426 * |
|
7427 * Return value: |
|
7428 * |
|
7429 * size of header |
|
7430 * |
|
7431 */ |
|
7432 mp4_i32 formatMdatHeader(mp4_u8 *buf, mp4_u64 size) |
|
7433 { |
|
7434 TInt i = 0; |
|
7435 if (size < MP4_INT_MAX) |
|
7436 { |
|
7437 //insert free box |
|
7438 insertu32(buf, (mp4_u32)8); |
|
7439 i += sizeof(mp4_u32); |
|
7440 insertu32(buf + i, (mp4_u32)ATOMTYPE_FREE); |
|
7441 i += sizeof(mp4_u32); |
|
7442 |
|
7443 //insert mdat box |
|
7444 insertu32(buf + i, (mp4_u32)size + 8); |
|
7445 i += sizeof(mp4_u32); |
|
7446 insertu32(buf + i, (mp4_u32)ATOMTYPE_MDAT); |
|
7447 i += sizeof(mp4_u32); |
|
7448 } |
|
7449 else |
|
7450 { |
|
7451 //insert mdat box |
|
7452 insertu32(buf + i, (mp4_u32)1); |
|
7453 i += sizeof(mp4_u32); |
|
7454 insertu32(buf + i, (mp4_u32)ATOMTYPE_MDAT); |
|
7455 i += sizeof(mp4_u32); |
|
7456 insertu64(buf + i, (mp4_u64)size + 16); |
|
7457 i += sizeof(mp4_u64); |
|
7458 } |
|
7459 |
|
7460 ASSERT(MDAT_HEADER_SIZE == i); |
|
7461 return i; |
|
7462 } |
|
7463 |
|
7464 // End of File |