os/mm/mmplugins/lib3gp/impl/src/compose.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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