30 Commits

Author SHA1 Message Date
Johns
58a76439ee Softer audio/video sync. 2013-09-30 20:54:27 +02:00
Johns
a13c25d309 Add function GetStats to the video output module. 2013-08-07 10:29:44 +02:00
Johns
5265e68aa9 Add function ResetStart to the video output module. 2013-08-06 12:16:30 +02:00
Johns
11121b5bdd Add function SetClosing to the video output module. 2013-08-04 17:43:11 +02:00
Johns
d8e96c7871 Generalize GetVaapiContext to GetHwAccelContext. 2013-08-03 17:27:52 +02:00
Johns
8ff65a011a Add compile time configurable trickspeed packets dump. 2013-07-29 19:14:32 +02:00
Johns
171a3f4dc9 Fix bug #1410: wrong spelled AC-3 and E-AC-3. 2013-07-26 16:55:33 +02:00
Johns
93357fb1cd Add compile time selectable h264 trickspeed workaround. 2013-07-24 20:06:05 +02:00
Johns
c646007db1 Use ffmpeg new names AVCodecID, AV_CODEC_... . 2013-07-18 17:08:47 +02:00
Johns
7615305960 Fix bug: video lagging behind after recording stop. 2013-07-16 16:39:46 +02:00
Johns
cc1e2de58b Reduce PES error messages. 2013-07-15 17:00:22 +02:00
Johns
738e9402d2 Report synced as info and not as debug message. 2013-07-15 16:58:36 +02:00
Johns
34fd275b42 Fix bug #1392: Wrong value for mixing LFE. 2013-07-08 14:36:08 +02:00
Johns
64c11efc1b Fix bug: wrong grab size, introduced with AMD VDPAU. 2013-05-16 20:28:44 +02:00
Johns
ebb8482226 Use VDR SPU decoder as default. 2013-05-15 10:07:30 +02:00
Johns
833112eaa9 Fix bug: grab image negative quality isn't 100. 2013-05-14 12:32:09 +02:00
Johns
3022920b40 Don't forget PIP documentation. 2013-05-10 16:33:37 +02:00
Johns
c1d3b9d048 Support AMD VDPAU with surface != requested size. 2013-05-10 15:53:26 +02:00
Johns
4fe1c43c08 Removes VA-API enabled as default.
Removes studio levels environment setting.
2013-04-23 20:46:36 +02:00
Johns
7a5e696bc4 Fix opengl and opengl threads bugs. 2013-04-17 16:35:51 +02:00
Johns
8f99f80d44 Initial opengl support with va-api only. 2013-04-16 16:44:42 +02:00
Johns
c0286b3ab4 Fix "broken driver" message if empty ring buffer. 2013-04-15 16:55:15 +02:00
Johns
9dd248f9d0 Enable seamless audio track change. 2013-04-11 12:03:38 +02:00
Johns
238224efc8 Better to unlock after the free and zero. 2013-04-10 15:04:09 +02:00
Johns
5b35e70b94 Fix bug #1302: Unsupported pixel format crash. 2013-04-08 16:42:47 +02:00
Johns
857546a3a5 Fix the fix, when sillpicture is called in suspend. 2013-04-06 14:24:08 +02:00
Johns
a1b77b1502 Fixes PIP Y translation. 2013-04-03 16:53:45 +02:00
Johns
7ef5667598 Patch was not 100% correct, fixed. 2013-04-03 16:51:27 +02:00
Johns
4e3f5f5414 Fix crash, when sillpicture is called in suspend mode. 2013-04-03 16:48:00 +02:00
Johns
23b0e0d599 Add workaround for zero width+height and ffmpeg >= 1.2. 2013-04-03 16:47:21 +02:00
13 changed files with 892 additions and 554 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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
View File

@@ -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
View File

@@ -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
View File

@@ -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;
} }

View File

@@ -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)
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

View File

@@ -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 ""

View File

@@ -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) {

View File

@@ -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);
} }

View File

@@ -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

974
video.c

File diff suppressed because it is too large Load Diff

View File

@@ -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.