mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
Rewrote video/audio start code.
This commit is contained in:
parent
4d1a516c80
commit
b0d9f41020
@ -1,6 +1,7 @@
|
|||||||
User johns
|
User johns
|
||||||
Date:
|
Date:
|
||||||
|
|
||||||
|
Rewrote video/audio start code.
|
||||||
Add support for attach/detach plugin.
|
Add support for attach/detach plugin.
|
||||||
OSS needs bigger audio buffers.
|
OSS needs bigger audio buffers.
|
||||||
Improved audio drift correction support.
|
Improved audio drift correction support.
|
||||||
|
120
audio.c
120
audio.c
@ -107,9 +107,11 @@ typedef struct _audio_module_
|
|||||||
|
|
||||||
void (*Thread) (void); ///< module thread handler
|
void (*Thread) (void); ///< module thread handler
|
||||||
void (*Enqueue) (const void *, int); ///< enqueue samples for output
|
void (*Enqueue) (const void *, int); ///< enqueue samples for output
|
||||||
|
void (*VideoReady) (void); ///< video ready, start audio
|
||||||
void (*FlushBuffers) (void); ///< flush sample buffers
|
void (*FlushBuffers) (void); ///< flush sample buffers
|
||||||
void (*Poller) (void); ///< output poller
|
void (*Poller) (void); ///< output poller
|
||||||
int (*FreeBytes) (void); ///< number of bytes free in buffer
|
int (*FreeBytes) (void); ///< number of bytes free in buffer
|
||||||
|
int (*UsedBytes) (void); ///< number of bytes used in buffer
|
||||||
uint64_t(*GetDelay) (void); ///< get current audio delay
|
uint64_t(*GetDelay) (void); ///< get current audio delay
|
||||||
void (*SetVolume) (int); ///< set output volume
|
void (*SetVolume) (int); ///< set output volume
|
||||||
int (*Setup) (int *, int *, int); ///< setup channels, samplerate
|
int (*Setup) (int *, int *, int); ///< setup channels, samplerate
|
||||||
@ -137,6 +139,7 @@ static const char *AudioMixerDevice; ///< alsa/OSS mixer device name
|
|||||||
static const char *AudioMixerChannel; ///< alsa/OSS mixer channel name
|
static const char *AudioMixerChannel; ///< alsa/OSS mixer channel name
|
||||||
static volatile char AudioRunning; ///< thread running / stopped
|
static volatile char AudioRunning; ///< thread running / stopped
|
||||||
static volatile char AudioPaused; ///< audio paused
|
static volatile char AudioPaused; ///< audio paused
|
||||||
|
static volatile char AudioVideoIsReady; ///< video ready start early
|
||||||
static unsigned AudioSampleRate; ///< audio sample rate in hz
|
static unsigned AudioSampleRate; ///< audio sample rate in hz
|
||||||
static unsigned AudioChannels; ///< number of audio channels
|
static unsigned AudioChannels; ///< number of audio channels
|
||||||
static const int AudioBytesProSample = 2; ///< number of bytes per sample
|
static const int AudioBytesProSample = 2; ///< number of bytes per sample
|
||||||
@ -152,7 +155,6 @@ static const int AudioThread; ///< dummy audio thread
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int VideoAudioDelay; ///< import audio/video delay
|
extern int VideoAudioDelay; ///< import audio/video delay
|
||||||
extern int VideoGetBuffers(void); ///< Get number of input buffers.
|
|
||||||
|
|
||||||
#ifdef USE_AUDIORING
|
#ifdef USE_AUDIORING
|
||||||
|
|
||||||
@ -292,16 +294,16 @@ static int AlsaAddToRingbuffer(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioRunning) {
|
if (!AudioRunning) {
|
||||||
Debug(3, "audio/alsa: start %4zd ms %d v-buf\n",
|
Debug(4, "audio/alsa: start %4zdms\n",
|
||||||
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
|
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
|
||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample),
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
VideoGetBuffers());
|
|
||||||
// forced start
|
// forced start
|
||||||
if (AlsaStartThreshold * 3 < RingBufferUsedBytes(AlsaRingBuffer)) {
|
if (AlsaStartThreshold * 2 < RingBufferUsedBytes(AlsaRingBuffer)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// enough video + audio buffered
|
// enough video + audio buffered
|
||||||
if (VideoGetBuffers() > 1
|
if (AudioVideoIsReady
|
||||||
&& AlsaStartThreshold < RingBufferUsedBytes(AlsaRingBuffer)) {
|
&& AlsaStartThreshold < RingBufferUsedBytes(AlsaRingBuffer)) {
|
||||||
// restart play-back
|
// restart play-back
|
||||||
return 1;
|
return 1;
|
||||||
@ -446,6 +448,7 @@ static void AlsaFlushBuffers(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AudioRunning = 0;
|
AudioRunning = 0;
|
||||||
|
AudioVideoIsReady = 0;
|
||||||
AudioPTS = INT64_C(0x8000000000000000);
|
AudioPTS = INT64_C(0x8000000000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -470,6 +473,14 @@ static int AlsaFreeBytes(void)
|
|||||||
return AlsaRingBuffer ? RingBufferFreeBytes(AlsaRingBuffer) : INT32_MAX;
|
return AlsaRingBuffer ? RingBufferFreeBytes(AlsaRingBuffer) : INT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get used bytes in audio output.
|
||||||
|
*/
|
||||||
|
static int AlsaUsedBytes(void)
|
||||||
|
{
|
||||||
|
return AlsaRingBuffer ? RingBufferUsedBytes(AlsaRingBuffer) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -706,6 +717,26 @@ static void AlsaThreadEnqueue(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Video is ready, start audio if possible,
|
||||||
|
*/
|
||||||
|
static void AlsaVideoReady(void)
|
||||||
|
{
|
||||||
|
if (AudioSampleRate && AudioChannels) {
|
||||||
|
Debug(3, "audio/alsa: start %4zdms video start\n",
|
||||||
|
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
|
||||||
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AudioRunning) {
|
||||||
|
// enough video + audio buffered
|
||||||
|
if (AlsaStartThreshold < RingBufferUsedBytes(AlsaRingBuffer)) {
|
||||||
|
AudioRunning = 1;
|
||||||
|
pthread_cond_signal(&AudioStartCond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Flush alsa buffers with thread.
|
** Flush alsa buffers with thread.
|
||||||
*/
|
*/
|
||||||
@ -1245,13 +1276,16 @@ static const AudioModule AlsaModule = {
|
|||||||
#ifdef USE_AUDIO_THREAD
|
#ifdef USE_AUDIO_THREAD
|
||||||
.Thread = AlsaThread,
|
.Thread = AlsaThread,
|
||||||
.Enqueue = AlsaThreadEnqueue,
|
.Enqueue = AlsaThreadEnqueue,
|
||||||
|
.VideoReady = AlsaVideoReady,
|
||||||
.FlushBuffers = AlsaThreadFlushBuffers,
|
.FlushBuffers = AlsaThreadFlushBuffers,
|
||||||
#else
|
#else
|
||||||
.Enqueue = AlsaEnqueue,
|
.Enqueue = AlsaEnqueue,
|
||||||
|
.VideoReady = AlsaVideoReady,
|
||||||
.FlushBuffers = AlsaFlushBuffers,
|
.FlushBuffers = AlsaFlushBuffers,
|
||||||
#endif
|
#endif
|
||||||
.Poller = AlsaPoller,
|
.Poller = AlsaPoller,
|
||||||
.FreeBytes = AlsaFreeBytes,
|
.FreeBytes = AlsaFreeBytes,
|
||||||
|
.UsedBytes = AlsaUsedBytes,
|
||||||
.GetDelay = AlsaGetDelay,
|
.GetDelay = AlsaGetDelay,
|
||||||
.SetVolume = AlsaSetVolume,
|
.SetVolume = AlsaSetVolume,
|
||||||
.Setup = AlsaSetup,
|
.Setup = AlsaSetup,
|
||||||
@ -1308,16 +1342,16 @@ static int OssAddToRingbuffer(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioRunning) {
|
if (!AudioRunning) {
|
||||||
Debug(3, "audio/oss: start %4zd ms %d v-buf\n",
|
Debug(4, "audio/oss: start %4zdms\n",
|
||||||
(RingBufferUsedBytes(OssRingBuffer) * 1000)
|
(RingBufferUsedBytes(OssRingBuffer) * 1000)
|
||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample),
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
VideoGetBuffers());
|
|
||||||
// forced start
|
// forced start
|
||||||
if (OssStartThreshold * 3 < RingBufferUsedBytes(OssRingBuffer)) {
|
if (OssStartThreshold * 2 < RingBufferUsedBytes(OssRingBuffer)) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
// enough video + audio buffered
|
// enough video + audio buffered
|
||||||
if (VideoGetBuffers() > 1
|
if (AudioVideoIsReady
|
||||||
&& OssStartThreshold < RingBufferUsedBytes(OssRingBuffer)) {
|
&& OssStartThreshold < RingBufferUsedBytes(OssRingBuffer)) {
|
||||||
// restart play-back
|
// restart play-back
|
||||||
return 1;
|
return 1;
|
||||||
@ -1392,6 +1426,7 @@ static void OssFlushBuffers(void)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
AudioRunning = 0;
|
AudioRunning = 0;
|
||||||
|
AudioVideoIsReady = 0;
|
||||||
AudioPTS = INT64_C(0x8000000000000000);
|
AudioPTS = INT64_C(0x8000000000000000);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1450,6 +1485,14 @@ static int OssFreeBytes(void)
|
|||||||
return OssRingBuffer ? RingBufferFreeBytes(OssRingBuffer) : INT32_MAX;
|
return OssRingBuffer ? RingBufferFreeBytes(OssRingBuffer) : INT32_MAX;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get used bytes in audio output.
|
||||||
|
*/
|
||||||
|
static int OssUsedBytes(void)
|
||||||
|
{
|
||||||
|
return OssRingBuffer ? RingBufferUsedBytes(OssRingBuffer) : 0;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef USE_AUDIO_THREAD
|
#ifdef USE_AUDIO_THREAD
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
@ -1520,6 +1563,26 @@ static void OssThreadEnqueue(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Video is ready, start audio if possible,
|
||||||
|
*/
|
||||||
|
static void OssVideoReady(void)
|
||||||
|
{
|
||||||
|
if (AudioSampleRate && AudioChannels) {
|
||||||
|
Debug(3, "audio/oss: start %4zdms video start\n",
|
||||||
|
(RingBufferUsedBytes(OssRingBuffer) * 1000)
|
||||||
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!AudioRunning) {
|
||||||
|
// enough video + audio buffered
|
||||||
|
if (OssStartThreshold < RingBufferUsedBytes(OssRingBuffer)) {
|
||||||
|
AudioRunning = 1;
|
||||||
|
pthread_cond_signal(&AudioStartCond);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Flush OSS buffers with thread.
|
** Flush OSS buffers with thread.
|
||||||
*/
|
*/
|
||||||
@ -1881,13 +1944,16 @@ static const AudioModule OssModule = {
|
|||||||
#ifdef USE_AUDIO_THREAD
|
#ifdef USE_AUDIO_THREAD
|
||||||
.Thread = OssThread,
|
.Thread = OssThread,
|
||||||
.Enqueue = OssThreadEnqueue,
|
.Enqueue = OssThreadEnqueue,
|
||||||
|
.VideoReady = OssVideoReady,
|
||||||
.FlushBuffers = OssThreadFlushBuffers,
|
.FlushBuffers = OssThreadFlushBuffers,
|
||||||
#else
|
#else
|
||||||
.Enqueue = OssEnqueue,
|
.Enqueue = OssEnqueue,
|
||||||
|
.VideoReady = OssVideoReady,
|
||||||
.FlushBuffers = OssFlushBuffers,
|
.FlushBuffers = OssFlushBuffers,
|
||||||
#endif
|
#endif
|
||||||
.Poller = OssPoller,
|
.Poller = OssPoller,
|
||||||
.FreeBytes = OssFreeBytes,
|
.FreeBytes = OssFreeBytes,
|
||||||
|
.UsedBytes = OssUsedBytes,
|
||||||
.GetDelay = OssGetDelay,
|
.GetDelay = OssGetDelay,
|
||||||
.SetVolume = OssSetVolume,
|
.SetVolume = OssSetVolume,
|
||||||
.Setup = OssSetup,
|
.Setup = OssSetup,
|
||||||
@ -1923,6 +1989,14 @@ static int NoopFreeBytes(void)
|
|||||||
return INT32_MAX; // no driver, much space
|
return INT32_MAX; // no driver, much space
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get used bytes in audio output.
|
||||||
|
*/
|
||||||
|
static int NoopUsedBytes(void)
|
||||||
|
{
|
||||||
|
return 0; // no driver, nothing used
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Get audio delay in time stamps.
|
** Get audio delay in time stamps.
|
||||||
**
|
**
|
||||||
@ -1970,9 +2044,11 @@ static void NoopVoid(void)
|
|||||||
static const AudioModule NoopModule = {
|
static const AudioModule NoopModule = {
|
||||||
.Name = "noop",
|
.Name = "noop",
|
||||||
.Enqueue = NoopEnqueue,
|
.Enqueue = NoopEnqueue,
|
||||||
|
.VideoReady = NoopVoid,
|
||||||
.FlushBuffers = NoopVoid,
|
.FlushBuffers = NoopVoid,
|
||||||
.Poller = NoopVoid,
|
.Poller = NoopVoid,
|
||||||
.FreeBytes = NoopFreeBytes,
|
.FreeBytes = NoopFreeBytes,
|
||||||
|
.UsedBytes = NoopUsedBytes,
|
||||||
.GetDelay = NoopGetDelay,
|
.GetDelay = NoopGetDelay,
|
||||||
.SetVolume = NoopSetVolume,
|
.SetVolume = NoopSetVolume,
|
||||||
.Setup = NoopSetup,
|
.Setup = NoopSetup,
|
||||||
@ -2002,9 +2078,10 @@ static void *AudioPlayHandlerThread(void *dummy)
|
|||||||
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
||||||
// cond_wait can return, without signal!
|
// cond_wait can return, without signal!
|
||||||
} while (!AudioRunning);
|
} while (!AudioRunning);
|
||||||
Debug(3, "audio/alsa: ----> %zd ms\n",
|
|
||||||
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
|
Debug(3, "audio: ----> %d ms\n", (AudioUsedBytes() * 1000)
|
||||||
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
|
|
||||||
pthread_mutex_unlock(&AudioMutex);
|
pthread_mutex_unlock(&AudioMutex);
|
||||||
|
|
||||||
#ifdef USE_AUDIORING
|
#ifdef USE_AUDIORING
|
||||||
@ -2130,6 +2207,15 @@ void AudioEnqueue(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Video is ready.
|
||||||
|
*/
|
||||||
|
void AudioVideoReady(void)
|
||||||
|
{
|
||||||
|
AudioVideoIsReady = 1;
|
||||||
|
AudioUsedModule->VideoReady();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Flush audio buffers.
|
** Flush audio buffers.
|
||||||
*/
|
*/
|
||||||
@ -2154,6 +2240,14 @@ int AudioFreeBytes(void)
|
|||||||
return AudioUsedModule->FreeBytes();
|
return AudioUsedModule->FreeBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Get used bytes in audio output.
|
||||||
|
*/
|
||||||
|
int AudioUsedBytes(void)
|
||||||
|
{
|
||||||
|
return AudioUsedModule->UsedBytes();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Get audio delay in time stamps.
|
** Get audio delay in time stamps.
|
||||||
**
|
**
|
||||||
|
3
audio.h
3
audio.h
@ -31,8 +31,7 @@ extern void AudioEnqueue(const void *, int); ///< buffer audio samples
|
|||||||
extern void AudioFlushBuffers(void); ///< flush audio buffers
|
extern void AudioFlushBuffers(void); ///< flush audio buffers
|
||||||
extern void AudioPoller(void); ///< poll audio events/handling
|
extern void AudioPoller(void); ///< poll audio events/handling
|
||||||
extern int AudioFreeBytes(void); ///< free bytes in audio output
|
extern int AudioFreeBytes(void); ///< free bytes in audio output
|
||||||
|
extern int AudioUsedBytes(void); ///< used bytes in audio output
|
||||||
//extern int AudioUsedBytes(void); ///< used bytes in audio output
|
|
||||||
extern uint64_t AudioGetDelay(void); ///< get current audio delay
|
extern uint64_t AudioGetDelay(void); ///< get current audio delay
|
||||||
extern void AudioSetClock(int64_t); ///< set audio clock base
|
extern void AudioSetClock(int64_t); ///< set audio clock base
|
||||||
extern int64_t AudioGetClock(); ///< get current audio clock
|
extern int64_t AudioGetClock(); ///< get current audio clock
|
||||||
|
63
video.c
63
video.c
@ -331,7 +331,7 @@ int VideoAudioDelay;
|
|||||||
/// Default zoom mode
|
/// Default zoom mode
|
||||||
static VideoZoomModes Video4to3ZoomMode;
|
static VideoZoomModes Video4to3ZoomMode;
|
||||||
|
|
||||||
//static char VideoSoftStartSync; ///< soft start sync audio/video
|
static char VideoSoftStartSync = 1; ///< soft start sync audio/video
|
||||||
|
|
||||||
static char Video60HzMode; ///< handle 60hz displays
|
static char Video60HzMode; ///< handle 60hz displays
|
||||||
|
|
||||||
@ -340,6 +340,7 @@ static xcb_atom_t NetWmState; ///< wm-state message atom
|
|||||||
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
||||||
|
|
||||||
extern uint32_t VideoSwitch; ///< ticks for channel switch
|
extern uint32_t VideoSwitch; ///< ticks for channel switch
|
||||||
|
extern void AudioVideoReady(void); ///< tell audio video is ready
|
||||||
|
|
||||||
#ifdef USE_VIDEO_THREAD
|
#ifdef USE_VIDEO_THREAD
|
||||||
|
|
||||||
@ -381,6 +382,9 @@ static const char *VideoTimeStampString(int64_t ts)
|
|||||||
int ss;
|
int ss;
|
||||||
int uu;
|
int uu;
|
||||||
|
|
||||||
|
if (ts == (int64_t) AV_NOPTS_VALUE) {
|
||||||
|
return "--:--:--.---";
|
||||||
|
}
|
||||||
idx ^= 1; // support two static buffers
|
idx ^= 1; // support two static buffers
|
||||||
ts = ts / 90;
|
ts = ts / 90;
|
||||||
uu = ts % 1000;
|
uu = ts % 1000;
|
||||||
@ -410,6 +414,7 @@ static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
|
|||||||
if (*pts_p != (int64_t) AV_NOPTS_VALUE) {
|
if (*pts_p != (int64_t) AV_NOPTS_VALUE) {
|
||||||
*pts_p += interlaced ? 40 * 90 : 20 * 90;
|
*pts_p += interlaced ? 40 * 90 : 20 * 90;
|
||||||
}
|
}
|
||||||
|
//av_opt_ptr(avcodec_get_frame_class(), frame, "best_effort_timestamp");
|
||||||
//pts = frame->best_effort_timestamp;
|
//pts = frame->best_effort_timestamp;
|
||||||
pts = frame->pkt_pts;
|
pts = frame->pkt_pts;
|
||||||
if (pts == (int64_t) AV_NOPTS_VALUE || !pts) {
|
if (pts == (int64_t) AV_NOPTS_VALUE || !pts) {
|
||||||
@ -1342,6 +1347,7 @@ struct _vaapi_decoder_
|
|||||||
struct timespec FrameTime; ///< time of last display
|
struct timespec FrameTime; ///< time of last display
|
||||||
int64_t PTS; ///< video PTS clock
|
int64_t PTS; ///< video PTS clock
|
||||||
|
|
||||||
|
int StartCounter; ///< number of start frames
|
||||||
int FramesDuped; ///< number of frames duplicated
|
int FramesDuped; ///< number of frames duplicated
|
||||||
int FramesMissed; ///< number of frames missed
|
int FramesMissed; ///< number of frames missed
|
||||||
int FramesDropped; ///< number of frames dropped
|
int FramesDropped; ///< number of frames dropped
|
||||||
@ -1813,10 +1819,13 @@ static void VaapiCleanup(VaapiDecoder * decoder)
|
|||||||
if (decoder->DeintImages[0].image_id != VA_INVALID_ID) {
|
if (decoder->DeintImages[0].image_id != VA_INVALID_ID) {
|
||||||
VaapiDestroyDeinterlaceImages(decoder);
|
VaapiDestroyDeinterlaceImages(decoder);
|
||||||
}
|
}
|
||||||
|
decoder->SurfaceRead = 0;
|
||||||
|
decoder->SurfaceWrite = 0;
|
||||||
|
|
||||||
decoder->SurfaceField = 1;
|
decoder->SurfaceField = 1;
|
||||||
|
|
||||||
//decoder->FrameCounter = 0;
|
//decoder->FrameCounter = 0;
|
||||||
|
decoder->StartCounter = 0;
|
||||||
decoder->PTS = AV_NOPTS_VALUE;
|
decoder->PTS = AV_NOPTS_VALUE;
|
||||||
VideoDeltaPTS = 0;
|
VideoDeltaPTS = 0;
|
||||||
}
|
}
|
||||||
@ -4379,6 +4388,14 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
filled = atomic_read(&decoder->SurfacesFilled);
|
filled = atomic_read(&decoder->SurfacesFilled);
|
||||||
// FIXME: audio not known assume 333ms delay
|
// FIXME: audio not known assume 333ms delay
|
||||||
|
|
||||||
|
decoder->StartCounter++;
|
||||||
|
if (!VideoSoftStartSync && decoder->StartCounter < 60
|
||||||
|
&& (audio_clock == (int64_t) AV_NOPTS_VALUE
|
||||||
|
|| video_clock > audio_clock + VideoAudioDelay + 120 * 90)) {
|
||||||
|
Debug(3, "video: initial slow down %d\n", decoder->StartCounter);
|
||||||
|
decoder->DupNextFrame = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (decoder->DupNextFrame) {
|
if (decoder->DupNextFrame) {
|
||||||
decoder->DupNextFrame--;
|
decoder->DupNextFrame--;
|
||||||
++decoder->FramesDuped;
|
++decoder->FramesDuped;
|
||||||
@ -4388,23 +4405,17 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
|
|
||||||
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
||||||
Debug(3, "video: pts difference too big\n");
|
Debug(3, "video: pts difference too big\n");
|
||||||
} else if (video_clock > audio_clock + VideoAudioDelay + 80 * 90) {
|
} else if (video_clock > audio_clock + VideoAudioDelay + 100 * 90) {
|
||||||
Debug(3, "video: slow down video\n");
|
Debug(3, "video: slow down video\n");
|
||||||
decoder->DupNextFrame += 2;
|
decoder->DupNextFrame += 2;
|
||||||
} else if (video_clock > audio_clock + VideoAudioDelay + 30 * 90) {
|
} else if (video_clock > audio_clock + VideoAudioDelay + 45 * 90) {
|
||||||
Debug(3, "video: slow down video\n");
|
Debug(3, "video: slow down video\n");
|
||||||
decoder->DupNextFrame++;
|
decoder->DupNextFrame++;
|
||||||
} else if (audio_clock + VideoAudioDelay > video_clock + 40 * 90
|
} else if (audio_clock + VideoAudioDelay > video_clock + 15 * 90
|
||||||
&& filled > 1) {
|
&& filled > 1) {
|
||||||
Debug(3, "video: speed up video\n");
|
Debug(3, "video: speed up video\n");
|
||||||
decoder->DropNextFrame = 1;
|
decoder->DropNextFrame = 1;
|
||||||
}
|
}
|
||||||
} else if (audio_clock == (int64_t) AV_NOPTS_VALUE
|
|
||||||
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
|
|
||||||
if (VideoGetBuffers() < 4) {
|
|
||||||
Debug(3, "video: initial slow down video\n");
|
|
||||||
decoder->DupNextFrame++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#if defined(DEBUG) || defined(AV_INFO)
|
#if defined(DEBUG) || defined(AV_INFO)
|
||||||
// debug audio/video sync
|
// debug audio/video sync
|
||||||
@ -4892,6 +4903,7 @@ typedef struct _vdpau_decoder_
|
|||||||
struct timespec FrameTime; ///< time of last display
|
struct timespec FrameTime; ///< time of last display
|
||||||
int64_t PTS; ///< video PTS clock
|
int64_t PTS; ///< video PTS clock
|
||||||
|
|
||||||
|
int StartCounter; ///< number of start frames
|
||||||
int FramesDuped; ///< number of frames duplicated
|
int FramesDuped; ///< number of frames duplicated
|
||||||
int FramesMissed; ///< number of frames missed
|
int FramesMissed; ///< number of frames missed
|
||||||
int FramesDropped; ///< number of frames dropped
|
int FramesDropped; ///< number of frames dropped
|
||||||
@ -5568,6 +5580,8 @@ static void VdpauCleanup(VdpauDecoder * decoder)
|
|||||||
|
|
||||||
decoder->SurfaceField = 0;
|
decoder->SurfaceField = 0;
|
||||||
|
|
||||||
|
//decoder->FrameCounter = 0;
|
||||||
|
decoder->StartCounter = 0;
|
||||||
decoder->PTS = AV_NOPTS_VALUE;
|
decoder->PTS = AV_NOPTS_VALUE;
|
||||||
VideoDeltaPTS = 0;
|
VideoDeltaPTS = 0;
|
||||||
}
|
}
|
||||||
@ -7431,6 +7445,14 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
filled = atomic_read(&decoder->SurfacesFilled);
|
filled = atomic_read(&decoder->SurfacesFilled);
|
||||||
// FIXME: audio not known assume 333ms delay
|
// FIXME: audio not known assume 333ms delay
|
||||||
|
|
||||||
|
decoder->StartCounter++;
|
||||||
|
if (!VideoSoftStartSync && decoder->StartCounter < 60
|
||||||
|
&& (audio_clock == (int64_t) AV_NOPTS_VALUE
|
||||||
|
|| video_clock > audio_clock + VideoAudioDelay + 120 * 90)) {
|
||||||
|
Debug(3, "video: initial slow down %d\n", decoder->StartCounter);
|
||||||
|
decoder->DupNextFrame = 2;
|
||||||
|
}
|
||||||
|
|
||||||
if (decoder->DupNextFrame) {
|
if (decoder->DupNextFrame) {
|
||||||
decoder->DupNextFrame--;
|
decoder->DupNextFrame--;
|
||||||
++decoder->FramesDuped;
|
++decoder->FramesDuped;
|
||||||
@ -7440,23 +7462,17 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
|
|
||||||
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
||||||
Debug(3, "video: pts difference too big\n");
|
Debug(3, "video: pts difference too big\n");
|
||||||
} else if (video_clock > audio_clock + VideoAudioDelay + 80 * 90) {
|
} else if (video_clock > audio_clock + VideoAudioDelay + 100 * 90) {
|
||||||
Debug(3, "video: slow down video\n");
|
Debug(3, "video: slow down video\n");
|
||||||
decoder->DupNextFrame += 2;
|
decoder->DupNextFrame += 2;
|
||||||
} else if (video_clock > audio_clock + VideoAudioDelay + 30 * 90) {
|
} else if (video_clock > audio_clock + VideoAudioDelay + 45 * 90) {
|
||||||
Debug(3, "video: slow down video\n");
|
Debug(3, "video: slow down video\n");
|
||||||
decoder->DupNextFrame++;
|
decoder->DupNextFrame++;
|
||||||
} else if (audio_clock + VideoAudioDelay > video_clock + 40 * 90
|
} else if (audio_clock + VideoAudioDelay > video_clock + 15 * 90
|
||||||
&& filled > 1 + 2 * decoder->Interlaced) {
|
&& filled > 1 + 2 * decoder->Interlaced) {
|
||||||
Debug(3, "video: speed up video\n");
|
Debug(3, "video: speed up video\n");
|
||||||
decoder->DropNextFrame = 1;
|
decoder->DropNextFrame = 1;
|
||||||
}
|
}
|
||||||
} else if (audio_clock == (int64_t) AV_NOPTS_VALUE
|
|
||||||
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
|
|
||||||
if (VideoGetBuffers() < 4) {
|
|
||||||
Debug(3, "video: initial slow down video\n");
|
|
||||||
decoder->DupNextFrame++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#if defined(DEBUG) || defined(AV_INFO)
|
#if defined(DEBUG) || defined(AV_INFO)
|
||||||
// debug audio/video sync
|
// debug audio/video sync
|
||||||
@ -7483,14 +7499,9 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
|||||||
{
|
{
|
||||||
VideoSetPts(&decoder->PTS, decoder->Interlaced, frame);
|
VideoSetPts(&decoder->PTS, decoder->Interlaced, frame);
|
||||||
|
|
||||||
if (VdpauPreemption) { // display preempted
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#ifdef DEBUG
|
|
||||||
if (!atomic_read(&decoder->SurfacesFilled)) {
|
if (!atomic_read(&decoder->SurfacesFilled)) {
|
||||||
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
|
Debug(3, "video: new stream frame %d\n", GetMsTicks() - VideoSwitch);
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
if (decoder->DropNextFrame) { // drop frame requested
|
if (decoder->DropNextFrame) { // drop frame requested
|
||||||
++decoder->FramesDropped;
|
++decoder->FramesDropped;
|
||||||
@ -7502,6 +7513,9 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
|||||||
decoder->DropNextFrame--;
|
decoder->DropNextFrame--;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (VdpauPreemption) { // display preempted
|
||||||
|
return;
|
||||||
|
}
|
||||||
// if video output buffer is full, wait and display surface.
|
// if video output buffer is full, wait and display surface.
|
||||||
// loop for interlace
|
// loop for interlace
|
||||||
while (atomic_read(&decoder->SurfacesFilled) >= VIDEO_SURFACES_MAX) {
|
while (atomic_read(&decoder->SurfacesFilled) >= VIDEO_SURFACES_MAX) {
|
||||||
@ -8618,6 +8632,7 @@ void VideoReleaseSurface(VideoHwDecoder * decoder, unsigned surface)
|
|||||||
enum PixelFormat Video_get_format(VideoHwDecoder * decoder,
|
enum PixelFormat Video_get_format(VideoHwDecoder * decoder,
|
||||||
AVCodecContext * video_ctx, const enum PixelFormat *fmt)
|
AVCodecContext * video_ctx, const enum PixelFormat *fmt)
|
||||||
{
|
{
|
||||||
|
AudioVideoReady();
|
||||||
if (VideoUsedModule) {
|
if (VideoUsedModule) {
|
||||||
return VideoUsedModule->get_format(decoder, video_ctx, fmt);
|
return VideoUsedModule->get_format(decoder, video_ctx, fmt);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user