Skip to content

Commit 97e225f

Browse files
committed
Merged a modified Quantomax's speedupdown patch found on #121.
1 parent 6bd46bf commit 97e225f

File tree

6 files changed

+81
-49
lines changed

6 files changed

+81
-49
lines changed

audio.c

+6-6
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,6 @@ static int AlsaPlayRingbuffer(void)
769769
Error("audio/alsa: bytes lost -> out of sync");
770770
}
771771
#endif
772-
773772
for (;;) {
774773
pthread_mutex_lock(&ReadAdvance_mutex);
775774
if (AlsaUseMmap) {
@@ -779,12 +778,13 @@ static int AlsaPlayRingbuffer(void)
779778
}
780779
if (err != frames) {
781780
if (err < 0) {
782-
pthread_mutex_unlock(&ReadAdvance_mutex);
783781
if (err == -EAGAIN) {
782+
pthread_mutex_unlock(&ReadAdvance_mutex);
784783
continue;
785784
}
786785
Error("audio/alsa: writei underrun error? '%s'", snd_strerror(err));
787786
err = snd_pcm_recover(AlsaPCMHandle, err, 0);
787+
pthread_mutex_unlock(&ReadAdvance_mutex);
788788
if (err >= 0) {
789789
return 0;
790790
}
@@ -1361,8 +1361,8 @@ static int AudioNextRing(void)
13611361
if (remain <= AUDIO_MIN_BUFFER_FREE) {
13621362
Debug5("audio: force start");
13631363
}
1364-
if (remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady || !SoftIsPlayingVideo)
1365-
&& AudioStartThreshold < used)) {
1364+
if (AudioStartThreshold * 4 < used || remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady
1365+
|| !SoftIsPlayingVideo) && AudioStartThreshold < used)) {
13661366
return 0;
13671367
}
13681368
return 1;
@@ -1613,8 +1613,8 @@ void AudioEnqueue(const void *samples, int count)
16131613
if (remain <= AUDIO_MIN_BUFFER_FREE) {
16141614
Debug5("audio: force start");
16151615
}
1616-
if (remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady || !SoftIsPlayingVideo)
1617-
&& AudioStartThreshold < n)) {
1616+
if (AudioStartThreshold * 4 < n || remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady
1617+
|| !SoftIsPlayingVideo) && AudioStartThreshold < n)) {
16181618
// restart play-back
16191619
// no lock needed, can wakeup next time
16201620
AudioRunning = 1;

codec.c

+6-9
Original file line numberDiff line numberDiff line change
@@ -450,15 +450,14 @@ void CodecVideoFlushBuffers(VideoDecoder * decoder)
450450
**
451451
** @param decoder video decoder data
452452
*/
453-
const char* CodecVideoGetCodecName(VideoDecoder * decoder)
453+
const char *CodecVideoGetCodecName(VideoDecoder * decoder)
454454
{
455455
if (decoder && decoder->VideoCodec)
456456
return avcodec_get_name(decoder->VideoCodec->id);
457457

458458
return avcodec_get_name(AV_CODEC_ID_NONE);
459459
}
460460

461-
462461
//----------------------------------------------------------------------------
463462
// Audio
464463
//----------------------------------------------------------------------------
@@ -567,7 +566,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
567566
switch (device_get_atype()) {
568567
case 0:
569568
break;
570-
case 0x3: /* FALLTHRU */
569+
case 0x3: /* FALLTHRU */
571570
case 0x4:
572571
codec_id = AV_CODEC_ID_MP2;
573572
break;
@@ -600,7 +599,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
600599
audio_decoder->AudioFmtCtx->audio_codec_id = codec_id;
601600

602601
av_dict_set_int(&options, "analyzeduration", 500, 0);
603-
av_dict_set_int(&options, "probesize", alloc_size / 2 , 0);
602+
av_dict_set_int(&options, "probesize", alloc_size / 2, 0);
604603

605604
input_format = av_find_input_format("mpeg");
606605
if (!input_format) {
@@ -622,18 +621,14 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
622621
Error("codec: failed to add audio stream to context");
623622
goto error_avformat_new_stream;
624623
}
625-
626-
#if 1
627624
audio_decoder->AudioFmtCtx->streams[0]->codecpar->codec_id = codec_id;
628625
audio_decoder->AudioFmtCtx->streams[0]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
629-
#endif
630-
#if 1
626+
631627
ret = avformat_find_stream_info(audio_decoder->AudioFmtCtx, NULL);
632628
if (ret < 0) {
633629
Error("codec: can't find audio stream info: %s", av_err2str(ret));
634630
goto error_avformat_find_stream_info;
635631
}
636-
#endif
637632

638633
av_dump_format(audio_decoder->AudioFmtCtx, 0, "vaapidevice audio", 0);
639634
#if 0
@@ -704,7 +699,9 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
704699
error_avcodec_alloc_context3:
705700
error_avcodec_find_decoder:
706701
error_avformat_new_stream:
702+
#if 0
707703
error_avformat_find_best_stream:
704+
#endif
708705
error_avformat_find_stream_info:
709706
error_avformat_open_input:
710707
av_freep(avio_ctx);

codec.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,7 @@ extern void CodecVideoDecode(VideoDecoder *);
7575
extern void CodecVideoFlushBuffers(VideoDecoder *);
7676

7777
/// Get video decoder name.
78-
extern const char* CodecVideoGetCodecName(VideoDecoder *);
78+
extern const char *CodecVideoGetCodecName(VideoDecoder *);
7979

8080
/// Allocate a new audio decoder context.
8181
extern AudioDecoder *CodecAudioNewDecoder(void);

vaapidev.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@
3636
#include "video.h"
3737
#include "codec.h"
3838

39-
4039
//////////////////////////////////////////////////////////////////////////////
4140
// Variables
4241
//////////////////////////////////////////////////////////////////////////////
@@ -1613,6 +1612,7 @@ char *GetVideoStats(void)
16131612
char *GetVideoInfo(void)
16141613
{
16151614
const char *codec = CodecVideoGetCodecName(MyVideoStream->Decoder);
1615+
16161616
return MyVideoStream->HwDecoder ? VideoGetInfo(MyVideoStream->HwDecoder, codec) : NULL;
16171617
}
16181618

vaapidevice.cpp

+7-5
Original file line numberDiff line numberDiff line change
@@ -1985,6 +1985,7 @@ void cVaapiDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
19851985
int cVaapiDevice::PlayAudio(const uchar * data, int length, uchar id)
19861986
{
19871987
const int ringBufferSize = KILOBYTE(512);
1988+
19881989
if (length > ringBufferSize) {
19891990
Error("Audio PES packet size (%d) too large for frame ringbuffer", length);
19901991
return 0;
@@ -1999,6 +2000,7 @@ int cVaapiDevice::PlayAudio(const uchar * data, int length, uchar id)
19992000
if (audioEof || !audioBuffer->Put(packet)) {
20002001
// If this happens often enough vdr will start asking for a clear of device
20012002
delete packet;
2003+
20022004
return 0;
20032005
}
20042006
// TODO: remove vaapidev code
@@ -2046,6 +2048,7 @@ void cVaapiDevice::SetVolumeDevice(int volume)
20462048
int cVaapiDevice::PlayVideo(const uchar * data, int length)
20472049
{
20482050
const int ringBufferSize = MEGABYTE(1);
2051+
20492052
if (length > ringBufferSize) {
20502053
Error("Video PES packet size (%d) too large for frame ringbuffer", length);
20512054
return 0;
@@ -2060,6 +2063,7 @@ int cVaapiDevice::PlayVideo(const uchar * data, int length)
20602063
if (videoEof || !videoBuffer->Put(packet)) {
20612064
// If this happens often enough vdr will start asking for a clear of device
20622065
delete packet;
2066+
20632067
return 0;
20642068
}
20652069

@@ -2124,10 +2128,9 @@ int cVaapiDevice::DeviceGetAtype()
21242128
eTrackType track = GetCurrentAudioTrack();
21252129

21262130
if (IS_AUDIO_TRACK(track)) {
2127-
return PatPmtParser()->Atype(int(track - ttAudioFirst));
2128-
}
2129-
else if (IS_DOLBY_TRACK(track)) {
2130-
return PatPmtParser()->Dtype(int(track - ttDolbyFirst));
2131+
return PatPmtParser()->Atype(int (track - ttAudioFirst));
2132+
} else if (IS_DOLBY_TRACK(track)) {
2133+
return PatPmtParser()->Dtype(int (track - ttDolbyFirst));
21312134
}
21322135

21332136
return -1;
@@ -2209,7 +2212,6 @@ int cVaapiDevice::DeviceAudioReadCallback(uchar * data, int size)
22092212

22102213
} while (!packet && ffmpegMode == 0 && retries++ < 3);
22112214

2212-
22132215
if (!packet) {
22142216
return ffmpegMode ? 0 : AVERROR_EOF;
22152217
}

video.c

+60-27
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,9 @@
7474
#define TO_VAAPI_DEVICE_CTX(x) ((AVVAAPIDeviceContext*)TO_AVHW_DEVICE_CTX(x)->hwctx)
7575
#define TO_VAAPI_FRAMES_CTX(x) ((AVVAAPIFramesContext*)TO_AVHW_FRAMES_CTX(x)->hwctx)
7676

77+
// PTS Filter-Elements of 1, 2, 4, 8, 16, ..
78+
#define LP_FILTER_CNT 2
79+
7780
//----------------------------------------------------------------------------
7881
// Declarations
7982
//----------------------------------------------------------------------------
@@ -830,7 +833,11 @@ struct _vaapi_decoder_
830833
int SyncOnAudio; ///< flag sync to audio
831834
int64_t PTS; ///< video PTS clock
832835

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+
834841
int SyncCounter; ///< counter to sync frames
835842
int StartCounter; ///< counter for video start
836843
int FramesDuped; ///< number of frames duplicated
@@ -1343,6 +1350,13 @@ static VaapiDecoder *VaapiNewHwDecoder(VideoStream * stream)
13431350

13441351
decoder->GetPutImage = 1;
13451352

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+
13461360
VaapiDecoders[VaapiDecoderN++] = decoder;
13471361

13481362
return decoder;
@@ -3603,7 +3617,8 @@ char *VaapiGetStats(VaapiDecoder * decoder)
36033617
if (snprintf(&buffer[0], sizeof(buffer),
36043618
" Frames: missed(%d) duped(%d) dropped(%d) total(%d) PTS(%s) drift(%" PRId64 ") audio(%" PRId64 ") video(%"
36053619
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)) {
36073622
return strdup(buffer);
36083623
}
36093624

@@ -3654,6 +3669,11 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
36543669
int filled;
36553670
int64_t audio_clock;
36563671
int64_t video_clock;
3672+
int64_t diff;
3673+
3674+
if (decoder == NULL) {
3675+
return;
3676+
}
36573677

36583678
err = 0;
36593679
mutex_start_time = GetMsTicks();
@@ -3675,7 +3695,7 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
36753695
goto out;
36763696
}
36773697
// 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) {
36793699
goto out;
36803700
}
36813701
// out of sync: audio before video
@@ -3705,35 +3725,48 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
37053725

37063726
if (audio_clock != (int64_t) AV_NOPTS_VALUE && video_clock != (int64_t) AV_NOPTS_VALUE) {
37073727
// 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;
37163755
}
37173756

3718-
if (abs(diff) > 5000 * 90) { // more than 5s
3757+
if (abs(diff) > (int64_t) 5000 * 90) { // more than 5s
37193758
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));
37303762
++decoder->FramesDuped;
37313763
if (VideoSoftStartSync) {
37323764
decoder->SyncCounter = 1;
37333765
goto out;
37343766
}
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));
37373770
++decoder->FramesDropped;
37383771
VaapiAdvanceDecoderFrame(decoder);
37393772
if (VideoSoftStartSync) {
@@ -3780,9 +3813,9 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
37803813
}
37813814
Info("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d%+d v-buf", Timestamp2String(video_clock),
37823815
(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));
37863819
if (!(decoder->FramesDisplayed % (5 * 60 * 60))) {
37873820
VaapiPrintFrames(decoder);
37883821
}

0 commit comments

Comments
 (0)