@@ -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
{
@@ -332,6 +333,10 @@ size_t VideoProperties::getBitRate() const
332
333
if (!_codecContext->width || !_codecContext->height )
333
334
throw std::runtime_error (" cannot compute bit rate: invalid frame size" );
334
335
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
+
335
340
// discard no frame type when decode
336
341
_codecContext->skip_frame = AVDISCARD_NONE;
337
342
@@ -413,13 +418,6 @@ size_t VideoProperties::getHeight() const
413
418
return _codecContext->height ;
414
419
}
415
420
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
-
423
421
size_t VideoProperties::getDtgActiveFormat () const
424
422
{
425
423
if (!_codecContext)
@@ -487,7 +485,8 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
487
485
Frame frame;
488
486
size_t count = 0 ;
489
487
int gotFrame = 0 ;
490
- bool stopAnalyse = false ;
488
+ int positionOfFirstKeyFrame = -1 ;
489
+ int positionOfLastKeyFrame = -1 ;
491
490
492
491
while (!av_read_frame (const_cast <AVFormatContext*>(_formatContext), &pkt))
493
492
{
@@ -497,25 +496,34 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
497
496
if (gotFrame)
498
497
{
499
498
AVFrame& avFrame = frame.getAVFrame ();
499
+
500
500
_gopStructure.push_back (
501
501
std::make_pair (av_get_picture_type_char (avFrame.pict_type ), avFrame.key_frame ));
502
502
_isInterlaced = avFrame.interlaced_frame ;
503
503
_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
+
504
512
++count;
505
- if (progress.progress (count, getGopSize ()) == eJobStatusCancel)
506
- stopAnalyse = true ;
507
513
}
508
514
}
509
-
510
515
av_free_packet (&pkt);
511
516
512
- if (getGopSize () == count)
517
+ // If the first 2 key frames are found
518
+ if (positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1 )
513
519
{
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 ();
518
525
break ;
526
+ }
519
527
}
520
528
521
529
// Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself)
0 commit comments