8 Commits
0.2.0 ... 0.3.0

Author SHA1 Message Date
Johns
8d624224e9 Version 0.3.0 released. 2012-01-09 22:10:42 +01:00
Johns
96eefca699 Video improvements.
Fix generate of video output from StillPicture.
Add support for resolution dependend video parameterts (Deinterlace,
Scaling, Denoise, Sharpen, ...).
2012-01-09 17:03:04 +01:00
Johns
5e005eeff5 Fix audio crash in ThreadExit and snd_pcm_prepare. 2012-01-09 15:31:47 +01:00
Johns
f6df79e8e6 Improved replay of recordings. 2012-01-08 21:46:00 +01:00
Johns
f1551cd321 Ebuild bug fix. 2012-01-08 14:19:48 +01:00
Johns
9568c5bd93 Fix build with vdr without yaepg support. 2012-01-07 23:47:07 +01:00
Johns
fd60c3c132 Support yaepghd video output position change.
And code and comments cleanups.
2012-01-07 22:36:06 +01:00
Johns
7b6d0ecf94 Gentoo ebuild. 2012-01-07 17:30:27 +01:00
13 changed files with 1058 additions and 541 deletions

View File

@@ -1,5 +1,15 @@
User johns
Data: Sat Jan 7 13:20:07 CET 2012
Date: Mon Jan 9 22:09:38 CET 2012
Release Version 0.3.0
Add support of resolution dependend video parameters (deint, scale, ...).
Add support for recording play back.
Add workaround for alsa crash in snd_pcm_prepare.
Fix bug: audio crash on exit.
Fix build with vdr without yaepg support.
Support yaepghd video picture output position change.
Date: Sat Jan 7 13:20:07 CET 2012
Release Version 0.2.0
Add support for ac3 audio pass through.

View File

@@ -95,23 +95,27 @@ Setup: /etc/vdr/setup.conf
softhddevice.MakePrimary = 1
0 = no change, 1 make softhddevice primary at start
softhddevice.Deinterlace = 0
<res> of the next parameters is 567i, 720p, 1080i_fake or 1080i.
1080i_fake is 1280x1080 or 1440x1080
1080i is "real" 1920x1080
softhddevice.<res>.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.<res>.Deinterlace = 0
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
(only 0, 1 supported with vaapi)
softhddevice.SkipChromaDeinterlace = 0
softhddevice.<res>.SkipChromaDeinterlace = 0
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
softhddevice.Denoise = 0
softhddevice.<res>.Denoise = 0
0 .. 1000 noise reduction level (0 off, 1000 max)
softhddevice.Sharpness = 0
softhddevice.<res>.Sharpness = 0
-1000 .. 1000 noise reduction level (0 off, -1000 max blur,
1000 max sharp)
softhddevice.Scaling = 0
0 = normal, 1 = fast, 2 = HQ, 3 = anamorphic
softhddevice.AudioDelay = 0
+n or -n ms

5
Todo
View File

@@ -41,6 +41,7 @@ vdpau:
libva:
hard channel switch
yaepghd (VaapiSetOutputPosition) support
libva-intel-driver:
intel still has hangups most with 1080i
@@ -79,10 +80,11 @@ audio/oss:
HDMI/SPDIF Passthrough:
only AC-3 written
Channels are wrong setup, if changing setting during operation.
playback of recording
play back is too fast
pause is not reset, when replay exit
replay/pause need 100% cpu
setup:
Setup of decoder type.
@@ -91,3 +93,4 @@ setup:
Setup 4:3 zoom type
Setup parameters are not used until restart.
Can a notice be added to the setup menu?
576i, 720p, fake 1080i, 1080i

108
audio.c
View File

