Improved replay of recordings.

This commit is contained in:
Johns 2012-01-08 21:46:00 +01:00
parent f1551cd321
commit f6df79e8e6
9 changed files with 244 additions and 59 deletions

2
Todo
View File

@ -83,8 +83,8 @@ HDMI/SPDIF Passthrough:
Channels are wrong setup, if changing setting during operation. Channels are wrong setup, if changing setting during operation.
playback of recording playback of recording
play back is too fast
pause is not reset, when replay exit pause is not reset, when replay exit
replay/pause need 100% cpu
setup: setup:
Setup of decoder type. Setup of decoder type.

99
audio.c
View File

@ -342,6 +342,11 @@ static int AlsaPlayRingbuffer(void)
if (err == -EAGAIN) { if (err == -EAGAIN) {
goto again; goto again;
} }
/*
if (err == -EBADFD) {
goto again;
}
*/
Error(_("audio/alsa: underrun error?\n")); Error(_("audio/alsa: underrun error?\n"));
err = snd_pcm_recover(AlsaPCMHandle, err, 0); err = snd_pcm_recover(AlsaPCMHandle, err, 0);
if (err >= 0) { if (err >= 0) {
@ -370,9 +375,13 @@ static void AlsaFlushBuffers(void)
int err; int err;
RingBufferReadAdvance(AlsaRingBuffer, RingBufferUsedBytes(AlsaRingBuffer)); RingBufferReadAdvance(AlsaRingBuffer, RingBufferUsedBytes(AlsaRingBuffer));
if ((err = snd_pcm_drop(AlsaPCMHandle))) { if ((err = snd_pcm_drop(AlsaPCMHandle)) < 0) {
Error(_("audio: snd_pcm_drop(): %s\n"), snd_strerror(err)); Error(_("audio: snd_pcm_drop(): %s\n"), snd_strerror(err));
} }
if ((err = snd_pcm_prepare(AlsaPCMHandle)) < 0) {
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
}
AudioPTS = INT64_C(0x8000000000000000);
} }
#if 0 #if 0
@ -567,8 +576,20 @@ static void AlsaThread(void)
for (;;) { for (;;) {
int err; int err;
Debug(4, "audio: play loop\n");
pthread_testcancel(); pthread_testcancel();
if (AlsaFlushBuffer) {
// we can flush too many, but wo cares
Debug(3, "audio/alsa: flushing buffers\n");
AlsaFlushBuffers();
/*
if ((err = snd_pcm_prepare(AlsaPCMHandle))) {
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
}
*/
AlsaFlushBuffer = 0;
break;
}
// wait for space in kernel buffers
if ((err = snd_pcm_wait(AlsaPCMHandle, 100)) < 0) { if ((err = snd_pcm_wait(AlsaPCMHandle, 100)) < 0) {
Error(_("audio/alsa: wait underrun error?\n")); Error(_("audio/alsa: wait underrun error?\n"));
err = snd_pcm_recover(AlsaPCMHandle, err, 0); err = snd_pcm_recover(AlsaPCMHandle, err, 0);
@ -580,14 +601,7 @@ static void AlsaThread(void)
continue; continue;
} }
if (AlsaFlushBuffer) { if (AlsaFlushBuffer) {
// we can flush too many, but wo cares continue;
Debug(3, "audio/alsa: flushing buffers\n");
AlsaFlushBuffers();
if ((err = snd_pcm_prepare(AlsaPCMHandle))) {
Error(_("audio: snd_pcm_prepare(): %s\n"), snd_strerror(err));
}
AlsaFlushBuffer = 0;
break;
} }
if ((err = AlsaPlayRingbuffer())) { // empty / error if ((err = AlsaPlayRingbuffer())) { // empty / error
snd_pcm_state_t state; snd_pcm_state_t state;
@ -600,7 +614,8 @@ static void AlsaThread(void)
Debug(3, "audio/alsa: stopping play\n"); Debug(3, "audio/alsa: stopping play\n");
break; break;
} }
usleep(20 * 1000); pthread_yield();
usleep(20 * 1000); // let fill the buffers
} }
} }
} }
@ -1195,6 +1210,21 @@ static int OssPlayRingbuffer(void)
return 0; return 0;
} }
/**
** Flush oss buffers.
*/
static void OssFlushBuffers(void)
{
RingBufferReadAdvance(OssRingBuffer, RingBufferUsedBytes(OssRingBuffer));
// flush kernel buffers
if (ioctl(OssPcmFildes, SNDCTL_DSP_HALT_OUTPUT, NULL) < 0) {
Error(_("audio/oss: ioctl(SNDCTL_DSP_HALT_OUTPUT): %s\n"),
strerror(errno));
return;
}
AudioPTS = INT64_C(0x8000000000000000);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// OSS pcm polled // OSS pcm polled
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -1410,14 +1440,7 @@ static int OssSetup(int *freq, int *channels)
// flush any buffered data // flush any buffered data
{ {
AudioRunning = 0; AudioRunning = 0;
RingBufferReadAdvance(OssRingBuffer, OssFlushBuffers();
RingBufferUsedBytes(OssRingBuffer));
// flush kernel buffers
if (ioctl(OssPcmFildes, SNDCTL_DSP_HALT_OUTPUT, NULL) == -1) {
Error(_("audio/oss: ioctl(SNDCTL_DSP_HALT_OUTPUT): %s\n"),
strerror(errno));
return -1;
}
} }
AudioPTS = INT64_C(0x8000000000000000); AudioPTS = INT64_C(0x8000000000000000);
@ -1672,6 +1695,30 @@ void AudioEnqueue(const void *samples, int count)
(void)count; (void)count;
} }
/**
** Flush audio buffers.
*/
void AudioFlushBuffers(void)
{
#ifdef USE_ALSA
#ifdef USE_AUDIO_THREAD
if (AudioRunning) {
while (AudioRunning) {
AlsaFlushBuffer = 1;
usleep(1 * 1000);
}
AlsaFlushBuffer = 0;
} else
#endif
{
AlsaFlushBuffers();
}
#endif
#ifdef USE_OSS
OssFlushBuffers();
#endif
}
/** /**
** Call back to play audio polled. ** Call back to play audio polled.
*/ */
@ -1687,6 +1734,20 @@ void AudioPoller(void)
#endif #endif
} }
/**
** Get free bytes in audio output.
*/
int AudioFreeBytes(void)
{
#ifdef USE_ALSA
return RingBufferFreeBytes(AlsaRingBuffer);
#endif
#ifdef USE_OSS
return RingBufferFreeBytes(OssRingBuffer);
#endif
return -1;
}
/** /**
** Set audio clock base. ** Set audio clock base.
** **

View File

@ -1,7 +1,7 @@
/// ///
/// @file audio.h @brief Audio module headerfile /// @file audio.h @brief Audio module headerfile
/// ///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -28,12 +28,14 @@
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
extern void AudioEnqueue(const void *, int); ///< buffer audio samples extern void AudioEnqueue(const void *, int); ///< buffer audio samples
extern void AudioFlushBuffers(void); ///< flush audio buffers
extern void AudioPoller(void); ///< poll audio events/handling
extern int AudioFreeBytes(void); ///< free bytes in audio output
//extern int AudioFreeBytes(void); ///< free bytes in audio output
//extern int AudioUsedBytes(void); ///< used bytes in audio output //extern int AudioUsedBytes(void); ///< used bytes in audio output
extern void AudioSetClock(int64_t); ///< set audio clock base extern void AudioSetClock(int64_t); ///< set audio clock base
extern int64_t AudioGetClock(); ///< get current audio clock extern int64_t AudioGetClock(); ///< get current audio clock
extern uint64_t AudioGetDelay(void); ///< get current audio delay extern uint64_t AudioGetDelay(void); ///< get current audio delay
extern int AudioSetup(int *, int *); ///< setup audio output extern int AudioSetup(int *, int *); ///< setup audio output

23
codec.c
View File

@ -561,6 +561,16 @@ void CodecVideoDecode(VideoDecoder * decoder, const AVPacket * avpkt)
} }
} }
/**
** Flush the video decoder.
**
** @param decoder video decoder data
*/
void CodecVideoFlushBuffers(VideoDecoder * decoder)
{
avcodec_flush_buffers(decoder->VideoCtx);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Audio // Audio
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
@ -738,9 +748,11 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
spkt->pts = avpkt->pts; spkt->pts = avpkt->pts;
spkt->dts = avpkt->dts; spkt->dts = avpkt->dts;
#endif #endif
#ifdef DEBUG
if (!audio_decoder->AudioParser) { if (!audio_decoder->AudioParser) {
Fatal(_("codec: internal error parser freeded while running\n")); Fatal(_("codec: internal error parser freeded while running\n"));
} }
#endif
audio_ctx = audio_decoder->AudioCtx; audio_ctx = audio_decoder->AudioCtx;
index = 0; index = 0;
@ -1026,6 +1038,17 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, const AVPacket * avpkt)
#endif #endif
/**
** Flush the audio decoder.
**
** @param decoder audio decoder data
*/
void CodecAudioFlushBuffers(AudioDecoder * decoder)
{
// FIXME: reset audio parser
avcodec_flush_buffers(decoder->AudioCtx);
}
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------
// Codec // Codec
//---------------------------------------------------------------------------- //----------------------------------------------------------------------------

24
codec.h
View File

@ -1,7 +1,7 @@
/// ///
/// @file codec.h @brief Codec module headerfile /// @file codec.h @brief Codec module headerfile
/// ///
/// Copyright (c) 2009 - 2011 by Johns. All Rights Reserved. /// Copyright (c) 2009 - 2012 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -40,26 +40,32 @@ typedef struct _audio_decoder_ AudioDecoder;
/// Allocate a new video decoder context. /// Allocate a new video decoder context.
extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *); extern VideoDecoder *CodecVideoNewDecoder(VideoHwDecoder *);
/// Open video codec /// Open video codec.
extern void CodecVideoOpen(VideoDecoder *, const char *, int); extern void CodecVideoOpen(VideoDecoder *, const char *, int);
/// Close video codec /// Close video codec.
extern void CodecVideoClose(VideoDecoder *); extern void CodecVideoClose(VideoDecoder *);
/// Decode a video packet /// Decode a video packet.
extern void CodecVideoDecode(VideoDecoder *, const AVPacket * pkt); extern void CodecVideoDecode(VideoDecoder *, const AVPacket *);
/// Flush video buffers.
extern void CodecVideoFlushBuffers(VideoDecoder *);
/// Allocate a new audio decoder context. /// Allocate a new audio decoder context.
extern AudioDecoder *CodecAudioNewDecoder(void); extern AudioDecoder *CodecAudioNewDecoder(void);
/// Open audio codec /// Open audio codec.
extern void CodecAudioOpen(AudioDecoder *, const char *, int); 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 /// Decode an audio packet.
extern void CodecAudioDecode(AudioDecoder *, const AVPacket * pkt); extern void CodecAudioDecode(AudioDecoder *, const AVPacket *);
/// Flush audio buffers.
extern void CodecAudioFlushBuffers(AudioDecoder *);
/// Setup and initialize codec module. /// Setup and initialize codec module.
extern void CodecInit(void); extern void CodecInit(void);

