From 2d52b68c2d9d5dc0e9bbb4d599b68e7374fb8fc8 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Thu, 5 Jul 2012 20:24:40 +0200 Subject: [PATCH 1/5] spark: implement cVideo::getBlank() this is a hack: the "mailbox" irq count does not increase if the decoders are not decoding, so we use this to determine if the video is in really playing. --- libspark/video.cpp | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/libspark/video.cpp b/libspark/video.cpp index b18fa11..49aae66 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -490,8 +490,34 @@ void cVideo::Standby(unsigned int bOn) int cVideo::getBlank(void) { - lt_debug("%s\n", __FUNCTION__); - return 0; + static unsigned int lastcount = 0; + unsigned int count = 0; + size_t n = 0; + ssize_t r; + char *line = NULL; + char *p; + /* hack: the "mailbox" irq is not increasing if + * no audio or video is decoded... */ + FILE *f = fopen("/proc/interrupts", "r"); + if (! f) /* huh? */ + return 0; + while ((r = getline(&line, &n, f)) != -1) + { + if (r <= strlen("mailbox")) /* should not happen... */ + continue; + line[r - 1] = 0; /* remove \n */ + if (!strcmp(&line[r - 1 - strlen("mailbox")], "mailbox")) + { + count = atoi(line + 5); + break; + } + } + free(line); + fclose(f); + int ret = (count == lastcount); /* no new decode -> return 1 */ + lt_debug("%s: %d (irq++: %d)\n", __func__, ret, count - lastcount); + lastcount = count; + return ret; } /* this function is regularly called, checks if video parameters From 618d1d65257acf4235cceef6bb0c1de7bf9e44dd Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 14 Jul 2012 10:54:01 +0200 Subject: [PATCH 2/5] triple: add necessary locking for inbuf_pos in cPlayback --- libtriple/playback_td.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/libtriple/playback_td.cpp b/libtriple/playback_td.cpp index ed8684c..e5c8e19 100644 --- a/libtriple/playback_td.cpp +++ b/libtriple/playback_td.cpp @@ -28,6 +28,7 @@ static pthread_cond_t playback_ready_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t playback_ready_mutex = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t currpos_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_mutex_t inbufpos_mutex = PTHREAD_MUTEX_INITIALIZER; static int dvrfd = -1; static int streamtype; @@ -295,7 +296,10 @@ void cPlayback::playthread(void) if (playstate == STATE_INIT) { /* hack for timeshift to determine start PTS */ - if (inbuf_read() < 0) + pthread_mutex_lock(&inbufpos_mutex); + ret = inbuf_read(); + pthread_mutex_unlock(&inbufpos_mutex); + if (ret < 0) break; usleep(100000); if (pts_start == -1) @@ -308,7 +312,10 @@ void cPlayback::playthread(void) usleep(1); continue; } - if (inbuf_read() < 0) + pthread_mutex_lock(&inbufpos_mutex); + ret = inbuf_read(); + pthread_mutex_unlock(&inbufpos_mutex); + if (ret < 0) break; /* autoselect PID for PLAYMODE_FILE */ @@ -326,9 +333,13 @@ void cPlayback::playthread(void) } } + pthread_mutex_lock(&inbufpos_mutex); towrite = inbuf_pos / 188 * 188; /* TODO: smaller chunks? */ if (towrite == 0) + { + pthread_mutex_unlock(&inbufpos_mutex); continue; + } retry: ret = write(dvrfd, inbuf, towrite); if (ret < 0) @@ -340,6 +351,7 @@ void cPlayback::playthread(void) } memmove(inbuf, inbuf + ret, inbuf_pos - ret); inbuf_pos -= ret; + pthread_mutex_unlock(&inbufpos_mutex); } pthread_cleanup_pop(1); @@ -597,12 +609,14 @@ off_t cPlayback::seek_to_pts(int64_t pts) newpos = mp_seekSync(newpos); if (newpos < 0) return newpos; + pthread_mutex_lock(&inbufpos_mutex); inbuf_pos = 0; inbuf_sync = 0; while (inbuf_pos < INBUF_SIZE * 8 / 10) { if (inbuf_read() <= 0) break; // EOF } + pthread_mutex_unlock(&inbufpos_mutex); if (pts_curr < pts_start) tmppts = pts_curr + 0x200000000ULL - pts_start; else @@ -786,6 +800,7 @@ int64_t cPlayback::get_PES_PTS(uint8_t *buf, int len, bool last) return pts; } +/* needs to be called with inbufpos_mutex locked! */ ssize_t cPlayback::inbuf_read() { if (filetype == FILETYPE_UNKNOWN) From ca321148636eaef19c520a17358e39d64cf0bb82 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 14 Jul 2012 18:13:55 +0200 Subject: [PATCH 3/5] triple: implement cVideo::getBlank() another hack :-) make the "blank" still-mpg 24fps and then check in getBlank() if the framerate is still 24fps, which means that no video has been decoded since blanking --- libtriple/video_td.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/libtriple/video_td.cpp b/libtriple/video_td.cpp index 7bf7c5b..356b023 100644 --- a/libtriple/video_td.cpp +++ b/libtriple/video_td.cpp @@ -108,6 +108,11 @@ cVideo::cVideo(int, void *, void *) free(blank_data[i]); /* don't leak... */ blank_data[i] = NULL; } + else + { /* set framerate to 24fps... see getBlank() */ + ((char *)blank_data[i])[7] &= 0xF0; + ((char *)blank_data[i])[7] += 2; + } } close(blankfd); } @@ -497,8 +502,15 @@ void cVideo::Standby(unsigned int bOn) int cVideo::getBlank(void) { - lt_debug("%s\n", __FUNCTION__); - return 0; + VIDEOINFO v; + memset(&v, 0, sizeof(v)); + ioctl(fd, MPEG_VID_GET_V_INFO, &v); + /* HACK HACK HACK :-) + * setBlank() puts a 24fps black mpeg into the decoder... + * regular broadcast does not have 24fps, so if it is still + * there, video did not decode... */ + lt_debug("%s: %hu (blank = 2)\n", __func__, v.frame_rate); + return (v.frame_rate == 2); } /* set zoom in percent (100% == 1:1) */ From caeb3f42304a157a01d69c36f9c6d132fca5923b Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 14 Jul 2012 20:02:36 +0200 Subject: [PATCH 4/5] azbox: reset PIG during videodecoder init --- azbox/video.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/azbox/video.cpp b/azbox/video.cpp index f561f40..0e679c2 100644 --- a/azbox/video.cpp +++ b/azbox/video.cpp @@ -112,6 +112,7 @@ cVideo::cVideo(int, void *, void *) close(blankfd); } openDevice(); + Pig(-1, -1, -1, -1); } cVideo::~cVideo(void) From 5583233e9e9afa9f0aa55f50cc5fa9a434623cb6 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 15 Jul 2012 11:44:16 +0200 Subject: [PATCH 5/5] spark,azbox: make demux FD nonblocking ...except for DMX_PSI_CHANNEL, which does not seem to expect that. --- azbox/dmx.cpp | 4 ++++ libspark/dmx.cpp | 3 +++ 2 files changed, 7 insertions(+) diff --git a/azbox/dmx.cpp b/azbox/dmx.cpp index 1353cfd..80d500a 100644 --- a/azbox/dmx.cpp +++ b/azbox/dmx.cpp @@ -95,6 +95,10 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe int flags = O_RDWR; if (fd > -1) lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd); + + if (pes_type != DMX_PSI_CHANNEL) + flags |= O_NONBLOCK; + fd = open(devname[devnum], flags); if (fd < 0) { diff --git a/libspark/dmx.cpp b/libspark/dmx.cpp index 188fd5f..bc5c0c2 100644 --- a/libspark/dmx.cpp +++ b/libspark/dmx.cpp @@ -94,6 +94,9 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe int flags = O_RDWR; if (fd > -1) lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd); + + if (pes_type != DMX_PSI_CHANNEL) + flags |= O_NONBLOCK; #if 0 if (pes_type == DMX_TP_CHANNEL) {