55 Commits
0.5.0 ... 0.5.1

Author SHA1 Message Date
Johns
583b6f246e Release Version 0.5.1 2012-07-03 16:36:53 +02:00
Johns
e6ce7832ba Add commandline support to disable hardware decoder. 2012-07-03 15:48:44 +02:00
Johns
696bb8e934 Display frame statistics in plugin menu. 2012-07-02 17:05:36 +02:00
Johns
3bb7782d40 Remove not working hotkeys from setup menu. 2012-07-02 15:20:14 +02:00
Johns
b5162bae5c Fix bug: 100% CPU use during playback. 2012-06-30 15:40:33 +02:00
Johns
d486fb2ca1 Fix bug: audio use 100% CPU during pause. 2012-06-30 00:19:36 +02:00
Johns
73d65968ae Remove video display format until it is working. 2012-06-29 15:23:17 +02:00
Johns
3be69730f0 Suggested change. 2012-06-29 15:13:38 +02:00
Johns
6f1c4d6ef6 Video_get_format AudioVideoReady feeds old PTS. 2012-06-27 21:47:30 +02:00
Johns
6aa8601f7d Guard audio skip against old PTS values. 2012-06-27 21:22:25 +02:00
Johns
0f62a521f4 Improved audio skip, after channel switch. 2012-06-25 17:30:30 +02:00
Johns
57af986367 Setup add preview of collapsed tree. 2012-06-23 16:47:04 +02:00
Johns
a2311748ca Removed gcc 4.6 warnings.
avcodec_flush_buffers crash fix.
2012-06-22 19:28:48 +02:00
Johns
2c5a14ae4a Removed gcc 4.6 warnings. Va sync experiment. 2012-06-22 19:27:15 +02:00
Johns
ed1e16dccf Removed warnings and old code. 2012-06-22 19:12:00 +02:00
Johns
da9886e9f1 Fix bug: dvd plugin times out. Readme update. 2012-06-08 15:27:42 +02:00
Johns
32527f832e Makes OSD size configurable. 2012-05-21 15:34:33 +02:00
Johns
57bbd02c57 Fix bug: Black screen is sometimes not shown. 2012-05-17 16:52:08 +02:00
Johns
940849d03f Safer 4:3 detection, 4:3 crop correction. 2012-05-17 16:50:40 +02:00
Johns
c112b850d8 Fix bug: 100% cpu use.
Fix bug: audio/video out of sync after jump in recordings.
2012-05-16 20:35:35 +02:00
Johns
752ee356fa Poll input buffers, if display buffers are full. 2012-05-13 18:33:24 +02:00
Johns
43e70b6a3f Reduce errors during suspend mode. 2012-05-13 16:58:45 +02:00
Johns
541754a619 Support display with non-square pixels. 2012-05-10 16:03:56 +02:00
Johns
3772b2160c Initial ADTS (AAC+) support. 2012-05-09 20:16:46 +02:00
Johns
465c68d839 Fix bug #959: log flooded with service messages. 2012-05-03 15:26:58 +02:00
aca508114b Adds VDR DFAtmo Plugin support. 2012-04-30 14:47:08 +02:00
Johns
49ae1c7211 Fix bug: PTS are 1/90ms and use AudioVideoDelay. 2012-04-30 13:56:26 +02:00
Johns
0cf110da81 Less logging. 2012-04-28 12:38:41 +02:00
Johns
8d5ff6f6fb Skip audio to sync with video. 2012-04-28 12:24:03 +02:00
Johns
5456164dce Mute pass-through, if volume is 0. 2012-04-27 12:31:40 +02:00
Johns
6dd7c2680a Skip audio sync while trick play. 2012-04-26 15:33:51 +02:00
Johns
3b5c1adef2 Fix bug: don't normalize or compress AC3 samples. 2012-04-24 16:02:07 +02:00
Johns
47d840bbff Force black picture after start or suspend. 2012-04-22 21:01:34 +02:00
Johns
207871fd9b Make audio ring buffer size a multiple of 3,5,7,8. 2012-04-22 17:17:54 +02:00
Johns
ebe0beb400 Add upmix from 5 to 6 channels. 2012-04-21 16:45:56 +02:00
Johns
93ddd26a4a Fix bug: alloca wrong size for audio buffer. 2012-04-21 15:47:50 +02:00
Johns
e30e1e5aad Handle jump in stream like stream start. 2012-04-21 12:59:04 +02:00
Johns
d26c34f34f Always compile audio drift correction.
Add audio drift correction configuration to the setup.
2012-04-20 18:28:25 +02:00
24a8c7f763 Add support for svdr command "stat". 2012-04-20 16:51:04 +02:00
Johns
3e39ffd5e0 New audio ring buffer code, now OSS part. 2012-04-20 16:05:40 +02:00
Johns
53f22a2ed2 Made showing black picture configurable. 2012-04-20 15:40:14 +02:00
Johns
44ca71fedb Adds audio normalize support. 2012-04-19 16:01:20 +02:00
Johns
8039e8ae04 New audio filters next part. 2012-04-19 00:47:34 +02:00
Johns
79e78bf235 Show black picture, if no video stream available.
New audio ring code.
New audio filters (first part).
2012-04-17 16:45:27 +02:00
Johns
c9ef8b759a Fix bug: autocrop toggle didn't work. 2012-04-15 23:03:40 +02:00
Johns
80db7c6656 Setup split into foldable sections. 2012-04-15 22:59:52 +02:00
Johns
3ba18d8720 Add -D option to getopt. 2012-04-15 14:46:57 +02:00
Johns
2ffcb874bb Adds show cursor on mouse move + hide after 200ms. 2012-04-14 21:58:14 +02:00
Johns
5b765f02bd Add Hot-key support for auto-crop enable/disable. 2012-04-14 21:25:44 +02:00
Johns
2c52955ac0 Adds detached start mode. 2012-04-14 21:16:01 +02:00
Johns
09d8588588 Fix buf: VDPAU looses preemption callback. 2012-04-12 15:38:22 +02:00
Johns
71f786711b Fix bug: X11 server keeps sending USR1 signals. 2012-04-12 15:37:19 +02:00
Johns
deea34eb5e Show message for hot-keys. 2012-04-11 18:20:08 +02:00
Johns
1f14af6590 Fix bug: playback errors with old PES recordings. 2012-04-11 12:16:00 +02:00
Johns
aeae505bd4 Adds Hot-key support for 4:3 zoom modes. 2012-04-11 12:15:12 +02:00
16 changed files with 3596 additions and 420 deletions

