diff --git a/app/avMeta/avMeta.cpp b/app/avMeta/avMeta.cpp index d74e4ae9..a65c3782 100644 --- a/app/avMeta/avMeta.cpp +++ b/app/avMeta/avMeta.cpp @@ -1,5 +1,5 @@ #include -#include +#include #include diff --git a/app/avTranscoder/avTranscoder.cpp b/app/avTranscoder/avTranscoder.cpp index 218a3ccd..e1001e58 100644 --- a/app/avTranscoder/avTranscoder.cpp +++ b/app/avTranscoder/avTranscoder.cpp @@ -28,7 +28,7 @@ void transcodeVideo( const char* inputfilename, const char* outputFilename ) InputFile input( inputfilename ); input.analyse( p ); - input.readStream( input.getProperties().videoStreams.at( 0 ).streamId ); + input.readStream( input.getProperties().getVideoProperties().at( 0 ).getStreamId() ); // init video decoders AvInputVideo inputVideo( input.getStream( 0 ) ); diff --git a/app/avplay/AvReader.hpp b/app/avplay/AvReader.hpp index 5cda2c80..0b239ca4 100644 --- a/app/avplay/AvReader.hpp +++ b/app/avplay/AvReader.hpp @@ -5,7 +5,7 @@ #include #include #include -#include +#include #include @@ -23,7 +23,7 @@ class AvReader : public Reader avtranscoder::ConsoleProgress p; _inputFile.analyse( p ); - _videoStream = _inputFile.getProperties().videoStreams.at(0).streamId; + _videoStream = _inputFile.getProperties().getVideoProperties().at( 0 ).getStreamId(); _inputFile.readStream( _videoStream ); @@ -58,17 +58,17 @@ class AvReader : public Reader size_t getWidth() { - return _inputFile.getProperties().videoStreams.at(0).width; + return _inputFile.getProperties().getVideoProperties().at( 0 ).getWidth(); }; size_t getHeight() { - return _inputFile.getProperties().videoStreams.at(0).height; + return _inputFile.getProperties().getVideoProperties().at( 0 ).getHeight(); } size_t getComponents() { - return _inputFile.getProperties().videoStreams.at(0).componentsCount; + return _inputFile.getProperties().getVideoProperties().at( 0 ).getComponentsCount(); } size_t getBitDepth() diff --git a/src/AvTranscoder/avTranscoder.i b/src/AvTranscoder/avTranscoder.i index 5768f912..dfd2b34e 100644 --- a/src/AvTranscoder/avTranscoder.i +++ b/src/AvTranscoder/avTranscoder.i @@ -25,8 +25,6 @@ #include #include -#include - #include #include @@ -62,6 +60,7 @@ namespace std { } %include "AvTranscoder/progress/progress.i" +%include "AvTranscoder/mediaProperty/mediaProperty.i" %include @@ -75,8 +74,6 @@ namespace std { %include %include -%include - %include %include diff --git a/src/AvTranscoder/file/InputFile.cpp b/src/AvTranscoder/file/InputFile.cpp index 1854a0b9..491e9aba 100644 --- a/src/AvTranscoder/file/InputFile.cpp +++ b/src/AvTranscoder/file/InputFile.cpp @@ -1,13 +1,13 @@ #include "InputFile.hpp" #include -#include -#include -#include -#include -#include -#include - +#include +#include +#include +#include +#include +#include +#include extern "C" { #include @@ -24,7 +24,8 @@ namespace avtranscoder InputFile::InputFile( const std::string& filename ) : _formatContext ( NULL ) - , _filename ( filename ) + , _properties( NULL ) + , _filename( filename ) { av_register_all(); if( avformat_open_input( &_formatContext, _filename.c_str(), NULL, NULL ) < 0 ) @@ -42,6 +43,10 @@ InputFile::InputFile( const std::string& filename ) throw std::runtime_error( "unable to find stream informations" ); } + // Initialize FileProperties + _properties = FileProperties( _formatContext ); + + // Create streams for( size_t streamIndex = 0; streamIndex < _formatContext->nb_streams; ++streamIndex ) { _inputStreams.push_back( new AvInputStream( *this, streamIndex ) ); @@ -68,56 +73,38 @@ InputFile& InputFile::analyse( IProgress& progress, const EAnalyseLevel level ) seekAtFrame( 0 ); - _properties.filename = _formatContext->filename; - _properties.formatName = _formatContext->iformat->name; - _properties.formatLongName = _formatContext->iformat->long_name; - _properties.streamsCount = _formatContext->nb_streams; - _properties.programsCount = _formatContext->nb_programs; - _properties.startTime = 1.0 * (unsigned int)_formatContext->start_time / AV_TIME_BASE; - _properties.duration = 1.0 * _formatContext->duration / AV_TIME_BASE; - _properties.bitRate = _formatContext->bit_rate; - _properties.packetSize = _formatContext->packet_size; - - detail::fillMetadataDictionnary( _formatContext->metadata, _properties.metadatas ); - for( size_t streamId = 0; streamId < _formatContext->nb_streams; streamId++ ) { switch( _formatContext->streams[streamId]->codec->codec_type ) { case AVMEDIA_TYPE_VIDEO: { - _properties.videoStreams.push_back( videoStreamInfo( _formatContext, streamId, progress, level ) ); - detail::fillMetadataDictionnary( _formatContext->streams[streamId]->metadata, _properties.videoStreams.back().metadatas ); + _properties.getVideoProperties().push_back( VideoProperties( _formatContext, streamId, progress ) ); break; } case AVMEDIA_TYPE_AUDIO: { - _properties.audioStreams.push_back( audioStreamInfo( _formatContext, streamId ) ); - detail::fillMetadataDictionnary( _formatContext->streams[streamId]->metadata, _properties.audioStreams.back().metadatas ); + _properties.getAudioProperties().push_back( AudioProperties( _formatContext, streamId ) ); break; } case AVMEDIA_TYPE_DATA: { - _properties.dataStreams.push_back( dataStreamInfo( _formatContext, streamId ) ); - detail::fillMetadataDictionnary( _formatContext->streams[streamId]->metadata, _properties.dataStreams.back().metadatas ); + _properties.getDataProperties().push_back( DataProperties( _formatContext, streamId ) ); break; } case AVMEDIA_TYPE_SUBTITLE: { - _properties.subtitleStreams.push_back( subtitleStreamInfo( _formatContext, streamId ) ); - detail::fillMetadataDictionnary( _formatContext->streams[streamId]->metadata, _properties.subtitleStreams.back().metadatas ); + _properties.getSubtitleProperties().push_back( SubtitleProperties( _formatContext, streamId ) ); break; } case AVMEDIA_TYPE_ATTACHMENT: { - _properties.attachementStreams.push_back( attachementStreamInfo( _formatContext, streamId ) ); - detail::fillMetadataDictionnary( _formatContext->streams[streamId]->metadata, _properties.attachementStreams.back().metadatas ); + _properties.getAttachementProperties().push_back( AttachementProperties( _formatContext, streamId ) ); break; } case AVMEDIA_TYPE_UNKNOWN: { - _properties.unknownStreams.push_back( unknownStreamInfo( _formatContext, streamId ) ); - detail::fillMetadataDictionnary( _formatContext->streams[streamId]->metadata, _properties.unknownStreams.back().metadatas ); + _properties.getUnknownPropertiesProperties().push_back( UnknownProperties( _formatContext, streamId ) ); break; } case AVMEDIA_TYPE_NB: @@ -132,13 +119,11 @@ InputFile& InputFile::analyse( IProgress& progress, const EAnalyseLevel level ) return *this; } -Properties InputFile::analyseFile( const std::string& filename, IProgress& progress, const EAnalyseLevel level ) +FileProperties InputFile::analyseFile( const std::string& filename, IProgress& progress, const EAnalyseLevel level ) { InputFile file( filename ); file.analyse( progress, level ); - Properties properties; - file.getProperties( properties ); - return properties; + return file.getProperties(); } AVMediaType InputFile::getStreamType( size_t index ) diff --git a/src/AvTranscoder/file/InputFile.hpp b/src/AvTranscoder/file/InputFile.hpp index a0542a09..5b85fe0d 100644 --- a/src/AvTranscoder/file/InputFile.hpp +++ b/src/AvTranscoder/file/InputFile.hpp @@ -8,7 +8,7 @@ #include -#include +#include #include @@ -37,7 +37,7 @@ class AvExport InputFile enum EAnalyseLevel { eAnalyseLevelFast = 0, - eAnalyseLevelFull = 0, + eAnalyseLevelFull = 1 ///< Analyse first GOP }; /** @@ -57,9 +57,9 @@ class AvExport InputFile * @note require to launch analyse() before to fill the property struture * @return structure of media metadatas **/ - const Properties& getProperties() const { return _properties; } + const FileProperties& getProperties() const { return _properties; } - void getProperties( Properties& properties ) const { properties = _properties; } + void getProperties( FileProperties& properties ) const { properties = _properties; } /** * @brief Get media file properties using static method. @@ -67,7 +67,7 @@ class AvExport InputFile * @param progress callback to get analysis progression * @return structure of media metadatas **/ - static Properties analyseFile( const std::string& filename, IProgress& progress, const EAnalyseLevel level = eAnalyseLevelFull ); + static FileProperties analyseFile( const std::string& filename, IProgress& progress, const EAnalyseLevel level = eAnalyseLevelFull ); /** * @brief Get stream type: video, audio, subtitle, etc. @@ -125,7 +125,7 @@ class AvExport InputFile protected: AVFormatContext* _formatContext; - Properties _properties; + FileProperties _properties; std::string _filename; std::vector _inputStreams; }; diff --git a/src/AvTranscoder/file/OutputFile.hpp b/src/AvTranscoder/file/OutputFile.hpp index e94c5f40..21119d34 100644 --- a/src/AvTranscoder/file/OutputFile.hpp +++ b/src/AvTranscoder/file/OutputFile.hpp @@ -3,7 +3,7 @@ #include -#include +#include #include #include diff --git a/src/AvTranscoder/mediaProperty/AttachementProperties.cpp b/src/AvTranscoder/mediaProperty/AttachementProperties.cpp new file mode 100644 index 00000000..77726093 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/AttachementProperties.cpp @@ -0,0 +1,31 @@ +#include "AttachementProperties.hpp" + +namespace avtranscoder +{ + + +AttachementProperties::AttachementProperties() + : _formatContext( NULL ) + , _streamId( 0 ) +{} + +AttachementProperties::AttachementProperties( const AVFormatContext* formatContext, const size_t index ) + : _formatContext( formatContext ) + , _streamId( index ) +{} + +MetadatasMap AttachementProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "streamId", _streamId ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +} diff --git a/src/AvTranscoder/mediaProperty/AttachementProperties.hpp b/src/AvTranscoder/mediaProperty/AttachementProperties.hpp new file mode 100644 index 00000000..5bd144f2 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/AttachementProperties.hpp @@ -0,0 +1,36 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_ATTACHEMENT_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_ATTACHEMENT_PROPERTIES_HPP + +#include +#include + +extern "C" { +#include +} + +namespace avtranscoder +{ + +class AvExport AttachementProperties +{ +public: + AttachementProperties(); + AttachementProperties( const AVFormatContext* formatContext, const size_t index ); + + size_t getStreamId() const { return _streamId; } + MetadatasMap& getMetadatas() { return _metadatas; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + + MetadatasMap getDataMap() const; + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + + size_t _streamId; + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/AttachementStreamProperty.hpp b/src/AvTranscoder/mediaProperty/AttachementStreamProperty.hpp deleted file mode 100644 index 93de0ae5..00000000 --- a/src/AvTranscoder/mediaProperty/AttachementStreamProperty.hpp +++ /dev/null @@ -1,18 +0,0 @@ -#ifndef _AV_TRANSCODER_ATTACHEMENT_STREAM_PROPERTIES_HPP_ -#define _AV_TRANSCODER_ATTACHEMENT_STREAM_PROPERTIES_HPP_ - -class AVFormatContext; - -namespace avtranscoder -{ - -AttachementProperties attachementStreamInfo( const AVFormatContext* formatContext, const size_t index ) -{ - AttachementProperties ap; - ap.streamId = index; - return ap; -} - -} - -#endif \ No newline at end of file diff --git a/src/AvTranscoder/mediaProperty/AudioProperties.cpp b/src/AvTranscoder/mediaProperty/AudioProperties.cpp new file mode 100644 index 00000000..233f6ea8 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/AudioProperties.cpp @@ -0,0 +1,134 @@ +#include "AudioProperties.hpp" + +extern "C" { +#include +#include +#include +#include +#include +} + +namespace avtranscoder +{ + +AudioProperties::AudioProperties() + : _formatContext( NULL ) + , _codecContext( NULL ) + , _streamId( 0 ) +{} + +AudioProperties::AudioProperties( const AVFormatContext* formatContext, const size_t index ) + : _formatContext( formatContext ) + , _codecContext( formatContext->streams[index]->codec ) + , _streamId( index ) +{} + +std::string AudioProperties::getCodecName() const +{ + AVCodec* codec = avcodec_find_decoder( _codecContext->codec_id ); + if( codec != NULL ) + return std::string( codec->name ); + else + return "unknown codec"; +} + +std::string AudioProperties::getCodecLongName() const +{ + AVCodec* codec = avcodec_find_decoder( _codecContext->codec_id ); + if( codec != NULL ) + return std::string( codec->long_name ); + return "unknown codec"; +} + +std::string AudioProperties::getSampleFormatName() const +{ + const char* fmtName = av_get_sample_fmt_name( _codecContext->sample_fmt ); + if( fmtName ) + return std::string( fmtName ); + return "unknown sample format"; +} + +std::string AudioProperties::getSampleFormatLongName() const +{ + switch( _codecContext->sample_fmt ) + { + case AV_SAMPLE_FMT_NONE: + return "none"; + case AV_SAMPLE_FMT_U8: + return "unsigned 8 bits"; + case AV_SAMPLE_FMT_S16: + return "signed 16 bits"; + case AV_SAMPLE_FMT_S32: + return "signed 32 bits"; + case AV_SAMPLE_FMT_FLT: + return "float"; + case AV_SAMPLE_FMT_DBL: + return "double"; + case AV_SAMPLE_FMT_U8P: + return "unsigned 8 bits, planar"; + case AV_SAMPLE_FMT_S16P: + return "signed 16 bits, planar"; + case AV_SAMPLE_FMT_S32P: + return "signed 32 bits, planar"; + case AV_SAMPLE_FMT_FLTP: + return "float, planar"; + case AV_SAMPLE_FMT_DBLP: + return "double, planar"; + case AV_SAMPLE_FMT_NB: + return "Number of sample formats."; + } + return "unknown sample format"; +} + +std::string AudioProperties::getChannelLayout() const +{ + char buf1[1024]; + av_get_channel_layout_string( buf1, sizeof( buf1 ), -1, _codecContext->channel_layout ); + return std::string( buf1 ); +} + +std::string AudioProperties::getChannelName() const +{ + const char* channelName = av_get_channel_name( _codecContext->channel_layout ); + if( channelName ) + return std::string( channelName ); + return "unknown channel name"; +} + +std::string AudioProperties::getChannelDescription() const +{ +#ifdef FF_RESAMPLE_LIBRARY + const char* channelDescription = av_get_channel_description( _codecContext->channel_layout ); + if( channelDescription ) + return std::string( channelDescription ); + return "unknown channel description"; +#endif + return "can't access channel description"; +} + +MetadatasMap AudioProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "stream id", getStreamId() ); + detail::add( dataMap, "codec id", getCodecId() ); + detail::add( dataMap, "codec name", getCodecName() ); + detail::add( dataMap, "codec long name", getCodecLongName() ); + detail::add( dataMap, "sample format name", getSampleFormatName() ); + detail::add( dataMap, "sample format long name", getSampleFormatLongName() ); + detail::add( dataMap, "sample rate", getSampleRate() ); + detail::add( dataMap, "bit rate", getBitRate() ); + detail::add( dataMap, "channels", getChannels() ); + detail::add( dataMap, "channel layout", getChannelLayout() ); + detail::add( dataMap, "channel name", getChannelName() ); + detail::add( dataMap, "channel description", getChannelDescription() ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +} diff --git a/src/AvTranscoder/mediaProperty/AudioProperties.hpp b/src/AvTranscoder/mediaProperty/AudioProperties.hpp new file mode 100644 index 00000000..e8eb73ab --- /dev/null +++ b/src/AvTranscoder/mediaProperty/AudioProperties.hpp @@ -0,0 +1,54 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_AUDIO_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_AUDIO_PROPERTIES_HPP + +#include +#include + +extern "C" { +#include +#include +} + +#include + +class AVFormatContext; + +namespace avtranscoder +{ + +class AvExport AudioProperties +{ +public: + AudioProperties(); + AudioProperties( const AVFormatContext* formatContext, const size_t index ); + + std::string getCodecName() const; + std::string getCodecLongName() const; + std::string getSampleFormatName() const; + std::string getSampleFormatLongName() const; + std::string getChannelLayout() const; + std::string getChannelName() const; + std::string getChannelDescription() const; + size_t getStreamId() const { return _streamId; } + size_t getCodecId() const { return _codecContext->codec_id; } + size_t getSampleRate() const { return _codecContext->sample_rate; } + size_t getChannels() const { return _codecContext->channels; } + size_t getBitRate() const { return _codecContext->bit_rate; } + MetadatasMap& getMetadatas() { return _metadatas; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + AVCodecContext& getAVCodecContext() { return *_codecContext; } + + MetadatasMap getDataMap() const; + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + AVCodecContext* _codecContext; ///< Has link (no ownership) + + size_t _streamId; + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp b/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp deleted file mode 100644 index 7b651cfa..00000000 --- a/src/AvTranscoder/mediaProperty/AudioStreamProperty.hpp +++ /dev/null @@ -1,72 +0,0 @@ -#ifndef _AV_TRANSCODER_AUDIO_STREAM_PROPERTIES_HPP_ -#define _AV_TRANSCODER_AUDIO_STREAM_PROPERTIES_HPP_ - -extern "C" { -#include -#include -#include -#include -#include -} - -namespace avtranscoder -{ - -avtranscoder::AudioProperties audioStreamInfo( const AVFormatContext* formatContext, const size_t index ) -{ - AudioProperties ap; - AVCodecContext* codec_context = formatContext->streams[index]->codec; - - ap.codecId = codec_context->codec_id; - ap.sampleRate = codec_context->sample_rate; - ap.channels = codec_context->channels; - ap.bit_rate = codec_context->bit_rate; - ap.streamId = index; - - AVCodec* codec = avcodec_find_decoder( codec_context->codec_id ); - if( codec != NULL ) - { - ap.codecName = codec->name; - ap.codecLongName = codec->long_name; - } - - char buf1[1024]; - av_get_channel_layout_string( buf1, sizeof( buf1 ), -1, codec_context->channel_layout ); - - ap.channelLayout = std::string( buf1 ); - - const char* channelName = av_get_channel_name( codec_context->channel_layout ); - if( channelName ) - ap.channelName = std::string( channelName ); -#ifdef FF_RESAMPLE_LIBRARY - const char* channelDescription = av_get_channel_description( codec_context->channel_layout ); - if( channelDescription ) - ap.channelDescription = std::string( channelDescription ); -#endif - const char* fmtName = av_get_sample_fmt_name( codec_context->sample_fmt ); - if( fmtName ) - ap.sampleFormatName = std::string( fmtName ); - - std::string sampleFormat = ""; - switch( codec_context->sample_fmt ) - { - case AV_SAMPLE_FMT_NONE : ap.sampleFormatLongName = "none"; break; - case AV_SAMPLE_FMT_U8 : ap.sampleFormatLongName = "unsigned 8 bits"; break; - case AV_SAMPLE_FMT_S16 : ap.sampleFormatLongName = "signed 16 bits"; break; - case AV_SAMPLE_FMT_S32 : ap.sampleFormatLongName = "signed 32 bits"; break; - case AV_SAMPLE_FMT_FLT : ap.sampleFormatLongName = "float"; break; - case AV_SAMPLE_FMT_DBL : ap.sampleFormatLongName = "double"; break; - case AV_SAMPLE_FMT_U8P : ap.sampleFormatLongName = "unsigned 8 bits, planar"; break; - case AV_SAMPLE_FMT_S16P : ap.sampleFormatLongName = "signed 16 bits, planar"; break; - case AV_SAMPLE_FMT_S32P : ap.sampleFormatLongName = "signed 32 bits, planar"; break; - case AV_SAMPLE_FMT_FLTP : ap.sampleFormatLongName = "float, planar"; break; - case AV_SAMPLE_FMT_DBLP : ap.sampleFormatLongName = "double, planar"; break; - case AV_SAMPLE_FMT_NB : ap.sampleFormatLongName = "Number of sample formats."; break; - } - - return ap; -} - -} - -#endif diff --git a/src/AvTranscoder/mediaProperty/DataStreamProperty.hpp b/src/AvTranscoder/mediaProperty/DataProperties.cpp similarity index 79% rename from src/AvTranscoder/mediaProperty/DataStreamProperty.hpp rename to src/AvTranscoder/mediaProperty/DataProperties.cpp index 6669ad99..7370501a 100644 --- a/src/AvTranscoder/mediaProperty/DataStreamProperty.hpp +++ b/src/AvTranscoder/mediaProperty/DataProperties.cpp @@ -1,28 +1,53 @@ -#ifndef _AV_TRANSCODER_DATA_STREAM_PROPERTIES_HPP_ -#define _AV_TRANSCODER_DATA_STREAM_PROPERTIES_HPP_ +#include "DataProperties.hpp" extern "C" { #include -#include #include #include } #include +#include namespace avtranscoder { -void detectAncillaryData( AVFormatContext* formatContext, const int index ) +DataProperties::DataProperties() + : _formatContext( NULL ) + , _streamId( 0 ) +{} + +DataProperties::DataProperties( const AVFormatContext* formatContext, const size_t index ) + : _formatContext( formatContext ) + , _streamId( index ) +{ + //detectAncillaryData( _formatContext, _streamId ); +} + +MetadatasMap DataProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "streamId", _streamId ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +void DataProperties::detectAncillaryData() { AVPacket pkt; av_init_packet( &pkt ); bool detection = false; - while( ! av_read_frame( formatContext, &pkt ) ) + while( ! av_read_frame( const_cast( _formatContext ), &pkt ) ) { - if( pkt.stream_index == index ) + if( pkt.stream_index == (int)_streamId ) { std::cout << "start detect packet" << std::endl; size_t offset = 0; @@ -62,20 +87,4 @@ void detectAncillaryData( AVFormatContext* formatContext, const int index ) } } -DataProperties dataStreamInfo( AVFormatContext* formatContext, const size_t index ) -{ - DataProperties dp; - dp.streamId = index; - - // AVCodecContext* codec_context = formatContext->streams[index]->codec; - - // dp.codecId = codec_context->codec_id; - - //detectAncillaryData( formatContext, index ); - - return dp; -} - } - -#endif \ No newline at end of file diff --git a/src/AvTranscoder/mediaProperty/DataProperties.hpp b/src/AvTranscoder/mediaProperty/DataProperties.hpp new file mode 100644 index 00000000..dec05520 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/DataProperties.hpp @@ -0,0 +1,39 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_DATA_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_DATA_PROPERTIES_HPP + +#include +#include + +extern "C" { +#include +} + +namespace avtranscoder +{ + +class AvExport DataProperties +{ +public: + DataProperties(); + DataProperties( const AVFormatContext* formatContext, const size_t index ); + + size_t getStreamId() const { return _streamId; } + MetadatasMap& getMetadatas() { return _metadatas; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + + MetadatasMap getDataMap() const; + +private: + void detectAncillaryData(); + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + + size_t _streamId; + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/FileProperties.cpp b/src/AvTranscoder/mediaProperty/FileProperties.cpp new file mode 100644 index 00000000..23158ac1 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/FileProperties.cpp @@ -0,0 +1,48 @@ +#include "FileProperties.hpp" + +namespace avtranscoder +{ + +FileProperties::FileProperties( const AVFormatContext* formatContext ) + : _formatContext( formatContext ) + , _videoStreams() + , _audioStreams() + , _dataStreams() + , _subtitleStreams() + , _attachementStreams() + , _unknownStreams() +{ + if( formatContext ) + detail::fillMetadataDictionnary( _formatContext->metadata, _metadatas ); +} + + +MetadatasMap FileProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "filename", getFilename() ); + detail::add( dataMap, "format name", getFormatName() ); + detail::add( dataMap, "format long name", getFormatLongName() ); + + detail::add( dataMap, "start time", getStartTime() ); + detail::add( dataMap, "duration", getDuration() ); + detail::add( dataMap, "bitrate", getBitRate() ); + detail::add( dataMap, "number of streams", getNbStreams() ); + detail::add( dataMap, "number of programs", getProgramsCount() ); + detail::add( dataMap, "number of video streams", getNbVideoStreams() ); + detail::add( dataMap, "number of audio streams", getNbAudioStreams() ); + detail::add( dataMap, "number of data streams", getNbDataStreams() ); + detail::add( dataMap, "number of subtitle streams", getNbSubtitleStreams() ); + detail::add( dataMap, "number of attachement streams", getNbAttachementStreams() ); + detail::add( dataMap, "number of unknown streams", getNbUnknownStreams() ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +} diff --git a/src/AvTranscoder/mediaProperty/FileProperties.hpp b/src/AvTranscoder/mediaProperty/FileProperties.hpp new file mode 100644 index 00000000..314ad05a --- /dev/null +++ b/src/AvTranscoder/mediaProperty/FileProperties.hpp @@ -0,0 +1,81 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_FILE_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_FILE_PROPERTIES_HPP + +#include +#include + +#include +#include +#include +#include +#include +#include + +extern "C" { +#include +} + +#include +#include + +namespace avtranscoder +{ + +class AvExport FileProperties +{ +public: + FileProperties( const AVFormatContext* formatContext ); + + std::string getFilename() const { return _formatContext->filename; } + std::string getFormatName() const { return _formatContext->iformat->name; } + std::string getFormatLongName() const { return _formatContext->iformat->long_name; } + + size_t getProgramsCount() const { return _formatContext->nb_programs; } + double getStartTime() const { return 1.0 * (unsigned int)_formatContext->start_time / AV_TIME_BASE; } + double getDuration() const { return 1.0 * _formatContext->duration / AV_TIME_BASE; } + size_t getBitRate() const { return _formatContext->bit_rate; } + size_t getPacketSize() const { return _formatContext->packet_size; } + + MetadatasMap& getMetadatas() { return _metadatas; } + + size_t getNbStreams() const { return _formatContext->nb_streams; } + size_t getNbVideoStreams() const { return _videoStreams.size(); } + size_t getNbAudioStreams() const { return _audioStreams.size(); } + size_t getNbDataStreams() const { return _dataStreams.size(); } + size_t getNbSubtitleStreams() const { return _subtitleStreams.size(); } + size_t getNbAttachementStreams() const { return _attachementStreams.size(); } + size_t getNbUnknownStreams() const { return _unknownStreams.size(); } + + std::vector< VideoProperties >& getVideoProperties() { return _videoStreams; } + const std::vector< VideoProperties >& getVideoProperties() const { return _videoStreams; } + std::vector< AudioProperties >& getAudioProperties() { return _audioStreams; } + const std::vector< AudioProperties >& getAudioProperties() const { return _audioStreams; } + std::vector< DataProperties >& getDataProperties() { return _dataStreams; } + const std::vector< DataProperties >& getDataProperties() const { return _dataStreams; } + std::vector< SubtitleProperties >& getSubtitleProperties() { return _subtitleStreams; } + const std::vector< SubtitleProperties >& getSubtitleProperties() const { return _subtitleStreams; } + std::vector< AttachementProperties >& getAttachementProperties() { return _attachementStreams; } + const std::vector< AttachementProperties >& getAttachementProperties() const { return _attachementStreams; } + std::vector< UnknownProperties >& getUnknownPropertiesProperties() { return _unknownStreams; } + const std::vector< UnknownProperties >& getUnknownPropertiesProperties() const { return _unknownStreams; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + + MetadatasMap getDataMap() const; + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + + std::vector< VideoProperties > _videoStreams; ///< Array of properties per video stream + std::vector< AudioProperties > _audioStreams; ///< Array of properties per audio stream + std::vector< DataProperties > _dataStreams; ///< Array of properties per data stream + std::vector< SubtitleProperties > _subtitleStreams; ///< Array of properties per subtitle stream + std::vector< AttachementProperties > _attachementStreams; ///< Array of properties per attachement stream + std::vector< UnknownProperties > _unknownStreams; ///< Array of properties per unknown stream + + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/SubtitleProperties.cpp b/src/AvTranscoder/mediaProperty/SubtitleProperties.cpp new file mode 100644 index 00000000..fc9157e2 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/SubtitleProperties.cpp @@ -0,0 +1,30 @@ +#include "SubtitleProperties.hpp" + +namespace avtranscoder +{ + +SubtitleProperties::SubtitleProperties() + : _formatContext( NULL ) + , _streamId( 0 ) +{} + +SubtitleProperties::SubtitleProperties( const AVFormatContext* formatContext, const size_t index ) + : _formatContext( formatContext ) + , _streamId( index ) +{} + +MetadatasMap SubtitleProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "streamId", _streamId ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +} diff --git a/src/AvTranscoder/mediaProperty/SubtitleProperties.hpp b/src/AvTranscoder/mediaProperty/SubtitleProperties.hpp new file mode 100644 index 00000000..717ccb95 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/SubtitleProperties.hpp @@ -0,0 +1,36 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_SUBTITLE_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_SUBTITLE_PROPERTIES_HPP + +#include +#include + +extern "C" { +#include +} + +namespace avtranscoder +{ + +class AvExport SubtitleProperties +{ +public: + SubtitleProperties(); + SubtitleProperties( const AVFormatContext* formatContext, const size_t index ); + + size_t getStreamId() const { return _streamId; } + MetadatasMap& getMetadatas() { return _metadatas; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + + MetadatasMap getDataMap() const; + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + + size_t _streamId; + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/SubtitleStreamProperty.hpp b/src/AvTranscoder/mediaProperty/SubtitleStreamProperty.hpp deleted file mode 100644 index 9253a319..00000000 --- a/src/AvTranscoder/mediaProperty/SubtitleStreamProperty.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _AV_TRANSCODER_SUBTITLE_STREAM_PROPERTIES_HPP_ -#define _AV_TRANSCODER_SUBTITLE_STREAM_PROPERTIES_HPP_ - -class AVFormatContext; - -namespace avtranscoder -{ - -SubtitleProperties subtitleStreamInfo( const AVFormatContext* formatContext, const size_t index ) -{ - SubtitleProperties sp; - sp.streamId = index; - - return sp; -} - -} - -#endif \ No newline at end of file diff --git a/src/AvTranscoder/mediaProperty/UnknownProperties.cpp b/src/AvTranscoder/mediaProperty/UnknownProperties.cpp new file mode 100644 index 00000000..0d115d5f --- /dev/null +++ b/src/AvTranscoder/mediaProperty/UnknownProperties.cpp @@ -0,0 +1,30 @@ +#include "UnknownProperties.hpp" + +namespace avtranscoder +{ + +UnknownProperties::UnknownProperties() + : _formatContext( NULL ) + , _streamId( 0 ) +{} + +UnknownProperties::UnknownProperties( const AVFormatContext* formatContext, const size_t index ) + : _formatContext( formatContext ) + , _streamId( index ) +{} + +MetadatasMap UnknownProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "streamId", _streamId ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +} diff --git a/src/AvTranscoder/mediaProperty/UnknownProperties.hpp b/src/AvTranscoder/mediaProperty/UnknownProperties.hpp new file mode 100644 index 00000000..b6c39711 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/UnknownProperties.hpp @@ -0,0 +1,36 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_UNKNOWN_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_UNKNOWN_PROPERTIES_HPP + +#include +#include + +extern "C" { +#include +} + +namespace avtranscoder +{ + +class AvExport UnknownProperties +{ +public: + UnknownProperties(); + UnknownProperties( const AVFormatContext* formatContext, const size_t index ); + + size_t getStreamId() const { return _streamId; } + MetadatasMap& getMetadatas() { return _metadatas; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + + MetadatasMap getDataMap() const; + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + + size_t _streamId; + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/UnknownStreamProperty.hpp b/src/AvTranscoder/mediaProperty/UnknownStreamProperty.hpp deleted file mode 100644 index 3d2b21e4..00000000 --- a/src/AvTranscoder/mediaProperty/UnknownStreamProperty.hpp +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef _AV_TRANSCODER_UNKNOWN_STREAM_PROPERTIES_HPP_ -#define _AV_TRANSCODER_UNKNOWN_STREAM_PROPERTIES_HPP_ - -class AVFormatContext; - -namespace avtranscoder -{ - -UnknownProperties unknownStreamInfo( const AVFormatContext* formatContext, const size_t index ) -{ - UnknownProperties up; - up.streamId = index; - - return up; -} - -} - -#endif \ No newline at end of file diff --git a/src/AvTranscoder/mediaProperty/VideoProperties.cpp b/src/AvTranscoder/mediaProperty/VideoProperties.cpp new file mode 100644 index 00000000..e8323dfe --- /dev/null +++ b/src/AvTranscoder/mediaProperty/VideoProperties.cpp @@ -0,0 +1,517 @@ +#include "VideoProperties.hpp" + +#include + +extern "C" { +#include +} + +#include +#include +#include + +#ifdef _MSC_VER +#include +#define isnan _isnan +#define isinf(x) (!_finite(x)) +#endif + +namespace avtranscoder +{ + +VideoProperties::VideoProperties() + : _formatContext( NULL ) + , _codecContext( NULL ) + , _pixFmt( NULL ) + , _streamId( 0 ) + , _isInterlaced( false ) + , _isTopFieldFirst( false ) + , _gopStructure() +{} + +VideoProperties::VideoProperties( const AVFormatContext* formatContext, const size_t index, IProgress& progress ) + : _formatContext( formatContext ) + , _codecContext( formatContext->streams[index]->codec ) + , _pixFmt( NULL ) + , _streamId( index ) + , _isInterlaced( false ) + , _isTopFieldFirst( false ) + , _gopStructure() +{ + // Skip decoding for selected frames + _codecContext->skip_frame = AVDISCARD_NONE; + + // Get pixel format +#if LIBAVUTIL_VERSION_MAJOR > 51 + _pixFmt = av_pix_fmt_desc_get( _codecContext->pix_fmt ); +#else + _pixFmt = NULL; + if( _codecContext->pix_fmt >= 0 && _codecContext->pix_fmt < PIX_FMT_NB ) + _pixFmt = &av_pix_fmt_descriptors[ _codecContext->pix_fmt ]; +#endif + + // Analyse GOP + //if( level == eAnalyseLevelFull ) + analyseGopStructure( progress ); +} + +std::string VideoProperties::getCodecName() const +{ + AVCodec* codec = NULL; + if( ( codec = avcodec_find_decoder( _codecContext->codec_id ) ) != NULL ) + { + if( codec->capabilities & CODEC_CAP_TRUNCATED ) + _codecContext->flags|= CODEC_FLAG_TRUNCATED; + + return std::string( codec->name ); + } + return "unknown codec"; +} + +std::string VideoProperties::getCodecLongName() const +{ + AVCodec* codec = NULL; + if( ( codec = avcodec_find_decoder( _codecContext->codec_id ) ) != NULL ) + { + if( codec->capabilities & CODEC_CAP_TRUNCATED ) + _codecContext->flags|= CODEC_FLAG_TRUNCATED; + + return std::string( codec->long_name ); + } + return "unknown codec"; +} + +std::string VideoProperties::getProfileName() const +{ + AVCodec* codec = NULL; + if( ( codec = avcodec_find_decoder( _codecContext->codec_id ) ) != NULL ) + { + if( codec->capabilities & CODEC_CAP_TRUNCATED ) + _codecContext->flags|= CODEC_FLAG_TRUNCATED; + + if( _codecContext->profile != -99 ) + { + const char* profile; + if( ( profile = av_get_profile_name( codec, _codecContext->profile ) ) != NULL ) + return std::string( profile ); + } + } + return "unknown profile"; +} + +std::string VideoProperties::getColorTransfert() const +{ + switch( _codecContext->color_trc ) + { + case AVCOL_TRC_BT709: + return "Rec 709 / ITU-R BT1361"; + case AVCOL_TRC_UNSPECIFIED: + return "unspecified"; + case AVCOL_TRC_GAMMA22: + return "Gamma 2.2"; + case AVCOL_TRC_GAMMA28: + return "Gamma 2.8"; +#if LIBAVCODEC_VERSION_MAJOR > 53 + case AVCOL_TRC_SMPTE240M: + return "Smpte 240M"; +#endif +#if LIBAVCODEC_VERSION_MAJOR > 54 +#ifdef AVCOL_TRC_SMPTE170M + case AVCOL_TRC_SMPTE170M: + return "Rec 601 / ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC"; +#endif +#ifdef AVCOL_TRC_LINEAR + case AVCOL_TRC_LINEAR: + return "Linear transfer characteristics"; +#endif +#ifdef AVCOL_TRC_LOG + case AVCOL_TRC_LOG: + return "Logarithmic transfer characteristic (100:1 range)"; +#endif +#ifdef AVCOL_TRC_LOG_SQRT + case AVCOL_TRC_LOG_SQRT: + return "Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range)"; +#endif +#ifdef AVCOL_TRC_IEC61966_2_4 + case AVCOL_TRC_IEC61966_2_4: + return "IEC 61966-2-4"; +#endif +#ifdef AVCOL_TRC_BT1361_ECG + case AVCOL_TRC_BT1361_ECG: + return "ITU-R BT1361 Extended Colour Gamut"; +#endif +#ifdef AVCOL_TRC_IEC61966_2_1 + case AVCOL_TRC_IEC61966_2_1: + return "IEC 61966-2-1 (sRGB or sYCC)"; +#endif +#ifdef AVCOL_TRC_BT2020_10 + case AVCOL_TRC_BT2020_10: + return "ITU-R BT2020 for 10 bit system"; +#endif +#ifdef AVCOL_TRC_BT2020_12 + case AVCOL_TRC_BT2020_12: + return "ITU-R BT2020 for 12 bit system"; +#endif +#endif + case AVCOL_TRC_NB: + return "Not ABI"; + default: + return ""; + } +} + +std::string VideoProperties::getColorspace() const +{ + switch( _codecContext->colorspace ) + { + case AVCOL_SPC_RGB: + return "RGB"; + case AVCOL_SPC_BT709: + return "Rec 709"; + case AVCOL_SPC_UNSPECIFIED: + return "unspecified"; + case AVCOL_SPC_FCC: + return "Four CC"; + case AVCOL_SPC_BT470BG: + return "BT470 (PAL - 625)"; + case AVCOL_SPC_SMPTE170M: + return "Smpte 170M (NTSC)"; + case AVCOL_SPC_SMPTE240M: + return "Smpte 240M"; +#if LIBAVCODEC_VERSION_MAJOR > 53 + case AVCOL_SPC_YCOCG: + return "Y Co Cg"; +//#else +// case AVCOL_SPC_YCGCO: +// return "Y Cg Co"; +#endif +#if LIBAVCODEC_VERSION_MAJOR > 54 +#ifdef AVCOL_TRC_BT2020_12 + case AVCOL_SPC_BT2020_NCL: + return "ITU-R BT2020 non-constant luminance system"; +#endif +#ifdef AVCOL_TRC_BT2020_CL + case AVCOL_SPC_BT2020_CL: + return "ITU-R BT2020 constant luminance system"; +#endif +#endif + case AVCOL_SPC_NB: + return "Not ABI"; + default: + return ""; + } +} + +std::string VideoProperties::getColorRange() const +{ + switch( _codecContext->color_range ) + { + case AVCOL_RANGE_UNSPECIFIED: + return "unspecified"; + case AVCOL_RANGE_MPEG: + return "Head"; + case AVCOL_RANGE_JPEG: + return "Full"; + case AVCOL_RANGE_NB: + return "Not ABI"; + default: + return ""; + } +} + +std::string VideoProperties::getColorPrimaries() const +{ + switch( _codecContext->color_primaries ) + { + case AVCOL_PRI_BT709: + return "Rec 709"; + case AVCOL_PRI_UNSPECIFIED: + return "unspecified"; + case AVCOL_PRI_BT470M: + return "BT 470M"; + case AVCOL_PRI_BT470BG: + return "Rec 601 (PAL & SECAM)"; + case AVCOL_PRI_SMPTE170M: + return "Rec 601 (NTSC)"; + case AVCOL_PRI_SMPTE240M: + return "Smpte 240 (NTSC)"; + case AVCOL_PRI_FILM: + return "Film"; +#if LIBAVCODEC_VERSION_MAJOR > 54 +#ifdef AVCOL_TRC_BT2020_CL + case AVCOL_PRI_BT2020: + return "ITU-R BT2020"; +#endif +#endif + case AVCOL_PRI_NB: + return "Not ABI"; + default: + return ""; + } +} + +std::string VideoProperties::getChromaSampleLocation() const +{ + switch( _codecContext->chroma_sample_location ) + { + case AVCHROMA_LOC_UNSPECIFIED: + return "unspecified"; + case AVCHROMA_LOC_LEFT: + return "left (mpeg2/4, h264 default)"; + case AVCHROMA_LOC_CENTER: + return "center (mpeg1, jpeg, h263)"; + case AVCHROMA_LOC_TOPLEFT: + return "top left"; + case AVCHROMA_LOC_TOP: + return "top"; + case AVCHROMA_LOC_BOTTOMLEFT: + return "bottom left"; + case AVCHROMA_LOC_BOTTOM: + return "bottom"; + case AVCHROMA_LOC_NB: + return "Not ABI"; + default: + return ""; + } +} + +std::string VideoProperties::getFieldOrder() const +{ + switch( _codecContext->field_order ) + { + case AV_FIELD_UNKNOWN: + return "unknown"; + case AV_FIELD_PROGRESSIVE: + return "progressive"; + case AV_FIELD_TT: + return "top top"; + case AV_FIELD_BB: + return "bottom bottom"; + case AV_FIELD_TB: + return "top bottom"; + case AV_FIELD_BT: + return "bottom top"; + default: + return ""; + } +} + +std::string VideoProperties::getEndianess() const +{ + return ( _pixFmt->flags & PIX_FMT_BE ) ? "big" : "little"; +} + +std::string VideoProperties::getStartTimecodeString() const +{ + int64_t stratTimeCode = getStartTimecode(); + std::ostringstream os; + os << std::setfill( '0' ); + os << std::setw(2) << ( stratTimeCode >> 19 & 0x1f ) << ":"; // 5-bit hours + os << std::setw(2) << ( stratTimeCode >> 13 & 0x3f ) << ":"; // 6-bit minutes + os << std::setw(2) << ( stratTimeCode >> 6 & 0x3f ) ; // 6-bit seconds + os << ( stratTimeCode & 1 << 24 ? ';' : ':' ); // 1-bit drop flag + os << std::setw(2) << ( stratTimeCode & 0x3f ); // 6-bit frames + return os.str(); +} + + +Rational VideoProperties::getTimeBase() const +{ + Rational timeBase; + timeBase.num = _codecContext->time_base.num; + timeBase.den = _codecContext->time_base.den; + return timeBase; +} + +Rational VideoProperties::getSar() const +{ + Rational sar; + sar.num = _codecContext->sample_aspect_ratio.num; + sar.den = _codecContext->sample_aspect_ratio.den; + return sar; +} + +Rational VideoProperties::getDar() const +{ + int darNum, darDen; + av_reduce( &darNum, &darDen, + _codecContext->width * getSar().num, + _codecContext->height * getSar().den, + 1024 * 1024); + + Rational dar; + dar.num = darNum; + dar.den = darDen; + return dar; +} + +double VideoProperties::getFps() const +{ + Rational timeBase = getTimeBase(); + double fps = 1.0 * timeBase.den / ( timeBase.num * getTicksPerFrame() ); + if( isinf( fps ) ) + fps = 0.0; + return fps; +} + +bool VideoProperties::isPseudoPaletted() const +{ +#if LIBAVCODEC_VERSION_MAJOR > 53 + return (bool) _pixFmt->flags & PIX_FMT_PSEUDOPAL; +#else + return false; +#endif +} + +bool VideoProperties::hasAlpha() const +{ +#if LIBAVCODEC_VERSION_MAJOR > 53 + return (bool) _pixFmt->flags & PIX_FMT_ALPHA; +#else + return false; +#endif +} + +void VideoProperties::analyseGopStructure( IProgress& progress ) +{ + AVCodec* codec = NULL; + if( ( codec = avcodec_find_decoder( _codecContext->codec_id ) ) != NULL ) + { + if( codec->capabilities & CODEC_CAP_TRUNCATED ) + _codecContext->flags|= CODEC_FLAG_TRUNCATED; + + if( _codecContext->width && _codecContext->height ) + { + AVPacket pkt; + +#if LIBAVCODEC_VERSION_MAJOR > 54 + AVFrame* frame = av_frame_alloc(); +#else + AVFrame* frame = avcodec_alloc_frame(); +#endif + + av_init_packet( &pkt ); + avcodec_open2( _codecContext, codec, NULL ); + + int count = 0; + int gotFrame = 0; + bool stopAnalyse = false; + + while( ! av_read_frame( const_cast( _formatContext ), &pkt ) ) + { + if( pkt.stream_index == (int)_streamId ) + { + avcodec_decode_video2( _codecContext, frame, &gotFrame, &pkt ); + if( gotFrame ) + { + _gopStructure.push_back( std::make_pair( av_get_picture_type_char( frame->pict_type ), frame->key_frame ) ); + _isInterlaced = frame->interlaced_frame; + _isTopFieldFirst = frame->top_field_first; + ++count; + if( progress.progress( count, _codecContext->gop_size ) == eJobStatusCancel ) + stopAnalyse = true; + } + } + + av_free_packet( &pkt ); + + if( _codecContext->gop_size == count ) + { + stopAnalyse = true; + } + + if( stopAnalyse ) + break; + } +#if LIBAVCODEC_VERSION_MAJOR > 54 + av_frame_free( &frame ); +#else +#if LIBAVCODEC_VERSION_MAJOR > 53 + avcodec_free_frame( &frame ); +#else + av_free( frame ); +#endif +#endif + } + } +} + +std::vector VideoProperties::getChannels() const +{ + std::vector channels; + for( size_t channel = 0; channel < (size_t)_pixFmt->nb_components; ++channel ) + { + Channel c; + c.id = channel; + c.chromaHeight = (size_t)_pixFmt->comp[channel].plane; + c.bitStep = (size_t)_pixFmt->comp[channel].step_minus1; + channels.push_back( c ); + } + return channels; +} + +MetadatasMap VideoProperties::getDataMap() const +{ + MetadatasMap dataMap; + + detail::add( dataMap, "stream id", getStreamId() ); + detail::add( dataMap, "codec id", getCodecId() ); + detail::add( dataMap, "codec name", getCodecName() ); + detail::add( dataMap, "codec long name", getCodecLongName() ); + detail::add( dataMap, "profile", getProfile() ); + detail::add( dataMap, "profile name", getProfileName() ); + detail::add( dataMap, "level", getLevel() ); + detail::add( dataMap, "start timecode", getStartTimecode() ); + detail::add( dataMap, "width", getWidth() ); + detail::add( dataMap, "height", getHeight() ); + detail::add( dataMap, "pixel aspect ratio", getSar().num / getSar().den ); + detail::add( dataMap, "display aspect ratio", getDar().num / getDar().den ); + detail::add( dataMap, "dtgActiveFormat", getDtgActiveFormat() ); + detail::add( dataMap, "components count", getComponentsCount() ); + detail::add( dataMap, "pixel type", getPixelName() ); + detail::add( dataMap, "bit wise acked", isBitWisePacked() ); + detail::add( dataMap, "rgb pixel", isRgbPixelData() ); + detail::add( dataMap, "as alpha", hasAlpha() ); + detail::add( dataMap, "chroma width", getChromaWidth() ); + detail::add( dataMap, "chroma height", getChromaHeight() ); + detail::add( dataMap, "endianess", getEndianess() ); + detail::add( dataMap, "color transfert", getColorTransfert() ); + detail::add( dataMap, "colorspace", getColorspace() ); + detail::add( dataMap, "color range", getColorRange() ); + detail::add( dataMap, "color primaries", getColorPrimaries() ); + detail::add( dataMap, "indexed colors", isIndexedColors() ); + detail::add( dataMap, "pseudo paletted", isPseudoPaletted() ); + detail::add( dataMap, "chroma sample location", getChromaSampleLocation() ); + detail::add( dataMap, "interlaced ", isInterlaced() ); + detail::add( dataMap, "top field first", isTopFieldFirst() ); + detail::add( dataMap, "field order", getFieldOrder() ); + detail::add( dataMap, "timeBase", getTimeBase().num / getTimeBase().den ); + detail::add( dataMap, "fps", getFps() ); + detail::add( dataMap, "ticksPerFrame", getTicksPerFrame() ); + detail::add( dataMap, "bit rate", getBitRate() ); + detail::add( dataMap, "max bit rate", getMaxBitRate() ); + detail::add( dataMap, "min bit rate", getMinBitRate() ); + detail::add( dataMap, "gop size", getGopSize() ); + + std::string gop; + NoDisplayProgress progress; + std::vector< std::pair< char, bool > > gopStructure = getGopStructure(); + for( size_t frameIndex = 0; frameIndex < gopStructure.size(); ++frameIndex ) + { + gop += gopStructure.at( frameIndex ).first; + gop += ( gopStructure.at( frameIndex ).second ? "*" : " " ); + } + detail::add( dataMap, "gop", gop ); + + detail::add( dataMap, "has B frames", hasBFrames() ); + detail::add( dataMap, "references frames", getReferencesFrames() ); + + for( size_t metadataIndex = 0; metadataIndex < _metadatas.size(); ++metadataIndex ) + { + detail::add( dataMap, _metadatas.at( metadataIndex ).first, _metadatas.at( metadataIndex ).second ); + } + + return dataMap; +} + +} diff --git a/src/AvTranscoder/mediaProperty/VideoProperties.hpp b/src/AvTranscoder/mediaProperty/VideoProperties.hpp new file mode 100644 index 00000000..ec776974 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/VideoProperties.hpp @@ -0,0 +1,126 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_VIDEO_PROPERTIES_HPP +#define _AV_TRANSCODER_MEDIA_PROPERTY_VIDEO_PROPERTIES_HPP + +#include +#include +#include + +extern "C" { +#include +#include +#include +} + +#include +#include +#include + +namespace avtranscoder +{ + +struct AvExport Channel +{ + size_t id; + size_t chromaHeight; + size_t bitStep; +}; + +class AvExport VideoProperties +{ +public: + VideoProperties(); + VideoProperties( const AVFormatContext* formatContext, const size_t index, IProgress& progress ); + + std::string getCodecName() const; + std::string getCodecLongName() const; + std::string getProfileName() const; + std::string getColorTransfert() const; + std::string getColorspace() const; + std::string getColorRange() const; + std::string getColorPrimaries() const; + std::string getChromaSampleLocation() const; + std::string getFieldOrder() const; + + std::string getPixelName() const { return _pixFmt->name; } + std::string getEndianess() const; + + int64_t getStartTimecode() const { return _codecContext->timecode_frame_start; } + std::string getStartTimecodeString() const; + + Rational getTimeBase() const; + Rational getSar() const; // sample/pixel aspect ratio + Rational getDar() const; // display aspect ratio + + size_t getStreamId() const { return _streamId; } + size_t getCodecId() const { return _codecContext->codec_id; } + size_t getBitRate() const { return _codecContext->bit_rate; } + size_t getMaxBitRate() const { return _codecContext->rc_max_rate; } + size_t getMinBitRate() const { return _codecContext->rc_min_rate; } + size_t getTicksPerFrame() const { return _codecContext->ticks_per_frame; } + size_t getWidth() const { return _codecContext->width; } + size_t getHeight() const { return _codecContext->height; } + size_t getGopSize() const { return _codecContext->gop_size; } + size_t getDtgActiveFormat() const { return _codecContext->dtg_active_format; } + size_t getReferencesFrames() const { return _codecContext->refs; } + int getProfile() const { return _codecContext->profile; } + int getLevel() const { return _codecContext->level; } + size_t getComponentsCount() const { return _pixFmt->nb_components; } + size_t getChromaWidth() const { return _pixFmt->log2_chroma_w; } + size_t getChromaHeight() const { return _pixFmt->log2_chroma_h; } + + double getFps() const; + + bool hasBFrames() const { return (bool) _codecContext->has_b_frames; } + bool isIndexedColors() const { return (bool) _pixFmt->flags & PIX_FMT_PAL; } + bool isBitWisePacked() const { return (bool) _pixFmt->flags & PIX_FMT_BITSTREAM; } + bool isHardwareAccelerated() const { return (bool) _pixFmt->flags & PIX_FMT_HWACCEL; } + bool isPlanar() const { return (bool) _pixFmt->flags & PIX_FMT_PLANAR; } + bool isRgbPixelData() const { return (bool) _pixFmt->flags & PIX_FMT_RGB; } + bool isPseudoPaletted() const; + bool hasAlpha() const; + + //@{ + // Warning: Can acces these data when analyse first gop + // Construct the VideoProperties with level = eAnalyseLevelFull + // @see EAnalyseLevel + // @see analyseGopStructure + bool isInterlaced() const { return _isInterlaced; } + bool isTopFieldFirst() const { return _isTopFieldFirst; } + std::vector< std::pair< char, bool > > getGopStructure() const { return _gopStructure; } + //@} + + std::vector getChannels() const; + + MetadatasMap& getMetadatas() { return _metadatas; } + + const AVFormatContext& getAVFormatContext() { return *_formatContext; } + AVCodecContext& getAVCodecContext() { return *_codecContext; } + const AVPixFmtDescriptor& getAVPixFmtDescriptor() { return *_pixFmt; } + + MetadatasMap getDataMap() const; ///< Warning: the method calls analyseGopStructure, which can modify state of the object + +private: + /** + * @brief frame type / is key frame + * @param progress: callback to get analysis progression + */ + void analyseGopStructure( IProgress& progress ); + +private: + const AVFormatContext* _formatContext; ///< Has link (no ownership) + AVCodecContext* _codecContext; ///< Has link (no ownership) + const AVPixFmtDescriptor* _pixFmt; ///< Has link (no ownership) + + size_t _streamId; + //@{ + // Can acces these data when analyse first gop + bool _isInterlaced; + bool _isTopFieldFirst; + std::vector< std::pair< char, bool > > _gopStructure; + //@} + MetadatasMap _metadatas; +}; + +} + +#endif diff --git a/src/AvTranscoder/mediaProperty/VideoStreamProperty.hpp b/src/AvTranscoder/mediaProperty/VideoStreamProperty.hpp deleted file mode 100644 index da3f0778..00000000 --- a/src/AvTranscoder/mediaProperty/VideoStreamProperty.hpp +++ /dev/null @@ -1,344 +0,0 @@ -#ifndef _AV_TRANSCODER_VIDEO_STREAM_PROPERTIES_HPP_ -#define _AV_TRANSCODER_VIDEO_STREAM_PROPERTIES_HPP_ - -extern "C" { -#include -#include -#include -#include -} - -#include -#include -#include - -#ifdef _MSC_VER -#include -#define isnan _isnan -#define isinf(x) (!_finite(x)) -#endif - -namespace avtranscoder -{ - -namespace details -{ - -void getGopProperties( - VideoProperties& vp, - AVFormatContext* formatContext, - AVCodecContext* codecContext, - AVCodec* codec, - const int videoStreamIndex, - IProgress& progress - ) -{ - AVPacket pkt; - -#if LIBAVCODEC_VERSION_MAJOR > 54 - AVFrame* frame = av_frame_alloc(); -#else - AVFrame* frame = avcodec_alloc_frame(); -#endif - - av_init_packet( &pkt ); - avcodec_open2( codecContext, codec, NULL ); - - int count = 0; - int gotFrame = 0; - bool stopAnalyse = false; - - while( ! av_read_frame( formatContext, &pkt ) ) - { - if( pkt.stream_index == videoStreamIndex ) - { - // std::cout << "decode frame" << std::endl; - avcodec_decode_video2( codecContext, frame, &gotFrame, &pkt ); - if( gotFrame ) - { - // std::cout << "inteleaved " << frame->interlaced_frame << std::endl; - vp.gopStructure.push_back( std::pair( av_get_picture_type_char( frame->pict_type ), frame->key_frame ) ); - vp.isInterlaced = frame->interlaced_frame; - vp.topFieldFirst = frame->top_field_first; - ++count; - if( progress.progress( count, codecContext->gop_size ) == eJobStatusCancel ) - stopAnalyse = true; - } - } - - av_free_packet( &pkt ); - - if( codecContext->gop_size == count ) - { - stopAnalyse = true; - } - - if( stopAnalyse ) - break; - } -#if LIBAVCODEC_VERSION_MAJOR > 54 - av_frame_free( &frame ); -#else - #if LIBAVCODEC_VERSION_MAJOR > 53 - avcodec_free_frame( &frame ); - #else - av_free( frame ); - #endif -#endif -} - -} - -std::string makeTimecodeMpegToString( uint32_t tc25bit ) -{ - std::ostringstream os; - os << std::setfill( '0' ); - os << std::setw(2) << ( tc25bit >> 19 & 0x1f ) << ":"; // 5-bit hours - os << std::setw(2) << ( tc25bit >> 13 & 0x3f ) << ":"; // 6-bit minutes - os << std::setw(2) << ( tc25bit >> 6 & 0x3f ) ; // 6-bit seconds - os << ( tc25bit & 1 << 24 ? ';' : ':' ); // 1-bit drop flag - os << std::setw(2) << ( tc25bit & 0x3f ); // 6-bit frames - return os.str(); -} - - -VideoProperties videoStreamInfo( - AVFormatContext* formatContext, - const size_t videoStreamIndex, - IProgress& progress, - const InputFile::EAnalyseLevel level - ) -{ - VideoProperties vp; - AVCodecContext* codec_context = formatContext->streams[videoStreamIndex]->codec; - - codec_context->skip_frame = AVDISCARD_NONE; - - vp.streamId = videoStreamIndex; - - vp.codecId = codec_context->codec_id; - vp.bitRate = codec_context->bit_rate; - vp.maxBitRate = codec_context->rc_max_rate; - vp.minBitRate = codec_context->rc_min_rate; - vp.isInterlaced = false; - vp.topFieldFirst = false; - - vp.ticksPerFrame = codec_context->ticks_per_frame, - vp.width = codec_context->width, - vp.height = codec_context->height, - vp.gopSize = codec_context->gop_size, - vp.dtgActiveFormat = codec_context->dtg_active_format, - vp.referencesFrames = codec_context->refs, - vp.profile = codec_context->profile, - vp.level = codec_context->level; - - vp.timeBase.num = codec_context->time_base.num; - vp.timeBase.den = codec_context->time_base.den; - vp.sar.num = codec_context->sample_aspect_ratio.num; - vp.sar.den = codec_context->sample_aspect_ratio.den; - - vp.startTimecode = makeTimecodeMpegToString( codec_context->timecode_frame_start ); - - int darNum, darDen; - av_reduce( &darNum, &darDen, - codec_context->width * codec_context->sample_aspect_ratio.num, - codec_context->height * codec_context->sample_aspect_ratio.den, - 1024 * 1024); - vp.dar.num = darNum; - vp.dar.den = darDen; - - vp.fps = 1.0 * codec_context->time_base.den / ( codec_context->time_base.num * codec_context->ticks_per_frame ); - - if( isinf( vp.fps ) ) - vp.fps = 0.0; - - vp.hasBFrames = (bool) codec_context->has_b_frames; - - - vp.colorspace = ""; - vp.colorTransfert = ""; - vp.colorRange = ""; - vp.colorPrimaries = ""; - vp.chromaSampleLocation = ""; - vp.fieldOrder = ""; - - switch( codec_context->color_trc ) - { - case AVCOL_TRC_BT709: vp.colorTransfert = "Rec 709 / ITU-R BT1361"; break; - case AVCOL_TRC_UNSPECIFIED: vp.colorTransfert = "unspecified"; break; - case AVCOL_TRC_GAMMA22: vp.colorTransfert = "Gamma 2.2"; break; - case AVCOL_TRC_GAMMA28: vp.colorTransfert = "Gamma 2.8"; break; -#if LIBAVCODEC_VERSION_MAJOR > 53 - case AVCOL_TRC_SMPTE240M: vp.colorTransfert = "Smpte 240M"; break; -#endif -#if LIBAVCODEC_VERSION_MAJOR > 54 - #ifdef AVCOL_TRC_SMPTE170M - case AVCOL_TRC_SMPTE170M: vp.colorTransfert = "Rec 601 / ITU-R BT601-6 525 or 625 / ITU-R BT1358 525 or 625 / ITU-R BT1700 NTSC"; break; - #endif - #ifdef AVCOL_TRC_LINEAR - case AVCOL_TRC_LINEAR: vp.colorTransfert = "Linear transfer characteristics"; break; - #endif - #ifdef AVCOL_TRC_LOG - case AVCOL_TRC_LOG: vp.colorTransfert = "Logarithmic transfer characteristic (100:1 range)"; break; - #endif - #ifdef AVCOL_TRC_LOG_SQRT - case AVCOL_TRC_LOG_SQRT: vp.colorTransfert = "Logarithmic transfer characteristic (100 * Sqrt( 10 ) : 1 range)"; break; - #endif - #ifdef AVCOL_TRC_IEC61966_2_4 - case AVCOL_TRC_IEC61966_2_4: vp.colorTransfert = "IEC 61966-2-4"; break; - #endif - #ifdef AVCOL_TRC_BT1361_ECG - case AVCOL_TRC_BT1361_ECG: vp.colorTransfert = "ITU-R BT1361 Extended Colour Gamut"; break; - #endif - #ifdef AVCOL_TRC_IEC61966_2_1 - case AVCOL_TRC_IEC61966_2_1: vp.colorTransfert = "IEC 61966-2-1 (sRGB or sYCC)"; break; - #endif - #ifdef AVCOL_TRC_BT2020_10 - case AVCOL_TRC_BT2020_10: vp.colorTransfert = "ITU-R BT2020 for 10 bit system"; break; - #endif - #ifdef AVCOL_TRC_BT2020_12 - case AVCOL_TRC_BT2020_12: vp.colorTransfert = "ITU-R BT2020 for 12 bit system"; break; - #endif -#endif - case AVCOL_TRC_NB: vp.colorTransfert = "Not ABI"; break; - default: break; - } - switch( codec_context->colorspace ) - { - case AVCOL_SPC_RGB: vp.colorspace = "RGB"; break; - case AVCOL_SPC_BT709: vp.colorspace = "Rec 709"; break; - case AVCOL_SPC_UNSPECIFIED: vp.colorspace = "unspecified"; break; - case AVCOL_SPC_FCC: vp.colorspace = "Four CC"; break; - case AVCOL_SPC_BT470BG: vp.colorspace = "BT470 (PAL - 625)"; break; - case AVCOL_SPC_SMPTE170M: vp.colorspace = "Smpte 170M (NTSC)"; break; - case AVCOL_SPC_SMPTE240M: vp.colorspace = "Smpte 240M"; break; -#if LIBAVCODEC_VERSION_MAJOR > 53 - case AVCOL_SPC_YCOCG: vp.colorspace = "Y Co Cg"; break; -//#else -// case AVCOL_SPC_YCGCO: vp.colorspace = "Y Cg Co"; break; -#endif -#if LIBAVCODEC_VERSION_MAJOR > 54 - #ifdef AVCOL_TRC_BT2020_12 - case AVCOL_SPC_BT2020_NCL: vp.colorspace = "ITU-R BT2020 non-constant luminance system"; break; - #endif - #ifdef AVCOL_TRC_BT2020_CL - case AVCOL_SPC_BT2020_CL: vp.colorspace = "ITU-R BT2020 constant luminance system"; break; - #endif -#endif - case AVCOL_SPC_NB: vp.colorspace = "Not ABI"; break; - default: break; - } - switch( codec_context->color_range ) - { - case AVCOL_RANGE_UNSPECIFIED: vp.colorRange = "unspecified"; break; - case AVCOL_RANGE_MPEG: vp.colorRange = "Head"; break; - case AVCOL_RANGE_JPEG: vp.colorRange = "Full"; break; - case AVCOL_RANGE_NB: vp.colorRange = "Not ABI"; break; - default: break; - } - switch( codec_context->color_primaries ) - { - case AVCOL_PRI_BT709: vp.colorPrimaries = "Rec 709"; break; - case AVCOL_PRI_UNSPECIFIED: vp.colorPrimaries = "unspecified"; break; - case AVCOL_PRI_BT470M: vp.colorPrimaries = "BT 470M"; break; - case AVCOL_PRI_BT470BG: vp.colorPrimaries = "Rec 601 (PAL & SECAM)"; break; - case AVCOL_PRI_SMPTE170M: vp.colorPrimaries = "Rec 601 (NTSC)"; break; - case AVCOL_PRI_SMPTE240M: vp.colorPrimaries = "Smpte 240 (NTSC)"; break; - case AVCOL_PRI_FILM: vp.colorPrimaries = "Film"; break; -#if LIBAVCODEC_VERSION_MAJOR > 54 - #ifdef AVCOL_TRC_BT2020_CL - case AVCOL_PRI_BT2020: vp.colorPrimaries = "ITU-R BT2020"; break; - #endif -#endif - case AVCOL_PRI_NB: vp.colorPrimaries = "Not ABI"; break; - default: break; - } - switch( codec_context->chroma_sample_location ) - { - case AVCHROMA_LOC_UNSPECIFIED: vp.chromaSampleLocation = "unspecified"; break; - case AVCHROMA_LOC_LEFT: vp.chromaSampleLocation = "left (mpeg2/4, h264 default)"; break; - case AVCHROMA_LOC_CENTER: vp.chromaSampleLocation = "center (mpeg1, jpeg, h263)"; break; - case AVCHROMA_LOC_TOPLEFT: vp.chromaSampleLocation = "top left"; break; - case AVCHROMA_LOC_TOP: vp.chromaSampleLocation = "top"; break; - case AVCHROMA_LOC_BOTTOMLEFT: vp.chromaSampleLocation = "bottom left"; break; - case AVCHROMA_LOC_BOTTOM: vp.chromaSampleLocation = "bottom"; break; - case AVCHROMA_LOC_NB: vp.chromaSampleLocation = "Not ABI"; break; - default: break; - } - switch( codec_context->field_order ) - { - case AV_FIELD_UNKNOWN: vp.fieldOrder = "unknown"; break; - case AV_FIELD_PROGRESSIVE: vp.fieldOrder = "progressive"; break; - case AV_FIELD_TT: vp.fieldOrder = "top top"; break; - case AV_FIELD_BB: vp.fieldOrder = "bottom bottom"; break; - case AV_FIELD_TB: vp.fieldOrder = "top bottom"; break; - case AV_FIELD_BT: vp.fieldOrder = "bottom top"; break; - default: break; - } -#if LIBAVUTIL_VERSION_MAJOR > 51 - const AVPixFmtDescriptor* pixFmt = av_pix_fmt_desc_get( codec_context->pix_fmt ); -#else - const AVPixFmtDescriptor* pixFmt = NULL; - if( codec_context->pix_fmt >= 0 && codec_context->pix_fmt < PIX_FMT_NB ) - pixFmt = &av_pix_fmt_descriptors[ codec_context->pix_fmt ]; -#endif - - if( pixFmt != NULL ) - { - vp.pixelName = pixFmt->name; - vp.componentsCount = pixFmt->nb_components; - vp.chromaWidth = pixFmt->log2_chroma_w; - vp.chromaHeight = pixFmt->log2_chroma_h; - vp.endianess = ( pixFmt->flags & PIX_FMT_BE ) ? "big" : "little"; - vp.indexedColors = (bool) pixFmt->flags & PIX_FMT_PAL; - vp.bitWisePacked = (bool) pixFmt->flags & PIX_FMT_BITSTREAM; - vp.hardwareAcceleration = (bool) pixFmt->flags & PIX_FMT_HWACCEL; - vp.notFirstPlane = (bool) pixFmt->flags & PIX_FMT_PLANAR; - vp.rgbPixelData = (bool) pixFmt->flags & PIX_FMT_RGB; -#if LIBAVCODEC_VERSION_MAJOR > 53 - vp.pseudoPaletted = (bool) pixFmt->flags & PIX_FMT_PSEUDOPAL; - vp.asAlpha = (bool) pixFmt->flags & PIX_FMT_ALPHA; -#else -#endif - - for( size_t channel = 0; channel < (size_t)pixFmt->nb_components; ++channel ) - { - Channel c; - c.id = channel; - c.chromaHeight = (size_t)pixFmt->comp[channel].plane; - c.bitStep = (size_t)pixFmt->comp[channel].step_minus1; - vp.channels.push_back( c ); - } - } - - AVCodec* codec = NULL; - if( ( codec = avcodec_find_decoder( codec_context->codec_id ) ) != NULL ) - { - if( codec->capabilities & CODEC_CAP_TRUNCATED ) - codec_context->flags|= CODEC_FLAG_TRUNCATED; - - vp.codecName = codec->name; - vp.codecLongName = codec->long_name; - - if( codec_context->profile != -99 ) - { - const char* profile; - if( ( profile = av_get_profile_name( codec, codec_context->profile ) ) != NULL ) - vp.profileName = profile; - } - - // std::cout << "pass here " << codec_context->width << "x" << codec_context->height<< std::endl; - - if( codec_context->width && codec_context->height )// && level != InputFile::eAnalyseLevelFast ) - { - // std::cout << "full analysis" << std::endl; - details::getGopProperties( vp, formatContext, codec_context, codec, videoStreamIndex, progress ); - } - } - - return vp; -} - -} - -#endif diff --git a/src/AvTranscoder/mediaProperty/mediaProperty.cpp b/src/AvTranscoder/mediaProperty/mediaProperty.cpp deleted file mode 100644 index 1b950179..00000000 --- a/src/AvTranscoder/mediaProperty/mediaProperty.cpp +++ /dev/null @@ -1,218 +0,0 @@ -#include "mediaProperty.hpp" - -extern "C" { -#include -} - -#include -#include - -namespace avtranscoder -{ - -namespace detail -{ - -template -void add( MetadatasMap& dataMap, const std::string& key, const T& value ) -{ - std::stringstream ss; - ss << value; - add( dataMap, key, ss.str() ); -} - -template<> -void add( MetadatasMap& dataMap, const std::string& key, const std::string& value ) -{ - dataMap.push_back( std::pair( key, value ) ); -} - -template<> -void add( MetadatasMap& dataMap, const std::string& key, const bool& value ) -{ - add( dataMap, key, value ? "True" : "False" ); -} - -void fillMetadataDictionnary( AVDictionary* avdictionnary, MetadatasMap& metadata ) -{ - AVDictionaryEntry* tag = NULL; - while( ( tag = av_dict_get( avdictionnary, "", tag, AV_DICT_IGNORE_SUFFIX ) ) ) - { - metadata.push_back( std::pair( tag->key, tag->value ) ); - } -} - -} - -MetadatasMap VideoProperties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "stream id", streamId ); - detail::add( dataMap, "codec id", codecId ); - detail::add( dataMap, "codec name", codecName ); - detail::add( dataMap, "codec long name", codecLongName ); - detail::add( dataMap, "profile", profile ); - detail::add( dataMap, "profile name", profileName ); - detail::add( dataMap, "level", level ); - detail::add( dataMap, "start timecode", startTimecode ); - detail::add( dataMap, "width", width ); - detail::add( dataMap, "height", height ); - detail::add( dataMap, "pixel aspect ratio", sar.num / sar.den ); - detail::add( dataMap, "display aspect ratio", dar.num / dar.den ); - detail::add( dataMap, "dtgActiveFormat", dtgActiveFormat ); - detail::add( dataMap, "components count", componentsCount ); - detail::add( dataMap, "pixel type", pixelName ); - detail::add( dataMap, "bit wise acked", bitWisePacked ); - detail::add( dataMap, "rgb pixel", rgbPixelData ); - detail::add( dataMap, "as alpha", asAlpha ); - detail::add( dataMap, "chroma width", chromaWidth ); - detail::add( dataMap, "chroma height", chromaHeight ); - detail::add( dataMap, "endianess", endianess ); - detail::add( dataMap, "color transfert", colorTransfert ); - detail::add( dataMap, "colorspace", colorspace ); - detail::add( dataMap, "color range", colorRange ); - detail::add( dataMap, "color primaries", colorPrimaries ); - detail::add( dataMap, "indexed colors", indexedColors ); - detail::add( dataMap, "pseudo paletted", pseudoPaletted ); - detail::add( dataMap, "chroma sample location", chromaSampleLocation); - detail::add( dataMap, "interlaced ", isInterlaced ); - detail::add( dataMap, "top field first", topFieldFirst ); - detail::add( dataMap, "field order", fieldOrder); - detail::add( dataMap, "timeBase", timeBase.num / timeBase.den ); - detail::add( dataMap, "fps", fps ); - detail::add( dataMap, "ticksPerFrame", ticksPerFrame ); - detail::add( dataMap, "bit rate", bitRate ); - detail::add( dataMap, "max bit rate", maxBitRate ); - detail::add( dataMap, "min bit rate", minBitRate ); - detail::add( dataMap, "gop size", gopSize ); - - std::string gop; - for( size_t frameIndex = 0; frameIndex < gopStructure.size(); ++frameIndex ) - { - gop += gopStructure.at( frameIndex ).first; - gop += ( gopStructure.at( frameIndex ).second ? "*" : " " ); - } - detail::add( dataMap, "gop", gop ); - - detail::add( dataMap, "has B frames", hasBFrames ); - detail::add( dataMap, "references frames", referencesFrames ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -MetadatasMap AudioProperties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "stream id", streamId ); - detail::add( dataMap, "codec id", codecId ); - detail::add( dataMap, "codec name", codecName ); - detail::add( dataMap, "codec long name", codecLongName ); - detail::add( dataMap, "sample format name", sampleFormatName ); - detail::add( dataMap, "sample format long name", sampleFormatLongName ); - detail::add( dataMap, "sample rate", sampleRate ); - detail::add( dataMap, "bit rate", bit_rate ); - detail::add( dataMap, "channels", channels ); - detail::add( dataMap, "channel layout", channelLayout ); - detail::add( dataMap, "channel name", channelName ); - detail::add( dataMap, "channel description", channelDescription ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -MetadatasMap DataProperties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "streamId", streamId ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -MetadatasMap SubtitleProperties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "streamId", streamId ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -MetadatasMap AttachementProperties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "streamId", streamId ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -MetadatasMap UnknownProperties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "streamId", streamId ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -MetadatasMap Properties::getDataMap() const -{ - MetadatasMap dataMap; - - detail::add( dataMap, "filename", filename ); - detail::add( dataMap, "format name", formatName ); - detail::add( dataMap, "format long name", formatLongName ); - - detail::add( dataMap, "start time", startTime ); - detail::add( dataMap, "duration", duration ); - detail::add( dataMap, "bitrate", bitRate ); - detail::add( dataMap, "number of streams", streamsCount ); - detail::add( dataMap, "number of programs", programsCount ); - detail::add( dataMap, "number of video streams", videoStreams.size() ); - detail::add( dataMap, "number of audio streams", audioStreams.size() ); - detail::add( dataMap, "number of data streams", dataStreams.size() ); - detail::add( dataMap, "number of subtitle streams", subtitleStreams.size() ); - detail::add( dataMap, "number of attachement streams", attachementStreams.size() ); - detail::add( dataMap, "number of unknown streams", unknownStreams.size() ); - - for( size_t metadataIndex = 0; metadataIndex < metadatas.size(); ++metadataIndex ) - { - detail::add( dataMap, metadatas.at( metadataIndex ).first, metadatas.at( metadataIndex ).second ); - } - - return dataMap; -} - -} diff --git a/src/AvTranscoder/mediaProperty/mediaProperty.hpp b/src/AvTranscoder/mediaProperty/mediaProperty.hpp deleted file mode 100644 index 89e89013..00000000 --- a/src/AvTranscoder/mediaProperty/mediaProperty.hpp +++ /dev/null @@ -1,189 +0,0 @@ -#ifndef _AV_TRANSCODER_MEDIA_HPP_ -#define _AV_TRANSCODER_MEDIA_HPP_ - -#include - -#include -#include -#include - -namespace avtranscoder -{ - -/** - * @brief Can get all data of Properties structures by getDataMap(), which return a MetadatasMap. - */ -typedef std::vector< std::pair > MetadatasMap; - -namespace detail -{ - /** - * @brief Fill metadata parameter with the given AVDictionary. - */ - void AvExport fillMetadataDictionnary( AVDictionary* avdictionnary, MetadatasMap& metadata ); -} - -struct AvExport Channel -{ - size_t id; - size_t chromaHeight; - size_t bitStep; -}; - -struct AvExport VideoProperties -{ - VideoProperties() - { - timeBase.num = 0; - timeBase.den = 0; - sar.num = 0; - sar.den = 0; - dar.num = 0; - dar.den = 0; - } - -public: - std::string codecName; - std::string codecLongName; - std::string profileName; - std::string colorTransfert; - std::string colorspace; - std::string colorRange; - std::string colorPrimaries; - std::string chromaSampleLocation; - std::string fieldOrder; - - std::string pixelName; - std::string endianess; - - std::string startTimecode; - - Rational timeBase; - Rational sar; // sample/pixel aspect ratio - Rational dar; // display aspect ratio - - size_t streamId; - size_t codecId; - size_t bitRate; - size_t maxBitRate; - size_t minBitRate; - size_t ticksPerFrame; - size_t width; - size_t height; - size_t gopSize; - size_t dtgActiveFormat; - size_t referencesFrames; - int profile; - int level; - size_t componentsCount; - size_t chromaWidth; - size_t chromaHeight; - - double fps; - - bool hasBFrames; - bool indexedColors; - bool bitWisePacked; - bool hardwareAcceleration; - bool notFirstPlane; - bool rgbPixelData; - bool pseudoPaletted; - bool asAlpha; - bool isInterlaced; - bool topFieldFirst; - - // ( frame type / is key frame ) - std::vector< std::pair< char, bool > > gopStructure; - std::vector channels; - - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -struct AvExport AudioProperties -{ - std::string codecName; - std::string codecLongName; - std::string sampleFormatName; - std::string sampleFormatLongName; - std::string channelLayout; - std::string channelName; - std::string channelDescription; - size_t streamId; - size_t codecId; - size_t sampleRate; - size_t channels; - size_t bit_rate; - - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -struct AvExport DataProperties -{ - size_t streamId; - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -struct AvExport SubtitleProperties -{ - size_t streamId; - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -struct AvExport AttachementProperties -{ - size_t streamId; - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -struct AvExport UnknownProperties -{ - size_t streamId; - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -struct AvExport Properties -{ - std::string filename; - std::string formatName; - std::string formatLongName; - size_t streamsCount; - size_t programsCount; - double startTime; - double duration; - size_t bitRate; - size_t packetSize; - - std::vector< VideoProperties > videoStreams; - std::vector< AudioProperties > audioStreams; - std::vector< DataProperties > dataStreams; - std::vector< SubtitleProperties > subtitleStreams; - std::vector< AttachementProperties > attachementStreams; - std::vector< UnknownProperties > unknownStreams; - - MetadatasMap metadatas; - -public: - MetadatasMap getDataMap() const; -}; - -} - -#endif \ No newline at end of file diff --git a/src/AvTranscoder/mediaProperty/mediaProperty.i b/src/AvTranscoder/mediaProperty/mediaProperty.i new file mode 100644 index 00000000..8719a2f0 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/mediaProperty.i @@ -0,0 +1,23 @@ +%{ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace avtranscoder; +%} + +%include +%include +%include +%include +%include +%include +%include +%include + diff --git a/src/AvTranscoder/mediaProperty/printMediaProperty.hpp b/src/AvTranscoder/mediaProperty/print.hpp similarity index 80% rename from src/AvTranscoder/mediaProperty/printMediaProperty.hpp rename to src/AvTranscoder/mediaProperty/print.hpp index a2a69c80..cdebeb4a 100644 --- a/src/AvTranscoder/mediaProperty/printMediaProperty.hpp +++ b/src/AvTranscoder/mediaProperty/print.hpp @@ -14,7 +14,7 @@ namespace avtranscoder static const size_t keyWidth = 32; static const std::string separator = "===================="; -std::ostream& operator<<( std::ostream& flux, const Properties& properties ) +std::ostream& operator<<( std::ostream& flux, const FileProperties& properties ) { flux << std::left; flux << separator << " Wrapper " << separator << std::endl; @@ -114,39 +114,39 @@ std::ostream& operator<<( std::ostream& flux, const InputFile& input ) flux << input.getProperties(); // video streams - for( size_t videoStreamIndex = 0; videoStreamIndex < input.getProperties().videoStreams.size(); ++videoStreamIndex ) + for( size_t videoStreamIndex = 0; videoStreamIndex < input.getProperties().getNbVideoStreams(); ++videoStreamIndex ) { - flux << input.getProperties().videoStreams.at( videoStreamIndex ); + flux << input.getProperties().getVideoProperties().at( videoStreamIndex ); } // audio streams - for( size_t audioStreamIndex = 0; audioStreamIndex < input.getProperties().audioStreams.size(); ++audioStreamIndex ) + for( size_t audioStreamIndex = 0; audioStreamIndex < input.getProperties().getNbAudioStreams(); ++audioStreamIndex ) { - flux << input.getProperties().audioStreams.at( audioStreamIndex ); + flux << input.getProperties().getAudioProperties().at( audioStreamIndex ); } // data streams - for( size_t dataStreamIndex = 0; dataStreamIndex < input.getProperties().dataStreams.size(); ++dataStreamIndex ) + for( size_t dataStreamIndex = 0; dataStreamIndex < input.getProperties().getNbDataStreams(); ++dataStreamIndex ) { - flux << input.getProperties().dataStreams.at( dataStreamIndex ); + flux << input.getProperties().getDataProperties().at( dataStreamIndex ); } // subtitle streams - for( size_t subtitleStreamIndex = 0; subtitleStreamIndex < input.getProperties().subtitleStreams.size(); ++subtitleStreamIndex ) + for( size_t subtitleStreamIndex = 0; subtitleStreamIndex < input.getProperties().getNbSubtitleStreams(); ++subtitleStreamIndex ) { - flux << input.getProperties().subtitleStreams.at( subtitleStreamIndex ); + flux << input.getProperties().getSubtitleProperties().at( subtitleStreamIndex ); } // attachement streams - for( size_t attachementStreamIndex = 0; attachementStreamIndex < input.getProperties().attachementStreams.size(); ++attachementStreamIndex ) + for( size_t attachementStreamIndex = 0; attachementStreamIndex < input.getProperties().getNbAttachementStreams(); ++attachementStreamIndex ) { - flux << input.getProperties().attachementStreams.at( attachementStreamIndex ); + flux << input.getProperties().getAttachementProperties().at( attachementStreamIndex ); } // unknown streams - for( size_t unknownStreamIndex = 0; unknownStreamIndex < input.getProperties().unknownStreams.size(); ++unknownStreamIndex ) + for( size_t unknownStreamIndex = 0; unknownStreamIndex < input.getProperties().getNbUnknownStreams(); ++unknownStreamIndex ) { - flux << input.getProperties().unknownStreams.at( unknownStreamIndex ); + flux << input.getProperties().getUnknownPropertiesProperties().at( unknownStreamIndex ); } return flux; diff --git a/src/AvTranscoder/mediaProperty/util.cpp b/src/AvTranscoder/mediaProperty/util.cpp new file mode 100644 index 00000000..6b4ab4dc --- /dev/null +++ b/src/AvTranscoder/mediaProperty/util.cpp @@ -0,0 +1,36 @@ +#include "util.hpp" + +extern "C" { +#include +} + +namespace avtranscoder +{ + +namespace detail +{ + +template<> +void add( MetadatasMap& dataMap, const std::string& key, const std::string& value ) +{ + dataMap.push_back( std::make_pair( key, value ) ); +} + +template<> +void add( MetadatasMap& dataMap, const std::string& key, const bool& value ) +{ + add( dataMap, key, value ? "True" : "False" ); +} + +void fillMetadataDictionnary( AVDictionary* avdictionnary, MetadatasMap& metadata ) +{ + AVDictionaryEntry* tag = NULL; + while( ( tag = av_dict_get( avdictionnary, "", tag, AV_DICT_IGNORE_SUFFIX ) ) ) + { + metadata.push_back( std::make_pair( tag->key, tag->value ) ); + } +} + +} + +} diff --git a/src/AvTranscoder/mediaProperty/util.hpp b/src/AvTranscoder/mediaProperty/util.hpp new file mode 100644 index 00000000..8170a021 --- /dev/null +++ b/src/AvTranscoder/mediaProperty/util.hpp @@ -0,0 +1,45 @@ +#ifndef _AV_TRANSCODER_MEDIA_PROPERTY_UTIL_HPP_ +#define _AV_TRANSCODER_MEDIA_PROPERTY_UTIL_HPP_ + +#include + +#include +#include +#include +#include + +namespace avtranscoder +{ + +/** + * @brief Can get all data of Properties structures by getDataMap(), which return a MetadatasMap. + */ +typedef std::vector< std::pair > MetadatasMap; + +namespace detail +{ + +template +void add( MetadatasMap& dataMap, const std::string& key, const T& value ) +{ + std::stringstream ss; + ss << value; + add( dataMap, key, ss.str() ); +} + +template<> +void add( MetadatasMap& dataMap, const std::string& key, const std::string& value ); + +template<> +void add( MetadatasMap& dataMap, const std::string& key, const bool& value ); + +/** + * @brief Fill metadata parameter with the given AVDictionary. + */ +void AvExport fillMetadataDictionnary( AVDictionary* avdictionnary, MetadatasMap& metadata ); + +} + +} + +#endif \ No newline at end of file diff --git a/src/AvTranscoder/transcoder/Transcoder.cpp b/src/AvTranscoder/transcoder/Transcoder.cpp index 2ee022a6..acf30709 100644 --- a/src/AvTranscoder/transcoder/Transcoder.cpp +++ b/src/AvTranscoder/transcoder/Transcoder.cpp @@ -384,16 +384,16 @@ void Transcoder::addTranscodeStream( const std::string& filename, const size_t s // Create profile as input configuration NoDisplayProgress progress; referenceFile->analyse( progress, InputFile::eAnalyseLevelFast ); - AudioProperties audioProperties = referenceFile->getProperties().audioStreams.at( streamIndex ); + AudioProperties audioProperties = referenceFile->getProperties().getAudioProperties().at( streamIndex ); ProfileLoader::Profile profile; profile[ constants::avProfileIdentificator ] = "presetRewrap"; profile[ constants::avProfileIdentificatorHuman ] = "Preset rewrap"; profile[ constants::avProfileType ] = avtranscoder::constants::avProfileTypeAudio; - profile[ constants::avProfileCodec ] = audioProperties.codecName; - profile[ constants::avProfileSampleFormat ] = audioProperties.sampleFormatName; + profile[ constants::avProfileCodec ] = audioProperties.getCodecName(); + profile[ constants::avProfileSampleFormat ] = audioProperties.getSampleFormatName(); std::stringstream ss; - ss << audioProperties.sampleRate; + ss << audioProperties.getSampleRate(); profile[ constants::avProfileSampleRate ] = ss.str(); profile[ constants::avProfileChannel ] = "1"; diff --git a/src/AvTranscoder/transform/AudioTransform.cpp b/src/AvTranscoder/transform/AudioTransform.cpp index 5c68a776..af9a2463 100644 --- a/src/AvTranscoder/transform/AudioTransform.cpp +++ b/src/AvTranscoder/transform/AudioTransform.cpp @@ -84,7 +84,7 @@ void AudioTransform::convert( const Frame& srcFrame, Frame& dstFrame ) throw std::runtime_error( "unable to convert audio samples" ); } - int nbOutputSamples = nbOutputSamplesPerChannel * static_cast( dstFrame ).desc().getChannels(); + size_t nbOutputSamples = nbOutputSamplesPerChannel * static_cast( dstFrame ).desc().getChannels(); if( dstFrame.getSize() != nbOutputSamples ) dstFrame.getBuffer().resize( nbOutputSamples, 0 ); diff --git a/test/pyTest/testProperties.py b/test/pyTest/testProperties.py index 8a380f04..58460e06 100644 --- a/test/pyTest/testProperties.py +++ b/test/pyTest/testProperties.py @@ -28,7 +28,7 @@ def testAddMetadataDate(): inputFile.analyse( progress, av.InputFile.eAnalyseLevelFast ) properties = inputFile.getProperties() - assert_in( metadata_to_check, properties.metadatas ) + assert_in( metadata_to_check, properties.getMetadatas() ) def testAddImpossibleMetadata(): """ @@ -53,4 +53,4 @@ def testAddImpossibleMetadata(): inputFile.analyse( progress, av.InputFile.eAnalyseLevelFast ) properties = inputFile.getProperties() - assert_not_in( metadata_to_check, properties.metadatas ) + assert_not_in( metadata_to_check, properties.getMetadatas() )