diff --git a/SConstruct b/SConstruct index 5b2fd410..e4d09e01 100644 --- a/SConstruct +++ b/SConstruct @@ -128,6 +128,11 @@ resampleLibraryName = 'avresample' if not conf.CheckLibWithHeader('avutil', 'libavutil/avutil.h', 'c'): sys.exit( 0 ) +if not conf.CheckLibWithHeader('avresample', 'libavresample/avresample.h', 'c'): + if conf.CheckLibWithHeader('swresample', 'libswresample/swresample.h', 'c'): + resampleLibraryFlag = '-DFF_RESAMPLE_LIBRARY' + resampleLibraryName = 'swresample' + if not conf.CheckLibWithHeader('avcodec', 'libavcodec/avcodec.h', 'c'): sys.exit( 0 ) @@ -137,10 +142,6 @@ if not conf.CheckLibWithHeader('avformat', 'libavformat/avformat.h', 'c'): if not conf.CheckLibWithHeader('swscale', 'libswscale/swscale.h', 'c'): sys.exit( 0 ) -if not conf.CheckLibWithHeader('avresample', 'libavresample/avresample.h', 'c'): - if conf.CheckLibWithHeader('swresample', 'libswresample/swresample.h', 'c'): - resampleLibraryFlag = '-DFF_RESAMPLE_LIBRARY' - resampleLibraryName = 'swresample' env.Append( CXXFLAGS = resampleLibraryFlag diff --git a/app/genericProcessor/genericProcessor.cpp b/app/genericProcessor/genericProcessor.cpp index 7a6ab6dd..9083426f 100644 --- a/app/genericProcessor/genericProcessor.cpp +++ b/app/genericProcessor/genericProcessor.cpp @@ -8,7 +8,8 @@ #include #include -bool verbose = false; +// bool verbose = false; +bool verbose = true; void parseConfigFile( const std::string& configFilename, avtranscoder::Transcoder& transcoder, avtranscoder::Profile& profile ) { @@ -26,9 +27,29 @@ void parseConfigFile( const std::string& configFilename, avtranscoder::Transcode { std::string transcodeProfile; std::getline( is_line, transcodeProfile ); + + std::stringstream ss( streamId ); + size_t streamIndex = 0; + char separator; + int subStreamIndex = -1; + ss >> streamIndex; + ss >> separator; + if( separator == '.' ) + ss >> subStreamIndex; + if( verbose ) - std::cout << filename << " ( " << streamId << " ) : " << transcodeProfile << std::endl; - transcoder.add( filename, atoi( streamId.c_str() ), transcodeProfile ); + { + std::cout << ( filename.length() ? filename : "dummy stream" ); + std::cout << " ( " << streamIndex; + if( subStreamIndex > -1 ) + std::cout << " | " << subStreamIndex << " "; + std::cout << " ) : "; + std::cout << ( transcodeProfile.length() ? transcodeProfile : "rewrap" ); + std::cout << std::endl; + } + + transcoder.add( filename, streamIndex, subStreamIndex, transcodeProfile ); + } } } diff --git a/src/AvTranscoder/CodedStream/AvInputStream.cpp b/src/AvTranscoder/CodedStream/AvInputStream.cpp index 7702a490..7cd36151 100644 --- a/src/AvTranscoder/CodedStream/AvInputStream.cpp +++ b/src/AvTranscoder/CodedStream/AvInputStream.cpp @@ -36,8 +36,16 @@ AvInputStream::AvInputStream( InputFile& inputFile, const size_t streamIndex ) , _streamIndex( streamIndex ) , _bufferized( false ) { - if( _inputFile->getFormatContext().streams[_streamIndex]->codec->codec_type == AVMEDIA_TYPE_AUDIO ) - _inputFile->getFormatContext().streams[_streamIndex]->codec->block_align = 5760; + AVCodecContext* context = _inputFile->getFormatContext().streams[_streamIndex]->codec; + if( context->codec_type == AVMEDIA_TYPE_AUDIO ) + { + double outputFps = 25; + size_t bytePerSample = av_get_bytes_per_sample( context->sample_fmt ); + + context->block_align = 1.0 * context->sample_rate * context->channels * bytePerSample / outputFps; + // std::cout << "channels " << context->channel_layout << std::endl; + // std::cout << "audio buffer read size " << context->block_align << std::endl; + } } AvInputStream::~AvInputStream( ) diff --git a/src/AvTranscoder/DatasStructures/AudioDesc.cpp b/src/AvTranscoder/DatasStructures/AudioDesc.cpp index 03869813..02f812ec 100644 --- a/src/AvTranscoder/DatasStructures/AudioDesc.cpp +++ b/src/AvTranscoder/DatasStructures/AudioDesc.cpp @@ -188,7 +188,7 @@ void AudioDesc::set( const std::string& key, const std::string& value ) std::string AudioDesc::getAudioCodec() const { assert( m_codecContext != NULL ); - return m_codecContext->codec_name; + return avcodec_descriptor_get( m_codecContext->codec_id )->name; } AVCodecID AudioDesc::getAudioCodecId() const @@ -197,7 +197,6 @@ AVCodecID AudioDesc::getAudioCodecId() const return m_codecContext->codec_id; } - const size_t AudioDesc::getSampleRate() const { assert( m_codecContext != NULL ); @@ -224,6 +223,7 @@ AudioFrameDesc AudioDesc::getFrameDesc() const audioFrameDesc.setChannels( m_codecContext->channels ); audioFrameDesc.setSampleRate( m_codecContext->sample_rate ); audioFrameDesc.setSampleFormat( m_codecContext->sample_fmt ); + // audioFrameDesc.setFps( 25 ); return audioFrameDesc; } diff --git a/src/AvTranscoder/DatasStructures/Frame.hpp b/src/AvTranscoder/DatasStructures/Frame.hpp index d7a3614e..bf0cdd84 100644 --- a/src/AvTranscoder/DatasStructures/Frame.hpp +++ b/src/AvTranscoder/DatasStructures/Frame.hpp @@ -9,7 +9,7 @@ namespace avtranscoder { -typedef std::vector< unsigned char> DataBuffer; +typedef std::vector< unsigned char > DataBuffer; class AvExport Frame { diff --git a/src/AvTranscoder/DatasStructures/Pixel.cpp b/src/AvTranscoder/DatasStructures/Pixel.cpp index 3fd7878b..5105c9cf 100644 --- a/src/AvTranscoder/DatasStructures/Pixel.cpp +++ b/src/AvTranscoder/DatasStructures/Pixel.cpp @@ -14,7 +14,12 @@ extern "C" { namespace avtranscoder { -Pixel::Pixel( const AVPixelFormat avpixelFormat ) +Pixel::Pixel( const std::string& avPixelFormat ) +{ + init( av_get_pix_fmt( avPixelFormat.c_str() ) ); +} + +Pixel::Pixel( const AVPixelFormat avPixelFormat ) : m_pixelSize ( 24 ) , m_components ( 3 ) , m_componentType ( eComponentYuv ) @@ -23,33 +28,7 @@ Pixel::Pixel( const AVPixelFormat avpixelFormat ) , m_withAlpha ( false ) , m_planar ( true ) { - const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get( avpixelFormat ); - setBitsPerPixel ( av_get_bits_per_pixel( pix_desc ) ); - setBigEndian ( pix_desc->flags & PIX_FMT_BE ); - setComponents ( pix_desc->nb_components ); - setAlpha ( pix_desc->flags & PIX_FMT_ALPHA ); - setPlanar ( ( pix_desc->flags & PIX_FMT_PLANAR ) != 0 ); - - if( pix_desc->nb_components == 1 ) - setColorComponents( eComponentGray ); - - if( pix_desc->flags & PIX_FMT_RGB ) - setColorComponents( eComponentRgb ); - else - setColorComponents( eComponentYuv ); - - setSubsampling( eSubsamplingNone ); - - if( ( pix_desc->log2_chroma_w == true ) && - ( pix_desc->log2_chroma_h == false ) ) - { - setSubsampling( eSubsampling422 ); - } - if( ( pix_desc->log2_chroma_w == true ) && - ( pix_desc->log2_chroma_h == true ) ) - { - setSubsampling( eSubsampling420 ); - } + init( avPixelFormat ); } AVPixelFormat Pixel::findPixel() const @@ -85,6 +64,37 @@ AVPixelFormat Pixel::findPixel() const return AV_PIX_FMT_NONE; } +void Pixel::init( const AVPixelFormat avPixelFormat ) +{ + const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get( avPixelFormat ); + setBitsPerPixel ( av_get_bits_per_pixel( pix_desc ) ); + setBigEndian ( pix_desc->flags & PIX_FMT_BE ); + setComponents ( pix_desc->nb_components ); + setAlpha ( pix_desc->flags & PIX_FMT_ALPHA ); + setPlanar ( ( pix_desc->flags & PIX_FMT_PLANAR ) != 0 ); + + if( pix_desc->nb_components == 1 ) + setColorComponents( eComponentGray ); + + if( pix_desc->flags & PIX_FMT_RGB ) + setColorComponents( eComponentRgb ); + else + setColorComponents( eComponentYuv ); + + setSubsampling( eSubsamplingNone ); + + if( ( pix_desc->log2_chroma_w == true ) && + ( pix_desc->log2_chroma_h == false ) ) + { + setSubsampling( eSubsampling422 ); + } + if( ( pix_desc->log2_chroma_w == true ) && + ( pix_desc->log2_chroma_h == true ) ) + { + setSubsampling( eSubsampling420 ); + } +} + bool Pixel::asCorrectColorComponents( const AVPixFmtDescriptor* pix_desc, const EComponentType componentType ) const { if( componentType == eComponentRgb && pix_desc->flags & PIX_FMT_RGB ) diff --git a/src/AvTranscoder/DatasStructures/Pixel.hpp b/src/AvTranscoder/DatasStructures/Pixel.hpp index cdf8c855..42127459 100644 --- a/src/AvTranscoder/DatasStructures/Pixel.hpp +++ b/src/AvTranscoder/DatasStructures/Pixel.hpp @@ -44,7 +44,9 @@ class Pixel , m_planar ( true ) { } - Pixel( const AVPixelFormat avpixelFormat ); + Pixel( const std::string& avPixelFormat ); + + Pixel( const AVPixelFormat avPixelFormat ); void setBitsPerPixel ( const size_t pixelSize ) { m_pixelSize = pixelSize; } void setBigEndian ( const bool endianess ) { m_endianess = endianess; } @@ -65,6 +67,8 @@ class Pixel AVPixelFormat findPixel() const; private: + void init( const AVPixelFormat avPixelFormat ); + bool asCorrectColorComponents( const AVPixFmtDescriptor* pix_desc, const EComponentType componentType ) const; bool asCorrectSubsampling( const AVPixFmtDescriptor* pix_desc, const ESubsamplingType subsamplingType ) const; diff --git a/src/AvTranscoder/DatasStructures/VideoDesc.cpp b/src/AvTranscoder/DatasStructures/VideoDesc.cpp index d5b78a96..c7dc4814 100644 --- a/src/AvTranscoder/DatasStructures/VideoDesc.cpp +++ b/src/AvTranscoder/DatasStructures/VideoDesc.cpp @@ -78,7 +78,7 @@ void VideoDesc::setTimeBase( const size_t num, const size_t den, const size_t ti std::string VideoDesc::getVideoCodec() const { assert( m_codecContext != NULL ); - return m_codecContext->codec_name; + return avcodec_descriptor_get( m_codecContext->codec_id )->name; } AVCodecID VideoDesc::getVideoCodecId() const diff --git a/src/AvTranscoder/EssenceStream/DummyAudio.cpp b/src/AvTranscoder/EssenceStream/DummyAudio.cpp index e9e67717..8df1edda 100644 --- a/src/AvTranscoder/EssenceStream/DummyAudio.cpp +++ b/src/AvTranscoder/EssenceStream/DummyAudio.cpp @@ -15,9 +15,10 @@ DummyAudio::~DummyAudio( ) { } -void DummyAudio::setAudioDesc( AudioDesc& audioDesc ) +void DummyAudio::setAudioDesc( const AudioDesc& audioDesc ) { _audioDesc = audioDesc; + _frameDesc.setSampleRate ( _audioDesc.getCodecContext()->sample_rate ); _frameDesc.setChannels ( _audioDesc.getCodecContext()->channels ); _frameDesc.setFps ( 25.0 ); @@ -47,28 +48,9 @@ bool DummyAudio::readNextFrame( Frame& frameBuffer ) return true; } -bool DummyAudio::readNextFrame( std::vector& frameBuffer ) +bool DummyAudio::readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ) { - if( frameBuffer.size() != _frameDesc.getChannels() ) - { - frameBuffer.resize( _frameDesc.getChannels() ); - } - - size_t dataSizeOneChannel = _frameDesc.getDataSize() / _frameDesc.getChannels(); - int fill_char = ( - _frameDesc.getSampleFormat() == AV_SAMPLE_FMT_U8 || - _frameDesc.getSampleFormat() == AV_SAMPLE_FMT_U8P - ) ? 0x80 : 0x00; - - for( size_t channel = 0; channel < _frameDesc.getChannels(); ++channel ) - { - AudioFrame& audioFrameBuffer = static_cast( frameBuffer.at( channel ) ); - audioFrameBuffer.setNbSamples( 1.0 * _frameDesc.getSampleRate() / _frameDesc.getFps() ); - frameBuffer.at( channel).getBuffer().resize( dataSizeOneChannel ); - memset( frameBuffer.at( channel).getPtr(), fill_char, frameBuffer.at( channel).getSize() ); - } - - return true; + return false; } } diff --git a/src/AvTranscoder/EssenceStream/DummyAudio.hpp b/src/AvTranscoder/EssenceStream/DummyAudio.hpp index fc443468..9024f1a5 100644 --- a/src/AvTranscoder/EssenceStream/DummyAudio.hpp +++ b/src/AvTranscoder/EssenceStream/DummyAudio.hpp @@ -17,17 +17,17 @@ class AvExport DummyAudio : public InputEssence ~DummyAudio( ); // Stream properties - void setAudioDesc( AudioDesc& audioDesc ); + void setAudioDesc( const AudioDesc& audioDesc ); AudioDesc getAudioDesc() const; void setup() {} bool readNextFrame( Frame& frameBuffer ); - bool readNextFrame( std::vector& frameBuffer ); + bool readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ); private: - AudioDesc _audioDesc; + AudioDesc _audioDesc; AudioFrameDesc _frameDesc; }; diff --git a/src/AvTranscoder/EssenceStream/DummyVideo.cpp b/src/AvTranscoder/EssenceStream/DummyVideo.cpp index 072ff9f4..37e66c6e 100644 --- a/src/AvTranscoder/EssenceStream/DummyVideo.cpp +++ b/src/AvTranscoder/EssenceStream/DummyVideo.cpp @@ -8,7 +8,7 @@ namespace avtranscoder DummyVideo::DummyVideo( ) : InputEssence( ) - , numberOfView( 1 ) + , _numberOfView( 1 ) { } @@ -37,19 +37,9 @@ bool DummyVideo::readNextFrame( Frame& frameBuffer ) return true; } -bool DummyVideo::readNextFrame( std::vector& frameBuffer ) +bool DummyVideo::readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ) { - if( frameBuffer.size() != numberOfView ) - { - frameBuffer.resize( numberOfView ); - } - - for( size_t view = 0; view < numberOfView; ++view ) - { - readNextFrame( frameBuffer.at( view ) ); - } - - return true; + return false; } } diff --git a/src/AvTranscoder/EssenceStream/DummyVideo.hpp b/src/AvTranscoder/EssenceStream/DummyVideo.hpp index 5a994c7f..40897fda 100644 --- a/src/AvTranscoder/EssenceStream/DummyVideo.hpp +++ b/src/AvTranscoder/EssenceStream/DummyVideo.hpp @@ -24,13 +24,13 @@ class AvExport DummyVideo : public InputEssence void setup() {} bool readNextFrame( Frame& frameBuffer ); - bool readNextFrame( std::vector& frameBuffer ); + bool readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ); private: VideoDesc _videoDesc; ImageDesc _imageDesc; - size_t numberOfView; + size_t _numberOfView; }; } diff --git a/src/AvTranscoder/EssenceStream/InputAudio.cpp b/src/AvTranscoder/EssenceStream/InputAudio.cpp index 335808ca..3c0b954d 100644 --- a/src/AvTranscoder/EssenceStream/InputAudio.cpp +++ b/src/AvTranscoder/EssenceStream/InputAudio.cpp @@ -133,26 +133,44 @@ bool InputAudio::readNextFrame( Frame& frameBuffer ) return true; } -bool InputAudio::readNextFrame( std::vector& frameBuffer ) +bool InputAudio::readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ) { if( ! getNextFrame() ) return false; - size_t nbChannels = av_get_channel_layout_nb_channels( _frame->channel_layout ); + size_t decodedSize = av_samples_get_buffer_size(NULL, 1, + _frame->nb_samples, + _codecContext->sample_fmt, 1); + + size_t nbChannels = _codecContext->channels; size_t bytePerSample = av_get_bytes_per_sample( (AVSampleFormat)_frame->format ); - frameBuffer.resize( nbChannels ); + AudioFrame& audioBuffer = static_cast( frameBuffer ); + + // std::cout << "needed size " << audioBuffer.desc().getDataSize() << std::endl; - for( size_t channel = 0; channel < nbChannels; ++ channel ) + // std::cout << _frame->nb_samples * bytePerSample << std::endl; + //audioBuffer.getBuffer().resize( _frame->nb_samples * bytePerSample ); + audioBuffer.setNbSamples( _frame->nb_samples ); + + if( decodedSize ) { - AudioFrame& audioBuffer = static_cast( frameBuffer.at( channel ) ); - audioBuffer.setNbSamples( _frame->nb_samples ); + if( audioBuffer.getSize() != decodedSize ) + audioBuffer.getBuffer().resize( decodedSize, 0 ); unsigned char* src = *_frame->data; unsigned char* dst = audioBuffer.getPtr(); + src += ( nbChannels - 1 ) - ( subStreamIndex * bytePerSample ); + + // std::cout << "frame samples count " << _frame->nb_samples << std::endl; + // std::cout << "frame data size " << audioBuffer.getSize() << std::endl; + for( int sample = 0; sample < _frame->nb_samples; ++sample ) { + // std::cout << "sample " << sample << " ==| "; + // std::cout << "src " << static_cast(src) << " -> "; + // std::cout << "dst " << static_cast(dst) << std::endl; memcpy( dst, src, bytePerSample ); dst += bytePerSample; src += bytePerSample * nbChannels; diff --git a/src/AvTranscoder/EssenceStream/InputAudio.hpp b/src/AvTranscoder/EssenceStream/InputAudio.hpp index a16e86e3..c366a15d 100644 --- a/src/AvTranscoder/EssenceStream/InputAudio.hpp +++ b/src/AvTranscoder/EssenceStream/InputAudio.hpp @@ -23,7 +23,7 @@ class AvExport InputAudio : public InputEssence void setup(); bool readNextFrame( Frame& frameBuffer ); - bool readNextFrame( std::vector& frameBuffer ); + bool readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ); private: bool getNextFrame(); diff --git a/src/AvTranscoder/EssenceStream/InputEssence.hpp b/src/AvTranscoder/EssenceStream/InputEssence.hpp index 80c4b86e..0284f3be 100644 --- a/src/AvTranscoder/EssenceStream/InputEssence.hpp +++ b/src/AvTranscoder/EssenceStream/InputEssence.hpp @@ -19,7 +19,7 @@ class AvExport InputEssence virtual void setup() = 0; virtual bool readNextFrame( Frame& frameBuffer ) = 0; - virtual bool readNextFrame( std::vector& frameBuffer ) = 0; + virtual bool readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ) = 0; }; } diff --git a/src/AvTranscoder/EssenceStream/InputVideo.cpp b/src/AvTranscoder/EssenceStream/InputVideo.cpp index 4e814d82..3dca6e79 100644 --- a/src/AvTranscoder/EssenceStream/InputVideo.cpp +++ b/src/AvTranscoder/EssenceStream/InputVideo.cpp @@ -136,7 +136,7 @@ bool InputVideo::readNextFrame( Frame& frameBuffer ) return true; } -bool InputVideo::readNextFrame( std::vector& frameBuffer ) +bool InputVideo::readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ) { return false; } diff --git a/src/AvTranscoder/EssenceStream/InputVideo.hpp b/src/AvTranscoder/EssenceStream/InputVideo.hpp index bc77fb34..92b5c896 100644 --- a/src/AvTranscoder/EssenceStream/InputVideo.hpp +++ b/src/AvTranscoder/EssenceStream/InputVideo.hpp @@ -25,7 +25,7 @@ class AvExport InputVideo : public InputEssence void setup(); bool readNextFrame( Frame& frameBuffer ); - bool readNextFrame( std::vector& frameBuffer ); + bool readNextFrame( Frame& frameBuffer, const size_t subStreamIndex ); void flushDecoder(); diff --git a/src/AvTranscoder/EssenceStream/OutputAudio.cpp b/src/AvTranscoder/EssenceStream/OutputAudio.cpp index 2d6d83af..b5dceacd 100644 --- a/src/AvTranscoder/EssenceStream/OutputAudio.cpp +++ b/src/AvTranscoder/EssenceStream/OutputAudio.cpp @@ -24,20 +24,27 @@ OutputAudio::OutputAudio() { } -bool OutputAudio::setup() +void OutputAudio::setup() { av_register_all(); // Warning: should be called only once AVCodecContext* codecContext( _audioDesc.getCodecContext() ); if( codecContext == NULL ) - return false; + { + throw std::runtime_error( "could not allocate audio codec context" ); + } // try to open encoder with parameters. - if( avcodec_open2( codecContext, _audioDesc.getCodec(), NULL ) < 0 ) - return false; - - return true; + int ret = avcodec_open2( codecContext, _audioDesc.getCodec(), NULL ); + if( ret < 0 ) + { + char err[250]; + av_strerror( ret, err, 250); + std::string msg = "could not open audio encoder: "; + msg += err; + throw std::runtime_error( msg ); + } } bool OutputAudio::encodeFrame( const Frame& sourceFrame, DataStream& codedFrame ) @@ -174,22 +181,11 @@ void OutputAudio::setProfile( Profile::ProfileDesc& desc, const AudioFrameDesc& if( ! desc.count( Profile::avProfileCodec ) || ! desc.count( Profile::avProfileSampleFormat ) || ! desc.count( Profile::avProfileSampleRate ) || - ! desc.count( Profile::avProfileChannel ) || - ! desc.count( Profile::avProfileChannelLayout ) ) + ! desc.count( Profile::avProfileChannel ) ) { throw std::runtime_error( "The profile " + desc[ Profile::avProfileIdentificatorHuman ] + " is invalid." ); } - // check some values of the profile - if( desc[ Profile::avProfileSampleRate ] == "0" ) - throw std::runtime_error( "Profile " + desc[ Profile::avProfileIdentificatorHuman ] + ": bad sample rate." ); - - if( desc[ Profile::avProfileChannel ] == "0" ) - throw std::runtime_error( "Profile " + desc[ Profile::avProfileIdentificatorHuman ] + ": bad audio channel." ); - - if( desc[ Profile::avProfileChannelLayout ] == "0" ) - throw std::runtime_error( "Profile " + desc[ Profile::avProfileIdentificatorHuman ] + ": bad audio channel layout." ); - _audioDesc.setAudioCodec( desc[ Profile::avProfileCodec ] ); size_t sample_rate = std::strtoul( desc[ Profile::avProfileSampleRate ].c_str(), NULL, 0 ); diff --git a/src/AvTranscoder/EssenceStream/OutputAudio.hpp b/src/AvTranscoder/EssenceStream/OutputAudio.hpp index 3632ecd8..aace4a58 100644 --- a/src/AvTranscoder/EssenceStream/OutputAudio.hpp +++ b/src/AvTranscoder/EssenceStream/OutputAudio.hpp @@ -17,7 +17,7 @@ class OutputAudio : public OutputEssence public: OutputAudio(); - bool setup(); + void setup(); /** * @param[out] codedFrame diff --git a/src/AvTranscoder/EssenceStream/OutputEssence.hpp b/src/AvTranscoder/EssenceStream/OutputEssence.hpp index f7942dc5..b4931878 100644 --- a/src/AvTranscoder/EssenceStream/OutputEssence.hpp +++ b/src/AvTranscoder/EssenceStream/OutputEssence.hpp @@ -30,9 +30,8 @@ class AvExport OutputEssence /** * @brief Setup the encoder - * @return status of setup */ - virtual bool setup() = 0; + virtual void setup() = 0; /** * @brief Encode a new frame, and get coded frame diff --git a/src/AvTranscoder/EssenceStream/OutputVideo.cpp b/src/AvTranscoder/EssenceStream/OutputVideo.cpp index a340c23b..cdff0a06 100644 --- a/src/AvTranscoder/EssenceStream/OutputVideo.cpp +++ b/src/AvTranscoder/EssenceStream/OutputVideo.cpp @@ -27,20 +27,27 @@ OutputVideo::OutputVideo( ) { } -bool OutputVideo::setup( ) +void OutputVideo::setup( ) { av_register_all(); // Warning: should be called only once AVCodecContext* codecContext( _videoDesc.getCodecContext() ); if( codecContext == NULL ) - return false; + { + throw std::runtime_error( "could not allocate video codec context" ); + } // try to open encoder with parameters - if( avcodec_open2( codecContext, _videoDesc.getCodec(), NULL ) < 0 ) - return false; - - return true; + int ret = avcodec_open2( codecContext, _videoDesc.getCodec(), NULL ); + if( ret < 0 ) + { + char err[250]; + av_strerror( ret, err, 250); + std::string msg = "could not open video encoder: "; + msg += err; + throw std::runtime_error( msg ); + } } @@ -195,8 +202,10 @@ void OutputVideo::setProfile( Profile::ProfileDesc& desc, const avtranscoder::Im } _videoDesc.setVideoCodec( desc[ Profile::avProfileCodec ] ); + const size_t frameRate = std::strtoul( desc[ Profile::avProfileFrameRate ].c_str(), NULL, 0 ); _videoDesc.setTimeBase( 1, frameRate ); + _videoDesc.setImageParameters( imageDesc ); for( Profile::ProfileDesc::iterator it = desc.begin(); it != desc.end(); ++it ) @@ -207,8 +216,8 @@ void OutputVideo::setProfile( Profile::ProfileDesc& desc, const avtranscoder::Im (*it).first == Profile::avProfileCodec || (*it).first == Profile::avProfilePixelFormat || (*it).first == Profile::avProfileWidth || - (*it).first == Profile::avProfileHeight|| - (*it).first == Profile::avProfileFrameRate) + (*it).first == Profile::avProfileHeight || + (*it).first == Profile::avProfileFrameRate ) continue; try @@ -231,8 +240,8 @@ void OutputVideo::setProfile( Profile::ProfileDesc& desc, const avtranscoder::Im (*it).first == Profile::avProfileCodec || (*it).first == Profile::avProfilePixelFormat || (*it).first == Profile::avProfileWidth || - (*it).first == Profile::avProfileHeight|| - (*it).first == Profile::avProfileFrameRate) + (*it).first == Profile::avProfileHeight || + (*it).first == Profile::avProfileFrameRate ) continue; try diff --git a/src/AvTranscoder/EssenceStream/OutputVideo.hpp b/src/AvTranscoder/EssenceStream/OutputVideo.hpp index c9e60ff7..b7509088 100644 --- a/src/AvTranscoder/EssenceStream/OutputVideo.hpp +++ b/src/AvTranscoder/EssenceStream/OutputVideo.hpp @@ -30,7 +30,7 @@ class AvExport OutputVideo : public OutputEssence public: OutputVideo(); - bool setup(); + void setup(); //void setVideoDesc( const VideoDesc& videoDesc ); diff --git a/src/AvTranscoder/File/OutputFile.cpp b/src/AvTranscoder/File/OutputFile.cpp index b18de13b..cfa4a317 100644 --- a/src/AvTranscoder/File/OutputFile.cpp +++ b/src/AvTranscoder/File/OutputFile.cpp @@ -135,6 +135,7 @@ bool OutputFile::beginWrap( ) bool OutputFile::wrap( const DataStream& data, const size_t streamId ) { + // std::cout << "wrap on stream " << streamId << " (" << data.getSize() << ")" << std::endl; AVPacket packet; av_init_packet( &packet ); @@ -147,9 +148,16 @@ bool OutputFile::wrap( const DataStream& data, const size_t streamId ) packet.dts = 0; packet.pts = _packetCount; - if( av_interleaved_write_frame( _formatContext, &packet ) != 0 ) + int ret = av_interleaved_write_frame( _formatContext, &packet ); + + if( ret != 0 ) { - std::cout << "error when writting packet in stream" << std::endl; + char err[250]; + av_strerror( ret, err, 250); + std::string msg = "error when writting packet in stream: "; + msg += err; + // throw std::runtime_error( msg ); + std::cout << msg << std::endl; return false; } diff --git a/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp b/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp index cf3d7f9c..dd332bc5 100644 --- a/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp +++ b/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp @@ -9,6 +9,7 @@ extern "C" { #include #include #include +#include } namespace avtranscoder @@ -31,6 +32,20 @@ AudioProperties audioStreamInfo( const AVFormatContext* formatContext, const siz ap.codecName = codec->name; ap.codecLongName = codec->long_name; } + + char buf1[1024]; + av_get_channel_layout_string( buf1, sizeof( buf1 ), -1, codec_context->channel_layout ); + + ap.channelLayout = std::string( buf1 ); + + const char* channelName = av_get_channel_name( codec_context->channel_layout ); + if( channelName ) + ap.channelName = std::string( channelName ); +#ifdef FF_RESAMPLE_LIBRARY + const char* channelDescription = av_get_channel_description( codec_context->channel_layout ); + if( channelDescription ) + ap.channelDescription = std::string( channelDescription ); +#endif std::string sampleFormat = ""; switch( codec_context->sample_fmt ) diff --git a/src/AvTranscoder/Metadatas/MediaMetadatasStructures.hpp b/src/AvTranscoder/Metadatas/MediaMetadatasStructures.hpp index a95afcc4..80f2ae40 100644 --- a/src/AvTranscoder/Metadatas/MediaMetadatasStructures.hpp +++ b/src/AvTranscoder/Metadatas/MediaMetadatasStructures.hpp @@ -76,6 +76,9 @@ struct AudioProperties { std::string codecName; std::string codecLongName; std::string sampleFormat; + std::string channelLayout; + std::string channelName; + std::string channelDescription; size_t streamId; size_t codecId; size_t sampleRate; diff --git a/src/AvTranscoder/Metadatas/Print.hpp b/src/AvTranscoder/Metadatas/Print.hpp index 5065af9a..7efa251f 100644 --- a/src/AvTranscoder/Metadatas/Print.hpp +++ b/src/AvTranscoder/Metadatas/Print.hpp @@ -110,6 +110,9 @@ void displayMetadatas( InputFile& input ) std::cout << std::setw( keyWidth ) << "stream id" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).streamId << std::endl; std::cout << std::setw( keyWidth ) << "sample rate" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).sampleRate << std::endl; std::cout << std::setw( keyWidth ) << "channels" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).channels << std::endl; + std::cout << std::setw( keyWidth ) << "channel layout" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).channelLayout << std::endl; + std::cout << std::setw( keyWidth ) << "channel name" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).channelName << std::endl; + std::cout << std::setw( keyWidth ) << "channel description" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).channelDescription << std::endl; std::cout << std::setw( keyWidth ) << "bit rate" << ": " << input.getProperties().audioStreams.at(audioStreamIndex).bit_rate << std::endl; } for( size_t dataStreamIndex = 0; dataStreamIndex < input.getProperties().dataStreams.size(); ++dataStreamIndex ) diff --git a/src/AvTranscoder/OptionLoader.cpp b/src/AvTranscoder/OptionLoader.cpp index 802c5812..2f6389a3 100644 --- a/src/AvTranscoder/OptionLoader.cpp +++ b/src/AvTranscoder/OptionLoader.cpp @@ -277,7 +277,7 @@ OptionLoader::OptionArray OptionLoader::loadOptions( void* av_class, int req_fla return options; } -std::vector OptionLoader::getPixelFormats( const std::string& videoCodecName ) const +std::vector OptionLoader::getPixelFormats( const std::string& videoCodecName ) { std::vector pixelFormats; @@ -323,7 +323,7 @@ std::vector OptionLoader::getPixelFormats( const std::string& video return pixelFormats; } -std::vector OptionLoader::getSampleFormats( const std::string& audioCodecName ) const +std::vector OptionLoader::getSampleFormats( const std::string& audioCodecName ) { std::vector sampleFormats; diff --git a/src/AvTranscoder/OptionLoader.hpp b/src/AvTranscoder/OptionLoader.hpp index d0296071..1f77b30d 100644 --- a/src/AvTranscoder/OptionLoader.hpp +++ b/src/AvTranscoder/OptionLoader.hpp @@ -60,18 +60,19 @@ class OptionLoader std::vector& getAudioCodecsLongNames() { return _audioCodecsLongNames; } std::vector& getAudioCodecsShortNames() { return _audioCodecsShortNames; } - + +public: /** * Get array of pixel format supported by a video codec. * @param videoCodecName: the video codec name (empty if not indicated, and so get all pixel formats supported by all video codecs). */ - std::vector getPixelFormats( const std::string& videoCodecName = "" ) const; + static std::vector getPixelFormats( const std::string& videoCodecName = "" ); /** * Get array of sample format supported by an audio codec. * @param audioCodecName: the audio codec name (empty if not indicated, and so get all sample formats supported by all audio codecs). */ - std::vector getSampleFormats( const std::string& audioCodecName = "" ) const; + static std::vector getSampleFormats( const std::string& audioCodecName = "" ); private: /** diff --git a/src/AvTranscoder/Profile.cpp b/src/AvTranscoder/Profile.cpp index fbfff4c1..c9097948 100644 --- a/src/AvTranscoder/Profile.cpp +++ b/src/AvTranscoder/Profile.cpp @@ -25,7 +25,6 @@ const std::string Profile::avProfileSampleFormat( "sample_fmt" ); const std::string Profile::avProfileFrameRate( "r" ); const std::string Profile::avProfileSampleRate( "ar" ); const std::string Profile::avProfileChannel( "ac" ); -const std::string Profile::avProfileChannelLayout( "channel_layout" ); const std::string Profile::avProfileWidth( "width" ); const std::string Profile::avProfileHeight( "height" ); diff --git a/src/AvTranscoder/Profile.hpp b/src/AvTranscoder/Profile.hpp index bb4cb5c6..eca96a4f 100644 --- a/src/AvTranscoder/Profile.hpp +++ b/src/AvTranscoder/Profile.hpp @@ -25,7 +25,6 @@ class Profile static const std::string avProfileFrameRate; static const std::string avProfileSampleRate; static const std::string avProfileChannel; - static const std::string avProfileChannelLayout; static const std::string avProfileWidth; static const std::string avProfileHeight; diff --git a/src/AvTranscoder/Profiles/DNxHD.hpp b/src/AvTranscoder/Profiles/DNxHD.hpp index 482f795e..1a998a54 100644 --- a/src/AvTranscoder/Profiles/DNxHD.hpp +++ b/src/AvTranscoder/Profiles/DNxHD.hpp @@ -44,4 +44,4 @@ void loadDNxHD( Profile::ProfilesDesc& profiles ) } -#endif \ No newline at end of file +#endif diff --git a/src/AvTranscoder/Profiles/Wave.hpp b/src/AvTranscoder/Profiles/Wave.hpp index 170bc6a4..0f5b0f57 100644 --- a/src/AvTranscoder/Profiles/Wave.hpp +++ b/src/AvTranscoder/Profiles/Wave.hpp @@ -8,7 +8,7 @@ void loadWave( Profile::ProfilesDesc& profiles ) { Profile::ProfileDesc wave24b48kMono; - wave24b48kMono[ Profile::avProfileIdentificator ] = "wave24b48kMono"; + wave24b48kMono[ Profile::avProfileIdentificator ] = "wave24b48kmono"; wave24b48kMono[ Profile::avProfileIdentificatorHuman ] = "Wave 24bits 48kHz mono"; wave24b48kMono[ Profile::avProfileType ] = Profile::avProfileTypeAudio; @@ -16,11 +16,10 @@ void loadWave( Profile::ProfilesDesc& profiles ) wave24b48kMono[ Profile::avProfileSampleFormat ] = "s32"; wave24b48kMono[ Profile::avProfileSampleRate ] = "48000"; wave24b48kMono[ Profile::avProfileChannel ] = "1"; - wave24b48kMono[ Profile::avProfileChannelLayout ] = "1"; Profile::ProfileDesc wave16b48kMono; - wave16b48kMono[ Profile::avProfileIdentificator ] = "wave16b48kMono"; + wave16b48kMono[ Profile::avProfileIdentificator ] = "wave16b48kmono"; wave16b48kMono[ Profile::avProfileIdentificatorHuman ] = "Wave 16bits 48kHz mono"; wave16b48kMono[ Profile::avProfileType ] = Profile::avProfileTypeAudio; @@ -28,7 +27,6 @@ void loadWave( Profile::ProfilesDesc& profiles ) wave16b48kMono[ Profile::avProfileSampleFormat ] = "s16"; wave16b48kMono[ Profile::avProfileSampleRate ] = "48000"; wave16b48kMono[ Profile::avProfileChannel ] = "1"; - wave16b48kMono[ Profile::avProfileChannelLayout ] = "1"; profiles.push_back( wave24b48kMono ); profiles.push_back( wave16b48kMono ); diff --git a/src/AvTranscoder/Transcoder/StreamTranscoder.cpp b/src/AvTranscoder/Transcoder/StreamTranscoder.cpp index e9aba161..4e73deac 100644 --- a/src/AvTranscoder/Transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/Transcoder/StreamTranscoder.cpp @@ -25,8 +25,9 @@ StreamTranscoder::StreamTranscoder( , _inputEssence( NULL ) , _outputEssence( NULL ) , _transform( NULL ) + , _subStreamIndex( -1 ) , _transcodeStream( false ) - , _dummyStream( false ) + , _verbose( false ) { // create a re-wrapping case switch( _inputStream->getStreamType() ) @@ -49,7 +50,8 @@ StreamTranscoder::StreamTranscoder( StreamTranscoder::StreamTranscoder( InputStream& inputStream, OutputFile& outputFile, - Profile::ProfileDesc& profile + Profile::ProfileDesc& profile, + const int subStreamIndex ) : _inputStream( &inputStream ) , _outputStream( NULL ) @@ -58,8 +60,9 @@ StreamTranscoder::StreamTranscoder( , _inputEssence( NULL ) , _outputEssence( NULL ) , _transform( NULL ) + , _subStreamIndex( subStreamIndex ) , _transcodeStream( true ) - , _dummyStream( false ) + , _verbose( false ) { // create a transcode case switch( _inputStream->getStreamType() ) @@ -72,11 +75,19 @@ StreamTranscoder::StreamTranscoder( OutputVideo* outputVideo = new OutputVideo(); _outputEssence = outputVideo; - outputVideo->setProfile( profile, _inputStream->getVideoDesc().getImageDesc() ); + + ImageDesc outputImageDesc = _inputStream->getVideoDesc().getImageDesc(); + + outputImageDesc.setPixel( Pixel( profile[ Profile::avProfilePixelFormat ].c_str() ) ); + + outputVideo->setProfile( profile, outputImageDesc ); _outputStream = &outputFile.addVideoStream( outputVideo->getVideoDesc() ); _sourceBuffer = new Image( _inputStream->getVideoDesc().getImageDesc() ); + + // outputVideo->getVideoDesc().setImageParameters( _inputStream->getVideoDesc().getImageDesc().getWidth(), _inputStream->getVideoDesc().getImageDesc().getHeight(), av_get_pix_fmt( desc[ Profile::avProfilePixelFormat ].c_str() ) ); + _frameBuffer = new Image( outputVideo->getVideoDesc().getImageDesc() ); _transform = new VideoEssenceTransform(); @@ -91,11 +102,16 @@ StreamTranscoder::StreamTranscoder( OutputAudio* outputAudio = new OutputAudio(); _outputEssence = outputAudio; - outputAudio->setProfile( profile, _inputStream->getAudioDesc().getFrameDesc() ); + AudioFrameDesc audioFrameDesc( _inputStream->getAudioDesc().getFrameDesc() ); + + if( subStreamIndex > -1 ) + audioFrameDesc.setChannels( 1 ); + + outputAudio->setProfile( profile, audioFrameDesc ); _outputStream = &outputFile.addAudioStream( outputAudio->getAudioDesc() ); - _sourceBuffer = new AudioFrame( _inputStream->getAudioDesc().getFrameDesc() ); + _sourceBuffer = new AudioFrame( audioFrameDesc ); _frameBuffer = new AudioFrame( outputAudio->getAudioDesc().getFrameDesc() ); _transform = new AudioEssenceTransform(); @@ -122,10 +138,11 @@ StreamTranscoder::StreamTranscoder( , _inputEssence( &inputEssence ) , _outputEssence( NULL ) , _transform( NULL ) + , _subStreamIndex( -1 ) , _transcodeStream( true ) - , _dummyStream( true ) + , _verbose( false ) { - // create a dummy case + // create a coding case based on a InputEssence (aka dummy reader) if( ! profile.count( Profile::avProfileType ) ) throw std::runtime_error( "unable to found stream type (audio, video, etc.)" ); @@ -158,7 +175,7 @@ StreamTranscoder::StreamTranscoder( _outputStream = &outputFile.addVideoStream( outputVideo->getVideoDesc() ); _sourceBuffer = new Image( outputVideo->getVideoDesc().getImageDesc() ); - _frameBuffer = new Image( outputVideo->getVideoDesc().getImageDesc() ); + _frameBuffer = new Image( outputVideo->getVideoDesc().getImageDesc() ); _transform = new VideoEssenceTransform(); @@ -174,7 +191,7 @@ StreamTranscoder::~StreamTranscoder() delete _frameBuffer; if( _sourceBuffer ) delete _sourceBuffer; - if( _inputEssence && ! _dummyStream ) + if( _inputEssence && _inputStream ) delete _inputEssence; if( _outputEssence ) delete _outputEssence; @@ -182,24 +199,53 @@ StreamTranscoder::~StreamTranscoder() delete _transform; } - bool StreamTranscoder::processFrame() { if( _transcodeStream ) { - return processTranscode(); + if( _subStreamIndex < 0 ) + { + return processTranscode(); + } + + return processTranscode( _subStreamIndex ); + } + + if( _subStreamIndex < 0 ) + { + return processRewrap(); } - return processRewrap(); + + return processRewrap( _subStreamIndex ); } bool StreamTranscoder::processRewrap() { assert( _inputStream != NULL ); + assert( _outputStream != NULL ); + + DataStream dataStream; + + if( ! _inputStream->readNextPacket( dataStream ) ) + return false; + + _outputStream->wrap( dataStream ); + return true; +} + +bool StreamTranscoder::processRewrap( const int subStreamIndex ) +{ + assert( _inputStream != NULL ); + assert( _outputStream != NULL ); DataStream dataStream; + // std::vector dataStream; + if( ! _inputStream->readNextPacket( dataStream ) ) return false; _outputStream->wrap( dataStream ); + // outputStream.wrap( dataStream.at( subStreamIndex ) ); + return true; } @@ -209,21 +255,65 @@ bool StreamTranscoder::processTranscode() assert( _outputEssence != NULL ); assert( _sourceBuffer != NULL ); assert( _frameBuffer != NULL ); + assert( _transform != NULL ); DataStream dataStream; + if( _verbose ) + std::cout << "transcode a frame " << std::endl; if( _inputEssence->readNextFrame( *_sourceBuffer ) ) { + if( _verbose ) + std::cout << "convert " << _sourceBuffer->getSize() << std::endl; _transform->convert( *_sourceBuffer, *_frameBuffer ); + if( _verbose ) + std::cout << "encode " << _frameBuffer->getSize() << std::endl; _outputEssence->encodeFrame( *_frameBuffer, dataStream ); } else { + if( _verbose ) + std::cout << "encode last frame(s)" << std::endl; if( ! _outputEssence->encodeFrame( dataStream ) ) { return false; } } + if( _verbose ) + std::cout << "wrap (" << dataStream.getSize() << ")" << std::endl; + _outputStream->wrap( dataStream ); + return true; +} + +bool StreamTranscoder::processTranscode( const int subStreamIndex ) +{ + assert( _inputEssence != NULL ); + assert( _outputEssence != NULL ); + assert( _sourceBuffer != NULL ); + assert( _frameBuffer != NULL ); + assert( _transform != NULL ); + + DataStream dataStream; + if( _verbose ) + std::cout << "transcode a frame " << std::endl; + if( _inputEssence->readNextFrame( *_sourceBuffer, subStreamIndex ) ) + { + if( _verbose ) + std::cout << "convert " << std::endl; + _transform->convert( *_sourceBuffer, *_frameBuffer ); + if( _verbose ) + std::cout << "encode" << std::endl; + _outputEssence->encodeFrame( *_frameBuffer, dataStream ); + } + else + { + if( ! _outputEssence->encodeFrame( dataStream ) ) + { + return false; + } + } + if( _verbose ) + std::cout << "wrap (" << dataStream.getSize() << ")" << std::endl; _outputStream->wrap( dataStream ); return true; } diff --git a/src/AvTranscoder/Transcoder/StreamTranscoder.hpp b/src/AvTranscoder/Transcoder/StreamTranscoder.hpp index b1b46b49..74246c15 100644 --- a/src/AvTranscoder/Transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/Transcoder/StreamTranscoder.hpp @@ -29,7 +29,7 @@ class StreamTranscoder /** * @brief transcode stream **/ - StreamTranscoder( InputStream& inputStream, OutputFile& outputFile, Profile::ProfileDesc& profile ); + StreamTranscoder( InputStream& inputStream, OutputFile& outputFile, Profile::ProfileDesc& profile, const int subStreamIndex = -1 ); /** * @brief encode from dummy stream @@ -46,9 +46,13 @@ class StreamTranscoder bool isTranscodeStream() const { return _transcodeStream; } + void setVerbose( bool verbose = true ){ _verbose = verbose; } + private: bool processRewrap(); + bool processRewrap( const int subStreamIndex ); bool processTranscode(); + bool processTranscode( const int subStreamIndex ); private: InputStream* _inputStream; @@ -62,8 +66,9 @@ class StreamTranscoder EssenceTransform* _transform; + int _subStreamIndex; bool _transcodeStream; - bool _dummyStream; + bool _verbose; }; } diff --git a/src/AvTranscoder/Transcoder/Transcoder.cpp b/src/AvTranscoder/Transcoder/Transcoder.cpp index f72bb5b0..e97304fe 100644 --- a/src/AvTranscoder/Transcoder/Transcoder.cpp +++ b/src/AvTranscoder/Transcoder/Transcoder.cpp @@ -24,6 +24,14 @@ Transcoder::~Transcoder() { delete (*it); } + // for( std::vector< DummyAudio* >::iterator it = _dummyAudio.begin(); it != _dummyAudio.end(); ++it ) + // { + // delete (*it); + // } + // for( std::vector< DummyVideo* >::iterator it = _dummyVideo.begin(); it != _dummyVideo.end(); ++it ) + // { + // delete (*it); + // } } void Transcoder::add( const std::string& filename, const size_t streamIndex, const std::string& profileName ) @@ -56,22 +64,68 @@ void Transcoder::add( const std::string& filename, const size_t streamIndex, Pro addTranscodeStream( filename, streamIndex, profileDesc ); } +void Transcoder::add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, const std::string& profileName ) +{ + if( subStreamIndex < 0 ) + { + add( filename, streamIndex, profileName ); + return; + } + + if( profileName.length() == 0 ) // no profile, only re-wrap stream + { + if( _verbose ) + std::cout << "add re-wrap stream for substream " << subStreamIndex << std::endl; + + addRewrapStream( filename, streamIndex ); + return; + } + + Profile::ProfileDesc& transcodeProfile = _profile.getProfile( profileName ); + add( filename, streamIndex, subStreamIndex, transcodeProfile ); +} + +void Transcoder::add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, Profile::ProfileDesc& profileDesc ) +{ + if( subStreamIndex < 0 ) + { + add( filename, streamIndex, profileDesc ); + return; + } + + _profile.update( profileDesc ); + if( ! filename.length() ) + { + if( _verbose ) + std::cout << "add encoding stream for dummy input" << std::endl; + addDummyStream( profileDesc ); + return; + } + + if( _verbose ) + std::cout << "add transcoding stream for substream " << subStreamIndex << std::endl; + addTranscodeStream( filename, streamIndex, subStreamIndex, profileDesc ); +} + bool Transcoder::processFrame() { + if( _streamTranscoders.size() == 0 ) + { + return false; + } + if( _verbose ) std::cout << "process frame" << std::endl; for( size_t streamIndex = 0; streamIndex < _streamTranscoders.size(); ++streamIndex ) { + if( _verbose ) + std::cout << "process stream " << streamIndex << "/" << _streamTranscoders.size() - 1 << std::endl; + if( ! _streamTranscoders.at( streamIndex )->processFrame() ) { _streamTranscoders.clear(); } } - - if( _streamTranscoders.size() == 0 ) - { - return false; - } return true; } @@ -121,6 +175,15 @@ void Transcoder::process( ProgressListener& progress ) _outputFile.endWrap(); } +void Transcoder::setVerbose( bool verbose ) +{ + _verbose = verbose; + for( std::vector< StreamTranscoder* >::iterator it = _streamTranscoders.begin(); it != _streamTranscoders.end(); ++it ) + { + (*it)->setVerbose( _verbose ); + } +} + void Transcoder::addRewrapStream( const std::string& filename, const size_t streamIndex ) { InputFile* referenceFile = addInputFile( filename, streamIndex ); @@ -157,6 +220,34 @@ void Transcoder::addTranscodeStream( const std::string& filename, const size_t s } } +void Transcoder::addTranscodeStream( const std::string& filename, const size_t streamIndex, const size_t subStreamIndex, Profile::ProfileDesc& profile ) +{ + InputFile* referenceFile = addInputFile( filename, streamIndex ); + + switch( referenceFile->getStreamType( streamIndex ) ) + { + case AVMEDIA_TYPE_VIDEO: + { + _streamTranscoders.push_back( new StreamTranscoder( referenceFile->getStream( streamIndex ), _outputFile, profile, subStreamIndex ) ); + _inputStreams.push_back( &referenceFile->getStream( streamIndex ) ); + break; + } + case AVMEDIA_TYPE_AUDIO: + { + _streamTranscoders.push_back( new StreamTranscoder( referenceFile->getStream( streamIndex ), _outputFile, profile, subStreamIndex ) ); + _inputStreams.push_back( &referenceFile->getStream( streamIndex ) ); + break; + } + case AVMEDIA_TYPE_DATA: + case AVMEDIA_TYPE_SUBTITLE: + case AVMEDIA_TYPE_ATTACHMENT: + default: + { + throw std::runtime_error( "unsupported media type in transcode setup" ); + } + } +} + void Transcoder::addDummyStream( Profile::ProfileDesc& profile ) { if( ! profile.count( Profile::avProfileType ) ) @@ -164,14 +255,14 @@ void Transcoder::addDummyStream( Profile::ProfileDesc& profile ) if( profile.find( Profile::avProfileType )->second == Profile::avProfileTypeAudio ) { - _dummyAudio.push_back( DummyAudio() ); - _streamTranscoders.push_back( new StreamTranscoder( _dummyAudio.back(), _outputFile, profile ) ); + _dummyAudio.push_back( new DummyAudio() ); + _streamTranscoders.push_back( new StreamTranscoder( *_dummyAudio.back(), _outputFile, profile ) ); } if( profile.find( Profile::avProfileType )->second == Profile::avProfileTypeVideo ) { - _dummyVideo.push_back( DummyVideo() ); - _streamTranscoders.push_back( new StreamTranscoder( _dummyVideo.back(), _outputFile, profile ) ); + _dummyVideo.push_back( new DummyVideo() ); + _streamTranscoders.push_back( new StreamTranscoder( *_dummyVideo.back(), _outputFile, profile ) ); } } @@ -181,7 +272,8 @@ InputFile* Transcoder::addInputFile( const std::string& filename, const size_t s for( std::vector< InputFile* >::iterator it = _inputFiles.begin(); it != _inputFiles.end(); ++it ) { - if( (*it)->getFilename() == filename ) + if( ( (*it)->getFilename() == filename ) && + ( ! (*it)->getReadStream( streamIndex ) ) ) { referenceFile = (*it); break; diff --git a/src/AvTranscoder/Transcoder/Transcoder.hpp b/src/AvTranscoder/Transcoder/Transcoder.hpp index c68a32ca..ee4d350b 100644 --- a/src/AvTranscoder/Transcoder/Transcoder.hpp +++ b/src/AvTranscoder/Transcoder/Transcoder.hpp @@ -37,11 +37,25 @@ class Transcoder */ void add( const std::string& filename, const size_t streamIndex, Profile::ProfileDesc& profileDesc ); + /** + * @brief Add a stream and set a profile + * @note If profile is empty, add a dummy stream. + * @note If subStreamIndex is negative, no substream a selected it's the stream. + */ + void add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, const std::string& profileName = "" ); + + /** + * @brief Add a stream and set a custom profile + * @note Profile will be updated, be sure to pass unique profile name. + * @note If subStreamIndex is negative, no substream a selected it's the stream. + */ + void add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, Profile::ProfileDesc& profileDesc ); + bool processFrame(); void process( ProgressListener& progress ); - void setVerbose( bool verbose = true ){ _verbose = verbose; } + void setVerbose( bool verbose = true ); private: @@ -49,6 +63,8 @@ class Transcoder void addTranscodeStream( const std::string& filename, const size_t streamIndex, Profile::ProfileDesc& profile ); + void addTranscodeStream( const std::string& filename, const size_t streamIndex, const size_t subStreamIndex, Profile::ProfileDesc& profile ); + void addDummyStream( Profile::ProfileDesc& profile ); InputFile* addInputFile( const std::string& filename, const size_t streamIndex ); @@ -60,12 +76,12 @@ class Transcoder std::vector< InputStream* > _inputStreams; std::vector< StreamTranscoder* > _streamTranscoders; - std::vector< DummyAudio > _dummyAudio; - std::vector< DummyVideo > _dummyVideo; + std::vector< DummyAudio* > _dummyAudio; + std::vector< DummyVideo* > _dummyVideo; Profile _profile; - bool _verbose; + bool _verbose; }; } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy