mp4.c
上传用户:kjfoods
上传日期:2020-07-06
资源大小:29949k
文件大小:62k
源码类别:

midi

开发平台:

Unix_Linux

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