summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog1
-rw-r--r--Todo6
-rw-r--r--codec.c11
-rw-r--r--softhddev.c58
-rw-r--r--softhddev.h6
-rw-r--r--softhddevice.cpp45
-rw-r--r--video.c35
-rw-r--r--video.h2
8 files changed, 139 insertions, 25 deletions
diff --git a/ChangeLog b/ChangeLog
index ef97925..d2eb94f 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,6 +1,7 @@
User johns
Date:
+ Initial support of replay.
Workaround for libva-driver-intel 1080i problems.
DisplayFrame displays now only a single frame.
Add deinterlace/scaling modes to setup.
diff --git a/Todo b/Todo
index 482f5ac..052299b 100644
--- a/Todo
+++ b/Todo
@@ -14,6 +14,7 @@ x11:
support resize of x11 window
support fullscreen window
support fullscreen / window toggle
+ close window should send power button
audio/alsa:
video/audio asyncron
@@ -26,3 +27,8 @@ audio/alsa:
this channels has packet start not at the beginning of the start packet
playback of recording
+
+setup:
+ Saved parameters aren't used as default for setup menu.
+ Setup parameters are not used until restart.
+ Can a notice be added to the setup menu?
diff --git a/codec.c b/codec.c
index 52e79bd..82fcef2 100644
--- a/codec.c
+++ b/codec.c
@@ -567,28 +567,29 @@ void CodecAudioDecode(AudioDecoder * audio_decoder, AVPacket * avpkt)
Fatal(_("codec: internal error parser freeded while running\n"));
}
#define spkt avpkt
-#if 0
+#if 0 // didn't fix crash in av_parser_parse2
AVPacket spkt[1];
- if (av_new_packet(spkt, avpkt->size + FF_INPUT_BUFFER_PADDING_SIZE)) {
+ // 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);
- memset(spkt->data + avpkt->size, 0, FF_INPUT_BUFFER_PADDING_SIZE);
spkt->pts = avpkt->pts;
+ spkt->dts = avpkt->dts;
#endif
audio_ctx = audio_decoder->AudioCtx;
index = 0;
- while (avpkt->size > index) {
+ while (spkt->size > index) {
int n;
int l;
AVPacket dpkt[1];
av_init_packet(dpkt);
n = av_parser_parse2(audio_decoder->AudioParser, audio_ctx,
- &dpkt->data, &dpkt->size, spkt->data + index, avpkt->size - index,
+ &dpkt->data, &dpkt->size, spkt->data + index, spkt->size - index,
!index ? (uint64_t) spkt->pts : AV_NOPTS_VALUE, AV_NOPTS_VALUE,
-1);
diff --git a/softhddev.c b/softhddev.c
index b4fc331..e5935c7 100644
--- a/softhddev.c
+++ b/softhddev.c
@@ -200,8 +200,13 @@ static AVPacket VideoPacketRb[VIDEO_PACKET_MAX];
static int VideoPacketWrite; ///< write pointer
static int VideoPacketRead; ///< read pointer
static atomic_t VideoPacketsFilled; ///< how many of the buffer is used
+static char VideoFreezed; ///< video freezed
+static char VideoClearBuffers; ///< clear video buffers
+
+#ifdef DEBUG
static int VideoMaxPacketSize; ///< biggest used packet buffer
static uint32_t VideoStartTick; ///< video start tick
+#endif
extern void VideoWakeup(void); ///< wakeup video handler
@@ -327,6 +332,15 @@ int VideoDecode(void)
int saved_size;
static int last_codec_id = CODEC_ID_NONE;
+ if (VideoFreezed) {
+ return 1;
+ }
+ if (VideoClearBuffers) {
+ atomic_set(&VideoPacketsFilled, 0);
+ VideoClearBuffers = 0;
+ return 1;
+ }
+
filled = atomic_read(&VideoPacketsFilled);
//Debug(3, "video: decode %3d packets buffered\n", filled);
if (!filled) {
@@ -503,6 +517,10 @@ int PlayVideo(const uint8_t * data, int size)
}
if (NewVideoStream) {
Debug(3, "video: new stream %d\n", GetMsTicks() - VideoSwitch);
+ // FIXME: hack to test results
+ if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
+ return 0;
+ }
VideoNextPacket(CODEC_ID_NONE);
VideoCodecID = CODEC_ID_NONE;
NewVideoStream = 0;
@@ -539,6 +557,10 @@ int PlayVideo(const uint8_t * data, int size)
if ((data[6] & 0xC0) != 0x80 || (!check[0] && !check[1]
&& check[2] == 0x1)) {
if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
+ // FIXME: hack to test results
+ if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
+ return 0;
+ }
VideoNextPacket(CODEC_ID_MPEG2VIDEO);
} else {
Debug(3, "video: mpeg2 detected\n");
@@ -548,6 +570,10 @@ int PlayVideo(const uint8_t * data, int size)
} else if (!check[0] && !check[1] && !check[2] && check[3] == 0x1
&& check[4] == 0x09) {
if (VideoCodecID == CODEC_ID_H264) {
+ // FIXME: hack to test results
+ if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
+ return 0;
+ }
VideoNextPacket(CODEC_ID_H264);
} else {
Debug(3, "video: h264 detected\n");
@@ -561,6 +587,10 @@ int PlayVideo(const uint8_t * data, int size)
}
if (VideoCodecID == CODEC_ID_MPEG2VIDEO) {
// mpeg codec supports incomplete packages
+ // FIXME: hack to test results
+ if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX - 1) {
+ return 0;
+ }
VideoNextPacket(CODEC_ID_MPEG2VIDEO);
}
}
@@ -595,11 +625,37 @@ void SetPlayMode(void)
}
/**
+** Clears all video and audio data from the device.
+*/
+void Clear(void)
+{
+ VideoClearBuffers = 1;
+ // FIXME: flush audio buffers
+}
+
+/**
+** Sets the device into play mode.
+*/
+void Play(void)
+{
+ VideoFreezed = 0;
+ // FIXME: restart audio
+}
+
+/**
+** Sets the device into "freeze frame" mode.
+*/
+void Freeze(void)
+{
+ VideoFreezed = 1;
+ // FIXME: freeze audio
+}
+
+/**
** Poll if device is ready. Called by replay.
*/
int Poll(int timeout)
{
- return 1;
// buffers are too full
if (atomic_read(&VideoPacketsFilled) >= VIDEO_PACKET_MAX / 2) {
if (timeout) {
diff --git a/softhddev.h b/softhddev.h
index 817be2c..c54fd2e 100644
--- a/softhddev.h
+++ b/softhddev.h
@@ -49,6 +49,12 @@ extern "C"
/// C plugin set play mode
extern void SetPlayMode(void);
+ /// C plugin clears all video and audio data from the device
+ extern void Clear(void);
+ /// C plugin sets the device into play mode
+ extern void Play(void);
+ /// C plugin sets the device into "freeze frame" mode
+ extern void Freeze(void);
/// C plugin poll if ready
extern int Poll(int);
diff --git a/softhddevice.cpp b/softhddevice.cpp
index dfaddbd..9ef3fa3 100644
--- a/softhddevice.cpp
+++ b/softhddevice.cpp
@@ -62,11 +62,11 @@ class cSoftRemote:public cRemote
public:
cSoftRemote(const char *name):cRemote(name)
{
- };
+ }
bool Put(const char *code, bool repeat = false, bool release = false) {
return cRemote::Put(code, repeat, release);
- };
+ }
};
extern "C" void FeedKeyPress(const char *keymap, const char *key, int repeat,
@@ -168,13 +168,13 @@ void cSoftOsd::Flush(void)
// FIXME: need only to convert and upload dirty areas
// DrawBitmap(bitmap);
- argb = (uint8_t *) malloc(bitmap->Width() * bitmap->Height() * 4);
-
w = bitmap->Width();
h = bitmap->Height();
+ argb = (uint8_t *) malloc(w * h * sizeof(uint32_t));
+
for (y = 0; y < h; ++y) {
for (x = 0; x < w; ++x) {
- ((uint32_t *) argb)[(x + y * w)] = bitmap->GetColor(x, y);
+ ((uint32_t *) argb)[x + y * w] = bitmap->GetColor(x, y);
}
}
@@ -353,12 +353,6 @@ cSoftHdDevice::~cSoftHdDevice(void)
dsyslog("[softhddev]%s:\n", __FUNCTION__);
}
-int64_t cSoftHdDevice::GetSTC(void)
-{
- dsyslog("[softhddev]%s:\n", __FUNCTION__);
- return 0L;
-};
-
void cSoftHdDevice::MakePrimaryDevice(bool on)
{
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, on);
@@ -385,7 +379,7 @@ cSpuDecoder *cSoftHdDevice::GetSpuDecoder(void)
spuDecoder = new cDvbSpuDecoder();
}
return spuDecoder;
-};
+}
bool cSoftHdDevice::HasDecoder(void) const
{
@@ -421,6 +415,13 @@ bool cSoftHdDevice::SetPlayMode(ePlayMode PlayMode)
return true;
}
+int64_t cSoftHdDevice::GetSTC(void)
+{
+ // dsyslog("[softhddev]%s:\n", __FUNCTION__);
+
+ return ::VideoGetClock();
+}
+
void cSoftHdDevice::TrickSpeed(int Speed)
{
dsyslog("[softhddev]%s: %d\n", __FUNCTION__, Speed);
@@ -429,16 +430,25 @@ void cSoftHdDevice::TrickSpeed(int Speed)
void cSoftHdDevice::Clear(void)
{
dsyslog("[softhddev]%s:\n", __FUNCTION__);
+
+ cDevice::Clear();
+ ::Clear();
}
void cSoftHdDevice::Play(void)
{
dsyslog("[softhddev]%s:\n", __FUNCTION__);
+
+ cDevice::Play();
+ ::Play();
}
void cSoftHdDevice::Freeze(void)
{
dsyslog("[softhddev]%s:\n", __FUNCTION__);
+
+ cDevice::Freeze();
+ ::Freeze();
}
void cSoftHdDevice::Mute(void)
@@ -467,16 +477,17 @@ void cSoftHdDevice::StillPicture(
bool cSoftHdDevice::Poll(
__attribute__ ((unused)) cPoller & poller, int timeout_ms)
{
- dsyslog("[softhddev]%s: %d\n", __FUNCTION__, timeout_ms);
+ // dsyslog("[softhddev]%s: %d\n", __FUNCTION__, timeout_ms);
return ::Poll(timeout_ms);
}
-bool cSoftHdDevice::Flush( __attribute__ ((unused)) int timeout_ms)
+bool cSoftHdDevice::Flush(int timeout_ms)
{
- dsyslog("[softhddev]%s:\n", __FUNCTION__);
+ dsyslog("[softhddev]%s: %d ms\n", __FUNCTION__, timeout_ms);
+
return true;
-};
+}
// ----------------------------------------------------------------------------
@@ -552,7 +563,7 @@ uchar *cSoftHdDevice::GrabImage(int &size, bool jpeg, int quality, int sizex,
quality, sizex, sizey);
return NULL;
-};
+}
//////////////////////////////////////////////////////////////////////////////
// cPlugin
diff --git a/video.c b/video.c
index 82a6d9e..f209dd5 100644
--- a/video.c
+++ b/video.c
@@ -3122,11 +3122,15 @@ static void *VideoDisplayHandlerThread(void *dummy)
decoder->StartTime.tv_nsec)) > delay)) {
if (!(decoder->FrameCounter % (50 * 10))) {
+ static int64_t last_video_clock;
+
Debug(3,
- "video: %09" PRIx64 "-%09" PRIx64 " pts %+dms %" PRId64
- "\n", audio_clock, video_clock,
+ "video: %09" PRIx64 "-%09" PRIx64 " %4" PRId64
+ " pts %+dms %" PRId64 "\n", audio_clock, video_clock,
+ video_clock - last_video_clock,
(int)(audio_clock - video_clock) / 90,
AudioGetDelay() / 90);
+ last_video_clock = video_clock;
}
if (0 && audio_clock < video_clock + 2000) {
err = 1;
@@ -3562,6 +3566,33 @@ void VideoDisplayHandler(void)
#endif
+/**
+** Get video clock.
+**
+** @note this isn't monoton, decoding reorders frames.
+*/
+int64_t VideoGetClock(void)
+{
+#ifdef USE_VAAPI
+ if (VideoVaapiEnabled) {
+ // pts is the timestamp of the latest decoded frame
+ // FIXME: +-20ms which field is currently displayed
+ if ((uint64_t) VaapiDecoders[0]->PTS == AV_NOPTS_VALUE) {
+ return AV_NOPTS_VALUE;
+ }
+ return VaapiDecoders[0]->PTS -
+ (VaapiDecoders[0]->Interlaced ? 40 : 20) * 90 *
+ atomic_read(&VaapiDecoders[0]->SurfacesFilled);
+ }
+#endif
+#ifdef USE_VDPAU
+ if (VideoVdpauEnabled) {
+ return 0L;
+ }
+#endif
+ return 0L;
+}
+
//----------------------------------------------------------------------------
// Setup
//----------------------------------------------------------------------------
diff --git a/video.h b/video.h
index 87bc181..47fcf41 100644
--- a/video.h
+++ b/video.h
@@ -83,6 +83,8 @@ extern void VideoOsdClear(void);
/// Draw an OSD ARGB image
extern void VideoOsdDrawARGB(int, int, int, int, const uint8_t *);
+extern int64_t VideoGetClock(void); ///< get video clock
+
extern void VideoOsdInit(void); ///< setup osd
extern void VideoOsdExit(void); ///< cleanup osd