@@ -296,6 +296,7 @@ static int AlsaPlayRingbuffer(void)
if (first) {
// happens with broken alsa drivers
Error(_("audio/alsa: broken driver %d\n"), avail);
usleep(5 * 1000);
}
Debug(4, "audio/alsa: break state %s\n",
snd_pcm_state_name(snd_pcm_state(AlsaPCMHandle)));
@@ -342,6 +343,11 @@ static int AlsaPlayRingbuffer(void)
if (err == -EAGAIN) {
goto again;
}
/*
if (err == -EBADFD) {
goto again;
}
*/
Error(_("audio/alsa: underrun error?\n"));
err = snd_pcm_recover(AlsaPCMHandle, err, 0);
if (err >= 0) {
@@ -368,11 +374,21 @@ static int AlsaPlayRingbuffer(void)
static void AlsaFlushBuffers(void)
{
int err;
snd_pcm_state_t state;
RingBufferReadAdvance(AlsaRingBuffer, RingBufferUsedBytes(AlsaRingBuffer));
if ((err = snd_pcm_drop(AlsaPCMHandle))) {
state = snd_pcm_state(AlsaPCMHandle);
Debug(3, "audio/alsa: state %d - %s\n", state, snd_pcm_state_name(state));
if (state != SND_PCM_STATE_OPEN) {
if ((err = snd_pcm_drop(AlsaPCMHandle)) < 0) {
Error(_("audio: snd_pcm_drop(): %s\n"), snd_strerror(err));
}
// ****ing alsa crash, when in open state here
if ((err = snd_pcm_prepare(AlsaPCMHandle)) < 0) {
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
}
}
AudioPTS = INT64_C(0x8000000000000000);
}
#if 0
@@ -567,8 +583,20 @@ static void AlsaThread(void)
for (;;) {
int err;
Debug(4, "audio: play loop\n");
pthread_testcancel();
if (AlsaFlushBuffer) {
// we can flush too many, but wo cares
Debug(3, "audio/alsa: flushing buffers\n");
AlsaFlushBuffers();
/*
if ((err = snd_pcm_prepare(AlsaPCMHandle))) {
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
}
*/
AlsaFlushBuffer = 0;
break;
}
// wait for space in kernel buffers
if ((err = snd_pcm_wait(AlsaPCMHandle, 100)) < 0) {
Error(_("audio/alsa: wait underrun error?\n"));
err = snd_pcm_recover(AlsaPCMHandle, err, 0);
@@ -580,14 +608,7 @@ static void AlsaThread(void)
continue;
}
if (AlsaFlushBuffer) {
// we can flush too many, but wo cares
Debug(3, "audio/alsa: flushing buffers\n");
AlsaFlushBuffers();
if ((err = snd_pcm_prepare(AlsaPCMHandle))) {
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
}
AlsaFlushBuffer = 0;
break;
continue;
}
if ((err = AlsaPlayRingbuffer())) { // empty / error
snd_pcm_state_t state;
@@ -600,7 +621,8 @@ static void AlsaThread(void)
Debug(3, "audio/alsa: stopping play\n");
break;
}
usleep(20 * 1000);
pthread_yield();
usleep(20 * 1000); // let fill the buffers
}
}
}
@@ -1195,6 +1217,21 @@ static int OssPlayRingbuffer(void)
return 0;
}
/**
** Flush oss buffers.
*/
static void OssFlushBuffers(void)
{
RingBufferReadAdvance(OssRingBuffer, RingBufferUsedBytes(OssRingBuffer));
// flush kernel buffers
if (ioctl(OssPcmFildes, SNDCTL_DSP_HALT_OUTPUT, NULL) < 0) {
Error(_("audio/oss: ioctl(SNDCTL_DSP_HALT_OUTPUT): %s\n"),
strerror(errno));
return;
}
AudioPTS = INT64_C(0x8000000000000000);
}
//----------------------------------------------------------------------------
// OSS pcm polled
//----------------------------------------------------------------------------
@@ -1410,14 +1447,7 @@ static int OssSetup(int *freq, int *channels)
// flush any buffered data
{
AudioRunning = 0;
RingBufferReadAdvance(OssRingBuffer,
RingBufferUsedBytes(OssRingBuffer));
// flush kernel buffers
if (ioctl(OssPcmFildes, SNDCTL_DSP_HALT_OUTPUT, NULL) == -1) {
Error(_("audio/oss: ioctl(SNDCTL_DSP_HALT_OUTPUT): %s\n"),
strerror(errno));
return -1;
}
OssFlushBuffers();
}
AudioPTS = INT64_C(0x8000000000000000);
@@ -1639,6 +1669,7 @@ static void AudioExitThread(void)
{
void *retval;
if (AudioThread) {
if (pthread_cancel(AudioThread)) {
Error(_("audio: can't queue cancel play thread\n"));
}
@@ -1648,6 +1679,7 @@ static void AudioExitThread(void)
pthread_cond_destroy(&AudioStartCond);
pthread_mutex_destroy(&AudioMutex);
}
}
#endif
@@ -1672,6 +1704,30 @@ void AudioEnqueue(const void *samples, int count)
(void)count;
}
/**
** Flush audio buffers.
*/
void AudioFlushBuffers(void)
{
#ifdef USE_ALSA
#ifdef USE_AUDIO_THREAD
if (AudioRunning) {
while (AudioRunning) {
AlsaFlushBuffer = 1;
usleep(1 * 1000);
}
AlsaFlushBuffer = 0;
} else
#endif
{
AlsaFlushBuffers();
}
#endif
#ifdef USE_OSS
OssFlushBuffers();
#endif
}
/**
** Call back to play audio polled.
*/
@@ -1687,6 +1743,20 @@ void AudioPoller(void)
#endif
}
/**
** Get free bytes in audio output.
*/
int AudioFreeBytes(void)
{
#ifdef USE_ALSA
return RingBufferFreeBytes(AlsaRingBuffer);
#endif
#ifdef USE_OSS
return RingBufferFreeBytes(OssRingBuffer);
#endif
return -1;
}
/**
** Set audio clock base.
**

View File

@@ -1,7 +1,7 @@
///
/// @file audio.h @brief Audio module headerfile
///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -28,12 +28,14 @@
//----------------------------------------------------------------------------
extern void AudioEnqueue(const void *, int); ///< buffer audio samples
extern void AudioFlushBuffers(void); ///< flush audio buffers
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 void AudioSetClock(int64_t); ///< set audio clock base
extern int64_t AudioGetClock(); ///< get current audio clock
extern uint64_t AudioGetDelay(void); ///< get current audio delay
extern int AudioSetup(int *, int *); ///< setup audio output

23
codec.c
View File

@@ -561,6 +561,16 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
}
}
/**
** Flush the video decoder.
**
** @param decoder video decoder data
*/
void CodecVideoFlushBuffers(VideoDecoder * decoder)
{
avcodec_flush_buffers(decoder->VideoCtx);
}
//----------------------------------------------------------------------------
// Audio
//----------------------------------------------------------------------------
@@ -738,9 +748,11 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
spkt->pts = avpkt->pts;
spkt->dts = avpkt->dts;
#endif
#ifdef DEBUG
if (!audio_decoder->AudioParser) {
Fatal(_("codec: internal error parser freeded while running\n"));
}
#endif
audio_ctx = audio_decoder->AudioCtx;
index = 0;
@@ -1026,6 +1038,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#endif
/**
** Flush the audio decoder.
**
** @param decoder audio decoder data
*/
void CodecAudioFlushBuffers(AudioDecoder * decoder)
{
// FIXME: reset audio parser
avcodec_flush_buffers(decoder->AudioCtx);
}
//----------------------------------------------------------------------------
// Codec
//----------------------------------------------------------------------------

