summaryrefslogtreecommitdiffstats
path: root/libvideoeditor/vss/3gpwriter/src/M4MP4W_Writer.c
diff options
context:
space:
mode:
Diffstat (limited to 'libvideoeditor/vss/3gpwriter/src/M4MP4W_Writer.c')
-rwxr-xr-xlibvideoeditor/vss/3gpwriter/src/M4MP4W_Writer.c5376
1 files changed, 0 insertions, 5376 deletions
diff --git a/libvideoeditor/vss/3gpwriter/src/M4MP4W_Writer.c b/libvideoeditor/vss/3gpwriter/src/M4MP4W_Writer.c
deleted file mode 100755
index cdfc441..0000000
--- a/libvideoeditor/vss/3gpwriter/src/M4MP4W_Writer.c
+++ /dev/null
@@ -1,5376 +0,0 @@
-/*
- * Copyright (C) 2011 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-/**
- ******************************************************************************
- * @file M4MP4W_Writer.c
- * @brief Implementation of the core MP4 writer
- ******************************************************************************
- */
-
-#include "NXPSW_CompilerSwitches.h"
-
-#ifndef _M4MP4W_USE_CST_MEMORY_WRITER
-
-#include "M4OSA_Error.h"
-#include "M4OSA_Debug.h"
-#include "M4MP4W_Writer.h"
-#include "M4MP4W_Utils.h"
-
-/* Check optimisation flags : BEGIN */
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-#ifdef _M4MP4W_MOOV_FIRST
-#error "_M4MP4W_OPTIMIZE_FOR_PHONE should not be used with _M4MP4W_MOOV_FIRST"
-
-#endif
-
-#endif
-
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-#ifndef _M4MP4W_OPTIMIZE_FOR_PHONE
-#error "_M4MP4W_UNBUFFERED_VIDEO should be used with _M4MP4W_OPTIMIZE_FOR_PHONE"
-
-#endif
-
-#endif
-/* Check optimisation flags : END */
-
-#ifndef _M4MP4W_DONT_USE_TIME_H
-#include <time.h>
-
-#endif /*_M4MP4W_DONT_USE_TIME_H*/
-
-/*MACROS*/
-#define MAJOR_VERSION 3
-#define MINOR_VERSION 3
-#define REVISION 0
-
-#define ERR_CHECK(exp, err) if (!(exp)) { return err; }
-#define CLEANUPonERR(func) if ((err = func) != M4NO_ERROR) goto cleanup
-
-#define max(a,b) (((a) > (b)) ? (a) : (b))
-
-/***************/
-/*Static blocks*/
-/***************/
-
-/*CommonBlocks*/
-
-const M4OSA_UChar Default_ftyp [] =
-{
- 0x00, 0x00, 0x00, 0x18, 'f', 't', 'y', 'p', '3', 'g', 'p', '7', 0x00, 0x00,
- 0x03, 0x00, '3', 'g', 'p', '7', 'i', 's', 'o', 'm'
-};
-
-const M4OSA_UChar CommonBlock2 [] =
-{
- 'm', 'd', 'a', 't'
-};
-
-const M4OSA_UChar CommonBlock3 [] =
-{
- 'm', 'o', 'o', 'v', 0x00, 0x00, 0x00, 0x6C, 'm', 'v', 'h', 'd', 0x00,
- 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock4 [] =
-{
- 0x00, 0x00, 0x03, 0xE8
-};
-
-const M4OSA_UChar CommonBlock5 [] =
-{
- 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03
-};
-
-const M4OSA_UChar CommonBlock6 [] =
-{
- 't', 'r', 'a', 'k', 0x00, 0x00, 0x00, 0x5C, 't', 'k', 'h', 'd', 0x00,
- 0x00, 0x00, 0x01
-};
-
-const M4OSA_UChar CommonBlock7 [] =
-{
- 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock7bis [] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock8 [] =
-{
- 'm', 'd', 'i', 'a', 0x00, 0x00, 0x00, 0x20, 'm', 'd', 'h', 'd', 0x00,
- 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock9 [] =
-{
- 0x55, 0xC4, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock10 [] =
-{
- 'm', 'i', 'n', 'f', 0x00, 0x00, 0x00, 0x24, 'd', 'i', 'n', 'f', 0x00,
- 0x00, 0x00, 0x1C, 'd', 'r', 'e', 'f', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x01, 0x00, 0x00, 0x00, 0x0C, 'u', 'r', 'l', ' ', 0x00, 0x00, 0x00,
- 0x01
-};
-
-const M4OSA_UChar CommonBlock11 [] =
-{
- 's', 't', 'b', 'l'
-};
-
-const M4OSA_UChar CommonBlock12 [] =
-{
- 's', 't', 't', 's', 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar SampleDescriptionHeader [] =
-{
- 's', 't', 's', 'd', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01
-};
-
-const M4OSA_UChar SampleDescriptionEntryStart [] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock15 [] =
-{
- 's', 't', 's', 'z', 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock16 [] =
-{
- 's', 't', 's', 'c', 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar CommonBlock17 [] =
-{
- 's', 't', 'c', 'o', 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar BlockSignatureSkipHeader [] =
-{
- 0x00, 0x00, 0x00, 0x5E, 's', 'k', 'i', 'p'
-};
-/* due to current limitations, size must be 16 */
-const M4OSA_UChar BlockSignatureSkipDefaultEmbeddedString [] =
-{
- 'N', 'X', 'P', 'S', 'W', ' ', 'C', 'A', 'M', 'C', 'O', 'R', 'D', 'E',
- 'R', ' '
-};
-/* follows the version (like " 3.0.2"), then " -- " */
-/* due to current limitations, size must be 60 */
-const M4OSA_UChar BlockSignatureSkipDefaultIntegrationTag [] =
-{
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/*VideoBlocks*/
-/* 320*240, now no longer hardcoded */
-/* const M4OSA_UChar VideoBlock1[] =
- { 0x01, 0x40, 0x00, 0x00, 0x00, 0xF0, 0x00, 0x00 }; */
-const M4OSA_UChar VideoBlock1_1 [] =
-{
- 0x00, 0x00, 0x00, 0x21, 'h', 'd', 'l', 'r', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 'v', 'i', 'd', 'e', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar SampleDescriptionEntryVideoBoilerplate1 [] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar SampleDescriptionEntryVideoBoilerplate2 [] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0xFF, 0xFF
-};
-
-const M4OSA_UChar VideoBlock4 [] =
-{
- 's', 't', 's', 's', 0x00, 0x00, 0x00, 0x00
-}; /*STSS*/
-
-const M4OSA_UChar VideoBlock5 [] =
-{
- 0x00, 0x00, 0x00, 0x14, 'v', 'm', 'h', 'd', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar VideoResolutions [] =
-{
- 0x00, 0x48, 0x00, 0x00, 0x00, 0x48, 0x00, 0x00
-};
-
-/*Mp4vBlocks*/
-const M4OSA_UChar Mp4vBlock1 [] =
-{
- 'm', 'p', '4', 'v'
-};
-
-const M4OSA_UChar Mp4vBlock3 [] =
-{
- 0x20, 0x11
-};
-
-/*H263Blocks*/
-const M4OSA_UChar H263Block1 [] =
-{
- 's', '2', '6', '3'
-};
-
-const M4OSA_UChar H263Block2 [] =
-{
- 0x00, 0x00, 0x00, 0x0F, 'd', '2', '6', '3'
-};
-
-const M4OSA_UChar H263Block2_bitr [] =
-{
- 0x00, 0x00, 0x00, 0x1F, 'd', '2', '6', '3'
-};
-
-const M4OSA_UChar H263Block3 [] =
-{
- 'P', 'H', 'L', 'P', 0x00, 0x0A, 0x00
-};
-
-const M4OSA_UChar H263Block4 [] =
-{
- 0x00, 0x00, 0x00, 0x10, 'b', 'i', 't', 'r'
-};
-
-/*H264Blocks*/
-const M4OSA_UChar H264Block1 [] =
-{
- 'a', 'v', 'c', '1'
-};
-
-/* Store the avcC field, the version (=1),
- the profile (=66), the compatibility (=0), */
-
-/* the level (=10),111111 + NAL field Size (= 4 - 1),
- 111 + number of PPS (=1) */
-
-const M4OSA_UChar H264Block2 [] =
-{
- // Remove the hardcoded DSI values of H264Block2
- 'a' , 'v' , 'c' , 'C'
-};
-
-/*AMRBlocks*/
-const M4OSA_UChar AMRBlock1 [] =
-{
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar AMRBlock1_1 [] =
-{
- 0x00, 0x00, 0x00, 0x21, 'h', 'd', 'l', 'r', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 's', 'o', 'u', 'n', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar AudioSampleDescEntryBoilerplate [] =
-{
- 0x00, 0x02, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00
-};
-
-const M4OSA_UChar AMRDSIHeader [] =
-{
- 0x00, 0x00, 0x00, 0x11, 'd', 'a', 'm', 'r'
-};
-
-const M4OSA_UChar AMRDefaultDSI [] =
-{
- 'P', 'H', 'L', 'P', 0x00, 0x00, 0x80, 0x00, 0x01
-};
-
-const M4OSA_UChar AMRBlock4 [] =
-{
- 0x00, 0x00, 0x00, 0x10, 's', 'm', 'h', 'd', 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00
-};
-
-/*AMR8Blocks*/
-const M4OSA_UChar AMR8Block1 [] =
-{
- 's', 'a', 'm', 'r'
-};
-
-/*AMR16Blocks*/
-/*const M4OSA_UChar AMR16Block1[] = { 's', 'a', 'w', 'b'};*/
-
-/*AACBlocks*/
-const M4OSA_UChar AACBlock1 [] =
-{
- 'm', 'p', '4', 'a'
-};
-
-const M4OSA_UChar AACBlock2 [] =
-{
- 0x40, 0x15
-};
-
-/*MPEGConfigBlocks (AAC & MP4V)*/
-const M4OSA_UChar MPEGConfigBlock0 [] =
-{
- 'e', 's', 'd', 's', 0x00, 0x00, 0x00, 0x00, 0x03
-};
-
-const M4OSA_UChar MPEGConfigBlock1 [] =
-{
- 0x00, 0x00, 0x00, 0x04
-};
-
-const M4OSA_UChar MPEGConfigBlock2 [] = { 0x05 };
-const M4OSA_UChar MPEGConfigBlock3 [] =
-{
- 0x06, 0x01, 0x02
-};
-
-/*EVRCBlocks*/
-const M4OSA_UChar EVRCBlock3_1 [] =
-{
- 0x00, 0x00, 0x00, 0x0E, 'd', 'e', 'v', 'c'
-};
-
-const M4OSA_UChar EVRCBlock3_2 [] =
-{
- 'P', 'H', 'L', 'P', 0x00, 0x00
-};
-
-/*EVRC8Blocks*/
-const M4OSA_UChar EVRC8Block1 [] =
-{
- 's', 'e', 'v', 'c'
-};
-
-/***********/
-/* Methods */
-/***********/
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_getVersion(M4OSA_UInt8 *major, M4OSA_UInt8 *minor,
- M4OSA_UInt8 *revision )
-/*******************************************************************************/
-{
- ERR_CHECK(M4OSA_NULL != major, M4ERR_PARAMETER);
- ERR_CHECK(M4OSA_NULL != minor, M4ERR_PARAMETER);
- ERR_CHECK(M4OSA_NULL != revision, M4ERR_PARAMETER);
-
- *major = MAJOR_VERSION;
- *minor = MINOR_VERSION;
- *revision = REVISION;
-
- return M4NO_ERROR;
-}
-
-static M4OSA_UInt32 M4MP4W_STTS_ALLOC_SIZE;
-static M4OSA_UInt32 M4MP4W_STSZ_ALLOC_SIZE;
-static M4OSA_UInt32 M4MP4W_STSS_ALLOC_SIZE;
-static M4OSA_UInt32 M4MP4W_CHUNK_ALLOC_NB;
-static M4OSA_UInt32 M4MP4W_STTS_AUDIO_ALLOC_SIZE;
-static M4OSA_UInt32 M4MP4W_STSZ_AUDIO_ALLOC_SIZE;
-static M4OSA_UInt32 M4MP4W_CHUNK_AUDIO_ALLOC_NB;
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-/* stsc[ ] table is splitted at 12 bits */
-#define M4MP4W_VIDEO_MAX_AU_PER_CHUNK 4095 /* 0=notused */
-
-#else
-#define M4MP4W_VIDEO_MAX_AU_PER_CHUNK 10 /* 0=notused */
-
-#endif
-
-#endif
-
-/*******************************************************************************/
-
-M4OSA_ERR M4MP4W_initializeAllocationParameters(M4MP4W_Mp4FileData *Ptr )
-/*******************************************************************************/
-{
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4OSA_UInt32 maxMemory, vesMemory;
- M4OSA_UInt32 nbVideoFrames, nbAudioFrames;
- M4OSA_UInt32 averageVideoChunk;
-
- /*-----------*/
- /* NB_FRAMES */
- /*-----------*/
-
- /* magical formula : memory = vesMemory + 12 * framerate * duration */
-
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-
- vesMemory = 0x32000; /* 200 kB */
-
-#else
-
- vesMemory = 0x3E800; /* 250 kB */
-
-#endif
-
-#define VIDEO_POOL_MEMORY 1000000
-
- maxMemory = VIDEO_POOL_MEMORY;
-
- if (maxMemory < vesMemory) {
- return M4ERR_ALLOC;
- }
-
- nbVideoFrames = ( maxMemory - vesMemory) / 12;
-
- M4OSA_TRACE1_1("M4MP4W: %d images max", nbVideoFrames);
-
- /* VIDEO */
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
- /* assume an average of 25 fpc : reference = 15 fps * 2s * 0.8 */
-
- averageVideoChunk = 2500;
-
-#else
-
- if (M4MP4W_VIDEO_MAX_AU_PER_CHUNK > 0)
- {
- averageVideoChunk = 100 * M4MP4W_VIDEO_MAX_AU_PER_CHUNK - 20
- * (M4MP4W_VIDEO_MAX_AU_PER_CHUNK - 1); /* margin 20% */
- }
- else
- {
- /* assume an average of 50 fpc */
- averageVideoChunk = 5000;
- }
-
-#endif
-
- M4MP4W_STTS_ALLOC_SIZE = nbVideoFrames * sizeof(M4OSA_UInt32);
- M4MP4W_STSZ_ALLOC_SIZE = nbVideoFrames * sizeof(M4OSA_UInt16);
- M4MP4W_STSS_ALLOC_SIZE = nbVideoFrames * sizeof(
- M4OSA_UInt32); /* very conservative (all images are intra) */
-
- M4MP4W_CHUNK_ALLOC_NB = ( nbVideoFrames * 100) / averageVideoChunk + 1;
-
- /* AUDIO */
-
- nbAudioFrames = nbVideoFrames;
- /* audio is 5 fps, which is the smallest framerate for video */
-
- M4MP4W_STTS_AUDIO_ALLOC_SIZE = 100; /* compressed */
- M4MP4W_STSZ_AUDIO_ALLOC_SIZE = 100; /* compressed */
-
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-
- M4MP4W_CHUNK_AUDIO_ALLOC_NB = nbAudioFrames / 10 + 1;
-
-#else
-
- M4MP4W_CHUNK_AUDIO_ALLOC_NB = nbAudioFrames / 38 + 1;
-
-#endif
-
- return M4NO_ERROR;
-
-#else
-
- /* VIDEO 5 min at 25 fps null-enc */
-
- M4MP4W_STTS_ALLOC_SIZE = 20000;
- M4MP4W_STSZ_ALLOC_SIZE = 18000;
- M4MP4W_STSS_ALLOC_SIZE = 5000;
- M4MP4W_CHUNK_ALLOC_NB = 500;
-
- /* AUDIO 2 min aac+ null-enc */
-
- M4MP4W_STTS_AUDIO_ALLOC_SIZE = 32000;
- M4MP4W_STSZ_AUDIO_ALLOC_SIZE = 20000;
- M4MP4W_CHUNK_AUDIO_ALLOC_NB = 1000;
-
- return M4NO_ERROR;
-
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_openWrite(M4OSA_Context *contextPtr,
- void *outputFileDescriptor,
- M4OSA_FileWriterPointer *fileWriterFunction,
- void *tempFileDescriptor,
- M4OSA_FileReadPointer *fileReaderFunction )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
- M4MP4W_Mp4FileData *mMp4FileDataPtr = M4OSA_NULL;
-
- ERR_CHECK(M4OSA_NULL != contextPtr, M4ERR_PARAMETER);
- ERR_CHECK(M4OSA_NULL != outputFileDescriptor, M4ERR_PARAMETER);
- ERR_CHECK(M4OSA_NULL != fileWriterFunction, M4ERR_PARAMETER);
-#ifdef _M4MP4W_RESERVED_MOOV_DISK_SPACE
- /* Optional, feature won't be used if NULL */
-
- M4OSA_TRACE2_1("tempFileDescriptor = %p", tempFileDescriptor);
-
- if (M4OSA_NULL == tempFileDescriptor)
- {
- M4OSA_TRACE1_0(
- "tempFileDescriptor is NULL, RESERVED_MOOV_DISK_SPACE feature not used");
- }
-
-#else /* _M4MP4W_RESERVED_MOOV_DISK_SPACE */
- /* Not used : ERR_CHECK(M4OSA_NULL != tempFileDescriptor, M4ERR_PARAMETER); */
-#endif /* _M4MP4W_RESERVED_MOOV_DISK_SPACE */
- /* Not used : ERR_CHECK(M4OSA_NULL != fileReaderFunction, M4ERR_PARAMETER); */
-
- /* The context reuse mode was suppressed*/
-
- mMp4FileDataPtr =
- (M4MP4W_Mp4FileData *)M4OSA_32bitAlignedMalloc(sizeof(M4MP4W_Mp4FileData),
- M4MP4_WRITER, (M4OSA_Char *)"MP4 writer context");
- ERR_CHECK(mMp4FileDataPtr != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->url = outputFileDescriptor;
- mMp4FileDataPtr->audioTrackPtr = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr = M4OSA_NULL;
- mMp4FileDataPtr->MaxChunkSize = M4MP4W_DefaultMaxChunkSize; /*default */
- mMp4FileDataPtr->MaxAUSize = M4MP4W_DefaultMaxAuSize; /*default */
- mMp4FileDataPtr->InterleaveDur =
- M4MP4W_DefaultInterleaveDur; /*default = 0, i.e. not used*/
- mMp4FileDataPtr->MaxFileSize = 0; /*default = 0, i.e. not used*/
- mMp4FileDataPtr->camcoderVersion = 0; /*default is " 0.0.0"*/
- mMp4FileDataPtr->embeddedString =
- M4OSA_NULL; /*default is in BlockSignatureSkipDefaultEmbeddedString */
- mMp4FileDataPtr->integrationTag = M4OSA_NULL; /*default is 0 */
- mMp4FileDataPtr->MaxFileDuration = 0; /*default = 0, i.e. not used*/
-
- mMp4FileDataPtr->fileWriterFunctions = fileWriterFunction;
- mMp4FileDataPtr->hasAudio = M4OSA_FALSE;
- mMp4FileDataPtr->hasVideo = M4OSA_FALSE;
- mMp4FileDataPtr->state = M4MP4W_opened;
- mMp4FileDataPtr->duration = 0; /*i*/
- /*patch for integrationTag 174 -> 238 (+64)*/
- mMp4FileDataPtr->filesize =
- 238; /*initialization with constant part in ftyp+mdat+moov+skip*/
-
- mMp4FileDataPtr->estimateAudioSize = M4OSA_FALSE;
- mMp4FileDataPtr->audioMsChunkDur =
- 0; /*set and used only when estimateAudioSize is true*/
- mMp4FileDataPtr->audioMsStopTime =
- 0; /*set and used only when estimateAudioSize is true*/
-
- mMp4FileDataPtr->fileWriterContext = M4OSA_NULL;
- /* + CRLV6775 -H.264 trimming */
- mMp4FileDataPtr->bMULPPSSPS = M4OSA_FALSE;
- /* - CRLV6775 -H.264 trimming */
-
-#ifndef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->absoluteCurrentPos =
- 32; /*init with ftyp + beginning of mdat size*/
-
-#endif
-
-#ifdef _M4MP4W_RESERVED_MOOV_DISK_SPACE
-
- mMp4FileDataPtr->safetyFileUrl = tempFileDescriptor;
- mMp4FileDataPtr->cleanSafetyFile =
- M4OSA_FALSE; /* No need to clean it just yet. */
-
-#endif /* _M4MP4W_RESERVED_MOOV_DISK_SPACE */
-
- /* ftyp atom */
-
- memset((void *) &mMp4FileDataPtr->ftyp,0,
- sizeof(mMp4FileDataPtr->ftyp));
-
- *contextPtr = mMp4FileDataPtr;
-
- M4MP4W_initializeAllocationParameters(mMp4FileDataPtr);
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_addStream(M4OSA_Context context,
- M4SYS_StreamDescription *streamDescPtr )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
-
- ERR_CHECK(M4OSA_NULL != context, M4ERR_PARAMETER);
-
- ERR_CHECK(( mMp4FileDataPtr->state == M4MP4W_opened)
- || (mMp4FileDataPtr->state == M4MP4W_ready), M4ERR_STATE);
- mMp4FileDataPtr->state = M4MP4W_ready;
-
- switch (streamDescPtr->streamType)
- {
- case M4SYS_kAMR:
- case M4SYS_kAAC:
- case M4SYS_kEVRC:
- /*Audio*/
- ERR_CHECK(streamDescPtr->streamID == AudioStreamID,
- M4ERR_PARAMETER);
-
- /*check if an audio track has already been added*/
- ERR_CHECK(mMp4FileDataPtr->hasAudio == M4OSA_FALSE,
- M4ERR_BAD_CONTEXT);
-
- /*check if alloc need to be done*/
- if (mMp4FileDataPtr->audioTrackPtr == M4OSA_NULL)
- {
- mMp4FileDataPtr->audioTrackPtr = (M4MP4W_AudioTrackData
- *)M4OSA_32bitAlignedMalloc(sizeof(M4MP4W_AudioTrackData),
- M4MP4_WRITER, (M4OSA_Char *)"M4MP4W_AudioTrackData");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr != M4OSA_NULL,
- M4ERR_ALLOC);
-
- /**
- * We must init these pointers in case an alloc bellow fails */
- mMp4FileDataPtr->audioTrackPtr->Chunk = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ = M4OSA_NULL;
- mMp4FileDataPtr->audioTrackPtr->DSI = M4OSA_NULL;
-
- /*now dynamic*/
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->audioTrackPtr->Chunk =
- (M4OSA_UChar ** )M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_AUDIO_ALLOC_NB
- * sizeof(M4OSA_UChar *),
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->Chunk");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
-
-#else
-
- mMp4FileDataPtr->audioTrackPtr->Chunk =
- (M4OSA_UChar ** )M4OSA_32bitAlignedMalloc(sizeof(M4OSA_UChar *),
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->Chunk");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
- mMp4FileDataPtr->audioTrackPtr->Chunk[0] = M4OSA_NULL;
-
- mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_AUDIO_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->chunkOffsetTable");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_STTS_AUDIO_ALLOC_SIZE,
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->TABLE_STTS");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->TABLE_STTS
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedSttsBlocks = 1;
-
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_AUDIO_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->chunkSizeTable");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkSizeTable
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_AUDIO_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->chunkSampleNbTable");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_AUDIO_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->chunkTimeMsTable");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
- mMp4FileDataPtr->audioTrackPtr->LastAllocatedChunk = 0;
- }
- mMp4FileDataPtr->hasAudio = M4OSA_TRUE;
- mMp4FileDataPtr->filesize += 402;
- mMp4FileDataPtr->audioTrackPtr->MaxChunkSize =
- mMp4FileDataPtr->MaxChunkSize; /* init value */
- mMp4FileDataPtr->audioTrackPtr->MaxAUSize =
- mMp4FileDataPtr->MaxAUSize;
- mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS = 0;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb = 0;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize = 0;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb = 1;
- mMp4FileDataPtr->audioTrackPtr->CommonData.timescale =
- streamDescPtr->timeScale;
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable[0] = 0; /*init*/
- mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable[0] = 0; /*init*/
- mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable[0] = 0; /*init*/
- mMp4FileDataPtr->audioTrackPtr->currentChunk =
- 0; /*1st chunk is Chunk[0]*/
- mMp4FileDataPtr->audioTrackPtr->currentPos = 0;
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->audioTrackPtr->currentStsc = 0;
-
-#endif
-
- mMp4FileDataPtr->audioTrackPtr->microState = M4MP4W_ready;
- mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedStszBlocks = 0;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ = M4OSA_NULL;
-
- mMp4FileDataPtr->audioTrackPtr->avgBitrate =
- streamDescPtr->averageBitrate;
- mMp4FileDataPtr->audioTrackPtr->maxBitrate =
- streamDescPtr->maxBitrate;
-
- if (streamDescPtr->streamType == M4SYS_kAMR)
- {
-
- mMp4FileDataPtr->audioTrackPtr->CommonData.trackType =
- M4SYS_kAMR;
- ERR_CHECK(streamDescPtr->timeScale == 8000, M4ERR_PARAMETER);
- mMp4FileDataPtr->audioTrackPtr->sampleDuration =
- 160; /*AMR8+timescale=8000 => sample duration 160 constant*/
-
- /*Use given DSI if passed, else use default value*/
- if (streamDescPtr->decoderSpecificInfoSize != 0)
- {
- /*amr DSI is 9 bytes long !*/
- mMp4FileDataPtr->audioTrackPtr->dsiSize =
- 9; /*always 9 for amr*/
- ERR_CHECK(streamDescPtr->decoderSpecificInfoSize == 9,
- M4ERR_PARAMETER);
- mMp4FileDataPtr->audioTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(9, M4MP4_WRITER,
- (M4OSA_Char *)"audioTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->DSI != M4OSA_NULL,
- M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->audioTrackPtr->DSI,
- (void *)streamDescPtr->decoderSpecificInfo,
- 9);
- }
- else
- {
- mMp4FileDataPtr->audioTrackPtr->DSI =
- M4OSA_NULL; /*default static block will be used*/
- mMp4FileDataPtr->audioTrackPtr->dsiSize =
- 0; /*but the actual static dsi is 9 bytes !*/
- }
- }
- else if (streamDescPtr->streamType == M4SYS_kEVRC)
- {
-
- mMp4FileDataPtr->audioTrackPtr->CommonData.trackType =
- M4SYS_kEVRC;
- ERR_CHECK(streamDescPtr->timeScale == 8000, M4ERR_PARAMETER);
- mMp4FileDataPtr->audioTrackPtr->sampleDuration =
- 160; /*EVRC+timescale=8000 => sample duration 160 constant*/
-
- /*Use given DSI if passed, else use default value*/
- if (streamDescPtr->decoderSpecificInfoSize != 0)
- {
- /*evrc DSI is 6 bytes long !*/
- mMp4FileDataPtr->audioTrackPtr->dsiSize =
- 6; /*always 6 for evrc*/
- ERR_CHECK(streamDescPtr->decoderSpecificInfoSize == 6,
- M4ERR_PARAMETER);
- mMp4FileDataPtr->audioTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(6, M4MP4_WRITER,
- (M4OSA_Char *)"audioTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->DSI != M4OSA_NULL,
- M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->audioTrackPtr->DSI,
- (void *)streamDescPtr->decoderSpecificInfo,
- 6);
- }
- else
- {
- mMp4FileDataPtr->audioTrackPtr->DSI =
- M4OSA_NULL; /*default static block will be used*/
- mMp4FileDataPtr->audioTrackPtr->dsiSize =
- 0; /*but the actual static dsi is 6 bytes !*/
- }
- }
- else /*M4SYS_kAAC*/
- {
- /*avg bitrate should be set*/
- ERR_CHECK(streamDescPtr->averageBitrate != -1, M4ERR_PARAMETER);
- ERR_CHECK(streamDescPtr->maxBitrate != -1, M4ERR_PARAMETER);
-
- mMp4FileDataPtr->audioTrackPtr->CommonData.trackType =
- M4SYS_kAAC;
- mMp4FileDataPtr->audioTrackPtr->sampleDuration =
- 0; /*don't know for aac, so set 0*/
-
- mMp4FileDataPtr->audioTrackPtr->dsiSize =
- (M4OSA_UInt8)streamDescPtr->decoderSpecificInfoSize;
-
- if (mMp4FileDataPtr->audioTrackPtr->dsiSize != 0)
- {
- mMp4FileDataPtr->audioTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(
- streamDescPtr->decoderSpecificInfoSize,
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->DSI != M4OSA_NULL,
- M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->audioTrackPtr->DSI,
- (void *)streamDescPtr->decoderSpecificInfo,
- streamDescPtr->decoderSpecificInfoSize);
- }
- else
- {
- /*no dsi: return bad parameter ?*/
- return M4ERR_PARAMETER;
- }
- }
-
- break;
-
- case (M4SYS_kMPEG_4):
- case (M4SYS_kH264):
- case (M4SYS_kH263):
- /*Video*/
- ERR_CHECK(streamDescPtr->streamID == VideoStreamID,
- M4ERR_PARAMETER);
-
- /*check if a video track has already been added*/
- ERR_CHECK(mMp4FileDataPtr->hasVideo == M4OSA_FALSE,
- M4ERR_BAD_CONTEXT);
-
- /*check if alloc need to be done*/
- if (mMp4FileDataPtr->videoTrackPtr == M4OSA_NULL)
- {
- mMp4FileDataPtr->videoTrackPtr = (M4MP4W_VideoTrackData
- *)M4OSA_32bitAlignedMalloc(sizeof(M4MP4W_VideoTrackData),
- M4MP4_WRITER, (M4OSA_Char *)"M4MP4W_VideoTrackData");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr != M4OSA_NULL,
- M4ERR_ALLOC);
-
- /**
- * We must init these pointers in case an alloc bellow fails */
- mMp4FileDataPtr->videoTrackPtr->Chunk = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSS = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->DSI = M4OSA_NULL;
-
- /*now dynamic*/
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->videoTrackPtr->Chunk =
- (M4OSA_UChar ** )M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_ALLOC_NB
- * sizeof(M4OSA_UChar *),
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->Chunk");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
-
-#else
- /*re-use the same chunk and flush it when full*/
-
- mMp4FileDataPtr->videoTrackPtr->Chunk =
- (M4OSA_UChar ** )M4OSA_32bitAlignedMalloc(sizeof(M4OSA_UChar *),
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->Chunk");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->Chunk[0] = M4OSA_NULL;
-
- mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->chunkOffsetTable");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->chunkSizeTable");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkSizeTable
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_ALLOC_NB
- * sizeof(M4OSA_UInt32),
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->chunkSampleNbTable");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable =
- (M4MP4W_Time32 *)M4OSA_32bitAlignedMalloc(M4MP4W_CHUNK_ALLOC_NB
- * sizeof(M4MP4W_Time32),
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->chunkTimeMsTable");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
- mMp4FileDataPtr->videoTrackPtr->LastAllocatedChunk = 0;
- /*tables are now dynamic*/
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_STTS_ALLOC_SIZE,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->TABLE_STTS");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->TABLE_STTS
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedSttsBlocks = 1;
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ =
- (M4OSA_UInt16 *)M4OSA_32bitAlignedMalloc(M4MP4W_STSZ_ALLOC_SIZE,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->TABLE_STSZ");
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_STSZ_ALLOC_SIZE,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->TABLE_STSZ");
-
-#endif
-
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStszBlocks = 1;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSS =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(M4MP4W_STSS_ALLOC_SIZE,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->TABLE_STSS");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->TABLE_STSS
- != M4OSA_NULL, M4ERR_ALLOC);
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStssBlocks = 1;
- }
- mMp4FileDataPtr->hasVideo = M4OSA_TRUE;
- mMp4FileDataPtr->filesize += 462;
- mMp4FileDataPtr->videoTrackPtr->width = M4MP4W_DefaultWidth;
- mMp4FileDataPtr->videoTrackPtr->height = M4MP4W_DefaultHeight;
- mMp4FileDataPtr->videoTrackPtr->MaxAUSize =
- mMp4FileDataPtr->MaxAUSize;
- mMp4FileDataPtr->videoTrackPtr->CommonData.trackType =
- streamDescPtr->streamType;
- mMp4FileDataPtr->videoTrackPtr->MaxChunkSize =
- mMp4FileDataPtr->MaxChunkSize; /* init value */
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->videoTrackPtr->MaxAUperChunk =
- M4MP4W_VIDEO_MAX_AU_PER_CHUNK;
-
-#endif
-
- ERR_CHECK(streamDescPtr->timeScale == 1000, M4ERR_PARAMETER);
- mMp4FileDataPtr->videoTrackPtr->CommonData.timescale = 1000;
- mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS = 0;
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb = 0;
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleSize = 0;
- mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb = 1;
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable[0] = 0; /*init*/
- mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable[0] = 0; /*init*/
- mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable[0] = 0; /*init*/
- mMp4FileDataPtr->videoTrackPtr->currentChunk =
- 0; /*1st chunk is Chunk[0]*/
- mMp4FileDataPtr->videoTrackPtr->currentPos = 0;
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->videoTrackPtr->currentStsc = 0;
-
-#endif
-
- mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb = 0;
- mMp4FileDataPtr->videoTrackPtr->microState = M4MP4W_ready;
-
- if (streamDescPtr->streamType == M4SYS_kH263)
- {
- if (( streamDescPtr->averageBitrate == -1)
- || (streamDescPtr->maxBitrate == -1))
- {
- /*the bitrate will not be written if the bitrate information
- is not fully set */
- mMp4FileDataPtr->videoTrackPtr->avgBitrate = -1;
- mMp4FileDataPtr->videoTrackPtr->maxBitrate = -1;
- }
- else
- {
- /*proprietary storage of h263 bitrate.
- Warning: not the actual bitrate (bit set to 1).*/
- mMp4FileDataPtr->videoTrackPtr->avgBitrate =
- streamDescPtr->averageBitrate;
- mMp4FileDataPtr->videoTrackPtr->maxBitrate =
- streamDescPtr->maxBitrate;
- }
-
- if (( 0 != streamDescPtr->decoderSpecificInfoSize)
- && (M4OSA_NULL != streamDescPtr->decoderSpecificInfo))
- {
- /*decoder specific info size is supposed to be always 7 bytes long */
- ERR_CHECK(streamDescPtr->decoderSpecificInfoSize == 7,
- M4ERR_PARAMETER);
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamDescPtr->decoderSpecificInfoSize;
- mMp4FileDataPtr->videoTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(
- streamDescPtr->decoderSpecificInfoSize,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI != M4OSA_NULL,
- M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->DSI,
- (void *)streamDescPtr->decoderSpecificInfo,
- streamDescPtr->decoderSpecificInfoSize);
- }
- else
- {
- /*use the default dsi*/
- mMp4FileDataPtr->videoTrackPtr->DSI = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->dsiSize = 0;
- }
- }
-
- if (streamDescPtr->streamType == M4SYS_kMPEG_4)
- {
- mMp4FileDataPtr->filesize += 22; /*extra bytes (from h263)*/
- /* allow DSI to be M4OSA_NULL, in which case the actual DSI will be
- set by setOption. */
- if (( 0 == streamDescPtr->decoderSpecificInfoSize)
- || (M4OSA_NULL == streamDescPtr->decoderSpecificInfo))
- {
- mMp4FileDataPtr->videoTrackPtr->DSI = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->dsiSize = 0;
- }
- else
- {
- /*MP4V specific*/
- /*decoder specific info size is supposed to be always <
- 105 so that ESD size can be coded with 1 byte*/
- /*(this should not be restrictive because dsi is always shorter !)*/
- ERR_CHECK(streamDescPtr->decoderSpecificInfoSize < 105,
- M4ERR_PARAMETER);
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamDescPtr->decoderSpecificInfoSize;
- mMp4FileDataPtr->videoTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(
- streamDescPtr->decoderSpecificInfoSize,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI != M4OSA_NULL,
- M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->DSI,
- (void *)streamDescPtr->decoderSpecificInfo,
- streamDescPtr->decoderSpecificInfoSize);
- mMp4FileDataPtr->filesize +=
- streamDescPtr->decoderSpecificInfoSize;
- }
- /*avg bitrate should be set*/
- ERR_CHECK(streamDescPtr->averageBitrate != -1, M4ERR_PARAMETER);
- mMp4FileDataPtr->videoTrackPtr->avgBitrate =
- streamDescPtr->averageBitrate;
- mMp4FileDataPtr->videoTrackPtr->maxBitrate =
- streamDescPtr->averageBitrate;
- }
-
- if (streamDescPtr->streamType == M4SYS_kH264)
- {
- /* H264 specific information */
- mMp4FileDataPtr->videoTrackPtr->avgBitrate =
- streamDescPtr->averageBitrate;
- mMp4FileDataPtr->videoTrackPtr->maxBitrate =
- streamDescPtr->maxBitrate;
-
- if ((0 != streamDescPtr->decoderSpecificInfoSize)
- && (M4OSA_NULL != streamDescPtr->decoderSpecificInfo))
- {
- /* + H.264 trimming */
- if (M4OSA_TRUE == mMp4FileDataPtr->bMULPPSSPS)
- {
- M4OSA_UInt16 SPSLength, PPSLength;
- M4OSA_UInt16 *DSI;
- /* Store the DSI size */
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamDescPtr->decoderSpecificInfoSize
- - 24;
-
- /* Copy the DSI (SPS + PPS) */
- mMp4FileDataPtr->videoTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(
- streamDescPtr->decoderSpecificInfoSize,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI
- != M4OSA_NULL, M4ERR_ALLOC);
-
- DSI =
- (M4OSA_UInt16 *)streamDescPtr->decoderSpecificInfo;
- SPSLength = DSI[6];
- PPSLength = DSI[10];
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->DSI,
- (void *)((streamDescPtr->
- decoderSpecificInfo)+12), 2);
- memcpy(
- (void *)((mMp4FileDataPtr->videoTrackPtr->
- DSI)+2), (void *)((streamDescPtr->
- decoderSpecificInfo)+28), SPSLength);
-
- memcpy(
- (void *)((mMp4FileDataPtr->videoTrackPtr->
- DSI)+2 + SPSLength),
- (void *)((streamDescPtr->
- decoderSpecificInfo)+20), 2);
- memcpy(
- (void *)((mMp4FileDataPtr->videoTrackPtr->
- DSI)+4 + SPSLength),
- (void *)((streamDescPtr->
- decoderSpecificInfo)+28 + SPSLength),
- PPSLength);
- /* - H.264 trimming */
- }
- else
- {
- /* Store the DSI size */
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamDescPtr->decoderSpecificInfoSize;
-
- /* Copy the DSI (SPS + PPS) */
- mMp4FileDataPtr->videoTrackPtr->DSI =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(
- streamDescPtr->decoderSpecificInfoSize,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI
- != M4OSA_NULL, M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->DSI,
- (void *)streamDescPtr->
- decoderSpecificInfo,
- streamDescPtr->decoderSpecificInfoSize);
- }
- }
- else
- {
- /*use the default dsi*/
- mMp4FileDataPtr->videoTrackPtr->DSI = M4OSA_NULL;
- mMp4FileDataPtr->videoTrackPtr->dsiSize = 0;
- }
- }
- break;
-
- default:
- err = M4ERR_PARAMETER;
- }
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_startWriting( M4OSA_Context context )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
- M4OSA_UInt32 fileModeAccess = M4OSA_kFileWrite | M4OSA_kFileCreate;
- M4OSA_UInt32 i;
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- ERR_CHECK((mMp4FileDataPtr->state == M4MP4W_ready), M4ERR_STATE);
- mMp4FileDataPtr->state = M4MP4W_writing;
-
- /*audio microstate */
- /* if (mMp4FileDataPtr->audioTrackPtr != M4OSA_NULL)*/
- if (mMp4FileDataPtr->hasAudio)
- {
- ERR_CHECK((mMp4FileDataPtr->audioTrackPtr->microState == M4MP4W_ready),
- M4ERR_STATE);
- mMp4FileDataPtr->audioTrackPtr->microState = M4MP4W_writing;
-
- /* First audio chunk allocation */
- mMp4FileDataPtr->audioTrackPtr->Chunk[0] = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(mMp4FileDataPtr->audioTrackPtr->MaxChunkSize,
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->Chunk[0]");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->Chunk[0] != M4OSA_NULL,
- M4ERR_ALLOC);
- }
-
- /*video microstate*/
- /* if (mMp4FileDataPtr->videoTrackPtr != M4OSA_NULL)*/
- if (mMp4FileDataPtr->hasVideo)
- {
- ERR_CHECK((mMp4FileDataPtr->videoTrackPtr->microState == M4MP4W_ready),
- M4ERR_STATE);
- mMp4FileDataPtr->videoTrackPtr->microState = M4MP4W_writing;
-
- /* First video chunk allocation */
- mMp4FileDataPtr->videoTrackPtr->Chunk[0] = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(mMp4FileDataPtr->videoTrackPtr->MaxChunkSize,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->Chunk[0]");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->Chunk[0] != M4OSA_NULL,
- M4ERR_ALLOC);
- }
-
- if (mMp4FileDataPtr->estimateAudioSize == M4OSA_TRUE)
- {
- /*set audioMsChunkDur (duration in ms before a new chunk is created)
- for audio size estimation*/
- ERR_CHECK(mMp4FileDataPtr->hasVideo, M4ERR_BAD_CONTEXT);
- ERR_CHECK(mMp4FileDataPtr->hasAudio, M4ERR_BAD_CONTEXT);
-
- mMp4FileDataPtr->audioMsChunkDur =
- 20 * mMp4FileDataPtr->audioTrackPtr->MaxChunkSize
- / mMp4FileDataPtr->audioTrackPtr->MaxAUSize;
-
- if (( mMp4FileDataPtr->InterleaveDur != 0)
- && (mMp4FileDataPtr->InterleaveDur
- < 20 *mMp4FileDataPtr->audioTrackPtr->MaxChunkSize
- / mMp4FileDataPtr->audioTrackPtr->MaxAUSize))
- {
- mMp4FileDataPtr->audioMsChunkDur = mMp4FileDataPtr->InterleaveDur;
- }
- }
-
-#ifndef _M4MP4W_MOOV_FIRST
-
- /*open file in write binary mode*/
-
- err = mMp4FileDataPtr->fileWriterFunctions->openWrite(
- &mMp4FileDataPtr->fileWriterContext,
- mMp4FileDataPtr->url, fileModeAccess);
- ERR_CHECK((M4NO_ERROR == err), err);
-
- /*ftyp atom*/
- if (mMp4FileDataPtr->ftyp.major_brand != 0)
- {
- /* Put customized ftyp box */
- err =
- M4MP4W_putBE32(16 + (mMp4FileDataPtr->ftyp.nbCompatibleBrands * 4),
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
- err = M4MP4W_putBE32(M4MPAC_FTYP_TAG,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
- err = M4MP4W_putBE32(mMp4FileDataPtr->ftyp.major_brand,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
- err = M4MP4W_putBE32(mMp4FileDataPtr->ftyp.minor_version,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
-
- for ( i = 0; i < mMp4FileDataPtr->ftyp.nbCompatibleBrands; i++ )
- {
- err = M4MP4W_putBE32(mMp4FileDataPtr->ftyp.compatible_brands[i],
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
- }
- }
- else
- {
- /* Put default ftyp box */
- err = M4MP4W_putBlock(Default_ftyp, sizeof(Default_ftyp),
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
- }
-
- /*init mdat value with 0 but the right value is set just before the file is closed*/
- err = M4MP4W_putBE32(0, mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
- err = M4MP4W_putBlock(CommonBlock2, sizeof(CommonBlock2),
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
- ERR_CHECK((M4NO_ERROR == err), err);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
-#ifdef _M4MP4W_RESERVED_MOOV_DISK_SPACE
-
- if (0 != mMp4FileDataPtr->MaxFileSize
- && M4OSA_NULL != mMp4FileDataPtr->safetyFileUrl)
- {
- M4OSA_ERR err2 = M4NO_ERROR;
- M4OSA_Context safetyFileContext = M4OSA_NULL;
- M4OSA_UInt32 safetyFileSize = 0, addendum = 0;
- M4OSA_UChar dummyData[100]; /* To fill the safety file with */
-
- err =
- mMp4FileDataPtr->fileWriterFunctions->openWrite(&safetyFileContext,
- mMp4FileDataPtr->safetyFileUrl, fileModeAccess);
- ERR_CHECK((M4NO_ERROR == err), err);
-
- mMp4FileDataPtr->cleanSafetyFile = M4OSA_TRUE;
-
- /* 10% seems to be a reasonable worst case, but also provision for 1kb of moov overhead.*/
- safetyFileSize = 1000 + (mMp4FileDataPtr->MaxFileSize * 10 + 99) / 100;
-
- /* Here we add space to take into account the fact we have to flush any pending
- chunk in closeWrite, this space is the sum of the maximum chunk sizes, for each
- track. */
-
-#ifndef _M4MP4W_UNBUFFERED_VIDEO
-
- if (mMp4FileDataPtr->hasVideo)
- {
- safetyFileSize += mMp4FileDataPtr->videoTrackPtr->MaxChunkSize;
- }
-
-#endif
-
- if (mMp4FileDataPtr->hasAudio)
- {
- safetyFileSize += mMp4FileDataPtr->audioTrackPtr->MaxChunkSize;
- }
-
- memset((void *)dummyData, 0xCA,sizeof(dummyData)); /* For extra safety. */
-
- for ( i = 0;
- i < (safetyFileSize + sizeof(dummyData) - 1) / sizeof(dummyData);
- i++ )
- {
- err = mMp4FileDataPtr->fileWriterFunctions->writeData(
- safetyFileContext, dummyData, sizeof(dummyData));
-
- if (M4NO_ERROR != err)
- break;
- /* Don't return from the function yet, as we need to close the file first. */
- }
-
- /* I don't need to keep it open. */
- err2 =
- mMp4FileDataPtr->fileWriterFunctions->closeWrite(safetyFileContext);
-
- if (M4NO_ERROR != err)
- {
- return err;
- }
- else
- ERR_CHECK((M4NO_ERROR == err2), err2);
-
- M4OSA_TRACE1_0("Safety file correctly created");
- }
-#endif /* _M4MP4W_RESERVED_MOOV_DISK_SPACE */
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_newAudioChunk( M4OSA_Context context,
- M4OSA_UInt32 *leftSpaceInChunk )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- M4OSA_Double scale_audio;
-
-#ifndef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4OSA_UInt32 reallocNb;
-
-#endif
-
- /* video only */
-
- if (mMp4FileDataPtr->audioTrackPtr == M4OSA_NULL)
- return M4NO_ERROR;
-
- M4OSA_TRACE1_0(" M4MP4W_newAudioChunk - flush audio");
- M4OSA_TRACE1_2("current chunk = %d offset = 0x%x",
- mMp4FileDataPtr->audioTrackPtr->currentChunk,
- mMp4FileDataPtr->absoluteCurrentPos);
-
- scale_audio = 1000.0 / mMp4FileDataPtr->audioTrackPtr->CommonData.timescale;
-
-#ifndef _M4MP4W_MOOV_FIRST
- /*flush chunk*/
-
- err = M4MP4W_putBlock(mMp4FileDataPtr->audioTrackPtr->Chunk[0],
- mMp4FileDataPtr->audioTrackPtr->currentPos,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
-
- if (M4NO_ERROR != err)
- {
- M4OSA_FilePosition temp = mMp4FileDataPtr->absoluteCurrentPos;
- M4OSA_TRACE2_1(
- "M4MP4W_newAudioChunk: putBlock error when flushing chunk: %#X",
- err);
- /* Ouch, we got an error writing to the file, but we need to properly react so that the
- state is still consistent and we can properly close the file so that what has been
- recorded so far is not lost. Yay error recovery! */
-
- /* First, we do not know where we are in the file. Put us back at where we were before
- attempting to write the data. That way, we're consistent with the chunk state data. */
- err = mMp4FileDataPtr->fileWriterFunctions->seek(
- mMp4FileDataPtr->fileWriterContext,
- M4OSA_kFileSeekBeginning, &temp);
-
- M4OSA_TRACE2_3(
- "Backtracking to position 0x%08X, seek returned %d and position %08X",
- mMp4FileDataPtr->absoluteCurrentPos, err, temp);
-
- /* Then, do not update any info whatsoever in the writing state. This will have the
- consequence that it will be as if the chunk has not been flushed yet, and therefore
- it will be done as part of closeWrite (where there could be room to do so,
- if some emergency room is freed for that purpose). */
-
- /* And lastly (for here), return that we've reached the limit of available space. */
-
- return M4WAR_MP4W_OVERSIZE;
- }
-
- /*update chunk offset*/
- mMp4FileDataPtr->audioTrackPtr->
- chunkOffsetTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- mMp4FileDataPtr->absoluteCurrentPos;
-
- /*add chunk size to absoluteCurrentPos*/
- mMp4FileDataPtr->absoluteCurrentPos +=
- mMp4FileDataPtr->audioTrackPtr->currentPos;
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- /*update chunk info */
-
- mMp4FileDataPtr->audioTrackPtr->
- chunkSizeTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- mMp4FileDataPtr->audioTrackPtr->currentPos;
- mMp4FileDataPtr->audioTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS;
-
- mMp4FileDataPtr->audioTrackPtr->currentChunk += 1;
- /*if audio amount of data is not estimated*/
- if (mMp4FileDataPtr->estimateAudioSize == M4OSA_FALSE)
- mMp4FileDataPtr->filesize += 16;
-
- /*alloc new chunk*/
- /*only if not already allocated*/
- if (mMp4FileDataPtr->audioTrackPtr->currentChunk
- > mMp4FileDataPtr->audioTrackPtr->LastAllocatedChunk)
- {
- /*update LastAllocatedChunk ( -> = currentChunk)*/
- mMp4FileDataPtr->audioTrackPtr->LastAllocatedChunk += 1;
-
- /*max nb of chunk is now dynamic*/
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- if (mMp4FileDataPtr->audioTrackPtr->LastAllocatedChunk
- + 3 > M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- {
- M4OSA_TRACE1_0("M4MP4W_newAudioChunk : audio chunk table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#else
-
- if (((mMp4FileDataPtr->audioTrackPtr->LastAllocatedChunk)
- % M4MP4W_CHUNK_AUDIO_ALLOC_NB) == 0)
- {
- reallocNb = mMp4FileDataPtr->audioTrackPtr->LastAllocatedChunk
- + M4MP4W_CHUNK_AUDIO_ALLOC_NB;
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->audioTrackPtr->Chunk =
- (M4OSA_UChar ** )M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->Chunk,
- ( reallocNb - M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- * sizeof(M4OSA_UChar *),
- reallocNb * sizeof(M4OSA_UChar *));
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
-
-#else
-
- mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->
- chunkOffsetTable,
- ( reallocNb - M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- * sizeof(M4OSA_UInt32),
- reallocNb * sizeof(M4OSA_UInt32));
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->
- chunkSizeTable,
- ( reallocNb - M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- * sizeof(M4OSA_UInt32),
- reallocNb * sizeof(M4OSA_UInt32));
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkSizeTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
- mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable,
- ( reallocNb - M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- * sizeof(M4OSA_UInt32),
- reallocNb * sizeof(M4OSA_UInt32));
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
- mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable =
- (M4MP4W_Time32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->
- chunkTimeMsTable,
- ( reallocNb - M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- * sizeof(M4MP4W_Time32),
- reallocNb * sizeof(M4MP4W_Time32));
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable
- != M4OSA_NULL, M4ERR_ALLOC);
- }
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->audioTrackPtr->
- Chunk[mMp4FileDataPtr->audioTrackPtr->currentChunk] = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(mMp4FileDataPtr->audioTrackPtr->MaxChunkSize,
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->currentChunk");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->
- Chunk[mMp4FileDataPtr->audioTrackPtr->currentChunk]
- != M4OSA_NULL, M4ERR_ALLOC);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- }
-
- /*update leftSpaceInChunk, currentPos and currentChunkDur*/
- *leftSpaceInChunk = mMp4FileDataPtr->audioTrackPtr->MaxChunkSize;
- mMp4FileDataPtr->audioTrackPtr->currentPos = 0;
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
- /* check wether to use a new stsc or not */
-
- if (mMp4FileDataPtr->audioTrackPtr->currentStsc > 0)
- {
- if (( mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->
- currentStsc] & 0xFFF) != (mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->currentStsc
- - 1] & 0xFFF))
- mMp4FileDataPtr->audioTrackPtr->currentStsc += 1;
- }
- else
- mMp4FileDataPtr->audioTrackPtr->currentStsc += 1;
-
- /* max nb of chunk is now dynamic */
- if (mMp4FileDataPtr->audioTrackPtr->currentStsc
- + 3 > M4MP4W_CHUNK_AUDIO_ALLOC_NB)
- {
- M4OSA_TRACE1_0("M4MP4W_newAudioChunk : audio stsc table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
- /* set nb of samples in the new chunk to 0 */
- mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->currentStsc] =
- 0 + (mMp4FileDataPtr->audioTrackPtr->currentChunk << 12);
-
-#else
- /*set nb of samples in the new chunk to 0*/
-
- mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] = 0;
-
-#endif
-
- /*set time of the new chunk to lastCTS (for initialization, but updated further to the
- CTS of the last sample in the chunk)*/
-
- mMp4FileDataPtr->audioTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- (M4OSA_UInt32)(mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS
- * scale_audio);
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_newVideoChunk( M4OSA_Context context,
- M4OSA_UInt32 *leftSpaceInChunk )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- M4OSA_Double scale_video;
-
-#ifndef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4OSA_UInt32 reallocNb;
-
-#endif
-
- /* audio only */
-
- if (mMp4FileDataPtr->videoTrackPtr == M4OSA_NULL)
- return M4NO_ERROR;
-
- M4OSA_TRACE1_0("M4MP4W_newVideoChunk - flush video");
- M4OSA_TRACE1_2("current chunk = %d offset = 0x%x",
- mMp4FileDataPtr->videoTrackPtr->currentChunk,
- mMp4FileDataPtr->absoluteCurrentPos);
-
- scale_video = 1000.0 / mMp4FileDataPtr->videoTrackPtr->CommonData.timescale;
-
-#ifndef _M4MP4W_MOOV_FIRST
-
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
- /* samples are already written to file */
-#else
- /*flush chunk*/
-
- err = M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->Chunk[0],
- mMp4FileDataPtr->videoTrackPtr->currentPos,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
-
- if (M4NO_ERROR != err)
- {
- M4OSA_FilePosition temp = mMp4FileDataPtr->absoluteCurrentPos;
- M4OSA_TRACE2_1(
- "M4MP4W_newVideoChunk: putBlock error when flushing chunk: %#X",
- err);
- /* Ouch, we got an error writing to the file, but we need to properly react so that the
- state is still consistent and we can properly close the file so that what has been
- recorded so far is not lost. Yay error recovery! */
-
- /* First, we do not know where we are in the file. Put us back at where we were before
- attempting to write the data. That way, we're consistent with the chunk state data. */
- err = mMp4FileDataPtr->fileWriterFunctions->seek(
- mMp4FileDataPtr->fileWriterContext,
- M4OSA_kFileSeekBeginning, &temp);
-
- M4OSA_TRACE2_3(
- "Backtracking to position 0x%08X, seek returned %d and position %08X",
- mMp4FileDataPtr->absoluteCurrentPos, err, temp);
- /* Then, do not update any info whatsoever in the writing state. This will have the
- consequence that it will be as if the chunk has not been flushed yet, and therefore it
- will be done as part of closeWrite (where there could be room to do so, if some
- emergency room is freed for that purpose). */
-
- /* And lastly (for here), return that we've reached the limit of available space.
- We don't care about the error originally returned by putBlock. */
-
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#endif
-
- /*update chunk offset*/
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkOffsetTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- mMp4FileDataPtr->absoluteCurrentPos;
-
- /*add chunk size to absoluteCurrentPos*/
- mMp4FileDataPtr->absoluteCurrentPos +=
- mMp4FileDataPtr->videoTrackPtr->currentPos;
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- /*update chunk info before to go for a new one*/
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkSizeTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- mMp4FileDataPtr->videoTrackPtr->currentPos;
- mMp4FileDataPtr->videoTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- (M4OSA_UInt32)(mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS
- * scale_video);
-
- mMp4FileDataPtr->videoTrackPtr->currentChunk += 1;
- mMp4FileDataPtr->filesize += 16;
-
- /*alloc new chunk*/
- /*only if not already allocated*/
- if (mMp4FileDataPtr->videoTrackPtr->currentChunk
- > mMp4FileDataPtr->videoTrackPtr->LastAllocatedChunk)
- {
- /*update LastAllocatedChunk ( -> = currentChunk)*/
- mMp4FileDataPtr->videoTrackPtr->LastAllocatedChunk += 1;
-
- /*max nb of chunk is now dynamic*/
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- if ( mMp4FileDataPtr->videoTrackPtr->LastAllocatedChunk
- + 3 > M4MP4W_CHUNK_ALLOC_NB)
- {
- M4OSA_TRACE1_0("M4MP4W_newVideoChunk : video chunk table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#else
-
- if (((mMp4FileDataPtr->videoTrackPtr->LastAllocatedChunk)
- % M4MP4W_CHUNK_ALLOC_NB) == 0)
- {
- reallocNb = mMp4FileDataPtr->videoTrackPtr->LastAllocatedChunk
- + M4MP4W_CHUNK_ALLOC_NB;
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->videoTrackPtr->Chunk =
- (M4OSA_UChar ** )M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->Chunk,
- ( reallocNb
- - M4MP4W_CHUNK_ALLOC_NB) * sizeof(M4OSA_UChar *),
- reallocNb * sizeof(M4OSA_UChar *));
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->Chunk != M4OSA_NULL,
- M4ERR_ALLOC);
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->
- chunkOffsetTable, ( reallocNb - M4MP4W_CHUNK_ALLOC_NB)
- * sizeof(M4OSA_UInt32),
- reallocNb * sizeof(M4OSA_UInt32));
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->
- chunkSizeTable, ( reallocNb - M4MP4W_CHUNK_ALLOC_NB)
- * sizeof(M4OSA_UInt32),
- reallocNb * sizeof(M4OSA_UInt32));
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkSizeTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
- mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable, ( reallocNb - M4MP4W_CHUNK_ALLOC_NB)
- * sizeof(M4OSA_UInt32),
- reallocNb * sizeof(M4OSA_UInt32));
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable
- != M4OSA_NULL, M4ERR_ALLOC);
-
- mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable =
- (M4MP4W_Time32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->
- chunkTimeMsTable, ( reallocNb
- - M4MP4W_CHUNK_ALLOC_NB) * sizeof(M4MP4W_Time32),
- reallocNb * sizeof(M4MP4W_Time32));
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable
- != M4OSA_NULL, M4ERR_ALLOC);
- }
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- mMp4FileDataPtr->videoTrackPtr->
- Chunk[mMp4FileDataPtr->videoTrackPtr->currentChunk] = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(mMp4FileDataPtr->videoTrackPtr->MaxChunkSize,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->MaxChunkSize");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->
- Chunk[mMp4FileDataPtr->videoTrackPtr->currentChunk]
- != M4OSA_NULL, M4ERR_ALLOC);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- }
-
- /*update leftSpaceInChunk, currentPos and currentChunkDur*/
- *leftSpaceInChunk = mMp4FileDataPtr->videoTrackPtr->MaxChunkSize;
- mMp4FileDataPtr->videoTrackPtr->currentPos = 0;
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
- /* check wether to use a new stsc or not */
-
- if (mMp4FileDataPtr->videoTrackPtr->currentStsc > 0)
- {
- if ((mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->
- currentStsc] & 0xFFF) != (mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->currentStsc
- - 1] & 0xFFF))
- mMp4FileDataPtr->videoTrackPtr->currentStsc += 1;
- }
- else
- mMp4FileDataPtr->videoTrackPtr->currentStsc += 1;
-
- /* max nb of chunk is now dynamic */
- if (mMp4FileDataPtr->videoTrackPtr->currentStsc
- + 3 > M4MP4W_CHUNK_ALLOC_NB)
- {
- M4OSA_TRACE1_0("M4MP4W_newVideoChunk : video stsc table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
- /* set nb of samples in the new chunk to 0 */
- mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->currentStsc] =
- 0 + (mMp4FileDataPtr->videoTrackPtr->currentChunk << 12);
-
-#else
- /*set nb of samples in the new chunk to 0*/
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] = 0;
-
-#endif
-
- /*set time of the new chunk to lastCTS (for initialization, but updated further to the
- CTS of the last sample in the chunk)*/
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- (M4OSA_UInt32)(mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS
- * scale_video);
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_startAU( M4OSA_Context context, M4SYS_StreamID streamID,
- M4SYS_AccessUnit *auPtr )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
-
- M4OSA_UInt32 leftSpaceInChunk;
- M4MP4W_Time32 chunkDurMs;
-
- M4OSA_Double scale_audio;
- M4OSA_Double scale_video;
-
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
- ERR_CHECK(auPtr != M4OSA_NULL, M4ERR_PARAMETER);
-
- M4OSA_TRACE2_0("----- M4MP4W_startAU -----");
-
- /*check macro state*/
- ERR_CHECK((mMp4FileDataPtr->state == M4MP4W_writing), M4ERR_STATE);
-
- if (streamID == AudioStreamID) /*audio stream*/
- {
- M4OSA_TRACE2_0("M4MP4W_startAU -> audio");
-
- scale_audio =
- 1000.0 / mMp4FileDataPtr->audioTrackPtr->CommonData.timescale;
-
- /*audio microstate*/
- ERR_CHECK((mMp4FileDataPtr->audioTrackPtr->microState
- == M4MP4W_writing), M4ERR_STATE);
- mMp4FileDataPtr->audioTrackPtr->microState = M4MP4W_writing_startAU;
-
- leftSpaceInChunk = mMp4FileDataPtr->audioTrackPtr->MaxChunkSize
- - mMp4FileDataPtr->audioTrackPtr->currentPos;
-
- M4OSA_TRACE2_2("audio %d %d",
- mMp4FileDataPtr->audioTrackPtr->currentPos, leftSpaceInChunk);
-
- chunkDurMs =
- (M4OSA_UInt32)(( mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS
- * scale_audio) - mMp4FileDataPtr->audioTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->audioTrackPtr->
- currentChunk]);
-
- if ((leftSpaceInChunk < mMp4FileDataPtr->audioTrackPtr->MaxAUSize)
- || (( mMp4FileDataPtr->InterleaveDur != 0)
- && (chunkDurMs >= mMp4FileDataPtr->InterleaveDur)))
- {
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
- /* only if there is at least 1 video sample in the chunk */
-
- if ((mMp4FileDataPtr->videoTrackPtr != M4OSA_NULL)
- && (mMp4FileDataPtr->videoTrackPtr->currentPos > 0))
- {
- /* close the opened video chunk before creating a new audio one */
- err = M4MP4W_newVideoChunk(context, &leftSpaceInChunk);
-
- if (err != M4NO_ERROR)
- return err;
- }
-
-#endif
- /* not enough space in current chunk: create a new one */
-
- err = M4MP4W_newAudioChunk(context, &leftSpaceInChunk);
-
- if (err != M4NO_ERROR)
- return err;
- }
-
- auPtr->size = leftSpaceInChunk;
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- auPtr->dataAddress = (M4OSA_MemAddr32)(mMp4FileDataPtr->audioTrackPtr->
- Chunk[mMp4FileDataPtr->audioTrackPtr->currentChunk]
- + mMp4FileDataPtr->audioTrackPtr->currentPos);
-
-#else
-
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->audioTrackPtr->Chunk[0]
- + mMp4FileDataPtr->audioTrackPtr->currentPos);
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- }
- else if (streamID == VideoStreamID) /*video stream*/
- {
- M4OSA_TRACE2_0("M4MP4W_startAU -> video");
-
- scale_video =
- 1000.0 / mMp4FileDataPtr->videoTrackPtr->CommonData.timescale;
-
- /*video microstate*/
- ERR_CHECK((mMp4FileDataPtr->videoTrackPtr->microState
- == M4MP4W_writing), M4ERR_STATE);
- mMp4FileDataPtr->videoTrackPtr->microState = M4MP4W_writing_startAU;
-
- leftSpaceInChunk = mMp4FileDataPtr->videoTrackPtr->MaxChunkSize
- - mMp4FileDataPtr->videoTrackPtr->currentPos;
-
- chunkDurMs =
- (M4OSA_UInt32)(( mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS
- * scale_video) - mMp4FileDataPtr->videoTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->videoTrackPtr->
- currentChunk]);
-
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-
- leftSpaceInChunk = mMp4FileDataPtr->videoTrackPtr->MaxChunkSize;
-
-#endif
-
- M4OSA_TRACE2_2("video %d %d",
- mMp4FileDataPtr->videoTrackPtr->currentPos, leftSpaceInChunk);
-
- if (( leftSpaceInChunk < mMp4FileDataPtr->videoTrackPtr->MaxAUSize)
- || (( mMp4FileDataPtr->InterleaveDur != 0)
- && (chunkDurMs >= mMp4FileDataPtr->InterleaveDur))
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- || (( mMp4FileDataPtr->videoTrackPtr->MaxAUperChunk != 0)
- && (( mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->
- currentStsc] & 0xFFF)
- == mMp4FileDataPtr->videoTrackPtr->MaxAUperChunk))
-
-#endif
-
- )
- {
- /*not enough space in current chunk: create a new one*/
- err = M4MP4W_newVideoChunk(context, &leftSpaceInChunk);
-
- if (err != M4NO_ERROR)
- return err;
- }
-
- M4OSA_TRACE2_3("startAU: size 0x%x pos 0x%x chunk %u", auPtr->size,
- mMp4FileDataPtr->videoTrackPtr->currentPos,
- mMp4FileDataPtr->videoTrackPtr->currentChunk);
-
- M4OSA_TRACE3_1("adr = 0x%p", auPtr->dataAddress);
-
- if (auPtr->dataAddress)
- {
- M4OSA_TRACE3_3(" data = %08X %08X %08X", auPtr->dataAddress[0],
- auPtr->dataAddress[1], auPtr->dataAddress[2]);
- }
-
- auPtr->size = leftSpaceInChunk;
-#ifdef _M4MP4W_MOOV_FIRST
-
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH264)
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->videoTrackPtr->
- Chunk[mMp4FileDataPtr->videoTrackPtr->currentChunk]
- + mMp4FileDataPtr->videoTrackPtr->currentPos + 4);
- else
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->videoTrackPtr->
- Chunk[mMp4FileDataPtr->videoTrackPtr->currentChunk]
- + mMp4FileDataPtr->videoTrackPtr->currentPos);
-
-#else
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH264)
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->videoTrackPtr->Chunk[0] + 4);
- else
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->videoTrackPtr->Chunk[0]);
-
-#else
-
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH264)
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->videoTrackPtr->Chunk[0]
- + mMp4FileDataPtr->videoTrackPtr->currentPos
- + 4); /* In H264, we must start by the length of the NALU, coded in 4 bytes */
- else
- auPtr->dataAddress =
- (M4OSA_MemAddr32)(mMp4FileDataPtr->videoTrackPtr->Chunk[0]
- + mMp4FileDataPtr->videoTrackPtr->currentPos);
-
-#endif /*_M4MP4W_UNBUFFERED_VIDEO*/
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- }
- else
- return M4ERR_BAD_STREAM_ID;
-
- M4OSA_TRACE1_3("M4MPW_startAU: start address:%p, size:%lu, stream:%d",
- auPtr->dataAddress, auPtr->size, streamID);
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_processAU( M4OSA_Context context, M4SYS_StreamID streamID,
- M4SYS_AccessUnit *auPtr )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
- M4MP4W_Time32 delta;
- M4MP4W_Time32 lastSampleDur;
- M4OSA_UInt32 i;
- /*expectedSize is the max filesize to forecast when adding a new AU:*/
- M4OSA_UInt32 expectedSize =
- 32; /*initialized with an estimation of the max metadata space needed for an AU.*/
- M4OSA_Double scale_audio = 0.0;
- M4OSA_Double scale_video = 0.0;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- /*check macro state*/
- ERR_CHECK((mMp4FileDataPtr->state == M4MP4W_writing), M4ERR_STATE);
-
- M4OSA_TRACE2_0("M4MP4W_processAU");
-
- if (streamID == AudioStreamID)
- scale_audio =
- 1000.0 / mMp4FileDataPtr->audioTrackPtr->CommonData.timescale;
-
- if (streamID == VideoStreamID)
- scale_video =
- 1000.0 / mMp4FileDataPtr->videoTrackPtr->CommonData.timescale;
-
- /* PL 27/10/2008: after the resurgence of the AAC 128 bug, I added a debug check that
- the encoded data didn't overflow the available space in the AU */
-
- switch( streamID )
- {
- case AudioStreamID:
- M4OSA_DEBUG_IF1(auPtr->size
- + mMp4FileDataPtr->audioTrackPtr->currentPos
- > mMp4FileDataPtr->audioTrackPtr->MaxChunkSize,
- M4ERR_CONTEXT_FAILED,
- "Uh oh. Buffer overflow in the writer. Abandon ship!");
- M4OSA_DEBUG_IF2(auPtr->size
- > mMp4FileDataPtr->audioTrackPtr->MaxAUSize,
- M4ERR_CONTEXT_FAILED,
- "Oops. An AU went over the declared Max AU size.\
- You might wish to investigate that.");
- break;
-
- case VideoStreamID:
- M4OSA_DEBUG_IF1(auPtr->size
- + mMp4FileDataPtr->videoTrackPtr->currentPos
- > mMp4FileDataPtr->videoTrackPtr->MaxChunkSize,
- M4ERR_CONTEXT_FAILED,
- "Uh oh. Buffer overflow in the writer. Abandon ship!");
- M4OSA_DEBUG_IF2(auPtr->size
- > mMp4FileDataPtr->videoTrackPtr->MaxAUSize,
- M4ERR_CONTEXT_FAILED,
- "Oops. An AU went over the declared Max AU size.\
- You might wish to investigate that.");
- break;
- }
-
- /*only if not in the case audio with estimateAudioSize
- (else, size already estimated at this point)*/
- if ((mMp4FileDataPtr->estimateAudioSize == M4OSA_FALSE)
- || (streamID == VideoStreamID))
- {
- /*check filesize if needed*/
- if (mMp4FileDataPtr->MaxFileSize != 0)
- {
- expectedSize += mMp4FileDataPtr->filesize + auPtr->size;
-
- if ((streamID == VideoStreamID)
- && (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH264))
- {
- expectedSize += 4;
- }
-
- if (expectedSize > mMp4FileDataPtr->MaxFileSize)
- {
- M4OSA_TRACE1_0("processAU : !! FILESIZE EXCEEDED !!");
-
- /* patch for autostop is MaxFileSize exceeded */
- M4OSA_TRACE1_0("M4MP4W_processAU : stop at targeted filesize");
- return M4WAR_MP4W_OVERSIZE;
- }
- }
- }
-
- /*case audioMsStopTime has already been set during video processing,
- and now check it for audio*/
- if ((mMp4FileDataPtr->estimateAudioSize == M4OSA_TRUE)
- && (streamID == AudioStreamID))
- {
- if (mMp4FileDataPtr->audioMsStopTime <= (auPtr->CTS *scale_audio))
- {
- /* bugfix: if a new chunk was just created, cancel it before to close */
- if ((mMp4FileDataPtr->audioTrackPtr->currentChunk != 0)
- && (mMp4FileDataPtr->audioTrackPtr->currentPos == 0))
- {
- mMp4FileDataPtr->audioTrackPtr->currentChunk--;
- }
- M4OSA_TRACE1_0("M4MP4W_processAU : audio stop time reached");
- return M4WAR_MP4W_OVERSIZE;
- }
- }
-
- if (streamID == AudioStreamID) /*audio stream*/
- {
- M4OSA_TRACE2_0("M4MP4W_processAU -> audio");
-
- /*audio microstate*/
- ERR_CHECK((mMp4FileDataPtr->audioTrackPtr->microState
- == M4MP4W_writing_startAU), M4ERR_STATE);
- mMp4FileDataPtr->audioTrackPtr->microState = M4MP4W_writing;
-
- mMp4FileDataPtr->audioTrackPtr->currentPos += auPtr->size;
- /* Warning: time conversion cast 64to32! */
- delta = (M4MP4W_Time32)auPtr->CTS
- - mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS;
-
- /* DEBUG stts entries which are equal to 0 */
- M4OSA_TRACE2_1("A_DELTA = %ld\n", delta);
-
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb
- == 0) /*test if first AU*/
- {
- /*set au size*/
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize = auPtr->size;
-
- /*sample duration is a priori constant in audio case, */
- /*but if an Au at least has different size, a stsz table will be created */
-
- /*mMp4FileDataPtr->audioTrackPtr->sampleDuration = delta; */
- /*TODO test sample duration? (should be 20ms in AMR8, 160 tics with timescale 8000) */
- }
- else
- {
- /*check if au size is constant (audio) */
- /*0 sample size means non constant size*/
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize != 0)
- {
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize
- != auPtr->size)
- {
- /*first AU with different size => non constant size => STSZ table needed*/
- /*computation of the nb of block of size M4MP4W_STSZ_ALLOC_SIZE to allocate*/
- mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedStszBlocks =
- 1 + mMp4FileDataPtr->audioTrackPtr->
- CommonData.sampleNb
- * 4 / M4MP4W_STSZ_AUDIO_ALLOC_SIZE;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ =
- (M4OSA_UInt32 *)M4OSA_32bitAlignedMalloc(
- mMp4FileDataPtr->audioTrackPtr->
- nbOfAllocatedStszBlocks
- * M4MP4W_STSZ_AUDIO_ALLOC_SIZE,
- M4MP4_WRITER, (M4OSA_Char *)"audioTrackPtr->TABLE_STSZ");
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ
- != M4OSA_NULL, M4ERR_ALLOC);
-
- for ( i = 0;
- i < mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- i++ )
- {
- mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ[i] =
- mMp4FileDataPtr->audioTrackPtr->
- CommonData.sampleSize;
- }
- mMp4FileDataPtr->audioTrackPtr->
- TABLE_STSZ[mMp4FileDataPtr->audioTrackPtr->
- CommonData.sampleNb] = auPtr->size;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize =
- 0; /*used as a flag in that case*/
- /*more bytes in the file in that case:*/
- if (mMp4FileDataPtr->estimateAudioSize == M4OSA_FALSE)
- mMp4FileDataPtr->filesize +=
- 4 * mMp4FileDataPtr->audioTrackPtr->
- CommonData.sampleNb;
- }
- }
- /*else table already exists*/
- else
- {
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- if (4 *(mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb + 3)
- >= mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedStszBlocks
- *M4MP4W_STSZ_AUDIO_ALLOC_SIZE)
- {
- M4OSA_TRACE1_0(
- "M4MP4W_processAU : audio stsz table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#else
-
- if (4 *mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb
- >= mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedStszBlocks
- *M4MP4W_STSZ_AUDIO_ALLOC_SIZE)
- {
- mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedStszBlocks +=
- 1;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->
- TABLE_STSZ, ( mMp4FileDataPtr->audioTrackPtr->
- nbOfAllocatedStszBlocks - 1)
- * M4MP4W_STSZ_AUDIO_ALLOC_SIZE,
- mMp4FileDataPtr->audioTrackPtr->
- nbOfAllocatedStszBlocks
- * M4MP4W_STSZ_AUDIO_ALLOC_SIZE);
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ
- != M4OSA_NULL, M4ERR_ALLOC);
- }
-
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
- mMp4FileDataPtr->audioTrackPtr->
- TABLE_STSZ[mMp4FileDataPtr->audioTrackPtr->
- CommonData.sampleNb] = auPtr->size;
-
- if (mMp4FileDataPtr->estimateAudioSize == M4OSA_FALSE)
- mMp4FileDataPtr->filesize += 4;
- }
- }
-
- if (delta > mMp4FileDataPtr->audioTrackPtr->sampleDuration)
- {
- /* keep track of real sample duration*/
- mMp4FileDataPtr->audioTrackPtr->sampleDuration = delta;
- }
-
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb
- == 0) /*test if first AU*/
- {
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[0] = 1;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[1] = 0;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb = 1;
- mMp4FileDataPtr->filesize += 8;
- }
- else if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb
- == 1) /*test if second AU*/
- {
-#ifndef DUPLICATE_STTS_IN_LAST_AU
-
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[0] += 1;
-
-#endif /*DUPLICATE_STTS_IN_LAST_AU*/
-
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[1] = delta;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb += 1;
- mMp4FileDataPtr->filesize += 8;
- }
- else
- {
- /*retrieve last sample delta*/
- lastSampleDur = mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[2
- * (mMp4FileDataPtr->audioTrackPtr->
- CommonData.sttsTableEntryNb - 1) - 1];
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- if (8 *(mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb
- + 3) >= mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedSttsBlocks
- *M4MP4W_STTS_AUDIO_ALLOC_SIZE)
- {
- M4OSA_TRACE1_0("M4MP4W_processAU : audio stts table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#else
-
- if (8 *mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb
- >= mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedSttsBlocks
- *M4MP4W_STTS_AUDIO_ALLOC_SIZE)
- {
- mMp4FileDataPtr->audioTrackPtr->nbOfAllocatedSttsBlocks += 1;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->audioTrackPtr->
- TABLE_STTS, ( mMp4FileDataPtr->audioTrackPtr->
- nbOfAllocatedSttsBlocks
- - 1) * M4MP4W_STTS_AUDIO_ALLOC_SIZE,
- mMp4FileDataPtr->audioTrackPtr->
- nbOfAllocatedSttsBlocks
- * M4MP4W_STTS_AUDIO_ALLOC_SIZE);
- ERR_CHECK(mMp4FileDataPtr->audioTrackPtr->TABLE_STTS
- != M4OSA_NULL, M4ERR_ALLOC);
- }
-
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
- if (delta != lastSampleDur) /*new entry in the table*/
- {
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[2 *(
- mMp4FileDataPtr->audioTrackPtr->
- CommonData.sttsTableEntryNb - 1)] = 1;
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[2 *(
- mMp4FileDataPtr->audioTrackPtr->
- CommonData.sttsTableEntryNb - 1) + 1] = delta;
- mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb +=
- 1;
- mMp4FileDataPtr->filesize += 8;
- }
- else
- {
- /*increase of 1 the number of consecutive AUs with same duration*/
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[2 *(
- mMp4FileDataPtr->audioTrackPtr->
- CommonData.sttsTableEntryNb - 1) - 2] += 1;
- }
- }
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb += 1;
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->currentStsc] +=
- 1;
-
-#else
-
- mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] +=
- 1;
-
-#endif
- /* Warning: time conversion cast 64to32! */
-
- mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS =
- (M4MP4W_Time32)auPtr->CTS;
- }
- else if (streamID == VideoStreamID) /*video stream*/
- {
- M4OSA_TRACE2_0("M4MP4W_processAU -> video");
-
- /* In h264, the size of the AU must be added to the data */
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH264)
- {
- /* Add the size of the NALU in BE */
- M4OSA_MemAddr8 pTmpDataAddress = M4OSA_NULL;
- auPtr->dataAddress -= 1;
- pTmpDataAddress = (M4OSA_MemAddr8)auPtr->dataAddress;
-
- // bit manipulation
- *pTmpDataAddress++ = (M4OSA_UInt8)((auPtr->size >> 24) & 0x000000FF);
- *pTmpDataAddress++ = (M4OSA_UInt8)((auPtr->size >> 16) & 0x000000FF);
- *pTmpDataAddress++ = (M4OSA_UInt8)((auPtr->size >> 8) & 0x000000FF);
- *pTmpDataAddress++ = (M4OSA_UInt8)((auPtr->size) & 0x000000FF);
-
- auPtr->size += 4;
- }
-
- /*video microstate*/
- ERR_CHECK((mMp4FileDataPtr->videoTrackPtr->microState
- == M4MP4W_writing_startAU), M4ERR_STATE);
- mMp4FileDataPtr->videoTrackPtr->microState = M4MP4W_writing;
-
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
- /* samples are written to file now */
-
- err = M4MP4W_putBlock((M4OSA_UChar *)auPtr->dataAddress, auPtr->size,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
-
- if (err != M4NO_ERROR)
- {
- M4OSA_FilePosition temp = mMp4FileDataPtr->absoluteCurrentPos
- + mMp4FileDataPtr->videoTrackPtr->currentPos;
- M4OSA_TRACE2_1(
- "M4MP4W_processAU: putBlock error when writing unbuffered video sample: %#X",
- err);
- /* Ouch, we got an error writing to the file, but we need to properly react so that
- the state is still consistent and we can properly close the file so that what has
- been recorded so far is not lost. Yay error recovery! */
-
- /* First, we do not know where we are in the file. Put us back at where we were before
- attempting to write the data. That way, we're consistent with the chunk and sample
- state data.absoluteCurrentPos is only updated for chunks, it points to the beginning
- of the chunk,therefore we need to add videoTrackPtr->currentPos to know where we
- were in the file. */
- err = mMp4FileDataPtr->fileWriterFunctions->seek(
- mMp4FileDataPtr->fileWriterContext,
- M4OSA_kFileSeekBeginning, &temp);
-
- M4OSA_TRACE2_3(
- "Backtracking to position 0x%08X, seek returned %d and position %08X",
- mMp4FileDataPtr->absoluteCurrentPos
- + mMp4FileDataPtr->videoTrackPtr->currentPos, err, temp);
-
- /* Then, do not update any info whatsoever in the writing state. This will have the
- consequence that it will be as if the sample has never been written, so the chunk
- will be merely closed after the previous sample (the sample we attempted to write
- here is lost). */
-
- /* And lastly (for here), return that we've reached the limit of available space.
- We don't care about the error originally returned by putBlock. */
-
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#endif
-
- if ((M4MP4W_Time32)auPtr->CTS < mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS) {
- // Do not report as error, it will abort the entire filewrite. Just skip this frame.
- M4OSA_TRACE1_0("Skip frame. Video frame has too old timestamp.");
- return M4NO_ERROR;
- }
-
- mMp4FileDataPtr->videoTrackPtr->currentPos += auPtr->size;
-
- /* Warning: time conversion cast 64to32! */
- delta = (M4MP4W_Time32)auPtr->CTS
- - mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS;
-
- /* DEBUG stts entries which are equal to 0 */
- M4OSA_TRACE2_1("V_DELTA = %ld\n", delta);
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- if (2 *(mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb + 3)
- >= mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStszBlocks
- *M4MP4W_STSZ_ALLOC_SIZE)
- {
- M4OSA_TRACE1_0("M4MP4W_processAU : video stsz table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
- mMp4FileDataPtr->videoTrackPtr->
- TABLE_STSZ[mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb] =
- (M4OSA_UInt16)auPtr->size;
- mMp4FileDataPtr->filesize += 4;
-
-#else
-
- if (4 *mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb
- >= mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStszBlocks
- *M4MP4W_STSZ_ALLOC_SIZE)
- {
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStszBlocks += 1;
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ,
- ( mMp4FileDataPtr->videoTrackPtr->
- nbOfAllocatedStszBlocks
- - 1) * M4MP4W_STSZ_ALLOC_SIZE,
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStszBlocks
- * M4MP4W_STSZ_ALLOC_SIZE);
-
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ != M4OSA_NULL,
- M4ERR_ALLOC);
- }
-
- mMp4FileDataPtr->videoTrackPtr->
- TABLE_STSZ[mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb] =
- auPtr->size;
- mMp4FileDataPtr->filesize += 4;
-
-#endif
-
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb
- == 0) /*test if first AU*/
- {
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4MP4W_put32_Lo(&mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[0], 1);
- M4MP4W_put32_Hi(&mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[0], 0);
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[0] = 1;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[1] = 0;
-
-#endif
-
- mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb = 1;
- mMp4FileDataPtr->filesize += 8;
- }
- else if (mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb
- == 1 ) /*test if second AU*/
- {
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4MP4W_put32_Hi(&mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[0],
- (M4OSA_UInt16)delta);
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[1] = delta;
-
-#endif
-
- }
- else
- {
- /*retrieve last sample delta*/
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- lastSampleDur = M4MP4W_get32_Hi(&mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1]);
-
- if (4 *(mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb
- + 3) >= mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedSttsBlocks
- *M4MP4W_STTS_ALLOC_SIZE)
- {
- M4OSA_TRACE1_0("M4MP4W_processAU : video stts table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#else
-
- lastSampleDur = mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2
- * (mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1) + 1];
-
- if (8 *mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb
- >= mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedSttsBlocks
- *M4MP4W_STTS_ALLOC_SIZE)
- {
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedSttsBlocks += 1;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS, ( mMp4FileDataPtr->videoTrackPtr->
- nbOfAllocatedSttsBlocks
- - 1) * M4MP4W_STTS_ALLOC_SIZE,
- mMp4FileDataPtr->videoTrackPtr->
- nbOfAllocatedSttsBlocks
- * M4MP4W_STTS_ALLOC_SIZE);
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->TABLE_STTS
- != M4OSA_NULL, M4ERR_ALLOC);
- }
-
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
- if (delta != lastSampleDur) /*new entry in the table*/
- {
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4MP4W_put32_Lo(&mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb], 1);
- M4MP4W_put32_Hi(&mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb], (M4OSA_UInt16)delta);
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2 *(
- mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb)] = 1;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2
- *(mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb)+1] = delta;
-
-#endif
-
- mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb +=
- 1;
- mMp4FileDataPtr->filesize += 8;
- }
- else
- {
- /*increase of 1 the number of consecutive AUs with same duration*/
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1] += 1;
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2 *(
- mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1)] += 1;
-
-#endif
-
- }
- }
-
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb += 1;
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->currentStsc] +=
- 1;
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] +=
- 1;
-
-#endif
-
- if (auPtr->attribute == AU_RAP)
- {
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- if (4 *(mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb + 3)
- >= mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStssBlocks
- *M4MP4W_STSS_ALLOC_SIZE)
- {
- M4OSA_TRACE1_0("M4MP4W_processAU : video stss table is full");
- return M4WAR_MP4W_OVERSIZE;
- }
-
-#else
-
- if (4 *mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb
- >= mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStssBlocks
- *M4MP4W_STSS_ALLOC_SIZE)
- {
- mMp4FileDataPtr->videoTrackPtr->nbOfAllocatedStssBlocks += 1;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STSS =
- (M4OSA_UInt32 *)M4MP4W_realloc(
- (M4OSA_MemAddr32)mMp4FileDataPtr->videoTrackPtr->
- TABLE_STSS, ( mMp4FileDataPtr->videoTrackPtr->
- nbOfAllocatedStssBlocks
- - 1) * M4MP4W_STSS_ALLOC_SIZE,
- mMp4FileDataPtr->videoTrackPtr->
- nbOfAllocatedStssBlocks
- * M4MP4W_STSS_ALLOC_SIZE);
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->TABLE_STSS
- != M4OSA_NULL, M4ERR_ALLOC);
- }
-
-#endif /*_M4MP4W_OPTIMIZE_FOR_PHONE*/
-
- mMp4FileDataPtr->videoTrackPtr->
- TABLE_STSS[mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb] =
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb;
- mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb += 1;
- mMp4FileDataPtr->filesize += 4;
- }
-
- /* Warning: time conversion cast 64to32! */
- mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS =
- (M4MP4W_Time32)auPtr->CTS;
- }
- else
- return M4ERR_BAD_STREAM_ID;
-
- /* I moved some state modification to after we know the sample has been written correctly. */
- if ((mMp4FileDataPtr->estimateAudioSize == M4OSA_TRUE)
- && (streamID == VideoStreamID))
- {
- mMp4FileDataPtr->audioMsStopTime =
- (M4MP4W_Time32)(auPtr->CTS * scale_video);
- }
-
- if ((mMp4FileDataPtr->estimateAudioSize == M4OSA_FALSE)
- || (streamID == VideoStreamID))
- {
- /*update fileSize*/
- mMp4FileDataPtr->filesize += auPtr->size;
- }
-
- if ((mMp4FileDataPtr->estimateAudioSize == M4OSA_TRUE)
- && (streamID == VideoStreamID))
- {
- /*update filesize with estimated audio data that will be added later. */
- /*Warning: Assumption is made that: */
- /* - audio samples have constant size (e.g. no sid). */
- /* - max audio sample size has been set, and is the actual sample size. */
-
- ERR_CHECK(mMp4FileDataPtr->audioMsChunkDur != 0,
- M4WAR_MP4W_NOT_EVALUABLE);
- mMp4FileDataPtr->filesize -=
- (M4OSA_UInt32)(( mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS
- * scale_video) * (0.05/*always 50 AMR samples per second*/
- *(M4OSA_Double)mMp4FileDataPtr->audioTrackPtr->MaxAUSize
- + 16/*additional data for a new chunk*/
- / (M4OSA_Double)mMp4FileDataPtr->audioMsChunkDur));
-
- mMp4FileDataPtr->filesize += (M4OSA_UInt32)(( auPtr->CTS * scale_video)
- * (0.05/*always 50 AMR samples per second*/
- *(M4OSA_Double)mMp4FileDataPtr->audioTrackPtr->MaxAUSize
- + 16/*additional data for a new chunk*/
- / (M4OSA_Double)mMp4FileDataPtr->audioMsChunkDur));
- }
-
- M4OSA_TRACE1_4("processAU : size 0x%x mode %d filesize %lu limit %lu",
- auPtr->size, auPtr->attribute, mMp4FileDataPtr->filesize,
- mMp4FileDataPtr->MaxFileSize);
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_closeWrite( M4OSA_Context context )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
- M4OSA_ERR err2 = M4NO_ERROR, err3 = M4NO_ERROR;
-
- /*Warning: test should be done here to ensure context->pContext is not M4OSA_NULL,
- but C is not C++...*/
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
-
- M4OSA_UChar camcoder_maj, camcoder_min, camcoder_rev; /*camcoder version*/
- M4OSA_Bool bAudio =
- (( mMp4FileDataPtr->hasAudio)
- && (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb
- != 0)); /*((mMp4FileDataPtr->audioTrackPtr != M4OSA_NULL) &&
- (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb != 0));*/
- M4OSA_Bool bVideo =
- (( mMp4FileDataPtr->hasVideo)
- && (mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb
- != 0)); /*((mMp4FileDataPtr->videoTrackPtr != M4OSA_NULL) &&
- (mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb != 0));*/
- M4OSA_Bool bH263 = M4OSA_FALSE;
- M4OSA_Bool bH264 = M4OSA_FALSE;
- M4OSA_Bool bMP4V = M4OSA_FALSE;
- M4OSA_Bool bAAC = M4OSA_FALSE;
- M4OSA_Bool bEVRC = M4OSA_FALSE;
-
- /*intermediate variables*/
- M4OSA_UInt32 A, B, N, AB4N;
-
- /*Trak variables*/
- M4OSA_UInt32 a_trakId = AudioStreamID; /* (audio=1)*/
- /* first trak offset is 32+moovSize, second equals 32+moovSize+1st_track_size*/
- M4OSA_UInt32 a_trakOffset = 32;
- M4OSA_UInt32 a_sttsSize = 24; /* A (audio=24)*/
- M4OSA_UInt32 a_stszSize = 20; /* B (audio=20)*/
- M4OSA_UInt32 a_trakSize = 402; /* (audio=402)*/
- M4OSA_UInt32 a_mdiaSize = 302; /* (audio=302)*/
- M4OSA_UInt32 a_minfSize = 229; /* (audio=229)*/
- M4OSA_UInt32 a_stblSize = 169; /* (audio=169)*/
- M4OSA_UInt32 a_stsdSize = 69; /* (audio=69 )*/
- M4OSA_UInt32 a_esdSize = 53; /* (audio=53 )*/
- M4OSA_UInt32 a_dataSize = 0; /* temp: At the end, = currentPos*/
- M4MP4W_Time32 a_trakDuration = 0; /* equals lastCTS*/
- M4MP4W_Time32 a_msTrakDuration = 0;
- M4OSA_UInt32 a_stscSize = 28; /* 16+12*nbchunksaudio*/
- M4OSA_UInt32 a_stcoSize = 20; /* 16+4*nbchunksaudio*/
-
- M4OSA_UInt32 v_trakId = VideoStreamID; /* (video=2)*/
- /* first trak offset is 32+moovSize, second equals 32+moovSize+1st_track_size*/
- M4OSA_UInt32 v_trakOffset = 32;
- M4OSA_UInt32 v_sttsSize = 0; /* A (video=16+8J)*/
- M4OSA_UInt32 v_stszSize = 0; /* B (video=20+4K)*/
- M4OSA_UInt32 v_trakSize = 0; /* (h263=A+B+4N+426), (mp4v=A+B+dsi+4N+448) */
- M4OSA_UInt32 v_mdiaSize = 0; /* (h263=A+B+4N+326), (mp4v=A+B+dsi+4N+348) */
- M4OSA_UInt32 v_minfSize = 0; /* (h263=A+B+4N+253), (mp4v=A+B+dsi+4N+275) */
- M4OSA_UInt32 v_stblSize = 0; /* (h263=A+B+4N+189), (mp4v=A+B+dsi+4N+211) */
- M4OSA_UInt32 v_stsdSize = 0; /* (h263=117) , (mp4v=139+dsi )*/
- M4OSA_UInt32 v_esdSize = 0; /* (h263=101) , (mp4v=153+dsi )*/
- M4OSA_UInt32 v_dataSize = 0; /* temp: At the end, = currentPos*/
- M4MP4W_Time32 v_trakDuration = 0; /* equals lastCTS*/
- M4MP4W_Time32 v_msTrakDuration = 0;
- M4OSA_UInt32 v_stscSize = 28; /* 16+12*nbchunksvideo*/
- M4OSA_UInt32 v_stcoSize = 20; /* 16+4*nbchunksvideo*/
-
- /*video variables*/
- M4OSA_UInt32 v_stssSize = 0; /* 4*N+16 STSS*/
-
- /*aac & mp4v temp variable*/
- M4OSA_UInt8 dsi = 0;
-
- /*H264 variables*/
- M4OSA_UInt32 v_avcCSize = 0; /* dsi+15*/
-
- /*MP4V variables*/
- M4OSA_UInt32 v_esdsSize = 0; /* dsi+37*/
- M4OSA_UInt8 v_ESDescriptorSize =
- 0; /* dsi+23 (warning: check dsi<105 for coding size on 1 byte)*/
- M4OSA_UInt8 v_DCDescriptorSize = 0; /* dsi+15*/
-
- /*AAC variables*/
- M4OSA_UInt32 a_esdsSize = 0; /* dsi+37*/
- M4OSA_UInt8 a_ESDescriptorSize =
- 0; /* dsi+23 (warning: check dsi<105 for coding size on 1 byte)*/
- M4OSA_UInt8 a_DCDescriptorSize = 0; /* dsi+15*/
-
- /*General variables*/
-
- /* audio chunk size + video chunk size*/
- M4OSA_UInt32 mdatSize = 8;
- M4OSA_UInt32 moovSize = 116; /* 116 + 402(audio) + (A+B+4N+426)(h263) or */
- /* (A+B+dsi+4N+448)(mp4v) */
- M4OSA_UInt32 creationTime; /* C */
-
- /*flag to set up the chunk interleave strategy*/
- M4OSA_Bool bInterleaveAV =
- (bAudio && bVideo && (mMp4FileDataPtr->InterleaveDur != 0));
-
- M4OSA_Context fileWriterContext = mMp4FileDataPtr->fileWriterContext;
-
- M4OSA_UInt32 i;
-
- M4OSA_Double scale_audio = 0.0;
- M4OSA_Double scale_video = 0.0;
- M4MP4W_Time32 delta;
-
-#ifndef _M4MP4W_MOOV_FIRST
-
- M4OSA_FilePosition moovPos, mdatPos;
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- /*macro state */
- mMp4FileDataPtr->state = M4MP4W_closed;
-
- /*if no data !*/
- if ((!bAudio) && (!bVideo))
- {
- err = M4NO_ERROR; /*would be better to return a warning ?*/
- goto cleanup;
- }
-
-#ifdef _M4MP4W_RESERVED_MOOV_DISK_SPACE
- /* Remove safety file to make room for what needs to be written out here
- (chunk flushing and moov). */
-
- if (M4OSA_TRUE == mMp4FileDataPtr->cleanSafetyFile)
- {
- M4OSA_Context tempContext;
- err = mMp4FileDataPtr->fileWriterFunctions->openWrite(&tempContext,
- mMp4FileDataPtr->safetyFileUrl,
- M4OSA_kFileWrite | M4OSA_kFileCreate);
-
- if (M4NO_ERROR != err)
- goto cleanup;
- err = mMp4FileDataPtr->fileWriterFunctions->closeWrite(tempContext);
-
- if (M4NO_ERROR != err)
- goto cleanup;
- mMp4FileDataPtr->safetyFileUrl = M4OSA_NULL;
- mMp4FileDataPtr->cleanSafetyFile = M4OSA_FALSE;
- }
-
-#endif /* _M4MP4W_RESERVED_MOOV_DISK_SPACE */
-
- if (bVideo)
- {
- if ((M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable)
- || (M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->chunkSizeTable)
- || (M4OSA_NULL
- == mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable)
- || (M4OSA_NULL
- == mMp4FileDataPtr->videoTrackPtr->chunkTimeMsTable)
- || (M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ)
- || (M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->TABLE_STTS)
- || (M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->TABLE_STSS))
- {
- mMp4FileDataPtr->fileWriterFunctions->closeWrite(
- fileWriterContext); /**< close the stream anyway */
- M4MP4W_freeContext(context); /**< Free the context content */
- return M4ERR_ALLOC;
- }
-
- /*video microstate*/
- mMp4FileDataPtr->videoTrackPtr->microState = M4MP4W_closed;
-
- /*current chunk is the last one and gives the total number of video chunks (-1)*/
- for ( i = 0; i < mMp4FileDataPtr->videoTrackPtr->currentChunk; i++ )
- {
- v_dataSize += mMp4FileDataPtr->videoTrackPtr->chunkSizeTable[i];
- }
-
-#ifndef _M4MP4W_MOOV_FIRST
-#ifndef _M4MP4W_UNBUFFERED_VIDEO
- /*flush chunk*/
-
- if (mMp4FileDataPtr->videoTrackPtr->currentPos > 0)
- {
- err = M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->Chunk[0],
- mMp4FileDataPtr->videoTrackPtr->currentPos,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
-
- if (M4NO_ERROR != err)
- goto cleanup;
- }
-
-#endif
-
- M4OSA_TRACE1_0("flush video | CLOSE");
- M4OSA_TRACE1_3("current chunk = %d offset = 0x%x size = 0x%08X",
- mMp4FileDataPtr->videoTrackPtr->currentChunk,
- mMp4FileDataPtr->absoluteCurrentPos,
- mMp4FileDataPtr->videoTrackPtr->currentPos);
-
- /*update chunk offset*/
- mMp4FileDataPtr->videoTrackPtr->
- chunkOffsetTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- mMp4FileDataPtr->absoluteCurrentPos;
-
- /*add chunk size to absoluteCurrentPos*/
- mMp4FileDataPtr->absoluteCurrentPos +=
- mMp4FileDataPtr->videoTrackPtr->currentPos;
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- /*update last chunk size, and add this value to v_dataSize*/
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkSizeTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- mMp4FileDataPtr->videoTrackPtr->currentPos;
- v_dataSize +=
- mMp4FileDataPtr->videoTrackPtr->currentPos; /*add last chunk size*/
-
- v_trakDuration = mMp4FileDataPtr->videoTrackPtr->
- CommonData.lastCTS; /* equals lastCTS*/
-
- /* bugfix: if a new chunk was just created, cancel it before to close */
- if ((mMp4FileDataPtr->videoTrackPtr->currentChunk != 0)
- && (mMp4FileDataPtr->videoTrackPtr->currentPos == 0))
- {
- mMp4FileDataPtr->videoTrackPtr->currentChunk--;
- }
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-
- if ((mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->videoTrackPtr->
- currentStsc] & 0xFFF) == 0)
- {
- mMp4FileDataPtr->videoTrackPtr->currentStsc--;
- }
-
-#endif /*_M4MP4W_UNBUFFERED_VIDEO*/
-
- /* Last sample duration */
- /* If we have the file duration we use it, else we duplicate the last AU */
-
- if (mMp4FileDataPtr->MaxFileDuration > 0)
- {
- /* use max file duration to calculate delta of last AU */
- delta = mMp4FileDataPtr->MaxFileDuration
- - mMp4FileDataPtr->videoTrackPtr->CommonData.lastCTS;
- v_trakDuration = mMp4FileDataPtr->MaxFileDuration;
-
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb > 1)
- {
- /* if more than 1 frame, create a new stts entry (else already created) */
- mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb++;
- }
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4MP4W_put32_Lo(&mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1], 1);
- M4MP4W_put32_Hi(&mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1], delta);
-
-#else
-
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2
- *(mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb
- - 1)] = 1;
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2
- *(mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb
- - 1) + 1] = delta;
-
-#endif
-
- }
- else
- {
- /* duplicate the delta of the previous frame */
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb > 1)
- {
- /* if more than 1 frame, duplicate the stts entry (else already exists) */
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- v_trakDuration +=
- M4MP4W_get32_Hi(&mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1]);
- mMp4FileDataPtr->videoTrackPtr->
- TABLE_STTS[mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1] += 1;
-
-#else
-
- v_trakDuration += mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2
- * (mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1) + 1];
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[2 *(
- mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb - 1)] += 1;
-
-#endif
-
- }
- else
- {
- M4OSA_TRACE1_0("M4MP4W_closeWrite : ! videoTrackPtr,\
- cannot know the duration of the unique AU !");
- /* If there is an audio track, we use it as a file duration
- (and so, as AU duration...) */
- if (mMp4FileDataPtr->audioTrackPtr != M4OSA_NULL)
- {
- M4OSA_TRACE1_0(
- "M4MP4W_closeWrite : ! Let's use the audio track duration !");
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[1] =
- (M4OSA_UInt32)(
- mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS
- * (1000.0 / mMp4FileDataPtr->audioTrackPtr->
- CommonData.timescale));
- v_trakDuration =
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[1];
- }
- /* Else, we use a MAGICAL value (66 ms) */
- else
- {
- M4OSA_TRACE1_0(
- "M4MP4W_closeWrite : ! No audio track -> use magical value (66) !"); /* */
- mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[1] = 66;
- v_trakDuration = 66;
- }
- }
- }
-
- /* Calculate table sizes */
- A = v_sttsSize = 16 + 8 * mMp4FileDataPtr->videoTrackPtr->
- CommonData.sttsTableEntryNb; /* A (video=16+8J)*/
- B = v_stszSize = 20 + 4 * mMp4FileDataPtr->videoTrackPtr->
- CommonData.sampleNb; /* B (video=20+4K)*/
- N = mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb;
- AB4N = A + B + 4 * N;
-
- scale_video =
- 1000.0 / mMp4FileDataPtr->videoTrackPtr->CommonData.timescale;
- v_msTrakDuration = (M4OSA_UInt32)(v_trakDuration * scale_video);
-
- /*Convert integers in the table from LE into BE*/
-#ifndef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- M4MP4W_table32ToBE(mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ,
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb);
- M4MP4W_table32ToBE(mMp4FileDataPtr->videoTrackPtr->TABLE_STTS,
- 2 * (mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb));
-
-#endif
-
- M4MP4W_table32ToBE(mMp4FileDataPtr->videoTrackPtr->TABLE_STSS,
- mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb);
-
- if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH263)
- {
- bH263 = M4OSA_TRUE;
- v_trakSize = AB4N + 426; /* (h263=A+B+4N+426)*/
- v_mdiaSize = AB4N + 326; /* (h263=A+B+4N+326)*/
- v_minfSize = AB4N + 253; /* (h263=A+B+4N+253)*/
- v_stblSize = AB4N + 189; /* (h263=A+B+4N+189)*/
- v_stsdSize = 117; /* (h263=117)*/
- v_esdSize = 101; /* (h263=101)*/
-
- moovSize += AB4N + 426;
-
- if (((M4OSA_Int32)mMp4FileDataPtr->videoTrackPtr->avgBitrate) != -1)
- {
- /*the optional 'bitr' atom is appended to the dsi,so filesize is 16 bytes bigger*/
- v_trakSize += 16;
- v_mdiaSize += 16;
- v_minfSize += 16;
- v_stblSize += 16;
- v_stsdSize += 16;
- v_esdSize += 16;
- moovSize += 16;
- }
- }
- else if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kH264)
- {
- bH264 = M4OSA_TRUE;
- /* For H264 there is no default DSI, and its presence is mandatory,
- so check the DSI has been set*/
- if (0 == mMp4FileDataPtr->videoTrackPtr->dsiSize
- || M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->DSI)
- {
- M4OSA_TRACE1_0(
- "M4MP4W_closeWrite: error, no H264 DSI has been set!");
- err = M4ERR_STATE;
- goto cleanup;
- }
-
- /*H264 sizes of the atom*/
-
- // Remove the hardcoded DSI values of H264Block2
- // TODO: check bMULPPSSPS case
- v_avcCSize = sizeof(M4OSA_UInt32) + sizeof(H264Block2) +
- mMp4FileDataPtr->videoTrackPtr->dsiSize;
-
- v_trakSize = AB4N + v_avcCSize + 411;
- v_mdiaSize = AB4N + v_avcCSize + 311;
- v_minfSize = AB4N + v_avcCSize + 238;
- v_stblSize = AB4N + v_avcCSize + 174;
- v_stsdSize = v_avcCSize + 102;
- v_esdSize = v_avcCSize + 86;
-
- moovSize += AB4N + v_avcCSize + 411;
-
- }
- else if (mMp4FileDataPtr->videoTrackPtr->CommonData.trackType
- == M4SYS_kMPEG_4)
- {
- bMP4V = M4OSA_TRUE;
- /* For MPEG4 there is no default DSI, and its presence is mandatory,
- so check the DSI has been set*/
- if (0 == mMp4FileDataPtr->videoTrackPtr->dsiSize
- || M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->DSI)
- {
- M4OSA_TRACE1_0(
- "M4MP4W_closeWrite: error, no MPEG4 DSI has been set!");
- err = M4ERR_STATE;
- goto cleanup;
- }
-
- /*MP4V variables*/
- dsi = mMp4FileDataPtr->videoTrackPtr->dsiSize;
- v_esdsSize = 37 + dsi; /* dsi+37*/
- v_ESDescriptorSize =
- 23
- + dsi; /* dsi+23 (warning: check dsi<105 for coding size on 1 byte)*/
- v_DCDescriptorSize = 15 + dsi; /* dsi+15*/
-
- v_trakSize = AB4N + dsi + 448; /* (mp4v=A+B+dsi+4N+448) */
- v_mdiaSize = AB4N + dsi + 348; /* (mp4v=A+B+dsi+4N+348) */
- v_minfSize = AB4N + dsi + 275; /* (mp4v=A+B+dsi+4N+275) */
- v_stblSize = AB4N + dsi + 211; /* (mp4v=A+B+dsi+4N+211) */
- v_stsdSize = dsi + 139; /* (mp4v=139+dsi)*/
- v_esdSize = dsi + 123; /* (mp4v=123+dsi)*/
-
- moovSize += AB4N + dsi + 448;
- }
-
- /*video variables*/
- v_stssSize = 16 + 4 * N; /* 4*N+16 STSS*/
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
- /* stsc update */
-
- v_stscSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentStsc;
- v_stblSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentStsc;
- v_minfSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentStsc;
- v_mdiaSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentStsc;
- v_trakSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentStsc;
- moovSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentStsc;
-
- /* stco update */
- v_stcoSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_stblSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_minfSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_mdiaSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_trakSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- moovSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
-
-#else
- /*stsc/stco update*/
-
- v_stscSize += 12 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_stcoSize += 4 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_stblSize += 16 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_minfSize += 16 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_mdiaSize += 16 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- v_trakSize += 16 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
- moovSize += 16 * mMp4FileDataPtr->videoTrackPtr->currentChunk;
-
-#endif
-
- /*update last chunk time*/
-
- mMp4FileDataPtr->videoTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->videoTrackPtr->currentChunk] =
- v_msTrakDuration;
- }
-
- if (bAudio)
- {
- if ((M4OSA_NULL == mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable)
- || (M4OSA_NULL == mMp4FileDataPtr->audioTrackPtr->chunkSizeTable)
- || (M4OSA_NULL
- == mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable)
- || (M4OSA_NULL
- == mMp4FileDataPtr->audioTrackPtr->chunkTimeMsTable)
- || (M4OSA_NULL == mMp4FileDataPtr->audioTrackPtr->TABLE_STTS))
- {
- mMp4FileDataPtr->fileWriterFunctions->closeWrite(
- fileWriterContext); /**< close the stream anyway */
- M4MP4W_freeContext(context); /**< Free the context content */
- return M4ERR_ALLOC;
- }
-
- /*audio microstate*/
- mMp4FileDataPtr->audioTrackPtr->microState = M4MP4W_closed;
-
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.trackType == M4SYS_kAAC)
- {
- bAAC =
- M4OSA_TRUE; /*else, audio is implicitely amr in the following*/
- dsi = mMp4FileDataPtr->audioTrackPtr->dsiSize; /*variable size*/
-
- a_esdsSize = 37 + dsi; /* dsi+37*/
- a_ESDescriptorSize =
- 23
- + dsi; /* dsi+23 (warning: check dsi<105 for coding size on 1 byte)*/
- a_DCDescriptorSize = 15 + dsi; /* dsi+15*/
-
- a_esdSize = dsi + 73; /*overwrite a_esdSize with aac value*/
- /*add dif. between amr & aac sizes: (- 53 + dsi + 37)*/
- a_stsdSize += dsi + 20;
- a_stblSize += dsi + 20;
- a_minfSize += dsi + 20;
- a_mdiaSize += dsi + 20;
- a_trakSize += dsi + 20;
- moovSize += dsi + 20;
- }
-
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.trackType
- == M4SYS_kEVRC)
- {
- bEVRC =
- M4OSA_TRUE; /*else, audio is implicitely amr in the following*/
-
- /* evrc dsi is only 6 bytes while amr dsi is 9 bytes,all other blocks are unchanged */
- a_esdSize -= 3;
- a_stsdSize -= 3;
- a_stblSize -= 3;
- a_minfSize -= 3;
- a_mdiaSize -= 3;
- a_trakSize -= 3;
- moovSize -= 3;
- }
-
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize == 0)
- {
- if (M4OSA_NULL == mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ)
- {
- mMp4FileDataPtr->fileWriterFunctions->closeWrite(
- fileWriterContext); /**< close the stream anyway */
- M4MP4W_freeContext(context); /**< Free the context content */
- return M4ERR_ALLOC;
- }
- /*Convert integers in the table from LE into BE*/
- M4MP4W_table32ToBE(mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ,
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb);
- a_stszSize +=
- 4 * mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- a_stblSize +=
- 4 * mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- a_minfSize +=
- 4 * mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- a_mdiaSize +=
- 4 * mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- a_trakSize +=
- 4 * mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- moovSize += 4 * mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb;
- }
-
- moovSize += 402;
-
- /*current chunk is the last one and gives the total number of audio chunks (-1)*/
- for ( i = 0; i < mMp4FileDataPtr->audioTrackPtr->currentChunk; i++ )
- {
- a_dataSize += mMp4FileDataPtr->audioTrackPtr->chunkSizeTable[i];
- }
-
-#ifndef _M4MP4W_MOOV_FIRST
- /*flush chunk*/
-
- if (mMp4FileDataPtr->audioTrackPtr->currentPos > 0)
- {
- err = M4MP4W_putBlock(mMp4FileDataPtr->audioTrackPtr->Chunk[0],
- mMp4FileDataPtr->audioTrackPtr->currentPos,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext);
-
- if (M4NO_ERROR != err)
- goto cleanup;
- }
-
- M4OSA_TRACE1_0("flush audio | CLOSE");
- M4OSA_TRACE1_2("current chunk = %d offset = 0x%x",
- mMp4FileDataPtr->audioTrackPtr->currentChunk,
- mMp4FileDataPtr->absoluteCurrentPos);
-
- /*update chunk offset*/
- mMp4FileDataPtr->audioTrackPtr->
- chunkOffsetTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- mMp4FileDataPtr->absoluteCurrentPos;
-
- /*add chunk size to absoluteCurrentPos*/
- mMp4FileDataPtr->absoluteCurrentPos +=
- mMp4FileDataPtr->audioTrackPtr->currentPos;
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- /*update last chunk size, and add this value to a_dataSize*/
-
- mMp4FileDataPtr->audioTrackPtr->
- chunkSizeTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- mMp4FileDataPtr->audioTrackPtr->currentPos;
- a_dataSize +=
- mMp4FileDataPtr->audioTrackPtr->currentPos; /*add last chunk size*/
-
- /* bugfix: if a new chunk was just created, cancel it before to close */
- if ((mMp4FileDataPtr->audioTrackPtr->currentChunk != 0)
- && (mMp4FileDataPtr->audioTrackPtr->currentPos == 0))
- {
- mMp4FileDataPtr->audioTrackPtr->currentChunk--;
- }
-#ifdef _M4MP4W_UNBUFFERED_VIDEO
-
- if ((mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[mMp4FileDataPtr->audioTrackPtr->
- currentStsc] & 0xFFF) == 0)
- {
- mMp4FileDataPtr->audioTrackPtr->currentStsc--;
- }
-
-#endif /*_M4MP4W_UNBUFFERED_VIDEO*/
-
- a_trakDuration = mMp4FileDataPtr->audioTrackPtr->
- CommonData.lastCTS; /* equals lastCTS*/
- /* add last sample dur */
-
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb != 1)
- {
-#ifdef DUPLICATE_STTS_IN_LAST_AU
- /*increase of 1 the number of consecutive AUs with same duration*/
-
- mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[2
- *(mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb
- - 1) - 2] += 1;
-
-#endif /*DUPLICATE_STTS_IN_LAST_AU*/
-
- a_trakDuration += mMp4FileDataPtr->audioTrackPtr->TABLE_STTS[2
- * (mMp4FileDataPtr->audioTrackPtr->
- CommonData.sttsTableEntryNb - 1) - 1];
- }
- else if (0 == mMp4FileDataPtr->audioTrackPtr->CommonData.lastCTS)
- {
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.trackType
- == M4SYS_kAMR)
- {
- if (12200 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 32
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (10200 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 27
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (7950 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 21
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (7400 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 20
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (6700 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 18
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (5900 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 16
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (5150 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 14
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- else if (4750 == mMp4FileDataPtr->audioTrackPtr->avgBitrate)
- {
- a_trakDuration = a_dataSize / 13
- * mMp4FileDataPtr->audioTrackPtr->sampleDuration;
- }
- }
- }
-
- scale_audio =
- 1000.0 / mMp4FileDataPtr->audioTrackPtr->CommonData.timescale;
- a_msTrakDuration = (M4OSA_UInt32)(a_trakDuration * scale_audio);
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
- /* stsc update */
-
- a_stscSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentStsc;
- a_stblSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentStsc;
- a_minfSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentStsc;
- a_mdiaSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentStsc;
- a_trakSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentStsc;
- moovSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentStsc;
-
- /* stso update */
- a_stcoSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_stblSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_minfSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_mdiaSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_trakSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- moovSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
-
-#else
- /*stsc/stco update*/
-
- a_stscSize += 12 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_stcoSize += 4 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_stblSize += 16 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_minfSize += 16 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_mdiaSize += 16 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- a_trakSize += 16 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
- moovSize += 16 * mMp4FileDataPtr->audioTrackPtr->currentChunk;
-
-#endif
-
- /* compute the new size of stts*/
-
- a_sttsSize = 16 + 8 * (mMp4FileDataPtr->audioTrackPtr->
- CommonData.sttsTableEntryNb - 1);
-
- moovSize += a_sttsSize - 24;
- a_mdiaSize += a_sttsSize - 24;
- a_minfSize += a_sttsSize - 24;
- a_stblSize += a_sttsSize - 24;
- a_trakSize += a_sttsSize - 24;
-
- /*update last chunk time*/
- mMp4FileDataPtr->audioTrackPtr->
- chunkTimeMsTable[mMp4FileDataPtr->audioTrackPtr->currentChunk] =
- a_msTrakDuration;
- }
-
- /* changing the way the mdat size is computed.
- The real purpose of the mdat size is to know the amount to skip to get to the next
- atom, which is the moov; the size of media in the mdat is almost secondary. Therefore,
- it is of utmost importance that the mdat size "points" to where the moov actually
- begins. Now, the moov begins right after the last data we wrote, so how could the sum
- of all chunk sizes be different from the total size of what has been written? Well, it
- can happen when the writing was unexpectedly stopped (because of lack of disk space,
- for instance), in this case a chunk may be partially written (the partial write is not
- necessarily erased) but it may not be reflected in the chunk size list (which may
- believe it hasn't been written or on the contrary that it has been fully written). In
- the case of such a mismatch, there is either unused data in the mdat (not very good,
- but tolerable) or when reading the last chunk it will read the beginning of the moov
- as part of the chunk (which means the last chunk won't be correctly decoded), both of
- which are still better than losing the whole recording. In the long run it'll probably
- be attempted to always clean up back to a consistent state, but at any rate it is
- always safer to have the mdat size be computed using the position where the moov
- actually begins, rather than using the size it is thought the mdat has.
-
- Therefore, I will record where we are just before writing the moov, to serve when
- updating the mdat size. */
-
- /* mdatSize += a_dataSize + v_dataSize; *//*TODO allow for multiple chunks*/
-
- /* End of Pierre Lebeaupin 19/12/2007: changing the way the mdat size is computed. */
-
- /* first trak offset is 32+moovSize, second equals 32+moovSize+1st_track_size*/
- a_trakOffset += moovSize;
- v_trakOffset += moovSize/*+ a_dataSize*/;
-
- if (bInterleaveAV == M4OSA_FALSE)
- v_trakOffset += a_dataSize;
-
- /*system time since 1970 */
-#ifndef _M4MP4W_DONT_USE_TIME_H
-
- time((time_t *)&creationTime);
- /*convert into time since 1/1/1904 00h00 (normative)*/
- creationTime += 2082841761; /*nb of sec between 1904 and 1970*/
-
-#else /*_M4MP4W_DONT_USE_TIME_H*/
-
- creationTime =
- 0xBBD09100; /* = 7/11/2003 00h00 ; in hexa because of code scrambler limitation with
- large integers */
-
-#endif /*_M4MP4W_DONT_USE_TIME_H*/
-
- mMp4FileDataPtr->duration =
- max(a_msTrakDuration, v_msTrakDuration); /*max audio/video*/
-
-#ifdef _M4MP4W_MOOV_FIRST
- /*open file in write binary mode*/
-
- err = mMp4FileDataPtr->fileWriterFunctions->openWrite(&fileWriterContext,
- mMp4FileDataPtr->url, 0x22);
- ERR_CHECK(err == M4NO_ERROR, err);
-
- /*ftyp atom*/
- if (mMp4FileDataPtr->ftyp.major_brand != 0)
- {
- M4OSA_UInt32 i;
-
- /* Put customized ftyp box */
- CLEANUPonERR(M4MP4W_putBE32(16
- + (mMp4FileDataPtr->ftyp.nbCompatibleBrands * 4),
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(M4MPAC_FTYP_TAG,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->ftyp.major_brand,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->ftyp.minor_version,
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext));
-
- for ( i = 0; i < mMp4FileDataPtr->ftyp.nbCompatibleBrands; i++ )
- {
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->ftyp.compatible_brands[i],
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext));
- }
- }
- else
- {
- /* Put default ftyp box */
- CLEANUPonERR(M4MP4W_putBlock(Default_ftyp, sizeof(Default_ftyp),
- mMp4FileDataPtr->fileWriterFunctions,
- mMp4FileDataPtr->fileWriterContext));
- }
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
-#ifndef _M4MP4W_MOOV_FIRST
- /* seek is used to get the current position relative to the start of the file. */
- /* ... or rather, seek used to be used for that, but it has been found this functionality
- is not reliably, or sometimes not at all, implemented in the various OSALs, so we now avoid
- using it. */
- /* Notice this new method assumes we're at the end of the file, this will break if ever we
- are overwriting a larger file. */
-
- CLEANUPonERR(mMp4FileDataPtr->fileWriterFunctions->getOption(
- mMp4FileDataPtr->fileWriterContext,
- M4OSA_kFileWriteGetFileSize, (M4OSA_DataOption *) &moovPos));
- /* moovPos will be used after writing the moov. */
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- CLEANUPonERR(M4MP4W_putBE32(moovSize, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock3, sizeof(CommonBlock3),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock4, sizeof(CommonBlock4),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->duration,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock5, sizeof(CommonBlock5),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- if (bAudio)
- {
- CLEANUPonERR(M4MP4W_putBE32(a_trakSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock6, sizeof(CommonBlock6),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(a_trakId,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock7, sizeof(CommonBlock7),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(a_msTrakDuration,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock7bis, sizeof(CommonBlock7bis),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(AMRBlock1, sizeof(AMRBlock1),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*audio*/
- CLEANUPonERR(M4MP4W_putBE32(a_mdiaSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock8, sizeof(CommonBlock8),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->CommonData.timescale,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(a_trakDuration,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock9, sizeof(CommonBlock9),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(AMRBlock1_1, sizeof(AMRBlock1_1),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*audio*/
- CLEANUPonERR(M4MP4W_putBE32(a_minfSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock10, sizeof(CommonBlock10),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(a_stblSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock11, sizeof(CommonBlock11),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(a_sttsSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock12, sizeof(CommonBlock12),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb - 1,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- /*invert the table data to bigendian*/
- M4MP4W_table32ToBE(mMp4FileDataPtr->audioTrackPtr->TABLE_STTS,
- 2 * (mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb
- - 1));
- CLEANUPonERR(M4MP4W_putBlock((const M4OSA_UChar
- *)mMp4FileDataPtr->audioTrackPtr->TABLE_STTS,
- ( mMp4FileDataPtr->audioTrackPtr->CommonData.sttsTableEntryNb - 1)
- * 8,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*audio*/
-
- /* stsd */
- CLEANUPonERR(M4MP4W_putBE32(a_stsdSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(SampleDescriptionHeader,
- sizeof(SampleDescriptionHeader),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(a_esdSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /* sample desc entry inside stsd */
- if (bAAC)
- {
- CLEANUPonERR(M4MP4W_putBlock(AACBlock1, sizeof(AACBlock1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- }
- else if (bEVRC)
- {
- CLEANUPonERR(M4MP4W_putBlock(EVRC8Block1, sizeof(EVRC8Block1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*evrc*/
- }
- else /*AMR8*/
- {
- CLEANUPonERR(M4MP4W_putBlock(AMR8Block1, sizeof(AMR8Block1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*amr8*/
- }
- CLEANUPonERR(M4MP4W_putBlock(SampleDescriptionEntryStart,
- sizeof(SampleDescriptionEntryStart),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(AudioSampleDescEntryBoilerplate,
- sizeof(AudioSampleDescEntryBoilerplate),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*audio*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->CommonData.timescale
- << 16,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /* DSI inside sample desc entry */
- if (bAAC)
- {
- CLEANUPonERR(M4MP4W_putBE32(a_esdsSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock0,
- sizeof(MPEGConfigBlock0), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putByte(a_ESDescriptorSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock1,
- sizeof(MPEGConfigBlock1), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putByte(a_DCDescriptorSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putBlock(AACBlock2, sizeof(AACBlock2),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(
- M4MP4W_putBE24(mMp4FileDataPtr->audioTrackPtr->avgBitrate * 5,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->maxBitrate,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->avgBitrate,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock2,
- sizeof(MPEGConfigBlock2), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putByte(mMp4FileDataPtr->audioTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putBlock(mMp4FileDataPtr->audioTrackPtr->DSI,
- mMp4FileDataPtr->audioTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock3,
- sizeof(MPEGConfigBlock3), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*aac*/
- }
- else if (bEVRC)
- {
- M4OSA_UInt8 localDsi[6];
- M4OSA_UInt32 localI;
-
- CLEANUPonERR(M4MP4W_putBlock(EVRCBlock3_1, sizeof(EVRCBlock3_1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*audio*/
-
- /* copy the default block in a local variable*/
- for ( localI = 0; localI < 6; localI++ )
- {
- localDsi[localI] = EVRCBlock3_2[localI];
- }
- /* computes the number of sample per au */
- /* and stores it in the DSI*/
- /* assumes a char is enough to store the data*/
- localDsi[5] =
- (M4OSA_UInt8)(mMp4FileDataPtr->audioTrackPtr->sampleDuration
- / 160)/*EVRC 1 frame duration*/;
-
- if (mMp4FileDataPtr->audioTrackPtr->DSI != M4OSA_NULL)
- {
- /* copy vendor name */
- for ( localI = 0; localI < 4; localI++ )
- {
- localDsi[localI] = (M4OSA_UInt8)(
- mMp4FileDataPtr->audioTrackPtr->DSI[localI]);
- }
- }
- CLEANUPonERR(M4MP4W_putBlock(localDsi, 6,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*audio*/
- }
- else /*AMR8*/
- {
- M4OSA_UInt8 localDsi[9];
- M4OSA_UInt32 localI;
-
- CLEANUPonERR(M4MP4W_putBlock(AMRDSIHeader, sizeof(AMRDSIHeader),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /* copy the default block in a local variable*/
- for ( localI = 0; localI < 9; localI++ )
- {
- localDsi[localI] = AMRDefaultDSI[localI];
- }
- /* computes the number of sample per au */
- /* and stores it in the DSI*/
- /* assumes a char is enough to store the data*/
- /* ALERT! The potential of the following line of code to explode in our face
- is enormous when anything (sample rate or whatever) will change. This
- calculation would be MUCH better handled by the VES or whatever deals with
- the encoder more directly. */
- localDsi[8] =
- (M4OSA_UInt8)(mMp4FileDataPtr->audioTrackPtr->sampleDuration
- / 160)/*AMR NB 1 frame duration*/;
-
- if (mMp4FileDataPtr->audioTrackPtr->DSI != M4OSA_NULL)
- {
- /* copy vendor name */
- for ( localI = 0; localI < 4; localI++ )
- {
- localDsi[localI] = (M4OSA_UInt8)(
- mMp4FileDataPtr->audioTrackPtr->DSI[localI]);
- }
-
- /* copy the Mode Set */
- for ( localI = 5; localI < 7; localI++ )
- {
- localDsi[localI] = (M4OSA_UInt8)(
- mMp4FileDataPtr->audioTrackPtr->DSI[localI]);
- }
- }
- CLEANUPonERR(M4MP4W_putBlock(localDsi, 9,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*audio*/
- }
-
- /*end trak*/
- CLEANUPonERR(M4MP4W_putBE32(a_stszSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock15, sizeof(CommonBlock15),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /*0 value for samplesize means not constant AU size*/
- if (mMp4FileDataPtr->audioTrackPtr->CommonData.sampleSize == 0)
- {
- CLEANUPonERR(M4MP4W_putBlock((const M4OSA_UChar
- *)mMp4FileDataPtr->audioTrackPtr->TABLE_STSZ,
- mMp4FileDataPtr->audioTrackPtr->CommonData.sampleNb * 4,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- }
-
- CLEANUPonERR(M4MP4W_putBE32(a_stscSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock16, sizeof(CommonBlock16),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->currentStsc
- + 1, mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- for ( i = 0; i <= mMp4FileDataPtr->audioTrackPtr->currentStsc; i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(
- ( mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable[i]
- >> 12) + 1, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32((mMp4FileDataPtr->audioTrackPtr->
- chunkSampleNbTable[i] & 0xFFF),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(1, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
-#else
-
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->currentChunk
- + 1, mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- for ( i = 0; i <= mMp4FileDataPtr->audioTrackPtr->currentChunk; i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(i + 1,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->audioTrackPtr->chunkSampleNbTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(1, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
-#endif
-
- CLEANUPonERR(M4MP4W_putBE32(a_stcoSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock17, sizeof(CommonBlock17),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->audioTrackPtr->currentChunk
- + 1, mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- for ( i = 0; i <= mMp4FileDataPtr->audioTrackPtr->currentChunk; i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(a_trakOffset,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- a_trakOffset += mMp4FileDataPtr->audioTrackPtr->chunkSizeTable[i];
-
- if (( bInterleaveAV == M4OSA_TRUE)
- && (mMp4FileDataPtr->videoTrackPtr->currentChunk >= i))
- {
- a_trakOffset +=
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable[i];
- }
- }
-
-#else
-
- for ( i = 0; i <= mMp4FileDataPtr->audioTrackPtr->currentChunk; i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->audioTrackPtr->chunkOffsetTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- CLEANUPonERR(M4MP4W_putBlock(AMRBlock4, sizeof(AMRBlock4),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*audio*/
- }
-
- if (bVideo)
- {
- /*trak*/
- CLEANUPonERR(M4MP4W_putBE32(v_trakSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock6, sizeof(CommonBlock6),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(v_trakId,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock7, sizeof(CommonBlock7),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(v_msTrakDuration,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock7bis, sizeof(CommonBlock7bis),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /* In the track header width and height are 16.16 fixed point values,
- so shift left the regular integer value by 16. */
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->width << 16,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->height
- << 16,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
-
- CLEANUPonERR(M4MP4W_putBE32(v_mdiaSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock8, sizeof(CommonBlock8),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(creationTime,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->CommonData.timescale,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(v_trakDuration,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock9, sizeof(CommonBlock9),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(VideoBlock1_1, sizeof(VideoBlock1_1),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBE32(v_minfSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock10, sizeof(CommonBlock10),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(v_stblSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock11, sizeof(CommonBlock11),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(v_sttsSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock12, sizeof(CommonBlock12),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- for ( i = 0;
- i < mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb;
- i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(M4MP4W_get32_Lo(
- &mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[i]),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBE32(M4MP4W_get32_Hi(
- &mMp4FileDataPtr->videoTrackPtr->TABLE_STTS[i]),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*video*/
- }
-
-#else
-
- CLEANUPonERR(M4MP4W_putBlock((const M4OSA_UChar
- *)mMp4FileDataPtr->videoTrackPtr->TABLE_STTS,
- ( mMp4FileDataPtr->videoTrackPtr->CommonData.sttsTableEntryNb) * 8,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
-
-#endif
-
- /* stsd */
-
- CLEANUPonERR(M4MP4W_putBE32(v_stsdSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(SampleDescriptionHeader,
- sizeof(SampleDescriptionHeader),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(v_esdSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /* sample desc entry inside stsd */
- if (bMP4V)
- {
- CLEANUPonERR(M4MP4W_putBlock(Mp4vBlock1, sizeof(Mp4vBlock1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- }
-
- if (bH263)
- {
- CLEANUPonERR(M4MP4W_putBlock(H263Block1, sizeof(H263Block1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h263*/
- }
-
- if (bH264)
- {
- CLEANUPonERR(M4MP4W_putBlock(H264Block1, sizeof(H264Block1),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h264*/
- }
- CLEANUPonERR(M4MP4W_putBlock(SampleDescriptionEntryStart,
- sizeof(SampleDescriptionEntryStart),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(SampleDescriptionEntryVideoBoilerplate1,
- sizeof(SampleDescriptionEntryVideoBoilerplate1),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBE16(mMp4FileDataPtr->videoTrackPtr->width,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBE16(mMp4FileDataPtr->videoTrackPtr->height,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBlock(VideoResolutions, sizeof(VideoResolutions),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(SampleDescriptionEntryVideoBoilerplate2,
- sizeof(SampleDescriptionEntryVideoBoilerplate2),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
-
- /* DSI inside sample desc entry */
- if (bH263)
- {
- /* The h263 dsi given through the api must be 7 bytes, that is, it shall not include
- the optional bitrate box. However, if the bitrate information is set in the stream
- handler, a bitrate box is appended here to the dsi */
- if (((M4OSA_Int32)mMp4FileDataPtr->videoTrackPtr->avgBitrate) != -1)
- {
- CLEANUPonERR(M4MP4W_putBlock(H263Block2_bitr,
- sizeof(H263Block2_bitr),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /* d263 box with bitr atom */
-
- if (M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->DSI)
- {
- CLEANUPonERR(M4MP4W_putBlock(H263Block3, sizeof(H263Block3),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h263*/
- }
- else
- {
- CLEANUPonERR(
- M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->DSI,
- mMp4FileDataPtr->videoTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
- CLEANUPonERR(M4MP4W_putBlock(H263Block4, sizeof(H263Block4),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h263*/
- /* Pierre Lebeaupin 2008/04/29: the two following lines used to be swapped;
- I changed to this order in order to conform to 3GPP. */
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->avgBitrate,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h263*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->maxBitrate,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h263*/
- }
- else
- {
- CLEANUPonERR(M4MP4W_putBlock(H263Block2, sizeof(H263Block2),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /* d263 box */
-
- if (M4OSA_NULL == mMp4FileDataPtr->videoTrackPtr->DSI)
- {
- CLEANUPonERR(M4MP4W_putBlock(H263Block3, sizeof(H263Block3),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h263*/
- }
- else
- {
- CLEANUPonERR(
- M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->DSI,
- mMp4FileDataPtr->videoTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
- }
- }
-
- if (bMP4V)
- {
- M4OSA_UInt32 bufferSizeDB = 5 * mMp4FileDataPtr->videoTrackPtr->
- avgBitrate; /*bufferSizeDB set to 5 times the bitrate*/
-
- CLEANUPonERR(M4MP4W_putBE32(v_esdsSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock0,
- sizeof(MPEGConfigBlock0), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putByte(v_ESDescriptorSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock1,
- sizeof(MPEGConfigBlock1), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putByte(v_DCDescriptorSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(Mp4vBlock3, sizeof(Mp4vBlock3),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBE24(bufferSizeDB,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->maxBitrate,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->avgBitrate,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock2,
- sizeof(MPEGConfigBlock2), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putByte(mMp4FileDataPtr->videoTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->DSI,
- mMp4FileDataPtr->videoTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- CLEANUPonERR(M4MP4W_putBlock(MPEGConfigBlock3,
- sizeof(MPEGConfigBlock3), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*mp4v*/
- }
-
- if (bH264)
- {
- M4OSA_UInt16 ppsLentgh = 0; /* PPS length */
- M4OSA_UInt16 spsLentgh = 0; /* SPS length */
- M4OSA_UChar *tmpDSI = mMp4FileDataPtr->videoTrackPtr->DSI; /* DSI */
- M4OSA_UInt16 NumberOfPPS;
- M4OSA_UInt16 lCntPPS;
-
- /* Put the avcC (header + DSI) size */
- CLEANUPonERR(M4MP4W_putBE32(v_avcCSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h264*/
- /* Put the avcC header */
- CLEANUPonERR(M4MP4W_putBlock(H264Block2, sizeof(H264Block2),
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*h264*/
- /* Put the DSI (SPS + PPS) int the 3gp format*/
- /* SPS length in BE */
-
- if ((0x01 != mMp4FileDataPtr->videoTrackPtr->DSI[0]) ||
- (0x42 != mMp4FileDataPtr->videoTrackPtr->DSI[1]))
- {
- M4OSA_TRACE1_2("!!! M4MP4W_closeWrite ERROR : invalid AVCC 0x%X 0x%X",
- mMp4FileDataPtr->videoTrackPtr->DSI[0],
- mMp4FileDataPtr->videoTrackPtr->DSI[1]);
- return M4ERR_PARAMETER;
- }
- // Do not strip the DSI
- CLEANUPonERR( M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->DSI,
- mMp4FileDataPtr->videoTrackPtr->dsiSize,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext) );/*h264*/
-
- }
-
- /*end trak*/
- CLEANUPonERR(M4MP4W_putBE32(v_stszSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock15, sizeof(CommonBlock15),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- for ( i = 0; i < mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb;
- i++ )
- {
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*video*/
- }
-
-#else
-
- CLEANUPonERR(M4MP4W_putBlock((const M4OSA_UChar
- *)mMp4FileDataPtr->videoTrackPtr->TABLE_STSZ,
- mMp4FileDataPtr->videoTrackPtr->CommonData.sampleNb * 4,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
-
-#endif
-
- CLEANUPonERR(M4MP4W_putBE32(v_stscSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock16, sizeof(CommonBlock16),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
-#ifdef _M4MP4W_OPTIMIZE_FOR_PHONE
-
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->currentStsc
- + 1, mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- for ( i = 0; i <= mMp4FileDataPtr->videoTrackPtr->currentStsc; i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(
- ( mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable[i]
- >> 12) + 1, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32((mMp4FileDataPtr->videoTrackPtr->
- chunkSampleNbTable[i] & 0xFFF),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(1, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
-#else
-
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->currentChunk
- + 1, mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- for (i = 0; i <= mMp4FileDataPtr->videoTrackPtr->currentChunk; i++)
- {
- CLEANUPonERR(M4MP4W_putBE32(i + 1,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->videoTrackPtr->chunkSampleNbTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(1, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
-#endif
-
- CLEANUPonERR(M4MP4W_putBE32(v_stcoSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock17, sizeof(CommonBlock17),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->currentChunk
- + 1, mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
-#ifdef _M4MP4W_MOOV_FIRST
-
- for (i = 0; i <= mMp4FileDataPtr->videoTrackPtr->currentChunk; i++)
- {
- if (( bInterleaveAV == M4OSA_TRUE)
- && (mMp4FileDataPtr->audioTrackPtr->currentChunk >= i))
- {
- v_trakOffset +=
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable[i];
- }
- CLEANUPonERR(M4MP4W_putBE32(v_trakOffset,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- v_trakOffset += mMp4FileDataPtr->videoTrackPtr->chunkSizeTable[i];
- }
-
-#else
-
- for ( i = 0; i <= mMp4FileDataPtr->videoTrackPtr->currentChunk; i++ )
- {
- CLEANUPonERR(M4MP4W_putBE32(
- mMp4FileDataPtr->videoTrackPtr->chunkOffsetTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- }
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- CLEANUPonERR(M4MP4W_putBE32(v_stssSize,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBlock(VideoBlock4, sizeof(VideoBlock4),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(
- M4MP4W_putBE32(mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb,
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBlock((const M4OSA_UChar
- *)mMp4FileDataPtr->videoTrackPtr->TABLE_STSS,
- mMp4FileDataPtr->videoTrackPtr->stssTableEntryNb * 4,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- CLEANUPonERR(M4MP4W_putBlock(VideoBlock5, sizeof(VideoBlock5),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext)); /*video*/
- }
-#ifdef _M4MP4W_MOOV_FIRST
- /*mdat*/
-
- CLEANUPonERR(M4MP4W_putBE32(mdatSize, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putBlock(CommonBlock2, sizeof(CommonBlock2),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /*write data, according to the interleave mode (default is not interleaved)*/
- if (bInterleaveAV == M4OSA_FALSE)
- {
- if (bAudio)
- {
- for ( i = 0; i <= mMp4FileDataPtr->audioTrackPtr->currentChunk;
- i++ )
- {
- CLEANUPonERR(
- M4MP4W_putBlock(mMp4FileDataPtr->audioTrackPtr->Chunk[i],
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*audio (previously a_dataSize)*/
- }
- }
-
- if (bVideo)
- {
- for ( i = 0; i <= mMp4FileDataPtr->videoTrackPtr->currentChunk;
- i++ )
- {
- CLEANUPonERR(
- M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->Chunk[i],
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*video (previously a_dataSize)*/
- }
- }
- }
- else /*in this mode, we have audio and video to interleave*/
- {
- for ( i = 0; i <= max(mMp4FileDataPtr->audioTrackPtr->currentChunk,
- mMp4FileDataPtr->videoTrackPtr->currentChunk); i++ )
- {
- if (i <= mMp4FileDataPtr->audioTrackPtr->currentChunk)
- {
- CLEANUPonERR(
- M4MP4W_putBlock(mMp4FileDataPtr->audioTrackPtr->Chunk[i],
- mMp4FileDataPtr->audioTrackPtr->chunkSizeTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*audio (previously a_dataSize)*/
- }
-
- if (i <= mMp4FileDataPtr->videoTrackPtr->currentChunk)
- {
- CLEANUPonERR(
- M4MP4W_putBlock(mMp4FileDataPtr->videoTrackPtr->Chunk[i],
- mMp4FileDataPtr->videoTrackPtr->chunkSizeTable[i],
- mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext)); /*video (previously a_dataSize)*/
- }
- }
- }
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
- /*skip*/
-
- CLEANUPonERR(M4MP4W_putBlock(BlockSignatureSkipHeader,
- sizeof(BlockSignatureSkipHeader), mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
-
- /* Write embedded string */
- if (mMp4FileDataPtr->embeddedString == M4OSA_NULL)
- {
- CLEANUPonERR(M4MP4W_putBlock(BlockSignatureSkipDefaultEmbeddedString,
- sizeof(BlockSignatureSkipDefaultEmbeddedString),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- }
- else
- {
- CLEANUPonERR(M4MP4W_putBlock(mMp4FileDataPtr->embeddedString, 16,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- }
-
- /* Write ves core version */
- camcoder_maj = (M4OSA_UChar)(mMp4FileDataPtr->camcoderVersion / 100);
- camcoder_min =
- (M4OSA_UChar)(( mMp4FileDataPtr->camcoderVersion - 100 * camcoder_maj)
- / 10);
- camcoder_rev =
- (M4OSA_UChar)(mMp4FileDataPtr->camcoderVersion - 100 * camcoder_maj - 10
- * camcoder_min);
-
- CLEANUPonERR(M4MP4W_putByte(' ', mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putByte((M4OSA_UChar)(camcoder_maj + '0'),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putByte('.', mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putByte((M4OSA_UChar)(camcoder_min + '0'),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- CLEANUPonERR(M4MP4W_putByte('.', mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
- CLEANUPonERR(M4MP4W_putByte((M4OSA_UChar)(camcoder_rev + '0'),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- /* Write integration tag */
- CLEANUPonERR(M4MP4W_putBlock((const M4OSA_UChar *)" -- ", 4,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
-
- if (mMp4FileDataPtr->integrationTag == M4OSA_NULL)
- {
- CLEANUPonERR(M4MP4W_putBlock(BlockSignatureSkipDefaultIntegrationTag,
- sizeof(BlockSignatureSkipDefaultIntegrationTag),
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- }
- else
- {
- CLEANUPonERR(M4MP4W_putBlock(mMp4FileDataPtr->integrationTag, 60,
- mMp4FileDataPtr->fileWriterFunctions, fileWriterContext));
- }
-
-#ifndef _M4MP4W_MOOV_FIRST
- /*overwrite mdat size*/
-
- if (mMp4FileDataPtr->ftyp.major_brand != 0)
- mdatPos= 16 + mMp4FileDataPtr->ftyp.nbCompatibleBrands * 4;
- else
- mdatPos = 24;
-
- moovPos = moovPos - mdatPos;
- mdatSize = moovPos;
-
- CLEANUPonERR(mMp4FileDataPtr->fileWriterFunctions->seek(fileWriterContext,
- M4OSA_kFileSeekBeginning, &mdatPos)); /*seek after ftyp...*/
- CLEANUPonERR(M4MP4W_putBE32(mdatSize, mMp4FileDataPtr->fileWriterFunctions,
- fileWriterContext));
-
-#endif /*_M4MP4W_MOOV_FIRST*/
-
-cleanup:
-
- /**
- * Close the file even if an error occured */
- if (M4OSA_NULL != mMp4FileDataPtr->fileWriterContext)
- {
- err2 =
- mMp4FileDataPtr->fileWriterFunctions->closeWrite(mMp4FileDataPtr->
- fileWriterContext); /**< close the stream anyway */
-
- if (M4NO_ERROR != err2)
- {
- M4OSA_TRACE1_1(
- "M4MP4W_closeWrite: fileWriterFunctions->closeWrite returns 0x%x",
- err2);
- }
- mMp4FileDataPtr->fileWriterContext = M4OSA_NULL;
- }
-
-#ifdef _M4MP4W_RESERVED_MOOV_DISK_SPACE
- /* Remove safety file if still present (here it is cleanup in case of error and NOT the normal
- removal of the safety file to free emergency space for the moov). */
-
- if (M4OSA_TRUE == mMp4FileDataPtr->cleanSafetyFile)
- {
- M4OSA_Context tempContext;
- err3 = mMp4FileDataPtr->fileWriterFunctions->openWrite(&tempContext,
- mMp4FileDataPtr->safetyFileUrl,
- M4OSA_kFileWrite | M4OSA_kFileCreate);
-
- if (M4NO_ERROR != err2)
- err2 = err3;
-
- if (M4NO_ERROR
- != err3) /* No sense closing if we couldn't open in the first place. */
- {
- err3 =
- mMp4FileDataPtr->fileWriterFunctions->closeWrite(tempContext);
-
- if (M4NO_ERROR != err2)
- err2 = err3;
- }
- mMp4FileDataPtr->safetyFileUrl = M4OSA_NULL;
- mMp4FileDataPtr->cleanSafetyFile = M4OSA_FALSE;
- }
-
-#endif /* _M4MP4W_RESERVED_MOOV_DISK_SPACE */
-
- /* Delete embedded string */
-
- if (M4OSA_NULL != mMp4FileDataPtr->embeddedString)
- {
- free(mMp4FileDataPtr->embeddedString);
- mMp4FileDataPtr->embeddedString = M4OSA_NULL;
- }
-
- /* Delete integration tag */
- if (M4OSA_NULL != mMp4FileDataPtr->integrationTag)
- {
- free(mMp4FileDataPtr->integrationTag);
- mMp4FileDataPtr->integrationTag = M4OSA_NULL;
- }
-
- /**
- * M4MP4W_freeContext() is now a private method, called only from here*/
- err3 = M4MP4W_freeContext(context);
-
- if (M4NO_ERROR != err3)
- {
- M4OSA_TRACE1_1("M4MP4W_closeWrite: M4MP4W_freeContext returns 0x%x",
- err3);
- }
-
- /**
- * Choose which error code to return */
- if (M4NO_ERROR != err)
- {
- /**
- * We give priority to main error */
- M4OSA_TRACE1_1("M4MP4W_closeWrite: returning err=0x%x", err);
- return err;
- }
- else if (M4NO_ERROR != err2)
- {
- /**
- * Error from closeWrite is returned if there is no main error */
- M4OSA_TRACE1_1("M4MP4W_closeWrite: returning err2=0x%x", err2);
- return err2;
- }
- else
- {
- /**
- * Error from M4MP4W_freeContext is returned only if there is no main error and
- no close error */
- M4OSA_TRACE1_1("M4MP4W_closeWrite: returning err3=0x%x", err3);
- return err3;
- }
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_getOption( M4OSA_Context context, M4OSA_OptionID option,
- M4OSA_DataOption *valuePtr )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4SYS_StreamIDValue *streamIDvaluePtr = M4OSA_NULL;
- M4MP4W_StreamIDsize *streamIDsizePtr = M4OSA_NULL;
- M4MP4W_memAddr *memAddrPtr = M4OSA_NULL;
- /* M4MP4W_WriteCallBack* callBackPtr = M4OSA_NULL;*/
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- ERR_CHECK(( mMp4FileDataPtr->state == M4MP4W_opened)
- || (mMp4FileDataPtr->state == M4MP4W_ready), M4ERR_STATE);
-
- switch( option )
- {
- case (M4MP4W_maxAUperChunk):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_maxChunkSize):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)(*valuePtr);
-
- switch( streamIDvaluePtr->streamID )
- {
- case (AudioStreamID):
- if (mMp4FileDataPtr->hasAudio == M4OSA_FALSE)
- return M4ERR_BAD_STREAM_ID;
- else
- streamIDvaluePtr->value =
- mMp4FileDataPtr->audioTrackPtr->MaxChunkSize;
- break;
-
- case (VideoStreamID):
- if (mMp4FileDataPtr->hasVideo == M4OSA_FALSE)
- return M4ERR_BAD_STREAM_ID;
- else
- streamIDvaluePtr->value =
- mMp4FileDataPtr->videoTrackPtr->MaxChunkSize;
- break;
-
- case (0): /*all streams*/
- streamIDvaluePtr->value = mMp4FileDataPtr->MaxChunkSize;
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
-
- break;
-
- case (M4MP4W_maxChunkInter):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)(*valuePtr);
-
- switch( streamIDvaluePtr->streamID )
- {
- case (0): /*all streams*/
- streamIDvaluePtr->value = (M4OSA_UInt32)mMp4FileDataPtr->
- InterleaveDur; /*time conversion !*/
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- case (M4MP4W_embeddedString):
- memAddrPtr = (M4MP4W_memAddr *)(*valuePtr);
- /*memAddrPtr must have been already allocated by the caller
- and memAddrPtr->size initialized with the max possible length in bytes*/
- ERR_CHECK(memAddrPtr->size >= 16, M4ERR_PARAMETER);
- ERR_CHECK(memAddrPtr->addr != M4OSA_NULL, M4ERR_PARAMETER);
- /*memAddrPtr->size is updated with the actual size of the string*/
- memAddrPtr->size = 16;
- /*if no value was set, return the default string */
- if (mMp4FileDataPtr->embeddedString != M4OSA_NULL)
- memcpy((void *)memAddrPtr->addr,
- (void *)mMp4FileDataPtr->embeddedString, 16);
- else
- memcpy((void *)memAddrPtr->addr,
- (void *)BlockSignatureSkipDefaultEmbeddedString,
- 16);
- break;
-
- case (M4MP4W_integrationTag):
- memAddrPtr = (M4MP4W_memAddr *)(*valuePtr);
- /*memAddrPtr must have been already allocated by the caller
- and memAddrPtr->size initialized with the max possible length in bytes*/
- ERR_CHECK(memAddrPtr->size >= 60, M4ERR_PARAMETER);
- ERR_CHECK(memAddrPtr->addr != M4OSA_NULL, M4ERR_PARAMETER);
- /*memAddrPtr->size is updated with the actual size of the string*/
- memAddrPtr->size = 60;
- /*if no value was set, return the default string 0 */
- if (mMp4FileDataPtr->integrationTag != M4OSA_NULL)
- memcpy((void *)memAddrPtr->addr,
- (void *)mMp4FileDataPtr->integrationTag, 60);
- else
- memcpy((void *)memAddrPtr->addr,
- (void *)BlockSignatureSkipDefaultIntegrationTag,
- 60);
- break;
-
- case (M4MP4W_CamcoderVersion):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)(*valuePtr);
-
- switch( streamIDvaluePtr->streamID )
- {
- case (0): /*all streams*/
- streamIDvaluePtr->value = mMp4FileDataPtr->camcoderVersion;
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- case (M4MP4W_preWriteCallBack):
- return M4ERR_NOT_IMPLEMENTED;
- /*callBackPtr = (M4MP4W_WriteCallBack*)(*valuePtr);
- *callBackPtr = mMp4FileDataPtr->PreWriteCallBack;
- break;*/
-
- case (M4MP4W_postWriteCallBack):
- return M4ERR_NOT_IMPLEMENTED;
- /*callBackPtr = (M4MP4W_WriteCallBack*)(*valuePtr);
- *callBackPtr = mMp4FileDataPtr->PostWriteCallBack;
- break;*/
-
- case (M4MP4W_maxAUsize):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)(*valuePtr);
-
- switch( streamIDvaluePtr->streamID )
- {
- case (AudioStreamID):
- if (mMp4FileDataPtr->hasAudio == M4OSA_FALSE)
- return M4ERR_BAD_STREAM_ID;
- else
- streamIDvaluePtr->value =
- mMp4FileDataPtr->audioTrackPtr->MaxAUSize;
- break;
-
- case (VideoStreamID):
- if (mMp4FileDataPtr->hasVideo == M4OSA_FALSE)
- return M4ERR_BAD_STREAM_ID;
- else
- streamIDvaluePtr->value =
- mMp4FileDataPtr->videoTrackPtr->MaxAUSize;
- break;
-
- case (0): /*all streams*/
- streamIDvaluePtr->value = mMp4FileDataPtr->MaxAUSize;
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
-
- break;
-
- case (M4MP4W_IOD):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_ESD):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_SDP):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_trackSize):
- streamIDsizePtr = (M4MP4W_StreamIDsize *)(*valuePtr);
- streamIDsizePtr->width = mMp4FileDataPtr->videoTrackPtr->width;
- streamIDsizePtr->height = mMp4FileDataPtr->videoTrackPtr->height;
- break;
-
- case (M4MP4W_estimateAudioSize):
- streamIDvaluePtr = (M4SYS_StreamIDValue *)(*valuePtr);
- streamIDvaluePtr->value =
- (M4OSA_UInt32)mMp4FileDataPtr->estimateAudioSize;
- break;
-
- case (M4MP4W_MOOVfirst):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_V2_MOOF):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_V2_tblCompres):
- return M4ERR_NOT_IMPLEMENTED;
-
- default:
- return M4ERR_BAD_OPTION_ID;
- }
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_setOption( M4OSA_Context context, M4OSA_OptionID option,
- M4OSA_DataOption value )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4SYS_StreamIDValue *streamIDvaluePtr = M4OSA_NULL;
- M4MP4W_StreamIDsize *streamIDsizePtr = M4OSA_NULL;
- M4MP4W_memAddr *memAddrPtr = M4OSA_NULL;
- M4SYS_StreamIDmemAddr *streamIDmemAddrPtr;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- /* Verify state */
- switch( option )
- {
- case M4MP4W_maxFileDuration:
- case M4MP4W_DSI:
- /* this param can be set at the end of a recording */
- ERR_CHECK((mMp4FileDataPtr->state != M4MP4W_closed), M4ERR_STATE);
- break;
-
- case M4MP4W_setFtypBox:
- /* this param can only be set before starting any write */
- ERR_CHECK(mMp4FileDataPtr->state == M4MP4W_opened, M4ERR_STATE);
- break;
-
- default:
- /* in general params can be set at open or ready stage */
- ERR_CHECK(( mMp4FileDataPtr->state == M4MP4W_opened)
- || (mMp4FileDataPtr->state == M4MP4W_ready), M4ERR_STATE);
- }
-
- /* Set option */
- switch( option )
- {
- case (M4MP4W_maxAUperChunk):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_maxChunkSize):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)value;
-
- switch( streamIDvaluePtr->streamID )
- {
- case (AudioStreamID):
- if (mMp4FileDataPtr->hasAudio == M4OSA_FALSE)
- return
- M4ERR_BAD_STREAM_ID; /*maybe the stream has not been added yet*/
- else
- {
- mMp4FileDataPtr->audioTrackPtr->MaxChunkSize =
- streamIDvaluePtr->value;
- }
-
- break;
-
- case (VideoStreamID):
- if (mMp4FileDataPtr->hasVideo == M4OSA_FALSE)
- return
- M4ERR_BAD_STREAM_ID; /*maybe the stream has not been added yet*/
- else
- {
- mMp4FileDataPtr->videoTrackPtr->MaxChunkSize =
- streamIDvaluePtr->value;
- }
- break;
-
- case (0): /*all streams*/
-
- /*In M4MP4W_opened state, no stream is present yet, so only global value
- needs to be updated.*/
- mMp4FileDataPtr->MaxChunkSize = streamIDvaluePtr->value;
-
- if (mMp4FileDataPtr->hasAudio == M4OSA_TRUE)
- {
- mMp4FileDataPtr->audioTrackPtr->MaxChunkSize =
- streamIDvaluePtr->value;
- }
-
- if (mMp4FileDataPtr->hasVideo == M4OSA_TRUE)
- {
- mMp4FileDataPtr->videoTrackPtr->MaxChunkSize =
- streamIDvaluePtr->value;
- }
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- case (M4MP4W_maxChunkInter):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)value;
-
- switch( streamIDvaluePtr->streamID )
- {
- case (0): /*all streams*/
- mMp4FileDataPtr->InterleaveDur =
- (M4MP4W_Time32)streamIDvaluePtr->
- value; /*time conversion!*/
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- /*not meaningfull to set this parameter on a streamID basis*/
- }
- break;
-
- case (M4MP4W_maxFileSize):
- mMp4FileDataPtr->MaxFileSize = *(M4OSA_UInt32 *)value;
- break;
-
- case (M4MP4W_embeddedString):
- memAddrPtr = (M4MP4W_memAddr *)value;
- /*
- * If memAddrPtr->size > 16 bytes, then the string will be truncated.
- * If memAddrPtr->size < 16 bytes, then return M4ERR_PARAMETER
- */
- ERR_CHECK(memAddrPtr->size >= 16, M4ERR_PARAMETER);
-
- if (mMp4FileDataPtr->embeddedString == M4OSA_NULL)
- {
- mMp4FileDataPtr->embeddedString =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(16, M4MP4_WRITER,
- (M4OSA_Char *)"embeddedString");
- ERR_CHECK(mMp4FileDataPtr->embeddedString != M4OSA_NULL,
- M4ERR_ALLOC);
- }
- /*else, just overwrite the previously set string*/
- memcpy((void *)mMp4FileDataPtr->embeddedString,
- (void *)memAddrPtr->addr, 16);
- break;
-
- case (M4MP4W_integrationTag):
- memAddrPtr = (M4MP4W_memAddr *)value;
- /*
- * If memAddrPtr->size > 60 bytes, then the string will be truncated.
- * If memAddrPtr->size < 60 bytes, then pad with 0
- */
- if (mMp4FileDataPtr->integrationTag == M4OSA_NULL)
- {
- mMp4FileDataPtr->integrationTag =
- (M4OSA_UChar *)M4OSA_32bitAlignedMalloc(60, M4MP4_WRITER,
- (M4OSA_Char *)"integrationTag");
- ERR_CHECK(mMp4FileDataPtr->integrationTag != M4OSA_NULL,
- M4ERR_ALLOC);
- }
- /*else, just overwrite the previously set string*/
- if (memAddrPtr->size < 60)
- {
- memcpy((void *)mMp4FileDataPtr->integrationTag,
- (void *)BlockSignatureSkipDefaultIntegrationTag,
- 60);
- memcpy((void *)mMp4FileDataPtr->integrationTag,
- (void *)memAddrPtr->addr, memAddrPtr->size);
- }
- else
- {
- memcpy((void *)mMp4FileDataPtr->integrationTag,
- (void *)memAddrPtr->addr, 60);
- }
- break;
-
- case (M4MP4W_CamcoderVersion):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)value;
-
- switch( streamIDvaluePtr->streamID )
- {
- case (0): /*all streams*/
- mMp4FileDataPtr->camcoderVersion = streamIDvaluePtr->value;
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- /*not meaningfull to set this parameter on a streamID basis*/
- }
- break;
-
- case (M4MP4W_preWriteCallBack):
- return M4ERR_NOT_IMPLEMENTED;
- /*mMp4FileDataPtr->PreWriteCallBack = *(M4MP4W_WriteCallBack*)value;
- break;*/
-
- case (M4MP4W_postWriteCallBack):
- return M4ERR_NOT_IMPLEMENTED;
- /*mMp4FileDataPtr->PostWriteCallBack = *(M4MP4W_WriteCallBack*)value;
- break;*/
-
- case (M4MP4W_maxAUsize):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)value;
-
- switch( streamIDvaluePtr->streamID )
- {
- case (AudioStreamID):
-
- /*if (mMp4FileDataPtr->audioTrackPtr == M4OSA_NULL)*/
- if (mMp4FileDataPtr->hasAudio == M4OSA_FALSE)
- return M4ERR_BAD_STREAM_ID;
- else
- mMp4FileDataPtr->audioTrackPtr->MaxAUSize =
- streamIDvaluePtr->value;
- break;
-
- case (VideoStreamID):
-
- /*if (mMp4FileDataPtr->videoTrackPtr == M4OSA_NULL)*/
- if (mMp4FileDataPtr->hasVideo == M4OSA_FALSE)
- return M4ERR_BAD_STREAM_ID;
- else
- mMp4FileDataPtr->videoTrackPtr->MaxAUSize =
- streamIDvaluePtr->value;
- break;
-
- case (0): /*all streams*/
-
- mMp4FileDataPtr->MaxAUSize = streamIDvaluePtr->value;
-
- if (mMp4FileDataPtr->hasAudio == M4OSA_TRUE)
- mMp4FileDataPtr->audioTrackPtr->MaxAUSize =
- streamIDvaluePtr->value;
-
- if (mMp4FileDataPtr->hasVideo == M4OSA_TRUE)
- mMp4FileDataPtr->videoTrackPtr->MaxAUSize =
- streamIDvaluePtr->value;
-
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- case (M4MP4W_IOD):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_ESD):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_SDP):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_trackSize):
-
- streamIDsizePtr = (M4MP4W_StreamIDsize *)value;
-
- if ((streamIDsizePtr->streamID != VideoStreamID)
- || (mMp4FileDataPtr->hasVideo == M4OSA_FALSE))
- return M4ERR_BAD_STREAM_ID;
- else
- {
- mMp4FileDataPtr->videoTrackPtr->width = streamIDsizePtr->width;
- mMp4FileDataPtr->videoTrackPtr->height =
- streamIDsizePtr->height;
- }
- break;
-
- case (M4MP4W_estimateAudioSize):
-
- streamIDvaluePtr = (M4SYS_StreamIDValue *)value;
-
- /*shall not set this option before audio and video streams were added*/
- /*nonsense to set this option if not in case audio+video*/
- if ((mMp4FileDataPtr->hasAudio == M4OSA_FALSE)
- || (mMp4FileDataPtr->hasVideo == M4OSA_FALSE))
- return M4ERR_STATE;
-
- mMp4FileDataPtr->estimateAudioSize =
- (M4OSA_Bool)streamIDvaluePtr->value;
- break;
-
- case (M4MP4W_MOOVfirst):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_V2_MOOF):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_V2_tblCompres):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (M4MP4W_maxFileDuration):
- mMp4FileDataPtr->MaxFileDuration = *(M4OSA_UInt32 *)value;
- break;
-
- case (M4MP4W_setFtypBox):
- {
- M4OSA_UInt32 size;
-
- ERR_CHECK(( (M4MP4C_FtypBox *)value)->major_brand != 0,
- M4ERR_PARAMETER);
-
- /* Copy structure */
- mMp4FileDataPtr->ftyp = *(M4MP4C_FtypBox *)value;
-
- /* Update global position variables with the difference between common and
- user block */
- size =
- mMp4FileDataPtr->ftyp.nbCompatibleBrands * sizeof(M4OSA_UInt32);
-
- mMp4FileDataPtr->absoluteCurrentPos = 8/*mdat*/ + 16 + size;
- mMp4FileDataPtr->filesize = 218/*mdat+moov+skip*/ + 16 + size;
- }
- break;
-
- case (M4MP4W_DSI):
- {
- streamIDmemAddrPtr = (M4SYS_StreamIDmemAddr *)value;
-
- /* Nested switch! Whee! */
- switch( streamIDmemAddrPtr->streamID )
- {
- case (AudioStreamID):
- return M4ERR_NOT_IMPLEMENTED;
-
- case (VideoStreamID):
-
- /* Protect DSI setting : only once allowed on a given stream */
-
- switch( mMp4FileDataPtr->videoTrackPtr->
- CommonData.trackType )
- {
- case M4SYS_kH263:
- if ((0 != mMp4FileDataPtr->videoTrackPtr->dsiSize)
- || (M4OSA_NULL
- != mMp4FileDataPtr->videoTrackPtr->DSI))
- {
- M4OSA_TRACE1_0(
- "M4MP4W_setOption: dsi already set !");
- return M4ERR_STATE;
- }
-
- if ((0 == streamIDmemAddrPtr->size)
- || (M4OSA_NULL == streamIDmemAddrPtr->addr))
- {
- M4OSA_TRACE1_0(
- "M4MP4W_setOption: Bad H263 dsi!");
- return M4ERR_PARAMETER;
- }
-
- /*decoder specific info size is supposed to be always 7
- bytes long */
- ERR_CHECK(streamIDmemAddrPtr->size == 7,
- M4ERR_PARAMETER);
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamIDmemAddrPtr->size;
- mMp4FileDataPtr->videoTrackPtr->DSI = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(streamIDmemAddrPtr->size,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI
- != M4OSA_NULL, M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->
- DSI,
- (void *)streamIDmemAddrPtr->addr,
- streamIDmemAddrPtr->size);
-
- break;
-
- case M4SYS_kMPEG_4:
- if ((0 != mMp4FileDataPtr->videoTrackPtr->dsiSize)
- || (M4OSA_NULL
- != mMp4FileDataPtr->videoTrackPtr->DSI))
- {
- M4OSA_TRACE1_0(
- "M4MP4W_setOption: dsi already set !");
- return M4ERR_STATE;
- }
-
- if ((0 == streamIDmemAddrPtr->size)
- || (M4OSA_NULL == streamIDmemAddrPtr->addr))
- {
- M4OSA_TRACE1_0(
- "M4MP4W_setOption: Bad MPEG4 dsi!");
- return M4ERR_PARAMETER;
- }
-
- /*MP4V specific*/
- ERR_CHECK(streamIDmemAddrPtr->size < 105,
- M4ERR_PARAMETER);
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamIDmemAddrPtr->size;
- mMp4FileDataPtr->videoTrackPtr->DSI = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(streamIDmemAddrPtr->size,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI
- != M4OSA_NULL, M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->
- DSI,
- (void *)streamIDmemAddrPtr->addr,
- streamIDmemAddrPtr->size);
- mMp4FileDataPtr->filesize +=
- streamIDmemAddrPtr->size;
-
- break;
-
- case M4SYS_kH264:
- if ((0 != mMp4FileDataPtr->videoTrackPtr->dsiSize)
- || (M4OSA_NULL
- != mMp4FileDataPtr->videoTrackPtr->DSI))
- {
- /* + H.264 trimming */
- if (M4OSA_TRUE == mMp4FileDataPtr->bMULPPSSPS)
- {
- free(mMp4FileDataPtr->videoTrackPtr->DSI);
-
- // Do not strip the DSI
- /* Store the DSI size */
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamIDmemAddrPtr->size;
- M4OSA_TRACE1_1("M4MP4W_setOption: in set option DSI size =%d"\
- ,mMp4FileDataPtr->videoTrackPtr->dsiSize);
- /* Copy the DSI (SPS + PPS) */
- mMp4FileDataPtr->videoTrackPtr->DSI =
- (M4OSA_UChar*)M4OSA_32bitAlignedMalloc(
- streamIDmemAddrPtr->size, M4MP4_WRITER,
- (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI !=
- M4OSA_NULL, M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->DSI,
- (void *)streamIDmemAddrPtr->addr,
- streamIDmemAddrPtr->size);
-
- break;
- /* - H.264 trimming */
- }
- else
- {
- M4OSA_TRACE1_0(
- "M4MP4W_setOption: dsi already set !");
- return M4ERR_STATE;
- }
- }
-
- if (( 0 == streamIDmemAddrPtr->size)
- || (M4OSA_NULL == streamIDmemAddrPtr->addr))
- {
- M4OSA_TRACE1_0(
- "M4MP4W_setOption: Bad H264 dsi!");
- return M4ERR_PARAMETER;
- }
-
- /* Store the DSI size */
- mMp4FileDataPtr->videoTrackPtr->dsiSize =
- (M4OSA_UInt8)streamIDmemAddrPtr->size;
-
- /* Copy the DSI (SPS + PPS) */
- mMp4FileDataPtr->videoTrackPtr->DSI = (M4OSA_UChar
- *)M4OSA_32bitAlignedMalloc(streamIDmemAddrPtr->size,
- M4MP4_WRITER, (M4OSA_Char *)"videoTrackPtr->DSI");
- ERR_CHECK(mMp4FileDataPtr->videoTrackPtr->DSI
- != M4OSA_NULL, M4ERR_ALLOC);
- memcpy(
- (void *)mMp4FileDataPtr->videoTrackPtr->
- DSI,
- (void *)streamIDmemAddrPtr->addr,
- streamIDmemAddrPtr->size);
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
- }
- break;
- /* H.264 Trimming */
- case M4MP4W_MUL_PPS_SPS:
- mMp4FileDataPtr->bMULPPSSPS = *(M4OSA_Int8 *)value;
- /* H.264 Trimming */
- break;
-
- default:
- return M4ERR_BAD_OPTION_ID;
- }
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_getState( M4OSA_Context context, M4MP4W_State *state,
- M4SYS_StreamID streamID )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- switch( streamID )
- {
- case (0):
- *state = mMp4FileDataPtr->state;
- break;
-
- case (AudioStreamID):
- if (mMp4FileDataPtr->hasAudio == M4OSA_TRUE)
- {
- *state = mMp4FileDataPtr->audioTrackPtr->microState;
- }
- else
- {
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- case (VideoStreamID):
- if (mMp4FileDataPtr->hasVideo == M4OSA_TRUE)
- {
- *state = mMp4FileDataPtr->videoTrackPtr->microState;
- }
- else
- {
- return M4ERR_BAD_STREAM_ID;
- }
- break;
-
- default:
- return M4ERR_BAD_STREAM_ID;
- }
-
- return err;
-}
-
-/*******************************************************************************/
-M4OSA_ERR M4MP4W_getCurrentFileSize( M4OSA_Context context,
- M4OSA_UInt32 *pCurrentFileSize )
-/*******************************************************************************/
-{
- M4OSA_ERR err = M4NO_ERROR;
-
- M4MP4W_Mp4FileData *mMp4FileDataPtr = (M4MP4W_Mp4FileData *)context;
- ERR_CHECK(context != M4OSA_NULL, M4ERR_PARAMETER);
-
- ERR_CHECK(pCurrentFileSize != M4OSA_NULL, M4ERR_PARAMETER);
- *pCurrentFileSize = mMp4FileDataPtr->filesize;
-
- return err;
-}
-
-#endif /* _M4MP4W_USE_CST_MEMORY_WRITER */