View File

@@ -1,3 +1,56 @@
User johns
Date: Tue Jul 3 16:35:46 CEST 2012
Release Version 0.5.1
Add commandline support to disable hardware decoder.
Display frame statistics in plugin menu.
Fix bug: 100% CPU use during playback.
Fix bug: audio use 100% CPU during pause.
Guard audio skip against old PTS values.
Improved audio skip, after channel switch.
Setup add preview of collapsed tree.
Fix bug: dvd plugin times out.
Makes OSD size configurable.
Support display with non-square pixels.
Initial ADTS (AAC+) support.
Fix bug #959: log flooded with service messages.
User durchflieger
Date: Mon Apr 30 14:46:51 CEST 2012
Adds VDR DFAtmo Plugin support.
User johns
Date: Mon Apr 30 13:56:26 CEST 2012
Fix bug: don't normalize or compress pass-through samples.
Make audio ring buffer size a multiple of 3,5,7,8.
Add reset ring buffer support.
Fix bug: alloca wrong size for audio buffer.
Handle jump in stream like stream start.
Always compile audio drift correction.
Add audio drift correction configuration to the setup.
User mini73
Date: Fri Apr 20 16:51:14 CEST 2012
Add support for svdr command "stat".
User johns
Date: Fri Apr 20 16:05:40 CEST 2012
Made showing black picture configurable.
Show black picture, if no video stream is available.
Setup split into foldable sections.
Adds show cursor on pointer move and hide after 200ms.
Adds Hot-key support for auto-crop enable/disable/toggle.
Adds detached start mode.
Fix bug: VDPAU looses preemption callback.
Fix bug: X11 server keeps sending USR1 signals, which confuses suspend.
Show message for hot-keys.
Fix bug: playback errors with old PES recordings.
Adds Hot-key support for 4:3 zoom modes.
User johns
Date: Sat Apr 7 20:21:16 CEST 2012

View File

@@ -19,8 +19,6 @@ GIT_REV = $(shell git describe --always 2>/dev/null)
### Configuration (edit this for your needs)
CONFIG := #-DDEBUG
#CONFIG += -DUSE_AUDIO_DRIFT_CORRECTION # build new audio drift code
#CONFIG += -DUSE_AC3_DRIFT_CORRECTION # build new ac-3 drift code
CONFIG += -DAV_INFO -DAV_INFO_TIME=3000 # debug a/v sync
#CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np
#CONFIG += -DNO_TS_AUDIO # disable ts audio parser
@@ -47,7 +45,7 @@ TMPDIR ?= /tmp
### Make sure that necessary options are included:
include $(VDRDIR)/Make.global
-include $(VDRDIR)/Make.global
### Allow user defined options to overwrite defaults:

View File

