Skip to content

Audio: encode process #5

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
37 changes: 27 additions & 10 deletions app/audioRewrapper/audioRewrapper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include <AvTranscoder/InputFile.hpp>
#include <AvTranscoder/AvInputStream.hpp>
#include <AvTranscoder/InputStreamAudio.hpp>
#include <AvTranscoder/OutputStreamAudio.hpp>

#include <AvTranscoder/OutputFile.hpp>

Expand Down Expand Up @@ -54,38 +55,54 @@ void transcodeAudio( const char* inputfilename, const char* outputFilename )
// init audio decoders
InputStreamAudio inputStreamAudio( inputFile.getStream( 0 ) );
inputFile.getStream( 0 ).setBufferred( true );

OutputFile outputFile( outputFilename );

outputFile.setup();

outputFile.addAudioStream( inputFile.getStream( 0 ).getAudioDesc() );

DataStream data;

outputFile.beginWrap();

OutputStreamAudio outputStreamAudio;
AudioDesc& audioDesc = outputStreamAudio.getAudioDesc();
audioDesc.setAudioCodec( "pcm_s16le" );
audioDesc.setAudioParameters(
inputFile.getStream( 0 ).getAudioDesc().getSampleRate(),
inputFile.getStream( 0 ).getAudioDesc().getChannels(),
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;

size_t frame = 0;
AudioFrameDesc audioFrameDesc;

AudioFrame audioFrame( audioFrameDesc );

DataStream codedFrame;

while( inputStreamAudio.readNextFrame( audioFrame ) )
{
std::cout << "\rprocess frame " << (int)frame - 1 << std::endl << std::flush;

// convert

//outputStreamAudio.encodeFrame( audioFrame, codedFrame );
outputStreamAudio.encodeFrame( audioFrame, codedFrame );

// outputFile.wrap( codedFrame, 0 );
outputFile.wrap( codedFrame, 0 );

++frame;
}
std::cout << std::endl;

outputStreamAudio.encodeFrame( codedFrame );

outputFile.endWrap();
}

int main( int argc, char** argv )
Expand Down
5 changes: 5 additions & 0 deletions src/AvTranscoder/DatasStructures/AudioFrame.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ class AudioFrame
AudioFrame( const AudioFrameDesc& ref )
: m_dataBuffer( ref.getDataSize(), 0 )
, m_audioFrameDesc( ref )
, m_nbSamples( 0 )
{ }

const AudioFrameDesc& desc() const { return m_audioFrameDesc; }
Expand All @@ -74,10 +75,14 @@ class AudioFrame
const unsigned char* getPtr() const { return &m_dataBuffer[0]; }
#endif
size_t getSize() const { return m_dataBuffer.size(); }

size_t getNbSamples() const { return m_nbSamples; }
void setNbSamples( size_t nbSamples ) { m_nbSamples = nbSamples; }

private:
DataBuffer m_dataBuffer;
const AudioFrameDesc m_audioFrameDesc;
size_t m_nbSamples;
};

}
Expand Down
21 changes: 12 additions & 9 deletions src/AvTranscoder/InputStreamAudio.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,6 @@ InputStreamAudio::InputStreamAudio( AvInputStream& inputStream )

int ret = avcodec_open2( m_codecContext, m_codec, NULL );

std::cout << "ret value : " << ret << std::endl;

if( ret < 0 || m_codecContext == NULL || m_codec == NULL )
{
std::string msg = "unable open audio codec: ";
Expand Down Expand Up @@ -122,7 +120,10 @@ bool InputStreamAudio::readNextFrame( AudioFrame& audioFrameBuffer )

if( ret < 0 )
{
throw std::runtime_error( "an error occured during audio decoding" );
char err[250];
av_strerror( ret, err, 250);

throw std::runtime_error( "an error occured during audio decoding" + std::string( err ) );
}

av_free_packet( &packet );
Expand All @@ -132,16 +133,18 @@ bool InputStreamAudio::readNextFrame( AudioFrame& audioFrameBuffer )
m_frame->nb_samples,
m_codecContext->sample_fmt, 1);

audioFrameBuffer.setNbSamples( m_frame->nb_samples );