24
codec.h
View File

@@ -1,7 +1,7 @@
///
/// @file codec.h @brief Codec module headerfile
///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved.
/// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -40,26 +40,32 @@ typedef struct _audio_decoder_ AudioDecoder;
/// Allocate a new video decoder context.
extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
/// Open video codec
/// Open video codec.
extern void CodecVideoOpen(VideoDecoder *, const char *, int);
/// Close video codec
/// Close video codec.
extern void CodecVideoClose(VideoDecoder *);
/// Decode a video packet
extern void CodecVideoDecode(VideoDecoder *, const AVPacket * pkt);
/// Decode a video packet.
extern void CodecVideoDecode(VideoDecoder *, const AVPacket *);
/// Flush video buffers.
extern void CodecVideoFlushBuffers(VideoDecoder *);
/// Allocate a new audio decoder context.
extern AudioDecoder *CodecAudioNewDecoder(void);
/// Open audio codec
/// Open audio codec.
extern void CodecAudioOpen(AudioDecoder *, const char *, int);
/// Close audio codec
/// Close audio codec.
extern void CodecAudioClose(AudioDecoder *);
/// Decode an audio packet
extern void CodecAudioDecode(AudioDecoder *, const AVPacket * pkt);
/// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);
/// Flush audio buffers.
extern void CodecAudioFlushBuffers(AudioDecoder *);
/// Setup and initialize codec module.
extern void CodecInit(void);

View File

