From eb08caec3bb983ca9ad242c215402f3aa0e722e0 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 17 Jul 2014 14:41:43 +0200 Subject: [PATCH 01/18] adding more metadatas about audio streams --- src/AvTranscoder/Metadatas/AudioStreamProperties.hpp | 12 ++++++++++++ .../Metadatas/MediaMetadatasStructures.hpp | 3 +++ src/AvTranscoder/Metadatas/Print.hpp | 3 +++ 3 files changed, 18 insertions(+) diff --git a/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp b/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp index cf3d7f9c..b6f606f3 100644 --- a/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp +++ b/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp @@ -31,7 +31,19 @@ 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 ); + const char* channelDescription = av_get_channel_description( codec_context->channel_layout ); + if( channelName ) + ap.channelName = std::string( channelName ); + if( channelDescription ) + ap.channelDescription = std::string( channelDescription ); + 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 ) From f25ff2eafaeddcc77b8dc3aa7bcc4b4afcf26642 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Thu, 17 Jul 2014 14:42:17 +0200 Subject: [PATCH 02/18] rename audio profiles in small caps --- src/AvTranscoder/Profiles/Wave.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/Profiles/Wave.hpp b/src/AvTranscoder/Profiles/Wave.hpp index 3e12d150..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; @@ -19,7 +19,7 @@ void loadWave( Profile::ProfilesDesc& profiles ) Profile::ProfileDesc wave16b48kMono; - wave16b48kMono[ Profile::avProfileIdentificator ] = "wave16b48kMono"; + wave16b48kMono[ Profile::avProfileIdentificator ] = "wave16b48kmono"; wave16b48kMono[ Profile::avProfileIdentificatorHuman ] = "Wave 16bits 48kHz mono"; wave16b48kMono[ Profile::avProfileType ] = Profile::avProfileTypeAudio; From e07fb930647aeba89a60b653c1b7ac0272d73e86 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 17 Jul 2014 17:52:47 +0200 Subject: [PATCH 03/18] OptionLoader: getPixelFormats and getSampleFormats are static You can get the list of pixel formats and sample formats without an instance of OptionLoader. Conflicts: src/AvTranscoder/OptionLoader.cpp src/AvTranscoder/OptionLoader.hpp --- src/AvTranscoder/OptionLoader.cpp | 32 ++++++++++++++++++++++++++++++- src/AvTranscoder/OptionLoader.hpp | 11 +++++++++-- 2 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/OptionLoader.cpp b/src/AvTranscoder/OptionLoader.cpp index 00867a01..064670d6 100644 --- a/src/AvTranscoder/OptionLoader.cpp +++ b/src/AvTranscoder/OptionLoader.cpp @@ -276,7 +276,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; @@ -322,4 +322,34 @@ std::vector OptionLoader::getPixelFormats( const std::string& video return pixelFormats; } +std::vector OptionLoader::getSampleFormats( const std::string& audioCodecName ) +{ + std::vector sampleFormats; + + if( audioCodecName.empty() ) + { + for( size_t sampleFormat = 0; sampleFormat < AV_SAMPLE_FMT_NB; ++sampleFormat) + { + sampleFormats.push_back( av_get_sample_fmt_name( static_cast( sampleFormat ) ) ); + } + } + else + { + const AVCodec* audioCodec = avcodec_find_encoder_by_name( audioCodecName.c_str() ); + if( audioCodec && audioCodec->sample_fmts != NULL ) + { + size_t sample_fmt = 0; + while( audioCodec->sample_fmts[sample_fmt] != -1 ) + { + const char* sampleFormatName = av_get_sample_fmt_name( audioCodec->sample_fmts[sample_fmt] ); + if( sampleFormatName ) + sampleFormats.push_back( std::string( sampleFormatName ) ); + sample_fmt++; + } + } + } + + return sampleFormats; +} + } diff --git a/src/AvTranscoder/OptionLoader.hpp b/src/AvTranscoder/OptionLoader.hpp index 0acb7efc..c9b9ce9d 100644 --- a/src/AvTranscoder/OptionLoader.hpp +++ b/src/AvTranscoder/OptionLoader.hpp @@ -60,12 +60,19 @@ class OptionLoader std::vector& getAudioCodecsLongNames() { return _audioCodecsLongNames; } std::vector& getAudioCodecsShortNames() { return _audioCodecsShortNames; } - + +public: /** * Get array of pixel format supported by 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). + */ + static std::vector getSampleFormats( const std::string& audioCodecName = "" ); private: /** From 398033dcb841e68a59783aa253d55d3f1556d5b6 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 17 Jul 2014 18:54:34 +0200 Subject: [PATCH 04/18] OutputEssence: raise exception in setup instead of return false OutputVideo and OutputAudio: raise runtime_error if "could not allocate" or "could not open" video / audio codec. --- .../EssenceStream/OutputAudio.cpp | 19 +++++++++++++------ .../EssenceStream/OutputAudio.hpp | 2 +- .../EssenceStream/OutputEssence.hpp | 3 +-- .../EssenceStream/OutputVideo.cpp | 19 +++++++++++++------ .../EssenceStream/OutputVideo.hpp | 2 +- 5 files changed, 29 insertions(+), 16 deletions(-) diff --git a/src/AvTranscoder/EssenceStream/OutputAudio.cpp b/src/AvTranscoder/EssenceStream/OutputAudio.cpp index e7730cc7..59876334 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 ) 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 42e212f1..207f9c71 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 ); + } } 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 ); From 5ad23f7895f5711d1eb6485ad99cbc33c7e61b5f Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 17 Jul 2014 18:59:54 +0200 Subject: [PATCH 05/18] Audio profile: remove channel layout requirement Fix: the channel layout is not required by FFMPEG when open audio codec context. So an audio profile has not to set this value. --- src/AvTranscoder/EssenceStream/OutputAudio.cpp | 6 +----- src/AvTranscoder/Profile.cpp | 1 - src/AvTranscoder/Profile.hpp | 1 - src/AvTranscoder/Profiles/Wave.hpp | 2 -- 4 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/AvTranscoder/EssenceStream/OutputAudio.cpp b/src/AvTranscoder/EssenceStream/OutputAudio.cpp index 59876334..38d9dc3d 100644 --- a/src/AvTranscoder/EssenceStream/OutputAudio.cpp +++ b/src/AvTranscoder/EssenceStream/OutputAudio.cpp @@ -181,8 +181,7 @@ 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." ); } @@ -194,9 +193,6 @@ void OutputAudio::setProfile( Profile::ProfileDesc& desc, const AudioFrameDesc& 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 ); size_t channels = std::strtoul( desc[ Profile::avProfileChannel ].c_str(), NULL, 0 ); 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/Wave.hpp b/src/AvTranscoder/Profiles/Wave.hpp index 170bc6a4..3e12d150 100644 --- a/src/AvTranscoder/Profiles/Wave.hpp +++ b/src/AvTranscoder/Profiles/Wave.hpp @@ -16,7 +16,6 @@ void loadWave( Profile::ProfilesDesc& profiles ) wave24b48kMono[ Profile::avProfileSampleFormat ] = "s32"; wave24b48kMono[ Profile::avProfileSampleRate ] = "48000"; wave24b48kMono[ Profile::avProfileChannel ] = "1"; - wave24b48kMono[ Profile::avProfileChannelLayout ] = "1"; Profile::ProfileDesc wave16b48kMono; @@ -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 ); From 935c1de09cfcf7404acba0818ed8c616f63aafe0 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 18 Jul 2014 10:47:46 +0200 Subject: [PATCH 06/18] OutputAudio: remove sample rate and channel checks of profile --- src/AvTranscoder/EssenceStream/OutputAudio.cpp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/AvTranscoder/EssenceStream/OutputAudio.cpp b/src/AvTranscoder/EssenceStream/OutputAudio.cpp index 38d9dc3d..3c1c420e 100644 --- a/src/AvTranscoder/EssenceStream/OutputAudio.cpp +++ b/src/AvTranscoder/EssenceStream/OutputAudio.cpp @@ -186,13 +186,6 @@ void OutputAudio::setProfile( Profile::ProfileDesc& desc, const AudioFrameDesc& 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." ); - _audioDesc.setAudioCodec( desc[ Profile::avProfileCodec ] ); size_t sample_rate = std::strtoul( desc[ Profile::avProfileSampleRate ].c_str(), NULL, 0 ); size_t channels = std::strtoul( desc[ Profile::avProfileChannel ].c_str(), NULL, 0 ); From 7d64d0a69d98ac92bf01b0d43f31b86d61e93830 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 10:47:59 +0200 Subject: [PATCH 07/18] only reindent --- src/AvTranscoder/DatasStructures/Frame.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 { From f632209d3e0faeb0b9423367a1da01fb85767a13 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 10:48:27 +0200 Subject: [PATCH 08/18] adding pixel contructor from string --- src/AvTranscoder/DatasStructures/Pixel.cpp | 66 +++++++++++++--------- src/AvTranscoder/DatasStructures/Pixel.hpp | 6 +- 2 files changed, 43 insertions(+), 29 deletions(-) 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; From 509ac5021ab207d9dce732273f69f8babde73874 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 10:51:09 +0200 Subject: [PATCH 09/18] adding enter at the end of file --- src/AvTranscoder/Profiles/DNxHD.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 From 24351be40388aeeb2d6bc8885b4c20d0f50466e9 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 10:55:17 +0200 Subject: [PATCH 10/18] starting to add substream processing --- app/genericProcessor/genericProcessor.cpp | 27 ++++- .../DatasStructures/AudioDesc.cpp | 1 + src/AvTranscoder/EssenceStream/DummyAudio.cpp | 26 +--- src/AvTranscoder/EssenceStream/DummyAudio.hpp | 6 +- src/AvTranscoder/EssenceStream/DummyVideo.cpp | 16 +-- src/AvTranscoder/EssenceStream/DummyVideo.hpp | 4 +- src/AvTranscoder/EssenceStream/InputAudio.cpp | 30 ++++- src/AvTranscoder/EssenceStream/InputAudio.hpp | 2 +- .../EssenceStream/InputEssence.hpp | 2 +- src/AvTranscoder/EssenceStream/InputVideo.cpp | 2 +- src/AvTranscoder/EssenceStream/InputVideo.hpp | 2 +- .../Transcoder/StreamTranscoder.cpp | 110 +++++++++++++++-- .../Transcoder/StreamTranscoder.hpp | 11 +- src/AvTranscoder/Transcoder/Transcoder.cpp | 112 ++++++++++++++++-- src/AvTranscoder/Transcoder/Transcoder.hpp | 24 +++- 15 files changed, 297 insertions(+), 78 deletions(-) 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/DatasStructures/AudioDesc.cpp b/src/AvTranscoder/DatasStructures/AudioDesc.cpp index bd85fd6a..8c990f7d 100644 --- a/src/AvTranscoder/DatasStructures/AudioDesc.cpp +++ b/src/AvTranscoder/DatasStructures/AudioDesc.cpp @@ -231,6 +231,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/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/Transcoder/StreamTranscoder.cpp b/src/AvTranscoder/Transcoder/StreamTranscoder.cpp index 53fbf7bf..91dadbdf 100644 --- a/src/AvTranscoder/Transcoder/StreamTranscoder.cpp +++ b/src/AvTranscoder/Transcoder/StreamTranscoder.cpp @@ -25,7 +25,9 @@ StreamTranscoder::StreamTranscoder( , _inputEssence( NULL ) , _outputEssence( NULL ) , _transform( NULL ) + , _subStreamIndex( -1 ) , _transcodeStream( false ) + , _verbose( false ) { // create a re-wrapping case switch( _inputStream->getStreamType() ) @@ -48,7 +50,8 @@ StreamTranscoder::StreamTranscoder( StreamTranscoder::StreamTranscoder( InputStream& inputStream, OutputFile& outputFile, - Profile::ProfileDesc& profile + Profile::ProfileDesc& profile, + const int subStreamIndex ) : _inputStream( &inputStream ) , _outputStream( NULL ) @@ -57,7 +60,9 @@ StreamTranscoder::StreamTranscoder( , _inputEssence( NULL ) , _outputEssence( NULL ) , _transform( NULL ) + , _subStreamIndex( subStreamIndex ) , _transcodeStream( true ) + , _verbose( false ) { // create a transcode case switch( _inputStream->getStreamType() ) @@ -70,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(); @@ -89,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(); @@ -120,8 +138,11 @@ StreamTranscoder::StreamTranscoder( , _inputEssence( &inputEssence ) , _outputEssence( NULL ) , _transform( NULL ) + , _subStreamIndex( -1 ) , _transcodeStream( true ) + , _verbose( false ) { + // 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.)" ); @@ -154,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(); @@ -176,24 +197,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; } @@ -203,21 +253,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 10257307..fe51fa76 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,9 +66,10 @@ class StreamTranscoder EssenceTransform* _transform; - bool _transcodeStream; - + int _subStreamIndex; + bool _transcodeStream; + 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; }; } From 5887da6f2fe6a319df3928a860506e789a84cf88 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 11:01:26 +0200 Subject: [PATCH 11/18] print error message when write packet is impossible --- src/AvTranscoder/File/OutputFile.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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; } From 144b8fc5a131b6018d99ad47719821eed90aec31 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 18 Jul 2014 11:02:29 +0200 Subject: [PATCH 12/18] OutputVideo: setProfile - refactoring --- .../EssenceStream/OutputVideo.cpp | 48 +++++++------------ 1 file changed, 18 insertions(+), 30 deletions(-) diff --git a/src/AvTranscoder/EssenceStream/OutputVideo.cpp b/src/AvTranscoder/EssenceStream/OutputVideo.cpp index 207f9c71..cdff0a06 100644 --- a/src/AvTranscoder/EssenceStream/OutputVideo.cpp +++ b/src/AvTranscoder/EssenceStream/OutputVideo.cpp @@ -202,27 +202,22 @@ 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 ) { - if( (*it).first == Profile::avProfileIdentificator ) - continue; - if( (*it).first == Profile::avProfileIdentificatorHuman ) - continue; - if( (*it).first == Profile::avProfileType ) - continue; - if( (*it).first == Profile::avProfileCodec ) - continue; - if( (*it).first == Profile::avProfilePixelFormat ) - continue; - if( (*it).first == Profile::avProfileWidth ) - continue; - if( (*it).first == Profile::avProfileHeight ) - continue; - if( (*it).first == Profile::avProfileFrameRate ) + if( (*it).first == Profile::avProfileIdentificator || + (*it).first == Profile::avProfileIdentificatorHuman || + (*it).first == Profile::avProfileType || + (*it).first == Profile::avProfileCodec || + (*it).first == Profile::avProfilePixelFormat || + (*it).first == Profile::avProfileWidth || + (*it).first == Profile::avProfileHeight || + (*it).first == Profile::avProfileFrameRate ) continue; try @@ -239,21 +234,14 @@ void OutputVideo::setProfile( Profile::ProfileDesc& desc, const avtranscoder::Im for( Profile::ProfileDesc::iterator it = desc.begin(); it != desc.end(); ++it ) { - if( (*it).first == Profile::avProfileIdentificator ) - continue; - if( (*it).first == Profile::avProfileIdentificatorHuman ) - continue; - if( (*it).first == Profile::avProfileType ) - continue; - if( (*it).first == Profile::avProfileCodec ) - continue; - if( (*it).first == Profile::avProfilePixelFormat ) - continue; - if( (*it).first == Profile::avProfileWidth ) - continue; - if( (*it).first == Profile::avProfileHeight ) - continue; - if( (*it).first == Profile::avProfileFrameRate ) + if( (*it).first == Profile::avProfileIdentificator || + (*it).first == Profile::avProfileIdentificatorHuman || + (*it).first == Profile::avProfileType || + (*it).first == Profile::avProfileCodec || + (*it).first == Profile::avProfilePixelFormat || + (*it).first == Profile::avProfileWidth || + (*it).first == Profile::avProfileHeight || + (*it).first == Profile::avProfileFrameRate ) continue; try From 323cb0c19786f4839aefa3416301f860cfdad31f Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 18 Jul 2014 11:02:50 +0200 Subject: [PATCH 13/18] OutputAudio: setProfile - refactoring --- src/AvTranscoder/EssenceStream/OutputAudio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/EssenceStream/OutputAudio.cpp b/src/AvTranscoder/EssenceStream/OutputAudio.cpp index 3c1c420e..e87ca9c9 100644 --- a/src/AvTranscoder/EssenceStream/OutputAudio.cpp +++ b/src/AvTranscoder/EssenceStream/OutputAudio.cpp @@ -187,9 +187,9 @@ void OutputAudio::setProfile( Profile::ProfileDesc& desc, const AudioFrameDesc& } _audioDesc.setAudioCodec( desc[ Profile::avProfileCodec ] ); + size_t sample_rate = std::strtoul( desc[ Profile::avProfileSampleRate ].c_str(), NULL, 0 ); size_t channels = std::strtoul( desc[ Profile::avProfileChannel ].c_str(), NULL, 0 ); - _audioDesc.setAudioParameters( sample_rate, channels, av_get_sample_fmt( desc[ Profile::avProfileSampleFormat ].c_str() ) ); setup(); From 45e523f0337196bdb79df12779dd127b954fc207 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 11:03:09 +0200 Subject: [PATCH 14/18] compute packet size for stream properties --- src/AvTranscoder/CodedStream/AvInputStream.cpp | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) 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( ) From 2ab2d4b10e7105944a5dc26890e56baa5a5dcb7b Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 11:46:13 +0200 Subject: [PATCH 15/18] fix library check order --- SConstruct | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) 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 From 6c64e058c59c0455cad2d218f31e90ec16a85cbd Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 11:48:06 +0200 Subject: [PATCH 16/18] update to remove deprecated methods --- src/AvTranscoder/DatasStructures/AudioDesc.cpp | 3 +-- src/AvTranscoder/DatasStructures/VideoDesc.cpp | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/DatasStructures/AudioDesc.cpp b/src/AvTranscoder/DatasStructures/AudioDesc.cpp index 2a77f267..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 ); 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 From 265685743c23511c45ba6c8ec5f0a15ae5ed335b Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 11:48:35 +0200 Subject: [PATCH 17/18] include header and fix LibAV build --- src/AvTranscoder/Metadatas/AudioStreamProperties.hpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp b/src/AvTranscoder/Metadatas/AudioStreamProperties.hpp index b6f606f3..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 @@ -38,12 +39,14 @@ AudioProperties audioStreamInfo( const AVFormatContext* formatContext, const siz ap.channelLayout = std::string( buf1 ); const char* channelName = av_get_channel_name( codec_context->channel_layout ); - const char* channelDescription = av_get_channel_description( 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 ) { From cdfe549ccb56239fe2a6d1e6ca8173c7bb342524 Mon Sep 17 00:00:00 2001 From: Marc-Antoine Arnaud Date: Fri, 18 Jul 2014 12:01:02 +0200 Subject: [PATCH 18/18] remove conflict method --- src/AvTranscoder/OptionLoader.hpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/AvTranscoder/OptionLoader.hpp b/src/AvTranscoder/OptionLoader.hpp index 821c1823..1f77b30d 100644 --- a/src/AvTranscoder/OptionLoader.hpp +++ b/src/AvTranscoder/OptionLoader.hpp @@ -74,12 +74,6 @@ class OptionLoader */ static std::vector getSampleFormats( const std::string& audioCodecName = "" ); - /** - * 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; - private: /** * @brief: load array of Option depending on the flags. 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