1
1
#include " VideoProperties.hpp"
2
2
3
+ #include < AvTranscoder/data/decoded/Frame.hpp>
3
4
#include < AvTranscoder/properties/util.hpp>
4
5
#include < AvTranscoder/progress/NoDisplayProgress.hpp>
5
6
@@ -19,9 +20,11 @@ namespace avtranscoder
19
20
VideoProperties::VideoProperties (const FormatContext& formatContext, const size_t index, IProgress& progress,
20
21
const EAnalyseLevel level)
21
22
: StreamProperties(formatContext, index)
23
+ , _levelAnalysis(level)
22
24
, _pixelProperties()
23
25
, _isInterlaced(false )
24
26
, _isTopFieldFirst(false )
27
+ , _gopSize(0 )
25
28
, _gopStructure()
26
29
, _firstGopTimeCode(-1 )
27
30
{
@@ -31,7 +34,7 @@ VideoProperties::VideoProperties(const FormatContext& formatContext, const size_
31
34
_firstGopTimeCode = _codecContext->timecode_frame_start ;
32
35
}
33
36
34
- if (level == eAnalyseLevelFirstGop)
37
+ if (_levelAnalysis == eAnalyseLevelFirstGop)
35
38
analyseGopStructure (progress);
36
39
}
37
40
@@ -43,11 +46,8 @@ std::string VideoProperties::getProfileName() const
43
46
if (_codec->capabilities & CODEC_CAP_TRUNCATED)
44
47
_codecContext->flags |= CODEC_FLAG_TRUNCATED;
45
48
46
- if (_codecContext->profile == -99 )
47
- throw std::runtime_error (" unknown codec profile" );
48
-
49
49
const char * profile = NULL ;
50
- if ((profile = av_get_profile_name (_codec, _codecContext-> profile )) == NULL )
50
+ if ((profile = av_get_profile_name (_codec, getProfile () )) == NULL )
51
51
throw std::runtime_error (" unknown codec profile" );
52
52
53
53
return std::string (profile);
@@ -333,51 +333,44 @@ size_t VideoProperties::getBitRate() const
333
333
if (!_codecContext->width || !_codecContext->height )
334
334
throw std::runtime_error (" cannot compute bit rate: invalid frame size" );
335
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
+
336
340
// discard no frame type when decode
337
341
_codecContext->skip_frame = AVDISCARD_NONE;
338
342
339
- #if LIBAVCODEC_VERSION_MAJOR > 54
340
- AVFrame* frame = av_frame_alloc ();
341
- #else
342
- AVFrame* frame = avcodec_alloc_frame ();
343
- #endif
343
+ Frame frame;
344
344
AVPacket pkt;
345
345
av_init_packet (&pkt);
346
346
avcodec_open2 (_codecContext, _codec, NULL );
347
347
348
348
int gotFrame = 0 ;
349
- int count = 0 ;
349
+ size_t count = 0 ;
350
350
int gopFramesSize = 0 ;
351
351
352
352
while (!av_read_frame (const_cast <AVFormatContext*>(_formatContext), &pkt))
353
353
{
354
354
if (pkt.stream_index == (int )_streamIndex)
355
355
{
356
- avcodec_decode_video2 (_codecContext, frame, &gotFrame, &pkt);
356
+ avcodec_decode_video2 (_codecContext, & frame. getAVFrame () , &gotFrame, &pkt);
357
357
if (gotFrame)
358
358
{
359
359
#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(54, 7, 100)
360
- gopFramesSize += av_frame_get_pkt_size ( frame);
360
+ gopFramesSize += frame. getEncodedSize ( );
361
361
#else
362
362
gopFramesSize += pkt.size ;
363
363
#endif
364
364
++count;
365
365
}
366
366
}
367
367
av_free_packet (&pkt);
368
- if (_codecContext-> gop_size == count)
368
+ if (getGopSize () == count)
369
369
break ;
370
370
}
371
- #if LIBAVCODEC_VERSION_MAJOR > 54
372
- av_frame_free (&frame);
373
- #elif LIBAVCODEC_VERSION_MAJOR > 53
374
- avcodec_free_frame (&frame);
375
- #else
376
- av_free (frame);
377
- #endif
378
371
379
372
int bitsPerByte = 8 ;
380
- return (gopFramesSize / _codecContext-> gop_size ) * bitsPerByte * getFps ();
373
+ return (gopFramesSize / getGopSize () ) * bitsPerByte * getFps ();
381
374
}
382
375
383
376
size_t VideoProperties::getMaxBitRate () const
@@ -425,13 +418,6 @@ size_t VideoProperties::getHeight() const
425
418
return _codecContext->height ;
426
419
}
427
420
428
- size_t VideoProperties::getGopSize () const
429
- {
430
- if (!_codecContext)
431
- throw std::runtime_error (" unknown codec context" );
432
- return _codecContext->gop_size ;
433
- }
434
-
435
421
size_t VideoProperties::getDtgActiveFormat () const
436
422
{
437
423
if (!_codecContext)
@@ -493,61 +479,55 @@ void VideoProperties::analyseGopStructure(IProgress& progress)
493
479
AVPacket pkt;
494
480
av_init_packet (&pkt);
495
481
496
- // Allocate frame
497
- #if LIBAVCODEC_VERSION_MAJOR > 54
498
- AVFrame* frame = av_frame_alloc ();
499
- #else
500
- AVFrame* frame = avcodec_alloc_frame ();
501
- #endif
502
-
503
482
// Initialize the AVCodecContext to use the given AVCodec
504
483
avcodec_open2 (_codecContext, _codec, NULL );
505
484
506
- int count = 0 ;
485
+ Frame frame;
486
+ size_t count = 0 ;
507
487
int gotFrame = 0 ;
508
- bool stopAnalyse = false ;
488
+ int positionOfFirstKeyFrame = -1 ;
489
+ int positionOfLastKeyFrame = -1 ;
509
490
510
491
while (!av_read_frame (const_cast <AVFormatContext*>(_formatContext), &pkt))
511
492
{
512
493
if (pkt.stream_index == (int )_streamIndex)
513
494
{
514
- avcodec_decode_video2 (_codecContext, frame, &gotFrame, &pkt);
495
+ avcodec_decode_video2 (_codecContext, & frame. getAVFrame () , &gotFrame, &pkt);
515
496
if (gotFrame)
516
497
{
498
+ AVFrame& avFrame = frame.getAVFrame ();
499
+
517
500
_gopStructure.push_back (
518
- std::make_pair (av_get_picture_type_char (frame->pict_type ), frame->key_frame ));
519
- _isInterlaced = frame->interlaced_frame ;
520
- _isTopFieldFirst = frame->top_field_first ;
501
+ std::make_pair (av_get_picture_type_char (avFrame.pict_type ), frame.getEncodedSize ()));
502
+ _isInterlaced = avFrame.interlaced_frame ;
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
+
521
512
++count;
522
- if (progress.progress (count, _codecContext->gop_size ) == eJobStatusCancel)
523
- stopAnalyse = true ;
524
513
}
525
514
}
526
-
527
515
av_free_packet (&pkt);
528
516
529
- if (_codecContext->gop_size == count)
517
+ // If the first 2 key frames are found
518
+ if (positionOfFirstKeyFrame != -1 && positionOfLastKeyFrame != -1 )
530
519
{
531
- stopAnalyse = true ;
532
- }
533
-
534
- 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 ();
535
525
break ;
526
+ }
536
527
}
537
528
538
529
// Close a given AVCodecContext and free all the data associated with it (but not the AVCodecContext itself)
539
530
avcodec_close (_codecContext);
540
-
541
- // Free frame
542
- #if LIBAVCODEC_VERSION_MAJOR > 54
543
- av_frame_free (&frame);
544
- #else
545
- #if LIBAVCODEC_VERSION_MAJOR > 53
546
- avcodec_free_frame (&frame);
547
- #else
548
- av_free (frame);
549
- #endif
550
- #endif
551
531
}
552
532
}
553
533
}
@@ -573,28 +553,43 @@ PropertyVector& VideoProperties::fillVector(PropertyVector& data) const
573
553
addProperty (data, " colorRange" , &VideoProperties::getColorRange);
574
554
addProperty (data, " colorPrimaries" , &VideoProperties::getColorPrimaries);
575
555
addProperty (data, " chromaSampleLocation" , &VideoProperties::getChromaSampleLocation);
576
- addProperty (data, " interlaced " , &VideoProperties::isInterlaced);
577
- addProperty (data, " topFieldFirst" , &VideoProperties::isTopFieldFirst);
578
556
addProperty (data, " fieldOrder" , &VideoProperties::getFieldOrder);
579
557
addProperty (data, " fps" , &VideoProperties::getFps);
580
558
addProperty (data, " nbFrame" , &VideoProperties::getNbFrames);
581
559
addProperty (data, " ticksPerFrame" , &VideoProperties::getTicksPerFrame);
582
560
addProperty (data, " bitRate" , &VideoProperties::getBitRate);
583
561
addProperty (data, " maxBitRate" , &VideoProperties::getMaxBitRate);
584
562
addProperty (data, " minBitRate" , &VideoProperties::getMinBitRate);
585
- addProperty (data, " gopSize" , &VideoProperties::getGopSize);
563
+ addProperty (data, " hasBFrames" , &VideoProperties::hasBFrames);
564
+ addProperty (data, " referencesFrames" , &VideoProperties::getReferencesFrames);
586
565
587
- std::string gop;
588
- for ( size_t frameIndex = 0 ; frameIndex < _gopStructure. size (); ++frameIndex )
566
+ // Add properties available when decode first gop
567
+ if (_levelAnalysis < eAnalyseLevelFirstGop )
589
568
{
590
- gop += _gopStructure.at (frameIndex).first ;
591
- gop += " " ;
569
+ detail::add (data, " gopSize" , detail::propertyValueIfError);
570
+ detail::add (data, " gop" , detail::propertyValueIfError);
571
+ detail::add (data, " interlaced" , detail::propertyValueIfError);
572
+ detail::add (data, " topFieldFirst" , detail::propertyValueIfError);
592
573
}
593
- detail::add (data, " gop" , gop);
594
- // detail::add( data, "isClosedGop", isClosedGop() );
574
+ else
575
+ {
576
+ addProperty (data, " gopSize" , &VideoProperties::getGopSize);
595
577
596
- addProperty (data, " hasBFrames" , &VideoProperties::hasBFrames);
597
- addProperty (data, " referencesFrames" , &VideoProperties::getReferencesFrames);
578
+ std::stringstream gop;
579
+ for (size_t frameIndex = 0 ; frameIndex < _gopStructure.size (); ++frameIndex)
580
+ {
581
+ gop << _gopStructure.at (frameIndex).first ;
582
+ gop << " (" ;
583
+ gop << _gopStructure.at (frameIndex).second ;;
584
+ gop << " )" ;
585
+ gop << " " ;
586
+ }
587
+ detail::add (data, " gop" , gop.str ());
588
+ // detail::add( data, "isClosedGop", isClosedGop() );
589
+
590
+ addProperty (data, " interlaced " , &VideoProperties::isInterlaced);
591
+ addProperty (data, " topFieldFirst" , &VideoProperties::isTopFieldFirst);
592
+ }
598
593
599
594
// Add properties of the pixel
600
595
PropertyVector pixelProperties;
0 commit comments