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