View File

@ -59,6 +59,7 @@ static const char DeviceStopped = 1; ///< flag device stopped
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
static volatile char NewAudioStream; ///< new audio stream static volatile char NewAudioStream; ///< new audio stream
static volatile char SkipAudio; ///< skip audio stream
static AudioDecoder *MyAudioDecoder; ///< audio decoder static AudioDecoder *MyAudioDecoder; ///< audio decoder
static enum CodecID AudioCodecID; ///< current codec id static enum CodecID AudioCodecID; ///< current codec id
@ -185,10 +186,11 @@ static int FindAudioSync(const AVPacket * avpkt)
** @param size size of PES packet ** @param size size of PES packet
** @param id PES packet type ** @param id PES packet type
*/ */
void PlayAudio(const uint8_t * data, int size, int PlayAudio(const uint8_t * data, int size,
__attribute__ ((unused)) uint8_t id) __attribute__ ((unused)) uint8_t id)
{ {
int n; int n;
int osize;
AVPacket avpkt[1]; AVPacket avpkt[1];
// channel switch: SetAudioChannelDevice: SetDigitalAudioDevice: // channel switch: SetAudioChannelDevice: SetDigitalAudioDevice:
@ -199,12 +201,19 @@ void PlayAudio(const uint8_t * data, int size,
AudioCodecID = CODEC_ID_NONE; AudioCodecID = CODEC_ID_NONE;
NewAudioStream = 0; NewAudioStream = 0;
} }
if (SkipAudio) {
return size;
}
// PES header 0x00 0x00 0x01 ID // PES header 0x00 0x00 0x01 ID
// ID 0xBD 0xC0-0xCF // ID 0xBD 0xC0-0xCF
if (size < 9) { if (size < 9) {
Error(_("[softhddev] invalid audio packet\n")); Error(_("[softhddev] invalid audio packet\n"));
return; return size;
}
// Don't overrun audio buffers on replay
if (AudioFreeBytes() < 3072 * 8 * 8) { // 8 channels 8 packets
return 0;
} }
n = data[8]; // header size n = data[8]; // header size
@ -225,11 +234,12 @@ void PlayAudio(const uint8_t * data, int size,
} }
} }
osize = size;
data += 9 + n; data += 9 + n;
size -= 9 + n; // skip pes header size -= 9 + n; // skip pes header
if (size <= 0) { if (size <= 0) {
Error(_("[softhddev] invalid audio packet\n")); Error(_("[softhddev] invalid audio packet\n"));
return; return osize;
} }
// Detect audio code // Detect audio code
// MPEG-PS mp2 MPEG1, MPEG2, AC3 // MPEG-PS mp2 MPEG1, MPEG2, AC3
@ -271,7 +281,7 @@ void PlayAudio(const uint8_t * data, int size,
avpkt->size = size; avpkt->size = size;
n = FindAudioSync(avpkt); n = FindAudioSync(avpkt);
if (n < 0) { if (n < 0) {
return; return osize;
} }
if (!MyAudioDecoder) { if (!MyAudioDecoder) {
MyAudioDecoder = CodecAudioNewDecoder(); MyAudioDecoder = CodecAudioNewDecoder();
@ -286,13 +296,15 @@ void PlayAudio(const uint8_t * data, int size,
// no decoder or codec known // no decoder or codec known
if (!MyAudioDecoder || AudioCodecID == CODEC_ID_NONE) { if (!MyAudioDecoder || AudioCodecID == CODEC_ID_NONE) {
return; return osize;
} }
avpkt->data = (void *)data; avpkt->data = (void *)data;
avpkt->size = size; avpkt->size = size;
//memset(avpkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE); //memset(avpkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
CodecAudioDecode(MyAudioDecoder, avpkt); CodecAudioDecode(MyAudioDecoder, avpkt);
return osize;
} }
/** /**
@ -300,6 +312,7 @@ void PlayAudio(const uint8_t * data, int size,
*/ */
void Mute(void) void Mute(void)
{ {
SkipAudio = 1;
AudioSetVolume(0); AudioSetVolume(0);
} }
@ -480,6 +493,10 @@ int VideoDecode(void)
} }
if (VideoClearBuffers) { if (VideoClearBuffers) {
atomic_set(&VideoPacketsFilled, 0); atomic_set(&VideoPacketsFilled, 0);
VideoPacketRead = VideoPacketWrite;
if (MyVideoDecoder) {
CodecVideoFlushBuffers(MyVideoDecoder);
}
VideoClearBuffers = 0; VideoClearBuffers = 0;
return 1; return 1;
} }
@ -751,8 +768,12 @@ void SetPlayMode(void)
} }
} }
if (MyAudioDecoder) { if (MyAudioDecoder) {
if (AudioCodecID != CODEC_ID_NONE) {
NewAudioStream = 1; NewAudioStream = 1;
} }
}
VideoFreezed = 0;
SkipAudio = 0;
} }
/** /**
@ -760,9 +781,16 @@ void SetPlayMode(void)
*/ */
void Clear(void) void Clear(void)
{ {
int i;
VideoNextPacket(VideoCodecID); // terminate work
VideoClearBuffers = 1; VideoClearBuffers = 1;
// FIXME: avcodec_flush_buffers // FIXME: avcodec_flush_buffers
// FIXME: flush audio buffers AudioFlushBuffers();
for (i = 0; VideoClearBuffers && i < 20; ++i) {
usleep(1 * 1000);
}
} }
/** /**
@ -771,6 +799,7 @@ void Clear(void)
void Play(void) void Play(void)
{ {
VideoFreezed = 0; VideoFreezed = 0;
SkipAudio = 0;
// FIXME: restart audio // FIXME: restart audio
} }
@ -781,16 +810,33 @@ void Freeze(void)
{ {
VideoFreezed = 1; VideoFreezed = 1;
// FIXME: freeze audio // FIXME: freeze audio
AudioFlushBuffers();
}
/**
** Display the given I-frame as a still picture.
*/
void StillPicture(const uint8_t * data, int size)
{
// must be a PES start code
if (size < 9 || !data || data[0] || data[1] || data[2] != 0x01) {
Error(_("[softhddev] invalid PES video packet\n"));
return;
}
PlayVideo(data, size);
PlayVideo(data, size);
VideoNextPacket(VideoCodecID); // terminate work
} }
/** /**
** Poll if device is ready. Called by replay. ** Poll if device is ready. Called by replay.
**
** @param timeout timeout to become ready in ms
*/ */
int Poll(int timeout) int Poll(int timeout)
{ {
// buffers are too full // buffers are too full
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) { if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) {
Debug(3, "replay: poll %d\n", timeout);
if (timeout) { if (timeout) {
// let display thread work // let display thread work
usleep(timeout * 1000); usleep(timeout * 1000);
@ -800,6 +846,22 @@ int Poll(int timeout)
return 0; return 0;
} }
/**
** Flush the device output buffers.
**
** @param timeout timeout to flush in ms
*/
int Flush(int timeout)
{
if (atomic_read(&VideoPacketsFilled)) {
if (timeout) { // let display thread work
usleep(timeout * 1000);
}
return !atomic_read(&VideoPacketsFilled);
}
return 1;
}
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////
// OSD // OSD
////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////

View File

@ -1,7 +1,7 @@
/// ///
/// @file softhddev.h @brief software HD device plugin header file. /// @file softhddev.h @brief software HD device plugin header file.
/// ///
/// Copyright (c) 2011 by Johns. All Rights Reserved. /// Copyright (c) 2011 - 2012 by Johns. All Rights Reserved.
/// ///
/// Contributor(s): /// Contributor(s):
/// ///
@ -36,7 +36,7 @@ extern "C"
extern void OsdDrawARGB(int, int, int, int, const uint8_t *); extern void OsdDrawARGB(int, int, int, int, const uint8_t *);
/// C plugin play audio packet /// C plugin play audio packet
extern void PlayAudio(const uint8_t *, int, uint8_t); extern int PlayAudio(const uint8_t *, int, uint8_t);
/// C plugin mute audio /// C plugin mute audio
extern void Mute(void); extern void Mute(void);
/// C plugin set audio volume /// C plugin set audio volume
@ -55,8 +55,12 @@ extern "C"
extern void Play(void); extern void Play(void);
/// C plugin sets the device into "freeze frame" mode /// C plugin sets the device into "freeze frame" mode
extern void Freeze(void); extern void Freeze(void);
/// C plugin display I-frame as a still picture.
extern void StillPicture(const uint8_t *, int);
/// C plugin poll if ready /// C plugin poll if ready
extern int Poll(int); extern int Poll(int);
/// C plugin flush output buffers
extern int Flush(int);
/// C plugin command line help /// C plugin command line help
extern const char *CommandLineHelp(void); extern const char *CommandLineHelp(void);

View File

@ -499,9 +499,14 @@ int64_t cSoftHdDevice::GetSTC(void)
return::VideoGetClock(); return::VideoGetClock();
} }
void cSoftHdDevice::TrickSpeed(int Speed) /**
** Set trick play speed.
**
** @param speed trick speed
*/
void cSoftHdDevice::TrickSpeed(int speed)
{ {
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, Speed); dsyslog("[softhddev]%s: %d\n", __FUNCTION__, speed);
} }
void cSoftHdDevice::Clear(void) void cSoftHdDevice::Clear(void)
@ -533,24 +538,37 @@ void cSoftHdDevice::Mute(void)
dsyslog("[softhddev]%s:\n", __FUNCTION__); dsyslog("[softhddev]%s:\n", __FUNCTION__);
cDevice::Mute(); cDevice::Mute();
::Mute(); ::Mute();
} }
void cSoftHdDevice::SetVolumeDevice(int volume) void cSoftHdDevice::SetVolumeDevice(int volume)
{ {
//dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume); dsyslog("[softhddev]%s: %d\n", __FUNCTION__, volume);
::SetVolumeDevice(volume); ::SetVolumeDevice(volume);
} }
void cSoftHdDevice::StillPicture( /**
__attribute__ ((unused)) const uchar * data, __attribute__ ((unused)) ** Display the given I-frame as a still picture.
int length) */
void cSoftHdDevice::StillPicture(const uchar * data, int length)
{ {
dsyslog("[softhddev]%s:\n", __FUNCTION__); dsyslog("[softhddev]%s:\n", __FUNCTION__);
if ( data[0] == 0x47 ) { // ts sync
cDevice::StillPicture(data, length);
return;
}
::StillPicture(data, length);
} }
/**
** Check if the device is ready for further action.
**
** @param poller file handles (unused)
** @param timeout_ms timeout in ms to become ready
*/
bool cSoftHdDevice::Poll( bool cSoftHdDevice::Poll(
__attribute__ ((unused)) cPoller & poller, int timeout_ms) __attribute__ ((unused)) cPoller & poller, int timeout_ms)
{ {
@ -559,11 +577,16 @@ bool cSoftHdDevice::Poll(
return::Poll(timeout_ms); return::Poll(timeout_ms);
} }
/**
** Flush the device output buffers.
**
** @param timeout_ms timeout in ms to become ready
*/
bool cSoftHdDevice::Flush(int timeout_ms) bool cSoftHdDevice::Flush(int timeout_ms)
{ {
dsyslog("[softhddev]%s: %d ms\n", __FUNCTION__, timeout_ms); dsyslog("[softhddev]%s: %d ms\n", __FUNCTION__, timeout_ms);
return true; return::Flush(timeout_ms);
} }
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@ -580,13 +603,14 @@ void cSoftHdDevice::GetOsdSize(int &width, int &height, double &pixel_aspect)
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/**
** Play a audio packet.
*/
int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id) int cSoftHdDevice::PlayAudio(const uchar * data, int length, uchar id)
{ {
//dsyslog("[softhddev]%s: %p %p %d %d\n", __FUNCTION__, this, data, length, id); //dsyslog("[softhddev]%s: %p %p %d %d\n", __FUNCTION__, this, data, length, id);
::PlayAudio(data, length, id); return::PlayAudio(data, length, id);
return length;
} }
void cSoftHdDevice::SetAudioTrackDevice( void cSoftHdDevice::SetAudioTrackDevice(

15
video.c
View File

@ -6245,6 +6245,7 @@ enum PixelFormat Video_get_format(VideoHwDecoder * decoder,
static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame) static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
{ {
int64_t pts; int64_t pts;
int64_t delta;
// update video clock // update video clock
if ((uint64_t) * pts_p != AV_NOPTS_VALUE) { if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
@ -6259,14 +6260,16 @@ static void VideoSetPts(int64_t * pts_p, int interlaced, const AVFrame * frame)
if (!pts) { if (!pts) {
pts = AV_NOPTS_VALUE; pts = AV_NOPTS_VALUE;
} }
// build a monotonic pts
if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
if (pts - *pts_p < -10 * 90) {
pts = AV_NOPTS_VALUE;
}
}
// libav: sets only pkt_dts which can be 0 // libav: sets only pkt_dts which can be 0
if ((uint64_t) pts != AV_NOPTS_VALUE) { if ((uint64_t) pts != AV_NOPTS_VALUE) {
// build a monotonic pts
if ((uint64_t) * pts_p != AV_NOPTS_VALUE) {
delta = pts - *pts_p;
// ignore negative jumps
if (delta > -300 * 90 && delta < -15 * 90) {
return;
}
}
if (*pts_p != pts) { if (*pts_p != pts) {
Debug(3, Debug(3,
"video: %#012" PRIx64 "->%#012" PRIx64 " %4" PRId64 " pts\n", "video: %#012" PRIx64 "->%#012" PRIx64 " %4" PRId64 " pts\n",