diff --git a/src/AvTranscoder/ProfileLoader.cpp b/src/AvTranscoder/ProfileLoader.cpp index d3565bff..dcc4ecca 100644 --- a/src/AvTranscoder/ProfileLoader.cpp +++ b/src/AvTranscoder/ProfileLoader.cpp @@ -85,15 +85,17 @@ void ProfileLoader::loadProfiles( const std::string& avProfilesPath ) void ProfileLoader::update( const Profile& profile ) { - std::string profileId( profile.find( constants::avProfileIdentificator )->second ); + Profile::const_iterator profileIt = profile.find( constants::avProfileIdentificator ); + if( profileIt == profile.end() ) + throw std::runtime_error( "Invalid profile: can't get identificator" ); + + std::string profileId( profileIt->second ); size_t profileIndex = 0; for( Profiles::iterator it = _profiles.begin(); it != _profiles.end(); ++it ) { + // profile already exists if( (*it).find( constants::avProfileIdentificator )->second == profileId ) - { - _profiles.at( profileIndex ) = profile; return; - } ++profileIndex; } // profile not found: add the new profile diff --git a/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp b/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp index 35c06c02..7b651cfa 100644 --- a/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp +++ b/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp @@ -43,22 +43,25 @@ avtranscoder::AudioProperties audioStreamInfo( const AVFormatContext* formatCont if( channelDescription ) ap.channelDescription = std::string( channelDescription ); #endif - + const char* fmtName = av_get_sample_fmt_name( codec_context->sample_fmt ); + if( fmtName ) + ap.sampleFormatName = std::string( fmtName ); + std::string sampleFormat = ""; switch( codec_context->sample_fmt ) { - case AV_SAMPLE_FMT_NONE : ap.sampleFormat = "none"; break; - case AV_SAMPLE_FMT_U8 : ap.sampleFormat = "unsigned 8 bits"; break; - case AV_SAMPLE_FMT_S16 : ap.sampleFormat = "signed 16 bits"; break; - case AV_SAMPLE_FMT_S32 : ap.sampleFormat = "signed 32 bits"; break; - case AV_SAMPLE_FMT_FLT : ap.sampleFormat = "float"; break; - case AV_SAMPLE_FMT_DBL : ap.sampleFormat = "double"; break; - case AV_SAMPLE_FMT_U8P : ap.sampleFormat = "unsigned 8 bits, planar"; break; - case AV_SAMPLE_FMT_S16P : ap.sampleFormat = "signed 16 bits, planar"; break; - case AV_SAMPLE_FMT_S32P : ap.sampleFormat = "signed 32 bits, planar"; break; - case AV_SAMPLE_FMT_FLTP : ap.sampleFormat = "float, planar"; break; - case AV_SAMPLE_FMT_DBLP : ap.sampleFormat = "double, planar"; break; - case AV_SAMPLE_FMT_NB : ap.sampleFormat = "Number of sample formats."; break; + case AV_SAMPLE_FMT_NONE : ap.sampleFormatLongName = "none"; break; + case AV_SAMPLE_FMT_U8 : ap.sampleFormatLongName = "unsigned 8 bits"; break; + case AV_SAMPLE_FMT_S16 : ap.sampleFormatLongName = "signed 16 bits"; break; + case AV_SAMPLE_FMT_S32 : ap.sampleFormatLongName = "signed 32 bits"; break; + case AV_SAMPLE_FMT_FLT : ap.sampleFormatLongName = "float"; break; + case AV_SAMPLE_FMT_DBL : ap.sampleFormatLongName = "double"; break; + case AV_SAMPLE_FMT_U8P : ap.sampleFormatLongName = "unsigned 8 bits, planar"; break; + case AV_SAMPLE_FMT_S16P : ap.sampleFormatLongName = "signed 16 bits, planar"; break; + case AV_SAMPLE_FMT_S32P : ap.sampleFormatLongName = "signed 32 bits, planar"; break; + case AV_SAMPLE_FMT_FLTP : ap.sampleFormatLongName = "float, planar"; break; + case AV_SAMPLE_FMT_DBLP : ap.sampleFormatLongName = "double, planar"; break; + case AV_SAMPLE_FMT_NB : ap.sampleFormatLongName = "Number of sample formats."; break; } return ap; diff --git a/src/AvTranscoder/mediaProperty/mediaProperty.cpp b/src/AvTranscoder/mediaProperty/mediaProperty.cpp index ad1016b8..1b950179 100644 --- a/src/AvTranscoder/mediaProperty/mediaProperty.cpp +++ b/src/AvTranscoder/mediaProperty/mediaProperty.cpp @@ -114,7 +114,8 @@ MetadatasMap AudioProperties::getDataMap() const detail::add( dataMap, "codec id", codecId ); detail::add( dataMap, "codec name", codecName ); detail::add( dataMap, "codec long name", codecLongName ); - detail::add( dataMap, "sample format", sampleFormat ); + detail::add( dataMap, "sample format name", sampleFormatName ); + detail::add( dataMap, "sample format long name", sampleFormatLongName ); detail::add( dataMap, "sample rate", sampleRate ); detail::add( dataMap, "bit rate", bit_rate ); detail::add( dataMap, "channels", channels ); diff --git a/src/AvTranscoder/mediaProperty/mediaProperty.hpp b/src/AvTranscoder/mediaProperty/mediaProperty.hpp index 68a3c038..89e89013 100644 --- a/src/AvTranscoder/mediaProperty/mediaProperty.hpp +++ b/src/AvTranscoder/mediaProperty/mediaProperty.hpp @@ -106,7 +106,8 @@ struct AvExport AudioProperties { std::string codecName; std::string codecLongName; - std::string sampleFormat; + std::string sampleFormatName; + std::string sampleFormatLongName; std::string channelLayout; std::string channelName; std::string channelDescription; diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.cpp b/src/AvTranscoder/transcoder/StreamTranscoder.cpp index ca95a3ca..35455665 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.cpp @@ -283,11 +283,7 @@ bool StreamTranscoder::processFrame() if( ! _inputEssence ) { - if( _subStreamIndex < 0 ) - { - return processRewrap(); - } - return processRewrap( _subStreamIndex ); + return processRewrap(); } if( _subStreamIndex < 0 ) @@ -311,20 +307,6 @@ bool StreamTranscoder::processRewrap() return true; } -bool StreamTranscoder::processRewrap( const int subStreamIndex ) -{ - assert( _inputStream != NULL ); - assert( _outputStream != NULL ); - - CodedData data; - - if( ! _inputStream->readNextPacket( data ) ) - return false; - _outputStream->wrap( data ); - - return true; -} - bool StreamTranscoder::processTranscode() { assert( _inputEssence != NULL ); diff --git a/src/AvTranscoder/transcoder/StreamTranscoder.hpp b/src/AvTranscoder/transcoder/StreamTranscoder.hpp index 3c46b61c..a8ef25c3 100644 --- a/src/AvTranscoder/transcoder/StreamTranscoder.hpp +++ b/src/AvTranscoder/transcoder/StreamTranscoder.hpp @@ -71,7 +71,6 @@ class AvExport StreamTranscoder private: bool processRewrap(); - bool processRewrap( const int subStreamIndex ); bool processTranscode(); bool processTranscode( const int subStreamIndex ); diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 9639a55b..2ee022a6 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -1,8 +1,11 @@ #include "Transcoder.hpp" +#include + #include #include #include +#include namespace avtranscoder { @@ -34,159 +37,198 @@ Transcoder::~Transcoder() void Transcoder::add( const std::string& filename, const size_t streamIndex, const std::string& profileName, const size_t offset ) { - if( profileName.length() == 0 ) // no profile, only re-wrap stream + // Re-wrap + if( profileName.length() == 0 ) { if( _verbose ) - std::cout << "add re-wrap stream" << std::endl; + std::cout << "Add re-wrap stream" << std::endl; + + // Check filename + if( filename.length() == 0 ) + throw std::runtime_error( "Can't re-wrap a stream without filename indicated" ); + addRewrapStream( filename, streamIndex ); - return; } - - ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); - add( filename, streamIndex, transcodeProfile, offset ); + // Transcode + else + { + ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); + add( filename, streamIndex, transcodeProfile, offset ); + } } void Transcoder::add( const std::string& filename, const size_t streamIndex, const std::string& profileName, ICodec& codec, const size_t offset ) { - if( profileName.length() == 0 ) // no profile, only re-wrap stream + // Re-wrap + if( profileName.length() == 0 ) { if( _verbose ) - std::cout << "add re-wrap stream" << std::endl; - + std::cout << "Add re-wrap stream" << std::endl; + + // Check filename if( filename.length() == 0 ) - { - std::cerr << "can't add a generated stream with no profileName indicated" << std::endl; - return; - } + throw std::runtime_error( "Can't re-wrap a stream without filename indicated" ); addRewrapStream( filename, streamIndex ); - return; } - - ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); - add( filename, streamIndex, transcodeProfile, codec, offset ); + // Transcode + else + { + ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); + add( filename, streamIndex, transcodeProfile, codec, offset ); + } } void Transcoder::add( const std::string& filename, const size_t streamIndex, ProfileLoader::Profile& profile, const size_t offset ) { + // Add profile if new _profileLoader.update( profile ); + + // Check filename if( ! filename.length() ) - { - std::cerr << "can't add a stream with no filename indicated" << std::endl; - return; - } + throw std::runtime_error( "Can't transcode a stream without filename indicated" ); if( _verbose ) - std::cout << "add transcoding stream" << std::endl; + std::cout << "Add transcoded stream" << std::endl; addTranscodeStream( filename, streamIndex, profile, offset ); } void Transcoder::add( const std::string& filename, const size_t streamIndex, ProfileLoader::Profile& profile, ICodec& codec, const size_t offset ) { + // Add profile if new _profileLoader.update( profile ); + + // Generator if( ! filename.length() ) { if( _verbose ) - std::cout << "add a generated stream" << std::endl; + std::cout << "Add generated stream" << std::endl; addDummyStream( profile, codec ); - return; } - - if( _verbose ) - std::cout << "add transcoding stream" << std::endl; - addTranscodeStream( filename, streamIndex, profile, offset ); + // Transcode + else + { + if( _verbose ) + std::cout << "Add transcoded stream" << std::endl; + addTranscodeStream( filename, streamIndex, profile, offset ); + } } void Transcoder::add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, const std::string& profileName, const size_t offset ) { + // No subStream selected if( subStreamIndex < 0 ) { add( filename, streamIndex, profileName, offset ); return; } - if( profileName.length() == 0 ) // no profile, only re-wrap stream + if( profileName.length() == 0 ) { - if( _verbose ) - std::cout << "add re-wrap stream for substream " << subStreamIndex << std::endl; - - addRewrapStream( filename, streamIndex ); - return; + // Re-wrap + if( subStreamIndex < 0 ) + { + if( _verbose ) + std::cout << "Add re-wrap stream" << std::endl; + addRewrapStream( filename, streamIndex ); + return; + } + // Transcode (transparent for the user) + else + { + if( _verbose ) + std::cout << "Add transcoded stream (because of demultiplexing)" << std::endl; + addTranscodeStream( filename, streamIndex, subStreamIndex, offset ); + } + } + // Transcode + else + { + ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); + add( filename, streamIndex, subStreamIndex, transcodeProfile, offset ); } - - ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); - add( filename, streamIndex, subStreamIndex, transcodeProfile, offset ); } void Transcoder::add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, const std::string& profileName, ICodec& codec, const size_t offset ) { + // No subStream selected if( subStreamIndex < 0 ) { add( filename, streamIndex, profileName, codec ); return; } - - if( profileName.length() == 0 ) // no profile, only re-wrap stream - { - if( _verbose ) - std::cout << "add re-wrap stream for substream " << subStreamIndex << std::endl; - if( filename.length() == 0 ) + // Re-wrap + if( profileName.length() == 0 ) + { + // Re-wrap + if( subStreamIndex < 0 ) { - std::cerr << "can't add a generated stream with no profileName indicated" << std::endl; + if( _verbose ) + std::cout << "Add re-wrap stream" << std::endl; + addRewrapStream( filename, streamIndex ); return; } - - addRewrapStream( filename, streamIndex ); - return; + // Transcode (transparent for the user) + else + { + if( _verbose ) + std::cout << "Add transcoded stream (because of demultiplexing)" << std::endl; + addTranscodeStream( filename, streamIndex, subStreamIndex, offset ); + } + } + // Transcode + else + { + ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); + add( filename, streamIndex, subStreamIndex, transcodeProfile, codec, offset ); } - - ProfileLoader::Profile& transcodeProfile = _profileLoader.getProfile( profileName ); - add( filename, streamIndex, subStreamIndex, transcodeProfile, codec, offset ); } void Transcoder::add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, ProfileLoader::Profile& profile, const size_t offset ) { + // Add profile if new _profileLoader.update( profile ); - + + // No subStream selected if( subStreamIndex < 0 ) { add( filename, streamIndex, profile, offset ); return; } - + + // Check filename if( ! filename.length() ) - { - if( _verbose ) - std::cerr << "can't add a stream with no filename indicated" << std::endl; - return; - } + throw std::runtime_error( "Can't transcode a stream without filename indicated" ); if( _verbose ) - std::cout << "add transcoding stream for substream " << subStreamIndex << std::endl; + std::cout << "Add transcoded for substream " << subStreamIndex << std::endl; addTranscodeStream( filename, streamIndex, subStreamIndex, profile, offset ); } void Transcoder::add( const std::string& filename, const size_t streamIndex, const int subStreamIndex, ProfileLoader::Profile& profile, ICodec& codec, const size_t offset ) { + // Add profile if new _profileLoader.update( profile ); + // No subStream selected if( subStreamIndex < 0 ) { add( filename, streamIndex, profile ); return; } - + + // Generator if( ! filename.length() ) { if( _verbose ) - std::cout << "add a generated stream" << std::endl; + std::cout << "Add generated stream" << std::endl; addDummyStream( profile, codec ); return; } if( _verbose ) - std::cout << "add transcoding stream for substream " << subStreamIndex << std::endl; + std::cout << "Add transcoded stream for substream " << subStreamIndex << std::endl; addTranscodeStream( filename, streamIndex, subStreamIndex, profile, offset ); } @@ -335,6 +377,47 @@ void Transcoder::addRewrapStream( const std::string& filename, const size_t stre _streamTranscoders.push_back( new StreamTranscoder( referenceFile->getStream( streamIndex ), _outputFile ) ); } +void Transcoder::addTranscodeStream( const std::string& filename, const size_t streamIndex, const size_t subStreamIndex, const size_t offset ) +{ + InputFile* referenceFile = addInputFile( filename, streamIndex ); + + // Create profile as input configuration + NoDisplayProgress progress; + referenceFile->analyse( progress, InputFile::eAnalyseLevelFast ); + AudioProperties audioProperties = referenceFile->getProperties().audioStreams.at( streamIndex ); + + ProfileLoader::Profile profile; + profile[ constants::avProfileIdentificator ] = "presetRewrap"; + profile[ constants::avProfileIdentificatorHuman ] = "Preset rewrap"; + profile[ constants::avProfileType ] = avtranscoder::constants::avProfileTypeAudio; + profile[ constants::avProfileCodec ] = audioProperties.codecName; + profile[ constants::avProfileSampleFormat ] = audioProperties.sampleFormatName; + std::stringstream ss; + ss << audioProperties.sampleRate; + profile[ constants::avProfileSampleRate ] = ss.str(); + profile[ constants::avProfileChannel ] = "1"; + + // Add profile + _profileLoader.update( profile ); + + switch( referenceFile->getStreamType( streamIndex ) ) + { + case AVMEDIA_TYPE_VIDEO: + case AVMEDIA_TYPE_AUDIO: + { + _streamTranscoders.push_back( new StreamTranscoder( referenceFile->getStream( streamIndex ), _outputFile, profile, subStreamIndex , offset ) ); + 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::addTranscodeStream( const std::string& filename, const size_t streamIndex, ProfileLoader::Profile& profile, const size_t offset ) { InputFile* referenceFile = addInputFile( filename, streamIndex ); diff --git a/src/AvTranscoder/transcoder/Transcoder.hpp b/src/AvTranscoder/transcoder/Transcoder.hpp index 418dfdd8..4f22c6fe 100644 --- a/src/AvTranscoder/transcoder/Transcoder.hpp +++ b/src/AvTranscoder/transcoder/Transcoder.hpp @@ -141,6 +141,11 @@ class AvExport Transcoder void addRewrapStream( const std::string& filename, const size_t streamIndex ); + /** + * @note Get profile from input + */ + void addTranscodeStream( const std::string& filename, const size_t streamIndex, const size_t subStreamIndex, const size_t offset ); + void addTranscodeStream( const std::string& filename, const size_t streamIndex, ProfileLoader::Profile& profile, const size_t offset = 0 ); void addTranscodeStream( const std::string& filename, const size_t streamIndex, const size_t subStreamIndex, ProfileLoader::Profile& profile, const size_t offset = 0 ); diff --git a/test/pyTest/testTranscoderRewrap.py b/test/pyTest/testTranscoderRewrap.py index e48bcfe7..c904e4b9 100644 --- a/test/pyTest/testTranscoderRewrap.py +++ b/test/pyTest/testTranscoderRewrap.py @@ -43,7 +43,8 @@ def testRewrapAudioStream(): # check audio stream assert_equals( src_audioStream.codecName, dst_audioStream.codecName ) assert_equals( src_audioStream.codecLongName, dst_audioStream.codecLongName ) - assert_equals( src_audioStream.sampleFormat, dst_audioStream.sampleFormat ) + assert_equals( src_audioStream.sampleFormatName, dst_audioStream.sampleFormatName ) + assert_equals( src_audioStream.sampleFormatLongName, dst_audioStream.sampleFormatLongName ) # assert_equals( src_audioStream.channelLayout, dst_audioStream.channelLayout ) # '5.1' != '0 channels' assert_equals( src_audioStream.channelName, dst_audioStream.channelName ) assert_equals( src_audioStream.channelDescription, dst_audioStream.channelDescription ) diff --git a/test/pyTest/testTranscoderTranscode.py b/test/pyTest/testTranscoderTranscode.py index f1784fdf..c025f7e4 100644 --- a/test/pyTest/testTranscoderTranscode.py +++ b/test/pyTest/testTranscoderTranscode.py @@ -29,7 +29,8 @@ def testTranscodeWave24b48kmono(): assert_equals( "pcm_s24le", dst_audioStream.codecName ) assert_equals( "PCM signed 24-bit little-endian", dst_audioStream.codecLongName ) - assert_equals( "signed 32 bits", dst_audioStream.sampleFormat ) + assert_equals( "s32", dst_audioStream.sampleFormatName ) + assert_equals( "signed 32 bits", dst_audioStream.sampleFormatLongName ) assert_equals( 48000, dst_audioStream.sampleRate ) # assert_equals( "1 channels", dst_audioStream.channelLayout ) # '1 channels' != '0 channels' assert_equals( 1, dst_audioStream.channels ) @@ -58,7 +59,8 @@ def testTranscodeWave16b48kmono(): assert_equals( "pcm_s16le", dst_audioStream.codecName ) assert_equals( "PCM signed 16-bit little-endian", dst_audioStream.codecLongName ) - assert_equals( "signed 16 bits", dst_audioStream.sampleFormat ) + assert_equals( "s16", dst_audioStream.sampleFormatName ) + assert_equals( "signed 16 bits", dst_audioStream.sampleFormatLongName ) assert_equals( 48000, dst_audioStream.sampleRate ) # assert_equals( "1 channels", dst_audioStream.channelLayout ) # '1 channels' != '0 channels' assert_equals( 1, dst_audioStream.channels )