@@ -59,11 +59,10 @@ static const char DeviceStopped = 1; ///< flag device stopped
//////////////////////////////////////////////////////////////////////////////
static volatile char NewAudioStream; ///< new audio stream
static volatile char SkipAudio; ///< skip audio stream
static AudioDecoder *MyAudioDecoder; ///< audio decoder
static enum CodecID AudioCodecID; ///< current codec id
extern void AudioTest(void); // FIXME:
/**
** mpeg bitrate table.
**
@@ -187,10 +186,11 @@ static int FindAudioSync(const AVPacket * avpkt)
** @param size size of PES packet
** @param id PES packet type
*/
void PlayAudio(const uint8_t * data, int size,
int PlayAudio(const uint8_t * data, int size,
__attribute__ ((unused)) uint8_t id)
{
int n;
int osize;
AVPacket avpkt[1];
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
@@ -201,12 +201,19 @@ void PlayAudio(const uint8_t * data, int size,
AudioCodecID = CODEC_ID_NONE;
NewAudioStream = 0;
}
if (SkipAudio) {
return size;
}
// PES header 0x00 0x00 0x01 ID
// ID 0xBD 0xC0-0xCF
if (size < 9) {
Error(_("[softhddev] invalid audio packet\n"));
return;
return size;
}
// Don't overrun audio buffers on replay
if (AudioFreeBytes() < 3072 * 8 * 8) { // 8 channels 8 packets
return 0;
}
n = data[8]; // header size
@@ -227,11 +234,12 @@ void PlayAudio(const uint8_t * data, int size,
}
}
osize = size;
data += 9 + n;
size -= 9 + n; // skip pes header
if (size <= 0) {
Error(_("[softhddev] invalid audio packet\n"));
return;
return osize;
}
// Detect audio code
// MPEG-PS mp2 MPEG1, MPEG2, AC3
@@ -273,7 +281,7 @@ void PlayAudio(const uint8_t * data, int size,
avpkt->size = size;
n = FindAudioSync(avpkt);
if (n < 0) {
return;
return osize;
}
if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder();
@@ -288,13 +296,15 @@ void PlayAudio(const uint8_t * data, int size,
// no decoder or codec known
if (!MyAudioDecoder || AudioCodecID == CODEC_ID_NONE) {
return;
return osize;
}
avpkt->data = (void *)data;
avpkt->size = size;
//memset(avpkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
CodecAudioDecode(MyAudioDecoder, avpkt);
return osize;
}
/**
@@ -302,6 +312,7 @@ void PlayAudio(const uint8_t * data, int size,
*/
void Mute(void)
{
SkipAudio = 1;
AudioSetVolume(0);
}
@@ -351,8 +362,6 @@ static void VideoPacketInit(void)
{
int i;
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
AVPacket *avpkt;
@@ -374,16 +383,10 @@ static void VideoPacketExit(void)
{
int i;
Debug(4, "[softhddev]: %s\n", __FUNCTION__);
atomic_set(&VideoPacketsFilled, 0);
for (i = 0; i < VIDEO_PACKET_MAX; ++i) {
AVPacket *avpkt;
avpkt = &VideoPacketRb[i];
// build a clean ffmpeg av packet
av_free_packet(avpkt);
av_free_packet(&VideoPacketRb[i]);
}
}
@@ -466,13 +469,13 @@ static void VideoNextPacket(int codec_id)
VideoPacketWrite = (VideoPacketWrite + 1) % VIDEO_PACKET_MAX;
atomic_inc(&VideoPacketsFilled);
VideoDisplayWakeup();
// intialize next package to use
avpkt = &VideoPacketRb[VideoPacketWrite];
avpkt->stream_index = 0;
avpkt->pts = AV_NOPTS_VALUE;
avpkt->dts = AV_NOPTS_VALUE;
VideoDisplayHandler();
}
/**
@@ -490,6 +493,10 @@ int VideoDecode(void)
}
if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
}
VideoClearBuffers = 0;
return 1;
}
@@ -761,18 +768,29 @@ void SetPlayMode(void)
}
}
if (MyAudioDecoder) {
if (AudioCodecID != CODEC_ID_NONE) {
NewAudioStream = 1;
}
}
VideoFreezed = 0;
SkipAudio = 0;
}
/**
** Clears all video and audio data from the device.
*/
void Clear(void)
{
int i;
VideoNextPacket(VideoCodecID); // terminate work
VideoClearBuffers = 1;
// FIXME: avcodec_flush_buffers
// FIXME: flush audio buffers
AudioFlushBuffers();
for (i = 0; VideoClearBuffers && i < 20; ++i) {
usleep(1 * 1000);
}
}
/**
@@ -781,6 +799,7 @@ void Clear(void)
void Play(void)
{
VideoFreezed = 0;
SkipAudio = 0;
// FIXME: restart audio
}
@@ -791,16 +810,38 @@ void Freeze(void)
{
VideoFreezed = 1;
// FIXME: freeze audio
AudioFlushBuffers();
}
/**
** Display the given I-frame as a still picture.
*/
void StillPicture(const uint8_t * data, int size)
{
int i;
// must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
Error(_("[softhddev] invalid PES video packet\n"));
return;
}
Clear(); // flush video buffers
// +1 future for deinterlace
for (i = -1; i < (VideoCodecID == CODEC_ID_MPEG2VIDEO ? 3 : 17); ++i) {
PlayVideo(data, size); // reference frames
}
VideoNextPacket(VideoCodecID); // terminate last packet
}
/**
** Poll if device is ready. Called by replay.
**
** @param timeout timeout to become ready in ms
*/
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);
@@ -810,6 +851,22 @@ int Poll(int timeout)
return 0;
}
/**
** Flush the device output buffers.
**
** @param timeout timeout to flush in ms
*/
int Flush(int timeout)
{
if (atomic_read(&VideoPacketsFilled)) {
if (timeout) { // let display thread work
usleep(timeout * 1000);
}
return !atomic_read(&VideoPacketsFilled);
}
return 1;
}
//////////////////////////////////////////////////////////////////////////////
// OSD
//////////////////////////////////////////////////////////////////////////////
@@ -819,7 +876,9 @@ int Poll(int timeout)
*/
void GetOsdSize(int *width, int *height, double *aspect)
{
#ifdef DEBUG
static char done;
#endif
// FIXME: should be configured!
*width = 1920;
@@ -829,11 +888,13 @@ void GetOsdSize(int *width, int *height, double *aspect)
*aspect = 16.0 / 9.0 / (double)*width * (double)*height;
#ifdef DEBUG
if (!done) {
Debug(3, "[softhddev]%s: %dx%d %g\n", __FUNCTION__, *width, *height,
*aspect);
done = 1;
}
#endif
}
/**
@@ -861,10 +922,10 @@ static char StartX11Server; ///< flag start the x11 server
*/
const char *CommandLineHelp(void)
{
return " -a device\talsa audio device (fe. hw:0,0)\n"
" -d display\tdisplay of x11 server (f.e :0.0)\n"
return " -a device\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\n"
" -d display\tdisplay of x11 server (fe. :0.0)\n"
" -g geometry\tx11 window geometry wxh+x+y\n"
" -x\tstart x11 server\n";
" -x\t\tstart x11 server\n";
}
/**
@@ -1076,7 +1137,4 @@ void Stop(void)
*/
void MainThreadHook(void)
{
if (!DeviceStopped) {
VideoDisplayHandler();
}
}

