Skip to content

Commit a86ec98

Browse files
author
Clement Champetier
committed
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.
1 parent 65712aa commit a86ec98

File tree

2 files changed

+29
-23
lines changed

2 files changed

+29
-23
lines changed

src/AvTranscoder/properties/VideoProperties.cpp

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ VideoProperties::VideoProperties(const FormatContext& formatContext, const size_
2424
, _pixelProperties()
2525
, _isInterlaced(false)
2626
, _isTopFieldFirst(false)
27+
, _gopSize(0)
2728
, _gopStructure()
2829
, _firstGopTimeCode(-1)
2930
{
@@ -332,6 +333,10 @@ size_t VideoProperties::getBitRate() const
332333
if(!_codecContext->width || !_codecContext->height)
333334
throw std::runtime_error("cannot compute bit rate: invalid frame size");
334335

336+
// Needed to get the gop size
337+
if(_levelAnalysis < eAnalyseLevelFirstGop)
338+
throw std::runtime_error("cannot compute bit rate: need to get info from the first gop (see eAnalyseLevelFirstGop)");
339+
335340
// discard no frame type when decode
336341
_codecContext->skip_frame = AVDISCARD_NONE;
337342

@@ -413,13 +418,6 @@ size_t VideoProperties::getHeight() const
413418
return _codecContext->height;
414419
}
415420

416-
size_t VideoProperties::getGopSize() const
417-
{
418-
if(!_codecContext)
419-
throw std::runtime_error("unknown codec context");
420-
return _codecContext->gop_size;
421-
}
422-
423421
size_t VideoProperties::getDtgActiveFormat() const
424422
{
425423
if(!_codecContext)
@@ -487,7 +485,8 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
487485
Frame frame;
488486
size_t count = 0;
489487
int gotFrame = 0;
490-
bool stopAnalyse = false;
488+
int positionOfFirstKeyFrame = -1;
489+
int positionOfLastKeyFrame = -1;
491490

492491
while(!av_read_frame(const_cast<AVFormatContext*>(_formatContext), &pkt))
493492
{
@@ -497,25 +496,34 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
497496
if(gotFrame)
498497
{
499498
AVFrame& avFrame = frame.getAVFrame();
499+
500500
_gopStructure.push_back(
501501
std::make_pair(av_get_picture_type_char(avFrame.pict_type), avFrame.key_frame));
502502
_isInterlaced = avFrame.interlaced_frame;
503503
_isTopFieldFirst = avFrame.top_field_first;
504+
if(avFrame.pict_type == AV_PICTURE_TYPE_I)
505+
{
506+
if(positionOfFirstKeyFrame == -1)
507+
positionOfFirstKeyFrame = count;
508+
else
509+
positionOfLastKeyFrame = count;
510+
}
511+
504512
++count;
505-
if(progress.progress(count, getGopSize()) == eJobStatusCancel)
506-
stopAnalyse = true;
507513
}
508514
}
509-
510515
av_free_packet(&pkt);
511516

512-
if(getGopSize() == count)
517+
// If the first 2 key frames are found
518+
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1)
513519
{
514-
stopAnalyse = true;
515-
}
516-
517-
if(stopAnalyse)
520+
// Set gop size as distance between these 2 key frames
521+
_gopSize = positionOfLastKeyFrame - positionOfFirstKeyFrame;
522+
// Update gop structure to keep only one gop
523+
while(_gopStructure.size() > _gopSize)
524+
_gopStructure.pop_back();
518525
break;
526+
}
519527
}
520528

521529
// Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself)

src/AvTranscoder/properties/VideoProperties.hpp

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -47,13 +47,6 @@ class AvExport VideoProperties : public StreamProperties
4747
size_t getTicksPerFrame() const;
4848
size_t getWidth() const;
4949
size_t getHeight() const;
50-
51-
/**
52-
* @return the distance between two nearest I frame
53-
* @note it returns 0 for intra_only
54-
*/
55-
size_t getGopSize() const;
56-
5750
size_t getDtgActiveFormat() const;
5851
size_t getReferencesFrames() const;
5952
int getProfile() const;
@@ -77,6 +70,10 @@ class AvExport VideoProperties : public StreamProperties
7770
// @see analyseGopStructure
7871
bool isInterlaced() const { return _isInterlaced; }
7972
bool isTopFieldFirst() const { return _isTopFieldFirst; }
73+
/**
74+
* @return the distance between two nearest I frame
75+
*/
76+
size_t getGopSize() const { return _gopSize; }
8077
std::vector<std::pair<char, bool> > getGopStructure() const { return _gopStructure; }
8178
//@}
8279

@@ -120,6 +117,7 @@ class AvExport VideoProperties : public StreamProperties
120117
// Can acces these data when analyse first gop
121118
bool _isInterlaced;
122119
bool _isTopFieldFirst;
120+
size_t _gopSize;
123121
std::vector<std::pair<char, bool> > _gopStructure;
124122
//@}
125123

0 commit comments

Comments
 (0)