15 Commits
0.4.5 ... 0.4.6

Author SHA1 Message Date
Johns
00cafd18ed Release Version 0.4.6. 2012-02-02 23:32:51 +01:00
Johns
ab4e89132e Auto-crop improvement and nicer a-v sync display. 2012-02-02 16:01:38 +01:00
Johns
3585f1df19 Increase audio buffer, if bigger audio delay used. 2012-02-02 16:01:08 +01:00
Johns
e258c35537 Makes SkipLines configure in setup menu. 2012-02-02 16:00:26 +01:00
Johns
91dbe46786 Add A-V info output and compile time option. 2012-02-01 23:12:45 +01:00
Johns
a7389111ff Fix bug: VA-API intel software decoder broken. 2012-02-01 18:36:24 +01:00
Johns
27e9a88e2f Video updates and bug fix.
Check if surface is ready in VaapiGetSurface.
Set PTS/DTS only in the first split video packet.
Add support for 4:3 output modes.
Quicker auto-crop after channel switch.
Add auto-crop support for Intel VA-API backend.
Fix bug: Auto-Crop logo skip didn't use displayed width.
2012-02-01 16:50:48 +01:00
Johns
33e9c71aea Removed debug printf. 2012-01-31 20:48:47 +01:00
Johns
bd84e3f3b9 Workaround for mpeg2 FFMpeg+VA-API+Intel GPU hung. 2012-01-31 20:45:09 +01:00
Johns
364cc04736 Fix bug: Only black picture with VA-API hw decoder. 2012-01-30 23:09:53 +01:00
ec4a899bb8 Add support to start the plugin in suspended mode. 2012-01-30 17:03:15 +01:00
Johns
dab31e2367 Finished rewrite of video code, to support modules. 2012-01-30 15:58:21 +01:00
Johns
e613ff1f7e Add aspect change support to software decoder path 2012-01-29 23:57:22 +01:00
Johns
1886b745e5 Repair software decoder with vaapi vdpau backend. 2012-01-29 19:28:46 +01:00
Johns
422c378a5e Add workaround for Intel VA-API MPEG GPU hung. 2012-01-29 11:28:10 +01:00
9 changed files with 1166 additions and 695 deletions

View File

@@ -1,5 +1,37 @@
User johns
Date:
Date: Thu Feb 2 23:29:35 CET 2012
Release Version 0.4.6
Warn only on the first duplicated frame in sequence.
Increase audio buffer, if bigger audio delay is used.
Makes SkipLines configure in setup menu.
Auto-crop only enabled with normal 4:3 display mode.
Vaapi updates OSD when cropping changes.
Add A-V info output and compile time option.
Fix bug: VA-API intel software decoder broken by aspect commit.
Add support for 4:3 output modes.
Quicker auto-crop after channel switch.
Add auto-crop support for Intel VA-API backend.
Fix bug: Auto-Crop logo skip didn't use displayed width.
Workaround for mpeg2 FFMpeg + VA-API + Intel GPU hung.
Fix bug: Missing vaSyncSurface and vaDestroyImage.
Fix bug: Only black picture with VA-API hw decoder.
User HelAu
Date: Mon Jan 30 16:54:47 CET 2012
Add support to start the plugin in suspended mode.
User johns
Date: Mon Jan 30 15:58:21 CET 2012
Finished rewrite of video code, to support output modules.
Add aspect change support to software decoder path.
Repair software decoder with vaapi vdpau backend.
Add workaround for Intel VA-API MPEG GPU hung.
User johns
Date: Sat Jan 28 13:32:12 CET 2012
Release Version 0.4.5
Add configurable skip lines at video top and bottom.

View File

@@ -19,6 +19,7 @@ GIT_REV = $(shell git describe --always 2>/dev/null)
### Configuration (edit this for your needs)
CONFIG := #-DDEBUG
CONFIG += -DAV_INFO
#CONFIG += -DHAVE_PTHREAD_NAME
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")

View File

@@ -146,6 +146,8 @@ Setup: /etc/vdr/setup.conf
if detected crop area is too small, cut max 'n' pixels at top and
bottom.
softhddevice.SkipLines = 0
skip 'n' lines at top and bottom of the video picture.
softhddevice.Suspend.Close = 0
1 suspend closes x11 window, connection and audio device.

