Skip to content

Commit 9feb59f

Browse files
Merge pull request #5 from cchampet/dev_audioProcessing
Audio: encode process
2 parents 75ebe8a + 3a719d0 commit 9feb59f

File tree

6 files changed

+237
-25
lines changed

6 files changed

+237
-25
lines changed

app/audioRewrapper/audioRewrapper.cpp

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#include <AvTranscoder/InputFile.hpp>
55
#include <AvTranscoder/AvInputStream.hpp>
66
#include <AvTranscoder/InputStreamAudio.hpp>
7+
#include <AvTranscoder/OutputStreamAudio.hpp>
78

89
#include <AvTranscoder/OutputFile.hpp>
910

@@ -54,38 +55,54 @@ void transcodeAudio( const char* inputfilename, const char* outputFilename )
5455
// init audio decoders
5556
InputStreamAudio inputStreamAudio( inputFile.getStream( 0 ) );
5657
inputFile.getStream( 0 ).setBufferred( true );
57-
58+
5859
OutputFile outputFile( outputFilename );
59-
6060
outputFile.setup();
61-
6261
outputFile.addAudioStream( inputFile.getStream( 0 ).getAudioDesc() );
63-
64-
DataStream data;
65-
62+
outputFile.beginWrap();
63+
64+
OutputStreamAudio outputStreamAudio;
65+
AudioDesc& audioDesc = outputStreamAudio.getAudioDesc();
66+
audioDesc.setAudioCodec( "pcm_s16le" );
67+
audioDesc.setAudioParameters(
68+
inputFile.getStream( 0 ).getAudioDesc().getSampleRate(),
69+
inputFile.getStream( 0 ).getAudioDesc().getChannels(),
70+
inputFile.getStream( 0 ).getAudioDesc().getSampleFormat()
71+
);
72+
73+
DataStream codedFrame;
74+
75+
if( ! outputStreamAudio.setup( ) )
76+
{
77+
std::cout << "error during initialising audio output stream" << std::endl;
78+
exit( -1 );
79+
}
80+
6681
// Transcoding
6782
std::cout << "start transcoding" << std::endl;
6883

6984
size_t frame = 0;
7085
AudioFrameDesc audioFrameDesc;
7186

7287
AudioFrame audioFrame( audioFrameDesc );
73-
74-
DataStream codedFrame;
7588

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

8093
// convert
8194

82-
//outputStreamAudio.encodeFrame( audioFrame, codedFrame );
95+
outputStreamAudio.encodeFrame( audioFrame, codedFrame );
8396

84-
// outputFile.wrap( codedFrame, 0 );
97+
outputFile.wrap( codedFrame, 0 );
8598

8699
++frame;
87100
}
88101
std::cout << std::endl;
102+
103+
outputStreamAudio.encodeFrame( codedFrame );
104+
105+
outputFile.endWrap();
89106
}
90107

91108
int main( int argc, char** argv )

src/AvTranscoder/DatasStructures/AudioFrame.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ class AudioFrame
6565
AudioFrame( const AudioFrameDesc& ref )
6666
: m_dataBuffer( ref.getDataSize(), 0 )
6767
, m_audioFrameDesc( ref )
68+
, m_nbSamples( 0 )
6869
{ }
6970

7071
const AudioFrameDesc& desc() const { return m_audioFrameDesc; }
@@ -74,10 +75,14 @@ class AudioFrame
7475
const unsigned char* getPtr() const { return &m_dataBuffer[0]; }
7576
#endif
7677
size_t getSize() const { return m_dataBuffer.size(); }
78+
79+
size_t getNbSamples() const { return m_nbSamples; }
80+
void setNbSamples( size_t nbSamples ) { m_nbSamples = nbSamples; }
7781

7882
private:
7983
DataBuffer m_dataBuffer;
8084
const AudioFrameDesc m_audioFrameDesc;
85+
size_t m_nbSamples;
8186
};
8287

8388
}

src/AvTranscoder/InputStreamAudio.cpp

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,6 @@ InputStreamAudio::InputStreamAudio( AvInputStream& inputStream )
5050

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