View File

@@ -1,7 +1,7 @@
///
/// @file softhddev.h @brief software HD device plugin header file.
///
/// Copyright (c) 2011 by Johns. All Rights Reserved.
/// Copyright (c) 2011 - 2012 by Johns. All Rights Reserved.
///
/// Contributor(s):
///
@@ -36,7 +36,7 @@ extern "C"
extern void OsdDrawARGB(int, int, int, int, const uint8_t *);
/// C plugin play audio packet
extern void PlayAudio(const uint8_t *, int, uint8_t);
extern int PlayAudio(const uint8_t *, int, uint8_t);
/// C plugin mute audio
extern void Mute(void);
/// C plugin set audio volume
@@ -55,8 +55,12 @@ extern "C"
extern void Play(void);
/// C plugin sets the device into "freeze frame" mode
extern void Freeze(void);
/// C plugin display I-frame as a still picture.
extern void StillPicture(const uint8_t *, int);
/// C plugin poll if ready
extern int Poll(int);
/// C plugin flush output buffers
extern int Flush(int);
/// C plugin command line help
extern const char *CommandLineHelp(void);

View File

@@ -42,7 +42,7 @@ extern "C"
//////////////////////////////////////////////////////////////////////////////
static const char *const VERSION = "0.2.0";
static const char *const VERSION = "0.3.0";
static const char *const DESCRIPTION =
trNOOP("A software and GPU emulated HD device");
@@ -51,14 +51,32 @@ static class cSoftHdDevice *MyDevice;
//////////////////////////////////////////////////////////////////////////////
#define RESOLUTIONS 4 ///< number of resolutions
static const char *const Resolution[RESOLUTIONS] = {
"576i", "720p", "1080i_fake", "1080i"
};
static char ConfigMakePrimary; ///< config primary wanted
static char ConfigVideoDeinterlace; ///< config deinterlace
static char ConfigVideoSkipChromaDeinterlace; ///< config skip chroma
static int ConfigVideoDenoise; ///< config denoise
static int ConfigVideoSharpen; ///< config sharpen
static char ConfigVideoScaling; ///< config scaling
/// config deinterlace
static int ConfigVideoDeinterlace[RESOLUTIONS];
/// config skip chroma
static int ConfigVideoSkipChromaDeinterlace[RESOLUTIONS];
/// config denoise
static int ConfigVideoDenoise[RESOLUTIONS];
/// config sharpen
static int ConfigVideoSharpen[RESOLUTIONS];
/// config scaling
static int ConfigVideoScaling[RESOLUTIONS];
static int ConfigVideoAudioDelay; ///< config audio delay
static int ConfigAudioPassthrough; ///< config audio pass-through
static volatile char DoMakePrimary; ///< flag switch primary
//////////////////////////////////////////////////////////////////////////////
@@ -135,6 +153,11 @@ cSoftOsd::~cSoftOsd(void)
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
SetActive(false);
#ifdef USE_YAEPG
if (vidWin.bpp) {
VideoSetOutputPosition(0, 0, 1920, 1080);
}
#endif
OsdClose();
}
@@ -148,7 +171,18 @@ void cSoftOsd::Flush(void)
if (!Active()) {
return;
}
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
// support yaepghd, video window
#ifdef USE_YAEPG
if (vidWin.bpp) {
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
vidWin.Height(), vidWin.x1, vidWin.y2);
// FIXME: vidWin is OSD relative not video window.
VideoSetOutputPosition(Left() + vidWin.x1, Top() + vidWin.y1,
vidWin.Width(), vidWin.Height());
}
#endif
if (!IsTrueColor()) {
static char warned;
cBitmap *bitmap;
@@ -255,6 +289,9 @@ bool cSoftOsdProvider::ProvidesTrueColor(void)
return true;
}
/**
** Create cOsdProvider class.
*/
cSoftOsdProvider::cSoftOsdProvider(void)
: cOsdProvider()
{
@@ -269,11 +306,11 @@ class cMenuSetupSoft:public cMenuSetupPage
{
protected:
int MakePrimary;
int Deinterlace;
int SkipChromaDeinterlace;
int Denoise;
int Sharpen;
int Scaling;
int Scaling[RESOLUTIONS];
int Deinterlace[RESOLUTIONS];
int SkipChromaDeinterlace[RESOLUTIONS];
int Denoise[RESOLUTIONS];
int Sharpen[RESOLUTIONS];
int AudioDelay;
int AudioPassthrough;
protected:
@@ -282,6 +319,19 @@ class cMenuSetupSoft:public cMenuSetupPage
cMenuSetupSoft(void);
};
/**
** Create a seperator item.
*/
static inline cOsdItem *SeparatorItem(const char *label)
{
cOsdItem *item;
item = new cOsdItem(cString::sprintf("* %s: ", label));
item->SetSelectable(false);
return item;
}
/**
** Constructor setup menu.
*/
@@ -296,26 +346,41 @@ cMenuSetupSoft::cMenuSetupSoft(void)
static const char *const passthrough[] = {
"None", "AC-3"
};
static const char *const resolution[RESOLUTIONS] = {
"576i", "720p", "fake 1080i", "1080i"
};
int i;
// cMenuEditBoolItem cMenuEditBitItem cMenuEditNumItem
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
MakePrimary = ConfigMakePrimary;
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
tr("no"), tr("yes")));
Deinterlace = ConfigVideoDeinterlace;
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace, 5,
//
// video
//
Add(SeparatorItem(tr("Video")));
for (i = 0; i < RESOLUTIONS; ++i) {
Add(SeparatorItem(resolution[i]));
Scaling[i] = ConfigVideoScaling[i];
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling[i], 4, scaling));
Deinterlace[i] = ConfigVideoDeinterlace[i];
Add(new cMenuEditStraItem(tr("Deinterlace"), &Deinterlace[i], 5,
deinterlace));
SkipChromaDeinterlace = ConfigVideoSkipChromaDeinterlace;
SkipChromaDeinterlace[i] = ConfigVideoSkipChromaDeinterlace[i];
Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
&SkipChromaDeinterlace, tr("no"), tr("yes")));
Denoise = ConfigVideoDenoise;
Add(new cMenuEditIntItem(tr("Denoise (vdpau 0..1000)"), &Denoise, 0,
1000));
Sharpen = ConfigVideoSharpen;
Add(new cMenuEditIntItem(tr("Sharpen (vdpau -1000..1000)"), &Sharpen,
-1000, 1000));
Scaling = ConfigVideoScaling;
Add(new cMenuEditStraItem(tr("Scaling"), &Scaling, 4, scaling));
&SkipChromaDeinterlace[i], tr("no"), tr("yes")));
Denoise[i] = ConfigVideoDenoise[i];
Add(new cMenuEditIntItem(tr("Denoise (0..1000) (vdpau)"), &Denoise[i],
0, 1000));
Sharpen[i] = ConfigVideoSharpen[i];
Add(new cMenuEditIntItem(tr("Sharpen (-1000..1000) (vdpau)"),
&Sharpen[i], -1000, 1000));
}
//
// audio
//
Add(SeparatorItem(tr("Audio")));
AudioDelay = ConfigVideoAudioDelay;
Add(new cMenuEditIntItem(tr("Audio delay (ms)"), &AudioDelay, -1000,
1000));
@@ -329,18 +394,32 @@ cMenuSetupSoft::cMenuSetupSoft(void)
*/
void cMenuSetupSoft::Store(void)
{
int i;
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
SetupStore("Deinterlace", ConfigVideoDeinterlace = Deinterlace);
VideoSetDeinterlace(ConfigVideoDeinterlace);
SetupStore("SkipChromaDeinterlace", ConfigVideoSkipChromaDeinterlace =
SkipChromaDeinterlace);
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
SetupStore("Denoise", ConfigVideoDenoise = Denoise);
VideoSetDenoise(ConfigVideoDenoise);
SetupStore("Sharpen", ConfigVideoSharpen = Sharpen);
VideoSetSharpen(ConfigVideoSharpen);
SetupStore("Scaling", ConfigVideoScaling = Scaling);
for (i = 0; i < RESOLUTIONS; ++i) {
char buf[128];
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
SetupStore(buf, ConfigVideoScaling[i] = Scaling[i]);
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
SetupStore(buf, ConfigVideoDeinterlace[i] = Deinterlace[i]);
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
"SkipChromaDeinterlace");
SetupStore(buf, ConfigVideoSkipChromaDeinterlace[i] =
SkipChromaDeinterlace[i]);
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
SetupStore(buf, ConfigVideoDenoise[i] = Denoise[i]);
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
SetupStore(buf, ConfigVideoSharpen[i] = Sharpen[i]);
}
VideoSetScaling(ConfigVideoScaling);
VideoSetDeinterlace(ConfigVideoDeinterlace);
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
VideoSetDenoise(ConfigVideoDenoise);
VideoSetSharpen(ConfigVideoSharpen);
SetupStore("AudioDelay", ConfigVideoAudioDelay = AudioDelay);
VideoSetAudioDelay(ConfigVideoAudioDelay);
SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
@@ -479,9 +558,14 @@ int64_t cSoftHdDevice::GetSTC(void)
return::VideoGetClock();
}
void cSoftHdDevice::TrickSpeed(int Speed)
/**
** Set trick play speed.
**
** @param speed trick speed
*/
void cSoftHdDevice::TrickSpeed(int speed)
{
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, Speed);
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
}
void cSoftHdDevice::Clear(void)
@@ -513,24 +597,38 @@ void cSoftHdDevice::Mute(void)
dsyslog("[softhddev]%s:\n", __FUNCTION__);
cDevice::Mute();
::Mute();
}
void cSoftHdDevice::SetVolumeDevice(int volume)
{
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume);
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume);
::SetVolumeDevice(volume);
}
void cSoftHdDevice::StillPicture(
__attribute__ ((unused)) const uchar * data, __attribute__ ((unused))
int length)
/**
** Display the given I-frame as a still picture.
*/
void cSoftHdDevice::StillPicture(const uchar * data, int length)
{
dsyslog("[softhddev]%s:\n", __FUNCTION__);
dsyslog("[softhddev]%s: %s\n", __FUNCTION__,
data[0] == 0x47 ? "ts" : "pes");
if (data[0] == 0x47) { // ts sync
cDevice::StillPicture(data, length);
return;
}
::StillPicture(data, length);
}
/**
** Check if the device is ready for further action.
**
** @param poller file handles (unused)
** @param timeout_ms timeout in ms to become ready
*/
bool cSoftHdDevice::Poll(
__attribute__ ((unused)) cPoller & poller, int timeout_ms)
{
@@ -539,11 +637,16 @@ bool cSoftHdDevice::Poll(
return::Poll(timeout_ms);
}
/**
** Flush the device output buffers.
**
** @param timeout_ms timeout in ms to become ready
*/
bool cSoftHdDevice::Flush(int timeout_ms)
{
dsyslog("[softhddev]%s: %d ms\n", __FUNCTION__, timeout_ms);
return true;
return::Flush(timeout_ms);
}
// ----------------------------------------------------------------------------
@@ -560,13 +663,14 @@ void cSoftHdDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
// ----------------------------------------------------------------------------
/**
** Play a audio packet.
*/
int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
{
//dsyslog("[softhddev]%s: %p %p %d %d\n", __FUNCTION__, this, data, length, id);
::PlayAudio(data, length, id);
return length;
return::PlayAudio(data, length, id);
}
void cSoftHdDevice::SetAudioTrackDevice(
@@ -816,34 +920,49 @@ cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
*/
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
{
//dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
int i;
char buf[128];
dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
// FIXME: handle the values
if (!strcmp(name, "MakePrimary")) {
ConfigMakePrimary = atoi(value);
return true;
}
if (!strcmp(name, "Deinterlace")) {
VideoSetDeinterlace(ConfigVideoDeinterlace = atoi(value));
for (i = 0; i < RESOLUTIONS; ++i) {
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
if (!strcmp(name, buf)) {
ConfigVideoScaling[i] = atoi(value);
VideoSetScaling(ConfigVideoScaling);
return true;
}
if (!strcmp(name, "SkipChromaDeinterlace")) {
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace =
atoi(value));
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Deinterlace");
if (!strcmp(name, buf)) {
ConfigVideoDeinterlace[i] = atoi(value);
VideoSetDeinterlace(ConfigVideoDeinterlace);
return true;
}
if (!strcmp(name, "Denoise")) {
VideoSetDenoise(ConfigVideoDenoise = atoi(value));
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i],
"SkipChromaDeinterlace");
if (!strcmp(name, buf)) {
ConfigVideoSkipChromaDeinterlace[i] = atoi(value);
VideoSetSkipChromaDeinterlace(ConfigVideoSkipChromaDeinterlace);
return true;
}
if (!strcmp(name, "Sharpen")) {
VideoSetSharpen(ConfigVideoSharpen = atoi(value));
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Denoise");
if (!strcmp(name, buf)) {
ConfigVideoDenoise[i] = atoi(value);
VideoSetDenoise(ConfigVideoDenoise);
return true;
}
if (!strcmp(name, "Scaling")) {
VideoSetScaling(ConfigVideoScaling = atoi(value));
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Sharpen");
if (!strcmp(name, buf)) {
ConfigVideoSharpen[i] = atoi(value);
VideoSetSharpen(ConfigVideoSharpen);
return true;
}
}
if (!strcmp(name, "AudioDelay")) {
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
return true;

View File

@@ -0,0 +1,71 @@
# Copyright 1999-2012 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $
EAPI="3"
inherit eutils vdr-plugin
if [[ ${PV} == "9999" ]] ; then
inherit git-2
EGIT_REPO_URI="git://projects.vdr-developer.org/vdr-plugin-softhddevice.git"
else
SRC_URI="http://projects.vdr-developer.org/attachments/download/838/${P}.tgz"
fi
DESCRIPTION="A software and GPU emulated HD output device plugin for VDR."
HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
SRC_URI=""
LICENSE="AGPL-3"
SLOT="0"
KEYWORDS="~x86 ~amd64"
IUSE="vaapi vdpau alsa oss yaepg"
DEPEND=">=x11-libs/libxcb-1.7
x11-libs/xcb-util
x11-libs/xcb-util-wm
x11-libs/xcb-util-wm
x11-libs/xcb-util-keysyms
x11-libs/xcb-util-renderutil
x11-libs/libX11
>=media-video/ffmpeg-0.7
sys-devel/gettext
sys-devel/make
dev-util/pkgconfig
yaepg? ( >=media-video/vdr-1.7[yaepg] )
!yaepg? ( >=media-video/vdr-1.7 )
vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva )
alsa? ( media-libs/alsa-lib )
"
src_prepare() {
vdr-plugin_src_prepare
}
src_compile() {
local myconf
myconf=""
use vdpau && myconf="${myconf} -DUSE_VDPAU"
use vaapi && myconf="${myconf} -DUSE_VAAPI"
use alsa && myconf="${myconf} -DUSE_ALSA"
use oss && myconf="${myconf} -DUSE_OSS"
emake all CC="$(tc-getCC)" CFLAGS="${CFLAGS}" \
LDFLAGS="${LDFLAGS}" CONFIG="${myconf}" LIBDIR="." || die
}
src_install() {
vdr-plugin_src_install
dodir /etc/vdr/plugins || die
insinto /etc/vdr/plugins
fowners -R vdr:vdr /etc/vdr || die
#insinto /etc/conf.d
#doins vdr.softhddevice
}

849
video.c

File diff suppressed because it is too large Load Diff

70
video.h
View File

@@ -30,13 +30,6 @@
/// Video hardware decoder typedef
typedef struct _video_hw_decoder_ VideoHwDecoder;
//----------------------------------------------------------------------------
// Variables
//----------------------------------------------------------------------------
//extern unsigned VideoWindowWidth; ///< current video output width
//extern unsigned VideoWindowHeight; ///< current video output height
//----------------------------------------------------------------------------
// Prototypes
//----------------------------------------------------------------------------
@@ -47,14 +40,14 @@ extern VideoHwDecoder *VideoNewHwDecoder(void);
/// Get and allocate a video hardware surface.
extern unsigned VideoGetSurface(VideoHwDecoder *);
/// Release a video hardware surface.
/// Release a video hardware surface
extern void VideoReleaseSurface(VideoHwDecoder *, unsigned);
#ifdef LIBAVCODEC_VERSION
/// Render a ffmpeg frame
/// Render a ffmpeg frame.
extern void VideoRenderFrame(VideoHwDecoder *, AVCodecContext *, AVFrame *);
/// Get ffmpeg vaapi context
/// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
/// Callback to negotiate the PixelFormat.
@@ -62,57 +55,60 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
const enum PixelFormat *);
#ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state
/// Draw vdpau render state.
extern void VideoDrawRenderState(VideoHwDecoder *,
struct vdpau_render_state *);
#endif
#endif
/// Display video TEST
extern void VideoDisplayHandler(void);
/// Poll video events
/// Poll video events.
extern void VideoPollEvent(void);
/// set video mode
/// Wakeup display handler.
extern void VideoDisplayWakeup(void);
/// Set video mode.
//extern void VideoSetVideoMode(int, int, int, int);
/// set video geometry
/// Set video geometry.
extern int VideoSetGeometry(const char *);
/// set deinterlace
extern void VideoSetDeinterlace(int);
/// Set video output position.
extern void VideoSetOutputPosition(int, int, int, int);
/// set skip chroma deinterlace
extern void VideoSetSkipChromaDeinterlace(int);
/// Set deinterlace.
extern void VideoSetDeinterlace(int[]);
/// set scaling
extern void VideoSetScaling(int);
/// Set skip chroma deinterlace.
extern void VideoSetSkipChromaDeinterlace(int[]);
/// set denoise
extern void VideoSetDenoise(int);
/// Set scaling.
extern void VideoSetScaling(int[]);
/// set sharpen
extern void VideoSetSharpen(int);
/// Set denoise.
extern void VideoSetDenoise(int[]);
/// set audio delay
/// Set sharpen.
extern void VideoSetSharpen(int[]);
/// Set audio delay.
extern void VideoSetAudioDelay(int);
/// Clear OSD
/// Clear OSD.
extern void VideoOsdClear(void);
/// Draw an OSD ARGB image
/// Draw an OSD ARGB image.
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
extern int64_t VideoGetClock(void); ///< get video clock
extern int64_t VideoGetClock(void); ///< Get video clock.
extern void VideoOsdInit(void); ///< setup osd
extern void VideoOsdExit(void); ///< cleanup osd
extern void VideoOsdInit(void); ///< Setup osd.
extern void VideoOsdExit(void); ///< Cleanup osd.
extern void VideoInit(const char *); ///< setup video module
extern void VideoExit(void); ///< cleanup and exit video module
extern void VideoInit(const char *); ///< Setup video module.
extern void VideoExit(void); ///< Cleanup and exit video module.
extern void VideoFlushInput(void); ///< flush codec input buffers
extern int VideoDecode(void); ///< decode
extern void VideoFlushInput(void); ///< Flush video input buffers.
extern int VideoDecode(void); ///< Decode video input buffers.
/// @}