summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohns <johns98@gmx.net>2011-12-19 17:03:40 +0100
committerJohns <johns98@gmx.net>2011-12-19 17:11:25 +0100
commit36b285b5f7351836f0ad6a364c3d4743549a99c7 (patch)
tree514d88c4eddc836b83cf7be4042f374ea08b910d
parent33460f1370b24bae464201e08bbc7bea26f98129 (diff)
downloadvdr-plugin-softhddevice-36b285b5f7351836f0ad6a364c3d4743549a99c7.tar.gz
vdr-plugin-softhddevice-36b285b5f7351836f0ad6a364c3d4743549a99c7.tar.bz2
Audio/video sync improvements.
Configurable audio delay. Use monotonic pts. Support old libav or ffmpeg libraries.
-rw-r--r--ChangeLog3
-rw-r--r--README.txt3
-rw-r--r--codec.c37
-rw-r--r--softhddev.c1
-rw-r--r--softhddevice.cpp10
-rw-r--r--video.c48
-rw-r--r--video.h6
7 files changed, 92 insertions, 16 deletions
diff --git a/ChangeLog b/ChangeLog
index 59d21d4..91d3cfe 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,9 @@
User johns
Date:
+ Configurable audio delay.
+ Make pts monotonic.
+ Support old libav and ffmpeg libs.
Support xcb_icccm_set_wm_protocols with xcb-util <0.3.8.
New video/audio sync code.
Support xcb-util <0.3.8.
diff --git a/README.txt b/README.txt
index 6d1436f..f4279f7 100644
--- a/README.txt
+++ b/README.txt
@@ -70,6 +70,9 @@ Setup: /etc/vdr/setup.conf
softhddevice.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
+ softhddevice.AudioDelay = 0
+ +n or -n ms
+
Requires:
---------
media-video/ffmpeg
diff --git a/codec.c b/codec.c
index fd5258d..656052a 100644
--- a/codec.c
+++ b/codec.c
@@ -259,6 +259,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
Debug(3, "codec: vdpau decoder found\n");
} else if (!(video_codec = avcodec_find_decoder(codec_id))) {
Fatal(_("codec: codec ID %#04x not found\n"), codec_id);
+ // FIXME: none fatal
}
decoder->VideoCodec = video_codec;
@@ -266,9 +267,15 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
Fatal(_("codec: can't allocate video codec context\n"));
}
// open codec
+#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(52,122,0)
+ if (avcodec_open(decoder->VideoCtx, video_codec) < 0) {
+ Fatal(_("codec: can't open video codec!\n"));
+ }
+#else
if (avcodec_open2(decoder->VideoCtx, video_codec, NULL) < 0) {
Fatal(_("codec: can't open video codec!\n"));
}
+#endif
decoder->VideoCtx->opaque = decoder; // our structure
@@ -354,26 +361,36 @@ void CodecVideoClose(VideoDecoder * video_decoder)
#if 0
-#ifdef DEBUG
-
/**
** Display pts...
+**
+** ffmpeg 0.9 pts always AV_NOPTS_VALUE
+** ffmpeg 0.9 pkt_pts nice monotonic (only with HD)
+** ffmpeg 0.9 pkt_dts wild jumping -160 - 340 ms
+**
+** libav 0.8_pre20111116 pts always AV_NOPTS_VALUE
+** libav 0.8_pre20111116 pkt_pts always 0
+** libav 0.8_pre20111116 pkt_dts wild jumping -160 - 340 ms
*/
void DisplayPts(AVCodecContext * video_ctx, AVFrame * frame)
{
int ms_delay;
+ int64_t pts;
+ static int64_t last_pts;
- if (frame->pts == (int64_t) AV_NOPTS_VALUE) {
+ pts = frame->pkt_pts;
+ if (pts == (int64_t) AV_NOPTS_VALUE) {
printf("*");
}
ms_delay = (1000 * video_ctx->time_base.num) / video_ctx->time_base.den;
ms_delay += frame->repeat_pict * ms_delay / 2;
- printf("codec: PTS %s%s %" PRId64 " %d/%d %dms\n",
+ printf("codec: PTS %s%s %" PRId64 " %d %d/%d %dms\n",
frame->repeat_pict ? "r" : " ", frame->interlaced_frame ? "I" : " ",
- frame->pts, video_ctx->time_base.num, video_ctx->time_base.den,
- ms_delay);
+ pts, (int)(pts - last_pts) / 90, video_ctx->time_base.num,
+ video_ctx->time_base.den, ms_delay);
+
+ last_pts = pts;
}
-#endif
#endif
@@ -506,9 +523,15 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
Fatal(_("codec: can't allocate audio codec context\n"));
}
// open codec
+#if LIBAVCODEC_VERSION_INT <= AV_VERSION_INT(52,122,0)
+ if (avcodec_open(audio_decoder->AudioCtx, audio_codec) < 0) {
+ Fatal(_("codec: can't open audio codec\n"));
+ }
+#else
if (avcodec_open2(audio_decoder->AudioCtx, audio_codec, NULL) < 0) {
Fatal(_("codec: can't open audio codec\n"));
}
+#endif
Debug(3, "codec: audio '%s'\n", audio_decoder->AudioCtx->codec_name);
if (audio_codec->capabilities & CODEC_CAP_TRUNCATED) {
diff --git a/softhddev.c b/softhddev.c
index a57eff9..a6c731b 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -655,6 +655,7 @@ int Poll(int timeout)
{
// buffers are too full
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) {
+ Debug(3, "replay: poll %d\n", timeout);
if (timeout) {
// let display thread work
usleep(timeout * 1000);
diff --git a/softhddevice.cpp b/softhddevice.cpp
index 260cc5f..ff675c9 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -51,6 +51,7 @@ static class cSoftHdDevice *MyDevice;
static char ConfigMakePrimary; ///< config primary wanted
static char ConfigVideoDeinterlace; ///< config deinterlace
static char ConfigVideoScaling; ///< config scaling
+static int ConfigVideoAudioDelay; ///< config audio delay
static char DoMakePrimary; ///< flag switch primary
//////////////////////////////////////////////////////////////////////////////
@@ -261,6 +262,7 @@ class cMenuSetupSoft:public cMenuSetupPage
int MakePrimary;
int Deinterlace;
int Scaling;
+ int AudioDelay;
protected:
virtual void Store(void);
public:
@@ -286,6 +288,8 @@ cMenuSetupSoft::cMenuSetupSoft(void)
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace, 5, deinterlace));
Scaling = ConfigVideoScaling;
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling, 4, scaling));
+ AudioDelay = ConfigVideoAudioDelay;
+ Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000, 1000));
}
/**
@@ -298,6 +302,8 @@ void cMenuSetupSoft::Store(void)
VideoSetDeinterlace(ConfigVideoDeinterlace);
SetupStore("Scaling", ConfigVideoScaling = Scaling);
VideoSetScaling(ConfigVideoScaling);
+ SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
+ VideoSetAudioDelay(ConfigVideoAudioDelay);
}
//////////////////////////////////////////////////////////////////////////////
@@ -766,6 +772,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
VideoSetScaling(ConfigVideoScaling = atoi(value));
return true;
}
+ if (!strcmp(name, "AudioDelay")) {
+ VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
+ return true;
+ }
return false;
}
diff --git a/video.c b/video.c
index 0e437d8..b7930b8 100644
--- a/video.c
+++ b/video.c
@@ -181,6 +181,9 @@ static VideoDeinterlaceModes VideoDeinterlace;
/// Default scaling mode
static VideoScalingModes VideoScaling;
+ /// Default audio/video delay
+static int VideoAudioDelay;
+
//static char VideoSoftStartSync; ///< soft start sync audio/video
static char Video60HzMode; ///< handle 60hz displays
@@ -2520,7 +2523,7 @@ static void VaapiDisplayFrame(void)
// deinterlace and full frame rate
// VDPAU driver only display a frame, if a full frame is put
// INTEL driver does the same, but only with 1080i
- if (decoder->Interlaced
+ if (0 && decoder->Interlaced
// FIXME: buggy libva-driver-vdpau, buggy libva-driver-intel
&& (VaapiBuggyVdpau || (0 && VaapiBuggyIntel
&& decoder->InputHeight == 1080))
@@ -3136,10 +3139,11 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
if (abs(video_clock - audio_clock) > 5000 * 90) {
Debug(3, "video: pts difference too big\n");
- } else if (video_clock > audio_clock + 300 * 90) {
+ } else if (video_clock > audio_clock + VideoAudioDelay + 30 * 90) {
Debug(3, "video: slow down video\n");
decoder->DupNextFrame = 1;
- } else if (audio_clock > video_clock + 300 * 90) {
+ } else if (audio_clock + VideoAudioDelay > video_clock + 50 * 90
+ && filled > 1) {
Debug(3, "video: speed up video\n");
decoder->DropNextFrame = 1;
}
@@ -3502,19 +3506,30 @@ void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx,
// FIXME: move into vaapi module
// update video clock
- decoder->Vaapi.PTS += decoder->Vaapi.Interlaced ? 40 * 90 : 20 * 90;
-
+ if ((uint64_t) decoder->Vaapi.PTS != AV_NOPTS_VALUE) {
+ decoder->Vaapi.PTS += decoder->Vaapi.Interlaced ? 40 * 90 : 20 * 90;
+ }
//pts = frame->best_effort_timestamp;
pts = frame->pkt_pts;
if ((uint64_t) pts == AV_NOPTS_VALUE || !pts) {
+ // libav: 0.8pre didn't set pts
pts = frame->pkt_dts;
}
- // libav: sets only pkt_dts
+ if (!pts) {
+ pts = AV_NOPTS_VALUE;
+ }
+ // build a monotonic pts
+ if ((uint64_t) decoder->Vaapi.PTS != AV_NOPTS_VALUE) {
+ if (pts - decoder->Vaapi.PTS < -10 * 90) {
+ pts = AV_NOPTS_VALUE;
+ }
+ }
+ // libav: sets only pkt_dts which can be 0
if ((uint64_t) pts != AV_NOPTS_VALUE) {
if (decoder->Vaapi.PTS != pts) {
- Debug(4,
+ Debug(3,
"video: %#012" PRIx64 "->%#012" PRIx64 " %4" PRId64 " pts\n",
- decoder->Vaapi.PTS, pts, decoder->Vaapi.PTS - pts);
+ decoder->Vaapi.PTS, pts, pts - decoder->Vaapi.PTS);
decoder->Vaapi.PTS = pts;
}
}
@@ -3557,6 +3572,10 @@ void VideoRenderFrame(VideoHwDecoder * decoder, AVCodecContext * video_ctx,
VaapiSyncDisplayFrame(&decoder->Vaapi);
}
+
+ if (frame->repeat_pict) {
+ Warning("video/vaapi: repeated pict found, but not handle\n");
+ }
#ifdef USE_VAAPI
if (VideoVaapiEnabled) {
VaapiRenderFrame(&decoder->Vaapi, video_ctx, frame);
@@ -3634,7 +3653,8 @@ void VideoDisplayHandler(void)
/**
** Get video clock.
**
-** @note this isn't monoton, decoding reorders frames.
+** @note this isn't monoton, decoding reorders frames,
+** setter keeps it monotonic
*/
int64_t VideoGetClock(void)
{
@@ -3777,6 +3797,16 @@ void VideoSetScaling(int mode)
}
/**
+** Set audio delay.
+**
+** @param ms delay in ms
+*/
+void VideoSetAudioDelay(int ms)
+{
+ VideoAudioDelay = ms * 90;
+}
+
+/**
** Initialize video output module.
**
** @param display_name X11 display name
diff --git a/video.h b/video.h
index 47fcf41..eaacc0a 100644
--- a/video.h
+++ b/video.h
@@ -65,6 +65,9 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
/// Display video TEST
extern void VideoDisplayHandler(void);
+ /// Poll video events
+extern void VideoPollEvent(void);
+
/// set video mode
//extern void VideoSetVideoMode(int, int, int, int);
@@ -77,6 +80,9 @@ extern void VideoSetDeinterlace(int);
/// set scaling
extern void VideoSetScaling(int);
+ /// set audio delay
+extern void VideoSetAudioDelay(int);
+
/// Clear OSD
extern void VideoOsdClear(void);