mirror of
https://projects.vdr-developer.org/git/vdr-plugin-softhddevice.git
synced 2023-10-10 19:16:51 +02:00
New audio PES handling.
New easier and more flexible audio PES packet parser, which includes own codec parser. Removed av_parser use. Reduced audio buffer time, faster channel switch. New audio transport stream parser (not enabled as default).
This commit is contained in:
parent
1f232db5b4
commit
5d8dea1b6b
@ -1,6 +1,7 @@
|
|||||||
User johns
|
User johns
|
||||||
Date:
|
Date:
|
||||||
|
|
||||||
|
New audio PES packet parser.
|
||||||
Fix bug: Grabbing a JPG image fails while suspended.
|
Fix bug: Grabbing a JPG image fails while suspended.
|
||||||
Add support for hot keys.
|
Add support for hot keys.
|
||||||
Add support to use characters input in edit mode.
|
Add support to use characters input in edit mode.
|
||||||
|
9
Makefile
9
Makefile
@ -19,8 +19,9 @@ GIT_REV = $(shell git describe --always 2>/dev/null)
|
|||||||
### Configuration (edit this for your needs)
|
### Configuration (edit this for your needs)
|
||||||
|
|
||||||
CONFIG := #-DDEBUG
|
CONFIG := #-DDEBUG
|
||||||
CONFIG += -DAV_INFO
|
CONFIG += -DAV_INFO # debug a/v sync
|
||||||
#CONFIG += -DHAVE_PTHREAD_NAME
|
#CONFIG += -DHAVE_PTHREAD_NAME # supports new pthread_setname_np
|
||||||
|
#CONFIG += -DUSE_TS_AUDIO # build new ts audio parser
|
||||||
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
|
CONFIG += $(shell pkg-config --exists vdpau && echo "-DUSE_VDPAU")
|
||||||
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
|
CONFIG += $(shell pkg-config --exists libva && echo "-DUSE_VAAPI")
|
||||||
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
|
CONFIG += $(shell pkg-config --exists alsa && echo "-DUSE_ALSA")
|
||||||
@ -66,7 +67,7 @@ DEFINES += $(CONFIG) -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' \
|
|||||||
$(if $(GIT_REV), -DGIT_REV='"$(GIT_REV)"')
|
$(if $(GIT_REV), -DGIT_REV='"$(GIT_REV)"')
|
||||||
|
|
||||||
_CFLAGS = $(DEFINES) $(INCLUDES) \
|
_CFLAGS = $(DEFINES) $(INCLUDES) \
|
||||||
$(shell pkg-config --cflags libavcodec libavformat) \
|
$(shell pkg-config --cflags libavcodec) \
|
||||||
`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
`pkg-config --cflags x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
||||||
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
||||||
`pkg-config --cflags gl glu` \
|
`pkg-config --cflags gl glu` \
|
||||||
@ -82,7 +83,7 @@ override CXXFLAGS += $(_CFLAGS)
|
|||||||
override CFLAGS += $(_CFLAGS)
|
override CFLAGS += $(_CFLAGS)
|
||||||
|
|
||||||
LIBS += -lrt \
|
LIBS += -lrt \
|
||||||
$(shell pkg-config --libs libavcodec libavformat) \
|
$(shell pkg-config --libs libavcodec) \
|
||||||
`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
`pkg-config --libs x11 x11-xcb xcb xcb-xv xcb-shm xcb-dpms xcb-atom\
|
||||||
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
|
||||||
`pkg-config --libs gl glu` \
|
`pkg-config --libs gl glu` \
|
||||||
|
9
Todo
9
Todo
@ -26,6 +26,8 @@ missing:
|
|||||||
Option deinterlace off / deinterlace force!
|
Option deinterlace off / deinterlace force!
|
||||||
ColorSpace aren't configurable with the gui.
|
ColorSpace aren't configurable with the gui.
|
||||||
Inverse telecine isn't configurable with the gui.
|
Inverse telecine isn't configurable with the gui.
|
||||||
|
Replay of old vdr 1.6 recordings.
|
||||||
|
svdrp support for hot-keys.
|
||||||
|
|
||||||
crash:
|
crash:
|
||||||
AudioPlayHandlerThread -> pthread_cond_wait
|
AudioPlayHandlerThread -> pthread_cond_wait
|
||||||
@ -99,8 +101,11 @@ HDMI/SPDIF Passthrough:
|
|||||||
only AC-3 written
|
only AC-3 written
|
||||||
|
|
||||||
playback of recording
|
playback of recording
|
||||||
pause is not reset, when replay exit
|
pause is not reset, when replay exit (fixed?)
|
||||||
replay/pause need 100% cpu
|
replay/pause need 100% cpu (fixed?)
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
mp3 plugin needs 100% cpu (OSD updates?)
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
Setup of decoder type.
|
Setup of decoder type.
|
||||||
|
101
audio.c
101
audio.c
@ -141,7 +141,7 @@ static unsigned AudioSampleRate; ///< audio sample rate in hz
|
|||||||
static unsigned AudioChannels; ///< number of audio channels
|
static unsigned AudioChannels; ///< number of audio channels
|
||||||
static const int AudioBytesProSample = 2; ///< number of bytes per sample
|
static const int AudioBytesProSample = 2; ///< number of bytes per sample
|
||||||
static int64_t AudioPTS; ///< audio pts clock
|
static int64_t AudioPTS; ///< audio pts clock
|
||||||
static const int AudioBufferTime = 350; ///< audio buffer time in ms
|
static int AudioBufferTime = 216; ///< audio buffer time in ms
|
||||||
|
|
||||||
#ifdef USE_AUDIO_THREAD
|
#ifdef USE_AUDIO_THREAD
|
||||||
static pthread_t AudioThread; ///< audio play thread
|
static pthread_t AudioThread; ///< audio play thread
|
||||||
@ -151,7 +151,8 @@ static pthread_cond_t AudioStartCond; ///< condition variable
|
|||||||
static const int AudioThread; ///< dummy audio thread
|
static const int AudioThread; ///< dummy audio thread
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
extern int VideoAudioDelay; /// import audio/video delay
|
extern int VideoAudioDelay; ///< import audio/video delay
|
||||||
|
extern int VideoGetBuffers(void); ///< Get number of input buffers.
|
||||||
|
|
||||||
#ifdef USE_AUDIORING
|
#ifdef USE_AUDIORING
|
||||||
|
|
||||||
@ -297,7 +298,17 @@ static int AlsaAddToRingbuffer(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioRunning) {
|
if (!AudioRunning) {
|
||||||
if (AlsaStartThreshold < RingBufferUsedBytes(AlsaRingBuffer)) {
|
Debug(3, "audio/alsa: start %zd ms %d\n",
|
||||||
|
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
|
||||||
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample),
|
||||||
|
VideoGetBuffers());
|
||||||
|
// forced start
|
||||||
|
if (AlsaStartThreshold * 2 < RingBufferUsedBytes(AlsaRingBuffer)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// enough video + audio buffered
|
||||||
|
if (VideoGetBuffers() > 1
|
||||||
|
&& AlsaStartThreshold < RingBufferUsedBytes(AlsaRingBuffer)) {
|
||||||
// restart play-back
|
// restart play-back
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -654,7 +665,8 @@ static void AlsaThread(void)
|
|||||||
}
|
}
|
||||||
state = snd_pcm_state(AlsaPCMHandle);
|
state = snd_pcm_state(AlsaPCMHandle);
|
||||||
if (state != SND_PCM_STATE_RUNNING) {
|
if (state != SND_PCM_STATE_RUNNING) {
|
||||||
Debug(3, "audio/alsa: stopping play\n");
|
Debug(3, "audio/alsa: stopping play '%s'\n",
|
||||||
|
snd_pcm_state_name(state));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pthread_yield();
|
pthread_yield();
|
||||||
@ -720,12 +732,11 @@ static snd_pcm_t *AlsaOpenPCM(int use_ac3)
|
|||||||
|
|
||||||
// &&|| hell
|
// &&|| hell
|
||||||
if (!(use_ac3 && ((device = AudioAC3Device)
|
if (!(use_ac3 && ((device = AudioAC3Device)
|
||||||
|| (device = getenv("ALSA_AC3_DEVICE"))
|
|| (device = getenv("ALSA_AC3_DEVICE"))))
|
||||||
|| (device = getenv("ALSA_PASSTHROUGH_DEVICE"))))
|
|
||||||
&& !(device = AudioPCMDevice) && !(device = getenv("ALSA_DEVICE"))) {
|
&& !(device = AudioPCMDevice) && !(device = getenv("ALSA_DEVICE"))) {
|
||||||
device = "default";
|
device = "default";
|
||||||
}
|
}
|
||||||
Debug(3, "audio/alsa: &&|| hell '%s'\n", device);
|
Info(_("audio/alsa: using device '%s'\n"), device);
|
||||||
|
|
||||||
// open none blocking; if device is already used, we don't want wait
|
// open none blocking; if device is already used, we don't want wait
|
||||||
if ((err =
|
if ((err =
|
||||||
@ -752,7 +763,8 @@ static void AlsaInitPCM(void)
|
|||||||
snd_pcm_t *handle;
|
snd_pcm_t *handle;
|
||||||
snd_pcm_hw_params_t *hw_params;
|
snd_pcm_hw_params_t *hw_params;
|
||||||
int err;
|
int err;
|
||||||
snd_pcm_uframes_t buffer_size;
|
|
||||||
|
//snd_pcm_uframes_t buffer_size;
|
||||||
|
|
||||||
if (!(handle = AlsaOpenPCM(0))) {
|
if (!(handle = AlsaOpenPCM(0))) {
|
||||||
return;
|
return;
|
||||||
@ -767,8 +779,9 @@ static void AlsaInitPCM(void)
|
|||||||
}
|
}
|
||||||
AlsaCanPause = snd_pcm_hw_params_can_pause(hw_params);
|
AlsaCanPause = snd_pcm_hw_params_can_pause(hw_params);
|
||||||
Info(_("audio/alsa: supports pause: %s\n"), AlsaCanPause ? "yes" : "no");
|
Info(_("audio/alsa: supports pause: %s\n"), AlsaCanPause ? "yes" : "no");
|
||||||
snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
|
// needs audio setup
|
||||||
Info(_("audio/alsa: max buffer size %lu\n"), buffer_size);
|
//snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
|
||||||
|
//Info(_("audio/alsa: max buffer size %lu\n"), buffer_size);
|
||||||
|
|
||||||
AlsaPCMHandle = handle;
|
AlsaPCMHandle = handle;
|
||||||
}
|
}
|
||||||
@ -941,7 +954,7 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
|
|||||||
snd_pcm_set_params(AlsaPCMHandle, SND_PCM_FORMAT_S16,
|
snd_pcm_set_params(AlsaPCMHandle, SND_PCM_FORMAT_S16,
|
||||||
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
|
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
|
||||||
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
|
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
|
||||||
125 * 1000))) {
|
96 * 1000))) {
|
||||||
Error(_("audio/alsa: set params error: %s\n"), snd_strerror(err));
|
Error(_("audio/alsa: set params error: %s\n"), snd_strerror(err));
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1053,7 +1066,7 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
|
|||||||
// FIXME: use hw_params for buffer_size period_size
|
// FIXME: use hw_params for buffer_size period_size
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
if (0) { // no underruns allowed, play silence
|
if (0) { // no underruns allowed, play silence
|
||||||
snd_pcm_sw_params_t *sw_params;
|
snd_pcm_sw_params_t *sw_params;
|
||||||
snd_pcm_uframes_t boundary;
|
snd_pcm_uframes_t boundary;
|
||||||
@ -1091,16 +1104,21 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
|
|||||||
// update buffer
|
// update buffer
|
||||||
|
|
||||||
snd_pcm_get_params(AlsaPCMHandle, &buffer_size, &period_size);
|
snd_pcm_get_params(AlsaPCMHandle, &buffer_size, &period_size);
|
||||||
Info(_("audio/alsa: buffer size %lu, period size %lu\n"), buffer_size,
|
Info(_("audio/alsa: buffer size %lu %lums, period size %lu %lums\n"),
|
||||||
period_size);
|
buffer_size, snd_pcm_frames_to_bytes(AlsaPCMHandle,
|
||||||
|
buffer_size) * 1000 / (AudioSampleRate * AudioChannels *
|
||||||
|
AudioBytesProSample), period_size,
|
||||||
|
snd_pcm_frames_to_bytes(AlsaPCMHandle,
|
||||||
|
period_size) * 1000 / (AudioSampleRate * AudioChannels *
|
||||||
|
AudioBytesProSample));
|
||||||
Debug(3, "audio/alsa: state %s\n",
|
Debug(3, "audio/alsa: state %s\n",
|
||||||
snd_pcm_state_name(snd_pcm_state(AlsaPCMHandle)));
|
snd_pcm_state_name(snd_pcm_state(AlsaPCMHandle)));
|
||||||
|
|
||||||
AlsaStartThreshold = snd_pcm_frames_to_bytes(AlsaPCMHandle, period_size);
|
AlsaStartThreshold = snd_pcm_frames_to_bytes(AlsaPCMHandle, period_size);
|
||||||
// buffer time/delay in ms
|
// buffer time/delay in ms
|
||||||
delay = AudioBufferTime;
|
delay = AudioBufferTime;
|
||||||
if (VideoAudioDelay > -100) {
|
if (VideoAudioDelay > 0) {
|
||||||
delay += 100 + VideoAudioDelay / 90;
|
delay += VideoAudioDelay / 90;
|
||||||
}
|
}
|
||||||
if (AlsaStartThreshold <
|
if (AlsaStartThreshold <
|
||||||
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
|
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
|
||||||
@ -1284,7 +1302,17 @@ static int OssAddToRingbuffer(const void *samples, int count)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!AudioRunning) {
|
if (!AudioRunning) {
|
||||||
if (OssStartThreshold < RingBufferUsedBytes(OssRingBuffer)) {
|
Debug(3, "audio/oss: start %zd ms %d\n",
|
||||||
|
(RingBufferUsedBytes(OssRingBuffer) * 1000)
|
||||||
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample),
|
||||||
|
VideoGetBuffers());
|
||||||
|
// forced start
|
||||||
|
if (OssStartThreshold * 2 < RingBufferUsedBytes(OssRingBuffer)) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
// enough video + audio buffered
|
||||||
|
if (VideoGetBuffers() > 1
|
||||||
|
&& OssStartThreshold < RingBufferUsedBytes(OssRingBuffer)) {
|
||||||
// restart play-back
|
// restart play-back
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -1522,7 +1550,7 @@ static int OssOpenPCM(int use_ac3)
|
|||||||
&& !(device = AudioPCMDevice) && !(device = getenv("OSS_AUDIODEV"))) {
|
&& !(device = AudioPCMDevice) && !(device = getenv("OSS_AUDIODEV"))) {
|
||||||
device = "/dev/dsp";
|
device = "/dev/dsp";
|
||||||
}
|
}
|
||||||
Debug(3, "audio/oss: &&|| hell '%s'\n", device);
|
Info(_("audio/oss: using device '%s'\n"), device);
|
||||||
|
|
||||||
if ((fildes = open(device, O_WRONLY)) < 0) {
|
if ((fildes = open(device, O_WRONLY)) < 0) {
|
||||||
Error(_("audio/oss: can't open dsp device '%s': %s\n"), device,
|
Error(_("audio/oss: can't open dsp device '%s': %s\n"), device,
|
||||||
@ -1774,8 +1802,8 @@ static int OssSetup(int *freq, int *channels, int use_ac3)
|
|||||||
OssStartThreshold = bi.bytes + tmp;
|
OssStartThreshold = bi.bytes + tmp;
|
||||||
// buffer time/delay in ms
|
// buffer time/delay in ms
|
||||||
delay = AudioBufferTime;
|
delay = AudioBufferTime;
|
||||||
if (VideoAudioDelay > -100) {
|
if (VideoAudioDelay > 0) {
|
||||||
delay += 100 + VideoAudioDelay / 90;
|
delay += VideoAudioDelay / 90;
|
||||||
}
|
}
|
||||||
if (OssStartThreshold <
|
if (OssStartThreshold <
|
||||||
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
|
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
|
||||||
@ -1964,6 +1992,9 @@ static void *AudioPlayHandlerThread(void *dummy)
|
|||||||
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
pthread_cond_wait(&AudioStartCond, &AudioMutex);
|
||||||
// cond_wait can return, without signal!
|
// cond_wait can return, without signal!
|
||||||
} while (!AudioRunning);
|
} while (!AudioRunning);
|
||||||
|
Debug(3, "audio/alsa: ----> %zd ms\n",
|
||||||
|
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
|
||||||
|
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
|
||||||
pthread_mutex_unlock(&AudioMutex);
|
pthread_mutex_unlock(&AudioMutex);
|
||||||
|
|
||||||
#ifdef USE_AUDIORING
|
#ifdef USE_AUDIORING
|
||||||
@ -2064,6 +2095,21 @@ static const AudioModule *AudioModules[] = {
|
|||||||
*/
|
*/
|
||||||
void AudioEnqueue(const void *samples, int count)
|
void AudioEnqueue(const void *samples, int count)
|
||||||
{
|
{
|
||||||
|
if (0) {
|
||||||
|
static uint32_t last;
|
||||||
|
static uint32_t tick;
|
||||||
|
static uint32_t max = 110;
|
||||||
|
uint64_t delay;
|
||||||
|
|
||||||
|
delay = AudioGetDelay();
|
||||||
|
tick = GetMsTicks();
|
||||||
|
if ((last && tick - last > max) || delay < 80 * 90) {
|
||||||
|
|
||||||
|
//max = tick - last;
|
||||||
|
Debug(3, "audio: packet delta %d %lu\n", tick - last, delay / 90);
|
||||||
|
}
|
||||||
|
last = tick;
|
||||||
|
}
|
||||||
AudioUsedModule->Enqueue(samples, count);
|
AudioUsedModule->Enqueue(samples, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2183,7 +2229,7 @@ int AudioSetup(int *freq, int *channels, int use_ac3)
|
|||||||
void AudioPlay(void)
|
void AudioPlay(void)
|
||||||
{
|
{
|
||||||
if (!AudioPaused) {
|
if (!AudioPaused) {
|
||||||
Warning("audio: not paused, check the code\n");
|
Debug(3, "audio: not paused, check the code\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Debug(3, "audio: resumed\n");
|
Debug(3, "audio: resumed\n");
|
||||||
@ -2197,13 +2243,24 @@ void AudioPlay(void)
|
|||||||
void AudioPause(void)
|
void AudioPause(void)
|
||||||
{
|
{
|
||||||
if (AudioPaused) {
|
if (AudioPaused) {
|
||||||
Warning("audio: already paused, check the code\n");
|
Debug(3, "audio: already paused, check the code\n");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Debug(3, "audio: paused\n");
|
Debug(3, "audio: paused\n");
|
||||||
AudioPaused = 1;
|
AudioPaused = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
** Set audio buffer time.
|
||||||
|
*/
|
||||||
|
void AudioSetBufferTime(int delay)
|
||||||
|
{
|
||||||
|
if (!delay) {
|
||||||
|
delay = 216;
|
||||||
|
}
|
||||||
|
AudioBufferTime = delay;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Set pcm audio device.
|
** Set pcm audio device.
|
||||||
**
|
**
|
||||||
|
2
audio.h
2
audio.h
@ -42,6 +42,8 @@ extern int AudioSetup(int *, int *, int); ///< setup audio output
|
|||||||
extern void AudioPlay(void); ///< play audio
|
extern void AudioPlay(void); ///< play audio
|
||||||
extern void AudioPause(void); ///< pause audio
|
extern void AudioPause(void); ///< pause audio
|
||||||
|
|
||||||
|
extern void AudioSetBufferTime(int); ///< set audio buffer time
|
||||||
|
|
||||||
extern void AudioSetDevice(const char *); ///< set PCM audio device
|
extern void AudioSetDevice(const char *); ///< set PCM audio device
|
||||||
extern void AudioSetDeviceAC3(const char *); ///< set pass-through device
|
extern void AudioSetDeviceAC3(const char *); ///< set pass-through device
|
||||||
extern void AudioSetChannel(const char *); ///< set mixer channel
|
extern void AudioSetChannel(const char *); ///< set mixer channel
|
||||||
|
242
codec.c
242
codec.c
@ -33,7 +33,7 @@
|
|||||||
/**
|
/**
|
||||||
** use av_parser to support insane dvb audio streams.
|
** use av_parser to support insane dvb audio streams.
|
||||||
*/
|
*/
|
||||||
#define USE_AVPARSER
|
#define noUSE_AVPARSER
|
||||||
|
|
||||||
/// compile with passthrough support (experimental)
|
/// compile with passthrough support (experimental)
|
||||||
#define USE_PASSTHROUGH
|
#define USE_PASSTHROUGH
|
||||||
@ -603,8 +603,10 @@ struct _audio_decoder_
|
|||||||
AVCodec *AudioCodec; ///< audio codec
|
AVCodec *AudioCodec; ///< audio codec
|
||||||
AVCodecContext *AudioCtx; ///< audio codec context
|
AVCodecContext *AudioCtx; ///< audio codec context
|
||||||
|
|
||||||
|
#ifdef USE_AVPARSER
|
||||||
/// audio parser to support insane dvb streaks
|
/// audio parser to support insane dvb streaks
|
||||||
AVCodecParserContext *AudioParser;
|
AVCodecParserContext *AudioParser;
|
||||||
|
#endif
|
||||||
int PassthroughAC3; ///< current ac-3 pass-through
|
int PassthroughAC3; ///< current ac-3 pass-through
|
||||||
int SampleRate; ///< current stream sample rate
|
int SampleRate; ///< current stream sample rate
|
||||||
int Channels; ///< current stream channels
|
int Channels; ///< current stream channels
|
||||||
@ -697,10 +699,12 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
|
|||||||
// we do not send complete frames
|
// we do not send complete frames
|
||||||
audio_decoder->AudioCtx->flags |= CODEC_FLAG_TRUNCATED;
|
audio_decoder->AudioCtx->flags |= CODEC_FLAG_TRUNCATED;
|
||||||
}
|
}
|
||||||
|
#ifdef USE_AVPARSER
|
||||||
if (!(audio_decoder->AudioParser =
|
if (!(audio_decoder->AudioParser =
|
||||||
av_parser_init(audio_decoder->AudioCtx->codec_id))) {
|
av_parser_init(audio_decoder->AudioCtx->codec_id))) {
|
||||||
Fatal(_("codec: can't init audio parser\n"));
|
Fatal(_("codec: can't init audio parser\n"));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
audio_decoder->SampleRate = 0;
|
audio_decoder->SampleRate = 0;
|
||||||
audio_decoder->Channels = 0;
|
audio_decoder->Channels = 0;
|
||||||
audio_decoder->HwSampleRate = 0;
|
audio_decoder->HwSampleRate = 0;
|
||||||
@ -719,10 +723,12 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
|
|||||||
audio_resample_close(audio_decoder->ReSample);
|
audio_resample_close(audio_decoder->ReSample);
|
||||||
audio_decoder->ReSample = NULL;
|
audio_decoder->ReSample = NULL;
|
||||||
}
|
}
|
||||||
|
#ifdef USE_AVPARSER
|
||||||
if (audio_decoder->AudioParser) {
|
if (audio_decoder->AudioParser) {
|
||||||
av_parser_close(audio_decoder->AudioParser);
|
av_parser_close(audio_decoder->AudioParser);
|
||||||
audio_decoder->AudioParser = NULL;
|
audio_decoder->AudioParser = NULL;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
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);
|
||||||
@ -808,7 +814,7 @@ static void CodecReorderAudioFrame(int16_t * buf, int size, int channels)
|
|||||||
** @param audio_decoder audio decoder data
|
** @param audio_decoder audio decoder data
|
||||||
** @param avpkt audio packet
|
** @param avpkt audio packet
|
||||||
*/
|
*/
|
||||||
void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
void CodecAudioDecodeOld(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
||||||
{
|
{
|
||||||
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
|
int16_t buf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
|
||||||
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
|
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
|
||||||
@ -844,8 +850,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
|||||||
av_init_packet(dpkt);
|
av_init_packet(dpkt);
|
||||||
n = av_parser_parse2(audio_decoder->AudioParser, audio_ctx,
|
n = av_parser_parse2(audio_decoder->AudioParser, audio_ctx,
|
||||||
&dpkt->data, &dpkt->size, spkt->data + index, spkt->size - index,
|
&dpkt->data, &dpkt->size, spkt->data + index, spkt->size - index,
|
||||||
!index ? (uint64_t) spkt->pts : AV_NOPTS_VALUE,
|
!index ? spkt->pts : (int64_t) AV_NOPTS_VALUE,
|
||||||
!index ? (uint64_t) spkt->dts : AV_NOPTS_VALUE, -1);
|
!index ? spkt->dts : (int64_t) AV_NOPTS_VALUE, -1);
|
||||||
|
|
||||||
// FIXME: make this a function for both #ifdef cases
|
// FIXME: make this a function for both #ifdef cases
|
||||||
if (dpkt->size) {
|
if (dpkt->size) {
|
||||||
@ -871,7 +877,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
|||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
// Update audio clock
|
// Update audio clock
|
||||||
if ((uint64_t) dpkt->pts != AV_NOPTS_VALUE) {
|
if (dpkt->pts != (int64_t) AV_NOPTS_VALUE) {
|
||||||
AudioSetClock(dpkt->pts);
|
AudioSetClock(dpkt->pts);
|
||||||
}
|
}
|
||||||
// FIXME: must first play remainings bytes, than change and play new.
|
// FIXME: must first play remainings bytes, than change and play new.
|
||||||
@ -1059,6 +1065,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Decode an audio packet.
|
** Decode an audio packet.
|
||||||
**
|
**
|
||||||
@ -1074,61 +1082,205 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
|||||||
AVCodecContext *audio_ctx;
|
AVCodecContext *audio_ctx;
|
||||||
int index;
|
int index;
|
||||||
|
|
||||||
//#define spkt avpkt
|
|
||||||
#if 1
|
|
||||||
AVPacket spkt[1];
|
|
||||||
|
|
||||||
// av_new_packet reserves FF_INPUT_BUFFER_PADDING_SIZE and clears it
|
|
||||||
if (av_new_packet(spkt, avpkt->size)) {
|
|
||||||
Error(_("codec: out of memory\n"));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
memcpy(spkt->data, avpkt->data, avpkt->size);
|
|
||||||
spkt->pts = avpkt->pts;
|
|
||||||
spkt->dts = avpkt->dts;
|
|
||||||
#endif
|
|
||||||
audio_ctx = audio_decoder->AudioCtx;
|
audio_ctx = audio_decoder->AudioCtx;
|
||||||
index = 0;
|
index = 0;
|
||||||
while (spkt->size > index) {
|
while (avpkt->size > index) {
|
||||||
int n;
|
int l;
|
||||||
int buf_sz;
|
int buf_sz;
|
||||||
AVPacket dpkt[1];
|
|
||||||
|
|
||||||
av_init_packet(dpkt);
|
|
||||||
dpkt->data = spkt->data + index;
|
|
||||||
dpkt->size = spkt->size - index;
|
|
||||||
|
|
||||||
buf_sz = sizeof(buf);
|
buf_sz = sizeof(buf);
|
||||||
n = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, dpkt);
|
l = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, (AVPacket *)avpkt);
|
||||||
if (n < 0) { // no audio frame could be decompressed
|
if (l == AVERROR(EAGAIN)) {
|
||||||
|
Error(_("codec: latm\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (l < 0) { // no audio frame could be decompressed
|
||||||
Error(_("codec: error audio data at %d\n"), index);
|
Error(_("codec: error audio data at %d\n"), index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#ifdef DEBUG
|
|
||||||
Debug(4, "codec/audio: -> %d\n", buf_sz);
|
|
||||||
if ((unsigned)buf_sz > sizeof(buf)) {
|
|
||||||
abort();
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef notyetFF_API_OLD_DECODE_AUDIO
|
#ifdef notyetFF_API_OLD_DECODE_AUDIO
|
||||||
// FIXME: ffmpeg git comeing
|
// FIXME: ffmpeg git comeing
|
||||||
int got_frame;
|
int got_frame;
|
||||||
|
|
||||||
avcodec_decode_audio4(audio_ctx, frame, &got_frame, dpkt);
|
avcodec_decode_audio4(audio_ctx, frame, &got_frame, avpkt);
|
||||||
#else
|
#else
|
||||||
#endif
|
#endif
|
||||||
// FIXME: see above, old code removed
|
// Update audio clock
|
||||||
|
if (avpkt->pts != (int64_t) AV_NOPTS_VALUE) {
|
||||||
|
AudioSetClock(avpkt->pts);
|
||||||
|
}
|
||||||
|
// FIXME: must first play remainings bytes, than change and play new.
|
||||||
|
if (audio_decoder->PassthroughAC3 != CodecPassthroughAC3
|
||||||
|
|| audio_decoder->SampleRate != audio_ctx->sample_rate
|
||||||
|
|| audio_decoder->Channels != audio_ctx->channels) {
|
||||||
|
int err;
|
||||||
|
int isAC3;
|
||||||
|
|
||||||
index += n;
|
audio_decoder->PassthroughAC3 = CodecPassthroughAC3;
|
||||||
|
// FIXME: use swr_convert from swresample (only in ffmpeg!)
|
||||||
|
// FIXME: tell ac3 decoder to use downmix
|
||||||
|
if (audio_decoder->ReSample) {
|
||||||
|
audio_resample_close(audio_decoder->ReSample);
|
||||||
|
audio_decoder->ReSample = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if 1
|
audio_decoder->SampleRate = audio_ctx->sample_rate;
|
||||||
// or av_free_packet, make no difference here
|
audio_decoder->HwSampleRate = audio_ctx->sample_rate;
|
||||||
av_destruct_packet(spkt);
|
audio_decoder->Channels = audio_ctx->channels;
|
||||||
#endif
|
// SPDIF/HDMI passthrough
|
||||||
|
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
|
||||||
|
audio_decoder->HwChannels = 2;
|
||||||
|
isAC3 = 1;
|
||||||
|
} else {
|
||||||
|
audio_decoder->HwChannels = audio_ctx->channels;
|
||||||
|
isAC3 = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// channels not support?
|
||||||
|
if ((err =
|
||||||
|
AudioSetup(&audio_decoder->HwSampleRate,
|
||||||
|
&audio_decoder->HwChannels, isAC3))) {
|
||||||
|
Debug(3, "codec/audio: resample %dHz *%d -> %dHz *%d\n",
|
||||||
|
audio_ctx->sample_rate, audio_ctx->channels,
|
||||||
|
audio_decoder->HwSampleRate, audio_decoder->HwChannels);
|
||||||
|
|
||||||
|
if (err == 1) {
|
||||||
|
audio_decoder->ReSample =
|
||||||
|
av_audio_resample_init(audio_decoder->HwChannels,
|
||||||
|
audio_ctx->channels, audio_decoder->HwSampleRate,
|
||||||
|
audio_ctx->sample_rate, audio_ctx->sample_fmt,
|
||||||
|
audio_ctx->sample_fmt, 16, 10, 0, 0.8);
|
||||||
|
// libav-0.8_pre didn't support 6 -> 2 channels
|
||||||
|
if (!audio_decoder->ReSample) {
|
||||||
|
Error(_("codec/audio: resample setup error\n"));
|
||||||
|
audio_decoder->HwChannels = 0;
|
||||||
|
audio_decoder->HwSampleRate = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Debug(3, "codec/audio: audio setup error\n");
|
||||||
|
// FIXME: handle errors
|
||||||
|
audio_decoder->HwChannels = 0;
|
||||||
|
audio_decoder->HwSampleRate = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (audio_decoder->HwSampleRate && audio_decoder->HwChannels) {
|
||||||
|
// need to resample audio
|
||||||
|
if (audio_decoder->ReSample) {
|
||||||
|
int16_t outbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 4 +
|
||||||
|
FF_INPUT_BUFFER_PADDING_SIZE]
|
||||||
|
__attribute__ ((aligned(16)));
|
||||||
|
int outlen;
|
||||||
|
|
||||||
|
// FIXME: libav-0.7.2 crash here
|
||||||
|
outlen =
|
||||||
|
audio_resample(audio_decoder->ReSample, outbuf, buf,
|
||||||
|
buf_sz);
|
||||||
|
#ifdef DEBUG
|
||||||
|
if (outlen != buf_sz) {
|
||||||
|
Debug(3, "codec/audio: possible fixed ffmpeg\n");
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
if (outlen) {
|
||||||
|
// outlen seems to be wrong in ffmpeg-0.9
|
||||||
|
outlen /= audio_decoder->Channels *
|
||||||
|
av_get_bytes_per_sample(audio_ctx->sample_fmt);
|
||||||
|
outlen *=
|
||||||
|
audio_decoder->HwChannels *
|
||||||
|
av_get_bytes_per_sample(audio_ctx->sample_fmt);
|
||||||
|
Debug(4, "codec/audio: %d -> %d\n", buf_sz, outlen);
|
||||||
|
CodecReorderAudioFrame(outbuf, outlen,
|
||||||
|
audio_decoder->HwChannels);
|
||||||
|
AudioEnqueue(outbuf, outlen);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
#ifdef USE_PASSTHROUGH
|
||||||
|
// SPDIF/HDMI passthrough
|
||||||
|
if (CodecPassthroughAC3 && audio_ctx->codec_id == CODEC_ID_AC3) {
|
||||||
|
// build SPDIF header and append A52 audio to it
|
||||||
|
// avpkt is the original data
|
||||||
|
buf_sz = 6144;
|
||||||
|
if (buf_sz < avpkt->size + 8) {
|
||||||
|
Error(_
|
||||||
|
("codec/audio: decoded data smaller than encoded\n"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
// copy original data for output
|
||||||
|
// FIXME: not 100% sure, if endian is correct
|
||||||
|
buf[0] = htole16(0xF872); // iec 61937 sync word
|
||||||
|
buf[1] = htole16(0x4E1F);
|
||||||
|
buf[2] = htole16(0x01 | (avpkt->data[5] & 0x07) << 8);
|
||||||
|
buf[3] = htole16(avpkt->size * 8);
|
||||||
|
swab(avpkt->data, buf + 4, avpkt->size);
|
||||||
|
memset(buf + 4 + avpkt->size / 2, 0,
|
||||||
|
buf_sz - 8 - avpkt->size);
|
||||||
|
}
|
||||||
|
#if 0
|
||||||
|
//
|
||||||
|
// old experimental code
|
||||||
|
//
|
||||||
|
if (1) {
|
||||||
|
// FIXME: need to detect dts
|
||||||
|
// copy original data for output
|
||||||
|
// FIXME: buf is sint
|
||||||
|
buf[0] = 0x72;
|
||||||
|
buf[1] = 0xF8;
|
||||||
|
buf[2] = 0x1F;
|
||||||
|
buf[3] = 0x4E;
|
||||||
|
buf[4] = 0x00;
|
||||||
|
switch (avpkt->size) {
|
||||||
|
case 512:
|
||||||
|
buf[5] = 0x0B;
|
||||||
|
break;
|
||||||
|
case 1024:
|
||||||
|
buf[5] = 0x0C;
|
||||||
|
break;
|
||||||
|
case 2048:
|
||||||
|
buf[5] = 0x0D;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
Debug(3,
|
||||||
|
"codec/audio: dts sample burst not supported\n");
|
||||||
|
buf[5] = 0x00;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
buf[6] = (avpkt->size * 8);
|
||||||
|
buf[7] = (avpkt->size * 8) >> 8;
|
||||||
|
//buf[8] = 0x0B;
|
||||||
|
//buf[9] = 0x77;
|
||||||
|
//printf("%x %x\n", avpkt->data[0],avpkt->data[1]);
|
||||||
|
// swab?
|
||||||
|
memcpy(buf + 8, avpkt->data, avpkt->size);
|
||||||
|
memset(buf + 8 + avpkt->size, 0, buf_sz - 8 - avpkt->size);
|
||||||
|
} else if (1) {
|
||||||
|
// FIXME: need to detect mp2
|
||||||
|
// FIXME: mp2 passthrough
|
||||||
|
// see softhddev.c version/layer
|
||||||
|
// 0x04 mpeg1 layer1
|
||||||
|
// 0x05 mpeg1 layer23
|
||||||
|
// 0x06 mpeg2 ext
|
||||||
|
// 0x07 mpeg2.5 layer 1
|
||||||
|
// 0x08 mpeg2.5 layer 2
|
||||||
|
// 0x09 mpeg2.5 layer 3
|
||||||
|
}
|
||||||
|
// DTS HD?
|
||||||
|
// True HD?
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
CodecReorderAudioFrame(buf, buf_sz, audio_decoder->HwChannels);
|
||||||
|
AudioEnqueue(buf, buf_sz);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (avpkt->size > l) {
|
||||||
|
Error(_("codec: error more than one frame data\n"));
|
||||||
|
}
|
||||||
|
|
||||||
|
index += l;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Flush the audio decoder.
|
** Flush the audio decoder.
|
||||||
@ -1137,7 +1289,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
|
|||||||
*/
|
*/
|
||||||
void CodecAudioFlushBuffers(AudioDecoder * decoder)
|
void CodecAudioFlushBuffers(AudioDecoder * decoder)
|
||||||
{
|
{
|
||||||
|
#ifdef USE_AVPARSER
|
||||||
// FIXME: reset audio parser
|
// FIXME: reset audio parser
|
||||||
|
if (decoder->AudioParser) {
|
||||||
|
av_parser_close(decoder->AudioParser);
|
||||||
|
decoder->AudioParser = NULL;
|
||||||
|
if (!(decoder->AudioParser =
|
||||||
|
av_parser_init(decoder->AudioCtx->codec_id))) {
|
||||||
|
Fatal(_("codec: can't init audio parser\n"));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
avcodec_flush_buffers(decoder->AudioCtx);
|
avcodec_flush_buffers(decoder->AudioCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
3
codec.h
3
codec.h
@ -67,6 +67,9 @@ extern void CodecAudioOpen(AudioDecoder *, const char *, int);
|
|||||||
/// Close audio codec.
|
/// Close audio codec.
|
||||||
extern void CodecAudioClose(AudioDecoder *);
|
extern void CodecAudioClose(AudioDecoder *);
|
||||||
|
|
||||||
|
/// Decode an audio packet.
|
||||||
|
extern void CodecAudioDecodeOld(AudioDecoder *, const AVPacket *);
|
||||||
|
|
||||||
/// Decode an audio packet.
|
/// Decode an audio packet.
|
||||||
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);
|
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);
|
||||||
|
|
||||||
|
1089
softhddev.c
1089
softhddev.c
File diff suppressed because it is too large
Load Diff
@ -37,6 +37,8 @@ extern "C"
|
|||||||
|
|
||||||
/// C plugin play audio packet
|
/// C plugin play audio packet
|
||||||
extern int PlayAudio(const uint8_t *, int, uint8_t);
|
extern int PlayAudio(const uint8_t *, int, uint8_t);
|
||||||
|
/// C plugin play TS audio packet
|
||||||
|
extern int PlayTsAudio(const uint8_t *, int);
|
||||||
/// C plugin set audio volume
|
/// C plugin set audio volume
|
||||||
extern void SetVolumeDevice(int);
|
extern void SetVolumeDevice(int);
|
||||||
|
|
||||||
|
@ -835,9 +835,11 @@ class cSoftHdDevice:public cDevice
|
|||||||
virtual void GetVideoSize(int &, int &, double &);
|
virtual void GetVideoSize(int &, int &, double &);
|
||||||
virtual void GetOsdSize(int &, int &, double &);
|
virtual void GetOsdSize(int &, int &, double &);
|
||||||
virtual int PlayVideo(const uchar *, int);
|
virtual int PlayVideo(const uchar *, int);
|
||||||
|
#ifndef xxUSE_TS_AUDIO
|
||||||
|
virtual int PlayAudio(const uchar *, int, uchar);
|
||||||
|
#endif
|
||||||
//virtual int PlayTsVideo(const uchar *, int);
|
//virtual int PlayTsVideo(const uchar *, int);
|
||||||
#ifndef USE_AUDIO_THREAD // FIXME: testing none threaded
|
#if !defined(USE_AUDIO_THREAD) || defined(USE_TS_AUDIO)
|
||||||
virtual int PlayTsAudio(const uchar *, int);
|
virtual int PlayTsAudio(const uchar *, int);
|
||||||
#endif
|
#endif
|
||||||
virtual void SetAudioChannelDevice(int);
|
virtual void SetAudioChannelDevice(int);
|
||||||
@ -845,7 +847,6 @@ class cSoftHdDevice:public cDevice
|
|||||||
virtual void SetDigitalAudioDevice(bool);
|
virtual void SetDigitalAudioDevice(bool);
|
||||||
virtual void SetAudioTrackDevice(eTrackType);
|
virtual void SetAudioTrackDevice(eTrackType);
|
||||||
virtual void SetVolumeDevice(int);
|
virtual void SetVolumeDevice(int);
|
||||||
virtual int PlayAudio(const uchar *, int, uchar);
|
|
||||||
|
|
||||||
// Image Grab facilities
|
// Image Grab facilities
|
||||||
|
|
||||||
@ -1066,8 +1067,8 @@ bool cSoftHdDevice::Flush(int timeout_ms)
|
|||||||
** Sets the video display format to the given one (only useful if this
|
** Sets the video display format to the given one (only useful if this
|
||||||
** device has an MPEG decoder).
|
** device has an MPEG decoder).
|
||||||
*/
|
*/
|
||||||
void cSoftHdDevice::
|
void cSoftHdDevice:: SetVideoDisplayFormat(eVideoDisplayFormat
|
||||||
SetVideoDisplayFormat(eVideoDisplayFormat video_display_format)
|
video_display_format)
|
||||||
{
|
{
|
||||||
static int last = -1;
|
static int last = -1;
|
||||||
|
|
||||||
@ -1124,8 +1125,14 @@ void cSoftHdDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
|
|||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#ifndef xxUSE_TS_AUDIO
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Play a audio packet.
|
** Play a audio packet.
|
||||||
|
**
|
||||||
|
** @param data exactly one complete PES packet (which is incomplete)
|
||||||
|
** @param length length of PES packet
|
||||||
|
** @param id type of audio data this packet holds
|
||||||
*/
|
*/
|
||||||
int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
|
int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
|
||||||
{
|
{
|
||||||
@ -1134,6 +1141,8 @@ int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
|
|||||||
return::PlayAudio(data, length, id);
|
return::PlayAudio(data, length, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
void cSoftHdDevice::SetAudioTrackDevice(
|
void cSoftHdDevice::SetAudioTrackDevice(
|
||||||
__attribute__ ((unused)) eTrackType type)
|
__attribute__ ((unused)) eTrackType type)
|
||||||
{
|
{
|
||||||
@ -1173,6 +1182,9 @@ void cSoftHdDevice::SetVolumeDevice(int volume)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
** Play a video packet.
|
** Play a video packet.
|
||||||
|
**
|
||||||
|
** @param data exactly one complete PES packet (which is incomplete)
|
||||||
|
** @param length length of PES packet
|
||||||
*/
|
*/
|
||||||
int cSoftHdDevice::PlayVideo(const uchar * data, int length)
|
int cSoftHdDevice::PlayVideo(const uchar * data, int length)
|
||||||
{
|
{
|
||||||
|
47
video.c
47
video.c
@ -329,7 +329,6 @@ static xcb_atom_t NetWmState; ///< wm-state message atom
|
|||||||
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
|
||||||
|
|
||||||
extern uint32_t VideoSwitch; ///< ticks for channel switch
|
extern uint32_t VideoSwitch; ///< ticks for channel switch
|
||||||
extern atomic_t VideoPacketsFilled; ///< how many of the buffer is used
|
|
||||||
|
|
||||||
#ifdef USE_VIDEO_THREAD
|
#ifdef USE_VIDEO_THREAD
|
||||||
|
|
||||||
@ -396,19 +395,19 @@ static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
|
|||||||
int64_t pts;
|
int64_t pts;
|
||||||
|
|
||||||
// update video clock
|
// update video clock
|
||||||
if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
|
if (*pts_p != (int64_t) AV_NOPTS_VALUE) {
|
||||||
*pts_p += interlaced ? 40 * 90 : 20 * 90;
|
*pts_p += interlaced ? 40 * 90 : 20 * 90;
|
||||||
}
|
}
|
||||||
//pts = frame->best_effort_timestamp;
|
//pts = frame->best_effort_timestamp;
|
||||||
pts = frame->pkt_pts;
|
pts = frame->pkt_pts;
|
||||||
if ((uint64_t) pts == AV_NOPTS_VALUE || !pts) {
|
if (pts == (int64_t) AV_NOPTS_VALUE || !pts) {
|
||||||
// libav: 0.8pre didn't set pts
|
// libav: 0.8pre didn't set pts
|
||||||
pts = frame->pkt_dts;
|
pts = frame->pkt_dts;
|
||||||
}
|
}
|
||||||
// libav: sets only pkt_dts which can be 0
|
// libav: sets only pkt_dts which can be 0
|
||||||
if (pts && (uint64_t) pts != AV_NOPTS_VALUE) {
|
if (pts && pts != (int64_t) AV_NOPTS_VALUE) {
|
||||||
// build a monotonic pts
|
// build a monotonic pts
|
||||||
if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
|
if (*pts_p != (int64_t) AV_NOPTS_VALUE) {
|
||||||
int64_t delta;
|
int64_t delta;
|
||||||
|
|
||||||
delta = pts - *pts_p;
|
delta = pts - *pts_p;
|
||||||
@ -4224,7 +4223,7 @@ static void VaapiAdvanceFrame(void)
|
|||||||
Warning(_
|
Warning(_
|
||||||
("video: display buffer empty, duping frame (%d/%d) %d\n"),
|
("video: display buffer empty, duping frame (%d/%d) %d\n"),
|
||||||
decoder->FramesDuped, decoder->FrameCounter,
|
decoder->FramesDuped, decoder->FrameCounter,
|
||||||
atomic_read(&VideoPacketsFilled));
|
VideoGetBuffers());
|
||||||
}
|
}
|
||||||
last_warned_frame = decoder->FrameCounter;
|
last_warned_frame = decoder->FrameCounter;
|
||||||
if (!(decoder->FramesDisplayed % 300)) {
|
if (!(decoder->FramesDisplayed % 300)) {
|
||||||
@ -4358,10 +4357,10 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
// FIXME: audio not known assume 333ms delay
|
// FIXME: audio not known assume 333ms delay
|
||||||
|
|
||||||
if (decoder->DupNextFrame) {
|
if (decoder->DupNextFrame) {
|
||||||
++decoder->FramesDuped;
|
|
||||||
decoder->DupNextFrame--;
|
decoder->DupNextFrame--;
|
||||||
} else if ((uint64_t) audio_clock != AV_NOPTS_VALUE
|
++decoder->FramesDuped;
|
||||||
&& (uint64_t) video_clock != AV_NOPTS_VALUE) {
|
} else if (audio_clock != (int64_t) AV_NOPTS_VALUE
|
||||||
|
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
|
||||||
// both clocks are known
|
// both clocks are known
|
||||||
|
|
||||||
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
||||||
@ -4377,6 +4376,12 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
Debug(3, "video: speed up video\n");
|
Debug(3, "video: speed up video\n");
|
||||||
decoder->DropNextFrame = 1;
|
decoder->DropNextFrame = 1;
|
||||||
}
|
}
|
||||||
|
} else if (audio_clock == (int64_t) AV_NOPTS_VALUE
|
||||||
|
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
|
||||||
|
if (VideoGetBuffers() < 4) {
|
||||||
|
Debug(3, "video: initial slow down video\n");
|
||||||
|
decoder->DupNextFrame++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if defined(DEBUG) || defined(AV_INFO)
|
#if defined(DEBUG) || defined(AV_INFO)
|
||||||
// debug audio/video sync
|
// debug audio/video sync
|
||||||
@ -4386,8 +4391,7 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
|
|||||||
VideoTimeStampString(video_clock),
|
VideoTimeStampString(video_clock),
|
||||||
abs((video_clock - audio_clock) / 90) <
|
abs((video_clock - audio_clock) / 90) <
|
||||||
9999 ? ((video_clock - audio_clock) / 90) : 88888,
|
9999 ? ((video_clock - audio_clock) / 90) : 88888,
|
||||||
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90,
|
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers());
|
||||||
atomic_read(&VideoPacketsFilled));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -4463,7 +4467,7 @@ static void VaapiSyncRenderFrame(VaapiDecoder * decoder,
|
|||||||
static int64_t VaapiGetClock(const VaapiDecoder * decoder)
|
static int64_t VaapiGetClock(const VaapiDecoder * decoder)
|
||||||
{
|
{
|
||||||
// pts is the timestamp of the latest decoded frame
|
// pts is the timestamp of the latest decoded frame
|
||||||
if (!decoder || (uint64_t) decoder->PTS == AV_NOPTS_VALUE) {
|
if (!decoder || decoder->PTS == (int64_t) AV_NOPTS_VALUE) {
|
||||||
return AV_NOPTS_VALUE;
|
return AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
// subtract buffered decoded frames
|
// subtract buffered decoded frames
|
||||||
@ -7235,7 +7239,7 @@ static void VdpauAdvanceFrame(void)
|
|||||||
Warning(_
|
Warning(_
|
||||||
("video: display buffer empty, duping frame (%d/%d) %d\n"),
|
("video: display buffer empty, duping frame (%d/%d) %d\n"),
|
||||||
decoder->FramesDuped, decoder->FrameCounter,
|
decoder->FramesDuped, decoder->FrameCounter,
|
||||||
atomic_read(&VideoPacketsFilled));
|
VideoGetBuffers());
|
||||||
}
|
}
|
||||||
last_warned_frame = decoder->FrameCounter;
|
last_warned_frame = decoder->FrameCounter;
|
||||||
if (!(decoder->FramesDisplayed % 300)) {
|
if (!(decoder->FramesDisplayed % 300)) {
|
||||||
@ -7371,8 +7375,9 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
|
|
||||||
if (decoder->DupNextFrame) {
|
if (decoder->DupNextFrame) {
|
||||||
decoder->DupNextFrame--;
|
decoder->DupNextFrame--;
|
||||||
} else if ((uint64_t) audio_clock != AV_NOPTS_VALUE
|
++decoder->FramesDuped;
|
||||||
&& (uint64_t) video_clock != AV_NOPTS_VALUE) {
|
} else if (audio_clock != (int64_t) AV_NOPTS_VALUE
|
||||||
|
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
|
||||||
// both clocks are known
|
// both clocks are known
|
||||||
|
|
||||||
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
if (abs(video_clock - audio_clock) > 5000 * 90) {
|
||||||
@ -7388,6 +7393,12 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
Debug(3, "video: speed up video\n");
|
Debug(3, "video: speed up video\n");
|
||||||
decoder->DropNextFrame = 1;
|
decoder->DropNextFrame = 1;
|
||||||
}
|
}
|
||||||
|
} else if (audio_clock == (int64_t) AV_NOPTS_VALUE
|
||||||
|
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
|
||||||
|
if (VideoGetBuffers() < 4) {
|
||||||
|
Debug(3, "video: initial slow down video\n");
|
||||||
|
decoder->DupNextFrame++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#if defined(DEBUG) || defined(AV_INFO)
|
#if defined(DEBUG) || defined(AV_INFO)
|
||||||
// debug audio/video sync
|
// debug audio/video sync
|
||||||
@ -7397,8 +7408,7 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
|
|||||||
VideoTimeStampString(video_clock),
|
VideoTimeStampString(video_clock),
|
||||||
abs((video_clock - audio_clock) / 90) <
|
abs((video_clock - audio_clock) / 90) <
|
||||||
9999 ? ((video_clock - audio_clock) / 90) : 88888,
|
9999 ? ((video_clock - audio_clock) / 90) : 88888,
|
||||||
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90,
|
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers());
|
||||||
atomic_read(&VideoPacketsFilled));
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@ -7480,7 +7490,7 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
|
|||||||
static int64_t VdpauGetClock(const VdpauDecoder * decoder)
|
static int64_t VdpauGetClock(const VdpauDecoder * decoder)
|
||||||
{
|
{
|
||||||
// pts is the timestamp of the latest decoded frame
|
// pts is the timestamp of the latest decoded frame
|
||||||
if (!decoder || (uint64_t) decoder->PTS == AV_NOPTS_VALUE) {
|
if (!decoder || decoder->PTS == (int64_t) AV_NOPTS_VALUE) {
|
||||||
return AV_NOPTS_VALUE;
|
return AV_NOPTS_VALUE;
|
||||||
}
|
}
|
||||||
// subtract buffered decoded frames
|
// subtract buffered decoded frames
|
||||||
@ -9324,6 +9334,7 @@ void VideoExit(void)
|
|||||||
if (VideoUsedModule) {
|
if (VideoUsedModule) {
|
||||||
VideoUsedModule->Exit();
|
VideoUsedModule->Exit();
|
||||||
}
|
}
|
||||||
|
VideoUsedModule = NULL; // FIXME: NoopModule;
|
||||||
#ifdef USE_GLX
|
#ifdef USE_GLX
|
||||||
if (GlxEnabled) {
|
if (GlxEnabled) {
|
||||||
GlxExit();
|
GlxExit();
|
||||||
|
1
video.h
1
video.h
@ -144,5 +144,6 @@ extern void VideoExit(void); ///< Cleanup and exit video module.
|
|||||||
|
|
||||||
extern void VideoFlushInput(void); ///< Flush video input buffers.
|
extern void VideoFlushInput(void); ///< Flush video input buffers.
|
||||||
extern int VideoDecode(void); ///< Decode video input buffers.
|
extern int VideoDecode(void); ///< Decode video input buffers.
|
||||||
|
extern int VideoGetBuffers(void); ///< Get number of input buffers.
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
Loading…
Reference in New Issue
Block a user