mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e619f5c836 | ||
|
|
973fcfe4dd | ||
|
|
eec30433b6 | ||
|
|
baf577aba5 | ||
|
|
81d7ef9755 | ||
|
|
7f7de8678f | ||
|
|
92bb00c410 | ||
|
|
d3b98b90f4 | ||
|
|
788636ee6b | ||
|
|
8e53cbd4a9 | ||
|
|
54661f90ea | ||
|
|
30d8e8afe9 | ||
|
|
19a37bb0bf | ||
|
|
2087968d55 | ||
|
|
d983f780b3 | ||
| 712b2e0de1 | |||
|
|
54f92e67fc | ||
|
|
960cd27ab5 | ||
|
|
3a97700981 |
30
ChangeLog
30
ChangeLog
@@ -1,4 +1,34 @@
|
||||
User johns
|
||||
Date: Sun Jan 15 16:56:04 CET 2012
|
||||
|
||||
Release Version 0.3.1
|
||||
Fix bug: AudioFreeBytes didn't check if audio running/compiled.
|
||||
Fix bug: snd_pcm_state: Assertion `pcm' failed.
|
||||
Add support for fullscreen and fullscreen toogle.
|
||||
Instant update deinterlace configuration changes.
|
||||
Fix subtitle position.
|
||||
Add SVDRP support.
|
||||
Suspend when user is inactive.
|
||||
|
||||
User Christian Rupper
|
||||
Date: Tue Jan 10 22:33:14 CET 2012
|
||||
|
||||
Move objects before $LIBS to avoid link failures with --as-needed.
|
||||
Do not override CFLAGS for video test.
|
||||
Rearrange *FLAGS incl. some minor fixes.
|
||||
Don't override VDRDIR, LIBDIR and TMPDIR in makefile.
|
||||
Don't abuse LDFLAGS in makefile.
|
||||
Define CC in makefile.
|
||||
Include GL/gl.h for the GL_COLOR_BUFFER_BIT definition.
|
||||
VideoInit() needs an argument.
|
||||
|
||||
User johns
|
||||
Date: Tue Jan 10 22:32:50 CET 2012
|
||||
|
||||
Add main menu entry, which suspends the plugin.
|
||||
Add support for resize window.
|
||||
Close window sends "close" as remote key press.
|
||||
|
||||
Date: Mon Jan 9 22:09:38 CET 2012
|
||||
|
||||
Release Version 0.3.0
|
||||
|
||||
73
Makefile
73
Makefile
@@ -26,40 +26,17 @@ CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
|
||||
|
||||
### The C++ compiler and options:
|
||||
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Woverloaded-virtual -fPIC
|
||||
override CXXFLAGS += $(DEFINES) $(INCLUDES)
|
||||
CFLAGS ?= -g -O2 -W -Wall -Wextra -Winit-self \
|
||||
-Wdeclaration-after-statement -fPIC
|
||||
#CFLAGS += -Werror
|
||||
override CFLAGS += $(DEFINES) $(INCLUDES) \
|
||||
$(shell pkg-config --cflags libavcodec libavformat) \
|
||||
`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
||||
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
||||
`pkg-config --cflags gl glu` \
|
||||
$(if $(findstring USE_VDPAU,$(CONFIG)), \
|
||||
`pkg-config --cflags vdpau`) \
|
||||
$(if $(findstring USE_VAAPI,$(CONFIG)), \
|
||||
`pkg-config --cflags libva-x11 libva-glx libva`) \
|
||||
$(if $(findstring USE_ALSA,$(CONFIG)), \
|
||||
`pkg-config --cflags alsa`)
|
||||
override LDFLAGS += -lrt \
|
||||
$(shell pkg-config --libs libavcodec libavformat) \
|
||||
`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
||||
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
||||
`pkg-config --libs gl glu` \
|
||||
$(if $(findstring USE_VDPAU,$(CONFIG)), \
|
||||
`pkg-config --libs vdpau`) \
|
||||
$(if $(findstring USE_VAAPI,$(CONFIG)), \
|
||||
`pkg-config --libs libva-x11 libva-glx libva`) \
|
||||
$(if $(findstring USE_ALSA,$(CONFIG)), \
|
||||
`pkg-config --libs alsa`)
|
||||
-Wdeclaration-after-statement
|
||||
CXXFLAGS ?= -g -O2 -W -Wall -Wextra -Woverloaded-virtual
|
||||
|
||||
### The directory environment:
|
||||
|
||||
VDRDIR = ../../..
|
||||
LIBDIR = ../../lib
|
||||
TMPDIR = /tmp
|
||||
VDRDIR ?= ../../..
|
||||
LIBDIR ?= ../../lib
|
||||
TMPDIR ?= /tmp
|
||||
|
||||
### Make sure that necessary options are included:
|
||||
|
||||
@@ -78,12 +55,40 @@ APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDI
|
||||
ARCHIVE = $(PLUGIN)-$(VERSION)
|
||||
PACKAGE = vdr-$(ARCHIVE)
|
||||
|
||||
### Includes and Defines (add further entries here):
|
||||
### Includes, Defines and dependencies (add further entries here):
|
||||
|
||||
INCLUDES += -I$(VDRDIR)/include
|
||||
|
||||
DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"'
|
||||
|
||||
_CFLAGS = $(DEFINES) $(INCLUDES) \
|
||||
$(shell pkg-config --cflags libavcodec libavformat) \
|
||||
`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
||||
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
||||
`pkg-config --cflags gl glu` \
|
||||
$(if $(findstring USE_VDPAU,$(CONFIG)), \
|
||||
`pkg-config --cflags vdpau`) \
|
||||
$(if $(findstring USE_VAAPI,$(CONFIG)), \
|
||||
`pkg-config --cflags libva-x11 libva-glx libva`) \
|
||||
$(if $(findstring USE_ALSA,$(CONFIG)), \
|
||||
`pkg-config --cflags alsa`)
|
||||
|
||||
#override _CFLAGS += -Werror
|
||||
override CXXFLAGS += $(_CFLAGS)
|
||||
override CFLAGS += $(_CFLAGS)
|
||||
|
||||
LIBS += -lrt \
|
||||
$(shell pkg-config --libs libavcodec libavformat) \
|
||||
`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
||||
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
||||
`pkg-config --libs gl glu` \
|
||||
$(if $(findstring USE_VDPAU,$(CONFIG)), \
|
||||
`pkg-config --libs vdpau`) \
|
||||
$(if $(findstring USE_VAAPI,$(CONFIG)), \
|
||||
`pkg-config --libs libva-x11 libva-glx libva`) \
|
||||
$(if $(findstring USE_ALSA,$(CONFIG)), \
|
||||
`pkg-config --libs alsa`)
|
||||
|
||||
### The object files (add further files here):
|
||||
|
||||
OBJS = $(PLUGIN).o softhddev.o video.o audio.o codec.o ringbuffer.o
|
||||
@@ -105,6 +110,8 @@ DEPFILE = .dependencies
|
||||
$(DEPFILE): Makefile
|
||||
@$(MAKEDEP) $(DEFINES) $(INCLUDES) $(SRCS) >$@
|
||||
|
||||
$(OBJS): Makefile
|
||||
|
||||
-include $(DEPFILE)
|
||||
|
||||
### Internationalization (I18N):
|
||||
@@ -137,7 +144,7 @@ i18n: $(I18Nmsgs) $(I18Npot)
|
||||
### Targets:
|
||||
|
||||
libvdr-$(PLUGIN).so: $(OBJS) Makefile
|
||||
$(CXX) $(CXXFLAGS) -shared $(OBJS) -o $@ $(LDFLAGS)
|
||||
$(CXX) $(CXXFLAGS) $(LDFLAGS) -shared -fPIC $(OBJS) -o $@ $(LIBS)
|
||||
@cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION)
|
||||
|
||||
dist: $(I18Npo) clean
|
||||
@@ -163,5 +170,5 @@ indent:
|
||||
done
|
||||
|
||||
video_test: video.c
|
||||
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $(LIBS) \
|
||||
-O0 -g -o $@ $<
|
||||
$(CC) -DVIDEO_TEST -DVERSION='"$(VERSION)"' $(CFLAGS) $(LDFLAGS) $< $(LIBS) \
|
||||
-o $@
|
||||
|
||||
26
README.txt
26
README.txt
@@ -33,7 +33,7 @@ A software and GPU emulated HD output device plugin for VDR.
|
||||
o Audio FFMpeg/Alsa/Analog
|
||||
o Audio FFMpeg/Alsa/Digital
|
||||
o Audio FFMpeg/OSS/Analog
|
||||
o planned: Alsa HDMI/SPDIF Passthrough
|
||||
o Alsa HDMI/SPDIF Passthrough
|
||||
o planned: OSS HDMI/SPDIF Passthrough
|
||||
|
||||
To compile you must have the 'requires' installed.
|
||||
@@ -95,6 +95,9 @@ Setup: /etc/vdr/setup.conf
|
||||
softhddevice.MakePrimary = 1
|
||||
0 = no change, 1 make softhddevice primary at start
|
||||
|
||||
softhddevice.HideMainMenuEntry = 0
|
||||
0 = show softhddevice main menu entry, 1 = hide entry
|
||||
|
||||
<res> of the next parameters is 567i, 720p, 1080i_fake or 1080i.
|
||||
1080i_fake is 1280x1080 or 1440x1080
|
||||
1080i is "real" 1920x1080
|
||||
@@ -122,12 +125,33 @@ Setup: /etc/vdr/setup.conf
|
||||
softhddevice.AudioPassthrough = 0
|
||||
0 = none, 1 = AC-3
|
||||
|
||||
Setup: /etc/vdr/remote.conf
|
||||
------
|
||||
|
||||
Add "XKeySym." definitions to /etc/vdr/remote.conf to control
|
||||
the vdr and plugin with the connected input device.
|
||||
|
||||
fe.
|
||||
XKeySym.Up Up
|
||||
XKeySym.Down Down
|
||||
...
|
||||
|
||||
Additional to the x11 input sends the window close button "Close".
|
||||
|
||||
fe.
|
||||
XKeySym.Power Close
|
||||
|
||||
Commandline:
|
||||
------------
|
||||
|
||||
Use vdr -h to see the command line arguments support by the plugin.
|
||||
|
||||
Running:
|
||||
--------
|
||||
|
||||
Click into video window to toggle fullscreen/window mode, only if you
|
||||
have a window manager running.
|
||||
|
||||
Warning:
|
||||
--------
|
||||
libav is not supported, expect many bugs with it.
|
||||
|
||||
38
Todo
38
Todo
@@ -19,17 +19,13 @@ GNU Affero General Public License for more details.
|
||||
$Id: $
|
||||
|
||||
missing:
|
||||
video out with xv
|
||||
video out with opengl
|
||||
software decoder for xv / opengl
|
||||
software deinterlace
|
||||
auto crop
|
||||
atmolight
|
||||
zoom/fit-zoom 4:3
|
||||
multistream handling
|
||||
disable screensaver
|
||||
disable window cursor
|
||||
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.
|
||||
|
||||
vdpau:
|
||||
1080i with temporal spatial and level 1 scaling too slow with my GT 520
|
||||
@@ -38,6 +34,7 @@ vdpau:
|
||||
Improve OSD handling, show only what is used. Big OSD costs performance
|
||||
VdpPreemptionCallback handling
|
||||
hard channel switch
|
||||
suspendoutput didn't show logo or black picture.
|
||||
|
||||
libva:
|
||||
hard channel switch
|
||||
@@ -57,16 +54,14 @@ libva-vdpau-driver:
|
||||
libva-xvba-driver:
|
||||
|
||||
x11:
|
||||
support resize of x11 window
|
||||
support fullscreen window
|
||||
support fullscreen / window toggle
|
||||
close window should send power button
|
||||
disable cursor
|
||||
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)
|
||||
|
||||
better downmix of >2 channels on 2 channel hardware
|
||||
remix support of unsupported sample rates
|
||||
@@ -74,6 +69,9 @@ audio/alsa:
|
||||
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
|
||||
ring buffer overflow with alsa oss emulation
|
||||
@@ -81,6 +79,7 @@ audio/oss:
|
||||
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
|
||||
|
||||
playback of recording
|
||||
pause is not reset, when replay exit
|
||||
@@ -91,6 +90,17 @@ setup:
|
||||
Setup of output type.
|
||||
Setup of display type.
|
||||
Setup 4:3 zoom type
|
||||
Setup parameters are not used until restart.
|
||||
Some setup parameters are not used until restart.
|
||||
Can a notice be added to the setup menu?
|
||||
576i, 720p, fake 1080i, 1080i
|
||||
|
||||
future features (not planed for 1.0 - 1.5)
|
||||
|
||||
video out with xv
|
||||
video out with opengl
|
||||
video out with xvba
|
||||
software decoder for xv / opengl
|
||||
atmolight support
|
||||
multistream handling
|
||||
|
||||
upmix stereo to AC-3
|
||||
|
||||
44
audio.c
44
audio.c
@@ -856,23 +856,9 @@ static int AlsaSetup(int *freq, int *channels)
|
||||
if (!AlsaPCMHandle) { // alsa not running yet
|
||||
return -1;
|
||||
}
|
||||
#if 1
|
||||
#if 1 // easy alsa hw setup way
|
||||
// flush any buffered data
|
||||
#ifndef SEARCH_HDMI_BUG2
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
if (AudioRunning) {
|
||||
while (AudioRunning) {
|
||||
AlsaFlushBuffer = 1;
|
||||
usleep(1 * 1000);
|
||||
}
|
||||
AlsaFlushBuffer = 0;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
AlsaFlushBuffers();
|
||||
}
|
||||
#endif
|
||||
AudioPTS = INT64_C(0x8000000000000000);
|
||||
AudioFlushBuffers();
|
||||
|
||||
if (1) { // close+open to fix hdmi no sound bugs
|
||||
handle = AlsaPCMHandle;
|
||||
@@ -1449,7 +1435,6 @@ static int OssSetup(int *freq, int *channels)
|
||||
AudioRunning = 0;
|
||||
OssFlushBuffers();
|
||||
}
|
||||
AudioPTS = INT64_C(0x8000000000000000);
|
||||
|
||||
ret = 0;
|
||||
|
||||
@@ -1711,17 +1696,18 @@ void AudioFlushBuffers(void)
|
||||
{
|
||||
#ifdef USE_ALSA
|
||||
#ifdef USE_AUDIO_THREAD
|
||||
if (AudioRunning) {
|
||||
while (AudioRunning) {
|
||||
AlsaFlushBuffer = 1;
|
||||
// signal thread to flush buffers
|
||||
if (AudioThread) {
|
||||
AlsaFlushBuffer = 1;
|
||||
do {
|
||||
AudioRunning = 1; // wakeup in case of sleeping
|
||||
pthread_cond_signal(&AudioStartCond);
|
||||
usleep(1 * 1000);
|
||||
}
|
||||
AlsaFlushBuffer = 0;
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
AlsaFlushBuffers();
|
||||
} while (AlsaFlushBuffer); // wait until flushed
|
||||
}
|
||||
#else
|
||||
AlsaFlushBuffers();
|
||||
#endif
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
OssFlushBuffers();
|
||||
@@ -1749,12 +1735,12 @@ void AudioPoller(void)
|
||||
int AudioFreeBytes(void)
|
||||
{
|
||||
#ifdef USE_ALSA
|
||||
return RingBufferFreeBytes(AlsaRingBuffer);
|
||||
return AlsaRingBuffer ? RingBufferFreeBytes(AlsaRingBuffer) : INT32_MAX;
|
||||
#endif
|
||||
#ifdef USE_OSS
|
||||
return RingBufferFreeBytes(OssRingBuffer);
|
||||
return OssRingBuffer ? RingBufferFreeBytes(OssRingBuffer) : INT32_MAX;
|
||||
#endif
|
||||
return -1;
|
||||
return INT32_MAX; // no driver, much space
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
126
softhddev.c
126
softhddev.c
@@ -35,6 +35,11 @@
|
||||
|
||||
#include <libavcodec/avcodec.h>
|
||||
|
||||
#ifndef __USE_GNU
|
||||
#define __USE_GNU
|
||||
#endif
|
||||
#include <pthread.h>
|
||||
|
||||
#include "misc.h"
|
||||
#include "softhddev.h"
|
||||
|
||||
@@ -52,7 +57,13 @@ static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
|
||||
#define ConfigVdpauDecoder 0 ///< no vdpau decoder configured
|
||||
#endif
|
||||
|
||||
static const char DeviceStopped = 1; ///< flag device stopped
|
||||
static char ConfigFullscreen; ///< fullscreen modus
|
||||
static char ConfigSuspendClose = 1; ///< suspend should close devices
|
||||
static char ConfigSuspendX11 = 1; ///< suspend should stop x11
|
||||
|
||||
static pthread_mutex_t SuspendLockMutex; ///< suspend lock mutex
|
||||
|
||||
static volatile char VideoFreezed; ///< video freezed
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Audio
|
||||
@@ -195,13 +206,16 @@ int PlayAudio(const uint8_t * data, int size,
|
||||
|
||||
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
|
||||
|
||||
if (VideoFreezed) { // video freezed
|
||||
return 0;
|
||||
}
|
||||
if (NewAudioStream) {
|
||||
// FIXME: does this clear the audio ringbuffer?
|
||||
CodecAudioClose(MyAudioDecoder);
|
||||
AudioCodecID = CODEC_ID_NONE;
|
||||
NewAudioStream = 0;
|
||||
}
|
||||
if (SkipAudio) {
|
||||
if (SkipAudio) { // skip audio
|
||||
return size;
|
||||
}
|
||||
// PES header 0x00 0x00 0x01 ID
|
||||
@@ -313,7 +327,7 @@ int PlayAudio(const uint8_t * data, int size,
|
||||
void Mute(void)
|
||||
{
|
||||
SkipAudio = 1;
|
||||
AudioSetVolume(0);
|
||||
//AudioSetVolume(0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -348,8 +362,8 @@ static AVPacket VideoPacketRb[VIDEO_PACKET_MAX];
|
||||
static int VideoPacketWrite; ///< write pointer
|
||||
static int VideoPacketRead; ///< read pointer
|
||||
static atomic_t VideoPacketsFilled; ///< how many of the buffer is used
|
||||
static volatile char VideoFreezed; ///< video freezed
|
||||
static volatile char VideoClearBuffers; ///< clear video buffers
|
||||
static volatile char SkipVideo; ///< skip video
|
||||
|
||||
#ifdef DEBUG
|
||||
static int VideoMaxPacketSize; ///< biggest used packet buffer
|
||||
@@ -567,19 +581,23 @@ int VideoDecode(void)
|
||||
/**
|
||||
** Try video start.
|
||||
**
|
||||
** Could be called, when already started.
|
||||
** NOT TRUE: Could be called, when already started.
|
||||
*/
|
||||
static void StartVideo(void)
|
||||
{
|
||||
VideoInit(X11DisplayName);
|
||||
if (ConfigFullscreen) {
|
||||
// FIXME: not good looking, mapped and then resized.
|
||||
VideoSetFullscreen(1);
|
||||
}
|
||||
VideoOsdInit();
|
||||
if (!MyVideoDecoder) {
|
||||
VideoHwDecoder *hw_decoder;
|
||||
|
||||
if ((hw_decoder = VideoNewHwDecoder())) {
|
||||
MyVideoDecoder = CodecVideoNewDecoder(hw_decoder);
|
||||
VideoCodecID = CODEC_ID_NONE;
|
||||
}
|
||||
VideoCodecID = CODEC_ID_NONE;
|
||||
}
|
||||
VideoPacketInit();
|
||||
}
|
||||
@@ -648,6 +666,12 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
if (!MyVideoDecoder) { // no x11 video started
|
||||
return size;
|
||||
}
|
||||
if (SkipVideo) { // skip video
|
||||
return size;
|
||||
}
|
||||
if (VideoFreezed) { // video freezed
|
||||
return 0;
|
||||
}
|
||||
if (NewVideoStream) { // channel switched
|
||||
Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch);
|
||||
// FIXME: hack to test results
|
||||
@@ -668,7 +692,7 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
n = data[8]; // header size
|
||||
// wrong size
|
||||
if (size < 9 + n + 4) {
|
||||
Error(_("[softhddev] invalid video packet\n"));
|
||||
Error(_("[softhddev] invalid video packet %d bytes\n"), size);
|
||||
return size;
|
||||
}
|
||||
// FIXME: hack to test results
|
||||
@@ -735,6 +759,16 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
Debug(3, "video: h264 detected\n");
|
||||
VideoCodecID = CODEC_ID_H264;
|
||||
}
|
||||
// Access Unit Delimiter (BBC-HD)
|
||||
// FIXME: the 4 offset are try & error selected
|
||||
} else if ((data[6] & 0xC0) == 0x80 && !check[4 + 0] && !check[4 + 1]
|
||||
&& !check[4 + 2] && check[4 + 3] == 0x1 && check[4 + 4] == 0x09) {
|
||||
if (VideoCodecID == CODEC_ID_H264) {
|
||||
VideoNextPacket(CODEC_ID_H264);
|
||||
} else {
|
||||
Debug(3, "video: h264 detected\n");
|
||||
VideoCodecID = CODEC_ID_H264;
|
||||
}
|
||||
} else {
|
||||
// this happens when vdr sends incomplete packets
|
||||
if (VideoCodecID == CODEC_ID_NONE) {
|
||||
@@ -761,6 +795,7 @@ int PlayVideo(const uint8_t * data, int size)
|
||||
*/
|
||||
void SetPlayMode(void)
|
||||
{
|
||||
Resume();
|
||||
if (MyVideoDecoder) {
|
||||
if (VideoCodecID != CODEC_ID_NONE) {
|
||||
NewVideoStream = 1;
|
||||
@@ -774,6 +809,7 @@ void SetPlayMode(void)
|
||||
}
|
||||
VideoFreezed = 0;
|
||||
SkipAudio = 0;
|
||||
SkipVideo = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -910,12 +946,13 @@ void OsdClose(void)
|
||||
*/
|
||||
void OsdDrawARGB(int x, int y, int height, int width, const uint8_t * argb)
|
||||
{
|
||||
Resume();
|
||||
VideoOsdDrawARGB(x, y, height, width, argb);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static char StartX11Server; ///< flag start the x11 server
|
||||
static char ConfigStartX11Server; ///< flag start the x11 server
|
||||
|
||||
/**
|
||||
** Return command line help string.
|
||||
@@ -924,6 +961,7 @@ const char *CommandLineHelp(void)
|
||||
{
|
||||
return " -a device\taudio device (fe. alsa: hw:0,0 oss: /dev/dsp)\n"
|
||||
" -d display\tdisplay of x11 server (fe. :0.0)\n"
|
||||
" -f\t\tstart with fullscreen window (only with window manager)\n"
|
||||
" -g geometry\tx11 window geometry wxh+x+y\n"
|
||||
" -x\t\tstart x11 server\n";
|
||||
}
|
||||
@@ -940,13 +978,16 @@ int ProcessArgs(int argc, char *const argv[])
|
||||
// Parse arguments.
|
||||
//
|
||||
for (;;) {
|
||||
switch (getopt(argc, argv, "-a:d:g:x")) {
|
||||
switch (getopt(argc, argv, "-a:d:fg:x")) {
|
||||
case 'a': // audio device
|
||||
AudioSetDevice(optarg);
|
||||
continue;
|
||||
case 'd': // x11 display name
|
||||
X11DisplayName = optarg;
|
||||
continue;
|
||||
case 'f': // fullscreen mode
|
||||
ConfigFullscreen = 1;
|
||||
continue;
|
||||
case 'g': // geometry
|
||||
if (VideoSetGeometry(optarg) < 0) {
|
||||
fprintf(stderr,
|
||||
@@ -956,7 +997,7 @@ int ProcessArgs(int argc, char *const argv[])
|
||||
}
|
||||
continue;
|
||||
case 'x': // x11 server
|
||||
StartX11Server = 1;
|
||||
ConfigStartX11Server = 1;
|
||||
continue;
|
||||
case EOF:
|
||||
break;
|
||||
@@ -1095,13 +1136,16 @@ void SoftHdDeviceExit(void)
|
||||
CodecExit();
|
||||
VideoPacketExit();
|
||||
|
||||
if (StartX11Server) {
|
||||
if (ConfigStartX11Server) {
|
||||
Debug(3, "x-setup: Stop x11 server\n");
|
||||
|
||||
if (X11ServerPid) {
|
||||
kill(X11ServerPid, SIGTERM);
|
||||
// FIXME: wait for x11 finishing
|
||||
}
|
||||
}
|
||||
|
||||
pthread_mutex_destroy(&SuspendLockMutex);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1109,15 +1153,17 @@ void SoftHdDeviceExit(void)
|
||||
*/
|
||||
void Start(void)
|
||||
{
|
||||
if (StartX11Server) {
|
||||
if (ConfigStartX11Server) {
|
||||
StartXServer();
|
||||
}
|
||||
CodecInit();
|
||||
// FIXME: AudioInit for HDMI after X11 startup
|
||||
AudioInit();
|
||||
if (!StartX11Server) {
|
||||
if (!ConfigStartX11Server) {
|
||||
StartVideo();
|
||||
}
|
||||
|
||||
pthread_mutex_init(&SuspendLockMutex, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1138,3 +1184,57 @@ void Stop(void)
|
||||
void MainThreadHook(void)
|
||||
{
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Suspend/Resume
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
** Suspend plugin.
|
||||
*/
|
||||
void Suspend(void)
|
||||
{
|
||||
pthread_mutex_lock(&SuspendLockMutex);
|
||||
if (SkipVideo && SkipAudio) { // already suspended
|
||||
pthread_mutex_unlock(&SuspendLockMutex);
|
||||
return;
|
||||
}
|
||||
|
||||
Debug(3, "[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
SkipVideo = 1;
|
||||
SkipAudio = 1;
|
||||
pthread_mutex_unlock(&SuspendLockMutex);
|
||||
|
||||
if (ConfigSuspendClose) {
|
||||
pthread_mutex_lock(&SuspendLockMutex);
|
||||
// FIXME: close audio
|
||||
// FIXME: close video
|
||||
pthread_mutex_unlock(&SuspendLockMutex);
|
||||
}
|
||||
if (ConfigSuspendX11) {
|
||||
// FIXME: stop x11, if started
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
** Resume plugin.
|
||||
*/
|
||||
void Resume(void)
|
||||
{
|
||||
if (!SkipVideo && !SkipAudio) { // we are not suspended
|
||||
return;
|
||||
}
|
||||
|
||||
Debug(3, "[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
if (ConfigSuspendX11) {
|
||||
}
|
||||
if (ConfigSuspendClose) {
|
||||
pthread_mutex_lock(&SuspendLockMutex);
|
||||
pthread_mutex_unlock(&SuspendLockMutex);
|
||||
}
|
||||
|
||||
SkipVideo = 0;
|
||||
SkipAudio = 0;
|
||||
}
|
||||
|
||||
@@ -76,6 +76,10 @@ extern "C"
|
||||
/// C plugin main thread hook
|
||||
extern void MainThreadHook(void);
|
||||
|
||||
/// Suspend plugin
|
||||
extern void Suspend(void);
|
||||
/// Resume plugin
|
||||
extern void Resume(void);
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
191
softhddevice.cpp
191
softhddevice.cpp
@@ -42,11 +42,11 @@ extern "C"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static const char *const VERSION = "0.3.0";
|
||||
static const char *const VERSION = "0.3.1";
|
||||
static const char *const DESCRIPTION =
|
||||
trNOOP("A software and GPU emulated HD device");
|
||||
|
||||
//static const char *MAINMENUENTRY = trNOOP("Soft-HD-Device");
|
||||
static const char *MAINMENUENTRY = trNOOP("Suspend Soft-HD-Device");
|
||||
static class cSoftHdDevice *MyDevice;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
@@ -58,6 +58,7 @@ static const char *const Resolution[RESOLUTIONS] = {
|
||||
};
|
||||
|
||||
static char ConfigMakePrimary; ///< config primary wanted
|
||||
static char ConfigHideMainMenuEntry; ///< config hide main menu entry
|
||||
|
||||
/// config deinterlace
|
||||
static int ConfigVideoDeinterlace[RESOLUTIONS];
|
||||
@@ -131,8 +132,10 @@ extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
|
||||
|
||||
class cSoftOsd:public cOsd
|
||||
{
|
||||
int Level; ///< level: subtitle
|
||||
|
||||
public:
|
||||
cSoftOsd(int, int, uint);
|
||||
cSoftOsd(int, int, uint);
|
||||
virtual ~ cSoftOsd(void);
|
||||
virtual void Flush(void);
|
||||
// virtual void SetActive(bool);
|
||||
@@ -145,6 +148,7 @@ cSoftOsd::cSoftOsd(int left, int top, uint level)
|
||||
dsyslog("[softhddev]%s: %dx%d+%d+%d, %d\n", __FUNCTION__, OsdWidth(),
|
||||
OsdHeight(), left, top, level);
|
||||
|
||||
this->Level = level;
|
||||
//SetActive(true);
|
||||
}
|
||||
|
||||
@@ -222,8 +226,24 @@ void cSoftOsd::Flush(void)
|
||||
}
|
||||
}
|
||||
|
||||
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(),
|
||||
bitmap->Width(), bitmap->Height(), argb);
|
||||
// check if subtitles
|
||||
if (this->Level == OSD_LEVEL_SUBTITLES) {
|
||||
int video_width;
|
||||
int video_height;
|
||||
|
||||
if (0) {
|
||||
dsyslog("[softhddev]%s: subtitle %d, %d\n", __FUNCTION__,
|
||||
Left() + bitmap->X0(), Top() + bitmap->Y0());
|
||||
}
|
||||
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);
|
||||
} else {
|
||||
OsdDrawARGB(Left() + bitmap->X0(), Top() + bitmap->Y0(),
|
||||
bitmap->Width(), bitmap->Height(), argb);
|
||||
}
|
||||
|
||||
bitmap->Clean();
|
||||
free(argb);
|
||||
@@ -306,6 +326,7 @@ class cMenuSetupSoft:public cMenuSetupPage
|
||||
{
|
||||
protected:
|
||||
int MakePrimary;
|
||||
int HideMainMenuEntry;
|
||||
int Scaling[RESOLUTIONS];
|
||||
int Deinterlace[RESOLUTIONS];
|
||||
int SkipChromaDeinterlace[RESOLUTIONS];
|
||||
@@ -338,7 +359,7 @@ static inline cOsdItem *SeparatorItem(const char *label)
|
||||
cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
{
|
||||
static const char *const deinterlace[] = {
|
||||
"Bob", "Weave", "Temporal", "TemporalSpatial", "Software"
|
||||
"Bob", "Weave/None", "Temporal", "TemporalSpatial", "Software"
|
||||
};
|
||||
static const char *const scaling[] = {
|
||||
"Normal", "Fast", "HQ", "Anamorphic"
|
||||
@@ -356,6 +377,9 @@ cMenuSetupSoft::cMenuSetupSoft(void)
|
||||
MakePrimary = ConfigMakePrimary;
|
||||
Add(new cMenuEditBoolItem(tr("Make primary device"), &MakePrimary,
|
||||
tr("no"), tr("yes")));
|
||||
HideMainMenuEntry = ConfigHideMainMenuEntry;
|
||||
Add(new cMenuEditBoolItem(tr("Hide main menu entry"), &HideMainMenuEntry,
|
||||
tr("no"), tr("yes")));
|
||||
//
|
||||
// video
|
||||
//
|
||||
@@ -397,6 +421,8 @@ void cMenuSetupSoft::Store(void)
|
||||
int i;
|
||||
|
||||
SetupStore("MakePrimary", ConfigMakePrimary = MakePrimary);
|
||||
SetupStore("HideMainMenuEntry", ConfigHideMainMenuEntry =
|
||||
HideMainMenuEntry);
|
||||
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
char buf[128];
|
||||
@@ -449,8 +475,15 @@ 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 GetOsdSize(int &, int &, double &);
|
||||
virtual int PlayVideo(const uchar *, int);
|
||||
|
||||
//virtual int PlayTsVideo(const uchar *, int);
|
||||
#ifdef USE_OSS // FIXME: testing only oss
|
||||
virtual int PlayTsAudio(const uchar *, int);
|
||||
@@ -467,11 +500,13 @@ class cSoftHdDevice:public cDevice
|
||||
|
||||
virtual int ProvidesCa(const cChannel *) const;
|
||||
|
||||
#if 0
|
||||
// SPU facilities
|
||||
private:
|
||||
cDvbSpuDecoder * spuDecoder;
|
||||
public:
|
||||
virtual cSpuDecoder * GetSpuDecoder(void);
|
||||
#endif
|
||||
|
||||
protected:
|
||||
virtual void MakePrimaryDevice(bool);
|
||||
@@ -481,7 +516,9 @@ cSoftHdDevice::cSoftHdDevice(void)
|
||||
{
|
||||
//dsyslog("[softhddev]%s\n", __FUNCTION__);
|
||||
|
||||
#if 0
|
||||
spuDecoder = NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
cSoftHdDevice::~cSoftHdDevice(void)
|
||||
@@ -499,15 +536,18 @@ void cSoftHdDevice::MakePrimaryDevice(bool on)
|
||||
}
|
||||
}
|
||||
|
||||
int cSoftHdDevice::ProvidesCa(
|
||||
__attribute__ ((unused)) const cChannel * channel) const
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
|
||||
int cSoftHdDevice::ProvidesCa(
|
||||
__attribute__ ((unused)) const cChannel *
|
||||
channel) const
|
||||
{
|
||||
//dsyslog("[softhddev]%s: %p\n", __FUNCTION__, channel);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
#if 0
|
||||
|
||||
cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
@@ -517,6 +557,8 @@ cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
|
||||
return spuDecoder;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
bool cSoftHdDevice::HasDecoder(void) const
|
||||
{
|
||||
return true;
|
||||
@@ -540,7 +582,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode PlayMode)
|
||||
case pmVideoOnly:
|
||||
break;
|
||||
case pmNone:
|
||||
break;
|
||||
return true;
|
||||
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
||||
break;
|
||||
default:
|
||||
@@ -584,6 +626,9 @@ void cSoftHdDevice::Play(void)
|
||||
::Play();
|
||||
}
|
||||
|
||||
/**
|
||||
** Puts the device into "freeze frame" mode.
|
||||
*/
|
||||
void cSoftHdDevice::Freeze(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
@@ -759,11 +804,13 @@ class cPluginSoftHdDevice:public cPlugin
|
||||
virtual void Stop(void);
|
||||
// virtual void Housekeeping(void);
|
||||
virtual void MainThreadHook(void);
|
||||
// virtual const char *MainMenuEntry(void);
|
||||
// virtual cOsdObject *MainMenuAction(void);
|
||||
virtual const char *MainMenuEntry(void);
|
||||
virtual cOsdObject *MainMenuAction(void);
|
||||
virtual cMenuSetupPage *SetupMenu(void);
|
||||
virtual bool SetupParse(const char *, const char *);
|
||||
// virtual bool Service(const char *Id, void *Data = NULL);
|
||||
// virtual bool Service(const char *, void * = NULL);
|
||||
virtual const char **SVDRPHelpPages(void);
|
||||
virtual cString SVDRPCommand(const char *, const char *, int &);
|
||||
};
|
||||
|
||||
cPluginSoftHdDevice::cPluginSoftHdDevice(void)
|
||||
@@ -820,15 +867,14 @@ bool cPluginSoftHdDevice::Initialize(void)
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
** Start any background activities the plugin shall perform.
|
||||
*/
|
||||
bool cPluginSoftHdDevice::Start(void)
|
||||
{
|
||||
const cDevice *primary;
|
||||
|
||||
// Start any background activities the plugin shall perform.
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
primary = cDevice::PrimaryDevice();
|
||||
if (MyDevice != primary) {
|
||||
if (!MyDevice->IsPrimaryDevice()) {
|
||||
isyslog("[softhddev] softhddevice is not the primary device!");
|
||||
if (ConfigMakePrimary) {
|
||||
// Must be done in the main thread
|
||||
@@ -860,14 +906,31 @@ void cPluginSoftHdDevice::Housekeeping(void)
|
||||
// Perform any cleanup or other regular tasks.
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Create main menu entry.
|
||||
*/
|
||||
const char *cPluginSoftHdDevice::MainMenuEntry(void)
|
||||
{
|
||||
//dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
return tr(MAINMENUENTRY);
|
||||
return NULL;
|
||||
|
||||
return ConfigHideMainMenuEntry ? NULL : tr(MAINMENUENTRY);
|
||||
}
|
||||
|
||||
#endif
|
||||
/**
|
||||
** Perform the action when selected from the main VDR menu.
|
||||
*/
|
||||
cOsdObject *cPluginSoftHdDevice::MainMenuAction(void)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
cDevice::PrimaryDevice()->StopReplay();
|
||||
Suspend();
|
||||
ShutdownHandler.SetUserInactive();
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
** Called for every plugin once during every cycle of VDR's main program
|
||||
@@ -882,29 +945,15 @@ void cPluginSoftHdDevice::MainThreadHook(void)
|
||||
cDevice::SetPrimaryDevice(MyDevice->DeviceNumber() + 1);
|
||||
DoMakePrimary = 0;
|
||||
}
|
||||
// check if user is inactive, automatic enter suspend mode
|
||||
if (ShutdownHandler.IsUserInactive()) {
|
||||
// this is regular called, but guarded against double calls
|
||||
Suspend();
|
||||
}
|
||||
|
||||
::MainThreadHook();
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
bool cPluginSoftHdDevice::Service(const char *Id, void *Data)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
cOsdObject *cPluginSoftHdDevice::MainMenuAction(void)
|
||||
{
|
||||
// Perform the action when selected from the main VDR menu.
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
** Return our setup menu.
|
||||
*/
|
||||
@@ -923,13 +972,16 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
int i;
|
||||
char buf[128];
|
||||
|
||||
dsyslog("[softhddev]%s: '%s' = '%s'\n", __FUNCTION__, name, value);
|
||||
//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, "HideMainMenuEntry")) {
|
||||
ConfigHideMainMenuEntry = atoi(value);
|
||||
return true;
|
||||
}
|
||||
for (i = 0; i < RESOLUTIONS; ++i) {
|
||||
snprintf(buf, sizeof(buf), "%s.%s", Resolution[i], "Scaling");
|
||||
if (!strcmp(name, buf)) {
|
||||
@@ -975,4 +1027,51 @@ bool cPluginSoftHdDevice::SetupParse(const char *name, const char *value)
|
||||
return false;
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
bool cPluginSoftHdDevice::Service(const char *Id, void *Data)
|
||||
{
|
||||
dsyslog("[softhddev]%s:\n", __FUNCTION__);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// cPlugin SVDRP
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
/**
|
||||
** Return SVDRP commands help pages.
|
||||
**
|
||||
** return a pointer to a list of help strings for all of the plugin's
|
||||
** SVDRP commands.
|
||||
*/
|
||||
const char **cPluginSoftHdDevice::SVDRPHelpPages(void)
|
||||
{
|
||||
// FIXME: translation?
|
||||
static const char *text[] = {
|
||||
"SUSP\n",
|
||||
" Suspend plugin",
|
||||
NULL
|
||||
};
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
** Handle SVDRP commands.
|
||||
*/
|
||||
cString cPluginSoftHdDevice::SVDRPCommand(const char *command,
|
||||
__attribute__ ((unused)) const char *option,
|
||||
__attribute__ ((unused)) int &reply_code)
|
||||
{
|
||||
if (!strcasecmp(command, "SUSP")) {
|
||||
Suspend();
|
||||
return "SoftHdDevice is suspended";
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
VDRPLUGINCREATOR(cPluginSoftHdDevice); // Don't touch this!
|
||||
|
||||
450
video.c
450
video.c
@@ -94,10 +94,28 @@
|
||||
#include <xcb/xcb_event.h>
|
||||
#include <xcb/xcb_atom.h>
|
||||
#include <xcb/xcb_icccm.h>
|
||||
#ifdef XCB_ICCCM_NUM_WM_SIZE_HINTS_ELEMENTS
|
||||
#include <xcb/xcb_ewmh.h>
|
||||
#else // compatibility hack for old xcb-util
|
||||
|
||||
/**
|
||||
* @brief Action on the _NET_WM_STATE property
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
/* Remove/unset property */
|
||||
XCB_EWMH_WM_STATE_REMOVE = 0,
|
||||
/* Add/set property */
|
||||
XCB_EWMH_WM_STATE_ADD = 1,
|
||||
/* Toggle property */
|
||||
XCB_EWMH_WM_STATE_TOGGLE = 2
|
||||
} xcb_ewmh_wm_state_action_t;
|
||||
#endif
|
||||
#include <xcb/xcb_keysyms.h>
|
||||
#endif
|
||||
|
||||
#ifdef USE_GLX
|
||||
#include <GL/gl.h> // For GL_COLOR_BUFFER_BIT
|
||||
#include <GL/glx.h>
|
||||
// only for gluErrorString
|
||||
#include <GL/glu.h>
|
||||
@@ -208,6 +226,8 @@ static int VideoWindowY; ///< video outout window y coordinate
|
||||
static unsigned VideoWindowWidth; ///< video output window width
|
||||
static unsigned VideoWindowHeight; ///< video output window height
|
||||
|
||||
static char VideoSurfaceModesChanged; ///< flag surface modes changed
|
||||
|
||||
/// Default deinterlace mode.
|
||||
static VideoDeinterlaceModes VideoDeinterlace[VideoResolutionMax];
|
||||
|
||||
@@ -239,6 +259,8 @@ static VideoZoomModes Video4to3ZoomMode;
|
||||
static char Video60HzMode; ///< handle 60hz displays
|
||||
|
||||
static xcb_atom_t WmDeleteWindowAtom; ///< WM delete message
|
||||
static xcb_atom_t NetWmState; ///< wm-state message atom
|
||||
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
||||
|
||||
extern uint32_t VideoSwitch; ///< ticks for channel switch
|
||||
|
||||
@@ -915,7 +937,6 @@ struct _vaapi_decoder_
|
||||
|
||||
/// flags for put surface for different resolutions groups
|
||||
unsigned SurfaceFlagsTable[VideoResolutionMax];
|
||||
unsigned SurfaceFlags; ///< current flags for put surface
|
||||
|
||||
enum PixelFormat PixFmt; ///< ffmpeg frame pixfmt
|
||||
int WrongInterlacedWarned; ///< warning about interlace flag issued
|
||||
@@ -1017,20 +1038,6 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
|
||||
Warning(_("video/vaapi: no osd subpicture yet\n"));
|
||||
return;
|
||||
}
|
||||
#if 0
|
||||
// FIXME: try to fix intel osd bugs
|
||||
if (vaDestroySubpicture(VaDisplay, VaOsdSubpicture)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: can't destroy subpicture\n"));
|
||||
}
|
||||
VaOsdSubpicture = VA_INVALID_ID;
|
||||
|
||||
if (vaCreateSubpicture(VaDisplay, VaOsdImage.image_id,
|
||||
&VaOsdSubpicture) != VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: can't create subpicture\n"));
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (VaapiUnscaledOsd) {
|
||||
if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
|
||||
@@ -1041,18 +1048,12 @@ static void VaapiCreateSurfaces(VaapiDecoder * decoder, int width, int height)
|
||||
Error(_("video/vaapi: can't associate subpicture\n"));
|
||||
}
|
||||
} else {
|
||||
int i;
|
||||
|
||||
if (vaAssociateSubpicture(VaDisplay, VaOsdSubpicture,
|
||||
decoder->SurfacesFree, decoder->SurfaceFreeN, 0, 0,
|
||||
VaOsdImage.width, VaOsdImage.height, 0, 0, width, height, 0)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: can't associate subpicture\n"));
|
||||
}
|
||||
for (i = 0; i < decoder->SurfaceFreeN; ++i) {
|
||||
Debug(4, "video/vaapi: associate %#010x surface\n",
|
||||
decoder->SurfacesFree[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1186,8 +1187,12 @@ static void VaapiInitSurfaceFlags(VaapiDecoder * decoder)
|
||||
|
||||
for (i = 0; i < VideoResolutionMax; ++i) {
|
||||
decoder->SurfaceFlagsTable[i] = VA_CLEAR_DRAWABLE;
|
||||
// FIXME: color space conversion none, ITU-R BT.601, ITU-R BT.709
|
||||
decoder->SurfaceFlagsTable[i] |= VA_SRC_BT601;
|
||||
// color space conversion none, ITU-R BT.601, ITU-R BT.709
|
||||
if (i > VideoResolution567i) {
|
||||
decoder->SurfaceFlagsTable[i] |= VA_SRC_BT709;
|
||||
} else {
|
||||
decoder->SurfaceFlagsTable[i] |= VA_SRC_BT601;
|
||||
}
|
||||
|
||||
// scaling flags FAST, HQ, NL_ANAMORPHIC
|
||||
// FIXME: need to detect the backend to choose the parameter
|
||||
@@ -1253,7 +1258,6 @@ static VaapiDecoder *VaapiNewDecoder(void)
|
||||
decoder->Window = VideoWindow;
|
||||
|
||||
VaapiInitSurfaceFlags(decoder);
|
||||
decoder->SurfaceFlags = decoder->SurfaceFlagsTable[0];
|
||||
|
||||
decoder->DeintImages[0].image_id = VA_INVALID_ID;
|
||||
decoder->DeintImages[1].image_id = VA_INVALID_ID;
|
||||
@@ -1557,6 +1561,12 @@ static void VaapiUpdateOutput(VaapiDecoder * decoder)
|
||||
decoder->InputWidth * input_aspect_ratio.num,
|
||||
decoder->InputHeight * input_aspect_ratio.den, 1024 * 1024);
|
||||
|
||||
// InputWidth/Height can be zero = uninitialized
|
||||
if (!display_aspect_ratio.num || !display_aspect_ratio.den) {
|
||||
display_aspect_ratio.num = 1;
|
||||
display_aspect_ratio.den = 1;
|
||||
}
|
||||
|
||||
Debug(3, "video: aspect %d:%d\n", display_aspect_ratio.num,
|
||||
display_aspect_ratio.den);
|
||||
|
||||
@@ -1787,7 +1797,6 @@ static enum PixelFormat Vaapi_get_format(VaapiDecoder * decoder,
|
||||
decoder->Resolution =
|
||||
VideoResolutionGroup(video_ctx->width, video_ctx->height,
|
||||
decoder->Interlaced);
|
||||
decoder->SurfaceFlags = decoder->SurfaceFlagsTable[decoder->Resolution];
|
||||
// FIXME: need only to create and destroy surfaces for size changes
|
||||
// or when number of needed surfaces changed!
|
||||
VaapiCreateSurfaces(decoder, video_ctx->width, video_ctx->height);
|
||||
@@ -1886,7 +1895,8 @@ static void VaapiPutSurfaceX11(VaapiDecoder * decoder, VASurfaceID surface,
|
||||
// video dst
|
||||
decoder->OutputX, decoder->OutputY, decoder->OutputWidth,
|
||||
decoder->OutputHeight, NULL, 0,
|
||||
type | decoder->SurfaceFlags)) != VA_STATUS_SUCCESS) {
|
||||
type | decoder->SurfaceFlagsTable[decoder->Resolution])) !=
|
||||
VA_STATUS_SUCCESS) {
|
||||
// switching video kills VdpPresentationQueueBlockUntilSurfaceIdle
|
||||
Error(_("video/vaapi: vaPutSurface failed %d\n"), status);
|
||||
}
|
||||
@@ -2005,7 +2015,8 @@ static void VaapiPutSurfaceGLX(VaapiDecoder * decoder, VASurfaceID surface,
|
||||
}
|
||||
start = GetMsTicks();
|
||||
if (vaCopySurfaceGLX(decoder->VaDisplay, decoder->GlxSurface[0], surface,
|
||||
type | decoder->SurfaceFlags) != VA_STATUS_SUCCESS) {
|
||||
type | decoder->SurfaceFlagsTable[decoder->Resolution]) !=
|
||||
VA_STATUS_SUCCESS) {
|
||||
Error(_("video/glx: vaCopySurfaceGLX failed\n"));
|
||||
return;
|
||||
}
|
||||
@@ -2127,7 +2138,6 @@ static void VaapiSetup(VaapiDecoder * decoder,
|
||||
// FIXME: interlaced not valid here?
|
||||
decoder->Resolution =
|
||||
VideoResolutionGroup(width, height, decoder->Interlaced);
|
||||
decoder->SurfaceFlags = decoder->SurfaceFlagsTable[decoder->Resolution];
|
||||
VaapiCreateSurfaces(decoder, width, height);
|
||||
|
||||
#ifdef USE_GLX
|
||||
@@ -2330,9 +2340,11 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
|
||||
vaPutSurface(decoder->VaDisplay, decoder->BlackSurface,
|
||||
decoder->Window,
|
||||
// decoder src
|
||||
0, 0, VideoWindowWidth, VideoWindowHeight,
|
||||
decoder->OutputX, decoder->OutputY, decoder->OutputWidth,
|
||||
decoder->OutputHeight,
|
||||
// video dst
|
||||
0, 0, VideoWindowWidth, VideoWindowHeight, NULL, 0,
|
||||
decoder->OutputX, decoder->OutputY, decoder->OutputWidth,
|
||||
decoder->OutputHeight, NULL, 0,
|
||||
VA_FRAME_PICTURE)) != VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: vaPutSurface failed %d\n"), status);
|
||||
}
|
||||
@@ -2341,9 +2353,8 @@ static void VaapiBlackSurface(VaapiDecoder * decoder)
|
||||
put1 = GetMsTicks();
|
||||
Debug(4, "video/vaapi: sync %2u put1 %2u\n", sync - start, put1 - sync);
|
||||
|
||||
if (0
|
||||
&& vaSyncSurface(decoder->VaDisplay,
|
||||
decoder->BlackSurface) != VA_STATUS_SUCCESS) {
|
||||
if (0 && vaSyncSurface(decoder->VaDisplay, decoder->BlackSurface)
|
||||
!= VA_STATUS_SUCCESS) {
|
||||
Error(_("video/vaapi: vaSyncSurface failed\n"));
|
||||
}
|
||||
|
||||
@@ -2772,10 +2783,16 @@ static void VaapiDisplayFrame(void)
|
||||
uint32_t put1;
|
||||
uint32_t put2;
|
||||
int i;
|
||||
VaapiDecoder *decoder;
|
||||
|
||||
if (VideoSurfaceModesChanged) { // handle changed modes
|
||||
for (i = 0; i < VaapiDecoderN; ++i) {
|
||||
VaapiInitSurfaceFlags(VaapiDecoders[i]);
|
||||
}
|
||||
VideoSurfaceModesChanged = 0;
|
||||
}
|
||||
// look if any stream have a new surface available
|
||||
for (i = 0; i < VaapiDecoderN; ++i) {
|
||||
VaapiDecoder *decoder;
|
||||
VASurfaceID surface;
|
||||
int filled;
|
||||
|
||||
@@ -3376,14 +3393,16 @@ static VdpGetErrorString *VdpauGetErrorString;
|
||||
static VdpDeviceDestroy *VdpauDeviceDestroy;
|
||||
static VdpGenerateCSCMatrix *VdpauGenerateCSCMatrix;
|
||||
static VdpVideoSurfaceQueryCapabilities *VdpauVideoSurfaceQueryCapabilities;
|
||||
static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities
|
||||
*VdpauVideoSurfaceQueryGetPutBitsYCbCrCapabilities;
|
||||
static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *
|
||||
VdpauVideoSurfaceQueryGetPutBitsYCbCrCapabilities;
|
||||
static VdpVideoSurfaceCreate *VdpauVideoSurfaceCreate;
|
||||
static VdpVideoSurfaceDestroy *VdpauVideoSurfaceDestroy;
|
||||
static VdpVideoSurfaceGetParameters *VdpauVideoSurfaceGetParameters;
|
||||
static VdpVideoSurfaceGetBitsYCbCr *VdpauVideoSurfaceGetBitsYCbCr;
|
||||
static VdpVideoSurfacePutBitsYCbCr *VdpauVideoSurfacePutBitsYCbCr;
|
||||
|
||||
static VdpOutputSurfaceQueryCapabilities *VdpauOutputSurfaceQueryCapabilities;
|
||||
|
||||
static VdpOutputSurfaceCreate *VdpauOutputSurfaceCreate;
|
||||
static VdpOutputSurfaceDestroy *VdpauOutputSurfaceDestroy;
|
||||
|
||||
@@ -3395,10 +3414,10 @@ static VdpBitmapSurfaceDestroy *VdpauBitmapSurfaceDestroy;
|
||||
|
||||
static VdpBitmapSurfacePutBitsNative *VdpauBitmapSurfacePutBitsNative;
|
||||
|
||||
static VdpOutputSurfaceRenderOutputSurface *
|
||||
VdpauOutputSurfaceRenderOutputSurface;
|
||||
static VdpOutputSurfaceRenderBitmapSurface *
|
||||
VdpauOutputSurfaceRenderBitmapSurface;
|
||||
static VdpOutputSurfaceRenderOutputSurface
|
||||
*VdpauOutputSurfaceRenderOutputSurface;
|
||||
static VdpOutputSurfaceRenderBitmapSurface
|
||||
*VdpauOutputSurfaceRenderBitmapSurface;
|
||||
|
||||
static VdpDecoderQueryCapabilities *VdpauDecoderQueryCapabilities;
|
||||
static VdpDecoderCreate *VdpauDecoderCreate;
|
||||
@@ -3407,8 +3426,8 @@ static VdpDecoderDestroy *VdpauDecoderDestroy;
|
||||
static VdpDecoderRender *VdpauDecoderRender;
|
||||
|
||||
static VdpVideoMixerQueryFeatureSupport *VdpauVideoMixerQueryFeatureSupport;
|
||||
static VdpVideoMixerQueryAttributeSupport *
|
||||
VdpauVideoMixerQueryAttributeSupport;
|
||||
static VdpVideoMixerQueryAttributeSupport
|
||||
*VdpauVideoMixerQueryAttributeSupport;
|
||||
|
||||
static VdpVideoMixerCreate *VdpauVideoMixerCreate;
|
||||
static VdpVideoMixerSetFeatureEnables *VdpauVideoMixerSetFeatureEnables;
|
||||
@@ -3419,18 +3438,18 @@ static VdpVideoMixerRender *VdpauVideoMixerRender;
|
||||
static VdpPresentationQueueTargetDestroy *VdpauPresentationQueueTargetDestroy;
|
||||
static VdpPresentationQueueCreate *VdpauPresentationQueueCreate;
|
||||
static VdpPresentationQueueDestroy *VdpauPresentationQueueDestroy;
|
||||
static VdpPresentationQueueSetBackgroundColor
|
||||
*VdpauPresentationQueueSetBackgroundColor;
|
||||
static VdpPresentationQueueSetBackgroundColor *
|
||||
VdpauPresentationQueueSetBackgroundColor;
|
||||
|
||||
static VdpPresentationQueueGetTime *VdpauPresentationQueueGetTime;
|
||||
static VdpPresentationQueueDisplay *VdpauPresentationQueueDisplay;
|
||||
static VdpPresentationQueueBlockUntilSurfaceIdle *
|
||||
VdpauPresentationQueueBlockUntilSurfaceIdle;
|
||||
static VdpPresentationQueueQuerySurfaceStatus *
|
||||
VdpauPresentationQueueQuerySurfaceStatus;
|
||||
static VdpPresentationQueueBlockUntilSurfaceIdle
|
||||
*VdpauPresentationQueueBlockUntilSurfaceIdle;
|
||||
static VdpPresentationQueueQuerySurfaceStatus
|
||||
*VdpauPresentationQueueQuerySurfaceStatus;
|
||||
|
||||
static VdpPresentationQueueTargetCreateX11
|
||||
*VdpauPresentationQueueTargetCreateX11;
|
||||
static VdpPresentationQueueTargetCreateX11 *
|
||||
VdpauPresentationQueueTargetCreateX11;
|
||||
///@}
|
||||
|
||||
///
|
||||
@@ -3921,6 +3940,95 @@ static inline void VdpauGetProc(const VdpFuncId id, void *addr,
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Initialize output queue.
|
||||
///
|
||||
static void VdpauInitOutputQueue(void)
|
||||
{
|
||||
VdpStatus status;
|
||||
int i;
|
||||
|
||||
status =
|
||||
VdpauPresentationQueueTargetCreateX11(VdpauDevice, VideoWindow,
|
||||
&VdpauQueueTarget);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't create presentation queue target: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
return;
|
||||
}
|
||||
|
||||
status =
|
||||
VdpauPresentationQueueCreate(VdpauDevice, VdpauQueueTarget,
|
||||
&VdpauQueue);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't create presentation queue: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
VdpauPresentationQueueTargetDestroy(VdpauQueueTarget);
|
||||
VdpauQueueTarget = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
VdpauBackgroundColor->red = 0.01;
|
||||
VdpauBackgroundColor->green = 0.02;
|
||||
VdpauBackgroundColor->blue = 0.03;
|
||||
VdpauBackgroundColor->alpha = 1.00;
|
||||
VdpauPresentationQueueSetBackgroundColor(VdpauQueue, VdpauBackgroundColor);
|
||||
|
||||
//
|
||||
// Create display output surfaces
|
||||
//
|
||||
for (i = 0; i < OUTPUT_SURFACES_MAX; ++i) {
|
||||
VdpRGBAFormat format;
|
||||
|
||||
format = VDP_RGBA_FORMAT_B8G8R8A8;
|
||||
// FIXME: does a 10bit rgba produce a better output?
|
||||
// format = VDP_RGBA_FORMAT_R10G10B10A2;
|
||||
status =
|
||||
VdpauOutputSurfaceCreate(VdpauDevice, format, VideoWindowWidth,
|
||||
VideoWindowHeight, VdpauSurfacesRb + i);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Fatal(_("video/vdpau: can't create output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
Debug(3, "video/vdpau: created output surface %dx%d with id 0x%08x\n",
|
||||
VideoWindowWidth, VideoWindowHeight, VdpauSurfacesRb[i]);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Cleanup output queue.
|
||||
///
|
||||
static void VdpauExitOutputQueue(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (VdpauQueue) {
|
||||
VdpauPresentationQueueDestroy(VdpauQueue);
|
||||
VdpauQueue = 0;
|
||||
}
|
||||
if (VdpauQueueTarget) {
|
||||
VdpauPresentationQueueTargetDestroy(VdpauQueueTarget);
|
||||
VdpauQueueTarget = 0;
|
||||
}
|
||||
//
|
||||
// destroy display output surfaces
|
||||
//
|
||||
for (i = 0; i < OUTPUT_SURFACES_MAX; ++i) {
|
||||
VdpStatus status;
|
||||
|
||||
Debug(4, "video/vdpau: destroy output surface with id 0x%08x\n",
|
||||
VdpauSurfacesRb[i]);
|
||||
if (VdpauSurfacesRb[i] != VDP_INVALID_HANDLE) {
|
||||
status = VdpauOutputSurfaceDestroy(VdpauSurfacesRb[i]);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't destroy output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
VdpauSurfacesRb[i] = VDP_INVALID_HANDLE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// VDPAU setup.
|
||||
///
|
||||
@@ -3995,8 +4103,10 @@ static void VideoVdpauInit(const char *display_name)
|
||||
&VdpauVideoSurfaceGetBitsYCbCr, "VideoSurfaceGetBitsYCbCr");
|
||||
VdpauGetProc(VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR,
|
||||
&VdpauVideoSurfacePutBitsYCbCr, "VideoSurfacePutBitsYCbCr");
|
||||
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES,
|
||||
&VdpauOutputSurfaceQueryCapabilities,
|
||||
"OutputSurfaceQueryCapabilities");
|
||||
#if 0
|
||||
VdpauGetProc(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES, &, "");
|
||||
VdpauGetProc
|
||||
(VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES, &,
|
||||
"");
|
||||
@@ -4115,33 +4225,6 @@ static void VideoVdpauInit(const char *display_name)
|
||||
|
||||
// vdp_preemption_callback_register
|
||||
|
||||
//
|
||||
// Create presentation queue, only one queue pro window
|
||||
//
|
||||
status =
|
||||
VdpauPresentationQueueTargetCreateX11(VdpauDevice, VideoWindow,
|
||||
&VdpauQueueTarget);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Fatal(_("video/vdpau: can't create presentation queue target: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
// FIXME: no fatal errors
|
||||
}
|
||||
|
||||
status =
|
||||
VdpauPresentationQueueCreate(VdpauDevice, VdpauQueueTarget,
|
||||
&VdpauQueue);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Fatal(_("video/vdpau: can't create presentation queue: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
|
||||
VdpauBackgroundColor->red = 0.01;
|
||||
VdpauBackgroundColor->green = 0.02;
|
||||
VdpauBackgroundColor->blue = 0.03;
|
||||
VdpauBackgroundColor->alpha = 1.00;
|
||||
|
||||
VdpauPresentationQueueSetBackgroundColor(VdpauQueue, VdpauBackgroundColor);
|
||||
|
||||
//
|
||||
// Look which levels of high quality scaling are supported
|
||||
//
|
||||
@@ -4244,7 +4327,7 @@ static void VideoVdpauInit(const char *display_name)
|
||||
VdpauVideoSurfaceQueryCapabilities(VdpauDevice, VDP_CHROMA_TYPE_420,
|
||||
&flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't create output surface: %s\n"),
|
||||
Error(_("video/vdpau: can't query video surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
@@ -4256,7 +4339,7 @@ static void VideoVdpauInit(const char *display_name)
|
||||
VdpauVideoSurfaceQueryCapabilities(VdpauDevice, VDP_CHROMA_TYPE_422,
|
||||
&flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't create output surface: %s\n"),
|
||||
Error(_("video/vdpau: can't query video surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
@@ -4268,7 +4351,7 @@ static void VideoVdpauInit(const char *display_name)
|
||||
VdpauVideoSurfaceQueryCapabilities(VdpauDevice, VDP_CHROMA_TYPE_444,
|
||||
&flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't create output surface: %s\n"),
|
||||
Error(_("video/vdpau: can't query video surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
@@ -4288,23 +4371,62 @@ static void VideoVdpauInit(const char *display_name)
|
||||
if (status != VDP_STATUS_OK || !flag) {
|
||||
Error(_("video/vdpau: doesn't support yv12 video surface\n"));
|
||||
}
|
||||
//FIXME: format support and size support
|
||||
//VdpOutputSurfaceQueryCapabilities
|
||||
|
||||
flag = VDP_FALSE;
|
||||
status =
|
||||
VdpauOutputSurfaceQueryCapabilities(VdpauDevice,
|
||||
VDP_RGBA_FORMAT_B8G8R8A8, &flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't query output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
Info(_("video/vdpau: 8bit BGRA format with %dx%d supported\n"),
|
||||
max_width, max_height);
|
||||
}
|
||||
flag = VDP_FALSE;
|
||||
status =
|
||||
VdpauOutputSurfaceQueryCapabilities(VdpauDevice,
|
||||
VDP_RGBA_FORMAT_R8G8B8A8, &flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't query output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
Info(_("video/vdpau: 8bit RGBA format with %dx%d supported\n"),
|
||||
max_width, max_height);
|
||||
}
|
||||
flag = VDP_FALSE;
|
||||
status =
|
||||
VdpauOutputSurfaceQueryCapabilities(VdpauDevice,
|
||||
VDP_RGBA_FORMAT_R10G10B10A2, &flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't query output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
Info(_("video/vdpau: 10bit RGBA format with %dx%d supported\n"),
|
||||
max_width, max_height);
|
||||
}
|
||||
flag = VDP_FALSE;
|
||||
status =
|
||||
VdpauOutputSurfaceQueryCapabilities(VdpauDevice,
|
||||
VDP_RGBA_FORMAT_B10G10R10A2, &flag, &max_width, &max_height);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't query output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
if (flag) {
|
||||
Info(_("video/vdpau: 8bit BRGA format with %dx%d supported\n"),
|
||||
max_width, max_height);
|
||||
}
|
||||
// FIXME: does only check for rgba formats, but no action
|
||||
|
||||
//
|
||||
// Create display output surfaces
|
||||
// Create presentation queue, only one queue pro window
|
||||
//
|
||||
for (i = 0; i < OUTPUT_SURFACES_MAX; ++i) {
|
||||
status =
|
||||
VdpauOutputSurfaceCreate(VdpauDevice, VDP_RGBA_FORMAT_B8G8R8A8,
|
||||
VideoWindowWidth, VideoWindowHeight, VdpauSurfacesRb + i);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Fatal(_("video/vdpau: can't create output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
Debug(3, "video/vdpau: created output surface %dx%d with id 0x%08x\n",
|
||||
VideoWindowWidth, VideoWindowHeight, VdpauSurfacesRb[i]);
|
||||
}
|
||||
VdpauInitOutputQueue();
|
||||
|
||||
}
|
||||
|
||||
///
|
||||
@@ -4312,38 +4434,13 @@ static void VideoVdpauInit(const char *display_name)
|
||||
///
|
||||
static void VideoVdpauExit(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (VdpauDecoders[0]) {
|
||||
VdpauDelDecoder(VdpauDecoders[0]);
|
||||
VdpauDecoders[0] = NULL;
|
||||
}
|
||||
|
||||
if (VdpauDevice) {
|
||||
|
||||
if (VdpauQueue) {
|
||||
VdpauPresentationQueueDestroy(VdpauQueue);
|
||||
VdpauQueue = 0;
|
||||
}
|
||||
if (VdpauQueueTarget) {
|
||||
VdpauPresentationQueueTargetDestroy(VdpauQueueTarget);
|
||||
VdpauQueueTarget = 0;
|
||||
}
|
||||
//
|
||||
// destroy display output surfaces
|
||||
//
|
||||
for (i = 0; i < OUTPUT_SURFACES_MAX; ++i) {
|
||||
VdpStatus status;
|
||||
|
||||
Debug(4, "video/vdpau: destroy output surface with id 0x%08x\n",
|
||||
VdpauSurfacesRb[i]);
|
||||
status = VdpauOutputSurfaceDestroy(VdpauSurfacesRb[i]);
|
||||
if (status != VDP_STATUS_OK) {
|
||||
Error(_("video/vdpau: can't destroy output surface: %s\n"),
|
||||
VdpauGetErrorString(status));
|
||||
}
|
||||
VdpauSurfacesRb[i] = VDP_INVALID_HANDLE;
|
||||
}
|
||||
VdpauExitOutputQueue();
|
||||
|
||||
// FIXME: more VDPAU cleanups...
|
||||
|
||||
@@ -4380,6 +4477,12 @@ static void VdpauUpdateOutput(VdpauDecoder * decoder)
|
||||
decoder->InputWidth * input_aspect_ratio.num,
|
||||
decoder->InputHeight * input_aspect_ratio.den, 1024 * 1024);
|
||||
|
||||
// InputWidth/Height can be zero = uninitialized
|
||||
if (!display_aspect_ratio.num || !display_aspect_ratio.den) {
|
||||
display_aspect_ratio.num = 1;
|
||||
display_aspect_ratio.den = 1;
|
||||
}
|
||||
|
||||
Debug(3, "video: aspect %d:%d\n", display_aspect_ratio.num,
|
||||
display_aspect_ratio.den);
|
||||
|
||||
@@ -6013,8 +6116,8 @@ static void VideoEvent(void)
|
||||
case ClientMessage:
|
||||
Debug(3, "video/event: ClientMessage\n");
|
||||
if (event.xclient.data.l[0] == (long)WmDeleteWindowAtom) {
|
||||
// FIXME: wrong, kills recordings ...
|
||||
Error(_("video/event: FIXME: wm-delete-message\n"));
|
||||
Debug(3, "video/event: wm-delete-message\n");
|
||||
FeedKeyPress("XKeySym", "Close", 0, 0);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -6031,7 +6134,12 @@ static void VideoEvent(void)
|
||||
Debug(3, "video/event: ReparentNotify\n");
|
||||
break;
|
||||
case ConfigureNotify:
|
||||
Debug(3, "video/event: ConfigureNotify\n");
|
||||
//Debug(3, "video/event: ConfigureNotify\n");
|
||||
VideoSetVideoMode(event.xconfigure.x, event.xconfigure.y,
|
||||
event.xconfigure.width, event.xconfigure.height);
|
||||
break;
|
||||
case ButtonPress:
|
||||
VideoSetFullscreen(-1);
|
||||
break;
|
||||
case KeyPress:
|
||||
keysym = XLookupKeysym(&event.xkey, 0);
|
||||
@@ -6604,6 +6712,22 @@ static void VideoCreateWindow(xcb_window_t parent, xcb_visualid_t visual,
|
||||
free(reply);
|
||||
}
|
||||
}
|
||||
//
|
||||
// prepare fullscreen.
|
||||
//
|
||||
if ((reply =
|
||||
xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection, 0,
|
||||
sizeof("_NET_WM_STATE") - 1, "_NET_WM_STATE"), NULL))) {
|
||||
NetWmState = reply->atom;
|
||||
free(reply);
|
||||
}
|
||||
if ((reply =
|
||||
xcb_intern_atom_reply(Connection, xcb_intern_atom(Connection, 0,
|
||||
sizeof("_NET_WM_STATE_FULLSCREEN") - 1,
|
||||
"_NET_WM_STATE_FULLSCREEN"), NULL))) {
|
||||
NetWmStateFullscreen = reply->atom;
|
||||
free(reply);
|
||||
}
|
||||
|
||||
xcb_map_window(Connection, VideoWindow);
|
||||
|
||||
@@ -6664,6 +6788,77 @@ void VideoSetOutputPosition(int x, int y, int width, int height)
|
||||
VdpauSetOutputPosition(VdpauDecoders[0], x, y, width, height);
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VAPI
|
||||
// FIXME: not supported by vaapi without unscaled OSD,
|
||||
// FIXME: if used to position video inside osd
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Set video window position.
|
||||
///
|
||||
/// @param x window x coordinate
|
||||
/// @param y window y coordinate
|
||||
/// @param width window width
|
||||
/// @param height window height
|
||||
///
|
||||
/// @note no need to lock, only called from inside the video thread
|
||||
///
|
||||
void VideoSetVideoMode(int x, int y, int width, int height)
|
||||
{
|
||||
Debug(3, "video: %s %dx%d%+d%+d\n", __FUNCTION__, width, height, x, y);
|
||||
if ((unsigned)width == VideoWindowWidth
|
||||
&& (unsigned)height == VideoWindowHeight) {
|
||||
return; // same size nothing todo
|
||||
}
|
||||
VideoWindowWidth = width;
|
||||
VideoWindowHeight = height;
|
||||
#ifdef USE_VAAPI
|
||||
if (VideoVaapiEnabled && VaapiDecoders[0]) {
|
||||
// FIXME: must update osd surfaces?
|
||||
VaapiUpdateOutput(VaapiDecoders[0]);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
#ifdef USE_VDPAU
|
||||
if (VideoVdpauEnabled && VdpauDecoders[0]) {
|
||||
VdpauExitOutputQueue();
|
||||
VdpauInitOutputQueue();
|
||||
VdpauUpdateOutput(VdpauDecoders[0]);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
///
|
||||
/// Send fullscreen message to window.
|
||||
///
|
||||
/// @param onoff -1 toggle, true turn on, false turn off
|
||||
///
|
||||
void VideoSetFullscreen(int onoff)
|
||||
{
|
||||
xcb_client_message_event_t event;
|
||||
|
||||
memset(&event, 0, sizeof(event));
|
||||
event.response_type = XCB_CLIENT_MESSAGE;
|
||||
event.format = 32;
|
||||
event.window = VideoWindow;
|
||||
event.type = NetWmState;
|
||||
if (onoff < 0) {
|
||||
event.data.data32[0] = XCB_EWMH_WM_STATE_TOGGLE;
|
||||
} else if (onoff) {
|
||||
event.data.data32[0] = XCB_EWMH_WM_STATE_ADD;
|
||||
} else {
|
||||
event.data.data32[0] = XCB_EWMH_WM_STATE_REMOVE;
|
||||
}
|
||||
event.data.data32[1] = NetWmStateFullscreen;
|
||||
|
||||
xcb_send_event(Connection, XCB_SEND_EVENT_DEST_POINTER_WINDOW,
|
||||
DefaultRootWindow(XlibDisplay),
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_NOTIFY |
|
||||
XCB_EVENT_MASK_SUBSTRUCTURE_REDIRECT, (void *)&event);
|
||||
Debug(3, "video/x11: send fullscreen message %x %x\n",
|
||||
event.data.data32[0], event.data.data32[1]);
|
||||
}
|
||||
|
||||
///
|
||||
@@ -6675,6 +6870,7 @@ void VideoSetDeinterlace(int mode[VideoResolutionMax])
|
||||
VideoDeinterlace[1] = mode[1];
|
||||
VideoDeinterlace[2] = mode[2];
|
||||
VideoDeinterlace[3] = mode[3];
|
||||
VideoSurfaceModesChanged = 1;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -6686,6 +6882,7 @@ void VideoSetSkipChromaDeinterlace(int onoff[VideoResolutionMax])
|
||||
VideoSkipChromaDeinterlace[1] = onoff[1];
|
||||
VideoSkipChromaDeinterlace[2] = onoff[2];
|
||||
VideoSkipChromaDeinterlace[3] = onoff[3];
|
||||
VideoSurfaceModesChanged = 1;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -6697,6 +6894,7 @@ void VideoSetDenoise(int level[VideoResolutionMax])
|
||||
VideoSharpen[1] = level[1];
|
||||
VideoSharpen[2] = level[2];
|
||||
VideoSharpen[3] = level[3];
|
||||
VideoSurfaceModesChanged = 1;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -6708,6 +6906,7 @@ void VideoSetSharpen(int level[VideoResolutionMax])
|
||||
VideoSharpen[1] = level[1];
|
||||
VideoSharpen[2] = level[2];
|
||||
VideoSharpen[3] = level[3];
|
||||
VideoSurfaceModesChanged = 1;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -6719,6 +6918,7 @@ void VideoSetScaling(int mode[VideoResolutionMax])
|
||||
VideoScaling[1] = mode[1];
|
||||
VideoScaling[2] = mode[2];
|
||||
VideoScaling[3] = mode[3];
|
||||
VideoSurfaceModesChanged = 1;
|
||||
}
|
||||
|
||||
///
|
||||
@@ -6977,7 +7177,7 @@ int main(int argc, char *const argv[])
|
||||
//
|
||||
// main loop
|
||||
//
|
||||
VideoInit();
|
||||
VideoInit(NULL);
|
||||
VideoOsdInit();
|
||||
for (;;) {
|
||||
VideoRenderOverlay();
|
||||
|
||||
9
video.h
9
video.h
@@ -67,15 +67,18 @@ extern void VideoPollEvent(void);
|
||||
/// Wakeup display handler.
|
||||
extern void VideoDisplayWakeup(void);
|
||||
|
||||
/// Set video mode.
|
||||
//extern void VideoSetVideoMode(int, int, int, int);
|
||||
|
||||
/// Set video geometry.
|
||||
extern int VideoSetGeometry(const char *);
|
||||
|
||||
/// Set video output position.
|
||||
extern void VideoSetOutputPosition(int, int, int, int);
|
||||
|
||||
/// Set video mode.
|
||||
extern void VideoSetVideoMode(int, int, int, int);
|
||||
|
||||
/// Set video fullscreen mode.
|
||||
extern void VideoSetFullscreen(int);
|
||||
|
||||
/// Set deinterlace.
|
||||
extern void VideoSetDeinterlace(int[]);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user