diff --git a/app/SConscript b/app/SConscript index 8070a012..8a36c3a6 100644 --- a/app/SConscript +++ b/app/SConscript @@ -69,6 +69,7 @@ audioRewrapper = env.Program( 'avformat', 'avcodec', 'swscale', + 'swresample', ] ) diff --git a/app/audioRewrapper/audioRewrapper.cpp b/app/audioRewrapper/audioRewrapper.cpp index 2310bdea..57f18b5a 100644 --- a/app/audioRewrapper/audioRewrapper.cpp +++ b/app/audioRewrapper/audioRewrapper.cpp @@ -2,11 +2,15 @@ #include #include +#include + #include #include #include -#include +#include + + void rewrapAudio( const char* inputfilename, const char* outputFilename ) { @@ -52,56 +56,66 @@ void transcodeAudio( const char* inputfilename, const char* outputFilename ) InputFile inputFile( inputfilename ); inputFile.analyse(); + OutputFile outputFile( outputFilename ); + outputFile.setup(); + // init audio decoders InputStreamAudio inputStreamAudio( inputFile.getStream( 0 ) ); inputFile.getStream( 0 ).setBufferred( true ); - - OutputFile outputFile( outputFilename ); - outputFile.setup(); - outputFile.addAudioStream( inputFile.getStream( 0 ).getAudioDesc() ); - outputFile.beginWrap(); + // init audio encoders OutputStreamAudio outputStreamAudio; - AudioDesc& audioDesc = outputStreamAudio.getAudioDesc(); - audioDesc.setAudioCodec( "pcm_s16le" ); - audioDesc.setAudioParameters( + AudioDesc& audioOutputDesc = outputStreamAudio.getAudioDesc(); + audioOutputDesc.setAudioCodec( "pcm_s24le" ); + audioOutputDesc.setAudioParameters( inputFile.getStream( 0 ).getAudioDesc().getSampleRate(), inputFile.getStream( 0 ).getAudioDesc().getChannels(), - inputFile.getStream( 0 ).getAudioDesc().getSampleFormat() + AV_SAMPLE_FMT_S32//,inputFile.getStream( 0 ).getAudioDesc().getSampleFormat() ); - DataStream codedFrame; - if( ! outputStreamAudio.setup( ) ) { std::cout << "error during initialising audio output stream" << std::endl; exit( -1 ); } - // Transcoding - std::cout << "start transcoding" << std::endl; + outputFile.addAudioStream( audioOutputDesc ); + outputFile.beginWrap(); + + // init convert + AudioTransform audioTransform; + + DataStream codedFrame; + // start transcoding process + std::cout << "start transcoding" << std::endl; + + AudioFrame audioFrameSource( inputFile.getStream( 0 ).getAudioDesc().getFrameDesc() ); + AudioFrame audioFrameToEncode( audioOutputDesc.getFrameDesc() ); + size_t frame = 0; - AudioFrameDesc audioFrameDesc; - - AudioFrame audioFrame( audioFrameDesc ); - - while( inputStreamAudio.readNextFrame( audioFrame ) ) + while( inputStreamAudio.readNextFrame( audioFrameSource ) ) { - std::cout << "\rprocess frame " << (int)frame - 1 << std::endl << std::flush; + std::cout << "\rprocess frame " << (int)frame - 1 << std::flush; - // convert - - outputStreamAudio.encodeFrame( audioFrame, codedFrame ); + audioTransform.convert( audioFrameSource, audioFrameToEncode ); + outputStreamAudio.encodeFrame( audioFrameToEncode, codedFrame ); + outputFile.wrap( codedFrame, 0 ); ++frame; + // if you want to stop the transcoding process (after 10s at 48,1 KHz) +// if(frame == 10*48100) +// break; } std::cout << std::endl; outputStreamAudio.encodeFrame( codedFrame ); - + outputFile.wrap( codedFrame, 0 ); + + // end of transcoding process + outputFile.endWrap(); } diff --git a/src/AvTranscoder/AudioTransform.cpp b/src/AvTranscoder/AudioTransform.cpp new file mode 100644 index 00000000..ca4fdca0 --- /dev/null +++ b/src/AvTranscoder/AudioTransform.cpp @@ -0,0 +1,70 @@ +#include "AudioTransform.hpp" +#include "DatasStructures/AudioFrame.hpp" +#include "common.hpp" + +extern "C" { +#ifndef __STDC_CONSTANT_MACROS + #define __STDC_CONSTANT_MACROS +#endif +#include +#include +#include +#if LIBAVCODEC_VERSION_MAJOR > 54 + #include +#endif +} + +#include + +namespace avtranscoder +{ + +AudioTransform::AudioTransform() + : m_audioConvertContext( NULL ) + , m_isInit ( false ) +{ +} + +bool AudioTransform::init( const AudioFrame& src, const AudioFrame& dst ) +{ + m_audioConvertContext = swr_alloc(); + + if( !m_audioConvertContext ) + { + throw std::runtime_error( "unable to create audio convert context" ); + } + + swr_alloc_set_opts( m_audioConvertContext, + av_get_default_channel_layout( dst.desc().getChannels() ), dst.desc().getSampleFormat(), av_get_default_channel_layout( dst.desc().getSampleRate() ), + av_get_default_channel_layout( src.desc().getChannels() ), src.desc().getSampleFormat(), av_get_default_channel_layout( src.desc().getSampleRate() ), + 0, NULL); + + if( swr_init( m_audioConvertContext ) < 0 ) + { + swr_free( &m_audioConvertContext ); + throw std::runtime_error( "unable to open audio convert context" ); + } + + return true; +} + +void AudioTransform::convert( const AudioFrame& src, AudioFrame& dst ) +{ + if( ! m_isInit ) + { + m_isInit = init( src, dst ); + m_isInit = true; + } + + if( dst.getSize() != src.getSize() ) + dst.getBuffer().resize( src.getSize(), 0 ); + + const unsigned char* srcData = src.getPtr(); + unsigned char* dstData = dst.getPtr(); + + swr_convert( m_audioConvertContext, &dstData, dst.getSize(), &srcData, src.getSize() ); + + dst.setNbSamples( src.getNbSamples() ); +} + +} diff --git a/src/AvTranscoder/AudioTransform.hpp b/src/AvTranscoder/AudioTransform.hpp new file mode 100644 index 00000000..543fe7f9 --- /dev/null +++ b/src/AvTranscoder/AudioTransform.hpp @@ -0,0 +1,30 @@ +#ifndef _AV_TRANSCODER_AUDIO_TRANSFORM_HPP +#define _AV_TRANSCODER_AUDIO_TRANSFORM_HPP + +#include "common.hpp" + +class SwrContext; + +namespace avtranscoder +{ + +class AudioFrame; + +class AvExport AudioTransform +{ +public: + AudioTransform(); + + void convert( const AudioFrame& src, AudioFrame& dst ); + +private: + bool init( const AudioFrame& src, const AudioFrame& dst ); + + SwrContext* m_audioConvertContext; + + bool m_isInit; +}; + +} + +#endif diff --git a/src/AvTranscoder/DatasStructures/AudioDesc.cpp b/src/AvTranscoder/DatasStructures/AudioDesc.cpp index 59199ea5..02207ed6 100644 --- a/src/AvTranscoder/DatasStructures/AudioDesc.cpp +++ b/src/AvTranscoder/DatasStructures/AudioDesc.cpp @@ -1,4 +1,5 @@ #include "AudioDesc.hpp" +#include "AudioFrame.hpp" extern "C" { #ifndef __STDC_CONSTANT_MACROS @@ -209,5 +210,16 @@ const AVSampleFormat AudioDesc::getSampleFormat() const return m_codecContext->sample_fmt; } +AudioFrameDesc AudioDesc::getFrameDesc() const +{ + AudioFrameDesc audioFrameDesc; + + audioFrameDesc.setChannels( m_codecContext->channels ); + audioFrameDesc.setSampleRate( m_codecContext->sample_rate ); + audioFrameDesc.setSampleFormat( m_codecContext->sample_fmt ); + + return audioFrameDesc; +} + } diff --git a/src/AvTranscoder/DatasStructures/AudioDesc.hpp b/src/AvTranscoder/DatasStructures/AudioDesc.hpp index d06f25cc..9b2132d6 100644 --- a/src/AvTranscoder/DatasStructures/AudioDesc.hpp +++ b/src/AvTranscoder/DatasStructures/AudioDesc.hpp @@ -15,6 +15,8 @@ extern "C" { #include } +#include + namespace avtranscoder { @@ -48,6 +50,8 @@ class AvExport AudioDesc AVCodecContext* getCodecContext() const { return m_codecContext; } #endif + AudioFrameDesc getFrameDesc() const; + private: void initCodecContext( ); diff --git a/src/AvTranscoder/InputStreamAudio.cpp b/src/AvTranscoder/InputStreamAudio.cpp index c65b14b5..f9a1889e 100644 --- a/src/AvTranscoder/InputStreamAudio.cpp +++ b/src/AvTranscoder/InputStreamAudio.cpp @@ -140,10 +140,9 @@ bool InputStreamAudio::readNextFrame( AudioFrame& audioFrameBuffer ) if( audioFrameBuffer.getSize() != decodedSize ) audioFrameBuffer.getBuffer().resize( decodedSize, 0 ); - unsigned char* dest = audioFrameBuffer.getPtr(); - int nb_channels = m_codecContext->channels; - av_samples_copy(&dest, (uint8_t* const* )m_frame->data, 0, - 0, m_frame->nb_samples, nb_channels, + unsigned char* dst = audioFrameBuffer.getPtr(); + av_samples_copy(&dst, (uint8_t* const* )m_frame->data, 0, + 0, m_frame->nb_samples, m_codecContext->channels, m_codecContext->sample_fmt); }