53-
std::cout << "ret value : " << ret << std::endl;
54-
5553
if( ret < 0 || m_codecContext == NULL || m_codec == NULL )
5654
{
5755
std::string msg = "unable open audio codec: ";
@@ -122,7 +120,10 @@ bool InputStreamAudio::readNextFrame( AudioFrame& audioFrameBuffer )
122120

123121
if( ret < 0 )
124122
{
125-
throw std::runtime_error( "an error occured during audio decoding" );
123+
char err[250];
124+
av_strerror( ret, err, 250);
125+
126+
throw std::runtime_error( "an error occured during audio decoding" + std::string( err ) );
126127
}
127128

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

136+
audioFrameBuffer.setNbSamples( m_frame->nb_samples );
137+
135138
if( decodedSize )
136139
{
137140
if( audioFrameBuffer.getSize() != decodedSize )
138-
audioFrameBuffer.getBuffer().resize( decodedSize );
139-
141+
audioFrameBuffer.getBuffer().resize( decodedSize, 0 );
142+
140143
unsigned char* dest = audioFrameBuffer.getPtr();
141-
av_samples_fill_arrays(&dest, m_frame->linesize,
142-
m_frame->data[0],
143-
m_frame->channels, m_frame->nb_samples,
144-
m_codecContext->sample_fmt, 1);
144+
int nb_channels = m_codecContext->channels;
145+
av_samples_copy(&dest, (uint8_t* const* )m_frame->data, 0,
146+
0, m_frame->nb_samples, nb_channels,
147+
m_codecContext->sample_fmt);
145148
}
146149

147150
return true;

src/AvTranscoder/InputStreamVideo.cpp

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,17 @@ bool InputStreamVideo::readNextFrame( Image& frameBuffer )
106106
packet.stream_index = m_selectedStream;
107107
packet.data = data.getPtr();
108108
packet.size = data.getSize();
109-
110-
avcodec_decode_video2( m_codecContext, m_frame, &got_frame, &packet );
111-
109+
110+
int ret = avcodec_decode_video2( m_codecContext, m_frame, &got_frame, &packet );
111+
112+
if( ret < 0 )
113+
{
114+
char err[250];
115+
av_strerror( ret, err, 250);
116+
117+
throw std::runtime_error( "an error occured during video decoding - " + std::string(err) );
118+
}
119+
112120
av_free_packet( &packet );
113121
}
114122

