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
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)
# support OSS audio output module
OSS ?= 1
# support VDPAU video output modue
# support VDPAU video output module
VDPAU ?= $(shell pkg-config --exists vdpau && echo 1)
# support VA-API video output modue
VAAPI ?= $(shell pkg-config --exists libva && echo 1)
# support VA-API video output module (deprecated)
#VAAPI ?= $(shell pkg-config --exists libva && echo 1)
# support glx output
#OPENGL ?= $(shell pkg-config --exists gl glu && echo 1)
# screensaver disable/enable
SCREENSAVER ?= 1
# use ffmpeg libswresample
@@ -33,7 +35,10 @@ CONFIG += -DUSE_PIP # PIP support
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser
#CONFIG += -DUSE_TS_VIDEO # build new ts video parser
#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)
CONFIG += -DUSE_ALSA
@@ -52,6 +57,15 @@ ifeq ($(VAAPI),1)
CONFIG += -DUSE_VAAPI
_CFLAGS += $(shell pkg-config --cflags 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
ifeq ($(SCREENSAVER),1)
CONFIG += -DUSE_SCREENSAVER

View File

@@ -20,14 +20,14 @@ $Id$
A software and GPU emulated HD output device plugin for VDR.
o Video decoder CPU / VA-API / VDPAU
o Video output VA-API / VDPAU
o Video decoder CPU / VDPAU
o Video output VDPAU
o Audio FFMpeg / Alsa / Analog
o Audio FFMpeg / Alsa / Digital
o Audio FFMpeg / OSS / Analog
o HDMI/SPDIF pass-through
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 Autocrop
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 PIP (Picture-in-Picture) (VDPAU only)
o planned: Video decoder VA-API Branch: vaapi-ext/staging
o planned: Video output XvBA / Opengl / Xv
o planned: VA-API grab image
o planned: Improved Software Deinterlacer (yadif or/and ffmpeg filters)
o planned: Remove VA-API decoder and output support
o planned: Video decoder OpenMax
o planned: Video output Opengl / Xv
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.
@@ -83,14 +84,12 @@ Setup: environment
if set don't use the hardware decoders
NO_MPEG_HW=1
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
ALSA_DEVICE=default
alsa PCM device name
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 control device name
ALSA_MIXER_CHANNEL=PCM
@@ -100,7 +99,7 @@ Setup: environment
OSS_AUDIODEV=/dev/dsp
oss dsp device name
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 mixer device name
OSS_MIXER_CHANNEL=pcm
@@ -130,7 +129,7 @@ Setup: /etc/vdr/setup.conf
softhddevice.<res>.Deinterlace = 0
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
0 = disabled, 1 = enabled (for slower cards, poor qualit<69>t)
@@ -361,7 +360,7 @@ Requires:
or
kernel support for oss/oss4 or alsa oss emulation
x11-libs/libva
x11-libs/libva (deprecated)
Video Acceleration (VA) API for Linux
http://www.freedesktop.org/wiki/Software/vaapi
x11-libs/libva-intel-driver

8
Todo
View File

@@ -1,6 +1,6 @@
@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):
@@ -19,6 +19,9 @@ GNU Affero General Public License for more details.
$Id: $
missing:
documentation of the PIP hotkeys.
svdrp help page missing PIP hotkeys.
svdrp stat: add X11 crashed status.
more software deinterlace (yadif, ...)
more software decoder with software deinterlace
suspend output / energie saver: stop and restart X11
@@ -40,11 +43,14 @@ video:
check start with 24Hz display rate
crash with ffmpeg without vaapi and vdpau.
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:
software deinterlace path not working.
OSD looses transparency, during channel switch.
OSD looses transparency, while moving cut marks.
ffmpeg >=1.2 supports same API like VA-API.
libva:
yaepghd (VaapiSetOutputPosition) support

