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:
Johns 2012-02-21 20:55:28 +01:00
parent 1f232db5b4
commit 5d8dea1b6b
12 changed files with 1302 additions and 420 deletions

View File

@ -1,6 +1,7 @@
User johns
Date:
New audio PES packet parser.
Fix bug: Grabbing a JPG image fails while suspended.
Add support for hot keys.
Add support to use characters input in edit mode.

View File

@ -19,8 +19,9 @@ GIT_REV = $(shell git describe --always 2>/dev/null)
### Configuration (edit this for your needs)
CONFIG := #-DDEBUG
CONFIG += -DAV_INFO
#CONFIG += -DHAVE_PTHREAD_NAME
CONFIG += -DAV_INFO # debug a/v sync
#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 libva && echo "-DUSE_VAAPI")
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)"')
_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\
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
`pkg-config --cflags gl glu` \
@ -82,7 +83,7 @@ override CXXFLAGS += $(_CFLAGS)
override CFLAGS += $(_CFLAGS)
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\
xcb-screensaver xcb-randr xcb-glx xcb-icccm xcb-keysyms`\
`pkg-config --libs gl glu` \

9
Todo
View File

@ -26,6 +26,8 @@ missing:
Option deinterlace off / deinterlace force!
ColorSpace aren'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:
AudioPlayHandlerThread -> pthread_cond_wait
@ -99,8 +101,11 @@ HDMI/SPDIF Passthrough:
only AC-3 written
playback of recording
pause is not reset, when replay exit
replay/pause need 100% cpu
pause is not reset, when replay exit (fixed?)
replay/pause need 100% cpu (fixed?)
plugins:
mp3 plugin needs 100% cpu (OSD updates?)
setup:
Setup of decoder type.

101
audio.c
View File

@ -141,7 +141,7 @@ static unsigned AudioSampleRate; ///< audio sample rate in hz
static unsigned AudioChannels; ///< number of audio channels
static const int AudioBytesProSample = 2; ///< number of bytes per sample
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
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
#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
@ -297,7 +298,17 @@ static int AlsaAddToRingbuffer(const void *samples, int count)
}
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
return 1;
}
@ -654,7 +665,8 @@ static void AlsaThread(void)
}
state = snd_pcm_state(AlsaPCMHandle);
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;
}
pthread_yield();
@ -720,12 +732,11 @@ static snd_pcm_t *AlsaOpenPCM(int use_ac3)
// &&|| hell
if (!(use_ac3 && ((device = AudioAC3Device)
|| (device = getenv("ALSA_AC3_DEVICE"))
|| (device = getenv("ALSA_PASSTHROUGH_DEVICE"))))
|| (device = getenv("ALSA_AC3_DEVICE"))))
&& !(device = AudioPCMDevice) && !(device = getenv("ALSA_DEVICE"))) {
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
if ((err =
@ -752,7 +763,8 @@ static void AlsaInitPCM(void)
snd_pcm_t *handle;
snd_pcm_hw_params_t *hw_params;
int err;
snd_pcm_uframes_t buffer_size;
//snd_pcm_uframes_t buffer_size;
if (!(handle = AlsaOpenPCM(0))) {
return;
@ -767,8 +779,9 @@ static void AlsaInitPCM(void)
}
AlsaCanPause = snd_pcm_hw_params_can_pause(hw_params);
Info(_("audio/alsa: supports pause: %s\n"), AlsaCanPause ? "yes" : "no");
snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
Info(_("audio/alsa: max buffer size %lu\n"), buffer_size);
// needs audio setup
//snd_pcm_hw_params_get_buffer_size_max(hw_params, &buffer_size);
//Info(_("audio/alsa: max buffer size %lu\n"), buffer_size);
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,
AlsaUseMmap ? SND_PCM_ACCESS_MMAP_INTERLEAVED :
SND_PCM_ACCESS_RW_INTERLEAVED, *channels, *freq, 1,
125 * 1000))) {
96 * 1000))) {
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
#endif
#if 1
#if 0
if (0) { // no underruns allowed, play silence
snd_pcm_sw_params_t *sw_params;
snd_pcm_uframes_t boundary;
@ -1091,16 +1104,21 @@ static int AlsaSetup(int *freq, int *channels, int use_ac3)
// update buffer
snd_pcm_get_params(AlsaPCMHandle, &buffer_size, &period_size);
Info(_("audio/alsa: buffer size %lu, period size %lu\n"), buffer_size,
period_size);
Info(_("audio/alsa: buffer size %lu %lums, period size %lu %lums\n"),
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",
snd_pcm_state_name(snd_pcm_state(AlsaPCMHandle)));
AlsaStartThreshold = snd_pcm_frames_to_bytes(AlsaPCMHandle, period_size);
// buffer time/delay in ms
delay = AudioBufferTime;
if (VideoAudioDelay > -100) {
delay += 100 + VideoAudioDelay / 90;
if (VideoAudioDelay > 0) {
delay += VideoAudioDelay / 90;
}
if (AlsaStartThreshold <
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
@ -1284,7 +1302,17 @@ static int OssAddToRingbuffer(const void *samples, int count)
}
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
return 1;
}
@ -1522,7 +1550,7 @@ static int OssOpenPCM(int use_ac3)
&& !(device = AudioPCMDevice) && !(device = getenv("OSS_AUDIODEV"))) {
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) {
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;
// buffer time/delay in ms
delay = AudioBufferTime;
if (VideoAudioDelay > -100) {
delay += 100 + VideoAudioDelay / 90;
if (VideoAudioDelay > 0) {
delay += VideoAudioDelay / 90;
}
if (OssStartThreshold <
(*freq * *channels * AudioBytesProSample * delay) / 1000U) {
@ -1964,6 +1992,9 @@ static void *AudioPlayHandlerThread(void *dummy)
pthread_cond_wait(&AudioStartCond, &AudioMutex);
// cond_wait can return, without signal!
} while (!AudioRunning);
Debug(3, "audio/alsa: ----> %zd ms\n",
(RingBufferUsedBytes(AlsaRingBuffer) * 1000)
/ (AudioSampleRate * AudioChannels * AudioBytesProSample));
pthread_mutex_unlock(&AudioMutex);
#ifdef USE_AUDIORING
@ -2064,6 +2095,21 @@ static const AudioModule *AudioModules[] = {
*/
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);
}
@ -2183,7 +2229,7 @@ int AudioSetup(int *freq, int *channels, int use_ac3)
void AudioPlay(void)
{
if (!AudioPaused) {
Warning("audio: not paused, check the code\n");
Debug(3, "audio: not paused, check the code\n");
return;
}
Debug(3, "audio: resumed\n");
@ -2197,13 +2243,24 @@ void AudioPlay(void)
void AudioPause(void)
{
if (AudioPaused) {
Warning("audio: already paused, check the code\n");
Debug(3, "audio: already paused, check the code\n");
return;
}
Debug(3, "audio: paused\n");
AudioPaused = 1;
}
/**
** Set audio buffer time.
*/
void AudioSetBufferTime(int delay)
{
if (!delay) {
delay = 216;
}
AudioBufferTime = delay;
}
/**
** Set pcm audio device.
**

View File

@ -42,6 +42,8 @@ extern int AudioSetup(int *, int *, int); ///< setup audio output
extern void AudioPlay(void); ///< play 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 AudioSetDeviceAC3(const char *); ///< set pass-through device
extern void AudioSetChannel(const char *); ///< set mixer channel

248
codec.c
View File

@ -33,7 +33,7 @@
/**
** use av_parser to support insane dvb audio streams.
*/
#define USE_AVPARSER
#define noUSE_AVPARSER
/// compile with passthrough support (experimental)
#define USE_PASSTHROUGH
@ -603,8 +603,10 @@ struct _audio_decoder_
AVCodec *AudioCodec; ///< audio codec
AVCodecContext *AudioCtx; ///< audio codec context
#ifdef USE_AVPARSER
/// audio parser to support insane dvb streaks
AVCodecParserContext *AudioParser;
#endif
int PassthroughAC3; ///< current ac-3 pass-through
int SampleRate; ///< current stream sample rate
int Channels; ///< current stream channels
@ -697,10 +699,12 @@ void CodecAudioOpen(AudioDecoder * audio_decoder, const char *name,
// we do not send complete frames
audio_decoder->AudioCtx->flags |= CODEC_FLAG_TRUNCATED;
}
#ifdef USE_AVPARSER
if (!(audio_decoder->AudioParser =
av_parser_init(audio_decoder->AudioCtx->codec_id))) {
Fatal(_("codec: can't init audio parser\n"));
}
#endif
audio_decoder->SampleRate = 0;
audio_decoder->Channels = 0;
audio_decoder->HwSampleRate = 0;
@ -719,10 +723,12 @@ void CodecAudioClose(AudioDecoder * audio_decoder)
audio_resample_close(audio_decoder->ReSample);
audio_decoder->ReSample = NULL;
}
#ifdef USE_AVPARSER
if (audio_decoder->AudioParser) {
av_parser_close(audio_decoder->AudioParser);
audio_decoder->AudioParser = NULL;
}
#endif
if (audio_decoder->AudioCtx) {
pthread_mutex_lock(&CodecLockMutex);
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 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 +
FF_INPUT_BUFFER_PADDING_SIZE] __attribute__ ((aligned(16)));
@ -844,8 +850,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
av_init_packet(dpkt);
n = av_parser_parse2(audio_decoder->AudioParser, audio_ctx,
&dpkt->data, &dpkt->size, spkt->data + index, spkt->size - index,
!index ? (uint64_t) spkt->pts : AV_NOPTS_VALUE,
!index ? (uint64_t) spkt->dts : AV_NOPTS_VALUE, -1);
!index ? spkt->pts : (int64_t) AV_NOPTS_VALUE,
!index ? spkt->dts : (int64_t) AV_NOPTS_VALUE, -1);
// FIXME: make this a function for both #ifdef cases
if (dpkt->size) {
@ -871,7 +877,7 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#else
#endif
// Update audio clock
if ((uint64_t) dpkt->pts != AV_NOPTS_VALUE) {
if (dpkt->pts != (int64_t) AV_NOPTS_VALUE) {
AudioSetClock(dpkt->pts);
}
// FIXME: must first play remainings bytes, than change and play new.
@ -1059,6 +1065,8 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#else
#endif
/**
** Decode an audio packet.
**
@ -1074,62 +1082,206 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
AVCodecContext *audio_ctx;
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;
index = 0;
while (spkt->size > index) {
int n;
while (avpkt->size > index) {
int l;
int buf_sz;
AVPacket dpkt[1];
av_init_packet(dpkt);
dpkt->data = spkt->data + index;
dpkt->size = spkt->size - index;
buf_sz = sizeof(buf);
n = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, dpkt);
if (n < 0) { // no audio frame could be decompressed
l = avcodec_decode_audio3(audio_ctx, buf, &buf_sz, (AVPacket *)avpkt);
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);
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
// FIXME: ffmpeg git comeing
int got_frame;
avcodec_decode_audio4(audio_ctx, frame, &got_frame, dpkt);
avcodec_decode_audio4(audio_ctx, frame, &got_frame, avpkt);
#else
#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;
}
audio_decoder->SampleRate = audio_ctx->sample_rate;
audio_decoder->HwSampleRate = audio_ctx->sample_rate;
audio_decoder->Channels = audio_ctx->channels;
// 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
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;
}
#if 1
// or av_free_packet, make no difference here
av_destruct_packet(spkt);
#endif
}
#endif
/**
** Flush the audio decoder.
**
@ -1137,7 +1289,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
*/
void CodecAudioFlushBuffers(AudioDecoder * decoder)
{
#ifdef USE_AVPARSER
// 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);
}

View File

@ -67,6 +67,9 @@ extern void CodecAudioOpen(AudioDecoder *, const char *, int);
/// Close audio codec.
extern void CodecAudioClose(AudioDecoder *);
/// Decode an audio packet.
extern void CodecAudioDecodeOld(AudioDecoder *, const AVPacket *);
/// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);

File diff suppressed because it is too large Load Diff

View File

@ -37,6 +37,8 @@ extern "C"
/// C plugin play audio packet
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
extern void SetVolumeDevice(int);

View File

@ -835,9 +835,11 @@ class cSoftHdDevice:public cDevice
virtual void GetVideoSize(int &, int &, double &);
virtual void GetOsdSize(int &, int &, double &);
virtual int PlayVideo(const uchar *, int);
#ifndef xxUSE_TS_AUDIO
virtual int PlayAudio(const uchar *, int, uchar);
#endif
//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);
#endif
virtual void SetAudioChannelDevice(int);
@ -845,7 +847,6 @@ class cSoftHdDevice:public cDevice
virtual void SetDigitalAudioDevice(bool);
virtual void SetAudioTrackDevice(eTrackType);
virtual void SetVolumeDevice(int);
virtual int PlayAudio(const uchar *, int, uchar);
// 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
** device has an MPEG decoder).
*/
void cSoftHdDevice::
SetVideoDisplayFormat(eVideoDisplayFormat video_display_format)
void cSoftHdDevice:: SetVideoDisplayFormat(eVideoDisplayFormat
video_display_format)
{
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.
**
** @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)
{
@ -1134,6 +1141,8 @@ int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
return::PlayAudio(data, length, id);
}
#endif
void cSoftHdDevice::SetAudioTrackDevice(
__attribute__ ((unused)) eTrackType type)
{
@ -1173,6 +1182,9 @@ void cSoftHdDevice::SetVolumeDevice(int volume)
/**
** 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)
{

47
video.c
View File

@ -329,7 +329,6 @@ static xcb_atom_t NetWmState; ///< wm-state message atom
static xcb_atom_t NetWmStateFullscreen; ///< fullscreen wm-state message atom
extern uint32_t VideoSwitch; ///< ticks for channel switch
extern atomic_t VideoPacketsFilled; ///< how many of the buffer is used
#ifdef USE_VIDEO_THREAD
@ -396,19 +395,19 @@ static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
int64_t pts;
// 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 = frame->best_effort_timestamp;
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
pts = frame->pkt_dts;
}
// 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
if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
if (*pts_p != (int64_t) AV_NOPTS_VALUE) {
int64_t delta;
delta = pts - *pts_p;
@ -4224,7 +4223,7 @@ static void VaapiAdvanceFrame(void)
Warning(_
("video: display buffer empty, duping frame (%d/%d) %d\n"),
decoder->FramesDuped, decoder->FrameCounter,
atomic_read(&VideoPacketsFilled));
VideoGetBuffers());
}
last_warned_frame = decoder->FrameCounter;
if (!(decoder->FramesDisplayed % 300)) {
@ -4358,10 +4357,10 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
// FIXME: audio not known assume 333ms delay
if (decoder->DupNextFrame) {
++decoder->FramesDuped;
decoder->DupNextFrame--;
} else if ((uint64_t) audio_clock != AV_NOPTS_VALUE
&& (uint64_t) video_clock != AV_NOPTS_VALUE) {
++decoder->FramesDuped;
} else if (audio_clock != (int64_t) AV_NOPTS_VALUE
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
// both clocks are known
if (abs(video_clock - audio_clock) > 5000 * 90) {
@ -4377,6 +4376,12 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
Debug(3, "video: speed up video\n");
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)
// debug audio/video sync
@ -4386,8 +4391,7 @@ static void VaapiSyncDisplayFrame(VaapiDecoder * decoder)
VideoTimeStampString(video_clock),
abs((video_clock - audio_clock) / 90) <
9999 ? ((video_clock - audio_clock) / 90) : 88888,
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90,
atomic_read(&VideoPacketsFilled));
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers());
}
#endif
}
@ -4463,7 +4467,7 @@ static void VaapiSyncRenderFrame(VaapiDecoder * decoder,
static int64_t VaapiGetClock(const VaapiDecoder * decoder)
{
// 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;
}
// subtract buffered decoded frames
@ -7235,7 +7239,7 @@ static void VdpauAdvanceFrame(void)
Warning(_
("video: display buffer empty, duping frame (%d/%d) %d\n"),
decoder->FramesDuped, decoder->FrameCounter,
atomic_read(&VideoPacketsFilled));
VideoGetBuffers());
}
last_warned_frame = decoder->FrameCounter;
if (!(decoder->FramesDisplayed % 300)) {
@ -7371,8 +7375,9 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
if (decoder->DupNextFrame) {
decoder->DupNextFrame--;
} else if ((uint64_t) audio_clock != AV_NOPTS_VALUE
&& (uint64_t) video_clock != AV_NOPTS_VALUE) {
++decoder->FramesDuped;
} else if (audio_clock != (int64_t) AV_NOPTS_VALUE
&& video_clock != (int64_t) AV_NOPTS_VALUE) {
// both clocks are known
if (abs(video_clock - audio_clock) > 5000 * 90) {
@ -7388,6 +7393,12 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
Debug(3, "video: speed up video\n");
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)
// debug audio/video sync
@ -7397,8 +7408,7 @@ static void VdpauSyncDisplayFrame(VdpauDecoder * decoder)
VideoTimeStampString(video_clock),
abs((video_clock - audio_clock) / 90) <
9999 ? ((video_clock - audio_clock) / 90) : 88888,
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90,
atomic_read(&VideoPacketsFilled));
AudioGetDelay() / 90, (int)VideoDeltaPTS / 90, VideoGetBuffers());
}
#endif
}
@ -7480,7 +7490,7 @@ static void VdpauSyncRenderFrame(VdpauDecoder * decoder,
static int64_t VdpauGetClock(const VdpauDecoder * decoder)
{
// 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;
}
// subtract buffered decoded frames
@ -9324,6 +9334,7 @@ void VideoExit(void)
if (VideoUsedModule) {
VideoUsedModule->Exit();
}
VideoUsedModule = NULL; // FIXME: NoopModule;
#ifdef USE_GLX
if (GlxEnabled) {
GlxExit();

View File

@ -144,5 +144,6 @@ 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 VideoGetBuffers(void); ///< Get number of input buffers.
/// @}