Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Add analyse level full#291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
valnoel merged 19 commits intoavTranscoder:developfromcchampet:addAnalyseLevelFull
Nov 23, 2016
Merged
Show file tree
Hide file tree
Changes fromall commits
Commits
Show all changes
19 commits
Select commitHold shift + click to select a range
dffb65a
file: add eAnalyseLevelFull level
Nov 2, 2016
525f0aa
VideoProperties: add analyseFull private method which decodes all the…
Nov 2, 2016
8861e17
Merge branch 'develop' of https://github.com/avTranscoder/avTranscode…
Nov 21, 2016
16aafd0
VideoProperties: fix compilation since updates of VideoFrameDesc
Nov 21, 2016
c33fb0f
VideoProperties: analyseGopStructure returns nb decoded frames
Nov 21, 2016
ac763ff
VideoProperties: fix nb decoded frames in analyseFull method
Nov 21, 2016
465af95
VideoProperties: refactor seek to the beginning of the file after ana…
Nov 21, 2016
b112ba8
VideoProperties: add progress callback in analyseFull method
Nov 21, 2016
604d7a8
VideoProperties: update log when estimate bitrate / duration
Nov 21, 2016
eb7442d
VideoProperties: refactor how to return the number of frames
Nov 21, 2016
b6978bc
VideoProperties: in case of full analysis get the exact duration
Nov 21, 2016
b01356f
VideoProperties: add log when no need to decode all the stream in cas…
Nov 21, 2016
b977583
VideoProperties: fix progress of full analysis
Nov 21, 2016
d853c8c
pyTest: add a test to check full analysis of a raw video stream
Nov 21, 2016
7f1077f
avMeta: use eAnalyseLevelFull level
Nov 21, 2016
84fc4bf
VideoProperties: add const to local variables of getNbFrames
Nov 22, 2016
ad44be7
VideoProperties: refactor how to launch deeper analysis
Nov 22, 2016
a61d95f
VideoProperties: refactor how to getDuration
Nov 22, 2016
0f7508f
VideoProperties: refactor how to getNbFrames
Nov 23, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletionsapp/avMeta/avMeta.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
#include <AvTranscoder/file/InputFile.hpp>
#include <AvTranscoder/progress/NoDisplayProgress.hpp>
#include <AvTranscoder/progress/ConsoleProgress.hpp>

#include <iostream>

Expand DownExpand Up@@ -43,8 +43,8 @@ int main(int argc, char** argv)

// analyse inputFile
avtranscoder::InputFile input(argv[1]);
avtranscoder::NoDisplayProgress p;
input.analyse(p, avtranscoder::eAnalyseLevelFirstGop);
avtranscoder::ConsoleProgress p;
input.analyse(p, avtranscoder::eAnalyseLevelFull);

// display file properties
if(toJson)
Expand Down
2 changes: 1 addition & 1 deletionsrc/AvTranscoder/file/util.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -11,7 +11,7 @@ enum EAnalyseLevel
{
eAnalyseLevelHeader =0,
eAnalyseLevelFirstGop =1,
//eAnalyseLevelFull = 2,
eAnalyseLevelFull =2
};
}