@@ -26,19 +26,19 @@ A software and GPU emulated HD output device plugin for VDR.
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
o Software deinterlacer Bob (VA-API only)
o Autocrop
o Grab image (VDPAU only)
o Suspend
o Letterbox, Stretch and Center cut-out video display modes
o atmo light support with plugin http://github.com/durchflieger/DFAtmo
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: software volume, software channel resample
o planned: atmo light support
To compile you must have the 'requires' installed.
@@ -108,12 +108,17 @@ Setup: /etc/vdr/setup.conf
------
Following is supported:
softhddevice.MakePrimary = 1
softhddevice.MakePrimary = 0
0 = no change, 1 make softhddevice primary at start
softhddevice.HideMainMenuEntry = 0
0 = show softhddevice main menu entry, 1 = hide entry
softhddevice.Osd.Width = 0
0 = auto (=display, unscaled) n = fixed osd size scaled for display
softhddevice.Osd.Height = 0
0 = auto (=display, unscaled) n = fixed osd size scaled for display
<res> of the next parameters is 576i, 720p, 1080i_fake or 1080i.
1080i_fake is 1280x1080 or 1440x1080
1080i is "real" 1920x1080
@@ -157,6 +162,29 @@ Setup: /etc/vdr/setup.conf
0 = none, 1 = downmix
downmix AC-3 to stero.
softhddevice.AudioSoftvol = 0
0 = off, use hardware volume control
1 = on, use software volume control
softhddevice.AudioNormalize = 0
0 = off, 1 = enable audio normalize
softhddevice.AudioMaxNormalize = 0
maximal volume factor/1000 of the normalize filter
softhddevice.AudioCompression = 0
0 = off, 1 = enable audio compression
softhddevice.AudioMaxCompression = 0
maximal volume factor/1000 of the compression filter
softhddevice.AudioStereoDescent = 0
reduce volume level (/1000) for stereo sources
softhddevice.AudioBufferTime = 0
0 = default (336 ms)
1 - 1000 = size of the buffer in ms
softhddevice.AutoCrop.Interval = 0
0 disables auto-crop
n each 'n' frames auto-crop is checked.
@@ -196,6 +224,10 @@ Setup: /etc/vdr/setup.conf
0 disable soft start of audio/video sync
1 enable soft start of audio/video sync
softhddevice.BlackPicture = 0
0 disable black picture during channel switch
1 enable black picture during channel switch
VideoDisplayFormat = ?
0 pan and scan
1 letter box
@@ -248,6 +280,18 @@ Keymacros:
@softhddevice Blue 1 0 disable pass-through
@softhddevice Blue 1 1 enable pass-through
@softhddevice Blue 1 2 toggle pass-through
@softhddevice Blue 1 3 decrease audio delay by 10ms
@softhddevice Blue 1 4 increase audio delay by 10ms
@softhddevice Blue 2 0 disable fullscreen
@softhddevice Blue 2 1 enable fullscreen
@softhddevice Blue 2 2 toggle fullscreen
@softhddevice Blue 2 3 disable auto-crop
@softhddevice Blue 2 4 enable auto-crop
@softhddevice Blue 2 5 toggle auto-crop
@softhddevice Blue 3 0 stretch 4:3 to 16:9
@softhddevice Blue 3 1 letter box 4:3 in 16:9
@softhddevice Blue 3 2 center cut-out 4:3 to 16:9
@softhddevice Blue 3 9 rotate 4:3 to 16:9 zoom mode
Running:
--------
@@ -259,6 +303,11 @@ Warning:
--------
libav is not supported, expect many bugs with it.
Known Bugs:
-----------
VA-API doesn't v-sync 1080i streams
vdr-image not working
Requires:
---------
media-video/ffmpeg (version >=0.7)

9
Todo
View File

@@ -37,6 +37,8 @@ video:
radio no need to wait on video buffers
starting with radio and own X11 server, shows no video
some low-bandwidth tv channels have hiccups.
check start with 24Hz display rate
crash with ffmpeg without vaapi and vdpau.
vdpau:
software decoder path not working
@@ -73,10 +75,8 @@ x11:
support embedded mode
audio:
Combine alsa+oss ringbuffer code.
Make alsa thread/polled and oss thread/polled output module runtime
selectable.
software volume support (could be done with asound.conf)
Mute should do a real mute and not only set volume to zero.
Starting suspended and muted, didn't register the mute.
Relaxed audio sync checks at end of packet and already in sync
@@ -84,12 +84,10 @@ audio:
only wait for video start, if video is running.
Not primary device, don't use and block audio/video.
multiple open of audio device, reduce them.
Not all channel conversions are written (f.e. 2->3 ... 5->6 ...)
audio/alsa:
better downmix of >2 channels on 2 channel hardware
remix support of unsupported sample rates
libav supports only resample of mono to 2 channels
ffmpeg didn't support resample of 5 to 2 channels
audio/oss:
alsa oss emulation mixer "pcm" not working
@@ -124,7 +122,6 @@ future features (not planed for 1.0 - 1.5)
video out with opengl
video out with xvba
software decoder for xv / opengl
atmolight support
multistream handling
pip support
save and use auto-crop with channel zapping

2075
audio.c

File diff suppressed because it is too large Load Diff

View File

@@ -42,6 +42,10 @@ extern void AudioPlay(void); ///< play audio
extern void AudioPause(void); ///< pause audio
extern void AudioSetBufferTime(int); ///< set audio buffer time
extern void AudioSetSoftvol(int); ///< enable/disable softvol
extern void AudioSetNormalize(int, int); ///< set normalize parameters
extern void AudioSetCompression(int, int); ///< set compression parameters
extern void AudioSetStereoDescent(int); ///< set stereo loudness descent
extern void AudioSetDevice(const char *); ///< set PCM audio device
extern void AudioSetDeviceAC3(const char *); ///< set pass-through device

67
codec.c
View File