if( decodedSize )
{
if( audioFrameBuffer.getSize() != decodedSize )
audioFrameBuffer.getBuffer().resize( decodedSize );

audioFrameBuffer.getBuffer().resize( decodedSize, 0 );
unsigned char* dest = audioFrameBuffer.getPtr();
av_samples_fill_arrays(&dest, m_frame->linesize,
m_frame->data[0],
m_frame->channels, m_frame->nb_samples,
m_codecContext->sample_fmt, 1);
int nb_channels = m_codecContext->channels;
av_samples_copy(&dest, (uint8_t* const* )m_frame->data, 0,
0, m_frame->nb_samples, nb_channels,
m_codecContext->sample_fmt);
}

return true;
Expand Down
14 changes: 11 additions & 3 deletions src/AvTranscoder/InputStreamVideo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,17 @@ bool InputStreamVideo::readNextFrame( Image& frameBuffer )
packet.stream_index = m_selectedStream;
packet.data = data.getPtr();
packet.size = data.getSize();

avcodec_decode_video2( m_codecContext, m_frame, &got_frame, &packet );


int ret = avcodec_decode_video2( m_codecContext, m_frame, &got_frame, &packet );

if( ret < 0 )
{
char err[250];
av_strerror( ret, err, 250);

throw std::runtime_error( "an error occured during video decoding - " + std::string(err) );
}

av_free_packet( &packet );
}

Expand Down
164 changes: 163 additions & 1 deletion src/AvTranscoder/OutputStreamAudio.cpp
Original file line number Diff line number Diff line change
@@ -1 +1,163 @@
#include "OutputStreamAudio.hpp"
#include "OutputStreamAudio.hpp"

extern "C" {
#ifndef __STDC_CONSTANT_MACROS
#define __STDC_CONSTANT_MACROS
#endif
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavutil/avutil.h>
}

namespace avtranscoder
{

OutputStreamAudio::OutputStreamAudio()
: m_audioDesc( "pcm_s16le" )
{
}

bool OutputStreamAudio::setup()
{
av_register_all(); // Warning: should be called only once

AVCodecContext* codecContext( m_audioDesc.getCodecContext() );

if( codecContext == NULL )
return false;

// try to open encoder with parameters.
if( avcodec_open2( codecContext, m_audioDesc.getCodec(), NULL ) < 0 )
return false;

return true;
}

bool OutputStreamAudio::encodeFrame( const AudioFrame& decodedFrame, DataStream& codedFrame )
{
#if LIBAVCODEC_VERSION_MAJOR > 54
AVFrame* frame = av_frame_alloc();
#else
AVFrame* frame = avcodec_alloc_frame();
#endif

AVCodecContext* codecContext = m_audioDesc.getCodecContext();

// Set default frame parameters
#if LIBAVCODEC_VERSION_MAJOR > 54
av_frame_unref( frame );
#else
avcodec_get_frame_defaults( frame );
#endif

frame->nb_samples = decodedFrame.getNbSamples();
frame->format = codecContext->sample_fmt;
frame->channel_layout = codecContext->channel_layout;

// we calculate the size of the samples buffer in bytes
int buffer_size = av_samples_get_buffer_size(NULL, codecContext->channels, frame->nb_samples, codecContext->sample_fmt, 0);
if( buffer_size < 0 )
{
char err[250];
av_strerror( buffer_size, err, 250);

throw std::runtime_error( "EncodeFrame error: buffer size < 0 - " + std::string(err) );
}

int retvalue = avcodec_fill_audio_frame(frame, codecContext->channels, codecContext->sample_fmt, decodedFrame.getPtr(), buffer_size, 0);
if( retvalue < 0 )
{
char err[250];
av_strerror( retvalue, err, 250);

throw std::runtime_error( "EncodeFrame error: avcodec fill audio frame - " + std::string(err) );
}

AVPacket packet;
av_init_packet( &packet );

packet.size = 0;
packet.data = NULL;
packet.stream_index = 0;

if( ( codecContext->coded_frame ) &&
( codecContext->coded_frame->pts != (int)AV_NOPTS_VALUE ) )
{
packet.pts = codecContext->coded_frame->pts;
}

if( codecContext->coded_frame &&
codecContext->coded_frame->key_frame )
{
packet.flags |= AV_PKT_FLAG_KEY;
}

#if LIBAVCODEC_VERSION_MAJOR > 53
int gotPacket = 0;
int ret = avcodec_encode_audio2( codecContext, &packet, frame, &gotPacket );
if( ret == 0 && gotPacket == 1 )
{
codedFrame.getBuffer().resize( packet.size );
memcpy( codedFrame.getPtr(), packet.data, packet.size );
}
#else
int ret = avcodec_encode_audio( codecContext, packet.data, packet.size, frame );
if( ret > 0 )
{
codedFrame.getBuffer().resize( packet.size );
memcpy( codedFrame.getPtr(), packet.data, packet.size );
}
#endif

av_free_packet( &packet );

#if LIBAVCODEC_VERSION_MAJOR > 54
av_frame_free( &frame );
return ret == 0 && gotPacket == 1;
#else
#if LIBAVCODEC_VERSION_MAJOR > 53
avcodec_free_frame( &frame );
return ret == 0 && gotPacket == 1;
#else
av_free( frame );
#endif
#endif
return ret == 0;
}

bool OutputStreamAudio::encodeFrame( DataStream& codedFrame )
{
AVCodecContext* codecContext = m_audioDesc.getCodecContext();

AVPacket packet;
av_init_packet( &packet );

packet.size = 0;
packet.data = NULL;
packet.stream_index = 0;

#if LIBAVCODEC_VERSION_MAJOR > 53
int gotPacket = 0;
int ret = avcodec_encode_audio2( codecContext, &packet, NULL, &gotPacket );
if( ret == 0 && gotPacket == 1 )
{
codedFrame.getBuffer().resize( packet.size );
memcpy( codedFrame.getPtr(), packet.data, packet.size );
}
av_free_packet( &packet );
return ret == 0 && gotPacket == 1;

#else
int ret = avcodec_encode_audio( codecContext, packet.data, packet.size, NULL );
if( ret > 0 )
{
codedFrame.getBuffer().resize( packet.size );
memcpy( codedFrame.getPtr(), packet.data, packet.size );
}
av_free_packet( &packet );
return ret == 0;

#endif
}

}
21 changes: 19 additions & 2 deletions src/AvTranscoder/OutputStreamAudio.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,34 @@
#define _AV_TRANSCODER_OUTPUT_STREAM_AUDIO_HPP_

