diff --git a/app/audioRewrapper/audioRewrapper.cpp b/app/audioRewrapper/audioRewrapper.cpp index 3348d1f8..2310bdea 100644 --- a/app/audioRewrapper/audioRewrapper.cpp +++ b/app/audioRewrapper/audioRewrapper.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include @@ -54,15 +55,29 @@ 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; @@ -70,8 +85,6 @@ void transcodeAudio( const char* inputfilename, const char* outputFilename ) AudioFrameDesc audioFrameDesc; AudioFrame audioFrame( audioFrameDesc ); - - DataStream codedFrame; while( inputStreamAudio.readNextFrame( audioFrame ) ) { @@ -79,13 +92,17 @@ void transcodeAudio( const char* inputfilename, const char* outputFilename ) // 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 ) diff --git a/src/AvTranscoder/DatasStructures/AudioFrame.hpp b/src/AvTranscoder/DatasStructures/AudioFrame.hpp index 26db2241..4f98f8e2 100644 --- a/src/AvTranscoder/DatasStructures/AudioFrame.hpp +++ b/src/AvTranscoder/DatasStructures/AudioFrame.hpp @@ -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; } @@ -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; }; } diff --git a/src/AvTranscoder/InputStreamAudio.cpp b/src/AvTranscoder/InputStreamAudio.cpp index baf05183..c65b14b5 100644 --- a/src/AvTranscoder/InputStreamAudio.cpp +++ b/src/AvTranscoder/InputStreamAudio.cpp @@ -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: "; @@ -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 ); @@ -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; diff --git a/src/AvTranscoder/InputStreamVideo.cpp b/src/AvTranscoder/InputStreamVideo.cpp index ff3291e4..76f78b3a 100644 --- a/src/AvTranscoder/InputStreamVideo.cpp +++ b/src/AvTranscoder/InputStreamVideo.cpp @@ -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 ); } diff --git a/src/AvTranscoder/OutputStreamAudio.cpp b/src/AvTranscoder/OutputStreamAudio.cpp index f6f13dc0..59dc022c 100644 --- a/src/AvTranscoder/OutputStreamAudio.cpp +++ b/src/AvTranscoder/OutputStreamAudio.cpp @@ -1 +1,163 @@ -#include "OutputStreamAudio.hpp" \ No newline at end of file +#include "OutputStreamAudio.hpp" + +extern "C" { +#ifndef __STDC_CONSTANT_MACROS + #define __STDC_CONSTANT_MACROS +#endif +#include +#include +#include +} + +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 +} + +} \ No newline at end of file diff --git a/src/AvTranscoder/OutputStreamAudio.hpp b/src/AvTranscoder/OutputStreamAudio.hpp index c0bdd0c9..5686c4f2 100644 --- a/src/AvTranscoder/OutputStreamAudio.hpp +++ b/src/AvTranscoder/OutputStreamAudio.hpp @@ -2,6 +2,9 @@ #define _AV_TRANSCODER_OUTPUT_STREAM_AUDIO_HPP_ #include "OutputStream.hpp" +#include "DatasStructures/AudioFrame.hpp" +#include "DatasStructures/AudioDesc.hpp" +#include "DatasStructures/DataStreamDesc.hpp" namespace avtranscoder { @@ -9,10 +12,24 @@ 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 + */ + bool encodeFrame( DataStream& codedFrame ); + AudioDesc& getAudioDesc() { return m_audioDesc; } + +private: + AudioDesc m_audioDesc; }; }