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.