74
74
#define TO_VAAPI_DEVICE_CTX (x ) ((AVVAAPIDeviceContext*)TO_AVHW_DEVICE_CTX(x)->hwctx)
75
75
#define TO_VAAPI_FRAMES_CTX (x ) ((AVVAAPIFramesContext*)TO_AVHW_FRAMES_CTX(x)->hwctx)
76
76
77
+ // PTS Filter-Elements of 1, 2, 4, 8, 16, ..
78
+ #define LP_FILTER_CNT 2
79
+
77
80
//----------------------------------------------------------------------------
78
81
// Declarations
79
82
//----------------------------------------------------------------------------
@@ -830,7 +833,11 @@ struct _vaapi_decoder_
830
833
int SyncOnAudio ; ///< flag sync to audio
831
834
int64_t PTS ; ///< video PTS clock
832
835
833
- int LastAVDiff ; ///< last audio - video difference
836
+ int64_t AvPtsDiffFilter ; ///< AV-PTS-Diff Delay element – 64 bits
837
+ int AvPtsDiffFilterInit ; ///< Filter Init Done
838
+ int64_t LastVideoPTS ; ///< Video-PTS Rollover Test
839
+ int64_t LastAudioPTS ; ///< Audio-PTS Rollover Test
840
+
834
841
int SyncCounter ; ///< counter to sync frames
835
842
int StartCounter ; ///< counter for video start
836
843
int FramesDuped ; ///< number of frames duplicated
@@ -1343,6 +1350,13 @@ static VaapiDecoder *VaapiNewHwDecoder(VideoStream * stream)
1343
1350
1344
1351
decoder -> GetPutImage = 1 ;
1345
1352
1353
+ decoder -> AvPtsDiffFilterInit = 1 ;
1354
+ decoder -> AvPtsDiffFilter = 0 ;
1355
+ decoder -> LastVideoPTS = 0 ;
1356
+ decoder -> LastAudioPTS = 0 ;
1357
+ decoder -> SyncCounter = 0 ;
1358
+ decoder -> StartCounter = 0 ;
1359
+
1346
1360
VaapiDecoders [VaapiDecoderN ++ ] = decoder ;
1347
1361
1348
1362
return decoder ;
@@ -3603,7 +3617,8 @@ char *VaapiGetStats(VaapiDecoder * decoder)
3603
3617
if (snprintf (& buffer [0 ], sizeof (buffer ),
3604
3618
" Frames: missed(%d) duped(%d) dropped(%d) total(%d) PTS(%s) drift(%" PRId64 ") audio(%" PRId64 ") video(%"
3605
3619
PRId64 ")" , decoder -> FramesMissed , decoder -> FramesDuped , decoder -> FramesDropped , decoder -> FrameCounter ,
3606
- Timestamp2String (video_clock ), (video_clock - audio_clock ) / 90 , AudioGetDelay () / 90 , VideoDeltaPTS / 90 )) {
3620
+ Timestamp2String (video_clock ), (video_clock - audio_clock ) / 90 , AudioGetDelay () / 90 ,
3621
+ VideoDeltaPTS / 90 )) {
3607
3622
return strdup (buffer );
3608
3623
}
3609
3624
@@ -3654,6 +3669,11 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
3654
3669
int filled ;
3655
3670
int64_t audio_clock ;
3656
3671
int64_t video_clock ;
3672
+ int64_t diff ;
3673
+
3674
+ if (decoder == NULL ) {
3675
+ return ;
3676
+ }
3657
3677
3658
3678
err = 0 ;
3659
3679
mutex_start_time = GetMsTicks ();
@@ -3675,7 +3695,7 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
3675
3695
goto out ;
3676
3696
}
3677
3697
// both clocks are known
3678
- if (audio_clock + VideoAudioDelay <= video_clock + 25 * 90 ) {
3698
+ if (audio_clock + ( int64_t ) VideoAudioDelay <= video_clock + ( int64_t ) 25 * 90 ) {
3679
3699
goto out ;
3680
3700
}
3681
3701
// out of sync: audio before video
@@ -3705,35 +3725,48 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
3705
3725
3706
3726
if (audio_clock != (int64_t ) AV_NOPTS_VALUE && video_clock != (int64_t ) AV_NOPTS_VALUE ) {
3707
3727
// both clocks are known
3708
- int diff ;
3709
- int lower_limit ;
3710
-
3711
- diff = video_clock - audio_clock - VideoAudioDelay ;
3712
- lower_limit = !IsReplay ()? -25 : 32 ;
3713
- if (!IsReplay ()) {
3714
- diff = (decoder -> LastAVDiff + diff ) / 2 ;
3715
- decoder -> LastAVDiff = diff ;
3728
+ // FIXME: "diff" doesn't checks frametype (i - Top/Bottom, p - Full)
3729
+ diff = video_clock - audio_clock - (int64_t ) VideoAudioDelay ;
3730
+
3731
+ // AV-Diff greater than 1:00:00.000 should be a PTS-Rollover,
3732
+ // but observable is: audio_clock jumps to negative values...
3733
+ if ((audio_clock < 0 ) || (video_clock < 0 ) || (abs (diff ) > (int64_t ) 60 * 60 * 90000 )) {
3734
+ // Set Bit 34 of video_clock if below 1:00:00.000
3735
+ if (video_clock < (int64_t ) 60 * 60 * 90000 )
3736
+ video_clock = video_clock + (int64_t ) 0x200000000 ;
3737
+ // Set Bit 34 of audio_clock if below 1:00:00.000
3738
+ if (audio_clock < (int64_t ) 60 * 60 * 90000 )
3739
+ audio_clock = audio_clock + (int64_t ) 0x200000000 ;
3740
+
3741
+ // Calc correct diff
3742
+ err = VaapiMessage (1 , "AV-PTS Rollover, correcting AV-PTS Difference" );
3743
+ diff = (video_clock - audio_clock - (int64_t ) VideoAudioDelay );
3744
+ }
3745
+ // Low-Pass Filter AV-PTS-Diff, if in Sync-Range of +/- 250 ms
3746
+ if (abs (diff ) < (int64_t ) 250 * 90 ) {
3747
+ // Filter-Init done?
3748
+ if (decoder -> AvPtsDiffFilterInit ) {
3749
+ // No.
3750
+ decoder -> AvPtsDiffFilterInit = 0 ;
3751
+ decoder -> AvPtsDiffFilter = diff * LP_FILTER_CNT ;
3752
+ }
3753
+ decoder -> AvPtsDiffFilter = decoder -> AvPtsDiffFilter - (decoder -> AvPtsDiffFilter / LP_FILTER_CNT ) + diff ;
3754
+ diff = decoder -> AvPtsDiffFilter / LP_FILTER_CNT ;
3716
3755
}
3717
3756
3718
- if (abs (diff ) > 5000 * 90 ) { // more than 5s
3757
+ if (abs (diff ) > ( int64_t ) 5000 * 90 ) { // more than 5s
3719
3758
err = VaapiMessage (2 , "video: audio/video difference too big" );
3720
- } else if (diff > 100 * 90 ) {
3721
- // FIXME: this quicker sync step, did not work with new code!
3722
- err = VaapiMessage (2 , "video: slow down video, duping frame" );
3723
- ++ decoder -> FramesDuped ;
3724
- if (VideoSoftStartSync ) {
3725
- decoder -> SyncCounter = 1 ;
3726
- goto out ;
3727
- }
3728
- } else if (diff > 55 * 90 ) {
3729
- err = VaapiMessage (2 , "video: slow down video, duping frame" );
3759
+ } else if (diff > (int64_t ) 40 * 90 ) {
3760
+ Debug ("video: slow down video, duping frame (/\\=%.2f ms, vClk %s - aClk %s)" , diff * 1000 / (double )90000 ,
3761
+ Timestamp2String (video_clock ), Timestamp2String (audio_clock ));
3730
3762
++ decoder -> FramesDuped ;
3731
3763
if (VideoSoftStartSync ) {
3732
3764
decoder -> SyncCounter = 1 ;
3733
3765
goto out ;
3734
3766
}
3735
- } else if (diff < lower_limit * 90 && filled > 1 + 2 * decoder -> Interlaced ) {
3736
- err = VaapiMessage (2 , "video: speed up video, droping frame" );
3767
+ } else if ((diff < (int64_t ) - 20 * 90 ) && (filled > 1 + 2 * decoder -> Interlaced )) {
3768
+ Debug ("video: speed up video, droping frame (/\\=%.2f ms, vClk %s - aClk %s)" , diff * 1000 / (double )90000 ,
3769
+ Timestamp2String (video_clock ), Timestamp2String (audio_clock ));
3737
3770
++ decoder -> FramesDropped ;
3738
3771
VaapiAdvanceDecoderFrame (decoder );
3739
3772
if (VideoSoftStartSync ) {
@@ -3780,9 +3813,9 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
3780
3813
}
3781
3814
Info ("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d%+d v-buf" , Timestamp2String (video_clock ),
3782
3815
(video_clock - audio_clock ) / 90 , AudioGetDelay () / 90 , (int )VideoDeltaPTS / 90 ,
3783
- VideoGetBuffers (decoder -> Stream ), decoder -> Interlaced ?
3784
- (2 * atomic_read (& decoder -> SurfacesFilled ) - decoder -> SurfaceField ) :
3785
- atomic_read (& decoder -> SurfacesFilled ));
3816
+ VideoGetBuffers (decoder -> Stream ),
3817
+ decoder -> Interlaced ? (2 * atomic_read (& decoder -> SurfacesFilled ) -
3818
+ decoder -> SurfaceField ) : atomic_read (& decoder -> SurfacesFilled ));
3786
3819
if (!(decoder -> FramesDisplayed % (5 * 60 * 60 ))) {
3787
3820
VaapiPrintFrames (decoder );
3788
3821
}
0 commit comments