@@ -33,7 +33,9 @@
/// compile with passthrough support (stable, ac3 only)
#define USE_PASSTHROUGH
/// compile audio drift correction support (experimental)
#define noUSE_AUDIO_DRIFT_CORRECTION
#define USE_AUDIO_DRIFT_CORRECTION
/// compile AC3 audio drift correction support (experimental)
#define USE_AC3_DRIFT_CORRECTION
#include <stdio.h>
#include <unistd.h>
@@ -583,7 +585,9 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
*/
void CodecVideoFlushBuffers(VideoDecoder * decoder)
{
avcodec_flush_buffers(decoder->VideoCtx);
if (decoder->VideoCtx) {
avcodec_flush_buffers(decoder->VideoCtx);
}
}
//----------------------------------------------------------------------------
@@ -631,6 +635,11 @@ struct _audio_decoder_
int RemainCount; ///< number of remaining samples
};
#ifdef USE_AUDIO_DRIFT_CORRECTION
static char CodecAudioDrift; ///< flag: enable audio-drift correction
#else
static const int CodecAudioDrift = 0;
#endif
#ifdef USE_PASSTHROUGH
//static char CodecPassthroughPCM; ///< pass pcm through (unsupported)
static char CodecPassthroughAC3; ///< pass ac3 through
@@ -773,8 +782,23 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
}
}
/**
** Set audio drift correction.
**
** @param mask enable mask (PCM, AC3)
*/
void CodecSetAudioDrift(int mask)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
CodecAudioDrift = mask & 3;
#endif
(void)mask;
}
/**
** Set audio pass-through.
**
** @param mask enable mask (PCM, AC3)
*/
void CodecSetAudioPassthrough(int mask)
{
@@ -791,6 +815,10 @@ void CodecSetAudioPassthrough(int mask)
*/
void CodecSetAudioDownmix(int onoff)
{
if (onoff == -1) {
CodecDownmix ^= 1;
return;
}
CodecDownmix = onoff;
}
@@ -882,7 +910,7 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->LastDelay = delay;
audio_decoder->Drift = 0;
audio_decoder->DriftFrac = 0;
Debug(3, "codec/audio: inital delay %zd ms\n", delay / 90);
Debug(3, "codec/audio: inital delay %" PRId64 "ms\n", delay / 90);
return;
}
// collect over some time
@@ -906,9 +934,10 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
audio_decoder->LastDelay = delay;
if (0) {
Debug(3, "codec/audio: interval P:%5zdms T:%5zdms D:%4zdms %f %d\n",
pts_diff / 90, tim_diff / (1000 * 1000), delay / 90, drift / 90.0,
audio_decoder->DriftCorr);
Debug(3,
"codec/audio: interval P:%5zdms T:%5" PRId64 "ms D:%4" PRId64
"ms %f %d\n", pts_diff / 90, tim_diff / (1000 * 1000), delay / 90,
drift / 90.0, audio_decoder->DriftCorr);
}
// underruns and av_resample have the same time :(((
if (abs(drift) > 10 * 90) {
@@ -916,17 +945,17 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
Debug(3, "codec/audio: drift(%6d) %3dms reset\n",
audio_decoder->DriftCorr, drift / 90);
audio_decoder->LastDelay = 0;
#ifdef DEBUG
corr = 0; // keep gcc happy
#endif
} else {
drift += audio_decoder->Drift;
audio_decoder->Drift = drift;
corr = (10 * audio_decoder->HwSampleRate * drift) / (90 * 1000);
#if defined(USE_PASSTHROUGH) && !defined(USE_AC3_DRIFT_CORRECTION)
// SPDIF/HDMI passthrough
if (!CodecPassthroughAC3
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)
#endif
{
if ((CodecAudioDrift & 2) && (!CodecPassthroughAC3
|| audio_decoder->AudioCtx->codec_id != CODEC_ID_AC3)) {
audio_decoder->DriftCorr = -corr;
}
@@ -949,8 +978,14 @@ static void CodecAudioSetClock(AudioDecoder * audio_decoder, int64_t pts)
av_resample_compensate(audio_decoder->AvResample,
audio_decoder->DriftCorr / 10, distance);
}
Debug(3, "codec/audio: drift(%6d) %8dus %5d\n", audio_decoder->DriftCorr,
drift * 1000 / 90, corr);
if (1) {
static int c;
if (!(c++ % 10)) {
Debug(3, "codec/audio: drift(%6d) %8dus %5d\n",
audio_decoder->DriftCorr, drift * 1000 / 90, corr);
}
}
}
/**
@@ -1025,7 +1060,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
}
// prepare audio drift resample
#ifdef USE_AUDIO_DRIFT_CORRECTION
if (!isAC3) {
if ((CodecAudioDrift & 1) && !isAC3) {
if (audio_decoder->AvResample) {
Error(_("codec/audio: overwrite resample\n"));
}
@@ -1056,7 +1091,7 @@ static void CodecAudioUpdateFormat(AudioDecoder * audio_decoder)
void CodecAudioEnqueue(AudioDecoder * audio_decoder, int16_t * data, int count)
{
#ifdef USE_AUDIO_DRIFT_CORRECTION
if (audio_decoder->AvResample) {
if ((CodecAudioDrift & 1) && audio_decoder->AvResample) {
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
int16_t buftmp[MAX_CHANNELS][(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4];
@@ -1211,7 +1246,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
buf_sz = 6144;
#ifdef USE_AC3_DRIFT_CORRECTION
if (1) {
if (CodecAudioDrift & 2) {
int x;
x = (audio_decoder->DriftFrac +

10
codec.h
View File

@@ -67,8 +67,14 @@ extern void CodecAudioOpen(AudioDecoder *, const char *, int);
/// Close audio codec.
extern void CodecAudioClose(AudioDecoder *);
/// Decode an audio packet.
extern void CodecAudioDecodeOld(AudioDecoder *, const AVPacket *);
/// Set audio drift correction.
extern void CodecSetAudioDrift(int);
/// Set audio pass-through.
extern void CodecSetAudioPassthrough(int);
/// Set audio downmix.
extern void CodecSetAudioDownmix(int);
/// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);

View File

@@ -48,6 +48,18 @@ struct _ring_buffer_
atomic_t Filled; ///< how many of the buffer is used
};
/**
** Reset ring buffer pointers.
**
** @param rb Ring buffer to reset read/write pointers.
*/
void RingBufferReset(RingBuffer * rb)
{
rb->ReadPointer = rb->Buffer;
rb->WritePointer = rb->Buffer;
atomic_set(&rb->Filled, 0);
}
/**
** Allocate a new ring buffer.
**
@@ -69,10 +81,8 @@ RingBuffer *RingBufferNew(size_t size)
}
rb->Size = size;
rb->ReadPointer = rb->Buffer;
rb->WritePointer = rb->Buffer;
rb->BufferEnd = rb->Buffer + size;
atomic_set(&rb->Filled, 0);
RingBufferReset(rb);
return rb;
}
@@ -89,7 +99,7 @@ void RingBufferDel(RingBuffer * rb)
/**
** Advance write pointer in ring buffer.
**
** @param rb Ring buffer to adance write pointer.
** @param rb Ring buffer to advance write pointer.
** @param cnt Number of bytes to be adavanced.
**
** @returns Number of bytes that could be advanced in ring buffer.
@@ -198,7 +208,7 @@ size_t RingBufferGetWritePointer(RingBuffer * rb, void **wp)
/**
** Advance read pointer in ring buffer.
**
** @param rb Ring buffer to adance read pointer.
** @param rb Ring buffer to advance read pointer.
** @param cnt Number of bytes to be advanced.
**
** @returns Number of bytes that could be advanced in ring buffer.

View File

@@ -23,13 +23,16 @@
/// @addtogroup Ringbuffer
/// @{
///< ring buffer typedef
/// ring buffer typedef
typedef struct _ring_buffer_ RingBuffer;
///< create new ring buffer
/// reset ring buffer pointers
extern void RingBufferReset(RingBuffer *);
/// create new ring buffer
extern RingBuffer *RingBufferNew(size_t);
///< free ring buffer
/// free ring buffer
extern void RingBufferDel(RingBuffer *);
/// write into ring buffer

View File

@@ -61,6 +61,7 @@ static char ConfigVdpauDecoder = 1; ///< use vdpau decoder, if possible
#define ConfigVdpauDecoder 0 ///< no vdpau decoder configured
#endif
extern int ConfigAudioBufferTime; ///< config size ms of audio buffer
static char ConfigStartSuspended; ///< flag to start in suspend mode
static char ConfigFullscreen; ///< fullscreen modus
static char ConfigStartX11Server; ///< flag start the x11 server
@@ -347,8 +348,8 @@ static int Ac3Check(const uint8_t * data, int size)
frmsizcod = data[4] & 0x3F; // invalid is checked by fast
frame_size = Ac3FrameSizeTable[frmsizcod][fscod] * 2;
if (frame_size + 2 > size) {
return -frame_size - 2;
if (frame_size + 5 > size) {
return -frame_size - 5;
}
// check if after this frame a new AC-3 frame starts
if (FastAc3Check(data + frame_size)) {
@@ -358,6 +359,71 @@ static int Ac3Check(const uint8_t * data, int size)
return 0;
}
///
/// Fast check for ADTS Audio Data Transport Stream.
///
/// 7/9 bytes 0xFFFxxxxxxxxxxx(xxxx) ADTS audio
///
static inline int FastAdtsCheck(const uint8_t * p)
{
if (p[0] != 0xFF) { // 12bit sync
return 0;
}
if ((p[1] & 0xF6) != 0xF0) { // sync + layer must be 0
return 0;
}
if ((p[2] & 0x3C) == 0x3C) { // sampling frequency index != 15
return 0;
}
return 1;
}
///
/// Check for ADTS Audio Data Transport Stream.
///
/// 0xFFF already checked.
///
/// @param data incomplete PES packet
/// @param size number of bytes
///
/// @retval <0 possible ADTS audio, but need more data
/// @retval 0 no valid ADTS audio
/// @retval >0 valid AC-3 audio
///
/// AAAAAAAA AAAABCCD EEFFFFGH HHIJKLMM MMMMMMMM MMMOOOOO OOOOOOPP
/// (QQQQQQQQ QQQQQQQ)
///
/// o A*12 syncword 0xFFF
/// o B*1 MPEG Version: 0 for MPEG-4, 1 for MPEG-2
/// o C*2 layer: always 0
/// o ..
/// o F*4 sampling frequency index (15 is invalid)
/// o ..
/// o M*13 frame length
///
static int AdtsCheck(const uint8_t * data, int size)
{
int frame_size;
if (size < 6) {
return -6;
}
frame_size = (data[3] & 0x03) << 11;
frame_size |= (data[4] & 0xFF) << 3;
frame_size |= (data[5] & 0xE0) >> 5;
if (frame_size + 3 > size) {
return -frame_size - 3;
}
// check if after this frame a new ADTS frame starts
if (FastAdtsCheck(data + frame_size)) {
return frame_size;
}
return 0;
}
#ifndef NO_TS_AUDIO
//////////////////////////////////////////////////////////////////////////////
@@ -540,11 +606,13 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
unsigned codec_id;
// 4 bytes 0xFFExxxxx Mpeg audio
// 3 bytes 0x56Exxx AAC LATM audio
// 5 bytes 0x0B77xxxxxx AC3 audio
// 3 bytes 0x56Exxx AAC LATM audio
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found
// FIXME: simple+faster detection, if codec already known
r = 0;
if (FastMpegCheck(q)) {
if (!r && FastMpegCheck(q)) {
r = MpegCheck(q, n);
codec_id = CODEC_ID_MP2;
}
@@ -556,6 +624,10 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
r = LatmCheck(q, n);
codec_id = CODEC_ID_AAC_LATM;
}
if (!r && FastAdtsCheck(q)) {
r = AdtsCheck(q, n);
codec_id = CODEC_ID_AAC;
}
if (r < 0) { // need more bytes
break;
}
@@ -583,6 +655,12 @@ static void PesParse(PesDemux * pesdx, const uint8_t * data, int size,
//pesdx->State = PES_MPEG_DECODE;
break;
}
if (AudioCodecID != CODEC_ID_NONE) {
// shouldn't happen after we have a vaild codec
// detected
Debug(4, "pesdemux: skip @%d %02x\n", pesdx->Skip,
q[0]);
}
// try next byte
++pesdx->Skip;
++q;
@@ -802,7 +880,9 @@ static int TsDemuxer(TsDemux * tsdx, const uint8_t * data, int size)
p = data;
while (size >= TS_PACKET_SIZE) {
#ifdef DEBUG
int pid;
#endif
int payload;
if (p[0] != TS_PACKET_SYNC) {
@@ -816,11 +896,11 @@ static int TsDemuxer(TsDemux * tsdx, const uint8_t * data, int size)
// FIXME: kill all buffers
goto next_packet;
}
#ifdef DEBUG
pid = (p[1] & 0x1F) << 8 | p[2];
Debug(4, "tsdemux: PID: %#04x%s%s\n", pid, p[1] & 0x40 ? " start" : "",
p[3] & 0x10 ? " payload" : "");
#endif
// skip adaptation field
switch (p[3] & 0x30) { // adaption field
case 0x00: // reserved
@@ -887,7 +967,8 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
if (NewAudioStream) {
// this clears the audio ringbuffer indirect, open and setup does it
CodecAudioClose(MyAudioDecoder);
AudioSetBufferTime(0);
AudioFlushBuffers();
AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1;
NewAudioStream = 0;
@@ -972,6 +1053,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
samplerate = samplerates[p[5] >> 4];
channels = (p[5] & 0x7) + 1;
// FIXME: ConfigAudioBufferTime + x
AudioSetBufferTime(400);
AudioSetup(&samplerate, &channels, 0);
if (samplerate != samplerates[p[5] >> 4]) {
@@ -1002,6 +1084,7 @@ int PlayAudio(const uint8_t * data, int size, uint8_t id)
p += 4;
n -= 4; // skip track header
if (AudioCodecID == CODEC_ID_NONE) {
// FIXME: ConfigAudioBufferTime + x
AudioSetBufferTime(400);
}
}
@@ -1018,6 +1101,7 @@ 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
// 7/9 bytes 0xFFFxxxxxxxxxxx ADTS audio
// PCM audio can't be found
r = 0;
codec_id = CODEC_ID_NONE; // keep compiler happy
@@ -1038,6 +1122,10 @@ 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;
}
if (r < 0) { // need more bytes
break;
}
@@ -1100,8 +1188,9 @@ int PlayTsAudio(const uint8_t * data, int size)
if (NewAudioStream) {
// this clears the audio ringbuffer indirect, open and setup does it
CodecAudioClose(MyAudioDecoder);
AudioFlushBuffers();
// max time between audio packets 200ms + 24ms hw buffer
AudioSetBufferTime(264);
AudioSetBufferTime(ConfigAudioBufferTime);
AudioCodecID = CODEC_ID_NONE;
AudioChannelID = -1;
NewAudioStream = 0;
@@ -1128,7 +1217,7 @@ int PlayTsAudio(const uint8_t * data, int size)
*/
void SetVolumeDevice(int volume)
{
AudioSetVolume((volume * 100) / 255);
AudioSetVolume((volume * 1000) / 255);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1347,6 +1436,29 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
CodecVideoDecode(MyVideoDecoder, tmp);
}
/**
** Poll PES packet ringbuffer.
**
** Called if video frame buffers are full.
*/
int VideoPollInput(void)
{
if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
VideoResetStart(MyHwDecoder);
}
VideoClearBuffers = 0;
return 1;
}
if (!atomic_read(&VideoPacketsFilled)) {
return -1;
}
return 1;
}
/**
** Decode from PES packet ringbuffer.
**
@@ -1354,25 +1466,27 @@ void FixPacketForFFMpeg(VideoDecoder * MyVideoDecoder, AVPacket * avpkt)
** @retval 1 stream paused
** @retval -1 empty stream
*/
int VideoDecode(void)
int VideoDecodeInput(void)
{
int filled;
AVPacket *avpkt;
int saved_size;
static int last_codec_id = CODEC_ID_NONE;
if (StreamFreezed) { // stream freezed
return 1;
}
if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
VideoResetStart(MyHwDecoder);
}
VideoClearBuffers = 0;
return 1;
}
if (StreamFreezed) { // stream freezed
// clear is called during freezed
return 1;
}
filled = atomic_read(&VideoPacketsFilled);
if (!filled) {
@@ -1438,33 +1552,6 @@ int VideoDecode(void)
avpkt->size = avpkt->stream_index;
avpkt->stream_index = 0;
if (0) {
static int done;
if (done < 2) {
int fildes;
int who_designed_this_is____;
if (done == 0)
fildes =
open("frame0.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
else if (done == 1)
fildes =
open("frame1.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
else
fildes =
open("frame2.pes", O_WRONLY | O_TRUNC | O_CREAT, 0666);
done++;
who_designed_this_is____ = write(fildes, avpkt->data, avpkt->size);
close(fildes);
}
}
if (ClosingVideoStream) { // closing don't sync
avpkt->pts = AV_NOPTS_VALUE;
avpkt->dts = AV_NOPTS_VALUE;
}
if (last_codec_id == CODEC_ID_MPEG2VIDEO) {
FixPacketForFFMpeg(MyVideoDecoder, avpkt);
} else {
@@ -1638,8 +1725,6 @@ int PlayVideo(const uint8_t * data, int size)
}
VideoNextPacket(CODEC_ID_NONE);
VideoCodecID = CODEC_ID_NONE;
// clear clock until new stream starts
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
ClosingVideoStream = 1;
NewVideoStream = 0;
}
@@ -1732,8 +1817,8 @@ int PlayVideo(const uint8_t * data, int size)
Debug(3, "softhddev/video: invalid mpeg2 video packet\n");
}
#endif
// SKIP PES header
VideoEnqueue(pts, check - 2, l + 2);
// SKIP PES header, begin of start code
VideoEnqueue(pts, check - z, l + z);
return size;
}
// this happens when vdr sends incomplete packets
@@ -1856,6 +1941,9 @@ int SetPlayMode(int play_mode)
if (MyVideoDecoder) { // tell video parser we have new stream
if (VideoCodecID != CODEC_ID_NONE) {
NewVideoStream = 1;
// tell hw decoder we are closing stream
VideoSetClosing(MyHwDecoder);
VideoResetStart(MyHwDecoder);
#ifdef DEBUG
VideoSwitch = GetMsTicks();
#endif
@@ -1871,11 +1959,9 @@ int SetPlayMode(int play_mode)
break;
case 2: // audio only
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
break;
case 3: // audio only, black screen
Debug(3, "softhddev: FIXME: audio only, silence video errors\n");
VideoSetClock(MyHwDecoder, AV_NOPTS_VALUE);
break;
case 4: // video only
break;
@@ -1927,16 +2013,21 @@ void Clear(void)
int i;
VideoResetPacket(); // terminate work
//closing not reset:
//VideoSetClosing(MyHwDecoder);
VideoResetStart(MyHwDecoder);
VideoClearBuffers = 1;
AudioFlushBuffers();
//NewAudioStream = 1;
// FIXME: audio avcodec_flush_buffers, video is done by VideoClearBuffers
// wait for empty buffers
// FIXME: without softstart sync VideoDecode isn't called.
for (i = 0; VideoClearBuffers && i < 20; ++i) {
usleep(1 * 1000);
}
Debug(3, "[softhddev]%s: buffers %d\n", __FUNCTION__, VideoGetBuffers());
Debug(3, "[softhddev]%s: %dms buffers %d\n", __FUNCTION__, i,
VideoGetBuffers());
}
/**
@@ -2090,10 +2181,15 @@ int Poll(int timeout)
#else
int full;
int t;
int used;
int filled;
// one buffer is full
full = AudioFreeBytes() >= AUDIO_MIN_BUFFER_FREE
|| atomic_read(&VideoPacketsFilled) < VIDEO_PACKET_MAX - 3;
used = AudioUsedBytes();
filled = atomic_read(&VideoPacketsFilled);
// soft limit + hard limit
full = (used > AUDIO_MIN_BUFFER_FREE && filled > 3)
|| AudioFreeBytes() < AUDIO_MIN_BUFFER_FREE
|| filled >= VIDEO_PACKET_MAX - 3;
if (!full || !timeout) {
return !full;
@@ -2198,7 +2294,8 @@ const char *CommandLineHelp(void)
"\tno-hw-decoder\t\tdisable hw decoder, use software decoder only\n"
"\tno-mpeg-hw-decoder\tdisable hw decoder for mpeg only\n"
"\talsa-driver-broken\tdisable broken alsa driver message\n"
"\tignore-repeat-pict\tdisable repeat pict message\n";
"\tignore-repeat-pict\tdisable repeat pict message\n"
" -D\t\tstart in detached mode\n";
}
/**
@@ -2213,7 +2310,7 @@ int ProcessArgs(int argc, char *const argv[])
// Parse arguments.
//
for (;;) {
switch (getopt(argc, argv, "-a:c:d:fg:p:sv:w:x")) {
switch (getopt(argc, argv, "-a:c:d:fg:p:sv:w:xD")) {
case 'a': // audio device for pcm
AudioSetDevice(optarg);
continue;
@@ -2250,9 +2347,14 @@ int ProcessArgs(int argc, char *const argv[])
case 's': // start in suspend mode
ConfigStartSuspended = 1;
continue;
case 'D': // start in detached mode
ConfigStartSuspended = -1;
continue;
case 'w': // workarounds
if (!strcasecmp("no-hw-decoder", optarg)) {
VideoHardwareDecoder = 0;
} else if (!strcasecmp("no-mpeg-hw-decoder", optarg)) {
VideoHardwareDecoder = 1;
} else if (!strcasecmp("alsa-driver-broken", optarg)) {
AudioAlsaDriverBroken = 1;
} else if (!strcasecmp("ignore-repeat-pict", optarg)) {
@@ -2333,6 +2435,8 @@ static void StartXServer(void)
argn = 1;
if (X11DisplayName) { // append display name
args[argn++] = X11DisplayName;
// export display for childs
setenv("DISPLAY", X11DisplayName, 1);
}
// split X server arguments string into words
if ((sval = X11ServerArguments)) {
@@ -2370,10 +2474,12 @@ static void StartXServer(void)
}
// child
signal(SIGUSR1, SIG_IGN); // ignore to force answer
//setpgid(0,getpid());
// start the X server
execvp(args[0], (char *const *)args);
Error(_("x-setup: Failed to start X server '%s'\n"), args[0]);
exit(-1);
}
/**
@@ -2436,6 +2542,10 @@ void SoftHdDeviceExit(void)
/**
** Prepare plugin.
**
** @retval 0 normal start
** @retval 1 suspended start
** @retval -1 detached start
*/
int Start(void)
{
@@ -2465,9 +2575,11 @@ int Start(void)
#ifndef NO_TS_AUDIO
PesInit(PesDemuxAudio);
#endif
Info(_("[softhddev] ready%s\n"), ConfigStartSuspended ? " suspended" : "");
Info(_("[softhddev] ready%s\n"),
ConfigStartSuspended ? ConfigStartSuspended ==
-1 ? "detached" : " suspended" : "");
return !ConfigStartSuspended;
return ConfigStartSuspended;
}
/**
@@ -2495,6 +2607,8 @@ void Housekeeping(void)
void MainThreadHook(void)
{
if (Usr1Signal) { // x11 server ready
// FIYME: x11 server keeps sending sigusr1 signals
signal(SIGUSR1, SIG_IGN); // ignore further signals
Usr1Signal = 0;
StartVideo();
VideoDisplayWakeup();
@@ -2577,3 +2691,22 @@ void Resume(void)
pthread_mutex_unlock(&SuspendLockMutex);
}
/*
** Get decoder statistics.
**
** @param[out] missed missed frames
** @param[out] duped duped frames
** @param[out] dropped dropped frames
** @param[out] count number of decoded frames
*/
void GetStats(int *missed, int *duped, int *dropped, int *counter)
{
*missed = 0;
*duped = 0;
*dropped = 0;
*counter = 0;
if (MyHwDecoder) {
VideoGetStats(MyHwDecoder, missed, duped, dropped, counter);
}
}

View File

@@ -90,6 +90,9 @@ extern "C"
extern void Suspend(int, int, int);
/// Resume plugin
extern void Resume(void);
/// Get decoder statistics
extern void GetStats(int *, int *, int *, int *);
#ifdef __cplusplus
}
#endif

