mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
18 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa27a1c73a | ||
|
|
e32857a27a | ||
|
|
5ba88bb822 | ||
|
|
0422b6aa5a | ||
|
|
eb024558de | ||
|
|
1593d5dd83 | ||
|
|
09f62307d4 | ||
|
|
87f7aa63cc | ||
|
|
b1ce88923e | ||
|
|
c6e66e0787 | ||
|
|
19d4eeed82 | ||
|
|
9f668c4750 | ||
|
|
e419742a40 | ||
|
|
2cacdc6c90 | ||
|
|
6efe558f78 | ||
|
|
80100299f3 | ||
|
|
5509d768ac | ||
|
|
c0d0a4ae7c |
27
ChangeLog
27
ChangeLog
@@ -1,4 +1,31 @@
|
||||
User johns
|
||||
Date: Sat Jan 21 15:49:16 CET 2012
|
||||
|
||||
Release Version 0.4.0
|
||||
VDPAU: Add grab image support.
|
||||
VDPAU: Add auto-crop support.
|
||||
VDPAU: Changed OSD alpha calculation.
|
||||
Fix bug: Used VideoSharpen for denoise settings.
|
||||
Instant update deinterlace/... configuration changes.
|
||||
Fix bug: AudioExit called without AudioInit crash.
|
||||
|
||||
Date: Thu Jan 19 15:58:40 CET 2012
|
||||
|
||||
Release Version 0.3.5
|
||||
OSD improvements:
|
||||
Use OSD size equal to video window.
|
||||
Update only dirty area(s) of OSD.
|
||||
Show/mix only used area of OSD.
|
||||
Fix bug: vpdau use previous resolution for deint, ...
|
||||
Fix software deinterlace with VA-API.
|
||||
Fix bug: transposed digits 567 should be 576.
|
||||
Audio module cleanup:
|
||||
Alsa + OSS can be included/build at the same time.
|
||||
Alsa or OSS can be runtime selected with -a.
|
||||
Add audio thread support to OSS module.
|
||||
Add polled audio support to alsa module.
|
||||
Removed some debug source code.
|
||||
|
||||
Date: Sun Jan 15 16:56:04 CET 2012
|
||||
|
||||
Release Version 0.3.1
|
||||
|
||||
6
Makefile
6
Makefile
@@ -14,6 +14,7 @@ PLUGIN = softhddevice
|
||||
### The version number of this plugin (taken from the main source file):
|
||||
|
||||
VERSION = $(shell grep 'static const char \*const VERSION *=' $(PLUGIN).cpp | awk '{ print $$7 }' | sed -e 's/[";]//g')
|
||||
GIT_REV = $(shell git describe --always 2>/dev/null)
|
||||
|
||||
### Configuration (edit this for your needs)
|
||||
|
||||
@@ -22,7 +23,7 @@ CONFIG := #-DDEBUG
|
||||
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
|
||||
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
|
||||
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
|
||||
#CONFIG += -DUSE_OSS
|
||||
CONFIG += -DUSE_OSS
|
||||
|
||||
### The C++ compiler and options:
|
||||
|
||||
@@ -59,7 +60,8 @@ PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
INCLUDES += -I$(VDRDIR)/include
|
||||
|
||||
DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \
|
||||
$(if $(GIT_REV), -DGIT_REV='"$(GIT_REV)"')
|
||||
|
||||
_CFLAGS = $(DEFINES) $(INCLUDES) \
|
||||
$(shell pkg-config --cflags libavcodec libavformat) \
|
||||
|
||||
34
README.txt
34
README.txt
@@ -24,17 +24,20 @@ A software and GPU emulated HD output device plugin for VDR.
|
||||
o Video CPU/VA-API
|
||||
o Video VDPAU/VDPAU
|
||||
o Video CPU/VDPAU
|
||||
o Audio FFMpeg/Alsa/Analog
|
||||
o Audio FFMpeg/Alsa/Digital
|
||||
o Audio FFMpeg/OSS/Analog
|
||||
o HDMI/SPDIF Passthrough
|
||||
o VA-API bob software deinterlace
|
||||
o Auto-crop
|
||||
|
||||
o planned: Video VA-API/Opengl
|
||||
o planned: Video VDPAU/Opengl
|
||||
o planned: Video CPU/Xv
|
||||
o planned: Video CPU/Opengl
|
||||
o planned: Software Deinterlacer
|
||||
o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
|
||||
o planned: Video XvBA/XvBA
|
||||
o Audio FFMpeg/Alsa/Analog
|
||||
o Audio FFMpeg/Alsa/Digital
|
||||
o Audio FFMpeg/OSS/Analog
|
||||
o Alsa HDMI/SPDIF Passthrough
|
||||
o planned: OSS HDMI/SPDIF Passthrough
|
||||
o planned: atmo light support
|
||||
|
||||
To compile you must have the 'requires' installed.
|
||||
|
||||
@@ -61,7 +64,7 @@ Install:
|
||||
http://projects.vdr-developer.org/projects/plg-softhddevice/files
|
||||
|
||||
tar vxf vdr-softhddevice-*.tar.bz2
|
||||
cd vdr-softhddevice
|
||||
cd softhddevice-*
|
||||
make VDRDIR=<path-to-your-vdr-files> LIBDIR=.
|
||||
|
||||
You can edit Makefile to enable/disable VDPAU / VA-API / Alsa / OSS
|
||||
@@ -125,6 +128,14 @@ Setup: /etc/vdr/setup.conf
|
||||
softhddevice.AudioPassthrough = 0
|
||||
0 = none, 1 = AC-3
|
||||
|
||||
softhddevice.AutoCrop.Interval = 0
|
||||
0 disables auto-crop
|
||||
n each 'n' frames auto-crop is checked.
|
||||
|
||||
softhddevice.AutoCrop.Delay = 0
|
||||
if auto-crop is over after 'n' intervals the same, the cropping is
|
||||
used.
|
||||
|
||||
Setup: /etc/vdr/remote.conf
|
||||
------
|
||||
|
||||
@@ -146,6 +157,15 @@ Commandline:
|
||||
|
||||
Use vdr -h to see the command line arguments support by the plugin.
|
||||
|
||||
-a audio_device
|
||||
|
||||
Selects audio output module and device.
|
||||
"" to disable audio output
|
||||
/... to use oss audio module (if compiled with oss
|
||||
support)
|
||||
other to use alsa audio module (if compiled with alsa
|
||||
support)
|
||||
|
||||
Running:
|
||||
--------
|
||||
|
||||
|
||||
55
Todo
55
Todo
@@ -19,35 +19,41 @@ GNU Affero General Public License for more details.
|
||||
$Id: $
|
||||
|
||||
missing:
|
||||
software deinterlace
|
||||
auto crop
|
||||
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 audio, stop video, configurable
|
||||
Option deinterlace off / deinterlace force!
|
||||
Make output drivers better moduluar.
|
||||
Make output drivers better modular (under construction).
|
||||
|
||||
video:
|
||||
subtitle not cleared
|
||||
subtitle could be asyncron
|
||||
reduce warnings after channel switch
|
||||
|
||||
vdpau:
|
||||
1080i with temporal spatial and level 1 scaling too slow with my GT 520
|
||||
1080i with temporal spatial too slow with my GT 520 on some channels
|
||||
SkipChromaDeinterlace improves performance
|
||||
Improve OSD handling, show only what is used. Big OSD costs performance
|
||||
VdpPreemptionCallback handling
|
||||
VdpPreemptionCallback handling (under construction)
|
||||
hard channel switch
|
||||
suspendoutput didn't show logo or black picture.
|
||||
|
||||
libva:
|
||||
hard channel switch
|
||||
yaepghd (VaapiSetOutputPosition) support
|
||||
can associate ony displayed part of osd
|
||||
auto crop for va-api
|
||||
grab image for va-api
|
||||
|
||||
libva: branch vaapi-ext
|
||||
add support for vaapi-ext
|
||||
|
||||
libva-intel-driver:
|
||||
intel still has hangups most with 1080i
|
||||
1080i does no v-sync (workaround written)
|
||||
osd has sometimes wrong size (workaround written)
|
||||
1080i does no v-sync (workaround written, fixed with vaapi-ext)
|
||||
OSD has sometimes wrong size (workaround written)
|
||||
|
||||
libva-vdpau-driver:
|
||||
G210 osd update too slow (needs hardware problem workaround)
|
||||
OSD update is too slow
|
||||
G210/GT520 OSD update too slow (needs hardware problem workaround)
|
||||
hangup on exit (VaapiDelDecoder -> VaapiCleanup
|
||||
-> vaDestroyContext -> pthread_rwlock_wrlock)
|
||||
|
||||
@@ -56,21 +62,18 @@ libva-xvba-driver:
|
||||
x11:
|
||||
disable screensaver
|
||||
|
||||
audio/alsa:
|
||||
done? video/audio asyncron
|
||||
random crashes in av_parser_parse2, when switching channels
|
||||
sometimes alsa hangs
|
||||
fixed? snd_pcm_state: Assertion `pcm' failed. while switching channels
|
||||
(thread problem)
|
||||
audio:
|
||||
write TS -> PES parser, which feeds audio before the next start packet
|
||||
CodecAudioOpen can fail "can't open audio codec" and does Fatal exit.
|
||||
Combine alsa+oss ringbuffer code.
|
||||
Make alsa thread/polled and oss thread/polled output module runtime
|
||||
selectable.
|
||||
|
||||
audio/alsa:
|
||||
better downmix of >2 channels on 2 channel hardware
|
||||
remix support of unsupported sample rates
|
||||
libav supports only resample of mono to 2 channels
|
||||
ffmpeg didn't support resample of 5 to 2 channels
|
||||
CodecAudioOpen can fail "can't open audio codec" and does Fatal exit.
|
||||
|
||||
audio:
|
||||
write TS -> PES parser, which feeds audio before the next start packet
|
||||
|
||||
audio/oss:
|
||||
alsa oss emulation mixer "pcm" not working
|
||||
@@ -80,6 +83,7 @@ HDMI/SPDIF Passthrough:
|
||||
only AC-3 written
|
||||
Channels are wrong setup, if changing setting during operation.
|
||||
split pcm and ac-3 out into two devices
|
||||
support oss pass-through
|
||||
|
||||
playback of recording
|
||||
pause is not reset, when replay exit
|
||||
@@ -92,7 +96,10 @@ setup:
|
||||
Setup 4:3 zoom type
|
||||
Some setup parameters are not used until restart.
|
||||
Can a notice be added to the setup menu?
|
||||
576i, 720p, fake 1080i, 1080i
|
||||
|
||||
unsorted:
|
||||
Menu -> Setup -> Plugins -> skingenigmang -> General
|
||||
-> Try 8bpp single area: no, has missing parts.
|
||||
|
||||
future features (not planed for 1.0 - 1.5)
|
||||
|
||||
@@ -102,5 +109,7 @@ future features (not planed for 1.0 - 1.5)
|
||||
software decoder for xv / opengl
|
||||
atmolight support
|
||||
multistream handling
|
||||
pip support
|
||||
grab image with jpeg
|
||||
|
||||
upmix stereo to AC-3
|
||||
|
||||
629
audio.c
629
audio.c
@@ -35,21 +35,19 @@
|
||||
///
|
||||
///
|
||||
/// @todo FIXME: there can be problems with little/big endian.
|
||||
/// @todo FIXME: can combine oss and alsa ring buffer
|
||||
/// @todo FIXME: can combine OSS and alsa ring buffer
|
||||
///
|
||||
|
||||
#ifdef USE_ALSA // only with alsa supported
|
||||
#define USE_AUDIO_THREAD ///< use thread for audio playback
|
||||
#endif
|
||||
//#define USE_ALSA ///< enable alsa support
|
||||
//#define USE_OSS ///< enable oss support
|
||||
#define noSEARCH_HDMI_BUG
|
||||
#define noSEARCH_HDMI_BUG2
|
||||
//#define USE_OSS ///< enable OSS support
|
||||
#define USE_AUDIO_THREAD ///< use thread for audio playback
|
||||
#define noUSE_AUDIORING ///< new audio ring code (incomplete)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <libintl.h>
|
||||
#define _(str) gettext(str) ///< gettext shortcut
|
||||
@@ -73,10 +71,10 @@
|
||||
# error "No valid SNDCTL_DSP_HALT_OUTPUT found."
|
||||
# endif
|
||||
#endif
|
||||
#include <poll.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
@@ -96,13 +94,42 @@
|
||||
#include "misc.h"
|
||||
#include "audio.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Declarations
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Audio output module structure and typedef.
|
||||
*/
|
||||
typedef struct _audio_module_
|
||||
{
|
||||
const char *Name; ///< audio output module name
|
||||
|
||||
void (*Thread) (void); ///< module thread handler
|
||||
void (*Enqueue) (const void *, int); ///< enqueue samples for output
|
||||
void (*FlushBuffers) (void); ///< flush sample buffers
|
||||
void (*Poller) (void); ///< output poller
|
||||
int (*FreeBytes) (void); ///< number of bytes free in buffer
|
||||
uint64_t(*GetDelay) (void); ///< get current audio delay
|
||||
void (*SetVolume) (int); ///< set output volume
|
||||
int (*Setup) (int *, int *); ///< setup channels, samplerate
|
||||
void (*Init) (void); ///< initialize audio output module
|
||||
void (*Exit) (void); ///< cleanup audio output module
|
||||
} AudioModule;
|
||||
|
||||
static const AudioModule NoopModule; ///< forward definition of noop module
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Variables
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
static const char *AudioPCMDevice; ///< alsa/oss PCM device name
|
||||
static const char *AudioMixerDevice; ///< alsa/oss mixer device name
|
||||
static const char *AudioMixerChannel; ///< alsa/oss mixer channel name
|
||||
static const char *AudioModuleName; ///< which audio module to use
|
||||
|
||||
/// Selected audio module.
|
||||
static const AudioModule *AudioUsedModule = &NoopModule;
|
||||
static const char *AudioPCMDevice; ///< alsa/OSS PCM device name
|
||||
static const char *AudioMixerDevice; ///< alsa/OSS mixer device name
|
||||
static const char *AudioMixerChannel; ///< alsa/OSS mixer channel name
|
||||
static volatile char AudioRunning; ///< thread running / stopped
|
||||
static int AudioPaused; ///< audio paused
|
||||
static unsigned AudioSampleRate; ///< audio sample rate in hz
|
||||
@@ -111,16 +138,20 @@ static const int AudioBytesProSample = 2; ///< number of bytes per sample
|
||||
static int64_t AudioPTS; ///< audio pts clock
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
static pthread_t AudioThread; ///< audio play thread
|
||||
static pthread_mutex_t AudioMutex; ///< audio condition mutex
|
||||
static pthread_cond_t AudioStartCond; ///< condition variable
|
||||
#else
|
||||
static const int AudioThread; ///< dummy audio thread
|
||||
#endif
|
||||
|
||||
#ifdef SEARCH_HDMI_BUG2
|
||||
#ifdef USE_AUDIORING
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// ring buffer
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
// FIXME: use this code, to combine alsa&oss ring buffers
|
||||
// FIXME: use this code, to combine alsa&OSS ring buffers
|
||||
|
||||
#define AUDIO_RING_MAX 8 ///< number of audio ring buffers
|
||||
|
||||
@@ -219,7 +250,10 @@ static int AlsaUseMmap; ///< use mmap
|
||||
|
||||
static RingBuffer *AlsaRingBuffer; ///< audio ring buffer
|
||||
static unsigned AlsaStartThreshold; ///< start play, if filled
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
static volatile char AlsaFlushBuffer; ///< flag empty buffer
|
||||
#endif
|
||||
|
||||
static snd_mixer_t *AlsaMixer; ///< alsa mixer handle
|
||||
static snd_mixer_elem_t *AlsaMixerElem; ///< alsa pcm mixer element
|
||||
@@ -295,26 +329,15 @@ static int AlsaPlayRingbuffer(void)
|
||||
if (avail < 256) { // too much overhead
|
||||
if (first) {
|
||||
// happens with broken alsa drivers
|
||||
Error(_("audio/alsa: broken driver %d\n"), avail);
|
||||
usleep(5 * 1000);
|
||||
if (AudioThread) {
|
||||
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)));
|
||||
break;
|
||||
}
|
||||
#ifdef SEARCH_HDMI_BUG
|
||||
{
|
||||
uint16_t buf[8192];
|
||||
unsigned u;
|
||||
|
||||
for (u = 0; u < sizeof(buf) / 2; u++) {
|
||||
buf[u] = random() & 0xffff;
|
||||
}
|
||||
|
||||
n = sizeof(buf);
|
||||
p = buf;
|
||||
}
|
||||
#else
|
||||
n = RingBufferGetReadPointer(AlsaRingBuffer, &p);
|
||||
if (!n) { // ring buffer empty
|
||||
if (first) { // only error on first loop
|
||||
@@ -322,7 +345,6 @@ static int AlsaPlayRingbuffer(void)
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
if (n < avail) { // not enough bytes in ring buffer
|
||||
avail = n;
|
||||
}
|
||||
@@ -376,21 +398,47 @@ static void AlsaFlushBuffers(void)
|
||||
int err;
|
||||
snd_pcm_state_t state;
|
||||
|
||||
RingBufferReadAdvance(AlsaRingBuffer, RingBufferUsedBytes(AlsaRingBuffer));
|
||||
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));
|
||||
if (AlsaRingBuffer && AlsaPCMHandle) {
|
||||
RingBufferReadAdvance(AlsaRingBuffer,
|
||||
RingBufferUsedBytes(AlsaRingBuffer));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
AudioRunning = 0;
|
||||
AudioPTS = INT64_C(0x8000000000000000);
|
||||
}
|
||||
|
||||
/**
|
||||
** Call back to play audio polled.
|
||||
*/
|
||||
static void AlsaPoller(void)
|
||||
{
|
||||
if (!AlsaPCMHandle) { // setup failure
|
||||
return;
|
||||
}
|
||||
if (!AudioThread && AudioRunning) {
|
||||
AlsaPlayRingbuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Get free bytes in audio output.
|
||||
*/
|
||||
static int AlsaFreeBytes(void)
|
||||
{
|
||||
return AlsaRingBuffer ? RingBufferFreeBytes(AlsaRingBuffer) : INT32_MAX;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -520,8 +568,6 @@ static void AlsaEnqueue(const void *samples, int count)
|
||||
|
||||
#endif
|
||||
|
||||
#if 0
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// direct playback
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -536,39 +582,11 @@ static void AlsaEnqueue(const void *samples, int count)
|
||||
*/
|
||||
static void AlsaEnqueue(const void *samples, int count)
|
||||
{
|
||||
snd_pcm_state_t state;
|
||||
int avail;
|
||||
int n;
|
||||
int err;
|
||||
int frames;
|
||||
const void *p;
|
||||
|
||||
Debug(3, "audio/alsa: %6zd + %4d\n", RingBufferUsedBytes(AlsaRingBuffer),
|
||||
count);
|
||||
n = RingBufferWrite(AlsaRingBuffer, samples, count);
|
||||
if (n != count) {
|
||||
Error(_("audio/alsa: can't place %d samples in ring buffer\n"), count);
|
||||
if (AlsaAddToRingbuffer(samples, count)) {
|
||||
AudioRunning = 1;
|
||||
}
|
||||
// check if running, wait until enough buffered
|
||||
state = snd_pcm_state(AlsaPCMHandle);
|
||||
Debug(4, "audio/alsa: state %d - %s\n", state, snd_pcm_state_name(state));
|
||||
if (state == SND_PCM_STATE_PREPARED) {
|
||||
// FIXME: adjust start ratio
|
||||
if (RingBufferFreeBytes(AlsaRingBuffer)
|
||||
> RingBufferUsedBytes(AlsaRingBuffer)) {
|
||||
return;
|
||||
}
|
||||
Debug(3, "audio/alsa: state %d - %s start play\n", state,
|
||||
snd_pcm_state_name(state));
|
||||
}
|
||||
// Update audio clock
|
||||
AudioPTS +=
|
||||
(size * 90000) / (AudioSampleRate * AudioChannels *
|
||||
AudioBytesProSample);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -622,7 +640,7 @@ static void AlsaThread(void)
|
||||
break;
|
||||
}
|
||||
pthread_yield();
|
||||
usleep(20 * 1000); // let fill the buffers
|
||||
usleep(20 * 1000); // let fill/empty the buffers
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -633,10 +651,9 @@ static void AlsaThread(void)
|
||||
** @param samples sample buffer
|
||||
** @param count number of bytes in sample buffer
|
||||
*/
|
||||
static void AlsaEnqueue(const void *samples, int count)
|
||||
static void AlsaThreadEnqueue(const void *samples, int count)
|
||||
{
|
||||
if (!AlsaRingBuffer || !AlsaPCMHandle || !AudioSampleRate) {
|
||||
printf("%p %p %d\n", AlsaRingBuffer, AlsaPCMHandle, AudioSampleRate);
|
||||
Debug(3, "audio/alsa: enqueue not ready\n");
|
||||
return;
|
||||
}
|
||||
@@ -652,8 +669,26 @@ static void AlsaEnqueue(const void *samples, int count)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Flush alsa buffers with thread.
|
||||
*/
|
||||
static void AlsaThreadFlushBuffers(void)
|
||||
{
|
||||
// signal thread to flush buffers
|
||||
if (AudioThread) {
|
||||
AlsaFlushBuffer = 1;
|
||||
do {
|
||||
AudioRunning = 1; // wakeup in case of sleeping
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
usleep(1 * 1000);
|
||||
} while (AlsaFlushBuffer); // wait until flushed
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Open alsa pcm device.
|
||||
*/
|
||||
@@ -1098,6 +1133,28 @@ static void AlsaExit(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Alsa module.
|
||||
*/
|
||||
static const AudioModule AlsaModule = {
|
||||
.Name = "alsa",
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
.Thread = AlsaThread,
|
||||
.Enqueue = AlsaThreadEnqueue,
|
||||
.FlushBuffers = AlsaThreadFlushBuffers,
|
||||
#else
|
||||
.Enqueue = AlsaEnqueue,
|
||||
.FlushBuffers = AlsaFlushBuffers,
|
||||
#endif
|
||||
.Poller = AlsaPoller,
|
||||
.FreeBytes = AlsaFreeBytes,
|
||||
.GetDelay = AlsaGetDelay,
|
||||
.SetVolume = AlsaSetVolume,
|
||||
.Setup = AlsaSetup,
|
||||
.Init = AlsaInit,
|
||||
.Exit = AlsaExit,
|
||||
};
|
||||
|
||||
#endif // USE_ALSA
|
||||
|
||||
#ifdef USE_OSS
|
||||
@@ -1116,6 +1173,10 @@ static int OssMixerChannel; ///< mixer channel index
|
||||
static RingBuffer *OssRingBuffer; ///< audio ring buffer
|
||||
static unsigned OssStartThreshold; ///< start play, if filled
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
static volatile char OssFlushBuffer; ///< flag empty buffer
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// OSS pcm
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -1204,17 +1265,20 @@ static int OssPlayRingbuffer(void)
|
||||
}
|
||||
|
||||
/**
|
||||
** Flush oss buffers.
|
||||
** 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;
|
||||
if (OssRingBuffer && OssPcmFildes != -1) {
|
||||
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));
|
||||
}
|
||||
}
|
||||
AudioRunning = 0;
|
||||
AudioPTS = INT64_C(0x8000000000000000);
|
||||
}
|
||||
|
||||
@@ -1256,15 +1320,108 @@ static void OssPoller(void)
|
||||
if (OssPcmFildes == -1) { // setup failure
|
||||
return;
|
||||
}
|
||||
if (AudioRunning) {
|
||||
if (!AudioThread && AudioRunning) {
|
||||
OssPlayRingbuffer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Get free bytes in audio output.
|
||||
*/
|
||||
static int OssFreeBytes(void)
|
||||
{
|
||||
return OssRingBuffer ? RingBufferFreeBytes(OssRingBuffer) : INT32_MAX;
|
||||
}
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// thread playback
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Initialize oss pcm device.
|
||||
** OSS thread
|
||||
*/
|
||||
static void OssThread(void)
|
||||
{
|
||||
for (;;) {
|
||||
struct pollfd fds[1];
|
||||
int err;
|
||||
|
||||
pthread_testcancel();
|
||||
if (OssFlushBuffer) {
|
||||
// we can flush too many, but wo cares
|
||||
Debug(3, "audio/oss: flushing buffers\n");
|
||||
OssFlushBuffers();
|
||||
OssFlushBuffer = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
fds[0].fd = OssPcmFildes;
|
||||
fds[0].events = POLLOUT | POLLERR;
|
||||
// wait for space in kernel buffers
|
||||
err = poll(fds, 1, 100);
|
||||
if (err < 0) {
|
||||
Error(_("audio/oss: error poll %s\n"), strerror(errno));
|
||||
usleep(100 * 1000);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (OssFlushBuffer) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if ((err = OssPlayRingbuffer())) { // empty / error
|
||||
if (err < 0) { // underrun error
|
||||
break;
|
||||
}
|
||||
pthread_yield();
|
||||
usleep(20 * 1000); // let fill/empty the buffers
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Place samples in audio output queue.
|
||||
**
|
||||
** @param samples sample buffer
|
||||
** @param count number of bytes in sample buffer
|
||||
*/
|
||||
static void OssThreadEnqueue(const void *samples, int count)
|
||||
{
|
||||
if (!OssRingBuffer || OssPcmFildes == -1 || !AudioSampleRate) {
|
||||
Debug(3, "audio/oss: enqueue not ready\n");
|
||||
return;
|
||||
}
|
||||
if (OssAddToRingbuffer(samples, count)) {
|
||||
// no lock needed, can wakeup next time
|
||||
AudioRunning = 1;
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Flush OSS buffers with thread.
|
||||
*/
|
||||
static void OssThreadFlushBuffers(void)
|
||||
{
|
||||
// signal thread to flush buffers
|
||||
if (AudioThread) {
|
||||
OssFlushBuffer = 1;
|
||||
do {
|
||||
AudioRunning = 1; // wakeup in case of sleeping
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
usleep(1 * 1000);
|
||||
} while (OssFlushBuffer); // wait until flushed
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Initialize OSS pcm device.
|
||||
**
|
||||
** @see AudioPCMDevice
|
||||
*/
|
||||
@@ -1292,7 +1449,7 @@ static void OssInitPCM(void)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Set oss mixer volume (0-100)
|
||||
** Set OSS mixer volume (0-100)
|
||||
**
|
||||
** @param volume volume (0 .. 100)
|
||||
*/
|
||||
@@ -1317,7 +1474,7 @@ static const char *OssMixerChannelNames[SOUND_MIXER_NRDEVICES] =
|
||||
SOUND_DEVICE_NAMES;
|
||||
|
||||
/**
|
||||
** Initialize oss mixer.
|
||||
** Initialize OSS mixer.
|
||||
*/
|
||||
static void OssInitMixer(void)
|
||||
{
|
||||
@@ -1371,7 +1528,7 @@ static void OssInitMixer(void)
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Get oss audio delay in time stamps.
|
||||
** Get OSS audio delay in time stamps.
|
||||
**
|
||||
** @returns audio delay in time stamps.
|
||||
*/
|
||||
@@ -1411,7 +1568,7 @@ static uint64_t OssGetDelay(void)
|
||||
}
|
||||
|
||||
/**
|
||||
** Setup oss audio for requested format.
|
||||
** Setup OSS audio for requested format.
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
@@ -1427,14 +1584,11 @@ static int OssSetup(int *freq, int *channels)
|
||||
int ret;
|
||||
int tmp;
|
||||
|
||||
if (OssPcmFildes == -1) { // oss not ready
|
||||
if (OssPcmFildes == -1) { // OSS not ready
|
||||
return -1;
|
||||
}
|
||||
// flush any buffered data
|
||||
{
|
||||
AudioRunning = 0;
|
||||
OssFlushBuffers();
|
||||
}
|
||||
AudioFlushBuffers();
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -1519,7 +1673,7 @@ static int OssSetup(int *freq, int *channels)
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize oss audio output module.
|
||||
** Initialize OSS audio output module.
|
||||
*/
|
||||
static void OssInit(void)
|
||||
{
|
||||
@@ -1530,7 +1684,7 @@ static void OssInit(void)
|
||||
}
|
||||
|
||||
/**
|
||||
** Cleanup oss audio output module.
|
||||
** Cleanup OSS audio output module.
|
||||
*/
|
||||
static void OssExit(void)
|
||||
{
|
||||
@@ -1544,17 +1698,116 @@ static void OssExit(void)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** OSS module.
|
||||
*/
|
||||
static const AudioModule OssModule = {
|
||||
.Name = "oss",
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
.Thread = OssThread,
|
||||
.Enqueue = OssThreadEnqueue,
|
||||
.FlushBuffers = OssThreadFlushBuffers,
|
||||
#else
|
||||
.Enqueue = OssEnqueue,
|
||||
.FlushBuffers = OssFlushBuffers,
|
||||
#endif
|
||||
.Poller = OssPoller,
|
||||
.FreeBytes = OssFreeBytes,
|
||||
.GetDelay = OssGetDelay,
|
||||
.SetVolume = OssSetVolume,
|
||||
.Setup = OssSetup,
|
||||
.Init = OssInit,
|
||||
.Exit = OssExit,
|
||||
};
|
||||
|
||||
#endif // USE_OSS
|
||||
|
||||
//============================================================================
|
||||
// Noop
|
||||
//============================================================================
|
||||
|
||||
/**
|
||||
** Noop enqueue samples.
|
||||
**
|
||||
** @param samples sample buffer
|
||||
** @param count number of bytes in sample buffer
|
||||
*/
|
||||
static void NoopEnqueue( __attribute__ ((unused))
|
||||
const void *samples, __attribute__ ((unused))
|
||||
int count)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** Get free bytes in audio output.
|
||||
*/
|
||||
static int NoopFreeBytes(void)
|
||||
{
|
||||
return INT32_MAX; // no driver, much space
|
||||
}
|
||||
|
||||
/**
|
||||
** Get audio delay in time stamps.
|
||||
**
|
||||
** @returns audio delay in time stamps.
|
||||
*/
|
||||
static uint64_t NoopGetDelay(void)
|
||||
{
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
/**
|
||||
** Set mixer volume (0-100)
|
||||
**
|
||||
** @param volume volume (0 .. 100)
|
||||
*/
|
||||
static void NoopSetVolume( __attribute__ ((unused))
|
||||
int volume)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** Noop setup.
|
||||
**
|
||||
** @param freq sample frequency
|
||||
** @param channels number of channels
|
||||
*/
|
||||
static int NoopSetup( __attribute__ ((unused))
|
||||
int *channels, __attribute__ ((unused))
|
||||
int *freq)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
** Noop void
|
||||
*/
|
||||
static void NoopVoid(void)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
** Noop module.
|
||||
*/
|
||||
static const AudioModule NoopModule = {
|
||||
.Name = "noop",
|
||||
.Enqueue = NoopEnqueue,
|
||||
.FlushBuffers = NoopVoid,
|
||||
.Poller = NoopVoid,
|
||||
.FreeBytes = NoopFreeBytes,
|
||||
.GetDelay = NoopGetDelay,
|
||||
.SetVolume = NoopSetVolume,
|
||||
.Setup = NoopSetup,
|
||||
.Init = NoopVoid,
|
||||
.Exit = NoopVoid,
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// thread playback
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
|
||||
static pthread_t AudioThread; ///< audio play thread
|
||||
static pthread_mutex_t AudioMutex; ///< audio condition mutex
|
||||
|
||||
/**
|
||||
** Audio play thread.
|
||||
*/
|
||||
@@ -1565,18 +1818,13 @@ static void *AudioPlayHandlerThread(void *dummy)
|
||||
Debug(3, "audio: wait on start condition\n");
|
||||
pthread_mutex_lock(&AudioMutex);
|
||||
AudioRunning = 0;
|
||||
#ifndef SEARCH_HDMI_BUG
|
||||
do {
|
||||
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
||||
// cond_wait can return, without signal!
|
||||
} while (!AudioRunning);
|
||||
#else
|
||||
usleep(1 * 1000);
|
||||
AudioRunning = 1;
|
||||
#endif
|
||||
pthread_mutex_unlock(&AudioMutex);
|
||||
|
||||
#ifdef SEARCH_HDMI_BUG2
|
||||
#ifdef USE_AUDIORING
|
||||
if (atomic_read(&AudioRingFilled) > 1) {
|
||||
int sample_rate;
|
||||
int channels;
|
||||
@@ -1619,9 +1867,7 @@ static void *AudioPlayHandlerThread(void *dummy)
|
||||
#endif
|
||||
|
||||
Debug(3, "audio: play start\n");
|
||||
#ifdef USE_ALSA
|
||||
AlsaThread();
|
||||
#endif
|
||||
AudioUsedModule->Thread();
|
||||
}
|
||||
|
||||
return dummy;
|
||||
@@ -1636,15 +1882,9 @@ static void AudioInitThread(void)
|
||||
pthread_cond_init(&AudioStartCond, NULL);
|
||||
pthread_create(&AudioThread, NULL, AudioPlayHandlerThread, NULL);
|
||||
pthread_setname_np(AudioThread, "softhddev audio");
|
||||
//pthread_detach(AudioThread);
|
||||
#ifdef very_old_unused_USE_ALSA
|
||||
// wait until thread has opened and is ready
|
||||
do {
|
||||
pthread_yield();
|
||||
} while (!AlsaPCMHandle);
|
||||
#endif
|
||||
|
||||
pthread_yield();
|
||||
usleep(5 * 1000);
|
||||
usleep(5 * 1000); // give thread some time to start
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1671,6 +1911,19 @@ static void AudioExitThread(void)
|
||||
//----------------------------------------------------------------------------
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Table of all audio modules.
|
||||
*/
|
||||
static const AudioModule *AudioModules[] = {
|
||||
#ifdef USE_ALSA
|
||||
&AlsaModule,
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
&OssModule,
|
||||
#endif
|
||||
&NoopModule,
|
||||
};
|
||||
|
||||
/**
|
||||
** Place samples in audio output queue.
|
||||
**
|
||||
@@ -1679,14 +1932,7 @@ static void AudioExitThread(void)
|
||||
*/
|
||||
void AudioEnqueue(const void *samples, int count)
|
||||
{
|
||||
#ifdef USE_ALSA
|
||||
AlsaEnqueue(samples, count);
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
OssEnqueue(samples, count);
|
||||
#endif
|
||||
(void)samples;
|
||||
(void)count;
|
||||
AudioUsedModule->Enqueue(samples, count);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1694,24 +1940,7 @@ void AudioEnqueue(const void *samples, int count)
|
||||
*/
|
||||
void AudioFlushBuffers(void)
|
||||
{
|
||||
#ifdef USE_ALSA
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
// signal thread to flush buffers
|
||||
if (AudioThread) {
|
||||
AlsaFlushBuffer = 1;
|
||||
do {
|
||||
AudioRunning = 1; // wakeup in case of sleeping
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
usleep(1 * 1000);
|
||||
} while (AlsaFlushBuffer); // wait until flushed
|
||||
}
|
||||
#else
|
||||
AlsaFlushBuffers();
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
OssFlushBuffers();
|
||||
#endif
|
||||
AudioUsedModule->FlushBuffers();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1719,14 +1948,7 @@ void AudioFlushBuffers(void)
|
||||
*/
|
||||
void AudioPoller(void)
|
||||
{
|
||||
#ifndef USE_AUDIO_THREAD
|
||||
#ifdef USE_ALSA
|
||||
Error(_("audio/alsa: poller not implemented\n"));
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
OssPoller();
|
||||
#endif
|
||||
#endif
|
||||
AudioUsedModule->Poller();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1734,13 +1956,17 @@ void AudioPoller(void)
|
||||
*/
|
||||
int AudioFreeBytes(void)
|
||||
{
|
||||
#ifdef USE_ALSA
|
||||
return AlsaRingBuffer ? RingBufferFreeBytes(AlsaRingBuffer) : INT32_MAX;
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
return OssRingBuffer ? RingBufferFreeBytes(OssRingBuffer) : INT32_MAX;
|
||||
#endif
|
||||
return INT32_MAX; // no driver, much space
|
||||
return AudioUsedModule->FreeBytes();
|
||||
}
|
||||
|
||||
/**
|
||||
** Get audio delay in time stamps.
|
||||
**
|
||||
** @returns audio delay in time stamps.
|
||||
*/
|
||||
uint64_t AudioGetDelay(void)
|
||||
{
|
||||
return AudioUsedModule->GetDelay();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1760,22 +1986,6 @@ void AudioSetClock(int64_t pts)
|
||||
AudioPTS = pts;
|
||||
}
|
||||
|
||||
/**
|
||||
** Get audio delay in time stamps.
|
||||
**
|
||||
** @returns audio delay in time stamps.
|
||||
*/
|
||||
uint64_t AudioGetDelay(void)
|
||||
{
|
||||
#ifdef USE_ALSA
|
||||
return AlsaGetDelay();
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
return OssGetDelay();
|
||||
#endif
|
||||
return 0UL;
|
||||
}
|
||||
|
||||
/**
|
||||
** Get current audio clock.
|
||||
**
|
||||
@@ -1783,11 +1993,12 @@ uint64_t AudioGetDelay(void)
|
||||
*/
|
||||
int64_t AudioGetClock(void)
|
||||
{
|
||||
int64_t delay;
|
||||
if ((uint64_t) AudioPTS != INT64_C(0x8000000000000000)) {
|
||||
int64_t delay;
|
||||
|
||||
delay = AudioGetDelay();
|
||||
if (delay && (uint64_t) AudioPTS != INT64_C(0x8000000000000000)) {
|
||||
return AudioPTS - delay;
|
||||
if ((delay = AudioGetDelay())) {
|
||||
return AudioPTS - delay;
|
||||
}
|
||||
}
|
||||
return INT64_C(0x8000000000000000);
|
||||
}
|
||||
@@ -1830,53 +2041,81 @@ int AudioSetup(int *freq, int *channels)
|
||||
// FIXME: set flag invalid setup
|
||||
return -1;
|
||||
}
|
||||
#if defined(SEARCH_HDMI_BUG) || defined(SEARCH_HDMI_BUG2)
|
||||
#ifdef USE_AUDIORING
|
||||
// FIXME: need to store possible combination and report this
|
||||
return AudioRingAdd(*freq, *channels);
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
return AlsaSetup(freq, channels);
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
return OssSetup(freq, channels);
|
||||
#endif
|
||||
return -1;
|
||||
return AudioUsedModule->Setup(freq, channels);
|
||||
}
|
||||
|
||||
/**
|
||||
** Set pcm audio device.
|
||||
**
|
||||
** @param device name of pcm device (fe. "hw:0,9" or "/dev/dsp")
|
||||
**
|
||||
** @note this is currently used to select alsa/OSS output module.
|
||||
*/
|
||||
void AudioSetDevice(const char *device)
|
||||
{
|
||||
AudioModuleName = "alsa"; // detect alsa/OSS
|
||||
if (!device[0]) {
|
||||
AudioModuleName = "noop";
|
||||
} else if (device[0] == '/') {
|
||||
AudioModuleName = "oss";
|
||||
}
|
||||
AudioPCMDevice = device;
|
||||
}
|
||||
|
||||
/**
|
||||
** Initialize audio output module.
|
||||
**
|
||||
** @todo FIXME: make audio output module selectable.
|
||||
*/
|
||||
void AudioInit(void)
|
||||
{
|
||||
int freq;
|
||||
int chan;
|
||||
unsigned u;
|
||||
const char *name;
|
||||
|
||||
#ifdef SEARCH_HDMI_BUG2
|
||||
AudioRingInit();
|
||||
name = "noop";
|
||||
#ifdef USE_OSS
|
||||
name = "oss";
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
AlsaInit();
|
||||
name = "alsa";
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
OssInit();
|
||||
if (AudioModuleName) {
|
||||
name = AudioModuleName;
|
||||
}
|
||||
//
|
||||
// search selected audio module.
|
||||
//
|
||||
for (u = 0; u < sizeof(AudioModules) / sizeof(*AudioModules); ++u) {
|
||||
if (!strcasecmp(name, AudioModules[u]->Name)) {
|
||||
AudioUsedModule = AudioModules[u];
|
||||
Info(_("audio: '%s' output module used\n"), AudioUsedModule->Name);
|
||||
goto found;
|
||||
}
|
||||
}
|
||||
Error(_("audio: '%s' output module isn't supported\n"), name);
|
||||
AudioUsedModule = &NoopModule;
|
||||
return;
|
||||
|
||||
found:
|
||||
#ifdef USE_AUDIORING
|
||||
AudioRingInit();
|
||||
#endif
|
||||
AudioUsedModule->Init();
|
||||
freq = 48000;
|
||||
chan = 2;
|
||||
if (AudioSetup(&freq, &chan)) { // set default parameters
|
||||
Error(_("audio: can't do initial setup\n"));
|
||||
}
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
AudioInitThread();
|
||||
if (AudioUsedModule->Thread) { // supports threads
|
||||
AudioInitThread();
|
||||
}
|
||||
#endif
|
||||
|
||||
AudioPaused = 1;
|
||||
@@ -1890,13 +2129,9 @@ void AudioExit(void)
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
AudioExitThread();
|
||||
#endif
|
||||
#ifdef USE_ALSA
|
||||
AlsaExit();
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
OssExit();
|
||||
#endif
|
||||
#ifdef SEARCH_HDMI_BUG2
|
||||
AudioUsedModule->Exit();
|
||||
AudioUsedModule = &NoopModule;
|
||||
#ifdef USE_AUDIORING
|
||||
AudioRingExit();
|
||||
#endif
|
||||
}
|
||||
@@ -1942,7 +2177,7 @@ static void PrintVersion(void)
|
||||
#ifdef GIT_REV
|
||||
"(GIT-" GIT_REV ")"
|
||||
#endif
|
||||
",\n\t(c) 2009 - 2011 by Johns\n"
|
||||
",\n\t(c) 2009 - 2012 by Johns\n"
|
||||
"\tLicense AGPLv3: GNU Affero General Public License version 3\n");
|
||||
}
|
||||
|
||||
|
||||
8
audio.h
8
audio.h
@@ -30,21 +30,19 @@
|
||||
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 AudioUsedBytes(void); ///< used bytes in audio output
|
||||
extern uint64_t AudioGetDelay(void); ///< get current audio delay
|
||||
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 void AudioSetVolume(int); ///< set volume
|
||||
extern int AudioSetup(int *, int *); ///< setup audio output
|
||||
|
||||
//extern void AudioPlay(void); ///< play audio
|
||||
//extern void AudioPause(void); ///< pause audio
|
||||
extern void AudioSetVolume(int); ///< set volume
|
||||
|
||||
extern void AudioSetDevice(const char *); ///< set alsa PCM audio device
|
||||
extern void AudioSetDevice(const char *); ///< set PCM audio device
|
||||
extern void AudioInit(void); ///< setup audio module
|
||||
extern void AudioExit(void); ///< cleanup and exit audio module
|
||||
|
||||
|
||||
54
softhddev.c
54
softhddev.c
@@ -652,6 +652,9 @@ static int ValidateMpeg(const uint8_t * data, int size)
|
||||
** supports complete packets.
|
||||
** We buffer here until we receive an complete PES Packet, which
|
||||
** is no problem, the audio is always far behind us.
|
||||
** cTsToPes::GetPes splits the packets.
|
||||
**
|
||||
** @todo FIXME: combine the 5 ifs at start of the function
|
||||
*/
|
||||
int PlayVideo(const uint8_t * data, int size)
|
||||
{
|
||||
@@ -695,7 +698,7 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
Error(_("[softhddev] invalid video packet %d bytes\n"), size);
|
||||
return size;
|
||||
}
|
||||
// FIXME: hack to test results
|
||||
// buffer full: needed for replay
|
||||
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
|
||||
return 0;
|
||||
}
|
||||
@@ -788,6 +791,29 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
** Grabs the currently visible screen image.
|
||||
**
|
||||
** @param size size of the returned data
|
||||
** @param jpeg flag true, create JPEG data
|
||||
** @param quality JPEG quality
|
||||
** @param width number of horizontal pixels in the frame
|
||||
** @param height number of vertical pixels in the frame
|
||||
*/
|
||||
uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
|
||||
{
|
||||
if (jpeg) {
|
||||
(void)quality;
|
||||
Error(_("softhddev: jpeg grabbing not supported\n"));
|
||||
return NULL;
|
||||
}
|
||||
if (width != -1 && height != -1) {
|
||||
Error(_("softhddev: scaling not supported\n"));
|
||||
return NULL;
|
||||
}
|
||||
return VideoGrab(size, &width, &height);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
@@ -913,22 +939,19 @@ int Flush(int timeout)
|
||||
void GetOsdSize(int *width, int *height, double *aspect)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
static char done;
|
||||
static int done_width;
|
||||
static int done_height;
|
||||
#endif
|
||||
|
||||
// FIXME: should be configured!
|
||||
*width = 1920;
|
||||
*height = 1080;
|
||||
//*width = 768;
|
||||
//*height = 576;
|
||||
|
||||
VideoGetOsdSize(width, height);
|
||||
*aspect = 16.0 / 9.0 / (double)*width * (double)*height;
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!done) {
|
||||
if (done_width != *width || done_height != *height) {
|
||||
Debug(3, "[softhddev]%s: %dx%d %g\n", __FUNCTION__, *width, *height,
|
||||
*aspect);
|
||||
done = 1;
|
||||
done_width = *width;
|
||||
done_height = *height;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
@@ -1117,8 +1140,12 @@ static void StartXServer(void)
|
||||
*/
|
||||
void SoftHdDeviceExit(void)
|
||||
{
|
||||
// lets hope that vdr does a good thead cleanup
|
||||
// no it doesn't do a good thread cleanup
|
||||
// lets hope that vdr does a good thread cleanup
|
||||
|
||||
VideoOsdExit();
|
||||
VideoExit();
|
||||
AudioExit();
|
||||
|
||||
if (MyVideoDecoder) {
|
||||
CodecVideoClose(MyVideoDecoder);
|
||||
// FIXME: CodecDelVideoDecoder(MyVideoDecoder);
|
||||
@@ -1130,9 +1157,6 @@ void SoftHdDeviceExit(void)
|
||||
MyAudioDecoder = NULL;
|
||||
}
|
||||
|
||||
VideoOsdExit();
|
||||
VideoExit();
|
||||
AudioExit();
|
||||
CodecExit();
|
||||
VideoPacketExit();
|
||||
|
||||
|
||||
@@ -46,6 +46,8 @@ extern "C"
|
||||
extern int PlayVideo(const uint8_t *, int);
|
||||
/// C plugin play TS video packet
|
||||
extern void PlayTsVideo(const uint8_t *, int);
|
||||
/// C plugin grab an image
|
||||
extern uint8_t *GrabImage(int *, int, int, int, int);
|
||||
|
||||
/// C plugin set play mode
|
||||
extern void SetPlayMode(void);
|
||||
|
||||
179
softhddevice.cpp
179
softhddevice.cpp
@@ -42,7 +42,7 @@ extern "C"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char *const VERSION = "0.3.1";
|
||||
static const char *const VERSION = "0.4.0";
|
||||
static const char *const DESCRIPTION =
|
||||
trNOOP("A software and GPU emulated HD device");
|
||||
|
||||
@@ -53,6 +53,7 @@ static class cSoftHdDevice *MyDevice;
|
||||
|
||||
#define RESOLUTIONS 4 ///< number of resolutions
|
||||
|
||||
/// resolutions names
|
||||
static const char *const Resolution[RESOLUTIONS] = {
|
||||
"576i", "720p", "1080i_fake", "1080i"
|
||||
};
|
||||
@@ -78,6 +79,9 @@ static int ConfigVideoScaling[RESOLUTIONS];
|
||||
static int ConfigVideoAudioDelay; ///< config audio delay
|
||||
static int ConfigAudioPassthrough; ///< config audio pass-through
|
||||
|
||||
static int ConfigAutoCropInterval; ///< auto crop detection interval
|
||||
static int ConfigAutoCropDelay; ///< auto crop detection delay
|
||||
|
||||
static volatile char DoMakePrimary; ///< flag switch primary
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -122,7 +126,7 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
|
||||
csoft = new cSoftRemote(keymap);
|
||||
}
|
||||
|
||||
dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
|
||||
//dsyslog("[softhddev]%s %s, %s\n", __FUNCTION__, keymap, key);
|
||||
csoft->Put(key, repeat, release);
|
||||
}
|
||||
|
||||
@@ -144,12 +148,13 @@ class cSoftOsd:public cOsd
|
||||
cSoftOsd::cSoftOsd(int left, int top, uint level)
|
||||
:cOsd(left, top, level)
|
||||
{
|
||||
// FIXME: OsdWidth/OsdHeight not correct!
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
||||
OsdHeight(), left, top, level);
|
||||
/* FIXME: OsdWidth/OsdHeight not correct!
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
||||
OsdHeight(), left, top, level);
|
||||
*/
|
||||
|
||||
this->Level = level;
|
||||
//SetActive(true);
|
||||
SetActive(true);
|
||||
}
|
||||
|
||||
cSoftOsd::~cSoftOsd(void)
|
||||
@@ -158,8 +163,15 @@ cSoftOsd::~cSoftOsd(void)
|
||||
SetActive(false);
|
||||
|
||||
#ifdef USE_YAEPG
|
||||
if (vidWin.bpp) {
|
||||
VideoSetOutputPosition(0, 0, 1920, 1080);
|
||||
// support yaepghd, video window
|
||||
if (vidWin.bpp) { // restore fullsized video
|
||||
int width;
|
||||
int height;
|
||||
double video_aspect;
|
||||
|
||||
::GetOsdSize(&width, &height, &video_aspect);
|
||||
// works osd relative
|
||||
VideoSetOutputPosition(0, 0, width, height);
|
||||
}
|
||||
#endif
|
||||
OsdClose();
|
||||
@@ -175,8 +187,8 @@ void cSoftOsd::Flush(void)
|
||||
if (!Active()) {
|
||||
return;
|
||||
}
|
||||
// support yaepghd, video window
|
||||
#ifdef USE_YAEPG
|
||||
// support yaepghd, video window
|
||||
if (vidWin.bpp) {
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d\n", __FUNCTION__, vidWin.Width(),
|
||||
vidWin.Height(), vidWin.x1, vidWin.y2);
|
||||
@@ -213,6 +225,7 @@ void cSoftOsd::Flush(void)
|
||||
if (!bitmap->Dirty(x1, y1, x2, y2)) {
|
||||
continue; // nothing dirty continue
|
||||
}
|
||||
#if 0
|
||||
// FIXME: need only to convert and upload dirty areas
|
||||
|
||||
// DrawBitmap(bitmap);
|
||||
@@ -225,7 +238,6 @@ void cSoftOsd::Flush(void)
|
||||
((uint32_t *) argb)[x + y * w] = bitmap->GetColor(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
// check if subtitles
|
||||
if (this->Level == OSD_LEVEL_SUBTITLES) {
|
||||
int video_width;
|
||||
@@ -238,12 +250,32 @@ void cSoftOsd::Flush(void)
|
||||
video_width = 1920;
|
||||
video_height = 1080;
|
||||
OsdDrawARGB((1920 - video_width) / 2 + Left() + bitmap->X0(),
|
||||
1080 - video_height + Top() + bitmap->Y0(),
|
||||
bitmap->Width(), bitmap->Height(), argb);
|
||||
1080 - video_height + Top() + bitmap->Y0(), w, h, argb);
|
||||
} else {
|
||||
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(),
|
||||
bitmap->Width(), bitmap->Height(), argb);
|
||||
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(), w, h,
|
||||
argb);
|
||||
}
|
||||
#else
|
||||
// convert and upload only dirty areas
|
||||
w = x2 - x1 + 1;
|
||||
h = y2 - y1 + 1;
|
||||
#ifdef DEBUG
|
||||
if (w > bitmap->Width() || h > bitmap->Height()) {
|
||||
esyslog(tr("softhdev: dirty area too big\n"));
|
||||
abort();
|
||||
}
|
||||
#endif
|
||||
argb = (uint8_t *) malloc(w * h * sizeof(uint32_t));
|
||||
for (y = y1; y <= y2; ++y) {
|
||||
for (x = x1; x <= x2; ++x) {
|
||||
((uint32_t *) argb)[x - x1 + (y - y1) * w] =
|
||||
bitmap->GetColor(x, y);
|
||||
}
|
||||
}
|
||||
// check if subtitles
|
||||
OsdDrawARGB(Left() + bitmap->X0() + x1, Top() + bitmap->Y0() + y1,
|
||||
w, h, argb);
|
||||
#endif
|
||||
|
||||
bitmap->Clean();
|
||||
free(argb);
|
||||
@@ -264,8 +296,8 @@ void cSoftOsd::Flush(void)
|
||||
h = pm->ViewPort().Height();
|
||||
|
||||
/*
|
||||
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h, x,
|
||||
y, pm->Data());
|
||||
dsyslog("[softhddev]%s: draw %dx%d+%d+%d %p\n", __FUNCTION__, w, h,
|
||||
x, y, pm->Data());
|
||||
*/
|
||||
|
||||
OsdDrawARGB(x, y, w, h, pm->Data());
|
||||
@@ -334,6 +366,8 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
int Sharpen[RESOLUTIONS];
|
||||
int AudioDelay;
|
||||
int AudioPassthrough;
|
||||
int AutoCropInterval;
|
||||
int AutoCropDelay;
|
||||
protected:
|
||||
virtual void Store(void);
|
||||
public:
|
||||
@@ -342,6 +376,8 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
|
||||
/**
|
||||
** Create a seperator item.
|
||||
**
|
||||
** @param label text inside separator
|
||||
*/
|
||||
static inline cOsdItem *SeparatorItem(const char *label)
|
||||
{
|
||||
@@ -376,10 +412,10 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
// cMenuEditStrItem cMenuEditStraItem cMenuEditIntItem
|
||||
MakePrimary = ConfigMakePrimary;
|
||||
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
|
||||
tr("no"), tr("yes")));
|
||||
trVDR("no"), trVDR("yes")));
|
||||
HideMainMenuEntry = ConfigHideMainMenuEntry;
|
||||
Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &HideMainMenuEntry,
|
||||
tr("no"), tr("yes")));
|
||||
trVDR("no"), trVDR("yes")));
|
||||
//
|
||||
// video
|
||||
//
|
||||
@@ -393,7 +429,7 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
deinterlace));
|
||||
SkipChromaDeinterlace[i] = ConfigVideoSkipChromaDeinterlace[i];
|
||||
Add(new cMenuEditBoolItem(tr("SkipChromaDeinterlace (vdpau)"),
|
||||
&SkipChromaDeinterlace[i], tr("no"), tr("yes")));
|
||||
&SkipChromaDeinterlace[i], trVDR("no"), trVDR("yes")));
|
||||
Denoise[i] = ConfigVideoDenoise[i];
|
||||
Add(new cMenuEditIntItem(tr("Denoise (0..1000) (vdpau)"), &Denoise[i],
|
||||
0, 1000));
|
||||
@@ -411,6 +447,16 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
AudioPassthrough = ConfigAudioPassthrough;
|
||||
Add(new cMenuEditStraItem(tr("Audio pass-through"), &AudioPassthrough, 2,
|
||||
passthrough));
|
||||
//
|
||||
// auto-crop
|
||||
//
|
||||
Add(SeparatorItem(tr("Auto-crop")));
|
||||
AutoCropInterval = ConfigAutoCropInterval;
|
||||
Add(new cMenuEditIntItem(tr("autocrop interval (frames)"),
|
||||
&AutoCropInterval, 0, 200));
|
||||
AutoCropDelay = ConfigAutoCropDelay;
|
||||
Add(new cMenuEditIntItem(tr("autocrop delay (n * interval)"),
|
||||
&AutoCropDelay, 0, 200));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -450,6 +496,11 @@ void cMenuSetupSoft::Store(void)
|
||||
VideoSetAudioDelay(ConfigVideoAudioDelay);
|
||||
SetupStore("AudioPassthrough", ConfigAudioPassthrough = AudioPassthrough);
|
||||
CodecSetAudioPassthrough(ConfigAudioPassthrough);
|
||||
|
||||
SetupStore("AutoCrop.Interval", ConfigAutoCropInterval = AutoCropInterval);
|
||||
SetupStore("AutoCrop.Delay", ConfigAutoCropDelay = AutoCropDelay);
|
||||
|
||||
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -475,17 +526,12 @@ class cSoftHdDevice:public cDevice
|
||||
virtual bool Poll(cPoller &, int = 0);
|
||||
virtual bool Flush(int = 0);
|
||||
virtual int64_t GetSTC(void);
|
||||
virtual void GetVideoSize(int &width, int &height, double &aspect)
|
||||
{
|
||||
width = 1920;
|
||||
height = 1080;
|
||||
aspect = (double)width / height;
|
||||
}
|
||||
virtual void GetVideoSize(int &, int &, double &);
|
||||
virtual void GetOsdSize(int &, int &, double &);
|
||||
virtual int PlayVideo(const uchar *, int);
|
||||
|
||||
//virtual int PlayTsVideo(const uchar *, int);
|
||||
#ifdef USE_OSS // FIXME: testing only oss
|
||||
#ifndef USE_AUDIO_THREAD // FIXME: testing none threaded
|
||||
virtual int PlayTsAudio(const uchar *, int);
|
||||
#endif
|
||||
virtual void SetAudioChannelDevice(int);
|
||||
@@ -498,8 +544,6 @@ class cSoftHdDevice:public cDevice
|
||||
|
||||
virtual uchar *GrabImage(int &, bool, int, int, int);
|
||||
|
||||
virtual int ProvidesCa(const cChannel *) const;
|
||||
|
||||
#if 0
|
||||
// SPU facilities
|
||||
private:
|
||||
@@ -526,6 +570,11 @@ cSoftHdDevice::~cSoftHdDevice(void)
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
}
|
||||
|
||||
/**
|
||||
** Informs a device that it will be the primary device.
|
||||
**
|
||||
** @param on flag if becoming or loosing primary
|
||||
*/
|
||||
void cSoftHdDevice::MakePrimaryDevice(bool on)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, on);
|
||||
@@ -536,18 +585,9 @@ void cSoftHdDevice::MakePrimaryDevice(bool on)
|
||||
}
|
||||
}
|
||||
|
||||
int cSoftHdDevice::ProvidesCa(
|
||||
__attribute__ ((unused)) const cChannel *
|
||||
channel) const
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
@@ -697,7 +737,18 @@ bool cSoftHdDevice::Flush(int timeout_ms)
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Returns the With, Height and PixelAspect ratio the OSD.
|
||||
** Returns the width, height and video_aspect ratio of the currently
|
||||
** displayed video material.
|
||||
**
|
||||
** @note the size is used to scale the subtitle.
|
||||
*/
|
||||
void cSoftHdDevice::GetVideoSize(int &width, int &height, double &video_aspect)
|
||||
{
|
||||
::GetOsdSize(&width, &height, &video_aspect);
|
||||
}
|
||||
|
||||
/**
|
||||
** Returns the width, height and pixel_aspect ratio the OSD.
|
||||
**
|
||||
** FIXME: Called every second, for nothing (no OSD displayed)?
|
||||
*/
|
||||
@@ -757,33 +808,47 @@ int cSoftHdDevice::PlayVideo(const uchar * data, int length)
|
||||
///
|
||||
/// Play a TS video packet.
|
||||
///
|
||||
int cSoftHdDevice::PlayTsVideo(const uchar * Data, int Length)
|
||||
int cSoftHdDevice::PlayTsVideo(const uchar * data, int length)
|
||||
{
|
||||
// many code to repeat
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef USE_OSS // FIXME: testing only oss
|
||||
#ifndef USE_AUDIO_THREAD // FIXME: testing none threaded
|
||||
|
||||
///
|
||||
/// Play a TS audio packet.
|
||||
///
|
||||
/// misuse this function as audio poller
|
||||
///
|
||||
/// @param data ts data buffer
|
||||
/// @param length ts packet length
|
||||
///
|
||||
int cSoftHdDevice::PlayTsAudio(const uchar * data, int length)
|
||||
{
|
||||
AudioPoller();
|
||||
|
||||
return cDevice::PlayTsAudio(data, length);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int sizex,
|
||||
int sizey)
|
||||
/**
|
||||
** Grabs the currently visible screen image.
|
||||
**
|
||||
** @param size size of the returned data
|
||||
** @param jpeg flag true, create JPEG data
|
||||
** @param quality JPEG quality
|
||||
** @param width number of horizontal pixels in the frame
|
||||
** @param height number of vertical pixels in the frame
|
||||
*/
|
||||
uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
|
||||
int height)
|
||||
{
|
||||
dsyslog("[softhddev]%s: %d, %d, %d, %dx%d\n", __FUNCTION__, size, jpeg,
|
||||
quality, sizex, sizey);
|
||||
quality, width, height);
|
||||
|
||||
return NULL;
|
||||
return::GrabImage(&size, jpeg, quality, width, height);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -927,7 +992,9 @@ cOsdObject *cPluginSoftHdDevice::MainMenuAction(void)
|
||||
|
||||
cDevice::PrimaryDevice()->StopReplay();
|
||||
Suspend();
|
||||
ShutdownHandler.SetUserInactive();
|
||||
if (ShutdownHandler.GetUserInactiveTime()) {
|
||||
ShutdownHandler.SetUserInactive();
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
@@ -966,11 +1033,15 @@ cMenuSetupPage *cPluginSoftHdDevice::SetupMenu(void)
|
||||
|
||||
/**
|
||||
** Parse setup parameters
|
||||
**
|
||||
** @param name paramter name (case sensetive)
|
||||
** @param value value as string
|
||||
**
|
||||
** @returns true if the parameter is supported.
|
||||
*/
|
||||
bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
{
|
||||
int i;
|
||||
char buf[128];
|
||||
|
||||
//dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
|
||||
|
||||
@@ -983,6 +1054,8 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
char buf[128];
|
||||
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
|
||||
if (!strcmp(name, buf)) {
|
||||
ConfigVideoScaling[i] = atoi(value);
|
||||
@@ -1015,6 +1088,7 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!strcmp(name, "AudioDelay")) {
|
||||
VideoSetAudioDelay(ConfigVideoAudioDelay = atoi(value));
|
||||
return true;
|
||||
@@ -1024,6 +1098,17 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!strcmp(name, "AutoCrop.Interval")) {
|
||||
VideoSetAutoCrop(ConfigAutoCropInterval =
|
||||
atoi(value), ConfigAutoCropDelay);
|
||||
return true;
|
||||
}
|
||||
if (!strcmp(name, "AutoCrop.Delay")) {
|
||||
VideoSetAutoCrop(ConfigAutoCropInterval, ConfigAutoCropDelay =
|
||||
atoi(value));
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,15 +21,15 @@ SRC_URI=""
|
||||
LICENSE="AGPL-3"
|
||||
SLOT="0"
|
||||
KEYWORDS="~x86 ~amd64"
|
||||
IUSE="vaapi vdpau alsa oss yaepg"
|
||||
IUSE="vaapi vdpau alsa oss yaepg opengl"
|
||||
|
||||
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
|
||||
opengl? ( virtual/opengl )
|
||||
>=media-video/ffmpeg-0.7
|
||||
sys-devel/gettext
|
||||
sys-devel/make
|
||||
@@ -39,6 +39,7 @@ DEPEND=">=x11-libs/libxcb-1.7
|
||||
vdpau? ( x11-libs/libvdpau )
|
||||
vaapi? ( x11-libs/libva )
|
||||
alsa? ( media-libs/alsa-lib )
|
||||
oss? ( sys-kernel/linux-headers )
|
||||
"
|
||||
|
||||
src_prepare() {
|
||||
|
||||
12
video.h
12
video.h
@@ -37,6 +37,9 @@ typedef struct _video_hw_decoder_ VideoHwDecoder;
|
||||
/// Allocate new video hardware decoder.
|
||||
extern VideoHwDecoder *VideoNewHwDecoder(void);
|
||||
|
||||
/// Deallocate video hardware decoder.
|
||||
extern void VideoDelHwDecoder(VideoHwDecoder *);
|
||||
|
||||
/// Get and allocate a video hardware surface.
|
||||
extern unsigned VideoGetSurface(VideoHwDecoder *);
|
||||
|
||||
@@ -97,14 +100,23 @@ extern void VideoSetSharpen(int[]);
|
||||
/// Set audio delay.
|
||||
extern void VideoSetAudioDelay(int);
|
||||
|
||||
/// Set auto-crop parameters.
|
||||
extern void VideoSetAutoCrop(int, int);
|
||||
|
||||
/// Clear OSD.
|
||||
extern void VideoOsdClear(void);
|
||||
|
||||
/// Draw an OSD ARGB image.
|
||||
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
|
||||
|
||||
/// Get OSD size.
|
||||
extern void VideoGetOsdSize(int *, int *);
|
||||
|
||||
extern int64_t VideoGetClock(void); ///< Get video clock.
|
||||
|
||||
/// Grab screen.
|
||||
extern uint8_t *VideoGrab(int *, int *, int *);
|
||||
|
||||
extern void VideoOsdInit(void); ///< Setup osd.
|
||||
extern void VideoOsdExit(void); ///< Cleanup osd.
|
||||
|
||||
|
||||
Reference in New Issue
Block a user