From a0215505806585671e3e8c4acaa5dfd3c7fb4d49 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 14:04:44 +0200 Subject: [PATCH 01/27] Frame: added getEncodedSize method --- src/AvTranscoder/data/decoded/Frame.cpp | 5 +++++ src/AvTranscoder/data/decoded/Frame.hpp | 6 ++++++ 2 files changed, 11 insertions(+) diff --git a/src/AvTranscoder/data/decoded/Frame.cpp b/src/AvTranscoder/data/decoded/Frame.cpp index 68491b24..655776c9 100644 --- a/src/AvTranscoder/data/decoded/Frame.cpp +++ b/src/AvTranscoder/data/decoded/Frame.cpp @@ -40,6 +40,11 @@ Frame::~Frame() } } +int Frame::getEncodedSize() const +{ + return av_frame_get_pkt_size(_frame); +} + void Frame::copyData(const Frame& frameToRef) { const int ret = av_frame_copy(_frame, &frameToRef.getAVFrame()); diff --git a/src/AvTranscoder/data/decoded/Frame.hpp b/src/AvTranscoder/data/decoded/Frame.hpp index aa3e45b1..482c92ff 100644 --- a/src/AvTranscoder/data/decoded/Frame.hpp +++ b/src/AvTranscoder/data/decoded/Frame.hpp @@ -43,6 +43,12 @@ class AvExport Frame */ int* getLineSize() const { return _frame->linesize; } + /** + * @return Size of the corresponding packet containing the compressed frame (in bytes) + * @warning returns a negative value if the size is unknown + */ + int getEncodedSize() const; + /** * @brief Copy the data of the given Frame. * @note This function does not allocate anything: the current frame must be already initialized and From f6da521de04ea777279fb45890998caa2316218c Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 14:08:06 +0200 Subject: [PATCH 02/27] VideoProperties: refactored the methods that use AVFrame * Use Frame class instead (allocation/free is managed by the class). --- .../properties/VideoProperties.cpp | 46 ++++--------------- 1 file changed, 10 insertions(+), 36 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 0dd86102..18da046a 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -1,5 +1,6 @@ #include "VideoProperties.hpp" +#include #include #include @@ -336,11 +337,7 @@ size_t VideoProperties::getBitRate() const // discard no frame type when decode _codecContext->skip_frame = AVDISCARD_NONE; -#if LIBAVCODEC_VERSION_MAJOR > 54 - AVFrame* frame = av_frame_alloc(); -#else - AVFrame* frame = avcodec_alloc_frame(); -#endif + Frame frame; AVPacket pkt; av_init_packet(&pkt); avcodec_open2(_codecContext, _codec, NULL); @@ -353,11 +350,11 @@ size_t VideoProperties::getBitRate() const { if(pkt.stream_index == (int)_streamIndex) { - avcodec_decode_video2(_codecContext, frame, &gotFrame, &pkt); + avcodec_decode_video2(_codecContext, &frame.getAVFrame(), &gotFrame, &pkt); if(gotFrame) { #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 7, 100) - gopFramesSize += av_frame_get_pkt_size(frame); + gopFramesSize += av_frame_get_pkt_size(&frame.getAVFrame()); #else gopFramesSize += pkt.size; #endif @@ -368,13 +365,6 @@ size_t VideoProperties::getBitRate() const if(_codecContext->gop_size == count) break; } -#if LIBAVCODEC_VERSION_MAJOR > 54 - av_frame_free(&frame); -#elif LIBAVCODEC_VERSION_MAJOR > 53 - avcodec_free_frame(&frame); -#else - av_free(frame); -#endif int bitsPerByte = 8; return (gopFramesSize / _codecContext->gop_size) * bitsPerByte * getFps(); @@ -493,16 +483,10 @@ void VideoProperties::analyseGopStructure(IProgress& progress) AVPacket pkt; av_init_packet(&pkt); -// Allocate frame -#if LIBAVCODEC_VERSION_MAJOR > 54 - AVFrame* frame = av_frame_alloc(); -#else - AVFrame* frame = avcodec_alloc_frame(); -#endif - // Initialize the AVCodecContext to use the given AVCodec avcodec_open2(_codecContext, _codec, NULL); + Frame frame; int count = 0; int gotFrame = 0; bool stopAnalyse = false; @@ -511,13 +495,14 @@ void VideoProperties::analyseGopStructure(IProgress& progress) { if(pkt.stream_index == (int)_streamIndex) { - avcodec_decode_video2(_codecContext, frame, &gotFrame, &pkt); + avcodec_decode_video2(_codecContext, &frame.getAVFrame(), &gotFrame, &pkt); if(gotFrame) { + AVFrame& avFrame = frame.getAVFrame(); _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; + std::make_pair(av_get_picture_type_char(avFrame.pict_type), avFrame.key_frame)); + _isInterlaced = avFrame.interlaced_frame; + _isTopFieldFirst = avFrame.top_field_first; ++count; if(progress.progress(count, _codecContext->gop_size) == eJobStatusCancel) stopAnalyse = true; @@ -537,17 +522,6 @@ void VideoProperties::analyseGopStructure(IProgress& progress) // Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself) avcodec_close(_codecContext); - -// Free frame -#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 } } } From 742d9d93ed7b705c64cc75bc3e18ebe4d0499480 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 14:08:39 +0200 Subject: [PATCH 03/27] VideoProperties: refactored getProfileName method Use VideoProperties::getProfile() method. --- src/AvTranscoder/properties/VideoProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 18da046a..f1bdb751 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -48,7 +48,7 @@ std::string VideoProperties::getProfileName() const throw std::runtime_error("unknown codec profile"); const char* profile = NULL; - if((profile = av_get_profile_name(_codec, _codecContext->profile)) == NULL) + if((profile = av_get_profile_name(_codec, getProfile())) == NULL) throw std::runtime_error("unknown codec profile"); return std::string(profile); From 7aa117929893943de233846502a54c0ab3d6a131 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 14:09:28 +0200 Subject: [PATCH 04/27] VideoProperties: refactored getBitRate method Use Frame::getEncodedSize() method. --- src/AvTranscoder/properties/VideoProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index f1bdb751..4f895903 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -354,7 +354,7 @@ size_t VideoProperties::getBitRate() const if(gotFrame) { #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 7, 100) - gopFramesSize += av_frame_get_pkt_size(&frame.getAVFrame()); + gopFramesSize += frame.getEncodedSize(); #else gopFramesSize += pkt.size; #endif From 4c82c58b486234a0c299b98c033d6b3e2d83c4de Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 14:45:24 +0200 Subject: [PATCH 05/27] VideoProperties: refactored the methods that use gop_size * Use VideoProperties::getGopSize() instead. * Add doc to this method. --- src/AvTranscoder/properties/VideoProperties.cpp | 12 ++++++------ src/AvTranscoder/properties/VideoProperties.hpp | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 4f895903..e4a1b251 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -343,7 +343,7 @@ size_t VideoProperties::getBitRate() const avcodec_open2(_codecContext, _codec, NULL); int gotFrame = 0; - int count = 0; + size_t count = 0; int gopFramesSize = 0; while(!av_read_frame(const_cast(_formatContext), &pkt)) @@ -362,12 +362,12 @@ size_t VideoProperties::getBitRate() const } } av_free_packet(&pkt); - if(_codecContext->gop_size == count) + if(getGopSize() == count) break; } int bitsPerByte = 8; - return (gopFramesSize / _codecContext->gop_size) * bitsPerByte * getFps(); + return (gopFramesSize / getGopSize()) * bitsPerByte * getFps(); } size_t VideoProperties::getMaxBitRate() const @@ -487,7 +487,7 @@ void VideoProperties::analyseGopStructure(IProgress& progress) avcodec_open2(_codecContext, _codec, NULL); Frame frame; - int count = 0; + size_t count = 0; int gotFrame = 0; bool stopAnalyse = false; @@ -504,14 +504,14 @@ void VideoProperties::analyseGopStructure(IProgress& progress) _isInterlaced = avFrame.interlaced_frame; _isTopFieldFirst = avFrame.top_field_first; ++count; - if(progress.progress(count, _codecContext->gop_size) == eJobStatusCancel) + if(progress.progress(count, getGopSize()) == eJobStatusCancel) stopAnalyse = true; } } av_free_packet(&pkt); - if(_codecContext->gop_size == count) + if(getGopSize() == count) { stopAnalyse = true; } diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index bd1cc301..163eea76 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -47,7 +47,13 @@ class AvExport VideoProperties : public StreamProperties size_t getTicksPerFrame() const; size_t getWidth() const; size_t getHeight() const; + + /** + * @return the distance between two nearest I frame + * @note it returns 0 for intra_only + */ size_t getGopSize() const; + size_t getDtgActiveFormat() const; size_t getReferencesFrames() const; int getProfile() const; From 1dffc17363da7d2fda02da1f80b19f9b8992e151 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 15:35:07 +0200 Subject: [PATCH 06/27] VideoProperties: added _levelAnalysis private attribute * To get the level of analysis asked inside member methods. * Will be used in the next commit. --- src/AvTranscoder/properties/VideoProperties.cpp | 1 + src/AvTranscoder/properties/VideoProperties.hpp | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index e4a1b251..9f0b3284 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -20,6 +20,7 @@ namespace avtranscoder VideoProperties::VideoProperties(const FormatContext& formatContext, const size_t index, IProgress& progress, const EAnalyseLevel level) : StreamProperties(formatContext, index) + , _levelAnalysis(level) , _pixelProperties() , _isInterlaced(false) , _isTopFieldFirst(false) diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index 163eea76..919f275b 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -110,6 +110,11 @@ class AvExport VideoProperties : public StreamProperties #endif private: + /** + * @brief Level of analysis asked. + */ + EAnalyseLevel _levelAnalysis; + PixelProperties _pixelProperties; //@{ // Can acces these data when analyse first gop From 7d7f7888294a0352b5ae33bc92d540620283ad9c Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 15:42:51 +0200 Subject: [PATCH 07/27] VideoProperties: fixed getGopSize method * AVCodecContext->gop_size is unused when decode according to the ffmpeg documentation: https://ffmpeg.org/doxygen/2.8/structAVCodecContext.html#a9b6b3f1fcbdcc2ad9f4dbb4370496e38 * So compute this info when analyseGopStructure, and store it inside the VideoProperties class. * Because the gop size could be used inside getBitRate() method, throw a runtime exception before using it. --- .../properties/VideoProperties.cpp | 40 +++++++++++-------- .../properties/VideoProperties.hpp | 12 +++--- 2 files changed, 29 insertions(+), 23 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 9f0b3284..059cbaf2 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -24,6 +24,7 @@ VideoProperties::VideoProperties(const FormatContext& formatContext, const size_ , _pixelProperties() , _isInterlaced(false) , _isTopFieldFirst(false) + , _gopSize(0) , _gopStructure() , _firstGopTimeCode(-1) { @@ -335,6 +336,10 @@ size_t VideoProperties::getBitRate() const if(!_codecContext->width || !_codecContext->height) throw std::runtime_error("cannot compute bit rate: invalid frame size"); + // Needed to get the gop size + if(_levelAnalysis < eAnalyseLevelFirstGop) + throw std::runtime_error("cannot compute bit rate: need to get info from the first gop (see eAnalyseLevelFirstGop)"); + // discard no frame type when decode _codecContext->skip_frame = AVDISCARD_NONE; @@ -416,13 +421,6 @@ size_t VideoProperties::getHeight() const return _codecContext->height; } -size_t VideoProperties::getGopSize() const -{ - if(!_codecContext) - throw std::runtime_error("unknown codec context"); - return _codecContext->gop_size; -} - size_t VideoProperties::getDtgActiveFormat() const { if(!_codecContext) @@ -490,7 +488,8 @@ void VideoProperties::analyseGopStructure(IProgress& progress) Frame frame; size_t count = 0; int gotFrame = 0; - bool stopAnalyse = false; + int positionOfFirstKeyFrame = -1; + int positionOfLastKeyFrame = -1; while(!av_read_frame(const_cast(_formatContext), &pkt)) { @@ -500,25 +499,34 @@ void VideoProperties::analyseGopStructure(IProgress& progress) if(gotFrame) { AVFrame& avFrame = frame.getAVFrame(); + _gopStructure.push_back( std::make_pair(av_get_picture_type_char(avFrame.pict_type), avFrame.key_frame)); _isInterlaced = avFrame.interlaced_frame; _isTopFieldFirst = avFrame.top_field_first; + if(avFrame.pict_type == AV_PICTURE_TYPE_I) + { + if(positionOfFirstKeyFrame == -1) + positionOfFirstKeyFrame = count; + else + positionOfLastKeyFrame = count; + } + ++count; - if(progress.progress(count, getGopSize()) == eJobStatusCancel) - stopAnalyse = true; } } - av_free_packet(&pkt); - if(getGopSize() == count) + // If the first 2 key frames are found + if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1) { - stopAnalyse = true; - } - - if(stopAnalyse) + // Set gop size as distance between these 2 key frames + _gopSize = positionOfLastKeyFrame - positionOfFirstKeyFrame; + // Update gop structure to keep only one gop + while(_gopStructure.size() > _gopSize) + _gopStructure.pop_back(); break; + } } // Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself) diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index 919f275b..c89ee2ca 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -47,13 +47,6 @@ class AvExport VideoProperties : public StreamProperties size_t getTicksPerFrame() const; size_t getWidth() const; size_t getHeight() const; - - /** - * @return the distance between two nearest I frame - * @note it returns 0 for intra_only - */ - size_t getGopSize() const; - size_t getDtgActiveFormat() const; size_t getReferencesFrames() const; int getProfile() const; @@ -77,6 +70,10 @@ class AvExport VideoProperties : public StreamProperties // @see analyseGopStructure bool isInterlaced() const { return _isInterlaced; } bool isTopFieldFirst() const { return _isTopFieldFirst; } + /** + * @return the distance between two nearest I frame + */ + size_t getGopSize() const { return _gopSize; } std::vector > getGopStructure() const { return _gopStructure; } //@} @@ -120,6 +117,7 @@ class AvExport VideoProperties : public StreamProperties // Can acces these data when analyse first gop bool _isInterlaced; bool _isTopFieldFirst; + size_t _gopSize; std::vector > _gopStructure; //@} From 2a81f063240d6b8920b49b3c35460bbf709b6134 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 15:44:17 +0200 Subject: [PATCH 08/27] VideoProperties: added doc to _pixelProperties attribute --- src/AvTranscoder/properties/VideoProperties.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index c89ee2ca..d995a565 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -112,7 +112,11 @@ class AvExport VideoProperties : public StreamProperties */ EAnalyseLevel _levelAnalysis; + /** + * @brief All the pixel properties contained in this stream. + */ PixelProperties _pixelProperties; + //@{ // Can acces these data when analyse first gop bool _isInterlaced; From 252531760bd793c54806cd6878261c1b592a9fa8 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 15:57:51 +0200 Subject: [PATCH 09/27] FormatContext: added const to local variables of methods --- src/AvTranscoder/file/FormatContext.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/AvTranscoder/file/FormatContext.cpp b/src/AvTranscoder/file/FormatContext.cpp index f15fa69d..cab0b3d7 100644 --- a/src/AvTranscoder/file/FormatContext.cpp +++ b/src/AvTranscoder/file/FormatContext.cpp @@ -53,7 +53,7 @@ FormatContext::~FormatContext() void FormatContext::findStreamInfo(AVDictionary** options) { - int err = avformat_find_stream_info(_avFormatContext, options); + const int err = avformat_find_stream_info(_avFormatContext, options); if(err < 0) { throw std::ios_base::failure("Unable to find stream informations: " + getDescriptionFromErrorCode(err)); @@ -65,7 +65,7 @@ void FormatContext::openRessource(const std::string& url, int flags) if((_avFormatContext->flags & AVFMT_NOFILE) == AVFMT_NOFILE) return; - int err = avio_open2(&_avFormatContext->pb, url.c_str(), flags, NULL, NULL); + const int err = avio_open2(&_avFormatContext->pb, url.c_str(), flags, NULL, NULL); if(err < 0) { throw std::ios_base::failure("Error when opening output format: " + getDescriptionFromErrorCode(err)); @@ -77,7 +77,7 @@ void FormatContext::closeRessource() if((_avFormatContext->flags & AVFMT_NOFILE) == AVFMT_NOFILE) return; - int err = avio_close(_avFormatContext->pb); + const int err = avio_close(_avFormatContext->pb); if(err < 0) { throw std::ios_base::failure("Error when close output format: " + getDescriptionFromErrorCode(err)); @@ -86,7 +86,7 @@ void FormatContext::closeRessource() void FormatContext::writeHeader(AVDictionary** options) { - int ret = avformat_write_header(_avFormatContext, options); + const int ret = avformat_write_header(_avFormatContext, options); if(ret != 0) { throw std::runtime_error("Could not write header: " + getDescriptionFromErrorCode(ret)); @@ -115,7 +115,7 @@ void FormatContext::writeFrame(AVPacket& packet, bool interleaved) void FormatContext::writeTrailer() { - int ret = av_write_trailer(_avFormatContext); + const int ret = av_write_trailer(_avFormatContext); if(ret != 0) { throw std::runtime_error("Could not write trailer: " + getDescriptionFromErrorCode(ret)); @@ -124,7 +124,7 @@ void FormatContext::writeTrailer() void FormatContext::addMetaData(const std::string& key, const std::string& value) { - int ret = av_dict_set(&_avFormatContext->metadata, key.c_str(), value.c_str(), 0); + const int ret = av_dict_set(&_avFormatContext->metadata, key.c_str(), value.c_str(), 0); if(ret < 0) { LOG_ERROR(getDescriptionFromErrorCode(ret)) @@ -144,8 +144,8 @@ AVStream& FormatContext::addAVStream(const AVCodec& avCodec) bool FormatContext::seek(const uint64_t position, const int flag) { - LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " (in AV_TIME_BASE units)") - int err = av_seek_frame(_avFormatContext, -1, position, flag); + LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " with flag '"<< flag << "'") + const int err = av_seek_frame(_avFormatContext, -1, position, flag); if(err < 0) { LOG_ERROR("Error when seek at " << position << " (in AV_TIME_BASE units) in file") From 68cc0dda98264e5fe27071b2840846c9f98ef0a8 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 16:25:26 +0200 Subject: [PATCH 10/27] pyTest: updated testInputFileAnalyseFirstGop --- test/pyTest/testInputFile.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/pyTest/testInputFile.py b/test/pyTest/testInputFile.py index d9b4f247..237ce06d 100644 --- a/test/pyTest/testInputFile.py +++ b/test/pyTest/testInputFile.py @@ -31,6 +31,7 @@ def testInputFileAnalyseFirstGop(): videoProperties = inputFile.getProperties().getVideoProperties()[0] assert_equals(videoProperties.isInterlaced(), False) assert_equals(videoProperties.isTopFieldFirst(), False) + assert_equals(videoProperties.getGopSize(), 0) assert_equals(videoProperties.getGopStructure(), ()) # Analyse first GOP @@ -39,4 +40,5 @@ def testInputFileAnalyseFirstGop(): # Check properties after GOP analysis videoProperties = inputFile.getProperties().getVideoProperties()[0] + assert_greater(videoProperties.getGopSize(), 0) assert_not_equals(videoProperties.getGopStructure(), ()) From 81bc92e9d7837cc3726459eede4e0f1ec9bec567 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 16:46:13 +0200 Subject: [PATCH 11/27] VideoProperties: updated value returned by getGopStructure * Before: picture type, is key frame * After: picture type, encoded frame size in bytes * Note: "is key frame" info can be found using the picture type (I frame). --- src/AvTranscoder/properties/VideoProperties.cpp | 2 +- src/AvTranscoder/properties/VideoProperties.hpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 059cbaf2..345d661f 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -501,7 +501,7 @@ void VideoProperties::analyseGopStructure(IProgress& progress) AVFrame& avFrame = frame.getAVFrame(); _gopStructure.push_back( - std::make_pair(av_get_picture_type_char(avFrame.pict_type), avFrame.key_frame)); + std::make_pair(av_get_picture_type_char(avFrame.pict_type), frame.getEncodedSize())); _isInterlaced = avFrame.interlaced_frame; _isTopFieldFirst = avFrame.top_field_first; if(avFrame.pict_type == AV_PICTURE_TYPE_I) diff --git a/src/AvTranscoder/properties/VideoProperties.hpp b/src/AvTranscoder/properties/VideoProperties.hpp index d995a565..66ef46e7 100644 --- a/src/AvTranscoder/properties/VideoProperties.hpp +++ b/src/AvTranscoder/properties/VideoProperties.hpp @@ -74,7 +74,7 @@ class AvExport VideoProperties : public StreamProperties * @return the distance between two nearest I frame */ size_t getGopSize() const { return _gopSize; } - std::vector > getGopStructure() const { return _gopStructure; } + std::vector > getGopStructure() const { return _gopStructure; } //@} #ifndef SWIG @@ -122,7 +122,7 @@ class AvExport VideoProperties : public StreamProperties bool _isInterlaced; bool _isTopFieldFirst; size_t _gopSize; - std::vector > _gopStructure; + std::vector > _gopStructure; ///< picture type, encoded frame size in bytes //@} /** From 4cee3de9b47262c2c638ecad593af36ed702d132 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 16:48:35 +0200 Subject: [PATCH 12/27] VideoProperties: get encoded frame size of GOP when fillVector of properties --- src/AvTranscoder/properties/VideoProperties.cpp | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 345d661f..063895d3 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -567,13 +567,16 @@ PropertyVector& VideoProperties::fillVector(PropertyVector& data) const addProperty(data, "minBitRate", &VideoProperties::getMinBitRate); addProperty(data, "gopSize", &VideoProperties::getGopSize); - std::string gop; + std::stringstream gop; for(size_t frameIndex = 0; frameIndex < _gopStructure.size(); ++frameIndex) { - gop += _gopStructure.at(frameIndex).first; - gop += " "; + gop << _gopStructure.at(frameIndex).first; + gop << "("; + gop << _gopStructure.at(frameIndex).second;; + gop << ")"; + gop << " "; } - detail::add(data, "gop", gop); + detail::add(data, "gop", gop.str()); // detail::add( data, "isClosedGop", isClosedGop() ); addProperty(data, "hasBFrames", &VideoProperties::hasBFrames); From c8ddd63e5c584a84cb1cda1a6c1b33f553c33672 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 16:50:57 +0200 Subject: [PATCH 13/27] StreamProperties: update getDuration method Throw a runtime_error if the duration is unknown. --- src/AvTranscoder/properties/StreamProperties.cpp | 5 ++++- src/AvTranscoder/properties/StreamProperties.hpp | 7 +++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/src/AvTranscoder/properties/StreamProperties.cpp b/src/AvTranscoder/properties/StreamProperties.cpp index 1bc28f31..23e00bb2 100644 --- a/src/AvTranscoder/properties/StreamProperties.cpp +++ b/src/AvTranscoder/properties/StreamProperties.cpp @@ -53,7 +53,10 @@ Rational StreamProperties::getTimeBase() const float StreamProperties::getDuration() const { const Rational timeBase = getTimeBase(); - return av_q2d(timeBase) * _formatContext->streams[_streamIndex]->duration; + const size_t streamDurationInStreamTimeBase = _formatContext->streams[_streamIndex]->duration; + if(streamDurationInStreamTimeBase == (size_t)AV_NOPTS_VALUE) + throw std::runtime_error("unknown stream duration"); + return av_q2d(timeBase) * streamDurationInStreamTimeBase; } AVMediaType StreamProperties::getStreamType() const diff --git a/src/AvTranscoder/properties/StreamProperties.hpp b/src/AvTranscoder/properties/StreamProperties.hpp index f3c68e04..df79cf8f 100644 --- a/src/AvTranscoder/properties/StreamProperties.hpp +++ b/src/AvTranscoder/properties/StreamProperties.hpp @@ -18,6 +18,13 @@ class AvExport StreamProperties size_t getStreamIndex() const { return _streamIndex; } size_t getStreamId() const; Rational getTimeBase() const; + + /** + * @return duration of the stream in seconds + * @throw runtime_error if the duration is unknown + * @note If a source file does not specify a duration, but does specify + * a bitrate, this value will be estimated from bitrate and file size. + */ float getDuration() const; ///< in seconds AVMediaType getStreamType() const; From 5625a8781bbeb4f1f5e30a0d291af149d0514e11 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 16:55:01 +0200 Subject: [PATCH 14/27] FileProperties: removed seek at the beginning when extractStreamProperties * These instructions make analysis impossible for some AVC Intra media. * WARNING: need to check if this commit induces some side effects. --- src/AvTranscoder/properties/FileProperties.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index c18083fe..2fb5ff40 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -31,10 +31,6 @@ void FileProperties::extractStreamProperties(IProgress& progress, const EAnalyse { clearStreamProperties(); - // if the analysis level wiil decode some streams parts, seek at the beginning - if(level > eAnalyseLevelHeader) - const_cast(_formatContext)->seek(0, AVSEEK_FLAG_BACKWARD); - for(size_t streamIndex = 0; streamIndex < _formatContext->getNbStreams(); ++streamIndex) { switch(_formatContext->getAVStream(streamIndex).codec->codec_type) @@ -118,10 +114,6 @@ void FileProperties::extractStreamProperties(IProgress& progress, const EAnalyse const size_t unknownStreamIndex = _unknownStreams.at(streamIndex).getStreamIndex(); _streams[unknownStreamIndex] = &_unknownStreams.at(streamIndex); } - - // if the analysis level has decoded some streams parts, return at the beginning - if(level > eAnalyseLevelHeader) - const_cast(_formatContext)->seek(0, AVSEEK_FLAG_BACKWARD); } std::string FileProperties::getFilename() const From b4cd1aab2fd06b8c88146e2aa1bc9f575ec0560e Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 16:58:15 +0200 Subject: [PATCH 15/27] properties: fixed GopPair/GopVector generated by SWIG The C++ structure was updated in commit: 81bc92e9d7837cc3726459eede4e0f1ec9bec567 --- src/AvTranscoder/properties/properties.i | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/AvTranscoder/properties/properties.i b/src/AvTranscoder/properties/properties.i index 00cbaeaa..0bbb720f 100644 --- a/src/AvTranscoder/properties/properties.i +++ b/src/AvTranscoder/properties/properties.i @@ -40,8 +40,8 @@ namespace std { %template(PropertyPair) pair< string, string >; %template(PropertyVector) vector< pair< string, string > >; -%template(GopPair) pair< char, bool >; -%template(GopVector) vector< pair< char, bool > >; +%template(GopPair) pair< char, int >; +%template(GopVector) vector< pair< char, int > >; %template(ChannelVector) vector< avtranscoder::Channel >; } From f56b7d10dfb72fa81f43cf12882dd236563a3c9d Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Tue, 3 May 2016 17:00:03 +0200 Subject: [PATCH 16/27] pyTest: updated testInputFileAnalyseFirstGop --- test/pyTest/testInputFile.py | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/test/pyTest/testInputFile.py b/test/pyTest/testInputFile.py index 237ce06d..3fdadc60 100644 --- a/test/pyTest/testInputFile.py +++ b/test/pyTest/testInputFile.py @@ -42,3 +42,8 @@ def testInputFileAnalyseFirstGop(): videoProperties = inputFile.getProperties().getVideoProperties()[0] assert_greater(videoProperties.getGopSize(), 0) assert_not_equals(videoProperties.getGopStructure(), ()) + for image in videoProperties.getGopStructure(): + pictureType = image[0] + encodedPictureSize = image[1] + assert_in(pictureType, ['I', 'P', 'B']) + assert_greater(encodedPictureSize, 0) From 4df7cc4ef80eaf0c39519819cc88f24cdc0d5bbf Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 9 May 2016 18:28:21 +0200 Subject: [PATCH 17/27] VideoProperties: removed check of profile when getProfileName This check is already done by av_get_profile_name method. --- src/AvTranscoder/properties/VideoProperties.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 063895d3..1f1df415 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -46,9 +46,6 @@ std::string VideoProperties::getProfileName() const if(_codec->capabilities & CODEC_CAP_TRUNCATED) _codecContext->flags |= CODEC_FLAG_TRUNCATED; - if(_codecContext->profile == -99) - throw std::runtime_error("unknown codec profile"); - const char* profile = NULL; if((profile = av_get_profile_name(_codec, getProfile())) == NULL) throw std::runtime_error("unknown codec profile"); From 378814d56cc8bceb260f8fd03ff65edb70e94761 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Mon, 9 May 2016 18:29:39 +0200 Subject: [PATCH 18/27] VideoProperties: used attribute instead of parameter in constructor To improve readability. --- src/AvTranscoder/properties/VideoProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index 1f1df415..dbf8c99b 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -34,7 +34,7 @@ VideoProperties::VideoProperties(const FormatContext& formatContext, const size_ _firstGopTimeCode = _codecContext->timecode_frame_start; } - if(level == eAnalyseLevelFirstGop) + if(_levelAnalysis == eAnalyseLevelFirstGop) analyseGopStructure(progress); } From bad195b40ef6460754cc067214ac4a22ad5f347f Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Wed, 11 May 2016 10:27:48 +0200 Subject: [PATCH 19/27] PixelProperties: fixed colorComponents value if not found All properties have the same value if not found. --- src/AvTranscoder/properties/PixelProperties.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/properties/PixelProperties.cpp b/src/AvTranscoder/properties/PixelProperties.cpp index 2f104421..bef52cd4 100644 --- a/src/AvTranscoder/properties/PixelProperties.cpp +++ b/src/AvTranscoder/properties/PixelProperties.cpp @@ -274,7 +274,7 @@ PropertyVector& PixelProperties::fillVector(PropertyVector& data) const } catch(const std::exception& e) { - detail::add(data, "colorComponents", e.what()); + detail::add(data, "colorComponents", detail::propertyValueIfError); } try From 8cb866a12e5baba8749e6ffea8d9154bab5c91f5 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 12 May 2016 14:32:01 +0200 Subject: [PATCH 20/27] VideoProperties: fixed value of properties available when decode first gop All properties have the same value if not found. --- .../properties/VideoProperties.cpp | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/src/AvTranscoder/properties/VideoProperties.cpp b/src/AvTranscoder/properties/VideoProperties.cpp index dbf8c99b..e2e56c1e 100644 --- a/src/AvTranscoder/properties/VideoProperties.cpp +++ b/src/AvTranscoder/properties/VideoProperties.cpp @@ -553,8 +553,6 @@ PropertyVector& VideoProperties::fillVector(PropertyVector& data) const addProperty(data, "colorRange", &VideoProperties::getColorRange); addProperty(data, "colorPrimaries", &VideoProperties::getColorPrimaries); addProperty(data, "chromaSampleLocation", &VideoProperties::getChromaSampleLocation); - addProperty(data, "interlaced ", &VideoProperties::isInterlaced); - addProperty(data, "topFieldFirst", &VideoProperties::isTopFieldFirst); addProperty(data, "fieldOrder", &VideoProperties::getFieldOrder); addProperty(data, "fps", &VideoProperties::getFps); addProperty(data, "nbFrame", &VideoProperties::getNbFrames); @@ -562,22 +560,36 @@ PropertyVector& VideoProperties::fillVector(PropertyVector& data) const addProperty(data, "bitRate", &VideoProperties::getBitRate); addProperty(data, "maxBitRate", &VideoProperties::getMaxBitRate); addProperty(data, "minBitRate", &VideoProperties::getMinBitRate); - addProperty(data, "gopSize", &VideoProperties::getGopSize); + addProperty(data, "hasBFrames", &VideoProperties::hasBFrames); + addProperty(data, "referencesFrames", &VideoProperties::getReferencesFrames); - std::stringstream gop; - for(size_t frameIndex = 0; frameIndex < _gopStructure.size(); ++frameIndex) + // Add properties available when decode first gop + if(_levelAnalysis < eAnalyseLevelFirstGop) { - gop << _gopStructure.at(frameIndex).first; - gop << "("; - gop << _gopStructure.at(frameIndex).second;; - gop << ")"; - gop << " "; + detail::add(data, "gopSize", detail::propertyValueIfError); + detail::add(data, "gop", detail::propertyValueIfError); + detail::add(data, "interlaced", detail::propertyValueIfError); + detail::add(data, "topFieldFirst", detail::propertyValueIfError); } - detail::add(data, "gop", gop.str()); - // detail::add( data, "isClosedGop", isClosedGop() ); + else + { + addProperty(data, "gopSize", &VideoProperties::getGopSize); - addProperty(data, "hasBFrames", &VideoProperties::hasBFrames); - addProperty(data, "referencesFrames", &VideoProperties::getReferencesFrames); + std::stringstream gop; + for(size_t frameIndex = 0; frameIndex < _gopStructure.size(); ++frameIndex) + { + gop << _gopStructure.at(frameIndex).first; + gop << "("; + gop << _gopStructure.at(frameIndex).second;; + gop << ")"; + gop << " "; + } + detail::add(data, "gop", gop.str()); + // detail::add( data, "isClosedGop", isClosedGop() ); + + addProperty(data, "interlaced ", &VideoProperties::isInterlaced); + addProperty(data, "topFieldFirst", &VideoProperties::isTopFieldFirst); + } // Add properties of the pixel PropertyVector pixelProperties; From 36a4f1acc312b35c24f5588ed7fe1ea42f264aef Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 12 May 2016 16:20:43 +0200 Subject: [PATCH 21/27] FileProperties: added seek before and after extractStreamProperties Revert of commit 5625a8781bbeb4f1f5e30a0d291af149d0514e11 --- src/AvTranscoder/properties/FileProperties.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index 2fb5ff40..c1106132 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -31,6 +31,10 @@ void FileProperties::extractStreamProperties(IProgress& progress, const EAnalyse { clearStreamProperties(); + // Seek at first key frame before the analysis + if(level > eAnalyseLevelHeader) + const_cast(_formatContext)->seek(0, AVSEEK_FLAG_BACKWARD); + for(size_t streamIndex = 0; streamIndex < _formatContext->getNbStreams(); ++streamIndex) { switch(_formatContext->getAVStream(streamIndex).codec->codec_type) @@ -114,6 +118,10 @@ void FileProperties::extractStreamProperties(IProgress& progress, const EAnalyse const size_t unknownStreamIndex = _unknownStreams.at(streamIndex).getStreamIndex(); _streams[unknownStreamIndex] = &_unknownStreams.at(streamIndex); } + + // Seek at first key frame after the analysis + if(level > eAnalyseLevelHeader) + const_cast(_formatContext)->seek(0, AVSEEK_FLAG_BACKWARD); } std::string FileProperties::getFilename() const From 258d7ff0c4f0374b1d91d6e34cb90c7b7ebb15db Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 12 May 2016 16:21:56 +0200 Subject: [PATCH 22/27] FileProperties: added mimeType to the list of properties when fillVector --- src/AvTranscoder/properties/FileProperties.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index c1106132..9e16cada 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -235,6 +235,7 @@ PropertyVector& FileProperties::fillVector(PropertyVector& data) const addProperty(data, "filename", &FileProperties::getFilename); addProperty(data, "formatName", &FileProperties::getFormatName); addProperty(data, "formatLongName", &FileProperties::getFormatLongName); + addProperty(data, "mimeType", &FileProperties::getFormatMimeType); addProperty(data, "startTime", &FileProperties::getStartTime); addProperty(data, "duration", &FileProperties::getDuration); From 17dca5ee9dd1bbff109eefb9b8f1cb7c80e76a9d Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 12 May 2016 16:25:26 +0200 Subject: [PATCH 23/27] FileProperties: throw runtime error if mime type is not found Like other getter to properties. --- src/AvTranscoder/properties/FileProperties.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/AvTranscoder/properties/FileProperties.cpp b/src/AvTranscoder/properties/FileProperties.cpp index 9e16cada..7cf4469c 100644 --- a/src/AvTranscoder/properties/FileProperties.cpp +++ b/src/AvTranscoder/properties/FileProperties.cpp @@ -148,15 +148,10 @@ std::string FileProperties::getFormatLongName() const std::string FileProperties::getFormatMimeType() const { #if LIBAVFORMAT_VERSION_MAJOR <= 55 - LOG_WARN("Cannot get mime type format of '" << getFilename() - << "' because your libavformat library has a major version <= 55.") - return "not available"; + throw std::runtime_error("cannot get mime type format: libavformat library has a major version <= 55."); #else if(_avFormatContext->iformat->mime_type == NULL) - { - LOG_WARN("Unknown demuxer format mime type of '" << getFilename() << "'.") - return ""; - } + throw std::runtime_error("Unknown demuxer format mime type"); return std::string(_avFormatContext->iformat->mime_type); #endif } From daee1cff2a7d822c02ff05515fed0dc2c3c25ea2 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Thu, 12 May 2016 16:27:15 +0200 Subject: [PATCH 24/27] FormatContext: no seek is done if the format is a raw bitstreams --- src/AvTranscoder/file/FormatContext.cpp | 10 ++++++++++ src/AvTranscoder/file/FormatContext.hpp | 1 + 2 files changed, 11 insertions(+) diff --git a/src/AvTranscoder/file/FormatContext.cpp b/src/AvTranscoder/file/FormatContext.cpp index cab0b3d7..fa0506cd 100644 --- a/src/AvTranscoder/file/FormatContext.cpp +++ b/src/AvTranscoder/file/FormatContext.cpp @@ -144,6 +144,16 @@ AVStream& FormatContext::addAVStream(const AVCodec& avCodec) bool FormatContext::seek(const uint64_t position, const int flag) { + // Check if the format is a raw bitstreams, without any container. + // In this case, avoid seeking. + const std::string formatLongName(_avFormatContext->iformat->long_name); + const std::size_t rawIndex = formatLongName.find("raw"); + if(rawIndex != std::string::npos) + { + LOG_WARN("Seek in '" << _avFormatContext->filename << "' is not possible since this is a raw bitstreams without access to timing information.") + return false; + } + LOG_INFO("Seek in '" << _avFormatContext->filename << "' at " << position << " with flag '"<< flag << "'") const int err = av_seek_frame(_avFormatContext, -1, position, flag); if(err < 0) diff --git a/src/AvTranscoder/file/FormatContext.hpp b/src/AvTranscoder/file/FormatContext.hpp index 2e885f32..dd73e527 100644 --- a/src/AvTranscoder/file/FormatContext.hpp +++ b/src/AvTranscoder/file/FormatContext.hpp @@ -78,6 +78,7 @@ class AvExport FormatContext * @param position: can be in AV_TIME_BASE units, in frames... depending on the flag value * @param flag: seeking mode (AVSEEK_FLAG_xxx) * @return seek status + * @warn No seek is done if the format is a raw bitstreams * @see flushDecoder */ bool seek(const uint64_t position, const int flag); From 79fab625c584f28497ec472cc9b3fd6cb6411f02 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 13 May 2016 10:16:38 +0200 Subject: [PATCH 25/27] FormatContext: fixed seek method if format long name is unknown Avoid RuntimeError: basic_string::_S_construct null not valid. --- src/AvTranscoder/file/FormatContext.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/AvTranscoder/file/FormatContext.cpp b/src/AvTranscoder/file/FormatContext.cpp index fa0506cd..44a7c0ca 100644 --- a/src/AvTranscoder/file/FormatContext.cpp +++ b/src/AvTranscoder/file/FormatContext.cpp @@ -146,7 +146,7 @@ bool FormatContext::seek(const uint64_t position, const int flag) { // Check if the format is a raw bitstreams, without any container. // In this case, avoid seeking. - const std::string formatLongName(_avFormatContext->iformat->long_name); + const std::string formatLongName(_avFormatContext->iformat->long_name ? _avFormatContext->iformat->long_name : ""); const std::size_t rawIndex = formatLongName.find("raw"); if(rawIndex != std::string::npos) { From a5ef6a108e164bf4bae46b225cfa6714e293544f Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 13 May 2016 10:22:20 +0200 Subject: [PATCH 26/27] pyTest: fixed dnx transcode tests Need to analyse first GOP to compute bitrate and get gop size of output. --- test/pyTest/testTranscoderTranscodeVideo.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/test/pyTest/testTranscoderTranscodeVideo.py b/test/pyTest/testTranscoderTranscodeVideo.py index 9bdcfb63..5a6b166f 100644 --- a/test/pyTest/testTranscoderTranscodeVideo.py +++ b/test/pyTest/testTranscoderTranscodeVideo.py @@ -35,6 +35,7 @@ def testTranscodeDnxhd120(): # get dst file of transcode dst_inputFile = av.InputFile( outputFileName ) + dst_inputFile.analyse(progress, av.eAnalyseLevelFirstGop) dst_properties = dst_inputFile.getProperties() dst_videoStream = dst_properties.getVideoProperties()[0] @@ -43,7 +44,7 @@ def testTranscodeDnxhd120(): deltaBitRate = expectedBitRate * 0.05 assert_almost_equals( expectedBitRate, dst_videoStream.getBitRate(), delta=deltaBitRate ) assert_equals( "yuv422p", dst_videoStream.getPixelProperties().getPixelName() ) - # assert_equals( 1, dst_videoStream.getGopSize() ) # 1 != 12L + assert_equals( 1, dst_videoStream.getGopSize() ) def testTranscodeDnxhd185(): """ @@ -70,6 +71,7 @@ def testTranscodeDnxhd185(): # get dst file of transcode dst_inputFile = av.InputFile( outputFileName ) + dst_inputFile.analyse(progress, av.eAnalyseLevelFirstGop) dst_properties = dst_inputFile.getProperties() dst_videoStream = dst_properties.getVideoProperties()[0] @@ -78,7 +80,7 @@ def testTranscodeDnxhd185(): deltaBitRate = expectedBitRate * 0.05 assert_almost_equals( expectedBitRate, dst_videoStream.getBitRate(), delta=deltaBitRate ) assert_equals( "yuv422p", dst_videoStream.getPixelProperties().getPixelName() ) - # assert_equals( 1, dst_videoStream.getGopSize() ) # 1 != 12L + assert_equals( 1, dst_videoStream.getGopSize() ) def testTranscodeDnxhd185x(): """ @@ -105,6 +107,7 @@ def testTranscodeDnxhd185x(): # get dst file of transcode dst_inputFile = av.InputFile( outputFileName ) + dst_inputFile.analyse(progress, av.eAnalyseLevelFirstGop) dst_properties = dst_inputFile.getProperties() dst_videoStream = dst_properties.getVideoProperties()[0] @@ -113,7 +116,7 @@ def testTranscodeDnxhd185x(): deltaBitRate = expectedBitRate * 0.05 assert_almost_equals( expectedBitRate, dst_videoStream.getBitRate(), delta=deltaBitRate ) assert_equals( "yuv422p10le", dst_videoStream.getPixelProperties().getPixelName() ) - # assert_equals( 1, dst_videoStream.getGopSize() ) # 1 != 12L + assert_equals( 1, dst_videoStream.getGopSize() ) def testTranscodeYUV420(): """ From c7db438bdf464d971b2283fab0416aa79f83ab05 Mon Sep 17 00:00:00 2001 From: Clement Champetier Date: Fri, 13 May 2016 10:25:36 +0200 Subject: [PATCH 27/27] pyTest: check width/height when transcode to dnxhd --- test/pyTest/testTranscoderTranscodeVideo.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/test/pyTest/testTranscoderTranscodeVideo.py b/test/pyTest/testTranscoderTranscodeVideo.py index 5a6b166f..8f486f94 100644 --- a/test/pyTest/testTranscoderTranscodeVideo.py +++ b/test/pyTest/testTranscoderTranscodeVideo.py @@ -44,6 +44,8 @@ def testTranscodeDnxhd120(): deltaBitRate = expectedBitRate * 0.05 assert_almost_equals( expectedBitRate, dst_videoStream.getBitRate(), delta=deltaBitRate ) assert_equals( "yuv422p", dst_videoStream.getPixelProperties().getPixelName() ) + assert_equals( 1920, dst_videoStream.getWidth() ) + assert_equals( 1080, dst_videoStream.getHeight() ) assert_equals( 1, dst_videoStream.getGopSize() ) def testTranscodeDnxhd185(): @@ -80,7 +82,9 @@ def testTranscodeDnxhd185(): deltaBitRate = expectedBitRate * 0.05 assert_almost_equals( expectedBitRate, dst_videoStream.getBitRate(), delta=deltaBitRate ) assert_equals( "yuv422p", dst_videoStream.getPixelProperties().getPixelName() ) - assert_equals( 1, dst_videoStream.getGopSize() ) + assert_equals( 1920, dst_videoStream.getWidth() ) + assert_equals( 1080, dst_videoStream.getHeight() ) + assert_equals( 1, dst_videoStream.getGopSize() ) def testTranscodeDnxhd185x(): """ @@ -116,6 +120,8 @@ def testTranscodeDnxhd185x(): deltaBitRate = expectedBitRate * 0.05 assert_almost_equals( expectedBitRate, dst_videoStream.getBitRate(), delta=deltaBitRate ) assert_equals( "yuv422p10le", dst_videoStream.getPixelProperties().getPixelName() ) + assert_equals( 1920, dst_videoStream.getWidth() ) + assert_equals( 1080, dst_videoStream.getHeight() ) assert_equals( 1, dst_videoStream.getGopSize() ) def testTranscodeYUV420():