Expand Down
130 changes: 96 additions & 34 deletionssrc/AvTranscoder/properties/VideoProperties.cpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -29,6 +29,7 @@ VideoProperties::VideoProperties(const FileProperties& fileProperties, const siz
, _isTopFieldFirst(false)
, _gopSize(0)
, _gopStructure()
, _nbFrames(0)
, _firstGopTimeCode(-1)
{
if(_codecContext)
Expand All@@ -37,8 +38,23 @@ VideoProperties::VideoProperties(const FileProperties& fileProperties, const siz
_firstGopTimeCode = _codecContext->timecode_frame_start;
}

if(_levelAnalysis == eAnalyseLevelFirstGop)
analyseGopStructure(progress);
switch(_levelAnalysis)
{
case eAnalyseLevelFirstGop:
analyseGopStructure(progress);
break;
case eAnalyseLevelFull:
analyseFull(progress);
break;
default:
break;
}

if(_levelAnalysis > eAnalyseLevelHeader)
{
// Returns at the beginning of the stream
const_cast<InputFile&>(_fileProperties->getInputFile()).seekAtFrame(0, AVSEEK_FLAG_BYTE);
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Shouldn't we use a switch statement here? We might have thisconst_cast<InputFile&>(_fileProperties->getInputFile()).seekAtFrame(0, AVSEEK_FLAG_BYTE); line twice, but it could be clearer, don't you think?

Copy link
MemberAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Something like that?ad44be7

}

std::string VideoProperties::getProfileName() const
Expand DownExpand Up@@ -329,11 +345,11 @@ size_t VideoProperties::getBitRate() const
// return bit rate of stream if present or VBR mode
if(_codecContext->bit_rate || _codecContext->rc_max_rate)
return _codecContext->bit_rate;
LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.")

if(_levelAnalysis == eAnalyseLevelHeader)
{
LOG_WARN("The bitrate of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown. "
"Need a deeper analysis: see eAnalyseLevelFirstGop.")
LOG_INFO("Need a deeper analysis: see eAnalyseLevelFirstGop.")
return 0;
}

Expand DownExpand Up@@ -364,21 +380,26 @@ size_t VideoProperties::getNbFrames() const
{
if(!_formatContext)
throw std::runtime_error("unknown format context");
size_t nbFrames = _formatContext->streams[_streamIndex]->nb_frames;
if(nbFrames == 0)

const size_t nbFrames = _formatContext->streams[_streamIndex]->nb_frames;
if(nbFrames)
return nbFrames;
LOG_WARN("The number of frames of the stream '" << _streamIndex << "' of file '" << _formatContext->filename
<< "' is unknown.")

if(_levelAnalysis == eAnalyseLevelHeader)
{
LOG_WARN("The number of frames in the stream '" << _streamIndex << "' of file '" << _formatContext->filename
<< "' is unknown.")
const float duration = getDuration();
if(duration != 0)
{
LOG_INFO("Try to compute the number of frames from the fps and the duration.")
nbFrames = getFps() * duration;
}
else
return 0;
LOG_INFO("Need a deeper analysis: see eAnalyseLevelFirstGop.")
return 0;
}
return nbFrames;

if(! _nbFrames)
{
LOG_INFO("Estimate the number of frames from the fps and the duration.")
return getFps() * getDuration();
}
LOG_INFO("Get the exact number of frames.")
return _nbFrames;
}

size_t VideoProperties::getTicksPerFrame() const
Expand DownExpand Up@@ -445,18 +466,23 @@ float VideoProperties::getDuration() const
const float duration = StreamProperties::getDuration();
if(duration != 0)
return duration;
LOG_WARN("The duration of the stream '" << _streamIndex << "' of file '" << _formatContext->filename << "' is unknown.")

if(_levelAnalysis == eAnalyseLevelHeader)
{
LOG_INFO("Need a deeper analysis: see eAnalyseLevelFirstGop.")
return 0;
}

if(_fileProperties->isRawFormat())
if(! _nbFrames)
{
LOG_INFO("Get thestream bitrate to computetheduration.")
LOG_INFO("Estimate theduration from the file size andthebitrate.")
const size_t bitRate = getBitRate();
if(bitRate)
{
LOG_INFO("Get the file size to compute the duration.")
return _fileProperties->getFileSize() / bitRate * 8;
}
}
return 0;
LOG_INFO("Get the exact duration from the number of frames and the fps.")
return _nbFrames / getFps();
}

bool VideoProperties::hasBFrames() const
Expand DownExpand Up@@ -503,24 +529,24 @@ std::vector<std::pair<char, int> > VideoProperties::getGopStructure() const
return _gopStructure;
}

void VideoProperties::analyseGopStructure(IProgress& progress)
size_t VideoProperties::analyseGopStructure(IProgress& progress)
{
if(! _formatContext || ! _codecContext || ! _codec)
return;
return 0;
if(! _codecContext->width || ! _codecContext->height)
return;
return 0;

InputFile& file = const_cast<InputFile&>(_fileProperties->getInputFile());
// Get the stream
IInputStream& stream = file.getStream(_streamIndex);
stream.activate();
// Create a decoder
VideoDecoder decoder(static_cast<InputStream&>(stream));
VideoFrame frame(VideoFrameDesc(getWidth(), getHeight(), getPixelFormatName(getPixelProperties().getAVPixelFormat())), false);

size_tcount = 0;
size_tnbDecodedFrames = 0;
int positionOfFirstKeyFrame = -1;
int positionOfLastKeyFrame = -1;
VideoFrame frame(VideoFrameDesc(getWidth(), getHeight(), getPixelFormatName(getPixelProperties().getAVPixelFormat())), false);
while(decoder.decodeNextFrame(frame))
{
AVFrame& avFrame = frame.getAVFrame();
Expand All@@ -532,12 +558,12 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
if(avFrame.pict_type == AV_PICTURE_TYPE_I)
{
if(positionOfFirstKeyFrame == -1)
positionOfFirstKeyFrame =count;
positionOfFirstKeyFrame =nbDecodedFrames;
else
positionOfLastKeyFrame =count;
positionOfLastKeyFrame =nbDecodedFrames;
}

_gopSize = ++count;
_gopSize = ++nbDecodedFrames;

// If the first 2 key frames are found
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1)
Expand All@@ -551,14 +577,50 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
}
}

