Skip to content

Commit 7d7f788

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 1dffc17 commit 7d7f788

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
{
@@ -335,6 +336,10 @@ size_t VideoProperties::getBitRate() const
335336
if(!_codecContext->width || !_codecContext->height)
336337
throw std::runtime_error("cannot compute bit rate: invalid frame size");
337338

339+
// Needed to get the gop size
340+
if(_levelAnalysis < eAnalyseLevelFirstGop)
341+
throw std::runtime_error("cannot compute bit rate: need to get info from the first gop (see eAnalyseLevelFirstGop)");
342+
338343
// discard no frame type when decode
339344
_codecContext->skip_frame = AVDISCARD_NONE;
340345

@@ -416,13 +421,6 @@ size_t VideoProperties::getHeight() const
416421
return _codecContext->height;
417422
}
418423

419-
size_t VideoProperties::getGopSize() const
420-
{
421-
if(!_codecContext)
422-
throw std::runtime_error("unknown codec context");
423-
return _codecContext->gop_size;
424-
}
425-
426424
size_t VideoProperties::getDtgActiveFormat() const
427425
{
428426
if(!_codecContext)
@@ -490,7 +488,8 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
490488
Frame frame;
491489
size_t count = 0;
492490
int gotFrame = 0;
493-
bool stopAnalyse = false;
491+
int positionOfFirstKeyFrame = -1;
492+
int positionOfLastKeyFrame = -1;
494493

495494
while(!av_read_frame(const_cast<AVFormatContext*>(_formatContext), &pkt))
496495
{
@@ -500,25 +499,34 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
500499
if(gotFrame)
501500
{
502501
AVFrame& avFrame = frame.getAVFrame();
502+
503503
_gopStructure.push_back(
504504
std::make_pair(av_get_picture_type_char(avFrame.pict_type), avFrame.key_frame));
505505
_isInterlaced = avFrame.interlaced_frame;
506506
_isTopFieldFirst = avFrame.top_field_first;
507+
if(avFrame.pict_type == AV_PICTURE_TYPE_I)
508+
{
509+
if(positionOfFirstKeyFrame == -1)
510+
positionOfFirstKeyFrame = count;
511+
else
512+
positionOfLastKeyFrame = count;
513+
}
514+
507515
++count;
508-
if(progress.progress(count, getGopSize()) == eJobStatusCancel)
509-
stopAnalyse = true;
510516
}
511517
}
512-
513518
av_free_packet(&pkt);
514519

515-
if(getGopSize() == count)
520+
// If the first 2 key frames are found
521+
if(positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1)
516522
{
517-
stopAnalyse = true;
518-
}
519-
520-
if(stopAnalyse)
523+
// Set gop size as distance between these 2 key frames
524+
_gopSize = positionOfLastKeyFrame - positionOfFirstKeyFrame;
525+
// Update gop structure to keep only one gop
526+
while(_gopStructure.size() > _gopSize)
527+
_gopStructure.pop_back();
521528
break;
529+
}
522530
}
523531

524532
// 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)