mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 17:16:51 +00:00
Compare commits
30 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
58a76439ee | ||
|
|
a13c25d309 | ||
|
|
5265e68aa9 | ||
|
|
11121b5bdd | ||
|
|
d8e96c7871 | ||
|
|
8ff65a011a | ||
|
|
171a3f4dc9 | ||
|
|
93357fb1cd | ||
|
|
c646007db1 | ||
|
|
7615305960 | ||
|
|
cc1e2de58b | ||
|
|
738e9402d2 | ||
|
|
34fd275b42 | ||
|
|
64c11efc1b | ||
|
|
ebb8482226 | ||
|
|
833112eaa9 | ||
|
|
3022920b40 | ||
|
|
c1d3b9d048 | ||
|
|
4fe1c43c08 | ||
|
|
7a5e696bc4 | ||
|
|
8f99f80d44 | ||
|
|
c0286b3ab4 | ||
|
|
9dd248f9d0 | ||
|
|
238224efc8 | ||
|
|
5b35e70b94 | ||
|
|
857546a3a5 | ||
|
|
a1b77b1502 | ||
|
|
7ef5667598 | ||
|
|
4e3f5f5414 | ||
|
|
23b0e0d599 |
29
ChangeLog
29
ChangeLog
@@ -1,3 +1,32 @@
|
|||||||
|
User johns
|
||||||
|
Date:
|
||||||
|
|
||||||
|
Softer audio/video sync.
|
||||||
|
Add function GetStats to the video output module.
|
||||||
|
Add function ResetStart to the video output module.
|
||||||
|
Add function SetClosing to the video output module.
|
||||||
|
Generalize GetVaapiContext to GetHwAccelContext.
|
||||||
|
Add compile time configurable trickspeed packets dump.
|
||||||
|
Fix bug #1410: wrong spelled AC-3 and E-AC-3.
|
||||||
|
Add compile time selectable h264 trickspeed workaround.
|
||||||
|
Use ffmpeg new names AVCodecID, AV_CODEC_... .
|
||||||
|
Fix bug: video lagging behind after recording stop.
|
||||||
|
Reduce PES error messages.
|
||||||
|
Fix bug #1392: Wrong value for mixing LFE.
|
||||||
|
Fix bug: wrong grab size, introduced with AMD VDPAU.
|
||||||
|
Use VDR SPU decoder as default.
|
||||||
|
Fix bug: grab image negative quality isn't the default 100.
|
||||||
|
Support AMD VDPAU with surface size != requested size.
|
||||||
|
Add cache for auto-crop buffer.
|
||||||
|
Fix opengl and opengl threads bugs.
|
||||||
|
Initial opengl support with va-api only.
|
||||||
|
Fix "broken driver" message if empty ring buffer.
|
||||||
|
Enable seamless audio track change.
|
||||||
|
Fix bug #1302: Unsupported pixel format crash.
|
||||||
|
Fix the fix, when sillpicture is called in suspend mode.
|
||||||
|
Fix crash, when sillpicture is called in suspend mode.
|
||||||
|
Add workaround for zero width+height and ffmpeg >= 1.2.
|
||||||
|
|
||||||
User johns
|
User johns
|
||||||
Date: Sun Mar 17 15:52:42 CET 2013
|
Date: Sun Mar 17 15:52:42 CET 2013
|
||||||
|
|
||||||
|
|||||||
22
Makefile
22
Makefile
@@ -15,10 +15,12 @@ PLUGIN = softhddevice
|
|||||||
ALSA ?= $(shell pkg-config --exists alsa && echo 1)
|
ALSA ?= $(shell pkg-config --exists alsa && echo 1)
|
||||||
# support OSS audio output module
|
# support OSS audio output module
|
||||||
OSS ?= 1
|
OSS ?= 1
|
||||||
# support VDPAU video output modue
|
# support VDPAU video output module
|
||||||
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
|
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
|
||||||
# support VA-API video output modue
|
# support VA-API video output module (deprecated)
|
||||||
VAAPI ?= $(shell pkg-config --exists libva && echo 1)
|
#VAAPI ?= $(shell pkg-config --exists libva && echo 1)
|
||||||
|
# support glx output
|
||||||
|
#OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
|
||||||
# screensaver disable/enable
|
# screensaver disable/enable
|
||||||
SCREENSAVER ?= 1
|
SCREENSAVER ?= 1
|
||||||
# use ffmpeg libswresample
|
# use ffmpeg libswresample
|
||||||
@@ -33,7 +35,10 @@ CONFIG += -DUSE_PIP # PIP support
|
|||||||
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser
|
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser
|
||||||
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser
|
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser
|
||||||
#CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
|
#CONFIG += -DUSE_MPEG_COMPLETE # support only complete mpeg packets
|
||||||
#CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
|
#CONFIG += -DH264_EOS_TRICKSPEED # insert seq end packets for trickspeed
|
||||||
|
#CONDIF += -DDUMP_TRICKSPEED # dump trickspeed packets
|
||||||
|
CONFIG += -DUSE_VDR_SPU # use VDR SPU decoder.
|
||||||
|
#CONFIG += -DUSE_SOFTLIMIT # (tobe removed) limit the buffer fill
|
||||||
|
|
||||||
ifeq ($(ALSA),1)
|
ifeq ($(ALSA),1)
|
||||||
CONFIG += -DUSE_ALSA
|
CONFIG += -DUSE_ALSA
|
||||||
@@ -52,6 +57,15 @@ ifeq ($(VAAPI),1)
|
|||||||
CONFIG += -DUSE_VAAPI
|
CONFIG += -DUSE_VAAPI
|
||||||
_CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
|
_CFLAGS += $(shell pkg-config --cflags libva-x11 libva)
|
||||||
LIBS += $(shell pkg-config --libs libva-x11 libva)
|
LIBS += $(shell pkg-config --libs libva-x11 libva)
|
||||||
|
ifeq ($(OPENGL),1)
|
||||||
|
_CFLAGS += $(shell pkg-config --cflags libva-glx)
|
||||||
|
LIBS += $(shell pkg-config --libs libva-glx)
|
||||||
|
endif
|
||||||
|
endif
|
||||||
|
ifeq ($(OPENGL),1)
|
||||||
|
CONFIG += -DUSE_GLX
|
||||||
|
_CFLAGS += $(shell pkg-config --cflags gl glu)
|
||||||
|
LIBS += $(shell pkg-config --libs gl glu)
|
||||||
endif
|
endif
|
||||||
ifeq ($(SCREENSAVER),1)
|
ifeq ($(SCREENSAVER),1)
|
||||||
CONFIG += -DUSE_SCREENSAVER
|
CONFIG += -DUSE_SCREENSAVER
|
||||||
|
|||||||
25
README.txt
25
README.txt
@@ -20,14 +20,14 @@ $Id$
|
|||||||
|
|
||||||
A software and GPU emulated HD output device plugin for VDR.
|
A software and GPU emulated HD output device plugin for VDR.
|
||||||
|
|
||||||
o Video decoder CPU / VA-API / VDPAU
|
o Video decoder CPU / VDPAU
|
||||||
o Video output VA-API / VDPAU
|
o Video output VDPAU
|
||||||
o Audio FFMpeg / Alsa / Analog
|
o Audio FFMpeg / Alsa / Analog
|
||||||
o Audio FFMpeg / Alsa / Digital
|
o Audio FFMpeg / Alsa / Digital
|
||||||
o Audio FFMpeg / OSS / Analog
|
o Audio FFMpeg / OSS / Analog
|
||||||
o HDMI/SPDIF pass-through
|
o HDMI/SPDIF pass-through
|
||||||
o Software volume, compression, normalize and channel resample
|
o Software volume, compression, normalize and channel resample
|
||||||
o YaepgHD support / new >1.7.33 VDR ScaleVideo API support
|
o VDR ScaleVideo API
|
||||||
o Software deinterlacer Bob (VA-API only)
|
o Software deinterlacer Bob (VA-API only)
|
||||||
o Autocrop
|
o Autocrop
|
||||||
o Grab image (VDPAU only)
|
o Grab image (VDPAU only)
|
||||||
@@ -36,10 +36,11 @@ A software and GPU emulated HD output device plugin for VDR.
|
|||||||
o atmo light support with plugin http://github.com/durchflieger/DFAtmo
|
o atmo light support with plugin http://github.com/durchflieger/DFAtmo
|
||||||
o PIP (Picture-in-Picture) (VDPAU only)
|
o PIP (Picture-in-Picture) (VDPAU only)
|
||||||
|
|
||||||
o planned: Video decoder VA-API Branch: vaapi-ext/staging
|
o planned: Remove VA-API decoder and output support
|
||||||
o planned: Video output XvBA / Opengl / Xv
|
o planned: Video decoder OpenMax
|
||||||
o planned: VA-API grab image
|
o planned: Video output Opengl / Xv
|
||||||
o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
|
o planned: Improved software deinterlacer (yadif or/and ffmpeg filters)
|
||||||
|
o XvBa support is no longer planned (use future Radeon UVD VDPAU)
|
||||||
|
|
||||||
To compile you must have the 'requires' installed.
|
To compile you must have the 'requires' installed.
|
||||||
|
|
||||||
@@ -83,14 +84,12 @@ Setup: environment
|
|||||||
if set don't use the hardware decoders
|
if set don't use the hardware decoders
|
||||||
NO_MPEG_HW=1
|
NO_MPEG_HW=1
|
||||||
if set don't use the hardware decoder for mpeg1/2
|
if set don't use the hardware decoder for mpeg1/2
|
||||||
STUDIO_LEVELS=1
|
|
||||||
if set use studio levels with vdpau (deprecated use setup)
|
|
||||||
|
|
||||||
only if alsa is configured
|
only if alsa is configured
|
||||||
ALSA_DEVICE=default
|
ALSA_DEVICE=default
|
||||||
alsa PCM device name
|
alsa PCM device name
|
||||||
ALSA_PASSTHROUGH_DEVICE=
|
ALSA_PASSTHROUGH_DEVICE=
|
||||||
alsa pass-though (AC3,EAC3,DTS,...) device name
|
alsa pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||||
ALSA_MIXER=default
|
ALSA_MIXER=default
|
||||||
alsa control device name
|
alsa control device name
|
||||||
ALSA_MIXER_CHANNEL=PCM
|
ALSA_MIXER_CHANNEL=PCM
|
||||||
@@ -100,7 +99,7 @@ Setup: environment
|
|||||||
OSS_AUDIODEV=/dev/dsp
|
OSS_AUDIODEV=/dev/dsp
|
||||||
oss dsp device name
|
oss dsp device name
|
||||||
OSS_PASSTHROUGHDEV=
|
OSS_PASSTHROUGHDEV=
|
||||||
oss pass-though (AC3,EAC3,DTS,...) device name
|
oss pass-though (AC-3,E-AC-3,DTS,...) device name
|
||||||
OSS_MIXERDEV=/dev/mixer
|
OSS_MIXERDEV=/dev/mixer
|
||||||
oss mixer device name
|
oss mixer device name
|
||||||
OSS_MIXER_CHANNEL=pcm
|
OSS_MIXER_CHANNEL=pcm
|
||||||
@@ -130,7 +129,7 @@ Setup: /etc/vdr/setup.conf
|
|||||||
|
|
||||||
softhddevice.<res>.Deinterlace = 0
|
softhddevice.<res>.Deinterlace = 0
|
||||||
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
|
0 = bob, 1 = weave, 2 = temporal, 3 = temporal_spatial, 4 = software
|
||||||
(only 0, 1 supported with vaapi)
|
(only 0, 1, 4 supported with VA-API)
|
||||||
|
|
||||||
softhddevice.<res>.SkipChromaDeinterlace = 0
|
softhddevice.<res>.SkipChromaDeinterlace = 0
|
||||||
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
|
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
|
||||||
@@ -361,7 +360,7 @@ Requires:
|
|||||||
or
|
or
|
||||||
kernel support for oss/oss4 or alsa oss emulation
|
kernel support for oss/oss4 or alsa oss emulation
|
||||||
|
|
||||||
x11-libs/libva
|
x11-libs/libva (deprecated)
|
||||||
Video Acceleration (VA) API for Linux
|
Video Acceleration (VA) API for Linux
|
||||||
http://www.freedesktop.org/wiki/Software/vaapi
|
http://www.freedesktop.org/wiki/Software/vaapi
|
||||||
x11-libs/libva-intel-driver
|
x11-libs/libva-intel-driver
|
||||||
|
|||||||
8
Todo
8
Todo
@@ -1,6 +1,6 @@
|
|||||||
@file Todo @brief A software HD output device for VDR
|
@file Todo @brief A software HD output device for VDR
|
||||||
|
|
||||||
Copyright (c) 2011, 2012 by Johns. All Rights Reserved.
|
Copyright (c) 2011 - 2013 by Johns. All Rights Reserved.
|
||||||
|
|
||||||
Contributor(s):
|
Contributor(s):
|
||||||
|
|
||||||
@@ -19,6 +19,9 @@ GNU Affero General Public License for more details.
|
|||||||
$Id: $
|
$Id: $
|
||||||
|
|
||||||
missing:
|
missing:
|
||||||
|
documentation of the PIP hotkeys.
|
||||||
|
svdrp help page missing PIP hotkeys.
|
||||||
|
svdrp stat: add X11 crashed status.
|
||||||
more software deinterlace (yadif, ...)
|
more software deinterlace (yadif, ...)
|
||||||
more software decoder with software deinterlace
|
more software decoder with software deinterlace
|
||||||
suspend output / energie saver: stop and restart X11
|
suspend output / energie saver: stop and restart X11
|
||||||
@@ -40,11 +43,14 @@ video:
|
|||||||
check start with 24Hz display rate
|
check start with 24Hz display rate
|
||||||
crash with ffmpeg without vaapi and vdpau.
|
crash with ffmpeg without vaapi and vdpau.
|
||||||
still-picture of PES recordings should use VideoMpegEnqueue.
|
still-picture of PES recordings should use VideoMpegEnqueue.
|
||||||
|
convert PIX_FMT_... PixelFormat to new names AV_PIX_FMT_..., AVPixelFormat.
|
||||||
|
atmo service support 3D grab
|
||||||
|
|
||||||
vdpau:
|
vdpau:
|
||||||
software deinterlace path not working.
|
software deinterlace path not working.
|
||||||
OSD looses transparency, during channel switch.
|
OSD looses transparency, during channel switch.
|
||||||
OSD looses transparency, while moving cut marks.
|
OSD looses transparency, while moving cut marks.
|
||||||
|
ffmpeg >=1.2 supports same API like VA-API.
|
||||||
|
|
||||||
libva:
|
libva:
|
||||||
yaepghd (VaapiSetOutputPosition) support
|
yaepghd (VaapiSetOutputPosition) support
|
||||||
|
|||||||
42
audio.c
42
audio.c
@@ -486,7 +486,7 @@ static void AudioSurround2Stereo(const int16_t * in, int in_chan, int frames,
|
|||||||
r += in[3] * 200; // Rs
|
r += in[3] * 200; // Rs
|
||||||
l += in[4] * 300; // C
|
l += in[4] * 300; // C
|
||||||
r += in[4] * 300;
|
r += in[4] * 300;
|
||||||
l += in[5] * 300; // LFE
|
l += in[5] * 100; // LFE
|
||||||
r += in[5] * 100;
|
r += in[5] * 100;
|
||||||
break;
|
break;
|
||||||
case 7: // 7.0
|
case 7: // 7.0
|
||||||
@@ -620,7 +620,7 @@ static void AudioResample(const int16_t * in, int in_chan, int frames,
|
|||||||
typedef struct _audio_ring_ring_
|
typedef struct _audio_ring_ring_
|
||||||
{
|
{
|
||||||
char FlushBuffers; ///< flag: flush buffers
|
char FlushBuffers; ///< flag: flush buffers
|
||||||
char Passthrough; ///< flag: use pass-through (AC3, ...)
|
char Passthrough; ///< flag: use pass-through (AC-3, ...)
|
||||||
int16_t PacketSize; ///< packet size
|
int16_t PacketSize; ///< packet size
|
||||||
unsigned HwSampleRate; ///< hardware sample rate in Hz
|
unsigned HwSampleRate; ///< hardware sample rate in Hz
|
||||||
unsigned HwChannels; ///< hardware number of channels
|
unsigned HwChannels; ///< hardware number of channels
|
||||||
@@ -642,7 +642,7 @@ static unsigned AudioStartThreshold; ///< start play, if filled
|
|||||||
**
|
**
|
||||||
** @param sample_rate sample-rate frequency
|
** @param sample_rate sample-rate frequency
|
||||||
** @param channels number of channels
|
** @param channels number of channels
|
||||||
** @param passthrough use /pass-through (AC3, ...) device
|
** @param passthrough use /pass-through (AC-3, ...) device
|
||||||
**
|
**
|
||||||
** @retval -1 error
|
** @retval -1 error
|
||||||
** @retval 0 okay
|
** @retval 0 okay
|
||||||
@@ -678,8 +678,7 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
|
|||||||
}
|
}
|
||||||
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
||||||
|
|
||||||
// FIXME: don't flush buffers here
|
AudioRing[AudioRingWrite].FlushBuffers = 0;
|
||||||
AudioRing[AudioRingWrite].FlushBuffers = 1;
|
|
||||||
AudioRing[AudioRingWrite].Passthrough = passthrough;
|
AudioRing[AudioRingWrite].Passthrough = passthrough;
|
||||||
AudioRing[AudioRingWrite].PacketSize = 0;
|
AudioRing[AudioRingWrite].PacketSize = 0;
|
||||||
AudioRing[AudioRingWrite].InSampleRate = sample_rate;
|
AudioRing[AudioRingWrite].InSampleRate = sample_rate;
|
||||||
@@ -689,6 +688,9 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
|
|||||||
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000);
|
AudioRing[AudioRingWrite].PTS = INT64_C(0x8000000000000000);
|
||||||
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
|
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
|
||||||
|
|
||||||
|
Debug(3, "audio: %d ring buffer prepared\n",
|
||||||
|
atomic_read(&AudioRingFilled) + 1);
|
||||||
|
|
||||||
atomic_inc(&AudioRingFilled);
|
atomic_inc(&AudioRingFilled);
|
||||||
|
|
||||||
#ifdef USE_AUDIO_THREAD
|
#ifdef USE_AUDIO_THREAD
|
||||||
@@ -836,7 +838,7 @@ static int AlsaPlayRingbuffer(void)
|
|||||||
if (!avail) { // full or buffer empty
|
if (!avail) { // full or buffer empty
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// muting pass-through ac3, can produce disturbance
|
// muting pass-through AC-3, can produce disturbance
|
||||||
if (AudioMute || (AudioSoftVolume
|
if (AudioMute || (AudioSoftVolume
|
||||||
&& !AudioRing[AudioRingRead].Passthrough)) {
|
&& !AudioRing[AudioRingRead].Passthrough)) {
|
||||||
// FIXME: quick&dirty cast
|
// FIXME: quick&dirty cast
|
||||||
@@ -985,7 +987,7 @@ static int AlsaThread(void)
|
|||||||
/**
|
/**
|
||||||
** Open alsa pcm device.
|
** Open alsa pcm device.
|
||||||
**
|
**
|
||||||
** @param passthrough use pass-through (AC3, ...) device
|
** @param passthrough use pass-through (AC-3, ...) device
|
||||||
*/
|
*/
|
||||||
static snd_pcm_t *AlsaOpenPCM(int passthrough)
|
static snd_pcm_t *AlsaOpenPCM(int passthrough)
|
||||||
{
|
{
|
||||||
@@ -1168,7 +1170,7 @@ static int64_t AlsaGetDelay(void)
|
|||||||
**
|
**
|
||||||
** @param freq sample frequency
|
** @param freq sample frequency
|
||||||
** @param channels number of channels
|
** @param channels number of channels
|
||||||
** @param passthrough use pass-through (AC3, ...) device
|
** @param passthrough use pass-through (AC-3, ...) device
|
||||||
**
|
**
|
||||||
** @retval 0 everything ok
|
** @retval 0 everything ok
|
||||||
** @retval 1 didn't support frequency/channels combination
|
** @retval 1 didn't support frequency/channels combination
|
||||||
@@ -1561,7 +1563,7 @@ static int OssThread(void)
|
|||||||
/**
|
/**
|
||||||
** Open OSS pcm device.
|
** Open OSS pcm device.
|
||||||
**
|
**
|
||||||
** @param passthrough use pass-through (AC3, ...) device
|
** @param passthrough use pass-through (AC-3, ...) device
|
||||||
*/
|
*/
|
||||||
static int OssOpenPCM(int passthrough)
|
static int OssOpenPCM(int passthrough)
|
||||||
{
|
{
|
||||||
@@ -1725,7 +1727,7 @@ static int64_t OssGetDelay(void)
|
|||||||
**
|
**
|
||||||
** @param sample_rate sample rate/frequency
|
** @param sample_rate sample rate/frequency
|
||||||
** @param channels number of channels
|
** @param channels number of channels
|
||||||
** @param passthrough use pass-through (AC3, ...) device
|
** @param passthrough use pass-through (AC-3, ...) device
|
||||||
**
|
**
|
||||||
** @retval 0 everything ok
|
** @retval 0 everything ok
|
||||||
** @retval 1 didn't support frequency/channels combination
|
** @retval 1 didn't support frequency/channels combination
|
||||||
@@ -1743,7 +1745,7 @@ static int OssSetup(int *sample_rate, int *channels, int passthrough)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (1) { // close+open for pcm / ac3
|
if (1) { // close+open for pcm / AC-3
|
||||||
int fildes;
|
int fildes;
|
||||||
|
|
||||||
fildes = OssPcmFildes;
|
fildes = OssPcmFildes;
|
||||||
@@ -1932,7 +1934,7 @@ static void NoopSetVolume( __attribute__ ((unused))
|
|||||||
**
|
**
|
||||||
** @param freq sample frequency
|
** @param freq sample frequency
|
||||||
** @param channels number of channels
|
** @param channels number of channels
|
||||||
** @param passthrough use pass-through (AC3, ...) device
|
** @param passthrough use pass-through (AC-3, ...) device
|
||||||
*/
|
*/
|
||||||
static int NoopSetup( __attribute__ ((unused))
|
static int NoopSetup( __attribute__ ((unused))
|
||||||
int *channels, __attribute__ ((unused))
|
int *channels, __attribute__ ((unused))
|
||||||
@@ -2031,10 +2033,10 @@ static void *AudioPlayHandlerThread(void *dummy)
|
|||||||
pthread_mutex_unlock(&AudioMutex);
|
pthread_mutex_unlock(&AudioMutex);
|
||||||
|
|
||||||
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
|
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
|
||||||
/ (!AudioRing[AudioRingRead].HwSampleRate +
|
/ (!AudioRing[AudioRingWrite].HwSampleRate +
|
||||||
!AudioRing[AudioRingRead].HwChannels +
|
!AudioRing[AudioRingWrite].HwChannels +
|
||||||
AudioRing[AudioRingRead].HwSampleRate *
|
AudioRing[AudioRingWrite].HwSampleRate *
|
||||||
AudioRing[AudioRingRead].HwChannels * AudioBytesProSample));
|
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample));
|
||||||
|
|
||||||
do {
|
do {
|
||||||
int filled;
|
int filled;
|
||||||
@@ -2067,7 +2069,10 @@ static void *AudioPlayHandlerThread(void *dummy)
|
|||||||
Debug(3, "audio: continue after flush\n");
|
Debug(3, "audio: continue after flush\n");
|
||||||
}
|
}
|
||||||
// try to play some samples
|
// try to play some samples
|
||||||
err = AudioUsedModule->Thread();
|
err = 0;
|
||||||
|
if (RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
|
||||||
|
err = AudioUsedModule->Thread();
|
||||||
|
}
|
||||||
// underrun, check if new ring buffer is available
|
// underrun, check if new ring buffer is available
|
||||||
if (!err) {
|
if (!err) {
|
||||||
int passthrough;
|
int passthrough;
|
||||||
@@ -2417,6 +2422,7 @@ void AudioFlushBuffers(void)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
old = AudioRingWrite;
|
old = AudioRingWrite;
|
||||||
|
// FIXME: check ring buffer overflow
|
||||||
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
|
||||||
AudioRing[AudioRingWrite].FlushBuffers = 1;
|
AudioRing[AudioRingWrite].FlushBuffers = 1;
|
||||||
AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
|
AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
|
||||||
@@ -2570,7 +2576,7 @@ void AudioSetVolume(int volume)
|
|||||||
**
|
**
|
||||||
** @param freq sample frequency
|
** @param freq sample frequency
|
||||||
** @param channels number of channels
|
** @param channels number of channels
|
||||||
** @param passthrough use pass-through (AC3, ...) device
|
** @param passthrough use pass-through (AC-3, ...) device
|
||||||
**
|
**
|
||||||
** @retval 0 everything ok
|
** @retval 0 everything ok
|
||||||
** @retval 1 didn't support frequency/channels combination
|
** @retval 1 didn't support frequency/channels combination
|
||||||
|
|||||||
50
codec.c
50
codec.c
@@ -56,6 +56,13 @@
|
|||||||
|
|
||||||
#include <alsa/iatomic.h>
|
#include <alsa/iatomic.h>
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
|
// support old ffmpeg versions <1.0
|
||||||
|
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
|
||||||
|
#define AVCodecID CodecID
|
||||||
|
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
|
||||||
|
#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
|
||||||
|
#define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||||
|
#endif
|
||||||
#include <libavcodec/vaapi.h>
|
#include <libavcodec/vaapi.h>
|
||||||
#ifdef USE_VDPAU
|
#ifdef USE_VDPAU
|
||||||
#include <libavcodec/vdpau.h>
|
#include <libavcodec/vdpau.h>
|
||||||
@@ -434,7 +441,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
|||||||
decoder->VideoCtx->opaque = decoder; // our structure
|
decoder->VideoCtx->opaque = decoder; // our structure
|
||||||
|
|
||||||
Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
|
Debug(3, "codec: video '%s'\n", decoder->VideoCtx->codec_name);
|
||||||
if (codec_id == CODEC_ID_H264) {
|
if (codec_id == AV_CODEC_ID_H264) {
|
||||||
// 2.53 Ghz CPU is too slow for this codec at 1080i
|
// 2.53 Ghz CPU is too slow for this codec at 1080i
|
||||||
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
|
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
|
||||||
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR;
|
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR;
|
||||||
@@ -476,7 +483,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
|
|||||||
} else {
|
} else {
|
||||||
decoder->VideoCtx->get_format = Codec_get_format;
|
decoder->VideoCtx->get_format = Codec_get_format;
|
||||||
decoder->VideoCtx->hwaccel_context =
|
decoder->VideoCtx->hwaccel_context =
|
||||||
VideoGetVaapiContext(decoder->HwDecoder);
|
VideoGetHwAccelContext(decoder->HwDecoder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// our pixel format video hardware decoder hook
|
// our pixel format video hardware decoder hook
|
||||||
@@ -515,8 +522,8 @@ void CodecVideoClose(VideoDecoder * video_decoder)
|
|||||||
if (video_decoder->VideoCtx) {
|
if (video_decoder->VideoCtx) {
|
||||||
pthread_mutex_lock(&CodecLockMutex);
|
pthread_mutex_lock(&CodecLockMutex);
|
||||||
avcodec_close(video_decoder->VideoCtx);
|
avcodec_close(video_decoder->VideoCtx);
|
||||||
pthread_mutex_unlock(&CodecLockMutex);
|
|
||||||
av_freep(&video_decoder->VideoCtx);
|
av_freep(&video_decoder->VideoCtx);
|
||||||
|
pthread_mutex_unlock(&CodecLockMutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -703,7 +710,7 @@ enum IEC61937
|
|||||||
|
|
||||||
#ifdef USE_AUDIO_DRIFT_CORRECTION
|
#ifdef USE_AUDIO_DRIFT_CORRECTION
|
||||||
#define CORRECT_PCM 1 ///< do PCM audio-drift correction
|
#define CORRECT_PCM 1 ///< do PCM audio-drift correction
|
||||||
#define CORRECT_AC3 2 ///< do AC3 audio-drift correction
|
#define CORRECT_AC3 2 ///< do AC-3 audio-drift correction
|
||||||
static char CodecAudioDrift; ///< flag: enable audio-drift correction
|
static char CodecAudioDrift; ///< flag: enable audio-drift correction
|
||||||
#else
|
#else
|
||||||
static const int CodecAudioDrift = 0;
|
static const int CodecAudioDrift = 0;
|
||||||
@@ -856,15 +863,15 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
|
|||||||
if (audio_decoder->AudioCtx) {
|
if (audio_decoder->AudioCtx) {
|
||||||
pthread_mutex_lock(&CodecLockMutex);
|
pthread_mutex_lock(&CodecLockMutex);
|
||||||
avcodec_close(audio_decoder->AudioCtx);
|
avcodec_close(audio_decoder->AudioCtx);
|
||||||
pthread_mutex_unlock(&CodecLockMutex);
|
|
||||||
av_freep(&audio_decoder->AudioCtx);
|
av_freep(&audio_decoder->AudioCtx);
|
||||||
|
pthread_mutex_unlock(&CodecLockMutex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Set audio drift correction.
|
** Set audio drift correction.
|
||||||
**
|
**
|
||||||
** @param mask enable mask (PCM, AC3)
|
** @param mask enable mask (PCM, AC-3)
|
||||||
*/
|
*/
|
||||||
void CodecSetAudioDrift(int mask)
|
void CodecSetAudioDrift(int mask)
|
||||||
{
|
{
|
||||||
@@ -877,7 +884,7 @@ void CodecSetAudioDrift(int mask)
|
|||||||
/**
|
/**
|
||||||
** Set audio pass-through.
|
** Set audio pass-through.
|
||||||
**
|
**
|
||||||
** @param mask enable mask (PCM, AC3, EAC3)
|
** @param mask enable mask (PCM, AC-3, E-AC-3)
|
||||||
*/
|
*/
|
||||||
void CodecSetAudioPassthrough(int mask)
|
void CodecSetAudioPassthrough(int mask)
|
||||||
{
|
{
|
||||||
@@ -978,8 +985,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
|
|||||||
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
|
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
|
||||||
audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
|
audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
|
||||||
CodecPassthrough & CodecMPA ? " MPA" : "",
|
CodecPassthrough & CodecMPA ? " MPA" : "",
|
||||||
CodecPassthrough & CodecAC3 ? " AC3" : "",
|
CodecPassthrough & CodecAC3 ? " AC-3" : "",
|
||||||
CodecPassthrough & CodecEAC3 ? " EAC3" : "",
|
CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
|
||||||
CodecPassthrough ? " pass-through" : "");
|
CodecPassthrough ? " pass-through" : "");
|
||||||
|
|
||||||
*passthrough = 0;
|
*passthrough = 0;
|
||||||
@@ -990,11 +997,11 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
|
|||||||
audio_decoder->Passthrough = CodecPassthrough;
|
audio_decoder->Passthrough = CodecPassthrough;
|
||||||
|
|
||||||
// SPDIF/HDMI pass-through
|
// SPDIF/HDMI pass-through
|
||||||
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3)
|
if ((CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3)
|
||||||
|| (CodecPassthrough & CodecEAC3
|
|| (CodecPassthrough & CodecEAC3
|
||||||
&& audio_ctx->codec_id == CODEC_ID_EAC3)) {
|
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
|
||||||
if (audio_ctx->codec_id == CODEC_ID_EAC3) {
|
if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
|
||||||
// EAC3 over HDMI some receivers need HBR
|
// E-AC-3 over HDMI some receivers need HBR
|
||||||
audio_decoder->HwSampleRate *= 4;
|
audio_decoder->HwSampleRate *= 4;
|
||||||
}
|
}
|
||||||
audio_decoder->HwChannels = 2;
|
audio_decoder->HwChannels = 2;
|
||||||
@@ -1007,9 +1014,9 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
|
|||||||
AudioSetup(&audio_decoder->HwSampleRate,
|
AudioSetup(&audio_decoder->HwSampleRate,
|
||||||
&audio_decoder->HwChannels, *passthrough))) {
|
&audio_decoder->HwChannels, *passthrough))) {
|
||||||
|
|
||||||
// try EAC3 none HBR
|
// try E-AC-3 none HBR
|
||||||
audio_decoder->HwSampleRate /= 4;
|
audio_decoder->HwSampleRate /= 4;
|
||||||
if (audio_ctx->codec_id != CODEC_ID_EAC3
|
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3
|
||||||
|| (err =
|
|| (err =
|
||||||
AudioSetup(&audio_decoder->HwSampleRate,
|
AudioSetup(&audio_decoder->HwSampleRate,
|
||||||
&audio_decoder->HwChannels, *passthrough))) {
|
&audio_decoder->HwChannels, *passthrough))) {
|
||||||
@@ -1044,7 +1051,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
|
|||||||
|
|
||||||
audio_ctx = audio_decoder->AudioCtx;
|
audio_ctx = audio_decoder->AudioCtx;
|
||||||
// SPDIF/HDMI passthrough
|
// SPDIF/HDMI passthrough
|
||||||
if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
|
if (CodecPassthrough & CodecAC3 && audio_ctx->codec_id == AV_CODEC_ID_AC3) {
|
||||||
uint16_t *spdif;
|
uint16_t *spdif;
|
||||||
int spdif_sz;
|
int spdif_sz;
|
||||||
|
|
||||||
@@ -1094,7 +1101,8 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
|
|||||||
AudioEnqueue(spdif, spdif_sz);
|
AudioEnqueue(spdif, spdif_sz);
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
if (CodecPassthrough & CodecEAC3 && audio_ctx->codec_id == CODEC_ID_EAC3) {
|
if (CodecPassthrough & CodecEAC3
|
||||||
|
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
|
||||||
uint16_t *spdif;
|
uint16_t *spdif;
|
||||||
int spdif_sz;
|
int spdif_sz;
|
||||||
int repeat;
|
int repeat;
|
||||||
@@ -1223,9 +1231,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
|||||||
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
|
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
|
||||||
// SPDIF/HDMI passthrough
|
// SPDIF/HDMI passthrough
|
||||||
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|
||||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
|
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
|
||||||
&& (!(CodecPassthrough & CodecEAC3)
|
&& (!(CodecPassthrough & CodecEAC3)
|
||||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
|
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
|
||||||
audio_decoder->DriftCorr = -corr;
|
audio_decoder->DriftCorr = -corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1625,9 +1633,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
|
|||||||
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
|
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
|
||||||
// SPDIF/HDMI passthrough
|
// SPDIF/HDMI passthrough
|
||||||
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|
if ((CodecAudioDrift & CORRECT_AC3) && (!(CodecPassthrough & CodecAC3)
|
||||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
|
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_AC3)
|
||||||
&& (!(CodecPassthrough & CodecEAC3)
|
&& (!(CodecPassthrough & CodecEAC3)
|
||||||
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
|
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
|
||||||
audio_decoder->DriftCorr = -corr;
|
audio_decoder->DriftCorr = -corr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
2
codec.h
2
codec.h
@@ -30,7 +30,7 @@
|
|||||||
#define CodecPCM 0x01 ///< PCM bit mask
|
#define CodecPCM 0x01 ///< PCM bit mask
|
||||||
#define CodecMPA 0x02 ///< MPA bit mask (planned)
|
#define CodecMPA 0x02 ///< MPA bit mask (planned)
|
||||||
#define CodecAC3 0x04 ///< AC-3 bit mask
|
#define CodecAC3 0x04 ///< AC-3 bit mask
|
||||||
#define CodecEAC3 0x08 ///< EAC-3 bit mask
|
#define CodecEAC3 0x08 ///< E-AC-3 bit mask
|
||||||
#define CodecDTS 0x10 ///< DTS bit mask (planned)
|
#define CodecDTS 0x10 ///< DTS bit mask (planned)
|
||||||
|
|
||||||
//----------------------------------------------------------------------------
|
//----------------------------------------------------------------------------
|
||||||
|
|||||||
27
po/de_DE.po
27
po/de_DE.po
@@ -7,7 +7,7 @@ msgid ""
|
|||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: VDR \n"
|
"Project-Id-Version: VDR \n"
|
||||||
"Report-Msgid-Bugs-To: <see README>\n"
|
"Report-Msgid-Bugs-To: <see README>\n"
|
||||||
"POT-Creation-Date: 2013-03-09 19:20+0100\n"
|
"POT-Creation-Date: 2013-08-03 17:21+0200\n"
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
@@ -384,6 +384,10 @@ msgstr ""
|
|||||||
msgid "[softhddev] invalid PES video packet\n"
|
msgid "[softhddev] invalid PES video packet\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "[softhddev] %d invalid PES video packet(s)\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "[softhddev] empty video packet\n"
|
msgid "[softhddev] empty video packet\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
@@ -587,10 +591,10 @@ msgstr ""
|
|||||||
msgid " AC-3 pass-through"
|
msgid " AC-3 pass-through"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid " EAC-3 pass-through"
|
msgid " E-AC-3 pass-through"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Enable (E)AC-3 (decoder) downmix"
|
msgid "Enable (E-)AC-3 (decoder) downmix"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "Volume control"
|
msgid "Volume control"
|
||||||
@@ -627,7 +631,7 @@ msgid "Pip X (%)"
|
|||||||
msgstr "PIP X (%)"
|
msgstr "PIP X (%)"
|
||||||
|
|
||||||
msgid "Pip Y (%)"
|
msgid "Pip Y (%)"
|
||||||
msgstr "PIP X (%)"
|
msgstr "PIP Y (%)"
|
||||||
|
|
||||||
msgid "Pip Width (%)"
|
msgid "Pip Width (%)"
|
||||||
msgstr "PIP Breite (%)"
|
msgstr "PIP Breite (%)"
|
||||||
@@ -672,7 +676,7 @@ msgid "Alternative Video Height (%)"
|
|||||||
msgstr "Alternative Videohöhe (%)"
|
msgstr "Alternative Videohöhe (%)"
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "[softhddev]pip: invalid pes packet %d\n"
|
msgid "[softhddev]pip: invalid PES packet %d\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "[softhddev]pip: pes buffer too small\n"
|
msgid "[softhddev]pip: pes buffer too small\n"
|
||||||
@@ -895,6 +899,9 @@ msgstr ""
|
|||||||
msgid "unsupported"
|
msgid "unsupported"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "video/glx: glx error\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "video/vaapi: unsupported pixel format %d\n"
|
msgid "video/vaapi: unsupported pixel format %d\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1265,6 +1272,9 @@ msgstr ""
|
|||||||
msgid "video/vdpau: can't put video surface bits: %s\n"
|
msgid "video/vdpau: can't put video surface bits: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
msgid "video: get hwaccel context, not supported\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "video/vdpau: can't render bitmap surface: %s\n"
|
msgid "video/vdpau: can't render bitmap surface: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1331,9 +1341,6 @@ msgstr ""
|
|||||||
msgid "video: repeated pict %d found, but not handled\n"
|
msgid "video: repeated pict %d found, but not handled\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
msgid "video/vaapi: get vaapi context, without vaapi enabled\n"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#, c-format
|
#, c-format
|
||||||
msgid "video/vdpau: decoder rendering failed: %s\n"
|
msgid "video/vdpau: decoder rendering failed: %s\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
@@ -1355,6 +1362,10 @@ msgstr ""
|
|||||||
msgid "video: Can't connect to X11 server on '%s'\n"
|
msgid "video: Can't connect to X11 server on '%s'\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#, c-format
|
||||||
|
msgid "video: Can't initialize X11 thread support on '%s'\n"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
msgid "video: Can't convert XLIB display to XCB connection\n"
|
msgid "video: Can't convert XLIB display to XCB connection\n"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|||||||
244
softhddev.c
244
softhddev.c
@@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#define noUSE_SOFTLIMIT ///< add soft buffer limits to Play..
|
#define noUSE_SOFTLIMIT ///< add soft buffer limits to Play..
|
||||||
#define noUSE_PIP ///< include PIP support + new API
|
#define noUSE_PIP ///< include PIP support + new API
|
||||||
|
#define noDUMP_TRICKSPEED ///< dump raw trickspeed packets
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
@@ -40,6 +41,19 @@
|
|||||||
#define _N(str) str ///< gettext_noop shortcut
|
#define _N(str) str ///< gettext_noop shortcut
|
||||||
|
|
||||||
#include <libavcodec/avcodec.h>
|
#include <libavcodec/avcodec.h>
|
||||||
|
// support old ffmpeg versions <1.0
|
||||||
|
#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(55,18,102)
|
||||||
|
#define AVCodecID CodecID
|
||||||
|
#define AV_CODEC_ID_AAC CODEC_ID_AAC
|
||||||
|
#define AV_CODEC_ID_AAC_LATM CODEC_ID_AAC_LATM
|
||||||
|
#define AV_CODEC_ID_AC3 CODEC_ID_AC3
|
||||||
|
#define AV_CODEC_ID_EAC3 CODEC_ID_EAC3
|
||||||
|
#define AV_CODEC_ID_H264 CODEC_ID_H264
|
||||||
|
#define AV_CODEC_ID_MP2 CODEC_ID_MP2
|
||||||
|
#define AV_CODEC_ID_MPEG2VIDEO CODEC_ID_MPEG2VIDEO
|
||||||
|
#define AV_CODEC_ID_NONE CODEC_ID_NONE
|
||||||
|
#define AV_CODEC_ID_PCM_DVD CODEC_ID_PCM_DVD
|
||||||
|
#endif
|
||||||
|
|
||||||
#ifndef __USE_GNU
|
#ifndef __USE_GNU
|
||||||
#define __USE_GNU
|
#define __USE_GNU
|
||||||
@@ -86,7 +100,7 @@ static volatile char StreamFreezed; ///< stream freezed
|
|||||||
static volatile char NewAudioStream; ///< new audio stream
|
static volatile char NewAudioStream; ///< new audio stream
|
||||||
static volatile char SkipAudio; ///< skip audio stream
|
static volatile char SkipAudio; ///< skip audio stream
|
||||||
static AudioDecoder *MyAudioDecoder; ///< audio decoder
|
static AudioDecoder *MyAudioDecoder; ///< audio decoder
|
||||||
static enum CodecID AudioCodecID; ///< current codec id
|
static enum AVCodecID AudioCodecID; ///< current codec id
|
||||||
static int AudioChannelID; ///< current audio channel id
|
static int AudioChannelID; ///< current audio channel id
|
||||||
static VideoStream *AudioSyncStream; ///< video stream for audio/video sync
|
static VideoStream *AudioSyncStream; ///< video stream for audio/video sync
|
||||||
|
|
||||||
@@ -296,7 +310,7 @@ static int LatmCheck(const uint8_t * data, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Possible AC3 frame sizes.
|
/// Possible AC-3 frame sizes.
|
||||||
///
|
///
|
||||||
/// from ATSC A/52 table 5.18 frame size code table.
|
/// from ATSC A/52 table 5.18 frame size code table.
|
||||||
///
|
///
|
||||||
@@ -314,9 +328,9 @@ const uint16_t Ac3FrameSizeTable[38][3] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Fast check for (E)AC3 audio.
|
/// Fast check for (E-)AC-3 audio.
|
||||||
///
|
///
|
||||||
/// 5 bytes 0x0B77xxxxxx AC3 audio
|
/// 5 bytes 0x0B77xxxxxx AC-3 audio
|
||||||
///
|
///
|
||||||
static inline int FastAc3Check(const uint8_t * p)
|
static inline int FastAc3Check(const uint8_t * p)
|
||||||
{
|
{
|
||||||
@@ -330,7 +344,7 @@ static inline int FastAc3Check(const uint8_t * p)
|
|||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Check for (E)AC-3 audio.
|
/// Check for (E-)AC-3 audio.
|
||||||
///
|
///
|
||||||
/// 0x0B77xxxxxx already checked.
|
/// 0x0B77xxxxxx already checked.
|
||||||
///
|
///
|
||||||
@@ -341,7 +355,7 @@ static inline int FastAc3Check(const uint8_t * p)
|
|||||||
/// @retval 0 no valid AC-3 audio
|
/// @retval 0 no valid AC-3 audio
|
||||||
/// @retval >0 valid AC-3 audio
|
/// @retval >0 valid AC-3 audio
|
||||||
///
|
///
|
||||||
/// o AC3 Header
|
/// o AC-3 Header
|
||||||
/// AAAAAAAA AAAAAAAA BBBBBBBB BBBBBBBB CCDDDDDD EEEEEFFF
|
/// AAAAAAAA AAAAAAAA BBBBBBBB BBBBBBBB CCDDDDDD EEEEEFFF
|
||||||
///
|
///
|
||||||
/// o a 16x Frame sync, always 0x0B77
|
/// o a 16x Frame sync, always 0x0B77
|
||||||
@@ -351,7 +365,7 @@ static inline int FastAc3Check(const uint8_t * p)
|
|||||||
/// o e 5x Bitstream ID
|
/// o e 5x Bitstream ID
|
||||||
/// o f 3x Bitstream mode
|
/// o f 3x Bitstream mode
|
||||||
///
|
///
|
||||||
/// o EAC3 Header
|
/// o E-AC-3 Header
|
||||||
/// AAAAAAAA AAAAAAAA BBCCCDDD DDDDDDDD EEFFGGGH IIIII...
|
/// AAAAAAAA AAAAAAAA BBCCCDDD DDDDDDDD EEFFGGGH IIIII...
|
||||||
///
|
///
|
||||||
/// o a 16x Frame sync, always 0x0B77
|
/// o a 16x Frame sync, always 0x0B77
|
||||||
@@ -365,17 +379,17 @@ static int Ac3Check(const uint8_t * data, int size)
|
|||||||
{
|
{
|
||||||
int frame_size;
|
int frame_size;
|
||||||
|
|
||||||
if (size < 5) { // need 5 bytes to see if AC3/EAC3
|
if (size < 5) { // need 5 bytes to see if AC-3/E-AC-3
|
||||||
return -5;
|
return -5;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data[5] > (10 << 3)) { // EAC3
|
if (data[5] > (10 << 3)) { // E-AC-3
|
||||||
if ((data[4] & 0xF0) == 0xF0) { // invalid fscod fscod2
|
if ((data[4] & 0xF0) == 0xF0) { // invalid fscod fscod2
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
frame_size = ((data[2] & 0x03) << 8) + data[3] + 1;
|
frame_size = ((data[2] & 0x03) << 8) + data[3] + 1;
|
||||||
frame_size *= 2;
|
frame_size *= 2;
|
||||||
} else { // AC3
|
} else { // AC-3
|
||||||
int fscod;
|
int fscod;
|
||||||
int frmsizcod;
|
int frmsizcod;
|
||||||
|
|
||||||
@@ -617,7 +631,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
|
|||||||
#if 0
|
#if 0
|
||||||
// Played with PlayAudio
|
// Played with PlayAudio
|
||||||
// FIXME: need 0x80 -- 0xA0 state
|
// FIXME: need 0x80 -- 0xA0 state
|
||||||
if (AudioCodecID == CODEC_ID_NONE) {
|
if (AudioCodecID == AV_CODEC_ID_NONE) {
|
||||||
if ((*p & 0xF0) == 0x80) { // AC-3 & DTS
|
if ((*p & 0xF0) == 0x80) { // AC-3 & DTS
|
||||||
Debug(3, "pesdemux: dvd ac-3\n");
|
Debug(3, "pesdemux: dvd ac-3\n");
|
||||||
} else if ((*p & 0xFF) == 0xA0) { // LPCM
|
} else if ((*p & 0xFF) == 0xA0) { // LPCM
|
||||||
@@ -651,8 +665,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
|
|||||||
unsigned codec_id;
|
unsigned codec_id;
|
||||||
|
|
||||||
// 4 bytes 0xFFExxxxx Mpeg audio
|
// 4 bytes 0xFFExxxxx Mpeg audio
|
||||||
// 5 bytes 0x0B77xxxxxx AC3 audio
|
// 5 bytes 0x0B77xxxxxx AC-3 audio
|
||||||
// 6 bytes 0x0B77xxxxxxxx EAC3 audio
|
// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
|
||||||
// 3 bytes 0x56Exxx AAC LATM audio
|
// 3 bytes 0x56Exxx AAC LATM audio
|
||||||
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
|
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
|
||||||
// PCM audio can't be found
|
// PCM audio can't be found
|
||||||
@@ -660,22 +674,22 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
|
|||||||
r = 0;
|
r = 0;
|
||||||
if (!r && FastMpegCheck(q)) {
|
if (!r && FastMpegCheck(q)) {
|
||||||
r = MpegCheck(q, n);
|
r = MpegCheck(q, n);
|
||||||
codec_id = CODEC_ID_MP2;
|
codec_id = AV_CODEC_ID_MP2;
|
||||||
}
|
}
|
||||||
if (!r && FastAc3Check(q)) {
|
if (!r && FastAc3Check(q)) {
|
||||||
r = Ac3Check(q, n);
|
r = Ac3Check(q, n);
|
||||||
codec_id = CODEC_ID_AC3;
|
codec_id = AV_CODEC_ID_AC3;
|
||||||
if (r > 0 && q[5] > (10 << 3)) {
|
if (r > 0 && q[5] > (10 << 3)) {
|
||||||
codec_id = CODEC_ID_EAC3;
|
codec_id = AV_CODEC_ID_EAC3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!r && FastLatmCheck(q)) {
|
if (!r && FastLatmCheck(q)) {
|
||||||
r = LatmCheck(q, n);
|
r = LatmCheck(q, n);
|
||||||
codec_id = CODEC_ID_AAC_LATM;
|
codec_id = AV_CODEC_ID_AAC_LATM;
|
||||||
}
|
}
|
||||||
if (!r && FastAdtsCheck(q)) {
|
if (!r && FastAdtsCheck(q)) {
|
||||||
r = AdtsCheck(q, n);
|
r = AdtsCheck(q, n);
|
||||||
codec_id = CODEC_ID_AAC;
|
codec_id = AV_CODEC_ID_AAC;
|
||||||
}
|
}
|
||||||
if (r < 0) { // need more bytes
|
if (r < 0) { // need more bytes
|
||||||
break;
|
break;
|
||||||
@@ -705,7 +719,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
|
|||||||
//pesdx->State = PES_MPEG_DECODE;
|
//pesdx->State = PES_MPEG_DECODE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (AudioCodecID != CODEC_ID_NONE) {
|
if (AudioCodecID != AV_CODEC_ID_NONE) {
|
||||||
// shouldn't happen after we have a vaild codec
|
// shouldn't happen after we have a vaild codec
|
||||||
// detected
|
// detected
|
||||||
Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip,
|
Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip,
|
||||||
@@ -831,7 +845,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
|
|||||||
int bits_per_sample;
|
int bits_per_sample;
|
||||||
const uint8_t *q;
|
const uint8_t *q;
|
||||||
|
|
||||||
if (AudioCodecID != CODEC_ID_PCM_DVD) {
|
if (AudioCodecID != AV_CODEC_ID_PCM_DVD) {
|
||||||
|
|
||||||
q = pesdx->Header;
|
q = pesdx->Header;
|
||||||
Debug(3, "pesdemux: LPCM %d sr:%d bits:%d chan:%d\n",
|
Debug(3, "pesdemux: LPCM %d sr:%d bits:%d chan:%d\n",
|
||||||
@@ -861,8 +875,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
|
|||||||
(q[5] & 0x7) + 1);
|
(q[5] & 0x7) + 1);
|
||||||
// FIXME: support resample
|
// FIXME: support resample
|
||||||
}
|
}
|
||||||
//CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
|
//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD);
|
||||||
AudioCodecID = CODEC_ID_PCM_DVD;
|
AudioCodecID = AV_CODEC_ID_PCM_DVD;
|
||||||
}
|
}
|
||||||
pesdx->State = PES_LPCM_PAYLOAD;
|
pesdx->State = PES_LPCM_PAYLOAD;
|
||||||
pesdx->Index = 0;
|
pesdx->Index = 0;
|
||||||
@@ -1023,7 +1037,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
CodecAudioClose(MyAudioDecoder);
|
CodecAudioClose(MyAudioDecoder);
|
||||||
AudioFlushBuffers();
|
AudioFlushBuffers();
|
||||||
AudioSetBufferTime(ConfigAudioBufferTime);
|
AudioSetBufferTime(ConfigAudioBufferTime);
|
||||||
AudioCodecID = CODEC_ID_NONE;
|
AudioCodecID = AV_CODEC_ID_NONE;
|
||||||
AudioChannelID = -1;
|
AudioChannelID = -1;
|
||||||
NewAudioStream = 0;
|
NewAudioStream = 0;
|
||||||
}
|
}
|
||||||
@@ -1081,7 +1095,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
|
|
||||||
if (AudioChannelID != id) { // id changed audio track changed
|
if (AudioChannelID != id) { // id changed audio track changed
|
||||||
AudioChannelID = id;
|
AudioChannelID = id;
|
||||||
AudioCodecID = CODEC_ID_NONE;
|
AudioCodecID = AV_CODEC_ID_NONE;
|
||||||
}
|
}
|
||||||
// Private stream + LPCM ID
|
// Private stream + LPCM ID
|
||||||
if ((id & 0xF0) == 0xA0) {
|
if ((id & 0xF0) == 0xA0) {
|
||||||
@@ -1089,7 +1103,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size);
|
Error(_("[softhddev] invalid LPCM audio packet %d bytes\n"), size);
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
if (AudioCodecID != CODEC_ID_PCM_DVD) {
|
if (AudioCodecID != AV_CODEC_ID_PCM_DVD) {
|
||||||
static int samplerates[] = { 48000, 96000, 44100, 32000 };
|
static int samplerates[] = { 48000, 96000, 44100, 32000 };
|
||||||
int samplerate;
|
int samplerate;
|
||||||
int channels;
|
int channels;
|
||||||
@@ -1123,8 +1137,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
(p[5] & 0x7) + 1);
|
(p[5] & 0x7) + 1);
|
||||||
// FIXME: support resample
|
// FIXME: support resample
|
||||||
}
|
}
|
||||||
//CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
|
//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD);
|
||||||
AudioCodecID = CODEC_ID_PCM_DVD;
|
AudioCodecID = AV_CODEC_ID_PCM_DVD;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) {
|
if (AudioAvPkt->pts != (int64_t) AV_NOPTS_VALUE) {
|
||||||
@@ -1140,7 +1154,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
if ((id & 0xF0) == 0x80 && (p[0] & 0xF0) == 0x80) {
|
if ((id & 0xF0) == 0x80 && (p[0] & 0xF0) == 0x80) {
|
||||||
p += 4;
|
p += 4;
|
||||||
n -= 4; // skip track header
|
n -= 4; // skip track header
|
||||||
if (AudioCodecID == CODEC_ID_NONE) {
|
if (AudioCodecID == AV_CODEC_ID_NONE) {
|
||||||
// FIXME: ConfigAudioBufferTime + x
|
// FIXME: ConfigAudioBufferTime + x
|
||||||
AudioSetBufferTime(400);
|
AudioSetBufferTime(400);
|
||||||
}
|
}
|
||||||
@@ -1157,25 +1171,25 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
|
|
||||||
// 4 bytes 0xFFExxxxx Mpeg audio
|
// 4 bytes 0xFFExxxxx Mpeg audio
|
||||||
// 3 bytes 0x56Exxx AAC LATM audio
|
// 3 bytes 0x56Exxx AAC LATM audio
|
||||||
// 5 bytes 0x0B77xxxxxx AC3 audio
|
// 5 bytes 0x0B77xxxxxx AC-3 audio
|
||||||
// 6 bytes 0x0B77xxxxxxxx EAC3 audio
|
// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
|
||||||
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
|
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
|
||||||
// PCM audio can't be found
|
// PCM audio can't be found
|
||||||
r = 0;
|
r = 0;
|
||||||
codec_id = CODEC_ID_NONE; // keep compiler happy
|
codec_id = AV_CODEC_ID_NONE; // keep compiler happy
|
||||||
if (id != 0xbd && FastMpegCheck(p)) {
|
if (id != 0xbd && FastMpegCheck(p)) {
|
||||||
r = MpegCheck(p, n);
|
r = MpegCheck(p, n);
|
||||||
codec_id = CODEC_ID_MP2;
|
codec_id = AV_CODEC_ID_MP2;
|
||||||
}
|
}
|
||||||
if (id != 0xbd && !r && FastLatmCheck(p)) {
|
if (id != 0xbd && !r && FastLatmCheck(p)) {
|
||||||
r = LatmCheck(p, n);
|
r = LatmCheck(p, n);
|
||||||
codec_id = CODEC_ID_AAC_LATM;
|
codec_id = AV_CODEC_ID_AAC_LATM;
|
||||||
}
|
}
|
||||||
if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) {
|
if ((id == 0xbd || (id & 0xF0) == 0x80) && !r && FastAc3Check(p)) {
|
||||||
r = Ac3Check(p, n);
|
r = Ac3Check(p, n);
|
||||||
codec_id = CODEC_ID_AC3;
|
codec_id = AV_CODEC_ID_AC3;
|
||||||
if (r > 0 && p[5] > (10 << 3)) {
|
if (r > 0 && p[5] > (10 << 3)) {
|
||||||
codec_id = CODEC_ID_EAC3;
|
codec_id = AV_CODEC_ID_EAC3;
|
||||||
}
|
}
|
||||||
/* faster ac3 detection at end of pes packet (no improvemnts)
|
/* faster ac3 detection at end of pes packet (no improvemnts)
|
||||||
if (AudioCodecID == codec_id && -r - 2 == n) {
|
if (AudioCodecID == codec_id && -r - 2 == n) {
|
||||||
@@ -1185,7 +1199,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
|
|||||||
}
|
}
|
||||||
if (id != 0xbd && !r && FastAdtsCheck(p)) {
|
if (id != 0xbd && !r && FastAdtsCheck(p)) {
|
||||||
r = AdtsCheck(p, n);
|
r = AdtsCheck(p, n);
|
||||||
codec_id = CODEC_ID_AAC;
|
codec_id = AV_CODEC_ID_AAC;
|
||||||
}
|
}
|
||||||
if (r < 0) { // need more bytes
|
if (r < 0) { // need more bytes
|
||||||
break;
|
break;
|
||||||
@@ -1253,7 +1267,7 @@ int PlayTsAudio(const uint8_t * data, int size)
|
|||||||
AudioFlushBuffers();
|
AudioFlushBuffers();
|
||||||
// max time between audio packets 200ms + 24ms hw buffer
|
// max time between audio packets 200ms + 24ms hw buffer
|
||||||
AudioSetBufferTime(ConfigAudioBufferTime);
|
AudioSetBufferTime(ConfigAudioBufferTime);
|
||||||
AudioCodecID = CODEC_ID_NONE;
|
AudioCodecID = AV_CODEC_ID_NONE;
|
||||||
AudioChannelID = -1;
|
AudioChannelID = -1;
|
||||||
NewAudioStream = 0;
|
NewAudioStream = 0;
|
||||||
PesReset(PesDemuxAudio);
|
PesReset(PesDemuxAudio);
|
||||||
@@ -1303,8 +1317,8 @@ struct __video_stream__
|
|||||||
VideoDecoder *Decoder; ///< video decoder
|
VideoDecoder *Decoder; ///< video decoder
|
||||||
pthread_mutex_t DecoderLockMutex; ///< video decoder lock mutex
|
pthread_mutex_t DecoderLockMutex; ///< video decoder lock mutex
|
||||||
|
|
||||||
enum CodecID CodecID; ///< current codec id
|
enum AVCodecID CodecID; ///< current codec id
|
||||||
enum CodecID LastCodecID; ///< last codec id
|
enum AVCodecID LastCodecID; ///< last codec id
|
||||||
|
|
||||||
volatile char NewStream; ///< flag new video stream
|
volatile char NewStream; ///< flag new video stream
|
||||||
volatile char ClosingStream; ///< flag closing video stream
|
volatile char ClosingStream; ///< flag closing video stream
|
||||||
@@ -1316,6 +1330,9 @@ struct __video_stream__
|
|||||||
volatile char ClearBuffers; ///< command clear video buffers
|
volatile char ClearBuffers; ///< command clear video buffers
|
||||||
volatile char ClearClose; ///< clear video buffers for close
|
volatile char ClearClose; ///< clear video buffers for close
|
||||||
|
|
||||||
|
int InvalidPesCounter; ///< counter of invalid PES packets
|
||||||
|
|
||||||
|
enum AVCodecID CodecIDRb[VIDEO_PACKET_MAX]; ///< codec ids in ring buffer
|
||||||
AVPacket PacketRb[VIDEO_PACKET_MAX]; ///< PES packet ring buffer
|
AVPacket PacketRb[VIDEO_PACKET_MAX]; ///< PES packet ring buffer
|
||||||
int StartCodeState; ///< last three bytes start code state
|
int StartCodeState; ///< last three bytes start code state
|
||||||
|
|
||||||
@@ -1442,9 +1459,9 @@ static void VideoResetPacket(VideoStream * stream)
|
|||||||
|
|
||||||
stream->StartCodeState = 0; // reset start code state
|
stream->StartCodeState = 0; // reset start code state
|
||||||
|
|
||||||
|
stream->CodecIDRb[stream->PacketWrite] = AV_CODEC_ID_NONE;
|
||||||
avpkt = &stream->PacketRb[stream->PacketWrite];
|
avpkt = &stream->PacketRb[stream->PacketWrite];
|
||||||
avpkt->stream_index = 0;
|
avpkt->stream_index = 0;
|
||||||
avpkt->priv = NULL;
|
|
||||||
avpkt->pts = AV_NOPTS_VALUE;
|
avpkt->pts = AV_NOPTS_VALUE;
|
||||||
avpkt->dts = AV_NOPTS_VALUE;
|
avpkt->dts = AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
@@ -1461,7 +1478,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
|
|||||||
|
|
||||||
avpkt = &stream->PacketRb[stream->PacketWrite];
|
avpkt = &stream->PacketRb[stream->PacketWrite];
|
||||||
if (!avpkt->stream_index) { // ignore empty packets
|
if (!avpkt->stream_index) { // ignore empty packets
|
||||||
if (codec_id != CODEC_ID_NONE) {
|
if (codec_id != AV_CODEC_ID_NONE) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Debug(3, "video: possible stream change loss\n");
|
Debug(3, "video: possible stream change loss\n");
|
||||||
@@ -1471,7 +1488,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
|
|||||||
// no free slot available drop last packet
|
// no free slot available drop last packet
|
||||||
Error(_("video: no empty slot in packet ringbuffer\n"));
|
Error(_("video: no empty slot in packet ringbuffer\n"));
|
||||||
avpkt->stream_index = 0;
|
avpkt->stream_index = 0;
|
||||||
if (codec_id == CODEC_ID_NONE) {
|
if (codec_id == AV_CODEC_ID_NONE) {
|
||||||
Debug(3, "video: possible stream change loss\n");
|
Debug(3, "video: possible stream change loss\n");
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@@ -1479,7 +1496,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
|
|||||||
// clear area for decoder, always enough space allocated
|
// clear area for decoder, always enough space allocated
|
||||||
memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
memset(avpkt->data + avpkt->stream_index, 0, FF_INPUT_BUFFER_PADDING_SIZE);
|
||||||
|
|
||||||
avpkt->priv = (void *)(size_t) codec_id;
|
stream->CodecIDRb[stream->PacketWrite] = codec_id;
|
||||||
//DumpH264(avpkt->data, avpkt->stream_index);
|
//DumpH264(avpkt->data, avpkt->stream_index);
|
||||||
|
|
||||||
// advance packet write
|
// advance packet write
|
||||||
@@ -1539,7 +1556,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
|
|||||||
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
|
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
|
||||||
#endif
|
#endif
|
||||||
stream->PacketRb[stream->PacketWrite].stream_index -= 3;
|
stream->PacketRb[stream->PacketWrite].stream_index -= 3;
|
||||||
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
|
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
|
||||||
VideoEnqueue(stream, pts, startcode, 3);
|
VideoEnqueue(stream, pts, startcode, 3);
|
||||||
first = p[0] == 0xb3;
|
first = p[0] == 0xb3;
|
||||||
p++;
|
p++;
|
||||||
@@ -1556,7 +1573,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
|
|||||||
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
|
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
|
||||||
#endif
|
#endif
|
||||||
stream->PacketRb[stream->PacketWrite].stream_index -= 2;
|
stream->PacketRb[stream->PacketWrite].stream_index -= 2;
|
||||||
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
|
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
|
||||||
VideoEnqueue(stream, pts, startcode, 2);
|
VideoEnqueue(stream, pts, startcode, 2);
|
||||||
first = p[1] == 0xb3;
|
first = p[1] == 0xb3;
|
||||||
p += 2;
|
p += 2;
|
||||||
@@ -1573,7 +1590,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
|
|||||||
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
|
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
|
||||||
#endif
|
#endif
|
||||||
stream->PacketRb[stream->PacketWrite].stream_index -= 1;
|
stream->PacketRb[stream->PacketWrite].stream_index -= 1;
|
||||||
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
|
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
|
||||||
VideoEnqueue(stream, pts, startcode, 1);
|
VideoEnqueue(stream, pts, startcode, 1);
|
||||||
first = p[2] == 0xb3;
|
first = p[2] == 0xb3;
|
||||||
p += 3;
|
p += 3;
|
||||||
@@ -1606,7 +1623,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
|
|||||||
*/
|
*/
|
||||||
// first packet goes only upto picture header
|
// first packet goes only upto picture header
|
||||||
VideoEnqueue(stream, pts, data, p - data);
|
VideoEnqueue(stream, pts, data, p - data);
|
||||||
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
|
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
fprintf(stderr, "fix\r");
|
fprintf(stderr, "fix\r");
|
||||||
#endif
|
#endif
|
||||||
@@ -1756,6 +1773,7 @@ static void VideoStreamClose(VideoStream * stream)
|
|||||||
VideoPacketExit(stream);
|
VideoPacketExit(stream);
|
||||||
|
|
||||||
stream->NewStream = 1;
|
stream->NewStream = 1;
|
||||||
|
stream->InvalidPesCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1853,9 +1871,8 @@ int VideoDecodeInput(VideoStream * stream)
|
|||||||
|
|
||||||
// flush buffers, if close is in the queue
|
// flush buffers, if close is in the queue
|
||||||
for (f = 0; f < filled; ++f) {
|
for (f = 0; f < filled; ++f) {
|
||||||
avpkt =
|
if (stream->CodecIDRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX]
|
||||||
&stream->PacketRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX];
|
== AV_CODEC_ID_NONE) {
|
||||||
if ((int)(size_t) avpkt->priv == CODEC_ID_NONE) {
|
|
||||||
if (f) {
|
if (f) {
|
||||||
Debug(3, "video: cleared upto close\n");
|
Debug(3, "video: cleared upto close\n");
|
||||||
atomic_sub(f, &stream->PacketsFilled);
|
atomic_sub(f, &stream->PacketsFilled);
|
||||||
@@ -1874,30 +1891,30 @@ int VideoDecodeInput(VideoStream * stream)
|
|||||||
// handle queued commands
|
// handle queued commands
|
||||||
//
|
//
|
||||||
avpkt = &stream->PacketRb[stream->PacketRead];
|
avpkt = &stream->PacketRb[stream->PacketRead];
|
||||||
switch ((int)(size_t) avpkt->priv) {
|
switch (stream->CodecIDRb[stream->PacketRead]) {
|
||||||
case CODEC_ID_NONE:
|
case AV_CODEC_ID_NONE:
|
||||||
stream->ClosingStream = 0;
|
stream->ClosingStream = 0;
|
||||||
if (stream->LastCodecID != CODEC_ID_NONE) {
|
if (stream->LastCodecID != AV_CODEC_ID_NONE) {
|
||||||
stream->LastCodecID = CODEC_ID_NONE;
|
stream->LastCodecID = AV_CODEC_ID_NONE;
|
||||||
CodecVideoClose(stream->Decoder);
|
CodecVideoClose(stream->Decoder);
|
||||||
goto skip;
|
goto skip;
|
||||||
}
|
}
|
||||||
// FIXME: look if more close are in the queue
|
// FIXME: look if more close are in the queue
|
||||||
// size can be zero
|
// size can be zero
|
||||||
goto skip;
|
goto skip;
|
||||||
case CODEC_ID_MPEG2VIDEO:
|
case AV_CODEC_ID_MPEG2VIDEO:
|
||||||
if (stream->LastCodecID != CODEC_ID_MPEG2VIDEO) {
|
if (stream->LastCodecID != AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
stream->LastCodecID = CODEC_ID_MPEG2VIDEO;
|
stream->LastCodecID = AV_CODEC_ID_MPEG2VIDEO;
|
||||||
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder < 0
|
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder < 0
|
||||||
&& VdpauDecoder ? "mpegvideo_vdpau" : NULL,
|
&& VdpauDecoder ? "mpegvideo_vdpau" : NULL,
|
||||||
CODEC_ID_MPEG2VIDEO);
|
AV_CODEC_ID_MPEG2VIDEO);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CODEC_ID_H264:
|
case AV_CODEC_ID_H264:
|
||||||
if (stream->LastCodecID != CODEC_ID_H264) {
|
if (stream->LastCodecID != AV_CODEC_ID_H264) {
|
||||||
stream->LastCodecID = CODEC_ID_H264;
|
stream->LastCodecID = AV_CODEC_ID_H264;
|
||||||
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder
|
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder
|
||||||
&& VdpauDecoder ? "h264_vdpau" : NULL, CODEC_ID_H264);
|
&& VdpauDecoder ? "h264_vdpau" : NULL, AV_CODEC_ID_H264);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@@ -1926,7 +1943,7 @@ int VideoDecodeInput(VideoStream * stream)
|
|||||||
//fprintf(stderr, "]\n");
|
//fprintf(stderr, "]\n");
|
||||||
#else
|
#else
|
||||||
// old version
|
// old version
|
||||||
if (stream->LastCodecID == CODEC_ID_MPEG2VIDEO) {
|
if (stream->LastCodecID == AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
FixPacketForFFMpeg(stream->Decoder, avpkt);
|
FixPacketForFFMpeg(stream->Decoder, avpkt);
|
||||||
} else {
|
} else {
|
||||||
CodecVideoDecode(stream->Decoder, avpkt);
|
CodecVideoDecode(stream->Decoder, avpkt);
|
||||||
@@ -1972,8 +1989,8 @@ static void StartVideo(void)
|
|||||||
VideoOsdInit();
|
VideoOsdInit();
|
||||||
if (!MyVideoStream->Decoder) {
|
if (!MyVideoStream->Decoder) {
|
||||||
MyVideoStream->SkipStream = 1;
|
MyVideoStream->SkipStream = 1;
|
||||||
MyVideoStream->CodecID = CODEC_ID_NONE;
|
MyVideoStream->CodecID = AV_CODEC_ID_NONE;
|
||||||
MyVideoStream->LastCodecID = CODEC_ID_NONE;
|
MyVideoStream->LastCodecID = AV_CODEC_ID_NONE;
|
||||||
|
|
||||||
if ((MyVideoStream->HwDecoder = VideoNewHwDecoder(MyVideoStream))) {
|
if ((MyVideoStream->HwDecoder = VideoNewHwDecoder(MyVideoStream))) {
|
||||||
MyVideoStream->Decoder =
|
MyVideoStream->Decoder =
|
||||||
@@ -2012,6 +2029,7 @@ static void StopVideo(void)
|
|||||||
VideoPacketExit(MyVideoStream);
|
VideoPacketExit(MyVideoStream);
|
||||||
|
|
||||||
MyVideoStream->NewStream = 1;
|
MyVideoStream->NewStream = 1;
|
||||||
|
MyVideoStream->InvalidPesCounter = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
@@ -2133,17 +2151,26 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
|
|||||||
Debug(3, "video: new video stream lost\n");
|
Debug(3, "video: new video stream lost\n");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
VideoNextPacket(stream, CODEC_ID_NONE);
|
VideoNextPacket(stream, AV_CODEC_ID_NONE);
|
||||||
stream->CodecID = CODEC_ID_NONE;
|
stream->CodecID = AV_CODEC_ID_NONE;
|
||||||
stream->ClosingStream = 1;
|
stream->ClosingStream = 1;
|
||||||
stream->NewStream = 0;
|
stream->NewStream = 0;
|
||||||
}
|
}
|
||||||
// must be a PES start code
|
// must be a PES start code
|
||||||
// FIXME: Valgrind-3.8.1 has a problem with this code
|
// FIXME: Valgrind-3.8.1 has a problem with this code
|
||||||
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
|
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
|
||||||
Error(_("[softhddev] invalid PES video packet\n"));
|
if (!stream->InvalidPesCounter++) {
|
||||||
|
Error(_("[softhddev] invalid PES video packet\n"));
|
||||||
|
}
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
|
if (stream->InvalidPesCounter) {
|
||||||
|
if (stream->InvalidPesCounter > 1) {
|
||||||
|
Error(_("[softhddev] %d invalid PES video packet(s)\n"),
|
||||||
|
stream->InvalidPesCounter);
|
||||||
|
}
|
||||||
|
stream->InvalidPesCounter = 0;
|
||||||
|
}
|
||||||
// 0xBE, filler, padding stream
|
// 0xBE, filler, padding stream
|
||||||
if (data[3] == PES_PADDING_STREAM) { // from DVD plugin
|
if (data[3] == PES_PADDING_STREAM) { // from DVD plugin
|
||||||
return size;
|
return size;
|
||||||
@@ -2197,8 +2224,26 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
|
|||||||
if ((data[6] & 0xC0) == 0x80 && z >= 2 && check[0] == 0x01
|
if ((data[6] & 0xC0) == 0x80 && z >= 2 && check[0] == 0x01
|
||||||
&& check[1] == 0x09 && !check[3] && !check[4]) {
|
&& check[1] == 0x09 && !check[3] && !check[4]) {
|
||||||
// old PES HDTV recording z == 2 -> stronger check!
|
// old PES HDTV recording z == 2 -> stronger check!
|
||||||
if (stream->CodecID == CODEC_ID_H264) {
|
if (stream->CodecID == AV_CODEC_ID_H264) {
|
||||||
#if 0
|
#ifdef DUMP_TRICKSPEED
|
||||||
|
if (stream->TrickSpeed) {
|
||||||
|
char buf[1024];
|
||||||
|
int fd;
|
||||||
|
static int FrameCounter;
|
||||||
|
|
||||||
|
snprintf(buf, sizeof(buf), "frame_%06d_%08d.raw", getpid(),
|
||||||
|
FrameCounter++);
|
||||||
|
if ((fd =
|
||||||
|
open(buf, O_WRONLY | O_CLOEXEC | O_CREAT | O_TRUNC,
|
||||||
|
0666)) >= 0) {
|
||||||
|
if (write(fd, data + 9 + n, size - 9 - n)) {
|
||||||
|
// this construct is to remove the annoying warning
|
||||||
|
}
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#ifdef H264_EOS_TRICKSPEED
|
||||||
// this should improve ffwd+frew, but produce crash in ffmpeg
|
// this should improve ffwd+frew, but produce crash in ffmpeg
|
||||||
// with some streams
|
// with some streams
|
||||||
if (stream->TrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) {
|
if (stream->TrickSpeed && pts != (int64_t) AV_NOPTS_VALUE) {
|
||||||
@@ -2209,16 +2254,16 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
|
|||||||
// 1-5=SLICE 6=SEI 7=SPS 8=PPS
|
// 1-5=SLICE 6=SEI 7=SPS 8=PPS
|
||||||
// NAL SPS sequence parameter set
|
// NAL SPS sequence parameter set
|
||||||
if ((check[7] & 0x1F) == 0x07) {
|
if ((check[7] & 0x1F) == 0x07) {
|
||||||
VideoNextPacket(CODEC_ID_H264);
|
VideoNextPacket(stream, AV_CODEC_ID_H264);
|
||||||
VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264,
|
VideoEnqueue(stream, AV_NOPTS_VALUE, seq_end_h264,
|
||||||
sizeof(seq_end_h264));
|
sizeof(seq_end_h264));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
VideoNextPacket(stream, CODEC_ID_H264);
|
VideoNextPacket(stream, AV_CODEC_ID_H264);
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "video: h264 detected\n");
|
Debug(3, "video: h264 detected\n");
|
||||||
stream->CodecID = CODEC_ID_H264;
|
stream->CodecID = AV_CODEC_ID_H264;
|
||||||
}
|
}
|
||||||
// SKIP PES header (ffmpeg supports short start code)
|
// SKIP PES header (ffmpeg supports short start code)
|
||||||
VideoEnqueue(stream, pts, check - 2, l + 2);
|
VideoEnqueue(stream, pts, check - 2, l + 2);
|
||||||
@@ -2226,11 +2271,11 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
|
|||||||
}
|
}
|
||||||
// PES start code 0x00 0x00 0x01 0x00|0xb3
|
// PES start code 0x00 0x00 0x01 0x00|0xb3
|
||||||
if (z > 1 && check[0] == 0x01 && (!check[1] || check[1] == 0xb3)) {
|
if (z > 1 && check[0] == 0x01 && (!check[1] || check[1] == 0xb3)) {
|
||||||
if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
|
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
|
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
|
||||||
} else {
|
} else {
|
||||||
Debug(3, "video: mpeg2 detected ID %02x\n", check[3]);
|
Debug(3, "video: mpeg2 detected ID %02x\n", check[3]);
|
||||||
stream->CodecID = CODEC_ID_MPEG2VIDEO;
|
stream->CodecID = AV_CODEC_ID_MPEG2VIDEO;
|
||||||
}
|
}
|
||||||
#ifdef noDEBUG // pip pes packet has no lenght
|
#ifdef noDEBUG // pip pes packet has no lenght
|
||||||
if (ValidateMpeg(data, size)) {
|
if (ValidateMpeg(data, size)) {
|
||||||
@@ -2246,12 +2291,12 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
|
|||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
// this happens when vdr sends incomplete packets
|
// this happens when vdr sends incomplete packets
|
||||||
if (stream->CodecID == CODEC_ID_NONE) {
|
if (stream->CodecID == AV_CODEC_ID_NONE) {
|
||||||
Debug(3, "video: not detected\n");
|
Debug(3, "video: not detected\n");
|
||||||
return size;
|
return size;
|
||||||
}
|
}
|
||||||
#ifdef USE_PIP
|
#ifdef USE_PIP
|
||||||
if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
|
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
// SKIP PES header
|
// SKIP PES header
|
||||||
VideoMpegEnqueue(stream, pts, data + 9 + n, size - 9 - n);
|
VideoMpegEnqueue(stream, pts, data + 9 + n, size - 9 - n);
|
||||||
#ifndef USE_MPEG_COMPLETE
|
#ifndef USE_MPEG_COMPLETE
|
||||||
@@ -2275,10 +2320,10 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
|
|||||||
// incomplete packets produce artefacts after channel switch
|
// incomplete packets produce artefacts after channel switch
|
||||||
// packet < 65526 is the last split packet, detect it here for
|
// packet < 65526 is the last split packet, detect it here for
|
||||||
// better latency
|
// better latency
|
||||||
if (size < 65526 && stream->CodecID == CODEC_ID_MPEG2VIDEO) {
|
if (size < 65526 && stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
// mpeg codec supports incomplete packets
|
// mpeg codec supports incomplete packets
|
||||||
// waiting for a full complete packages, increases needed delays
|
// waiting for a full complete packages, increases needed delays
|
||||||
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
|
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -2403,13 +2448,15 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
|
|||||||
int SetPlayMode(int play_mode)
|
int SetPlayMode(int play_mode)
|
||||||
{
|
{
|
||||||
VideoDisplayWakeup();
|
VideoDisplayWakeup();
|
||||||
if (MyVideoStream->Decoder) { // tell video parser we have new stream
|
// tell video parser we have new stream
|
||||||
|
if (MyVideoStream->Decoder && !MyVideoStream->SkipStream) {
|
||||||
if (MyVideoStream->ClearClose) { // replay clear buffers on close
|
if (MyVideoStream->ClearClose) { // replay clear buffers on close
|
||||||
Clear(); // flush all buffers
|
Clear(); // flush all buffers
|
||||||
MyVideoStream->ClearClose = 0;
|
MyVideoStream->ClearClose = 0;
|
||||||
}
|
}
|
||||||
if (MyVideoStream->CodecID != CODEC_ID_NONE) {
|
if (MyVideoStream->CodecID != AV_CODEC_ID_NONE) {
|
||||||
MyVideoStream->NewStream = 1;
|
MyVideoStream->NewStream = 1;
|
||||||
|
MyVideoStream->InvalidPesCounter = 0;
|
||||||
// tell hw decoder we are closing stream
|
// tell hw decoder we are closing stream
|
||||||
VideoSetClosing(MyVideoStream->HwDecoder);
|
VideoSetClosing(MyVideoStream->HwDecoder);
|
||||||
VideoResetStart(MyVideoStream->HwDecoder);
|
VideoResetStart(MyVideoStream->HwDecoder);
|
||||||
@@ -2419,7 +2466,7 @@ int SetPlayMode(int play_mode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (MyAudioDecoder) { // tell audio parser we have new stream
|
if (MyAudioDecoder) { // tell audio parser we have new stream
|
||||||
if (AudioCodecID != CODEC_ID_NONE) {
|
if (AudioCodecID != AV_CODEC_ID_NONE) {
|
||||||
NewAudioStream = 1;
|
NewAudioStream = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2579,6 +2626,10 @@ void StillPicture(const uint8_t * data, int size)
|
|||||||
int i;
|
int i;
|
||||||
int old_video_hardware_decoder;
|
int old_video_hardware_decoder;
|
||||||
|
|
||||||
|
// might be called in Suspended Mode
|
||||||
|
if (!MyVideoStream->Decoder || MyVideoStream->SkipStream) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
// must be a PES start code
|
// must be a PES start code
|
||||||
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
|
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
|
||||||
Error(_("[softhddev] invalid still video packet\n"));
|
Error(_("[softhddev] invalid still video packet\n"));
|
||||||
@@ -2593,10 +2644,10 @@ void StillPicture(const uint8_t * data, int size)
|
|||||||
// enable/disable hardware decoder for still picture
|
// enable/disable hardware decoder for still picture
|
||||||
if (VideoHardwareDecoder != ConfigStillDecoder) {
|
if (VideoHardwareDecoder != ConfigStillDecoder) {
|
||||||
VideoHardwareDecoder = ConfigStillDecoder;
|
VideoHardwareDecoder = ConfigStillDecoder;
|
||||||
VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
|
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream
|
||||||
}
|
}
|
||||||
|
|
||||||
if (MyVideoStream->CodecID == CODEC_ID_NONE) {
|
if (MyVideoStream->CodecID == AV_CODEC_ID_NONE) {
|
||||||
// FIXME: should detect codec, see PlayVideo
|
// FIXME: should detect codec, see PlayVideo
|
||||||
Error(_("[softhddev] no codec known for still picture\n"));
|
Error(_("[softhddev] no codec known for still picture\n"));
|
||||||
}
|
}
|
||||||
@@ -2605,7 +2656,7 @@ void StillPicture(const uint8_t * data, int size)
|
|||||||
#ifdef STILL_DEBUG
|
#ifdef STILL_DEBUG
|
||||||
fprintf(stderr, "still-picture\n");
|
fprintf(stderr, "still-picture\n");
|
||||||
#endif
|
#endif
|
||||||
for (i = 0; i < (MyVideoStream->CodecID == CODEC_ID_MPEG2VIDEO ? 4 : 4);
|
for (i = 0; i < (MyVideoStream->CodecID == AV_CODEC_ID_MPEG2VIDEO ? 4 : 4);
|
||||||
++i) {
|
++i) {
|
||||||
const uint8_t *split;
|
const uint8_t *split;
|
||||||
int n;
|
int n;
|
||||||
@@ -2645,13 +2696,13 @@ void StillPicture(const uint8_t * data, int size)
|
|||||||
|
|
||||||
VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet
|
VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet
|
||||||
} else { // ES packet
|
} else { // ES packet
|
||||||
if (MyVideoStream->CodecID != CODEC_ID_MPEG2VIDEO) {
|
if (MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) {
|
||||||
VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
|
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream
|
||||||
MyVideoStream->CodecID = CODEC_ID_MPEG2VIDEO;
|
MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO;
|
||||||
}
|
}
|
||||||
VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, data, size);
|
VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, data, size);
|
||||||
}
|
}
|
||||||
if (MyVideoStream->CodecID == CODEC_ID_H264) {
|
if (MyVideoStream->CodecID == AV_CODEC_ID_H264) {
|
||||||
VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, seq_end_h264,
|
VideoEnqueue(MyVideoStream, AV_NOPTS_VALUE, seq_end_h264,
|
||||||
sizeof(seq_end_h264));
|
sizeof(seq_end_h264));
|
||||||
} else {
|
} else {
|
||||||
@@ -2672,7 +2723,7 @@ void StillPicture(const uint8_t * data, int size)
|
|||||||
#endif
|
#endif
|
||||||
if (VideoHardwareDecoder != old_video_hardware_decoder) {
|
if (VideoHardwareDecoder != old_video_hardware_decoder) {
|
||||||
VideoHardwareDecoder = old_video_hardware_decoder;
|
VideoHardwareDecoder = old_video_hardware_decoder;
|
||||||
VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
|
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream
|
||||||
}
|
}
|
||||||
VideoSetTrickSpeed(MyVideoStream->HwDecoder, 0);
|
VideoSetTrickSpeed(MyVideoStream->HwDecoder, 0);
|
||||||
}
|
}
|
||||||
@@ -3122,7 +3173,7 @@ int Start(void)
|
|||||||
AudioInit();
|
AudioInit();
|
||||||
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
|
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
|
||||||
MyAudioDecoder = CodecAudioNewDecoder();
|
MyAudioDecoder = CodecAudioNewDecoder();
|
||||||
AudioCodecID = CODEC_ID_NONE;
|
AudioCodecID = AV_CODEC_ID_NONE;
|
||||||
AudioChannelID = -1;
|
AudioChannelID = -1;
|
||||||
|
|
||||||
if (!ConfigStartX11Server) {
|
if (!ConfigStartX11Server) {
|
||||||
@@ -3275,7 +3326,7 @@ void Resume(void)
|
|||||||
AudioInit();
|
AudioInit();
|
||||||
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
|
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
|
||||||
MyAudioDecoder = CodecAudioNewDecoder();
|
MyAudioDecoder = CodecAudioNewDecoder();
|
||||||
AudioCodecID = CODEC_ID_NONE;
|
AudioCodecID = AV_CODEC_ID_NONE;
|
||||||
AudioChannelID = -1;
|
AudioChannelID = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3376,8 +3427,8 @@ void PipStart(int x, int y, int width, int height, int pip_x, int pip_y,
|
|||||||
|
|
||||||
if (!PipVideoStream->Decoder) {
|
if (!PipVideoStream->Decoder) {
|
||||||
PipVideoStream->SkipStream = 1;
|
PipVideoStream->SkipStream = 1;
|
||||||
PipVideoStream->CodecID = CODEC_ID_NONE;
|
PipVideoStream->CodecID = AV_CODEC_ID_NONE;
|
||||||
PipVideoStream->LastCodecID = CODEC_ID_NONE;
|
PipVideoStream->LastCodecID = AV_CODEC_ID_NONE;
|
||||||
|
|
||||||
if ((PipVideoStream->HwDecoder = VideoNewHwDecoder(PipVideoStream))) {
|
if ((PipVideoStream->HwDecoder = VideoNewHwDecoder(PipVideoStream))) {
|
||||||
PipVideoStream->Decoder =
|
PipVideoStream->Decoder =
|
||||||
@@ -3422,6 +3473,7 @@ void PipStop(void)
|
|||||||
VideoPacketExit(PipVideoStream);
|
VideoPacketExit(PipVideoStream);
|
||||||
|
|
||||||
PipVideoStream->NewStream = 1;
|
PipVideoStream->NewStream = 1;
|
||||||
|
PipVideoStream->InvalidPesCounter = 0;
|
||||||
#else
|
#else
|
||||||
PipVideoStream->Close = 1;
|
PipVideoStream->Close = 1;
|
||||||
for (i = 0; PipVideoStream->Close && i < 50; ++i) {
|
for (i = 0; PipVideoStream->Close && i < 50; ++i) {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ extern "C"
|
|||||||
/// vdr-plugin version number.
|
/// vdr-plugin version number.
|
||||||
/// Makefile extracts the version number for generating the file name
|
/// Makefile extracts the version number for generating the file name
|
||||||
/// for the distribution archive.
|
/// for the distribution archive.
|
||||||
static const char *const VERSION = "0.6.0"
|
static const char *const VERSION = "0.6.1rc1"
|
||||||
#ifdef GIT_REV
|
#ifdef GIT_REV
|
||||||
"-GIT" GIT_REV
|
"-GIT" GIT_REV
|
||||||
#endif
|
#endif
|
||||||
@@ -854,9 +854,9 @@ void cMenuSetupSoft::Create(void)
|
|||||||
&AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
|
&AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
|
||||||
Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"),
|
Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"),
|
||||||
&AudioPassthroughAC3, trVDR("no"), trVDR("yes")));
|
&AudioPassthroughAC3, trVDR("no"), trVDR("yes")));
|
||||||
Add(new cMenuEditBoolItem(tr("\040\040EAC-3 pass-through"),
|
Add(new cMenuEditBoolItem(tr("\040\040E-AC-3 pass-through"),
|
||||||
&AudioPassthroughEAC3, trVDR("no"), trVDR("yes")));
|
&AudioPassthroughEAC3, trVDR("no"), trVDR("yes")));
|
||||||
Add(new cMenuEditBoolItem(tr("Enable (E)AC-3 (decoder) downmix"),
|
Add(new cMenuEditBoolItem(tr("Enable (E-)AC-3 (decoder) downmix"),
|
||||||
&AudioDownmix, trVDR("no"), trVDR("yes")));
|
&AudioDownmix, trVDR("no"), trVDR("yes")));
|
||||||
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
|
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
|
||||||
tr("Hardware"), tr("Software")));
|
tr("Hardware"), tr("Software")));
|
||||||
@@ -1443,12 +1443,12 @@ static void PipPesParse(const uint8_t * data, int size, int is_start)
|
|||||||
if (is_start) { // start of pes packet
|
if (is_start) { // start of pes packet
|
||||||
if (pes_index) {
|
if (pes_index) {
|
||||||
if (0) {
|
if (0) {
|
||||||
fprintf(stderr, "pip: pes packet %8d %02x%02x\n", pes_index,
|
fprintf(stderr, "pip: PES packet %8d %02x%02x\n", pes_index,
|
||||||
pes_buf[2], pes_buf[3]);
|
pes_buf[2], pes_buf[3]);
|
||||||
}
|
}
|
||||||
if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) {
|
if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) {
|
||||||
// FIXME: first should always fail
|
// FIXME: first should always fail
|
||||||
esyslog(tr("[softhddev]pip: invalid pes packet %d\n"),
|
esyslog(tr("[softhddev]pip: invalid PES packet %d\n"),
|
||||||
pes_index);
|
pes_index);
|
||||||
} else {
|
} else {
|
||||||
PipPlayVideo(pes_buf, pes_index);
|
PipPlayVideo(pes_buf, pes_index);
|
||||||
@@ -2190,7 +2190,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
|
|||||||
case pmVideoOnly:
|
case pmVideoOnly:
|
||||||
break;
|
break;
|
||||||
case pmNone:
|
case pmNone:
|
||||||
return true;
|
break;
|
||||||
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
case pmExtern_THIS_SHOULD_BE_AVOIDED:
|
||||||
dsyslog("[softhddev] play mode external\n");
|
dsyslog("[softhddev] play mode external\n");
|
||||||
// FIXME: what if already suspended?
|
// FIXME: what if already suspended?
|
||||||
@@ -2512,6 +2512,9 @@ uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
|
|||||||
if (SuspendMode != NOT_SUSPENDED) {
|
if (SuspendMode != NOT_SUSPENDED) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (quality < 0) { // caller should care, but fix it
|
||||||
|
quality = 95;
|
||||||
|
}
|
||||||
|
|
||||||
return::GrabImage(&size, jpeg, quality, width, height);
|
return::GrabImage(&size, jpeg, quality, width, height);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ HOMEPAGE="http://projects.vdr-developer.org/projects/show/plg-softhddevice"
|
|||||||
|
|
||||||
LICENSE="AGPL-3"
|
LICENSE="AGPL-3"
|
||||||
SLOT="0"
|
SLOT="0"
|
||||||
IUSE="alsa oss vaapi vdpau yaepg xscreensaver debug"
|
IUSE="alsa oss vaapi vdpau opengl yaepg xscreensaver debug"
|
||||||
|
|
||||||
RDEPEND=">=media-video/vdr-1.7
|
RDEPEND=">=media-video/vdr-1.7
|
||||||
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
|
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
|
||||||
@@ -30,6 +30,7 @@ RDEPEND=">=media-video/vdr-1.7
|
|||||||
alsa? ( media-libs/alsa-lib )
|
alsa? ( media-libs/alsa-lib )
|
||||||
vdpau? ( x11-libs/libvdpau )
|
vdpau? ( x11-libs/libvdpau )
|
||||||
vaapi? ( x11-libs/libva )
|
vaapi? ( x11-libs/libva )
|
||||||
|
opengl? ( virtual/opengl )
|
||||||
alsa? ( media-libs/alsa-lib )
|
alsa? ( media-libs/alsa-lib )
|
||||||
yaepg? ( >=media-video/vdr-1.7[yaepg] )"
|
yaepg? ( >=media-video/vdr-1.7[yaepg] )"
|
||||||
DEPEND="${RDEPEND}
|
DEPEND="${RDEPEND}
|
||||||
@@ -44,6 +45,7 @@ src_compile() {
|
|||||||
myconf+=" ALSA=$(usex alsa 1 0)"
|
myconf+=" ALSA=$(usex alsa 1 0)"
|
||||||
myconf+=" OSS=$(usex oss 1 0)"
|
myconf+=" OSS=$(usex oss 1 0)"
|
||||||
myconf+=" VDPAU=$(usex vdpau 1 0)"
|
myconf+=" VDPAU=$(usex vdpau 1 0)"
|
||||||
|
myconf+=" OPENGL=$(usex opengl 1 0)"
|
||||||
myconf+=" VAAPI=$(usex vaapi 1 0)"
|
myconf+=" VAAPI=$(usex vaapi 1 0)"
|
||||||
myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
|
myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
|
||||||
if has_version ">=media-video/ffmpeg-0.8" ; then
|
if has_version ">=media-video/ffmpeg-0.8" ; then
|
||||||
|
|||||||
4
video.h
4
video.h
@@ -67,8 +67,8 @@ extern enum PixelFormat Video_get_format(VideoHwDecoder *, AVCodecContext *,
|
|||||||
extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
|
extern void VideoRenderFrame(VideoHwDecoder *, const AVCodecContext *,
|
||||||
const AVFrame *);
|
const AVFrame *);
|
||||||
|
|
||||||
/// Get ffmpeg vaapi context.
|
/// Get hwaccel context for ffmpeg.
|
||||||
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
|
extern void *VideoGetHwAccelContext(VideoHwDecoder *);
|
||||||
|
|
||||||
#ifdef AVCODEC_VDPAU_H
|
#ifdef AVCODEC_VDPAU_H
|
||||||
/// Draw vdpau render state.
|
/// Draw vdpau render state.
|
||||||
|
|||||||
Reference in New Issue
Block a user