// Returns at the beginning of the stream
file.seekAtFrame(0, AVSEEK_FLAG_BYTE);

// Check GOP size
if(_gopSize <= 0)
{
throw std::runtime_error("Invalid GOP size when decoding the first data.");
}
return nbDecodedFrames;
}

size_t VideoProperties::analyseFull(IProgress& progress)
{
const size_t nbDecodedFrames = analyseGopStructure(progress);

if(! _fileProperties->isRawFormat())
{
LOG_INFO("No need to decode all the stream to get more information.")
return nbDecodedFrames;
}

if(! _formatContext || ! _codecContext || ! _codec)
return 0;
if(! _codecContext->width || ! _codecContext->height)
return 0;

InputFile& file = const_cast<InputFile&>(_fileProperties->getInputFile());
// Get the stream
IInputStream& stream = file.getStream(_streamIndex);
stream.activate();
// Create a decoder
VideoDecoder decoder(static_cast<InputStream&>(stream));
VideoFrame frame(VideoFrameDesc(getWidth(), getHeight(), getPixelFormatName(getPixelProperties().getAVPixelFormat())), false);

const size_t estimateNbFrames = getNbFrames();
_nbFrames = nbDecodedFrames;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Does this have a real sense to set the number of images with the GOP image number?

while(decoder.decodeNextFrame(frame))
{
progress.progress(++_nbFrames, estimateNbFrames);
}

// Check GOP size
if(_nbFrames <= 0)
{
throw std::runtime_error("Invalid number of frames when decoding the video stream.");
}
return _nbFrames;
}

PropertyVector& VideoProperties::fillVector(PropertyVector& data) const
Expand Down
21 changes: 17 additions & 4 deletionssrc/AvTranscoder/properties/VideoProperties.hpp
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -104,10 +104,16 @@ class AvExport VideoProperties : public StreamProperties

private:
/**
* @brief frame type / is key frame
* @param progress: callbacktoget analysis progression
*@param progress: callback to get analysis progression
*@return the number of decoded framestocompute the GOP structure.
*/
void analyseGopStructure(IProgress& progress);
size_t analyseGopStructure(IProgress& progress);

/**
* @param progress: callback to get analysis progression
* @return the number of decoded frames to parse all the file.
*/
size_t analyseFull(IProgress& progress);

#ifndef SWIG
template <typename T>
Expand DownExpand Up@@ -136,13 +142,20 @@ class AvExport VideoProperties : public StreamProperties
PixelProperties _pixelProperties;

//@{
// Can acces these data when analyse first gop
// @brief Can access these data when analysing the first GOP.
// @see eAnalyseLevelFirstGOP
bool _isInterlaced;
bool _isTopFieldFirst;
size_t _gopSize;
std::vector<std::pair<char, int> > _gopStructure; ///< picture type, encoded frame size in bytes
//@}

//@{
// @brief Can access these data when analysing all the stream.
// @see eAnalyseLevelFull
size_t _nbFrames;
//}

/**
* @brief GOP timecode of the first frame
* @note AVCodecContext stores the GOP timecode of the last decoded frame
Expand Down
28 changes: 28 additions & 0 deletionstest/pyTest/testInputFile.py
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -92,3 +92,31 @@ def testInputFileAnalyseFirstGop():
encodedPictureSize = image[1]
assert_in(pictureType, ['I', 'P', 'B'])
assert_greater(encodedPictureSize, 0)
assert_not_equals(videoProperties.getDuration(), 0)
assert_not_equals(videoProperties.getBitRate(), 0)
assert_not_equals(videoProperties.getNbFrames(), 0)


def testInputFileAnalyseFull():
"""
Analyse the full video stream of an InputFile, and check if the correct attributes are filled.
"""
inputFileName = os.environ['AVTRANSCODER_TEST_VIDEO_RAW_FILE']
inputFile = av.InputFile( inputFileName )

# Analyse full stream
progress = av.ConsoleProgress()
inputFile.analyse(progress, av.eAnalyseLevelFull)

# Check properties after full analysis
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)
assert_not_equals(videoProperties.getDuration(), 0)
assert_not_equals(videoProperties.getBitRate(), 0)
assert_not_equals(videoProperties.getNbFrames(), 0)

[8]ページ先頭

©2009-2025 Movatter.jp