Skip to content

Add AudioTransform: convert samples #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/SConscript
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ audioRewrapper = env.Program(
'avformat',
'avcodec',
'swscale',
'swresample',
]
)

Expand Down
62 changes: 38 additions & 24 deletions app/audioRewrapper/audioRewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,15 @@
#include <iomanip>

#include <AvTranscoder/InputFile.hpp>
#include <AvTranscoder/OutputFile.hpp>

#include <AvTranscoder/AvInputStream.hpp>
#include <AvTranscoder/InputStreamAudio.hpp>
#include <AvTranscoder/OutputStreamAudio.hpp>

#include <AvTranscoder/OutputFile.hpp>
#include <AvTranscoder/AudioTransform.hpp>



void rewrapAudio( const char* inputfilename, const char* outputFilename )
{
Expand Down Expand Up @@ -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)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no magick number without explanation.

// break;
}
std::cout << std::endl;

outputStreamAudio.encodeFrame( codedFrame );

outputFile.wrap( codedFrame, 0 );

// end of transcoding process

outputFile.endWrap();
}

Expand Down
70 changes: 70 additions & 0 deletions src/AvTranscoder/AudioTransform.cpp
Original file line number Diff line number Diff line change
@@ -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 <libavcodec/avcodec.h>
#include <libavutil/opt.h>
#include <libswresample/swresample.h>
#if LIBAVCODEC_VERSION_MAJOR > 54
#include <libavutil/frame.h>
#endif
}

#include <stdexcept>

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() );
}

}
30 changes: 30 additions & 0 deletions src/AvTranscoder/AudioTransform.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#ifndef _AV_TRANSCODER_AUDIO_TRANSFORM_HPP
#define _AV_TRANSCODER_AUDIO_TRANSFORM_HPP

#include "common.hpp"

class SwrContext;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

forward declaration outside of the namespace?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SwrContext is a LibAV class, so can't declare it inside avTranscoder namespace.
SwrContext is included in the .cpp.
We just use a pointer of it in the .hpp...

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, it's private and doesn't appear in the API. So it's a good thing to use forward declaration.


namespace avtranscoder
{

class AudioFrame;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Used in the public API, so should not use forward declaration.


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
12 changes: 12 additions & 0 deletions src/AvTranscoder/DatasStructures/AudioDesc.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "AudioDesc.hpp"
#include "AudioFrame.hpp"

extern "C" {
#ifndef __STDC_CONSTANT_MACROS
Expand Down Expand Up @@ -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;
}


}
4 changes: 4 additions & 0 deletions src/AvTranscoder/DatasStructures/AudioDesc.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ extern "C" {
#include <libavcodec/avcodec.h>
}

#include <AvTranscoder/DatasStructures/AudioFrame.hpp>

namespace avtranscoder
{

Expand Down Expand Up @@ -48,6 +50,8 @@ class AvExport AudioDesc
AVCodecContext* getCodecContext() const { return m_codecContext; }
#endif

AudioFrameDesc getFrameDesc() const;

private:
void initCodecContext( );

Expand Down
7 changes: 3 additions & 4 deletions src/AvTranscoder/InputStreamAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down