40
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
l += in[4] * 300; // C
r += in[4] * 300;
l += in[5] * 300; // LFE
l += in[5] * 100; // LFE
r += in[5] * 100;
break;
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_
{
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
unsigned HwSampleRate; ///< hardware sample rate in Hz
unsigned HwChannels; ///< hardware number of channels
@@ -642,7 +642,7 @@ static unsigned AudioStartThreshold; ///< start play, if filled
**
** @param sample_rate sample-rate frequency
** @param channels number of channels
** @param passthrough use /pass-through (AC3, ...) device
** @param passthrough use /pass-through (AC-3, ...) device
**
** @retval -1 error
** @retval 0 okay
@@ -678,8 +678,7 @@ static int AudioRingAdd(unsigned sample_rate, int channels, int passthrough)
}
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
// FIXME: don't flush buffers here
AudioRing[AudioRingWrite].FlushBuffers = 1;
AudioRing[AudioRingWrite].FlushBuffers = 0;
AudioRing[AudioRingWrite].Passthrough = passthrough;
AudioRing[AudioRingWrite].PacketSize = 0;
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);
RingBufferReset(AudioRing[AudioRingWrite].RingBuffer);
Debug(3, "audio: %d ring buffer prepared\n",
atomic_read(&AudioRingFilled) + 1);
atomic_inc(&AudioRingFilled);
#ifdef USE_AUDIO_THREAD
@@ -836,7 +838,7 @@ static int AlsaPlayRingbuffer(void)
if (!avail) { // full or buffer empty
break;
}
// muting pass-through ac3, can produce disturbance
// muting pass-through AC-3, can produce disturbance
if (AudioMute || (AudioSoftVolume
&& !AudioRing[AudioRingRead].Passthrough)) {
// FIXME: quick&dirty cast
@@ -985,7 +987,7 @@ static int AlsaThread(void)
/**
** 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)
{
@@ -1168,7 +1170,7 @@ static int64_t AlsaGetDelay(void)
**
** @param freq sample frequency
** @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 1 didn't support frequency/channels combination
@@ -1561,7 +1563,7 @@ static int OssThread(void)
/**
** Open OSS pcm device.
**
** @param passthrough use pass-through (AC3, ...) device
** @param passthrough use pass-through (AC-3, ...) device
*/
static int OssOpenPCM(int passthrough)
{
@@ -1725,7 +1727,7 @@ static int64_t OssGetDelay(void)
**
** @param sample_rate sample rate/frequency
** @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 1 didn't support frequency/channels combination
@@ -1743,7 +1745,7 @@ static int OssSetup(int *sample_rate, int *channels, int passthrough)
return -1;
}
if (1) { // close+open for pcm / ac3
if (1) { // close+open for pcm / AC-3
int fildes;
fildes = OssPcmFildes;
@@ -1932,7 +1934,7 @@ static void NoopSetVolume( __attribute__ ((unused))
**
** @param freq sample frequency
** @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))
int *channels, __attribute__ ((unused))
@@ -2031,10 +2033,10 @@ static void *AudioPlayHandlerThread(void *dummy)
pthread_mutex_unlock(&AudioMutex);
Debug(3, "audio: ----> %dms start\n", (AudioUsedBytes() * 1000)
/ (!AudioRing[AudioRingRead].HwSampleRate +
!AudioRing[AudioRingRead].HwChannels +
AudioRing[AudioRingRead].HwSampleRate *
AudioRing[AudioRingRead].HwChannels * AudioBytesProSample));
/ (!AudioRing[AudioRingWrite].HwSampleRate +
!AudioRing[AudioRingWrite].HwChannels +
AudioRing[AudioRingWrite].HwSampleRate *
AudioRing[AudioRingWrite].HwChannels * AudioBytesProSample));
do {
int filled;
@@ -2067,7 +2069,10 @@ static void *AudioPlayHandlerThread(void *dummy)
Debug(3, "audio: continue after flush\n");
}
// try to play some samples
err = 0;
if (RingBufferUsedBytes(AudioRing[AudioRingRead].RingBuffer)) {
err = AudioUsedModule->Thread();
}
// underrun, check if new ring buffer is available
if (!err) {
int passthrough;
@@ -2417,6 +2422,7 @@ void AudioFlushBuffers(void)
int i;
old = AudioRingWrite;
// FIXME: check ring buffer overflow
AudioRingWrite = (AudioRingWrite + 1) % AUDIO_RING_MAX;
AudioRing[AudioRingWrite].FlushBuffers = 1;
AudioRing[AudioRingWrite].Passthrough = AudioRing[old].Passthrough;
@@ -2570,7 +2576,7 @@ void AudioSetVolume(int volume)
**
** @param freq sample frequency
** @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 1 didn't support frequency/channels combination

50
codec.c
View File

@@ -56,6 +56,13 @@
#include <alsa/iatomic.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>
#ifdef USE_VDPAU
#include <libavcodec/vdpau.h>
@@ -434,7 +441,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
decoder->VideoCtx->opaque = decoder; // our structure
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
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_ALL;
//decoder->VideoCtx->skip_loop_filter = AVDISCARD_BIDIR;
@@ -476,7 +483,7 @@ void CodecVideoOpen(VideoDecoder * decoder, const char *name, int codec_id)
} else {
decoder->VideoCtx->get_format = Codec_get_format;
decoder->VideoCtx->hwaccel_context =
VideoGetVaapiContext(decoder->HwDecoder);
VideoGetHwAccelContext(decoder->HwDecoder);
}
// our pixel format video hardware decoder hook
@@ -515,8 +522,8 @@ void CodecVideoClose(VideoDecoder * video_decoder)
if (video_decoder->VideoCtx) {
pthread_mutex_lock(&CodecLockMutex);
avcodec_close(video_decoder->VideoCtx);
pthread_mutex_unlock(&CodecLockMutex);
av_freep(&video_decoder->VideoCtx);
pthread_mutex_unlock(&CodecLockMutex);
}
}
@@ -703,7 +710,7 @@ enum IEC61937
#ifdef USE_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
#else
static const int CodecAudioDrift = 0;
@@ -856,15 +863,15 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
if (audio_decoder->AudioCtx) {
pthread_mutex_lock(&CodecLockMutex);
avcodec_close(audio_decoder->AudioCtx);
pthread_mutex_unlock(&CodecLockMutex);
av_freep(&audio_decoder->AudioCtx);
pthread_mutex_unlock(&CodecLockMutex);
}
}
/**
** Set audio drift correction.
**
** @param mask enable mask (PCM, AC3)
** @param mask enable mask (PCM, AC-3)
*/
void CodecSetAudioDrift(int mask)
{
@@ -877,7 +884,7 @@ void CodecSetAudioDrift(int mask)
/**
** 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)
{
@@ -978,8 +985,8 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
av_get_sample_fmt_name(audio_ctx->sample_fmt), audio_ctx->sample_rate,
audio_ctx->channels, CodecPassthrough & CodecPCM ? " PCM" : "",
CodecPassthrough & CodecMPA ? " MPA" : "",
CodecPassthrough & CodecAC3 ? " AC3" : "",
CodecPassthrough & CodecEAC3 ? " EAC3" : "",
CodecPassthrough & CodecAC3 ? " AC-3" : "",
CodecPassthrough & CodecEAC3 ? " E-AC-3" : "",
CodecPassthrough ? " pass-through" : "");
*passthrough = 0;
@@ -990,11 +997,11 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
audio_decoder->Passthrough = CodecPassthrough;
// 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
&& audio_ctx->codec_id == CODEC_ID_EAC3)) {
if (audio_ctx->codec_id == CODEC_ID_EAC3) {
// EAC3 over HDMI some receivers need HBR
&& audio_ctx->codec_id == AV_CODEC_ID_EAC3)) {
if (audio_ctx->codec_id == AV_CODEC_ID_EAC3) {
// E-AC-3 over HDMI some receivers need HBR
audio_decoder->HwSampleRate *= 4;
}
audio_decoder->HwChannels = 2;
@@ -1007,9 +1014,9 @@ static int CodecAudioUpdateHelper(AudioDecoder * audio_decoder,
AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, *passthrough))) {
// try EAC3 none HBR
// try E-AC-3 none HBR
audio_decoder->HwSampleRate /= 4;
if (audio_ctx->codec_id != CODEC_ID_EAC3
if (audio_ctx->codec_id != AV_CODEC_ID_EAC3
|| (err =
AudioSetup(&audio_decoder->HwSampleRate,
&audio_decoder->HwChannels, *passthrough))) {
@@ -1044,7 +1051,7 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
audio_ctx = audio_decoder->AudioCtx;
// 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;
int spdif_sz;
@@ -1094,7 +1101,8 @@ static int CodecAudioPassthroughHelper(AudioDecoder * audio_decoder,
AudioEnqueue(spdif, spdif_sz);
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;
int spdif_sz;
int repeat;
@@ -1223,9 +1231,9 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
// SPDIF/HDMI passthrough
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)
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
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);
// SPDIF/HDMI passthrough
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)
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_EAC3)) {
|| audio_decoder->AudioCtx->codec_id != AV_CODEC_ID_EAC3)) {
audio_decoder->DriftCorr = -corr;
}

View File

@@ -30,7 +30,7 @@
#define CodecPCM 0x01 ///< PCM bit mask
#define CodecMPA 0x02 ///< MPA bit mask (planned)
#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)
//----------------------------------------------------------------------------

View File

@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: VDR \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"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -384,6 +384,10 @@ msgstr ""
msgid "[softhddev] invalid PES video packet\n"
msgstr ""
#, c-format
msgid "[softhddev] %d invalid PES video packet(s)\n"
msgstr ""
msgid "[softhddev] empty video packet\n"
msgstr ""
@@ -587,10 +591,10 @@ msgstr ""
msgid " AC-3 pass-through"
msgstr ""
msgid " EAC-3 pass-through"
msgid " E-AC-3 pass-through"
msgstr ""
msgid "Enable (E)AC-3 (decoder) downmix"
msgid "Enable (E-)AC-3 (decoder) downmix"
msgstr ""
msgid "Volume control"
@@ -627,7 +631,7 @@ msgid "Pip X (%)"
msgstr "PIP X (%)"
msgid "Pip Y (%)"
msgstr "PIP X (%)"
msgstr "PIP Y (%)"
msgid "Pip Width (%)"
msgstr "PIP Breite (%)"
@@ -672,7 +676,7 @@ msgid "Alternative Video Height (%)"
msgstr "Alternative Videohöhe (%)"
#, c-format
msgid "[softhddev]pip: invalid pes packet %d\n"
msgid "[softhddev]pip: invalid PES packet %d\n"
msgstr ""
msgid "[softhddev]pip: pes buffer too small\n"
@@ -895,6 +899,9 @@ msgstr ""
msgid "unsupported"
msgstr ""
msgid "video/glx: glx error\n"
msgstr ""
#, c-format
msgid "video/vaapi: unsupported pixel format %d\n"
msgstr ""
@@ -1265,6 +1272,9 @@ msgstr ""
msgid "video/vdpau: can't put video surface bits: %s\n"
msgstr ""
msgid "video: get hwaccel context, not supported\n"
msgstr ""
#, c-format
msgid "video/vdpau: can't render bitmap surface: %s\n"
msgstr ""
@@ -1331,9 +1341,6 @@ msgstr ""
msgid "video: repeated pict %d found, but not handled\n"
msgstr ""
msgid "video/vaapi: get vaapi context, without vaapi enabled\n"
msgstr ""
#, c-format
msgid "video/vdpau: decoder rendering failed: %s\n"
msgstr ""
@@ -1355,6 +1362,10 @@ msgstr ""
msgid "video: Can't connect to X11 server on '%s'\n"
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"
msgstr ""

View File

@@ -22,6 +22,7 @@
#define noUSE_SOFTLIMIT ///< add soft buffer limits to Play..
#define noUSE_PIP ///< include PIP support + new API
#define noDUMP_TRICKSPEED ///< dump raw trickspeed packets
#include <sys/types.h>
#include <sys/stat.h>
@@ -40,6 +41,19 @@
#define _N(str) str ///< gettext_noop shortcut
#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
#define __USE_GNU
@@ -86,7 +100,7 @@ static volatile char StreamFreezed; ///< stream freezed
static volatile char NewAudioStream; ///< new audio stream
static volatile char SkipAudio; ///< skip audio stream
static AudioDecoder *MyAudioDecoder; ///< audio decoder
static enum CodecID AudioCodecID; ///< current codec id
static enum AVCodecID AudioCodecID; ///< current codec id
static int AudioChannelID; ///< current audio channel id
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.
///
@@ -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)
{
@@ -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.
///
@@ -341,7 +355,7 @@ static inline int FastAc3Check(const uint8_t * p)
/// @retval 0 no valid AC-3 audio
/// @retval >0 valid AC-3 audio
///
/// o AC3 Header
/// o AC-3 Header
/// AAAAAAAA AAAAAAAA BBBBBBBB BBBBBBBB CCDDDDDD EEEEEFFF
///
/// 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 f 3x Bitstream mode
///
/// o EAC3 Header
/// o E-AC-3 Header
/// AAAAAAAA AAAAAAAA BBCCCDDD DDDDDDDD EEFFGGGH IIIII...
///
/// o a 16x Frame sync, always 0x0B77
@@ -365,17 +379,17 @@ static int Ac3Check(const uint8_t * data, int 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;
}
if (data[5] > (10 << 3)) { // EAC3
if (data[5] > (10 << 3)) { // E-AC-3
if ((data[4] & 0xF0) == 0xF0) { // invalid fscod fscod2
return 0;
}
frame_size = ((data[2] & 0x03) << 8) + data[3] + 1;
frame_size *= 2;
} else { // AC3
} else { // AC-3
int fscod;
int frmsizcod;
@@ -617,7 +631,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
#if 0
// Played with PlayAudio
// FIXME: need 0x80 -- 0xA0 state
if (AudioCodecID == CODEC_ID_NONE) {
if (AudioCodecID == AV_CODEC_ID_NONE) {
if ((*p & 0xF0) == 0x80) { // AC-3 & DTS
Debug(3, "pesdemux: dvd ac-3\n");
} else if ((*p & 0xFF) == 0xA0) { // LPCM
@@ -651,8 +665,8 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
unsigned codec_id;
// 4 bytes 0xFFExxxxx Mpeg audio
// 5 bytes 0x0B77xxxxxx AC3 audio
// 6 bytes 0x0B77xxxxxxxx EAC3 audio
// 5 bytes 0x0B77xxxxxx AC-3 audio
// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
// 3 bytes 0x56Exxx AAC LATM audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found
@@ -660,22 +674,22 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
r = 0;
if (!r && FastMpegCheck(q)) {
r = MpegCheck(q, n);
codec_id = CODEC_ID_MP2;
codec_id = AV_CODEC_ID_MP2;
}
if (!r && FastAc3Check(q)) {
r = Ac3Check(q, n);
codec_id = CODEC_ID_AC3;
codec_id = AV_CODEC_ID_AC3;
if (r > 0 && q[5] > (10 << 3)) {
codec_id = CODEC_ID_EAC3;
codec_id = AV_CODEC_ID_EAC3;
}
}
if (!r && FastLatmCheck(q)) {
r = LatmCheck(q, n);
codec_id = CODEC_ID_AAC_LATM;
codec_id = AV_CODEC_ID_AAC_LATM;
}
if (!r && FastAdtsCheck(q)) {
r = AdtsCheck(q, n);
codec_id = CODEC_ID_AAC;
codec_id = AV_CODEC_ID_AAC;
}
if (r < 0) { // need more bytes
break;
@@ -705,7 +719,7 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
//pesdx->State = PES_MPEG_DECODE;
break;
}
if (AudioCodecID != CODEC_ID_NONE) {
if (AudioCodecID != AV_CODEC_ID_NONE) {
// shouldn't happen after we have a vaild codec
// detected
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;
const uint8_t *q;
if (AudioCodecID != CODEC_ID_PCM_DVD) {
if (AudioCodecID != AV_CODEC_ID_PCM_DVD) {
q = pesdx->Header;
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);
// FIXME: support resample
}
//CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
AudioCodecID = CODEC_ID_PCM_DVD;
//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD);
AudioCodecID = AV_CODEC_ID_PCM_DVD;
}
pesdx->State = PES_LPCM_PAYLOAD;
pesdx->Index = 0;
@@ -1023,7 +1037,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
CodecAudioClose(MyAudioDecoder);
AudioFlushBuffers();
AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = CODEC_ID_NONE;
AudioCodecID = AV_CODEC_ID_NONE;
AudioChannelID = -1;
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
AudioChannelID = id;
AudioCodecID = CODEC_ID_NONE;
AudioCodecID = AV_CODEC_ID_NONE;
}
// Private stream + LPCM ID
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);
return size;
}
if (AudioCodecID != CODEC_ID_PCM_DVD) {
if (AudioCodecID != AV_CODEC_ID_PCM_DVD) {
static int samplerates[] = { 48000, 96000, 44100, 32000 };
int samplerate;
int channels;
@@ -1123,8 +1137,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
(p[5] & 0x7) + 1);
// FIXME: support resample
}
//CodecAudioOpen(MyAudioDecoder, NULL, CODEC_ID_PCM_DVD);
AudioCodecID = CODEC_ID_PCM_DVD;
//CodecAudioOpen(MyAudioDecoder, NULL, AV_CODEC_ID_PCM_DVD);
AudioCodecID = AV_CODEC_ID_PCM_DVD;
}
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) {
p += 4;
n -= 4; // skip track header
if (AudioCodecID == CODEC_ID_NONE) {
if (AudioCodecID == AV_CODEC_ID_NONE) {
// FIXME: ConfigAudioBufferTime + x
AudioSetBufferTime(400);
}
@@ -1157,25 +1171,25 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
// 4 bytes 0xFFExxxxx Mpeg audio
// 3 bytes 0x56Exxx AAC LATM audio
// 5 bytes 0x0B77xxxxxx AC3 audio
// 6 bytes 0x0B77xxxxxxxx EAC3 audio
// 5 bytes 0x0B77xxxxxx AC-3 audio
// 6 bytes 0x0B77xxxxxxxx E-AC-3 audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found
r = 0;
codec_id = CODEC_ID_NONE; // keep compiler happy
codec_id = AV_CODEC_ID_NONE; // keep compiler happy
if (id != 0xbd && FastMpegCheck(p)) {
r = MpegCheck(p, n);
codec_id = CODEC_ID_MP2;
codec_id = AV_CODEC_ID_MP2;
}
if (id != 0xbd && !r && FastLatmCheck(p)) {
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)) {
r = Ac3Check(p, n);
codec_id = CODEC_ID_AC3;
codec_id = AV_CODEC_ID_AC3;
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)
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)) {
r = AdtsCheck(p, n);
codec_id = CODEC_ID_AAC;
codec_id = AV_CODEC_ID_AAC;
}
if (r < 0) { // need more bytes
break;
@@ -1253,7 +1267,7 @@ int PlayTsAudio(const uint8_t * data, int size)
AudioFlushBuffers();
// max time between audio packets 200ms + 24ms hw buffer
AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = CODEC_ID_NONE;
AudioCodecID = AV_CODEC_ID_NONE;
AudioChannelID = -1;
NewAudioStream = 0;
PesReset(PesDemuxAudio);
@@ -1303,8 +1317,8 @@ struct __video_stream__
VideoDecoder *Decoder; ///< video decoder
pthread_mutex_t DecoderLockMutex; ///< video decoder lock mutex
enum CodecID CodecID; ///< current codec id
enum CodecID LastCodecID; ///< last codec id
enum AVCodecID CodecID; ///< current codec id
enum AVCodecID LastCodecID; ///< last codec id
volatile char NewStream; ///< flag new 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 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
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->CodecIDRb[stream->PacketWrite] = AV_CODEC_ID_NONE;
avpkt = &stream->PacketRb[stream->PacketWrite];
avpkt->stream_index = 0;
avpkt->priv = NULL;
avpkt->pts = 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];
if (!avpkt->stream_index) { // ignore empty packets
if (codec_id != CODEC_ID_NONE) {
if (codec_id != AV_CODEC_ID_NONE) {
return;
}
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
Error(_("video: no empty slot in packet ringbuffer\n"));
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");
}
return;
@@ -1479,7 +1496,7 @@ static void VideoNextPacket(VideoStream * stream, int codec_id)
// clear area for decoder, always enough space allocated
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);
// advance packet write
@@ -1539,7 +1556,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
#endif
stream->PacketRb[stream->PacketWrite].stream_index -= 3;
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
VideoEnqueue(stream, pts, startcode, 3);
first = p[0] == 0xb3;
p++;
@@ -1556,7 +1573,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
#endif
stream->PacketRb[stream->PacketWrite].stream_index -= 2;
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
VideoEnqueue(stream, pts, startcode, 2);
first = p[1] == 0xb3;
p += 2;
@@ -1573,7 +1590,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
fprintf(stderr, "last: %d start\n", stream->StartCodeState);
#endif
stream->PacketRb[stream->PacketWrite].stream_index -= 1;
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
VideoEnqueue(stream, pts, startcode, 1);
first = p[2] == 0xb3;
p += 3;
@@ -1606,7 +1623,7 @@ static void VideoMpegEnqueue(VideoStream * stream, int64_t pts,
*/
// first packet goes only upto picture header
VideoEnqueue(stream, pts, data, p - data);
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
#ifdef DEBUG
fprintf(stderr, "fix\r");
#endif
@@ -1756,6 +1773,7 @@ static void VideoStreamClose(VideoStream * stream)
VideoPacketExit(stream);
stream->NewStream = 1;
stream->InvalidPesCounter = 0;
}
/**
@@ -1853,9 +1871,8 @@ int VideoDecodeInput(VideoStream * stream)
// flush buffers, if close is in the queue
for (f = 0; f < filled; ++f) {
avpkt =
&stream->PacketRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX];
if ((int)(size_t) avpkt->priv == CODEC_ID_NONE) {
if (stream->CodecIDRb[(stream->PacketRead + f) % VIDEO_PACKET_MAX]
== AV_CODEC_ID_NONE) {
if (f) {
Debug(3, "video: cleared upto close\n");
atomic_sub(f, &stream->PacketsFilled);
@@ -1874,30 +1891,30 @@ int VideoDecodeInput(VideoStream * stream)
// handle queued commands
//
avpkt = &stream->PacketRb[stream->PacketRead];
switch ((int)(size_t) avpkt->priv) {
case CODEC_ID_NONE:
switch (stream->CodecIDRb[stream->PacketRead]) {
case AV_CODEC_ID_NONE:
stream->ClosingStream = 0;
if (stream->LastCodecID != CODEC_ID_NONE) {
stream->LastCodecID = CODEC_ID_NONE;
if (stream->LastCodecID != AV_CODEC_ID_NONE) {
stream->LastCodecID = AV_CODEC_ID_NONE;
CodecVideoClose(stream->Decoder);
goto skip;
}
// FIXME: look if more close are in the queue
// size can be zero
goto skip;
case CODEC_ID_MPEG2VIDEO:
if (stream->LastCodecID != CODEC_ID_MPEG2VIDEO) {
stream->LastCodecID = CODEC_ID_MPEG2VIDEO;
case AV_CODEC_ID_MPEG2VIDEO:
if (stream->LastCodecID != AV_CODEC_ID_MPEG2VIDEO) {
stream->LastCodecID = AV_CODEC_ID_MPEG2VIDEO;
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder < 0
&& VdpauDecoder ? "mpegvideo_vdpau" : NULL,
CODEC_ID_MPEG2VIDEO);
AV_CODEC_ID_MPEG2VIDEO);
}
break;
case CODEC_ID_H264:
if (stream->LastCodecID != CODEC_ID_H264) {
stream->LastCodecID = CODEC_ID_H264;
case AV_CODEC_ID_H264:
if (stream->LastCodecID != AV_CODEC_ID_H264) {
stream->LastCodecID = AV_CODEC_ID_H264;
CodecVideoOpen(stream->Decoder, VideoHardwareDecoder
&& VdpauDecoder ? "h264_vdpau" : NULL, CODEC_ID_H264);
&& VdpauDecoder ? "h264_vdpau" : NULL, AV_CODEC_ID_H264);
}
break;
default:
@@ -1926,7 +1943,7 @@ int VideoDecodeInput(VideoStream * stream)
//fprintf(stderr, "]\n");
#else
// old version
if (stream->LastCodecID == CODEC_ID_MPEG2VIDEO) {
if (stream->LastCodecID == AV_CODEC_ID_MPEG2VIDEO) {
FixPacketForFFMpeg(stream->Decoder, avpkt);
} else {
CodecVideoDecode(stream->Decoder, avpkt);
@@ -1972,8 +1989,8 @@ static void StartVideo(void)
VideoOsdInit();
if (!MyVideoStream->Decoder) {
MyVideoStream->SkipStream = 1;
MyVideoStream->CodecID = CODEC_ID_NONE;
MyVideoStream->LastCodecID = CODEC_ID_NONE;
MyVideoStream->CodecID = AV_CODEC_ID_NONE;
MyVideoStream->LastCodecID = AV_CODEC_ID_NONE;
if ((MyVideoStream->HwDecoder = VideoNewHwDecoder(MyVideoStream))) {
MyVideoStream->Decoder =
@@ -2012,6 +2029,7 @@ static void StopVideo(void)
VideoPacketExit(MyVideoStream);
MyVideoStream->NewStream = 1;
MyVideoStream->InvalidPesCounter = 0;
}
#ifdef DEBUG
@@ -2133,17 +2151,26 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
Debug(3, "video: new video stream lost\n");
return 0;
}
VideoNextPacket(stream, CODEC_ID_NONE);
stream->CodecID = CODEC_ID_NONE;
VideoNextPacket(stream, AV_CODEC_ID_NONE);
stream->CodecID = AV_CODEC_ID_NONE;
stream->ClosingStream = 1;
stream->NewStream = 0;
}
// must be a PES start code
// FIXME: Valgrind-3.8.1 has a problem with this code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
if (!stream->InvalidPesCounter++) {
Error(_("[softhddev] invalid PES video packet\n"));
}
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
if (data[3] == PES_PADDING_STREAM) { // from DVD plugin
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
&& check[1] == 0x09 && !check[3] && !check[4]) {
// old PES HDTV recording z == 2 -> stronger check!
if (stream->CodecID == CODEC_ID_H264) {
#if 0
if (stream->CodecID == AV_CODEC_ID_H264) {
#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
// with some streams
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
// NAL SPS sequence parameter set
if ((check[7] & 0x1F) == 0x07) {
VideoNextPacket(CODEC_ID_H264);
VideoEnqueue(AV_NOPTS_VALUE, seq_end_h264,
VideoNextPacket(stream, AV_CODEC_ID_H264);
VideoEnqueue(stream, AV_NOPTS_VALUE, seq_end_h264,
sizeof(seq_end_h264));
}
}
#endif
VideoNextPacket(stream, CODEC_ID_H264);
VideoNextPacket(stream, AV_CODEC_ID_H264);
} else {
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)
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
if (z > 1 && check[0] == 0x01 && (!check[1] || check[1] == 0xb3)) {
if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
} else {
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
if (ValidateMpeg(data, size)) {
@@ -2246,12 +2291,12 @@ int PlayVideo3(VideoStream * stream, const uint8_t * data, int size)
return size;
}
// 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");
return size;
}
#ifdef USE_PIP
if (stream->CodecID == CODEC_ID_MPEG2VIDEO) {
if (stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
// SKIP PES header
VideoMpegEnqueue(stream, pts, data + 9 + n, size - 9 - n);
#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
// packet < 65526 is the last split packet, detect it here for
// better latency
if (size < 65526 && stream->CodecID == CODEC_ID_MPEG2VIDEO) {
if (size < 65526 && stream->CodecID == AV_CODEC_ID_MPEG2VIDEO) {
// mpeg codec supports incomplete packets
// waiting for a full complete packages, increases needed delays
VideoNextPacket(stream, CODEC_ID_MPEG2VIDEO);
VideoNextPacket(stream, AV_CODEC_ID_MPEG2VIDEO);
}
#endif
@@ -2403,13 +2448,15 @@ uint8_t *GrabImage(int *size, int jpeg, int quality, int width, int height)
int SetPlayMode(int play_mode)
{
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
Clear(); // flush all buffers
MyVideoStream->ClearClose = 0;
}
if (MyVideoStream->CodecID != CODEC_ID_NONE) {
if (MyVideoStream->CodecID != AV_CODEC_ID_NONE) {
MyVideoStream->NewStream = 1;
MyVideoStream->InvalidPesCounter = 0;
// tell hw decoder we are closing stream
VideoSetClosing(MyVideoStream->HwDecoder);
VideoResetStart(MyVideoStream->HwDecoder);
@@ -2419,7 +2466,7 @@ int SetPlayMode(int play_mode)
}
}
if (MyAudioDecoder) { // tell audio parser we have new stream
if (AudioCodecID != CODEC_ID_NONE) {
if (AudioCodecID != AV_CODEC_ID_NONE) {
NewAudioStream = 1;
}
}
@@ -2579,6 +2626,10 @@ void StillPicture(const uint8_t * data, int size)
int i;
int old_video_hardware_decoder;
// might be called in Suspended Mode
if (!MyVideoStream->Decoder || MyVideoStream->SkipStream) {
return;
}
// must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
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
if (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
Error(_("[softhddev] no codec known for still picture\n"));
}
@@ -2605,7 +2656,7 @@ void StillPicture(const uint8_t * data, int size)
#ifdef STILL_DEBUG
fprintf(stderr, "still-picture\n");
#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) {
const uint8_t *split;
int n;
@@ -2645,13 +2696,13 @@ void StillPicture(const uint8_t * data, int size)
VideoNextPacket(MyVideoStream, MyVideoStream->CodecID); // terminate last packet
} else { // ES packet
if (MyVideoStream->CodecID != CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(MyVideoStream, CODEC_ID_NONE); // close last stream
MyVideoStream->CodecID = CODEC_ID_MPEG2VIDEO;
if (MyVideoStream->CodecID != AV_CODEC_ID_MPEG2VIDEO) {
VideoNextPacket(MyVideoStream, AV_CODEC_ID_NONE); // close last stream
MyVideoStream->CodecID = AV_CODEC_ID_MPEG2VIDEO;
}
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,
sizeof(seq_end_h264));
} else {
@@ -2672,7 +2723,7 @@ void StillPicture(const uint8_t * data, int size)
#endif
if (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);
}
@@ -3122,7 +3173,7 @@ int Start(void)
AudioInit();
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
AudioCodecID = AV_CODEC_ID_NONE;
AudioChannelID = -1;
if (!ConfigStartX11Server) {
@@ -3275,7 +3326,7 @@ void Resume(void)
AudioInit();
av_new_packet(AudioAvPkt, AUDIO_BUFFER_SIZE);
MyAudioDecoder = CodecAudioNewDecoder();
AudioCodecID = CODEC_ID_NONE;
AudioCodecID = AV_CODEC_ID_NONE;
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) {
PipVideoStream->SkipStream = 1;
PipVideoStream->CodecID = CODEC_ID_NONE;
PipVideoStream->LastCodecID = CODEC_ID_NONE;
PipVideoStream->CodecID = AV_CODEC_ID_NONE;
PipVideoStream->LastCodecID = AV_CODEC_ID_NONE;
if ((PipVideoStream->HwDecoder = VideoNewHwDecoder(PipVideoStream))) {
PipVideoStream->Decoder =
@@ -3422,6 +3473,7 @@ void PipStop(void)
VideoPacketExit(PipVideoStream);
PipVideoStream->NewStream = 1;
PipVideoStream->InvalidPesCounter = 0;
#else
PipVideoStream->Close = 1;
for (i = 0; PipVideoStream->Close && i < 50; ++i) {

View File

@@ -52,7 +52,7 @@ extern "C"
/// vdr-plugin version number.
/// Makefile extracts the version number for generating the file name
/// for the distribution archive.
static const char *const VERSION = "0.6.0"
static const char *const VERSION = "0.6.1rc1"
#ifdef GIT_REV
"-GIT" GIT_REV
#endif
@@ -854,9 +854,9 @@ void cMenuSetupSoft::Create(void)
&AudioPassthroughPCM, trVDR("no"), trVDR("yes")));
Add(new cMenuEditBoolItem(tr("\040\040AC-3 pass-through"),
&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")));
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")));
Add(new cMenuEditBoolItem(tr("Volume control"), &AudioSoftvol,
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 (pes_index) {
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]);
}
if (pes_buf[0] || pes_buf[1] || pes_buf[2] != 0x01) {
// 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);
} else {
PipPlayVideo(pes_buf, pes_index);
@@ -2190,7 +2190,7 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode play_mode)
case pmVideoOnly:
break;
case pmNone:
return true;
break;
case pmExtern_THIS_SHOULD_BE_AVOIDED:
dsyslog("[softhddev] play mode external\n");
// FIXME: what if already suspended?
@@ -2512,6 +2512,9 @@ uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int width,
if (SuspendMode != NOT_SUSPENDED) {
return NULL;
}
if (quality < 0) { // caller should care, but fix it
quality = 95;
}
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"
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
>=virtual/ffmpeg-0.7[vdpau?,vaapi?]
@@ -30,6 +30,7 @@ RDEPEND=">=media-video/vdr-1.7
alsa? ( media-libs/alsa-lib )
vdpau? ( x11-libs/libvdpau )
vaapi? ( x11-libs/libva )
opengl? ( virtual/opengl )
alsa? ( media-libs/alsa-lib )
yaepg? ( >=media-video/vdr-1.7[yaepg] )"
DEPEND="${RDEPEND}
@@ -44,6 +45,7 @@ src_compile() {
myconf+=" ALSA=$(usex alsa 1 0)"
myconf+=" OSS=$(usex oss 1 0)"
myconf+=" VDPAU=$(usex vdpau 1 0)"
myconf+=" OPENGL=$(usex opengl 1 0)"
myconf+=" VAAPI=$(usex vaapi 1 0)"
myconf+=" SCREENSAVER=$(usex xscreensaver 1 0)"
if has_version ">=media-video/ffmpeg-0.8" ; then

964
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 *,
const AVFrame *);
/// Get ffmpeg vaapi context.
extern struct vaapi_context *VideoGetVaapiContext(VideoHwDecoder *);
/// Get hwaccel context for ffmpeg.
extern void *VideoGetHwAccelContext(VideoHwDecoder *);
#ifdef AVCODEC_VDPAU_H
/// Draw vdpau render state.