* udp.c
*****************************************************************************
* Copyright (C) 2001, 2002 VideoLAN
- * $Id: udp.c,v 1.16 2003/11/17 14:46:37 massiot Exp $
+ * $Id: udp.c,v 1.17 2004/01/23 17:56:14 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Eric Petit <titer@videolan.org>
#include "network.h"
#define DEFAULT_PORT 1234
-#define LATENCY 100000
-#define MAX_ERROR 500000
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
module_t *p_network;
network_socket_t socket_desc;
- char *val;
+ vlc_value_t val;
+ char *psz_val;
if( !( p_sys = p_access->p_sys =
malloc( sizeof( sout_access_out_sys_t ) ) ) )
{
msg_Err( p_access, "Not enough memory" );
- return( VLC_EGENERIC );
+ return VLC_EGENERIC;
}
if( !p_sys->p_thread )
{
msg_Err( p_access, "out of memory" );
- return( VLC_EGENERIC );
+ return VLC_EGENERIC;
}
p_sys->p_thread->p_sout = p_access->p_sout;
socket_desc.psz_bind_addr = "";
socket_desc.i_bind_port = 0;
socket_desc.i_ttl = 0;
- if( ( val = sout_cfg_find_value( p_access->p_cfg, "ttl" ) ) )
+ if( ( psz_val = sout_cfg_find_value( p_access->p_cfg, "ttl" ) ) )
{
- socket_desc.i_ttl = atoi( val );
+ socket_desc.i_ttl = atoi( psz_val );
}
p_sys->p_thread->p_private = (void*)&socket_desc;
- if( !( p_network = module_Need( p_sys->p_thread,
- "network", "" ) ) )
+ if( !( p_network = module_Need( p_sys->p_thread, "network", "" ) ) )
{
msg_Err( p_access, "failed to open a connection (udp)" );
- return( VLC_EGENERIC );
+ return VLC_EGENERIC;
}
module_Unneed( p_sys->p_thread, p_network );
p_sys->p_thread->i_handle = socket_desc.i_handle;
- p_sys->p_thread->i_caching = config_GetInt( p_this, "udp-sout-caching" ) * 1000;
- if( ( val = sout_cfg_find_value( p_access->p_cfg, "caching" ) ) )
+
+ var_Create( p_this, "udp-sout-caching",
+ VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
+ var_Get( p_this, "udp-sout-caching", &val );
+ p_sys->p_thread->i_caching = val.i_int * 1000;
+ if( ( psz_val = sout_cfg_find_value( p_access->p_cfg, "caching" ) ) )
{
- p_sys->p_thread->i_caching = atoll( val ) * 1000;
+ p_sys->p_thread->i_caching = atoll( psz_val ) * 1000;
}
- p_sys->i_mtu = socket_desc.i_mtu;
+ p_sys->i_mtu = socket_desc.i_mtu;
if( vlc_thread_create( p_sys->p_thread, "sout write thread", ThreadWrite,
VLC_THREAD_PRIORITY_OUTPUT, VLC_FALSE ) )
{
msg_Err( p_access->p_sout, "cannot spawn sout access thread" );
vlc_object_destroy( p_sys->p_thread );
- return( VLC_EGENERIC );
+ return VLC_EGENERIC;
}
srand( (uint32_t)mdate());
if( sout_cfg_find( p_access->p_cfg, "raw" ) )
{
- p_access->pf_write = WriteRaw;
+ p_access->pf_write = WriteRaw;
}
else
{
- p_access->pf_write = Write;
+ p_access->pf_write = Write;
}
- p_access->pf_seek = Seek;
- msg_Info( p_access, "Open: addr:`%s' port:`%d'",
- psz_dst_addr, i_dst_port );
+ p_access->pf_seek = Seek;
+
+ msg_Info( p_access, "Open: addr:`%s' port:`%d'", psz_dst_addr, i_dst_port);
free( psz_dst_addr );
return VLC_SUCCESS;
*****************************************************************************/
static void Close( vlc_object_t * p_this )
{
- sout_access_out_t *p_access = (sout_access_out_t*)p_this;
- sout_access_out_sys_t *p_sys = p_access->p_sys;
- int i;
+ sout_access_out_t *p_access = (sout_access_out_t*)p_this;
+ sout_access_out_sys_t *p_sys = p_access->p_sys;
+ int i;
p_sys->p_thread->b_die = 1;
for( i = 0; i < 10; i++ )
{
- sout_buffer_t *p_dummy;
+ sout_buffer_t *p_dummy;
p_dummy = sout_BufferNew( p_access->p_sout, p_sys->i_mtu );
p_dummy->i_dts = 0;
*****************************************************************************/
static int Write( sout_access_out_t *p_access, sout_buffer_t *p_buffer )
{
- sout_access_out_sys_t *p_sys = p_access->p_sys;
+ sout_access_out_sys_t *p_sys = p_access->p_sys;
unsigned int i_write;
while( p_buffer )
*****************************************************************************/
static int Seek( sout_access_out_t *p_access, off_t i_pos )
{
-
msg_Err( p_access, "udp sout access cannot seek" );
return( -1 );
}
* mp4.c: mp4/mov muxer
*****************************************************************************
* Copyright (C) 2001, 2002, 2003 VideoLAN
- * $Id: mp4.c,v 1.9 2004/01/13 15:54:09 gbazin Exp $
+ * $Id: mp4.c,v 1.10 2004/01/23 17:56:14 gbazin Exp $
*
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
* Gildas Bazin <gbazin at videolan dot org>
/*****************************************************************************
* Exported prototypes
*****************************************************************************/
-static int Open ( vlc_object_t * );
-static void Close ( vlc_object_t * );
+static int Open ( vlc_object_t * );
+static void Close ( vlc_object_t * );
static int Capability(sout_mux_t *, int, void *, void * );
static int AddStream( sout_mux_t *, sout_input_t * );
/*****************************************************************************
* Module descriptor
*****************************************************************************/
+#define FASTSTART_TEXT N_("Create \"Fast start\" files")
+#define FASTSTART_LONGTEXT N_( \
+ "When this option is turned on, \"Fast start\" files will be created. " \
+ "(\"Fast start\" files are optimized for download, allowing the user " \
+ "to start previewing the file while it is downloading).")
+
vlc_module_begin();
set_description( _("MP4/MOV muxer") );
+
+ add_category_hint( "MP4/MOV muxer", NULL, VLC_TRUE );
+ add_bool( "mp4-faststart", 1, NULL, FASTSTART_TEXT, FASTSTART_LONGTEXT, VLC_TRUE );
+
set_capability( "sout mux", 5 );
add_shortcut( "mp4" );
add_shortcut( "mov" );
set_callbacks( Open, Close );
vlc_module_end();
+/*****************************************************************************
+ * Local prototypes
+ *****************************************************************************/
typedef struct
{
uint64_t i_pos;
/* stats */
mtime_t i_duration;
+
+ /* for later stco fix-up (fast start files) */
+ uint64_t i_stco_pos;
+ vlc_bool_t b_stco64;
+
} mp4_stream_t;
struct sout_mux_sys_t
{
vlc_bool_t b_mov;
vlc_bool_t b_64_ext;
+ vlc_bool_t b_fast_start;
uint64_t i_mdat_pos;
uint64_t i_pos;
mp4_stream_t **pp_streams;
};
-
-typedef struct bo_t bo_t;
-struct bo_t
+typedef struct bo_t
{
vlc_bool_t b_grow;
int i_buffer;
uint8_t *p_buffer;
-};
+} bo_t;
static void bo_init ( bo_t *, int , uint8_t *, vlc_bool_t );
static void bo_add_8 ( bo_t *, uint8_t );
static void bo_add_fourcc(bo_t *, char * );
static void bo_add_bo ( bo_t *, bo_t * );
static void bo_add_mem ( bo_t *, int , uint8_t * );
-static void bo_add_descr ( bo_t *, uint8_t , uint32_t );
+static void bo_add_descr( bo_t *, uint8_t , uint32_t );
static void bo_fix_32be ( bo_t *, int , uint32_t );
static int64_t get_timestamp();
-static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout, bo_t *box );
+static sout_buffer_t *bo_to_sout( sout_instance_t *p_sout, bo_t *box );
/*****************************************************************************
* Open:
p_sys->b_mov = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mov" );
p_sys->i_start_dts = 0;
- msg_Info( p_mux, "Open" );
+ msg_Dbg( p_mux, "Open" );
p_mux->pf_capacity = Capability;
p_mux->pf_addstream = AddStream;
return smi;
}
-/*****************************************************************************
- * Close:
- *****************************************************************************/
-static uint32_t mvhd_matrix[9] =
- { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
-
-static void Close( vlc_object_t * p_this )
+static bo_t *GetUdtaTag( sout_mux_t *p_mux )
{
- sout_mux_t *p_mux = (sout_mux_t*)p_this;
- sout_mux_sys_t *p_sys = p_mux->p_sys;
- sout_buffer_t *p_hdr;
- bo_t bo;
- bo_t *moov, *mvhd;
- unsigned int i;
- int i_trak, i_index;
-
- uint32_t i_movie_timescale = 90000;
- int64_t i_movie_duration = 0;
- msg_Info( p_mux, "Close" );
+ sout_mux_sys_t *p_sys = p_mux->p_sys;
+ bo_t *udta = box_new( "udta" );
+ int i_track;
- /* create general info */
- for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
+ /* Requirements */
+ for( i_track = 0; i_track < p_sys->i_nb_streams; i_track++ )
{
- mp4_stream_t *p_stream;
-
- p_stream = p_sys->pp_streams[i_trak];
+ mp4_stream_t *p_stream = p_sys->pp_streams[i_track];
- i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration );
+ if( p_stream->p_fmt->i_codec == VLC_FOURCC('m','p','4','v') ||
+ p_stream->p_fmt->i_codec == VLC_FOURCC('m','p','4','a') )
+ {
+ bo_t *box = box_new( "\251req" );
+ /* String length */
+ bo_add_16be( box, sizeof("QuickTime 6.0 or greater") - 1);
+ bo_add_16be( box, 0 );
+ bo_add_mem( box, sizeof("QuickTime 6.0 or greater") - 1,
+ "QuickTime 6.0 or greater" );
+ box_fix( box );
+ box_gather( udta, box );
+ break;
+ }
}
- msg_Dbg( p_mux, "movie duration %ds",
- (uint32_t)( i_movie_duration / (mtime_t)1000000 ) );
-
- i_movie_duration = i_movie_duration *
- (int64_t)i_movie_timescale / (int64_t)1000000;
- /* *** update mdat size *** */
- bo_init ( &bo, 0, NULL, VLC_TRUE );
- if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) )
+ /* Encoder */
{
- /* Extended size */
- bo_add_32be ( &bo, 1 );
- bo_add_fourcc( &bo, "mdat" );
- bo_add_64be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos );
- }
- else
- {
- bo_add_32be ( &bo, 8 );
- bo_add_fourcc( &bo, "wide" );
- bo_add_32be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 );
- bo_add_fourcc( &bo, "mdat" );
+ bo_t *box = box_new( "\251enc" );
+ /* String length */
+ bo_add_16be( box, sizeof(PACKAGE_STRING " stream output") - 1);
+ bo_add_16be( box, 0 );
+ bo_add_mem( box, sizeof(PACKAGE_STRING " stream output") - 1,
+ PACKAGE_STRING " stream output" );
+ box_fix( box );
+ box_gather( udta, box );
}
- p_hdr = bo_to_sout( p_mux->p_sout, &bo );
- free( bo.p_buffer );
+ box_fix( udta );
+ return udta;
+}
- /* seek to mdat */
- sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );
- sout_AccessOutWrite( p_mux->p_access, p_hdr );
+static uint32_t mvhd_matrix[9] =
+ { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
+
+static bo_t *GetMoovTag( sout_mux_t *p_mux )
+{
+ sout_mux_sys_t *p_sys = p_mux->p_sys;
- /* Now create header */
- sout_AccessOutSeek( p_mux->p_access, p_sys->i_pos );
+ bo_t *moov, *mvhd;
+ unsigned int i;
+ int i_trak, i_index;
+
+ uint32_t i_movie_timescale = 90000;
+ int64_t i_movie_duration = 0;
moov = box_new( "moov" );
mp4_stream_t *p_stream;
uint32_t i_timescale;
uint32_t i_chunk_count;
+ unsigned int i_chunk;
bo_t *trak;
bo_t *tkhd;
bo_t *stbl;
bo_t *stsd;
bo_t *stts;
+ bo_t *stco;
+ bo_t *stsc;
bo_t *stsz;
p_stream = p_sys->pp_streams[i_trak];
bo_add_16be( soun, 0 ); // revision level (0)
bo_add_32be( soun, 0 ); // vendor
bo_add_16be( soun, p_stream->p_fmt->audio.i_channels ); // channel-count
- bo_add_16be( soun, 16); // FIXME sample size
+ // sample size
+ bo_add_16be( soun, p_stream->p_fmt->audio.i_bitspersample ?
+ p_stream->p_fmt->audio.i_bitspersample : 16 );
bo_add_16be( soun, -2 ); // compression id
bo_add_16be( soun, 0 ); // packet size (0)
bo_add_16be( soun, p_stream->p_fmt->audio.i_rate ); // sampleratehi
box_fix( stsd );
box_gather( stbl, stsd );
- /* we will create chunk table and stsc table FIXME optim stsc table FIXME */
+ /* we will create chunk table and stsc table
+ * FIXME optim stsc table FIXME */
i_chunk_count = 0;
for( i = 0; i < p_stream->i_entry_count; )
{
}
/* chunk offset table */
+ p_stream->i_stco_pos = stbl->i_buffer + 16;
if( p_sys->i_pos >= (((uint64_t)0x1) << 32) )
{
/* 64 bits version */
- bo_t *co64;
- bo_t *stsc;
-
- unsigned int i_chunk;
-
msg_Dbg( p_mux, "creating %d chunk (co64)", i_chunk_count );
-
- co64 = box_full_new( "co64", 0, 0 );
- bo_add_32be( co64, i_chunk_count );
-
- stsc = box_full_new( "stsc", 0, 0 );
- bo_add_32be( stsc, i_chunk_count ); // entry-count
- for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
- {
- int i_first;
- bo_add_64be( co64, p_stream->entry[i].i_pos );
-
- i_first = i;
-
- while( i < p_stream->i_entry_count )
- {
- if( i + 1 < p_stream->i_entry_count &&
- p_stream->entry[i].i_pos + p_stream->entry[i].i_size
- != p_stream->entry[i + 1].i_pos )
- {
- i++;
- break;
- }
-
- i++;
- }
- bo_add_32be( stsc, 1 + i_chunk ); // first-chunk
- bo_add_32be( stsc, i - i_first ) ; // samples-per-chunk
- bo_add_32be( stsc, 1 ); // sample-descr-index
- }
- /* append co64 to stbl */
- box_fix( co64 );
- box_gather( stbl, co64 );
-
- /* append stsc to stbl */
- box_fix( stsc );
- box_gather( stbl, stsc );
+ p_stream->b_stco64 = VLC_TRUE;
+ stco = box_full_new( "co64", 0, 0 );
}
else
{
/* 32 bits version */
- bo_t *stco;
- bo_t *stsc;
-
- unsigned int i_chunk;
-
msg_Dbg( p_mux, "creating %d chunk (stco)", i_chunk_count );
-
+ p_stream->b_stco64 = VLC_FALSE;
stco = box_full_new( "stco", 0, 0 );
- bo_add_32be( stco, i_chunk_count );
+ }
- stsc = box_full_new( "stsc", 0, 0 );
- bo_add_32be( stsc, i_chunk_count ); // entry-count
- for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
- {
- int i_first;
+ bo_add_32be( stco, i_chunk_count );
+
+ stsc = box_full_new( "stsc", 0, 0 );
+ bo_add_32be( stsc, i_chunk_count ); // entry-count
+ for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
+ {
+ int i_first;
+
+ if( p_stream->b_stco64 )
+ bo_add_64be( stco, p_stream->entry[i].i_pos );
+ else
bo_add_32be( stco, p_stream->entry[i].i_pos );
- i_first = i;
+ i_first = i;
- while( i < p_stream->i_entry_count )
+ while( i < p_stream->i_entry_count )
+ {
+ if( i + 1 < p_stream->i_entry_count &&
+ p_stream->entry[i].i_pos + p_stream->entry[i].i_size
+ != p_stream->entry[i + 1].i_pos )
{
- if( i + 1 < p_stream->i_entry_count &&
- p_stream->entry[i].i_pos + p_stream->entry[i].i_size
- != p_stream->entry[i + 1].i_pos )
- {
- i++;
- break;
- }
-
i++;
+ break;
}
- bo_add_32be( stsc, 1 + i_chunk ); // first-chunk
- bo_add_32be( stsc, i - i_first ) ; // samples-per-chunk
- bo_add_32be( stsc, 1 ); // sample-descr-index
- }
- /* append stco to stbl */
- box_fix( stco );
- box_gather( stbl, stco );
- /* append stsc to stbl */
- box_fix( stsc );
- box_gather( stbl, stsc );
+ i++;
+ }
+ bo_add_32be( stsc, 1 + i_chunk ); // first-chunk
+ bo_add_32be( stsc, i - i_first ) ; // samples-per-chunk
+ bo_add_32be( stsc, 1 ); // sample-descr-index
}
+ /* append stco to stbl */
+ box_fix( stco );
+ box_gather( stbl, stco );
+
+ /* append stsc to stbl */
+ box_fix( stsc );
+ box_gather( stbl, stsc );
/* add stts */
stts = box_full_new( "stts", 0, 0 );
/* append stbl to minf */
box_fix( stbl );
+ p_stream->i_stco_pos += minf->i_buffer;
box_gather( minf, stbl );
/* append minf to mdia */
box_fix( minf );
+ p_stream->i_stco_pos += mdia->i_buffer;
box_gather( mdia, minf );
/* append mdia to trak */
box_fix( mdia );
+ p_stream->i_stco_pos += trak->i_buffer;
box_gather( trak, mdia );
/* append trak to moov */
box_fix( trak );
+ p_stream->i_stco_pos += moov->i_buffer;
box_gather( moov, trak );
}
+ /* Add user data tags */
+ box_gather( moov, GetUdtaTag( p_mux ) );
+
box_fix( moov );
- box_send( p_mux, moov );
+ return moov;
+}
- /* *** release memory *** */
+/*****************************************************************************
+ * Close:
+ *****************************************************************************/
+static void Close( vlc_object_t * p_this )
+{
+ sout_mux_t *p_mux = (sout_mux_t*)p_this;
+ sout_mux_sys_t *p_sys = p_mux->p_sys;
+ sout_buffer_t *p_hdr;
+ bo_t bo, *moov;
+ vlc_value_t val;
+
+ int i_trak;
+ uint64_t i_moov_pos;
+
+ uint32_t i_movie_timescale = 90000;
+ int64_t i_movie_duration = 0;
+
+ msg_Dbg( p_mux, "Close" );
+
+ /* Create general info */
for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
{
- mp4_stream_t *p_stream;
+ mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
+ i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration );
+ }
+ msg_Dbg( p_mux, "movie duration %ds",
+ (uint32_t)( i_movie_duration / (mtime_t)1000000 ) );
- p_stream = p_sys->pp_streams[i_trak];
+ i_movie_duration = i_movie_duration * i_movie_timescale / 1000000;
+
+ /* Update mdat size */
+ bo_init( &bo, 0, NULL, VLC_TRUE );
+ if( p_sys->i_pos - p_sys->i_mdat_pos >= (((uint64_t)1)<<32) )
+ {
+ /* Extended size */
+ bo_add_32be ( &bo, 1 );
+ bo_add_fourcc( &bo, "mdat" );
+ bo_add_64be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos );
+ }
+ else
+ {
+ bo_add_32be ( &bo, 8 );
+ bo_add_fourcc( &bo, "wide" );
+ bo_add_32be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos - 8 );
+ bo_add_fourcc( &bo, "mdat" );
+ }
+ p_hdr = bo_to_sout( p_mux->p_sout, &bo );
+ free( bo.p_buffer );
+
+ sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos );
+ sout_AccessOutWrite( p_mux->p_access, p_hdr );
+
+ /* Create MOOV header */
+ i_moov_pos = p_sys->i_pos;
+ moov = GetMoovTag( p_mux );
+
+ /* Check we need to create "fast start" files */
+ var_Create( p_this, "mp4-faststart", VLC_VAR_BOOL | VLC_VAR_DOINHERIT );
+ var_Get( p_this, "mp4-faststart", &val );
+ p_sys->b_fast_start = val.b_bool;
+ while( p_sys->b_fast_start )
+ {
+ /* Move data to the end of the file so we can fit the moov header
+ * at the start */
+ sout_buffer_t *p_buf;
+ int64_t i_chunk, i_size = p_sys->i_pos - p_sys->i_mdat_pos;
+ int i_moov_size = moov->i_buffer;
+
+ while( i_size > 0 )
+ {
+ i_chunk = __MIN( 32768, i_size );
+ p_buf = sout_BufferNew( p_mux->p_sout, i_chunk );
+ sout_AccessOutSeek( p_mux->p_access,
+ p_sys->i_mdat_pos + i_size - i_chunk );
+ if( sout_AccessOutRead( p_mux->p_access, p_buf ) < i_chunk )
+ {
+ msg_Warn( p_this, "read() not supported by acces output, "
+ "won't create a fast start file" );
+ p_sys->b_fast_start = VLC_FALSE;
+ break;
+ }
+ sout_AccessOutSeek( p_mux->p_access, p_sys->i_mdat_pos + i_size +
+ i_moov_size - i_chunk );
+ sout_AccessOutWrite( p_mux->p_access, p_buf );
+ i_size -= i_chunk;
+ }
+
+ if( !p_sys->b_fast_start ) break;
+
+ /* Fix-up samples to chunks table in MOOV header */
+ for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
+ {
+ mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
+ unsigned int i;
+ int i_chunk;
+
+ moov->i_buffer = p_stream->i_stco_pos;
+ for( i_chunk = 0, i = 0; i < p_stream->i_entry_count; i_chunk++ )
+ {
+ if( p_stream->b_stco64 )
+ bo_add_64be( moov, p_stream->entry[i].i_pos + i_moov_size);
+ else
+ bo_add_32be( moov, p_stream->entry[i].i_pos + i_moov_size);
+
+ while( i < p_stream->i_entry_count )
+ {
+ if( i + 1 < p_stream->i_entry_count &&
+ p_stream->entry[i].i_pos + p_stream->entry[i].i_size
+ != p_stream->entry[i + 1].i_pos )
+ {
+ i++;
+ break;
+ }
+
+ i++;
+ }
+ }
+ }
+
+ moov->i_buffer = i_moov_size;
+ i_moov_pos = p_sys->i_mdat_pos;
+ p_sys->b_fast_start = VLC_FALSE;
+ }
+
+ /* Write MOOV header */
+ sout_AccessOutSeek( p_mux->p_access, i_moov_pos );
+ box_send( p_mux, moov );
+
+ /* Clean-up */
+ for( i_trak = 0; i_trak < p_sys->i_nb_streams; i_trak++ )
+ {
+ mp4_stream_t *p_stream = p_sys->pp_streams[i_trak];
if( p_stream->p_fmt->p_extra )
{
box_free( box2 );
}
-
static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout, bo_t *box )
{
sout_buffer_t *p_buf;