sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include <3gplibrary/mp4config.h> sl@0: #include <3gplibrary/mp4lib.h> sl@0: #include "mp4atom.h" sl@0: #include "mp4memwrap.h" sl@0: #include "mp4file.h" sl@0: #include "mp4endian.h" sl@0: #include "mp4compose.h" sl@0: #include "mp4currenttime.h" sl@0: #include "mp4utils.h" sl@0: sl@0: #define MP4_INT_MAX KMaxTInt32 sl@0: #define MDAT_HEADER_SIZE 16 sl@0: sl@0: // MACROS sl@0: // Debug print macro sl@0: #ifdef _DEBUG sl@0: #include sl@0: #define PRINT(x) sl@0: #else sl@0: #define PRINT(x) sl@0: #endif sl@0: sl@0: sl@0: inline void updateChunkOffset(sampleTable *st, mp4_i32 index, mp4_i64 value) sl@0: { sl@0: if (value > MP4_INT_MAX) sl@0: st->stcoNeed64Bits = ETrue; sl@0: sl@0: st->stcoChunkOffset[index] = value; sl@0: } sl@0: sl@0: /* must be called after determineAudioTrakMetaDataSize and determineVideoTrakMetaDataSize */ sl@0: size_t mvhdAtomSize(MP4HandleImp handle) sl@0: { sl@0: if (handle->videoDuration > MP4_INT_MAX || handle->audioDuration > MP4_INT_MAX) sl@0: { sl@0: return 120; sl@0: } sl@0: else sl@0: { sl@0: return 108; sl@0: } sl@0: } sl@0: sl@0: sl@0: sl@0: /* helper functions */ sl@0: mp4_i32 formatMdatHeader(mp4_u8 *buffer, mp4_i64 size); sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateVideoMetaData(MP4HandleImp handle, sl@0: * mp4_u32 size, sl@0: * mp4_u32 duration) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates sample table atom data. sl@0: * sl@0: * One call of this function will generate one chunk in the MP4 file. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * size Size of video frame to insert sl@0: * duration Duration of the video frame (in media timescale) sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateVideoMetaData(MP4HandleImp handle, mp4_u32 size, mp4_u32 duration, mp4_bool keyframe) sl@0: { sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (handle->metaDataBlocks == BLOCK_LIMIT) sl@0: { sl@0: /* Write metadata to temporary files */ sl@0: sl@0: if (writeMetaDataTmp(handle) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: handle->metaDataBlocks++; sl@0: } sl@0: sl@0: handle->videoSampleTable->currentChunk++; sl@0: sl@0: if (updateDecodingTimeToSample(handle, handle->videoSampleTable, duration) < 0) sl@0: return -1; sl@0: sl@0: if (updateSampleSize(handle, handle->videoSampleTable, size) < 0) sl@0: return -1; sl@0: sl@0: if (updateSampleToChunk(handle->videoSampleTable) < 0) sl@0: return -1; sl@0: sl@0: if (updateChunkOffset(handle, handle->videoSampleTable) < 0) sl@0: return -1; sl@0: sl@0: if (keyframe) sl@0: if (updateSyncSample(handle, handle->videoSampleTable) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateAudioMetaData(MP4HandleImp handle, sl@0: * mp4_u32 size, sl@0: * mp4_u32 numberofframes) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates sample table atom data. sl@0: * sl@0: * One call of this function will generate one chunk in the MP4 file. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * size Size of video frame to insert sl@0: * duration Duration of audio frames (in timescale, sl@0: * see MP4ComposeAddAudioDescription) sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateAudioMetaData(MP4HandleImp handle, mp4_u32 size, mp4_u32 duration) sl@0: { sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (handle->metaDataBlocks == BLOCK_LIMIT) sl@0: { sl@0: /* Write metadata to temporary files */ sl@0: sl@0: if (writeMetaDataTmp(handle) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: handle->metaDataBlocks++; sl@0: } sl@0: sl@0: handle->audioSampleTable->currentChunk++; sl@0: sl@0: if (updateDecodingTimeToSample(handle, handle->audioSampleTable, duration) < 0) sl@0: return -1; sl@0: sl@0: if (updateSampleSize(handle, handle->audioSampleTable, size) < 0) sl@0: return -1; sl@0: sl@0: if (updateSampleToChunk(handle->audioSampleTable) < 0) sl@0: return -1; sl@0: sl@0: if (updateChunkOffset(handle, handle->audioSampleTable) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeFTYPAndMDATToFile(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes FTYP box to a file. In addition, it writes MDAT box sl@0: * size and type to a file. The function is used when meta data is put to sl@0: * the end of file. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeFTYPAndMDATToFile(MP4HandleImp handle) sl@0: { sl@0: mp4_u8 buf[32]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: if (writeFTYP(handle) < 0) sl@0: return -1; sl@0: sl@0: handle->ftypWritten = MP4TRUE; sl@0: sl@0: sl@0: i = formatMdatHeader(buf, (mp4_u32)0); sl@0: if (writeFile(handle, buf, i) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeDataToFile(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes meta and media data to a file. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeDataToFile(MP4HandleImp handle) sl@0: { sl@0: PRINT((_L("e_writedatatofile 1"))); sl@0: mp4_u32 metaDataSize = 0; sl@0: trakSize *audioTrackSize; sl@0: trakSize *videoTrackSize; sl@0: mp4_bool haveAudio = MP4FALSE; sl@0: mp4_bool haveVideo = MP4FALSE; sl@0: mp4_u8 ftypdelta = 0; sl@0: sl@0: sl@0: if ((handle->type & MP4_TYPE_AMR_NB) || sl@0: (handle->type & MP4_TYPE_AMR_WB) || sl@0: (handle->type & MP4_TYPE_QCELP_13K) || sl@0: (handle->type & MP4_TYPE_MPEG4_AUDIO)) sl@0: haveAudio = MP4TRUE; sl@0: sl@0: if ((handle->type & MP4_TYPE_H263_PROFILE_0) || sl@0: (handle->type & MP4_TYPE_H263_PROFILE_3) || sl@0: (handle->type & MP4_TYPE_MPEG4_VIDEO) || sl@0: containsAvcVideo( handle->type ) ) sl@0: haveVideo = MP4TRUE; sl@0: sl@0: if ((handle->generate3G2 && !(handle->type & MP4_TYPE_QCELP_13K)) || sl@0: (!handle->generate3G2 && !(handle->type & MP4_TYPE_AMR_WB))) sl@0: ftypdelta = 4; /* one more additional compatible brand */ sl@0: else sl@0: ftypdelta = 0; sl@0: sl@0: if( containsAvcVideo( handle->type ) ) sl@0: { sl@0: ftypdelta += 4; sl@0: } sl@0: sl@0: PRINT((_L("e_writedatatofile_alloc_audiotrk 1"))); sl@0: audioTrackSize = (trakSize *)mp4malloc(sizeof(trakSize)); sl@0: if (audioTrackSize == NULL) sl@0: return -1; sl@0: PRINT((_L("e_writedatatofile_alloc_audiotrk 0"))); sl@0: sl@0: PRINT((_L("e_writedatatofile_alloc_videotrk 1"))); sl@0: videoTrackSize = (trakSize *)mp4malloc(sizeof(trakSize)); sl@0: if (videoTrackSize == NULL) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_alloc_videotrk 0"))); sl@0: sl@0: if (haveAudio) sl@0: { sl@0: PRINT((_L("e_writedatatofile_deter_audiotrk_metadatasize 1"))); sl@0: if (determineAudioTrakMetaDataSize(handle, handle->audioSampleTable, audioTrackSize) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_deter_audiotrk_metadatasize 0"))); sl@0: } sl@0: sl@0: if (haveVideo) sl@0: { sl@0: PRINT((_L("e_writedatatofile_deter_videotrk_metadatasize 1"))); sl@0: if (determineVideoTrakMetaDataSize(handle, handle->videoSampleTable, videoTrackSize) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_deter_videotrk_metadatasize 0"))); sl@0: } sl@0: sl@0: if (handle->flags & MP4_FLAG_METADATALAST) sl@0: { sl@0: metaDataSize += (FTYP_SIZE + ftypdelta); /* ftyp */ sl@0: handle->metaDataSize = metaDataSize; sl@0: } sl@0: else sl@0: { sl@0: metaDataSize += (FTYP_SIZE + ftypdelta); /* ftyp */ sl@0: metaDataSize += 8; /* moov atomheader */ sl@0: metaDataSize += mvhdAtomSize(handle); /* mvhd */ sl@0: if (handle->moovUDTA) sl@0: { sl@0: metaDataSize += 8 + (mp4_u32)handle->moovUDTA->atomcontentsize; sl@0: } sl@0: metaDataSize += audioTrackSize->trak; /* Audio trak */ sl@0: metaDataSize += videoTrackSize->trak; /* Video trak */ sl@0: sl@0: handle->metaDataSize = metaDataSize; sl@0: } sl@0: sl@0: sl@0: if (!(handle->flags & MP4_FLAG_LONGCLIP)) sl@0: { sl@0: /* Update metadata pointers only if metadata is in memory */ sl@0: sl@0: if (haveAudio) sl@0: { sl@0: PRINT((_L("e_writedatatofile_reupdata_audiometadata 1"))); sl@0: if (reUpdateAudioMetaData(handle->audioSampleTable, metaDataSize) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_reupdata_audiometadata 0"))); sl@0: } sl@0: sl@0: if (haveVideo) sl@0: { sl@0: PRINT((_L("e_writedatatofile_reupdata_videometadata 1"))); sl@0: if (reUpdateVideoMetaData(handle->videoSampleTable, metaDataSize) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_reupdata_videometadata 0"))); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: /* Write the rest of metadata to temporary files */ sl@0: PRINT((_L("e_writedatatofile_write_metadatablocks 1"))); sl@0: if (handle->metaDataBlocks) sl@0: if (writeMetaDataTmp(handle) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_write_metadatablocks 0"))); sl@0: } sl@0: sl@0: sl@0: if (handle->flags & MP4_FLAG_METADATALAST) sl@0: { sl@0: mp4_u8 buf[16]; sl@0: mp4_u32 moovSize = 0; sl@0: sl@0: moovSize += 8; /* moov atomheader */ sl@0: moovSize += mvhdAtomSize(handle); /* mvhd */ sl@0: moovSize += audioTrackSize->trak; /* Audio trak */ sl@0: moovSize += videoTrackSize->trak; /* Video trak */ sl@0: if (handle->moovUDTA) sl@0: { sl@0: moovSize += 8 + handle->moovUDTA->atomcontentsize; sl@0: } sl@0: sl@0: PRINT((_L("e_writedatatofile_write_moov 1"))); sl@0: if (writeMOOV(handle, moovSize, haveAudio, haveVideo, audioTrackSize, videoTrackSize) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_write_moov 0"))); sl@0: sl@0: /* Overwrite media data size */ sl@0: PRINT((_L("e_writedatatofile_update_moov_media_size 1"))); sl@0: if(!handle->bufferWrite) sl@0: { sl@0: if (seekFileAbsWrite(handle, (FTYP_SIZE + ftypdelta)) != 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: //make sure the buf is large enough to hold the mdat header sl@0: TInt i; sl@0: i = formatMdatHeader(buf, handle->mediaDataBytes); sl@0: if (writeFileUnbuffered(handle, buf, i) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_update_moov_media_size 0"))); sl@0: } sl@0: else sl@0: { sl@0: PRINT((_L("e_writedatatofile_write_ftyp 1"))); sl@0: if (writeFTYP(handle) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_write_ftyp 0"))); sl@0: sl@0: PRINT((_L("e_writedatatofile_write_new_moov 1"))); sl@0: if (writeMOOV(handle, metaDataSize - (FTYP_SIZE + ftypdelta), haveAudio, haveVideo, audioTrackSize, videoTrackSize) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_write_new_moov 0"))); sl@0: sl@0: PRINT((_L("e_writedatatofile_write_new_mdia 1"))); sl@0: if (writeMediaData(handle) < 0) sl@0: { sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: sl@0: return -1; sl@0: } sl@0: PRINT((_L("e_writedatatofile_write_new_mdia 0"))); sl@0: } sl@0: sl@0: PRINT((_L("e_writedatatofile_free_audioandvideotrks 1"))); sl@0: mp4free(audioTrackSize); sl@0: mp4free(videoTrackSize); sl@0: PRINT((_L("e_writedatatofile_free_audioandvideotrks 0"))); sl@0: PRINT((_L("e_writedatatofile 0"))); sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateDecodingTimeToSample(MP4HandleImp handle, sl@0: * sampleTable *st, sl@0: * mp4_u32 duration) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates stts atom data. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * st sampleTable sl@0: * duration Duration of sample to insert (in media timescale) sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateDecodingTimeToSample(MP4HandleImp handle, sampleTable *st, mp4_u32 duration) sl@0: { sl@0: if (!handle) sl@0: return -1; sl@0: sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (st->sttsCurrentEntryCount == 0) sl@0: { sl@0: st->sttsSampleCount[st->sttsCurrentEntryCount] = 1; sl@0: st->sttsSampleDelta[st->sttsCurrentEntryCount] = duration; sl@0: sl@0: st->sttsCurrentEntryCount++; sl@0: st->sttsEntryCount++; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: if (st->sttsCurrentEntryCount == st->sttsMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->sttsSampleCount, sl@0: 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, sl@0: sizeof(mp4_u32) * st->sttsMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->sttsSampleCount = (mp4_u32 *)p; sl@0: sl@0: p = mp4realloc(st->sttsSampleDelta, sl@0: 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, sl@0: sizeof(mp4_u32) * st->sttsMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->sttsSampleDelta = (mp4_u32 *)p; sl@0: sl@0: st->sttsMaxEntryCount *= 2; sl@0: } sl@0: sl@0: if (st->sttsSampleDelta[st->sttsCurrentEntryCount - 1] == duration) sl@0: { sl@0: st->sttsSampleCount[st->sttsCurrentEntryCount - 1]++; sl@0: } sl@0: else sl@0: { sl@0: st->sttsSampleCount[st->sttsCurrentEntryCount] = 1; sl@0: st->sttsSampleDelta[st->sttsCurrentEntryCount] = duration; sl@0: sl@0: st->sttsCurrentEntryCount++; sl@0: st->sttsEntryCount++; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (st->sttsEntryCount == 0) sl@0: { sl@0: st->sttsSampleCount[st->sttsEntryCount]++; sl@0: st->sttsSampleDelta[st->sttsEntryCount] = duration; sl@0: sl@0: st->sttsEntryCount++; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: if (st->sttsEntryCount == st->sttsMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->sttsSampleCount, sl@0: 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, sl@0: sizeof(mp4_u32) * st->sttsMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->sttsSampleCount = (mp4_u32 *)p; sl@0: sl@0: p = mp4realloc(st->sttsSampleDelta, sl@0: 2 * sizeof(mp4_u32) * st->sttsMaxEntryCount, sl@0: sizeof(mp4_u32) * st->sttsMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->sttsSampleDelta = (mp4_u32 *)p; sl@0: sl@0: st->sttsMaxEntryCount *= 2; sl@0: } sl@0: sl@0: if (st->sttsSampleDelta[st->sttsEntryCount - 1] == duration) sl@0: { sl@0: st->sttsSampleCount[st->sttsEntryCount - 1]++; sl@0: } sl@0: else sl@0: { sl@0: st->sttsSampleCount[st->sttsEntryCount] = 1; sl@0: st->sttsSampleDelta[st->sttsEntryCount] = duration; sl@0: sl@0: st->sttsEntryCount++; sl@0: } sl@0: } sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateSampleSize(MP4HandleImp handle, sl@0: * sampleTable *st, sl@0: * mp4_u32 size) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates stsz atom data. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * st sampleTable sl@0: * size Size of sample in bytes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateSampleSize(MP4HandleImp handle, sampleTable *st, mp4_u32 size) sl@0: { sl@0: if (!handle) sl@0: return -1; sl@0: sl@0: if (size == 0) sl@0: return -1; sl@0: sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (st->stszCurrentSampleCount == st->stszMaxSampleCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->stszEntrySize, sl@0: 2 * sizeof(mp4_u32) * st->stszMaxSampleCount, sl@0: sizeof(mp4_u32) * st->stszMaxSampleCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->stszEntrySize = (mp4_u32 *)p; sl@0: sl@0: st->stszMaxSampleCount *= 2; sl@0: } sl@0: sl@0: st->stszEntrySize[st->stszCurrentSampleCount] = size; sl@0: sl@0: st->stszCurrentSampleCount++; sl@0: st->stszSampleCount++; sl@0: } sl@0: else sl@0: { sl@0: if (st->stszSampleCount == st->stszMaxSampleCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->stszEntrySize, sl@0: 2 * sizeof(mp4_u32) * st->stszMaxSampleCount, sl@0: sizeof(mp4_u32) * st->stszMaxSampleCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->stszEntrySize = (mp4_u32 *)p; sl@0: sl@0: st->stszMaxSampleCount *= 2; sl@0: } sl@0: sl@0: st->stszEntrySize[st->stszSampleCount] = size; sl@0: sl@0: st->stszSampleCount++; sl@0: } sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateSampleToChunk(sampleTable *st) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates stsc atom data. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * st sampleTable sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateSampleToChunk(sampleTable *st) sl@0: { sl@0: if (st->stscEntryCount != 0) sl@0: return 0; sl@0: sl@0: sl@0: st->stscFirstChunk[st->stscEntryCount] = st->currentChunk; sl@0: st->stscSamplesPerChunk[st->stscEntryCount] = 1; sl@0: st->stscSampleDescriptionIndex[st->stscEntryCount] = 1; /* Note: Need to update here for multiple sample entry support */ sl@0: st->stscEntryCount++; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateChunkOffset(MP4HandleImp handle, sl@0: * sampleTable *st) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates stco atom data. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * st sampleTable sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateChunkOffset(MP4HandleImp handle, sampleTable *st) sl@0: { sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (st->stcoCurrentEntryCount == st->stcoMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->stcoChunkOffset, sl@0: 2 * sizeof(mp4_u64) * st->stcoMaxEntryCount, sl@0: sizeof(mp4_u64) * st->stcoMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->stcoChunkOffset = (mp4_u64*)p; sl@0: sl@0: st->stcoMaxEntryCount *= 2; sl@0: } sl@0: sl@0: if (handle->flags & MP4_FLAG_METADATALAST) sl@0: updateChunkOffset(st, st->stcoCurrentEntryCount, handle->mediaDataBytes); sl@0: else sl@0: updateChunkOffset(st, st->stcoCurrentEntryCount, handle->bytesInTmpFile); sl@0: sl@0: st->stcoCurrentEntryCount++; sl@0: st->stcoEntryCount++; sl@0: } sl@0: else sl@0: { sl@0: if (st->stcoEntryCount == st->stcoMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->stcoChunkOffset, sl@0: 2 * sizeof(mp4_u64) * st->stcoMaxEntryCount, sl@0: sizeof(mp4_u64) * st->stcoMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->stcoChunkOffset = (mp4_u64 *)p; sl@0: sl@0: st->stcoMaxEntryCount *= 2; sl@0: } sl@0: sl@0: if (handle->flags & MP4_FLAG_METADATALAST) sl@0: updateChunkOffset(st, st->stcoEntryCount, handle->mediaDataBytes); sl@0: else sl@0: updateChunkOffset(st, st->stcoEntryCount, handle->bytesInTmpFile); sl@0: sl@0: st->stcoEntryCount++; sl@0: } sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateSyncSample(MP4HandleImp handle, sl@0: * sampleTable *st) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates stss atom data. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * st sampleTable sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateSyncSample(MP4HandleImp handle, sampleTable *st) sl@0: { sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (st->stssCurrentEntryCount == st->stssMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->stssSampleNumber, sl@0: 2 * sizeof(mp4_u32) * st->stssMaxEntryCount, sl@0: sizeof(mp4_u32) * st->stssMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->stssSampleNumber = (mp4_u32 *)p; sl@0: sl@0: st->stssMaxEntryCount *= 2; sl@0: } sl@0: sl@0: st->stssSampleNumber[st->stssCurrentEntryCount] = handle->videoSampleNum; sl@0: st->stssCurrentEntryCount++; sl@0: st->stssEntryCount++; sl@0: } sl@0: else sl@0: { sl@0: if (st->stssEntryCount == st->stssMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(st->stssSampleNumber, sl@0: 2 * sizeof(mp4_u32) * st->stssMaxEntryCount, sl@0: sizeof(mp4_u32) * st->stssMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: st->stssSampleNumber = (mp4_u32 *)p; sl@0: sl@0: st->stssMaxEntryCount *= 2; sl@0: } sl@0: sl@0: st->stssSampleNumber[st->stssEntryCount] = handle->videoSampleNum; sl@0: st->stssEntryCount++; sl@0: } sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineAudioTrakMetaDataSize(MP4HandleImp handle, sl@0: * sampleTable *st, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function calculates the audio track meta data size. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * st Sample table data sl@0: * ts Atom sizes are returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 determineAudioTrakMetaDataSize(MP4HandleImp handle, sampleTable *st, trakSize *ts) sl@0: { sl@0: if (handle->type & MP4_TYPE_AMR_NB) /* AMR-NB */ sl@0: { sl@0: ts->damr = 17; sl@0: ts->samr = 36 + ts->damr; sl@0: ts->stsd = 16 + ts->samr; sl@0: } sl@0: else if (handle->type & MP4_TYPE_AMR_WB) /* AMR-WB */ sl@0: { sl@0: ts->damr = 17; sl@0: ts->sawb = 36 + ts->damr; sl@0: ts->stsd = 16 + ts->sawb; sl@0: } sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) /* QCELP 13K stored in QCELPSampleEntry */ sl@0: { sl@0: ts->dqcp = 14; sl@0: ts->sqcp = 36 + ts->dqcp; sl@0: ts->stsd = 16 + ts->sqcp; sl@0: } sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) /* QCELP 13K stored in MP4AudioDescription */ sl@0: { sl@0: calculateES_DescriptorSize(handle, MP4_TYPE_QCELP_13K); sl@0: ts->esds = 12 + handle->ES_DescriptorSize; /*37 + handle->audioDecSpecificInfoSize;*/ sl@0: ts->mp4a = 36 + ts->esds; sl@0: ts->stsd = 16 + ts->mp4a; sl@0: } sl@0: else /* MPEG audio */ sl@0: { sl@0: calculateES_DescriptorSize(handle, MP4_TYPE_MPEG4_AUDIO); sl@0: ts->esds = 12 + handle->ES_DescriptorSize; /*37 + handle->audioDecSpecificInfoSize;*/ sl@0: ts->mp4a = 36 + ts->esds; sl@0: ts->stsd = 16 + ts->mp4a; sl@0: } sl@0: ts->stts = 16 + st->sttsEntryCount * 8; sl@0: ts->stsc = 16 + st->stscEntryCount * 12; sl@0: if (st->stszSampleSize != 0) sl@0: ts->stsz = 20; sl@0: else sl@0: ts->stsz = 20 + st->stszSampleCount * 4; sl@0: ts->stco = 16 + st->stcoEntryCount * (st->stcoNeed64Bits ? 8 : 4); sl@0: ts->stbl = 8 + ts->stsd + ts->stts + ts->stsc + ts->stsz + ts->stco; sl@0: ts->dref = 28; sl@0: ts->dinf = 8 + ts->dref; sl@0: ts->smhd = 16; sl@0: ts->minf = 8 + ts->smhd + ts->dinf + ts->stbl; sl@0: ts->hdlr = 33; sl@0: sl@0: if (handle->audioDuration > MP4_INT_MAX) sl@0: { sl@0: ts->mdhd = 44; sl@0: ts->tkhd = 104; sl@0: } sl@0: else sl@0: { sl@0: ts->mdhd = 32; sl@0: ts->tkhd = 92; sl@0: } sl@0: sl@0: ts->mdia = 8 + ts->mdhd + ts->hdlr + ts->minf; sl@0: if ( handle->audioUDTA ) sl@0: { sl@0: ts->udta = 8 + handle->audioUDTA->atomcontentsize; sl@0: } sl@0: ts->trak = 8 + ts->tkhd + ts->mdia + ts->udta; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 determineVideoTrakMetaDataSize(MP4HandleImp handle, sl@0: * sampleTable *st, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function calculates the video track meta data size. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * st Sample table data sl@0: * ts Atom sizes are returned here sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 determineVideoTrakMetaDataSize(MP4HandleImp handle, sampleTable *st, trakSize *ts) sl@0: { sl@0: /* Note: This functions assumes single sample entry per media track. sl@0: If necessary, modify to support multiple sample entries in the future. */ sl@0: if ((handle->type & MP4_TYPE_H263_PROFILE_0) || (handle->type & MP4_TYPE_H263_PROFILE_3)) sl@0: { sl@0: ts->d263 = 15; sl@0: ts->s263 = 86 + ts->d263; sl@0: ts->stsd = 16 + ts->s263; sl@0: } sl@0: else /* MPEG-4 */ sl@0: if ((handle->type & MP4_TYPE_MPEG4_VIDEO)) sl@0: { sl@0: ts->esds = 37 + handle->videoDecSpecificInfoSize; sl@0: ts->mp4v = 86 + ts->esds; sl@0: ts->stsd = 16 + ts->mp4v; sl@0: } sl@0: else /* AVC */ sl@0: if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: /* Note: If necessary, add btrt and m4ds boxes here in the future. */ sl@0: ts->avcc = 8 + handle->videoDecSpecificInfoSize; /*handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize;*/ sl@0: ts->avc1 = 86 + ts->avcc; sl@0: ts->stsd = 16 + ts->avc1; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: ts->stts = 16 + st->sttsEntryCount * 8; sl@0: ts->stsc = 16 + st->stscEntryCount * 12; sl@0: if (st->stszSampleSize != 0) sl@0: ts->stsz = 20; sl@0: else sl@0: ts->stsz = 20 + st->stszSampleCount * 4; sl@0: ts->stco = 16 + st->stcoEntryCount * (st->stcoNeed64Bits ? 8 : 4); sl@0: ts->stss = 16 + st->stssEntryCount * 4; sl@0: if( handle->videoSampleTable->sdtpEntryCount ) sl@0: ts->sdtp = 4 + 4 + 1 + 3 + handle->videoSampleTable->sdtpEntryCount; //size + 'SDTP' + ver + flags + dependencies sl@0: else sl@0: ts->sdtp = 0; sl@0: sl@0: ts->stbl = 8 + ts->stsd + ts->stts + ts->stsc + ts->stsz + ts->stco + ts->stss + ts->sdtp; sl@0: ts->dref = 28; sl@0: ts->dinf = 8 + ts->dref; sl@0: ts->vmhd = 20; sl@0: ts->minf = 8 + ts->vmhd + ts->dinf + ts->stbl; sl@0: ts->hdlr = 33; sl@0: sl@0: if (handle->videoDuration > MP4_INT_MAX) sl@0: { sl@0: ts->mdhd = 44; sl@0: ts->tkhd = 104; sl@0: } sl@0: else sl@0: { sl@0: ts->mdhd = 32; sl@0: ts->tkhd = 92; sl@0: } sl@0: sl@0: ts->mdia = 8 + ts->mdhd + ts->hdlr + ts->minf; sl@0: if ( handle->videoUDTA ) sl@0: { sl@0: ts->udta = 8 + handle->videoUDTA->atomcontentsize; sl@0: } sl@0: ts->trak = 8 + ts->tkhd + ts->mdia + ts->udta; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 reUpdateAudioMetaData(sampleTable *st, sl@0: * mp4_u32 metaDataSize) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates the chunk offsets in the meta data to point to sl@0: * correct places. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * st Sample table data sl@0: * metaDataSize Meta data size sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 reUpdateAudioMetaData(sampleTable *st, mp4_u32 metaDataSize) sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: sl@0: for (i = 0; i < st->stcoEntryCount; i++) sl@0: updateChunkOffset(st, i, st->stcoChunkOffset[i] + metaDataSize + MDAT_HEADER_SIZE); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 reUpdateVideoMetaData(sampleTable *st, sl@0: * mp4_u32 metaDataSize) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function updates the chunk offsets in the meta data to point to sl@0: * correct places. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * st Sample table data sl@0: * metaDataSize Meta data size sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 reUpdateVideoMetaData(sampleTable *st, mp4_u32 metaDataSize) sl@0: { sl@0: mp4_u32 i; sl@0: sl@0: sl@0: for (i = 0; i < st->stcoEntryCount; i++) sl@0: updateChunkOffset(st, i, st->stcoChunkOffset[i] + metaDataSize + MDAT_HEADER_SIZE); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeFTYP(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write FTYP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeFTYP(MP4HandleImp handle) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u8 ftypdelta = 0; sl@0: sl@0: if ((handle->generate3G2 && !(handle->type & MP4_TYPE_QCELP_13K)) || sl@0: (!handle->generate3G2 && !(handle->type & MP4_TYPE_AMR_WB))) sl@0: ftypdelta = 4; /* one more additional compatible brand */ sl@0: else sl@0: ftypdelta = 0; sl@0: sl@0: if( containsAvcVideo( handle->type ) ) sl@0: { sl@0: ftypdelta += 4; sl@0: } sl@0: if(handle->bufferWrite) sl@0: handle->ftypdelta=ftypdelta; sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(FTYP_SIZE + ftypdelta); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)(FTYP_SIZE + ftypdelta)); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_FTYP); sl@0: i += 4; sl@0: sl@0: if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: if(handle->generateMP4) sl@0: { sl@0: /* MPEG-4 Major brand */ sl@0: buf[i++] = 'm'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: buf[i++] = '2'; sl@0: } sl@0: sl@0: else sl@0: { sl@0: /* AVC is included for 3GPP Release 6 and beyond */ sl@0: /* Major brand */ sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '6'; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if(handle->generateMP4) sl@0: { sl@0: /* MPEG-4 Major brand */ sl@0: buf[i++] = 'm'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: buf[i++] = '2'; sl@0: } sl@0: else if(handle->generate3G2) sl@0: { sl@0: /* 3GPP2 Major brand */ sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = '2'; sl@0: buf[i++] = 'a'; sl@0: } sl@0: else sl@0: { sl@0: /* 3GPP Major brand */ sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: } sl@0: } sl@0: sl@0: /* Minor version */ sl@0: if(handle->generateMP4) sl@0: { /* MPEG-4 Minor Version */ sl@0: insertu32(buf+i, (mp4_u32)(0)); /* 0 */ sl@0: i += 4; sl@0: } sl@0: else if(handle->generate3G2) sl@0: { /* 3GPP2 Minor Version */ sl@0: if( containsAvcVideo( handle->type ) ) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)(2*256*256)); /* VB.0.0 */ sl@0: i += 4; sl@0: } sl@0: else sl@0: { sl@0: insertu32(buf+i, (mp4_u32)(1*256*256)); /* VA.0.0 */ sl@0: i += 4; sl@0: } sl@0: } sl@0: else sl@0: { /* 3GPP Minor Version */ sl@0: if( containsAvcVideo( handle->type ) ) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)2*256); /* V6.3.0 */ sl@0: i += 4; sl@0: } sl@0: else sl@0: { sl@0: insertu32(buf+i, (mp4_u32)4*256); /* V4.4.0 */ sl@0: i += 4; sl@0: } sl@0: } sl@0: sl@0: /* Compatible brands */ sl@0: if(handle->generateMP4) sl@0: {/* MPEG-4 Compatible Brands */ sl@0: buf[i++] = 'm'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: buf[i++] = '2'; sl@0: sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: sl@0: buf[i++] = 'i'; sl@0: buf[i++] = 's'; sl@0: buf[i++] = 'o'; sl@0: buf[i++] = 'm'; sl@0: if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: /* AVC is included for 3GPP Release 6 and beyond */ sl@0: buf[i++] = 'a'; sl@0: buf[i++] = 'v'; sl@0: buf[i++] = 'c'; sl@0: buf[i++] = '1'; sl@0: } sl@0: } sl@0: else if(handle->generate3G2) sl@0: {/* 3GPP2 Compatible Brands */ sl@0: if( containsAvcVideo( handle->type ) ) sl@0: { sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = '2'; sl@0: buf[i++] = 'b'; sl@0: if (!(handle->type & MP4_TYPE_QCELP_13K)) sl@0: { // If 3GPP codecs are used, then put 3GP6 in compatible brands sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '6'; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = '2'; sl@0: buf[i++] = 'a'; sl@0: if (!(handle->type & MP4_TYPE_QCELP_13K)) sl@0: { // If 3GPP codecs are used, then put 3GP4 in compatible brands sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: } sl@0: } sl@0: if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: /* AVC is included for 3GPP Release 6 and beyond */ sl@0: buf[i++] = 'a'; sl@0: buf[i++] = 'v'; sl@0: buf[i++] = 'c'; sl@0: buf[i++] = '1'; sl@0: } sl@0: sl@0: buf[i++] = 'i'; sl@0: buf[i++] = 's'; sl@0: buf[i++] = 'o'; sl@0: buf[i++] = 'm'; sl@0: } sl@0: else sl@0: {/* 3GPP Compatible Brands */ sl@0: if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '6'; sl@0: } sl@0: else sl@0: { sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = 'p'; sl@0: buf[i++] = '4'; sl@0: } sl@0: sl@0: if (!(handle->type & MP4_TYPE_AMR_WB)) sl@0: { // If 3GPP2 codecs are used, then put 3G2A in compatible brands sl@0: buf[i++] = '3'; sl@0: buf[i++] = 'g'; sl@0: buf[i++] = '2'; sl@0: buf[i++] = 'a'; sl@0: } sl@0: sl@0: buf[i++] = 'i'; sl@0: buf[i++] = 's'; sl@0: buf[i++] = 'o'; sl@0: buf[i++] = 'm'; sl@0: sl@0: if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: /* AVC is included for 3GPP Release 6 and beyond */ sl@0: buf[i++] = 'a'; sl@0: buf[i++] = 'v'; sl@0: buf[i++] = 'c'; sl@0: buf[i++] = '1'; sl@0: } sl@0: sl@0: } sl@0: if (writeFile(handle, buf, (FTYP_SIZE + ftypdelta)) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeMOOV(MP4HandleImp handle, sl@0: * mp4_u32 moovSize, sl@0: * mp4_bool haveAudio, sl@0: * mp4_bool haveVideo, sl@0: * trakSize *audioTrackSize, sl@0: * trakSize *videoTrackSize) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write MOOV atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * moovSize Size of MOOV atom in bytes sl@0: * haveAudio Flag to indicate whether audio exists or not sl@0: * haveVideo Flag to indicate whether video exists or not sl@0: * audioTrackSize Size of audio track in bytes sl@0: * videoTrackSize Size of video track in bytes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeMOOV(MP4HandleImp handle, mp4_u32 moovSize, mp4_bool haveAudio, mp4_bool haveVideo, trakSize *audioTrackSize, trakSize *videoTrackSize) sl@0: { sl@0: PRINT((_L("e_writemoov 1"))); sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, moovSize); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MOOV); sl@0: i += 4; sl@0: sl@0: PRINT((_L("e_writemoov_header 1"))); sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: PRINT((_L("e_writemoov_header 0"))); sl@0: sl@0: PRINT((_L("e_writemoov_mvhd 1"))); sl@0: if (writeMVHD(handle) < 0) sl@0: return -1; sl@0: PRINT((_L("e_writemoov_mvhd 0"))); sl@0: sl@0: PRINT((_L("e_writemoov_video 1"))); sl@0: if (haveVideo) sl@0: if (writeVideoTrak(handle, videoTrackSize) < 0) sl@0: return -1; sl@0: PRINT((_L("e_writemoov_video 0"))); sl@0: sl@0: PRINT((_L("e_writemoov_audio 1"))); sl@0: if (haveAudio) sl@0: if (writeAudioTrak(handle, audioTrackSize) < 0) sl@0: return -1; sl@0: PRINT((_L("e_writemoov_audio 0"))); sl@0: sl@0: PRINT((_L("e_writemoov_udta 1"))); sl@0: if (handle->moovUDTA) sl@0: { sl@0: if (writeUDTA(handle, handle->moovUDTA) < 0) sl@0: { sl@0: return -1; sl@0: } sl@0: } sl@0: PRINT((_L("e_writemoov_udta 0"))); sl@0: PRINT((_L("e_writemoov 0"))); sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeMVHD(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write MVHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeMVHD(MP4HandleImp handle) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 u32; sl@0: sl@0: size_t mvhdSize = mvhdAtomSize(handle); sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(mvhdSize); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)mvhdSize); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MVHD); sl@0: i += 4; sl@0: sl@0: sl@0: if (handle->videoDuration > MP4_INT_MAX || handle->audioDuration > MP4_INT_MAX) sl@0: { sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0x01000000); //its going to be a version 1 atom sl@0: i += 4; sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Timescale */ sl@0: insertu32(buf+i, (mp4_u32)MVHD_TIMESCALE); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: { sl@0: mp4_u64 u64; sl@0: mp4_u64 videoDuration = 0; sl@0: mp4_u64 audioDuration = 0; sl@0: sl@0: sl@0: if (handle->videoTimeScale) sl@0: videoDuration = (mp4_u64)((mp4_double)MVHD_TIMESCALE * sl@0: (mp4_double)handle->videoDuration / sl@0: (mp4_double)handle->videoTimeScale + sl@0: (mp4_double)0.5); sl@0: if (handle->audioTimeScale) sl@0: audioDuration = (mp4_u64)((mp4_double)MVHD_TIMESCALE * sl@0: (mp4_double)handle->audioDuration / sl@0: (mp4_double)handle->audioTimeScale + sl@0: (mp4_double)0.5); sl@0: sl@0: if (audioDuration > videoDuration) sl@0: u64 = audioDuration; sl@0: else sl@0: u64 = videoDuration; sl@0: sl@0: insertu64(buf+i, u64); sl@0: i += 8; sl@0: } sl@0: sl@0: } sl@0: else sl@0: { sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu32(buf+i, (mp4_u32)MVHD_TIMESCALE); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: { sl@0: mp4_u32 videoDuration = 0; sl@0: mp4_u32 audioDuration = 0; sl@0: sl@0: sl@0: if (handle->videoTimeScale) sl@0: videoDuration = (mp4_u32)((mp4_double)MVHD_TIMESCALE * sl@0: (mp4_double)handle->videoDuration / sl@0: (mp4_double)handle->videoTimeScale + sl@0: (mp4_double)0.5); sl@0: if (handle->audioTimeScale) sl@0: audioDuration = (mp4_u32)((mp4_double)MVHD_TIMESCALE * sl@0: (mp4_double)handle->audioDuration / sl@0: (mp4_double)handle->audioTimeScale + sl@0: (mp4_double)0.5); sl@0: sl@0: if (audioDuration > videoDuration) sl@0: u32 = audioDuration; sl@0: else sl@0: u32 = videoDuration; sl@0: sl@0: insertu32(buf+i, u32); sl@0: i += 4; sl@0: } sl@0: } sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0x0100); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0x0000); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x40000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, mvhdSize) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoTrak(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video track atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoTrak(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->trak); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_TRAK); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoTKHD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoMDIA(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->videoUDTA) sl@0: { sl@0: if (writeUDTA(handle, handle->videoUDTA) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoTKHD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write TKHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoTKHD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 u32; sl@0: mp4_double ud; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->tkhd); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->tkhd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_TKHD); sl@0: i += 4; sl@0: sl@0: sl@0: if (handle->videoDuration > MP4_INT_MAX) sl@0: { sl@0: mp4_u64 u64; sl@0: /* Version and flags */ sl@0: buf[i++] = 1; //make this a version 1 atom sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 7; /* Track enabled, used in movie and preview */ sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Track ID */ sl@0: insertu32(buf+i, (mp4_u32)1); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: if ( (handle->videoDuration == 0) || (handle->videoTimeScale == 0) ) sl@0: { sl@0: ud = 0; sl@0: } sl@0: else sl@0: { sl@0: ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->videoDuration / (mp4_double)handle->videoTimeScale + (mp4_double)0.5; sl@0: } sl@0: sl@0: u64 = (mp4_u64)ud; sl@0: insertu64(buf+i, u64); sl@0: i += 8; sl@0: } sl@0: else sl@0: { sl@0: /* Version and flags */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 7; /* Track enabled, used in movie and preview */ sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Track ID */ sl@0: insertu32(buf+i, (mp4_u32)1); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: if ( (handle->videoDuration == 0) || (handle->videoTimeScale == 0) ) sl@0: { sl@0: ud = 0; sl@0: } sl@0: else sl@0: { sl@0: ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->videoDuration / (mp4_double)handle->videoTimeScale + (mp4_double)0.5; sl@0: } sl@0: sl@0: u32 = (mp4_u32)ud; sl@0: insertu32(buf+i, u32); sl@0: i += 4; sl@0: } sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0); /* Visual track */ sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x40000000); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)handle->videoWidth); /* Width */ sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)handle->videoHeight); /* Height */ sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, ts->tkhd) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoMDIA(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video MDIA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoMDIA(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->mdia); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MDIA); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoMDHD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoHDLR(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoMINF(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoMDHD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video MDHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoMDHD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 u32; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->mdhd); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->mdhd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MDHD); sl@0: i += 4; sl@0: sl@0: if (handle->videoDuration > MP4_INT_MAX) sl@0: { sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0x01000000); //version 1 atom sl@0: i += 4; sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Timescale */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoTimeScale); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: insertu64(buf+i, handle->videoDuration); sl@0: i += 8; sl@0: } sl@0: else sl@0: { sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoTimeScale); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoDuration); sl@0: i += 4; sl@0: } sl@0: sl@0: /* Language */ sl@0: insertu16(buf+i, (mp4_u16)0x55c4); /* 'und' */ sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu16(buf+i, (mp4_u16)0x0000); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, ts->mdhd) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoHDLR(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video HDLR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoHDLR(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->hdlr); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->hdlr); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_HDLR); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Handler type */ sl@0: buf[i++] = 'v'; sl@0: buf[i++] = 'i'; sl@0: buf[i++] = 'd'; sl@0: buf[i++] = 'e'; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Empty string */ sl@0: buf[i++] = 0; sl@0: sl@0: if (writeFile(handle, buf, ts->hdlr) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoMINF(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video MINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoMINF(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->minf); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MINF); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeVMHD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeDINF(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoSTBL(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVMHD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write VMHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVMHD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->vmhd); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->vmhd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_VMHD); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0x00000001); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, ts->vmhd) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeDINF(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write DINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeDINF(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->dinf); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_DINF); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeDREF(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeDREF(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write DREF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeDREF(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->dref); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->dref); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_DREF); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)1); sl@0: i += 4; sl@0: sl@0: /* URL atom */ sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)12); sl@0: i += 4; sl@0: sl@0: /* Type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_URL); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0x00000001); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, ts->dref) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTBL(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STBL atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTBL(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stbl); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STBL); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeVideoSTSD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (writeVideoSTTSLongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeVideoSTTS(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: if (writeVideoSTSC(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (writeVideoSTSZLongClip(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->videoSampleTable->stcoNeed64Bits) sl@0: { sl@0: if (writeVideoCO64LongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeVideoSTCOLongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: if (writeVideoSTSSLongClip(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if(ts->sdtp && writeVideoSDTPLongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeVideoSTSZ(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->videoSampleTable->stcoNeed64Bits) sl@0: { sl@0: if (writeVideoCO64(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeVideoSTCO(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: if (writeVideoSTSS(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if(ts->sdtp && writeVideoSDTP(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTSD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STSD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTSD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[16]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSD); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)1); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 16) < 0) sl@0: return -1; sl@0: sl@0: if (handle->type & MP4_TYPE_MPEG4_VIDEO) sl@0: { sl@0: if (writeMP4V(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else if ((handle->type & MP4_TYPE_H263_PROFILE_0) || sl@0: (handle->type & MP4_TYPE_H263_PROFILE_3)) sl@0: { sl@0: if (writeS263(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else if ( containsAvcVideo( handle->type ) ) sl@0: { sl@0: if (writeAVC1(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeMP4V(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write MP4V atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeMP4V(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(86); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->mp4v); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MP4V); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Width */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoWidth); sl@0: i += 2; sl@0: sl@0: /* Height */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoHeight); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)24); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0xffff); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 86) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeVideoESD(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoESD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video ESD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoESD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->esds); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->esds); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_ESD); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* ES_DescrTag */ sl@0: buf[i++] = 0x03; sl@0: sl@0: /* Size */ sl@0: buf[i++] = (mp4_u8)(23 + handle->videoDecSpecificInfoSize); sl@0: sl@0: /* ES_ID */ sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: /* Flags */ sl@0: buf[i++] = 0; sl@0: sl@0: /* DecoderConfigDescrTag */ sl@0: buf[i++] = 0x04; sl@0: sl@0: /* Size */ sl@0: buf[i++] = (mp4_u8)(15 + handle->videoDecSpecificInfoSize); sl@0: sl@0: /* ObjectTypeIndication */ sl@0: buf[i++] = 0x20; sl@0: sl@0: /* Flags */ sl@0: buf[i++] = 0x11; sl@0: sl@0: /* BufferSizeDB */ sl@0: buf[i++] = 0x00; sl@0: buf[i++] = 0x50; sl@0: buf[i++] = 0x00; sl@0: sl@0: /* MaxBitrate */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoMaxBitrate); sl@0: i += 4; sl@0: sl@0: /* AvgBitrate */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoAvgBitrate); sl@0: i += 4; sl@0: sl@0: /* DecSpecificInfoTag */ sl@0: buf[i++] = 0x05; sl@0: sl@0: /* Size */ sl@0: buf[i++] = (mp4_u8)handle->videoDecSpecificInfoSize; sl@0: sl@0: /* DecoderSpecificInfo */ sl@0: mp4memcpy(buf+i, handle->videoDecSpecificInfo, handle->videoDecSpecificInfoSize); sl@0: i += handle->videoDecSpecificInfoSize; sl@0: sl@0: /* SLConfigDescrTag */ sl@0: buf[i++] = 0x06; sl@0: sl@0: /* Size */ sl@0: buf[i++] = 1; sl@0: sl@0: /* */ sl@0: buf[i++] = 2; sl@0: sl@0: if (writeFile(handle, buf, ts->esds) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeS263(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write S263 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeS263(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(86); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->s263); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_S263); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Width */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoWidth); sl@0: i += 2; sl@0: sl@0: /* Height */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoHeight); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)24); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0xffff); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 86) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeD263(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeD263(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write D263 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeD263(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[15]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->d263); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_D263); sl@0: i += 4; sl@0: sl@0: /* Vendor */ sl@0: buf[i++] = 'S'; sl@0: buf[i++] = '6'; sl@0: buf[i++] = '0'; sl@0: buf[i++] = ' '; sl@0: sl@0: /* Decoder version */ sl@0: buf[i++] = 0; sl@0: sl@0: /* H263_Level */ sl@0: buf[i++] = handle->videoLevel; sl@0: sl@0: /* H263_Profile */ sl@0: if (handle->type & MP4_TYPE_H263_PROFILE_0) sl@0: buf[i++] = 0; sl@0: else if (handle->type & MP4_TYPE_H263_PROFILE_3) sl@0: buf[i++] = 3; sl@0: else sl@0: return -1; sl@0: sl@0: if (writeFile(handle, buf, 15) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAVC1(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write AVC1 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAVC1(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(86); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->avc1); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_AVC1); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Width */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoWidth); sl@0: i += 2; sl@0: sl@0: /* Height */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoHeight); sl@0: i += 2; sl@0: sl@0: /* H-res (default is 72dpi = 0x00480000) */ sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: /* V-res (default is 72dpi = 0x00480000) */ sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Frame count (default is 1) */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Compressor name (32 byte string) */ sl@0: // The spec *recommends* inserting "\012AVC Coding" here sl@0: // but we just have a string of nulls. sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Depth (default is 0x0018 which indicates colour images with no alpha) */ sl@0: insertu16(buf+i, (mp4_u16)24); sl@0: i += 2; sl@0: sl@0: /* Pre-defined (-1) */ sl@0: insertu16(buf+i, (mp4_u16)0xffff); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 86) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeAVCC(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Note: If necessary, include writing of btrt and m4ds atoms. */ sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAVCC(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write AVCC atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAVCC(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->avcc); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->avcc); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_AVCC); sl@0: i += 4; sl@0: sl@0: /*mp4memcpy(buf+i, handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfig, sl@0: handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize);*/ sl@0: sl@0: mp4memcpy(buf+i, handle->videoDecSpecificInfo, handle->videoDecSpecificInfoSize); sl@0: sl@0: /*i += handle->moov->trakVideo->mdia->minf->stbl->stsd->avc1[0]->avcc->avcConfigSize;*/ sl@0: sl@0: i += handle->videoDecSpecificInfoSize; sl@0: sl@0: if (writeFile(handle, buf, ts->avcc) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTTS(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTTS(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stts); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stts); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsEntryCount); sl@0: i += 4; sl@0: sl@0: /* Sample count and sample delta */ sl@0: for (j = 0; j < handle->videoSampleTable->sttsEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsSampleCount[j]); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsSampleDelta[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTTSLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTTSLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stts); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->sttsEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Sample count and delta */ sl@0: sl@0: /* Seek to the beginning of temporary files */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->videoSampleTable->sttsEntryCount * 4; /* Bytes left in each file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > METADATA_COPY_BUFFERSIZE / 2) sl@0: bytestoread = METADATA_COPY_BUFFERSIZE / 2; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + 2*j, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + 2*j + 4, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, 2 * bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTSC(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STSC atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTSC(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stsc); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsc); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSC); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscEntryCount); sl@0: i += 4; sl@0: sl@0: /* First chunk, samples per chunk and sample description index */ sl@0: for (j = 0; j < handle->videoSampleTable->stscEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscFirstChunk[j]); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscSamplesPerChunk[j]); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stscSampleDescriptionIndex[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stsc) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTSZ(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STSZ atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTSZ(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stsz); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsz); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Sample size */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleSize); sl@0: i += 4; sl@0: sl@0: /* Sample count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleCount); sl@0: i += 4; sl@0: sl@0: /* Entry sizes */ sl@0: if (handle->videoSampleTable->stszSampleSize == 0) sl@0: { sl@0: for (j = 0; j < handle->videoSampleTable->stszSampleCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszEntrySize[j]); sl@0: i += 4; sl@0: } sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stsz) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTSZLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STSZ atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTSZLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsz); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Sample size */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleSize); sl@0: i += 4; sl@0: sl@0: /* Sample count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stszSampleCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Entry sizes */ sl@0: sl@0: if (handle->videoSampleTable->stszSampleSize == 0) sl@0: { sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->videoSampleTable->stszSampleCount * 4; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > METADATA_COPY_BUFFERSIZE) sl@0: bytestoread = METADATA_COPY_BUFFERSIZE; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTCO(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STCO atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTCO(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stco); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: /* Chunk offsets */ sl@0: for (j = 0; j < handle->videoSampleTable->stcoEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoChunkOffset[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stco) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoCO64(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video CO64 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoCO64(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stco); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: /* Chunk offsets */ sl@0: for (j = 0; j < handle->videoSampleTable->stcoEntryCount; j++) sl@0: { sl@0: insertu64(buf+i, (mp4_u64)handle->videoSampleTable->stcoChunkOffset[j]); sl@0: i += 8; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stco) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTCOLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STCO atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTCOLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 sl@0: //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Chunk offsets */ sl@0: sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->videoSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > bufferSize) sl@0: bytestoread = bufferSize; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 8) sl@0: { sl@0: ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ sl@0: insertu32(buf + j/2, ((mp4_u64 *)buf2)[j / 8]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread/2) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoCO64LongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video CO64 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoCO64LongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 sl@0: //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Chunk offsets */ sl@0: sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->videoSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > bufferSize) sl@0: bytestoread = bufferSize; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 8) sl@0: { sl@0: ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ sl@0: insertu64(buf + j, ((mp4_u64 *)buf2)[j / 8]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTSS(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STSS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTSS(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stss); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stss); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSS); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssEntryCount); sl@0: i += 4; sl@0: sl@0: /* Sample numbers */ sl@0: for (j = 0; j < handle->videoSampleTable->stssEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssSampleNumber[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stss) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSTSSLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video STSS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSTSSLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stss); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSS); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->videoSampleTable->stssEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Sample numbers */ sl@0: sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->videoSampleTable->stssEntryCount * 4; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > METADATA_COPY_BUFFERSIZE) sl@0: bytestoread = METADATA_COPY_BUFFERSIZE; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioTrak(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio track atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioTrak(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->trak); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_TRAK); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioTKHD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioMDIA(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->audioUDTA) sl@0: { sl@0: if (writeUDTA(handle, handle->audioUDTA) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioTKHD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio TKHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioTKHD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 u32; sl@0: mp4_double ud; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->tkhd); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->tkhd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_TKHD); sl@0: i += 4; sl@0: sl@0: sl@0: if (handle->audioDuration > MP4_INT_MAX) sl@0: { sl@0: mp4_u64 u64; sl@0: /* Version and flags */ sl@0: buf[i++] = 1; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 7; /* Track enabled, used in movie and preview */ sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Track ID */ sl@0: insertu32(buf+i, (mp4_u32)2); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: if ( ( handle->audioTimeScale == 0 ) || ( handle->audioDuration == 0 ) ) sl@0: { sl@0: ud = 0; sl@0: } sl@0: else sl@0: { sl@0: ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->audioDuration / (mp4_double)handle->audioTimeScale + (mp4_double)0.5; sl@0: } sl@0: u64 = (mp4_u64)ud; sl@0: insertu64(buf+i, u64); sl@0: i += 8; sl@0: sl@0: } sl@0: else sl@0: { sl@0: /* Version and flags */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 7; /* Track enabled, used in movie and preview */ sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Track ID */ sl@0: insertu32(buf+i, (mp4_u32)2); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: if ( ( handle->audioTimeScale == 0 ) || ( handle->audioDuration == 0 ) ) sl@0: { sl@0: ud = 0; sl@0: } sl@0: else sl@0: { sl@0: ud = (mp4_double)MVHD_TIMESCALE * (mp4_double)handle->audioDuration / (mp4_double)handle->audioTimeScale + (mp4_double)0.5; sl@0: } sl@0: u32 = (mp4_u32)ud; sl@0: insertu32(buf+i, u32); sl@0: i += 4; sl@0: } sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0x0100); /* Audio track */ sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00010000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x40000000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); /* Audio track */ sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); /* Audio track */ sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, ts->tkhd) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioMDIA(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio MDIA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioMDIA(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->mdia); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MDIA); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioMDHD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioHDLR(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioMINF(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioMDHD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio MDHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioMDHD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 u32; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->mdhd); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->mdhd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MDHD); sl@0: i += 4; sl@0: sl@0: if (handle->audioDuration > MP4_INT_MAX) sl@0: { sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0x1000000); //version 1 atom sl@0: i += 4; sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu64(buf+i, (mp4_u64)u32); sl@0: i += 8; sl@0: sl@0: /* Timescale */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioTimeScale); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: insertu64(buf+i, handle->audioDuration); sl@0: i += 8; sl@0: sl@0: } sl@0: else sl@0: { sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Creation time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Modification time */ sl@0: if (getCurrentTime(&u32) < 0) sl@0: u32 = 0; sl@0: insertu32(buf+i, (mp4_u32)u32); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioTimeScale); sl@0: i += 4; sl@0: sl@0: /* Duration */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioDuration); sl@0: i += 4; sl@0: } sl@0: sl@0: /* Language */ sl@0: insertu16(buf+i, (mp4_u16)0x55c4); /* 'und' */ sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu16(buf+i, (mp4_u16)0x0000); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, ts->mdhd) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioHDLR(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio HDLR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioHDLR(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->hdlr); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->hdlr); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_HDLR); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Handler type */ sl@0: buf[i++] = 's'; sl@0: buf[i++] = 'o'; sl@0: buf[i++] = 'u'; sl@0: buf[i++] = 'n'; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Empty string */ sl@0: buf[i++] = 0; sl@0: sl@0: if (writeFile(handle, buf, ts->hdlr) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioMINF(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio MINF atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioMINF(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->minf); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MINF); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeSMHD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeDINF(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioSTBL(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeSMHD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write SMHD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeSMHD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->smhd); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->smhd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_SMHD); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, ts->smhd) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTBL(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STBL atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTBL(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stbl); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STBL); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeAudioSTSD(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (writeAudioSTTSLongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeAudioSTTS(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: sl@0: if (writeAudioSTSC(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (writeAudioSTSZLongClip(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->audioSampleTable->stcoNeed64Bits) sl@0: { sl@0: if (writeAudioCO64LongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeAudioSTCOLongClip(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (writeAudioSTSZ(handle, ts) < 0) sl@0: return -1; sl@0: sl@0: if (handle->audioSampleTable->stcoNeed64Bits) sl@0: { sl@0: if (writeAudioCO64(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: if (writeAudioSTCO(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: } sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTSD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STSD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTSD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[16]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsd); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSD); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)1); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 16) < 0) sl@0: return -1; sl@0: sl@0: if (handle->type & MP4_TYPE_MPEG4_AUDIO) sl@0: { sl@0: if (writeMP4A(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else if (handle->type & MP4_TYPE_AMR_NB) sl@0: { sl@0: if (writeSAMR(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else if (handle->type & MP4_TYPE_AMR_WB) sl@0: { sl@0: if (writeSAWB(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (!handle->qcelpStoredAsMPEGAudio)) sl@0: { sl@0: if (writeSQCP(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) sl@0: { sl@0: if (writeMP4A(handle, ts) < 0) sl@0: return -1; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeMP4A(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write MP4A atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeMP4A(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(36); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->mp4a); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_MP4A); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)2); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)16); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu16(buf+i, (mp4_u16)handle->audioTimeScale); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 36) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeAudioESD(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioESD(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio ESD atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioESD(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 bitrate = 0; sl@0: mp4_u32 num_of_bytes = 0; sl@0: mp4_u32 size = 0; sl@0: mp4_u32 index = 0; sl@0: mp4_u32 tempnum = 0; sl@0: sl@0: mp4_u32 size1, size2; sl@0: mp4_u32 numofsizebytes1, numofsizebytes2; sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->esds); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Calculate the necessary size information */ sl@0: size1 = handle->audioDecSpecificInfoSize; sl@0: if (size1 < 128) sl@0: numofsizebytes1 = 1; sl@0: else sl@0: { sl@0: numofsizebytes1 = 1; sl@0: while ( size1 >= 128 ) sl@0: { sl@0: size1 = size1 >> 7; sl@0: numofsizebytes1++; sl@0: } sl@0: } sl@0: sl@0: size2 = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize; sl@0: if (size2 < 128) sl@0: numofsizebytes2 = 1; sl@0: else sl@0: { sl@0: numofsizebytes2 = 1; sl@0: while ( size2 >= 128 ) sl@0: { sl@0: size2 = size2 >> 7; sl@0: numofsizebytes2++; sl@0: } sl@0: } sl@0: /* End of size calculations */ sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->esds); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_ESD); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* ES_DescrTag */ sl@0: buf[i++] = 0x03; sl@0: sl@0: /* Size */ sl@0: size = 21 + numofsizebytes1 + numofsizebytes2 + handle->audioDecSpecificInfoSize; sl@0: if (size < 128) sl@0: buf[i++] = (mp4_u8)(size); sl@0: else sl@0: { sl@0: num_of_bytes = 0; sl@0: while ( size >= 128 ) sl@0: { sl@0: size = size >> 7; sl@0: num_of_bytes++; sl@0: } sl@0: size = 21 + numofsizebytes1 + numofsizebytes2 + handle->audioDecSpecificInfoSize; sl@0: for(index = num_of_bytes; index > 0; index--) sl@0: { sl@0: tempnum = size >> (7 * index); sl@0: buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum); sl@0: size -= (tempnum << (7 * index)); sl@0: } sl@0: buf[i++] = (mp4_u8)size; sl@0: } sl@0: sl@0: /* ES_ID */ sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: /* Flags */ sl@0: buf[i++] = 0; sl@0: sl@0: /* DecoderConfigDescrTag */ sl@0: buf[i++] = 0x04; sl@0: sl@0: /* Size */ sl@0: size = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize; sl@0: if (size < 128) sl@0: buf[i++] = (mp4_u8)(size); sl@0: else sl@0: { sl@0: num_of_bytes = 0; sl@0: while ( size >= 128 ) sl@0: { sl@0: size = size >> 7; sl@0: num_of_bytes++; sl@0: } sl@0: size = 14 + numofsizebytes1 + handle->audioDecSpecificInfoSize; sl@0: for(index = num_of_bytes; index > 0; index--) sl@0: { sl@0: tempnum = size >> (7 * index); sl@0: buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum); sl@0: size -= (tempnum << (7 * index)); sl@0: } sl@0: buf[i++] = (mp4_u8)size; sl@0: } sl@0: sl@0: /* ObjectTypeIndication */ sl@0: if (handle->type & MP4_TYPE_MPEG4_AUDIO) sl@0: buf[i++] = 0x40; sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) sl@0: buf[i++] = 0xE1; sl@0: else sl@0: { sl@0: } sl@0: sl@0: /* Flags */ sl@0: buf[i++] = 0x15; sl@0: sl@0: /* BufferSizeDB */ sl@0: if (handle->type & MP4_TYPE_MPEG4_AUDIO) sl@0: { sl@0: buf[i++] = 0x00; sl@0: buf[i++] = 0x00; sl@0: buf[i++] = 0x00; sl@0: } sl@0: else if ((handle->type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) sl@0: { /* 4096 for QCELP 13K */ sl@0: buf[i++] = 0x00; sl@0: buf[i++] = 0x10; sl@0: buf[i++] = 0x00; sl@0: } sl@0: else sl@0: { sl@0: } sl@0: sl@0: sl@0: if ((handle->audioDuration != 0) && (handle->audioTimeScale != 0)) sl@0: bitrate = (mp4_u32)((mp4_double)8 * sl@0: (mp4_double)handle->audioMediaDataSize / sl@0: ((mp4_double)handle->audioDuration / sl@0: (mp4_double)handle->audioTimeScale)); sl@0: else sl@0: bitrate = 0; sl@0: sl@0: /* MaxBitrate */ sl@0: insertu32(buf+i, (mp4_u32)bitrate); /*0x00010000*/ sl@0: i += 4; sl@0: sl@0: /* AvgBitrate */ sl@0: insertu32(buf+i, (mp4_u32)bitrate);/*0x00008000*/ sl@0: i += 4; sl@0: sl@0: /* DecSpecificInfoTag */ sl@0: buf[i++] = 0x05; sl@0: sl@0: /* Size */ sl@0: size = handle->audioDecSpecificInfoSize; sl@0: if (size < 128) sl@0: buf[i++] = (mp4_u8)(size); sl@0: else sl@0: { sl@0: num_of_bytes = 0; sl@0: while ( size >= 128 ) sl@0: { sl@0: size = size >> 7; sl@0: num_of_bytes++; sl@0: } sl@0: size = handle->audioDecSpecificInfoSize; sl@0: for(index = num_of_bytes; index > 0; index--) sl@0: { sl@0: tempnum = size >> (7 * index); sl@0: buf[i++] = (mp4_u8)(0x80 | (mp4_u8) tempnum); sl@0: size -= (tempnum << (7 * index)); sl@0: } sl@0: buf[i++] = (mp4_u8)size; sl@0: } sl@0: sl@0: /* DecoderSpecificInfo */ sl@0: mp4memcpy(buf+i, handle->audioDecSpecificInfo, handle->audioDecSpecificInfoSize); sl@0: i += handle->audioDecSpecificInfoSize; sl@0: sl@0: /* SLConfigDescrTag */ sl@0: buf[i++] = 0x06; sl@0: sl@0: /* Size */ sl@0: buf[i++] = 1; sl@0: sl@0: /* */ sl@0: buf[i++] = 2; sl@0: sl@0: if (writeFile(handle, buf, ts->esds) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeSAMR(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write SAMR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeSAMR(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(36); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->samr); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_SAMR); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)2); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)16); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu16(buf+i, (mp4_u16)handle->audioTimeScale); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 36) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeDAMR(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeSAWB(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write SAWB atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeSAWB(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(36); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->sawb); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_SAWB); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)2); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)16); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu16(buf+i, (mp4_u16)handle->audioTimeScale); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 36) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeDAMR(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeDAMR(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write DAMR atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeDAMR(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[17]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->damr); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_DAMR); sl@0: i += 4; sl@0: sl@0: /* Vendor */ sl@0: buf[i++] = 'S'; sl@0: buf[i++] = '6'; sl@0: buf[i++] = '0'; sl@0: buf[i++] = ' '; sl@0: sl@0: /* Decoder version */ sl@0: buf[i++] = 0; sl@0: sl@0: /* Mode set */ sl@0: insertu16(buf+i, (mp4_u16)handle->audioModeSet); sl@0: i += 2; sl@0: sl@0: /* Mode change period */ sl@0: buf[i++] = 0; sl@0: sl@0: /* Frames per sample */ sl@0: buf[i++] = handle->audioFramesPerSample; sl@0: sl@0: if (writeFile(handle, buf, 17) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTTS(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTTS(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stts); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stts); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsEntryCount); sl@0: i += 4; sl@0: sl@0: /* Sample count and sample delta */ sl@0: for (j = 0; j < handle->audioSampleTable->sttsEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsSampleCount[j]); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsSampleDelta[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTTSLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STTS atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTTSLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stts); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STTS); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->sttsEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Sample count and delta */ sl@0: sl@0: /* Seek to the beginning of temporary files */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->audioSampleTable->sttsEntryCount * 4; /* Bytes left in each file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > METADATA_COPY_BUFFERSIZE / 2) sl@0: bytestoread = METADATA_COPY_BUFFERSIZE / 2; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + 2*j, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + 2*j + 4, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, 2 * bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTSC(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STSC atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTSC(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stsc); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsc); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSC); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscEntryCount); sl@0: i += 4; sl@0: sl@0: /* First chunk, samples per chunk and sample description index */ sl@0: for (j = 0; j < handle->audioSampleTable->stscEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscFirstChunk[j]); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscSamplesPerChunk[j]); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stscSampleDescriptionIndex[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stsc) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTSZ(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STSZ atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTSZ(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stsz); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsz); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Sample size */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleSize); sl@0: i += 4; sl@0: sl@0: /* Sample count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleCount); sl@0: i += 4; sl@0: sl@0: /* Entry sizes */ sl@0: if (handle->audioSampleTable->stszSampleSize == 0) sl@0: { sl@0: for (j = 0; j < handle->audioSampleTable->stszSampleCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszEntrySize[j]); sl@0: i += 4; sl@0: } sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stsz) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTSZLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STSZ atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTSZLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stsz); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STSZ); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Sample size */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleSize); sl@0: i += 4; sl@0: sl@0: /* Sample count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stszSampleCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Entry sizes */ sl@0: sl@0: if (handle->audioSampleTable->stszSampleSize == 0) sl@0: { sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->audioSampleTable->stszSampleCount * 4; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > METADATA_COPY_BUFFERSIZE) sl@0: bytestoread = METADATA_COPY_BUFFERSIZE; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 4) sl@0: { sl@0: insertu32(buf + j, ((mp4_u32 *)buf2)[j / 4]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTCO(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STCO atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTCO(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stco); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: /* Chunk offsets */ sl@0: for (j = 0; j < handle->audioSampleTable->stcoEntryCount; j++) sl@0: { sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoChunkOffset[j]); sl@0: i += 4; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stco) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioCO64(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio CO64 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioCO64(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->stco); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: /* Chunk offsets */ sl@0: for (j = 0; j < handle->audioSampleTable->stcoEntryCount; j++) sl@0: { sl@0: insertu64(buf+j, (mp4_u64)handle->audioSampleTable->stcoChunkOffset[j]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->stco) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioSTCOLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio STCO atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioSTCOLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 sl@0: //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_STCO); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Chunk offsets */ sl@0: sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->audioSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > bufferSize) sl@0: bytestoread = bufferSize; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 8) sl@0: { sl@0: ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ sl@0: insertu32(buf + j/2, ((mp4_u64 *)buf2)[j / 8]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread/2) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAudioCO64LongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write audio CO64 atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAudioCO64LongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: mp4_u32 bufferSize = (METADATA_COPY_BUFFERSIZE/sizeof(mp4_u64)) * sizeof(mp4_u64); //must be a multiple of u64 sl@0: //METADATA_COPY_BUFFERSIZE is only guaranteed to be a multiple of 4 sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(bufferSize); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->stco); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_CO64); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Entry count */ sl@0: insertu32(buf+i, (mp4_u32)handle->audioSampleTable->stcoEntryCount); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Chunk offsets */ sl@0: sl@0: /* Seek to the beginning of temporary file */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->audioSampleTable->stcoEntryCount * 8; /* Bytes left in the file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > bufferSize) sl@0: bytestoread = bufferSize; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: for (j = 0; j < bytestoread; j += 8) sl@0: { sl@0: ((mp4_u64 *)buf2)[j / 8] += (handle->metaDataSize + MDAT_HEADER_SIZE); /* Update chunk offsets */ sl@0: insertu64(buf + j, ((mp4_u64 *)buf2)[j / 8]); sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeMediaData(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes media data to the output file. sl@0: * sl@0: * Before writing media data to the output file, meta data has sl@0: * been written to the file. Media data that is in tmpfile is sl@0: * read from there and written to the end of the output file. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeMediaData(MP4HandleImp handle) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u64 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(1024); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: sl@0: i = formatMdatHeader(buf, handle->bytesInTmpFile); sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Seek to the beginning of tmpfile */ sl@0: if (seekTmpFileAbs(handle, 0) < 0) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->bytesInTmpFile; sl@0: sl@0: while (left) sl@0: { sl@0: if (left > 1024) sl@0: bytestoread = 1024; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readTmpFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 insertu64(mp4_u8 *buf, sl@0: * mp4_u64 value) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes value into buf taking into account the endianism sl@0: * of the current computer. sl@0: * sl@0: * It is assumed that the caller of the function has allocated enough sl@0: * space for buf. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * buf Buffer to write to sl@0: * value Value to write to buf sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 insertu64(mp4_u8 *buf, mp4_u64 value) sl@0: { sl@0: mp4_u64 u64; sl@0: sl@0: sl@0: u64 = u64endian(value); sl@0: mp4memcpy(buf, &u64, sizeof(mp4_u64)); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 insertu32(mp4_u8 *buf, sl@0: * mp4_u32 value) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes value into buf taking into account the endianism sl@0: * of the current computer. sl@0: * sl@0: * It is assumed that the caller of the function has allocated enough sl@0: * space for buf. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * buf Buffer to write to sl@0: * value Value to write to buf sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 insertu32(mp4_u8 *buf, mp4_u32 value) sl@0: { sl@0: mp4_u32 u32; sl@0: sl@0: sl@0: u32 = u32endian(value); sl@0: mp4memcpy(buf, &u32, 4); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 insertu16(mp4_u8 *buf, sl@0: * mp4_u16 value) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes value into buf taking into account the endianism sl@0: * of the current computer. sl@0: * sl@0: * It is assumed that the caller of the function has allocated enough sl@0: * space for buf. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * buf Buffer to write to sl@0: * value Value to write to buf sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 insertu16(mp4_u8 *buf, mp4_u16 value) sl@0: { sl@0: mp4_u16 u16; sl@0: sl@0: sl@0: u16 = u16endian(value); sl@0: mp4memcpy(buf, &u16, 2); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeMetaDataTmp(MP4HandleImp handle) sl@0: * sl@0: * Description: sl@0: * sl@0: * This function writes metadata accumulated in memory to the disk. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeMetaDataTmp(MP4HandleImp handle) sl@0: { sl@0: PRINT((_L("e_writemetadatatmp 1"))); sl@0: if (handle->videoSampleTable) sl@0: { sl@0: PRINT((_L("e_writemetadatatmp_writemetadata_video 1"))); sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->videoSampleTable->sttsSampleCount, sl@0: handle->videoSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), sl@0: METADATAFILE_VIDEO_STTS_SAMPLE_COUNT) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->videoSampleTable->sttsSampleDelta, sl@0: handle->videoSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), sl@0: METADATAFILE_VIDEO_STTS_SAMPLE_DELTA) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->videoSampleTable->stszEntrySize, sl@0: handle->videoSampleTable->stszCurrentSampleCount * sizeof(mp4_u32), sl@0: METADATAFILE_VIDEO_STSZ_ENTRY_SIZE) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->videoSampleTable->stcoChunkOffset, sl@0: handle->videoSampleTable->stcoCurrentEntryCount * sizeof(mp4_u64), sl@0: METADATAFILE_VIDEO_STCO_CHUNK_OFFSET) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->videoSampleTable->stssSampleNumber, sl@0: handle->videoSampleTable->stssCurrentEntryCount * sizeof(mp4_u32), sl@0: METADATAFILE_VIDEO_STSS_SAMPLE_NUMBER) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->videoSampleTable->sdtpSampleDependency, sl@0: handle->videoSampleTable->sdtpCurrentEntryCount * sizeof(mp4_u8), sl@0: METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0) sl@0: return -1; sl@0: PRINT((_L("e_writemetadatatmp_writemetadata_video 0"))); sl@0: } sl@0: sl@0: if (handle->audioSampleTable) sl@0: { sl@0: PRINT((_L("e_writemetadatatmp_writemetadata_audio 1"))); sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->audioSampleTable->sttsSampleCount, sl@0: handle->audioSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), sl@0: METADATAFILE_AUDIO_STTS_SAMPLE_COUNT) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->audioSampleTable->sttsSampleDelta, sl@0: handle->audioSampleTable->sttsCurrentEntryCount * sizeof(mp4_u32), sl@0: METADATAFILE_AUDIO_STTS_SAMPLE_DELTA) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->audioSampleTable->stszEntrySize, sl@0: handle->audioSampleTable->stszCurrentSampleCount * sizeof(mp4_u32), sl@0: METADATAFILE_AUDIO_STSZ_ENTRY_SIZE) < 0) sl@0: return -1; sl@0: sl@0: if (writeMetaDataFileNum(handle, sl@0: (mp4_u8 *)handle->audioSampleTable->stcoChunkOffset, sl@0: handle->audioSampleTable->stcoCurrentEntryCount * sizeof(mp4_u64), sl@0: METADATAFILE_AUDIO_STCO_CHUNK_OFFSET) < 0) sl@0: return -1; sl@0: PRINT((_L("e_writemetadatatmp_writemetadata_audio 0"))); sl@0: } sl@0: sl@0: if (handle->videoSampleTable) sl@0: { sl@0: handle->videoSampleTable->sttsCurrentEntryCount = 0; sl@0: handle->videoSampleTable->stszCurrentSampleCount = 0; sl@0: handle->videoSampleTable->stcoCurrentEntryCount = 0; sl@0: handle->videoSampleTable->stssCurrentEntryCount = 0; sl@0: handle->videoSampleTable->sdtpCurrentEntryCount = 0; sl@0: } sl@0: sl@0: if (handle->audioSampleTable) sl@0: { sl@0: handle->audioSampleTable->sttsCurrentEntryCount = 0; sl@0: handle->audioSampleTable->stszCurrentSampleCount = 0; sl@0: handle->audioSampleTable->stcoCurrentEntryCount = 0; sl@0: } sl@0: sl@0: handle->metaDataBlocks = 0; sl@0: handle->metaDataOnDisk = MP4TRUE; sl@0: sl@0: PRINT((_L("e_writemetadatatmp 0"))); sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeSQCP(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write SQCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeSQCP(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(36); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->sqcp); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_SQCP); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)2); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)16); sl@0: i += 2; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Timescale */ sl@0: insertu16(buf+i, (mp4_u16)handle->audioTimeScale); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu16(buf+i, (mp4_u16)0); sl@0: i += 2; sl@0: sl@0: if (writeFile(handle, buf, 36) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeDQCP(handle, ts) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeDQCP(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write DQCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeDQCP(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 buf[14]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->dqcp); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_DQCP); sl@0: i += 4; sl@0: sl@0: /* Vendor */ sl@0: buf[i++] = 'n'; sl@0: buf[i++] = 'o'; sl@0: buf[i++] = 'k'; sl@0: buf[i++] = 'i'; sl@0: sl@0: /* Decoder version */ sl@0: buf[i++] = 0; sl@0: sl@0: /* Mode set */ sl@0: // insertu16(buf+i, (mp4_u16)handle->audioModeSet); sl@0: // i += 2; sl@0: sl@0: /* Mode change period */ sl@0: // buf[i++] = 0; sl@0: sl@0: /* Frames per sample */ sl@0: buf[i++] = handle->audioFramesPerSample; sl@0: sl@0: if (writeFile(handle, buf, 14) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 calculateES_DescriptorSize(mp4_u32 type) sl@0: * sl@0: * Description: sl@0: * sl@0: * Calculated the ES_Descriptor size inside the ESDS box. sl@0: * Updates handle->ES_DescriptorSize; sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * type the media type: sl@0: * MP4_TYPE_QCELP_13K sl@0: * MP4_TYPE_MPEG_AUDIO sl@0: * MP4_TYPE_MPEG4_VIDEO sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * sl@0: */ sl@0: mp4_i32 calculateES_DescriptorSize(MP4HandleImp handle, mp4_u32 type) sl@0: { sl@0: mp4_u32 size1, size2, size3; sl@0: mp4_u32 numofsizebytes1, numofsizebytes2, numofsizebytes3; sl@0: mp4_u32 decspecinfosize = 0; sl@0: sl@0: if (((type & MP4_TYPE_QCELP_13K) && (handle->qcelpStoredAsMPEGAudio)) || sl@0: (type & MP4_TYPE_MPEG4_AUDIO)) sl@0: decspecinfosize = handle->audioDecSpecificInfoSize; sl@0: else /* MPEG video case */ sl@0: decspecinfosize = handle->videoDecSpecificInfoSize; sl@0: sl@0: size1 = decspecinfosize; sl@0: if (size1 < 128) sl@0: numofsizebytes1 = 1; sl@0: else sl@0: { sl@0: numofsizebytes1 = 1; sl@0: while ( size1 >= 128 ) sl@0: { sl@0: size1 = size1 >> 7; sl@0: numofsizebytes1++; sl@0: } sl@0: } sl@0: sl@0: size2 = 14 + numofsizebytes1 + decspecinfosize; sl@0: if (size2 < 128) sl@0: numofsizebytes2 = 1; sl@0: else sl@0: { sl@0: numofsizebytes2 = 1; sl@0: while ( size2 >= 128 ) sl@0: { sl@0: size2 = size2 >> 7; sl@0: numofsizebytes2++; sl@0: } sl@0: } sl@0: sl@0: size3 = 21 + numofsizebytes1 + numofsizebytes2 + decspecinfosize; sl@0: if (size3 < 128) sl@0: numofsizebytes3 = 1; sl@0: else sl@0: { sl@0: numofsizebytes3 = 1; sl@0: while ( size3 >= 128 ) sl@0: { sl@0: size3 = size3 >> 7; sl@0: numofsizebytes3++; sl@0: } sl@0: } sl@0: sl@0: /* ES_DescriptorSize contains the size of the ES_Descriptor Field, including the 0x03 (ES_ID Tag) */ sl@0: handle->ES_DescriptorSize = 21 + numofsizebytes1 + numofsizebytes2 + decspecinfosize + numofsizebytes3 + 1; sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeUDTA(MP4HandleImp handle, sl@0: * userDataAtom *udta) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write UDTA atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeUDTA(MP4HandleImp handle, userDataAtom *udta) sl@0: { sl@0: mp4_u8 buf[8]; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, 8 + (mp4_u32)udta->atomcontentsize); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_UDTA); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, 8) < 0) sl@0: return -1; sl@0: sl@0: if (writeFile(handle, udta->contentdata, udta->atomcontentsize) < 0) sl@0: return -1; sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 updateVideoDependencyMetaData(MP4HandleImp handle, sl@0: * mp4_u8 aDependsOn, sl@0: * mp4_u8 aIsDependentOn, sl@0: * mp4_u8 aHasRedundancy) sl@0: * sl@0: * Description: sl@0: * sl@0: * Updates SDTP video dependency data sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * aDependsOn This frame's dependency on other frames sl@0: * aIsDependentOn Other frames's dependency on this frame sl@0: * aHasRedundancy Whether there is redundant coding in this frame sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 updateVideoDependencyMetaData(MP4HandleImp handle, mp4_u8 aDependsOn, mp4_u8 aIsDependentOn, mp4_u8 aHasRedundancy) sl@0: { sl@0: if (handle->flags & MP4_FLAG_LONGCLIP) sl@0: { sl@0: if (handle->videoSampleTable->sdtpCurrentEntryCount == handle->videoSampleTable->sdtpMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(handle->videoSampleTable->sdtpSampleDependency, sl@0: 2 * sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount, sl@0: sizeof(mp4_u8) * handle->videoSampleTable->stssMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: handle->videoSampleTable->sdtpSampleDependency = (mp4_u8 *)p; sl@0: sl@0: handle->videoSampleTable->sdtpMaxEntryCount *= 2; sl@0: } sl@0: sl@0: handle->videoSampleTable->sdtpSampleDependency[handle->videoSampleTable->sdtpCurrentEntryCount] = (aDependsOn << 4) | (aIsDependentOn << 2) | (aHasRedundancy); sl@0: handle->videoSampleTable->sdtpCurrentEntryCount++; sl@0: handle->videoSampleTable->sdtpEntryCount++; sl@0: } sl@0: else sl@0: { sl@0: if (handle->videoSampleTable->sdtpEntryCount == handle->videoSampleTable->sdtpMaxEntryCount) sl@0: { sl@0: void *p; sl@0: sl@0: p = mp4realloc(handle->videoSampleTable->sdtpSampleDependency, sl@0: 2 * sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount, sl@0: sizeof(mp4_u8) * handle->videoSampleTable->sdtpMaxEntryCount); sl@0: if (p == NULL) sl@0: return -1; sl@0: sl@0: handle->videoSampleTable->sdtpSampleDependency = (mp4_u8 *)p; sl@0: sl@0: handle->videoSampleTable->sdtpMaxEntryCount *= 2; sl@0: } sl@0: sl@0: handle->videoSampleTable->sdtpSampleDependency[handle->videoSampleTable->sdtpEntryCount] = (aDependsOn << 4) | (aIsDependentOn << 2) | (aHasRedundancy); sl@0: handle->videoSampleTable->sdtpEntryCount++; sl@0: } sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSDTP(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video SDTP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSDTP(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 j; sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(ts->sdtp); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->sdtp); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_SDTP); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Sample dependencies */ sl@0: for (j = 0; j < handle->videoSampleTable->sdtpEntryCount; j++) sl@0: { sl@0: buf[i++] = (mp4_u8)handle->videoSampleTable->sdtpSampleDependency[j]; sl@0: } sl@0: sl@0: if (writeFile(handle, buf, ts->sdtp) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeVideoSDTPLongClip(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write video SDTP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeVideoSDTPLongClip(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u8 *buf2; sl@0: mp4_u32 i = 0; sl@0: mp4_u32 left; sl@0: mp4_u32 bytestoread; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE); sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: buf2 = (mp4_u8 *)mp4malloc(METADATA_COPY_BUFFERSIZE / 2); sl@0: if (buf2 == NULL) sl@0: { sl@0: mp4free(buf); sl@0: return -1; sl@0: } sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->sdtp); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_SDTP); sl@0: i += 4; sl@0: sl@0: /* Version and flags */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: if (writeFile(handle, buf, i) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: /* Sample count and delta */ sl@0: sl@0: /* Seek to the beginning of temporary files */ sl@0: sl@0: if (seekMetaDataFileNumAbs(handle, 0, METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: return -1; sl@0: } sl@0: sl@0: left = handle->videoSampleTable->sdtpEntryCount; /* Bytes left in each file */ sl@0: sl@0: while (left) sl@0: { sl@0: if (left > METADATA_COPY_BUFFERSIZE / 2) sl@0: bytestoread = METADATA_COPY_BUFFERSIZE / 2; sl@0: else sl@0: bytestoread = left; sl@0: sl@0: if (readMetaDataFileNum(handle, buf2, bytestoread, METADATAFILE_VIDEO_SDTP_SAMPLE_DEPENDENCY) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: if (writeFile(handle, buf2, bytestoread) < 0) sl@0: { sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: left -= bytestoread; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: mp4free(buf2); sl@0: sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 writeAVCP(MP4HandleImp handle, sl@0: * trakSize *ts) sl@0: * sl@0: * Description: sl@0: * sl@0: * Write AVCP atom. sl@0: * sl@0: * Parameters: sl@0: * sl@0: * handle MP4 library handle sl@0: * ts Atom sizes sl@0: * sl@0: * Return value: sl@0: * sl@0: * 0 Success sl@0: * -1 Error sl@0: * sl@0: */ sl@0: mp4_i32 writeAVCP(MP4HandleImp handle, trakSize *ts) sl@0: { sl@0: mp4_u8 *buf; sl@0: mp4_u32 i = 0; sl@0: sl@0: sl@0: buf = (mp4_u8 *)mp4malloc(86+7); // 86 = size of VisualSampleEntry, 7 = size of AVCDecoderConfigurationRecord sl@0: // with PPS and SPS sizes set to 0 sl@0: if (buf == NULL) sl@0: return -1; sl@0: sl@0: /* Size */ sl@0: insertu32(buf+i, (mp4_u32)ts->avcp); sl@0: i += 4; sl@0: sl@0: /* Atom type */ sl@0: insertu32(buf+i, (mp4_u32)ATOMTYPE_AVCP); sl@0: i += 4; sl@0: sl@0: /* Reserved */ sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: buf[i++] = 0; sl@0: sl@0: /* Data reference index */ sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: /* Width */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoWidth); sl@0: i += 2; sl@0: sl@0: /* Height */ sl@0: insertu16(buf+i, (mp4_u16)handle->videoHeight); sl@0: i += 2; sl@0: sl@0: /* Reserved */ sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0x00480000); sl@0: i += 4; sl@0: sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)1); sl@0: i += 2; sl@0: sl@0: // Compressorname sl@0: buf[i++] = 14; sl@0: insertu32(buf+i, (mp4_u32)0x41564320); // "AVC " sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)0x70617261); // "para" sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)0x6d657465); // "mete" sl@0: i += 4; sl@0: insertu16(buf+i, (mp4_u16)0x7273); // "rs" sl@0: i += 2; sl@0: buf[i++] = 0; sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: insertu32(buf+i, (mp4_u32)0); sl@0: i += 4; sl@0: sl@0: insertu16(buf+i, (mp4_u16)24); sl@0: i += 2; sl@0: sl@0: insertu16(buf+i, (mp4_u16)0xffff); sl@0: i += 2; sl@0: sl@0: // AVCC without picparams & seqparams sl@0: mp4memcpy(buf+i, handle->videoDecSpecificInfo, 5); // 5 = configurationVersion + AVCProfileIndication + sl@0: // profile_compatibility + AVCLevelIndication + sl@0: // '111111' + lengthSizeMinusOne (2 bits) sl@0: i += 5; sl@0: buf[i++] = 0xE0 | 0; // '111' + numOfSequenceParameterSets (5 bits) sl@0: buf[i++] = 0; // numOfPictureParameterSets sl@0: sl@0: if (writeFile(handle, buf, 86+7) < 0) sl@0: { sl@0: mp4free(buf); sl@0: sl@0: return -1; sl@0: } sl@0: sl@0: mp4free(buf); sl@0: sl@0: return 0; sl@0: } sl@0: sl@0: /* sl@0: * Function: sl@0: * sl@0: * mp4_i32 formatMdatHeader(mp4_u8 *buffer, sl@0: * mp4_u64 size) sl@0: * sl@0: * Description: sl@0: * sl@0: * Formats the MDAT header into buffer sl@0: * sl@0: * Parameters: sl@0: * sl@0: * buffer buffer to write the MDAT header into sl@0: * size Size of the media data (excluding the MDAT header) sl@0: * sl@0: * Return value: sl@0: * sl@0: * size of header sl@0: * sl@0: */ sl@0: mp4_i32 formatMdatHeader(mp4_u8 *buf, mp4_u64 size) sl@0: { sl@0: TInt i = 0; sl@0: if (size < MP4_INT_MAX) sl@0: { sl@0: //insert free box sl@0: insertu32(buf, (mp4_u32)8); sl@0: i += sizeof(mp4_u32); sl@0: insertu32(buf + i, (mp4_u32)ATOMTYPE_FREE); sl@0: i += sizeof(mp4_u32); sl@0: sl@0: //insert mdat box sl@0: insertu32(buf + i, (mp4_u32)size + 8); sl@0: i += sizeof(mp4_u32); sl@0: insertu32(buf + i, (mp4_u32)ATOMTYPE_MDAT); sl@0: i += sizeof(mp4_u32); sl@0: } sl@0: else sl@0: { sl@0: //insert mdat box sl@0: insertu32(buf + i, (mp4_u32)1); sl@0: i += sizeof(mp4_u32); sl@0: insertu32(buf + i, (mp4_u32)ATOMTYPE_MDAT); sl@0: i += sizeof(mp4_u32); sl@0: insertu64(buf + i, (mp4_u64)size + 16); sl@0: i += sizeof(mp4_u64); sl@0: } sl@0: sl@0: ASSERT(MDAT_HEADER_SIZE == i); sl@0: return i; sl@0: } sl@0: sl@0: // End of File