1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/mm/mmplugins/lib3gp/impl/src/compose.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,7464 @@
1.4 +// Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +#include <3gplibrary/mp4config.h>
1.20 +#include <3gplibrary/mp4lib.h>
1.21 +#include "mp4atom.h"
1.22 +#include "mp4memwrap.h"
1.23 +#include "mp4file.h"
1.24 +#include "mp4endian.h"
1.25 +#include "mp4compose.h"
1.26 +#include "mp4currenttime.h"
1.27 +#include "mp4utils.h"
1.28 +
1.29 +#define MP4_INT_MAX KMaxTInt32
1.30 +#define MDAT_HEADER_SIZE 16
1.31 +
1.32 +// MACROS
1.33 +// Debug print macro
1.34 +#ifdef _DEBUG
1.35 +#include <e32svr.h>
1.36 +#define PRINT(x)
1.37 +#else
1.38 +#define PRINT(x)
1.39 +#endif
1.40 +
1.41 +
1.42 +inline void updateChunkOffset(sampleTable *st, mp4_i32 index, mp4_i64 value)
1.43 +{
1.44 + if (value > MP4_INT_MAX)
1.45 + st->stcoNeed64Bits = ETrue;
1.46 +
1.47 + st->stcoChunkOffset[index] = value;
1.48 +}
1.49 +
1.50 +/* must be called after determineAudioTrakMetaDataSize and determineVideoTrakMetaDataSize */
1.51 +size_t mvhdAtomSize(MP4HandleImp handle)
1.52 +{
1.53 + if (handle->videoDuration > MP4_INT_MAX || handle->audioDuration > MP4_INT_MAX)
1.54 + {
1.55 + return 120;
1.56 + }
1.57 + else
1.58 + {
1.59 + return 108;
1.60 + }
1.61 +}
1.62 +
1.63 +
1.64 +
1.65 +/* helper functions */
1.66 +mp4_i32 formatMdatHeader(mp4_u8 *buffer, mp4_i64 size);
1.67 +
1.68 +/*
1.69 + * Function:
1.70 + *
1.71 + * mp4_i32 updateVideoMetaData(MP4HandleImp handle,
1.72 + * mp4_u32 size,
1.73 + * mp4_u32 duration)
1.74 + *
1.75 + * Description:
1.76 + *
1.77 + * This function updates sample table atom data.
1.78 + *
1.79 + * One call of this function will generate one chunk in the MP4 file.
1.80 + *
1.81 + * Parameters:
1.82 + *
1.83 + * handle MP4 library handle
1.84 + * size Size of video frame to insert
1.85 + * duration Duration of the video frame (in media timescale)
1.86 + *
1.87 + * Return value:
1.88 + *
1.89 + * 0 Success
1.90 + * -1 Error
1.91 + *
1.92 + */
1.93 +mp4_i32 updateVideoMetaData(MP4HandleImp handle, mp4_u32 size, mp4_u32 duration, mp4_bool keyframe)
1.94 +{
1.95 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.96 + {
1.97 + if (handle->metaDataBlocks == BLOCK_LIMIT)
1.98 + {
1.99 + /* Write metadata to temporary files */
1.100 +
1.101 + if (writeMetaDataTmp(handle) < 0)
1.102 + return -1;
1.103 + }
1.104 +
1.105 + handle->metaDataBlocks++;
1.106 + }
1.107 +
1.108 + handle->videoSampleTable->currentChunk++;
1.109 +
1.110 + if (updateDecodingTimeToSample(handle, handle->videoSampleTable, duration) < 0)
1.111 + return -1;
1.112 +
1.113 + if (updateSampleSize(handle, handle->videoSampleTable, size) < 0)
1.114 + return -1;
1.115 +
1.116 + if (updateSampleToChunk(handle->videoSampleTable) < 0)
1.117 + return -1;
1.118 +
1.119 + if (updateChunkOffset(handle, handle->videoSampleTable) < 0)
1.120 + return -1;
1.121 +
1.122 + if (keyframe)
1.123 + if (updateSyncSample(handle, handle->videoSampleTable) < 0)
1.124 + return -1;
1.125 +
1.126 + return 0;
1.127 +}
1.128 +
1.129 +
1.130 +/*
1.131 + * Function:
1.132 + *
1.133 + * mp4_i32 updateAudioMetaData(MP4HandleImp handle,
1.134 + * mp4_u32 size,
1.135 + * mp4_u32 numberofframes)
1.136 + *
1.137 + * Description:
1.138 + *
1.139 + * This function updates sample table atom data.
1.140 + *
1.141 + * One call of this function will generate one chunk in the MP4 file.
1.142 + *
1.143 + * Parameters:
1.144 + *
1.145 + * handle MP4 library handle
1.146 + * size Size of video frame to insert
1.147 + * duration Duration of audio frames (in timescale,
1.148 + * see MP4ComposeAddAudioDescription)
1.149 + *
1.150 + * Return value:
1.151 + *
1.152 + * 0 Success
1.153 + * -1 Error
1.154 + *
1.155 + */
1.156 +mp4_i32 updateAudioMetaData(MP4HandleImp handle, mp4_u32 size, mp4_u32 duration)
1.157 +{
1.158 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.159 + {
1.160 + if (handle->metaDataBlocks == BLOCK_LIMIT)
1.161 + {
1.162 + /* Write metadata to temporary files */
1.163 +
1.164 + if (writeMetaDataTmp(handle) < 0)
1.165 + return -1;
1.166 + }
1.167 +
1.168 + handle->metaDataBlocks++;
1.169 + }
1.170 +
1.171 + handle->audioSampleTable->currentChunk++;
1.172 +
1.173 + if (updateDecodingTimeToSample(handle, handle->audioSampleTable, duration) < 0)
1.174 + return -1;
1.175 +
1.176 + if (updateSampleSize(handle, handle->audioSampleTable, size) < 0)
1.177 + return -1;
1.178 +
1.179 + if (updateSampleToChunk(handle->audioSampleTable) < 0)
1.180 + return -1;
1.181 +
1.182 + if (updateChunkOffset(handle, handle->audioSampleTable) < 0)
1.183 + return -1;
1.184 +
1.185 + return 0;
1.186 +}
1.187 +
1.188 +
1.189 +/*
1.190 + * Function:
1.191 + *
1.192 + * mp4_i32 writeFTYPAndMDATToFile(MP4HandleImp handle)
1.193 + *
1.194 + * Description:
1.195 + *
1.196 + * This function writes FTYP box to a file. In addition, it writes MDAT box
1.197 + * size and type to a file. The function is used when meta data is put to
1.198 + * the end of file.
1.199 + *
1.200 + * Parameters:
1.201 + *
1.202 + * handle MP4 library handle
1.203 + *
1.204 + * Return value:
1.205 + *
1.206 + * 0 Success
1.207 + * -1 Error
1.208 + *
1.209 + */
1.210 +mp4_i32 writeFTYPAndMDATToFile(MP4HandleImp handle)
1.211 +{
1.212 + mp4_u8 buf[32];
1.213 + mp4_u32 i = 0;
1.214 +
1.215 +
1.216 + if (writeFTYP(handle) < 0)
1.217 + return -1;
1.218 +
1.219 + handle->ftypWritten = MP4TRUE;
1.220 +
1.221 +
1.222 + i = formatMdatHeader(buf, (mp4_u32)0);
1.223 + if (writeFile(handle, buf, i) < 0)
1.224 + return -1;
1.225 +
1.226 + return 0;
1.227 +}
1.228 +
1.229 +
1.230 +/*
1.231 + * Function:
1.232 + *
1.233 + * mp4_i32 writeDataToFile(MP4HandleImp handle)
1.234 + *
1.235 + * Description:
1.236 + *
1.237 + * This function writes meta and media data to a file.
1.238 + *
1.239 + * Parameters:
1.240 + *
1.241 + * handle MP4 library handle
1.242 + *
1.243 + * Return value:
1.244 + *
1.245 + * 0 Success
1.246 + * -1 Error
1.247 + *
1.248 + */
1.249 +mp4_i32 writeDataToFile(MP4HandleImp handle)
1.250 +{
1.251 + PRINT((_L("e_writedatatofile 1")));
1.252 + mp4_u32 metaDataSize = 0;
1.253 + trakSize *audioTrackSize;
1.254 + trakSize *videoTrackSize;
1.255 + mp4_bool haveAudio = MP4FALSE;
1.256 + mp4_bool haveVideo = MP4FALSE;
1.257 + mp4_u8 ftypdelta = 0;
1.258 +
1.259 +
1.260 + if ((handle->type & MP4_TYPE_AMR_NB) ||
1.261 + (handle->type & MP4_TYPE_AMR_WB) ||
1.262 + (handle->type & MP4_TYPE_QCELP_13K) ||
1.263 + (handle->type & MP4_TYPE_MPEG4_AUDIO))
1.264 + haveAudio = MP4TRUE;
1.265 +
1.266 + if ((handle->type & MP4_TYPE_H263_PROFILE_0) ||
1.267 + (handle->type & MP4_TYPE_H263_PROFILE_3) ||
1.268 + (handle->type & MP4_TYPE_MPEG4_VIDEO) ||
1.269 + containsAvcVideo( handle->type ) )
1.270 + haveVideo = MP4TRUE;
1.271 +
1.272 + if ((handle->generate3G2 && !(handle->type & MP4_TYPE_QCELP_13K)) ||
1.273 + (!handle->generate3G2 && !(handle->type & MP4_TYPE_AMR_WB)))
1.274 + ftypdelta = 4; /* one more additional compatible brand */
1.275 + else
1.276 + ftypdelta = 0;
1.277 +
1.278 + if( containsAvcVideo( handle->type ) )
1.279 + {
1.280 + ftypdelta += 4;
1.281 + }
1.282 +
1.283 + PRINT((_L("e_writedatatofile_alloc_audiotrk 1")));
1.284 + audioTrackSize = (trakSize *)mp4malloc(sizeof(trakSize));
1.285 + if (audioTrackSize == NULL)
1.286 + return -1;
1.287 + PRINT((_L("e_writedatatofile_alloc_audiotrk 0")));
1.288 +
1.289 + PRINT((_L("e_writedatatofile_alloc_videotrk 1")));
1.290 + videoTrackSize = (trakSize *)mp4malloc(sizeof(trakSize));
1.291 + if (videoTrackSize == NULL)
1.292 + {
1.293 + mp4free(audioTrackSize);
1.294 +
1.295 + return -1;
1.296 + }
1.297 + PRINT((_L("e_writedatatofile_alloc_videotrk 0")));
1.298 +
1.299 + if (haveAudio)
1.300 + {
1.301 + PRINT((_L("e_writedatatofile_deter_audiotrk_metadatasize 1")));
1.302 + if (determineAudioTrakMetaDataSize(handle, handle->audioSampleTable, audioTrackSize) < 0)
1.303 + {
1.304 + mp4free(audioTrackSize);
1.305 + mp4free(videoTrackSize);
1.306 + return -1;
1.307 + }
1.308 + PRINT((_L("e_writedatatofile_deter_audiotrk_metadatasize 0")));
1.309 + }
1.310 +
1.311 + if (haveVideo)
1.312 + {
1.313 + PRINT((_L("e_writedatatofile_deter_videotrk_metadatasize 1")));
1.314 + if (determineVideoTrakMetaDataSize(handle, handle->videoSampleTable, videoTrackSize) < 0)
1.315 + {
1.316 + mp4free(audioTrackSize);
1.317 + mp4free(videoTrackSize);
1.318 + return -1;
1.319 + }
1.320 +PRINT((_L("e_writedatatofile_deter_videotrk_metadatasize 0")));
1.321 + }
1.322 +
1.323 + if (handle->flags & MP4_FLAG_METADATALAST)
1.324 + {
1.325 + metaDataSize += (FTYP_SIZE + ftypdelta); /* ftyp */
1.326 + handle->metaDataSize = metaDataSize;
1.327 + }
1.328 + else
1.329 + {
1.330 + metaDataSize += (FTYP_SIZE + ftypdelta); /* ftyp */
1.331 + metaDataSize += 8; /* moov atomheader */
1.332 + metaDataSize += mvhdAtomSize(handle); /* mvhd */
1.333 + if (handle->moovUDTA)
1.334 + {
1.335 + metaDataSize += 8 + (mp4_u32)handle->moovUDTA->atomcontentsize;
1.336 + }
1.337 + metaDataSize += audioTrackSize->trak; /* Audio trak */
1.338 + metaDataSize += videoTrackSize->trak; /* Video trak */
1.339 +
1.340 + handle->metaDataSize = metaDataSize;
1.341 + }
1.342 +
1.343 +
1.344 + if (!(handle->flags & MP4_FLAG_LONGCLIP))
1.345 + {
1.346 + /* Update metadata pointers only if metadata is in memory */
1.347 +
1.348 + if (haveAudio)
1.349 + {
1.350 + PRINT((_L("e_writedatatofile_reupdata_audiometadata 1")));
1.351 + if (reUpdateAudioMetaData(handle->audioSampleTable, metaDataSize) < 0)
1.352 + {
1.353 + mp4free(audioTrackSize);
1.354 + mp4free(videoTrackSize);
1.355 +
1.356 + return -1;
1.357 + }
1.358 + PRINT((_L("e_writedatatofile_reupdata_audiometadata 0")));
1.359 + }
1.360 +
1.361 + if (haveVideo)
1.362 + {
1.363 + PRINT((_L("e_writedatatofile_reupdata_videometadata 1")));
1.364 + if (reUpdateVideoMetaData(handle->videoSampleTable, metaDataSize) < 0)
1.365 + {
1.366 + mp4free(audioTrackSize);
1.367 + mp4free(videoTrackSize);
1.368 +
1.369 + return -1;
1.370 + }
1.371 + PRINT((_L("e_writedatatofile_reupdata_videometadata 0")));
1.372 + }
1.373 + }
1.374 + else
1.375 + {
1.376 + /* Write the rest of metadata to temporary files */
1.377 + PRINT((_L("e_writedatatofile_write_metadatablocks 1")));
1.378 + if (handle->metaDataBlocks)
1.379 + if (writeMetaDataTmp(handle) < 0)
1.380 + {
1.381 + mp4free(audioTrackSize);
1.382 + mp4free(videoTrackSize);
1.383 + return -1;
1.384 + }
1.385 + PRINT((_L("e_writedatatofile_write_metadatablocks 0")));
1.386 + }
1.387 +
1.388 +
1.389 + if (handle->flags & MP4_FLAG_METADATALAST)
1.390 + {
1.391 + mp4_u8 buf[16];
1.392 + mp4_u32 moovSize = 0;
1.393 +
1.394 + moovSize += 8; /* moov atomheader */
1.395 + moovSize += mvhdAtomSize(handle); /* mvhd */
1.396 + moovSize += audioTrackSize->trak; /* Audio trak */
1.397 + moovSize += videoTrackSize->trak; /* Video trak */
1.398 + if (handle->moovUDTA)
1.399 + {
1.400 + moovSize += 8 + handle->moovUDTA->atomcontentsize;
1.401 + }
1.402 +
1.403 + PRINT((_L("e_writedatatofile_write_moov 1")));
1.404 + if (writeMOOV(handle, moovSize, haveAudio, haveVideo, audioTrackSize, videoTrackSize) < 0)
1.405 + {
1.406 + mp4free(audioTrackSize);
1.407 + mp4free(videoTrackSize);
1.408 +
1.409 + return -1;
1.410 + }
1.411 + PRINT((_L("e_writedatatofile_write_moov 0")));
1.412 +
1.413 + /* Overwrite media data size */
1.414 + PRINT((_L("e_writedatatofile_update_moov_media_size 1")));
1.415 + if(!handle->bufferWrite)
1.416 + {
1.417 + if (seekFileAbsWrite(handle, (FTYP_SIZE + ftypdelta)) != 0)
1.418 + {
1.419 + mp4free(audioTrackSize);
1.420 + mp4free(videoTrackSize);
1.421 + return -1;
1.422 + }
1.423 + }
1.424 +
1.425 + //make sure the buf is large enough to hold the mdat header
1.426 + TInt i;
1.427 + i = formatMdatHeader(buf, handle->mediaDataBytes);
1.428 + if (writeFileUnbuffered(handle, buf, i) < 0)
1.429 + {
1.430 + mp4free(audioTrackSize);
1.431 + mp4free(videoTrackSize);
1.432 + return -1;
1.433 + }
1.434 + PRINT((_L("e_writedatatofile_update_moov_media_size 0")));
1.435 + }
1.436 + else
1.437 + {
1.438 + PRINT((_L("e_writedatatofile_write_ftyp 1")));
1.439 + if (writeFTYP(handle) < 0)
1.440 + {
1.441 + mp4free(audioTrackSize);
1.442 + mp4free(videoTrackSize);
1.443 +
1.444 + return -1;
1.445 + }
1.446 + PRINT((_L("e_writedatatofile_write_ftyp 0")));
1.447 +
1.448 + PRINT((_L("e_writedatatofile_write_new_moov 1")));
1.449 + if (writeMOOV(handle, metaDataSize - (FTYP_SIZE + ftypdelta), haveAudio, haveVideo, audioTrackSize, videoTrackSize) < 0)
1.450 + {
1.451 + mp4free(audioTrackSize);
1.452 + mp4free(videoTrackSize);
1.453 +
1.454 + return -1;
1.455 + }
1.456 + PRINT((_L("e_writedatatofile_write_new_moov 0")));
1.457 +
1.458 + PRINT((_L("e_writedatatofile_write_new_mdia 1")));
1.459 + if (writeMediaData(handle) < 0)
1.460 + {
1.461 + mp4free(audioTrackSize);
1.462 + mp4free(videoTrackSize);
1.463 +
1.464 + return -1;
1.465 + }
1.466 + PRINT((_L("e_writedatatofile_write_new_mdia 0")));
1.467 + }
1.468 +
1.469 +PRINT((_L("e_writedatatofile_free_audioandvideotrks 1")));
1.470 + mp4free(audioTrackSize);
1.471 + mp4free(videoTrackSize);
1.472 +PRINT((_L("e_writedatatofile_free_audioandvideotrks 0")));
1.473 +PRINT((_L("e_writedatatofile 0")));
1.474 + return 0;
1.475 +}
1.476 +
1.477 +
1.478 +/*
1.479 + * Function:
1.480 + *
1.481 + * mp4_i32 updateDecodingTimeToSample(MP4HandleImp handle,
1.482 + * sampleTable *st,
1.483 + * mp4_u32 duration)
1.484 + *
1.485 + * Description:
1.486 + *
1.487 + * This function updates stts atom data.
1.488 + *
1.489 + * Parameters:
1.490 + *
1.491 + * handle MP4 library handle
1.492 + * st sampleTable
1.493 + * duration Duration of sample to insert (in media timescale)
1.494 + *
1.495 + * Return value:
1.496 + *
1.497 + * 0 Success
1.498 + * -1 Error
1.499 + *
1.500 + */
1.501 +mp4_i32 updateDecodingTimeToSample(MP4HandleImp handle, sampleTable *st, mp4_u32 duration)
1.502 +{
1.503 + if (!handle)
1.504 + return -1;
1.505 +
1.506 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.507 + {
1.508 + if (st->sttsCurrentEntryCount == 0)
1.509 + {
1.510 + st->sttsSampleCount[st->sttsCurrentEntryCount] = 1;
1.511 + st->sttsSampleDelta[st->sttsCurrentEntryCount] = duration;
1.512 +
1.513 + st->sttsCurrentEntryCount++;
1.514 + st->sttsEntryCount++;
1.515 +
1.516 + return 0;
1.517 + }
1.518 +
1.519 + if (st->sttsCurrentEntryCount == st->sttsMaxEntryCount)
1.520 + {
1.521 + void *p;
1.522 +
1.523 + p = mp4realloc(st->sttsSampleCount,
1.524 + 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount,
1.525 + sizeof(mp4_u32) * st->sttsMaxEntryCount);
1.526 + if (p == NULL)
1.527 + return -1;
1.528 +
1.529 + st->sttsSampleCount = (mp4_u32 *)p;
1.530 +
1.531 + p = mp4realloc(st->sttsSampleDelta,
1.532 + 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount,
1.533 + sizeof(mp4_u32) * st->sttsMaxEntryCount);
1.534 + if (p == NULL)
1.535 + return -1;
1.536 +
1.537 + st->sttsSampleDelta = (mp4_u32 *)p;
1.538 +
1.539 + st->sttsMaxEntryCount *= 2;
1.540 + }
1.541 +
1.542 + if (st->sttsSampleDelta[st->sttsCurrentEntryCount - 1] == duration)
1.543 + {
1.544 + st->sttsSampleCount[st->sttsCurrentEntryCount - 1]++;
1.545 + }
1.546 + else
1.547 + {
1.548 + st->sttsSampleCount[st->sttsCurrentEntryCount] = 1;
1.549 + st->sttsSampleDelta[st->sttsCurrentEntryCount] = duration;
1.550 +
1.551 + st->sttsCurrentEntryCount++;
1.552 + st->sttsEntryCount++;
1.553 + }
1.554 + }
1.555 + else
1.556 + {
1.557 + if (st->sttsEntryCount == 0)
1.558 + {
1.559 + st->sttsSampleCount[st->sttsEntryCount]++;
1.560 + st->sttsSampleDelta[st->sttsEntryCount] = duration;
1.561 +
1.562 + st->sttsEntryCount++;
1.563 +
1.564 + return 0;
1.565 + }
1.566 +
1.567 + if (st->sttsEntryCount == st->sttsMaxEntryCount)
1.568 + {
1.569 + void *p;
1.570 +
1.571 + p = mp4realloc(st->sttsSampleCount,
1.572 + 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount,
1.573 + sizeof(mp4_u32) * st->sttsMaxEntryCount);
1.574 + if (p == NULL)
1.575 + return -1;
1.576 +
1.577 + st->sttsSampleCount = (mp4_u32 *)p;
1.578 +
1.579 + p = mp4realloc(st->sttsSampleDelta,
1.580 + 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount,
1.581 + sizeof(mp4_u32) * st->sttsMaxEntryCount);
1.582 + if (p == NULL)
1.583 + return -1;
1.584 +
1.585 + st->sttsSampleDelta = (mp4_u32 *)p;
1.586 +
1.587 + st->sttsMaxEntryCount *= 2;
1.588 + }
1.589 +
1.590 + if (st->sttsSampleDelta[st->sttsEntryCount - 1] == duration)
1.591 + {
1.592 + st->sttsSampleCount[st->sttsEntryCount - 1]++;
1.593 + }
1.594 + else
1.595 + {
1.596 + st->sttsSampleCount[st->sttsEntryCount] = 1;
1.597 + st->sttsSampleDelta[st->sttsEntryCount] = duration;
1.598 +
1.599 + st->sttsEntryCount++;
1.600 + }
1.601 + }
1.602 +
1.603 +
1.604 + return 0;
1.605 +}
1.606 +
1.607 +
1.608 +/*
1.609 + * Function:
1.610 + *
1.611 + * mp4_i32 updateSampleSize(MP4HandleImp handle,
1.612 + * sampleTable *st,
1.613 + * mp4_u32 size)
1.614 + *
1.615 + * Description:
1.616 + *
1.617 + * This function updates stsz atom data.
1.618 + *
1.619 + * Parameters:
1.620 + *
1.621 + * handle MP4 library handle
1.622 + * st sampleTable
1.623 + * size Size of sample in bytes
1.624 + *
1.625 + * Return value:
1.626 + *
1.627 + * 0 Success
1.628 + * -1 Error
1.629 + *
1.630 + */
1.631 +mp4_i32 updateSampleSize(MP4HandleImp handle, sampleTable *st, mp4_u32 size)
1.632 +{
1.633 + if (!handle)
1.634 + return -1;
1.635 +
1.636 + if (size == 0)
1.637 + return -1;
1.638 +
1.639 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.640 + {
1.641 + if (st->stszCurrentSampleCount == st->stszMaxSampleCount)
1.642 + {
1.643 + void *p;
1.644 +
1.645 + p = mp4realloc(st->stszEntrySize,
1.646 + 2 * sizeof(mp4_u32) * st->stszMaxSampleCount,
1.647 + sizeof(mp4_u32) * st->stszMaxSampleCount);
1.648 + if (p == NULL)
1.649 + return -1;
1.650 +
1.651 + st->stszEntrySize = (mp4_u32 *)p;
1.652 +
1.653 + st->stszMaxSampleCount *= 2;
1.654 + }
1.655 +
1.656 + st->stszEntrySize[st->stszCurrentSampleCount] = size;
1.657 +
1.658 + st->stszCurrentSampleCount++;
1.659 + st->stszSampleCount++;
1.660 + }
1.661 + else
1.662 + {
1.663 + if (st->stszSampleCount == st->stszMaxSampleCount)
1.664 + {
1.665 + void *p;
1.666 +
1.667 + p = mp4realloc(st->stszEntrySize,
1.668 + 2 * sizeof(mp4_u32) * st->stszMaxSampleCount,
1.669 + sizeof(mp4_u32) * st->stszMaxSampleCount);
1.670 + if (p == NULL)
1.671 + return -1;
1.672 +
1.673 + st->stszEntrySize = (mp4_u32 *)p;
1.674 +
1.675 + st->stszMaxSampleCount *= 2;
1.676 + }
1.677 +
1.678 + st->stszEntrySize[st->stszSampleCount] = size;
1.679 +
1.680 + st->stszSampleCount++;
1.681 + }
1.682 +
1.683 +
1.684 + return 0;
1.685 +}
1.686 +
1.687 +
1.688 +/*
1.689 + * Function:
1.690 + *
1.691 + * mp4_i32 updateSampleToChunk(sampleTable *st)
1.692 + *
1.693 + * Description:
1.694 + *
1.695 + * This function updates stsc atom data.
1.696 + *
1.697 + * Parameters:
1.698 + *
1.699 + * st sampleTable
1.700 + *
1.701 + * Return value:
1.702 + *
1.703 + * 0 Success
1.704 + * -1 Error
1.705 + *
1.706 + */
1.707 +mp4_i32 updateSampleToChunk(sampleTable *st)
1.708 +{
1.709 + if (st->stscEntryCount != 0)
1.710 + return 0;
1.711 +
1.712 +
1.713 + st->stscFirstChunk[st->stscEntryCount] = st->currentChunk;
1.714 + st->stscSamplesPerChunk[st->stscEntryCount] = 1;
1.715 + st->stscSampleDescriptionIndex[st->stscEntryCount] = 1; /* Note: Need to update here for multiple sample entry support */
1.716 + st->stscEntryCount++;
1.717 +
1.718 + return 0;
1.719 +}
1.720 +
1.721 +
1.722 +/*
1.723 + * Function:
1.724 + *
1.725 + * mp4_i32 updateChunkOffset(MP4HandleImp handle,
1.726 + * sampleTable *st)
1.727 + *
1.728 + * Description:
1.729 + *
1.730 + * This function updates stco atom data.
1.731 + *
1.732 + * Parameters:
1.733 + *
1.734 + * handle MP4 library handle
1.735 + * st sampleTable
1.736 + *
1.737 + * Return value:
1.738 + *
1.739 + * 0 Success
1.740 + * -1 Error
1.741 + *
1.742 + */
1.743 +mp4_i32 updateChunkOffset(MP4HandleImp handle, sampleTable *st)
1.744 +{
1.745 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.746 + {
1.747 + if (st->stcoCurrentEntryCount == st->stcoMaxEntryCount)
1.748 + {
1.749 + void *p;
1.750 +
1.751 + p = mp4realloc(st->stcoChunkOffset,
1.752 + 2 * sizeof(mp4_u64) * st->stcoMaxEntryCount,
1.753 + sizeof(mp4_u64) * st->stcoMaxEntryCount);
1.754 + if (p == NULL)
1.755 + return -1;
1.756 +
1.757 + st->stcoChunkOffset = (mp4_u64*)p;
1.758 +
1.759 + st->stcoMaxEntryCount *= 2;
1.760 + }
1.761 +
1.762 + if (handle->flags & MP4_FLAG_METADATALAST)
1.763 + updateChunkOffset(st, st->stcoCurrentEntryCount, handle->mediaDataBytes);
1.764 + else
1.765 + updateChunkOffset(st, st->stcoCurrentEntryCount, handle->bytesInTmpFile);
1.766 +
1.767 + st->stcoCurrentEntryCount++;
1.768 + st->stcoEntryCount++;
1.769 + }
1.770 + else
1.771 + {
1.772 + if (st->stcoEntryCount == st->stcoMaxEntryCount)
1.773 + {
1.774 + void *p;
1.775 +
1.776 + p = mp4realloc(st->stcoChunkOffset,
1.777 + 2 * sizeof(mp4_u64) * st->stcoMaxEntryCount,
1.778 + sizeof(mp4_u64) * st->stcoMaxEntryCount);
1.779 + if (p == NULL)
1.780 + return -1;
1.781 +
1.782 + st->stcoChunkOffset = (mp4_u64 *)p;
1.783 +
1.784 + st->stcoMaxEntryCount *= 2;
1.785 + }
1.786 +
1.787 + if (handle->flags & MP4_FLAG_METADATALAST)
1.788 + updateChunkOffset(st, st->stcoEntryCount, handle->mediaDataBytes);
1.789 + else
1.790 + updateChunkOffset(st, st->stcoEntryCount, handle->bytesInTmpFile);
1.791 +
1.792 + st->stcoEntryCount++;
1.793 + }
1.794 +
1.795 +
1.796 + return 0;
1.797 +}
1.798 +
1.799 +
1.800 +/*
1.801 + * Function:
1.802 + *
1.803 + * mp4_i32 updateSyncSample(MP4HandleImp handle,
1.804 + * sampleTable *st)
1.805 + *
1.806 + * Description:
1.807 + *
1.808 + * This function updates stss atom data.
1.809 + *
1.810 + * Parameters:
1.811 + *
1.812 + * handle MP4 library handle
1.813 + * st sampleTable
1.814 + *
1.815 + * Return value:
1.816 + *
1.817 + * 0 Success
1.818 + * -1 Error
1.819 + *
1.820 + */
1.821 +mp4_i32 updateSyncSample(MP4HandleImp handle, sampleTable *st)
1.822 +{
1.823 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.824 + {
1.825 + if (st->stssCurrentEntryCount == st->stssMaxEntryCount)
1.826 + {
1.827 + void *p;
1.828 +
1.829 + p = mp4realloc(st->stssSampleNumber,
1.830 + 2 * sizeof(mp4_u32) * st->stssMaxEntryCount,
1.831 + sizeof(mp4_u32) * st->stssMaxEntryCount);
1.832 + if (p == NULL)
1.833 + return -1;
1.834 +
1.835 + st->stssSampleNumber = (mp4_u32 *)p;
1.836 +
1.837 + st->stssMaxEntryCount *= 2;
1.838 + }
1.839 +
1.840 + st->stssSampleNumber[st->stssCurrentEntryCount] = handle->videoSampleNum;
1.841 + st->stssCurrentEntryCount++;
1.842 + st->stssEntryCount++;
1.843 + }
1.844 + else
1.845 + {
1.846 + if (st->stssEntryCount == st->stssMaxEntryCount)
1.847 + {
1.848 + void *p;
1.849 +
1.850 + p = mp4realloc(st->stssSampleNumber,
1.851 + 2 * sizeof(mp4_u32) * st->stssMaxEntryCount,
1.852 + sizeof(mp4_u32) * st->stssMaxEntryCount);
1.853 + if (p == NULL)
1.854 + return -1;
1.855 +
1.856 + st->stssSampleNumber = (mp4_u32 *)p;
1.857 +
1.858 + st->stssMaxEntryCount *= 2;
1.859 + }
1.860 +
1.861 + st->stssSampleNumber[st->stssEntryCount] = handle->videoSampleNum;
1.862 + st->stssEntryCount++;
1.863 + }
1.864 +
1.865 +
1.866 + return 0;
1.867 +}
1.868 +
1.869 +
1.870 +/*
1.871 + * Function:
1.872 + *
1.873 + * mp4_i32 determineAudioTrakMetaDataSize(MP4HandleImp handle,
1.874 + * sampleTable *st,
1.875 + * trakSize *ts)
1.876 + *
1.877 + * Description:
1.878 + *
1.879 + * This function calculates the audio track meta data size.
1.880 + *
1.881 + * Parameters:
1.882 + *
1.883 + * handle MP4 library handle
1.884 + * st Sample table data
1.885 + * ts Atom sizes are returned here
1.886 + *
1.887 + * Return value:
1.888 + *
1.889 + * 0 Success
1.890 + *
1.891 + */
1.892 +mp4_i32 determineAudioTrakMetaDataSize(MP4HandleImp handle, sampleTable *st, trakSize *ts)
1.893 +{
1.894 + if (handle->type & MP4_TYPE_AMR_NB) /* AMR-NB */
1.895 + {
1.896 + ts->damr = 17;
1.897 + ts->samr = 36 + ts->damr;
1.898 + ts->stsd = 16 + ts->samr;
1.899 + }
1.900 + else if (handle->type & MP4_TYPE_AMR_WB) /* AMR-WB */
1.901 + {
1.902 + ts->damr = 17;
1.903 + ts->sawb = 36 + ts->damr;
1.904 + ts->stsd = 16 + ts->sawb;
1.905 + }
1.906 + else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) /* QCELP 13K stored in QCELPSampleEntry */
1.907 + {
1.908 + ts->dqcp = 14;
1.909 + ts->sqcp = 36 + ts->dqcp;
1.910 + ts->stsd = 16 + ts->sqcp;
1.911 + }
1.912 + else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) /* QCELP 13K stored in MP4AudioDescription */
1.913 + {
1.914 + calculateES_DescriptorSize(handle, MP4_TYPE_QCELP_13K);
1.915 + ts->esds = 12 + handle->ES_DescriptorSize; /*37 + handle->audioDecSpecificInfoSize;*/
1.916 + ts->mp4a = 36 + ts->esds;
1.917 + ts->stsd = 16 + ts->mp4a;
1.918 + }
1.919 + else /* MPEG audio */
1.920 + {
1.921 + calculateES_DescriptorSize(handle, MP4_TYPE_MPEG4_AUDIO);
1.922 + ts->esds = 12 + handle->ES_DescriptorSize; /*37 + handle->audioDecSpecificInfoSize;*/
1.923 + ts->mp4a = 36 + ts->esds;
1.924 + ts->stsd = 16 + ts->mp4a;
1.925 + }
1.926 + ts->stts = 16 + st->sttsEntryCount * 8;
1.927 + ts->stsc = 16 + st->stscEntryCount * 12;
1.928 + if (st->stszSampleSize != 0)
1.929 + ts->stsz = 20;
1.930 + else
1.931 + ts->stsz = 20 + st->stszSampleCount * 4;
1.932 + ts->stco = 16 + st->stcoEntryCount * (st->stcoNeed64Bits ? 8 : 4);
1.933 + ts->stbl = 8 + ts->stsd + ts->stts + ts->stsc + ts->stsz + ts->stco;
1.934 + ts->dref = 28;
1.935 + ts->dinf = 8 + ts->dref;
1.936 + ts->smhd = 16;
1.937 + ts->minf = 8 + ts->smhd + ts->dinf + ts->stbl;
1.938 + ts->hdlr = 33;
1.939 +
1.940 + if (handle->audioDuration > MP4_INT_MAX)
1.941 + {
1.942 + ts->mdhd = 44;
1.943 + ts->tkhd = 104;
1.944 + }
1.945 + else
1.946 + {
1.947 + ts->mdhd = 32;
1.948 + ts->tkhd = 92;
1.949 + }
1.950 +
1.951 + ts->mdia = 8 + ts->mdhd + ts->hdlr + ts->minf;
1.952 + if ( handle->audioUDTA )
1.953 + {
1.954 + ts->udta = 8 + handle->audioUDTA->atomcontentsize;
1.955 + }
1.956 + ts->trak = 8 + ts->tkhd + ts->mdia + ts->udta;
1.957 +
1.958 + return 0;
1.959 +}
1.960 +
1.961 +
1.962 +/*
1.963 + * Function:
1.964 + *
1.965 + * mp4_i32 determineVideoTrakMetaDataSize(MP4HandleImp handle,
1.966 + * sampleTable *st,
1.967 + * trakSize *ts)
1.968 + *
1.969 + * Description:
1.970 + *
1.971 + * This function calculates the video track meta data size.
1.972 + *
1.973 + * Parameters:
1.974 + *
1.975 + * handle MP4 library handle
1.976 + * st Sample table data
1.977 + * ts Atom sizes are returned here
1.978 + *
1.979 + * Return value:
1.980 + *
1.981 + * 0 Success
1.982 + *
1.983 + */
1.984 +mp4_i32 determineVideoTrakMetaDataSize(MP4HandleImp handle, sampleTable *st, trakSize *ts)
1.985 +{
1.986 + /* Note: This functions assumes single sample entry per media track.
1.987 + If necessary, modify to support multiple sample entries in the future. */
1.988 + if ((handle->type & MP4_TYPE_H263_PROFILE_0) || (handle->type & MP4_TYPE_H263_PROFILE_3))
1.989 + {
1.990 + ts->d263 = 15;
1.991 + ts->s263 = 86 + ts->d263;
1.992 + ts->stsd = 16 + ts->s263;
1.993 + }
1.994 + else /* MPEG-4 */
1.995 + if ((handle->type & MP4_TYPE_MPEG4_VIDEO))
1.996 + {
1.997 + ts->esds = 37 + handle->videoDecSpecificInfoSize;
1.998 + ts->mp4v = 86 + ts->esds;
1.999 + ts->stsd = 16 + ts->mp4v;
1.1000 + }
1.1001 + else /* AVC */
1.1002 + if ( containsAvcVideo( handle->type ) )
1.1003 + {
1.1004 + /* Note: If necessary, add btrt and m4ds boxes here in the future. */
1.1005 + ts->avcc = 8 + handle->videoDecSpecificInfoSize; /*handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize;*/
1.1006 + ts->avc1 = 86 + ts->avcc;
1.1007 + ts->stsd = 16 + ts->avc1;
1.1008 + }
1.1009 + else
1.1010 + {
1.1011 + }
1.1012 +
1.1013 + ts->stts = 16 + st->sttsEntryCount * 8;
1.1014 + ts->stsc = 16 + st->stscEntryCount * 12;
1.1015 + if (st->stszSampleSize != 0)
1.1016 + ts->stsz = 20;
1.1017 + else
1.1018 + ts->stsz = 20 + st->stszSampleCount * 4;
1.1019 + ts->stco = 16 + st->stcoEntryCount * (st->stcoNeed64Bits ? 8 : 4);
1.1020 + ts->stss = 16 + st->stssEntryCount * 4;
1.1021 + if( handle->videoSampleTable->sdtpEntryCount )
1.1022 + ts->sdtp = 4 + 4 + 1 + 3 + handle->videoSampleTable->sdtpEntryCount; //size + 'SDTP' + ver + flags + dependencies
1.1023 + else
1.1024 + ts->sdtp = 0;
1.1025 +
1.1026 + ts->stbl = 8 + ts->stsd + ts->stts + ts->stsc + ts->stsz + ts->stco + ts->stss + ts->sdtp;
1.1027 + ts->dref = 28;
1.1028 + ts->dinf = 8 + ts->dref;
1.1029 + ts->vmhd = 20;
1.1030 + ts->minf = 8 + ts->vmhd + ts->dinf + ts->stbl;
1.1031 + ts->hdlr = 33;
1.1032 +
1.1033 + if (handle->videoDuration > MP4_INT_MAX)
1.1034 + {
1.1035 + ts->mdhd = 44;
1.1036 + ts->tkhd = 104;
1.1037 + }
1.1038 + else
1.1039 + {
1.1040 + ts->mdhd = 32;
1.1041 + ts->tkhd = 92;
1.1042 + }
1.1043 +
1.1044 + ts->mdia = 8 + ts->mdhd + ts->hdlr + ts->minf;
1.1045 + if ( handle->videoUDTA )
1.1046 + {
1.1047 + ts->udta = 8 + handle->videoUDTA->atomcontentsize;
1.1048 + }
1.1049 + ts->trak = 8 + ts->tkhd + ts->mdia + ts->udta;
1.1050 +
1.1051 + return 0;
1.1052 +}
1.1053 +
1.1054 +
1.1055 +/*
1.1056 + * Function:
1.1057 + *
1.1058 + * mp4_i32 reUpdateAudioMetaData(sampleTable *st,
1.1059 + * mp4_u32 metaDataSize)
1.1060 + *
1.1061 + * Description:
1.1062 + *
1.1063 + * This function updates the chunk offsets in the meta data to point to
1.1064 + * correct places.
1.1065 + *
1.1066 + * Parameters:
1.1067 + *
1.1068 + * st Sample table data
1.1069 + * metaDataSize Meta data size
1.1070 + *
1.1071 + * Return value:
1.1072 + *
1.1073 + * 0 Success
1.1074 + *
1.1075 + */
1.1076 +mp4_i32 reUpdateAudioMetaData(sampleTable *st, mp4_u32 metaDataSize)
1.1077 +{
1.1078 + mp4_u32 i;
1.1079 +
1.1080 +
1.1081 + for (i = 0; i < st->stcoEntryCount; i++)
1.1082 + updateChunkOffset(st, i, st->stcoChunkOffset[i] + metaDataSize + MDAT_HEADER_SIZE);
1.1083 +
1.1084 + return 0;
1.1085 +}
1.1086 +
1.1087 +
1.1088 +/*
1.1089 + * Function:
1.1090 + *
1.1091 + * mp4_i32 reUpdateVideoMetaData(sampleTable *st,
1.1092 + * mp4_u32 metaDataSize)
1.1093 + *
1.1094 + * Description:
1.1095 + *
1.1096 + * This function updates the chunk offsets in the meta data to point to
1.1097 + * correct places.
1.1098 + *
1.1099 + * Parameters:
1.1100 + *
1.1101 + * st Sample table data
1.1102 + * metaDataSize Meta data size
1.1103 + *
1.1104 + * Return value:
1.1105 + *
1.1106 + * 0 Success
1.1107 + *
1.1108 + */
1.1109 +mp4_i32 reUpdateVideoMetaData(sampleTable *st, mp4_u32 metaDataSize)
1.1110 +{
1.1111 + mp4_u32 i;
1.1112 +
1.1113 +
1.1114 + for (i = 0; i < st->stcoEntryCount; i++)
1.1115 + updateChunkOffset(st, i, st->stcoChunkOffset[i] + metaDataSize + MDAT_HEADER_SIZE);
1.1116 +
1.1117 + return 0;
1.1118 +}
1.1119 +
1.1120 +
1.1121 +/*
1.1122 + * Function:
1.1123 + *
1.1124 + * mp4_i32 writeFTYP(MP4HandleImp handle)
1.1125 + *
1.1126 + * Description:
1.1127 + *
1.1128 + * Write FTYP atom.
1.1129 + *
1.1130 + * Parameters:
1.1131 + *
1.1132 + * handle MP4 library handle
1.1133 + *
1.1134 + * Return value:
1.1135 + *
1.1136 + * 0 Success
1.1137 + * -1 Error
1.1138 + *
1.1139 + */
1.1140 +mp4_i32 writeFTYP(MP4HandleImp handle)
1.1141 +{
1.1142 + mp4_u8 *buf;
1.1143 + mp4_u32 i = 0;
1.1144 + mp4_u8 ftypdelta = 0;
1.1145 +
1.1146 + if ((handle->generate3G2 && !(handle->type & MP4_TYPE_QCELP_13K)) ||
1.1147 + (!handle->generate3G2 && !(handle->type & MP4_TYPE_AMR_WB)))
1.1148 + ftypdelta = 4; /* one more additional compatible brand */
1.1149 + else
1.1150 + ftypdelta = 0;
1.1151 +
1.1152 + if( containsAvcVideo( handle->type ) )
1.1153 + {
1.1154 + ftypdelta += 4;
1.1155 + }
1.1156 + if(handle->bufferWrite)
1.1157 + handle->ftypdelta=ftypdelta;
1.1158 +
1.1159 + buf = (mp4_u8 *)mp4malloc(FTYP_SIZE + ftypdelta);
1.1160 + if (buf == NULL)
1.1161 + return -1;
1.1162 +
1.1163 + /* Size */
1.1164 + insertu32(buf+i, (mp4_u32)(FTYP_SIZE + ftypdelta));
1.1165 + i += 4;
1.1166 +
1.1167 + /* Atom type */
1.1168 + insertu32(buf+i, (mp4_u32)ATOMTYPE_FTYP);
1.1169 + i += 4;
1.1170 +
1.1171 + if ( containsAvcVideo( handle->type ) )
1.1172 + {
1.1173 + if(handle->generateMP4)
1.1174 + {
1.1175 + /* MPEG-4 Major brand */
1.1176 + buf[i++] = 'm';
1.1177 + buf[i++] = 'p';
1.1178 + buf[i++] = '4';
1.1179 + buf[i++] = '2';
1.1180 + }
1.1181 +
1.1182 + else
1.1183 + {
1.1184 + /* AVC is included for 3GPP Release 6 and beyond */
1.1185 + /* Major brand */
1.1186 + buf[i++] = '3';
1.1187 + buf[i++] = 'g';
1.1188 + buf[i++] = 'p';
1.1189 + buf[i++] = '6';
1.1190 + }
1.1191 + }
1.1192 + else
1.1193 + {
1.1194 + if(handle->generateMP4)
1.1195 + {
1.1196 + /* MPEG-4 Major brand */
1.1197 + buf[i++] = 'm';
1.1198 + buf[i++] = 'p';
1.1199 + buf[i++] = '4';
1.1200 + buf[i++] = '2';
1.1201 + }
1.1202 + else if(handle->generate3G2)
1.1203 + {
1.1204 + /* 3GPP2 Major brand */
1.1205 + buf[i++] = '3';
1.1206 + buf[i++] = 'g';
1.1207 + buf[i++] = '2';
1.1208 + buf[i++] = 'a';
1.1209 + }
1.1210 + else
1.1211 + {
1.1212 + /* 3GPP Major brand */
1.1213 + buf[i++] = '3';
1.1214 + buf[i++] = 'g';
1.1215 + buf[i++] = 'p';
1.1216 + buf[i++] = '4';
1.1217 + }
1.1218 + }
1.1219 +
1.1220 + /* Minor version */
1.1221 + if(handle->generateMP4)
1.1222 + { /* MPEG-4 Minor Version */
1.1223 + insertu32(buf+i, (mp4_u32)(0)); /* 0 */
1.1224 + i += 4;
1.1225 + }
1.1226 + else if(handle->generate3G2)
1.1227 + { /* 3GPP2 Minor Version */
1.1228 + if( containsAvcVideo( handle->type ) )
1.1229 + {
1.1230 + insertu32(buf+i, (mp4_u32)(2*256*256)); /* VB.0.0 */
1.1231 + i += 4;
1.1232 + }
1.1233 + else
1.1234 + {
1.1235 + insertu32(buf+i, (mp4_u32)(1*256*256)); /* VA.0.0 */
1.1236 + i += 4;
1.1237 + }
1.1238 + }
1.1239 + else
1.1240 + { /* 3GPP Minor Version */
1.1241 + if( containsAvcVideo( handle->type ) )
1.1242 + {
1.1243 + insertu32(buf+i, (mp4_u32)2*256); /* V6.3.0 */
1.1244 + i += 4;
1.1245 + }
1.1246 + else
1.1247 + {
1.1248 + insertu32(buf+i, (mp4_u32)4*256); /* V4.4.0 */
1.1249 + i += 4;
1.1250 + }
1.1251 + }
1.1252 +
1.1253 + /* Compatible brands */
1.1254 + if(handle->generateMP4)
1.1255 + {/* MPEG-4 Compatible Brands */
1.1256 + buf[i++] = 'm';
1.1257 + buf[i++] = 'p';
1.1258 + buf[i++] = '4';
1.1259 + buf[i++] = '2';
1.1260 +
1.1261 + buf[i++] = '3';
1.1262 + buf[i++] = 'g';
1.1263 + buf[i++] = 'p';
1.1264 + buf[i++] = '4';
1.1265 +
1.1266 + buf[i++] = 'i';
1.1267 + buf[i++] = 's';
1.1268 + buf[i++] = 'o';
1.1269 + buf[i++] = 'm';
1.1270 + if ( containsAvcVideo( handle->type ) )
1.1271 + {
1.1272 + /* AVC is included for 3GPP Release 6 and beyond */
1.1273 + buf[i++] = 'a';
1.1274 + buf[i++] = 'v';
1.1275 + buf[i++] = 'c';
1.1276 + buf[i++] = '1';
1.1277 + }
1.1278 + }
1.1279 + else if(handle->generate3G2)
1.1280 + {/* 3GPP2 Compatible Brands */
1.1281 + if( containsAvcVideo( handle->type ) )
1.1282 + {
1.1283 + buf[i++] = '3';
1.1284 + buf[i++] = 'g';
1.1285 + buf[i++] = '2';
1.1286 + buf[i++] = 'b';
1.1287 + if (!(handle->type & MP4_TYPE_QCELP_13K))
1.1288 + { // If 3GPP codecs are used, then put 3GP6 in compatible brands
1.1289 + buf[i++] = '3';
1.1290 + buf[i++] = 'g';
1.1291 + buf[i++] = 'p';
1.1292 + buf[i++] = '6';
1.1293 + }
1.1294 + }
1.1295 + else
1.1296 + {
1.1297 + buf[i++] = '3';
1.1298 + buf[i++] = 'g';
1.1299 + buf[i++] = '2';
1.1300 + buf[i++] = 'a';
1.1301 + if (!(handle->type & MP4_TYPE_QCELP_13K))
1.1302 + { // If 3GPP codecs are used, then put 3GP4 in compatible brands
1.1303 + buf[i++] = '3';
1.1304 + buf[i++] = 'g';
1.1305 + buf[i++] = 'p';
1.1306 + buf[i++] = '4';
1.1307 + }
1.1308 + }
1.1309 + if ( containsAvcVideo( handle->type ) )
1.1310 + {
1.1311 + /* AVC is included for 3GPP Release 6 and beyond */
1.1312 + buf[i++] = 'a';
1.1313 + buf[i++] = 'v';
1.1314 + buf[i++] = 'c';
1.1315 + buf[i++] = '1';
1.1316 + }
1.1317 +
1.1318 + buf[i++] = 'i';
1.1319 + buf[i++] = 's';
1.1320 + buf[i++] = 'o';
1.1321 + buf[i++] = 'm';
1.1322 + }
1.1323 + else
1.1324 + {/* 3GPP Compatible Brands */
1.1325 + if ( containsAvcVideo( handle->type ) )
1.1326 + {
1.1327 + buf[i++] = '3';
1.1328 + buf[i++] = 'g';
1.1329 + buf[i++] = 'p';
1.1330 + buf[i++] = '6';
1.1331 + }
1.1332 + else
1.1333 + {
1.1334 + buf[i++] = '3';
1.1335 + buf[i++] = 'g';
1.1336 + buf[i++] = 'p';
1.1337 + buf[i++] = '4';
1.1338 + }
1.1339 +
1.1340 + if (!(handle->type & MP4_TYPE_AMR_WB))
1.1341 + { // If 3GPP2 codecs are used, then put 3G2A in compatible brands
1.1342 + buf[i++] = '3';
1.1343 + buf[i++] = 'g';
1.1344 + buf[i++] = '2';
1.1345 + buf[i++] = 'a';
1.1346 + }
1.1347 +
1.1348 + buf[i++] = 'i';
1.1349 + buf[i++] = 's';
1.1350 + buf[i++] = 'o';
1.1351 + buf[i++] = 'm';
1.1352 +
1.1353 + if ( containsAvcVideo( handle->type ) )
1.1354 + {
1.1355 + /* AVC is included for 3GPP Release 6 and beyond */
1.1356 + buf[i++] = 'a';
1.1357 + buf[i++] = 'v';
1.1358 + buf[i++] = 'c';
1.1359 + buf[i++] = '1';
1.1360 + }
1.1361 +
1.1362 + }
1.1363 + if (writeFile(handle, buf, (FTYP_SIZE + ftypdelta)) < 0)
1.1364 + {
1.1365 + mp4free(buf);
1.1366 +
1.1367 + return -1;
1.1368 + }
1.1369 +
1.1370 + mp4free(buf);
1.1371 +
1.1372 + return 0;
1.1373 +}
1.1374 +
1.1375 +
1.1376 +/*
1.1377 + * Function:
1.1378 + *
1.1379 + * mp4_i32 writeMOOV(MP4HandleImp handle,
1.1380 + * mp4_u32 moovSize,
1.1381 + * mp4_bool haveAudio,
1.1382 + * mp4_bool haveVideo,
1.1383 + * trakSize *audioTrackSize,
1.1384 + * trakSize *videoTrackSize)
1.1385 + *
1.1386 + * Description:
1.1387 + *
1.1388 + * Write MOOV atom.
1.1389 + *
1.1390 + * Parameters:
1.1391 + *
1.1392 + * handle MP4 library handle
1.1393 + * moovSize Size of MOOV atom in bytes
1.1394 + * haveAudio Flag to indicate whether audio exists or not
1.1395 + * haveVideo Flag to indicate whether video exists or not
1.1396 + * audioTrackSize Size of audio track in bytes
1.1397 + * videoTrackSize Size of video track in bytes
1.1398 + *
1.1399 + * Return value:
1.1400 + *
1.1401 + * 0 Success
1.1402 + * -1 Error
1.1403 + *
1.1404 + */
1.1405 +mp4_i32 writeMOOV(MP4HandleImp handle, mp4_u32 moovSize, mp4_bool haveAudio, mp4_bool haveVideo, trakSize *audioTrackSize, trakSize *videoTrackSize)
1.1406 +{
1.1407 + PRINT((_L("e_writemoov 1")));
1.1408 + mp4_u8 buf[8];
1.1409 + mp4_u32 i = 0;
1.1410 +
1.1411 +
1.1412 + /* Size */
1.1413 + insertu32(buf+i, moovSize);
1.1414 + i += 4;
1.1415 +
1.1416 + /* Atom type */
1.1417 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MOOV);
1.1418 + i += 4;
1.1419 +
1.1420 + PRINT((_L("e_writemoov_header 1")));
1.1421 + if (writeFile(handle, buf, 8) < 0)
1.1422 + return -1;
1.1423 + PRINT((_L("e_writemoov_header 0")));
1.1424 +
1.1425 + PRINT((_L("e_writemoov_mvhd 1")));
1.1426 + if (writeMVHD(handle) < 0)
1.1427 + return -1;
1.1428 + PRINT((_L("e_writemoov_mvhd 0")));
1.1429 +
1.1430 + PRINT((_L("e_writemoov_video 1")));
1.1431 + if (haveVideo)
1.1432 + if (writeVideoTrak(handle, videoTrackSize) < 0)
1.1433 + return -1;
1.1434 + PRINT((_L("e_writemoov_video 0")));
1.1435 +
1.1436 + PRINT((_L("e_writemoov_audio 1")));
1.1437 + if (haveAudio)
1.1438 + if (writeAudioTrak(handle, audioTrackSize) < 0)
1.1439 + return -1;
1.1440 + PRINT((_L("e_writemoov_audio 0")));
1.1441 +
1.1442 + PRINT((_L("e_writemoov_udta 1")));
1.1443 + if (handle->moovUDTA)
1.1444 + {
1.1445 + if (writeUDTA(handle, handle->moovUDTA) < 0)
1.1446 + {
1.1447 + return -1;
1.1448 + }
1.1449 + }
1.1450 + PRINT((_L("e_writemoov_udta 0")));
1.1451 + PRINT((_L("e_writemoov 0")));
1.1452 + return 0;
1.1453 +}
1.1454 +
1.1455 +
1.1456 +/*
1.1457 + * Function:
1.1458 + *
1.1459 + * mp4_i32 writeMVHD(MP4HandleImp handle)
1.1460 + *
1.1461 + * Description:
1.1462 + *
1.1463 + * Write MVHD atom.
1.1464 + *
1.1465 + * Parameters:
1.1466 + *
1.1467 + * handle MP4 library handle
1.1468 + *
1.1469 + * Return value:
1.1470 + *
1.1471 + * 0 Success
1.1472 + * -1 Error
1.1473 + *
1.1474 + */
1.1475 +mp4_i32 writeMVHD(MP4HandleImp handle)
1.1476 +{
1.1477 + mp4_u8 *buf;
1.1478 + mp4_u32 i = 0;
1.1479 + mp4_u32 u32;
1.1480 +
1.1481 + size_t mvhdSize = mvhdAtomSize(handle);
1.1482 +
1.1483 + buf = (mp4_u8 *)mp4malloc(mvhdSize);
1.1484 + if (buf == NULL)
1.1485 + return -1;
1.1486 +
1.1487 + /* Size */
1.1488 + insertu32(buf+i, (mp4_u32)mvhdSize);
1.1489 + i += 4;
1.1490 +
1.1491 + /* Atom type */
1.1492 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MVHD);
1.1493 + i += 4;
1.1494 +
1.1495 +
1.1496 + if (handle->videoDuration > MP4_INT_MAX || handle->audioDuration > MP4_INT_MAX)
1.1497 + {
1.1498 + /* Version and flags */
1.1499 + insertu32(buf+i, (mp4_u32)0x01000000); //its going to be a version 1 atom
1.1500 + i += 4;
1.1501 +
1.1502 + /* Creation time */
1.1503 + if (getCurrentTime(&u32) < 0)
1.1504 + u32 = 0;
1.1505 + insertu64(buf+i, (mp4_u64)u32);
1.1506 + i += 8;
1.1507 +
1.1508 + /* Modification time */
1.1509 + if (getCurrentTime(&u32) < 0)
1.1510 + u32 = 0;
1.1511 + insertu64(buf+i, (mp4_u64)u32);
1.1512 + i += 8;
1.1513 +
1.1514 + /* Timescale */
1.1515 + insertu32(buf+i, (mp4_u32)MVHD_TIMESCALE);
1.1516 + i += 4;
1.1517 +
1.1518 + /* Duration */
1.1519 + {
1.1520 + mp4_u64 u64;
1.1521 + mp4_u64 videoDuration = 0;
1.1522 + mp4_u64 audioDuration = 0;
1.1523 +
1.1524 +
1.1525 + if (handle->videoTimeScale)
1.1526 + videoDuration = (mp4_u64)((mp4_double)MVHD_TIMESCALE *
1.1527 + (mp4_double)handle->videoDuration /
1.1528 + (mp4_double)handle->videoTimeScale +
1.1529 + (mp4_double)0.5);
1.1530 + if (handle->audioTimeScale)
1.1531 + audioDuration = (mp4_u64)((mp4_double)MVHD_TIMESCALE *
1.1532 + (mp4_double)handle->audioDuration /
1.1533 + (mp4_double)handle->audioTimeScale +
1.1534 + (mp4_double)0.5);
1.1535 +
1.1536 + if (audioDuration > videoDuration)
1.1537 + u64 = audioDuration;
1.1538 + else
1.1539 + u64 = videoDuration;
1.1540 +
1.1541 + insertu64(buf+i, u64);
1.1542 + i += 8;
1.1543 + }
1.1544 +
1.1545 + }
1.1546 + else
1.1547 + {
1.1548 + /* Version and flags */
1.1549 + insertu32(buf+i, (mp4_u32)0);
1.1550 + i += 4;
1.1551 +
1.1552 + /* Creation time */
1.1553 + if (getCurrentTime(&u32) < 0)
1.1554 + u32 = 0;
1.1555 + insertu32(buf+i, (mp4_u32)u32);
1.1556 + i += 4;
1.1557 +
1.1558 + /* Modification time */
1.1559 + if (getCurrentTime(&u32) < 0)
1.1560 + u32 = 0;
1.1561 + insertu32(buf+i, (mp4_u32)u32);
1.1562 + i += 4;
1.1563 +
1.1564 + /* Timescale */
1.1565 + insertu32(buf+i, (mp4_u32)MVHD_TIMESCALE);
1.1566 + i += 4;
1.1567 +
1.1568 + /* Duration */
1.1569 + {
1.1570 + mp4_u32 videoDuration = 0;
1.1571 + mp4_u32 audioDuration = 0;
1.1572 +
1.1573 +
1.1574 + if (handle->videoTimeScale)
1.1575 + videoDuration = (mp4_u32)((mp4_double)MVHD_TIMESCALE *
1.1576 + (mp4_double)handle->videoDuration /
1.1577 + (mp4_double)handle->videoTimeScale +
1.1578 + (mp4_double)0.5);
1.1579 + if (handle->audioTimeScale)
1.1580 + audioDuration = (mp4_u32)((mp4_double)MVHD_TIMESCALE *
1.1581 + (mp4_double)handle->audioDuration /
1.1582 + (mp4_double)handle->audioTimeScale +
1.1583 + (mp4_double)0.5);
1.1584 +
1.1585 + if (audioDuration > videoDuration)
1.1586 + u32 = audioDuration;
1.1587 + else
1.1588 + u32 = videoDuration;
1.1589 +
1.1590 + insertu32(buf+i, u32);
1.1591 + i += 4;
1.1592 + }
1.1593 + }
1.1594 + /* Reserved */
1.1595 + insertu32(buf+i, (mp4_u32)0x00010000);
1.1596 + i += 4;
1.1597 +
1.1598 + insertu16(buf+i, (mp4_u16)0x0100);
1.1599 + i += 2;
1.1600 +
1.1601 + insertu16(buf+i, (mp4_u16)0x0000);
1.1602 + i += 2;
1.1603 +
1.1604 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1605 + i += 4;
1.1606 +
1.1607 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1608 + i += 4;
1.1609 +
1.1610 + insertu32(buf+i, (mp4_u32)0x00010000);
1.1611 + i += 4;
1.1612 +
1.1613 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1614 + i += 4;
1.1615 +
1.1616 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1617 + i += 4;
1.1618 +
1.1619 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1620 + i += 4;
1.1621 +
1.1622 + insertu32(buf+i, (mp4_u32)0x00010000);
1.1623 + i += 4;
1.1624 +
1.1625 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1626 + i += 4;
1.1627 +
1.1628 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1629 + i += 4;
1.1630 +
1.1631 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1632 + i += 4;
1.1633 +
1.1634 + insertu32(buf+i, (mp4_u32)0x40000000);
1.1635 + i += 4;
1.1636 +
1.1637 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1638 + i += 4;
1.1639 +
1.1640 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1641 + i += 4;
1.1642 +
1.1643 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1644 + i += 4;
1.1645 +
1.1646 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1647 + i += 4;
1.1648 +
1.1649 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1650 + i += 4;
1.1651 +
1.1652 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1653 + i += 4;
1.1654 +
1.1655 + insertu32(buf+i, (mp4_u32)0x00010000);
1.1656 + i += 4;
1.1657 +
1.1658 + if (writeFile(handle, buf, mvhdSize) < 0)
1.1659 + {
1.1660 + mp4free(buf);
1.1661 +
1.1662 + return -1;
1.1663 + }
1.1664 +
1.1665 + mp4free(buf);
1.1666 +
1.1667 + return 0;
1.1668 +}
1.1669 +
1.1670 +
1.1671 +/*
1.1672 + * Function:
1.1673 + *
1.1674 + * mp4_i32 writeVideoTrak(MP4HandleImp handle,
1.1675 + * trakSize *ts)
1.1676 + *
1.1677 + * Description:
1.1678 + *
1.1679 + * Write video track atom.
1.1680 + *
1.1681 + * Parameters:
1.1682 + *
1.1683 + * handle MP4 library handle
1.1684 + * ts Atom sizes
1.1685 + *
1.1686 + * Return value:
1.1687 + *
1.1688 + * 0 Success
1.1689 + * -1 Error
1.1690 + *
1.1691 + */
1.1692 +mp4_i32 writeVideoTrak(MP4HandleImp handle, trakSize *ts)
1.1693 +{
1.1694 + mp4_u8 buf[8];
1.1695 + mp4_u32 i = 0;
1.1696 +
1.1697 +
1.1698 + /* Size */
1.1699 + insertu32(buf+i, (mp4_u32)ts->trak);
1.1700 + i += 4;
1.1701 +
1.1702 + /* Atom type */
1.1703 + insertu32(buf+i, (mp4_u32)ATOMTYPE_TRAK);
1.1704 + i += 4;
1.1705 +
1.1706 + if (writeFile(handle, buf, 8) < 0)
1.1707 + return -1;
1.1708 +
1.1709 + if (writeVideoTKHD(handle, ts) < 0)
1.1710 + return -1;
1.1711 +
1.1712 + if (writeVideoMDIA(handle, ts) < 0)
1.1713 + return -1;
1.1714 +
1.1715 + if (handle->videoUDTA)
1.1716 + {
1.1717 + if (writeUDTA(handle, handle->videoUDTA) < 0)
1.1718 + return -1;
1.1719 + }
1.1720 +
1.1721 + return 0;
1.1722 +}
1.1723 +
1.1724 +
1.1725 +/*
1.1726 + * Function:
1.1727 + *
1.1728 + * mp4_i32 writeVideoTKHD(MP4HandleImp handle,
1.1729 + * trakSize *ts)
1.1730 + *
1.1731 + * Description:
1.1732 + *
1.1733 + * Write TKHD atom.
1.1734 + *
1.1735 + * Parameters:
1.1736 + *
1.1737 + * handle MP4 library handle
1.1738 + * ts Atom sizes
1.1739 + *
1.1740 + * Return value:
1.1741 + *
1.1742 + * 0 Success
1.1743 + * -1 Error
1.1744 + *
1.1745 + */
1.1746 +mp4_i32 writeVideoTKHD(MP4HandleImp handle, trakSize *ts)
1.1747 +{
1.1748 + mp4_u8 *buf;
1.1749 + mp4_u32 i = 0;
1.1750 + mp4_u32 u32;
1.1751 + mp4_double ud;
1.1752 +
1.1753 +
1.1754 + buf = (mp4_u8 *)mp4malloc(ts->tkhd);
1.1755 + if (buf == NULL)
1.1756 + return -1;
1.1757 +
1.1758 + /* Size */
1.1759 + insertu32(buf+i, (mp4_u32)ts->tkhd);
1.1760 + i += 4;
1.1761 +
1.1762 + /* Atom type */
1.1763 + insertu32(buf+i, (mp4_u32)ATOMTYPE_TKHD);
1.1764 + i += 4;
1.1765 +
1.1766 +
1.1767 + if (handle->videoDuration > MP4_INT_MAX)
1.1768 + {
1.1769 + mp4_u64 u64;
1.1770 + /* Version and flags */
1.1771 + buf[i++] = 1; //make this a version 1 atom
1.1772 + buf[i++] = 0;
1.1773 + buf[i++] = 0;
1.1774 + buf[i++] = 7; /* Track enabled, used in movie and preview */
1.1775 +
1.1776 + /* Creation time */
1.1777 + if (getCurrentTime(&u32) < 0)
1.1778 + u32 = 0;
1.1779 + insertu64(buf+i, (mp4_u64)u32);
1.1780 + i += 8;
1.1781 +
1.1782 + /* Modification time */
1.1783 + if (getCurrentTime(&u32) < 0)
1.1784 + u32 = 0;
1.1785 + insertu64(buf+i, (mp4_u64)u32);
1.1786 + i += 8;
1.1787 +
1.1788 + /* Track ID */
1.1789 + insertu32(buf+i, (mp4_u32)1);
1.1790 + i += 4;
1.1791 +
1.1792 + /* Reserved */
1.1793 + insertu32(buf+i, (mp4_u32)0);
1.1794 + i += 4;
1.1795 +
1.1796 + /* Duration */
1.1797 + if ( (handle->videoDuration == 0) || (handle->videoTimeScale == 0) )
1.1798 + {
1.1799 + ud = 0;
1.1800 + }
1.1801 + else
1.1802 + {
1.1803 + ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->videoDuration / (mp4_double)handle->videoTimeScale + (mp4_double)0.5;
1.1804 + }
1.1805 +
1.1806 + u64 = (mp4_u64)ud;
1.1807 + insertu64(buf+i, u64);
1.1808 + i += 8;
1.1809 + }
1.1810 + else
1.1811 + {
1.1812 + /* Version and flags */
1.1813 + buf[i++] = 0;
1.1814 + buf[i++] = 0;
1.1815 + buf[i++] = 0;
1.1816 + buf[i++] = 7; /* Track enabled, used in movie and preview */
1.1817 +
1.1818 + /* Creation time */
1.1819 + if (getCurrentTime(&u32) < 0)
1.1820 + u32 = 0;
1.1821 + insertu32(buf+i, (mp4_u32)u32);
1.1822 + i += 4;
1.1823 +
1.1824 + /* Modification time */
1.1825 + if (getCurrentTime(&u32) < 0)
1.1826 + u32 = 0;
1.1827 + insertu32(buf+i, (mp4_u32)u32);
1.1828 + i += 4;
1.1829 +
1.1830 + /* Track ID */
1.1831 + insertu32(buf+i, (mp4_u32)1);
1.1832 + i += 4;
1.1833 +
1.1834 + /* Reserved */
1.1835 + insertu32(buf+i, (mp4_u32)0);
1.1836 + i += 4;
1.1837 +
1.1838 + /* Duration */
1.1839 + if ( (handle->videoDuration == 0) || (handle->videoTimeScale == 0) )
1.1840 + {
1.1841 + ud = 0;
1.1842 + }
1.1843 + else
1.1844 + {
1.1845 + ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->videoDuration / (mp4_double)handle->videoTimeScale + (mp4_double)0.5;
1.1846 + }
1.1847 +
1.1848 + u32 = (mp4_u32)ud;
1.1849 + insertu32(buf+i, u32);
1.1850 + i += 4;
1.1851 + }
1.1852 + /* Reserved */
1.1853 + insertu32(buf+i, (mp4_u32)0);
1.1854 + i += 4;
1.1855 +
1.1856 + insertu32(buf+i, (mp4_u32)0);
1.1857 + i += 4;
1.1858 +
1.1859 + insertu32(buf+i, (mp4_u32)0);
1.1860 + i += 4;
1.1861 +
1.1862 + insertu16(buf+i, (mp4_u16)0); /* Visual track */
1.1863 + i += 2;
1.1864 +
1.1865 + insertu16(buf+i, (mp4_u16)0);
1.1866 + i += 2;
1.1867 +
1.1868 + insertu32(buf+i, (mp4_u32)0x00010000);
1.1869 + i += 4;
1.1870 +
1.1871 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1872 + i += 4;
1.1873 +
1.1874 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1875 + i += 4;
1.1876 +
1.1877 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1878 + i += 4;
1.1879 +
1.1880 + insertu32(buf+i, (mp4_u32)0x00010000);
1.1881 + i += 4;
1.1882 +
1.1883 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1884 + i += 4;
1.1885 +
1.1886 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1887 + i += 4;
1.1888 +
1.1889 + insertu32(buf+i, (mp4_u32)0x00000000);
1.1890 + i += 4;
1.1891 +
1.1892 + insertu32(buf+i, (mp4_u32)0x40000000);
1.1893 + i += 4;
1.1894 +
1.1895 + insertu16(buf+i, (mp4_u16)handle->videoWidth); /* Width */
1.1896 + i += 2;
1.1897 +
1.1898 + insertu16(buf+i, (mp4_u16)0);
1.1899 + i += 2;
1.1900 +
1.1901 + insertu16(buf+i, (mp4_u16)handle->videoHeight); /* Height */
1.1902 + i += 2;
1.1903 +
1.1904 + insertu16(buf+i, (mp4_u16)0);
1.1905 + i += 2;
1.1906 +
1.1907 + if (writeFile(handle, buf, ts->tkhd) < 0)
1.1908 + {
1.1909 + mp4free(buf);
1.1910 +
1.1911 + return -1;
1.1912 + }
1.1913 +
1.1914 + mp4free(buf);
1.1915 +
1.1916 + return 0;
1.1917 +}
1.1918 +
1.1919 +
1.1920 +/*
1.1921 + * Function:
1.1922 + *
1.1923 + * mp4_i32 writeVideoMDIA(MP4HandleImp handle,
1.1924 + * trakSize *ts)
1.1925 + *
1.1926 + * Description:
1.1927 + *
1.1928 + * Write video MDIA atom.
1.1929 + *
1.1930 + * Parameters:
1.1931 + *
1.1932 + * handle MP4 library handle
1.1933 + * ts Atom sizes
1.1934 + *
1.1935 + * Return value:
1.1936 + *
1.1937 + * 0 Success
1.1938 + * -1 Error
1.1939 + *
1.1940 + */
1.1941 +mp4_i32 writeVideoMDIA(MP4HandleImp handle, trakSize *ts)
1.1942 +{
1.1943 + mp4_u8 buf[8];
1.1944 + mp4_u32 i = 0;
1.1945 +
1.1946 +
1.1947 + /* Size */
1.1948 + insertu32(buf+i, (mp4_u32)ts->mdia);
1.1949 + i += 4;
1.1950 +
1.1951 + /* Atom type */
1.1952 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MDIA);
1.1953 + i += 4;
1.1954 +
1.1955 + if (writeFile(handle, buf, 8) < 0)
1.1956 + return -1;
1.1957 +
1.1958 + if (writeVideoMDHD(handle, ts) < 0)
1.1959 + return -1;
1.1960 +
1.1961 + if (writeVideoHDLR(handle, ts) < 0)
1.1962 + return -1;
1.1963 +
1.1964 + if (writeVideoMINF(handle, ts) < 0)
1.1965 + return -1;
1.1966 +
1.1967 + return 0;
1.1968 +}
1.1969 +
1.1970 +
1.1971 +/*
1.1972 + * Function:
1.1973 + *
1.1974 + * mp4_i32 writeVideoMDHD(MP4HandleImp handle,
1.1975 + * trakSize *ts)
1.1976 + *
1.1977 + * Description:
1.1978 + *
1.1979 + * Write video MDHD atom.
1.1980 + *
1.1981 + * Parameters:
1.1982 + *
1.1983 + * handle MP4 library handle
1.1984 + * ts Atom sizes
1.1985 + *
1.1986 + * Return value:
1.1987 + *
1.1988 + * 0 Success
1.1989 + * -1 Error
1.1990 + *
1.1991 + */
1.1992 +mp4_i32 writeVideoMDHD(MP4HandleImp handle, trakSize *ts)
1.1993 +{
1.1994 + mp4_u8 *buf;
1.1995 + mp4_u32 i = 0;
1.1996 + mp4_u32 u32;
1.1997 +
1.1998 +
1.1999 + buf = (mp4_u8 *)mp4malloc(ts->mdhd);
1.2000 + if (buf == NULL)
1.2001 + return -1;
1.2002 +
1.2003 + /* Size */
1.2004 + insertu32(buf+i, (mp4_u32)ts->mdhd);
1.2005 + i += 4;
1.2006 +
1.2007 + /* Atom type */
1.2008 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MDHD);
1.2009 + i += 4;
1.2010 +
1.2011 + if (handle->videoDuration > MP4_INT_MAX)
1.2012 + {
1.2013 + /* Version and flags */
1.2014 + insertu32(buf+i, (mp4_u32)0x01000000); //version 1 atom
1.2015 + i += 4;
1.2016 +
1.2017 + /* Creation time */
1.2018 + if (getCurrentTime(&u32) < 0)
1.2019 + u32 = 0;
1.2020 + insertu64(buf+i, (mp4_u64)u32);
1.2021 + i += 8;
1.2022 +
1.2023 + /* Modification time */
1.2024 + if (getCurrentTime(&u32) < 0)
1.2025 + u32 = 0;
1.2026 + insertu64(buf+i, (mp4_u64)u32);
1.2027 + i += 8;
1.2028 +
1.2029 + /* Timescale */
1.2030 + insertu32(buf+i, (mp4_u32)handle->videoTimeScale);
1.2031 + i += 4;
1.2032 +
1.2033 + /* Duration */
1.2034 + insertu64(buf+i, handle->videoDuration);
1.2035 + i += 8;
1.2036 + }
1.2037 + else
1.2038 + {
1.2039 + /* Version and flags */
1.2040 + insertu32(buf+i, (mp4_u32)0);
1.2041 + i += 4;
1.2042 +
1.2043 + /* Creation time */
1.2044 + if (getCurrentTime(&u32) < 0)
1.2045 + u32 = 0;
1.2046 + insertu32(buf+i, (mp4_u32)u32);
1.2047 + i += 4;
1.2048 +
1.2049 + /* Modification time */
1.2050 + if (getCurrentTime(&u32) < 0)
1.2051 + u32 = 0;
1.2052 + insertu32(buf+i, (mp4_u32)u32);
1.2053 + i += 4;
1.2054 +
1.2055 + /* Timescale */
1.2056 + insertu32(buf+i, (mp4_u32)handle->videoTimeScale);
1.2057 + i += 4;
1.2058 +
1.2059 + /* Duration */
1.2060 + insertu32(buf+i, (mp4_u32)handle->videoDuration);
1.2061 + i += 4;
1.2062 + }
1.2063 +
1.2064 + /* Language */
1.2065 + insertu16(buf+i, (mp4_u16)0x55c4); /* 'und' */
1.2066 + i += 2;
1.2067 +
1.2068 + /* Reserved */
1.2069 + insertu16(buf+i, (mp4_u16)0x0000);
1.2070 + i += 2;
1.2071 +
1.2072 + if (writeFile(handle, buf, ts->mdhd) < 0)
1.2073 + {
1.2074 + mp4free(buf);
1.2075 +
1.2076 + return -1;
1.2077 + }
1.2078 +
1.2079 + mp4free(buf);
1.2080 +
1.2081 + return 0;
1.2082 +}
1.2083 +
1.2084 +
1.2085 +/*
1.2086 + * Function:
1.2087 + *
1.2088 + * mp4_i32 writeVideoHDLR(MP4HandleImp handle,
1.2089 + * trakSize *ts)
1.2090 + *
1.2091 + * Description:
1.2092 + *
1.2093 + * Write video HDLR atom.
1.2094 + *
1.2095 + * Parameters:
1.2096 + *
1.2097 + * handle MP4 library handle
1.2098 + * ts Atom sizes
1.2099 + *
1.2100 + * Return value:
1.2101 + *
1.2102 + * 0 Success
1.2103 + * -1 Error
1.2104 + *
1.2105 + */
1.2106 +mp4_i32 writeVideoHDLR(MP4HandleImp handle, trakSize *ts)
1.2107 +{
1.2108 + mp4_u8 *buf;
1.2109 + mp4_u32 i = 0;
1.2110 +
1.2111 +
1.2112 + buf = (mp4_u8 *)mp4malloc(ts->hdlr);
1.2113 + if (buf == NULL)
1.2114 + return -1;
1.2115 +
1.2116 + /* Size */
1.2117 + insertu32(buf+i, (mp4_u32)ts->hdlr);
1.2118 + i += 4;
1.2119 +
1.2120 + /* Atom type */
1.2121 + insertu32(buf+i, (mp4_u32)ATOMTYPE_HDLR);
1.2122 + i += 4;
1.2123 +
1.2124 + /* Version and flags */
1.2125 + insertu32(buf+i, (mp4_u32)0);
1.2126 + i += 4;
1.2127 +
1.2128 + /* Reserved */
1.2129 + insertu32(buf+i, (mp4_u32)0);
1.2130 + i += 4;
1.2131 +
1.2132 + /* Handler type */
1.2133 + buf[i++] = 'v';
1.2134 + buf[i++] = 'i';
1.2135 + buf[i++] = 'd';
1.2136 + buf[i++] = 'e';
1.2137 +
1.2138 + /* Reserved */
1.2139 + insertu32(buf+i, (mp4_u32)0);
1.2140 + i += 4;
1.2141 +
1.2142 + /* Reserved */
1.2143 + insertu32(buf+i, (mp4_u32)0);
1.2144 + i += 4;
1.2145 +
1.2146 + /* Reserved */
1.2147 + insertu32(buf+i, (mp4_u32)0);
1.2148 + i += 4;
1.2149 +
1.2150 + /* Empty string */
1.2151 + buf[i++] = 0;
1.2152 +
1.2153 + if (writeFile(handle, buf, ts->hdlr) < 0)
1.2154 + {
1.2155 + mp4free(buf);
1.2156 +
1.2157 + return -1;
1.2158 + }
1.2159 +
1.2160 + mp4free(buf);
1.2161 +
1.2162 + return 0;
1.2163 +}
1.2164 +
1.2165 +
1.2166 +/*
1.2167 + * Function:
1.2168 + *
1.2169 + * mp4_i32 writeVideoMINF(MP4HandleImp handle,
1.2170 + * trakSize *ts)
1.2171 + *
1.2172 + * Description:
1.2173 + *
1.2174 + * Write video MINF atom.
1.2175 + *
1.2176 + * Parameters:
1.2177 + *
1.2178 + * handle MP4 library handle
1.2179 + * ts Atom sizes
1.2180 + *
1.2181 + * Return value:
1.2182 + *
1.2183 + * 0 Success
1.2184 + * -1 Error
1.2185 + *
1.2186 + */
1.2187 +mp4_i32 writeVideoMINF(MP4HandleImp handle, trakSize *ts)
1.2188 +{
1.2189 + mp4_u8 buf[8];
1.2190 + mp4_u32 i = 0;
1.2191 +
1.2192 +
1.2193 + /* Size */
1.2194 + insertu32(buf+i, (mp4_u32)ts->minf);
1.2195 + i += 4;
1.2196 +
1.2197 + /* Atom type */
1.2198 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MINF);
1.2199 + i += 4;
1.2200 +
1.2201 + if (writeFile(handle, buf, 8) < 0)
1.2202 + return -1;
1.2203 +
1.2204 + if (writeVMHD(handle, ts) < 0)
1.2205 + return -1;
1.2206 +
1.2207 + if (writeDINF(handle, ts) < 0)
1.2208 + return -1;
1.2209 +
1.2210 + if (writeVideoSTBL(handle, ts) < 0)
1.2211 + return -1;
1.2212 +
1.2213 + return 0;
1.2214 +}
1.2215 +
1.2216 +
1.2217 +/*
1.2218 + * Function:
1.2219 + *
1.2220 + * mp4_i32 writeVMHD(MP4HandleImp handle,
1.2221 + * trakSize *ts)
1.2222 + *
1.2223 + * Description:
1.2224 + *
1.2225 + * Write VMHD atom.
1.2226 + *
1.2227 + * Parameters:
1.2228 + *
1.2229 + * handle MP4 library handle
1.2230 + * ts Atom sizes
1.2231 + *
1.2232 + * Return value:
1.2233 + *
1.2234 + * 0 Success
1.2235 + * -1 Error
1.2236 + *
1.2237 + */
1.2238 +mp4_i32 writeVMHD(MP4HandleImp handle, trakSize *ts)
1.2239 +{
1.2240 + mp4_u8 *buf;
1.2241 + mp4_u32 i = 0;
1.2242 +
1.2243 +
1.2244 + buf = (mp4_u8 *)mp4malloc(ts->vmhd);
1.2245 + if (buf == NULL)
1.2246 + return -1;
1.2247 +
1.2248 + /* Size */
1.2249 + insertu32(buf+i, (mp4_u32)ts->vmhd);
1.2250 + i += 4;
1.2251 +
1.2252 + /* Atom type */
1.2253 + insertu32(buf+i, (mp4_u32)ATOMTYPE_VMHD);
1.2254 + i += 4;
1.2255 +
1.2256 + /* Version and flags */
1.2257 + insertu32(buf+i, (mp4_u32)0x00000001);
1.2258 + i += 4;
1.2259 +
1.2260 + /* Reserved */
1.2261 + insertu32(buf+i, (mp4_u32)0);
1.2262 + i += 4;
1.2263 +
1.2264 + insertu32(buf+i, (mp4_u32)0);
1.2265 + i += 4;
1.2266 +
1.2267 + if (writeFile(handle, buf, ts->vmhd) < 0)
1.2268 + {
1.2269 + mp4free(buf);
1.2270 +
1.2271 + return -1;
1.2272 + }
1.2273 +
1.2274 + mp4free(buf);
1.2275 +
1.2276 + return 0;
1.2277 +}
1.2278 +
1.2279 +
1.2280 +/*
1.2281 + * Function:
1.2282 + *
1.2283 + * mp4_i32 writeDINF(MP4HandleImp handle,
1.2284 + * trakSize *ts)
1.2285 + *
1.2286 + * Description:
1.2287 + *
1.2288 + * Write DINF atom.
1.2289 + *
1.2290 + * Parameters:
1.2291 + *
1.2292 + * handle MP4 library handle
1.2293 + * ts Atom sizes
1.2294 + *
1.2295 + * Return value:
1.2296 + *
1.2297 + * 0 Success
1.2298 + * -1 Error
1.2299 + *
1.2300 + */
1.2301 +mp4_i32 writeDINF(MP4HandleImp handle, trakSize *ts)
1.2302 +{
1.2303 + mp4_u8 buf[8];
1.2304 + mp4_u32 i = 0;
1.2305 +
1.2306 +
1.2307 + /* Size */
1.2308 + insertu32(buf+i, (mp4_u32)ts->dinf);
1.2309 + i += 4;
1.2310 +
1.2311 + /* Atom type */
1.2312 + insertu32(buf+i, (mp4_u32)ATOMTYPE_DINF);
1.2313 + i += 4;
1.2314 +
1.2315 + if (writeFile(handle, buf, 8) < 0)
1.2316 + return -1;
1.2317 +
1.2318 + if (writeDREF(handle, ts) < 0)
1.2319 + return -1;
1.2320 +
1.2321 + return 0;
1.2322 +}
1.2323 +
1.2324 +
1.2325 +/*
1.2326 + * Function:
1.2327 + *
1.2328 + * mp4_i32 writeDREF(MP4HandleImp handle,
1.2329 + * trakSize *ts)
1.2330 + *
1.2331 + * Description:
1.2332 + *
1.2333 + * Write DREF atom.
1.2334 + *
1.2335 + * Parameters:
1.2336 + *
1.2337 + * handle MP4 library handle
1.2338 + * ts Atom sizes
1.2339 + *
1.2340 + * Return value:
1.2341 + *
1.2342 + * 0 Success
1.2343 + * -1 Error
1.2344 + *
1.2345 + */
1.2346 +mp4_i32 writeDREF(MP4HandleImp handle, trakSize *ts)
1.2347 +{
1.2348 + mp4_u8 *buf;
1.2349 + mp4_u32 i = 0;
1.2350 +
1.2351 +
1.2352 + buf = (mp4_u8 *)mp4malloc(ts->dref);
1.2353 + if (buf == NULL)
1.2354 + return -1;
1.2355 +
1.2356 + /* Size */
1.2357 + insertu32(buf+i, (mp4_u32)ts->dref);
1.2358 + i += 4;
1.2359 +
1.2360 + /* Atom type */
1.2361 + insertu32(buf+i, (mp4_u32)ATOMTYPE_DREF);
1.2362 + i += 4;
1.2363 +
1.2364 + /* Version and flags */
1.2365 + insertu32(buf+i, (mp4_u32)0);
1.2366 + i += 4;
1.2367 +
1.2368 + /* Entry count */
1.2369 + insertu32(buf+i, (mp4_u32)1);
1.2370 + i += 4;
1.2371 +
1.2372 + /* URL atom */
1.2373 +
1.2374 + /* Size */
1.2375 + insertu32(buf+i, (mp4_u32)12);
1.2376 + i += 4;
1.2377 +
1.2378 + /* Type */
1.2379 + insertu32(buf+i, (mp4_u32)ATOMTYPE_URL);
1.2380 + i += 4;
1.2381 +
1.2382 + /* Version and flags */
1.2383 + insertu32(buf+i, (mp4_u32)0x00000001);
1.2384 + i += 4;
1.2385 +
1.2386 + if (writeFile(handle, buf, ts->dref) < 0)
1.2387 + {
1.2388 + mp4free(buf);
1.2389 +
1.2390 + return -1;
1.2391 + }
1.2392 +
1.2393 + mp4free(buf);
1.2394 +
1.2395 + return 0;
1.2396 +}
1.2397 +
1.2398 +
1.2399 +/*
1.2400 + * Function:
1.2401 + *
1.2402 + * mp4_i32 writeVideoSTBL(MP4HandleImp handle,
1.2403 + * trakSize *ts)
1.2404 + *
1.2405 + * Description:
1.2406 + *
1.2407 + * Write video STBL atom.
1.2408 + *
1.2409 + * Parameters:
1.2410 + *
1.2411 + * handle MP4 library handle
1.2412 + * ts Atom sizes
1.2413 + *
1.2414 + * Return value:
1.2415 + *
1.2416 + * 0 Success
1.2417 + * -1 Error
1.2418 + *
1.2419 + */
1.2420 +mp4_i32 writeVideoSTBL(MP4HandleImp handle, trakSize *ts)
1.2421 +{
1.2422 + mp4_u8 buf[8];
1.2423 + mp4_u32 i = 0;
1.2424 +
1.2425 +
1.2426 + /* Size */
1.2427 + insertu32(buf+i, (mp4_u32)ts->stbl);
1.2428 + i += 4;
1.2429 +
1.2430 + /* Atom type */
1.2431 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STBL);
1.2432 + i += 4;
1.2433 +
1.2434 + if (writeFile(handle, buf, 8) < 0)
1.2435 + return -1;
1.2436 +
1.2437 + if (writeVideoSTSD(handle, ts) < 0)
1.2438 + return -1;
1.2439 +
1.2440 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.2441 + {
1.2442 + if (writeVideoSTTSLongClip(handle, ts) < 0)
1.2443 + return -1;
1.2444 + }
1.2445 + else
1.2446 + {
1.2447 + if (writeVideoSTTS(handle, ts) < 0)
1.2448 + return -1;
1.2449 + }
1.2450 +
1.2451 + if (writeVideoSTSC(handle, ts) < 0)
1.2452 + return -1;
1.2453 +
1.2454 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.2455 + {
1.2456 + if (writeVideoSTSZLongClip(handle, ts) < 0)
1.2457 + return -1;
1.2458 +
1.2459 + if (handle->videoSampleTable->stcoNeed64Bits)
1.2460 + {
1.2461 + if (writeVideoCO64LongClip(handle, ts) < 0)
1.2462 + return -1;
1.2463 + }
1.2464 + else
1.2465 + {
1.2466 + if (writeVideoSTCOLongClip(handle, ts) < 0)
1.2467 + return -1;
1.2468 + }
1.2469 +
1.2470 + if (writeVideoSTSSLongClip(handle, ts) < 0)
1.2471 + return -1;
1.2472 +
1.2473 + if(ts->sdtp && writeVideoSDTPLongClip(handle, ts) < 0)
1.2474 + return -1;
1.2475 + }
1.2476 + else
1.2477 + {
1.2478 + if (writeVideoSTSZ(handle, ts) < 0)
1.2479 + return -1;
1.2480 +
1.2481 + if (handle->videoSampleTable->stcoNeed64Bits)
1.2482 + {
1.2483 + if (writeVideoCO64(handle, ts) < 0)
1.2484 + return -1;
1.2485 + }
1.2486 + else
1.2487 + {
1.2488 + if (writeVideoSTCO(handle, ts) < 0)
1.2489 + return -1;
1.2490 + }
1.2491 +
1.2492 + if (writeVideoSTSS(handle, ts) < 0)
1.2493 + return -1;
1.2494 +
1.2495 + if(ts->sdtp && writeVideoSDTP(handle, ts) < 0)
1.2496 + return -1;
1.2497 + }
1.2498 + return 0;
1.2499 +}
1.2500 +
1.2501 +
1.2502 +/*
1.2503 + * Function:
1.2504 + *
1.2505 + * mp4_i32 writeVideoSTSD(MP4HandleImp handle,
1.2506 + * trakSize *ts)
1.2507 + *
1.2508 + * Description:
1.2509 + *
1.2510 + * Write video STSD atom.
1.2511 + *
1.2512 + * Parameters:
1.2513 + *
1.2514 + * handle MP4 library handle
1.2515 + * ts Atom sizes
1.2516 + *
1.2517 + * Return value:
1.2518 + *
1.2519 + * 0 Success
1.2520 + * -1 Error
1.2521 + *
1.2522 + */
1.2523 +mp4_i32 writeVideoSTSD(MP4HandleImp handle, trakSize *ts)
1.2524 +{
1.2525 + mp4_u8 buf[16];
1.2526 + mp4_u32 i = 0;
1.2527 +
1.2528 +
1.2529 + /* Size */
1.2530 + insertu32(buf+i, (mp4_u32)ts->stsd);
1.2531 + i += 4;
1.2532 +
1.2533 + /* Atom type */
1.2534 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSD);
1.2535 + i += 4;
1.2536 +
1.2537 + /* Version and flags */
1.2538 + insertu32(buf+i, (mp4_u32)0);
1.2539 + i += 4;
1.2540 +
1.2541 + /* Entry count */
1.2542 + insertu32(buf+i, (mp4_u32)1);
1.2543 + i += 4;
1.2544 +
1.2545 + if (writeFile(handle, buf, 16) < 0)
1.2546 + return -1;
1.2547 +
1.2548 + if (handle->type & MP4_TYPE_MPEG4_VIDEO)
1.2549 + {
1.2550 + if (writeMP4V(handle, ts) < 0)
1.2551 + return -1;
1.2552 + }
1.2553 + else if ((handle->type & MP4_TYPE_H263_PROFILE_0) ||
1.2554 + (handle->type & MP4_TYPE_H263_PROFILE_3))
1.2555 + {
1.2556 + if (writeS263(handle, ts) < 0)
1.2557 + return -1;
1.2558 + }
1.2559 + else if ( containsAvcVideo( handle->type ) )
1.2560 + {
1.2561 + if (writeAVC1(handle, ts) < 0)
1.2562 + return -1;
1.2563 + }
1.2564 + else
1.2565 + {
1.2566 + }
1.2567 +
1.2568 + return 0;
1.2569 +}
1.2570 +
1.2571 +
1.2572 +/*
1.2573 + * Function:
1.2574 + *
1.2575 + * mp4_i32 writeMP4V(MP4HandleImp handle,
1.2576 + * trakSize *ts)
1.2577 + *
1.2578 + * Description:
1.2579 + *
1.2580 + * Write MP4V atom.
1.2581 + *
1.2582 + * Parameters:
1.2583 + *
1.2584 + * handle MP4 library handle
1.2585 + * ts Atom sizes
1.2586 + *
1.2587 + * Return value:
1.2588 + *
1.2589 + * 0 Success
1.2590 + * -1 Error
1.2591 + *
1.2592 + */
1.2593 +mp4_i32 writeMP4V(MP4HandleImp handle, trakSize *ts)
1.2594 +{
1.2595 + mp4_u8 *buf;
1.2596 + mp4_u32 i = 0;
1.2597 +
1.2598 +
1.2599 + buf = (mp4_u8 *)mp4malloc(86);
1.2600 + if (buf == NULL)
1.2601 + return -1;
1.2602 +
1.2603 + /* Size */
1.2604 + insertu32(buf+i, (mp4_u32)ts->mp4v);
1.2605 + i += 4;
1.2606 +
1.2607 + /* Atom type */
1.2608 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MP4V);
1.2609 + i += 4;
1.2610 +
1.2611 + /* Reserved */
1.2612 + buf[i++] = 0;
1.2613 + buf[i++] = 0;
1.2614 + buf[i++] = 0;
1.2615 + buf[i++] = 0;
1.2616 + buf[i++] = 0;
1.2617 + buf[i++] = 0;
1.2618 +
1.2619 + /* Data reference index */
1.2620 + insertu16(buf+i, (mp4_u16)1);
1.2621 + i += 2;
1.2622 +
1.2623 + /* Reserved */
1.2624 + insertu32(buf+i, (mp4_u32)0);
1.2625 + i += 4;
1.2626 +
1.2627 + insertu32(buf+i, (mp4_u32)0);
1.2628 + i += 4;
1.2629 +
1.2630 + insertu32(buf+i, (mp4_u32)0);
1.2631 + i += 4;
1.2632 +
1.2633 + insertu32(buf+i, (mp4_u32)0);
1.2634 + i += 4;
1.2635 +
1.2636 + /* Width */
1.2637 + insertu16(buf+i, (mp4_u16)handle->videoWidth);
1.2638 + i += 2;
1.2639 +
1.2640 + /* Height */
1.2641 + insertu16(buf+i, (mp4_u16)handle->videoHeight);
1.2642 + i += 2;
1.2643 +
1.2644 + /* Reserved */
1.2645 + insertu32(buf+i, (mp4_u32)0x00480000);
1.2646 + i += 4;
1.2647 +
1.2648 + insertu32(buf+i, (mp4_u32)0x00480000);
1.2649 + i += 4;
1.2650 +
1.2651 + insertu32(buf+i, (mp4_u32)0);
1.2652 + i += 4;
1.2653 +
1.2654 + insertu16(buf+i, (mp4_u16)1);
1.2655 + i += 2;
1.2656 +
1.2657 + insertu32(buf+i, (mp4_u32)0);
1.2658 + i += 4;
1.2659 +
1.2660 + insertu32(buf+i, (mp4_u32)0);
1.2661 + i += 4;
1.2662 +
1.2663 + insertu32(buf+i, (mp4_u32)0);
1.2664 + i += 4;
1.2665 +
1.2666 + insertu32(buf+i, (mp4_u32)0);
1.2667 + i += 4;
1.2668 +
1.2669 + insertu32(buf+i, (mp4_u32)0);
1.2670 + i += 4;
1.2671 +
1.2672 + insertu32(buf+i, (mp4_u32)0);
1.2673 + i += 4;
1.2674 +
1.2675 + insertu32(buf+i, (mp4_u32)0);
1.2676 + i += 4;
1.2677 +
1.2678 + insertu32(buf+i, (mp4_u32)0);
1.2679 + i += 4;
1.2680 +
1.2681 + insertu16(buf+i, (mp4_u16)24);
1.2682 + i += 2;
1.2683 +
1.2684 + insertu16(buf+i, (mp4_u16)0xffff);
1.2685 + i += 2;
1.2686 +
1.2687 + if (writeFile(handle, buf, 86) < 0)
1.2688 + {
1.2689 + mp4free(buf);
1.2690 +
1.2691 + return -1;
1.2692 + }
1.2693 +
1.2694 + if (writeVideoESD(handle, ts) < 0)
1.2695 + {
1.2696 + mp4free(buf);
1.2697 +
1.2698 + return -1;
1.2699 + }
1.2700 +
1.2701 + mp4free(buf);
1.2702 +
1.2703 + return 0;
1.2704 +}
1.2705 +
1.2706 +
1.2707 +/*
1.2708 + * Function:
1.2709 + *
1.2710 + * mp4_i32 writeVideoESD(MP4HandleImp handle,
1.2711 + * trakSize *ts)
1.2712 + *
1.2713 + * Description:
1.2714 + *
1.2715 + * Write video ESD atom.
1.2716 + *
1.2717 + * Parameters:
1.2718 + *
1.2719 + * handle MP4 library handle
1.2720 + * ts Atom sizes
1.2721 + *
1.2722 + * Return value:
1.2723 + *
1.2724 + * 0 Success
1.2725 + * -1 Error
1.2726 + *
1.2727 + */
1.2728 +mp4_i32 writeVideoESD(MP4HandleImp handle, trakSize *ts)
1.2729 +{
1.2730 + mp4_u8 *buf;
1.2731 + mp4_u32 i = 0;
1.2732 +
1.2733 +
1.2734 + buf = (mp4_u8 *)mp4malloc(ts->esds);
1.2735 + if (buf == NULL)
1.2736 + return -1;
1.2737 +
1.2738 + /* Size */
1.2739 + insertu32(buf+i, (mp4_u32)ts->esds);
1.2740 + i += 4;
1.2741 +
1.2742 + /* Atom type */
1.2743 + insertu32(buf+i, (mp4_u32)ATOMTYPE_ESD);
1.2744 + i += 4;
1.2745 +
1.2746 + /* Version and flags */
1.2747 + insertu32(buf+i, (mp4_u32)0);
1.2748 + i += 4;
1.2749 +
1.2750 + /* ES_DescrTag */
1.2751 + buf[i++] = 0x03;
1.2752 +
1.2753 + /* Size */
1.2754 + buf[i++] = (mp4_u8)(23 + handle->videoDecSpecificInfoSize);
1.2755 +
1.2756 + /* ES_ID */
1.2757 + insertu16(buf+i, (mp4_u16)0);
1.2758 + i += 2;
1.2759 +
1.2760 + /* Flags */
1.2761 + buf[i++] = 0;
1.2762 +
1.2763 + /* DecoderConfigDescrTag */
1.2764 + buf[i++] = 0x04;
1.2765 +
1.2766 + /* Size */
1.2767 + buf[i++] = (mp4_u8)(15 + handle->videoDecSpecificInfoSize);
1.2768 +
1.2769 + /* ObjectTypeIndication */
1.2770 + buf[i++] = 0x20;
1.2771 +
1.2772 + /* Flags */
1.2773 + buf[i++] = 0x11;
1.2774 +
1.2775 + /* BufferSizeDB */
1.2776 + buf[i++] = 0x00;
1.2777 + buf[i++] = 0x50;
1.2778 + buf[i++] = 0x00;
1.2779 +
1.2780 + /* MaxBitrate */
1.2781 + insertu32(buf+i, (mp4_u32)handle->videoMaxBitrate);
1.2782 + i += 4;
1.2783 +
1.2784 + /* AvgBitrate */
1.2785 + insertu32(buf+i, (mp4_u32)handle->videoAvgBitrate);
1.2786 + i += 4;
1.2787 +
1.2788 + /* DecSpecificInfoTag */
1.2789 + buf[i++] = 0x05;
1.2790 +
1.2791 + /* Size */
1.2792 + buf[i++] = (mp4_u8)handle->videoDecSpecificInfoSize;
1.2793 +
1.2794 + /* DecoderSpecificInfo */
1.2795 + mp4memcpy(buf+i, handle->videoDecSpecificInfo, handle->videoDecSpecificInfoSize);
1.2796 + i += handle->videoDecSpecificInfoSize;
1.2797 +
1.2798 + /* SLConfigDescrTag */
1.2799 + buf[i++] = 0x06;
1.2800 +
1.2801 + /* Size */
1.2802 + buf[i++] = 1;
1.2803 +
1.2804 + /* */
1.2805 + buf[i++] = 2;
1.2806 +
1.2807 + if (writeFile(handle, buf, ts->esds) < 0)
1.2808 + {
1.2809 + mp4free(buf);
1.2810 +
1.2811 + return -1;
1.2812 + }
1.2813 +
1.2814 + mp4free(buf);
1.2815 +
1.2816 + return 0;
1.2817 +}
1.2818 +
1.2819 +
1.2820 +/*
1.2821 + * Function:
1.2822 + *
1.2823 + * mp4_i32 writeS263(MP4HandleImp handle,
1.2824 + * trakSize *ts)
1.2825 + *
1.2826 + * Description:
1.2827 + *
1.2828 + * Write S263 atom.
1.2829 + *
1.2830 + * Parameters:
1.2831 + *
1.2832 + * handle MP4 library handle
1.2833 + * ts Atom sizes
1.2834 + *
1.2835 + * Return value:
1.2836 + *
1.2837 + * 0 Success
1.2838 + * -1 Error
1.2839 + *
1.2840 + */
1.2841 +mp4_i32 writeS263(MP4HandleImp handle, trakSize *ts)
1.2842 +{
1.2843 + mp4_u8 *buf;
1.2844 + mp4_u32 i = 0;
1.2845 +
1.2846 +
1.2847 + buf = (mp4_u8 *)mp4malloc(86);
1.2848 + if (buf == NULL)
1.2849 + return -1;
1.2850 +
1.2851 + /* Size */
1.2852 + insertu32(buf+i, (mp4_u32)ts->s263);
1.2853 + i += 4;
1.2854 +
1.2855 + /* Atom type */
1.2856 + insertu32(buf+i, (mp4_u32)ATOMTYPE_S263);
1.2857 + i += 4;
1.2858 +
1.2859 + /* Reserved */
1.2860 + buf[i++] = 0;
1.2861 + buf[i++] = 0;
1.2862 + buf[i++] = 0;
1.2863 + buf[i++] = 0;
1.2864 + buf[i++] = 0;
1.2865 + buf[i++] = 0;
1.2866 +
1.2867 + /* Data reference index */
1.2868 + insertu16(buf+i, (mp4_u16)1);
1.2869 + i += 2;
1.2870 +
1.2871 + /* Reserved */
1.2872 + insertu32(buf+i, (mp4_u32)0);
1.2873 + i += 4;
1.2874 +
1.2875 + insertu32(buf+i, (mp4_u32)0);
1.2876 + i += 4;
1.2877 +
1.2878 + insertu32(buf+i, (mp4_u32)0);
1.2879 + i += 4;
1.2880 +
1.2881 + insertu32(buf+i, (mp4_u32)0);
1.2882 + i += 4;
1.2883 +
1.2884 + /* Width */
1.2885 + insertu16(buf+i, (mp4_u16)handle->videoWidth);
1.2886 + i += 2;
1.2887 +
1.2888 + /* Height */
1.2889 + insertu16(buf+i, (mp4_u16)handle->videoHeight);
1.2890 + i += 2;
1.2891 +
1.2892 + /* Reserved */
1.2893 + insertu32(buf+i, (mp4_u32)0x00480000);
1.2894 + i += 4;
1.2895 +
1.2896 + insertu32(buf+i, (mp4_u32)0x00480000);
1.2897 + i += 4;
1.2898 +
1.2899 + insertu32(buf+i, (mp4_u32)0);
1.2900 + i += 4;
1.2901 +
1.2902 + insertu16(buf+i, (mp4_u16)1);
1.2903 + i += 2;
1.2904 +
1.2905 + insertu32(buf+i, (mp4_u32)0);
1.2906 + i += 4;
1.2907 +
1.2908 + insertu32(buf+i, (mp4_u32)0);
1.2909 + i += 4;
1.2910 +
1.2911 + insertu32(buf+i, (mp4_u32)0);
1.2912 + i += 4;
1.2913 +
1.2914 + insertu32(buf+i, (mp4_u32)0);
1.2915 + i += 4;
1.2916 +
1.2917 + insertu32(buf+i, (mp4_u32)0);
1.2918 + i += 4;
1.2919 +
1.2920 + insertu32(buf+i, (mp4_u32)0);
1.2921 + i += 4;
1.2922 +
1.2923 + insertu32(buf+i, (mp4_u32)0);
1.2924 + i += 4;
1.2925 +
1.2926 + insertu32(buf+i, (mp4_u32)0);
1.2927 + i += 4;
1.2928 +
1.2929 + insertu16(buf+i, (mp4_u16)24);
1.2930 + i += 2;
1.2931 +
1.2932 + insertu16(buf+i, (mp4_u16)0xffff);
1.2933 + i += 2;
1.2934 +
1.2935 + if (writeFile(handle, buf, 86) < 0)
1.2936 + {
1.2937 + mp4free(buf);
1.2938 +
1.2939 + return -1;
1.2940 + }
1.2941 +
1.2942 + if (writeD263(handle, ts) < 0)
1.2943 + {
1.2944 + mp4free(buf);
1.2945 +
1.2946 + return -1;
1.2947 + }
1.2948 +
1.2949 + mp4free(buf);
1.2950 +
1.2951 + return 0;
1.2952 +}
1.2953 +
1.2954 +
1.2955 +/*
1.2956 + * Function:
1.2957 + *
1.2958 + * mp4_i32 writeD263(MP4HandleImp handle,
1.2959 + * trakSize *ts)
1.2960 + *
1.2961 + * Description:
1.2962 + *
1.2963 + * Write D263 atom.
1.2964 + *
1.2965 + * Parameters:
1.2966 + *
1.2967 + * handle MP4 library handle
1.2968 + * ts Atom sizes
1.2969 + *
1.2970 + * Return value:
1.2971 + *
1.2972 + * 0 Success
1.2973 + * -1 Error
1.2974 + *
1.2975 + */
1.2976 +mp4_i32 writeD263(MP4HandleImp handle, trakSize *ts)
1.2977 +{
1.2978 + mp4_u8 buf[15];
1.2979 + mp4_u32 i = 0;
1.2980 +
1.2981 +
1.2982 + /* Size */
1.2983 + insertu32(buf+i, (mp4_u32)ts->d263);
1.2984 + i += 4;
1.2985 +
1.2986 + /* Atom type */
1.2987 + insertu32(buf+i, (mp4_u32)ATOMTYPE_D263);
1.2988 + i += 4;
1.2989 +
1.2990 + /* Vendor */
1.2991 + buf[i++] = 'S';
1.2992 + buf[i++] = '6';
1.2993 + buf[i++] = '0';
1.2994 + buf[i++] = ' ';
1.2995 +
1.2996 + /* Decoder version */
1.2997 + buf[i++] = 0;
1.2998 +
1.2999 + /* H263_Level */
1.3000 + buf[i++] = handle->videoLevel;
1.3001 +
1.3002 + /* H263_Profile */
1.3003 + if (handle->type & MP4_TYPE_H263_PROFILE_0)
1.3004 + buf[i++] = 0;
1.3005 + else if (handle->type & MP4_TYPE_H263_PROFILE_3)
1.3006 + buf[i++] = 3;
1.3007 + else
1.3008 + return -1;
1.3009 +
1.3010 + if (writeFile(handle, buf, 15) < 0)
1.3011 + return -1;
1.3012 +
1.3013 + return 0;
1.3014 +}
1.3015 +
1.3016 +/*
1.3017 + * Function:
1.3018 + *
1.3019 + * mp4_i32 writeAVC1(MP4HandleImp handle,
1.3020 + * trakSize *ts)
1.3021 + *
1.3022 + * Description:
1.3023 + *
1.3024 + * Write AVC1 atom.
1.3025 + *
1.3026 + * Parameters:
1.3027 + *
1.3028 + * handle MP4 library handle
1.3029 + * ts Atom sizes
1.3030 + *
1.3031 + * Return value:
1.3032 + *
1.3033 + * 0 Success
1.3034 + * -1 Error
1.3035 + *
1.3036 + */
1.3037 +mp4_i32 writeAVC1(MP4HandleImp handle, trakSize *ts)
1.3038 +{
1.3039 + mp4_u8 *buf;
1.3040 + mp4_u32 i = 0;
1.3041 +
1.3042 +
1.3043 + buf = (mp4_u8 *)mp4malloc(86);
1.3044 + if (buf == NULL)
1.3045 + return -1;
1.3046 +
1.3047 + /* Size */
1.3048 + insertu32(buf+i, (mp4_u32)ts->avc1);
1.3049 + i += 4;
1.3050 +
1.3051 + /* Atom type */
1.3052 + insertu32(buf+i, (mp4_u32)ATOMTYPE_AVC1);
1.3053 + i += 4;
1.3054 +
1.3055 + /* Reserved */
1.3056 + buf[i++] = 0;
1.3057 + buf[i++] = 0;
1.3058 + buf[i++] = 0;
1.3059 + buf[i++] = 0;
1.3060 + buf[i++] = 0;
1.3061 + buf[i++] = 0;
1.3062 +
1.3063 + /* Data reference index */
1.3064 + insertu16(buf+i, (mp4_u16)1);
1.3065 + i += 2;
1.3066 +
1.3067 + /* Reserved */
1.3068 + insertu32(buf+i, (mp4_u32)0);
1.3069 + i += 4;
1.3070 +
1.3071 + insertu32(buf+i, (mp4_u32)0);
1.3072 + i += 4;
1.3073 +
1.3074 + insertu32(buf+i, (mp4_u32)0);
1.3075 + i += 4;
1.3076 +
1.3077 + insertu32(buf+i, (mp4_u32)0);
1.3078 + i += 4;
1.3079 +
1.3080 + /* Width */
1.3081 + insertu16(buf+i, (mp4_u16)handle->videoWidth);
1.3082 + i += 2;
1.3083 +
1.3084 + /* Height */
1.3085 + insertu16(buf+i, (mp4_u16)handle->videoHeight);
1.3086 + i += 2;
1.3087 +
1.3088 + /* H-res (default is 72dpi = 0x00480000) */
1.3089 + insertu32(buf+i, (mp4_u32)0x00480000);
1.3090 + i += 4;
1.3091 +
1.3092 + /* V-res (default is 72dpi = 0x00480000) */
1.3093 + insertu32(buf+i, (mp4_u32)0x00480000);
1.3094 + i += 4;
1.3095 +
1.3096 + /* Reserved */
1.3097 + insertu32(buf+i, (mp4_u32)0);
1.3098 + i += 4;
1.3099 +
1.3100 + /* Frame count (default is 1) */
1.3101 + insertu16(buf+i, (mp4_u16)1);
1.3102 + i += 2;
1.3103 +
1.3104 + /* Compressor name (32 byte string) */
1.3105 + // The spec *recommends* inserting "\012AVC Coding" here
1.3106 + // but we just have a string of nulls.
1.3107 + insertu32(buf+i, (mp4_u32)0);
1.3108 + i += 4;
1.3109 +
1.3110 + insertu32(buf+i, (mp4_u32)0);
1.3111 + i += 4;
1.3112 +
1.3113 + insertu32(buf+i, (mp4_u32)0);
1.3114 + i += 4;
1.3115 +
1.3116 + insertu32(buf+i, (mp4_u32)0);
1.3117 + i += 4;
1.3118 +
1.3119 + insertu32(buf+i, (mp4_u32)0);
1.3120 + i += 4;
1.3121 +
1.3122 + insertu32(buf+i, (mp4_u32)0);
1.3123 + i += 4;
1.3124 +
1.3125 + insertu32(buf+i, (mp4_u32)0);
1.3126 + i += 4;
1.3127 +
1.3128 + insertu32(buf+i, (mp4_u32)0);
1.3129 + i += 4;
1.3130 +
1.3131 + /* Depth (default is 0x0018 which indicates colour images with no alpha) */
1.3132 + insertu16(buf+i, (mp4_u16)24);
1.3133 + i += 2;
1.3134 +
1.3135 + /* Pre-defined (-1) */
1.3136 + insertu16(buf+i, (mp4_u16)0xffff);
1.3137 + i += 2;
1.3138 +
1.3139 + if (writeFile(handle, buf, 86) < 0)
1.3140 + {
1.3141 + mp4free(buf);
1.3142 +
1.3143 + return -1;
1.3144 + }
1.3145 +
1.3146 + if (writeAVCC(handle, ts) < 0)
1.3147 + {
1.3148 + mp4free(buf);
1.3149 +
1.3150 + return -1;
1.3151 + }
1.3152 +
1.3153 + /* Note: If necessary, include writing of btrt and m4ds atoms. */
1.3154 +
1.3155 + mp4free(buf);
1.3156 +
1.3157 + return 0;
1.3158 +}
1.3159 +
1.3160 +/*
1.3161 + * Function:
1.3162 + *
1.3163 + * mp4_i32 writeAVCC(MP4HandleImp handle,
1.3164 + * trakSize *ts)
1.3165 + *
1.3166 + * Description:
1.3167 + *
1.3168 + * Write AVCC atom.
1.3169 + *
1.3170 + * Parameters:
1.3171 + *
1.3172 + * handle MP4 library handle
1.3173 + * ts Atom sizes
1.3174 + *
1.3175 + * Return value:
1.3176 + *
1.3177 + * 0 Success
1.3178 + * -1 Error
1.3179 + *
1.3180 + */
1.3181 +mp4_i32 writeAVCC(MP4HandleImp handle, trakSize *ts)
1.3182 +{
1.3183 + mp4_u8 *buf;
1.3184 + mp4_u32 i = 0;
1.3185 +
1.3186 +
1.3187 + buf = (mp4_u8 *)mp4malloc(ts->avcc);
1.3188 + if (buf == NULL)
1.3189 + return -1;
1.3190 +
1.3191 + /* Size */
1.3192 + insertu32(buf+i, (mp4_u32)ts->avcc);
1.3193 + i += 4;
1.3194 +
1.3195 + /* Atom type */
1.3196 + insertu32(buf+i, (mp4_u32)ATOMTYPE_AVCC);
1.3197 + i += 4;
1.3198 +
1.3199 + /*mp4memcpy(buf+i, handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig,
1.3200 + handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize);*/
1.3201 +
1.3202 + mp4memcpy(buf+i, handle->videoDecSpecificInfo, handle->videoDecSpecificInfoSize);
1.3203 +
1.3204 + /*i += handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize;*/
1.3205 +
1.3206 + i += handle->videoDecSpecificInfoSize;
1.3207 +
1.3208 + if (writeFile(handle, buf, ts->avcc) < 0)
1.3209 + {
1.3210 + mp4free(buf);
1.3211 +
1.3212 + return -1;
1.3213 + }
1.3214 +
1.3215 + mp4free(buf);
1.3216 +
1.3217 + return 0;
1.3218 +}
1.3219 +
1.3220 +
1.3221 +/*
1.3222 + * Function:
1.3223 + *
1.3224 + * mp4_i32 writeVideoSTTS(MP4HandleImp handle,
1.3225 + * trakSize *ts)
1.3226 + *
1.3227 + * Description:
1.3228 + *
1.3229 + * Write video STTS atom.
1.3230 + *
1.3231 + * Parameters:
1.3232 + *
1.3233 + * handle MP4 library handle
1.3234 + * ts Atom sizes
1.3235 + *
1.3236 + * Return value:
1.3237 + *
1.3238 + * 0 Success
1.3239 + * -1 Error
1.3240 + *
1.3241 + */
1.3242 +mp4_i32 writeVideoSTTS(MP4HandleImp handle, trakSize *ts)
1.3243 +{
1.3244 + mp4_u8 *buf;
1.3245 + mp4_u32 i = 0;
1.3246 + mp4_u32 j;
1.3247 +
1.3248 +
1.3249 + buf = (mp4_u8 *)mp4malloc(ts->stts);
1.3250 + if (buf == NULL)
1.3251 + return -1;
1.3252 +
1.3253 + /* Size */
1.3254 + insertu32(buf+i, (mp4_u32)ts->stts);
1.3255 + i += 4;
1.3256 +
1.3257 + /* Atom type */
1.3258 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS);
1.3259 + i += 4;
1.3260 +
1.3261 + /* Version and flags */
1.3262 + insertu32(buf+i, (mp4_u32)0);
1.3263 + i += 4;
1.3264 +
1.3265 + /* Entry count */
1.3266 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsEntryCount);
1.3267 + i += 4;
1.3268 +
1.3269 + /* Sample count and sample delta */
1.3270 + for (j = 0; j < handle->videoSampleTable->sttsEntryCount; j++)
1.3271 + {
1.3272 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsSampleCount[j]);
1.3273 + i += 4;
1.3274 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsSampleDelta[j]);
1.3275 + i += 4;
1.3276 + }
1.3277 +
1.3278 + if (writeFile(handle, buf, ts->stts) < 0)
1.3279 + {
1.3280 + mp4free(buf);
1.3281 +
1.3282 + return -1;
1.3283 + }
1.3284 +
1.3285 + mp4free(buf);
1.3286 +
1.3287 + return 0;
1.3288 +}
1.3289 +
1.3290 +
1.3291 +/*
1.3292 + * Function:
1.3293 + *
1.3294 + * mp4_i32 writeVideoSTTSLongClip(MP4HandleImp handle,
1.3295 + * trakSize *ts)
1.3296 + *
1.3297 + * Description:
1.3298 + *
1.3299 + * Write video STTS atom.
1.3300 + *
1.3301 + * Parameters:
1.3302 + *
1.3303 + * handle MP4 library handle
1.3304 + * ts Atom sizes
1.3305 + *
1.3306 + * Return value:
1.3307 + *
1.3308 + * 0 Success
1.3309 + * -1 Error
1.3310 + *
1.3311 + */
1.3312 +mp4_i32 writeVideoSTTSLongClip(MP4HandleImp handle, trakSize *ts)
1.3313 +{
1.3314 + mp4_u8 *buf;
1.3315 + mp4_u8 *buf2;
1.3316 + mp4_u32 i = 0;
1.3317 + mp4_u32 j;
1.3318 + mp4_u32 left;
1.3319 + mp4_u32 bytestoread;
1.3320 +
1.3321 +
1.3322 + buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.3323 + if (buf == NULL)
1.3324 + return -1;
1.3325 +
1.3326 + buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2);
1.3327 + if (buf2 == NULL)
1.3328 + {
1.3329 + mp4free(buf);
1.3330 + return -1;
1.3331 + }
1.3332 +
1.3333 + /* Size */
1.3334 + insertu32(buf+i, (mp4_u32)ts->stts);
1.3335 + i += 4;
1.3336 +
1.3337 + /* Atom type */
1.3338 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS);
1.3339 + i += 4;
1.3340 +
1.3341 + /* Version and flags */
1.3342 + insertu32(buf+i, (mp4_u32)0);
1.3343 + i += 4;
1.3344 +
1.3345 + /* Entry count */
1.3346 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsEntryCount);
1.3347 + i += 4;
1.3348 +
1.3349 + if (writeFile(handle, buf, i) < 0)
1.3350 + {
1.3351 + mp4free(buf);
1.3352 + mp4free(buf2);
1.3353 +
1.3354 + return -1;
1.3355 + }
1.3356 +
1.3357 + /* Sample count and delta */
1.3358 +
1.3359 + /* Seek to the beginning of temporary files */
1.3360 +
1.3361 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0)
1.3362 + {
1.3363 + mp4free(buf);
1.3364 + mp4free(buf2);
1.3365 + return -1;
1.3366 + }
1.3367 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0)
1.3368 + {
1.3369 + mp4free(buf);
1.3370 + mp4free(buf2);
1.3371 + return -1;
1.3372 + }
1.3373 +
1.3374 + left = handle->videoSampleTable->sttsEntryCount * 4; /* Bytes left in each file */
1.3375 +
1.3376 + while (left)
1.3377 + {
1.3378 + if (left > METADATA_COPY_BUFFERSIZE / 2)
1.3379 + bytestoread = METADATA_COPY_BUFFERSIZE / 2;
1.3380 + else
1.3381 + bytestoread = left;
1.3382 +
1.3383 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0)
1.3384 + {
1.3385 + mp4free(buf);
1.3386 + mp4free(buf2);
1.3387 +
1.3388 + return -1;
1.3389 + }
1.3390 +
1.3391 + for (j = 0; j < bytestoread; j += 4)
1.3392 + {
1.3393 + insertu32(buf + 2*j, ((mp4_u32 *)buf2)[j / 4]);
1.3394 + }
1.3395 +
1.3396 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0)
1.3397 + {
1.3398 + mp4free(buf);
1.3399 + mp4free(buf2);
1.3400 +
1.3401 + return -1;
1.3402 + }
1.3403 +
1.3404 + for (j = 0; j < bytestoread; j += 4)
1.3405 + {
1.3406 + insertu32(buf + 2*j + 4, ((mp4_u32 *)buf2)[j / 4]);
1.3407 + }
1.3408 +
1.3409 + if (writeFile(handle, buf, 2 * bytestoread) < 0)
1.3410 + {
1.3411 + mp4free(buf);
1.3412 + mp4free(buf2);
1.3413 +
1.3414 + return -1;
1.3415 + }
1.3416 +
1.3417 + left -= bytestoread;
1.3418 + }
1.3419 +
1.3420 + mp4free(buf);
1.3421 + mp4free(buf2);
1.3422 +
1.3423 +
1.3424 + return 0;
1.3425 +}
1.3426 +
1.3427 +
1.3428 +/*
1.3429 + * Function:
1.3430 + *
1.3431 + * mp4_i32 writeVideoSTSC(MP4HandleImp handle,
1.3432 + * trakSize *ts)
1.3433 + *
1.3434 + * Description:
1.3435 + *
1.3436 + * Write video STSC atom.
1.3437 + *
1.3438 + * Parameters:
1.3439 + *
1.3440 + * handle MP4 library handle
1.3441 + * ts Atom sizes
1.3442 + *
1.3443 + * Return value:
1.3444 + *
1.3445 + * 0 Success
1.3446 + * -1 Error
1.3447 + *
1.3448 + */
1.3449 +mp4_i32 writeVideoSTSC(MP4HandleImp handle, trakSize *ts)
1.3450 +{
1.3451 + mp4_u8 *buf;
1.3452 + mp4_u32 i = 0;
1.3453 + mp4_u32 j;
1.3454 +
1.3455 +
1.3456 + buf = (mp4_u8 *)mp4malloc(ts->stsc);
1.3457 + if (buf == NULL)
1.3458 + return -1;
1.3459 +
1.3460 + /* Size */
1.3461 + insertu32(buf+i, (mp4_u32)ts->stsc);
1.3462 + i += 4;
1.3463 +
1.3464 + /* Atom type */
1.3465 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSC);
1.3466 + i += 4;
1.3467 +
1.3468 + /* Version and flags */
1.3469 + insertu32(buf+i, (mp4_u32)0);
1.3470 + i += 4;
1.3471 +
1.3472 + /* Entry count */
1.3473 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscEntryCount);
1.3474 + i += 4;
1.3475 +
1.3476 + /* First chunk, samples per chunk and sample description index */
1.3477 + for (j = 0; j < handle->videoSampleTable->stscEntryCount; j++)
1.3478 + {
1.3479 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscFirstChunk[j]);
1.3480 + i += 4;
1.3481 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscSamplesPerChunk[j]);
1.3482 + i += 4;
1.3483 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscSampleDescriptionIndex[j]);
1.3484 + i += 4;
1.3485 + }
1.3486 +
1.3487 + if (writeFile(handle, buf, ts->stsc) < 0)
1.3488 + {
1.3489 + mp4free(buf);
1.3490 +
1.3491 + return -1;
1.3492 + }
1.3493 +
1.3494 + mp4free(buf);
1.3495 +
1.3496 + return 0;
1.3497 +}
1.3498 +
1.3499 +
1.3500 +/*
1.3501 + * Function:
1.3502 + *
1.3503 + * mp4_i32 writeVideoSTSZ(MP4HandleImp handle,
1.3504 + * trakSize *ts)
1.3505 + *
1.3506 + * Description:
1.3507 + *
1.3508 + * Write video STSZ atom.
1.3509 + *
1.3510 + * Parameters:
1.3511 + *
1.3512 + * handle MP4 library handle
1.3513 + * ts Atom sizes
1.3514 + *
1.3515 + * Return value:
1.3516 + *
1.3517 + * 0 Success
1.3518 + * -1 Error
1.3519 + *
1.3520 + */
1.3521 +mp4_i32 writeVideoSTSZ(MP4HandleImp handle, trakSize *ts)
1.3522 +{
1.3523 + mp4_u8 *buf;
1.3524 + mp4_u32 i = 0;
1.3525 + mp4_u32 j;
1.3526 +
1.3527 +
1.3528 + buf = (mp4_u8 *)mp4malloc(ts->stsz);
1.3529 + if (buf == NULL)
1.3530 + return -1;
1.3531 +
1.3532 + /* Size */
1.3533 + insertu32(buf+i, (mp4_u32)ts->stsz);
1.3534 + i += 4;
1.3535 +
1.3536 + /* Atom type */
1.3537 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ);
1.3538 + i += 4;
1.3539 +
1.3540 + /* Version and flags */
1.3541 + insertu32(buf+i, (mp4_u32)0);
1.3542 + i += 4;
1.3543 +
1.3544 + /* Sample size */
1.3545 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleSize);
1.3546 + i += 4;
1.3547 +
1.3548 + /* Sample count */
1.3549 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleCount);
1.3550 + i += 4;
1.3551 +
1.3552 + /* Entry sizes */
1.3553 + if (handle->videoSampleTable->stszSampleSize == 0)
1.3554 + {
1.3555 + for (j = 0; j < handle->videoSampleTable->stszSampleCount; j++)
1.3556 + {
1.3557 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszEntrySize[j]);
1.3558 + i += 4;
1.3559 + }
1.3560 + }
1.3561 +
1.3562 + if (writeFile(handle, buf, ts->stsz) < 0)
1.3563 + {
1.3564 + mp4free(buf);
1.3565 +
1.3566 + return -1;
1.3567 + }
1.3568 +
1.3569 + mp4free(buf);
1.3570 +
1.3571 + return 0;
1.3572 +}
1.3573 +
1.3574 +
1.3575 +/*
1.3576 + * Function:
1.3577 + *
1.3578 + * mp4_i32 writeVideoSTSZLongClip(MP4HandleImp handle,
1.3579 + * trakSize *ts)
1.3580 + *
1.3581 + * Description:
1.3582 + *
1.3583 + * Write video STSZ atom.
1.3584 + *
1.3585 + * Parameters:
1.3586 + *
1.3587 + * handle MP4 library handle
1.3588 + * ts Atom sizes
1.3589 + *
1.3590 + * Return value:
1.3591 + *
1.3592 + * 0 Success
1.3593 + * -1 Error
1.3594 + *
1.3595 + */
1.3596 +mp4_i32 writeVideoSTSZLongClip(MP4HandleImp handle, trakSize *ts)
1.3597 +{
1.3598 + mp4_u8 *buf;
1.3599 + mp4_u8 *buf2;
1.3600 + mp4_u32 i = 0;
1.3601 + mp4_u32 j;
1.3602 + mp4_u32 left;
1.3603 + mp4_u32 bytestoread;
1.3604 +
1.3605 +
1.3606 + buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.3607 + if (buf == NULL)
1.3608 + return -1;
1.3609 +
1.3610 + buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.3611 + if (buf2 == NULL)
1.3612 + {
1.3613 + mp4free(buf);
1.3614 + return -1;
1.3615 + }
1.3616 +
1.3617 + /* Size */
1.3618 + insertu32(buf+i, (mp4_u32)ts->stsz);
1.3619 + i += 4;
1.3620 +
1.3621 + /* Atom type */
1.3622 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ);
1.3623 + i += 4;
1.3624 +
1.3625 + /* Version and flags */
1.3626 + insertu32(buf+i, (mp4_u32)0);
1.3627 + i += 4;
1.3628 +
1.3629 + /* Sample size */
1.3630 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleSize);
1.3631 + i += 4;
1.3632 +
1.3633 + /* Sample count */
1.3634 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleCount);
1.3635 + i += 4;
1.3636 +
1.3637 + if (writeFile(handle, buf, i) < 0)
1.3638 + {
1.3639 + mp4free(buf);
1.3640 + mp4free(buf2);
1.3641 +
1.3642 + return -1;
1.3643 + }
1.3644 +
1.3645 + /* Entry sizes */
1.3646 +
1.3647 + if (handle->videoSampleTable->stszSampleSize == 0)
1.3648 + {
1.3649 + /* Seek to the beginning of temporary file */
1.3650 +
1.3651 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0)
1.3652 + {
1.3653 + mp4free(buf);
1.3654 + mp4free(buf2);
1.3655 + return -1;
1.3656 + }
1.3657 +
1.3658 + left = handle->videoSampleTable->stszSampleCount * 4; /* Bytes left in the file */
1.3659 +
1.3660 + while (left)
1.3661 + {
1.3662 + if (left > METADATA_COPY_BUFFERSIZE)
1.3663 + bytestoread = METADATA_COPY_BUFFERSIZE;
1.3664 + else
1.3665 + bytestoread = left;
1.3666 +
1.3667 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0)
1.3668 + {
1.3669 + mp4free(buf);
1.3670 + mp4free(buf2);
1.3671 +
1.3672 + return -1;
1.3673 + }
1.3674 +
1.3675 + for (j = 0; j < bytestoread; j += 4)
1.3676 + {
1.3677 + insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]);
1.3678 + }
1.3679 +
1.3680 + if (writeFile(handle, buf, bytestoread) < 0)
1.3681 + {
1.3682 + mp4free(buf);
1.3683 + mp4free(buf2);
1.3684 +
1.3685 + return -1;
1.3686 + }
1.3687 +
1.3688 + left -= bytestoread;
1.3689 + }
1.3690 + }
1.3691 +
1.3692 + mp4free(buf);
1.3693 + mp4free(buf2);
1.3694 +
1.3695 +
1.3696 + return 0;
1.3697 +}
1.3698 +
1.3699 +
1.3700 +/*
1.3701 + * Function:
1.3702 + *
1.3703 + * mp4_i32 writeVideoSTCO(MP4HandleImp handle,
1.3704 + * trakSize *ts)
1.3705 + *
1.3706 + * Description:
1.3707 + *
1.3708 + * Write video STCO atom.
1.3709 + *
1.3710 + * Parameters:
1.3711 + *
1.3712 + * handle MP4 library handle
1.3713 + * ts Atom sizes
1.3714 + *
1.3715 + * Return value:
1.3716 + *
1.3717 + * 0 Success
1.3718 + * -1 Error
1.3719 + *
1.3720 + */
1.3721 +mp4_i32 writeVideoSTCO(MP4HandleImp handle, trakSize *ts)
1.3722 +{
1.3723 + mp4_u8 *buf;
1.3724 + mp4_u32 i = 0;
1.3725 + mp4_u32 j;
1.3726 +
1.3727 +
1.3728 + buf = (mp4_u8 *)mp4malloc(ts->stco);
1.3729 + if (buf == NULL)
1.3730 + return -1;
1.3731 +
1.3732 + /* Size */
1.3733 + insertu32(buf+i, (mp4_u32)ts->stco);
1.3734 + i += 4;
1.3735 +
1.3736 + /* Atom type */
1.3737 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO);
1.3738 + i += 4;
1.3739 +
1.3740 + /* Version and flags */
1.3741 + insertu32(buf+i, (mp4_u32)0);
1.3742 + i += 4;
1.3743 +
1.3744 + /* Entry count */
1.3745 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount);
1.3746 + i += 4;
1.3747 +
1.3748 + /* Chunk offsets */
1.3749 + for (j = 0; j < handle->videoSampleTable->stcoEntryCount; j++)
1.3750 + {
1.3751 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoChunkOffset[j]);
1.3752 + i += 4;
1.3753 + }
1.3754 +
1.3755 + if (writeFile(handle, buf, ts->stco) < 0)
1.3756 + {
1.3757 + mp4free(buf);
1.3758 +
1.3759 + return -1;
1.3760 + }
1.3761 +
1.3762 + mp4free(buf);
1.3763 +
1.3764 + return 0;
1.3765 +}
1.3766 +
1.3767 +/*
1.3768 + * Function:
1.3769 + *
1.3770 + * mp4_i32 writeVideoCO64(MP4HandleImp handle,
1.3771 + * trakSize *ts)
1.3772 + *
1.3773 + * Description:
1.3774 + *
1.3775 + * Write video CO64 atom.
1.3776 + *
1.3777 + * Parameters:
1.3778 + *
1.3779 + * handle MP4 library handle
1.3780 + * ts Atom sizes
1.3781 + *
1.3782 + * Return value:
1.3783 + *
1.3784 + * 0 Success
1.3785 + * -1 Error
1.3786 + *
1.3787 + */
1.3788 +mp4_i32 writeVideoCO64(MP4HandleImp handle, trakSize *ts)
1.3789 +{
1.3790 + mp4_u8 *buf;
1.3791 + mp4_u32 i = 0;
1.3792 + mp4_u32 j;
1.3793 +
1.3794 +
1.3795 + buf = (mp4_u8 *)mp4malloc(ts->stco);
1.3796 + if (buf == NULL)
1.3797 + return -1;
1.3798 +
1.3799 + /* Size */
1.3800 + insertu32(buf+i, (mp4_u32)ts->stco);
1.3801 + i += 4;
1.3802 +
1.3803 + /* Atom type */
1.3804 + insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64);
1.3805 + i += 4;
1.3806 +
1.3807 + /* Version and flags */
1.3808 + insertu32(buf+i, (mp4_u32)0);
1.3809 + i += 4;
1.3810 +
1.3811 + /* Entry count */
1.3812 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount);
1.3813 + i += 4;
1.3814 +
1.3815 + /* Chunk offsets */
1.3816 + for (j = 0; j < handle->videoSampleTable->stcoEntryCount; j++)
1.3817 + {
1.3818 + insertu64(buf+i, (mp4_u64)handle->videoSampleTable->stcoChunkOffset[j]);
1.3819 + i += 8;
1.3820 + }
1.3821 +
1.3822 + if (writeFile(handle, buf, ts->stco) < 0)
1.3823 + {
1.3824 + mp4free(buf);
1.3825 +
1.3826 + return -1;
1.3827 + }
1.3828 +
1.3829 + mp4free(buf);
1.3830 +
1.3831 + return 0;
1.3832 +}
1.3833 +
1.3834 +/*
1.3835 + * Function:
1.3836 + *
1.3837 + * mp4_i32 writeVideoSTCOLongClip(MP4HandleImp handle,
1.3838 + * trakSize *ts)
1.3839 + *
1.3840 + * Description:
1.3841 + *
1.3842 + * Write video STCO atom.
1.3843 + *
1.3844 + * Parameters:
1.3845 + *
1.3846 + * handle MP4 library handle
1.3847 + * ts Atom sizes
1.3848 + *
1.3849 + * Return value:
1.3850 + *
1.3851 + * 0 Success
1.3852 + * -1 Error
1.3853 + *
1.3854 + */
1.3855 +mp4_i32 writeVideoSTCOLongClip(MP4HandleImp handle, trakSize *ts)
1.3856 +{
1.3857 + mp4_u8 *buf;
1.3858 + mp4_u8 *buf2;
1.3859 + mp4_u32 i = 0;
1.3860 + mp4_u32 j;
1.3861 + mp4_u32 left;
1.3862 + mp4_u32 bytestoread;
1.3863 + mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64
1.3864 + //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4
1.3865 +
1.3866 + buf = (mp4_u8 *)mp4malloc(bufferSize);
1.3867 + if (buf == NULL)
1.3868 + return -1;
1.3869 +
1.3870 + buf2 = (mp4_u8 *)mp4malloc(bufferSize);
1.3871 + if (buf2 == NULL)
1.3872 + {
1.3873 + mp4free(buf);
1.3874 + return -1;
1.3875 + }
1.3876 +
1.3877 + /* Size */
1.3878 + insertu32(buf+i, (mp4_u32)ts->stco);
1.3879 + i += 4;
1.3880 +
1.3881 + /* Atom type */
1.3882 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO);
1.3883 + i += 4;
1.3884 +
1.3885 + /* Version and flags */
1.3886 + insertu32(buf+i, (mp4_u32)0);
1.3887 + i += 4;
1.3888 +
1.3889 + /* Entry count */
1.3890 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount);
1.3891 + i += 4;
1.3892 +
1.3893 + if (writeFile(handle, buf, i) < 0)
1.3894 + {
1.3895 + mp4free(buf);
1.3896 + mp4free(buf2);
1.3897 +
1.3898 + return -1;
1.3899 + }
1.3900 +
1.3901 + /* Chunk offsets */
1.3902 +
1.3903 + /* Seek to the beginning of temporary file */
1.3904 +
1.3905 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0)
1.3906 + {
1.3907 + mp4free(buf);
1.3908 + mp4free(buf2);
1.3909 + return -1;
1.3910 + }
1.3911 +
1.3912 + left = handle->videoSampleTable->stcoEntryCount * 8; /* Bytes left in the file */
1.3913 +
1.3914 + while (left)
1.3915 + {
1.3916 + if (left > bufferSize)
1.3917 + bytestoread = bufferSize;
1.3918 + else
1.3919 + bytestoread = left;
1.3920 +
1.3921 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0)
1.3922 + {
1.3923 + mp4free(buf);
1.3924 + mp4free(buf2);
1.3925 +
1.3926 + return -1;
1.3927 + }
1.3928 +
1.3929 + for (j = 0; j < bytestoread; j += 8)
1.3930 + {
1.3931 + ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */
1.3932 + insertu32(buf + j/2, ((mp4_u64 *)buf2)[j / 8]);
1.3933 + }
1.3934 +
1.3935 + if (writeFile(handle, buf, bytestoread/2) < 0)
1.3936 + {
1.3937 + mp4free(buf);
1.3938 + mp4free(buf2);
1.3939 +
1.3940 + return -1;
1.3941 + }
1.3942 +
1.3943 + left -= bytestoread;
1.3944 + }
1.3945 +
1.3946 + mp4free(buf);
1.3947 + mp4free(buf2);
1.3948 +
1.3949 +
1.3950 + return 0;
1.3951 +}
1.3952 +
1.3953 +/*
1.3954 + * Function:
1.3955 + *
1.3956 + * mp4_i32 writeVideoCO64LongClip(MP4HandleImp handle,
1.3957 + * trakSize *ts)
1.3958 + *
1.3959 + * Description:
1.3960 + *
1.3961 + * Write video CO64 atom.
1.3962 + *
1.3963 + * Parameters:
1.3964 + *
1.3965 + * handle MP4 library handle
1.3966 + * ts Atom sizes
1.3967 + *
1.3968 + * Return value:
1.3969 + *
1.3970 + * 0 Success
1.3971 + * -1 Error
1.3972 + *
1.3973 + */
1.3974 +mp4_i32 writeVideoCO64LongClip(MP4HandleImp handle, trakSize *ts)
1.3975 +{
1.3976 + mp4_u8 *buf;
1.3977 + mp4_u8 *buf2;
1.3978 + mp4_u32 i = 0;
1.3979 + mp4_u32 j;
1.3980 + mp4_u32 left;
1.3981 + mp4_u32 bytestoread;
1.3982 + mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64
1.3983 + //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4
1.3984 +
1.3985 + buf = (mp4_u8 *)mp4malloc(bufferSize);
1.3986 + if (buf == NULL)
1.3987 + return -1;
1.3988 +
1.3989 + buf2 = (mp4_u8 *)mp4malloc(bufferSize);
1.3990 + if (buf2 == NULL)
1.3991 + {
1.3992 + mp4free(buf);
1.3993 + return -1;
1.3994 + }
1.3995 +
1.3996 + /* Size */
1.3997 + insertu32(buf+i, (mp4_u32)ts->stco);
1.3998 + i += 4;
1.3999 +
1.4000 + /* Atom type */
1.4001 + insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64);
1.4002 + i += 4;
1.4003 +
1.4004 + /* Version and flags */
1.4005 + insertu32(buf+i, (mp4_u32)0);
1.4006 + i += 4;
1.4007 +
1.4008 + /* Entry count */
1.4009 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount);
1.4010 + i += 4;
1.4011 +
1.4012 + if (writeFile(handle, buf, i) < 0)
1.4013 + {
1.4014 + mp4free(buf);
1.4015 + mp4free(buf2);
1.4016 +
1.4017 + return -1;
1.4018 + }
1.4019 +
1.4020 + /* Chunk offsets */
1.4021 +
1.4022 + /* Seek to the beginning of temporary file */
1.4023 +
1.4024 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0)
1.4025 + {
1.4026 + mp4free(buf);
1.4027 + mp4free(buf2);
1.4028 + return -1;
1.4029 + }
1.4030 +
1.4031 + left = handle->videoSampleTable->stcoEntryCount * 8; /* Bytes left in the file */
1.4032 +
1.4033 + while (left)
1.4034 + {
1.4035 + if (left > bufferSize)
1.4036 + bytestoread = bufferSize;
1.4037 + else
1.4038 + bytestoread = left;
1.4039 +
1.4040 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0)
1.4041 + {
1.4042 + mp4free(buf);
1.4043 + mp4free(buf2);
1.4044 +
1.4045 + return -1;
1.4046 + }
1.4047 +
1.4048 + for (j = 0; j < bytestoread; j += 8)
1.4049 + {
1.4050 + ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */
1.4051 + insertu64(buf + j, ((mp4_u64 *)buf2)[j / 8]);
1.4052 + }
1.4053 +
1.4054 + if (writeFile(handle, buf, bytestoread) < 0)
1.4055 + {
1.4056 + mp4free(buf);
1.4057 + mp4free(buf2);
1.4058 +
1.4059 + return -1;
1.4060 + }
1.4061 +
1.4062 + left -= bytestoread;
1.4063 + }
1.4064 +
1.4065 + mp4free(buf);
1.4066 + mp4free(buf2);
1.4067 +
1.4068 +
1.4069 + return 0;
1.4070 +}
1.4071 +
1.4072 +/*
1.4073 + * Function:
1.4074 + *
1.4075 + * mp4_i32 writeVideoSTSS(MP4HandleImp handle,
1.4076 + * trakSize *ts)
1.4077 + *
1.4078 + * Description:
1.4079 + *
1.4080 + * Write video STSS atom.
1.4081 + *
1.4082 + * Parameters:
1.4083 + *
1.4084 + * handle MP4 library handle
1.4085 + * ts Atom sizes
1.4086 + *
1.4087 + * Return value:
1.4088 + *
1.4089 + * 0 Success
1.4090 + * -1 Error
1.4091 + *
1.4092 + */
1.4093 +mp4_i32 writeVideoSTSS(MP4HandleImp handle, trakSize *ts)
1.4094 +{
1.4095 + mp4_u8 *buf;
1.4096 + mp4_u32 i = 0;
1.4097 + mp4_u32 j;
1.4098 +
1.4099 +
1.4100 + buf = (mp4_u8 *)mp4malloc(ts->stss);
1.4101 + if (buf == NULL)
1.4102 + return -1;
1.4103 +
1.4104 + /* Size */
1.4105 + insertu32(buf+i, (mp4_u32)ts->stss);
1.4106 + i += 4;
1.4107 +
1.4108 + /* Atom type */
1.4109 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSS);
1.4110 + i += 4;
1.4111 +
1.4112 + /* Version and flags */
1.4113 + insertu32(buf+i, (mp4_u32)0);
1.4114 + i += 4;
1.4115 +
1.4116 + /* Entry count */
1.4117 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssEntryCount);
1.4118 + i += 4;
1.4119 +
1.4120 + /* Sample numbers */
1.4121 + for (j = 0; j < handle->videoSampleTable->stssEntryCount; j++)
1.4122 + {
1.4123 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssSampleNumber[j]);
1.4124 + i += 4;
1.4125 + }
1.4126 +
1.4127 + if (writeFile(handle, buf, ts->stss) < 0)
1.4128 + {
1.4129 + mp4free(buf);
1.4130 +
1.4131 + return -1;
1.4132 + }
1.4133 +
1.4134 + mp4free(buf);
1.4135 +
1.4136 + return 0;
1.4137 +}
1.4138 +
1.4139 +
1.4140 +/*
1.4141 + * Function:
1.4142 + *
1.4143 + * mp4_i32 writeVideoSTSSLongClip(MP4HandleImp handle,
1.4144 + * trakSize *ts)
1.4145 + *
1.4146 + * Description:
1.4147 + *
1.4148 + * Write video STSS atom.
1.4149 + *
1.4150 + * Parameters:
1.4151 + *
1.4152 + * handle MP4 library handle
1.4153 + * ts Atom sizes
1.4154 + *
1.4155 + * Return value:
1.4156 + *
1.4157 + * 0 Success
1.4158 + * -1 Error
1.4159 + *
1.4160 + */
1.4161 +mp4_i32 writeVideoSTSSLongClip(MP4HandleImp handle, trakSize *ts)
1.4162 +{
1.4163 + mp4_u8 *buf;
1.4164 + mp4_u8 *buf2;
1.4165 + mp4_u32 i = 0;
1.4166 + mp4_u32 j;
1.4167 + mp4_u32 left;
1.4168 + mp4_u32 bytestoread;
1.4169 +
1.4170 +
1.4171 + buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.4172 + if (buf == NULL)
1.4173 + return -1;
1.4174 +
1.4175 + buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.4176 + if (buf2 == NULL)
1.4177 + {
1.4178 + mp4free(buf);
1.4179 + return -1;
1.4180 + }
1.4181 +
1.4182 + /* Size */
1.4183 + insertu32(buf+i, (mp4_u32)ts->stss);
1.4184 + i += 4;
1.4185 +
1.4186 + /* Atom type */
1.4187 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSS);
1.4188 + i += 4;
1.4189 +
1.4190 + /* Version and flags */
1.4191 + insertu32(buf+i, (mp4_u32)0);
1.4192 + i += 4;
1.4193 +
1.4194 + /* Entry count */
1.4195 + insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssEntryCount);
1.4196 + i += 4;
1.4197 +
1.4198 + if (writeFile(handle, buf, i) < 0)
1.4199 + {
1.4200 + mp4free(buf);
1.4201 + mp4free(buf2);
1.4202 +
1.4203 + return -1;
1.4204 + }
1.4205 +
1.4206 + /* Sample numbers */
1.4207 +
1.4208 + /* Seek to the beginning of temporary file */
1.4209 +
1.4210 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0)
1.4211 + {
1.4212 + mp4free(buf);
1.4213 + mp4free(buf2);
1.4214 + return -1;
1.4215 + }
1.4216 +
1.4217 + left = handle->videoSampleTable->stssEntryCount * 4; /* Bytes left in the file */
1.4218 +
1.4219 + while (left)
1.4220 + {
1.4221 + if (left > METADATA_COPY_BUFFERSIZE)
1.4222 + bytestoread = METADATA_COPY_BUFFERSIZE;
1.4223 + else
1.4224 + bytestoread = left;
1.4225 +
1.4226 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0)
1.4227 + {
1.4228 + mp4free(buf);
1.4229 + mp4free(buf2);
1.4230 +
1.4231 + return -1;
1.4232 + }
1.4233 +
1.4234 + for (j = 0; j < bytestoread; j += 4)
1.4235 + {
1.4236 + insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]);
1.4237 + }
1.4238 +
1.4239 + if (writeFile(handle, buf, bytestoread) < 0)
1.4240 + {
1.4241 + mp4free(buf);
1.4242 + mp4free(buf2);
1.4243 +
1.4244 + return -1;
1.4245 + }
1.4246 +
1.4247 + left -= bytestoread;
1.4248 + }
1.4249 +
1.4250 + mp4free(buf);
1.4251 + mp4free(buf2);
1.4252 +
1.4253 +
1.4254 + return 0;
1.4255 +}
1.4256 +
1.4257 +
1.4258 +/*
1.4259 + * Function:
1.4260 + *
1.4261 + * mp4_i32 writeAudioTrak(MP4HandleImp handle,
1.4262 + * trakSize *ts)
1.4263 + *
1.4264 + * Description:
1.4265 + *
1.4266 + * Write audio track atom.
1.4267 + *
1.4268 + * Parameters:
1.4269 + *
1.4270 + * handle MP4 library handle
1.4271 + * ts Atom sizes
1.4272 + *
1.4273 + * Return value:
1.4274 + *
1.4275 + * 0 Success
1.4276 + * -1 Error
1.4277 + *
1.4278 + */
1.4279 +mp4_i32 writeAudioTrak(MP4HandleImp handle, trakSize *ts)
1.4280 +{
1.4281 + mp4_u8 buf[8];
1.4282 + mp4_u32 i = 0;
1.4283 +
1.4284 +
1.4285 + /* Size */
1.4286 + insertu32(buf+i, (mp4_u32)ts->trak);
1.4287 + i += 4;
1.4288 +
1.4289 + /* Atom type */
1.4290 + insertu32(buf+i, (mp4_u32)ATOMTYPE_TRAK);
1.4291 + i += 4;
1.4292 +
1.4293 + if (writeFile(handle, buf, 8) < 0)
1.4294 + return -1;
1.4295 +
1.4296 + if (writeAudioTKHD(handle, ts) < 0)
1.4297 + return -1;
1.4298 +
1.4299 + if (writeAudioMDIA(handle, ts) < 0)
1.4300 + return -1;
1.4301 +
1.4302 + if (handle->audioUDTA)
1.4303 + {
1.4304 + if (writeUDTA(handle, handle->audioUDTA) < 0)
1.4305 + return -1;
1.4306 + }
1.4307 +
1.4308 + return 0;
1.4309 +}
1.4310 +
1.4311 +
1.4312 +/*
1.4313 + * Function:
1.4314 + *
1.4315 + * mp4_i32 writeAudioTKHD(MP4HandleImp handle,
1.4316 + * trakSize *ts)
1.4317 + *
1.4318 + * Description:
1.4319 + *
1.4320 + * Write audio TKHD atom.
1.4321 + *
1.4322 + * Parameters:
1.4323 + *
1.4324 + * handle MP4 library handle
1.4325 + * ts Atom sizes
1.4326 + *
1.4327 + * Return value:
1.4328 + *
1.4329 + * 0 Success
1.4330 + * -1 Error
1.4331 + *
1.4332 + */
1.4333 +mp4_i32 writeAudioTKHD(MP4HandleImp handle, trakSize *ts)
1.4334 +{
1.4335 + mp4_u8 *buf;
1.4336 + mp4_u32 i = 0;
1.4337 + mp4_u32 u32;
1.4338 + mp4_double ud;
1.4339 +
1.4340 +
1.4341 + buf = (mp4_u8 *)mp4malloc(ts->tkhd);
1.4342 + if (buf == NULL)
1.4343 + return -1;
1.4344 +
1.4345 + /* Size */
1.4346 + insertu32(buf+i, (mp4_u32)ts->tkhd);
1.4347 + i += 4;
1.4348 +
1.4349 + /* Atom type */
1.4350 + insertu32(buf+i, (mp4_u32)ATOMTYPE_TKHD);
1.4351 + i += 4;
1.4352 +
1.4353 +
1.4354 + if (handle->audioDuration > MP4_INT_MAX)
1.4355 + {
1.4356 + mp4_u64 u64;
1.4357 + /* Version and flags */
1.4358 + buf[i++] = 1;
1.4359 + buf[i++] = 0;
1.4360 + buf[i++] = 0;
1.4361 + buf[i++] = 7; /* Track enabled, used in movie and preview */
1.4362 +
1.4363 + /* Creation time */
1.4364 + if (getCurrentTime(&u32) < 0)
1.4365 + u32 = 0;
1.4366 + insertu64(buf+i, (mp4_u64)u32);
1.4367 + i += 8;
1.4368 +
1.4369 + /* Modification time */
1.4370 + if (getCurrentTime(&u32) < 0)
1.4371 + u32 = 0;
1.4372 + insertu64(buf+i, (mp4_u64)u32);
1.4373 + i += 8;
1.4374 +
1.4375 + /* Track ID */
1.4376 + insertu32(buf+i, (mp4_u32)2);
1.4377 + i += 4;
1.4378 +
1.4379 + /* Reserved */
1.4380 + insertu32(buf+i, (mp4_u32)0);
1.4381 + i += 4;
1.4382 +
1.4383 + /* Duration */
1.4384 + if ( ( handle->audioTimeScale == 0 ) || ( handle->audioDuration == 0 ) )
1.4385 + {
1.4386 + ud = 0;
1.4387 + }
1.4388 + else
1.4389 + {
1.4390 + ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->audioDuration / (mp4_double)handle->audioTimeScale + (mp4_double)0.5;
1.4391 + }
1.4392 + u64 = (mp4_u64)ud;
1.4393 + insertu64(buf+i, u64);
1.4394 + i += 8;
1.4395 +
1.4396 + }
1.4397 + else
1.4398 + {
1.4399 + /* Version and flags */
1.4400 + buf[i++] = 0;
1.4401 + buf[i++] = 0;
1.4402 + buf[i++] = 0;
1.4403 + buf[i++] = 7; /* Track enabled, used in movie and preview */
1.4404 +
1.4405 + /* Creation time */
1.4406 + if (getCurrentTime(&u32) < 0)
1.4407 + u32 = 0;
1.4408 + insertu32(buf+i, (mp4_u32)u32);
1.4409 + i += 4;
1.4410 +
1.4411 + /* Modification time */
1.4412 + if (getCurrentTime(&u32) < 0)
1.4413 + u32 = 0;
1.4414 + insertu32(buf+i, (mp4_u32)u32);
1.4415 + i += 4;
1.4416 +
1.4417 + /* Track ID */
1.4418 + insertu32(buf+i, (mp4_u32)2);
1.4419 + i += 4;
1.4420 +
1.4421 + /* Reserved */
1.4422 + insertu32(buf+i, (mp4_u32)0);
1.4423 + i += 4;
1.4424 +
1.4425 + /* Duration */
1.4426 + if ( ( handle->audioTimeScale == 0 ) || ( handle->audioDuration == 0 ) )
1.4427 + {
1.4428 + ud = 0;
1.4429 + }
1.4430 + else
1.4431 + {
1.4432 + ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->audioDuration / (mp4_double)handle->audioTimeScale + (mp4_double)0.5;
1.4433 + }
1.4434 + u32 = (mp4_u32)ud;
1.4435 + insertu32(buf+i, u32);
1.4436 + i += 4;
1.4437 + }
1.4438 + /* Reserved */
1.4439 + insertu32(buf+i, (mp4_u32)0);
1.4440 + i += 4;
1.4441 +
1.4442 + insertu32(buf+i, (mp4_u32)0);
1.4443 + i += 4;
1.4444 +
1.4445 + insertu32(buf+i, (mp4_u32)0);
1.4446 + i += 4;
1.4447 +
1.4448 + insertu16(buf+i, (mp4_u16)0x0100); /* Audio track */
1.4449 + i += 2;
1.4450 +
1.4451 + insertu16(buf+i, (mp4_u16)0);
1.4452 + i += 2;
1.4453 +
1.4454 + insertu32(buf+i, (mp4_u32)0x00010000);
1.4455 + i += 4;
1.4456 +
1.4457 + insertu32(buf+i, (mp4_u32)0x00000000);
1.4458 + i += 4;
1.4459 +
1.4460 + insertu32(buf+i, (mp4_u32)0x00000000);
1.4461 + i += 4;
1.4462 +
1.4463 + insertu32(buf+i, (mp4_u32)0x00000000);
1.4464 + i += 4;
1.4465 +
1.4466 + insertu32(buf+i, (mp4_u32)0x00010000);
1.4467 + i += 4;
1.4468 +
1.4469 + insertu32(buf+i, (mp4_u32)0x00000000);
1.4470 + i += 4;
1.4471 +
1.4472 + insertu32(buf+i, (mp4_u32)0x00000000);
1.4473 + i += 4;
1.4474 +
1.4475 + insertu32(buf+i, (mp4_u32)0x00000000);
1.4476 + i += 4;
1.4477 +
1.4478 + insertu32(buf+i, (mp4_u32)0x40000000);
1.4479 + i += 4;
1.4480 +
1.4481 + insertu32(buf+i, (mp4_u32)0); /* Audio track */
1.4482 + i += 4;
1.4483 +
1.4484 + insertu32(buf+i, (mp4_u32)0); /* Audio track */
1.4485 + i += 4;
1.4486 +
1.4487 + if (writeFile(handle, buf, ts->tkhd) < 0)
1.4488 + {
1.4489 + mp4free(buf);
1.4490 +
1.4491 + return -1;
1.4492 + }
1.4493 +
1.4494 + mp4free(buf);
1.4495 +
1.4496 + return 0;
1.4497 +}
1.4498 +
1.4499 +
1.4500 +/*
1.4501 + * Function:
1.4502 + *
1.4503 + * mp4_i32 writeAudioMDIA(MP4HandleImp handle,
1.4504 + * trakSize *ts)
1.4505 + *
1.4506 + * Description:
1.4507 + *
1.4508 + * Write audio MDIA atom.
1.4509 + *
1.4510 + * Parameters:
1.4511 + *
1.4512 + * handle MP4 library handle
1.4513 + * ts Atom sizes
1.4514 + *
1.4515 + * Return value:
1.4516 + *
1.4517 + * 0 Success
1.4518 + * -1 Error
1.4519 + *
1.4520 + */
1.4521 +mp4_i32 writeAudioMDIA(MP4HandleImp handle, trakSize *ts)
1.4522 +{
1.4523 + mp4_u8 buf[8];
1.4524 + mp4_u32 i = 0;
1.4525 +
1.4526 +
1.4527 + /* Size */
1.4528 + insertu32(buf+i, (mp4_u32)ts->mdia);
1.4529 + i += 4;
1.4530 +
1.4531 + /* Atom type */
1.4532 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MDIA);
1.4533 + i += 4;
1.4534 +
1.4535 + if (writeFile(handle, buf, 8) < 0)
1.4536 + return -1;
1.4537 +
1.4538 + if (writeAudioMDHD(handle, ts) < 0)
1.4539 + return -1;
1.4540 +
1.4541 + if (writeAudioHDLR(handle, ts) < 0)
1.4542 + return -1;
1.4543 +
1.4544 + if (writeAudioMINF(handle, ts) < 0)
1.4545 + return -1;
1.4546 +
1.4547 + return 0;
1.4548 +}
1.4549 +
1.4550 +
1.4551 +/*
1.4552 + * Function:
1.4553 + *
1.4554 + * mp4_i32 writeAudioMDHD(MP4HandleImp handle,
1.4555 + * trakSize *ts)
1.4556 + *
1.4557 + * Description:
1.4558 + *
1.4559 + * Write audio MDHD atom.
1.4560 + *
1.4561 + * Parameters:
1.4562 + *
1.4563 + * handle MP4 library handle
1.4564 + * ts Atom sizes
1.4565 + *
1.4566 + * Return value:
1.4567 + *
1.4568 + * 0 Success
1.4569 + * -1 Error
1.4570 + *
1.4571 + */
1.4572 +mp4_i32 writeAudioMDHD(MP4HandleImp handle, trakSize *ts)
1.4573 +{
1.4574 + mp4_u8 *buf;
1.4575 + mp4_u32 i = 0;
1.4576 + mp4_u32 u32;
1.4577 +
1.4578 +
1.4579 + buf = (mp4_u8 *)mp4malloc(ts->mdhd);
1.4580 + if (buf == NULL)
1.4581 + return -1;
1.4582 +
1.4583 + /* Size */
1.4584 + insertu32(buf+i, (mp4_u32)ts->mdhd);
1.4585 + i += 4;
1.4586 +
1.4587 + /* Atom type */
1.4588 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MDHD);
1.4589 + i += 4;
1.4590 +
1.4591 + if (handle->audioDuration > MP4_INT_MAX)
1.4592 + {
1.4593 + /* Version and flags */
1.4594 + insertu32(buf+i, (mp4_u32)0x1000000); //version 1 atom
1.4595 + i += 4;
1.4596 +
1.4597 + /* Creation time */
1.4598 + if (getCurrentTime(&u32) < 0)
1.4599 + u32 = 0;
1.4600 + insertu64(buf+i, (mp4_u64)u32);
1.4601 + i += 8;
1.4602 +
1.4603 + /* Modification time */
1.4604 + if (getCurrentTime(&u32) < 0)
1.4605 + u32 = 0;
1.4606 + insertu64(buf+i, (mp4_u64)u32);
1.4607 + i += 8;
1.4608 +
1.4609 + /* Timescale */
1.4610 + insertu32(buf+i, (mp4_u32)handle->audioTimeScale);
1.4611 + i += 4;
1.4612 +
1.4613 + /* Duration */
1.4614 + insertu64(buf+i, handle->audioDuration);
1.4615 + i += 8;
1.4616 +
1.4617 + }
1.4618 + else
1.4619 + {
1.4620 + /* Version and flags */
1.4621 + insertu32(buf+i, (mp4_u32)0);
1.4622 + i += 4;
1.4623 +
1.4624 + /* Creation time */
1.4625 + if (getCurrentTime(&u32) < 0)
1.4626 + u32 = 0;
1.4627 + insertu32(buf+i, (mp4_u32)u32);
1.4628 + i += 4;
1.4629 +
1.4630 + /* Modification time */
1.4631 + if (getCurrentTime(&u32) < 0)
1.4632 + u32 = 0;
1.4633 + insertu32(buf+i, (mp4_u32)u32);
1.4634 + i += 4;
1.4635 +
1.4636 + /* Timescale */
1.4637 + insertu32(buf+i, (mp4_u32)handle->audioTimeScale);
1.4638 + i += 4;
1.4639 +
1.4640 + /* Duration */
1.4641 + insertu32(buf+i, (mp4_u32)handle->audioDuration);
1.4642 + i += 4;
1.4643 + }
1.4644 +
1.4645 + /* Language */
1.4646 + insertu16(buf+i, (mp4_u16)0x55c4); /* 'und' */
1.4647 + i += 2;
1.4648 +
1.4649 + /* Reserved */
1.4650 + insertu16(buf+i, (mp4_u16)0x0000);
1.4651 + i += 2;
1.4652 +
1.4653 + if (writeFile(handle, buf, ts->mdhd) < 0)
1.4654 + {
1.4655 + mp4free(buf);
1.4656 +
1.4657 + return -1;
1.4658 + }
1.4659 +
1.4660 + mp4free(buf);
1.4661 +
1.4662 + return 0;
1.4663 +}
1.4664 +
1.4665 +
1.4666 +/*
1.4667 + * Function:
1.4668 + *
1.4669 + * mp4_i32 writeAudioHDLR(MP4HandleImp handle,
1.4670 + * trakSize *ts)
1.4671 + *
1.4672 + * Description:
1.4673 + *
1.4674 + * Write audio HDLR atom.
1.4675 + *
1.4676 + * Parameters:
1.4677 + *
1.4678 + * handle MP4 library handle
1.4679 + * ts Atom sizes
1.4680 + *
1.4681 + * Return value:
1.4682 + *
1.4683 + * 0 Success
1.4684 + * -1 Error
1.4685 + *
1.4686 + */
1.4687 +mp4_i32 writeAudioHDLR(MP4HandleImp handle, trakSize *ts)
1.4688 +{
1.4689 + mp4_u8 *buf;
1.4690 + mp4_u32 i = 0;
1.4691 +
1.4692 +
1.4693 + buf = (mp4_u8 *)mp4malloc(ts->hdlr);
1.4694 + if (buf == NULL)
1.4695 + return -1;
1.4696 +
1.4697 + /* Size */
1.4698 + insertu32(buf+i, (mp4_u32)ts->hdlr);
1.4699 + i += 4;
1.4700 +
1.4701 + /* Atom type */
1.4702 + insertu32(buf+i, (mp4_u32)ATOMTYPE_HDLR);
1.4703 + i += 4;
1.4704 +
1.4705 + /* Version and flags */
1.4706 + insertu32(buf+i, (mp4_u32)0);
1.4707 + i += 4;
1.4708 +
1.4709 + /* Reserved */
1.4710 + insertu32(buf+i, (mp4_u32)0);
1.4711 + i += 4;
1.4712 +
1.4713 + /* Handler type */
1.4714 + buf[i++] = 's';
1.4715 + buf[i++] = 'o';
1.4716 + buf[i++] = 'u';
1.4717 + buf[i++] = 'n';
1.4718 +
1.4719 + /* Reserved */
1.4720 + insertu32(buf+i, (mp4_u32)0);
1.4721 + i += 4;
1.4722 +
1.4723 + /* Reserved */
1.4724 + insertu32(buf+i, (mp4_u32)0);
1.4725 + i += 4;
1.4726 +
1.4727 + /* Reserved */
1.4728 + insertu32(buf+i, (mp4_u32)0);
1.4729 + i += 4;
1.4730 +
1.4731 + /* Empty string */
1.4732 + buf[i++] = 0;
1.4733 +
1.4734 + if (writeFile(handle, buf, ts->hdlr) < 0)
1.4735 + {
1.4736 + mp4free(buf);
1.4737 +
1.4738 + return -1;
1.4739 + }
1.4740 +
1.4741 + mp4free(buf);
1.4742 +
1.4743 + return 0;
1.4744 +}
1.4745 +
1.4746 +
1.4747 +/*
1.4748 + * Function:
1.4749 + *
1.4750 + * mp4_i32 writeAudioMINF(MP4HandleImp handle,
1.4751 + * trakSize *ts)
1.4752 + *
1.4753 + * Description:
1.4754 + *
1.4755 + * Write audio MINF atom.
1.4756 + *
1.4757 + * Parameters:
1.4758 + *
1.4759 + * handle MP4 library handle
1.4760 + * ts Atom sizes
1.4761 + *
1.4762 + * Return value:
1.4763 + *
1.4764 + * 0 Success
1.4765 + * -1 Error
1.4766 + *
1.4767 + */
1.4768 +mp4_i32 writeAudioMINF(MP4HandleImp handle, trakSize *ts)
1.4769 +{
1.4770 + mp4_u8 buf[8];
1.4771 + mp4_u32 i = 0;
1.4772 +
1.4773 +
1.4774 + /* Size */
1.4775 + insertu32(buf+i, (mp4_u32)ts->minf);
1.4776 + i += 4;
1.4777 +
1.4778 + /* Atom type */
1.4779 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MINF);
1.4780 + i += 4;
1.4781 +
1.4782 + if (writeFile(handle, buf, 8) < 0)
1.4783 + return -1;
1.4784 +
1.4785 + if (writeSMHD(handle, ts) < 0)
1.4786 + return -1;
1.4787 +
1.4788 + if (writeDINF(handle, ts) < 0)
1.4789 + return -1;
1.4790 +
1.4791 + if (writeAudioSTBL(handle, ts) < 0)
1.4792 + return -1;
1.4793 +
1.4794 + return 0;
1.4795 +}
1.4796 +
1.4797 +
1.4798 +/*
1.4799 + * Function:
1.4800 + *
1.4801 + * mp4_i32 writeSMHD(MP4HandleImp handle,
1.4802 + * trakSize *ts)
1.4803 + *
1.4804 + * Description:
1.4805 + *
1.4806 + * Write SMHD atom.
1.4807 + *
1.4808 + * Parameters:
1.4809 + *
1.4810 + * handle MP4 library handle
1.4811 + * ts Atom sizes
1.4812 + *
1.4813 + * Return value:
1.4814 + *
1.4815 + * 0 Success
1.4816 + * -1 Error
1.4817 + *
1.4818 + */
1.4819 +mp4_i32 writeSMHD(MP4HandleImp handle, trakSize *ts)
1.4820 +{
1.4821 + mp4_u8 *buf;
1.4822 + mp4_u32 i = 0;
1.4823 +
1.4824 +
1.4825 + buf = (mp4_u8 *)mp4malloc(ts->smhd);
1.4826 + if (buf == NULL)
1.4827 + return -1;
1.4828 +
1.4829 + /* Size */
1.4830 + insertu32(buf+i, (mp4_u32)ts->smhd);
1.4831 + i += 4;
1.4832 +
1.4833 + /* Atom type */
1.4834 + insertu32(buf+i, (mp4_u32)ATOMTYPE_SMHD);
1.4835 + i += 4;
1.4836 +
1.4837 + /* Version and flags */
1.4838 + insertu32(buf+i, (mp4_u32)0);
1.4839 + i += 4;
1.4840 +
1.4841 + /* Reserved */
1.4842 + insertu32(buf+i, (mp4_u32)0);
1.4843 + i += 4;
1.4844 +
1.4845 + if (writeFile(handle, buf, ts->smhd) < 0)
1.4846 + {
1.4847 + mp4free(buf);
1.4848 +
1.4849 + return -1;
1.4850 + }
1.4851 +
1.4852 + mp4free(buf);
1.4853 +
1.4854 + return 0;
1.4855 +}
1.4856 +
1.4857 +
1.4858 +/*
1.4859 + * Function:
1.4860 + *
1.4861 + * mp4_i32 writeAudioSTBL(MP4HandleImp handle,
1.4862 + * trakSize *ts)
1.4863 + *
1.4864 + * Description:
1.4865 + *
1.4866 + * Write audio STBL atom.
1.4867 + *
1.4868 + * Parameters:
1.4869 + *
1.4870 + * handle MP4 library handle
1.4871 + * ts Atom sizes
1.4872 + *
1.4873 + * Return value:
1.4874 + *
1.4875 + * 0 Success
1.4876 + * -1 Error
1.4877 + *
1.4878 + */
1.4879 +mp4_i32 writeAudioSTBL(MP4HandleImp handle, trakSize *ts)
1.4880 +{
1.4881 + mp4_u8 buf[8];
1.4882 + mp4_u32 i = 0;
1.4883 +
1.4884 +
1.4885 + /* Size */
1.4886 + insertu32(buf+i, (mp4_u32)ts->stbl);
1.4887 + i += 4;
1.4888 +
1.4889 + /* Atom type */
1.4890 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STBL);
1.4891 + i += 4;
1.4892 +
1.4893 + if (writeFile(handle, buf, 8) < 0)
1.4894 + return -1;
1.4895 +
1.4896 + if (writeAudioSTSD(handle, ts) < 0)
1.4897 + return -1;
1.4898 +
1.4899 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.4900 + {
1.4901 + if (writeAudioSTTSLongClip(handle, ts) < 0)
1.4902 + return -1;
1.4903 + }
1.4904 + else
1.4905 + {
1.4906 + if (writeAudioSTTS(handle, ts) < 0)
1.4907 + return -1;
1.4908 + }
1.4909 +
1.4910 + if (writeAudioSTSC(handle, ts) < 0)
1.4911 + return -1;
1.4912 +
1.4913 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.4914 + {
1.4915 + if (writeAudioSTSZLongClip(handle, ts) < 0)
1.4916 + return -1;
1.4917 +
1.4918 + if (handle->audioSampleTable->stcoNeed64Bits)
1.4919 + {
1.4920 + if (writeAudioCO64LongClip(handle, ts) < 0)
1.4921 + return -1;
1.4922 + }
1.4923 + else
1.4924 + {
1.4925 + if (writeAudioSTCOLongClip(handle, ts) < 0)
1.4926 + return -1;
1.4927 + }
1.4928 + }
1.4929 + else
1.4930 + {
1.4931 + if (writeAudioSTSZ(handle, ts) < 0)
1.4932 + return -1;
1.4933 +
1.4934 + if (handle->audioSampleTable->stcoNeed64Bits)
1.4935 + {
1.4936 + if (writeAudioCO64(handle, ts) < 0)
1.4937 + return -1;
1.4938 + }
1.4939 + else
1.4940 + {
1.4941 + if (writeAudioSTCO(handle, ts) < 0)
1.4942 + return -1;
1.4943 + }
1.4944 + }
1.4945 +
1.4946 +
1.4947 + return 0;
1.4948 +}
1.4949 +
1.4950 +
1.4951 +/*
1.4952 + * Function:
1.4953 + *
1.4954 + * mp4_i32 writeAudioSTSD(MP4HandleImp handle,
1.4955 + * trakSize *ts)
1.4956 + *
1.4957 + * Description:
1.4958 + *
1.4959 + * Write audio STSD atom.
1.4960 + *
1.4961 + * Parameters:
1.4962 + *
1.4963 + * handle MP4 library handle
1.4964 + * ts Atom sizes
1.4965 + *
1.4966 + * Return value:
1.4967 + *
1.4968 + * 0 Success
1.4969 + * -1 Error
1.4970 + *
1.4971 + */
1.4972 +mp4_i32 writeAudioSTSD(MP4HandleImp handle, trakSize *ts)
1.4973 +{
1.4974 + mp4_u8 buf[16];
1.4975 + mp4_u32 i = 0;
1.4976 +
1.4977 +
1.4978 + /* Size */
1.4979 + insertu32(buf+i, (mp4_u32)ts->stsd);
1.4980 + i += 4;
1.4981 +
1.4982 + /* Atom type */
1.4983 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSD);
1.4984 + i += 4;
1.4985 +
1.4986 + /* Version and flags */
1.4987 + insertu32(buf+i, (mp4_u32)0);
1.4988 + i += 4;
1.4989 +
1.4990 + /* Entry count */
1.4991 + insertu32(buf+i, (mp4_u32)1);
1.4992 + i += 4;
1.4993 +
1.4994 + if (writeFile(handle, buf, 16) < 0)
1.4995 + return -1;
1.4996 +
1.4997 + if (handle->type & MP4_TYPE_MPEG4_AUDIO)
1.4998 + {
1.4999 + if (writeMP4A(handle, ts) < 0)
1.5000 + return -1;
1.5001 + }
1.5002 + else if (handle->type & MP4_TYPE_AMR_NB)
1.5003 + {
1.5004 + if (writeSAMR(handle, ts) < 0)
1.5005 + return -1;
1.5006 + }
1.5007 + else if (handle->type & MP4_TYPE_AMR_WB)
1.5008 + {
1.5009 + if (writeSAWB(handle, ts) < 0)
1.5010 + return -1;
1.5011 + }
1.5012 + else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio))
1.5013 + {
1.5014 + if (writeSQCP(handle, ts) < 0)
1.5015 + return -1;
1.5016 + }
1.5017 + else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio))
1.5018 + {
1.5019 + if (writeMP4A(handle, ts) < 0)
1.5020 + return -1;
1.5021 + }
1.5022 + else
1.5023 + {
1.5024 + }
1.5025 +
1.5026 + return 0;
1.5027 +}
1.5028 +
1.5029 +
1.5030 +/*
1.5031 + * Function:
1.5032 + *
1.5033 + * mp4_i32 writeMP4A(MP4HandleImp handle,
1.5034 + * trakSize *ts)
1.5035 + *
1.5036 + * Description:
1.5037 + *
1.5038 + * Write MP4A atom.
1.5039 + *
1.5040 + * Parameters:
1.5041 + *
1.5042 + * handle MP4 library handle
1.5043 + * ts Atom sizes
1.5044 + *
1.5045 + * Return value:
1.5046 + *
1.5047 + * 0 Success
1.5048 + * -1 Error
1.5049 + *
1.5050 + */
1.5051 +mp4_i32 writeMP4A(MP4HandleImp handle, trakSize *ts)
1.5052 +{
1.5053 + mp4_u8 *buf;
1.5054 + mp4_u32 i = 0;
1.5055 +
1.5056 +
1.5057 + buf = (mp4_u8 *)mp4malloc(36);
1.5058 + if (buf == NULL)
1.5059 + return -1;
1.5060 +
1.5061 + /* Size */
1.5062 + insertu32(buf+i, (mp4_u32)ts->mp4a);
1.5063 + i += 4;
1.5064 +
1.5065 + /* Atom type */
1.5066 + insertu32(buf+i, (mp4_u32)ATOMTYPE_MP4A);
1.5067 + i += 4;
1.5068 +
1.5069 + /* Reserved */
1.5070 + buf[i++] = 0;
1.5071 + buf[i++] = 0;
1.5072 + buf[i++] = 0;
1.5073 + buf[i++] = 0;
1.5074 + buf[i++] = 0;
1.5075 + buf[i++] = 0;
1.5076 +
1.5077 + /* Data reference index */
1.5078 + insertu16(buf+i, (mp4_u16)1);
1.5079 + i += 2;
1.5080 +
1.5081 + /* Reserved */
1.5082 + insertu32(buf+i, (mp4_u32)0);
1.5083 + i += 4;
1.5084 +
1.5085 + insertu32(buf+i, (mp4_u32)0);
1.5086 + i += 4;
1.5087 +
1.5088 + insertu16(buf+i, (mp4_u16)2);
1.5089 + i += 2;
1.5090 +
1.5091 + insertu16(buf+i, (mp4_u16)16);
1.5092 + i += 2;
1.5093 +
1.5094 + insertu32(buf+i, (mp4_u32)0);
1.5095 + i += 4;
1.5096 +
1.5097 + /* Timescale */
1.5098 + insertu16(buf+i, (mp4_u16)handle->audioTimeScale);
1.5099 + i += 2;
1.5100 +
1.5101 + /* Reserved */
1.5102 + insertu16(buf+i, (mp4_u16)0);
1.5103 + i += 2;
1.5104 +
1.5105 + if (writeFile(handle, buf, 36) < 0)
1.5106 + {
1.5107 + mp4free(buf);
1.5108 +
1.5109 + return -1;
1.5110 + }
1.5111 +
1.5112 + if (writeAudioESD(handle, ts) < 0)
1.5113 + {
1.5114 + mp4free(buf);
1.5115 +
1.5116 + return -1;
1.5117 + }
1.5118 +
1.5119 + mp4free(buf);
1.5120 +
1.5121 + return 0;
1.5122 +}
1.5123 +
1.5124 +
1.5125 +/*
1.5126 + * Function:
1.5127 + *
1.5128 + * mp4_i32 writeAudioESD(MP4HandleImp handle,
1.5129 + * trakSize *ts)
1.5130 + *
1.5131 + * Description:
1.5132 + *
1.5133 + * Write audio ESD atom.
1.5134 + *
1.5135 + * Parameters:
1.5136 + *
1.5137 + * handle MP4 library handle
1.5138 + * ts Atom sizes
1.5139 + *
1.5140 + * Return value:
1.5141 + *
1.5142 + * 0 Success
1.5143 + * -1 Error
1.5144 + *
1.5145 + */
1.5146 +mp4_i32 writeAudioESD(MP4HandleImp handle, trakSize *ts)
1.5147 +{
1.5148 + mp4_u8 *buf;
1.5149 + mp4_u32 i = 0;
1.5150 + mp4_u32 bitrate = 0;
1.5151 + mp4_u32 num_of_bytes = 0;
1.5152 + mp4_u32 size = 0;
1.5153 + mp4_u32 index = 0;
1.5154 + mp4_u32 tempnum = 0;
1.5155 +
1.5156 + mp4_u32 size1, size2;
1.5157 + mp4_u32 numofsizebytes1, numofsizebytes2;
1.5158 +
1.5159 + buf = (mp4_u8 *)mp4malloc(ts->esds);
1.5160 + if (buf == NULL)
1.5161 + return -1;
1.5162 +
1.5163 + /* Calculate the necessary size information */
1.5164 + size1 = handle->audioDecSpecificInfoSize;
1.5165 + if (size1 < 128)
1.5166 + numofsizebytes1 = 1;
1.5167 + else
1.5168 + {
1.5169 + numofsizebytes1 = 1;
1.5170 + while ( size1 >= 128 )
1.5171 + {
1.5172 + size1 = size1 >> 7;
1.5173 + numofsizebytes1++;
1.5174 + }
1.5175 + }
1.5176 +
1.5177 + size2 = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize;
1.5178 + if (size2 < 128)
1.5179 + numofsizebytes2 = 1;
1.5180 + else
1.5181 + {
1.5182 + numofsizebytes2 = 1;
1.5183 + while ( size2 >= 128 )
1.5184 + {
1.5185 + size2 = size2 >> 7;
1.5186 + numofsizebytes2++;
1.5187 + }
1.5188 + }
1.5189 + /* End of size calculations */
1.5190 +
1.5191 + /* Size */
1.5192 + insertu32(buf+i, (mp4_u32)ts->esds);
1.5193 + i += 4;
1.5194 +
1.5195 + /* Atom type */
1.5196 + insertu32(buf+i, (mp4_u32)ATOMTYPE_ESD);
1.5197 + i += 4;
1.5198 +
1.5199 + /* Version and flags */
1.5200 + insertu32(buf+i, (mp4_u32)0);
1.5201 + i += 4;
1.5202 +
1.5203 + /* ES_DescrTag */
1.5204 + buf[i++] = 0x03;
1.5205 +
1.5206 + /* Size */
1.5207 + size = 21 + numofsizebytes1 + numofsizebytes2 + handle->audioDecSpecificInfoSize;
1.5208 + if (size < 128)
1.5209 + buf[i++] = (mp4_u8)(size);
1.5210 + else
1.5211 + {
1.5212 + num_of_bytes = 0;
1.5213 + while ( size >= 128 )
1.5214 + {
1.5215 + size = size >> 7;
1.5216 + num_of_bytes++;
1.5217 + }
1.5218 + size = 21 + numofsizebytes1 + numofsizebytes2 + handle->audioDecSpecificInfoSize;
1.5219 + for(index = num_of_bytes; index > 0; index--)
1.5220 + {
1.5221 + tempnum = size >> (7 * index);
1.5222 + buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum);
1.5223 + size -= (tempnum << (7 * index));
1.5224 + }
1.5225 + buf[i++] = (mp4_u8)size;
1.5226 + }
1.5227 +
1.5228 + /* ES_ID */
1.5229 + insertu16(buf+i, (mp4_u16)0);
1.5230 + i += 2;
1.5231 +
1.5232 + /* Flags */
1.5233 + buf[i++] = 0;
1.5234 +
1.5235 + /* DecoderConfigDescrTag */
1.5236 + buf[i++] = 0x04;
1.5237 +
1.5238 + /* Size */
1.5239 + size = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize;
1.5240 + if (size < 128)
1.5241 + buf[i++] = (mp4_u8)(size);
1.5242 + else
1.5243 + {
1.5244 + num_of_bytes = 0;
1.5245 + while ( size >= 128 )
1.5246 + {
1.5247 + size = size >> 7;
1.5248 + num_of_bytes++;
1.5249 + }
1.5250 + size = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize;
1.5251 + for(index = num_of_bytes; index > 0; index--)
1.5252 + {
1.5253 + tempnum = size >> (7 * index);
1.5254 + buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum);
1.5255 + size -= (tempnum << (7 * index));
1.5256 + }
1.5257 + buf[i++] = (mp4_u8)size;
1.5258 + }
1.5259 +
1.5260 + /* ObjectTypeIndication */
1.5261 + if (handle->type & MP4_TYPE_MPEG4_AUDIO)
1.5262 + buf[i++] = 0x40;
1.5263 + else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio))
1.5264 + buf[i++] = 0xE1;
1.5265 + else
1.5266 + {
1.5267 + }
1.5268 +
1.5269 + /* Flags */
1.5270 + buf[i++] = 0x15;
1.5271 +
1.5272 + /* BufferSizeDB */
1.5273 + if (handle->type & MP4_TYPE_MPEG4_AUDIO)
1.5274 + {
1.5275 + buf[i++] = 0x00;
1.5276 + buf[i++] = 0x00;
1.5277 + buf[i++] = 0x00;
1.5278 + }
1.5279 + else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio))
1.5280 + { /* 4096 for QCELP 13K */
1.5281 + buf[i++] = 0x00;
1.5282 + buf[i++] = 0x10;
1.5283 + buf[i++] = 0x00;
1.5284 + }
1.5285 + else
1.5286 + {
1.5287 + }
1.5288 +
1.5289 +
1.5290 + if ((handle->audioDuration != 0) && (handle->audioTimeScale != 0))
1.5291 + bitrate = (mp4_u32)((mp4_double)8 *
1.5292 + (mp4_double)handle->audioMediaDataSize /
1.5293 + ((mp4_double)handle->audioDuration /
1.5294 + (mp4_double)handle->audioTimeScale));
1.5295 + else
1.5296 + bitrate = 0;
1.5297 +
1.5298 + /* MaxBitrate */
1.5299 + insertu32(buf+i, (mp4_u32)bitrate); /*0x00010000*/
1.5300 + i += 4;
1.5301 +
1.5302 + /* AvgBitrate */
1.5303 + insertu32(buf+i, (mp4_u32)bitrate);/*0x00008000*/
1.5304 + i += 4;
1.5305 +
1.5306 + /* DecSpecificInfoTag */
1.5307 + buf[i++] = 0x05;
1.5308 +
1.5309 + /* Size */
1.5310 + size = handle->audioDecSpecificInfoSize;
1.5311 + if (size < 128)
1.5312 + buf[i++] = (mp4_u8)(size);
1.5313 + else
1.5314 + {
1.5315 + num_of_bytes = 0;
1.5316 + while ( size >= 128 )
1.5317 + {
1.5318 + size = size >> 7;
1.5319 + num_of_bytes++;
1.5320 + }
1.5321 + size = handle->audioDecSpecificInfoSize;
1.5322 + for(index = num_of_bytes; index > 0; index--)
1.5323 + {
1.5324 + tempnum = size >> (7 * index);
1.5325 + buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum);
1.5326 + size -= (tempnum << (7 * index));
1.5327 + }
1.5328 + buf[i++] = (mp4_u8)size;
1.5329 + }
1.5330 +
1.5331 + /* DecoderSpecificInfo */
1.5332 + mp4memcpy(buf+i, handle->audioDecSpecificInfo, handle->audioDecSpecificInfoSize);
1.5333 + i += handle->audioDecSpecificInfoSize;
1.5334 +
1.5335 + /* SLConfigDescrTag */
1.5336 + buf[i++] = 0x06;
1.5337 +
1.5338 + /* Size */
1.5339 + buf[i++] = 1;
1.5340 +
1.5341 + /* */
1.5342 + buf[i++] = 2;
1.5343 +
1.5344 + if (writeFile(handle, buf, ts->esds) < 0)
1.5345 + {
1.5346 + mp4free(buf);
1.5347 +
1.5348 + return -1;
1.5349 + }
1.5350 +
1.5351 + mp4free(buf);
1.5352 +
1.5353 + return 0;
1.5354 +}
1.5355 +
1.5356 +
1.5357 +/*
1.5358 + * Function:
1.5359 + *
1.5360 + * mp4_i32 writeSAMR(MP4HandleImp handle,
1.5361 + * trakSize *ts)
1.5362 + *
1.5363 + * Description:
1.5364 + *
1.5365 + * Write SAMR atom.
1.5366 + *
1.5367 + * Parameters:
1.5368 + *
1.5369 + * handle MP4 library handle
1.5370 + * ts Atom sizes
1.5371 + *
1.5372 + * Return value:
1.5373 + *
1.5374 + * 0 Success
1.5375 + * -1 Error
1.5376 + *
1.5377 + */
1.5378 +mp4_i32 writeSAMR(MP4HandleImp handle, trakSize *ts)
1.5379 +{
1.5380 + mp4_u8 *buf;
1.5381 + mp4_u32 i = 0;
1.5382 +
1.5383 +
1.5384 + buf = (mp4_u8 *)mp4malloc(36);
1.5385 + if (buf == NULL)
1.5386 + return -1;
1.5387 +
1.5388 + /* Size */
1.5389 + insertu32(buf+i, (mp4_u32)ts->samr);
1.5390 + i += 4;
1.5391 +
1.5392 + /* Atom type */
1.5393 + insertu32(buf+i, (mp4_u32)ATOMTYPE_SAMR);
1.5394 + i += 4;
1.5395 +
1.5396 + /* Reserved */
1.5397 + buf[i++] = 0;
1.5398 + buf[i++] = 0;
1.5399 + buf[i++] = 0;
1.5400 + buf[i++] = 0;
1.5401 + buf[i++] = 0;
1.5402 + buf[i++] = 0;
1.5403 +
1.5404 + /* Data reference index */
1.5405 + insertu16(buf+i, (mp4_u16)1);
1.5406 + i += 2;
1.5407 +
1.5408 + /* Reserved */
1.5409 + insertu32(buf+i, (mp4_u32)0);
1.5410 + i += 4;
1.5411 +
1.5412 + insertu32(buf+i, (mp4_u32)0);
1.5413 + i += 4;
1.5414 +
1.5415 + insertu16(buf+i, (mp4_u16)2);
1.5416 + i += 2;
1.5417 +
1.5418 + insertu16(buf+i, (mp4_u16)16);
1.5419 + i += 2;
1.5420 +
1.5421 + insertu32(buf+i, (mp4_u32)0);
1.5422 + i += 4;
1.5423 +
1.5424 + /* Timescale */
1.5425 + insertu16(buf+i, (mp4_u16)handle->audioTimeScale);
1.5426 + i += 2;
1.5427 +
1.5428 + /* Reserved */
1.5429 + insertu16(buf+i, (mp4_u16)0);
1.5430 + i += 2;
1.5431 +
1.5432 + if (writeFile(handle, buf, 36) < 0)
1.5433 + {
1.5434 + mp4free(buf);
1.5435 +
1.5436 + return -1;
1.5437 + }
1.5438 +
1.5439 + if (writeDAMR(handle, ts) < 0)
1.5440 + {
1.5441 + mp4free(buf);
1.5442 +
1.5443 + return -1;
1.5444 + }
1.5445 +
1.5446 + mp4free(buf);
1.5447 +
1.5448 + return 0;
1.5449 +}
1.5450 +
1.5451 +
1.5452 +/*
1.5453 + * Function:
1.5454 + *
1.5455 + * mp4_i32 writeSAWB(MP4HandleImp handle,
1.5456 + * trakSize *ts)
1.5457 + *
1.5458 + * Description:
1.5459 + *
1.5460 + * Write SAWB atom.
1.5461 + *
1.5462 + * Parameters:
1.5463 + *
1.5464 + * handle MP4 library handle
1.5465 + * ts Atom sizes
1.5466 + *
1.5467 + * Return value:
1.5468 + *
1.5469 + * 0 Success
1.5470 + * -1 Error
1.5471 + *
1.5472 + */
1.5473 +mp4_i32 writeSAWB(MP4HandleImp handle, trakSize *ts)
1.5474 +{
1.5475 + mp4_u8 *buf;
1.5476 + mp4_u32 i = 0;
1.5477 +
1.5478 +
1.5479 + buf = (mp4_u8 *)mp4malloc(36);
1.5480 + if (buf == NULL)
1.5481 + return -1;
1.5482 +
1.5483 + /* Size */
1.5484 + insertu32(buf+i, (mp4_u32)ts->sawb);
1.5485 + i += 4;
1.5486 +
1.5487 + /* Atom type */
1.5488 + insertu32(buf+i, (mp4_u32)ATOMTYPE_SAWB);
1.5489 + i += 4;
1.5490 +
1.5491 + /* Reserved */
1.5492 + buf[i++] = 0;
1.5493 + buf[i++] = 0;
1.5494 + buf[i++] = 0;
1.5495 + buf[i++] = 0;
1.5496 + buf[i++] = 0;
1.5497 + buf[i++] = 0;
1.5498 +
1.5499 + /* Data reference index */
1.5500 + insertu16(buf+i, (mp4_u16)1);
1.5501 + i += 2;
1.5502 +
1.5503 + /* Reserved */
1.5504 + insertu32(buf+i, (mp4_u32)0);
1.5505 + i += 4;
1.5506 +
1.5507 + insertu32(buf+i, (mp4_u32)0);
1.5508 + i += 4;
1.5509 +
1.5510 + insertu16(buf+i, (mp4_u16)2);
1.5511 + i += 2;
1.5512 +
1.5513 + insertu16(buf+i, (mp4_u16)16);
1.5514 + i += 2;
1.5515 +
1.5516 + insertu32(buf+i, (mp4_u32)0);
1.5517 + i += 4;
1.5518 +
1.5519 + /* Timescale */
1.5520 + insertu16(buf+i, (mp4_u16)handle->audioTimeScale);
1.5521 + i += 2;
1.5522 +
1.5523 + /* Reserved */
1.5524 + insertu16(buf+i, (mp4_u16)0);
1.5525 + i += 2;
1.5526 +
1.5527 + if (writeFile(handle, buf, 36) < 0)
1.5528 + {
1.5529 + mp4free(buf);
1.5530 +
1.5531 + return -1;
1.5532 + }
1.5533 +
1.5534 + if (writeDAMR(handle, ts) < 0)
1.5535 + {
1.5536 + mp4free(buf);
1.5537 +
1.5538 + return -1;
1.5539 + }
1.5540 +
1.5541 + mp4free(buf);
1.5542 +
1.5543 + return 0;
1.5544 +}
1.5545 +
1.5546 +
1.5547 +/*
1.5548 + * Function:
1.5549 + *
1.5550 + * mp4_i32 writeDAMR(MP4HandleImp handle,
1.5551 + * trakSize *ts)
1.5552 + *
1.5553 + * Description:
1.5554 + *
1.5555 + * Write DAMR atom.
1.5556 + *
1.5557 + * Parameters:
1.5558 + *
1.5559 + * handle MP4 library handle
1.5560 + * ts Atom sizes
1.5561 + *
1.5562 + * Return value:
1.5563 + *
1.5564 + * 0 Success
1.5565 + * -1 Error
1.5566 + *
1.5567 + */
1.5568 +mp4_i32 writeDAMR(MP4HandleImp handle, trakSize *ts)
1.5569 +{
1.5570 + mp4_u8 buf[17];
1.5571 + mp4_u32 i = 0;
1.5572 +
1.5573 +
1.5574 + /* Size */
1.5575 + insertu32(buf+i, (mp4_u32)ts->damr);
1.5576 + i += 4;
1.5577 +
1.5578 + /* Atom type */
1.5579 + insertu32(buf+i, (mp4_u32)ATOMTYPE_DAMR);
1.5580 + i += 4;
1.5581 +
1.5582 + /* Vendor */
1.5583 + buf[i++] = 'S';
1.5584 + buf[i++] = '6';
1.5585 + buf[i++] = '0';
1.5586 + buf[i++] = ' ';
1.5587 +
1.5588 + /* Decoder version */
1.5589 + buf[i++] = 0;
1.5590 +
1.5591 + /* Mode set */
1.5592 + insertu16(buf+i, (mp4_u16)handle->audioModeSet);
1.5593 + i += 2;
1.5594 +
1.5595 + /* Mode change period */
1.5596 + buf[i++] = 0;
1.5597 +
1.5598 + /* Frames per sample */
1.5599 + buf[i++] = handle->audioFramesPerSample;
1.5600 +
1.5601 + if (writeFile(handle, buf, 17) < 0)
1.5602 + return -1;
1.5603 +
1.5604 + return 0;
1.5605 +}
1.5606 +
1.5607 +
1.5608 +/*
1.5609 + * Function:
1.5610 + *
1.5611 + * mp4_i32 writeAudioSTTS(MP4HandleImp handle,
1.5612 + * trakSize *ts)
1.5613 + *
1.5614 + * Description:
1.5615 + *
1.5616 + * Write audio STTS atom.
1.5617 + *
1.5618 + * Parameters:
1.5619 + *
1.5620 + * handle MP4 library handle
1.5621 + * ts Atom sizes
1.5622 + *
1.5623 + * Return value:
1.5624 + *
1.5625 + * 0 Success
1.5626 + * -1 Error
1.5627 + *
1.5628 + */
1.5629 +mp4_i32 writeAudioSTTS(MP4HandleImp handle, trakSize *ts)
1.5630 +{
1.5631 + mp4_u8 *buf;
1.5632 + mp4_u32 i = 0;
1.5633 + mp4_u32 j;
1.5634 +
1.5635 +
1.5636 + buf = (mp4_u8 *)mp4malloc(ts->stts);
1.5637 + if (buf == NULL)
1.5638 + return -1;
1.5639 +
1.5640 + /* Size */
1.5641 + insertu32(buf+i, (mp4_u32)ts->stts);
1.5642 + i += 4;
1.5643 +
1.5644 + /* Atom type */
1.5645 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS);
1.5646 + i += 4;
1.5647 +
1.5648 + /* Version and flags */
1.5649 + insertu32(buf+i, (mp4_u32)0);
1.5650 + i += 4;
1.5651 +
1.5652 + /* Entry count */
1.5653 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsEntryCount);
1.5654 + i += 4;
1.5655 +
1.5656 + /* Sample count and sample delta */
1.5657 + for (j = 0; j < handle->audioSampleTable->sttsEntryCount; j++)
1.5658 + {
1.5659 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsSampleCount[j]);
1.5660 + i += 4;
1.5661 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsSampleDelta[j]);
1.5662 + i += 4;
1.5663 + }
1.5664 +
1.5665 + if (writeFile(handle, buf, ts->stts) < 0)
1.5666 + {
1.5667 + mp4free(buf);
1.5668 +
1.5669 + return -1;
1.5670 + }
1.5671 +
1.5672 + mp4free(buf);
1.5673 +
1.5674 + return 0;
1.5675 +}
1.5676 +
1.5677 +
1.5678 +/*
1.5679 + * Function:
1.5680 + *
1.5681 + * mp4_i32 writeAudioSTTSLongClip(MP4HandleImp handle,
1.5682 + * trakSize *ts)
1.5683 + *
1.5684 + * Description:
1.5685 + *
1.5686 + * Write audio STTS atom.
1.5687 + *
1.5688 + * Parameters:
1.5689 + *
1.5690 + * handle MP4 library handle
1.5691 + * ts Atom sizes
1.5692 + *
1.5693 + * Return value:
1.5694 + *
1.5695 + * 0 Success
1.5696 + * -1 Error
1.5697 + *
1.5698 + */
1.5699 +mp4_i32 writeAudioSTTSLongClip(MP4HandleImp handle, trakSize *ts)
1.5700 +{
1.5701 + mp4_u8 *buf;
1.5702 + mp4_u8 *buf2;
1.5703 + mp4_u32 i = 0;
1.5704 + mp4_u32 j;
1.5705 + mp4_u32 left;
1.5706 + mp4_u32 bytestoread;
1.5707 +
1.5708 +
1.5709 + buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.5710 + if (buf == NULL)
1.5711 + return -1;
1.5712 +
1.5713 + buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2);
1.5714 + if (buf2 == NULL)
1.5715 + {
1.5716 + mp4free(buf);
1.5717 + return -1;
1.5718 + }
1.5719 +
1.5720 + /* Size */
1.5721 + insertu32(buf+i, (mp4_u32)ts->stts);
1.5722 + i += 4;
1.5723 +
1.5724 + /* Atom type */
1.5725 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS);
1.5726 + i += 4;
1.5727 +
1.5728 + /* Version and flags */
1.5729 + insertu32(buf+i, (mp4_u32)0);
1.5730 + i += 4;
1.5731 +
1.5732 + /* Entry count */
1.5733 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsEntryCount);
1.5734 + i += 4;
1.5735 +
1.5736 + if (writeFile(handle, buf, i) < 0)
1.5737 + {
1.5738 + mp4free(buf);
1.5739 + mp4free(buf2);
1.5740 +
1.5741 + return -1;
1.5742 + }
1.5743 +
1.5744 + /* Sample count and delta */
1.5745 +
1.5746 + /* Seek to the beginning of temporary files */
1.5747 +
1.5748 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0)
1.5749 + {
1.5750 + mp4free(buf);
1.5751 + mp4free(buf2);
1.5752 + return -1;
1.5753 + }
1.5754 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0)
1.5755 + {
1.5756 + mp4free(buf);
1.5757 + mp4free(buf2);
1.5758 + return -1;
1.5759 + }
1.5760 +
1.5761 + left = handle->audioSampleTable->sttsEntryCount * 4; /* Bytes left in each file */
1.5762 +
1.5763 + while (left)
1.5764 + {
1.5765 + if (left > METADATA_COPY_BUFFERSIZE / 2)
1.5766 + bytestoread = METADATA_COPY_BUFFERSIZE / 2;
1.5767 + else
1.5768 + bytestoread = left;
1.5769 +
1.5770 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0)
1.5771 + {
1.5772 + mp4free(buf);
1.5773 + mp4free(buf2);
1.5774 +
1.5775 + return -1;
1.5776 + }
1.5777 +
1.5778 + for (j = 0; j < bytestoread; j += 4)
1.5779 + {
1.5780 + insertu32(buf + 2*j, ((mp4_u32 *)buf2)[j / 4]);
1.5781 + }
1.5782 +
1.5783 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0)
1.5784 + {
1.5785 + mp4free(buf);
1.5786 + mp4free(buf2);
1.5787 +
1.5788 + return -1;
1.5789 + }
1.5790 +
1.5791 + for (j = 0; j < bytestoread; j += 4)
1.5792 + {
1.5793 + insertu32(buf + 2*j + 4, ((mp4_u32 *)buf2)[j / 4]);
1.5794 + }
1.5795 +
1.5796 + if (writeFile(handle, buf, 2 * bytestoread) < 0)
1.5797 + {
1.5798 + mp4free(buf);
1.5799 + mp4free(buf2);
1.5800 +
1.5801 + return -1;
1.5802 + }
1.5803 +
1.5804 + left -= bytestoread;
1.5805 + }
1.5806 +
1.5807 + mp4free(buf);
1.5808 + mp4free(buf2);
1.5809 +
1.5810 +
1.5811 + return 0;
1.5812 +}
1.5813 +
1.5814 +
1.5815 +/*
1.5816 + * Function:
1.5817 + *
1.5818 + * mp4_i32 writeAudioSTSC(MP4HandleImp handle,
1.5819 + * trakSize *ts)
1.5820 + *
1.5821 + * Description:
1.5822 + *
1.5823 + * Write audio STSC atom.
1.5824 + *
1.5825 + * Parameters:
1.5826 + *
1.5827 + * handle MP4 library handle
1.5828 + * ts Atom sizes
1.5829 + *
1.5830 + * Return value:
1.5831 + *
1.5832 + * 0 Success
1.5833 + * -1 Error
1.5834 + *
1.5835 + */
1.5836 +mp4_i32 writeAudioSTSC(MP4HandleImp handle, trakSize *ts)
1.5837 +{
1.5838 + mp4_u8 *buf;
1.5839 + mp4_u32 i = 0;
1.5840 + mp4_u32 j;
1.5841 +
1.5842 +
1.5843 + buf = (mp4_u8 *)mp4malloc(ts->stsc);
1.5844 + if (buf == NULL)
1.5845 + return -1;
1.5846 +
1.5847 + /* Size */
1.5848 + insertu32(buf+i, (mp4_u32)ts->stsc);
1.5849 + i += 4;
1.5850 +
1.5851 + /* Atom type */
1.5852 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSC);
1.5853 + i += 4;
1.5854 +
1.5855 + /* Version and flags */
1.5856 + insertu32(buf+i, (mp4_u32)0);
1.5857 + i += 4;
1.5858 +
1.5859 + /* Entry count */
1.5860 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscEntryCount);
1.5861 + i += 4;
1.5862 +
1.5863 + /* First chunk, samples per chunk and sample description index */
1.5864 + for (j = 0; j < handle->audioSampleTable->stscEntryCount; j++)
1.5865 + {
1.5866 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscFirstChunk[j]);
1.5867 + i += 4;
1.5868 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscSamplesPerChunk[j]);
1.5869 + i += 4;
1.5870 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscSampleDescriptionIndex[j]);
1.5871 + i += 4;
1.5872 + }
1.5873 +
1.5874 + if (writeFile(handle, buf, ts->stsc) < 0)
1.5875 + {
1.5876 + mp4free(buf);
1.5877 +
1.5878 + return -1;
1.5879 + }
1.5880 +
1.5881 + mp4free(buf);
1.5882 +
1.5883 + return 0;
1.5884 +}
1.5885 +
1.5886 +
1.5887 +/*
1.5888 + * Function:
1.5889 + *
1.5890 + * mp4_i32 writeAudioSTSZ(MP4HandleImp handle,
1.5891 + * trakSize *ts)
1.5892 + *
1.5893 + * Description:
1.5894 + *
1.5895 + * Write audio STSZ atom.
1.5896 + *
1.5897 + * Parameters:
1.5898 + *
1.5899 + * handle MP4 library handle
1.5900 + * ts Atom sizes
1.5901 + *
1.5902 + * Return value:
1.5903 + *
1.5904 + * 0 Success
1.5905 + * -1 Error
1.5906 + *
1.5907 + */
1.5908 +mp4_i32 writeAudioSTSZ(MP4HandleImp handle, trakSize *ts)
1.5909 +{
1.5910 + mp4_u8 *buf;
1.5911 + mp4_u32 i = 0;
1.5912 + mp4_u32 j;
1.5913 +
1.5914 +
1.5915 + buf = (mp4_u8 *)mp4malloc(ts->stsz);
1.5916 + if (buf == NULL)
1.5917 + return -1;
1.5918 +
1.5919 + /* Size */
1.5920 + insertu32(buf+i, (mp4_u32)ts->stsz);
1.5921 + i += 4;
1.5922 +
1.5923 + /* Atom type */
1.5924 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ);
1.5925 + i += 4;
1.5926 +
1.5927 + /* Version and flags */
1.5928 + insertu32(buf+i, (mp4_u32)0);
1.5929 + i += 4;
1.5930 +
1.5931 + /* Sample size */
1.5932 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleSize);
1.5933 + i += 4;
1.5934 +
1.5935 + /* Sample count */
1.5936 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleCount);
1.5937 + i += 4;
1.5938 +
1.5939 + /* Entry sizes */
1.5940 + if (handle->audioSampleTable->stszSampleSize == 0)
1.5941 + {
1.5942 + for (j = 0; j < handle->audioSampleTable->stszSampleCount; j++)
1.5943 + {
1.5944 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszEntrySize[j]);
1.5945 + i += 4;
1.5946 + }
1.5947 + }
1.5948 +
1.5949 + if (writeFile(handle, buf, ts->stsz) < 0)
1.5950 + {
1.5951 + mp4free(buf);
1.5952 +
1.5953 + return -1;
1.5954 + }
1.5955 +
1.5956 + mp4free(buf);
1.5957 +
1.5958 + return 0;
1.5959 +}
1.5960 +
1.5961 +
1.5962 +/*
1.5963 + * Function:
1.5964 + *
1.5965 + * mp4_i32 writeAudioSTSZLongClip(MP4HandleImp handle,
1.5966 + * trakSize *ts)
1.5967 + *
1.5968 + * Description:
1.5969 + *
1.5970 + * Write audio STSZ atom.
1.5971 + *
1.5972 + * Parameters:
1.5973 + *
1.5974 + * handle MP4 library handle
1.5975 + * ts Atom sizes
1.5976 + *
1.5977 + * Return value:
1.5978 + *
1.5979 + * 0 Success
1.5980 + * -1 Error
1.5981 + *
1.5982 + */
1.5983 +mp4_i32 writeAudioSTSZLongClip(MP4HandleImp handle, trakSize *ts)
1.5984 +{
1.5985 + mp4_u8 *buf;
1.5986 + mp4_u8 *buf2;
1.5987 + mp4_u32 i = 0;
1.5988 + mp4_u32 j;
1.5989 + mp4_u32 left;
1.5990 + mp4_u32 bytestoread;
1.5991 +
1.5992 +
1.5993 + buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.5994 + if (buf == NULL)
1.5995 + return -1;
1.5996 +
1.5997 + buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.5998 + if (buf2 == NULL)
1.5999 + {
1.6000 + mp4free(buf);
1.6001 + return -1;
1.6002 + }
1.6003 +
1.6004 + /* Size */
1.6005 + insertu32(buf+i, (mp4_u32)ts->stsz);
1.6006 + i += 4;
1.6007 +
1.6008 + /* Atom type */
1.6009 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ);
1.6010 + i += 4;
1.6011 +
1.6012 + /* Version and flags */
1.6013 + insertu32(buf+i, (mp4_u32)0);
1.6014 + i += 4;
1.6015 +
1.6016 + /* Sample size */
1.6017 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleSize);
1.6018 + i += 4;
1.6019 +
1.6020 + /* Sample count */
1.6021 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleCount);
1.6022 + i += 4;
1.6023 +
1.6024 + if (writeFile(handle, buf, i) < 0)
1.6025 + {
1.6026 + mp4free(buf);
1.6027 + mp4free(buf2);
1.6028 +
1.6029 + return -1;
1.6030 + }
1.6031 +
1.6032 + /* Entry sizes */
1.6033 +
1.6034 + if (handle->audioSampleTable->stszSampleSize == 0)
1.6035 + {
1.6036 + /* Seek to the beginning of temporary file */
1.6037 +
1.6038 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0)
1.6039 + {
1.6040 + mp4free(buf);
1.6041 + mp4free(buf2);
1.6042 + return -1;
1.6043 + }
1.6044 +
1.6045 + left = handle->audioSampleTable->stszSampleCount * 4; /* Bytes left in the file */
1.6046 +
1.6047 + while (left)
1.6048 + {
1.6049 + if (left > METADATA_COPY_BUFFERSIZE)
1.6050 + bytestoread = METADATA_COPY_BUFFERSIZE;
1.6051 + else
1.6052 + bytestoread = left;
1.6053 +
1.6054 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0)
1.6055 + {
1.6056 + mp4free(buf);
1.6057 + mp4free(buf2);
1.6058 +
1.6059 + return -1;
1.6060 + }
1.6061 +
1.6062 + for (j = 0; j < bytestoread; j += 4)
1.6063 + {
1.6064 + insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]);
1.6065 + }
1.6066 +
1.6067 + if (writeFile(handle, buf, bytestoread) < 0)
1.6068 + {
1.6069 + mp4free(buf);
1.6070 + mp4free(buf2);
1.6071 +
1.6072 + return -1;
1.6073 + }
1.6074 +
1.6075 + left -= bytestoread;
1.6076 + }
1.6077 + }
1.6078 +
1.6079 + mp4free(buf);
1.6080 + mp4free(buf2);
1.6081 +
1.6082 +
1.6083 + return 0;
1.6084 +}
1.6085 +
1.6086 +
1.6087 +/*
1.6088 + * Function:
1.6089 + *
1.6090 + * mp4_i32 writeAudioSTCO(MP4HandleImp handle,
1.6091 + * trakSize *ts)
1.6092 + *
1.6093 + * Description:
1.6094 + *
1.6095 + * Write audio STCO atom.
1.6096 + *
1.6097 + * Parameters:
1.6098 + *
1.6099 + * handle MP4 library handle
1.6100 + * ts Atom sizes
1.6101 + *
1.6102 + * Return value:
1.6103 + *
1.6104 + * 0 Success
1.6105 + * -1 Error
1.6106 + *
1.6107 + */
1.6108 +mp4_i32 writeAudioSTCO(MP4HandleImp handle, trakSize *ts)
1.6109 +{
1.6110 + mp4_u8 *buf;
1.6111 + mp4_u32 i = 0;
1.6112 + mp4_u32 j;
1.6113 +
1.6114 +
1.6115 + buf = (mp4_u8 *)mp4malloc(ts->stco);
1.6116 + if (buf == NULL)
1.6117 + return -1;
1.6118 +
1.6119 + /* Size */
1.6120 + insertu32(buf+i, (mp4_u32)ts->stco);
1.6121 + i += 4;
1.6122 +
1.6123 + /* Atom type */
1.6124 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO);
1.6125 + i += 4;
1.6126 +
1.6127 + /* Version and flags */
1.6128 + insertu32(buf+i, (mp4_u32)0);
1.6129 + i += 4;
1.6130 +
1.6131 + /* Entry count */
1.6132 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount);
1.6133 + i += 4;
1.6134 +
1.6135 + /* Chunk offsets */
1.6136 + for (j = 0; j < handle->audioSampleTable->stcoEntryCount; j++)
1.6137 + {
1.6138 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoChunkOffset[j]);
1.6139 + i += 4;
1.6140 + }
1.6141 +
1.6142 + if (writeFile(handle, buf, ts->stco) < 0)
1.6143 + {
1.6144 + mp4free(buf);
1.6145 +
1.6146 + return -1;
1.6147 + }
1.6148 +
1.6149 + mp4free(buf);
1.6150 +
1.6151 + return 0;
1.6152 +}
1.6153 +
1.6154 +/*
1.6155 + * Function:
1.6156 + *
1.6157 + * mp4_i32 writeAudioCO64(MP4HandleImp handle,
1.6158 + * trakSize *ts)
1.6159 + *
1.6160 + * Description:
1.6161 + *
1.6162 + * Write audio CO64 atom.
1.6163 + *
1.6164 + * Parameters:
1.6165 + *
1.6166 + * handle MP4 library handle
1.6167 + * ts Atom sizes
1.6168 + *
1.6169 + * Return value:
1.6170 + *
1.6171 + * 0 Success
1.6172 + * -1 Error
1.6173 + *
1.6174 + */
1.6175 +mp4_i32 writeAudioCO64(MP4HandleImp handle, trakSize *ts)
1.6176 +{
1.6177 + mp4_u8 *buf;
1.6178 + mp4_u32 i = 0;
1.6179 + mp4_u32 j;
1.6180 +
1.6181 +
1.6182 + buf = (mp4_u8 *)mp4malloc(ts->stco);
1.6183 + if (buf == NULL)
1.6184 + return -1;
1.6185 +
1.6186 + /* Size */
1.6187 + insertu32(buf+i, (mp4_u32)ts->stco);
1.6188 + i += 4;
1.6189 +
1.6190 + /* Atom type */
1.6191 + insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64);
1.6192 + i += 4;
1.6193 +
1.6194 + /* Version and flags */
1.6195 + insertu32(buf+i, (mp4_u32)0);
1.6196 + i += 4;
1.6197 +
1.6198 + /* Entry count */
1.6199 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount);
1.6200 + i += 4;
1.6201 +
1.6202 + /* Chunk offsets */
1.6203 + for (j = 0; j < handle->audioSampleTable->stcoEntryCount; j++)
1.6204 + {
1.6205 + insertu64(buf+j, (mp4_u64)handle->audioSampleTable->stcoChunkOffset[j]);
1.6206 + }
1.6207 +
1.6208 + if (writeFile(handle, buf, ts->stco) < 0)
1.6209 + {
1.6210 + mp4free(buf);
1.6211 +
1.6212 + return -1;
1.6213 + }
1.6214 +
1.6215 + mp4free(buf);
1.6216 +
1.6217 + return 0;
1.6218 +}
1.6219 +
1.6220 +/*
1.6221 + * Function:
1.6222 + *
1.6223 + * mp4_i32 writeAudioSTCOLongClip(MP4HandleImp handle,
1.6224 + * trakSize *ts)
1.6225 + *
1.6226 + * Description:
1.6227 + *
1.6228 + * Write audio STCO atom.
1.6229 + *
1.6230 + * Parameters:
1.6231 + *
1.6232 + * handle MP4 library handle
1.6233 + * ts Atom sizes
1.6234 + *
1.6235 + * Return value:
1.6236 + *
1.6237 + * 0 Success
1.6238 + * -1 Error
1.6239 + *
1.6240 + */
1.6241 +mp4_i32 writeAudioSTCOLongClip(MP4HandleImp handle, trakSize *ts)
1.6242 +{
1.6243 + mp4_u8 *buf;
1.6244 + mp4_u8 *buf2;
1.6245 + mp4_u32 i = 0;
1.6246 + mp4_u32 j;
1.6247 + mp4_u32 left;
1.6248 + mp4_u32 bytestoread;
1.6249 + mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64
1.6250 + //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4
1.6251 +
1.6252 +
1.6253 + buf = (mp4_u8 *)mp4malloc(bufferSize);
1.6254 + if (buf == NULL)
1.6255 + return -1;
1.6256 +
1.6257 + buf2 = (mp4_u8 *)mp4malloc(bufferSize);
1.6258 + if (buf2 == NULL)
1.6259 + {
1.6260 + mp4free(buf);
1.6261 + return -1;
1.6262 + }
1.6263 +
1.6264 + /* Size */
1.6265 + insertu32(buf+i, (mp4_u32)ts->stco);
1.6266 + i += 4;
1.6267 +
1.6268 + /* Atom type */
1.6269 + insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO);
1.6270 + i += 4;
1.6271 +
1.6272 + /* Version and flags */
1.6273 + insertu32(buf+i, (mp4_u32)0);
1.6274 + i += 4;
1.6275 +
1.6276 + /* Entry count */
1.6277 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount);
1.6278 + i += 4;
1.6279 +
1.6280 + if (writeFile(handle, buf, i) < 0)
1.6281 + {
1.6282 + mp4free(buf);
1.6283 + mp4free(buf2);
1.6284 +
1.6285 + return -1;
1.6286 + }
1.6287 +
1.6288 + /* Chunk offsets */
1.6289 +
1.6290 + /* Seek to the beginning of temporary file */
1.6291 +
1.6292 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0)
1.6293 + {
1.6294 + mp4free(buf);
1.6295 + mp4free(buf2);
1.6296 + return -1;
1.6297 + }
1.6298 +
1.6299 + left = handle->audioSampleTable->stcoEntryCount * 8; /* Bytes left in the file */
1.6300 +
1.6301 + while (left)
1.6302 + {
1.6303 + if (left > bufferSize)
1.6304 + bytestoread = bufferSize;
1.6305 + else
1.6306 + bytestoread = left;
1.6307 +
1.6308 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0)
1.6309 + {
1.6310 + mp4free(buf);
1.6311 + mp4free(buf2);
1.6312 +
1.6313 + return -1;
1.6314 + }
1.6315 +
1.6316 + for (j = 0; j < bytestoread; j += 8)
1.6317 + {
1.6318 + ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */
1.6319 + insertu32(buf + j/2, ((mp4_u64 *)buf2)[j / 8]);
1.6320 + }
1.6321 +
1.6322 + if (writeFile(handle, buf, bytestoread/2) < 0)
1.6323 + {
1.6324 + mp4free(buf);
1.6325 + mp4free(buf2);
1.6326 +
1.6327 + return -1;
1.6328 + }
1.6329 +
1.6330 + left -= bytestoread;
1.6331 + }
1.6332 +
1.6333 + mp4free(buf);
1.6334 + mp4free(buf2);
1.6335 +
1.6336 +
1.6337 + return 0;
1.6338 +}
1.6339 +
1.6340 +/*
1.6341 + * Function:
1.6342 + *
1.6343 + * mp4_i32 writeAudioCO64LongClip(MP4HandleImp handle,
1.6344 + * trakSize *ts)
1.6345 + *
1.6346 + * Description:
1.6347 + *
1.6348 + * Write audio CO64 atom.
1.6349 + *
1.6350 + * Parameters:
1.6351 + *
1.6352 + * handle MP4 library handle
1.6353 + * ts Atom sizes
1.6354 + *
1.6355 + * Return value:
1.6356 + *
1.6357 + * 0 Success
1.6358 + * -1 Error
1.6359 + *
1.6360 + */
1.6361 +mp4_i32 writeAudioCO64LongClip(MP4HandleImp handle, trakSize *ts)
1.6362 +{
1.6363 + mp4_u8 *buf;
1.6364 + mp4_u8 *buf2;
1.6365 + mp4_u32 i = 0;
1.6366 + mp4_u32 j;
1.6367 + mp4_u32 left;
1.6368 + mp4_u32 bytestoread;
1.6369 + mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64
1.6370 + //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4
1.6371 +
1.6372 +
1.6373 + buf = (mp4_u8 *)mp4malloc(bufferSize);
1.6374 + if (buf == NULL)
1.6375 + return -1;
1.6376 +
1.6377 + buf2 = (mp4_u8 *)mp4malloc(bufferSize);
1.6378 + if (buf2 == NULL)
1.6379 + {
1.6380 + mp4free(buf);
1.6381 + return -1;
1.6382 + }
1.6383 +
1.6384 + /* Size */
1.6385 + insertu32(buf+i, (mp4_u32)ts->stco);
1.6386 + i += 4;
1.6387 +
1.6388 + /* Atom type */
1.6389 + insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64);
1.6390 + i += 4;
1.6391 +
1.6392 + /* Version and flags */
1.6393 + insertu32(buf+i, (mp4_u32)0);
1.6394 + i += 4;
1.6395 +
1.6396 + /* Entry count */
1.6397 + insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount);
1.6398 + i += 4;
1.6399 +
1.6400 + if (writeFile(handle, buf, i) < 0)
1.6401 + {
1.6402 + mp4free(buf);
1.6403 + mp4free(buf2);
1.6404 +
1.6405 + return -1;
1.6406 + }
1.6407 +
1.6408 + /* Chunk offsets */
1.6409 +
1.6410 + /* Seek to the beginning of temporary file */
1.6411 +
1.6412 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0)
1.6413 + {
1.6414 + mp4free(buf);
1.6415 + mp4free(buf2);
1.6416 + return -1;
1.6417 + }
1.6418 +
1.6419 + left = handle->audioSampleTable->stcoEntryCount * 8; /* Bytes left in the file */
1.6420 +
1.6421 + while (left)
1.6422 + {
1.6423 + if (left > bufferSize)
1.6424 + bytestoread = bufferSize;
1.6425 + else
1.6426 + bytestoread = left;
1.6427 +
1.6428 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0)
1.6429 + {
1.6430 + mp4free(buf);
1.6431 + mp4free(buf2);
1.6432 +
1.6433 + return -1;
1.6434 + }
1.6435 +
1.6436 + for (j = 0; j < bytestoread; j += 8)
1.6437 + {
1.6438 + ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */
1.6439 + insertu64(buf + j, ((mp4_u64 *)buf2)[j / 8]);
1.6440 + }
1.6441 +
1.6442 + if (writeFile(handle, buf, bytestoread) < 0)
1.6443 + {
1.6444 + mp4free(buf);
1.6445 + mp4free(buf2);
1.6446 +
1.6447 + return -1;
1.6448 + }
1.6449 +
1.6450 + left -= bytestoread;
1.6451 + }
1.6452 +
1.6453 + mp4free(buf);
1.6454 + mp4free(buf2);
1.6455 +
1.6456 +
1.6457 + return 0;
1.6458 +}
1.6459 +
1.6460 +
1.6461 +/*
1.6462 + * Function:
1.6463 + *
1.6464 + * mp4_i32 writeMediaData(MP4HandleImp handle)
1.6465 + *
1.6466 + * Description:
1.6467 + *
1.6468 + * This function writes media data to the output file.
1.6469 + *
1.6470 + * Before writing media data to the output file, meta data has
1.6471 + * been written to the file. Media data that is in tmpfile is
1.6472 + * read from there and written to the end of the output file.
1.6473 + *
1.6474 + * Parameters:
1.6475 + *
1.6476 + * handle MP4 library handle
1.6477 + *
1.6478 + * Return value:
1.6479 + *
1.6480 + * 0 Success
1.6481 + * -1 Error
1.6482 + *
1.6483 + */
1.6484 +mp4_i32 writeMediaData(MP4HandleImp handle)
1.6485 +{
1.6486 + mp4_u8 *buf;
1.6487 + mp4_u32 i = 0;
1.6488 + mp4_u64 left;
1.6489 + mp4_u32 bytestoread;
1.6490 +
1.6491 +
1.6492 + buf = (mp4_u8 *)mp4malloc(1024);
1.6493 + if (buf == NULL)
1.6494 + return -1;
1.6495 +
1.6496 +
1.6497 + i = formatMdatHeader(buf, handle->bytesInTmpFile);
1.6498 + if (writeFile(handle, buf, i) < 0)
1.6499 + {
1.6500 + mp4free(buf);
1.6501 +
1.6502 + return -1;
1.6503 + }
1.6504 +
1.6505 + /* Seek to the beginning of tmpfile */
1.6506 + if (seekTmpFileAbs(handle, 0) < 0)
1.6507 + {
1.6508 + mp4free(buf);
1.6509 + return -1;
1.6510 + }
1.6511 +
1.6512 + left = handle->bytesInTmpFile;
1.6513 +
1.6514 + while (left)
1.6515 + {
1.6516 + if (left > 1024)
1.6517 + bytestoread = 1024;
1.6518 + else
1.6519 + bytestoread = left;
1.6520 +
1.6521 + if (readTmpFile(handle, buf, bytestoread) < 0)
1.6522 + {
1.6523 + mp4free(buf);
1.6524 +
1.6525 + return -1;
1.6526 + }
1.6527 +
1.6528 + if (writeFile(handle, buf, bytestoread) < 0)
1.6529 + {
1.6530 + mp4free(buf);
1.6531 +
1.6532 + return -1;
1.6533 + }
1.6534 +
1.6535 + left -= bytestoread;
1.6536 + }
1.6537 +
1.6538 + mp4free(buf);
1.6539 +
1.6540 + return 0;
1.6541 +}
1.6542 +
1.6543 +/*
1.6544 + * Function:
1.6545 + *
1.6546 + * mp4_i32 insertu64(mp4_u8 *buf,
1.6547 + * mp4_u64 value)
1.6548 + *
1.6549 + * Description:
1.6550 + *
1.6551 + * This function writes value into buf taking into account the endianism
1.6552 + * of the current computer.
1.6553 + *
1.6554 + * It is assumed that the caller of the function has allocated enough
1.6555 + * space for buf.
1.6556 + *
1.6557 + * Parameters:
1.6558 + *
1.6559 + * buf Buffer to write to
1.6560 + * value Value to write to buf
1.6561 + *
1.6562 + * Return value:
1.6563 + *
1.6564 + * 0 Success
1.6565 + *
1.6566 + */
1.6567 +mp4_i32 insertu64(mp4_u8 *buf, mp4_u64 value)
1.6568 +{
1.6569 + mp4_u64 u64;
1.6570 +
1.6571 +
1.6572 + u64 = u64endian(value);
1.6573 + mp4memcpy(buf, &u64, sizeof(mp4_u64));
1.6574 +
1.6575 + return 0;
1.6576 +}
1.6577 +
1.6578 +
1.6579 +/*
1.6580 + * Function:
1.6581 + *
1.6582 + * mp4_i32 insertu32(mp4_u8 *buf,
1.6583 + * mp4_u32 value)
1.6584 + *
1.6585 + * Description:
1.6586 + *
1.6587 + * This function writes value into buf taking into account the endianism
1.6588 + * of the current computer.
1.6589 + *
1.6590 + * It is assumed that the caller of the function has allocated enough
1.6591 + * space for buf.
1.6592 + *
1.6593 + * Parameters:
1.6594 + *
1.6595 + * buf Buffer to write to
1.6596 + * value Value to write to buf
1.6597 + *
1.6598 + * Return value:
1.6599 + *
1.6600 + * 0 Success
1.6601 + *
1.6602 + */
1.6603 +mp4_i32 insertu32(mp4_u8 *buf, mp4_u32 value)
1.6604 +{
1.6605 + mp4_u32 u32;
1.6606 +
1.6607 +
1.6608 + u32 = u32endian(value);
1.6609 + mp4memcpy(buf, &u32, 4);
1.6610 +
1.6611 + return 0;
1.6612 +}
1.6613 +
1.6614 +
1.6615 +/*
1.6616 + * Function:
1.6617 + *
1.6618 + * mp4_i32 insertu16(mp4_u8 *buf,
1.6619 + * mp4_u16 value)
1.6620 + *
1.6621 + * Description:
1.6622 + *
1.6623 + * This function writes value into buf taking into account the endianism
1.6624 + * of the current computer.
1.6625 + *
1.6626 + * It is assumed that the caller of the function has allocated enough
1.6627 + * space for buf.
1.6628 + *
1.6629 + * Parameters:
1.6630 + *
1.6631 + * buf Buffer to write to
1.6632 + * value Value to write to buf
1.6633 + *
1.6634 + * Return value:
1.6635 + *
1.6636 + * 0 Success
1.6637 + *
1.6638 + */
1.6639 +mp4_i32 insertu16(mp4_u8 *buf, mp4_u16 value)
1.6640 +{
1.6641 + mp4_u16 u16;
1.6642 +
1.6643 +
1.6644 + u16 = u16endian(value);
1.6645 + mp4memcpy(buf, &u16, 2);
1.6646 +
1.6647 + return 0;
1.6648 +}
1.6649 +
1.6650 +
1.6651 +/*
1.6652 + * Function:
1.6653 + *
1.6654 + * mp4_i32 writeMetaDataTmp(MP4HandleImp handle)
1.6655 + *
1.6656 + * Description:
1.6657 + *
1.6658 + * This function writes metadata accumulated in memory to the disk.
1.6659 + *
1.6660 + * Parameters:
1.6661 + *
1.6662 + * handle MP4 library handle
1.6663 + *
1.6664 + * Return value:
1.6665 + *
1.6666 + * 0 Success
1.6667 + * -1 Error
1.6668 + *
1.6669 + */
1.6670 +mp4_i32 writeMetaDataTmp(MP4HandleImp handle)
1.6671 +{
1.6672 + PRINT((_L("e_writemetadatatmp 1")));
1.6673 + if (handle->videoSampleTable)
1.6674 + {
1.6675 + PRINT((_L("e_writemetadatatmp_writemetadata_video 1")));
1.6676 + if (writeMetaDataFileNum(handle,
1.6677 + (mp4_u8 *)handle->videoSampleTable->sttsSampleCount,
1.6678 + handle->videoSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32),
1.6679 + METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0)
1.6680 + return -1;
1.6681 +
1.6682 + if (writeMetaDataFileNum(handle,
1.6683 + (mp4_u8 *)handle->videoSampleTable->sttsSampleDelta,
1.6684 + handle->videoSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32),
1.6685 + METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0)
1.6686 + return -1;
1.6687 +
1.6688 + if (writeMetaDataFileNum(handle,
1.6689 + (mp4_u8 *)handle->videoSampleTable->stszEntrySize,
1.6690 + handle->videoSampleTable->stszCurrentSampleCount * sizeof(mp4_u32),
1.6691 + METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0)
1.6692 + return -1;
1.6693 +
1.6694 + if (writeMetaDataFileNum(handle,
1.6695 + (mp4_u8 *)handle->videoSampleTable->stcoChunkOffset,
1.6696 + handle->videoSampleTable->stcoCurrentEntryCount * sizeof(mp4_u64),
1.6697 + METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0)
1.6698 + return -1;
1.6699 +
1.6700 + if (writeMetaDataFileNum(handle,
1.6701 + (mp4_u8 *)handle->videoSampleTable->stssSampleNumber,
1.6702 + handle->videoSampleTable->stssCurrentEntryCount * sizeof(mp4_u32),
1.6703 + METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0)
1.6704 + return -1;
1.6705 +
1.6706 + if (writeMetaDataFileNum(handle,
1.6707 + (mp4_u8 *)handle->videoSampleTable->sdtpSampleDependency,
1.6708 + handle->videoSampleTable->sdtpCurrentEntryCount * sizeof(mp4_u8),
1.6709 + METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0)
1.6710 + return -1;
1.6711 + PRINT((_L("e_writemetadatatmp_writemetadata_video 0")));
1.6712 + }
1.6713 +
1.6714 + if (handle->audioSampleTable)
1.6715 + {
1.6716 + PRINT((_L("e_writemetadatatmp_writemetadata_audio 1")));
1.6717 + if (writeMetaDataFileNum(handle,
1.6718 + (mp4_u8 *)handle->audioSampleTable->sttsSampleCount,
1.6719 + handle->audioSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32),
1.6720 + METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0)
1.6721 + return -1;
1.6722 +
1.6723 + if (writeMetaDataFileNum(handle,
1.6724 + (mp4_u8 *)handle->audioSampleTable->sttsSampleDelta,
1.6725 + handle->audioSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32),
1.6726 + METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0)
1.6727 + return -1;
1.6728 +
1.6729 + if (writeMetaDataFileNum(handle,
1.6730 + (mp4_u8 *)handle->audioSampleTable->stszEntrySize,
1.6731 + handle->audioSampleTable->stszCurrentSampleCount * sizeof(mp4_u32),
1.6732 + METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0)
1.6733 + return -1;
1.6734 +
1.6735 + if (writeMetaDataFileNum(handle,
1.6736 + (mp4_u8 *)handle->audioSampleTable->stcoChunkOffset,
1.6737 + handle->audioSampleTable->stcoCurrentEntryCount * sizeof(mp4_u64),
1.6738 + METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0)
1.6739 + return -1;
1.6740 + PRINT((_L("e_writemetadatatmp_writemetadata_audio 0")));
1.6741 + }
1.6742 +
1.6743 + if (handle->videoSampleTable)
1.6744 + {
1.6745 + handle->videoSampleTable->sttsCurrentEntryCount = 0;
1.6746 + handle->videoSampleTable->stszCurrentSampleCount = 0;
1.6747 + handle->videoSampleTable->stcoCurrentEntryCount = 0;
1.6748 + handle->videoSampleTable->stssCurrentEntryCount = 0;
1.6749 + handle->videoSampleTable->sdtpCurrentEntryCount = 0;
1.6750 + }
1.6751 +
1.6752 + if (handle->audioSampleTable)
1.6753 + {
1.6754 + handle->audioSampleTable->sttsCurrentEntryCount = 0;
1.6755 + handle->audioSampleTable->stszCurrentSampleCount = 0;
1.6756 + handle->audioSampleTable->stcoCurrentEntryCount = 0;
1.6757 + }
1.6758 +
1.6759 + handle->metaDataBlocks = 0;
1.6760 + handle->metaDataOnDisk = MP4TRUE;
1.6761 +
1.6762 + PRINT((_L("e_writemetadatatmp 0")));
1.6763 + return 0;
1.6764 +}
1.6765 +
1.6766 +/*
1.6767 + * Function:
1.6768 + *
1.6769 + * mp4_i32 writeSQCP(MP4HandleImp handle,
1.6770 + * trakSize *ts)
1.6771 + *
1.6772 + * Description:
1.6773 + *
1.6774 + * Write SQCP atom.
1.6775 + *
1.6776 + * Parameters:
1.6777 + *
1.6778 + * handle MP4 library handle
1.6779 + * ts Atom sizes
1.6780 + *
1.6781 + * Return value:
1.6782 + *
1.6783 + * 0 Success
1.6784 + * -1 Error
1.6785 + *
1.6786 + */
1.6787 +mp4_i32 writeSQCP(MP4HandleImp handle, trakSize *ts)
1.6788 +{
1.6789 + mp4_u8 *buf;
1.6790 + mp4_u32 i = 0;
1.6791 +
1.6792 +
1.6793 + buf = (mp4_u8 *)mp4malloc(36);
1.6794 + if (buf == NULL)
1.6795 + return -1;
1.6796 +
1.6797 + /* Size */
1.6798 + insertu32(buf+i, (mp4_u32)ts->sqcp);
1.6799 + i += 4;
1.6800 +
1.6801 + /* Atom type */
1.6802 + insertu32(buf+i, (mp4_u32)ATOMTYPE_SQCP);
1.6803 + i += 4;
1.6804 +
1.6805 + /* Reserved */
1.6806 + buf[i++] = 0;
1.6807 + buf[i++] = 0;
1.6808 + buf[i++] = 0;
1.6809 + buf[i++] = 0;
1.6810 + buf[i++] = 0;
1.6811 + buf[i++] = 0;
1.6812 +
1.6813 + /* Data reference index */
1.6814 + insertu16(buf+i, (mp4_u16)1);
1.6815 + i += 2;
1.6816 +
1.6817 + /* Reserved */
1.6818 + insertu32(buf+i, (mp4_u32)0);
1.6819 + i += 4;
1.6820 +
1.6821 + insertu32(buf+i, (mp4_u32)0);
1.6822 + i += 4;
1.6823 +
1.6824 + insertu16(buf+i, (mp4_u16)2);
1.6825 + i += 2;
1.6826 +
1.6827 + insertu16(buf+i, (mp4_u16)16);
1.6828 + i += 2;
1.6829 +
1.6830 + insertu32(buf+i, (mp4_u32)0);
1.6831 + i += 4;
1.6832 +
1.6833 + /* Timescale */
1.6834 + insertu16(buf+i, (mp4_u16)handle->audioTimeScale);
1.6835 + i += 2;
1.6836 +
1.6837 + /* Reserved */
1.6838 + insertu16(buf+i, (mp4_u16)0);
1.6839 + i += 2;
1.6840 +
1.6841 + if (writeFile(handle, buf, 36) < 0)
1.6842 + {
1.6843 + mp4free(buf);
1.6844 +
1.6845 + return -1;
1.6846 + }
1.6847 +
1.6848 + if (writeDQCP(handle, ts) < 0)
1.6849 + {
1.6850 + mp4free(buf);
1.6851 +
1.6852 + return -1;
1.6853 + }
1.6854 +
1.6855 + mp4free(buf);
1.6856 +
1.6857 + return 0;
1.6858 +}
1.6859 +
1.6860 +/*
1.6861 + * Function:
1.6862 + *
1.6863 + * mp4_i32 writeDQCP(MP4HandleImp handle,
1.6864 + * trakSize *ts)
1.6865 + *
1.6866 + * Description:
1.6867 + *
1.6868 + * Write DQCP atom.
1.6869 + *
1.6870 + * Parameters:
1.6871 + *
1.6872 + * handle MP4 library handle
1.6873 + * ts Atom sizes
1.6874 + *
1.6875 + * Return value:
1.6876 + *
1.6877 + * 0 Success
1.6878 + * -1 Error
1.6879 + *
1.6880 + */
1.6881 +mp4_i32 writeDQCP(MP4HandleImp handle, trakSize *ts)
1.6882 +{
1.6883 + mp4_u8 buf[14];
1.6884 + mp4_u32 i = 0;
1.6885 +
1.6886 +
1.6887 + /* Size */
1.6888 + insertu32(buf+i, (mp4_u32)ts->dqcp);
1.6889 + i += 4;
1.6890 +
1.6891 + /* Atom type */
1.6892 + insertu32(buf+i, (mp4_u32)ATOMTYPE_DQCP);
1.6893 + i += 4;
1.6894 +
1.6895 + /* Vendor */
1.6896 + buf[i++] = 'n';
1.6897 + buf[i++] = 'o';
1.6898 + buf[i++] = 'k';
1.6899 + buf[i++] = 'i';
1.6900 +
1.6901 + /* Decoder version */
1.6902 + buf[i++] = 0;
1.6903 +
1.6904 + /* Mode set */
1.6905 +// insertu16(buf+i, (mp4_u16)handle->audioModeSet);
1.6906 +// i += 2;
1.6907 +
1.6908 + /* Mode change period */
1.6909 +// buf[i++] = 0;
1.6910 +
1.6911 + /* Frames per sample */
1.6912 + buf[i++] = handle->audioFramesPerSample;
1.6913 +
1.6914 + if (writeFile(handle, buf, 14) < 0)
1.6915 + return -1;
1.6916 +
1.6917 + return 0;
1.6918 +}
1.6919 +
1.6920 +/*
1.6921 + * Function:
1.6922 + *
1.6923 + * mp4_i32 calculateES_DescriptorSize(mp4_u32 type)
1.6924 + *
1.6925 + * Description:
1.6926 + *
1.6927 + * Calculated the ES_Descriptor size inside the ESDS box.
1.6928 + * Updates handle->ES_DescriptorSize;
1.6929 + *
1.6930 + * Parameters:
1.6931 + *
1.6932 + * handle MP4 library handle
1.6933 + * type the media type:
1.6934 + * MP4_TYPE_QCELP_13K
1.6935 + * MP4_TYPE_MPEG_AUDIO
1.6936 + * MP4_TYPE_MPEG4_VIDEO
1.6937 + *
1.6938 + * Return value:
1.6939 + *
1.6940 + * 0 Success
1.6941 + *
1.6942 + */
1.6943 +mp4_i32 calculateES_DescriptorSize(MP4HandleImp handle, mp4_u32 type)
1.6944 +{
1.6945 + mp4_u32 size1, size2, size3;
1.6946 + mp4_u32 numofsizebytes1, numofsizebytes2, numofsizebytes3;
1.6947 + mp4_u32 decspecinfosize = 0;
1.6948 +
1.6949 + if (((type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) ||
1.6950 + (type & MP4_TYPE_MPEG4_AUDIO))
1.6951 + decspecinfosize = handle->audioDecSpecificInfoSize;
1.6952 + else /* MPEG video case */
1.6953 + decspecinfosize = handle->videoDecSpecificInfoSize;
1.6954 +
1.6955 + size1 = decspecinfosize;
1.6956 + if (size1 < 128)
1.6957 + numofsizebytes1 = 1;
1.6958 + else
1.6959 + {
1.6960 + numofsizebytes1 = 1;
1.6961 + while ( size1 >= 128 )
1.6962 + {
1.6963 + size1 = size1 >> 7;
1.6964 + numofsizebytes1++;
1.6965 + }
1.6966 + }
1.6967 +
1.6968 + size2 = 14 + numofsizebytes1 + decspecinfosize;
1.6969 + if (size2 < 128)
1.6970 + numofsizebytes2 = 1;
1.6971 + else
1.6972 + {
1.6973 + numofsizebytes2 = 1;
1.6974 + while ( size2 >= 128 )
1.6975 + {
1.6976 + size2 = size2 >> 7;
1.6977 + numofsizebytes2++;
1.6978 + }
1.6979 + }
1.6980 +
1.6981 + size3 = 21 + numofsizebytes1 + numofsizebytes2 + decspecinfosize;
1.6982 + if (size3 < 128)
1.6983 + numofsizebytes3 = 1;
1.6984 + else
1.6985 + {
1.6986 + numofsizebytes3 = 1;
1.6987 + while ( size3 >= 128 )
1.6988 + {
1.6989 + size3 = size3 >> 7;
1.6990 + numofsizebytes3++;
1.6991 + }
1.6992 + }
1.6993 +
1.6994 + /* ES_DescriptorSize contains the size of the ES_Descriptor Field, including the 0x03 (ES_ID Tag) */
1.6995 + handle->ES_DescriptorSize = 21 + numofsizebytes1 + numofsizebytes2 + decspecinfosize + numofsizebytes3 + 1;
1.6996 + return 0;
1.6997 +}
1.6998 +
1.6999 +/*
1.7000 + * Function:
1.7001 + *
1.7002 + * mp4_i32 writeUDTA(MP4HandleImp handle,
1.7003 + * userDataAtom *udta)
1.7004 + *
1.7005 + * Description:
1.7006 + *
1.7007 + * Write UDTA atom.
1.7008 + *
1.7009 + * Parameters:
1.7010 + *
1.7011 + * handle MP4 library handle
1.7012 + * ts Atom sizes
1.7013 + *
1.7014 + * Return value:
1.7015 + *
1.7016 + * 0 Success
1.7017 + * -1 Error
1.7018 + *
1.7019 + */
1.7020 +mp4_i32 writeUDTA(MP4HandleImp handle, userDataAtom *udta)
1.7021 +{
1.7022 + mp4_u8 buf[8];
1.7023 + mp4_u32 i = 0;
1.7024 +
1.7025 +
1.7026 + /* Size */
1.7027 + insertu32(buf+i, 8 + (mp4_u32)udta->atomcontentsize);
1.7028 + i += 4;
1.7029 +
1.7030 + /* Atom type */
1.7031 + insertu32(buf+i, (mp4_u32)ATOMTYPE_UDTA);
1.7032 + i += 4;
1.7033 +
1.7034 + if (writeFile(handle, buf, 8) < 0)
1.7035 + return -1;
1.7036 +
1.7037 + if (writeFile(handle, udta->contentdata, udta->atomcontentsize) < 0)
1.7038 + return -1;
1.7039 +
1.7040 + return 0;
1.7041 +}
1.7042 +
1.7043 +/*
1.7044 + * Function:
1.7045 + *
1.7046 + * mp4_i32 updateVideoDependencyMetaData(MP4HandleImp handle,
1.7047 + * mp4_u8 aDependsOn,
1.7048 + * mp4_u8 aIsDependentOn,
1.7049 + * mp4_u8 aHasRedundancy)
1.7050 + *
1.7051 + * Description:
1.7052 + *
1.7053 + * Updates SDTP video dependency data
1.7054 + *
1.7055 + * Parameters:
1.7056 + *
1.7057 + * handle MP4 library handle
1.7058 + * aDependsOn This frame's dependency on other frames
1.7059 + * aIsDependentOn Other frames's dependency on this frame
1.7060 + * aHasRedundancy Whether there is redundant coding in this frame
1.7061 + *
1.7062 + * Return value:
1.7063 + *
1.7064 + * 0 Success
1.7065 + * -1 Error
1.7066 + *
1.7067 + */
1.7068 +mp4_i32 updateVideoDependencyMetaData(MP4HandleImp handle, mp4_u8 aDependsOn, mp4_u8 aIsDependentOn, mp4_u8 aHasRedundancy)
1.7069 +{
1.7070 + if (handle->flags & MP4_FLAG_LONGCLIP)
1.7071 + {
1.7072 + if (handle->videoSampleTable->sdtpCurrentEntryCount == handle->videoSampleTable->sdtpMaxEntryCount)
1.7073 + {
1.7074 + void *p;
1.7075 +
1.7076 + p = mp4realloc(handle->videoSampleTable->sdtpSampleDependency,
1.7077 + 2 * sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount,
1.7078 + sizeof(mp4_u8) * handle->videoSampleTable->stssMaxEntryCount);
1.7079 + if (p == NULL)
1.7080 + return -1;
1.7081 +
1.7082 + handle->videoSampleTable->sdtpSampleDependency = (mp4_u8 *)p;
1.7083 +
1.7084 + handle->videoSampleTable->sdtpMaxEntryCount *= 2;
1.7085 + }
1.7086 +
1.7087 + handle->videoSampleTable->sdtpSampleDependency[handle->videoSampleTable->sdtpCurrentEntryCount] = (aDependsOn << 4) | (aIsDependentOn << 2) | (aHasRedundancy);
1.7088 + handle->videoSampleTable->sdtpCurrentEntryCount++;
1.7089 + handle->videoSampleTable->sdtpEntryCount++;
1.7090 + }
1.7091 + else
1.7092 + {
1.7093 + if (handle->videoSampleTable->sdtpEntryCount == handle->videoSampleTable->sdtpMaxEntryCount)
1.7094 + {
1.7095 + void *p;
1.7096 +
1.7097 + p = mp4realloc(handle->videoSampleTable->sdtpSampleDependency,
1.7098 + 2 * sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount,
1.7099 + sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount);
1.7100 + if (p == NULL)
1.7101 + return -1;
1.7102 +
1.7103 + handle->videoSampleTable->sdtpSampleDependency = (mp4_u8 *)p;
1.7104 +
1.7105 + handle->videoSampleTable->sdtpMaxEntryCount *= 2;
1.7106 + }
1.7107 +
1.7108 + handle->videoSampleTable->sdtpSampleDependency[handle->videoSampleTable->sdtpEntryCount] = (aDependsOn << 4) | (aIsDependentOn << 2) | (aHasRedundancy);
1.7109 + handle->videoSampleTable->sdtpEntryCount++;
1.7110 + }
1.7111 +
1.7112 + return 0;
1.7113 +}
1.7114 +
1.7115 +/*
1.7116 + * Function:
1.7117 + *
1.7118 + * mp4_i32 writeVideoSDTP(MP4HandleImp handle,
1.7119 + * trakSize *ts)
1.7120 + *
1.7121 + * Description:
1.7122 + *
1.7123 + * Write video SDTP atom.
1.7124 + *
1.7125 + * Parameters:
1.7126 + *
1.7127 + * handle MP4 library handle
1.7128 + * ts Atom sizes
1.7129 + *
1.7130 + * Return value:
1.7131 + *
1.7132 + * 0 Success
1.7133 + * -1 Error
1.7134 + *
1.7135 + */
1.7136 +mp4_i32 writeVideoSDTP(MP4HandleImp handle, trakSize *ts)
1.7137 +{
1.7138 + mp4_u8 *buf;
1.7139 + mp4_u32 i = 0;
1.7140 + mp4_u32 j;
1.7141 +
1.7142 + buf = (mp4_u8 *)mp4malloc(ts->sdtp);
1.7143 + if (buf == NULL)
1.7144 + return -1;
1.7145 +
1.7146 + /* Size */
1.7147 + insertu32(buf+i, (mp4_u32)ts->sdtp);
1.7148 + i += 4;
1.7149 +
1.7150 + /* Atom type */
1.7151 + insertu32(buf+i, (mp4_u32)ATOMTYPE_SDTP);
1.7152 + i += 4;
1.7153 +
1.7154 + /* Version and flags */
1.7155 + insertu32(buf+i, (mp4_u32)0);
1.7156 + i += 4;
1.7157 +
1.7158 + /* Sample dependencies */
1.7159 + for (j = 0; j < handle->videoSampleTable->sdtpEntryCount; j++)
1.7160 + {
1.7161 + buf[i++] = (mp4_u8)handle->videoSampleTable->sdtpSampleDependency[j];
1.7162 + }
1.7163 +
1.7164 + if (writeFile(handle, buf, ts->sdtp) < 0)
1.7165 + {
1.7166 + mp4free(buf);
1.7167 +
1.7168 + return -1;
1.7169 + }
1.7170 +
1.7171 + mp4free(buf);
1.7172 +
1.7173 + return 0;
1.7174 +}
1.7175 +
1.7176 +/*
1.7177 + * Function:
1.7178 + *
1.7179 + * mp4_i32 writeVideoSDTPLongClip(MP4HandleImp handle,
1.7180 + * trakSize *ts)
1.7181 + *
1.7182 + * Description:
1.7183 + *
1.7184 + * Write video SDTP atom.
1.7185 + *
1.7186 + * Parameters:
1.7187 + *
1.7188 + * handle MP4 library handle
1.7189 + * ts Atom sizes
1.7190 + *
1.7191 + * Return value:
1.7192 + *
1.7193 + * 0 Success
1.7194 + * -1 Error
1.7195 + *
1.7196 + */
1.7197 +mp4_i32 writeVideoSDTPLongClip(MP4HandleImp handle, trakSize *ts)
1.7198 +{
1.7199 + mp4_u8 *buf;
1.7200 + mp4_u8 *buf2;
1.7201 + mp4_u32 i = 0;
1.7202 + mp4_u32 left;
1.7203 + mp4_u32 bytestoread;
1.7204 +
1.7205 +
1.7206 + buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE);
1.7207 + if (buf == NULL)
1.7208 + return -1;
1.7209 +
1.7210 + buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2);
1.7211 + if (buf2 == NULL)
1.7212 + {
1.7213 + mp4free(buf);
1.7214 + return -1;
1.7215 + }
1.7216 +
1.7217 + /* Size */
1.7218 + insertu32(buf+i, (mp4_u32)ts->sdtp);
1.7219 + i += 4;
1.7220 +
1.7221 + /* Atom type */
1.7222 + insertu32(buf+i, (mp4_u32)ATOMTYPE_SDTP);
1.7223 + i += 4;
1.7224 +
1.7225 + /* Version and flags */
1.7226 + insertu32(buf+i, (mp4_u32)0);
1.7227 + i += 4;
1.7228 +
1.7229 + if (writeFile(handle, buf, i) < 0)
1.7230 + {
1.7231 + mp4free(buf);
1.7232 + mp4free(buf2);
1.7233 +
1.7234 + return -1;
1.7235 + }
1.7236 +
1.7237 + /* Sample count and delta */
1.7238 +
1.7239 + /* Seek to the beginning of temporary files */
1.7240 +
1.7241 + if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0)
1.7242 + {
1.7243 + mp4free(buf);
1.7244 + mp4free(buf2);
1.7245 + return -1;
1.7246 + }
1.7247 +
1.7248 + left = handle->videoSampleTable->sdtpEntryCount; /* Bytes left in each file */
1.7249 +
1.7250 + while (left)
1.7251 + {
1.7252 + if (left > METADATA_COPY_BUFFERSIZE / 2)
1.7253 + bytestoread = METADATA_COPY_BUFFERSIZE / 2;
1.7254 + else
1.7255 + bytestoread = left;
1.7256 +
1.7257 + if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0)
1.7258 + {
1.7259 + mp4free(buf);
1.7260 + mp4free(buf2);
1.7261 +
1.7262 + return -1;
1.7263 + }
1.7264 +
1.7265 + if (writeFile(handle, buf2, bytestoread) < 0)
1.7266 + {
1.7267 + mp4free(buf);
1.7268 + mp4free(buf2);
1.7269 +
1.7270 + return -1;
1.7271 + }
1.7272 +
1.7273 + left -= bytestoread;
1.7274 + }
1.7275 +
1.7276 + mp4free(buf);
1.7277 + mp4free(buf2);
1.7278 +
1.7279 +
1.7280 + return 0;
1.7281 +}
1.7282 +
1.7283 +/*
1.7284 + * Function:
1.7285 + *
1.7286 + * mp4_i32 writeAVCP(MP4HandleImp handle,
1.7287 + * trakSize *ts)
1.7288 + *
1.7289 + * Description:
1.7290 + *
1.7291 + * Write AVCP atom.
1.7292 + *
1.7293 + * Parameters:
1.7294 + *
1.7295 + * handle MP4 library handle
1.7296 + * ts Atom sizes
1.7297 + *
1.7298 + * Return value:
1.7299 + *
1.7300 + * 0 Success
1.7301 + * -1 Error
1.7302 + *
1.7303 + */
1.7304 +mp4_i32 writeAVCP(MP4HandleImp handle, trakSize *ts)
1.7305 +{
1.7306 + mp4_u8 *buf;
1.7307 + mp4_u32 i = 0;
1.7308 +
1.7309 +
1.7310 + buf = (mp4_u8 *)mp4malloc(86+7); // 86 = size of VisualSampleEntry, 7 = size of AVCDecoderConfigurationRecord
1.7311 + // with PPS and SPS sizes set to 0
1.7312 + if (buf == NULL)
1.7313 + return -1;
1.7314 +
1.7315 + /* Size */
1.7316 + insertu32(buf+i, (mp4_u32)ts->avcp);
1.7317 + i += 4;
1.7318 +
1.7319 + /* Atom type */
1.7320 + insertu32(buf+i, (mp4_u32)ATOMTYPE_AVCP);
1.7321 + i += 4;
1.7322 +
1.7323 + /* Reserved */
1.7324 + buf[i++] = 0;
1.7325 + buf[i++] = 0;
1.7326 + buf[i++] = 0;
1.7327 + buf[i++] = 0;
1.7328 + buf[i++] = 0;
1.7329 + buf[i++] = 0;
1.7330 +
1.7331 + /* Data reference index */
1.7332 + insertu16(buf+i, (mp4_u16)1);
1.7333 + i += 2;
1.7334 +
1.7335 + /* Reserved */
1.7336 + insertu32(buf+i, (mp4_u32)0);
1.7337 + i += 4;
1.7338 +
1.7339 + insertu32(buf+i, (mp4_u32)0);
1.7340 + i += 4;
1.7341 +
1.7342 + insertu32(buf+i, (mp4_u32)0);
1.7343 + i += 4;
1.7344 +
1.7345 + insertu32(buf+i, (mp4_u32)0);
1.7346 + i += 4;
1.7347 +
1.7348 + /* Width */
1.7349 + insertu16(buf+i, (mp4_u16)handle->videoWidth);
1.7350 + i += 2;
1.7351 +
1.7352 + /* Height */
1.7353 + insertu16(buf+i, (mp4_u16)handle->videoHeight);
1.7354 + i += 2;
1.7355 +
1.7356 + /* Reserved */
1.7357 + insertu32(buf+i, (mp4_u32)0x00480000);
1.7358 + i += 4;
1.7359 +
1.7360 + insertu32(buf+i, (mp4_u32)0x00480000);
1.7361 + i += 4;
1.7362 +
1.7363 + insertu32(buf+i, (mp4_u32)0);
1.7364 + i += 4;
1.7365 +
1.7366 + insertu16(buf+i, (mp4_u16)1);
1.7367 + i += 2;
1.7368 +
1.7369 +// Compressorname
1.7370 + buf[i++] = 14;
1.7371 + insertu32(buf+i, (mp4_u32)0x41564320); // "AVC "
1.7372 + i += 4;
1.7373 + insertu32(buf+i, (mp4_u32)0x70617261); // "para"
1.7374 + i += 4;
1.7375 + insertu32(buf+i, (mp4_u32)0x6d657465); // "mete"
1.7376 + i += 4;
1.7377 + insertu16(buf+i, (mp4_u16)0x7273); // "rs"
1.7378 + i += 2;
1.7379 + buf[i++] = 0;
1.7380 + insertu32(buf+i, (mp4_u32)0);
1.7381 + i += 4;
1.7382 + insertu32(buf+i, (mp4_u32)0);
1.7383 + i += 4;
1.7384 + insertu32(buf+i, (mp4_u32)0);
1.7385 + i += 4;
1.7386 + insertu32(buf+i, (mp4_u32)0);
1.7387 + i += 4;
1.7388 +
1.7389 + insertu16(buf+i, (mp4_u16)24);
1.7390 + i += 2;
1.7391 +
1.7392 + insertu16(buf+i, (mp4_u16)0xffff);
1.7393 + i += 2;
1.7394 +
1.7395 + // AVCC without picparams & seqparams
1.7396 + mp4memcpy(buf+i, handle->videoDecSpecificInfo, 5); // 5 = configurationVersion + AVCProfileIndication +
1.7397 + // profile_compatibility + AVCLevelIndication +
1.7398 + // '111111' + lengthSizeMinusOne (2 bits)
1.7399 + i += 5;
1.7400 + buf[i++] = 0xE0 | 0; // '111' + numOfSequenceParameterSets (5 bits)
1.7401 + buf[i++] = 0; // numOfPictureParameterSets
1.7402 +
1.7403 + if (writeFile(handle, buf, 86+7) < 0)
1.7404 + {
1.7405 + mp4free(buf);
1.7406 +
1.7407 + return -1;
1.7408 + }
1.7409 +
1.7410 + mp4free(buf);
1.7411 +
1.7412 + return 0;
1.7413 +}
1.7414 +
1.7415 +/*
1.7416 + * Function:
1.7417 + *
1.7418 + * mp4_i32 formatMdatHeader(mp4_u8 *buffer,
1.7419 + * mp4_u64 size)
1.7420 + *
1.7421 + * Description:
1.7422 + *
1.7423 + * Formats the MDAT header into buffer
1.7424 + *
1.7425 + * Parameters:
1.7426 + *
1.7427 + * buffer buffer to write the MDAT header into
1.7428 + * size Size of the media data (excluding the MDAT header)
1.7429 + *
1.7430 + * Return value:
1.7431 + *
1.7432 + * size of header
1.7433 + *
1.7434 + */
1.7435 +mp4_i32 formatMdatHeader(mp4_u8 *buf, mp4_u64 size)
1.7436 +{
1.7437 + TInt i = 0;
1.7438 + if (size < MP4_INT_MAX)
1.7439 + {
1.7440 + //insert free box
1.7441 + insertu32(buf, (mp4_u32)8);
1.7442 + i += sizeof(mp4_u32);
1.7443 + insertu32(buf + i, (mp4_u32)ATOMTYPE_FREE);
1.7444 + i += sizeof(mp4_u32);
1.7445 +
1.7446 + //insert mdat box
1.7447 + insertu32(buf + i, (mp4_u32)size + 8);
1.7448 + i += sizeof(mp4_u32);
1.7449 + insertu32(buf + i, (mp4_u32)ATOMTYPE_MDAT);
1.7450 + i += sizeof(mp4_u32);
1.7451 + }
1.7452 + else
1.7453 + {
1.7454 + //insert mdat box
1.7455 + insertu32(buf + i, (mp4_u32)1);
1.7456 + i += sizeof(mp4_u32);
1.7457 + insertu32(buf + i, (mp4_u32)ATOMTYPE_MDAT);
1.7458 + i += sizeof(mp4_u32);
1.7459 + insertu64(buf + i, (mp4_u64)size + 16);
1.7460 + i += sizeof(mp4_u64);
1.7461 + }
1.7462 +
1.7463 + ASSERT(MDAT_HEADER_SIZE == i);
1.7464 + return i;
1.7465 +}
1.7466 +
1.7467 +// End of File