Lines changed: 163 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,163 @@
1-
#include "OutputStreamAudio.hpp"
1+
#include "OutputStreamAudio.hpp"
2+
3+
extern "C" {
4+
#ifndef __STDC_CONSTANT_MACROS
5+
#define __STDC_CONSTANT_MACROS
6+
#endif
7+
#include <libavcodec/avcodec.h>
8+
#include <libavformat/avformat.h>
9+
#include <libavutil/avutil.h>
10+
}
11+
12+
namespace avtranscoder
13+
{
14+
15+
OutputStreamAudio::OutputStreamAudio()
16+
: m_audioDesc( "pcm_s16le" )
17+
{
18+
}
19+
20+
bool OutputStreamAudio::setup()
21+
{
22+
av_register_all(); // Warning: should be called only once
23+
24+
AVCodecContext* codecContext( m_audioDesc.getCodecContext() );
25+
26+
if( codecContext == NULL )
27+
return false;
28+
29+
// try to open encoder with parameters.
30+
if( avcodec_open2( codecContext, m_audioDesc.getCodec(), NULL ) < 0 )
31+
return false;
32+
33+
return true;
34+
}
35+
36+
bool OutputStreamAudio::encodeFrame( const AudioFrame& decodedFrame, DataStream& codedFrame )
37+
{
38+
#if LIBAVCODEC_VERSION_MAJOR > 54
39+
AVFrame* frame = av_frame_alloc();
40+
#else
41+
AVFrame* frame = avcodec_alloc_frame();
42+
#endif
43+
44+
AVCodecContext* codecContext = m_audioDesc.getCodecContext();
45+
46+
// Set default frame parameters
47+
#if LIBAVCODEC_VERSION_MAJOR > 54
48+
av_frame_unref( frame );
49+
#else
50+
avcodec_get_frame_defaults( frame );
51+
#endif
52+
53+
frame->nb_samples = decodedFrame.getNbSamples();
54+
frame->format = codecContext->sample_fmt;
55+
frame->channel_layout = codecContext->channel_layout;
56+
57+
// we calculate the size of the samples buffer in bytes
58+
int buffer_size = av_samples_get_buffer_size(NULL, codecContext->channels, frame->nb_samples, codecContext->sample_fmt, 0);
59+
if( buffer_size < 0 )
60+
{
61+
char err[250];
62+
av_strerror( buffer_size, err, 250);
63+
64+
throw std::runtime_error( "EncodeFrame error: buffer size < 0 - " + std::string(err) );
65+
}
66+
67+
int retvalue = avcodec_fill_audio_frame(frame, codecContext->channels, codecContext->sample_fmt, decodedFrame.getPtr(), buffer_size, 0);
68+
if( retvalue < 0 )
69+
{
70+
char err[250];
71+
av_strerror( retvalue, err, 250);
72+
73+
throw std::runtime_error( "EncodeFrame error: avcodec fill audio frame - " + std::string(err) );
74+
}
75+
76+
AVPacket packet;
77+
av_init_packet( &packet );
78+
79+
packet.size = 0;
80+
packet.data = NULL;
81+
packet.stream_index = 0;
82+
83+
if( ( codecContext->coded_frame ) &&
84+
( codecContext->coded_frame->pts != (int)AV_NOPTS_VALUE ) )
85+
{
86+
packet.pts = codecContext->coded_frame->pts;
87+
}
88+
89+
if( codecContext->coded_frame &&
90+
codecContext->coded_frame->key_frame )
91+
{
92+
packet.flags |= AV_PKT_FLAG_KEY;
93+
}
94+
95+
#if LIBAVCODEC_VERSION_MAJOR > 53
96+
int gotPacket = 0;
97+
int ret = avcodec_encode_audio2( codecContext, &packet, frame, &gotPacket );
98+
if( ret == 0 && gotPacket == 1 )
99+
{
100+
codedFrame.getBuffer().resize( packet.size );
101+
memcpy( codedFrame.getPtr(), packet.data, packet.size );
102+
}
103+
#else
104+
int ret = avcodec_encode_audio( codecContext, packet.data, packet.size, frame );
105+
if( ret > 0 )
106+
{
107+
codedFrame.getBuffer().resize( packet.size );
108+
memcpy( codedFrame.getPtr(), packet.data, packet.size );
109+
}
110+
#endif
111+
112+
av_free_packet( &packet );
113+
114+
#if LIBAVCODEC_VERSION_MAJOR > 54
115+
av_frame_free( &frame );
116+
return ret == 0 && gotPacket == 1;
117+
#else
118+
#if LIBAVCODEC_VERSION_MAJOR > 53
119+
avcodec_free_frame( &frame );
120+
return ret == 0 && gotPacket == 1;
121+
#else
122+
av_free( frame );
123+
#endif
124+
#endif
125+
return ret == 0;
126+
}
127+
128+
bool OutputStreamAudio::encodeFrame( DataStream& codedFrame )
129+
{
130+
AVCodecContext* codecContext = m_audioDesc.getCodecContext();
131+
132+
AVPacket packet;
133+
av_init_packet( &packet );
134+
135+
packet.size = 0;
136+
packet.data = NULL;
137+
packet.stream_index = 0;
138+
139+
#if LIBAVCODEC_VERSION_MAJOR > 53
140+
int gotPacket = 0;
141+
int ret = avcodec_encode_audio2( codecContext, &packet, NULL, &gotPacket );
142+
if( ret == 0 && gotPacket == 1 )
143+
{
144+
codedFrame.getBuffer().resize( packet.size );
145+
memcpy( codedFrame.getPtr(), packet.data, packet.size );
146+
}
147+
av_free_packet( &packet );
148+
return ret == 0 && gotPacket == 1;
149+
150+
#else
151+
int ret = avcodec_encode_audio( codecContext, packet.data, packet.size, NULL );
152+
if( ret > 0 )
153+
{
154+
codedFrame.getBuffer().resize( packet.size );
155+
memcpy( codedFrame.getPtr(), packet.data, packet.size );
156+
}
157+
av_free_packet( &packet );
158+
return ret == 0;
159+
160+
#endif
161+
}
162+
163+
}

src/AvTranscoder/OutputStreamAudio.hpp

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,34 @@
22
#define _AV_TRANSCODER_OUTPUT_STREAM_AUDIO_HPP_
33

44
#include "OutputStream.hpp"
5+
#include "DatasStructures/AudioFrame.hpp"
6+
#include "DatasStructures/AudioDesc.hpp"
7+
#include "DatasStructures/DataStreamDesc.hpp"
58

69
namespace avtranscoder
710
{
811

912
class OutputStreamAudio : public OutputStream
1013
{
1114
public:
12-
OutputStreamAudio(){};
15+
OutputStreamAudio();
16+
17+
bool setup();
1318

14-
private:
19+
/**
20+
* @param[out] codedFrame
21+
*/
22+
bool encodeFrame( const AudioFrame& decodedFrame, DataStream& codedFrame );
23+
24+
/**
25+
* get delayed encoded frames
26+
*/
27+
bool encodeFrame( DataStream& codedFrame );
1528

29+
AudioDesc& getAudioDesc() { return m_audioDesc; }
30+
31+
private:
32+
AudioDesc m_audioDesc;
1633
};
1734

1835
}

0 commit comments

Comments
 (0)