- Notifications
You must be signed in to change notification settings - Fork50
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
Uh oh!
There was an error while loading.Please reload this page.
Changes fromall commits
dffb65a
525f0aa
8861e17
16aafd0
c33fb0f
ac763ff
465af95
b112ba8
604d7a8
eb7442d
b6978bc
b01356f
b977583
d853c8c
7f1077f
84fc4bf
ad44be7
a61d95f
0f7508f
File filter
Filter by extension
Conversations
Uh oh!
There was an error while loading.Please reload this page.
Jump to
Uh oh!
There was an error while loading.Please reload this page.
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -11,7 +11,7 @@ enum EAnalyseLevel | ||
{ | ||
eAnalyseLevelHeader =0, | ||
eAnalyseLevelFirstGop =1, | ||
eAnalyseLevelFull =2 | ||
}; | ||
} | ||
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -29,6 +29,7 @@ VideoProperties::VideoProperties(const FileProperties& fileProperties, const siz | ||
, _isTopFieldFirst(false) | ||
, _gopSize(0) | ||
, _gopStructure() | ||
, _nbFrames(0) | ||
, _firstGopTimeCode(-1) | ||
{ | ||
if(_codecContext) | ||
@@ -37,8 +38,23 @@ VideoProperties::VideoProperties(const FileProperties& fileProperties, const siz | ||
_firstGopTimeCode = _codecContext->timecode_frame_start; | ||
} | ||
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); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Shouldn't we use a switch statement here? We might have this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others.Learn more. Something like that?ad44be7 | ||
} | ||
std::string VideoProperties::getProfileName() const | ||
@@ -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_INFO("Need a deeper analysis: see eAnalyseLevelFirstGop.") | ||
return 0; | ||
} | ||
@@ -364,21 +380,26 @@ size_t VideoProperties::getNbFrames() const | ||
{ | ||
if(!_formatContext) | ||
throw std::runtime_error("unknown format context"); | ||
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_INFO("Need a deeper analysis: see eAnalyseLevelFirstGop.") | ||
return 0; | ||
} | ||
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 | ||
@@ -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(! _nbFrames) | ||
{ | ||
LOG_INFO("Estimate theduration from the file size andthebitrate.") | ||
const size_t bitRate = getBitRate(); | ||
if(bitRate) | ||
return _fileProperties->getFileSize() / bitRate * 8; | ||
} | ||
LOG_INFO("Get the exact duration from the number of frames and the fps.") | ||
return _nbFrames / getFps(); | ||
} | ||
bool VideoProperties::hasBFrames() const | ||
@@ -503,24 +529,24 @@ std::vector<std::pair<char, int> > VideoProperties::getGopStructure() const | ||
return _gopStructure; | ||
} | ||
size_t VideoProperties::analyseGopStructure(IProgress& progress) | ||
{ | ||
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); | ||
size_tnbDecodedFrames = 0; | ||
int positionOfFirstKeyFrame = -1; | ||
int positionOfLastKeyFrame = -1; | ||
while(decoder.decodeNextFrame(frame)) | ||
{ | ||
AVFrame& avFrame = frame.getAVFrame(); | ||
@@ -532,12 +558,12 @@ void VideoProperties::analyseGopStructure(IProgress& progress) | ||
if(avFrame.pict_type == AV_PICTURE_TYPE_I) | ||
{ | ||
if(positionOfFirstKeyFrame == -1) | ||
positionOfFirstKeyFrame =nbDecodedFrames; | ||
else | ||
positionOfLastKeyFrame =nbDecodedFrames; | ||
} | ||
_gopSize = ++nbDecodedFrames; | ||
// If the first 2 key frames are found | ||
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1) | ||
@@ -551,14 +577,50 @@ void VideoProperties::analyseGopStructure(IProgress& progress) | ||
} | ||
} | ||
// 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; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 | ||