@@ -24,6 +24,7 @@ VideoProperties::VideoProperties(const FormatContext& formatContext, const size_
24
24
, _pixelProperties()
25
25
, _isInterlaced(false )
26
26
, _isTopFieldFirst(false )
27
+ , _gopSize(0 )
27
28
, _gopStructure()
28
29
, _firstGopTimeCode(-1 )
29
30
{
@@ -335,6 +336,10 @@ size_t VideoProperties::getBitRate() const
335
336
if (!_codecContext->width || !_codecContext->height )
336
337
throw std::runtime_error (" cannot compute bit rate: invalid frame size" );
337
338
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
+
338
343
// discard no frame type when decode
339
344
_codecContext->skip_frame = AVDISCARD_NONE;
340
345
@@ -416,13 +421,6 @@ size_t VideoProperties::getHeight() const
416
421
return _codecContext->height ;
417
422
}
418
423
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
-
426
424
size_t VideoProperties::getDtgActiveFormat () const
427
425
{
428
426
if (!_codecContext)
@@ -490,7 +488,8 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
490
488
Frame frame;
491
489
size_t count = 0 ;
492
490
int gotFrame = 0 ;
493
- bool stopAnalyse = false ;
491
+ int positionOfFirstKeyFrame = -1 ;
492
+ int positionOfLastKeyFrame = -1 ;
494
493
495
494
while (!av_read_frame (const_cast <AVFormatContext*>(_formatContext), &pkt))
496
495
{
@@ -500,25 +499,34 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
500
499
if (gotFrame)
501
500
{
502
501
AVFrame& avFrame = frame.getAVFrame ();
502
+
503
503
_gopStructure.push_back (
504
504
std::make_pair (av_get_picture_type_char (avFrame.pict_type ), avFrame.key_frame ));
505
505
_isInterlaced = avFrame.interlaced_frame ;
506
506
_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
+
507
515
++count;
508
- if (progress.progress (count, getGopSize ()) == eJobStatusCancel)
509
- stopAnalyse = true ;
510
516
}
511
517
}
512
-
513
518
av_free_packet (&pkt);
514
519
515
- if (getGopSize () == count)
520
+ // If the first 2 key frames are found
521
+ if (positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1 )
516
522
{
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 ();
521
528
break ;
529
+ }
522
530
}
523
531
524
532
// Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself)
0 commit comments