Commit 6cad86e5 authored by Gildas Bazin's avatar Gildas Bazin

* modules/mux/mp4.c: support for mov muxing + cleanup.
* modules/codec/quicktime.c: small cleanup.
parent 3efebdbf
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* quicktime.c: a quicktime decoder that uses the QT library/dll * quicktime.c: a quicktime decoder that uses the QT library/dll
***************************************************************************** *****************************************************************************
* Copyright (C) 2003 VideoLAN * Copyright (C) 2003 VideoLAN
* $Id: quicktime.c,v 1.9 2003/07/21 17:48:31 gbazin Exp $ * $Id: quicktime.c,v 1.10 2003/08/01 20:06:43 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir at via.ecp.fr> * Authors: Laurent Aimar <fenrir at via.ecp.fr>
* Derk-Jan Hartman <thedj at users.sf.net> * Derk-Jan Hartman <thedj at users.sf.net>
...@@ -521,8 +521,6 @@ static int InitThreadAudio( adec_thread_t *p_dec ) ...@@ -521,8 +521,6 @@ static int InitThreadAudio( adec_thread_t *p_dec )
p_dec->i_buffer_size = 100*1000; p_dec->i_buffer_size = 100*1000;
p_dec->p_buffer = malloc( p_dec->i_buffer_size ); p_dec->p_buffer = malloc( p_dec->i_buffer_size );
p_dec->pts = -1;
vlc_mutex_unlock( lockval.p_address ); vlc_mutex_unlock( lockval.p_address );
return VLC_SUCCESS; return VLC_SUCCESS;
...@@ -549,10 +547,8 @@ static void DecodeThreadAudio( adec_thread_t *p_dec ) ...@@ -549,10 +547,8 @@ static void DecodeThreadAudio( adec_thread_t *p_dec )
p_dec->p_fifo->b_error = 1; p_dec->p_fifo->b_error = 1;
return; return;
} }
/*if( p_dec->pts <= 0 )*/
{
p_dec->pts = p_pes->i_pts; p_dec->pts = p_pes->i_pts;
}
if( p_pes->i_pes_size > 0 && p_pes->i_pts > mdate() ) if( p_pes->i_pes_size > 0 && p_pes->i_pts > mdate() )
{ {
...@@ -663,8 +659,6 @@ static void DecodeThreadAudio( adec_thread_t *p_dec ) ...@@ -663,8 +659,6 @@ static void DecodeThreadAudio( adec_thread_t *p_dec )
p_buff += i_frames * 4; p_buff += i_frames * 4;
i_out_frames -= i_frames; i_out_frames -= i_frames;
} }
p_dec->pts = -1;
} }
} }
} }
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* mp4.c * mp4.c
***************************************************************************** *****************************************************************************
* Copyright (C) 2001, 2002, 2003 VideoLAN * Copyright (C) 2001, 2002, 2003 VideoLAN
* $Id: mp4.c,v 1.2 2003/04/19 00:12:50 fenrir Exp $ * $Id: mp4.c,v 1.3 2003/08/01 20:06:43 gbazin Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -32,6 +32,10 @@ ...@@ -32,6 +32,10 @@
#include <vlc/input.h> #include <vlc/input.h>
#include <vlc/sout.h> #include <vlc/sout.h>
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#include "codecs.h" #include "codecs.h"
/***************************************************************************** /*****************************************************************************
...@@ -83,6 +87,8 @@ typedef struct ...@@ -83,6 +87,8 @@ typedef struct
struct sout_mux_sys_t struct sout_mux_sys_t
{ {
vlc_bool_t b_mov;
uint64_t i_mdat_pos; uint64_t i_mdat_pos;
uint64_t i_pos; uint64_t i_pos;
...@@ -114,14 +120,16 @@ static void bo_add_mem ( bo_t *, int , uint8_t * ); ...@@ -114,14 +120,16 @@ static void bo_add_mem ( bo_t *, int , uint8_t * );
static void bo_fix_32be ( bo_t *, int , uint32_t ); static void bo_fix_32be ( bo_t *, int , uint32_t );
static bo_t * box_new ( char *fcc ); static bo_t *box_new ( char *fcc );
static bo_t * box_full_new( char *fcc, uint8_t v, uint32_t f ); static bo_t *box_full_new( char *fcc, uint8_t v, uint32_t f );
static void box_fix ( bo_t *box ); static void box_fix ( bo_t *box );
static void box_free( bo_t *box ); static void box_free ( bo_t *box );
static void box_gather ( bo_t *box, bo_t *box2 ); static void box_gather ( bo_t *box, bo_t *box2 );
static void box_send( sout_mux_t *p_mux, bo_t *box ); static void box_send( sout_mux_t *p_mux, bo_t *box );
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 );
/***************************************************************************** /*****************************************************************************
...@@ -137,7 +145,8 @@ static int Open( vlc_object_t *p_this ) ...@@ -137,7 +145,8 @@ static int Open( vlc_object_t *p_this )
p_sys->i_pos = 0; p_sys->i_pos = 0;
p_sys->i_nb_streams = 0; p_sys->i_nb_streams = 0;
p_sys->pp_streams = NULL; p_sys->pp_streams = NULL;
p_sys->i_mdat_pos = 0;
p_sys->b_mov = p_mux->psz_mux && !strcmp( p_mux->psz_mux, "mov" );
msg_Info( p_mux, "Open" ); msg_Info( p_mux, "Open" );
...@@ -146,8 +155,9 @@ static int Open( vlc_object_t *p_this ) ...@@ -146,8 +155,9 @@ static int Open( vlc_object_t *p_this )
p_mux->pf_delstream = DelStream; p_mux->pf_delstream = DelStream;
p_mux->pf_mux = Mux; p_mux->pf_mux = Mux;
p_mux->p_sys = p_sys; p_mux->p_sys = p_sys;
//p_mux->i_preheader = 0;
if( !p_sys->b_mov )
{
/* Now add ftyp header */ /* Now add ftyp header */
box = box_new( "ftyp" ); box = box_new( "ftyp" );
bo_add_fourcc( box, "isom" ); bo_add_fourcc( box, "isom" );
...@@ -159,10 +169,11 @@ static int Open( vlc_object_t *p_this ) ...@@ -159,10 +169,11 @@ static int Open( vlc_object_t *p_this )
p_sys->i_mdat_pos = p_sys->i_pos; p_sys->i_mdat_pos = p_sys->i_pos;
box_send( p_mux, box ); box_send( p_mux, box );
}
/* Now add mdat header */ /* Now add mdat header */
box = box_new( "mdat" ); box = box_new( "mdat" );
bo_add_64be ( box, 0 ); // XXX large size bo_add_64be ( box, 0 ); // enough to store an extended size
p_sys->i_pos += box->i_buffer; p_sys->i_pos += box->i_buffer;
...@@ -201,25 +212,31 @@ static bo_t *GetESDS( mp4_stream_t *p_stream ) ...@@ -201,25 +212,31 @@ static bo_t *GetESDS( mp4_stream_t *p_stream )
esds = box_full_new( "esds", 0, 0 ); esds = box_full_new( "esds", 0, 0 );
bo_add_8 ( esds, 0x03 ); // ES_DescrTag bo_add_8 ( esds, 0x03 ); // ES_DescrTag
bo_add_24be( esds, GetDescriptorLength24b( 25 + i_decoder_specific_info_size ) ); bo_add_24be( esds,
GetDescriptorLength24b( 25 + i_decoder_specific_info_size ) );
bo_add_16be( esds, p_stream->i_track_id ); bo_add_16be( esds, p_stream->i_track_id );
bo_add_8 ( esds, 0x1f ); // flags=0|streamPriority=0x1f bo_add_8 ( esds, 0x1f ); // flags=0|streamPriority=0x1f
bo_add_8 ( esds, 0x04 ); // DecoderConfigDescrTag bo_add_8 ( esds, 0x04 ); // DecoderConfigDescrTag
bo_add_24be( esds, GetDescriptorLength24b( 13 + i_decoder_specific_info_size ) ); bo_add_24be( esds,
GetDescriptorLength24b( 13 + i_decoder_specific_info_size ) );
switch( p_stream->p_fmt->i_fourcc ) switch( p_stream->p_fmt->i_fourcc )
{ {
case VLC_FOURCC( 'm', 'p', '4', 'v' ): case VLC_FOURCC( 'm', 'p', '4', 'v' ):
i_object_type_indication = 0x20; i_object_type_indication = 0x20;
break; break;
case VLC_FOURCC( 'm', 'p', 'g', 'v' ): case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
i_object_type_indication = 0x60; /* FIXME MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */ /* FIXME MPEG-I=0x6b, MPEG-II = 0x60 -> 0x65 */
i_object_type_indication = 0x60;
break; break;
case VLC_FOURCC( 'm', 'p', '4', 'a' ): case VLC_FOURCC( 'm', 'p', '4', 'a' ):
i_object_type_indication = 0x40; /* FIXME for mpeg2-aac == 0x66->0x68 */ /* FIXME for mpeg2-aac == 0x66->0x68 */
i_object_type_indication = 0x40;
break; break;
case VLC_FOURCC( 'm', 'p', 'g', 'a' ): case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
i_object_type_indication = p_stream->p_fmt->i_sample_rate < 32000 ? 0x69 : 0x6b; i_object_type_indication =
p_stream->p_fmt->i_sample_rate < 32000 ? 0x69 : 0x6b;
break; break;
default: default:
i_object_type_indication = 0x00; i_object_type_indication = 0x00;
...@@ -232,15 +249,17 @@ static bo_t *GetESDS( mp4_stream_t *p_stream ) ...@@ -232,15 +249,17 @@ static bo_t *GetESDS( mp4_stream_t *p_stream )
bo_add_24be( esds, 1024 * 1024 ); // bufferSizeDB bo_add_24be( esds, 1024 * 1024 ); // bufferSizeDB
bo_add_32be( esds, 0x7fffffff ); // maxBitrate bo_add_32be( esds, 0x7fffffff ); // maxBitrate
bo_add_32be( esds, 0 ); // avgBitrate bo_add_32be( esds, 0 ); // avgBitrate
if( p_stream->p_fmt->i_extra_data > 0 ) if( p_stream->p_fmt->i_extra_data > 0 )
{ {
int i; int i;
bo_add_8 ( esds, 0x05 ); // DecoderSpecificInfo bo_add_8 ( esds, 0x05 ); // DecoderSpecificInfo
bo_add_24be( esds, GetDescriptorLength24b( p_stream->p_fmt->i_extra_data ) ); bo_add_24be( esds,
GetDescriptorLength24b( p_stream->p_fmt->i_extra_data ) );
for( i = 0; i < p_stream->p_fmt->i_extra_data; i++ ) for( i = 0; i < p_stream->p_fmt->i_extra_data; i++ )
{ {
bo_add_8 ( esds, p_stream->p_fmt->p_extra_data[i] ); bo_add_8( esds, p_stream->p_fmt->p_extra_data[i] );
} }
} }
...@@ -249,17 +268,16 @@ static bo_t *GetESDS( mp4_stream_t *p_stream ) ...@@ -249,17 +268,16 @@ static bo_t *GetESDS( mp4_stream_t *p_stream )
bo_add_24be( esds, GetDescriptorLength24b( 1 ) ); bo_add_24be( esds, GetDescriptorLength24b( 1 ) );
bo_add_8 ( esds, 0x02 ); // sl_predefined bo_add_8 ( esds, 0x02 ); // sl_predefined
box_fix( esds ); box_fix( esds );
return esds; return esds;
} }
/***************************************************************************** /*****************************************************************************
* Close: * Close:
*****************************************************************************/ *****************************************************************************/
static uint32_t mvhd_matrix[9] = { 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 }; static uint32_t mvhd_matrix[9] =
{ 0x10000, 0, 0, 0, 0x10000, 0, 0, 0, 0x40000000 };
static void Close( vlc_object_t * p_this ) static void Close( vlc_object_t * p_this )
{ {
...@@ -284,15 +302,29 @@ static void Close( vlc_object_t * p_this ) ...@@ -284,15 +302,29 @@ static void Close( vlc_object_t * p_this )
i_movie_duration = __MAX( i_movie_duration, p_stream->i_duration ); 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 ) ); 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; i_movie_duration = i_movie_duration *
(int64_t)i_movie_timescale / (int64_t)1000000;
/* *** update mdat size *** */ /* *** update mdat size *** */
bo_init ( &bo, 0, NULL, VLC_TRUE ); 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_32be ( &bo, 1 );
bo_add_fourcc( &bo, "mdat" ); bo_add_fourcc( &bo, "mdat" );
bo_add_64be ( &bo, p_sys->i_pos - p_sys->i_mdat_pos ); 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 ); p_hdr = bo_to_sout( p_mux->p_sout, &bo );
free( bo.p_buffer ); free( bo.p_buffer );
...@@ -306,11 +338,22 @@ static void Close( vlc_object_t * p_this ) ...@@ -306,11 +338,22 @@ static void Close( vlc_object_t * p_this )
moov = box_new( "moov" ); moov = box_new( "moov" );
/* *** add /moov/mvhd *** */ /* *** add /moov/mvhd *** */
if( p_sys->b_mov )
{
mvhd = box_full_new( "mvhd", 0, 0 );
bo_add_32be( mvhd, get_timestamp() ); // creation time
bo_add_32be( mvhd, get_timestamp() ); // modification time
bo_add_32be( mvhd, i_movie_timescale); // timescale
bo_add_32be( mvhd, i_movie_duration ); // duration
}
else
{
mvhd = box_full_new( "mvhd", 1, 0 ); mvhd = box_full_new( "mvhd", 1, 0 );
bo_add_64be( mvhd, 0 ); // creation time FIXME bo_add_64be( mvhd, get_timestamp() ); // creation time
bo_add_64be( mvhd, 0 ); // modification time FIXME bo_add_64be( mvhd, get_timestamp() ); // modification time
bo_add_32be( mvhd, i_movie_timescale); // timescale bo_add_32be( mvhd, i_movie_timescale); // timescale
bo_add_64be( mvhd, i_movie_duration ); // duration bo_add_64be( mvhd, i_movie_duration ); // duration
}
bo_add_32be( mvhd, 0x10000 ); // rate bo_add_32be( mvhd, 0x10000 ); // rate
bo_add_16be( mvhd, 0x100 ); // volume bo_add_16be( mvhd, 0x100 ); // volume
bo_add_16be( mvhd, 0 ); // reserved bo_add_16be( mvhd, 0 ); // reserved
...@@ -326,7 +369,23 @@ static void Close( vlc_object_t * p_this ) ...@@ -326,7 +369,23 @@ static void Close( vlc_object_t * p_this )
{ {
bo_add_32be( mvhd, 0 ); // pre-defined bo_add_32be( mvhd, 0 ); // pre-defined
} }
bo_add_32be( mvhd, 0xffffffff ); // next-track-id FIXME
/* Find the 1st track id */
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->i_cat == AUDIO_ES ||
p_stream->p_fmt->i_cat == VIDEO_ES )
{
/* Found it */
bo_add_32be( mvhd, p_stream->i_track_id ); // next-track-id
break;
}
}
if( i_trak == p_sys->i_nb_streams ) /* Just for sanity reasons */
bo_add_32be( mvhd, 0xffffffff );
box_fix( mvhd ); box_fix( mvhd );
box_gather( moov, mvhd ); box_gather( moov, mvhd );
...@@ -351,7 +410,8 @@ static void Close( vlc_object_t * p_this ) ...@@ -351,7 +410,8 @@ static void Close( vlc_object_t * p_this )
p_stream = p_sys->pp_streams[i_trak]; p_stream = p_sys->pp_streams[i_trak];
if( p_stream->p_fmt->i_cat != AUDIO_ES && p_stream->p_fmt->i_cat != VIDEO_ES ) if( p_stream->p_fmt->i_cat != AUDIO_ES &&
p_stream->p_fmt->i_cat != VIDEO_ES )
{ {
msg_Err( p_mux, "FIXME ignoring trak (noaudio&&novideo)" ); msg_Err( p_mux, "FIXME ignoring trak (noaudio&&novideo)" );
continue; continue;
...@@ -369,14 +429,29 @@ static void Close( vlc_object_t * p_this ) ...@@ -369,14 +429,29 @@ static void Close( vlc_object_t * p_this )
trak = box_new( "trak" ); trak = box_new( "trak" );
/* *** add /moov/trak/tkhd *** */ /* *** add /moov/trak/tkhd *** */
if( p_sys->b_mov )
{
tkhd = box_full_new( "tkhd", 0, 1 );
bo_add_32be( tkhd, get_timestamp() ); // creation time
bo_add_32be( tkhd, get_timestamp() ); // modification time
bo_add_32be( tkhd, p_stream->i_track_id );
bo_add_32be( tkhd, 0 ); // reserved 0
bo_add_32be( tkhd, p_stream->i_duration *
(int64_t)i_movie_timescale /
(mtime_t)1000000 ); // duration
}
else
{
tkhd = box_full_new( "tkhd", 1, 1 ); tkhd = box_full_new( "tkhd", 1, 1 );
bo_add_64be( tkhd, 0 ); // creation time bo_add_64be( tkhd, get_timestamp() ); // creation time
bo_add_64be( tkhd, 0 ); // modification time bo_add_64be( tkhd, get_timestamp() ); // modification time
bo_add_32be( tkhd, p_stream->i_track_id ); bo_add_32be( tkhd, p_stream->i_track_id );
bo_add_32be( tkhd, 0 ); // reserved 0 bo_add_32be( tkhd, 0 ); // reserved 0
bo_add_64be( tkhd, p_stream->i_duration * bo_add_64be( tkhd, p_stream->i_duration *
(int64_t)i_movie_timescale / (int64_t)i_movie_timescale /
(mtime_t)1000000 ); // duration (mtime_t)1000000 ); // duration
}
for( i = 0; i < 2; i++ ) for( i = 0; i < 2; i++ )
{ {
bo_add_32be( tkhd, 0 ); // reserved bo_add_32be( tkhd, 0 ); // reserved
...@@ -406,13 +481,24 @@ static void Close( vlc_object_t * p_this ) ...@@ -406,13 +481,24 @@ static void Close( vlc_object_t * p_this )
mdia = box_new( "mdia" ); mdia = box_new( "mdia" );
/* */ /* */
if( p_sys->b_mov )
{
mdhd = box_full_new( "mdhd", 0, 0 );
bo_add_32be( mdhd, get_timestamp() ); // creation time
bo_add_32be( mdhd, get_timestamp() ); // modification time
bo_add_32be( mdhd, i_timescale); // timescale
bo_add_32be( mdhd, p_stream->i_duration * (int64_t)i_timescale /
(mtime_t)1000000 ); // duration
}
else
{
mdhd = box_full_new( "mdhd", 1, 0 ); mdhd = box_full_new( "mdhd", 1, 0 );
bo_add_64be( mdhd, 0 ); // creation time bo_add_64be( mdhd, get_timestamp() ); // creation time
bo_add_64be( mdhd, 0 ); // modification time bo_add_64be( mdhd, get_timestamp() ); // modification time
bo_add_32be( mdhd, i_timescale); // timescale bo_add_32be( mdhd, i_timescale); // timescale
bo_add_64be( mdhd, p_stream->i_duration * bo_add_64be( mdhd, p_stream->i_duration * (int64_t)i_timescale /
(int64_t)i_timescale /
(mtime_t)1000000 ); // duration (mtime_t)1000000 ); // duration
}
bo_add_16be( mdhd, 0 ); // language FIXME bo_add_16be( mdhd, 0 ); // language FIXME
bo_add_16be( mdhd, 0 ); // predefined bo_add_16be( mdhd, 0 ); // predefined
...@@ -498,11 +584,18 @@ static void Close( vlc_object_t * p_this ) ...@@ -498,11 +584,18 @@ static void Close( vlc_object_t * p_this )
switch( p_stream->p_fmt->i_fourcc ) switch( p_stream->p_fmt->i_fourcc )
{ {
case VLC_FOURCC( 'm', 'p', '4', 'a' ): case VLC_FOURCC( 'm', 'p', '4', 'a' ):
case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
memcpy( fcc, "mp4a", 4 ); memcpy( fcc, "mp4a", 4 );
b_mpeg4_hdr = VLC_TRUE; b_mpeg4_hdr = VLC_TRUE;
break; break;
case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
if( p_sys->b_mov )
memcpy( fcc, ".mp3 ", 4 );
else
memcpy( fcc, "mp4a", 4 );
b_mpeg4_hdr = VLC_FALSE;
break;
default: default:
memcpy( fcc, (char*)&p_stream->p_fmt->i_fourcc, 4 ); memcpy( fcc, (char*)&p_stream->p_fmt->i_fourcc, 4 );
b_mpeg4_hdr = VLC_FALSE; b_mpeg4_hdr = VLC_FALSE;
...@@ -553,6 +646,11 @@ static void Close( vlc_object_t * p_this ) ...@@ -553,6 +646,11 @@ static void Close( vlc_object_t * p_this )
b_mpeg4_hdr = VLC_TRUE; b_mpeg4_hdr = VLC_TRUE;
break; break;
case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
memcpy( fcc, "mjpa", 4 );
b_mpeg4_hdr = VLC_FALSE;
break;
default: default:
memcpy( fcc, (char*)&p_stream->p_fmt->i_fourcc, 4 ); memcpy( fcc, (char*)&p_stream->p_fmt->i_fourcc, 4 );
b_mpeg4_hdr = VLC_FALSE; b_mpeg4_hdr = VLC_FALSE;
...@@ -613,7 +711,9 @@ static void Close( vlc_object_t * p_this ) ...@@ -613,7 +711,9 @@ static void Close( vlc_object_t * p_this )
{ {
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++; i++;
break; break;
...@@ -686,7 +786,8 @@ static void Close( vlc_object_t * p_this ) ...@@ -686,7 +786,8 @@ static void Close( vlc_object_t * p_this )
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 + 1].i_length != i_delta ) if( i + 1 < p_stream->i_entry_count &&
p_stream->entry[i + 1].i_length != i_delta )
{ {
i++; i++;
break; break;
...@@ -696,8 +797,7 @@ static void Close( vlc_object_t * p_this ) ...@@ -696,8 +797,7 @@ static void Close( vlc_object_t * p_this )
} }
bo_add_32be( stts, i - i_first ); // sample-count bo_add_32be( stts, i - i_first ); // sample-count
bo_add_32be( stts, i_delta * bo_add_32be( stts, i_delta * (int64_t)i_timescale /
(int64_t)i_timescale /
(int64_t)1000000 ); // sample-delta (int64_t)1000000 ); // sample-delta
} }
bo_fix_32be( stts, 12, i_index ); bo_fix_32be( stts, 12, i_index );
...@@ -723,12 +823,10 @@ static void Close( vlc_object_t * p_this ) ...@@ -723,12 +823,10 @@ static void Close( vlc_object_t * p_this )
box_fix( stbl ); box_fix( stbl );
box_gather( minf, stbl ); box_gather( minf, stbl );
/* append minf to mdia */ /* append minf to mdia */
box_fix( minf ); box_fix( minf );
box_gather( mdia, minf ); box_gather( mdia, minf );
/* append mdia to trak */ /* append mdia to trak */
box_fix( mdia ); box_fix( mdia );
box_gather( trak, mdia ); box_gather( trak, mdia );
...@@ -759,7 +857,8 @@ static void Close( vlc_object_t * p_this ) ...@@ -759,7 +857,8 @@ static void Close( vlc_object_t * p_this )
free( p_sys ); free( p_sys );
} }
static int Capability( sout_mux_t *p_mux, int i_query, void *p_args, void *p_answer ) static int Capability( sout_mux_t *p_mux, int i_query, void *p_args,
void *p_answer )
{ {
switch( i_query ) switch( i_query )
{ {
...@@ -782,10 +881,11 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -782,10 +881,11 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
case VLC_FOURCC( 'm', 'p', '4', 'v' ): case VLC_FOURCC( 'm', 'p', '4', 'v' ):
case VLC_FOURCC( 'm', 'p', 'g', 'a' ): case VLC_FOURCC( 'm', 'p', 'g', 'a' ):
case VLC_FOURCC( 'm', 'p', 'g', 'v' ): case VLC_FOURCC( 'm', 'p', 'g', 'v' ):
case VLC_FOURCC( 'M', 'J', 'P', 'G' ):
case VLC_FOURCC( 'm', 'j', 'p', 'b' ):
break; break;
default: default:
msg_Err( p_mux, msg_Err( p_mux, "unsupported codec %4.4s in mp4",
"unsupported codec %4.4s in mp4",
(char*)&p_input->p_fmt->i_fourcc ); (char*)&p_input->p_fmt->i_fourcc );
return VLC_EGENERIC; return VLC_EGENERIC;
} }
...@@ -795,7 +895,8 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -795,7 +895,8 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
memcpy( p_stream->p_fmt, p_input->p_fmt, sizeof( sout_format_t ) ); memcpy( p_stream->p_fmt, p_input->p_fmt, sizeof( sout_format_t ) );
if( p_stream->p_fmt->i_extra_data ) if( p_stream->p_fmt->i_extra_data )
{ {
p_stream->p_fmt->p_extra_data = malloc( p_stream->p_fmt->i_extra_data ); p_stream->p_fmt->p_extra_data =
malloc( p_stream->p_fmt->i_extra_data );
memcpy( p_stream->p_fmt->p_extra_data, memcpy( p_stream->p_fmt->p_extra_data,
p_input->p_fmt->p_extra_data, p_input->p_fmt->p_extra_data,
p_input->p_fmt->i_extra_data ); p_input->p_fmt->i_extra_data );
...@@ -803,7 +904,8 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -803,7 +904,8 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
p_stream->i_track_id = p_sys->i_nb_streams + 1; p_stream->i_track_id = p_sys->i_nb_streams + 1;
p_stream->i_entry_count = 0; p_stream->i_entry_count = 0;
p_stream->i_entry_max = 1000; p_stream->i_entry_max = 1000;
p_stream->entry = calloc( p_stream->i_entry_max, sizeof( mp4_entry_t ) ); p_stream->entry =
calloc( p_stream->i_entry_max, sizeof( mp4_entry_t ) );
p_stream->i_duration = 0; p_stream->i_duration = 0;
p_input->p_sys = p_stream; p_input->p_sys = p_stream;
...@@ -816,17 +918,13 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input ) ...@@ -816,17 +918,13 @@ static int AddStream( sout_mux_t *p_mux, sout_input_t *p_input )
static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input ) static int DelStream( sout_mux_t *p_mux, sout_input_t *p_input )
{ {
msg_Dbg( p_mux, "removing input" ); msg_Dbg( p_mux, "removing input" );
return( 0 ); return( 0 );
} }
/****************************************************************************/ /****************************************************************************/
static int MuxGetStream( sout_mux_t *p_mux, static int MuxGetStream( sout_mux_t *p_mux, int *pi_stream, mtime_t *pi_dts )
int *pi_stream,
mtime_t *pi_dts )
{ {
mtime_t i_dts; mtime_t i_dts;
int i_stream; int i_stream;
...@@ -865,8 +963,7 @@ static int MuxGetStream( sout_mux_t *p_mux, ...@@ -865,8 +963,7 @@ static int MuxGetStream( sout_mux_t *p_mux,
return( i_stream ); return( i_stream );
} }
static int Mux( sout_mux_t *p_mux )
static int Mux ( sout_mux_t *p_mux )
{ {
sout_mux_sys_t *p_sys = p_mux->p_sys; sout_mux_sys_t *p_sys = p_mux->p_sys;
...@@ -895,13 +992,16 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -895,13 +992,16 @@ static int Mux ( sout_mux_t *p_mux )
p_stream->entry[p_stream->i_entry_count].i_size = p_data->i_size; p_stream->entry[p_stream->i_entry_count].i_size = p_data->i_size;
p_stream->entry[p_stream->i_entry_count].i_pts = p_data->i_pts; p_stream->entry[p_stream->i_entry_count].i_pts = p_data->i_pts;
p_stream->entry[p_stream->i_entry_count].i_dts = p_data->i_dts; p_stream->entry[p_stream->i_entry_count].i_dts = p_data->i_dts;
p_stream->entry[p_stream->i_entry_count].i_length= __MAX( p_data->i_length, 0 ); p_stream->entry[p_stream->i_entry_count].i_length=
__MAX( p_data->i_length, 0 );
p_stream->i_entry_count++; p_stream->i_entry_count++;
if( p_stream->i_entry_count >= p_stream->i_entry_max ) if( p_stream->i_entry_count >= p_stream->i_entry_max )
{ {
p_stream->i_entry_max += 1000; p_stream->i_entry_max += 1000;
p_stream->entry = realloc( p_stream->entry, p_stream->i_entry_max * sizeof( mp4_entry_t ) ); p_stream->entry =
realloc( p_stream->entry,
p_stream->i_entry_max * sizeof( mp4_entry_t ) );
} }
/* update */ /* update */
...@@ -918,8 +1018,8 @@ static int Mux ( sout_mux_t *p_mux ) ...@@ -918,8 +1018,8 @@ static int Mux ( sout_mux_t *p_mux )
/****************************************************************************/ /****************************************************************************/
static void bo_init( bo_t *p_bo, int i_size, uint8_t *p_buffer,
static void bo_init( bo_t *p_bo, int i_size, uint8_t *p_buffer, vlc_bool_t b_grow ) vlc_bool_t b_grow )
{ {
if( !p_buffer ) if( !p_buffer )
{ {
...@@ -1086,7 +1186,6 @@ static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout, bo_t *box ) ...@@ -1086,7 +1186,6 @@ static sout_buffer_t * bo_to_sout( sout_instance_t *p_sout, bo_t *box )
return p_buf; return p_buf;
} }
static void box_send( sout_mux_t *p_mux, bo_t *box ) static void box_send( sout_mux_t *p_mux, bo_t *box )
{ {
sout_buffer_t *p_buf; sout_buffer_t *p_buf;
...@@ -1097,5 +1196,15 @@ static void box_send( sout_mux_t *p_mux, bo_t *box ) ...@@ -1097,5 +1196,15 @@ static void box_send( sout_mux_t *p_mux, bo_t *box )
sout_AccessOutWrite( p_mux->p_access, p_buf ); sout_AccessOutWrite( p_mux->p_access, p_buf );
} }
static int64_t get_timestamp()
{
int64_t i_timestamp = 0;
#ifdef HAVE_TIME_H
i_timestamp = time(NULL);
i_timestamp += 2082844800; // MOV/MP4 start date is 1/1/1904
// 208284480 is (((1970 - 1904) * 365) + 17) * 24 * 60 * 60
#endif
return i_timestamp;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment