Skip to content

Commit

Permalink
Merged a modified Quantomax's speedupdown patch found on #121.
Browse files Browse the repository at this point in the history
  • Loading branch information
rofafor committed Jun 30, 2018
1 parent 6bd46bf commit 97e225f
Show file tree
Hide file tree
Showing 6 changed files with 81 additions and 49 deletions.
12 changes: 6 additions & 6 deletions audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -769,7 +769,6 @@ static int AlsaPlayRingbuffer(void)
Error("audio/alsa: bytes lost -> out of sync");
}
#endif

for (;;) {
pthread_mutex_lock(&ReadAdvance_mutex);
if (AlsaUseMmap) {
Expand All @@ -779,12 +778,13 @@ static int AlsaPlayRingbuffer(void)
}
if (err != frames) {
if (err < 0) {
pthread_mutex_unlock(&ReadAdvance_mutex);
if (err == -EAGAIN) {
pthread_mutex_unlock(&ReadAdvance_mutex);
continue;
}
Error("audio/alsa: writei underrun error? '%s'", snd_strerror(err));
err = snd_pcm_recover(AlsaPCMHandle, err, 0);
pthread_mutex_unlock(&ReadAdvance_mutex);
if (err >= 0) {
return 0;
}
Expand Down Expand Up @@ -1361,8 +1361,8 @@ static int AudioNextRing(void)
if (remain <= AUDIO_MIN_BUFFER_FREE) {
Debug5("audio: force start");
}
if (remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady || !SoftIsPlayingVideo)
&& AudioStartThreshold < used)) {
if (AudioStartThreshold * 4 < used || remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady
|| !SoftIsPlayingVideo) && AudioStartThreshold < used)) {
return 0;
}
return 1;
Expand Down Expand Up @@ -1613,8 +1613,8 @@ void AudioEnqueue(const void *samples, int count)
if (remain <= AUDIO_MIN_BUFFER_FREE) {
Debug5("audio: force start");
}
if (remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady || !SoftIsPlayingVideo)
&& AudioStartThreshold < n)) {
if (AudioStartThreshold * 4 < n || remain <= AUDIO_MIN_BUFFER_FREE || ((AudioVideoIsReady
|| !SoftIsPlayingVideo) && AudioStartThreshold < n)) {
// restart play-back
// no lock needed, can wakeup next time
AudioRunning = 1;
Expand Down
15 changes: 6 additions & 9 deletions codec.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,15 +450,14 @@ void CodecVideoFlushBuffers(VideoDecoder * decoder)
**
** @param decoder video decoder data
*/
const char* CodecVideoGetCodecName(VideoDecoder * decoder)
const char *CodecVideoGetCodecName(VideoDecoder * decoder)
{
if (decoder && decoder->VideoCodec)
return avcodec_get_name(decoder->VideoCodec->id);

return avcodec_get_name(AV_CODEC_ID_NONE);
}


//----------------------------------------------------------------------------
// Audio
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -567,7 +566,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
switch (device_get_atype()) {
case 0:
break;
case 0x3: /* FALLTHRU */
case 0x3: /* FALLTHRU */
case 0x4:
codec_id = AV_CODEC_ID_MP2;
break;
Expand Down Expand Up @@ -600,7 +599,7 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
audio_decoder->AudioFmtCtx->audio_codec_id = codec_id;

av_dict_set_int(&options, "analyzeduration", 500, 0);
av_dict_set_int(&options, "probesize", alloc_size / 2 , 0);
av_dict_set_int(&options, "probesize", alloc_size / 2, 0);

input_format = av_find_input_format("mpeg");
if (!input_format) {
Expand All @@ -622,18 +621,14 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
Error("codec: failed to add audio stream to context");
goto error_avformat_new_stream;
}

#if 1
audio_decoder->AudioFmtCtx->streams[0]->codecpar->codec_id = codec_id;
audio_decoder->AudioFmtCtx->streams[0]->codecpar->codec_type = AVMEDIA_TYPE_AUDIO;
#endif
#if 1

ret = avformat_find_stream_info(audio_decoder->AudioFmtCtx, NULL);
if (ret < 0) {
Error("codec: can't find audio stream info: %s", av_err2str(ret));
goto error_avformat_find_stream_info;
}
#endif

av_dump_format(audio_decoder->AudioFmtCtx, 0, "vaapidevice audio", 0);
#if 0
Expand Down Expand Up @@ -704,7 +699,9 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, int codec_id_old)
error_avcodec_alloc_context3:
error_avcodec_find_decoder:
error_avformat_new_stream:
#if 0
error_avformat_find_best_stream:
#endif
error_avformat_find_stream_info:
error_avformat_open_input:
av_freep(avio_ctx);
Expand Down
2 changes: 1 addition & 1 deletion codec.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ extern void CodecVideoDecode(VideoDecoder *);
extern void CodecVideoFlushBuffers(VideoDecoder *);

/// Get video decoder name.
extern const char* CodecVideoGetCodecName(VideoDecoder *);
extern const char *CodecVideoGetCodecName(VideoDecoder *);

/// Allocate a new audio decoder context.
extern AudioDecoder *CodecAudioNewDecoder(void);
Expand Down
2 changes: 1 addition & 1 deletion vaapidev.c
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@
#include "video.h"
#include "codec.h"


//////////////////////////////////////////////////////////////////////////////
// Variables
//////////////////////////////////////////////////////////////////////////////
Expand Down Expand Up @@ -1613,6 +1612,7 @@ char *GetVideoStats(void)
char *GetVideoInfo(void)
{
const char *codec = CodecVideoGetCodecName(MyVideoStream->Decoder);

return MyVideoStream->HwDecoder ? VideoGetInfo(MyVideoStream->HwDecoder, codec) : NULL;
}

Expand Down
12 changes: 7 additions & 5 deletions vaapidevice.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1985,6 +1985,7 @@ void cVaapiDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
int cVaapiDevice::PlayAudio(const uchar * data, int length, uchar id)
{
const int ringBufferSize = KILOBYTE(512);

if (length > ringBufferSize) {
Error("Audio PES packet size (%d) too large for frame ringbuffer", length);
return 0;
Expand All @@ -1999,6 +2000,7 @@ int cVaapiDevice::PlayAudio(const uchar * data, int length, uchar id)
if (audioEof || !audioBuffer->Put(packet)) {
// If this happens often enough vdr will start asking for a clear of device
delete packet;

return 0;
}
// TODO: remove vaapidev code
Expand Down Expand Up @@ -2046,6 +2048,7 @@ void cVaapiDevice::SetVolumeDevice(int volume)
int cVaapiDevice::PlayVideo(const uchar * data, int length)
{
const int ringBufferSize = MEGABYTE(1);

if (length > ringBufferSize) {
Error("Video PES packet size (%d) too large for frame ringbuffer", length);
return 0;
Expand All @@ -2060,6 +2063,7 @@ int cVaapiDevice::PlayVideo(const uchar * data, int length)
if (videoEof || !videoBuffer->Put(packet)) {
// If this happens often enough vdr will start asking for a clear of device
delete packet;

return 0;
}

Expand Down Expand Up @@ -2124,10 +2128,9 @@ int cVaapiDevice::DeviceGetAtype()
eTrackType track = GetCurrentAudioTrack();

if (IS_AUDIO_TRACK(track)) {
return PatPmtParser()->Atype(int(track - ttAudioFirst));
}
else if (IS_DOLBY_TRACK(track)) {
return PatPmtParser()->Dtype(int(track - ttDolbyFirst));
return PatPmtParser()->Atype(int (track - ttAudioFirst));
} else if (IS_DOLBY_TRACK(track)) {
return PatPmtParser()->Dtype(int (track - ttDolbyFirst));
}

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

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


if (!packet) {
return ffmpegMode ? 0 : AVERROR_EOF;
}
Expand Down
87 changes: 60 additions & 27 deletions video.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@
#define TO_VAAPI_DEVICE_CTX(x) ((AVVAAPIDeviceContext*)TO_AVHW_DEVICE_CTX(x)->hwctx)
#define TO_VAAPI_FRAMES_CTX(x) ((AVVAAPIFramesContext*)TO_AVHW_FRAMES_CTX(x)->hwctx)

// PTS Filter-Elements of 1, 2, 4, 8, 16, ..
#define LP_FILTER_CNT 2

//----------------------------------------------------------------------------
// Declarations
//----------------------------------------------------------------------------
Expand Down Expand Up @@ -830,7 +833,11 @@ struct _vaapi_decoder_
int SyncOnAudio; ///< flag sync to audio
int64_t PTS; ///< video PTS clock

int LastAVDiff; ///< last audio - video difference
int64_t AvPtsDiffFilter; ///< AV-PTS-Diff Delay element – 64 bits
int AvPtsDiffFilterInit; ///< Filter Init Done
int64_t LastVideoPTS; ///< Video-PTS Rollover Test
int64_t LastAudioPTS; ///< Audio-PTS Rollover Test

int SyncCounter; ///< counter to sync frames
int StartCounter; ///< counter for video start
int FramesDuped; ///< number of frames duplicated
Expand Down Expand Up @@ -1343,6 +1350,13 @@ static VaapiDecoder *VaapiNewHwDecoder(VideoStream * stream)

decoder->GetPutImage = 1;

decoder->AvPtsDiffFilterInit = 1;
decoder->AvPtsDiffFilter = 0;
decoder->LastVideoPTS = 0;
decoder->LastAudioPTS = 0;
decoder->SyncCounter = 0;
decoder->StartCounter = 0;

VaapiDecoders[VaapiDecoderN++] = decoder;

return decoder;
Expand Down Expand Up @@ -3603,7 +3617,8 @@ char *VaapiGetStats(VaapiDecoder * decoder)
if (snprintf(&buffer[0], sizeof(buffer),
" Frames: missed(%d) duped(%d) dropped(%d) total(%d) PTS(%s) drift(%" PRId64 ") audio(%" PRId64 ") video(%"
PRId64 ")", decoder->FramesMissed, decoder->FramesDuped, decoder->FramesDropped, decoder->FrameCounter,
Timestamp2String(video_clock), (video_clock - audio_clock) / 90, AudioGetDelay() / 90, VideoDeltaPTS / 90)) {
Timestamp2String(video_clock), (video_clock - audio_clock) / 90, AudioGetDelay() / 90,
VideoDeltaPTS / 90)) {
return strdup(buffer);
}

Expand Down Expand Up @@ -3654,6 +3669,11 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
int filled;
int64_t audio_clock;
int64_t video_clock;
int64_t diff;

if (decoder == NULL) {
return;
}

err = 0;
mutex_start_time = GetMsTicks();
Expand All @@ -3675,7 +3695,7 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
goto out;
}
// both clocks are known
if (audio_clock + VideoAudioDelay <= video_clock + 25 * 90) {
if (audio_clock + (int64_t) VideoAudioDelay <= video_clock + (int64_t) 25 * 90) {
goto out;
}
// out of sync: audio before video
Expand Down Expand Up @@ -3705,35 +3725,48 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)

if (audio_clock != (int64_t) AV_NOPTS_VALUE && video_clock != (int64_t) AV_NOPTS_VALUE) {
// both clocks are known
int diff;
int lower_limit;

diff = video_clock - audio_clock - VideoAudioDelay;
lower_limit = !IsReplay()? -25 : 32;
if (!IsReplay()) {
diff = (decoder->LastAVDiff + diff) / 2;
decoder->LastAVDiff = diff;
// FIXME: "diff" doesn't checks frametype (i - Top/Bottom, p - Full)
diff = video_clock - audio_clock - (int64_t) VideoAudioDelay;

// AV-Diff greater than 1:00:00.000 should be a PTS-Rollover,
// but observable is: audio_clock jumps to negative values...
if ((audio_clock < 0) || (video_clock < 0) || (abs(diff) > (int64_t) 60 * 60 * 90000)) {
// Set Bit 34 of video_clock if below 1:00:00.000
if (video_clock < (int64_t) 60 * 60 * 90000)
video_clock = video_clock + (int64_t) 0x200000000;
// Set Bit 34 of audio_clock if below 1:00:00.000
if (audio_clock < (int64_t) 60 * 60 * 90000)
audio_clock = audio_clock + (int64_t) 0x200000000;

// Calc correct diff
err = VaapiMessage(1, "AV-PTS Rollover, correcting AV-PTS Difference");
diff = (video_clock - audio_clock - (int64_t) VideoAudioDelay);
}
// Low-Pass Filter AV-PTS-Diff, if in Sync-Range of +/- 250 ms
if (abs(diff) < (int64_t) 250 * 90) {
// Filter-Init done?
if (decoder->AvPtsDiffFilterInit) {
// No.
decoder->AvPtsDiffFilterInit = 0;
decoder->AvPtsDiffFilter = diff * LP_FILTER_CNT;
}
decoder->AvPtsDiffFilter = decoder->AvPtsDiffFilter - (decoder->AvPtsDiffFilter / LP_FILTER_CNT) + diff;
diff = decoder->AvPtsDiffFilter / LP_FILTER_CNT;
}

if (abs(diff) > 5000 * 90) { // more than 5s
if (abs(diff) > (int64_t) 5000 * 90) { // more than 5s
err = VaapiMessage(2, "video: audio/video difference too big");
} else if (diff > 100 * 90) {
// FIXME: this quicker sync step, did not work with new code!
err = VaapiMessage(2, "video: slow down video, duping frame");
++decoder->FramesDuped;
if (VideoSoftStartSync) {
decoder->SyncCounter = 1;
goto out;
}
} else if (diff > 55 * 90) {
err = VaapiMessage(2, "video: slow down video, duping frame");
} else if (diff > (int64_t) 40 * 90) {
Debug("video: slow down video, duping frame (/\\=%.2f ms, vClk %s - aClk %s)", diff * 1000 / (double)90000,
Timestamp2String(video_clock), Timestamp2String(audio_clock));
++decoder->FramesDuped;
if (VideoSoftStartSync) {
decoder->SyncCounter = 1;
goto out;
}
} else if (diff < lower_limit * 90 && filled > 1 + 2 * decoder->Interlaced) {
err = VaapiMessage(2, "video: speed up video, droping frame");
} else if ((diff < (int64_t) - 20 * 90) && (filled > 1 + 2 * decoder->Interlaced)) {
Debug("video: speed up video, droping frame (/\\=%.2f ms, vClk %s - aClk %s)", diff * 1000 / (double)90000,
Timestamp2String(video_clock), Timestamp2String(audio_clock));
++decoder->FramesDropped;
VaapiAdvanceDecoderFrame(decoder);
if (VideoSoftStartSync) {
Expand Down Expand Up @@ -3780,9 +3813,9 @@ static void VaapiSyncDecoder(VaapiDecoder * decoder)
}
Info("video: %s%+5" PRId64 " %4" PRId64 " %3d/\\ms %3d%+d v-buf", Timestamp2String(video_clock),
(video_clock - audio_clock) / 90, AudioGetDelay() / 90, (int)VideoDeltaPTS / 90,
VideoGetBuffers(decoder->Stream), decoder->Interlaced ?
(2 * atomic_read(&decoder->SurfacesFilled) - decoder->SurfaceField) :
atomic_read(&decoder->SurfacesFilled));
VideoGetBuffers(decoder->Stream),
decoder->Interlaced ? (2 * atomic_read(&decoder->SurfacesFilled) -
decoder->SurfaceField) : atomic_read(&decoder->SurfacesFilled));
if (!(decoder->FramesDisplayed % (5 * 60 * 60))) {
VaapiPrintFrames(decoder);
}
Expand Down

0 comments on commit 97e225f

Please sign in to comment.