File diff suppressed because it is too large Load Diff

44
softhddevice_service.h Normal file
View File

@@ -0,0 +1,44 @@
///
/// @file softhddev_service.h @brief software HD device service header file.
///
/// Copyright (c) 2012 by durchflieger. All Rights Reserved.
///
/// Contributor(s):
///
/// License: AGPLv3
///
/// This program is free software: you can redistribute it and/or modify
/// it under the terms of the GNU Affero General Public License as
/// published by the Free Software Foundation, either version 3 of the
/// License.
///
/// This program is distributed in the hope that it will be useful,
/// but WITHOUT ANY WARRANTY; without even the implied warranty of
/// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
/// GNU Affero General Public License for more details.
///
/// $Id$
//////////////////////////////////////////////////////////////////////////////
#pragma once
#define ATMO_GRAB_SERVICE "SoftHDDevice-AtmoGrabService-v1.0"
enum
{ GRAB_IMG_RGBA_FORMAT_B8G8R8A8 };
typedef struct
{
int structSize;
// request data
int analyseSize;
int clippedOverscan;
// reply data
int imgType;
int imgSize;
int width;
int height;
void *img;
} SoftHDDevice_AtmoGrabService_v1_0_t;

607
video.c

File diff suppressed because it is too large Load Diff

23
video.h
View File

