mp4.c
上传用户:riyaled888
上传日期:2009-03-27
资源大小:7338k
文件大小:60k
源码类别:

多媒体

开发平台:

MultiPlatform

  1. /*****************************************************************************
  2.  * mp4.c: mp4/mov muxer
  3.  *****************************************************************************
  4.  * Copyright (C) 2001, 2002, 2003 VideoLAN
  5.  * $Id: mp4.c 9078 2004-10-29 09:19:38Z gbazin $
  6.  *
  7.  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
  8.  *          Gildas Bazin <gbazin at videolan dot org>
  9.  *
  10.  * This program is free software; you can redistribute it and/or modify
  11.  * it under the terms of the GNU General Public License as published by
  12.  * the Free Software Foundation; either version 2 of the License, or
  13.  * (at your option) any later version.
  14.  *
  15.  * This program is distributed in the hope that it will be useful,
  16.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  18.  * GNU General Public License for more details.
  19.  *
  20.  * You should have received a copy of the GNU General Public License
  21.  * along with this program; if not, write to the Free Software
  22.  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
  23.  *****************************************************************************/
  24. /*****************************************************************************
  25.  * Preamble
  26.  *****************************************************************************/
  27. #include <stdlib.h>
  28. #include <string.h>
  29. #include <vlc/vlc.h>
  30. #include <vlc/input.h>
  31. #include <vlc/sout.h>
  32. #ifdef HAVE_TIME_H
  33. #include <time.h>
  34. #endif
  35. #include "iso_lang.h"
  36. #include "vlc_meta.h"
  37. /*****************************************************************************
  38.  * Module descriptor
  39.  *****************************************************************************/
  40. #define FASTSTART_TEXT N_("Create "Fast start" files")
  41. #define FASTSTART_LONGTEXT N_( 
  42.     "When this option is turned on, "Fast start" files will be created. " 
  43.     "("Fast start" files are optimized for download, allowing the user " 
  44.     "to start previewing the file while it is downloading).")
  45. static int  Open   ( vlc_object_t * );
  46. static void Close  ( vlc_object_t * );
  47. #define SOUT_CFG_PREFIX "sout-mp4-"
  48. vlc_module_begin();
  49.     set_description( _("MP4/MOV muxer") );
  50.     add_bool( SOUT_CFG_PREFIX "faststart", 1, NULL, FASTSTART_TEXT, FASTSTART_LONGTEXT,
  51.               VLC_TRUE );
  52.     set_capability( "sout mux", 5 );
  53.     add_shortcut( "mp4" );
  54.     add_shortcut( "mov" );
  55.     add_shortcut( "3gp" );
  56.     set_callbacks( Open, Close );
  57. vlc_module_end();
  58. /*****************************************************************************
  59.  * Exported prototypes
  60.  *****************************************************************************/
  61. static const char *ppsz_sout_options[] = {
  62.     "faststart", NULL
  63. };
  64. static int Control( sout_mux_t *, int, va_list );
  65. static int AddStream( sout_mux_t *, sout_input_t * );
  66. static int DelStream( sout_mux_t *, sout_input_t * );
  67. static int Mux      ( sout_mux_t * );
  68. /*****************************************************************************
  69.  * Local prototypes
  70.  *****************************************************************************/
  71. typedef struct
  72. {
  73.     uint64_t i_pos;
  74.     int      i_size;
  75.     mtime_t  i_pts_dts;
  76.     mtime_t  i_length;
  77.     unsigned int i_flags;
  78. } mp4_entry_t;
  79. typedef struct
  80. {
  81.     es_format_t   fmt;
  82.     int           i_track_id;
  83.     /* index */
  84.     unsigned int i_entry_count;
  85.     unsigned int i_entry_max;
  86.     mp4_entry_t  *entry;
  87.     int64_t      i_length_neg;
  88.     /* stats */
  89.     int64_t      i_dts_start;
  90.     int64_t      i_duration;
  91.     /* for later stco fix-up (fast start files) */
  92.     uint64_t i_stco_pos;
  93.     vlc_bool_t b_stco64;
  94.     /* for h264 */
  95.     struct
  96.     {
  97.         int     i_profile;
  98.         int     i_level;
  99.         int     i_sps;
  100.         uint8_t *sps;
  101.         int     i_pps;
  102.         uint8_t *pps;
  103.     } avc;
  104.     /* for spu */
  105.     int64_t i_last_dts;
  106. } mp4_stream_t;
  107. struct sout_mux_sys_t
  108. {
  109.     vlc_bool_t b_mov;
  110.     vlc_bool_t b_3gp;
  111.     vlc_bool_t b_64_ext;
  112.     vlc_bool_t b_fast_start;
  113.     uint64_t i_mdat_pos;
  114.     uint64_t i_pos;
  115.     int64_t  i_dts_start;
  116.     int          i_nb_streams;
  117.     mp4_stream_t **pp_streams;
  118. };
  119. typedef struct bo_t
  120. {
  121.     vlc_bool_t b_grow;
  122.     int        i_buffer_size;
  123.     int        i_buffer;
  124.     uint8_t    *p_buffer;
  125. } bo_t;
  126. static void bo_init     ( bo_t *, int , uint8_t *, vlc_bool_t  );
  127. static void bo_add_8    ( bo_t *, uint8_t );
  128. static void bo_add_16be ( bo_t *, uint16_t );
  129. static void bo_add_24be ( bo_t *, uint32_t );
  130. static void bo_add_32be ( bo_t *, uint32_t );
  131. static void bo_add_64be ( bo_t *, uint64_t );
  132. static void bo_add_fourcc(bo_t *, char * );
  133. static void bo_add_bo   ( bo_t *, bo_t * );
  134. static void bo_add_mem  ( bo_t *, int , uint8_t * );
  135. static void bo_add_descr( bo_t *, uint8_t , uint32_t );
  136. static void bo_fix_32be ( bo_t *, int , uint32_t );
  137. static bo_t *box_new     ( char *fcc );
  138. static bo_t *box_full_new( char *fcc, uint8_t v, uint32_t f );
  139. static void  box_fix     ( bo_t *box );
  140. static void  box_free    ( bo_t *box );
  141. static void  box_gather  ( bo_t *box, bo_t *box2 );
  142. static void box_send( sout_mux_t *p_mux,  bo_t *box );
  143. static block_t *bo_to_sout( sout_instance_t *p_sout,  bo_t *box );
  144. static bo_t *GetMoovBox( sout_mux_t *p_mux );
  145. static block_t *ConvertSUBT( sout_mux_t *, mp4_stream_t *, block_t *);
  146. static void ConvertAVC1( sout_mux_t *, mp4_stream_t *, block_t * );
  147. /*****************************************************************************
  148.  * Open:
  149.  *****************************************************************************/
  150. static int Open( vlc_object_t *p_this )
  151. {
  152.     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
  153.     sout_mux_sys_t  *p_sys;
  154.     bo_t            *box;
  155.     msg_Dbg( p_mux, "Mp4 muxer opend" );
  156.     sout_CfgParse( p_mux, SOUT_CFG_PREFIX, ppsz_sout_options, p_mux->p_cfg );
  157.     p_mux->pf_control   = Control;
  158.     p_mux->pf_addstream = AddStream;
  159.     p_mux->pf_delstream = DelStream;
  160.     p_mux->pf_mux       = Mux;
  161.     p_mux->p_sys        = p_sys = malloc( sizeof( sout_mux_sys_t ) );
  162.     p_sys->i_pos        = 0;
  163.     p_sys->i_nb_streams = 0;
  164.     p_sys->pp_streams   = NULL;
  165.     p_sys->i_mdat_pos   = 0;
  166.     p_sys->b_mov        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mov" );
  167.     p_sys->b_3gp        = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "3gp" );
  168.     p_sys->i_dts_start  = 0;
  169.     if( !p_sys->b_mov )
  170.     {
  171.         /* Now add ftyp header */
  172.         box = box_new( "ftyp" );
  173.         if( p_sys->b_3gp ) bo_add_fourcc( box, "3gp4" );
  174.         else bo_add_fourcc( box, "isom" );
  175.         bo_add_32be  ( box, 0 );
  176.         if( p_sys->b_3gp ) bo_add_fourcc( box, "3gp4" );
  177.         else bo_add_fourcc( box, "mp41" );
  178.         box_fix( box );
  179.         p_sys->i_pos += box->i_buffer;
  180.         p_sys->i_mdat_pos = p_sys->i_pos;
  181.         box_send( p_mux, box );
  182.     }
  183.     /* FIXME FIXME
  184.      * Quicktime actually doesn't like the 64 bits extensions !!! */
  185.     p_sys->b_64_ext = VLC_FALSE;
  186.     /* Now add mdat header */
  187.     box = box_new( "mdat" );
  188.     bo_add_64be  ( box, 0 ); // enough to store an extended size
  189.     p_sys->i_pos += box->i_buffer;
  190.     box_send( p_mux, box );
  191.     return VLC_SUCCESS;
  192. }
  193. /*****************************************************************************
  194.  * Close:
  195.  *****************************************************************************/
  196. static void Close( vlc_object_t * p_this )
  197. {
  198.     sout_mux_t      *p_mux = (sout_mux_t*)p_this;
  199.     sout_mux_sys_t  *p_sys = p_mux->p_sys;
  200.     block_t   *p_hdr;
  201.     bo_t            bo, *moov;
  202.     vlc_value_t     val;
  203.     int             i_trak;
  204.     uint64_t        i_moov_pos;
  205.     msg_Dbg( p_mux, "Close" );
  206.     /* Update mdat size */
  207.     bo_init( &bo, 0, NULL, VLC_TRUE );
  208.     if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) )
  209.     {
  210.         /* Extended size */
  211.         bo_add_32be  ( &bo, 1 );
  212.         bo_add_fourcc( &bo, "mdat" );
  213.         bo_add_64be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos );
  214.     }
  215.     else
  216.     {
  217.         bo_add_32be  ( &bo, 8 );
  218.         bo_add_fourcc( &bo, "wide" );
  219.         bo_add_32be  ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 );
  220.         bo_add_fourcc( &bo, "mdat" );
  221.     }
  222.     p_hdr = bo_to_sout( p_mux->p_sout, &bo );
  223.     free( bo.p_buffer );
  224.     sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );
  225.     sout_AccessOutWrite( p_mux->p_access, p_hdr );
  226.     /* Create MOOV header */
  227.     i_moov_pos = p_sys->i_pos;
  228.     moov = GetMoovBox( p_mux );
  229.     /* Check we need to create "fast start" files */
  230.     var_Get( p_this, SOUT_CFG_PREFIX "faststart", &val );
  231.     p_sys->b_fast_start = val.b_bool;
  232.     while( p_sys->b_fast_start )
  233.     {
  234.         /* Move data to the end of the file so we can fit the moov header
  235.          * at the start */
  236.         block_t *p_buf;
  237.         int64_t i_chunk, i_size = p_sys->i_pos - p_sys->i_mdat_pos;
  238.         int i_moov_size = moov->i_buffer;
  239.         while( i_size > 0 )
  240.         {
  241.             i_chunk = __MIN( 32768, i_size );
  242.             p_buf = block_New( p_mux, i_chunk );
  243.             sout_AccessOutSeek( p_mux->p_access,
  244.                                 p_sys->i_mdat_pos + i_size - i_chunk );
  245.             if( sout_AccessOutRead( p_mux->p_access, p_buf ) < i_chunk )
  246.             {
  247.                 msg_Warn( p_this, "read() not supported by acces output, "
  248.                           "won't create a fast start file" );
  249.                 p_sys->b_fast_start = VLC_FALSE;
  250.                 block_Release( p_buf );
  251.                 break;
  252.             }
  253.             sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos + i_size +
  254.                                 i_moov_size - i_chunk );
  255.             sout_AccessOutWrite( p_mux->p_access, p_buf );
  256.             i_size -= i_chunk;
  257.         }
  258.         if( !p_sys->b_fast_start ) break;
  259.         /* Fix-up samples to chunks table in MOOV header */
  260.         for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
  261.         {
  262.             mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
  263.             unsigned int i;
  264.             int i_chunk;
  265.             moov->i_buffer = p_stream->i_stco_pos;
  266.             for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
  267.             {
  268.                 if( p_stream->b_stco64 )
  269.                     bo_add_64be( moov, p_stream->entry[i].i_pos + i_moov_size);
  270.                 else
  271.                     bo_add_32be( moov, p_stream->entry[i].i_pos + i_moov_size);
  272.                 while( i < p_stream->i_entry_count )
  273.                 {
  274.                     if( i + 1 < p_stream->i_entry_count &&
  275.                         p_stream->entry[i].i_pos + p_stream->entry[i].i_size
  276.                         != p_stream->entry[i + 1].i_pos )
  277.                     {
  278.                         i++;
  279.                         break;
  280.                     }
  281.                     i++;
  282.                 }
  283.             }
  284.         }
  285.         moov->i_buffer = i_moov_size;
  286.         i_moov_pos = p_sys->i_mdat_pos;
  287.         p_sys->b_fast_start = VLC_FALSE;
  288.     }
  289.     /* Write MOOV header */
  290.     sout_AccessOutSeek( p_mux->p_access, i_moov_pos );
  291.     box_send( p_mux, moov );
  292.     /* Clean-up */
  293.     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
  294.     {
  295.         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
  296.         es_format_Clean( &p_stream->fmt );
  297.         if( p_stream->avc.i_sps ) free( p_stream->avc.sps );
  298.         if( p_stream->avc.i_pps ) free( p_stream->avc.pps );
  299.         free( p_stream->entry );
  300.         free( p_stream );
  301.     }
  302.     if( p_sys->i_nb_streams ) free( p_sys->pp_streams );
  303.     free( p_sys );
  304. }
  305. /*****************************************************************************
  306.  * Control:
  307.  *****************************************************************************/
  308. static int Control( sout_mux_t *p_mux, int i_query, va_list args )
  309. {
  310.     vlc_bool_t *pb_bool;
  311.    switch( i_query )
  312.    {
  313.        case MUX_CAN_ADD_STREAM_WHILE_MUXING:
  314.            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
  315.            *pb_bool = VLC_FALSE;
  316.            return VLC_SUCCESS;
  317.        case MUX_GET_ADD_STREAM_WAIT:
  318.            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t * );
  319.            *pb_bool = VLC_TRUE;
  320.            return VLC_SUCCESS;
  321.        case MUX_GET_MIME:   /* Not needed, as not streamable */
  322.         default:
  323.             return VLC_EGENERIC;
  324.    }
  325. }
  326. /*****************************************************************************
  327.  * AddStream:
  328.  *****************************************************************************/
  329. static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
  330. {
  331.     sout_mux_sys_t  *p_sys = p_mux->p_sys;
  332.     mp4_stream_t    *p_stream;
  333.     switch( p_input->p_fmt->i_codec )
  334.     {
  335.         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
  336.         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
  337.         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
  338.         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
  339.         case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
  340.         case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
  341.         case VLC_FOURCC( 'S', 'V', 'Q', '1' ):
  342.         case VLC_FOURCC( 'S', 'V', 'Q', '3' ):
  343.         case VLC_FOURCC( 'h', '2', '6', '4' ):
  344.             break;
  345.         case VLC_FOURCC( 's', 'u', 'b', 't' ):
  346.             msg_Warn( p_mux, "subtitle track added like in .mov (even when creating .mp4)" );
  347.             break;
  348.         default:
  349.             msg_Err( p_mux, "unsupported codec %4.4s in mp4",
  350.                      (char*)&p_input->p_fmt->i_codec );
  351.             return VLC_EGENERIC;
  352.     }
  353.     p_stream                = malloc( sizeof( mp4_stream_t ) );
  354.     es_format_Copy( &p_stream->fmt, p_input->p_fmt );
  355.     p_stream->i_track_id    = p_sys->i_nb_streams + 1;
  356.     p_stream->i_length_neg  = 0;
  357.     p_stream->i_entry_count = 0;
  358.     p_stream->i_entry_max   = 1000;
  359.     p_stream->entry         =
  360.         calloc( p_stream->i_entry_max, sizeof( mp4_entry_t ) );
  361.     p_stream->i_dts_start   = 0;
  362.     p_stream->i_duration    = 0;
  363.     p_stream->avc.i_profile = 77;
  364.     p_stream->avc.i_level   = 51;
  365.     p_stream->avc.i_sps     = 0;
  366.     p_stream->avc.sps       = NULL;
  367.     p_stream->avc.i_pps     = 0;
  368.     p_stream->avc.pps       = NULL;
  369.     p_input->p_sys          = p_stream;
  370.     msg_Dbg( p_mux, "adding input" );
  371.     TAB_APPEND( p_sys->i_nb_streams, p_sys->pp_streams, p_stream );
  372.     return VLC_SUCCESS;
  373. }
  374. /*****************************************************************************
  375.  * DelStream:
  376.  *****************************************************************************/
  377. static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
  378. {
  379.     msg_Dbg( p_mux, "removing input" );
  380.     return VLC_SUCCESS;
  381. }
  382. static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
  383. {
  384.     mtime_t i_dts;
  385.     int     i_stream;
  386.     int     i;
  387.     for( i = 0, i_dts = 0, i_stream = -1; i < p_mux->i_nb_inputs; i++ )
  388.     {
  389.         block_fifo_t   *p_fifo = p_mux->pp_inputs[i]->p_fifo;
  390.         block_t *p_buf;
  391.         if( p_fifo->i_depth <= 1 )
  392.         {
  393.             if( p_mux->pp_inputs[i]->p_fmt->i_cat != SPU_ES )
  394.             {
  395.                 return -1; // wait that all fifo have at least 2 packets
  396.             }
  397.             /* For SPU, we wait only 1 packet */
  398.             continue;
  399.         }
  400.         p_buf = block_FifoShow( p_fifo );
  401.         if( i_stream < 0 || p_buf->i_dts < i_dts )
  402.         {
  403.             i_dts = p_buf->i_dts;
  404.             i_stream = i;
  405.         }
  406.     }
  407.     if( pi_stream )
  408.     {
  409.         *pi_stream = i_stream;
  410.     }
  411.     if( pi_dts )
  412.     {
  413.         *pi_dts = i_dts;
  414.     }
  415.     return i_stream;
  416. }
  417. /*****************************************************************************
  418.  * Mux:
  419.  *****************************************************************************/
  420. static int Mux( sout_mux_t *p_mux )
  421. {
  422.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  423.     for( ;; )
  424.     {
  425.         sout_input_t    *p_input;
  426.         int             i_stream;
  427.         mp4_stream_t    *p_stream;
  428.         block_t         *p_data;
  429.         mtime_t         i_dts;
  430.         if( MuxGetStream( p_mux, &i_stream, &i_dts) < 0 )
  431.         {
  432.             return( VLC_SUCCESS );
  433.         }
  434.         p_input  = p_mux->pp_inputs[i_stream];
  435.         p_stream = (mp4_stream_t*)p_input->p_sys;
  436.         p_data  = block_FifoGet( p_input->p_fifo );
  437.         if( p_stream->fmt.i_codec == VLC_FOURCC( 'h', '2', '6', '4' ) )
  438.         {
  439.             ConvertAVC1( p_mux, p_stream, p_data );
  440.         }
  441.         else if( p_stream->fmt.i_codec == VLC_FOURCC( 's', 'u', 'b', 't' ) )
  442.         {
  443.             p_data = ConvertSUBT( p_mux, p_stream, p_data );
  444.         }
  445.         if( p_stream->fmt.i_cat != SPU_ES )
  446.         {
  447.             /* Fix length of the sample */
  448.             if( p_input->p_fifo->i_depth > 0 )
  449.             {
  450.                 block_t *p_next = block_FifoShow( p_input->p_fifo );
  451.                 int64_t       i_diff  = p_next->i_dts - p_data->i_dts;
  452.                 if( i_diff < I64C(1000000 ) )   /* protection */
  453.                 {
  454.                     p_data->i_length = i_diff;
  455.                 }
  456.             }
  457.             if( p_data->i_length <= 0 )
  458.             {
  459.                 msg_Warn( p_mux, "i_length <= 0" );
  460.                 p_stream->i_length_neg += p_data->i_length - 1;
  461.                 p_data->i_length = 1;
  462.             }
  463.             else if( p_stream->i_length_neg < 0 )
  464.             {
  465.                 int64_t i_recover = __MIN( p_data->i_length / 4, - p_stream->i_length_neg );
  466.                 p_data->i_length -= i_recover;
  467.                 p_stream->i_length_neg += i_recover;
  468.             }
  469.         }
  470.         /* Save starting time */
  471.         if( p_stream->i_entry_count == 0 )
  472.         {
  473.             p_stream->i_dts_start = p_data->i_dts;
  474.             /* Update global dts_start */
  475.             if( p_sys->i_dts_start <= 0 ||
  476.                 p_stream->i_dts_start < p_sys->i_dts_start )
  477.             {
  478.                 p_sys->i_dts_start = p_stream->i_dts_start;
  479.             }
  480.         }
  481.         if( p_stream->fmt.i_cat == SPU_ES && p_stream->i_entry_count > 0 )
  482.         {
  483.             int64_t i_length = p_data->i_dts - p_stream->i_last_dts;
  484.             if( i_length <= 0 )
  485.             {
  486.                 /* FIXME handle this broken case */
  487.                 i_length = 1;
  488.             }
  489.             /* Fix last entry */
  490.             if( p_stream->entry[p_stream->i_entry_count-1].i_length <= 0 )
  491.             {
  492.                 p_stream->entry[p_stream->i_entry_count-1].i_length = i_length;
  493.             }
  494.         }
  495.         /* add index entry */
  496.         p_stream->entry[p_stream->i_entry_count].i_pos    = p_sys->i_pos;
  497.         p_stream->entry[p_stream->i_entry_count].i_size   = p_data->i_buffer;
  498.         p_stream->entry[p_stream->i_entry_count].i_pts_dts=
  499.             __MAX( p_data->i_pts - p_data->i_dts, 0 );
  500.         p_stream->entry[p_stream->i_entry_count].i_length = p_data->i_length;
  501.         p_stream->entry[p_stream->i_entry_count].i_flags  = p_data->i_flags;
  502.         p_stream->i_entry_count++;
  503.         /* XXX: -1 to always have 2 entry for easy adding of empty SPU */
  504.         if( p_stream->i_entry_count >= p_stream->i_entry_max - 1 )
  505.         {
  506.             p_stream->i_entry_max += 1000;
  507.             p_stream->entry =
  508.                 realloc( p_stream->entry,
  509.                          p_stream->i_entry_max * sizeof( mp4_entry_t ) );
  510.         }
  511.         /* update */
  512.         p_stream->i_duration += p_data->i_length;
  513.         p_sys->i_pos += p_data->i_buffer;
  514.         /* Save the DTS */
  515.         p_stream->i_last_dts = p_data->i_dts;
  516.         /* write data */
  517.         sout_AccessOutWrite( p_mux->p_access, p_data );
  518.         if( p_stream->fmt.i_cat == SPU_ES )
  519.         {
  520.             int64_t i_length = p_stream->entry[p_stream->i_entry_count-1].i_length;
  521.             if( i_length != 0 )
  522.             {
  523.                 /* TODO */
  524.                 msg_Dbg( p_mux, "writing a empty subs" ) ;
  525.                 /* Append a idx entry */
  526.                 p_stream->entry[p_stream->i_entry_count].i_pos    = p_sys->i_pos;
  527.                 p_stream->entry[p_stream->i_entry_count].i_size   = 3;
  528.                 p_stream->entry[p_stream->i_entry_count].i_pts_dts= 0;
  529.                 p_stream->entry[p_stream->i_entry_count].i_length = 0;
  530.                 p_stream->entry[p_stream->i_entry_count].i_flags  = 0;
  531.                 /* XXX: No need to grow the entry here */
  532.                 p_stream->i_entry_count++;
  533.                 /* Fix last dts */
  534.                 p_stream->i_last_dts += i_length;
  535.                 /* Write a " " */
  536.                 p_data = block_New( p_mux, 3 );
  537.                 p_data->p_buffer[0] = 0;
  538.                 p_data->p_buffer[1] = 1;
  539.                 p_data->p_buffer[2] = ' ';
  540.                 p_sys->i_pos += p_data->i_buffer;
  541.                 sout_AccessOutWrite( p_mux->p_access, p_data );
  542.             }
  543.             /* Fix duration */
  544.             p_stream->i_duration = p_stream->i_last_dts - p_stream->i_dts_start;
  545.         }
  546.     }
  547.     return( VLC_SUCCESS );
  548. }
  549. /*****************************************************************************
  550.  *
  551.  *****************************************************************************/
  552. static block_t *ConvertSUBT( sout_mux_t *p_mux, mp4_stream_t *tk, block_t *p_block )
  553. {
  554.     p_block = block_Realloc( p_block, 2, p_block->i_buffer );
  555.     /* No trailling '' */
  556.     if( p_block->i_buffer > 2 && p_block->p_buffer[p_block->i_buffer-1] == '' )
  557.         p_block->i_buffer--;
  558.     p_block->p_buffer[0] = ( (p_block->i_buffer - 2) >> 8 )&0xff;
  559.     p_block->p_buffer[1] = ( (p_block->i_buffer - 2)      )&0xff;
  560.     return p_block;
  561. }
  562. static void ConvertAVC1( sout_mux_t *p_mux, mp4_stream_t *tk, block_t *p_block )
  563. {
  564.     uint8_t *last = p_block->p_buffer;  /* Assume it starts with 0x00000001 */
  565.     uint8_t *dat  = &p_block->p_buffer[4];
  566.     uint8_t *end = &p_block->p_buffer[p_block->i_buffer];
  567.     /* Replace the 4 bytes start code with 4 bytes size,
  568.      * FIXME are all startcode 4 bytes ? (I don't think :( */
  569.     while( dat < end )
  570.     {
  571.         int i_size;
  572.         while( dat < end - 4 )
  573.         {
  574.             if( dat[0] == 0x00 && dat[1] == 0x00  &&
  575.                 dat[2] == 0x00 && dat[3] == 0x01 )
  576.             {
  577.                 break;
  578.             }
  579.             dat++;
  580.         }
  581.         if( dat >= end - 4 )
  582.         {
  583.             dat = end;
  584.         }
  585.         /* Fix size */
  586.         i_size = dat - &last[4];
  587.         last[0] = ( i_size >> 24 )&0xff;
  588.         last[1] = ( i_size >> 16 )&0xff;
  589.         last[2] = ( i_size >>  8 )&0xff;
  590.         last[3] = ( i_size       )&0xff;
  591.         if( (last[4]&0x1f) == 7 && tk->avc.i_sps <= 0 )  /* SPS */
  592.         {
  593.             tk->avc.i_sps = i_size;
  594.             tk->avc.sps = malloc( i_size );
  595.             memcpy( tk->avc.sps, &last[4], i_size );
  596.             tk->avc.i_profile = tk->avc.sps[1];
  597.             tk->avc.i_level   = tk->avc.sps[3];
  598.         }
  599.         else if( (last[4]&0x1f) == 8 && tk->avc.i_pps <= 0 )   /* PPS */
  600.         {
  601.             tk->avc.i_pps = i_size;
  602.             tk->avc.pps = malloc( i_size );
  603.             memcpy( tk->avc.pps, &last[4], i_size );
  604.         }
  605.         last = dat;
  606.         dat += 4;
  607.     }
  608. }
  609. static int GetDescrLength( int i_size )
  610. {
  611.     if( i_size < 0x00000080 )
  612.         return 2 + i_size;
  613.     else if( i_size < 0x00004000 )
  614.         return 3 + i_size;
  615.     else if( i_size < 0x00200000 )
  616.         return 4 + i_size;
  617.     else
  618.         return 5 + i_size;
  619. }
  620. static bo_t *GetESDS( mp4_stream_t *p_stream )
  621. {
  622.     bo_t *esds;
  623.     int  i_stream_type;
  624.     int  i_object_type_indication;
  625.     int  i_decoder_specific_info_size;
  626.     unsigned int i;
  627.     int64_t i_bitrate_avg = 0;
  628.     int64_t i_bitrate_max = 0;
  629.     /* Compute avg/max bitrate */
  630.     for( i = 0; i < p_stream->i_entry_count; i++ )
  631.     {
  632.         i_bitrate_avg += p_stream->entry[i].i_size;
  633.         if( p_stream->entry[i].i_length > 0)
  634.         {
  635.             int64_t i_bitrate = I64C(8000000) * p_stream->entry[i].i_size / p_stream->entry[i].i_length;
  636.             if( i_bitrate > i_bitrate_max )
  637.                 i_bitrate_max = i_bitrate;
  638.         }
  639.     }
  640.     if( p_stream->i_duration > 0 )
  641.         i_bitrate_avg = I64C(8000000) * i_bitrate_avg / p_stream->i_duration;
  642.     else
  643.         i_bitrate_avg = 0;
  644.     if( i_bitrate_max <= 1 )
  645.         i_bitrate_max = 0x7fffffff;
  646.     /* */
  647.     if( p_stream->fmt.i_extra > 0 )
  648.     {
  649.         i_decoder_specific_info_size =
  650.             GetDescrLength( p_stream->fmt.i_extra );
  651.     }
  652.     else
  653.     {
  654.         i_decoder_specific_info_size = 0;
  655.     }
  656.     esds = box_full_new( "esds", 0, 0 );
  657.     /* ES_Descr */
  658.     bo_add_descr( esds, 0x03, 3 +
  659.                   GetDescrLength( 13 + i_decoder_specific_info_size ) +
  660.                   GetDescrLength( 1 ) );
  661.     bo_add_16be( esds, p_stream->i_track_id );
  662.     bo_add_8   ( esds, 0x1f );      // flags=0|streamPriority=0x1f
  663.     /* DecoderConfigDescr */
  664.     bo_add_descr( esds, 0x04, 13 + i_decoder_specific_info_size );
  665.     switch( p_stream->fmt.i_codec )
  666.     {
  667.         case VLC_FOURCC( 'm', 'p', '4', 'v' ):
  668.             i_object_type_indication = 0x20;
  669.             break;
  670.         case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
  671.             /* FIXME MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
  672.             i_object_type_indication = 0x60;
  673.             break;
  674.         case VLC_FOURCC( 'm', 'p', '4', 'a' ):
  675.             /* FIXME for mpeg2-aac == 0x66->0x68 */
  676.             i_object_type_indication = 0x40;
  677.             break;
  678.         case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
  679.             i_object_type_indication =
  680.                 p_stream->fmt.audio.i_rate < 32000 ? 0x69 : 0x6b;
  681.             break;
  682.         default:
  683.             i_object_type_indication = 0x00;
  684.             break;
  685.     }
  686.     i_stream_type = p_stream->fmt.i_cat == VIDEO_ES ? 0x04 : 0x05;
  687.     bo_add_8   ( esds, i_object_type_indication );
  688.     bo_add_8   ( esds, ( i_stream_type << 2 ) | 1 );
  689.     bo_add_24be( esds, 1024 * 1024 );       // bufferSizeDB
  690.     bo_add_32be( esds, i_bitrate_max );     // maxBitrate
  691.     bo_add_32be( esds, i_bitrate_avg );     // avgBitrate
  692.     if( p_stream->fmt.i_extra > 0 )
  693.     {
  694.         int i;
  695.         /* DecoderSpecificInfo */
  696.         bo_add_descr( esds, 0x05, p_stream->fmt.i_extra );
  697.         for( i = 0; i < p_stream->fmt.i_extra; i++ )
  698.         {
  699.             bo_add_8( esds, ((uint8_t*)p_stream->fmt.p_extra)[i] );
  700.         }
  701.     }
  702.     /* SL_Descr mandatory */
  703.     bo_add_descr( esds, 0x06, 1 );
  704.     bo_add_8    ( esds, 0x02 );  // sl_predefined
  705.     box_fix( esds );
  706.     return esds;
  707. }
  708. static bo_t *GetWaveTag( mp4_stream_t *p_stream )
  709. {
  710.     bo_t *wave;
  711.     bo_t *box;
  712.     wave = box_new( "wave" );
  713.     box = box_new( "frma" );
  714.     bo_add_fourcc( box, "mp4a" );
  715.     box_fix( box );
  716.     box_gather( wave, box );
  717.     box = box_new( "mp4a" );
  718.     bo_add_32be( box, 0 );
  719.     box_fix( box );
  720.     box_gather( wave, box );
  721.     box = GetESDS( p_stream );
  722.     box_fix( box );
  723.     box_gather( wave, box );
  724.     box = box_new( "srcq" );
  725.     bo_add_32be( box, 0x40 );
  726.     box_fix( box );
  727.     box_gather( wave, box );
  728.     /* wazza ? */
  729.     bo_add_32be( wave, 8 ); /* new empty box */
  730.     bo_add_32be( wave, 0 ); /* box label */
  731.     box_fix( wave );
  732.     return wave;
  733. }
  734. static bo_t *GetAvcCTag( mp4_stream_t *p_stream )
  735. {
  736.     bo_t *avcC;
  737.     /* FIXME use better value */
  738.     avcC = box_new( "avcC" );
  739.     bo_add_8( avcC, 1 );      /* configuration version */
  740.     bo_add_8( avcC, p_stream->avc.i_profile );
  741.     bo_add_8( avcC, p_stream->avc.i_profile );     /* profile compatible ??? */
  742.     bo_add_8( avcC, p_stream->avc.i_level );       /* level, 5.1 */
  743.     bo_add_8( avcC, 0xff );   /* 0b11111100 | lengthsize = 0x11 */
  744.     bo_add_8( avcC, 0xe0 | (p_stream->avc.i_sps > 0 ? 1 : 0) );   /* 0b11100000 | sps_count */
  745.     if( p_stream->avc.i_sps > 0 )
  746.     {
  747.         bo_add_16be( avcC, p_stream->avc.i_sps );
  748.         bo_add_mem( avcC, p_stream->avc.i_sps, p_stream->avc.sps );
  749.     }
  750.     bo_add_8( avcC, (p_stream->avc.i_pps > 0 ? 1 : 0) );   /* pps_count */
  751.     if( p_stream->avc.i_pps > 0 )
  752.     {
  753.         bo_add_16be( avcC, p_stream->avc.i_pps );
  754.         bo_add_mem( avcC, p_stream->avc.i_pps, p_stream->avc.pps );
  755.     }
  756.     box_fix( avcC );
  757.     return avcC;
  758. }
  759. /* TODO: No idea about these values */
  760. static bo_t *GetSVQ3Tag( mp4_stream_t *p_stream )
  761. {
  762.     bo_t *smi = box_new( "SMI " );
  763.     if( p_stream->fmt.i_extra > 0x4e )
  764.     {
  765.         uint8_t *p_end = &((uint8_t*)p_stream->fmt.p_extra)[p_stream->fmt.i_extra];
  766.         uint8_t *p     = &((uint8_t*)p_stream->fmt.p_extra)[0x46];
  767.         while( p + 8 < p_end )
  768.         {
  769.             int i_size = GetDWBE( p );
  770.             if( i_size <= 1 )
  771.             {
  772.                 /* FIXME handle 1 as long size */
  773.                 break;
  774.             }
  775.             if( !strncmp( &p[4], "SMI ", 4 ) )
  776.             {
  777.                 bo_add_mem( smi, p_end - p - 8, &p[8] );
  778.                 return smi;
  779.             }
  780.             p += i_size;
  781.         }
  782.     }
  783.     /* Create a dummy one in fallback */
  784.     bo_add_fourcc( smi, "SEQH" );
  785.     bo_add_32be( smi, 0x5 );
  786.     bo_add_32be( smi, 0xe2c0211d );
  787.     bo_add_8( smi, 0xc0 );
  788.     box_fix( smi );
  789.     return smi;
  790. }
  791. static bo_t *GetUdtaTag( sout_mux_t *p_mux )
  792. {
  793.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  794.     bo_t *udta = box_new( "udta" );
  795.     vlc_meta_t *p_meta = p_mux->p_sout->p_meta;
  796.     int i_track;
  797.     /* Requirements */
  798.     for( i_track = 0; i_track < p_sys->i_nb_streams; i_track++ )
  799.     {
  800.         mp4_stream_t *p_stream = p_sys->pp_streams[i_track];
  801.         if( p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','v') ||
  802.             p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','a') )
  803.         {
  804.             bo_t *box = box_new( "251req" );
  805.             /* String length */
  806.             bo_add_16be( box, sizeof("QuickTime 6.0 or greater") - 1);
  807.             bo_add_16be( box, 0 );
  808.             bo_add_mem( box, sizeof("QuickTime 6.0 or greater") - 1,
  809.                         "QuickTime 6.0 or greater" );
  810.             box_fix( box );
  811.             box_gather( udta, box );
  812.             break;
  813.         }
  814.     }
  815.     /* Encoder */
  816.     {
  817.         bo_t *box = box_new( "251enc" );
  818.         /* String length */
  819.         bo_add_16be( box, sizeof(PACKAGE_STRING " stream output") - 1);
  820.         bo_add_16be( box, 0 );
  821.         bo_add_mem( box, sizeof(PACKAGE_STRING " stream output") - 1,
  822.                     PACKAGE_STRING " stream output" );
  823.         box_fix( box );
  824.         box_gather( udta, box );
  825.     }
  826.     /* Misc atoms */
  827.     if( p_meta )
  828.     {
  829.         int i;
  830.         for( i = 0; i < p_meta->i_meta; i++ )
  831.         {
  832.             bo_t *box = NULL;
  833.             if( !strcmp( p_meta->name[i], VLC_META_TITLE ) )
  834.                 box = box_new( "251nam" );
  835.             else if( !strcmp( p_meta->name[i], VLC_META_AUTHOR ) )
  836.                 box = box_new( "251aut" );
  837.             else if( !strcmp( p_meta->name[i], VLC_META_ARTIST ) )
  838.                 box = box_new( "251ART" );
  839.             else if( !strcmp( p_meta->name[i], VLC_META_GENRE ) )
  840.                 box = box_new( "251gen" );
  841.             else if( !strcmp( p_meta->name[i], VLC_META_COPYRIGHT ) )
  842.                 box = box_new( "251cpy" );
  843.             else if( !strcmp( p_meta->name[i], VLC_META_DESCRIPTION ) )
  844.                 box = box_new( "251des" );
  845.             else if( !strcmp( p_meta->name[i], VLC_META_DATE ) )
  846.                 box = box_new( "251day" );
  847.             else if( !strcmp( p_meta->name[i], VLC_META_URL ) )
  848.                 box = box_new( "251url" );
  849.             if( box )
  850.             {
  851.                 bo_add_16be( box, strlen( p_meta->value[i] ) );
  852.                 bo_add_16be( box, 0 );
  853.                 bo_add_mem( box, strlen( p_meta->value[i] ),
  854.                             p_meta->value[i] );
  855.                 box_fix( box );
  856.                 box_gather( udta, box );
  857.             }
  858.         }
  859.     }
  860.     box_fix( udta );
  861.     return udta;
  862. }
  863. static bo_t *GetSounBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
  864. {
  865.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  866.     vlc_bool_t b_descr = VLC_FALSE;
  867.     bo_t *soun;
  868.     char fcc[4] = "    ";
  869.     int  i;
  870.     switch( p_stream->fmt.i_codec )
  871.     {
  872.     case VLC_FOURCC('m','p','4','a'):
  873.         memcpy( fcc, "mp4a", 4 );
  874.         b_descr = VLC_TRUE;
  875.         break;
  876.     case VLC_FOURCC('m','p','g','a'):
  877.         if( p_sys->b_mov )
  878.             memcpy( fcc, ".mp3", 4 );
  879.         else
  880.         {
  881.             memcpy( fcc, "mp4a", 4 );
  882.             b_descr = VLC_TRUE;
  883.         }
  884.         break;
  885.     default:
  886.         memcpy( fcc, (char*)&p_stream->fmt.i_codec, 4 );
  887.         break;
  888.     }
  889.     soun = box_new( fcc );
  890.     for( i = 0; i < 6; i++ )
  891.     {
  892.         bo_add_8( soun, 0 );        // reserved;
  893.     }
  894.     bo_add_16be( soun, 1 );         // data-reference-index
  895.     /* SoundDescription */
  896.     if( p_sys->b_mov &&
  897.         p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','a') )
  898.     {
  899.         bo_add_16be( soun, 1 );     // version 1;
  900.     }
  901.     else
  902.     {
  903.         bo_add_16be( soun, 0 );     // version 0;
  904.     }
  905.     bo_add_16be( soun, 0 );         // revision level (0)
  906.     bo_add_32be( soun, 0 );         // vendor
  907.     // channel-count
  908.     bo_add_16be( soun, p_stream->fmt.audio.i_channels );
  909.     // sample size
  910.     bo_add_16be( soun, p_stream->fmt.audio.i_bitspersample ?
  911.                  p_stream->fmt.audio.i_bitspersample : 16 );
  912.     bo_add_16be( soun, -2 );        // compression id
  913.     bo_add_16be( soun, 0 );         // packet size (0)
  914.     bo_add_16be( soun, p_stream->fmt.audio.i_rate ); // sampleratehi
  915.     bo_add_16be( soun, 0 );                             // sampleratelo
  916.     /* Extended data for SoundDescription V1 */
  917.     if( p_sys->b_mov &&
  918.         p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','a') )
  919.     {
  920.         /* samples per packet */
  921.         bo_add_32be( soun, p_stream->fmt.audio.i_frame_length );
  922.         bo_add_32be( soun, 1536 ); /* bytes per packet */
  923.         bo_add_32be( soun, 2 );    /* bytes per frame */
  924.         /* bytes per sample */
  925.         bo_add_32be( soun, 2 /*p_stream->fmt.audio.i_bitspersample/8 */);
  926.     }
  927.     /* Add an ES Descriptor */
  928.     if( b_descr )
  929.     {
  930.         bo_t *box;
  931.         if( p_sys->b_mov &&
  932.             p_stream->fmt.i_codec == VLC_FOURCC('m','p','4','a') )
  933.         {
  934.             box = GetWaveTag( p_stream );
  935.         }
  936.         else
  937.         {
  938.             box = GetESDS( p_stream );
  939.         }
  940.         box_fix( box );
  941.         box_gather( soun, box );
  942.     }
  943.     box_fix( soun );
  944.     return soun;
  945. }
  946. static bo_t *GetVideBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
  947. {
  948.     bo_t *vide;
  949.     char fcc[4] = "    ";
  950.     int  i;
  951.     switch( p_stream->fmt.i_codec )
  952.     {
  953.     case VLC_FOURCC('m','p','4','v'):
  954.     case VLC_FOURCC('m','p','g','v'):
  955.         memcpy( fcc, "mp4v", 4 );
  956.         break;
  957.     case VLC_FOURCC('M','J','P','G'):
  958.         memcpy( fcc, "mjpa", 4 );
  959.         break;
  960.     case VLC_FOURCC('S','V','Q','1'):
  961.         memcpy( fcc, "SVQ1", 4 );
  962.         break;
  963.     case VLC_FOURCC('S','V','Q','3'):
  964.         memcpy( fcc, "SVQ3", 4 );
  965.         break;
  966.     case VLC_FOURCC('h','2','6','4'):
  967.         memcpy( fcc, "avc1", 4 );
  968.         break;
  969.     default:
  970.         memcpy( fcc, (char*)&p_stream->fmt.i_codec, 4 );
  971.         break;
  972.     }
  973.     vide = box_new( fcc );
  974.     for( i = 0; i < 6; i++ )
  975.     {
  976.         bo_add_8( vide, 0 );        // reserved;
  977.     }
  978.     bo_add_16be( vide, 1 );         // data-reference-index
  979.     bo_add_16be( vide, 0 );         // predefined;
  980.     bo_add_16be( vide, 0 );         // reserved;
  981.     for( i = 0; i < 3; i++ )
  982.     {
  983.         bo_add_32be( vide, 0 );     // predefined;
  984.     }
  985.     bo_add_16be( vide, p_stream->fmt.video.i_width );  // i_width
  986.     bo_add_16be( vide, p_stream->fmt.video.i_height ); // i_height
  987.     bo_add_32be( vide, 0x00480000 );                // h 72dpi
  988.     bo_add_32be( vide, 0x00480000 );                // v 72dpi
  989.     bo_add_32be( vide, 0 );         // data size, always 0
  990.     bo_add_16be( vide, 1 );         // frames count per sample
  991.     // compressor name;
  992.     for( i = 0; i < 32; i++ )
  993.     {
  994.         bo_add_8( vide, 0 );
  995.     }
  996.     bo_add_16be( vide, 0x18 );      // depth
  997.     bo_add_16be( vide, 0xffff );    // predefined
  998.     /* add an ES Descriptor */
  999.     switch( p_stream->fmt.i_codec )
  1000.     {
  1001.     case VLC_FOURCC('m','p','4','v'):
  1002.     case VLC_FOURCC('m','p','g','v'):
  1003.         {
  1004.             bo_t *esds = GetESDS( p_stream );
  1005.             box_fix( esds );
  1006.             box_gather( vide, esds );
  1007.         }
  1008.         break;
  1009.     case VLC_FOURCC('S','V','Q','3'):
  1010.         {
  1011.             bo_t *esds = GetSVQ3Tag( p_stream );
  1012.             box_fix( esds );
  1013.             box_gather( vide, esds );
  1014.         }
  1015.         break;
  1016.     case VLC_FOURCC('h','2','6','4'):
  1017.         box_gather( vide, GetAvcCTag( p_stream ) );
  1018.         break;
  1019.     default:
  1020.         break;
  1021.     }
  1022.     box_fix( vide );
  1023.     return vide;
  1024. }
  1025. static bo_t *GetTextBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
  1026. {
  1027.     bo_t *text = box_new( "text" );
  1028.     int  i;
  1029.     for( i = 0; i < 6; i++ )
  1030.     {
  1031.         bo_add_8( text, 0 );        // reserved;
  1032.     }
  1033.     bo_add_16be( text, 1 );         // data-reference-index
  1034.     bo_add_32be( text, 0 );         // display flags
  1035.     bo_add_32be( text, 0 );         // justification
  1036.     for( i = 0; i < 3; i++ )
  1037.     {
  1038.         bo_add_16be( text, 0 );     // back ground color
  1039.     }
  1040.     bo_add_16be( text, 0 );         // box text
  1041.     bo_add_16be( text, 0 );         // box text
  1042.     bo_add_16be( text, 0 );         // box text
  1043.     bo_add_16be( text, 0 );         // box text
  1044.     bo_add_64be( text, 0 );         // reserved
  1045.     for( i = 0; i < 3; i++ )
  1046.     {
  1047.         bo_add_16be( text, 0xff );  // foreground color
  1048.     }
  1049.     bo_add_8 ( text, 9 );
  1050.     bo_add_mem( text, 9, "Helvetica" );
  1051.     box_fix( text );
  1052.     return text;
  1053. }
  1054. static bo_t *GetStblBox( sout_mux_t *p_mux, mp4_stream_t *p_stream )
  1055. {
  1056.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  1057.     unsigned int i_chunk, i_stsc_last_val, i_stsc_entries, i, i_index;
  1058.     bo_t *stbl, *stsd, *stts, *stco, *stsc, *stsz, *stss;
  1059.     uint32_t i_timescale;
  1060.     int64_t i_dts, i_dts_q;
  1061.     stbl = box_new( "stbl" );
  1062.     /* sample description */
  1063.     stsd = box_full_new( "stsd", 0, 0 );
  1064.     bo_add_32be( stsd, 1 );
  1065.     if( p_stream->fmt.i_cat == AUDIO_ES )
  1066.     {
  1067.         bo_t *soun = GetSounBox( p_mux, p_stream );
  1068.         box_gather( stsd, soun );
  1069.     }
  1070.     else if( p_stream->fmt.i_cat == VIDEO_ES )
  1071.     {
  1072.         bo_t *vide = GetVideBox( p_mux, p_stream );
  1073.         box_gather( stsd, vide );
  1074.     }
  1075.     else if( p_stream->fmt.i_cat == SPU_ES )
  1076.     {
  1077.         box_gather( stsd, GetTextBox( p_mux, p_stream ) );
  1078.     }
  1079.     box_fix( stsd );
  1080.     /* chunk offset table */
  1081.     if( p_sys->i_pos >= (((uint64_t)0x1) << 32) )
  1082.     {
  1083.         /* 64 bits version */
  1084.         p_stream->b_stco64 = VLC_TRUE;
  1085.         stco = box_full_new( "co64", 0, 0 );
  1086.     }
  1087.     else
  1088.     {
  1089.         /* 32 bits version */
  1090.         p_stream->b_stco64 = VLC_FALSE;
  1091.         stco = box_full_new( "stco", 0, 0 );
  1092.     }
  1093.     bo_add_32be( stco, 0 );     // entry-count (fixed latter)
  1094.     /* sample to chunk table */
  1095.     stsc = box_full_new( "stsc", 0, 0 );
  1096.     bo_add_32be( stsc, 0 );     // entry-count (fixed latter)
  1097.     for( i_chunk = 0, i_stsc_last_val = 0, i_stsc_entries = 0, i = 0;
  1098.          i < p_stream->i_entry_count; i_chunk++ )
  1099.     {
  1100.         int i_first = i;
  1101.         if( p_stream->b_stco64 )
  1102.             bo_add_64be( stco, p_stream->entry[i].i_pos );
  1103.         else
  1104.             bo_add_32be( stco, p_stream->entry[i].i_pos );
  1105.         while( i < p_stream->i_entry_count )
  1106.         {
  1107.             if( i + 1 < p_stream->i_entry_count &&
  1108.                 p_stream->entry[i].i_pos + p_stream->entry[i].i_size
  1109.                 != p_stream->entry[i + 1].i_pos )
  1110.             {
  1111.                 i++;
  1112.                 break;
  1113.             }
  1114.             i++;
  1115.         }
  1116.         /* Add entry to the stsc table */
  1117.         if( i_stsc_last_val != i - i_first )
  1118.         {
  1119.             bo_add_32be( stsc, 1 + i_chunk );   // first-chunk
  1120.             bo_add_32be( stsc, i - i_first ) ;  // samples-per-chunk
  1121.             bo_add_32be( stsc, 1 );             // sample-descr-index
  1122.             i_stsc_last_val = i - i_first;
  1123.             i_stsc_entries++;
  1124.         }
  1125.     }
  1126.     /* Fix stco entry count */
  1127.     bo_fix_32be( stco, 12, i_chunk );
  1128.     msg_Dbg( p_mux, "created %d chunks (stco)", i_chunk );
  1129.     box_fix( stco );
  1130.     /* Fix stsc entry count */
  1131.     bo_fix_32be( stsc, 12, i_stsc_entries  );
  1132.     box_fix( stsc );
  1133.     /* add stts */
  1134.     stts = box_full_new( "stts", 0, 0 );
  1135.     bo_add_32be( stts, 0 );     // entry-count (fixed latter)
  1136.     if( p_stream->fmt.i_cat == AUDIO_ES )
  1137.         i_timescale = p_stream->fmt.audio.i_rate;
  1138.     else
  1139.         i_timescale = 1001;
  1140.     /* first, create quantified length */
  1141.     for( i = 0, i_dts = 0, i_dts_q = 0; i < p_stream->i_entry_count; i++ )
  1142.     {
  1143.         int64_t i_dts_deq = i_dts_q * I64C(1000000) / (int64_t)i_timescale;
  1144.         int64_t i_delta = p_stream->entry[i].i_length + i_dts - i_dts_deq;
  1145.         i_dts += p_stream->entry[i].i_length;
  1146.         p_stream->entry[i].i_length =
  1147.             i_delta * (int64_t)i_timescale / I64C(1000000);
  1148.         i_dts_q += p_stream->entry[i].i_length;
  1149.     }
  1150.     /* then write encoded table */
  1151.     for( i = 0, i_index = 0; i < p_stream->i_entry_count; i_index++)
  1152.     {
  1153.         int     i_first = i;
  1154.         int64_t i_delta = p_stream->entry[i].i_length;
  1155.         while( i < p_stream->i_entry_count )
  1156.         {
  1157.             i++;
  1158.             if( i >= p_stream->i_entry_count ||
  1159.                 p_stream->entry[i].i_length != i_delta )
  1160.             {
  1161.                 break;
  1162.             }
  1163.         }
  1164.         bo_add_32be( stts, i - i_first ); // sample-count
  1165.         bo_add_32be( stts, i_delta );     // sample-delta
  1166.     }
  1167.     bo_fix_32be( stts, 12, i_index );
  1168.     box_fix( stts );
  1169.     /* FIXME add ctts ?? FIXME */
  1170.     stsz = box_full_new( "stsz", 0, 0 );
  1171.     bo_add_32be( stsz, 0 );                             // sample-size
  1172.     bo_add_32be( stsz, p_stream->i_entry_count );       // sample-count
  1173.     for( i = 0; i < p_stream->i_entry_count; i++ )
  1174.     {
  1175.         bo_add_32be( stsz, p_stream->entry[i].i_size ); // sample-size
  1176.     }
  1177.     box_fix( stsz );
  1178.     /* create stss table */
  1179.     stss = NULL;
  1180.     for( i = 0, i_index = 0; i < p_stream->i_entry_count; i++ )
  1181.     {
  1182.         if( p_stream->entry[i].i_flags & BLOCK_FLAG_TYPE_I )
  1183.         {
  1184.             if( stss == NULL )
  1185.             {
  1186.                 stss = box_full_new( "stss", 0, 0 );
  1187.                 bo_add_32be( stss, 0 ); /* fixed later */
  1188.             }
  1189.             bo_add_32be( stss, 1 + i );
  1190.             i_index++;
  1191.         }
  1192.     }
  1193.     if( stss )
  1194.     {
  1195.         bo_fix_32be( stss, 12, i_index );
  1196.         box_fix( stss );
  1197.     }
  1198.     /* Now gather all boxes into stbl */
  1199.     box_gather( stbl, stsd );
  1200.     box_gather( stbl, stts );
  1201.     if( stss )
  1202.     {
  1203.         box_gather( stbl, stss );
  1204.     }
  1205.     box_gather( stbl, stsc );
  1206.     box_gather( stbl, stsz );
  1207.     p_stream->i_stco_pos = stbl->i_buffer + 16;
  1208.     box_gather( stbl, stco );
  1209.     /* finish stbl */
  1210.     box_fix( stbl );
  1211.     return stbl;
  1212. }
  1213. static int64_t get_timestamp();
  1214. static uint32_t mvhd_matrix[9] =
  1215.     { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
  1216. static bo_t *GetMoovBox( sout_mux_t *p_mux )
  1217. {
  1218.     sout_mux_sys_t *p_sys = p_mux->p_sys;
  1219.     bo_t            *moov, *mvhd;
  1220.     int             i_trak, i;
  1221.     uint32_t        i_movie_timescale = 90000;
  1222.     int64_t         i_movie_duration  = 0;
  1223.     moov = box_new( "moov" );
  1224.     /* Create general info */
  1225.     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
  1226.     {
  1227.         mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
  1228.         i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration );
  1229.     }
  1230.     msg_Dbg( p_mux, "movie duration %ds",
  1231.              (uint32_t)( i_movie_duration / (mtime_t)1000000 ) );
  1232.     i_movie_duration = i_movie_duration * i_movie_timescale / 1000000;
  1233.     /* *** add /moov/mvhd *** */
  1234.     if( !p_sys->b_64_ext )
  1235.     {
  1236.         mvhd = box_full_new( "mvhd", 0, 0 );
  1237.         bo_add_32be( mvhd, get_timestamp() );   // creation time
  1238.         bo_add_32be( mvhd, get_timestamp() );   // modification time
  1239.         bo_add_32be( mvhd, i_movie_timescale);  // timescale
  1240.         bo_add_32be( mvhd, i_movie_duration );  // duration
  1241.     }
  1242.     else
  1243.     {
  1244.         mvhd = box_full_new( "mvhd", 1, 0 );
  1245.         bo_add_64be( mvhd, get_timestamp() );   // creation time
  1246.         bo_add_64be( mvhd, get_timestamp() );   // modification time
  1247.         bo_add_32be( mvhd, i_movie_timescale);  // timescale
  1248.         bo_add_64be( mvhd, i_movie_duration );  // duration
  1249.     }
  1250.     bo_add_32be( mvhd, 0x10000 );           // rate
  1251.     bo_add_16be( mvhd, 0x100 );             // volume
  1252.     bo_add_16be( mvhd, 0 );                 // reserved
  1253.     for( i = 0; i < 2; i++ )
  1254.     {
  1255.         bo_add_32be( mvhd, 0 );             // reserved
  1256.     }
  1257.     for( i = 0; i < 9; i++ )
  1258.     {
  1259.         bo_add_32be( mvhd, mvhd_matrix[i] );// matrix
  1260.     }
  1261.     for( i = 0; i < 6; i++ )
  1262.     {
  1263.         bo_add_32be( mvhd, 0 );             // pre-defined
  1264.     }
  1265.     /* Next available track id */
  1266.     bo_add_32be( mvhd, p_sys->i_nb_streams + 1 ); // next-track-id
  1267.     box_fix( mvhd );
  1268.     box_gather( moov, mvhd );
  1269.     for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
  1270.     {
  1271.         mp4_stream_t *p_stream;
  1272.         uint32_t     i_timescale;
  1273.         bo_t *trak, *tkhd, *edts, *elst, *mdia, *mdhd, *hdlr;
  1274.         bo_t *minf, *dinf, *dref, *url, *stbl;
  1275.         p_stream = p_sys->pp_streams[i_trak];
  1276.         if( p_stream->fmt.i_cat == AUDIO_ES )
  1277.             i_timescale = p_stream->fmt.audio.i_rate;
  1278.         else
  1279.             i_timescale = 1001;
  1280.         /* *** add /moov/trak *** */
  1281.         trak = box_new( "trak" );
  1282.         /* *** add /moov/trak/tkhd *** */
  1283.         if( !p_sys->b_64_ext )
  1284.         {
  1285.             if( p_sys->b_mov )
  1286.                 tkhd = box_full_new( "tkhd", 0, 0x0f );
  1287.             else
  1288.                 tkhd = box_full_new( "tkhd", 0, 1 );
  1289.             bo_add_32be( tkhd, get_timestamp() );       // creation time
  1290.             bo_add_32be( tkhd, get_timestamp() );       // modification time
  1291.             bo_add_32be( tkhd, p_stream->i_track_id );
  1292.             bo_add_32be( tkhd, 0 );                     // reserved 0
  1293.             bo_add_32be( tkhd, p_stream->i_duration *
  1294.                          (int64_t)i_movie_timescale /
  1295.                          (mtime_t)1000000 );            // duration
  1296.         }
  1297.         else
  1298.         {
  1299.             if( p_sys->b_mov )
  1300.                 tkhd = box_full_new( "tkhd", 1, 0x0f );
  1301.             else
  1302.                 tkhd = box_full_new( "tkhd", 1, 1 );
  1303.             bo_add_64be( tkhd, get_timestamp() );       // creation time
  1304.             bo_add_64be( tkhd, get_timestamp() );       // modification time
  1305.             bo_add_32be( tkhd, p_stream->i_track_id );
  1306.             bo_add_32be( tkhd, 0 );                     // reserved 0
  1307.             bo_add_64be( tkhd, p_stream->i_duration *
  1308.                          (int64_t)i_movie_timescale /
  1309.                          (mtime_t)1000000 );            // duration
  1310.         }
  1311.         for( i = 0; i < 2; i++ )
  1312.         {
  1313.             bo_add_32be( tkhd, 0 );                 // reserved
  1314.         }
  1315.         bo_add_16be( tkhd, 0 );                     // layer
  1316.         bo_add_16be( tkhd, 0 );                     // pre-defined
  1317.         // volume
  1318.         bo_add_16be( tkhd, p_stream->fmt.i_cat == AUDIO_ES ? 0x100 : 0 );
  1319.         bo_add_16be( tkhd, 0 );                     // reserved
  1320.         for( i = 0; i < 9; i++ )
  1321.         {
  1322.             bo_add_32be( tkhd, mvhd_matrix[i] );    // matrix
  1323.         }
  1324.         if( p_stream->fmt.i_cat == AUDIO_ES )
  1325.         {
  1326.             bo_add_32be( tkhd, 0 );                 // width (presentation)
  1327.             bo_add_32be( tkhd, 0 );                 // height(presentation)
  1328.         }
  1329.         else if( p_stream->fmt.i_cat == VIDEO_ES )
  1330.         {
  1331.             int i_width = p_stream->fmt.video.i_width << 16;
  1332.             if( p_stream->fmt.video.i_aspect > 0 )
  1333.             {
  1334.                 i_width = (int64_t)p_stream->fmt.video.i_aspect *
  1335.                           ((int64_t)p_stream->fmt.video.i_height << 16) /
  1336.                           VOUT_ASPECT_FACTOR;
  1337.             }
  1338.             // width (presentation)
  1339.             bo_add_32be( tkhd, i_width );
  1340.             // height(presentation)
  1341.             bo_add_32be( tkhd, p_stream->fmt.video.i_height << 16 );
  1342.         }
  1343.         else
  1344.         {
  1345.             int i_width = 320 << 16;
  1346.             int i_height = 200;
  1347.             int i;
  1348.             for( i = 0; i < p_sys->i_nb_streams; i++ )
  1349.             {
  1350.                 mp4_stream_t *tk = p_sys->pp_streams[i];
  1351.                 if( tk->fmt.i_cat == VIDEO_ES )
  1352.                 {
  1353.                     if( p_stream->fmt.video.i_aspect )
  1354.                         i_width = (int64_t)p_stream->fmt.video.i_aspect *
  1355.                                    ((int64_t)p_stream->fmt.video.i_height<<16) / VOUT_ASPECT_FACTOR;
  1356.                     else
  1357.                         i_width = p_stream->fmt.video.i_width << 16;
  1358.                     i_height = p_stream->fmt.video.i_height;
  1359.                     break;
  1360.                 }
  1361.             }
  1362.             bo_add_32be( tkhd, i_width );     // width (presentation)
  1363.             bo_add_32be( tkhd, i_height << 16 );    // height(presentation)
  1364.         }
  1365.         box_fix( tkhd );
  1366.         box_gather( trak, tkhd );
  1367.         /* *** add /moov/trak/edts and elst */
  1368.         edts = box_new( "edts" );
  1369.         elst = box_full_new( "elst", p_sys->b_64_ext ? 1 : 0, 0 );
  1370.         if( p_stream->i_dts_start > p_sys->i_dts_start )
  1371.         {
  1372.             bo_add_32be( elst, 2 );
  1373.             if( p_sys->b_64_ext )
  1374.             {
  1375.                 bo_add_64be( elst, (p_stream->i_dts_start-p_sys->i_dts_start) *
  1376.                              i_movie_timescale / I64C(1000000) );
  1377.                 bo_add_64be( elst, -1 );
  1378.             }
  1379.             else
  1380.             {
  1381.                 bo_add_32be( elst, (p_stream->i_dts_start-p_sys->i_dts_start) *
  1382.                              i_movie_timescale / I64C(1000000) );
  1383.                 bo_add_32be( elst, -1 );
  1384.             }
  1385.             bo_add_16be( elst, 1 );
  1386.             bo_add_16be( elst, 0 );
  1387.         }
  1388.         else
  1389.         {
  1390.             bo_add_32be( elst, 1 );
  1391.         }
  1392.         if( p_sys->b_64_ext )
  1393.         {
  1394.             bo_add_64be( elst, p_stream->i_duration *
  1395.                          i_movie_timescale / I64C(1000000) );
  1396.             bo_add_64be( elst, 0 );
  1397.         }
  1398.         else
  1399.         {
  1400.             bo_add_32be( elst, p_stream->i_duration *
  1401.                          i_movie_timescale / I64C(1000000) );
  1402.             bo_add_32be( elst, 0 );
  1403.         }
  1404.         bo_add_16be( elst, 1 );
  1405.         bo_add_16be( elst, 0 );
  1406.         box_fix( elst );
  1407.         box_gather( edts, elst );
  1408.         box_fix( edts );
  1409.         box_gather( trak, edts );
  1410.         /* *** add /moov/trak/mdia *** */
  1411.         mdia = box_new( "mdia" );
  1412.         /* media header */
  1413.         if( !p_sys->b_64_ext )
  1414.         {
  1415.             mdhd = box_full_new( "mdhd", 0, 0 );
  1416.             bo_add_32be( mdhd, get_timestamp() );   // creation time
  1417.             bo_add_32be( mdhd, get_timestamp() );   // modification time
  1418.             bo_add_32be( mdhd, i_timescale);        // timescale
  1419.             bo_add_32be( mdhd, p_stream->i_duration * (int64_t)i_timescale /
  1420.                                (mtime_t)1000000 );  // duration
  1421.         }
  1422.         else
  1423.         {
  1424.             mdhd = box_full_new( "mdhd", 1, 0 );
  1425.             bo_add_64be( mdhd, get_timestamp() );   // creation time
  1426.             bo_add_64be( mdhd, get_timestamp() );   // modification time
  1427.             bo_add_32be( mdhd, i_timescale);        // timescale
  1428.             bo_add_64be( mdhd, p_stream->i_duration * (int64_t)i_timescale /
  1429.                                (mtime_t)1000000 );  // duration
  1430.         }
  1431.         if( p_stream->fmt.psz_language )
  1432.         {
  1433.             char *psz = p_stream->fmt.psz_language;
  1434.             const iso639_lang_t *pl = NULL;
  1435.             uint16_t lang = 0x0;
  1436.             if( strlen( psz ) == 2 )
  1437.             {
  1438.                 pl = GetLang_1( psz );
  1439.             }
  1440.             else if( strlen( psz ) == 3 )
  1441.             {
  1442.                 pl = GetLang_2B( psz );
  1443.                 if( !strcmp( pl->psz_iso639_1, "??" ) )
  1444.                 {
  1445.                     pl = GetLang_2T( psz );
  1446.                 }
  1447.             }
  1448.             if( pl && strcmp( pl->psz_iso639_1, "??" ) )
  1449.             {
  1450.                 lang = ( ( pl->psz_iso639_2T[0] - 0x60 ) << 10 ) |
  1451.                        ( ( pl->psz_iso639_2T[1] - 0x60 ) <<  5 ) |
  1452.                        ( ( pl->psz_iso639_2T[2] - 0x60 ) );
  1453.             }
  1454.             bo_add_16be( mdhd, lang );          // language
  1455.         }
  1456.         else
  1457.         {
  1458.             bo_add_16be( mdhd, 0    );          // language
  1459.         }
  1460.         bo_add_16be( mdhd, 0    );              // predefined
  1461.         box_fix( mdhd );
  1462.         box_gather( mdia, mdhd );
  1463.         /* handler reference */
  1464.         hdlr = box_full_new( "hdlr", 0, 0 );
  1465.         if( p_sys->b_mov )
  1466.             bo_add_fourcc( hdlr, "mhlr" );         // media handler
  1467.         else
  1468.             bo_add_32be( hdlr, 0 );
  1469.         if( p_stream->fmt.i_cat == AUDIO_ES )
  1470.             bo_add_fourcc( hdlr, "soun" );
  1471.         else if( p_stream->fmt.i_cat == VIDEO_ES )
  1472.             bo_add_fourcc( hdlr, "vide" );
  1473.         else if( p_stream->fmt.i_cat == SPU_ES )
  1474.             bo_add_fourcc( hdlr, "text" );
  1475.         bo_add_32be( hdlr, 0 );         // reserved
  1476.         bo_add_32be( hdlr, 0 );         // reserved
  1477.         bo_add_32be( hdlr, 0 );         // reserved
  1478.         if( p_sys->b_mov )
  1479.             bo_add_8( hdlr, 12 );   /* Pascal string for .mov */
  1480.         if( p_stream->fmt.i_cat == AUDIO_ES )
  1481.             bo_add_mem( hdlr, 12, "SoundHandler" );
  1482.         else if( p_stream->fmt.i_cat == VIDEO_ES )
  1483.             bo_add_mem( hdlr, 12, "VideoHandler" );
  1484.         else
  1485.             bo_add_mem( hdlr, 12, "Text Handler" );
  1486.         if( !p_sys->b_mov )
  1487.             bo_add_8( hdlr, 0 );   /* asciiz string for .mp4, yes that's BRAIN DAMAGED F**K MP4 */
  1488.         box_fix( hdlr );
  1489.         box_gather( mdia, hdlr );
  1490.         /* minf*/
  1491.         minf = box_new( "minf" );
  1492.         /* add smhd|vmhd */
  1493.         if( p_stream->fmt.i_cat == AUDIO_ES )
  1494.         {
  1495.             bo_t *smhd;
  1496.             smhd = box_full_new( "smhd", 0, 0 );
  1497.             bo_add_16be( smhd, 0 );     // balance
  1498.             bo_add_16be( smhd, 0 );     // reserved
  1499.             box_fix( smhd );
  1500.             box_gather( minf, smhd );
  1501.         }
  1502.         else if( p_stream->fmt.i_cat == VIDEO_ES )
  1503.         {
  1504.             bo_t *vmhd;
  1505.             vmhd = box_full_new( "vmhd", 0, 1 );
  1506.             bo_add_16be( vmhd, 0 );     // graphicsmode
  1507.             for( i = 0; i < 3; i++ )
  1508.             {
  1509.                 bo_add_16be( vmhd, 0 ); // opcolor
  1510.             }
  1511.             box_fix( vmhd );
  1512.             box_gather( minf, vmhd );
  1513.         }
  1514.         else if( p_stream->fmt.i_cat == SPU_ES )
  1515.         {
  1516.             bo_t *gmhd = box_new( "gmhd" );
  1517.             bo_t *gmin = box_full_new( "gmin", 0, 1 );
  1518.             bo_add_16be( gmin, 0 );     // graphicsmode
  1519.             for( i = 0; i < 3; i++ )
  1520.             {
  1521.                 bo_add_16be( gmin, 0 ); // opcolor
  1522.             }
  1523.             bo_add_16be( gmin, 0 );     // balance
  1524.             bo_add_16be( gmin, 0 );     // reserved
  1525.             box_fix( gmin );
  1526.             box_gather( gmhd, gmin );
  1527.             box_fix( gmhd );
  1528.             box_gather( minf, gmhd );
  1529.         }
  1530.         /* dinf */
  1531.         dinf = box_new( "dinf" );
  1532.         dref = box_full_new( "dref", 0, 0 );
  1533.         bo_add_32be( dref, 1 );
  1534.         url = box_full_new( "url ", 0, 0x01 );
  1535.         box_fix( url );
  1536.         box_gather( dref, url );
  1537.         box_fix( dref );
  1538.         box_gather( dinf, dref );
  1539.         /* append dinf to mdia */
  1540.         box_fix( dinf );
  1541.         box_gather( minf, dinf );
  1542.         /* add stbl */
  1543.         stbl = GetStblBox( p_mux, p_stream );
  1544.         /* append stbl to minf */
  1545.         p_stream->i_stco_pos += minf->i_buffer;
  1546.         box_gather( minf, stbl );
  1547.         /* append minf to mdia */
  1548.         box_fix( minf );
  1549.         p_stream->i_stco_pos += mdia->i_buffer;
  1550.         box_gather( mdia, minf );
  1551.         /* append mdia to trak */
  1552.         box_fix( mdia );
  1553.         p_stream->i_stco_pos += trak->i_buffer;
  1554.         box_gather( trak, mdia );
  1555.         /* append trak to moov */
  1556.         box_fix( trak );
  1557.         p_stream->i_stco_pos += moov->i_buffer;
  1558.         box_gather( moov, trak );
  1559.     }
  1560.     /* Add user data tags */
  1561.     box_gather( moov, GetUdtaTag( p_mux ) );
  1562.     box_fix( moov );
  1563.     return moov;
  1564. }
  1565. /****************************************************************************/
  1566. static void bo_init( bo_t *p_bo, int i_size, uint8_t *p_buffer,
  1567.                      vlc_bool_t b_grow )
  1568. {
  1569.     if( !p_buffer )
  1570.     {
  1571.         p_bo->i_buffer_size = __MAX( i_size, 1024 );
  1572.         p_bo->p_buffer = malloc( p_bo->i_buffer_size );
  1573.     }
  1574.     else
  1575.     {
  1576.         p_bo->i_buffer_size = i_size;
  1577.         p_bo->p_buffer = p_buffer;
  1578.     }
  1579.     p_bo->b_grow = b_grow;
  1580.     p_bo->i_buffer = 0;
  1581. }
  1582. static void bo_add_8( bo_t *p_bo, uint8_t i )
  1583. {
  1584.     if( p_bo->i_buffer < p_bo->i_buffer_size )
  1585.     {
  1586.         p_bo->p_buffer[p_bo->i_buffer] = i;
  1587.     }
  1588.     else if( p_bo->b_grow )
  1589.     {
  1590.         p_bo->i_buffer_size += 1024;
  1591.         p_bo->p_buffer = realloc( p_bo->p_buffer, p_bo->i_buffer_size );
  1592.         p_bo->p_buffer[p_bo->i_buffer] = i;
  1593.     }
  1594.     p_bo->i_buffer++;
  1595. }
  1596. static void bo_add_16be( bo_t *p_bo, uint16_t i )
  1597. {
  1598.     bo_add_8( p_bo, ( ( i >> 8) &0xff ) );
  1599.     bo_add_8( p_bo, i &0xff );
  1600. }
  1601. static void bo_add_24be( bo_t *p_bo, uint32_t i )
  1602. {
  1603.     bo_add_8( p_bo, ( ( i >> 16) &0xff ) );
  1604.     bo_add_8( p_bo, ( ( i >> 8) &0xff ) );
  1605.     bo_add_8( p_bo, (   i &0xff ) );
  1606. }
  1607. static void bo_add_32be( bo_t *p_bo, uint32_t i )
  1608. {
  1609.     bo_add_16be( p_bo, ( ( i >> 16) &0xffff ) );
  1610.     bo_add_16be( p_bo, i &0xffff );
  1611. }
  1612. static void bo_fix_32be ( bo_t *p_bo, int i_pos, uint32_t i)
  1613. {
  1614.     p_bo->p_buffer[i_pos    ] = ( i >> 24 )&0xff;
  1615.     p_bo->p_buffer[i_pos + 1] = ( i >> 16 )&0xff;
  1616.     p_bo->p_buffer[i_pos + 2] = ( i >>  8 )&0xff;
  1617.     p_bo->p_buffer[i_pos + 3] = ( i       )&0xff;
  1618. }
  1619. static void bo_add_64be( bo_t *p_bo, uint64_t i )
  1620. {
  1621.     bo_add_32be( p_bo, ( ( i >> 32) &0xffffffff ) );
  1622.     bo_add_32be( p_bo, i &0xffffffff );
  1623. }
  1624. static void bo_add_fourcc( bo_t *p_bo, char *fcc )
  1625. {
  1626.     bo_add_8( p_bo, fcc[0] );
  1627.     bo_add_8( p_bo, fcc[1] );
  1628.     bo_add_8( p_bo, fcc[2] );
  1629.     bo_add_8( p_bo, fcc[3] );
  1630. }
  1631. static void bo_add_mem( bo_t *p_bo, int i_size, uint8_t *p_mem )
  1632. {
  1633.     int i;
  1634.     for( i = 0; i < i_size; i++ )
  1635.     {
  1636.         bo_add_8( p_bo, p_mem[i] );
  1637.     }
  1638. }
  1639. static void bo_add_descr( bo_t *p_bo, uint8_t tag, uint32_t i_size )
  1640. {
  1641.     uint32_t i_length;
  1642.     uint8_t  vals[4];
  1643.     i_length = i_size;
  1644.     vals[3] = (unsigned char)(i_length & 0x7f);
  1645.     i_length >>= 7;
  1646.     vals[2] = (unsigned char)((i_length & 0x7f) | 0x80); 
  1647.     i_length >>= 7;
  1648.     vals[1] = (unsigned char)((i_length & 0x7f) | 0x80); 
  1649.     i_length >>= 7;
  1650.     vals[0] = (unsigned char)((i_length & 0x7f) | 0x80);
  1651.     bo_add_8( p_bo, tag );
  1652.     if( i_size < 0x00000080 )
  1653.     {
  1654.         bo_add_8( p_bo, vals[3] );
  1655.     }
  1656.     else if( i_size < 0x00004000 )
  1657.     {
  1658.         bo_add_8( p_bo, vals[2] );
  1659.         bo_add_8( p_bo, vals[3] );
  1660.     }
  1661.     else if( i_size < 0x00200000 )
  1662.     {
  1663.         bo_add_8( p_bo, vals[1] );
  1664.         bo_add_8( p_bo, vals[2] );
  1665.         bo_add_8( p_bo, vals[3] );
  1666.     }
  1667.     else if( i_size < 0x10000000 )
  1668.     {
  1669.         bo_add_8( p_bo, vals[0] );
  1670.         bo_add_8( p_bo, vals[1] );
  1671.         bo_add_8( p_bo, vals[2] );
  1672.         bo_add_8( p_bo, vals[3] );
  1673.     }
  1674. }
  1675. static void bo_add_bo( bo_t *p_bo, bo_t *p_bo2 )
  1676. {
  1677.     int i;
  1678.     for( i = 0; i < p_bo2->i_buffer; i++ )
  1679.     {
  1680.         bo_add_8( p_bo, p_bo2->p_buffer[i] );
  1681.     }
  1682. }
  1683. static bo_t * box_new( char *fcc )
  1684. {
  1685.     bo_t *box;
  1686.     if( ( box = malloc( sizeof( bo_t ) ) ) )
  1687.     {
  1688.         bo_init( box, 0, NULL, VLC_TRUE );
  1689.         bo_add_32be  ( box, 0 );
  1690.         bo_add_fourcc( box, fcc );
  1691.     }
  1692.     return box;
  1693. }
  1694. static bo_t * box_full_new( char *fcc, uint8_t v, uint32_t f )
  1695. {
  1696.     bo_t *box;
  1697.     if( ( box = malloc( sizeof( bo_t ) ) ) )
  1698.     {
  1699.         bo_init( box, 0, NULL, VLC_TRUE );
  1700.         bo_add_32be  ( box, 0 );
  1701.         bo_add_fourcc( box, fcc );
  1702.         bo_add_8     ( box, v );
  1703.         bo_add_24be  ( box, f );
  1704.     }
  1705.     return box;
  1706. }
  1707. static void box_fix( bo_t *box )
  1708. {
  1709.     bo_t box_tmp;
  1710.     memcpy( &box_tmp, box, sizeof( bo_t ) );
  1711.     box_tmp.i_buffer = 0;
  1712.     bo_add_32be( &box_tmp, box->i_buffer );
  1713. }
  1714. static void box_free( bo_t *box )
  1715. {
  1716.     if( box->p_buffer )
  1717.     {
  1718.         free( box->p_buffer );
  1719.     }
  1720.     free( box );
  1721. }
  1722. static void box_gather ( bo_t *box, bo_t *box2 )
  1723. {
  1724.     bo_add_bo( box, box2 );
  1725.     box_free( box2 );
  1726. }
  1727. static block_t * bo_to_sout( sout_instance_t *p_sout,  bo_t *box )
  1728. {
  1729.     block_t *p_buf;
  1730.     p_buf = block_New( p_sout, box->i_buffer );
  1731.     if( box->i_buffer > 0 )
  1732.     {
  1733.         memcpy( p_buf->p_buffer, box->p_buffer, box->i_buffer );
  1734.     }
  1735.     return p_buf;
  1736. }
  1737. static void box_send( sout_mux_t *p_mux,  bo_t *box )
  1738. {
  1739.     block_t *p_buf;
  1740.     p_buf = bo_to_sout( p_mux->p_sout, box );
  1741.     box_free( box );
  1742.     sout_AccessOutWrite( p_mux->p_access, p_buf );
  1743. }
  1744. static int64_t get_timestamp()
  1745. {
  1746.     int64_t i_timestamp = 0;
  1747. #ifdef HAVE_TIME_H
  1748.     i_timestamp = time(NULL);
  1749.     i_timestamp += 2082844800; // MOV/MP4 start date is 1/1/1904
  1750.     // 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
  1751. #endif
  1752.     return i_timestamp;
  1753. }