21
Todo
View File

@@ -21,11 +21,10 @@ $Id: $
missing:
software deinterlace (yadif, ...)
software decoder with software deinterlace
zoom/fit-zoom 4:3 (SetVideoDisplayFormat, SetVideoFormat?)
ITU BT601, ITU BT709 (HD), RGB studio levels (16-235)?
suspend output / energie saver: stop and restart X11
suspend plugin didn't restore full-screen (is this wanted?)
Option deinterlace off / deinterlace force!
Make output drivers better modular (under construction).
crash:
AudioPlayHandlerThread -> pthread_cond_wait
@@ -38,15 +37,18 @@ video:
suspendoutput didn't show logo or black pictures
(must detect video format to show image)
hard channel switch
skip line not configurable from setup menu.
skip lines not configurable from setup menu.
OSD can only be shown after some stream could be shown
vdpau:
software decoder path not working
libva:
yaepghd (VaapiSetOutputPosition) support
can associate only displayed part of osd
grab image for va-api
still many:
remove stderr output of libva init
still many: (workaround export NO_MPEG_HW=1)
[drm:i915_hangcheck_elapsed] *ERROR* Hangcheck timer elapsed... GPU hung
[drm:i915_wait_request] *ERROR* i915_wait_request returns -11 ...
@@ -54,21 +56,24 @@ libva: branch vaapi-ext
add support for vaapi-ext
libva-intel-driver:
deinterlace only supported with vaapi-ext
1080i does no v-sync (sometimes correct working with vaapi-ext)
OSD has sometimes wrong size (workaround written)
software decoder needs UV swab
sometimes software decoder deinterlace isn't working and 1080i channels
show artefacts
libva-vdpau-driver:
G210/GT520 OSD update too slow (needs hardware problem workaround)
hangup on exit (VaapiDelDecoder -> VaapiCleanup
-> vaDestroyContext -> pthread_rwlock_wrlock)
with auto-crop OSD has wrong position
OSD still has some problems with auto-crop and 4:3 zoom.
libva-xvba-driver:
with auto-crop OSD has wrong position
x11:
disable screensaver
skip multiple configure-notify, handle only the last one.
support embedded mode
audio:
write TS -> PES parser, which feeds audio before the next start packet
@@ -85,6 +90,7 @@ audio/alsa:
audio/oss:
alsa oss emulation mixer "pcm" not working
oss4 mixer channel not working
ring buffer overflow with alsa oss emulation
HDMI/SPDIF Passthrough:
@@ -118,5 +124,6 @@ future features (not planed for 1.0 - 1.5)
atmolight support
multistream handling
pip support
save and use auto-crop with channel zapping
upmix stereo to AC-3

25
audio.c
View File