@@ -34,6 +34,7 @@ typedef struct _video_hw_decoder_ VideoHwDecoder;
// Variables
//----------------------------------------------------------------------------
extern char VideoHardwareDecoder; ///< flag use hardware decoder
extern char VideoIgnoreRepeatPict; ///< disable repeat pict warning
extern int VideoAudioDelay; ///< audio/video delay
@@ -90,6 +91,9 @@ extern void VideoSet60HzMode(int);
/// Set soft start audio/video sync.
extern void VideoSetSoftStartSync(int);
/// Set show black picture during channel switch.
extern void VideoSetBlackPicture(int);
/// Set video output position.
extern void VideoSetOutputPosition(int, int, int, int);
@@ -147,26 +151,41 @@ extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
/// Get OSD size.
extern void VideoGetOsdSize(int *, int *);
/// Set OSD size.
extern void VideoSetOsdSize(int, int);
/// Set video clock.
extern void VideoSetClock(VideoHwDecoder *, int64_t);
/// Get video clock.
extern int64_t VideoGetClock(const VideoHwDecoder *);
/// Set closing flag.
extern void VideoSetClosing(VideoHwDecoder *);
/// Reset start of frame counter
extern void VideoResetStart(VideoHwDecoder *);
/// Set trick play speed.
extern void VideoSetTrickSpeed(VideoHwDecoder *, int);
/// Grab screen.
extern uint8_t *VideoGrab(int *, int *, int *, int);
/// Grab screen raw.
extern uint8_t *VideoGrabService(int *, int *, int *);
/// Get decoder statistics.
extern void VideoGetStats(VideoHwDecoder *, int *, int *, int *, int *);
extern void VideoOsdInit(void); ///< Setup osd.
extern void VideoOsdExit(void); ///< Cleanup osd.
extern void VideoInit(const char *); ///< Setup video module.
extern void VideoExit(void); ///< Cleanup and exit video module.
extern void VideoFlushInput(void); ///< Flush video input buffers.
extern int VideoDecode(void); ///< Decode video input buffers.
extern int VideoPollInput(void); ///< Poll video input buffers.
extern int VideoDecodeInput(void); ///< Decode video input buffers.
extern int VideoGetBuffers(void); ///< Get number of input buffers.
/// @}