#include "OutputStream.hpp"
#include "DatasStructures/AudioFrame.hpp"
#include "DatasStructures/AudioDesc.hpp"
#include "DatasStructures/DataStreamDesc.hpp"

namespace avtranscoder
{

class OutputStreamAudio : public OutputStream
{
public:
OutputStreamAudio(){};
OutputStreamAudio();

bool setup();

private:
/**
* @param[out] codedFrame
*/
bool encodeFrame( const AudioFrame& decodedFrame, DataStream& codedFrame );

/**
* get delayed encoded frames
Copy link

Choose a reason for hiding this comment

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

Could you explain more?
From where the input comes from?

Copy link
Member

Choose a reason for hiding this comment

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

Itr's similar to video processing.
AudioFrame is the raw sound of data, like an image in video.
And the DataStream is the coded data.

I don't have doxygen generation on API, but need to provide it for adding correct documentation when API is a little more stable.

Copy link
Contributor

Choose a reason for hiding this comment

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

My question was about "encodeFrame( DataStream& codedFrame )" which has no decodedFrame argument.
Documentation can't be done at the end...

Copy link
Member

Choose a reason for hiding this comment

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

Hoo yep !

It's for ending last frame with data buffered in coder.
Also similar to video where latency can be not null ... due to a
reoganization of video frames or packetisation of audio streams.

2014-06-04 11:20 GMT+02:00 Fabien Castan notifications@github.com:

In src/AvTranscoder/OutputStreamAudio.hpp:

-private:

  • /**
  • * @param[out] codedFrame
  • */
  • bool encodeFrame( const AudioFrame& decodedFrame, DataStream& codedFrame );
  • /**
  • * get delayed encoded frames

My question was about "encodeFrame( DataStream& codedFrame )" which has no
decodedFrame argument.
Documentation can't be done at the end...


Reply to this email directly or view it on GitHub
https://github.com/MarcAntoine-Arnaud/avTranscoder/pull/5/files#r13377592
.

[image: Mikros Image - Pub Evian Spider-man the amazing babyme 2]
http://www.mikrosimage.eu/realisations/pub-l-evian-spider-man-the-amazing-babyme-2/
Marc-Antoine ARNAUD
R&D Software Developer -
Image Processing & Media Technology Expert

+33 1 55 63 11 00
mrn@mikrosimage.eu

Mikros Image /
Digital Post-Production for Video and Film

www.mikrosimage.eu

*/
bool encodeFrame( DataStream& codedFrame );

AudioDesc& getAudioDesc() { return m_audioDesc; }

private:
AudioDesc m_audioDesc;
};

}
Expand Down