Commit d1d56e18 authored by Laurent Aimar's avatar Laurent Aimar

Improved ac3/eac3 support in mp4 (fix #2524).

parent 247685e3
...@@ -1111,6 +1111,31 @@ error: ...@@ -1111,6 +1111,31 @@ error:
MP4_READBOX_EXIT( 0 ); MP4_READBOX_EXIT( 0 );
} }
static int MP4_ReadBox_dac3( stream_t *p_stream, MP4_Box_t *p_box )
{
MP4_Box_data_dac3_t *p_dac3;
MP4_READBOX_ENTER( MP4_Box_data_dac3_t );
p_dac3 = p_box->data.p_dac3;
unsigned i_header;
MP4_GET3BYTES( i_header );
p_dac3->i_fscod = ( i_header >> 22 ) & 0x03;
p_dac3->i_bsid = ( i_header >> 17 ) & 0x01f;
p_dac3->i_bsmod = ( i_header >> 14 ) & 0x07;
p_dac3->i_acmod = ( i_header >> 11 ) & 0x07;
p_dac3->i_lfeon = ( i_header >> 10 ) & 0x01;
p_dac3->i_bitrate_code = ( i_header >> 5) & 0x1f;
#ifdef MP4_VERBOSE
msg_Dbg( p_stream,
"read box: \"dac3\" fscod=0x%x bsid=0x%x bsmod=0x%x acmod=0x%x lfeon=0x%x bitrate_code=0x%x",
p_dac3->i_fscod, p_dac3->i_bsid, p_dac3->i_bsmod, p_dac3->i_acmod, p_dac3->i_lfeon, p_dac3->i_bitrate_code );
#endif
MP4_READBOX_EXIT( 1 );
}
static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box ) static int MP4_ReadBox_sample_soun( stream_t *p_stream, MP4_Box_t *p_box )
{ {
unsigned int i; unsigned int i;
...@@ -2528,6 +2553,7 @@ static const struct ...@@ -2528,6 +2553,7 @@ static const struct
{ FOURCC_dcom, MP4_ReadBox_dcom, MP4_FreeBox_Common }, { FOURCC_dcom, MP4_ReadBox_dcom, MP4_FreeBox_Common },
{ FOURCC_cmvd, MP4_ReadBox_cmvd, MP4_FreeBox_cmvd }, { FOURCC_cmvd, MP4_ReadBox_cmvd, MP4_FreeBox_cmvd },
{ FOURCC_avcC, MP4_ReadBox_avcC, MP4_FreeBox_avcC }, { FOURCC_avcC, MP4_ReadBox_avcC, MP4_FreeBox_avcC },
{ FOURCC_dac3, MP4_ReadBox_dac3, MP4_FreeBox_Common },
/* Nothing to do with this box */ /* Nothing to do with this box */
{ FOURCC_mdat, MP4_ReadBoxSkip, MP4_FreeBox_Common }, { FOURCC_mdat, MP4_ReadBoxSkip, MP4_FreeBox_Common },
......
...@@ -118,6 +118,8 @@ ...@@ -118,6 +118,8 @@
#define FOURCC_sawb VLC_FOURCC( 's', 'a', 'w', 'b' ) #define FOURCC_sawb VLC_FOURCC( 's', 'a', 'w', 'b' )
#define FOURCC_OggS VLC_FOURCC( 'O', 'g', 'g', 'S' ) #define FOURCC_OggS VLC_FOURCC( 'O', 'g', 'g', 'S' )
#define FOURCC_alac VLC_FOURCC( 'a', 'l', 'a', 'c' ) #define FOURCC_alac VLC_FOURCC( 'a', 'l', 'a', 'c' )
#define FOURCC_dac3 VLC_FOURCC( 'd', 'a', 'c', '3' )
#define FOURCC_dec3 VLC_FOURCC( 'd', 'e', 'c', '3' )
#define FOURCC_zlib VLC_FOURCC( 'z', 'l', 'i', 'b' ) #define FOURCC_zlib VLC_FOURCC( 'z', 'l', 'i', 'b' )
#define FOURCC_SVQ1 VLC_FOURCC( 'S', 'V', 'Q', '1' ) #define FOURCC_SVQ1 VLC_FOURCC( 'S', 'V', 'Q', '1' )
...@@ -859,6 +861,17 @@ typedef struct ...@@ -859,6 +861,17 @@ typedef struct
} MP4_Box_data_avcC_t; } MP4_Box_data_avcC_t;
typedef struct
{
uint8_t i_fscod;
uint8_t i_bsid;
uint8_t i_bsmod;
uint8_t i_acmod;
uint8_t i_lfeon;
uint8_t i_bitrate_code;
} MP4_Box_data_dac3_t;
/* /*
typedef struct MP4_Box_data__s typedef struct MP4_Box_data__s
{ {
...@@ -892,6 +905,7 @@ typedef union MP4_Box_data_s ...@@ -892,6 +905,7 @@ typedef union MP4_Box_data_s
MP4_Box_data_esds_t *p_esds; MP4_Box_data_esds_t *p_esds;
MP4_Box_data_avcC_t *p_avcC; MP4_Box_data_avcC_t *p_avcC;
MP4_Box_data_dac3_t *p_dac3;
MP4_Box_data_stsz_t *p_stsz; MP4_Box_data_stsz_t *p_stsz;
MP4_Box_data_stz2_t *p_stz2; MP4_Box_data_stz2_t *p_stz2;
......
...@@ -1486,6 +1486,70 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track, ...@@ -1486,6 +1486,70 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
} }
} }
/* */
switch( p_track->fmt.i_cat )
{
case VIDEO_ES:
p_track->fmt.video.i_width = p_sample->data.p_sample_vide->i_width;
p_track->fmt.video.i_height = p_sample->data.p_sample_vide->i_height;
p_track->fmt.video.i_bits_per_pixel =
p_sample->data.p_sample_vide->i_depth;
/* fall on display size */
if( p_track->fmt.video.i_width <= 0 )
p_track->fmt.video.i_width = p_track->i_width;
if( p_track->fmt.video.i_height <= 0 )
p_track->fmt.video.i_height = p_track->i_height;
/* Find out apect ratio from display size */
if( p_track->i_width > 0 && p_track->i_height > 0 &&
/* Work-around buggy muxed files */
p_sample->data.p_sample_vide->i_width != p_track->i_width )
p_track->fmt.video.i_aspect =
VOUT_ASPECT_FACTOR * p_track->i_width / p_track->i_height;
/* Support for cropping (eg. in H263 files) */
p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
/* Frame rate */
p_track->fmt.video.i_frame_rate = p_track->i_timescale;
p_track->fmt.video.i_frame_rate_base = 1;
if( p_track->fmt.video.i_frame_rate &&
(p_box = MP4_BoxGet( p_track->p_stbl, "stts" )) &&
p_box->data.p_stts->i_entry_count >= 1 )
{
p_track->fmt.video.i_frame_rate_base =
p_box->data.p_stts->i_sample_delta[0];
}
break;
case AUDIO_ES:
p_track->fmt.audio.i_channels =
p_sample->data.p_sample_soun->i_channelcount;
p_track->fmt.audio.i_rate =
p_sample->data.p_sample_soun->i_sampleratehi;
p_track->fmt.i_bitrate = p_sample->data.p_sample_soun->i_channelcount *
p_sample->data.p_sample_soun->i_sampleratehi *
p_sample->data.p_sample_soun->i_samplesize;
p_track->fmt.audio.i_bitspersample =
p_sample->data.p_sample_soun->i_samplesize;
if( p_track->i_sample_size != 0 &&
p_sample->data.p_sample_soun->i_qt_version == 1 && p_sample->data.p_sample_soun->i_sample_per_packet <= 0 )
{
msg_Err( p_demux, "Invalid sample per packet value for qt_version 1" );
return VLC_EGENERIC;
}
break;
default:
break;
}
/* It's a little ugly but .. there are special cases */ /* It's a little ugly but .. there are special cases */
switch( p_sample->i_type ) switch( p_sample->i_type )
{ {
...@@ -1498,6 +1562,34 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track, ...@@ -1498,6 +1562,34 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
p_soun->i_qt_version = 0; p_soun->i_qt_version = 0;
break; break;
} }
case( VLC_FOURCC( 'a', 'c', '-', '3' ) ):
{
MP4_Box_t *p_dac3_box = MP4_BoxGet( p_sample, "dac3", 0 );
p_track->fmt.i_codec = VLC_FOURCC( 'a', '5', '2', ' ' );
if( p_dac3_box )
{
static const int pi_bitrate[] = {
32, 40, 48, 56,
64, 80, 96, 112,
128, 160, 192, 224,
256, 320, 384, 448,
512, 576, 640,
};
MP4_Box_data_dac3_t *p_dac3 = p_dac3_box->data.p_dac3;
p_track->fmt.audio.i_channels = 0;
p_track->fmt.i_bitrate = 0;
if( p_dac3->i_bitrate_code < sizeof(pi_bitrate)/sizeof(*pi_bitrate) )
p_track->fmt.i_bitrate = pi_bitrate[p_dac3->i_bitrate_code] * 1000;
p_track->fmt.audio.i_bitspersample = 0;
}
break;
}
case( VLC_FOURCC( 'e', 'c', '-', '3' ) ):
{
p_track->fmt.i_codec = VLC_FOURCC( 'e', 'a', 'c', '3' );
break;
}
case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ): case( VLC_FOURCC( 'r', 'a', 'w', ' ' ) ):
case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ): case( VLC_FOURCC( 'N', 'O', 'N', 'E' ) ):
...@@ -1740,69 +1832,6 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track, ...@@ -1740,69 +1832,6 @@ static int TrackCreateES( demux_t *p_demux, mp4_track_t *p_track,
#undef p_decconfig #undef p_decconfig
/* some last initialisation */
switch( p_track->fmt.i_cat )
{
case VIDEO_ES:
p_track->fmt.video.i_width = p_sample->data.p_sample_vide->i_width;
p_track->fmt.video.i_height = p_sample->data.p_sample_vide->i_height;
p_track->fmt.video.i_bits_per_pixel =
p_sample->data.p_sample_vide->i_depth;
/* fall on display size */
if( p_track->fmt.video.i_width <= 0 )
p_track->fmt.video.i_width = p_track->i_width;
if( p_track->fmt.video.i_height <= 0 )
p_track->fmt.video.i_height = p_track->i_height;
/* Find out apect ratio from display size */
if( p_track->i_width > 0 && p_track->i_height > 0 &&
/* Work-around buggy muxed files */
p_sample->data.p_sample_vide->i_width != p_track->i_width )
p_track->fmt.video.i_aspect =
VOUT_ASPECT_FACTOR * p_track->i_width / p_track->i_height;
/* Support for cropping (eg. in H263 files) */
p_track->fmt.video.i_visible_width = p_track->fmt.video.i_width;
p_track->fmt.video.i_visible_height = p_track->fmt.video.i_height;
/* Frame rate */
p_track->fmt.video.i_frame_rate = p_track->i_timescale;
p_track->fmt.video.i_frame_rate_base = 1;
if( p_track->fmt.video.i_frame_rate &&
(p_box = MP4_BoxGet( p_track->p_stbl, "stts" )) &&
p_box->data.p_stts->i_entry_count >= 1 )
{
p_track->fmt.video.i_frame_rate_base =
p_box->data.p_stts->i_sample_delta[0];
}
break;
case AUDIO_ES:
p_track->fmt.audio.i_channels =
p_sample->data.p_sample_soun->i_channelcount;
p_track->fmt.audio.i_rate =
p_sample->data.p_sample_soun->i_sampleratehi;
p_track->fmt.i_bitrate = p_sample->data.p_sample_soun->i_channelcount *
p_sample->data.p_sample_soun->i_sampleratehi *
p_sample->data.p_sample_soun->i_samplesize;
p_track->fmt.audio.i_bitspersample =
p_sample->data.p_sample_soun->i_samplesize;
if( p_track->i_sample_size != 0 &&
p_sample->data.p_sample_soun->i_qt_version == 1 && p_sample->data.p_sample_soun->i_sample_per_packet <= 0 )
{
msg_Err( p_demux, "Invalid sample per packet value for qt_version 1" );
return VLC_EGENERIC;
}
break;
default:
break;
}
if( pp_es ) if( pp_es )
*pp_es = es_out_Add( p_demux->out, &p_track->fmt ); *pp_es = es_out_Add( p_demux->out, &p_track->fmt );
......
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