Commit 94bda0d1 authored by Laurent Aimar's avatar Laurent Aimar

* include/common.h and input_ext-plugins.h, src/misc/modules_plugin.h :...

    * include/common.h and input_ext-plugins.h, src/misc/modules_plugin.h : export input_ClockGetTS for plugins.
    * plugins/mpeg_system/mpeg_audio.c : a demux for mpeg audio stream (file, web radio ...)
    * Makefile configure.in : to compile it
parent cdfc1ede
...@@ -128,6 +128,7 @@ PLUGINS_TARGETS := a52/a52 \ ...@@ -128,6 +128,7 @@ PLUGINS_TARGETS := a52/a52 \
motion/motionmmxext \ motion/motionmmxext \
motion/motion3dnow \ motion/motion3dnow \
motion/motionaltivec \ motion/motionaltivec \
mpeg_system/mpeg_audio \
mpeg_system/mpeg_es \ mpeg_system/mpeg_es \
mpeg_system/mpeg_ps \ mpeg_system/mpeg_ps \
mpeg_system/mpeg_ts \ mpeg_system/mpeg_ts \
......
...@@ -5417,7 +5417,7 @@ case x"${target_cpu}" in ...@@ -5417,7 +5417,7 @@ case x"${target_cpu}" in
esac esac
BUILTINS="${BUILTINS} idct idctclassic motion imdct downmix chroma_i420_rgb chroma_i420_yuy2 chroma_i422_yuy2 chroma_i420_ymga mpeg_adec ac3_adec mpeg_vdec" BUILTINS="${BUILTINS} idct idctclassic motion imdct downmix chroma_i420_rgb chroma_i420_yuy2 chroma_i422_yuy2 chroma_i420_ymga mpeg_adec ac3_adec mpeg_vdec"
PLUGINS="${PLUGINS} dummy null rc logger mpeg_es mpeg_ps mpeg_ts file udp http ipv4 memcpy lpcm_adec ac3_spdif spudec filter_deinterlace filter_invert filter_wall filter_transform filter_distort fx_scope" PLUGINS="${PLUGINS} dummy null rc logger mpeg_es mpeg_ps mpeg_ts mpeg_audio file udp http ipv4 memcpy lpcm_adec ac3_spdif spudec filter_deinterlace filter_invert filter_wall filter_transform filter_distort fx_scope"
MMX_MODULES="memcpymmx idctmmx motionmmx chroma_i420_rgb_mmx chroma_i420_yuy2_mmx chroma_i422_yuy2_mmx chroma_i420_ymga_mmx" MMX_MODULES="memcpymmx idctmmx motionmmx chroma_i420_rgb_mmx chroma_i420_yuy2_mmx chroma_i422_yuy2_mmx chroma_i420_ymga_mmx"
MMXEXT_MODULES="memcpymmxext idctmmxext motionmmxext" MMXEXT_MODULES="memcpymmxext idctmmxext motionmmxext"
......
...@@ -406,7 +406,7 @@ dnl ...@@ -406,7 +406,7 @@ dnl
dnl default modules dnl default modules
dnl dnl
BUILTINS="${BUILTINS} idct idctclassic motion imdct downmix chroma_i420_rgb chroma_i420_yuy2 chroma_i422_yuy2 chroma_i420_ymga mpeg_adec ac3_adec mpeg_vdec" BUILTINS="${BUILTINS} idct idctclassic motion imdct downmix chroma_i420_rgb chroma_i420_yuy2 chroma_i422_yuy2 chroma_i420_ymga mpeg_adec ac3_adec mpeg_vdec"
PLUGINS="${PLUGINS} dummy null rc logger mpeg_es mpeg_ps mpeg_ts file udp http ipv4 memcpy lpcm_adec ac3_spdif spudec filter_deinterlace filter_invert filter_wall filter_transform filter_distort fx_scope" PLUGINS="${PLUGINS} dummy null rc logger mpeg_es mpeg_ps mpeg_ts mpeg_audio file udp http ipv4 memcpy lpcm_adec ac3_spdif spudec filter_deinterlace filter_invert filter_wall filter_transform filter_distort fx_scope"
dnl dnl
dnl Accelerated modules dnl Accelerated modules
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* Collection of useful common types and macros definitions * Collection of useful common types and macros definitions
***************************************************************************** *****************************************************************************
* Copyright (C) 1998, 1999, 2000 VideoLAN * Copyright (C) 1998, 1999, 2000 VideoLAN
* $Id: common.h,v 1.103 2002/05/03 20:49:30 sam Exp $ * $Id: common.h,v 1.104 2002/05/10 02:04:16 fenrir Exp $
* *
* Authors: Samuel Hocevar <sam@via.ecp.fr> * Authors: Samuel Hocevar <sam@via.ecp.fr>
* Vincent Seguin <seguin@via.ecp.fr> * Vincent Seguin <seguin@via.ecp.fr>
...@@ -636,6 +636,9 @@ typedef struct module_symbols_s ...@@ -636,6 +636,9 @@ typedef struct module_symbols_s
int ( * input_ClockManageControl ) ( struct input_thread_s *, int ( * input_ClockManageControl ) ( struct input_thread_s *,
struct pgrm_descriptor_s *, struct pgrm_descriptor_s *,
mtime_t ); mtime_t );
mtime_t ( *input_ClockGetTS ) ( struct input_thread_s *,
struct pgrm_descriptor_s *,
mtime_t );
void ( * input_FDSeek ) ( struct input_thread_s *, off_t ); void ( * input_FDSeek ) ( struct input_thread_s *, off_t );
void ( * input_FDClose ) ( struct input_thread_s * ); void ( * input_FDClose ) ( struct input_thread_s * );
ssize_t ( * input_FDRead ) ( struct input_thread_s *, byte_t *, ssize_t ( * input_FDRead ) ( struct input_thread_s *, byte_t *,
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* but exported to plug-ins * but exported to plug-ins
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2002 VideoLAN * Copyright (C) 1999-2002 VideoLAN
* $Id: input_ext-plugins.h,v 1.24 2002/04/25 21:52:42 sam Exp $ * $Id: input_ext-plugins.h,v 1.25 2002/05/10 02:04:16 fenrir Exp $
* *
* Authors: Christophe Massiot <massiot@via.ecp.fr> * Authors: Christophe Massiot <massiot@via.ecp.fr>
* *
...@@ -102,6 +102,7 @@ mtime_t input_ClockGetTS( struct input_thread_s *, ...@@ -102,6 +102,7 @@ mtime_t input_ClockGetTS( struct input_thread_s *,
#else #else
# define input_ClockManageRef p_symbols->input_ClockManageRef # define input_ClockManageRef p_symbols->input_ClockManageRef
# define input_ClockManageControl p_symbols->input_ClockManageControl # define input_ClockManageControl p_symbols->input_ClockManageControl
# define input_ClockGetTS p_symbols->input_ClockGetTS
#endif #endif
/***************************************************************************** /*****************************************************************************
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* avi.c : AVI file Stream input module for vlc * avi.c : AVI file Stream input module for vlc
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: avi.c,v 1.14 2002/05/07 13:53:55 fenrir Exp $ * $Id: avi.c,v 1.15 2002/05/10 02:04:17 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
...@@ -438,7 +438,7 @@ static int AVIInit( input_thread_t *p_input ) ...@@ -438,7 +438,7 @@ static int AVIInit( input_thread_t *p_input )
/* we need to seek to be able to readcorrectly */ /* we need to seek to be able to readcorrectly */
if( !p_input->stream.b_seekable ) if( !p_input->stream.b_seekable )
{ {
intf_ErrMsg( "input error: need the ability to seek in stream" ); intf_WarnMsg( 2,"input: RIFF-AVI plug-in discarded (no seekable)" );
return( -1 ); return( -1 );
} }
p_input->p_demux_data = p_input->p_demux_data =
...@@ -461,7 +461,7 @@ static int AVIInit( input_thread_t *p_input ) ...@@ -461,7 +461,7 @@ static int AVIInit( input_thread_t *p_input )
if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 ) if( RIFF_TestFileHeader( p_input, &p_riff, FOURCC_AVI ) != 0 )
{ {
__AVIFreeDemuxData( p_input ); __AVIFreeDemuxData( p_input );
intf_ErrMsg( "input: RIFF-AVI plug-in discarded (avi_file)" ); intf_WarnMsg( 2,"input: RIFF-AVI plug-in discarded (avi_file)" );
return( -1 ); return( -1 );
} }
p_avi_demux->p_riff = p_riff; p_avi_demux->p_riff = p_riff;
...@@ -802,7 +802,6 @@ static int AVIInit( input_thread_t *p_input ) ...@@ -802,7 +802,6 @@ static int AVIInit( input_thread_t *p_input )
} }
else else
{ {
/* TODO: if there is more than 1 video stream */
intf_Msg( "input error: no video stream found !" ); intf_Msg( "input error: no video stream found !" );
} }
if( p_avi_demux->p_info_audio != NULL ) if( p_avi_demux->p_info_audio != NULL )
...@@ -883,17 +882,14 @@ static int __AVI_NextIndexEntry( input_thread_t *p_input, ...@@ -883,17 +882,14 @@ static int __AVI_NextIndexEntry( input_thread_t *p_input,
p_info->i_idxposc--; p_info->i_idxposc--;
/* create entry on the fly */ /* create entry on the fly */
/* TODO: when parsing for a stream take care of the other to not do /* search for the more advance stream and parse from it for all streams*/
the same things two time */
/* search for the less advance stream and parse from it for all streams*/
p_info_tmp = p_info; p_info_tmp = p_info;
/* XXX XXX XXX change to take the stream the more advanced */
for( i = 0; i < p_avi_demux->i_streams; i++ ) for( i = 0; i < p_avi_demux->i_streams; i++ )
{ {
#define p_info_i p_avi_demux->pp_info[i] #define p_info_i p_avi_demux->pp_info[i]
if( p_info_i->p_index[p_info_i->i_idxnb - 1].i_offset + if( p_info_i->p_index[p_info_i->i_idxnb - 1].i_offset +
p_info_i->i_idxoffset < p_info_i->i_idxoffset >
p_info_tmp->p_index[p_info_tmp->i_idxnb - 1].i_offset + p_info_tmp->p_index[p_info_tmp->i_idxnb - 1].i_offset +
p_info_tmp->i_idxoffset ) p_info_tmp->i_idxoffset )
{ {
...@@ -1264,6 +1260,8 @@ static int AVI_ReAlign( input_thread_t *p_input ) ...@@ -1264,6 +1260,8 @@ static int AVI_ReAlign( input_thread_t *p_input )
&& ( i_pos < p_info->p_index[p_info->i_idxposc].i_offset + && ( i_pos < p_info->p_index[p_info->i_idxposc].i_offset +
p_info->p_index[p_info->i_idxposc].i_length ) ) p_info->p_index[p_info->i_idxposc].i_length ) )
{ {
/* FIXME FIXME FIXME if master == audio and samplesize != 0 */
/* don't work with big chunk */
/* don't do anything we are in the current chunk */ /* don't do anything we are in the current chunk */
return( 0 ); return( 0 );
} }
...@@ -1387,7 +1385,6 @@ static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input, ...@@ -1387,7 +1385,6 @@ static pes_packet_t *AVI_GetFrameInPES( input_thread_t *p_input,
/* stream is chunk based , easy */ /* stream is chunk based , easy */
int i_chunk = __AVI_PTSToChunk( p_info, i_dpts); int i_chunk = __AVI_PTSToChunk( p_info, i_dpts);
/* at least one frame */ /* at least one frame */
/* i_chunk = __MIN( 50, i_chunk ); */ /* but no more than 20 */
/* read them */ /* read them */
p_pes_first = NULL; p_pes_first = NULL;
for( i = 0; i < i_chunk; i++ ) for( i = 0; i < i_chunk; i++ )
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* ffmpeg.c: video decoder using ffmpeg library * ffmpeg.c: video decoder using ffmpeg library
***************************************************************************** *****************************************************************************
* Copyright (C) 1999-2001 VideoLAN * Copyright (C) 1999-2001 VideoLAN
* $Id: ffmpeg.c,v 1.6 2002/05/07 13:55:36 fenrir Exp $ * $Id: ffmpeg.c,v 1.7 2002/05/10 02:04:17 fenrir Exp $
* *
* Authors: Laurent Aimar <fenrir@via.ecp.fr> * Authors: Laurent Aimar <fenrir@via.ecp.fr>
* *
...@@ -120,7 +120,7 @@ static int decoder_Probe( u8 *pi_type ) ...@@ -120,7 +120,7 @@ static int decoder_Probe( u8 *pi_type )
switch( *pi_type ) switch( *pi_type )
{ {
/* case( MPEG1_VIDEO_ES ): marche pas pr le moment /* case( MPEG1_VIDEO_ES ): marche pas pr le moment
case( MPEG2_VIDEO_ES ): */ case( MPEG2_VIDEO_ES ): */
case( MSMPEG4_VIDEO_ES ): case( MSMPEG4_VIDEO_ES ):
case( MPEG4_VIDEO_ES ): case( MPEG4_VIDEO_ES ):
return( 0 ); return( 0 );
......
...@@ -292,7 +292,7 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -292,7 +292,7 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
{ {
p_mad_adec->p_aout_fifo = aout_CreateFifo( p_mad_adec->p_aout_fifo = aout_CreateFifo(
AOUT_FIFO_PCM, /* fifo type */ AOUT_FIFO_PCM, /* fifo type */
p_libmad_pcm->channels, /* nr. of channels */ 2, /*p_libmad_pcm->channels,*/ /* nr. of channels */
p_libmad_pcm->samplerate, /* frame rate in Hz ?*/ p_libmad_pcm->samplerate, /* frame rate in Hz ?*/
p_libmad_pcm->length*2, /* length of output buffer *2 channels*/ p_libmad_pcm->length*2, /* length of output buffer *2 channels*/
NULL ); /* buffer */ NULL ); /* buffer */
...@@ -373,9 +373,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header ...@@ -373,9 +373,11 @@ enum mad_flow libmad_output(void *data, struct mad_header const *p_libmad_header
} }
/* DEBUG */ /* DEBUG */
/*
if (p_libmad_pcm->channels == 1) { if (p_libmad_pcm->channels == 1) {
intf_ErrMsg( "mad debug: libmad_output channels [%d]", p_libmad_pcm->channels); intf_ErrMsg( "mad debug: libmad_output channels [%d]", p_libmad_pcm->channels);
} }
*/
vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock); vlc_mutex_lock (&p_mad_adec->p_aout_fifo->data_lock);
p_mad_adec->p_aout_fifo->i_end_frame = (p_mad_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE; p_mad_adec->p_aout_fifo->i_end_frame = (p_mad_adec->p_aout_fifo->i_end_frame + 1) & AOUT_FIFO_SIZE;
......
...@@ -2,3 +2,5 @@ mpeg_es_SOURCES = mpeg_es.c ...@@ -2,3 +2,5 @@ mpeg_es_SOURCES = mpeg_es.c
mpeg_ps_SOURCES = mpeg_ps.c mpeg_ps_SOURCES = mpeg_ps.c
mpeg_ts_SOURCES = mpeg_ts.c mpeg_ts_SOURCES = mpeg_ts.c
mpeg_ts_dvbpsi_SOURCES = mpeg_ts.c mpeg_ts_dvbpsi_SOURCES = mpeg_ts.c
mpeg_audio_SOURCES = mpeg_audio.c
/*****************************************************************************
* mpeg_audio.c : mpeg_audio Stream input module for vlc
*****************************************************************************
* Copyright (C) 2001 VideoLAN
* $Id: mpeg_audio.c,v 1.1 2002/05/10 02:04:17 fenrir Exp $
* Authors: Laurent Aimar <fenrir@via.ecp.fr>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*****************************************************************************/
/*****************************************************************************
* Preamble
*****************************************************************************/
#include <stdlib.h> /* malloc(), free() */
#include <videolan/vlc.h>
#include <sys/types.h>
#include "stream_control.h"
#include "input_ext-intf.h"
#include "input_ext-dec.h"
#include "input_ext-plugins.h"
/*****************************************************************************
* Local prototypes
*****************************************************************************/
static void input_getfunctions( function_list_t * p_function_list );
static int MPEGAudioDemux ( struct input_thread_s * );
static int MPEGAudioInit ( struct input_thread_s * );
static void MPEGAudioEnd ( struct input_thread_s * );
/* TODO: support MPEG-2.5, not difficult */
/*****************************************************************************
* Build configuration tree.
*****************************************************************************/
MODULE_CONFIG_START
MODULE_CONFIG_STOP
MODULE_INIT_START
SET_DESCRIPTION( "MPEG I/II Audio stream demux" )
ADD_CAPABILITY( DEMUX, 110 )
ADD_SHORTCUT( "mpeg_audio" )
MODULE_INIT_STOP
MODULE_ACTIVATE_START
input_getfunctions( &p_module->p_functions->demux );
MODULE_ACTIVATE_STOP
MODULE_DEACTIVATE_START
MODULE_DEACTIVATE_STOP
/*****************************************************************************
* Functions exported as capabilities. They are declared as static so that
* we don't pollute the namespace too much.
*****************************************************************************/
static void input_getfunctions( function_list_t * p_function_list )
{
#define input p_function_list->functions.demux
input.pf_init = MPEGAudioInit;
input.pf_end = MPEGAudioEnd;
input.pf_demux = MPEGAudioDemux;
input.pf_rewind = NULL;
#undef input
}
/*****************************************************************************
* Definitions of structures and functions used by this plugins
*****************************************************************************/
typedef struct mpegaudio_format_s
{
u32 i_header;
int i_version;
int i_layer;
int i_crc;
int i_bitrate;
int i_samplingfreq;
int i_padding;
int i_extension;
int i_mode;
int i_modeext;
int i_copyright;
int i_original;
int i_emphasis;
} mpegaudio_format_t;
/* Xing Header if present */
#define FRAMES_FLAG 0x0001 /* these flags is for i_flags */
#define BYTES_FLAG 0x0002 /* because all is optionnal */
#define TOC_FLAG 0x0004
#define VBR_SCALE_FLAG 0x0008
typedef struct mpegaudio_xing_header_s
{
int i_flags; /* from Xing header data */
int i_frames; /* total bit stream frames from Xing header data */
int i_bytes; /* total bit stream bytes from Xing header data */
int i_vbr_scale; /* encoded vbr scale from Xing header data */
u8 i_toc[100]; /* for seek */
int i_avgbitrate; /* calculated, XXX: bits/sec not Kb */
} mpegaudio_xing_header_t;
typedef struct demux_data_mpegaudio_s
{
mtime_t i_pts;
int i_framecount;
es_descriptor_t *p_es;
mpegaudio_format_t mpeg;
mpegaudio_xing_header_t xingheader;
} demux_data_mpegaudio_t;
static int mpegaudio_bitrate[2][3][16] =
{
{
{ 0, 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448, 0 }, /* v1 l1 */
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384, 0 }, /* v1 l2 */
{ 0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 0 } /* v1 l3 */
},
{
{ 0, 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256, 0 }, /* v2 l1 */
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 }, /* v2 l2 */
{ 0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 0 } /* v2 l3 */
}
};
static int mpegaudio_samplingfreq[2][4] = /* version 1 then 2 */
{
{ 44100, 48000, 32000, 0 },
{ 22050, 24000, 16000, 0 }
};
static char* mpegaudio_mode[4] =
{
"stereo", "joint stereo", "dual channel", "mono"
};
/*****************************************************************************
* MPEGAudio_CheckHeader : Test the validity of the header
*****************************************************************************/
static int MPEGAudio_CheckHeader( u32 i_header )
{
if( ((( i_header >> 20 )&0x0FFF) != 0x0FFF ) /* header sync */
|| (((i_header >> 17)&0x03) == 0 ) /* valid layer ?*/
|| (((i_header >> 12)&0x0F) == 0x0F )
|| (((i_header >> 12)&0x0F) == 0x00 ) /* valid bitrate ? */
|| (((i_header >> 10) & 0x03) == 0x03 ) /* valide sampling freq ? */
|| ((i_header & 0x03) == 0x02 )) /* valid emphasis ? */
{
return( 0 ); /*invalid */
}
return( 1 ); /* valid */
}
/*****************************************************************************
* MPEGAudio_ParseHeader : Parse a header ;)
*****************************************************************************/
static void MPEGAudio_ParseHeader( u32 i_header, mpegaudio_format_t *p_mpeg )
{
p_mpeg->i_header = i_header;
p_mpeg->i_version = 1 - ( ( i_header >> 19 ) & 0x01 );
p_mpeg->i_layer = 3 - ( ( i_header >> 17 ) & 0x03 );
p_mpeg->i_crc = 1 - (( i_header >> 16 ) & 0x01);
p_mpeg->i_bitrate = mpegaudio_bitrate[p_mpeg->i_version][p_mpeg->i_layer][(i_header>>12)&0x0F];
p_mpeg->i_samplingfreq = mpegaudio_samplingfreq[p_mpeg->i_version][(i_header>>10)&0x03];
p_mpeg->i_padding = (( i_header >> 9 ) & 0x01);
p_mpeg->i_extension = ( i_header >> 7 ) & 0x01;
p_mpeg->i_mode = ( i_header >> 6 ) & 0x03;
p_mpeg->i_modeext = ( i_header >> 4 ) & 0x03;
p_mpeg->i_copyright = ( i_header >> 3 ) & 0x01;
p_mpeg->i_original = ( i_header >> 2 ) & 0x01;
p_mpeg->i_emphasis = ( i_header ) & 0x03;
}
/*****************************************************************************
* MPEGAudio_FrameSize : give the size of a frame in the mpeg stream
*****************************************************************************/
static int MPEGAudio_FrameSize( mpegaudio_format_t *p_mpeg )
{
/* XXX if crc do i need to add 2 bytes or not? */
switch( p_mpeg->i_layer )
{
case( 0 ):
return( ( ( ( !p_mpeg->i_version ? 12000 : 6000 ) *
p_mpeg->i_bitrate ) /
p_mpeg->i_samplingfreq + p_mpeg->i_padding ) * 4);
case( 1 ):
case( 2 ):
return( ( ( !p_mpeg->i_version ? 144000 : 72000 ) *
p_mpeg->i_bitrate ) /
p_mpeg->i_samplingfreq + p_mpeg->i_padding );
}
return( 1024 ); /* must never happen, 1k to advance in stream*/
}
/*****************************************************************************
* MPEGAudio_DecodedFrameSize : give the length of the decoded pcm data
*****************************************************************************/
static int MPEGAudio_DecodedFrameSize( mpegaudio_format_t *p_mpeg )
{
switch( p_mpeg->i_layer )
{
case( 0 ): /* layer 1 */
return( 384);
case( 1 ): /* layer 2 */
return( 1152 );
case( 2 ): /* layer 3 */
return( !p_mpeg->i_version ? 1152 : 576 );
/* XXX: perhaps we have to /2 for all layer but i'm not sure */
}
return( 0 );
}
/*****************************************************************************
* MPEGAudio_FindFrame : Find a header that could be valid.
*****************************************************************************
* The idea is to search for 2 consecutive headers that seem valid
* Perhaps we can search 2 header with same version or samplefreq(...) to be
* more secure but this seems to be enougth
*****************************************************************************/
static int MPEGAudio_FindFrame( input_thread_t *p_input,
int *pi_pos,
mpegaudio_format_t *p_mpeg )
{
byte_t *p_buff;
u32 i_header;
int i_framesize;
int i_pos = 0;
int i_size = input_Peek( p_input, &p_buff, 8192 );
while( i_pos + 4 <= i_size ) /* need at least 4 bytes */
{
i_header = U32_AT( p_buff );
if( MPEGAudio_CheckHeader( i_header ) )
{
MPEGAudio_ParseHeader( i_header, p_mpeg );
i_framesize = MPEGAudio_FrameSize( p_mpeg );
if( ( i_pos + i_framesize + 4 > i_size )
||( MPEGAudio_CheckHeader( U32_AT( p_buff + i_framesize ) ) ) )
{
*pi_pos = i_pos;
return( 1 );
}
}
p_buff++;
i_pos++;
}
*pi_pos = 0;
return( 0 );
}
/*****************************************************************************
* MPEGAudio_ExtractXingHeader : extract a Xing header if exist
*****************************************************************************
* It also calcul avgbitrate, using Xing header if present or assume that
* the bitrate of the first frame is the same for the all file
*****************************************************************************/
static void MPEGAudio_ExtractXingHeader( input_thread_t *p_input,
mpegaudio_xing_header_t *p_xh )
{
int i_pos;
int i_size;
mpegaudio_format_t mpeg;
byte_t *p_buff;
p_xh->i_flags = 0; /* nothing present */
if( !(MPEGAudio_FindFrame( p_input, &i_pos, &mpeg )) )
{
return; /* failed , can't */
}
p_xh->i_avgbitrate = mpeg.i_bitrate * 1000; /* default */
/* 1024 is very very enougth */
if( ( i_size = input_Peek( p_input, &p_buff, 1024 + i_pos ) ) < 8 )
{
return;
}
p_buff += i_pos;
/* calculate pos of xing header */
if( !mpeg.i_version )
{
p_buff += mpeg.i_mode != 3 ? 36 : 21;
}
else
{
p_buff += mpeg.i_mode != 3 ? 21 : 13;
}
if( (*p_buff != 'X' )||(*(p_buff+1) != 'i' )
||(*(p_buff+2) != 'n' )||(*(p_buff+3) != 'g' ) )
{
return;
}
p_buff += 4;
p_xh->i_flags = U32_AT( p_buff );
p_buff += 4;
if( p_xh->i_flags&FRAMES_FLAG )
{
p_xh->i_frames = U32_AT( p_buff );
p_buff += 4;
}
if( p_xh->i_flags&BYTES_FLAG )
{
p_xh->i_bytes = U32_AT( p_buff );
p_buff += 4;
}
if( p_xh->i_flags&TOC_FLAG )
{
FAST_MEMCPY( p_xh->i_toc, p_buff, 100 );
p_buff += 100;
}
if( p_xh->i_flags&VBR_SCALE_FLAG )
{
p_xh->i_vbr_scale = U32_AT( p_buff );
p_buff += 4;
}
if( ( p_xh->i_flags&FRAMES_FLAG )&&( p_xh->i_flags&BYTES_FLAG ) )
{
p_xh->i_avgbitrate =
((u64)p_xh->i_bytes * (u64)8 * (u64)mpeg.i_samplingfreq) /
((u64)p_xh->i_frames * (u64)MPEGAudio_DecodedFrameSize( &mpeg));
}
}
/*****************************************************************************
* MPEGaudioInit : initializes MPEGaudio structures
*****************************************************************************/
static int MPEGAudioInit( input_thread_t * p_input )
{
demux_data_mpegaudio_t *p_mpegaudio;
mpegaudio_format_t mpeg;
es_descriptor_t * p_es;
int i_pos;
/* XXX: i don't know what it's supposed to do, copied from ESInit */
/* Initialize access plug-in structures. */
if( p_input->i_mtu == 0 )
{
/* Improve speed. */
p_input->i_bufsize = INPUT_DEFAULT_BUFSIZE;
}
if( !(MPEGAudio_FindFrame( p_input, &i_pos, &mpeg )) )
{
intf_ErrMsg( "input: MPEGAudio plug-in discarded (no MPEG header)" );
return( -1 );
}
vlc_mutex_lock( &p_input->stream.stream_lock );
if( input_InitStream( p_input, 0 ) == -1)
{
intf_ErrMsg( "input error: cannot init stream" );
return( -1 );
}
if( input_AddProgram( p_input, 0, 0) == NULL )
{
intf_ErrMsg( "input error: cannot add program" );
return( -1 );
}
p_input->stream.pp_programs[0]->b_is_ok = 0;
p_input->stream.p_selected_program =
p_input->stream.p_new_program = p_input->stream.pp_programs[0];
/* create our ES */
p_es = input_AddES( p_input,
p_input->stream.p_selected_program,
1, /* id */
0 );
if( !p_es )
{
vlc_mutex_unlock( &p_input->stream.stream_lock );
intf_ErrMsg( "input error: not enough memory." );
return( -1 );
}
p_es->i_stream_id = 1;
p_es->i_type = !mpeg.i_layer ? MPEG1_AUDIO_ES : MPEG2_AUDIO_ES;
p_es->i_cat = AUDIO_ES;
p_es->b_audio = 1;
input_SelectES( p_input, p_es );
p_input->stream.p_selected_program->b_is_ok = 1;
vlc_mutex_unlock( &p_input->stream.stream_lock );
/* create p_mpegaudio and init it */
p_input->p_demux_data =
p_mpegaudio = malloc( sizeof( demux_data_mpegaudio_t ));
if( !p_mpegaudio )
{
intf_ErrMsg( "input error: not enough memory." );
return( -1 );
}
/*input_ClockInit( p_input->stream.p_selected_program );
done by AddProgram */
p_mpegaudio->p_es = p_es;
p_mpegaudio->mpeg = mpeg;
p_mpegaudio->i_framecount = 0;
p_mpegaudio->i_pts = 0;
/* parse Xing Header if present */
MPEGAudio_ExtractXingHeader( p_input, &p_mpegaudio->xingheader );
vlc_mutex_lock( &p_input->stream.stream_lock );
p_input->stream.i_mux_rate = p_mpegaudio->xingheader.i_avgbitrate / 50 / 8;
vlc_mutex_unlock( &p_input->stream.stream_lock );
/* FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
/* if i don't do that, it don't work correctly but why ??? */
if( p_input->stream.b_seekable )
{
p_input->pf_seek( p_input, 0 );
input_AccessReinit( p_input );
}
/* FIXME FIXME FIXME FIXME FIXME FIXME FIXME */
/* all is ok :)) */
intf_Msg( "input init: Audio MPEG-%d layer %d %s %dHz %dKb/s %s",
mpeg.i_version + 1,
mpeg.i_layer +1 ,
mpegaudio_mode[mpeg.i_mode],
mpeg.i_samplingfreq,
p_mpegaudio->xingheader.i_avgbitrate / 1000,
p_mpegaudio->xingheader.i_flags ?
"VBR (Xing)" : ""
);
return( 0 );
}
/*****************************************************************************
* MPEGAudioEnd: frees unused data
*****************************************************************************/
static void MPEGAudioEnd( input_thread_t * p_input )
{
}
/*****************************************************************************
* MPEGAudioDemux: reads and demuxes data packets
*****************************************************************************
* Returns -1 in case of error, 0 in case of EOF, 1 otherwise
*****************************************************************************/
static int MPEGAudioDemux( input_thread_t * p_input )
{
int i_pos;
int i_toread;
pes_packet_t *p_pes;
mpegaudio_format_t mpeg;
demux_data_mpegaudio_t *p_mpegaudio =
(demux_data_mpegaudio_t*) p_input->p_demux_data;
/* look for a frame */
if( !MPEGAudio_FindFrame( p_input, &i_pos, &mpeg ) )
{
intf_WarnMsg( 1, "input error: cannot found next frame");
return( 0 );
}
/* if stream has changed */
if( ( mpeg.i_version != p_mpegaudio->mpeg.i_version )
||( mpeg.i_layer != p_mpegaudio->mpeg.i_layer )
||( mpeg.i_samplingfreq != p_mpegaudio->mpeg.i_samplingfreq ) )
{
intf_WarnMsg( 1, "input demux: stream has changed" );
p_mpegaudio->i_framecount = 0;
p_mpegaudio->i_pts = 0;
}
input_ClockManageRef( p_input,
p_input->stream.p_selected_program,
p_mpegaudio->i_pts );
/* in fact i_pos may be garbage but ... i don't want to skip it
it's borring ;) */
i_toread = MPEGAudio_FrameSize( &mpeg ) + i_pos;
/* create one pes */
if( !(p_pes = input_NewPES( p_input->p_method_data )) )
{
intf_ErrMsg( "input demux: out of memory" );
return( -1 );
}
while( i_toread > 0 )
{
data_packet_t *p_data;
int i_read;
if( (i_read = input_SplitBuffer( p_input, &p_data, i_toread ) ) <= 0 )
{
break;
}
if( !p_pes->p_first )
{
p_pes->p_first = p_data;
p_pes->i_nb_data = 1;
p_pes->i_pes_size = i_read;
}
else
{
p_pes->p_last->p_next = p_data;
p_pes->i_nb_data++;
p_pes->i_pes_size += i_read;
}
p_pes->p_last = p_data;
i_toread -= i_read;
}
/* XXX VERY STRANGE need to *90000 and not *1000000 WHYYYY ???
I know that for mpeg system clock unit is based on 90000 but
pts is not supposed to be in microsec for vlc ?
At least it's welcome to write it somewhere in input_clock.c
i've wasted time because of it :( */
p_mpegaudio->i_pts = (mtime_t)90000 *
(mtime_t)p_mpegaudio->i_framecount *
(mtime_t)MPEGAudio_DecodedFrameSize( &mpeg ) /
(mtime_t)mpeg.i_samplingfreq;
p_pes->i_dts = 0;
p_pes->i_pts = input_ClockGetTS( p_input,
p_input->stream.p_selected_program,
p_mpegaudio->i_pts );
if( !p_mpegaudio->p_es->p_decoder_fifo )
{
intf_ErrMsg( "input demux: no audio decoder" );
input_DeletePES( p_input->p_method_data, p_pes );
return( -1 ); /* perhaps not, it's my choice */
}
else
{
input_DecodePES( p_mpegaudio->p_es->p_decoder_fifo, p_pes );
}
p_mpegaudio->i_framecount++;
p_mpegaudio->mpeg = mpeg;
return( 1 );
}
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
* modules_plugin.h : Plugin management functions used by the core application. * modules_plugin.h : Plugin management functions used by the core application.
***************************************************************************** *****************************************************************************
* Copyright (C) 2001 VideoLAN * Copyright (C) 2001 VideoLAN
* $Id: modules_plugin.h,v 1.24 2002/05/03 20:49:30 sam Exp $ * $Id: modules_plugin.h,v 1.25 2002/05/10 02:04:17 fenrir Exp $
* *
* Authors: Samuel Hocevar <sam@zoy.org> * Authors: Samuel Hocevar <sam@zoy.org>
* *
...@@ -253,6 +253,7 @@ module_error( char *psz_buffer ) ...@@ -253,6 +253,7 @@ module_error( char *psz_buffer )
(p_symbols)->input_DemuxTS = input_DemuxTS; \ (p_symbols)->input_DemuxTS = input_DemuxTS; \
(p_symbols)->input_ClockManageRef = input_ClockManageRef; \ (p_symbols)->input_ClockManageRef = input_ClockManageRef; \
(p_symbols)->input_ClockManageControl = input_ClockManageControl; \ (p_symbols)->input_ClockManageControl = input_ClockManageControl; \
(p_symbols)->input_ClockGetTS = input_ClockGetTS; \
(p_symbols)->input_FDSeek = input_FDSeek; \ (p_symbols)->input_FDSeek = input_FDSeek; \
(p_symbols)->input_FDClose = input_FDClose; \ (p_symbols)->input_FDClose = input_FDClose; \
(p_symbols)->input_FDRead = input_FDRead; \ (p_symbols)->input_FDRead = input_FDRead; \
......
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