@@ -137,7 +137,7 @@ static unsigned AudioSampleRate; ///< audio sample rate in hz
static unsigned AudioChannels; ///< number of audio channels
static const int AudioBytesProSample = 2; ///< number of bytes per sample
static int64_t AudioPTS; ///< audio pts clock
static const int AudioBufferTime = 450; ///< audio buffer time in ms
static const int AudioBufferTime = 350; ///< audio buffer time in ms
#ifdef USE_AUDIO_THREAD
static pthread_t AudioThread; ///< audio play thread
@@ -147,6 +147,8 @@ static pthread_cond_t AudioStartCond; ///< condition variable
static const int AudioThread; ///< dummy audio thread
#endif
extern int VideoAudioDelay; /// import audio/video delay
#ifdef USE_AUDIORING
//----------------------------------------------------------------------------
@@ -900,6 +902,7 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
snd_pcm_uframes_t period_size;
int err;
int ret;
int delay;
snd_pcm_t *handle;
if (!AlsaPCMHandle) { // alsa not running yet
@@ -1085,11 +1088,14 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
AlsaStartThreshold = snd_pcm_frames_to_bytes(AlsaPCMHandle, period_size);
// buffer time/delay in ms
delay = AudioBufferTime;
if (VideoAudioDelay > -100) {
delay += 100 + VideoAudioDelay / 90;
}
if (AlsaStartThreshold <
(*freq * *channels * AudioBytesProSample * AudioBufferTime) / 1000U) {
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
AlsaStartThreshold =
(*freq * *channels * AudioBytesProSample * AudioBufferTime) /
1000U;
(*freq * *channels * AudioBytesProSample * delay) / 1000U;
}
// no bigger, than the buffer
if (AlsaStartThreshold > RingBufferFreeBytes(AlsaRingBuffer)) {
@@ -1622,6 +1628,7 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
{
int ret;
int tmp;
int delay;
if (OssPcmFildes == -1) { // OSS not ready
return -1;
@@ -1708,12 +1715,14 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
// start when enough bytes for initial write
OssStartThreshold = bi.bytes + tmp;
// buffer time/delay in ms
delay = AudioBufferTime;
if (VideoAudioDelay > -100) {
delay += 100 + VideoAudioDelay / 90;
}
if (OssStartThreshold <
(*freq * *channels * AudioBytesProSample * AudioBufferTime) /
1000U) {
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
OssStartThreshold =
(*freq * *channels * AudioBytesProSample * AudioBufferTime) /
1000U;
(*freq * *channels * AudioBytesProSample * delay) / 1000U;
}
// no bigger, than the buffer
if (OssStartThreshold > RingBufferFreeBytes(OssRingBuffer)) {

View File

@@ -61,6 +61,8 @@ static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
#endif
static char ConfigFullscreen; ///< fullscreen modus
static char ConfigStartSuspended; ///< flag to start in suspend mode
static char ConfigStartX11Server; ///< flag start the x11 server
static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex
@@ -485,6 +487,50 @@ static void VideoNextPacket(int codec_id)
avpkt->dts = AV_NOPTS_VALUE;
}
/**
** Fix packet for FFMpeg.
**
** Some tv-stations sends mulitple pictures in a singe PES packet.
** Current ffmpeg 0.10 and libav-0.8 has problems with this.
** Split the packet into single picture packets.
*/
void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
{
uint8_t *p;
int n;
AVPacket tmp[1];
int first;
p = avpkt->data;
n = avpkt->size;
*tmp = *avpkt;
first = 1;
while (n > 4) {
// scan for picture header 0x00000100
if (!p[0] && !p[1] && p[2] == 0x01 && !p[3]) {
if (first) {
first = 0;
n -= 4;
p += 4;
continue;
}
// packet has already an picture header
tmp->size = p - tmp->data;
CodecVideoDecode(MyVideoDecoder, tmp);
// time-stamp only valid for first packet
tmp->pts = AV_NOPTS_VALUE;
tmp->dts = AV_NOPTS_VALUE;
tmp->data = p;
tmp->size = n;
}
--n;
++p;
}
CodecVideoDecode(MyVideoDecoder, tmp);
}
/**
** Decode from PES packet ringbuffer.
*/
@@ -559,7 +605,33 @@ int VideoDecode(void)
avpkt->size = avpkt->stream_index;
avpkt->stream_index = 0;
CodecVideoDecode(MyVideoDecoder, avpkt);
if (0) {
static int done;
if (done < 2) {
int fildes;
int who_designed_this_is____;
if (done == 0)
fildes =
open("frame0.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
else if (done == 1)
fildes =
open("frame1.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
else
fildes =
open("frame2.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
done++;
who_designed_this_is____ = write(fildes, avpkt->data, avpkt->size);
close(fildes);
}
}
if (last_codec_id == CODEC_ID_MPEG2VIDEO) {
FixPacketForFFMpeg(MyVideoDecoder, avpkt);
} else {
CodecVideoDecode(MyVideoDecoder, avpkt);
}
avpkt->size = saved_size;
@@ -894,6 +966,10 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
*/
void SetPlayMode(void)
{
if (ConfigStartSuspended) { // ignore first call, if start suspended
ConfigStartSuspended = 0;
return;
}
Resume();
if (MyVideoDecoder) {
if (VideoCodecID != CODEC_ID_NONE) {
@@ -1079,8 +1155,6 @@ void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb)
//////////////////////////////////////////////////////////////////////////////
static char ConfigStartX11Server; ///< flag start the x11 server
/**
** Return command line help string.
*/
@@ -1091,7 +1165,7 @@ const char *CommandLineHelp(void)
" -d display\tdisplay of x11 server (fe. :0.0)\n"
" -f\t\tstart with fullscreen window (only with window manager)\n"
" -g geometry\tx11 window geometry wxh+x+y\n"
" -x\t\tstart x11 server\n";
" -x\t\tstart x11 server\n" " -s\t\tstart in suspended mode\n";
}
/**
@@ -1106,7 +1180,7 @@ int ProcessArgs(int argc, char *const argv[])
// Parse arguments.
//
for (;;) {
switch (getopt(argc, argv, "-a:p:d:fg:x")) {
switch (getopt(argc, argv, "-a:p:d:fg:xs")) {
case 'a': // audio device
AudioSetDevice(optarg);
continue;
@@ -1130,6 +1204,9 @@ int ProcessArgs(int argc, char *const argv[])
case 'x': // x11 server
ConfigStartX11Server = 1;
continue;
case 's': // start in suspend mode
ConfigStartSuspended = 1;
continue;
case EOF:
break;
case '-':
@@ -1311,15 +1388,19 @@ void Start(void)
}
CodecInit();
// FIXME: AudioInit for HDMI after X11 startup
AudioInit();
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
if (!ConfigStartSuspended) {
// FIXME: AudioInit for HDMI after X11 startup
AudioInit();
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
if (!ConfigStartX11Server) {
StartVideo();
if (!ConfigStartX11Server) {
StartVideo();
}
} else {
SkipVideo = 1;
SkipAudio = 1;
}
pthread_mutex_init(&SuspendLockMutex, NULL);
}

View File

@@ -42,7 +42,7 @@ extern "C"
//////////////////////////////////////////////////////////////////////////////
static const char *const VERSION = "0.4.5";
static const char *const VERSION = "0.4.6";
static const char *const DESCRIPTION =
trNOOP("A software and GPU emulated HD device");
@@ -61,6 +61,8 @@ static const char *const Resolution[RESOLUTIONS] = {
static char ConfigMakePrimary; ///< config primary wanted
static char ConfigHideMainMenuEntry; ///< config hide main menu entry
static int ConfigVideoSkipLines; ///< config skip lines top/bottom
/// config deinterlace
static int ConfigVideoDeinterlace[RESOLUTIONS];
@@ -77,7 +79,6 @@ static int ConfigVideoSharpen[RESOLUTIONS];
static int ConfigVideoScaling[RESOLUTIONS];
static int ConfigVideoAudioDelay; ///< config audio delay
static int ConfigVideoSkipLines; ///< config skip lines top/bottom
static int ConfigAudioPassthrough; ///< config audio pass-through
static int ConfigAutoCropInterval; ///< auto crop detection interval
@@ -364,6 +365,7 @@ class cMenuSetupSoft:public cMenuSetupPage
protected:
int MakePrimary;
int HideMainMenuEntry;
int SkipLines;
int Scaling[RESOLUTIONS];
int Deinterlace[RESOLUTIONS];
int SkipChromaDeinterlace[RESOLUTIONS];
@@ -428,6 +430,11 @@ cMenuSetupSoft::cMenuSetupSoft(void)
// video
//
Add(SeparatorItem(tr("Video")));
SkipLines = ConfigVideoSkipLines;
Add(new cMenuEditIntItem(tr("Skip lines top+bot (pixel)"), &SkipLines, 0,
64));
for (i = 0; i < RESOLUTIONS; ++i) {
Add(SeparatorItem(resolution[i]));
Scaling[i] = ConfigVideoScaling[i];
@@ -491,6 +498,9 @@ void cMenuSetupSoft::Store(void)
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
HideMainMenuEntry);
SetupStore("SkipLines", ConfigVideoSkipLines = SkipLines);
VideoSetSkipLines(ConfigVideoSkipLines);
for (i = 0; i < RESOLUTIONS; ++i) {
char buf[128];
@@ -520,8 +530,10 @@ void cMenuSetupSoft::Store(void)
SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval);
SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay);
SetupStore("AutoCrop.Tolerance", ConfigAutoCropTolerance = AutoCropTolerance);
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay, ConfigAutoCropTolerance);
SetupStore("AutoCrop.Tolerance", ConfigAutoCropTolerance =
AutoCropTolerance);
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay,
ConfigAutoCropTolerance);
SetupStore("Suspend.Close", ConfigSuspendClose = SuspendClose);
SetupStore("Suspend.X11", ConfigSuspendX11 = SuspendX11);
@@ -625,6 +637,7 @@ class cSoftHdDevice:public cDevice
virtual bool Poll(cPoller &, int = 0);
virtual bool Flush(int = 0);
virtual int64_t GetSTC(void);
virtual void SetVideoDisplayFormat(eVideoDisplayFormat);
virtual void GetVideoSize(int &, int &, double &);
virtual void GetOsdSize(int &, int &, double &);
virtual int PlayVideo(const uchar *, int);
@@ -740,6 +753,10 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
return true;
}
/**
** Gets the current System Time Counter, which can be used to
** synchronize audio, video and subtitles.
*/
int64_t cSoftHdDevice::GetSTC(void)
{
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
@@ -843,6 +860,28 @@ bool cSoftHdDevice::Flush(int timeout_ms)
// ----------------------------------------------------------------------------
/**
** Sets the video display format to the given one (only useful if this
** device has an MPEG decoder).
**
** @note FIXME: this function isn't called on the initial channel
*/
void cSoftHdDevice::
SetVideoDisplayFormat(eVideoDisplayFormat video_display_format)
{
static int last = -1;
cDevice::SetVideoDisplayFormat(video_display_format);
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, video_display_format);
// called on every channel switch, no need to kill osd...
if (last != video_display_format) {
last = video_display_format;
::VideoSetDisplayFormat(video_display_format);
}
}
/**
** Returns the width, height and video_aspect ratio of the currently
** displayed video material.
@@ -1168,6 +1207,10 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
ConfigHideMainMenuEntry = atoi(value);
return true;
}
if (!strcmp(name, "SkipLines")) {
VideoSetSkipLines(ConfigVideoSkipLines = atoi(value));
return true;
}
for (i = 0; i < RESOLUTIONS; ++i) {
char buf[128];
@@ -1204,10 +1247,6 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
}
}
if (!strcmp(name, "SkipLines")) {
VideoSetSkipLines(ConfigVideoSkipLines = atoi(value));
return true;
}
if (!strcmp(name, "AudioDelay")) {
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
return true;
@@ -1228,7 +1267,8 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
return true;
}
if (!strcmp(name, "AutoCrop.Tolerance")) {
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay, ConfigAutoCropTolerance = atoi(value));
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay,
ConfigAutoCropTolerance = atoi(value));
return true;
}
@@ -1268,10 +1308,8 @@ const char **cPluginSoftHdDevice::SVDRPHelpPages(void)
{
// FIXME: translation?
static const char *text[] = {
"SUSP\n"
" Suspend plugin.\n",
"RESU\n"
" Resume plugin.\n",
"SUSP\n" " Suspend plugin.\n",
"RESU\n" " Resume plugin.\n",
NULL
};

1593
video.c

File diff suppressed because it is too large Load Diff

16
video.h
View File

@@ -47,16 +47,17 @@ extern unsigned VideoGetSurface(VideoHwDecoder *);
extern void VideoReleaseSurface(VideoHwDecoder *, unsigned);
#ifdef LIBAVCODEC_VERSION
/// Render a ffmpeg frame.
extern void VideoRenderFrame(VideoHwDecoder *, AVCodecContext *, AVFrame *);
/// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
/// Callback to negotiate the PixelFormat.
extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
const enum PixelFormat *);
/// Render a ffmpeg frame.
extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
const AVFrame *);
/// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
#ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state.
extern void VideoDrawRenderState(VideoHwDecoder *,
@@ -79,6 +80,9 @@ extern void VideoSetOutputPosition(int, int, int, int);
/// Set video mode.
extern void VideoSetVideoMode(int, int, int, int);
/// Set display format.
extern void VideoSetDisplayFormat(int);
/// Set video fullscreen mode.
extern void VideoSetFullscreen(int);