Commit d5f049db authored by Eric Petit's avatar Eric Petit

src/modules/raw2ts/*: capture audio in a separate thread (fixes bad

                       quality problems). needs cleaning.
parent 5207cf14
......@@ -2,7 +2,7 @@
* raw2ts.cpp: raw -> ES ffmpeg encoder -> TS
*-------------------------------------------------------------------------------
* (c)1999-2001 VideoLAN
* $Id: raw2ts.cpp,v 1.9 2003/02/21 00:18:56 titer Exp $
* $Id: raw2ts.cpp,v 1.10 2003/02/21 16:28:11 titer Exp $
*
* Authors: Tristan Leteurtre <tooney@videolan.org>
* (inspirated from Fabrice Bellard...)
......@@ -102,7 +102,6 @@ void C_Raw2TsMpegConverter::InitWork()
C_MpegConverter::InitWork();
iVideoContinuityCounter = 0;
iAudioContinuityCounter = 0;
iPATContinuityCounter = 0;
iPMTContinuityCounter = 0;
......@@ -176,29 +175,11 @@ void C_Raw2TsMpegConverter::InitWork()
m_Picture = (AVPicture *)malloc(sizeof(AVPicture));
// sound
register_avcodec(&mp2_encoder);
m_AudioCodec = avcodec_find_encoder( CODEC_ID_MP2 );
if( !m_AudioCodec )
{
throw E_Exception(GEN_ERR, "Cannot find encoder MP2 Audio");
}
m_AudioCodecContext = avcodec_alloc_context();
m_AudioCodecContext->bit_rate = 64000;
m_AudioCodecContext->sample_rate = 44100;
m_AudioCodecContext->channels = 2;
if( avcodec_open( m_AudioCodecContext, m_AudioCodec ) < 0 )
{
throw E_Exception(GEN_ERR, "Cannot init audio encoder");
}
m_iAudioSampleBufSize = 2 * m_AudioCodecContext->frame_size *
m_AudioCodecContext->channels;
m_iAudioOutBufSize = 10000; // FIXME: totally arbitrary !
m_AudioSampleBuf = (byte*)malloc( m_iAudioSampleBufSize );
m_AudioOutBuf = (byte*)malloc( m_iAudioOutBufSize );
// launch the sound thread
C_AudioThread * audioThread = new C_AudioThread( this, m_pReader,
m_pTsProvider,
m_pHandler );
audioThread->Create();
}
......@@ -281,29 +262,6 @@ void C_Raw2TsMpegConverter::DoWork()
TSPacketization(PesPacket, TimeStamp, 0xE0, &iVideoContinuityCounter);
// Get and encode the sound: time needed = ( 1 / m_iFrameRate ) second
int iLeft = 2 * 44100 / m_iFrameRate; // 16 bits samples
while( iLeft > 0 )
{
int inSize;
int outSize;
if( iLeft < m_iAudioSampleBufSize )
inSize = iLeft;
else
inSize = m_iAudioSampleBufSize;
m_pReader->GetAudioFrame(&m_AudioSampleBuf, m_iAudioSampleBufSize);
outSize = avcodec_encode_audio( m_AudioCodecContext, m_AudioOutBuf,
m_iAudioSampleBufSize, (short*)m_AudioSampleBuf );
PesPacket->BuildPacket(TimeStamp, 0xC0, m_AudioOutBuf, outSize );
TSPacketization(PesPacket, TimeStamp, 0xC0, &iAudioContinuityCounter);
iLeft -= inSize;
}
if(iRc == MPEG_ENDOFSTREAM)
{
C_String strPgrmName = m_pBroadcast->GetProgram()->GetName();
......@@ -392,3 +350,80 @@ u64 C_Raw2TsMpegConverter::GetTime(void)
return( (u64)tmp.tv_sec * 1000000 + (u64)tmp.tv_usec );
}
C_AudioThread::C_AudioThread( C_Raw2TsMpegConverter *pConverter,
C_MpegReader * pReader,
C_NetList * pTsProvider,
I_TsPacketHandler * pHandler )
: C_Thread()
{
m_pConverter = pConverter;
m_pReader = pReader;
m_pTsProvider = pTsProvider;
m_pHandler = pHandler;
}
void C_AudioThread::InitWork()
{
iAudioContinuityCounter = 0;
// find a codec
register_avcodec(&mp2_encoder);
m_AudioCodec = avcodec_find_encoder( CODEC_ID_MP2 );
if( !m_AudioCodec )
{
throw E_Exception(GEN_ERR, "Cannot find encoder MP2 Audio");
}
// set parameters
m_AudioCodecContext = avcodec_alloc_context();
m_AudioCodecContext->bit_rate = 64000;
m_AudioCodecContext->sample_rate = 44100;
m_AudioCodecContext->channels = 2;
// open it
if( avcodec_open( m_AudioCodecContext, m_AudioCodec ) < 0 )
{
throw E_Exception(GEN_ERR, "Cannot init audio encoder");
}
m_iAudioSampleBufSize = 2 * m_AudioCodecContext->frame_size *
m_AudioCodecContext->channels;
m_iAudioOutBufSize = 10000; // FIXME: totally arbitrary !
m_AudioSampleBuf = (byte*)malloc( m_iAudioSampleBufSize );
m_AudioOutBuf = (byte*)malloc( m_iAudioOutBufSize );
}
void C_AudioThread::DoWork()
{
int outSize;
u64 TimeStamp;
C_PesPacket * PesPacket = new C_PesPacket();
while( 1 )
{
TimeStamp = GetTime()*9/100 & 0x0effffff;
/* get some sound */
m_pReader->GetAudioFrame(&m_AudioSampleBuf, m_iAudioSampleBufSize);
/* encode it */
outSize = avcodec_encode_audio( m_AudioCodecContext, m_AudioOutBuf,
m_iAudioSampleBufSize, (short*)m_AudioSampleBuf );
/* build a packet and send it */
PesPacket->BuildPacket(TimeStamp, 0xC0, m_AudioOutBuf, outSize );
m_pConverter->TSPacketization(PesPacket, TimeStamp, 0xC0,
&iAudioContinuityCounter);
}
delete PesPacket;
}
u64 C_AudioThread::GetTime(void)
{
struct timeval tmp;
gettimeofday(&tmp, NULL);
return( (u64)tmp.tv_sec * 1000000 + (u64)tmp.tv_usec );
}
......@@ -2,7 +2,7 @@
* raw2ts.h: raw -> ES ffmpeg encoder -> TS
*-------------------------------------------------------------------------------
* (c)1999-2001 VideoLAN
* $Id: raw2ts.h,v 1.4 2003/02/20 05:57:23 titer Exp $
* $Id: raw2ts.h,v 1.5 2003/02/21 16:28:11 titer Exp $
*
* Authors: Tristan Leteurtre <tooney@videolan.org>
*
......@@ -43,36 +43,29 @@ class C_Raw2TsMpegConverter : public C_MpegConverter
{
public:
C_Raw2TsMpegConverter(C_Module* pModule, C_MpegConverterConfig& cConfig);
void TSPacketization(C_PesPacket * PesPacket, int TimeStamp,
u8 iPayloadType, int * iCC);
protected:
virtual void InitWork();
virtual void DoWork();
void TSPacketization(C_PesPacket * PesPacket, int TimeStamp,
u8 iPayloadType, int * iCC);
u64 GetTime();
// ffmpeg variables
AVCodec * m_Codec;
AVCodecContext *m_CodecContext;
AVCodec * m_AudioCodec;
AVCodecContext *m_AudioCodecContext;
// buffers
// AVFrame * m_Frame;
AVPicture * m_Picture;
byte *m_OutBuf, *m_PictureBuf;
int m_iOutBufSize, m_iOutSize, m_iPictureBufSize;
byte *m_AudioOutBuf, // to store encoded data
*m_AudioSampleBuf; // to store the raw data coming from dsp
int m_iAudioOutBufSize, m_iAudioSampleBufSize;
// parameters of the image
int m_iHeight, m_iWidth, m_iFrameRate, m_iPalette;
int iVideoContinuityCounter;
int iAudioContinuityCounter;
int iPATContinuityCounter, iPMTContinuityCounter ;
};
......@@ -80,6 +73,41 @@ protected:
// Declaration and implementation of C_Raw2TsMpegConverterModule
DECLARE_MODULE(Raw2Ts, MpegConverter, "raw2ts", C_MpegConverterConfig&);
//------------------------------------------------------------------------------
// C_AudioThread class
//------------------------------------------------------------------------------
//
//------------------------------------------------------------------------------
class C_AudioThread : public C_Thread
{
public:
C_AudioThread( C_Raw2TsMpegConverter * pConverter,
C_MpegReader * pReader, C_NetList * pTsProvider,
I_TsPacketHandler * pHandler );
protected:
virtual void InitWork();
virtual void DoWork();
virtual void StopWork() {}
virtual void CleanWork() {}
u64 GetTime();
private:
C_Raw2TsMpegConverter * m_pConverter;
C_MpegReader * m_pReader;
C_NetList * m_pTsProvider;
I_TsPacketHandler * m_pHandler;
AVCodec * m_AudioCodec;
AVCodecContext *m_AudioCodecContext;
byte *m_AudioOutBuf, // to store encoded data
*m_AudioSampleBuf; // to store the raw data coming from dsp
int m_iAudioOutBufSize, m_iAudioSampleBufSize;
int iAudioContinuityCounter;
};
#else
#error "Multiple inclusions of raw2ts.h"
......
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