From ca5b505b857a8319305ac9a1f1646e773060ae92 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 15 Aug 2010 17:12:27 +0200 Subject: [PATCH 0001/1070] add *.so to gitignore file Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/223de4019d521262c562b5e870cb361fd3589706 Author: Stefan Seyfried Date: 2010-08-15 (Sun, 15 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index c341c7b38..82a60602d 100644 --- a/.gitignore +++ b/.gitignore @@ -20,6 +20,7 @@ INSTALL .libs .deps *.o +*.so *.lo *.a *.la From 93d4db23ac72c356b31f52caf8bf73dac5fbcc3c Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 8 Aug 2010 14:00:09 +0200 Subject: [PATCH 0002/1070] libtriple: add lt_debug() for controllable debug output Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/34a95c04c0a2628d2563e18d659a6f5e07954a0b Author: Stefan Seyfried Date: 2010-08-08 (Sun, 08 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/Makefile.am | 1 + lib/libtriple/lt_debug.cpp | 18 ++++++++++++++++++ lib/libtriple/lt_debug.h | 4 ++++ 3 files changed, 23 insertions(+) create mode 100644 lib/libtriple/lt_debug.cpp create mode 100644 lib/libtriple/lt_debug.h diff --git a/lib/libtriple/Makefile.am b/lib/libtriple/Makefile.am index ee7d2b627..5d98bf2db 100644 --- a/lib/libtriple/Makefile.am +++ b/lib/libtriple/Makefile.am @@ -11,6 +11,7 @@ noinst_LIBRARIES = libtriple.a AM_CPPFLAGS = -fno-rtti -fno-exceptions libtriple_a_SOURCES = \ + lt_debug.cpp \ dmx_td.cpp \ video_td.cpp \ audio_td.cpp \ diff --git a/lib/libtriple/lt_debug.cpp b/lib/libtriple/lt_debug.cpp new file mode 100644 index 000000000..38a424e56 --- /dev/null +++ b/lib/libtriple/lt_debug.cpp @@ -0,0 +1,18 @@ +/* libtriple debug functions */ + +#include +#include + +int cnxt_debug = 0; + +void lt_debug(const char *fmt, ...) +{ + if (! cnxt_debug) + return; + + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + diff --git a/lib/libtriple/lt_debug.h b/lib/libtriple/lt_debug.h new file mode 100644 index 000000000..90340edb5 --- /dev/null +++ b/lib/libtriple/lt_debug.h @@ -0,0 +1,4 @@ +#ifndef __LT_DEBUG_H +#define __LT_DEBUG_H +void lt_debug(const char *fmt, ...); +#endif From 5f0c2be71cbdf4cbc4fa1677490f09491971fb18 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Fri, 26 Feb 2010 21:14:04 +0100 Subject: [PATCH 0003/1070] libtriple: implement working cDemux class Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/ca7c6eeba6d1a459845ff4349d8603222d30ecc1 Author: Stefan Seyfried Date: 2010-02-26 (Fri, 26 Feb 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/dmx_td.cpp | 442 +++++++++++++++++++++++++++++++++++++++ lib/libtriple/dmx_td.h | 56 +++++ 2 files changed, 498 insertions(+) create mode 100644 lib/libtriple/dmx_td.cpp create mode 100644 lib/libtriple/dmx_td.h diff --git a/lib/libtriple/dmx_td.cpp b/lib/libtriple/dmx_td.cpp new file mode 100644 index 000000000..e56400119 --- /dev/null +++ b/lib/libtriple/dmx_td.cpp @@ -0,0 +1,442 @@ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "dmx_td.h" +#include "lt_debug.h" + +cDemux *videoDemux = NULL; +cDemux *audioDemux = NULL; +//cDemux *pcrDemux = NULL; + +static const char *DMX_T[] = { + "", + "DMX_VIDEO_CHANNEL", + "DMX_AUDIO_CHANNEL", + "DMX_PES_CHANNEL", + "DMX_PSI_CHANNEL", + "DMX_PIP_CHANNEL", + "DMX_TP_CHANNEL", + "DMX_PCR_ONLY_CHANNEL" +}; + +/* map the device numbers as used to the TD devices */ +static const char *devname[] = { + "/dev/" DEVICE_NAME_DEMUX "0", + "/dev/" DEVICE_NAME_DEMUX "1", + "/dev/" DEVICE_NAME_DEMUX "2", +}; + +cDemux::cDemux(int n) +{ + if (n < 0 || n > 2) + { + fprintf(stderr, "ERROR: cDemux::cDemux, n invalid (%d)\n", n); + num = 0; + } + else + num = n; + fd = -1; +} + +cDemux::~cDemux() +{ + fprintf(stderr, "cDemux::%s #%d fd: %d\n", __FUNCTION__, num, fd); + Close(); +} + +bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize) +{ + if (fd > -1) + fprintf(stderr, "cDemux::Open FD ALREADY OPENED? fd = %d\n", fd); + fd = open(devname[num], O_RDWR); + if (fd < 0) + { + fprintf(stderr, "cDemux::Open %s: %m", devname[num]); + return false; + } + lt_debug("cDemux::Open #%d pes_type: %s (%d), uBufferSize: %d devname: %s fd: %d\n", + num, DMX_T[pes_type], pes_type, uBufferSize, devname[num], fd); + + dmx_type = pes_type; + + if (!pesfds.empty()) + { + fprintf(stderr, "ERROR! pesfds not empty!\n"); /* TODO: error handling */ + return false; + } + if (pes_type == DMX_TP_CHANNEL) + { + struct demux_bucket_para bp; + bp.unloader.unloader_type = UNLOADER_TYPE_TRANSPORT; + bp.unloader.threshold = 128; + ioctl(fd, DEMUX_SELECT_SOURCE, INPUT_FROM_CHANNEL0); + ioctl(fd, DEMUX_SET_BUFFER_SIZE, 230400); + ioctl(fd, DEMUX_FILTER_BUCKET_SET, &bp); + return true; + } + if (uBufferSize > 0) + { + /* probably uBufferSize == 0 means "use default size". TODO: find a reasonable default */ + if (ioctl(fd, DEMUX_SET_BUFFER_SIZE, uBufferSize) < 0) + fprintf(stderr, "cDemux::Open DEMUX_SET_BUFFER_SIZE failed (%m)\n"); + } + + return true; +} + +void cDemux::Close(void) +{ + if (fd < 0) + { + fprintf(stderr, "cDemux::%s #%d: not open!\n", __FUNCTION__, num); + return; + } + + for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) + { + fprintf(stderr, "iterator: stopping and closing demux fd %d\n", *i); + if (ioctl(*i, DEMUX_STOP) < 0) + perror("DEMUX_STOP"); + if (close(*i) < 0) + perror("close"); + } + pesfds.clear(); + ioctl(fd, DEMUX_STOP); + close(fd); + fd = -1; +} + +bool cDemux::Start(void) +{ + if (fd < 0) + { + fprintf(stderr, "cDemux::%s #%d: not open!\n", __FUNCTION__, num); + return false; + } + + for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) + { + fprintf(stderr, "iterator: starting demux fd %d\n", *i); + if (ioctl(*i, DEMUX_START) < 0) + perror("DEMUX_START"); + } + ioctl(fd, DEMUX_START); + return true; +} + +bool cDemux::Stop(void) +{ + if (fd < 0) + { + fprintf(stderr, "cDemux::%s #%d: not open!\n", __FUNCTION__, num); + return false; + } + for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) + { + fprintf(stderr, "iterator: stopping demux fd %d\n", *i); + if (ioctl(*i, DEMUX_STOP) < 0) + perror("DEMUX_STOP"); + } + ioctl(fd, DEMUX_STOP); + return true; +} + +int cDemux::Read(unsigned char *buff, int len, int timeout) +{ +#if 0 + if (len != 4095 && timeout != 10) + fprintf(stderr, "cDemux::%s #%d fd: %d type: %s len: %d timeout: %d\n", + __FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout); +#endif + int rc; + struct pollfd ufds; + ufds.fd = fd; + ufds.events = POLLIN; + ufds.revents = 0; + + if (timeout > 0) + { + retry: + rc = ::poll(&ufds, 1, timeout); + if (!rc) + return 0; // timeout + else if (rc < 0) + { + perror("[cDemux::Read] poll"); + /* happens, when running under gdb... */ + if (errno == EINTR) + goto retry; + return -1; + } + if (ufds.revents & POLLERR) /* POLLERR means buffer error, i.e. buffer overflow */ + { + fprintf(stderr, "[cDemux::Read] received POLLERR, fd %d, revents 0x%x\n", fd, ufds.revents); + /* this seems to happen sometimes at recording start, without bad effects */ + return 0; + } + if (ufds.revents & POLLHUP) /* we get POLLHUP if e.g. a too big DMX_BUFFER_SIZE was set */ + { + fprintf(stderr, "[cDemux::Read] received POLLHUP, fd %d\n", fd); + return -1; + } + if (!(ufds.revents & POLLIN)) /* we requested POLLIN but did not get it? */ + { + fprintf(stderr, "cDemux::%s: not ufds.revents&POLLIN, please report! " + "revents: 0x%x fd: %d rc: %d '%m'\n", __FUNCTION__, ufds.revents, fd, rc); + return 0; + } + } + + rc = ::read(fd, buff, len); + //fprintf(stderr, "fd %d ret: %d\n", fd, rc); + if (rc < 0) + perror ("[cDemux::Read] read"); + + return rc; +} + +bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filter, + const unsigned char * const mask, int len, int timeout, + const unsigned char * const negmask) +{ + struct demux_filter_para flt; + memset(&flt, 0, sizeof(flt)); + + if (len > FILTER_LENGTH - 2) + fprintf(stderr, "cDemux::sectionFilter #%d: len too long: %d, FILTER_LENGTH: %d\n", num, len, FILTER_LENGTH); + + flt.pid = pid; + flt.filter_length = len + 2 * (len > 1); /* only add the two bytes if required */ + flt.filter[0] = filter[0]; + flt.mask[0] = mask[0]; + flt.timeout = timeout; + memcpy(&flt.filter[3], &filter[1], len - 1); + memcpy(&flt.mask[3], &mask[1], len - 1); + if (negmask != NULL) + { + flt.positive[0] = negmask[0]; + memcpy(&flt.positive[3], &negmask[1], len - 1); + } + + flt.flags = XPDF_IMMEDIATE_START; + + int to = 0; + switch (filter[0]) { + case 0x00: /* program_association_section */ + to = 2000; + break; + case 0x01: /* conditional_access_section */ + to = 6000; + break; + case 0x02: /* program_map_section */ + to = 1500; + break; + case 0x03: /* transport_stream_description_section */ + to = 10000; + break; + /* 0x04 - 0x3F: reserved */ + case 0x40: /* network_information_section - actual_network */ + to = 10000; + break; + case 0x41: /* network_information_section - other_network */ + to = 15000; + break; + case 0x42: /* service_description_section - actual_transport_stream */ + to = 10000; + break; + /* 0x43 - 0x45: reserved for future use */ + case 0x46: /* service_description_section - other_transport_stream */ + to = 10000; + break; + /* 0x47 - 0x49: reserved for future use */ + case 0x4A: /* bouquet_association_section */ + to = 11000; + break; + /* 0x4B - 0x4D: reserved for future use */ + case 0x4E: /* event_information_section - actual_transport_stream, present/following */ + to = 2000; + break; + case 0x4F: /* event_information_section - other_transport_stream, present/following */ + to = 10000; + break; + /* 0x50 - 0x5F: event_information_section - actual_transport_stream, schedule */ + /* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */ + case 0x70: /* time_date_section */ + flt.flags |= (XPDF_NO_CRC); /* section has no CRC */ + //flt.pid = 0x0014; + to = 30000; + break; + case 0x71: /* running_status_section */ + flt.flags |= (XPDF_NO_CRC); /* section has no CRC */ + to = 0; + break; + case 0x72: /* stuffing_section */ + flt.flags |= (XPDF_NO_CRC); /* section has no CRC */ + to = 0; + break; + case 0x73: /* time_offset_section */ + //flt.pid = 0x0014; + to = 30000; + break; + /* 0x74 - 0x7D: reserved for future use */ + case 0x7E: /* discontinuity_information_section */ + flt.flags |= (XPDF_NO_CRC); /* section has no CRC */ + to = 0; + break; + case 0x7F: /* selection_information_section */ + to = 0; + break; + /* 0x80 - 0x8F: ca_message_section */ + /* 0x90 - 0xFE: user defined */ + /* 0xFF: reserved */ + default: + break; +// return -1; + } + if (timeout == 0) + flt.timeout = to; +#if 0 + fprintf(stderr, "cDemux::%s #%d pid:0x%04hx fd:%d type:%s len:%d/%d to:%d flags:%x\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type], len,flt.filter_length, flt.timeout,flt.flags); + fprintf(stderr,"filt: ");for(int i=0;i= 0x0002 && pid <= 0x000f) || pid >= 0x1fff) + return false; + +fprintf(stderr, "cDemux::%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]); + + if (dmx_type == DMX_TP_CHANNEL) + { + unsigned int n = pesfds.size(); + addPid(pid); + return (n != pesfds.size()); + } + memset(&flt, 0, sizeof(flt)); + flt.pid = pid; + flt.output = OUT_DECODER; + switch (dmx_type) { + case DMX_PCR_ONLY_CHANNEL: + flt.pesType = DMX_PES_PCR; + break; + case DMX_AUDIO_CHANNEL: + flt.pesType = DMX_PES_AUDIO; + break; + case DMX_VIDEO_CHANNEL: + flt.pesType = DMX_PES_VIDEO; + break; + case DMX_PES_CHANNEL: + flt.unloader.unloader_type = UNLOADER_TYPE_PAYLOAD; + flt.unloader.threshold = 64; + flt.pesType = DMX_PES_OTHER; + flt.output = OUT_MEMORY; + default: + flt.pesType = DMX_PES_OTHER; + } + + return (ioctl(fd, DEMUX_FILTER_PES_SET, &flt) >= 0); +} + +void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/) +{ + fprintf(stderr, "cDemux::%s #%d\n", __FUNCTION__, num); +} + +void *cDemux::getBuffer() +{ + fprintf(stderr, "cDemux::%s #%d\n", __FUNCTION__, num); + return NULL; +} + +void *cDemux::getChannel() +{ + fprintf(stderr, "cDemux::%s #%d\n", __FUNCTION__, num); + return NULL; +} + +void cDemux::addPid(unsigned short Pid) +{ + int pfd; + int ret; + struct demux_pes_para p; + if (dmx_type != DMX_TP_CHANNEL) + { + fprintf(stderr, "cDemux::%s pes_type!=DMX_TP_CHANNEL (%s) not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid); + return; + } + if (fd == -1) + fprintf(stderr, "cDemux::%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid); + pfd = open(devname[num], O_RDWR); + if (pfd < 0) + { + fprintf(stderr, "cDemux::%s #%d Pid = %hx open failed (%m)\n", __FUNCTION__, num, Pid); + return; + } + fprintf(stderr, "cDemux::%s #%d Pid = %hx pfd = %d\n", __FUNCTION__, num, Pid, pfd); + + p.pid = Pid; + p.pesType = DMX_PES_OTHER; + p.output = OUT_NOTHING; + p.flags = 0; + p.unloader.unloader_type = UNLOADER_TYPE_BUCKET; + p.unloader.threshold = 128; + + ioctl(pfd, DEMUX_SELECT_SOURCE, INPUT_FROM_CHANNEL0); + ret = ioctl(pfd, DEMUX_SET_BUFFER_SIZE, 0x10000); // 64k + if (ret == -1) + perror("DEMUX_SET_BUFFER_SIZE"); + else + { + ret = ioctl(pfd, DEMUX_FILTER_PES_SET, &p); + if (ret == -1) + perror("DEMUX_FILTER_PES_SET"); + } + if (ret != -1) + /* success! */ + pesfds.push_back(pfd); + else + /* error! */ + close(pfd); + return; +} + +void cDemux::getSTC(int64_t * STC) +{ + lt_debug("cDemux::%s #%d\n", __FUNCTION__, num); + /* this is a guess, but seems to work... int32_t gives errno 515... */ +#define STC_TYPE uint64_t + STC_TYPE stc; + if (ioctl(fd, DEMUX_GET_CURRENT_STC, &stc)) + perror("cDemux::getSTC DEMUX_GET_CURRENT_STC"); + *STC = (stc >> 32); +} + +int cDemux::getUnit(void) +{ + lt_debug("cDemux::%s #%d\n", __FUNCTION__, num); + /* just guessed that this is the right thing to do. + right now this is only used by the CA code which is stubbed out + anyway */ + return num; +} diff --git a/lib/libtriple/dmx_td.h b/lib/libtriple/dmx_td.h new file mode 100644 index 000000000..aba9ec835 --- /dev/null +++ b/lib/libtriple/dmx_td.h @@ -0,0 +1,56 @@ +#ifndef __DEMUX_TD_H +#define __DEMUX_TD_H + +#include +#include +extern "C" { +#include +#include +} +#if defined DMX_FILTER_SIZE +#undef DMX_FILTER_SIZE +#endif +#define DMX_FILTER_SIZE FILTER_LENGTH + +typedef enum +{ + DMX_VIDEO_CHANNEL = 1, + DMX_AUDIO_CHANNEL, + DMX_PES_CHANNEL, + DMX_PSI_CHANNEL, + DMX_PIP_CHANNEL, + DMX_TP_CHANNEL, + DMX_PCR_ONLY_CHANNEL +} DMX_CHANNEL_TYPE; + +class cDemux +{ + private: + int num; + int fd; + DMX_CHANNEL_TYPE dmx_type; + std::vector pesfds; + public: + + bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0); + void Close(void); + bool Start(void); + bool Stop(void); + int Read(unsigned char *buff, int len, int Timeout = 0); + bool sectionFilter(unsigned short pid, const unsigned char * const filter, const unsigned char * const mask, int len, int Timeout = 0, const unsigned char * const negmask = NULL); + bool pesFilter(const unsigned short pid); +#define AVSYNC_TYPE int + void SetSyncMode(AVSYNC_TYPE mode); + void * getBuffer(); + void * getChannel(); + DMX_CHANNEL_TYPE getChannelType(void) { return dmx_type; }; + void addPid(unsigned short pid); + void getSTC(int64_t * STC); + int getUnit(void); + int getFD(void) { return fd; }; /* needed by cPlayback class */ + // + cDemux(int num = 0); + ~cDemux(); +}; + +#endif //__DEMUX_H From 6dbd46e95a6292d297acc3a8696358b477e3efaa Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 6 Mar 2010 15:51:10 +0100 Subject: [PATCH 0004/1070] libtriple: implement working cVideo class Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/8844c96ae899ff81f911d76a302e599471c9e24a Author: Stefan Seyfried Date: 2010-03-06 (Sat, 06 Mar 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/video_td.cpp | 545 +++++++++++++++++++++++++++++++++++++ lib/libtriple/video_td.h | 189 +++++++++++++ 2 files changed, 734 insertions(+) create mode 100644 lib/libtriple/video_td.cpp create mode 100644 lib/libtriple/video_td.h diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp new file mode 100644 index 000000000..a5a90382c --- /dev/null +++ b/lib/libtriple/video_td.cpp @@ -0,0 +1,545 @@ +/* + * $Id$ + * + * (C) 2002-2003 Andreas Oberritter + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +//#include +#include +//#include + +#include +#include +#include "video_td.h" +#include +#define VIDEO_DEVICE "/dev/" DEVICE_NAME_VIDEO + +cVideo * videoDecoder = NULL; +int system_rev = 0; + +extern struct Ssettings settings; + +cVideo::cVideo(int, void *, void *) +{ + if ((fd = open(VIDEO_DEVICE, O_RDWR)) < 0) + ERROR(VIDEO_DEVICE); + + playstate = VIDEO_STOPPED; + croppingMode = VID_DISPMODE_NORM; + outputformat = VID_OUTFMT_RGBC_SVIDEO; + scartvoltage = -1; + z[0] = 100; + z[1] = 100; + zoomvalue = &z[0]; + const char *blanknames[2] = { "/share/tuxbox/blank_576.mpg", "/share/tuxbox/blank_480.mpg" }; + int blankfd; + struct stat st; + + for (int i = 0; i < 2; i++) + { + blank_data[i] = NULL; /* initialize */ + blank_size[i] = 0; + blankfd = open(blanknames[i], O_RDONLY); + if (blankfd < 0) + { + WARN("cannot open %s: %m", blanknames[i]); + continue; + } + if (fstat(blankfd, &st) != -1 && st.st_size > 0) + { + blank_size[i] = st.st_size; + blank_data[i] = malloc(blank_size[i]); + if (! blank_data[i]) + ERROR("cannot malloc memory"); + else if (read(blankfd, blank_data[i], blank_size[i]) != blank_size[i]) + { + ERROR("short read"); + free(blank_data[i]); /* don't leak... */ + blank_data[i] = NULL; + } + } + close(blankfd); + } +} + +cVideo::~cVideo(void) +{ + playstate = VIDEO_STOPPED; + for (int i = 0; i < 2; i++) + { + if (blank_data[i]) + free(blank_data[i]); + blank_data[i] = NULL; + } + /* disable DACs and SCART voltage */ + Standby(true); + if (fd >= 0) + close(fd); +} + +int cVideo::setAspectRatio(int aspect, int mode) +{ + static int _mode = -1; + static int _aspect = -1; + vidDispSize_t dsize = VID_DISPSIZE_UNKNOWN; + vidDispMode_t dmode = VID_DISPMODE_NORM; + /* 1 = 4:3, 3 = 16:9, 4 = 2.21:1, 0 = unknown */ + int v_ar = getAspectRatio(); + + if (aspect != -1) + _aspect = aspect; + if (mode != -1) + _mode = mode; + fprintf(stderr, "cVideo::setAspectRatio(%d, %d)_(%d, %d) v_ar %d\n", aspect, mode, _aspect, _mode, v_ar); + + /* values are hardcoded in neutrino_menue.cpp, "2" is 14:9 -> not used */ + if (_aspect != -1) + { + switch(_aspect) + { + case 1: + dsize = VID_DISPSIZE_4x3; + scartvoltage = 12; + break; + case 3: + dsize = VID_DISPSIZE_16x9; + scartvoltage = 6; + break; + default: + break; + } + } + if (_mode != -1) + { + switch(_mode) + { + case DISPLAY_AR_MODE_PANSCAN: + if (v_ar < 3) + dsize = VID_DISPSIZE_4x3; + break; + case DISPLAY_AR_MODE_LETTERBOX: + dmode = VID_DISPMODE_LETTERBOX; + break; + case DISPLAY_AR_MODE_PANSCAN2: + if ((v_ar < 3 && _aspect == 3) || (v_ar >= 3 && _aspect == 1)) + { + /* unfortunately, this partly reimplements the setZoom code... */ + int zoom = 100 * 16 / 14; /* 16:9 vs 14:9 */ + dsize = VID_DISPSIZE_UNKNOWN; + dmode = VID_DISPMODE_SCALE; + SCALEINFO s; + memset(&s, 0, sizeof(s)); + if (v_ar < 3) { /* 4:3 */ + s.src.hori_size = 720; + s.src.vert_size = 2 * 576 - 576 * zoom / 100; + s.des.hori_size = zoom * 720 * 3/4 / 100; + s.des.vert_size = 576; + } else { + s.src.hori_size = 2 * 720 - 720 * zoom / 100; + s.src.vert_size = 576; + s.des.hori_size = 720; + s.des.vert_size = zoom * 576 * 3/4 / 100; + } + s.des.vert_off = (576 - s.des.vert_size) / 2; + s.des.hori_off = (720 - s.des.hori_size) / 2; + lt_debug("PANSCAN2: %d%% src: %d:%d:%d:%d dst: %d:%d:%d:%d\n", zoom, + s.src.hori_off,s.src.vert_off,s.src.hori_size,s.src.vert_size, + s.des.hori_off,s.des.vert_off,s.des.hori_size,s.des.vert_size); + fop(ioctl, MPEG_VID_SCALE_ON); + fop(ioctl, MPEG_VID_SET_SCALE_POS, &s); + } + default: + break; + } + setCroppingMode(dmode); + } + const char *ds[] = { "4x3", "16x9", "2.21", "unknown" }; + const char *d; + if (dsize >=0 && dsize < 4) + d = ds[dsize]; + else + d = "invalid!"; + lt_debug("cVideo::setAspectRatio:dispsize(%d) (%s)\n", dsize, d); + fop(ioctl, MPEG_VID_SET_DISPSIZE, dsize); + + int avsfd = open("/dev/stb/tdsystem", O_RDONLY); + if (avsfd < 0) + { + perror("open tdsystem"); + return 0; + } + lt_debug("cVideo::setAspectRatio: setting SCART_PIN_8 to %dV\n", scartvoltage); + if (scartvoltage > 0 && ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) + perror("IOC_AVS_SCART_PIN8_SET"); + close(avsfd); + return 0; +} + +int cVideo::getAspectRatio(void) +{ + VIDEOINFO v; + /* this memset silences *TONS* of valgrind warnings */ + memset(&v, 0, sizeof(v)); + quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); + if (v.pel_aspect_ratio < VID_DISPSIZE_4x3 || v.pel_aspect_ratio > VID_DISPSIZE_UNKNOWN) + { + WARN("invalid value %d, returning 0 for 'unknown' fd: %d", v.pel_aspect_ratio, fd); + return 0; + } + /* convert to Coolstream api values. Taken from streaminfo2.cpp */ + switch (v.pel_aspect_ratio) + { + case VID_DISPSIZE_4x3: + return 1; + case VID_DISPSIZE_16x9: + return 3; + case VID_DISPSIZE_221x100: + return 4; + default: + return 0; + } +} + +int cVideo::setCroppingMode(vidDispMode_t format) +{ + croppingMode = format; + const char *format_string[] = { "norm", "letterbox", "unknown", "mode_1_2", "mode_1_4", "mode_2x", "scale", "disexp" }; + const char *f; + if (format >= VID_DISPMODE_NORM && format <= VID_DISPMODE_DISEXP) + f = format_string[format]; + else + f = "ILLEGAL format!"; + lt_debug("cVideo::setCroppingMode(%d) => %s\n", format, f); + return fop(ioctl, MPEG_VID_SET_DISPMODE, format); +} + +int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/) +{ + if (playstate == VIDEO_PLAYING) + return 0; + if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */ + fop(ioctl, MPEG_VID_CONTINUE); + playstate = VIDEO_PLAYING; + fop(ioctl, MPEG_VID_PLAY); + return fop(ioctl, MPEG_VID_SYNC_ON, VID_SYNC_AUD); +} + +int cVideo::Stop(bool blank) +{ + //fprintf(stderr, "cVideo::Stop %d\n", blank); + if (blank) + { + playstate = VIDEO_STOPPED; + fop(ioctl, MPEG_VID_STOP); + return setBlank(1); + } + playstate = VIDEO_FREEZED; + return fop(ioctl, MPEG_VID_FREEZE); +} + +int cVideo::setBlank(int) +{ + /* The TripleDragon has no VIDEO_SET_BLANK ioctl. + instead, you write a black still-MPEG Iframe into the decoder. + The original software uses different files for 4:3 and 16:9 and + for PAL and NTSC. I optimized that a little bit + */ + int index = 0; /* default PAL */ + VIDEOINFO v; + BUFINFO buf; + memset(&v, 0, sizeof(v)); + quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); + + if ((v.v_size % 240) == 0) /* NTSC */ + { + INFO("NTSC format detected"); + index = 1; + } + + if (blank_data[index] == NULL) /* no MPEG found */ + return -1; + + /* hack: this might work only on those two still-MPEG files! + I diff'ed the 4:3 and the 16:9 still mpeg from the original + soft and spotted the single bit difference, so there is no + need to keep two different MPEGs in memory + If we would read them from disk all the time it would be + slower and it might wake up the drive occasionally */ + if (v.pel_aspect_ratio == VID_DISPSIZE_4x3) + ((char *)blank_data[index])[7] &= ~0x10; // clear the bit + else + ((char *)blank_data[index])[7] |= 0x10; // set the bit + + //WARN("blank[7] == 0x%02x", ((char *)blank_data[index])[7]); + + buf.ulLen = blank_size[index]; + buf.ulStartAdrOff = (int)blank_data[index]; + fop(ioctl, MPEG_VID_STILLP_WRITE, &buf); + return fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX); +} + +int cVideo::SetVideoSystem(int video_system, bool remember) +{ + fprintf(stderr, "cVideo::setVideoSystem(%d, %d)\n", video_system, remember); + if (video_system > VID_DISPFMT_SECAM || video_system < 0) + video_system = VID_DISPFMT_PAL; + return fop(ioctl, MPEG_VID_SET_DISPFMT, video_system); +} + +int cVideo::getPlayState(void) +{ + return playstate; +} + +void cVideo::SetVideoMode(analog_mode_t mode) +{ + lt_debug("cVideo::setVideoMode(%d)\n", mode); + switch(mode) + { + case ANALOG_SD_YPRPB_SCART: + outputformat = VID_OUTFMT_YBR_SVIDEO; + break; + case ANALOG_SD_RGB_SCART: + outputformat = VID_OUTFMT_RGBC_SVIDEO; + break; + default: + fprintf(stderr, "cVideo::setVideoMode: unknown mode %d\n", mode); + return; + } + fop(ioctl, MPEG_VID_SET_OUTFMT, outputformat); +} + +void cVideo::ShowPicture(const char * fname) +{ + fprintf(stderr, "cVideo::ShowPicture: %s\n", fname); +} + +void cVideo::StopPicture() +{ + lt_debug("cVideo::StopPicture()\n"); + fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX); +} + +void cVideo::Standby(unsigned int bOn) +{ + lt_debug("cVideo::Standby: %d\n", bOn); + if (bOn) + { + setBlank(1); + fop(ioctl, MPEG_VID_SET_OUTFMT, VID_OUTFMT_DISABLE_DACS); + } else + fop(ioctl, MPEG_VID_SET_OUTFMT, outputformat); + routeVideo(bOn); +} + +int cVideo::getBlank(void) +{ + fprintf(stderr, "cVideo::getBlank\n"); + return 0; +} + +/* set zoom in percent (100% == 1:1) */ +int cVideo::setZoom(int zoom) +{ + if (zoom == -1) // "auto" reset + zoom = *zoomvalue; + + if (zoom > 150 || zoom < 100) + return -1; + + *zoomvalue = zoom; + + if (zoom == 100) + { + setCroppingMode(croppingMode); + return fop(ioctl, MPEG_VID_SCALE_OFF); + } + + /* the SCALEINFO describes the source and destination of the scaled + video. "src" is the part of the source picture that gets scaled, + "dst" is the area on the screen where this part is displayed + Messing around with MPEG_VID_SET_SCALE_POS disables the automatic + letterboxing, which, as I guess, is only a special case of + MPEG_VID_SET_SCALE_POS. Therefor we need to care for letterboxing + etc here, which is probably not yet totally correct */ + SCALEINFO s; + memset(&s, 0, sizeof(s)); + if (zoom > 100) + { + vidDispSize_t x = (vidDispSize_t)getAspectRatio(); + if (x == VID_DISPSIZE_4x3 && croppingMode == VID_DISPMODE_NORM) + { + s.src.hori_size = 720; + s.des.hori_size = 720 * 3/4 * zoom / 100; + if (s.des.hori_size > 720) + { + /* the destination exceeds the screen size. + TODO: decrease source size to allow higher + zoom factors (is this useful ?) */ + s.des.hori_size = 720; + zoom = 133; // (720*4*100)/(720*3) + *zoomvalue = zoom; + } + } + else + { + s.src.hori_size = 2 * 720 - 720 * zoom / 100; + s.des.hori_size = 720; + } + s.src.vert_size = 2 * 576 - 576 * zoom / 100; + s.des.hori_off = (720 - s.des.hori_size) / 2; + s.des.vert_size = 576; + } +/* not working correctly (wrong formula) and does not make sense IMHO + else + { + s.src.hori_size = 720; + s.src.vert_size = 576; + s.des.hori_size = 720 * zoom / 100; + s.des.vert_size = 576 * zoom / 100; + s.des.hori_off = (720 - s.des.hori_size) / 2; + s.des.vert_off = (576 - s.des.vert_size) / 2; + } + */ + DBG("setZoom: %d%% src: %d:%d:%d:%d dst: %d:%d:%d:%d", zoom, + s.src.hori_off,s.src.vert_off,s.src.hori_size,s.src.vert_size, + s.des.hori_off,s.des.vert_off,s.des.hori_size,s.des.vert_size); + fop(ioctl, MPEG_VID_SET_DISPMODE, VID_DISPMODE_SCALE); + fop(ioctl, MPEG_VID_SCALE_ON); + return fop(ioctl, MPEG_VID_SET_SCALE_POS, &s); +} + +#if 0 +int cVideo::getZoom(void) +{ + return *zoomvalue; +} + +void cVideo::setZoomAspect(int index) +{ + if (index < 0 || index > 1) + WARN("index out of range"); + else + zoomvalue = &z[index]; +} +#endif + +void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/) +{ + /* x = y = w = h = -1 -> reset / "hide" PIG */ + if (x == -1 && y == -1 && w == -1 && h == -1) + { + setZoom(-1); + return; + } + SCALEINFO s; + memset(&s, 0, sizeof(s)); + s.src.hori_size = 720; + s.src.vert_size = 576; + s.des.hori_off = x; + s.des.vert_off = y; + s.des.hori_size = w; + s.des.vert_size = h; + DBG("setPig src: %d:%d:%d:%d dst: %d:%d:%d:%d", + s.src.hori_off,s.src.vert_off,s.src.hori_size,s.src.vert_size, + s.des.hori_off,s.des.vert_off,s.des.hori_size,s.des.vert_size); + fop(ioctl, MPEG_VID_SET_DISPMODE, VID_DISPMODE_SCALE); + fop(ioctl, MPEG_VID_SCALE_ON); + fop(ioctl, MPEG_VID_SET_SCALE_POS, &s); +} + +void cVideo::getPictureInfo(int &width, int &height, int &rate) +{ + VIDEOINFO v; + /* this memset silences *TONS* of valgrind warnings */ + memset(&v, 0, sizeof(v)); + quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); + /* convert to Coolstream API */ + rate = (int)v.frame_rate - 1; + width = (int)v.h_size; + height = (int)v.v_size; +} + +void cVideo::SetSyncMode(AVSYNC_TYPE /*Mode*/) +{ + fprintf(stderr, "cVideo::%s\n", __FUNCTION__); +}; + +int cVideo::SetStreamType(VIDEO_FORMAT type) +{ + static const char *VF[] = { + "VIDEO_FORMAT_MPEG2", + "VIDEO_FORMAT_MPEG4", + "VIDEO_FORMAT_VC1", + "VIDEO_FORMAT_JPEG", + "VIDEO_FORMAT_GIF", + "VIDEO_FORMAT_PNG" + }; + + lt_debug("cVideo::SetStreamType - type=%s\n", VF[type]); + return 0; +} + +void cVideo::routeVideo(int standby) +{ + lt_debug("cVideo::routeVideo(%d)\n", standby); + + int avsfd = open("/dev/stb/tdsystem", O_RDONLY); + if (avsfd < 0) + { + perror("open tdsystem"); + return; + } + + /* in standby, we always route VCR scart to the TV. Once there is a UI + to configure this, we can think more about this... */ + if (standby) + { + printf("[routeVideo] setting FASTBLANK to follow VCR SCART\n"); + if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, (unsigned char)3) < 0) + perror("IOC_AVS_FASTBLANK_SET, 3"); + /* TODO: should probably depend on aspect ratio setting */ + printf("[routeVideo] setting SCART_PIN_8 to follow VCR SCART\n"); + if (ioctl(avsfd, IOC_AVS_SCART_PIN8_FOLLOW_VCR) < 0) + perror("IOC_AVS_SCART_PIN8_FOLLOW_VCR"); + printf("[routeVideo] routing VCR to TV SCART\n"); + if (ioctl(avsfd, IOC_AVS_ROUTE_VCR2TV) < 0) + perror("IOC_AVS_ROUTE_VCR2TV"); + return; + } + unsigned char fblk = 1; + printf("[routeVideo] setting FASTBLANK to %d\n", fblk); + if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, fblk) < 0) + perror("IOC_AVS_FASTBLANK_SET, fblk"); + printf("[routeVideo] setting SCART_PIN_8 to %dV\n", scartvoltage); + if (ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) + perror("IOC_AVS_SCART_PIN8_SET"); + printf("[routeVideo] routing TV encoder to TV SCART\n"); + if (ioctl(avsfd, IOC_AVS_ROUTE_ENC2TV) < 0) + perror("IOC_AVS_ROUTE_ENC2TV"); + close(avsfd); +} diff --git a/lib/libtriple/video_td.h b/lib/libtriple/video_td.h new file mode 100644 index 000000000..49778b12a --- /dev/null +++ b/lib/libtriple/video_td.h @@ -0,0 +1,189 @@ +#ifndef _VIDEO_TD_H +#define _VIDEO_TD_H + +#include +#define video_format_t vidDispSize_t +//#define video_displayformat_t vidDispMode_t + + +typedef enum { + ANALOG_SD_RGB_SCART = 0x00, + ANALOG_SD_YPRPB_SCART, + ANALOG_HD_RGB_SCART, + ANALOG_HD_YPRPB_SCART, + ANALOG_SD_RGB_CINCH = 0x80, + ANALOG_SD_YPRPB_CINCH, + ANALOG_HD_RGB_CINCH, + ANALOG_HD_YPRPB_CINCH, +} analog_mode_t; + +typedef enum { + VIDEO_FORMAT_MPEG2 = 0, + VIDEO_FORMAT_MPEG4, + VIDEO_FORMAT_VC1, + VIDEO_FORMAT_JPEG, + VIDEO_FORMAT_GIF, + VIDEO_FORMAT_PNG +} VIDEO_FORMAT; + +typedef enum { + VIDEO_SD = 0, + VIDEO_HD, + VIDEO_120x60i, + VIDEO_320x240i, + VIDEO_1440x800i, + VIDEO_360x288i +} VIDEO_DEFINITION; + +typedef enum { + VIDEO_FRAME_RATE_23_976 = 0, + VIDEO_FRAME_RATE_24, + VIDEO_FRAME_RATE_25, + VIDEO_FRAME_RATE_29_97, + VIDEO_FRAME_RATE_30, + VIDEO_FRAME_RATE_50, + VIDEO_FRAME_RATE_59_94, + VIDEO_FRAME_RATE_60 +} VIDEO_FRAME_RATE; + +typedef enum { + DISPLAY_AR_1_1, + DISPLAY_AR_4_3, + DISPLAY_AR_14_9, + DISPLAY_AR_16_9, + DISPLAY_AR_20_9, + DISPLAY_AR_RAW, +} DISPLAY_AR; + +typedef enum { + DISPLAY_AR_MODE_PANSCAN = 0, + DISPLAY_AR_MODE_LETTERBOX, + DISPLAY_AR_MODE_NONE, + DISPLAY_AR_MODE_PANSCAN2 +} DISPLAY_AR_MODE; + +typedef enum { + VIDEO_DB_DR_NEITHER = 0, + VIDEO_DB_ON, + VIDEO_DB_DR_BOTH +} VIDEO_DB_DR; + +typedef enum { + VIDEO_PLAY_STILL = 0, + VIDEO_PLAY_CLIP, + VIDEO_PLAY_TRICK, + VIDEO_PLAY_MOTION, + VIDEO_PLAY_MOTION_NO_SYNC +} VIDEO_PLAY_MODE; + +typedef enum { + VIDEO_STD_NTSC = VID_DISPFMT_NTSC, /* 0 */ + VIDEO_STD_PAL = VID_DISPFMT_PAL, /* 1 */ + VIDEO_STD_SECAM = VID_DISPFMT_SECAM, /* 4 */ + VIDEO_STD_1080I50 = VIDEO_STD_PAL, /* hack, this is used in neutrino settings default */ + VIDEO_STD_MAX = VIDEO_STD_SECAM +} VIDEO_STD; + +typedef enum { + VIDEO_STOPPED, /* Video is stopped */ + VIDEO_PLAYING, /* Video is currently playing */ + VIDEO_FREEZED /* Video is freezed */ +} video_play_state_t; + +/* not used, for dummy functions */ +typedef enum { + VIDEO_HDMI_CEC_MODE_OFF = 0, + VIDEO_HDMI_CEC_MODE_TUNER, + VIDEO_HDMI_CEC_MODE_RECORDER +} VIDEO_HDMI_CEC_MODE; + +typedef enum +{ + VIDEO_CONTROL_BRIGHTNESS = 0, + VIDEO_CONTROL_CONTRAST, + VIDEO_CONTROL_SATURATION, + VIDEO_CONTROL_HUE, + VIDEO_CONTROL_SHARPNESS, + VIDEO_CONTROL_MAX = VIDEO_CONTROL_SHARPNESS +} VIDEO_CONTROL; + + +class cVideo +{ + private: + /* video device */ + int fd; + /* apparently we cannot query the driver's state + => remember it */ + video_play_state_t playstate; + vidDispMode_t croppingMode; + vidOutFmt_t outputformat; + int scartvoltage; + int z[2]; /* zoomvalue for 4:3 (0) and 16:9 (1) in percent */ + int *zoomvalue; + void *blank_data[2]; /* we store two blank MPEGs (PAL/NTSC) in there */ + int blank_size[2]; + + VIDEO_FORMAT StreamType; + VIDEO_DEFINITION VideoDefinition; + DISPLAY_AR DisplayAR; + VIDEO_PLAY_MODE SyncMode; + DISPLAY_AR_MODE ARMode; + VIDEO_DB_DR eDbDr; + DISPLAY_AR PictureAR; + VIDEO_FRAME_RATE FrameRate; + void routeVideo(int standby); + public: + /* constructor & destructor */ + cVideo(int mode, void *, void *); + ~cVideo(void); + + void * GetTVEnc() { return NULL; }; + void * GetTVEncSD() { return NULL; }; + + /* aspect ratio */ + int getAspectRatio(void); + void getPictureInfo(int &width, int &height, int &rate); + int setAspectRatio(int aspect, int mode); + + /* cropping mode */ + int setCroppingMode(vidDispMode_t x = VID_DISPMODE_NORM); + + /* get play state */ + int getPlayState(void); + + /* blank on freeze */ + int getBlank(void); + int setBlank(int enable); + + /* change video play state. Parameters are all unused. */ + int Start(void *PcrChannel = NULL, unsigned short PcrPid = 0, unsigned short VideoPid = 0, void *x = NULL); + int Stop(bool blank = true); + bool Pause(void); + + /* set video_system */ + int SetVideoSystem(int video_system, bool remember = true); + int SetStreamType(VIDEO_FORMAT type); +#define AVSYNC_TYPE int + void SetSyncMode(AVSYNC_TYPE mode); + bool SetCECMode(VIDEO_HDMI_CEC_MODE) { return true; }; + void SetCECAutoView(bool) { return; }; + void SetCECAutoStandby(bool) { return; }; + void ShowPicture(const char * fname); + void StopPicture(); + void Standby(unsigned int bOn); + void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600); + void SetControl(int, int) { return; }; + int setZoom(int); + void setContrast(int val); + void SetVideoMode(analog_mode_t mode); + void SetDBDR(int) { return; }; + void SetAudioHandle(void *) { return; }; + void SetAutoModes(int [VIDEO_STD_MAX]) { return; }; + int OpenVBI(int) { return 0; }; + int CloseVBI(void) { return 0; }; + int StartVBI(unsigned short) { return 0; }; + int StopVBI(void) { return 0; }; +}; + +#endif From 2d086adc0f9c08b077514c4d73a397cc75a33355 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 7 Nov 2010 17:24:28 +0100 Subject: [PATCH 0005/1070] libtriple: implement ShowPicture() in cVideo this needs the ffmpeg binary with support for mjpeg decoder and mpeg2video encoder to recode the jpgs to m2v Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/3a0e21e00c5effe32ae7f82d4182a671a76abf7d Author: Stefan Seyfried Date: 2010-11-07 (Sun, 07 Nov 2010) ------------------ This commit was generated by Migit --- lib/libtriple/video_td.cpp | 108 +++++++++++++++++++++++++++++++++++-- 1 file changed, 104 insertions(+), 4 deletions(-) diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index a5a90382c..812e184eb 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -28,6 +28,8 @@ #include #include +#include + //#include #include //#include @@ -41,7 +43,16 @@ cVideo * videoDecoder = NULL; int system_rev = 0; +#if 0 +/* this would be necessary for the DirectFB implementation of ShowPicture */ +#include +#include +extern IDirectFB *dfb; +extern IDirectFBSurface *dfbdest; +#endif + extern struct Ssettings settings; +static pthread_mutex_t stillp_mutex = PTHREAD_MUTEX_INITIALIZER; cVideo::cVideo(int, void *, void *) { @@ -263,14 +274,17 @@ int cVideo::Stop(bool blank) int cVideo::setBlank(int) { + lt_debug("cVideo::setBlank\n"); /* The TripleDragon has no VIDEO_SET_BLANK ioctl. instead, you write a black still-MPEG Iframe into the decoder. The original software uses different files for 4:3 and 16:9 and for PAL and NTSC. I optimized that a little bit */ int index = 0; /* default PAL */ + int ret = 0; VIDEOINFO v; BUFINFO buf; + pthread_mutex_lock(&stillp_mutex); memset(&v, 0, sizeof(v)); quiet_fop(ioctl, MPEG_VID_GET_V_INFO, &v); @@ -281,8 +295,10 @@ int cVideo::setBlank(int) } if (blank_data[index] == NULL) /* no MPEG found */ - return -1; - + { + ret = -1; + goto out; + } /* hack: this might work only on those two still-MPEG files! I diff'ed the 4:3 and the 16:9 still mpeg from the original soft and spotted the single bit difference, so there is no @@ -299,7 +315,10 @@ int cVideo::setBlank(int) buf.ulLen = blank_size[index]; buf.ulStartAdrOff = (int)blank_data[index]; fop(ioctl, MPEG_VID_STILLP_WRITE, &buf); - return fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX); + ret = fop(ioctl, MPEG_VID_SELECT_SOURCE, VID_SOURCE_DEMUX); + out: + pthread_mutex_unlock(&stillp_mutex); + return ret; } int cVideo::SetVideoSystem(int video_system, bool remember) @@ -335,7 +354,88 @@ void cVideo::SetVideoMode(analog_mode_t mode) void cVideo::ShowPicture(const char * fname) { - fprintf(stderr, "cVideo::ShowPicture: %s\n", fname); + lt_debug("cVideo::ShowPicture: %s\n", fname); + char destname[512]; + char cmd[512]; + char *p; + void *data; + int mfd; + struct stat st; + strcpy(destname, "/var/cache"); + mkdir(destname, 0755); + /* the cache filename is (example for /share/tuxbox/neutrino/icons/radiomode.jpg): + /var/cache/share.tuxbox.neutrino.icons.radiomode.jpg.m2v + build that filename first... + TODO: this could cause name clashes, use a hashing function instead... */ + strcat(destname, fname); + p = &destname[strlen("/var/cache/")]; + while ((p = strchr(p, '/')) != NULL) + *p = '.'; + strcat(destname, ".m2v"); + /* ...then check if it exists already... + TODO: check if the cache file is older than the jpeg file... */ + if (access(destname, R_OK)) + { + /* it does not exist, so call ffmpeg to create it... */ + sprintf(cmd, "ffmpeg -y -f mjpeg -i '%s' -s 704x576 '%s' 0) + { + data = malloc(st.st_size); + if (! data) + ERROR("cannot malloc memory"); + else if (read(mfd, data, st.st_size) != st.st_size) + ERROR("short read"); + else + { + BUFINFO buf; + buf.ulLen = st.st_size; + buf.ulStartAdrOff = (int)data; + Stop(false); + fop(ioctl, MPEG_VID_STILLP_WRITE, &buf); + } + free(data); + } + close(mfd); + out: + pthread_mutex_unlock(&stillp_mutex); + return; +#if 0 + /* DirectFB based picviewer: works, but is slow and the infobar + draws in the same plane */ + int width; + int height; + if (!fname) + return; + + IDirectFBImageProvider *provider; + DFBResult err = dfb->CreateImageProvider(dfb, fname, &provider); + if (err) + { + fprintf(stderr, "cVideo::ShowPicture: CreateImageProvider error!\n"); + return; + } + + DFBSurfaceDescription desc; + provider->GetSurfaceDescription (provider, &desc); + width = desc.width; + height = desc.height; + provider->RenderTo(provider, dfbdest, NULL); + provider->Release(provider); +#endif } void cVideo::StopPicture() From 5d6416fc20a51fb32d9d5da3291f3954122c9816 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 7 Mar 2010 02:12:15 +0100 Subject: [PATCH 0006/1070] libtriple: implement cAudio class Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/14849689e59a37e02e3f19d6f541bd68cdbb00a5 Author: Stefan Seyfried Date: 2010-03-07 (Sun, 07 Mar 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/audio_td.cpp | 249 +++++++++++++++++++++++++++++++++++++ lib/libtriple/audio_td.h | 88 +++++++++++++ 2 files changed, 337 insertions(+) create mode 100644 lib/libtriple/audio_td.cpp create mode 100644 lib/libtriple/audio_td.h diff --git a/lib/libtriple/audio_td.cpp b/lib/libtriple/audio_td.cpp new file mode 100644 index 000000000..8350118f3 --- /dev/null +++ b/lib/libtriple/audio_td.cpp @@ -0,0 +1,249 @@ +#include +#include +#include +#include +#include + + +#include +#define AUDIO_DEVICE "/dev/" DEVICE_NAME_AUDIO +#include "audio_td.h" + +cAudio * audioDecoder = NULL; + +cAudio::cAudio(void *, void *, void *) +{ + fd = -1; + openDevice(); + Muted = false; +} + +cAudio::~cAudio(void) +{ + closeDevice(); +} + +void cAudio::openDevice(void) +{ + if (fd < 0) + { + if ((fd = open(AUDIO_DEVICE, O_RDWR)) < 0) + fprintf(stderr, "cAudio::openDevice: open failed (%m)\n"); + } + else + fprintf(stderr, "cAudio::openDevice: already open (fd = %d)\n", fd); +} + +void cAudio::closeDevice(void) +{ + if (fd >= 0) + close(fd); + fd = -1; +} + +int cAudio::do_mute(bool enable, bool remember) +{ + lt_debug("cAudio::%s(%d, %d)\n", __FUNCTION__, enable, remember); + int ret; + if (remember) + Muted = enable; + ret = ioctl(fd, MPEG_AUD_SET_MUTE, enable); + if (ret < 0) + fprintf(stderr, "cAudio::%s(%d) failed (%m)\n", __FUNCTION__, (int)enable); + return ret; +} + +int map_volume(const int volume) +{ + unsigned char vol = volume; + if (vol > 100) + vol = 100; + +// vol = (invlog63[volume] + 1) / 2; + vol = 31 - vol * 31 / 100; + return vol; +} + +int cAudio::setVolume(unsigned int left, unsigned int right) +{ +// int avsfd; + int ret; + int vl = map_volume(left); + int vr = map_volume(right); + int v = map_volume((left + right) / 2); +// if (settings.volume_type == CControld::TYPE_OST || forcetype == (int)CControld::TYPE_OST) + { + AUDVOL vol; + vol.frontleft = vl; + vol.frontright = vr; + vol.rearleft = vl; + vol.rearright = vr; + vol.center = v; + vol.lfe = v; + ret = ioctl(fd, MPEG_AUD_SET_VOL, &vol); + if (ret < 0) + fprintf(stderr, "cAudio::setVolume MPEG_AUD_SET_VOL failed (%m)\n"); + return ret; + } +#if 0 + else if (settings.volume_type == CControld::TYPE_AVS || forcetype == (int)CControld::TYPE_AVS) + { + if ((avsfd = open(AVS_DEVICE, O_RDWR)) < 0) + perror("[controld] " AVS_DEVICE); + else { + if (ioctl(avsfd, IOC_AVS_SET_VOLUME, v)) + perror("[controld] IOC_AVS_SET_VOLUME"); + close(avsfd); + return 0; + } + } + fprintf(stderr, "CAudio::setVolume: invalid settings.volume_type = %d\n", settings.volume_type); + return -1; +#endif +} + +int cAudio::Start(void) +{ + int ret; + ret = ioctl(fd, MPEG_AUD_PLAY); + /* this seems to be not strictly necessary since neutrino + re-mutes all the time, but is certainly more correct */ + ioctl(fd, MPEG_AUD_SET_MUTE, Muted); + return ret; +} + +int cAudio::Stop(void) +{ + return ioctl(fd, MPEG_AUD_STOP); +} + +bool cAudio::Pause(bool /*Pcm*/) +{ + return true; +}; + +void cAudio::SetSyncMode(AVSYNC_TYPE /*Mode*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::SetStreamType(AUDIO_FORMAT type) +{ + int bypass_disable; + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + StreamType = type; + + if (StreamType != AUDIO_FMT_DOLBY_DIGITAL && StreamType != AUDIO_FMT_MPEG && StreamType != AUDIO_FMT_MPG1) + fprintf(stderr, "cAudio::%s unhandled AUDIO_FORMAT %d\n", __FUNCTION__, StreamType); + + bypass_disable = (StreamType != AUDIO_FMT_DOLBY_DIGITAL); + setBypassMode(bypass_disable); + + if (StreamType == AUDIO_FMT_MPEG) + ioctl(fd, MPEG_AUD_SET_STREAM_TYPE, AUD_STREAM_TYPE_PES); + if (StreamType == AUDIO_FMT_MPG1) + ioctl(fd, MPEG_AUD_SET_STREAM_TYPE, AUD_STREAM_TYPE_MPEG1); +}; + +int cAudio::setChannel(int /*channel*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +int cAudio::PrepareClipPlay(int /*uNoOfChannels*/, int /*uSampleRate*/, int /*uBitsPerSample*/, int /*bLittleEndian*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +int cAudio::WriteClip(unsigned char * /*buffer*/, int /*size*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +int cAudio::StopClip() +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + return 0; +}; + +void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + unsigned int atype; + static const int freq_mpg[] = {44100, 48000, 32000, 0}; + static const int freq_ac3[] = {48000, 44100, 32000, 0}; + scratchl2 i; + if (ioctl(fd, MPEG_AUD_GET_DECTYP, &atype) < 0) + perror("cAudio::getAudioInfo MPEG_AUD_GET_DECTYP"); + if (ioctl(fd, MPEG_AUD_GET_STATUS, &i) < 0) + perror("cAudio::getAudioInfo MPEG_AUD_GET_STATUS"); + + type = atype; +#if 0 +/* this does not work, some of the values are negative?? */ + AMPEGStatus A; + memcpy(&A, &i.word00, sizeof(i.word00)); + layer = A.audio_mpeg_layer; + mode = A.audio_mpeg_mode; + bitrate = A.audio_mpeg_bitrate; + switch(A.audio_mpeg_frequency) +#endif + /* layer and bitrate are not used anyway... */ + layer = 0; //(i.word00 >> 17) & 3; + bitrate = 0; //(i.word00 >> 12) & 3; + switch (type) + { + case 0: /* MPEG */ + mode = (i.word00 >> 6) & 3; + freq = freq_mpg[(i.word00 >> 10) & 3]; + break; + case 1: /* AC3 */ + mode = (i.word00 >> 28) & 7; + freq = freq_ac3[(i.word00 >> 16) & 3]; + break; + default: + mode = 0; + freq = 0; + } + //fprintf(stderr, "type: %d layer: %d freq: %d bitrate: %d mode: %d\n", type, layer, freq, bitrate, mode); +}; + +void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::SetSpdifDD(bool /*enable*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::ScheduleMute(bool /*On*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::EnableAnalogOut(bool /*enable*/) +{ + fprintf(stderr, "cAudio::%s\n", __FUNCTION__); +}; + +void cAudio::setBypassMode(bool disable) +{ + /* disable = true: audio is MPEG, disable = false: audio is AC3 */ + if (disable) + { + ioctl(fd, MPEG_AUD_SET_MODE, AUD_MODE_MPEG); + return; + } + /* dvb2001 does always set AUD_MODE_DTS before setting AUD_MODE_AC3, + this might be some workaround, so we do the same... */ + ioctl(fd, MPEG_AUD_SET_MODE, AUD_MODE_DTS); + ioctl(fd, MPEG_AUD_SET_MODE, AUD_MODE_AC3); + return; + /* all those ioctl aways return "invalid argument", but they seem to + work anyway, so there's no use in checking the return value */ +} diff --git a/lib/libtriple/audio_td.h b/lib/libtriple/audio_td.h new file mode 100644 index 000000000..7178ecfb9 --- /dev/null +++ b/lib/libtriple/audio_td.h @@ -0,0 +1,88 @@ +/* public header file */ + +#ifndef _AUDIO_TD_H_ +#define _AUDIO_TD_H_ + +#include + +typedef enum +{ + AUDIO_SYNC_WITH_PTS, + AUDIO_NO_SYNC, + AUDIO_SYNC_AUDIO_MASTER +} AUDIO_SYNC_MODE; + +typedef enum +{ + AUDIO_FMT_AUTO = 0, + AUDIO_FMT_MPEG, + AUDIO_FMT_MP3, + AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_BASIC = AUDIO_FMT_DOLBY_DIGITAL, + AUDIO_FMT_AAC, + AUDIO_FMT_AAC_PLUS, + AUDIO_FMT_DD_PLUS, + AUDIO_FMT_DTS, + AUDIO_FMT_AVS, + AUDIO_FMT_MLP, + AUDIO_FMT_WMA, + AUDIO_FMT_MPG1, // TD only. For Movieplayer / cPlayback + AUDIO_FMT_ADVANCED = AUDIO_FMT_MLP +} AUDIO_FORMAT; + +class cAudio +{ + private: + int fd; + bool Muted; + + AUDIO_FORMAT StreamType; + AUDIO_SYNC_MODE SyncMode; + bool started; + + int volume; + + void openDevice(void); + void closeDevice(void); + + int do_mute(bool enable, bool remember); + void setBypassMode(bool disable); + public: + /* construct & destruct */ + cAudio(void *, void *, void *); + ~cAudio(void); + + void *GetHandle() { return NULL; }; + /* shut up */ + int mute(bool remember = true) { return do_mute(true, remember); }; + int unmute(bool remember = true) { return do_mute(false, remember); }; + + /* volume, min = 0, max = 255 */ + int setVolume(unsigned int left, unsigned int right); + int getVolume(void) { return volume;} + bool getMuteStatus(void) { return Muted; }; + + /* start and stop audio */ + int Start(void); + int Stop(void); + bool Pause(bool Pcm = true); + void SetStreamType(AUDIO_FORMAT type); +#define AVSYNC_TYPE int + void SetSyncMode(AVSYNC_TYPE Mode); + + /* select channels */ + int setChannel(int channel); + int PrepareClipPlay(int uNoOfChannels, int uSampleRate, int uBitsPerSample, int bLittleEndian); + int WriteClip(unsigned char * buffer, int size); + int StopClip(); + void getAudioInfo(int &type, int &layer, int& freq, int &bitrate, int &mode); + void SetSRS(int iq_enable, int nmgr_enable, int iq_mode, int iq_level); + bool IsHdmiDDSupported() { return false; }; + void SetHdmiDD(bool) { return; }; + void SetSpdifDD(bool enable); + void ScheduleMute(bool On); + void EnableAnalogOut(bool enable); +}; + +#endif + From 3cc6ab875082751ceb66292f770aa71173e0ff42 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 7 Mar 2010 19:53:52 +0100 Subject: [PATCH 0007/1070] libtriple: implement cRecord class TS recording now somewhat works ;) this version does not need ringbuffer code and only one thread Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/ea818a095396f7712ab784fc841a0b48cf699367 Author: Stefan Seyfried Date: 2010-03-07 (Sun, 07 Mar 2010) ------------------ This commit was generated by Migit --- lib/libtriple/record_td.cpp | 214 ++++++++++++++++++++++++++++++++++++ lib/libtriple/record_td.h | 39 +++++++ 2 files changed, 253 insertions(+) create mode 100644 lib/libtriple/record_td.cpp create mode 100644 lib/libtriple/record_td.h diff --git a/lib/libtriple/record_td.cpp b/lib/libtriple/record_td.cpp new file mode 100644 index 000000000..1ab9ed70a --- /dev/null +++ b/lib/libtriple/record_td.cpp @@ -0,0 +1,214 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include "record_td.h" + +#if 0 +#include +#include +#endif + +#define INFO(fmt, args...) fprintf(stderr, "[cRecord:%s:%d] " fmt, __FUNCTION__, __LINE__, ##args) +#if 0 // change for verbose debug output +#define DBG INFO +#else +#define DBG(args...) +#endif + +/* helper function to call the cpp thread loop */ +void *execute_record_thread(void *c) +{ + cRecord *obj = (cRecord *)c; + obj->RecordThread(); + return NULL; +} + +cRecord::cRecord(int /*num*/) +{ + INFO("\n"); + dmx = NULL; + record_thread_running = false; + file_fd = -1; + exit_flag = RECORD_STOPPED; +} + +cRecord::~cRecord() +{ + INFO("calling ::Stop()\n"); + Stop(); + INFO("end\n"); +} + +bool cRecord::Open(int /*numpids*/) +{ + INFO("\n"); + exit_flag = RECORD_STOPPED; + return true; +} + +#if 0 +// unused +void cRecord::Close(void) +{ + INFO("\n"); +} +#endif + +bool cRecord::Start(int fd, unsigned short vpid, unsigned short * apids, int numpids) +{ + INFO("fd %d, vpid 0x%02x\n", fd, vpid); + int i; + + if (!dmx) + dmx = new cDemux(1); + + dmx->Open(DMX_TP_CHANNEL, NULL, 0); + dmx->pesFilter(vpid); + + for (i = 0; i < numpids; i++) + dmx->addPid(apids[i]); + + file_fd = fd; + exit_flag = RECORD_RUNNING; + if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED)) + perror("posix_fadvise"); + + i = pthread_create(&record_thread, 0, execute_record_thread, this); + if (i != 0) + { + exit_flag = RECORD_FAILED_READ; + errno = i; + INFO("error creating thread! (%m)\n"); + delete dmx; + dmx = NULL; + return false; + } + record_thread_running = true; + return true; +} + +bool cRecord::Stop(void) +{ + INFO("\n"); + + if (exit_flag != RECORD_RUNNING) + INFO("status not RUNNING? (%d)\n", exit_flag); + + exit_flag = RECORD_STOPPED; + if (record_thread_running) + pthread_join(record_thread, NULL); + record_thread_running = false; + + /* We should probably do that from the destructor... */ + if (!dmx) + INFO("dmx == NULL?\n"); + else + delete dmx; + dmx = NULL; + + if (file_fd != -1) + close(file_fd); + else + INFO("file_fd not open??\n"); + file_fd = -1; + return true; +} + +void cRecord::RecordThread() +{ + INFO("begin\n"); +#define BUFSIZE (1 << 19) /* 512 kB */ + ssize_t r = 0; + int buf_pos = 0; + uint8_t *buf; + buf = (uint8_t *)malloc(BUFSIZE); + + if (!buf) + { + exit_flag = RECORD_FAILED_MEMORY; + INFO("unable to allocate buffer! (out of memory)\n"); + } + + dmx->Start(); + while (exit_flag == RECORD_RUNNING) + { + if (buf_pos < BUFSIZE) + { + r = dmx->Read(buf + buf_pos, BUFSIZE - 1 - buf_pos, 100); + DBG("buf_pos %6d r %6d / %6d\n", buf_pos, (int)r, BUFSIZE - 1 - buf_pos); + if (r < 0) + { + if (errno != EAGAIN) + { + INFO("read failed: %m\n"); + exit_flag = RECORD_FAILED_READ; + break; + } + INFO("EAGAIN\n"); + } + else + buf_pos += r; + } + else + INFO("buffer full! Overflow?\n"); + if (buf_pos > (BUFSIZE / 3)) /* start writeout */ + { + size_t towrite = BUFSIZE / 2; + if (buf_pos < BUFSIZE / 2) + towrite = buf_pos; + r = write(file_fd, buf, towrite); + if (r < 0) + { + exit_flag = RECORD_FAILED_FILE; + INFO("write error: %m\n"); + break; + } + buf_pos -= r; + memmove(buf, buf + r, buf_pos); + DBG("buf_pos %6d w %6d / %6d\n", buf_pos, (int)r, (int)towrite); +#if 0 + if (fdatasync(file_fd)) + perror("cRecord::FileThread() fdatasync"); +#endif + if (posix_fadvise(file_fd, 0, 0, POSIX_FADV_DONTNEED)) + perror("posix_fadvise"); + } + } + dmx->Stop(); + while (buf_pos > 0) /* write out the unwritten buffer content */ + { + r = write(file_fd, buf, buf_pos); + if (r < 0) + { + exit_flag = RECORD_FAILED_FILE; + INFO("write error: %m\n"); + break; + } + buf_pos -= r; + memmove(buf, buf + r, buf_pos); + } + free(buf); + +#if 0 + // TODO: do we need to notify neutrino about failing recording? + CEventServer eventServer; + eventServer.registerEvent2(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, "/tmp/neutrino.sock"); + stream2file_status2_t s; + s.status = exit_flag; + strncpy(s.filename,basename(myfilename),512); + s.filename[511] = '\0'; + strncpy(s.dir,dirname(myfilename),100); + s.dir[99] = '\0'; + eventServer.sendEvent(NeutrinoMessages::EVT_RECORDING_ENDED, CEventServer::INITID_NEUTRINO, &s, sizeof(s)); + printf("[stream2file]: pthreads exit code: %i, dir: '%s', filename: '%s' myfilename: '%s'\n", exit_flag, s.dir, s.filename, myfilename); +#endif + + INFO("end"); + pthread_exit(NULL); +} + diff --git a/lib/libtriple/record_td.h b/lib/libtriple/record_td.h new file mode 100644 index 000000000..3ee61c317 --- /dev/null +++ b/lib/libtriple/record_td.h @@ -0,0 +1,39 @@ +#ifndef __RECORD_TD_H +#define __RECORD_TD_H + +#include +#include "dmx_td.h" + +typedef enum { + RECORD_RUNNING, + RECORD_STOPPED, + RECORD_FAILED_READ, /* failed to read from DMX */ + RECORD_FAILED_OVERFLOW, /* cannot write fast enough */ + RECORD_FAILED_FILE, /* cannot write to file */ + RECORD_FAILED_MEMORY /* out of memory */ +} record_state_t; + +class cRecord +{ + private: + int file_fd; + cDemux *dmx; + pthread_t record_thread; + bool record_thread_running; + record_state_t exit_flag; + public: + cRecord(int num = 0); + ~cRecord(); + + bool Open(int numpids); + bool Start(int fd, unsigned short vpid, unsigned short *apids, int numpids); + bool Stop(void); + + void RecordThread(); +#if 0 + /* apparently unused */ + void Close(void); + void RecordNotify(int Event, void *pData); +#endif +}; +#endif From acfde0eaf03a1c095c1e3d6205cfa6a816e2f6a2 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 13 Mar 2010 22:11:40 +0100 Subject: [PATCH 0008/1070] libtriple: implement working cPlayback class no fast forward, no mpeg playback (yet ;) Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/912b736dee1bb74e35b426fe28cadafd5c4914fe Author: Stefan Seyfried Date: 2010-03-13 (Sat, 13 Mar 2010) ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 1171 +++++++++++++++++++++++++++++++++ lib/libtriple/playback_td.h | 120 ++++ 2 files changed, 1291 insertions(+) create mode 100644 lib/libtriple/playback_td.cpp create mode 100644 lib/libtriple/playback_td.h diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp new file mode 100644 index 000000000..59dd37cd0 --- /dev/null +++ b/lib/libtriple/playback_td.cpp @@ -0,0 +1,1171 @@ +#include +#include +#include +#include +#include +#include + +#include +#include "playback_td.h" +#include "dmx_td.h" +#include "audio_td.h" +#include "video_td.h" + +#include +#define DVR "/dev/" DEVICE_NAME_PVR + +#define INFO(fmt, args...) fprintf(stderr, "[cPlayback:%s:%d] " fmt, __FUNCTION__, __LINE__, ##args) +#if 0 // change for verbose debug output +#define DBG INFO +#else +#define DBG(args...) +#endif + +static int mp_syncPES(uint8_t *, int); +static int sync_ts(uint8_t *, int); +static inline uint16_t get_pid(uint8_t *buf); +static void *start_playthread(void *c); +static void playthread_cleanup_handler(void *); + +static pthread_cond_t playback_ready_cond = PTHREAD_COND_INITIALIZER; +static pthread_mutex_t playback_ready_mutex = PTHREAD_MUTEX_INITIALIZER; + +static int dvrfd = -1; + +extern cDemux *videoDemux; +extern cDemux *audioDemux; +extern cVideo *videoDecoder; +extern cAudio *audioDecoder; + +cPlayback::cPlayback(int) +{ + INFO("\n"); + thread_started = false; + inbuf = NULL; + pesbuf = NULL; + filelist.clear(); + curr_fileno = -1; + in_fd = -1; +} + +cPlayback::~cPlayback() +{ + INFO("\n"); + Close(); +} + + +bool cPlayback::Open(playmode_t mode) +{ + static const char *PMODE[] = { + "PLAYMODE_TS", + "PLAYMODE_FILE" + }; + + INFO("PlayMode = %s\n", PMODE[mode]); + thread_started = false; + playMode = mode; + filetype = FILETYPE_TS; + playback_speed = 0; + last_size = 0; + numpida = 0; + memset(&apids, 0, sizeof(apids)); + memset(&ac3flags, 0, sizeof(ac3flags)); + memset(&cc, 0, 256); + return true; +} + +//Used by Fileplay +void cPlayback::Close(void) +{ + INFO("\n"); + playstate = STATE_STOP; + if (thread_started) + { + INFO("before pthread_join\n"); + pthread_join(thread, NULL); + } + thread_started = false; + INFO("after pthread_join\n"); + mf_close(); + filelist.clear(); + + if (inbuf) + free(inbuf); + inbuf = NULL; + if (pesbuf) + free(pesbuf); + pesbuf = NULL; + //Stop(); +} + +bool cPlayback::Start(char *filename, unsigned short vp, int vtype, unsigned short ap, bool _ac3) +{ + struct stat s; + off_t r; + vpid = vp; + apid = ap; + ac3 = _ac3; + INFO("name = '%s' vpid 0x%04hx vtype %d apid 0x%04hx ac3 %d filelist.size: %u\n", + filename, vpid, vtype, apid, ac3, filelist.size()); + if (!filelist.empty()) + { + INFO("filelist not empty?\n"); + return false; + } + if (stat(filename, &s)) + { + INFO("filename does not exist? (%m)\n"); + return false; + } + if (!inbuf) + inbuf = (uint8_t *)malloc(INBUF_SIZE); /* 256 k */ + if (!inbuf) + { + INFO("allocating input buffer failed (%m)\n"); + return false; + } + if (!pesbuf) + pesbuf = (uint8_t *)malloc(PESBUF_SIZE); /* 128 k */ + if (!pesbuf) + { + INFO("allocating PES buffer failed (%m)\n"); + return false; + } + filelist_t file; + file.Name = std::string(filename); + file.Size = s.st_size; + filelist.push_back(file); + filelist_auto_add(); + if (mf_open(0) < 0) + return false; + + curr_pos = 0; + inbuf_pos = 0; + inbuf_sync = 0; + r = mf_getsize(); + + if (r > INBUF_SIZE) + { + if (mp_seekSync(r - INBUF_SIZE) < 0) + return false; + inbuf_read(); /* assume that we fill the buffer with one read() */ + for (r = (inbuf_pos / 188) * 188; r > 0; r -= 188) + { + pts_end = get_pts(inbuf + r, false); + if (pts_end > -1) + break; + } + } + else + pts_end = -1; /* unknown */ + + if (mp_seekSync(0) < 0) + return false; + + pesbuf_pos = 0; + inbuf_pos = 0; + inbuf_sync = 0; + while (inbuf_pos < INBUF_SIZE / 2 && inbuf_read() > 0) {}; + for (r = 0; r < inbuf_pos - 188; r += 188) + { + pts_start = get_pts(inbuf + r, false); + if (pts_start > -1) + break; + } + pts_curr = pts_start; + bytes_per_second = -1; + int duration = (pts_end - pts_start) / 90000; + if (duration > 0) + bytes_per_second = mf_getsize() / duration; + INFO("start: %lld end %lld duration %d bps %lld\n", pts_start, pts_end, duration, bytes_per_second); + /* yes, we start in pause mode... */ + playback_speed = 0; + if (pts_start == -1) + playstate = STATE_INIT; + else + playstate = STATE_PAUSE; + pthread_mutex_lock(&playback_ready_mutex); + if (pthread_create(&thread, 0, start_playthread, this) != 0) + INFO("pthread_create failed\n"); + else + pthread_cond_wait(&playback_ready_cond, &playback_ready_mutex); + pthread_mutex_unlock(&playback_ready_mutex); + return true; +} + +static void *start_playthread(void *c) +{ + cPlayback *obj = (cPlayback *)c; + obj->playthread(); + return NULL; +} + +void cPlayback::playthread(void) +{ + thread_started = true; + int ret, towrite; + dvrfd = open(DVR, O_WRONLY); + if (dvrfd < 0) + { + INFO("open tdpvr failed: %m\n"); + pthread_exit(NULL); + } + + pthread_cleanup_push(playthread_cleanup_handler, 0); + + ioctl(audioDemux->getFD(), DEMUX_SELECT_SOURCE, INPUT_FROM_PVR); + if (ac3) + audioDecoder->SetStreamType(AUDIO_FMT_DOLBY_DIGITAL); + else + audioDecoder->SetStreamType(AUDIO_FMT_MPEG); + + audioDemux->pesFilter(apid); + videoDemux->pesFilter(vpid); + +// audioDemux->Start(); + videoDemux->Start(); + +// videoDecoder->setBlank(1); +// videoDecoder->Start(); +// audioDecoder->Start(); + /* everything is set up now, signal ::Start() that it can return */ + pthread_mutex_lock(&playback_ready_mutex); + pthread_cond_broadcast(&playback_ready_cond); + pthread_mutex_unlock(&playback_ready_mutex); + + while (playstate != STATE_STOP) + { + if (playstate == STATE_INIT) + { + /* hack for timeshift to determine start PTS */ + if (inbuf_read() < 0) + break; + usleep(100000); + if (pts_start == -1) + continue; + } + + if (playback_speed == 0) + { + playstate = STATE_PAUSE; + usleep(1); + continue; + } + if (inbuf_read() < 0) + break; + + /* autoselect PID for PLAYMODE_FILE */ + if (apid == 0 && numpida > 0) + { + for (int i = 0; i < numpida; i++) + { + if (ac3flags[i] == 0) + { + apid = apids[i]; + INFO("setting Audio pid to 0x%04hx\n", apid); + SetAPid(apid, 0); + break; + } + } + } + + towrite = inbuf_pos / 188 * 188; /* TODO: smaller chunks? */ + if (towrite == 0) + continue; + retry: + ret = write(dvrfd, inbuf, towrite); + if (ret < 0) + { + if (errno == EAGAIN && playstate != STATE_STOP) + goto retry; + INFO("write dvr failed: %m\n"); + break; + } + memmove(inbuf, inbuf + ret, inbuf_pos - ret); + inbuf_pos -= ret; + } + + pthread_cleanup_pop(1); + pthread_exit(NULL); +} + +static void playthread_cleanup_handler(void *) +{ + INFO("\n"); + ioctl(audioDemux->getFD(), DEMUX_SELECT_SOURCE, INPUT_FROM_CHANNEL0); + audioDemux->Stop(); + videoDemux->Stop(); + audioDecoder->Stop(); + videoDecoder->Stop(); + close(dvrfd); + dvrfd = -1; +} + +bool cPlayback::SetAPid(unsigned short pid, bool _ac3) +{ + INFO("pid: 0x%04hx ac3: %d\n", pid, _ac3); + apid = pid; + ac3 = _ac3; + + audioDemux->Stop(); + audioDecoder->Stop(); + videoDemux->Stop(); + videoDecoder->Stop(false); + + if (ac3) + audioDecoder->SetStreamType(AUDIO_FMT_DOLBY_DIGITAL); + else + audioDecoder->SetStreamType(AUDIO_FMT_MPEG); + audioDemux->pesFilter(apid); + + videoDemux->Start(); + audioDemux->Start(); + audioDecoder->Start(); + videoDecoder->Start(); + return true; +} + +bool cPlayback::SetSpeed(int speed) +{ + INFO("speed = %d\n", speed); + if (speed != 0 && playback_speed == 0) + { + videoDemux->Stop(); + videoDemux->Start(); + audioDemux->Start(); + audioDecoder->Start(); + videoDecoder->Start(); + playstate = STATE_PLAY; + } + playback_speed = speed; + if (playback_speed == 0) + { + audioDecoder->Stop(); + audioDemux->Stop(); + videoDecoder->Stop(false); + } + return true; +} + +bool cPlayback::GetSpeed(int &speed) const +{ + DBG("\n"); + speed = playback_speed; + return true; +} + +// in milliseconds +bool cPlayback::GetPosition(int &position, int &duration) +{ + int64_t tmppts; + DBG("\n"); + off_t currsize = mf_getsize(); + bool update = false; + /* handle a growing file, e.g. for timeshift. + this might be pretty expensive... */ + if (filetype == FILETYPE_TS && filelist.size() == 1) + { + off_t tmppos = currsize - PESBUF_SIZE; + if (currsize != last_size && tmppos > 0) + { + update = true; + /* file size has changed => update endpts */ + last_size = currsize; + off_t oldpos = curr_pos; + ssize_t n, r; + int s; + mf_lseek(tmppos); + n = read(in_fd, pesbuf, PESBUF_SIZE); /* abuse the pesbuf... */ + s = sync_ts(pesbuf, n); + if (s >= 0) + { + n -= s; + for (r = (n / 188) * 188; r > 0; r -= 188) + { + tmppts = get_pts(pesbuf + r + s, false); + if (tmppts > -1) + { + DBG("n: %d s: %d endpts %lld size: %lld\n", n, s, tmppts, currsize); + pts_end = tmppts; + break; + } + } + } + mf_lseek(oldpos); + } + } + if (pts_end != -1 && pts_start > pts_end) /* should trigger only once ;) */ + pts_end += 0x200000000ULL; + + if (pts_curr != -1 && pts_curr < pts_start) + tmppts = pts_curr + 0x200000000ULL - pts_start; + else + tmppts = pts_curr - pts_start; + if (pts_end != -1 && pts_curr != -1) + { + position = tmppts / 90; + duration = (pts_end - pts_start) / 90; + if (update && duration >= 1000) + { + bytes_per_second = currsize / (duration / 1000); + INFO("updated bps: %lld size: %lld duration %d\n", bytes_per_second, currsize, duration); + } + return true; + } + position = 0; + duration = 0; + return false; +} + +bool cPlayback::SetPosition(int position, bool absolute) +{ + INFO("pos = %d abs = %d\n", position, absolute); + int currpos, target, duration, oldspeed; + bool ret; + + if (absolute) + target = position; + else + { + GetPosition(currpos, duration); + target = currpos + position; + INFO("current position %d target %d\n", currpos, target); + } + + oldspeed = playback_speed; + if (oldspeed != 0) + SetSpeed(0); /* request pause */ + + while (playstate == STATE_PLAY) /* playthread did not acknowledge pause */ + usleep(1); + if (playstate == STATE_STOP) /* we did get stopped by someone else */ + return false; + + ret = (seek_to_pts(target * 90) > 0); + + if (oldspeed != 0) + { + SetSpeed(oldspeed); + /* avoid ugly artifacts */ + videoDecoder->Stop(); + videoDecoder->Start(); + } + return ret; +} + +void cPlayback::FindAllPids(uint16_t *_apids, unsigned short *_ac3flags, uint16_t *_numpida, std::string *language) +{ + INFO("\n"); + memcpy(_apids, &apids, sizeof(apids)); + memcpy(_ac3flags, &ac3flags, sizeof(&ac3flags)); + language = alang; /* TODO: language */ + *_numpida = numpida; +} + +off_t cPlayback::seek_to_pts(int64_t pts) +{ + off_t newpos = curr_pos; + int64_t tmppts, ptsdiff; + int count = 0; + if (pts_start < 0 || pts_end < 0 || bytes_per_second < 0) + { + INFO("pts_start (%lld) or pts_end (%lld) or bytes_per_second (%lld) not initialized\n", + pts_start, pts_end, bytes_per_second); + return -1; + } + /* sanity check: buffer is without locking, so we must only seek while in pause mode */ + if (playstate != STATE_PAUSE) + { + INFO("playstate (%d) != STATE_PAUSE, not seeking\n", playstate); + return -1; + } + + /* tmppts is normalized current pts */ + if (pts_curr < pts_start) + tmppts = pts_curr + 0x200000000ULL - pts_start; + else + tmppts = pts_curr - pts_start; + while (abs(pts - tmppts) > 90000LL && count < 10) + { + count++; + ptsdiff = pts - tmppts; + newpos += ptsdiff * bytes_per_second / 90000; + INFO("try #%d seek from %lldms to %lldms dt %lldms pos %lldk newpos %lldk kB/s %lld\n", + count, tmppts / 90, pts / 90, ptsdiff / 90, curr_pos / 1024, newpos / 1024, bytes_per_second / 1024); + if (newpos < 0) + newpos = 0; + newpos = mp_seekSync(newpos); + if (newpos < 0) + return newpos; + inbuf_pos = 0; + inbuf_sync = 0; + inbuf_read(); /* also updates current pts */ + if (pts_curr < pts_start) + tmppts = pts_curr + 0x200000000ULL - pts_start; + else + tmppts = pts_curr - pts_start; + } + INFO("end after %d tries, ptsdiff now %lld sec\n", count, (pts - tmppts) / 90000); + return newpos; +} + +bool cPlayback::filelist_auto_add() +{ + if (filelist.size() != 1) + return false; + + const char *filename = filelist[0].Name.c_str(); + const char *ext; + ext = strrchr(filename, '.'); // FOO-xxx-2007-12-31.001.ts <- the dot before "ts" + // 001.vdr <- the dot before "vdr" + // check if there is something to do... + if (! ext) + return false; + if (!((ext - 7 >= filename && !strcmp(ext, ".ts") && *(ext - 4) == '.') || + (ext - 4 >= filename && !strcmp(ext, ".vdr")))) + return false; + + int num = 0; + struct stat s; + size_t numpos = strlen(filename) - strlen(ext) - 3; + sscanf(filename + numpos, "%d", &num); + do { + num++; + char nextfile[strlen(filename) + 1]; /* todo: use fixed buffer? */ + memcpy(nextfile, filename, numpos); + sprintf(nextfile + numpos, "%03d%s", num, ext); + if (stat(nextfile, &s)) + break; // file does not exist + filelist_t file; + file.Name = std::string(nextfile); + file.Size = s.st_size; + INFO("auto-adding '%s' to playlist\n", nextfile); + filelist.push_back(file); + } while (true && num < 999); + + return (filelist.size() > 1); +} + +/* the mf_* functions are wrappers for multiple-file I/O */ +int cPlayback::mf_open(int fileno) +{ + if (filelist.empty()) + return -1; + + if (fileno >= (int)filelist.size()) + return -1; + + mf_close(); + + in_fd = open(filelist[fileno].Name.c_str(), O_RDONLY); + if (in_fd != -1) + curr_fileno = fileno; + + return in_fd; +} + +int cPlayback::mf_close(void) +{ + int ret = 0; +INFO("in_fd = %d curr_fileno = %d\n", in_fd, curr_fileno); + if (in_fd != -1) + ret = close(in_fd); + in_fd = curr_fileno = -1; + + return ret; +} + +off_t cPlayback::mf_getsize(void) +{ + off_t ret = 0; + if (filelist.size() == 1 && in_fd != -1) + { + /* for timeshift, we need to deal with a growing file... */ + struct stat st; + if (fstat(in_fd, &st) == 0) + return st.st_size; + /* else, fallback to filelist.size() */ + } + for (unsigned int i = 0; i < filelist.size(); i++) + ret += filelist[i].Size; + return ret; +} + +off_t cPlayback::mf_lseek(off_t pos) +{ + off_t offset = 0, lpos = pos, ret; + unsigned int fileno; + /* this is basically needed for timeshifting - to allow + growing files to be handled... */ + if (filelist.size() == 1 && filetype == FILETYPE_TS) + { + if (lpos > mf_getsize()) + return -2; + fileno = 0; + } + else + { + for (fileno = 0; fileno < filelist.size(); fileno++) + { + if (lpos < filelist[fileno].Size) + break; + offset += filelist[fileno].Size; + lpos -= filelist[fileno].Size; + } + if (fileno == filelist.size()) + return -2; // EOF + } + + if ((int)fileno != curr_fileno) + { + INFO("old fileno: %d new fileno: %d, offset: %lld\n", curr_fileno, fileno, (long long)lpos); + in_fd = mf_open(fileno); + if (in_fd < 0) + { + INFO("cannot open file %d:%s (%m)\n", fileno, filelist[fileno].Name.c_str()); + return -1; + } + } + + ret = lseek(in_fd, lpos, SEEK_SET); + if (ret < 0) + return ret; + + curr_pos = offset + ret; + return curr_pos; +} + +/* gets the PTS at a specific file position from a PES + ATTENTION! resets buf! */ +int64_t cPlayback::get_PES_PTS(uint8_t *buf, int len, bool last) +{ + int64_t pts = -1; + int off, plen; + uint8_t *p; + + off = mp_syncPES(buf, len); + + if (off < 0) + return off; + + p = buf + off; + while (off < len - 14 && (pts == -1 || last)) + { + plen = ((p[4] << 8) | p[5]) + 6; + + switch(p[3]) + { + int64_t tmppts; + case 0xe0 ... 0xef: // video! + tmppts = get_pts(p, true); + if (tmppts >= 0) + pts = tmppts; + break; + case 0xbb: + case 0xbe: + case 0xbf: + case 0xf0 ... 0xf3: + case 0xff: + case 0xc0 ... 0xcf: + case 0xd0 ... 0xdf: + break; + case 0xb9: + case 0xba: + case 0xbc: + default: + plen = 1; + break; + } + p += plen; + off += plen; + } + return pts; +} + +ssize_t cPlayback::inbuf_read() +{ + if (filetype == FILETYPE_UNKNOWN) + return -1; + if (filetype == FILETYPE_TS) + return read_ts(); + /* FILETYPE_MPG or FILETYPE_VDR */ + return read_mpeg(); +} + +ssize_t cPlayback::read_ts() +{ + ssize_t toread, ret = 0, sync, off; + toread = INBUF_SIZE - inbuf_pos; + bool retry = true; + /* fprintf(stderr, "%s:%d curr_pos %lld, inbuf_pos: %ld, toread: %ld\n", + __FUNCTION__, __LINE__, (long long)curr_pos, (long)inbuf_pos, (long)toread); */ + + while(true) + { + ret = read(in_fd, inbuf + inbuf_pos, toread); + if (ret == 0 && retry) /* EOF */ + { + mf_lseek(curr_pos); + retry = false; + continue; + } + break; + } + if (ret < 0) + { + INFO("failed: %m\n"); + return ret; + } + if (ret == 0) + return ret; + inbuf_pos += ret; + curr_pos += ret; + + sync = sync_ts(inbuf + inbuf_sync, INBUF_SIZE - inbuf_sync); + if (sync < 0) + { + INFO("cannot sync\n"); + return ret; + } + inbuf_sync += sync; + /* check for A/V PIDs */ + uint16_t pid; + int i, j; + bool pid_new; + int64_t pts; + // fprintf(stderr, "inbuf_pos: %ld - sync: %ld\n", (long)inbuf_pos, (long)sync); + int synccnt = 0; + for (i = 0; i < inbuf_pos - inbuf_sync - 13;) { + uint8_t *buf = inbuf + inbuf_sync + i; + if (*buf != 0x47) + { + synccnt++; + i++; + continue; + } + if (synccnt) + INFO("TS went out of sync %d\n", synccnt); + synccnt = 0; + if (!(buf[1] & 0x40)) /* PUSI */ + { + i += 188; + continue; + } + off = 0; + if (buf[3] & 0x20) /* adaptation field? */ + off = buf[4] + 1; + pid = get_pid(buf + 1); + pid_new = true; + /* PES signature is at buf + 4, streamtype is after 00 00 01 */ + switch (buf[4 + 3 + off]) + { + case 0xe0 ... 0xef: /* video stream */ + if (vpid == 0) + vpid = pid; + pts = get_pts(buf + 4 + off, true); + if (pts < 0) + break; + pts_curr = pts; + if (pts_start < 0) + { + INFO("updating pts_start to %lld ", pts); + pts_start = pts; + if (pts_end > -1) + { + if (pts_end < pts_start) + { + pts_end += 0x200000000ULL; + fprintf(stderr, "pts_end to %lld ", pts_end); + } + int duration = (pts_end - pts_start) / 90000; + if (duration > 0) + { + bytes_per_second = (mf_getsize() - curr_pos) / duration; + fprintf(stderr, "bytes_per_second to %lldk duration to %ds at %lldk", + bytes_per_second / 1024, duration, curr_pos / 1024); + } + } + fprintf(stderr, "\n"); + } + break; + case 0xbd: /* private stream 1 - ac3 */ + case 0xc0 ... 0xdf: /* audio stream */ + if (numpida > 9) + break; + for (j = 0; j < numpida; j++) { + if (apids[j] == pid) + { + pid_new = false; + break; + } + } + if (!pid_new) + break; + if (buf[7 + off] == 0xbd) + { + if (buf[12 + off] == 0x24) /* 0x24 == TTX */ + break; + ac3flags[numpida] = 1; + } + else + ac3flags[numpida] = 0; + apids[numpida] = pid; + INFO("found apid #%d 0x%04hx ac3:%d\n", numpida, pid, ac3flags[numpida]); + numpida++; + break; + } + i += 188; + } + + // fprintf(stderr, "%s:%d ret %ld\n", __FUNCTION__, __LINE__, (long long)ret); + return ret; +} + +ssize_t cPlayback::read_mpeg() +{ + ssize_t toread, ret, sync; + toread = PESBUF_SIZE - pesbuf_pos; + bool retry = true; + + while(true) + { + ret = read(in_fd, pesbuf + pesbuf_pos, toread); + if (ret == 0 && retry) /* EOF */ + { + mf_lseek(curr_pos); + retry = false; + continue; + } + break; + } + if (ret < 0) + { + INFO("failed: %m\n"); + return ret; + } + pesbuf_pos += ret; + curr_pos += ret; + + int i; + int count = 0; + uint16_t pid = 0; + while (count < pesbuf_pos - 10) + { + sync = mp_syncPES(pesbuf + count, pesbuf_pos - count - 10); + if (sync < 0) + { + INFO("cannot sync\n"); + break; + } + if (sync) + INFO("needed sync\n"); + count += sync; + uint8_t *ppes = pesbuf + count; + int av = 0; // 1 = video, 2 = audio + int64_t pts; + switch(ppes[3]) + { + case 0xba: + // fprintf(stderr, "pack start code, 0x%02x\n", ppes[4]); + if ((ppes[4] & 0x3) == 1) // ?? + { + //type = 1; // mpeg1 + count += 12; + } + else + count += 14; + continue; + break; + case 0xbd: // AC3 + { + int off = ppes[8] + 8 + 1; // ppes[8] is often 0 + if (count + off >= pesbuf_pos) + break; + int subid = ppes[off]; + // if (offset == 0x24 && subid == 0x10 ) // TTX? + if (subid < 0x80 || subid > 0x87) + break; + DBG("AC3: ofs 0x%02x subid 0x%02x\n", off, subid); + //subid -= 0x60; // normalize to 32...39 (hex 0x20..0x27) + + if (numpida > 9) + break; + bool found = false; + for (i = 0; i < numpida; i++) { + if (apids[i] == subid) + { + found = true; + break; + } + } + if (!found) + { + apids[numpida] = subid; + ac3flags[numpida] = 1; + numpida++; + INFO("found aid: %02x\n", subid); + } + pid = subid; + av = 2; + break; + } + case 0xbb: + case 0xbe: + case 0xbf: + case 0xf0 ... 0xf3: + case 0xff: + //skip = (ppes[4] << 8 | ppes[5]) + 6; + //DBG("0x%02x header, skip = %d\n", ppes[3], skip); + break; + case 0xc0 ... 0xcf: + case 0xd0 ... 0xdf: + { + // fprintf(stderr, "audio stream 0x%02x\n", ppes[3]); + int id = ppes[3]; // - 0xC0; // normalize to 0...31 (hex 0x0...0x1f) + bool found = false; + for (i = 0; i < numpida; i++) { + if (apids[i] == id) + { + found = true; + break; + } + } + if (!found) + { + apids[numpida] = id; + ac3flags[numpida] = 0; + numpida++; + INFO("found aid: %02x\n", id); + } + pid = id; + av = 2; + break; + } + case 0xe0 ... 0xef: + // fprintf(stderr, "video stream 0x%02x, %02x %02x \n", ppes[3], ppes[4], ppes[5]); + pid = 0x40; + av = 1; + pts = get_pts(ppes, true); + if (pts < 0) + break; + pts_curr = pts; + if (pts_start < 0) + pts_start = pts; + break; + case 0xb9: + case 0xbc: + DBG("%s\n", (ppes[3] == 0xb9) ? "program_end_code" : "program_stream_map"); + //resync = true; + // fallthrough. TODO: implement properly. + default: + //if (! resync) + // DBG("Unknown stream id: 0x%X.\n", ppes[3]); + count++; + continue; + break; + } + + int pesPacketLen = ((ppes[4] << 8) | ppes[5]) + 6; + if (count + pesPacketLen >= pesbuf_pos) + { + INFO("buffer len: %d, pesPacketLen: %d :-(\n", pesbuf_pos - count, pesPacketLen); + memmove(pesbuf, ppes, pesbuf_pos - count); + pesbuf_pos -= count; + break; + } + + if (av) + { + int tsPacksCount = pesPacketLen / 184; + int rest = pesPacketLen % 184; + + // divide PES packet into small TS packets + uint8_t pusi = 0x40; + int j; + uint8_t *ts = inbuf + inbuf_pos; + for (j = 0; j < tsPacksCount; j++) + { + ts[0] = 0x47; // SYNC Byte + ts[1] = pusi; // Set PUSI if first packet + ts[2] = pid; // PID (low) + ts[3] = 0x10 | (cc[pid] & 0x0F); // No adaptation field, payload only, continuity counter + cc[pid]++; + memcpy(ts + 4, ppes + j * 184, 184); + pusi = 0x00; // clear PUSI + ts += 188; + inbuf_pos += 188; + } + + if (rest > 0) + { + ts[0] = 0x47; // SYNC Byte + ts[1] = pusi; // Set PUSI or + ts[2] = pid; // PID (low) + ts[3] = 0x30 | (cc[pid] & 0x0F); // adaptation field, payload, continuity counter + cc[pid]++; + ts[4] = 183 - rest; + if (ts[4] > 0) + { + ts[5] = 0x00; + memset(ts + 6, 0xFF, ts[4] - 1); + } + memcpy(ts + 188 - rest, ppes + j * 184, rest); + inbuf_pos += 188; + } + } //if (av) + + memmove(pesbuf, ppes + pesPacketLen, pesbuf_pos - count - pesPacketLen); + pesbuf_pos -= count + pesPacketLen; + count = 0; /* we shifted everything to the start of the buffer => offset == 0 */ + } + return ret; +} + +//== seek to pos with sync to next proper TS packet == +//== returns offset to start of TS packet or actual == +//== pos on failure. == +//==================================================== +off_t cPlayback::mp_seekSync(off_t pos) +{ + off_t npos = pos; + off_t ret; + uint8_t pkt[188]; + + ret = mf_lseek(npos); + if (ret < 0) + INFO("lseek ret < 0 (%m)\n"); + + while (read(in_fd, pkt, 1) > 0) + { + //-- check every byte until sync word reached -- + npos++; + if (*pkt == 0x47) + { + //-- if found double check for next sync word -- + if (read(in_fd, pkt, 188) == 188) + { + if(pkt[188-1] == 0x47) + { + ret = mf_lseek(npos - 1); // assume sync ok + if (ret < 0) + INFO("lseek ret < 0 (%m)\n"); + return ret; + } + else + { + ret = mf_lseek(npos); // oops, next pkt doesn't start with sync + if (ret < 0) + INFO("lseek ret < 0 (%m)\n"); + } + } + } + + //-- check probe limits -- + if (npos > (pos + 100 * 188)) + break; + } + + //-- on error stay on actual position -- + return mf_lseek(pos); +} + +static int sync_ts(uint8_t *p, int len) +{ + int count; + if (len < 189) + return -1; + + count = 0; + while (*p != 0x47 || *(p + 188) != 0x47) + { + count++; + p++; + if (count + 188 > len) + return -1; + } + return count; +} + +/* get the pts value from a TS or PES packet + pes == true selects PES mode. */ +int64_t cPlayback::get_pts(uint8_t *p, bool pes) +{ + if (!pes) + { + const uint8_t *end = p + 188; + if (p[0] != 0x47) + return -1; + if (!(p[1] & 0x40)) + return -1; + if (get_pid(p + 1) != vpid) + return -1; + if (!(p[3] & 0x10)) + return -1; + + if (p[3] & 0x20) + p += p[4] + 4 + 1; + else + p += 4; + + if (p + 13 > end) + return -1; + /* p is now pointing at the PES header. hopefully */ + if (p[0] || p[1] || (p[2] != 1)) + return -1; + } + + if ((p[7] & 0x80) == 0) // packets with both pts, don't care for dts + // if ((p[7] & 0xC0) != 0x80) // packets with only pts + // if ((p[7] & 0xC0) != 0xC0) // packets with pts and dts + return -1; + if (p[8] < 5) + return -1; + if (!(p[9] & 0x20)) + return -1; + + int64_t pts = + ((p[ 9] & 0x0EULL) << 29) | + ((p[10] & 0xFFULL) << 22) | + ((p[11] & 0xFEULL) << 14) | + ((p[12] & 0xFFULL) << 7) | + ((p[13] & 0xFEULL) >> 1); + + //int msec = pts / 90; + //INFO("time: %02d:%02d:%02d\n", msec / 3600000, (msec / 60000) % 60, (msec / 1000) % 60); + return pts; +} + +/* returns: 0 == was already synchronous, > 0 == is now synchronous, -1 == could not sync */ +static int mp_syncPES(uint8_t *buf, int len) +{ + int ret = 0; + while (ret < len - 3) + { + if (buf[ret + 2] != 0x01) + { + ret++; + continue; + } + if (buf[ret + 1] != 0x00) + { + ret += 2; + continue; + } + if (buf[ret] != 0x00) + { + ret += 3; + continue; + } + return ret; + } + + INFO("No valid PES signature found. %d Bytes deleted.\n", ret); + return -1; +} + +static inline uint16_t get_pid(uint8_t *buf) +{ + return (*buf & 0x1f) << 8 | *(buf + 1); +} + diff --git a/lib/libtriple/playback_td.h b/lib/libtriple/playback_td.h new file mode 100644 index 000000000..006a3b64d --- /dev/null +++ b/lib/libtriple/playback_td.h @@ -0,0 +1,120 @@ +#ifndef __PLAYBACK_TD_H +#define __PLAYBACK_TD_H + +#include +#include +#include + +/* almost 256kB */ +#define INBUF_SIZE (1394 * 188) +#define PESBUF_SIZE (128 * 1024) + +typedef enum { + PLAYMODE_TS = 0, + PLAYMODE_FILE, +} playmode_t; + +typedef enum { + FILETYPE_UNKNOWN, + FILETYPE_TS, + FILETYPE_MPG, + FILETYPE_VDR +} filetype_t; + +typedef enum { + STATE_STOP, + STATE_PLAY, + STATE_PAUSE, + STATE_FF, + STATE_REW, + STATE_INIT +} playstate_t; + +typedef struct { + std::string Name; + off_t Size; +} filelist_t; + +class cPlayback +{ + private: + uint8_t *inbuf; + ssize_t inbuf_pos; + ssize_t inbuf_sync; + uint8_t *pesbuf; + ssize_t pesbuf_pos; + ssize_t inbuf_read(void); + ssize_t read_ts(void); + ssize_t read_mpeg(void); + + uint8_t cc[256]; + + int in_fd; + + int video_type; + int playback_speed; + int mSpeed; + playmode_t playMode; + std::vector filelist; /* for multi-file playback */ + + bool filelist_auto_add(void); + int mf_open(int fileno); + int mf_close(void); + off_t mf_lseek(off_t pos); + off_t mf_getsize(void); + int curr_fileno; + off_t curr_pos; + off_t last_size; + off_t bytes_per_second; + + uint16_t vpid; + uint16_t apid; + bool ac3; + uint16_t apids[10]; + unsigned short ac3flags[10]; + std::string alang[10]; + uint16_t numpida; + + int64_t pts_start; + int64_t pts_end; + int64_t pts_curr; + int64_t get_pts(uint8_t *p, bool pes); + + filetype_t filetype; + playstate_t playstate; + + off_t seek_to_pts(int64_t pts); + off_t mp_seekSync(off_t pos); + int64_t get_PES_PTS(uint8_t *buf, int len, bool until_eof); + + pthread_t thread; + bool thread_started; + public: + cPlayback(int num = 0); + ~cPlayback(); + + void playthread(); + + bool Open(playmode_t PlayMode); + void Close(void); + bool Start(char *filename, unsigned short vpid, int vtype, unsigned short apid, bool ac3); + bool SetAPid(unsigned short pid, bool ac3); + bool SetSpeed(int speed); + bool GetSpeed(int &speed) const; + bool GetPosition(int &position, int &duration); /* pos: current time in ms, dur: file length in ms */ + bool SetPosition(int position, bool absolute = false); /* position: jump in ms */ + void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language); +#if 0 + // Functions that are not used by movieplayer.cpp: + bool Stop(void); + bool GetOffset(off64_t &offset); + bool IsPlaying(void) const { return playing; } + bool IsEnabled(void) const { return enabled; } + void * GetHandle(void); + void * GetDmHandle(void); + int GetCurrPlaybackSpeed(void) const { return nPlaybackSpeed; } + void PlaybackNotify (int Event, void *pData, void *pTag); + void DMNotify(int Event, void *pTsBuf, void *Tag); +#endif +}; +#endif From 599de89a92aefc48aeacec7e99a96c00877b64be Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 8 Aug 2010 13:27:26 +0200 Subject: [PATCH 0009/1070] libtriple: implement pwrmngr cpufreq classes (mostly dummies) Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/2fcba0b70efedf28a9d9b941e7aff6d10f194925 Author: Stefan Seyfried Date: 2010-08-08 (Sun, 08 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/pwrmngr.cpp | 67 +++++++++++++++++++++++++++++++++++++++ lib/libtriple/pwrmngr.h | 53 +++++++++++++++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 lib/libtriple/pwrmngr.cpp create mode 100644 lib/libtriple/pwrmngr.h diff --git a/lib/libtriple/pwrmngr.cpp b/lib/libtriple/pwrmngr.cpp new file mode 100644 index 000000000..7c7dfbe10 --- /dev/null +++ b/lib/libtriple/pwrmngr.cpp @@ -0,0 +1,67 @@ +#include + +#include "pwrmngr.h" +#include "lt_debug.h" +#include +#include +#include +#include +#include + +#include + +static const char * FILENAME = "pwrmngr.cpp"; + +void cCpuFreqManager::Up(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } +void cCpuFreqManager::Down(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } +void cCpuFreqManager::Reset(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } +/* those function dummies return true or "harmless" values */ +bool cCpuFreqManager::SetDelta(unsigned long) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); return true; } +unsigned long cCpuFreqManager::GetCpuFreq(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); return 0; } +unsigned long cCpuFreqManager::GetDelta(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); return 0; } +// +cCpuFreqManager::cCpuFreqManager(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } + +bool cPowerManager::SetState(PWR_STATE) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); return true; } + +bool cPowerManager::Open(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); return true; } +void cPowerManager::Close(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } +// +bool cPowerManager::SetStandby(bool Active, bool Passive) +{ + lt_debug("%s:%s(%d, %d)\n", FILENAME, __FUNCTION__, Active, Passive); + return true; +} + +bool cCpuFreqManager::SetCpuFreq(unsigned long f) +{ + /* actually SetCpuFreq is used to determine if the system is in standby + this is an "elegant" hack, because: + * during a recording, cpu freq is kept "high", even if the box is sent to standby + * the "SetStandby" call is made even if a recording is running + On the TD, setting standby disables the frontend, so we must not do it + if a recording is running. + For now, the values in neutrino are hardcoded: + * f == 0 => max => not standby + * f == 50000000 => min => standby + */ + lt_debug("%s:%s(%lu)\n", FILENAME, __FUNCTION__, f); + int fd = open("/dev/stb/tdsystem", O_RDONLY); + if (fd < 0) + { + perror("open tdsystem"); + return false; + } + if (f) + ioctl(fd, IOC_AVS_STANDBY_ENTER); + else + ioctl(fd, IOC_AVS_STANDBY_LEAVE); + + close(fd); + return true; +} + +// +cPowerManager::cPowerManager(void) { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } +cPowerManager::~cPowerManager() { lt_debug("%s:%s\n", FILENAME, __FUNCTION__); } + diff --git a/lib/libtriple/pwrmngr.h b/lib/libtriple/pwrmngr.h new file mode 100644 index 000000000..55dc98454 --- /dev/null +++ b/lib/libtriple/pwrmngr.h @@ -0,0 +1,53 @@ +#ifndef __PWRMNGR_H__ +#define __PWRMNGR_H__ + +// -- cCpuFreqManager ---------------------------------------------------------- + +class cCpuFreqManager { +private: + unsigned long startCpuFreq; + unsigned long delta; +public: + void Up(void); + void Down(void); + void Reset(void); + // + bool SetCpuFreq(unsigned long CpuFreq); + bool SetDelta(unsigned long Delta); + unsigned long GetCpuFreq(void); + unsigned long GetDelta(void); + // + cCpuFreqManager(void); + +}; + +// -- cPowerManageger ---------------------------------------------------------- + +typedef enum +{ + PWR_INIT = 1, + PWR_FULL_ACTIVE, /* all devices/clocks up */ + PWR_ACTIVE_STANDBY, + PWR_PASSIVE_STANDBY, + PWR_INVALID +} PWR_STATE; + +class cPowerManager { +private: + bool init; + bool opened; + PWR_STATE powerState; + // + static void ApplicationCallback(void *, void *, signed long, void *, void *) {} + bool SetState(PWR_STATE PowerState); +public: + bool Open(void); + void Close(void); + // + bool SetStandby(bool Active, bool Passive); + // + cPowerManager(void); + virtual ~cPowerManager(); +}; + +#endif // __PWRMNGR_H__ From 4b732596c7952192958036542f6ee512988a6a53 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 8 Aug 2010 14:16:37 +0200 Subject: [PATCH 0010/1070] libtriple: make most of libtriple use lt_debug Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/031cf4875216f8dc1f94dd9eaefe26c382ad45d4 Author: Stefan Seyfried Date: 2010-08-08 (Sun, 08 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/audio_td.cpp | 19 ++++++++++--------- lib/libtriple/dmx_td.cpp | 18 +++++++++--------- lib/libtriple/video_td.cpp | 5 +++-- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/lib/libtriple/audio_td.cpp b/lib/libtriple/audio_td.cpp index 8350118f3..555db92fc 100644 --- a/lib/libtriple/audio_td.cpp +++ b/lib/libtriple/audio_td.cpp @@ -8,6 +8,7 @@ #include #define AUDIO_DEVICE "/dev/" DEVICE_NAME_AUDIO #include "audio_td.h" +#include "lt_debug.h" cAudio * audioDecoder = NULL; @@ -124,7 +125,7 @@ bool cAudio::Pause(bool /*Pcm*/) void cAudio::SetSyncMode(AVSYNC_TYPE /*Mode*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); }; void cAudio::SetStreamType(AUDIO_FORMAT type) @@ -147,25 +148,25 @@ void cAudio::SetStreamType(AUDIO_FORMAT type) int cAudio::setChannel(int /*channel*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); return 0; }; int cAudio::PrepareClipPlay(int /*uNoOfChannels*/, int /*uSampleRate*/, int /*uBitsPerSample*/, int /*bLittleEndian*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); return 0; }; int cAudio::WriteClip(unsigned char * /*buffer*/, int /*size*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); return 0; }; int cAudio::StopClip() { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); return 0; }; @@ -213,22 +214,22 @@ void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &m void cAudio::SetSRS(int /*iq_enable*/, int /*nmgr_enable*/, int /*iq_mode*/, int /*iq_level*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); }; void cAudio::SetSpdifDD(bool /*enable*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); }; void cAudio::ScheduleMute(bool /*On*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); }; void cAudio::EnableAnalogOut(bool /*enable*/) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); }; void cAudio::setBypassMode(bool disable) diff --git a/lib/libtriple/dmx_td.cpp b/lib/libtriple/dmx_td.cpp index e56400119..dac776a47 100644 --- a/lib/libtriple/dmx_td.cpp +++ b/lib/libtriple/dmx_td.cpp @@ -48,7 +48,7 @@ cDemux::cDemux(int n) cDemux::~cDemux() { - fprintf(stderr, "cDemux::%s #%d fd: %d\n", __FUNCTION__, num, fd); + lt_debug("cDemux::%s #%d fd: %d\n", __FUNCTION__, num, fd); Close(); } @@ -102,7 +102,7 @@ void cDemux::Close(void) for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) { - fprintf(stderr, "iterator: stopping and closing demux fd %d\n", *i); + lt_debug("cDemux::Close: stopping and closing demux fd %d\n", *i); if (ioctl(*i, DEMUX_STOP) < 0) perror("DEMUX_STOP"); if (close(*i) < 0) @@ -124,7 +124,7 @@ bool cDemux::Start(void) for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) { - fprintf(stderr, "iterator: starting demux fd %d\n", *i); + lt_debug("cDemux::Start: starting demux fd %d\n", *i); if (ioctl(*i, DEMUX_START) < 0) perror("DEMUX_START"); } @@ -141,7 +141,7 @@ bool cDemux::Stop(void) } for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) { - fprintf(stderr, "iterator: stopping demux fd %d\n", *i); + lt_debug("cDemux::Stop: stopping demux fd %d\n", *i); if (ioctl(*i, DEMUX_STOP) < 0) perror("DEMUX_STOP"); } @@ -325,7 +325,7 @@ bool cDemux::pesFilter(const unsigned short pid) if ((pid >= 0x0002 && pid <= 0x000f) || pid >= 0x1fff) return false; -fprintf(stderr, "cDemux::%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]); + lt_debug("cDemux::%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, num, pid, fd, DMX_T[dmx_type]); if (dmx_type == DMX_TP_CHANNEL) { @@ -360,18 +360,18 @@ fprintf(stderr, "cDemux::%s #%d pid: 0x%04hx fd: %d type: %s\n", __FUNCTION__, n void cDemux::SetSyncMode(AVSYNC_TYPE /*mode*/) { - fprintf(stderr, "cDemux::%s #%d\n", __FUNCTION__, num); + lt_debug("cDemux::%s #%d\n", __FUNCTION__, num); } void *cDemux::getBuffer() { - fprintf(stderr, "cDemux::%s #%d\n", __FUNCTION__, num); + lt_debug("cDemux::%s #%d\n", __FUNCTION__, num); return NULL; } void *cDemux::getChannel() { - fprintf(stderr, "cDemux::%s #%d\n", __FUNCTION__, num); + lt_debug("cDemux::%s #%d\n", __FUNCTION__, num); return NULL; } @@ -393,7 +393,7 @@ void cDemux::addPid(unsigned short Pid) fprintf(stderr, "cDemux::%s #%d Pid = %hx open failed (%m)\n", __FUNCTION__, num, Pid); return; } - fprintf(stderr, "cDemux::%s #%d Pid = %hx pfd = %d\n", __FUNCTION__, num, Pid, pfd); + lt_debug("cDemux::%s #%d Pid = %hx pfd = %d\n", __FUNCTION__, num, Pid, pfd); p.pid = Pid; p.pesType = DMX_PES_OTHER; diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index 812e184eb..b1a8cada5 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -39,6 +39,7 @@ #include "video_td.h" #include #define VIDEO_DEVICE "/dev/" DEVICE_NAME_VIDEO +#include "lt_debug.h" cVideo * videoDecoder = NULL; int system_rev = 0; @@ -458,7 +459,7 @@ void cVideo::Standby(unsigned int bOn) int cVideo::getBlank(void) { - fprintf(stderr, "cVideo::getBlank\n"); + lt_debug("cVideo::getBlank\n"); return 0; } @@ -586,7 +587,7 @@ void cVideo::getPictureInfo(int &width, int &height, int &rate) void cVideo::SetSyncMode(AVSYNC_TYPE /*Mode*/) { - fprintf(stderr, "cVideo::%s\n", __FUNCTION__); + lt_debug("cVideo::%s\n", __FUNCTION__); }; int cVideo::SetStreamType(VIDEO_FORMAT type) From 5ce1a1023a2b6f557c5bd5ddcc114f9dbfbd5cb0 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 14 Aug 2010 16:10:45 +0200 Subject: [PATCH 0011/1070] libtriple: implement fast forward in cPlayback() First try at implementing fast forward. Needs more love. Reverse does not work yet, setting speed to negative values right now simply resets to "play" mode. Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/a3440d19df22b2a47157032dc299d49c8429044b Author: Stefan Seyfried Date: 2010-08-14 (Sat, 14 Aug 2010) ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 158 ++++++++++++++++++++++++++++------ lib/libtriple/video_td.cpp | 6 ++ lib/libtriple/video_td.h | 1 + 3 files changed, 138 insertions(+), 27 deletions(-) diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp index 59dd37cd0..e8ff878c2 100644 --- a/lib/libtriple/playback_td.cpp +++ b/lib/libtriple/playback_td.cpp @@ -329,15 +329,30 @@ bool cPlayback::SetAPid(unsigned short pid, bool _ac3) bool cPlayback::SetSpeed(int speed) { INFO("speed = %d\n", speed); - if (speed != 0 && playback_speed == 0) + if (speed < 0) + speed = 1; /* fast rewind not yet implemented... */ + if (speed == 1 && playback_speed != 1) { - videoDemux->Stop(); - videoDemux->Start(); - audioDemux->Start(); + if (playback_speed == 0) + { + videoDemux->Stop(); + videoDemux->Start(); + audioDemux->Start(); + } + else + { + audioDecoder->Stop(); + videoDecoder->Stop(); + } audioDecoder->Start(); videoDecoder->Start(); playstate = STATE_PLAY; } + if (playback_speed == 1 && speed > 1) + { + audioDecoder->mute(false); + videoDecoder->FastForwardMode(); + } playback_speed = speed; if (playback_speed == 0) { @@ -698,46 +713,135 @@ ssize_t cPlayback::read_ts() ssize_t toread, ret = 0, sync, off; toread = INBUF_SIZE - inbuf_pos; bool retry = true; + uint8_t *buf; /* fprintf(stderr, "%s:%d curr_pos %lld, inbuf_pos: %ld, toread: %ld\n", __FUNCTION__, __LINE__, (long long)curr_pos, (long)inbuf_pos, (long)toread); */ - while(true) + if (playback_speed > 1) { - ret = read(in_fd, inbuf + inbuf_pos, toread); - if (ret == 0 && retry) /* EOF */ + sync = 0; + ssize_t tmpread = PESBUF_SIZE / 188 * 188; + int n, skipped = 0; + bool skip = false; + bool eof = true; + while (toread > 0) { - mf_lseek(curr_pos); - retry = false; - continue; + ssize_t done = 0; + while (done < tmpread) + { + ret = read(in_fd, pesbuf, tmpread - done); + if (ret == 0 && retry) /* EOF */ + { + mf_lseek(curr_pos); + retry = false; + continue; + } + if (ret < 0) + { + INFO("failed: %m\n"); + return ret; + } + if (ret == 0 && eof) + goto out; + eof = false; + done += ret; + curr_pos += ret; + } + sync = sync_ts(pesbuf, ret); + if (sync != 0) + { + INFO("out of sync: %d\n", sync); + if (sync < 0) + { + return -1; + } + memmove(pesbuf, pesbuf + sync, ret - sync); + if (pesbuf[0] != 0x47) + INFO("??????????????????????????????\n"); + } + for (n = 0; n < done / 188 * 188; n += 188) + { + buf = pesbuf + n; + if (buf[1] & 0x40) // PUSI + { + /* only video packets... */ + int of = 4; + if (buf[3] & 0x20) // adaptation field + of += buf[4] + 1; + if ((buf[of + 3] & 0xF0) == 0xE0 && // Video stream + buf[of + 2] == 0x01 && buf[of + 1] == 0x00 && buf[of] == 0x00) // PES + { + skip = true; + skipped++; + if (skipped >= playback_speed) + { + skipped = 0; + skip = false; + } + } + } + if (! skip) + { + memcpy(inbuf + inbuf_pos, buf, 188); + inbuf_pos += 188; + toread -= 188; + if (toread <= 0) + { + /* the output buffer is full, discard the input :-( */ + if (done - n > 0) + { + DBG("not done: %d, resetting filepos\n", done - n); + mf_lseek(curr_pos - (done - n)); + } + break; + } + } + } } - break; + out: + if (eof) + return 0; } - if (ret < 0) + else { - INFO("failed: %m\n"); - return ret; - } - if (ret == 0) - return ret; - inbuf_pos += ret; - curr_pos += ret; + while(true) + { + ret = read(in_fd, inbuf + inbuf_pos, toread); + if (ret == 0 && retry) /* EOF */ + { + mf_lseek(curr_pos); + retry = false; + continue; + } + break; + } + if (ret < 0) + { + INFO("failed: %m\n"); + return ret; + } + if (ret == 0) + return ret; + inbuf_pos += ret; + curr_pos += ret; - sync = sync_ts(inbuf + inbuf_sync, INBUF_SIZE - inbuf_sync); - if (sync < 0) - { - INFO("cannot sync\n"); - return ret; + sync = sync_ts(inbuf + inbuf_sync, INBUF_SIZE - inbuf_sync); + if (sync < 0) + { + INFO("cannot sync\n"); + return ret; + } + inbuf_sync += sync; } - inbuf_sync += sync; /* check for A/V PIDs */ uint16_t pid; int i, j; bool pid_new; int64_t pts; - // fprintf(stderr, "inbuf_pos: %ld - sync: %ld\n", (long)inbuf_pos, (long)sync); + //fprintf(stderr, "inbuf_pos: %ld - sync: %ld, inbuf_syc: %ld\n", (long)inbuf_pos, (long)sync, (long)inbuf_sync); int synccnt = 0; for (i = 0; i < inbuf_pos - inbuf_sync - 13;) { - uint8_t *buf = inbuf + inbuf_sync + i; + buf = inbuf + inbuf_sync + i; if (*buf != 0x47) { synccnt++; diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index b1a8cada5..8149deddf 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -644,3 +644,9 @@ void cVideo::routeVideo(int standby) perror("IOC_AVS_ROUTE_ENC2TV"); close(avsfd); } + +void cVideo::FastForwardMode(int mode) +{ + lt_debug("cVideo::%s\n", __FUNCTION__); + fop(ioctl, MPEG_VID_FASTFORWARD, mode); +} diff --git a/lib/libtriple/video_td.h b/lib/libtriple/video_td.h index 49778b12a..8a9f4f03b 100644 --- a/lib/libtriple/video_td.h +++ b/lib/libtriple/video_td.h @@ -179,6 +179,7 @@ class cVideo void SetVideoMode(analog_mode_t mode); void SetDBDR(int) { return; }; void SetAudioHandle(void *) { return; }; + void FastForwardMode(int mode = 0); void SetAutoModes(int [VIDEO_STD_MAX]) { return; }; int OpenVBI(int) { return 0; }; int CloseVBI(void) { return 0; }; From 08776d6029eb4676f8a5162a9afcb447a7d6f51f Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 15 Aug 2010 22:36:38 +0200 Subject: [PATCH 0012/1070] libtriple: implement mpeg/vdr playback Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/2698788643027d087c7541c113afc6dffd00a530 Author: Stefan Seyfried Date: 2010-08-15 (Sun, 15 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 184 +++++++++++++++++++++++++++++----- 1 file changed, 161 insertions(+), 23 deletions(-) diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp index e8ff878c2..e8f2439bd 100644 --- a/lib/libtriple/playback_td.cpp +++ b/lib/libtriple/playback_td.cpp @@ -21,7 +21,7 @@ #define DBG(args...) #endif -static int mp_syncPES(uint8_t *, int); +static int mp_syncPES(uint8_t *, int, bool quiet = false); static int sync_ts(uint8_t *, int); static inline uint16_t get_pid(uint8_t *buf); static void *start_playthread(void *c); @@ -37,6 +37,13 @@ extern cDemux *audioDemux; extern cVideo *videoDecoder; extern cAudio *audioDecoder; +static const char *FILETYPE[] = { + "FILETYPE_UNKNOWN", + "FILETYPE_TS", + "FILETYPE_MPG", + "FILETYPE_VDR" +}; + cPlayback::cPlayback(int) { INFO("\n"); @@ -135,11 +142,43 @@ bool cPlayback::Start(char *filename, unsigned short vp, int vtype, unsigned sho filelist_t file; file.Name = std::string(filename); file.Size = s.st_size; + if (file.Name.rfind(".ts") == file.Name.length() - 3 || + file.Name.rfind(".TS") == file.Name.length() - 3) + filetype = FILETYPE_TS; + else + { + if (file.Name.rfind(".vdr") == file.Name.length() - 4) + { + filetype = FILETYPE_VDR; + std::string::size_type p = file.Name.rfind("info.vdr"); + if (p == std::string::npos) + p = file.Name.rfind("index.vdr"); + if (p != std::string::npos) + { + file.Name.replace(p, std::string::npos, "001.vdr"); + INFO("replaced filename with '%s'\n", file.Name.c_str()); + if (stat(file.Name.c_str(), &s)) + { + INFO("filename does not exist? (%m)\n"); + return false; + } + file.Size = s.st_size; + } + } + else + filetype = FILETYPE_MPG; + vpid = 0x40; + } + + INFO("detected (ok, guessed) filetype: %s\n", FILETYPE[filetype]); + filelist.push_back(file); filelist_auto_add(); if (mf_open(0) < 0) return false; + pts_start = pts_end = pts_curr = -1; + pesbuf_pos = 0; curr_pos = 0; inbuf_pos = 0; inbuf_sync = 0; @@ -149,13 +188,21 @@ bool cPlayback::Start(char *filename, unsigned short vp, int vtype, unsigned sho { if (mp_seekSync(r - INBUF_SIZE) < 0) return false; - inbuf_read(); /* assume that we fill the buffer with one read() */ - for (r = (inbuf_pos / 188) * 188; r > 0; r -= 188) - { - pts_end = get_pts(inbuf + r, false); - if (pts_end > -1) + while(true) { + if (inbuf_read() <= 0) + break; // EOF + if (curr_pos >= r) //just to make sure... break; } + if (filetype == FILETYPE_TS) + for (r = (inbuf_pos / 188) * 188; r > 0; r -= 188) + { + pts_end = get_pts(inbuf + r, false); + if (pts_end > -1) + break; + } + else + pts_end = pts_curr; } else pts_end = -1; /* unknown */ @@ -449,7 +496,7 @@ bool cPlayback::SetPosition(int position, bool absolute) } oldspeed = playback_speed; - if (oldspeed != 0) +// if (oldspeed != 0) SetSpeed(0); /* request pause */ while (playstate == STATE_PLAY) /* playthread did not acknowledge pause */ @@ -515,7 +562,10 @@ off_t cPlayback::seek_to_pts(int64_t pts) return newpos; inbuf_pos = 0; inbuf_sync = 0; - inbuf_read(); /* also updates current pts */ + while (inbuf_pos < INBUF_SIZE * 8 / 10) { + if (inbuf_read() <= 0) + break; // EOF + } if (pts_curr < pts_start) tmppts = pts_curr + 0x200000000ULL - pts_start; else @@ -929,9 +979,17 @@ ssize_t cPlayback::read_ts() ssize_t cPlayback::read_mpeg() { ssize_t toread, ret, sync; - toread = PESBUF_SIZE - pesbuf_pos; + //toread = PESBUF_SIZE - pesbuf_pos; + /* experiments found, that 80kB is the best buffer size, otherwise a/v sync seems + to suffer and / or audio stutters */ + toread = 80 * 1024 - pesbuf_pos; bool retry = true; + if (INBUF_SIZE - inbuf_pos < toread) + { + INFO("adjusting toread to %d due to inbuf full (old: %ld)\n", INBUF_SIZE - inbuf_pos, toread); + toread = INBUF_SIZE - inbuf_pos; + } while(true) { ret = read(in_fd, pesbuf + pesbuf_pos, toread); @@ -945,7 +1003,7 @@ ssize_t cPlayback::read_mpeg() } if (ret < 0) { - INFO("failed: %m\n"); + INFO("failed: %m, pesbuf_pos: %ld, toread: %ld\n", pesbuf_pos, toread); return ret; } pesbuf_pos += ret; @@ -954,17 +1012,22 @@ ssize_t cPlayback::read_mpeg() int i; int count = 0; uint16_t pid = 0; + bool resync = true; while (count < pesbuf_pos - 10) { - sync = mp_syncPES(pesbuf + count, pesbuf_pos - count - 10); - if (sync < 0) + if (resync) { - INFO("cannot sync\n"); - break; + sync = mp_syncPES(pesbuf + count, pesbuf_pos - count - 10); + if (sync < 0) + { + if (pesbuf_pos - count - 10 > 4) + INFO("cannot sync (count = %d, pesbuf_pos = %ld)\n", count, pesbuf_pos); + break; + } + if (sync) + INFO("needed sync %ld\n", sync); + count += sync; } - if (sync) - INFO("needed sync\n"); - count += sync; uint8_t *ppes = pesbuf + count; int av = 0; // 1 = video, 2 = audio int64_t pts; @@ -979,6 +1042,7 @@ ssize_t cPlayback::read_mpeg() } else count += 14; + resync = true; continue; break; case 0xbd: // AC3 @@ -1066,6 +1130,7 @@ ssize_t cPlayback::read_mpeg() //if (! resync) // DBG("Unknown stream id: 0x%X.\n", ppes[3]); count++; + resync = true; continue; break; } @@ -1073,7 +1138,19 @@ ssize_t cPlayback::read_mpeg() int pesPacketLen = ((ppes[4] << 8) | ppes[5]) + 6; if (count + pesPacketLen >= pesbuf_pos) { - INFO("buffer len: %d, pesPacketLen: %d :-(\n", pesbuf_pos - count, pesPacketLen); + DBG("buffer len: %ld, pesPacketLen: %d :-(\n", pesbuf_pos - count, pesPacketLen); + if (count != 0) + { + memmove(pesbuf, ppes, pesbuf_pos - count); + pesbuf_pos -= count; + } + break; + } + + int tsPacksCount = pesPacketLen / 184; + if ((tsPacksCount + 1) * 188 > INBUF_SIZE - inbuf_pos) + { + INFO("not enough size in inbuf (needed %d, got %d)\n", (tsPacksCount + 1) * 188, INBUF_SIZE - inbuf_pos); memmove(pesbuf, ppes, pesbuf_pos - count); pesbuf_pos -= count; break; @@ -1081,7 +1158,6 @@ ssize_t cPlayback::read_mpeg() if (av) { - int tsPacksCount = pesPacketLen / 184; int rest = pesPacketLen % 184; // divide PES packet into small TS packets @@ -1134,12 +1210,65 @@ off_t cPlayback::mp_seekSync(off_t pos) { off_t npos = pos; off_t ret; - uint8_t pkt[188]; + uint8_t pkt[1024]; ret = mf_lseek(npos); if (ret < 0) INFO("lseek ret < 0 (%m)\n"); + if (filetype != FILETYPE_TS) + { + int offset = 0; + int s; + ssize_t r; + bool retry = false; + while (true) + { + r = read(in_fd, &pkt[offset], 1024 - offset); + if (r < 0) + { + INFO("read failed: %m\n"); + break; + } + if (r == 0) // EOF? + { + if (retry) + break; + if (mf_lseek(npos) < 0) /* next file in list? */ + { + INFO("lseek ret < 0 (%m)\n"); + break; + } + retry = true; + continue; + } + s = mp_syncPES(pkt, r + offset, true); + if (s < 0) + { + /* if the last 3 bytes of the buffer were 00 00 01, then + mp_sync_PES would not find it. So keep them and check + again in the next iteration */ + memmove(pkt, &pkt[r + offset - 3], 3); + npos += r; + offset = 3; + } + else + { + npos += s; + INFO("sync after %lld\n", npos - pos); + ret = mf_lseek(npos); + if (ret < 0) + INFO("lseek ret < 0 (%m)\n"); + return ret; + } + if (npos > (pos + 0x20000)) /* 128k enough? */ + break; + } + INFO("could not sync to PES offset: %d r: %zd\n", offset, r); + return mf_lseek(pos); + } + + /* TODO: use bigger buffer here, too and handle EOF / next splitfile */ while (read(in_fd, pkt, 1) > 0) { //-- check every byte until sync word reached -- @@ -1241,10 +1370,10 @@ int64_t cPlayback::get_pts(uint8_t *p, bool pes) } /* returns: 0 == was already synchronous, > 0 == is now synchronous, -1 == could not sync */ -static int mp_syncPES(uint8_t *buf, int len) +static int mp_syncPES(uint8_t *buf, int len, bool quiet) { int ret = 0; - while (ret < len - 3) + while (ret < len - 4) { if (buf[ret + 2] != 0x01) { @@ -1261,10 +1390,19 @@ static int mp_syncPES(uint8_t *buf, int len) ret += 3; continue; } + /* all stream IDs are > 0x80 */ + if ((buf[ret + 3] & 0x80) != 0x80) + { + /* we already checked for 00 00 01, if the stream ID + is not valid, we can skip those 3 bytes */ + ret += 3; + continue; + } return ret; } - INFO("No valid PES signature found. %d Bytes deleted.\n", ret); + if (!quiet && len > 5) /* only warn if enough space was available... */ + INFO("No valid PES signature found. %d Bytes deleted.\n", ret); return -1; } From 4fd9305fd738254e5e446f894884ad21dd57f8c2 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 29 Aug 2010 21:53:04 +0200 Subject: [PATCH 0013/1070] libtriple: cPlayback: improve get_pts * add the buffer size to the call to avoid overflows * extract PTS also from MPEG1 packets Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/f50f68677f878abbce37c05f4f5250c9b0a6362a Author: Stefan Seyfried Date: 2010-08-29 (Sun, 29 Aug 2010) ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 50 +++++++++++++++++++++++++---------- lib/libtriple/playback_td.h | 2 +- 2 files changed, 37 insertions(+), 15 deletions(-) diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp index e8f2439bd..bef15c1aa 100644 --- a/lib/libtriple/playback_td.cpp +++ b/lib/libtriple/playback_td.cpp @@ -197,7 +197,7 @@ bool cPlayback::Start(char *filename, unsigned short vp, int vtype, unsigned sho if (filetype == FILETYPE_TS) for (r = (inbuf_pos / 188) * 188; r > 0; r -= 188) { - pts_end = get_pts(inbuf + r, false); + pts_end = get_pts(inbuf + r, false, inbuf_pos - r); if (pts_end > -1) break; } @@ -216,7 +216,7 @@ bool cPlayback::Start(char *filename, unsigned short vp, int vtype, unsigned sho while (inbuf_pos < INBUF_SIZE / 2 && inbuf_read() > 0) {}; for (r = 0; r < inbuf_pos - 188; r += 188) { - pts_start = get_pts(inbuf + r, false); + pts_start = get_pts(inbuf + r, false, inbuf_pos - r); if (pts_start > -1) break; } @@ -445,7 +445,7 @@ bool cPlayback::GetPosition(int &position, int &duration) n -= s; for (r = (n / 188) * 188; r > 0; r -= 188) { - tmppts = get_pts(pesbuf + r + s, false); + tmppts = get_pts(pesbuf + r + s, false, n - r); if (tmppts > -1) { DBG("n: %d s: %d endpts %lld size: %lld\n", n, s, tmppts, currsize); @@ -723,7 +723,7 @@ int64_t cPlayback::get_PES_PTS(uint8_t *buf, int len, bool last) { int64_t tmppts; case 0xe0 ... 0xef: // video! - tmppts = get_pts(p, true); + tmppts = get_pts(p, true, len - off); if (tmppts >= 0) pts = tmppts; break; @@ -917,7 +917,7 @@ ssize_t cPlayback::read_ts() case 0xe0 ... 0xef: /* video stream */ if (vpid == 0) vpid = pid; - pts = get_pts(buf + 4 + off, true); + pts = get_pts(buf + 4 + off, true, inbuf_pos - inbuf_sync - i - off - 4); if (pts < 0) break; pts_curr = pts; @@ -1114,7 +1114,7 @@ ssize_t cPlayback::read_mpeg() // fprintf(stderr, "video stream 0x%02x, %02x %02x \n", ppes[3], ppes[4], ppes[5]); pid = 0x40; av = 1; - pts = get_pts(ppes, true); + pts = get_pts(ppes, true, pesbuf_pos - count); if (pts < 0) break; pts_curr = pts; @@ -1322,11 +1322,13 @@ static int sync_ts(uint8_t *p, int len) /* get the pts value from a TS or PES packet pes == true selects PES mode. */ -int64_t cPlayback::get_pts(uint8_t *p, bool pes) +int64_t cPlayback::get_pts(uint8_t *p, bool pes, int bufsize) { + const uint8_t *end = p + bufsize; /* check for overflow */ + if (bufsize < 14) + return -1; if (!pes) { - const uint8_t *end = p + 188; if (p[0] != 0x47) return -1; if (!(p[1] & 0x40)) @@ -1348,12 +1350,32 @@ int64_t cPlayback::get_pts(uint8_t *p, bool pes) return -1; } - if ((p[7] & 0x80) == 0) // packets with both pts, don't care for dts - // if ((p[7] & 0xC0) != 0x80) // packets with only pts - // if ((p[7] & 0xC0) != 0xC0) // packets with pts and dts - return -1; - if (p[8] < 5) - return -1; + if ((p[6] & 0xC0) != 0x80) // MPEG1 + { + p += 6; + while (*p == 0xff) + { + p++; + if (p > end) + return -1; + } + if ((*p & 0xc0) == 0x40) + p += 2; + p -= 9; /* so that the p[9]...p[13] matches the below */ + if (p + 13 > end) + return -1; + } + else + { + /* MPEG2 */ + if ((p[7] & 0x80) == 0) // packets with both pts, don't care for dts + // if ((p[7] & 0xC0) != 0x80) // packets with only pts + // if ((p[7] & 0xC0) != 0xC0) // packets with pts and dts + return -1; + if (p[8] < 5) + return -1; + } + if (!(p[9] & 0x20)) return -1; diff --git a/lib/libtriple/playback_td.h b/lib/libtriple/playback_td.h index 006a3b64d..0ebd45b2e 100644 --- a/lib/libtriple/playback_td.h +++ b/lib/libtriple/playback_td.h @@ -78,7 +78,7 @@ class cPlayback int64_t pts_start; int64_t pts_end; int64_t pts_curr; - int64_t get_pts(uint8_t *p, bool pes); + int64_t get_pts(uint8_t *p, bool pes, int bufsize); filetype_t filetype; playstate_t playstate; From 0477665fcce9b97d5901fa465ea7619b2cb3e83a Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 29 Aug 2010 19:03:08 +0200 Subject: [PATCH 0014/1070] libtriple: fix compiler warnings in playback_td Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/d95e1bbaf31111b7a911f6b39d82cf5356e58e4e Author: Stefan Seyfried Date: 2010-08-29 (Sun, 29 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp index bef15c1aa..8338d6018 100644 --- a/lib/libtriple/playback_td.cpp +++ b/lib/libtriple/playback_td.cpp @@ -987,7 +987,7 @@ ssize_t cPlayback::read_mpeg() if (INBUF_SIZE - inbuf_pos < toread) { - INFO("adjusting toread to %d due to inbuf full (old: %ld)\n", INBUF_SIZE - inbuf_pos, toread); + INFO("adjusting toread to %d due to inbuf full (old: %zd)\n", INBUF_SIZE - inbuf_pos, toread); toread = INBUF_SIZE - inbuf_pos; } while(true) @@ -1003,7 +1003,7 @@ ssize_t cPlayback::read_mpeg() } if (ret < 0) { - INFO("failed: %m, pesbuf_pos: %ld, toread: %ld\n", pesbuf_pos, toread); + INFO("failed: %m, pesbuf_pos: %zd, toread: %zd\n", pesbuf_pos, toread); return ret; } pesbuf_pos += ret; @@ -1021,11 +1021,11 @@ ssize_t cPlayback::read_mpeg() if (sync < 0) { if (pesbuf_pos - count - 10 > 4) - INFO("cannot sync (count = %d, pesbuf_pos = %ld)\n", count, pesbuf_pos); + INFO("cannot sync (count = %d, pesbuf_pos = %zd)\n", count, pesbuf_pos); break; } if (sync) - INFO("needed sync %ld\n", sync); + INFO("needed sync %zd\n", sync); count += sync; } uint8_t *ppes = pesbuf + count; From 03aa7c6031ad553295253e045504d98655d6645b Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 21 Aug 2010 15:48:57 +0200 Subject: [PATCH 0015/1070] libtriple: hack different notify sizes for subs and ttx into cDemux Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/0249c65167b3c400673c132b460a449de64c9e5c Author: Stefan Seyfried Date: 2010-08-21 (Sat, 21 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/dmx_td.cpp | 7 +++++-- lib/libtriple/dmx_td.h | 1 + 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/libtriple/dmx_td.cpp b/lib/libtriple/dmx_td.cpp index dac776a47..fe9566b31 100644 --- a/lib/libtriple/dmx_td.cpp +++ b/lib/libtriple/dmx_td.cpp @@ -88,6 +88,7 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe if (ioctl(fd, DEMUX_SET_BUFFER_SIZE, uBufferSize) < 0) fprintf(stderr, "cDemux::Open DEMUX_SET_BUFFER_SIZE failed (%m)\n"); } + buffersize = uBufferSize; return true; } @@ -348,13 +349,15 @@ bool cDemux::pesFilter(const unsigned short pid) break; case DMX_PES_CHANNEL: flt.unloader.unloader_type = UNLOADER_TYPE_PAYLOAD; - flt.unloader.threshold = 64; + if (buffersize <= 0x10000) // dvbsubtitle, instant delivery... + flt.unloader.threshold = 1; + else + flt.unloader.threshold = 8; // 1k, teletext flt.pesType = DMX_PES_OTHER; flt.output = OUT_MEMORY; default: flt.pesType = DMX_PES_OTHER; } - return (ioctl(fd, DEMUX_FILTER_PES_SET, &flt) >= 0); } diff --git a/lib/libtriple/dmx_td.h b/lib/libtriple/dmx_td.h index aba9ec835..f36758684 100644 --- a/lib/libtriple/dmx_td.h +++ b/lib/libtriple/dmx_td.h @@ -28,6 +28,7 @@ class cDemux private: int num; int fd; + int buffersize; DMX_CHANNEL_TYPE dmx_type; std::vector pesfds; public: From cc16cede59a00dadf7891b3cfe847ca9f57532c7 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 25 Aug 2010 16:38:01 +0200 Subject: [PATCH 0016/1070] libtriple: reduce some messages to debug, consolidate scart messages Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/6aaa97c4233154c5ce61410e8cfd8582ab603c3e Author: Stefan Seyfried Date: 2010-08-25 (Wed, 25 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/audio_td.cpp | 4 ++-- lib/libtriple/video_td.cpp | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/lib/libtriple/audio_td.cpp b/lib/libtriple/audio_td.cpp index 555db92fc..49cf07db2 100644 --- a/lib/libtriple/audio_td.cpp +++ b/lib/libtriple/audio_td.cpp @@ -131,7 +131,7 @@ void cAudio::SetSyncMode(AVSYNC_TYPE /*Mode*/) void cAudio::SetStreamType(AUDIO_FORMAT type) { int bypass_disable; - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); StreamType = type; if (StreamType != AUDIO_FMT_DOLBY_DIGITAL && StreamType != AUDIO_FMT_MPEG && StreamType != AUDIO_FMT_MPG1) @@ -172,7 +172,7 @@ int cAudio::StopClip() void cAudio::getAudioInfo(int &type, int &layer, int &freq, int &bitrate, int &mode) { - fprintf(stderr, "cAudio::%s\n", __FUNCTION__); + lt_debug("cAudio::%s\n", __FUNCTION__); unsigned int atype; static const int freq_mpg[] = {44100, 48000, 32000, 0}; static const int freq_ac3[] = {48000, 44100, 32000, 0}; diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index 8149deddf..718e696ae 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -620,26 +620,22 @@ void cVideo::routeVideo(int standby) to configure this, we can think more about this... */ if (standby) { - printf("[routeVideo] setting FASTBLANK to follow VCR SCART\n"); + printf("[%s] setting fastblank and pin8 to follow VCR SCART, route VCR to TV\n", __FUNCTION__); if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, (unsigned char)3) < 0) perror("IOC_AVS_FASTBLANK_SET, 3"); /* TODO: should probably depend on aspect ratio setting */ - printf("[routeVideo] setting SCART_PIN_8 to follow VCR SCART\n"); if (ioctl(avsfd, IOC_AVS_SCART_PIN8_FOLLOW_VCR) < 0) perror("IOC_AVS_SCART_PIN8_FOLLOW_VCR"); - printf("[routeVideo] routing VCR to TV SCART\n"); if (ioctl(avsfd, IOC_AVS_ROUTE_VCR2TV) < 0) perror("IOC_AVS_ROUTE_VCR2TV"); return; } unsigned char fblk = 1; - printf("[routeVideo] setting FASTBLANK to %d\n", fblk); + printf("[%s] setting fastblank to %d, pin8 to %dV, routing encoder to TV\n", __FUNCTION__, fblk, scartvoltage); if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, fblk) < 0) perror("IOC_AVS_FASTBLANK_SET, fblk"); - printf("[routeVideo] setting SCART_PIN_8 to %dV\n", scartvoltage); if (ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) perror("IOC_AVS_SCART_PIN8_SET"); - printf("[routeVideo] routing TV encoder to TV SCART\n"); if (ioctl(avsfd, IOC_AVS_ROUTE_ENC2TV) < 0) perror("IOC_AVS_ROUTE_ENC2TV"); close(avsfd); From b5cfd70c8ae009c18fb9d0c8af99e324b8ff6866 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 28 Aug 2010 14:03:58 +0200 Subject: [PATCH 0017/1070] libtriple: add debug messages to cDemux and cVideo functions Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/81ae635dcb61ab1f17519cadc7fedad87aa48dcb Author: Stefan Seyfried Date: 2010-08-28 (Sat, 28 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/dmx_td.cpp | 1 + lib/libtriple/video_td.cpp | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/libtriple/dmx_td.cpp b/lib/libtriple/dmx_td.cpp index fe9566b31..5e6474e78 100644 --- a/lib/libtriple/dmx_td.cpp +++ b/lib/libtriple/dmx_td.cpp @@ -95,6 +95,7 @@ bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBuffe void cDemux::Close(void) { + lt_debug("cDemux::%s #%d, fd = %d\n", __FUNCTION__, num, fd); if (fd < 0) { fprintf(stderr, "cDemux::%s #%d: not open!\n", __FUNCTION__, num); diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index 718e696ae..1e2b30b0e 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -251,6 +251,7 @@ int cVideo::setCroppingMode(vidDispMode_t format) int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned short /*VideoPid*/, void * /*hChannel*/) { + lt_debug("cVideo::Start playstate = %d\n", playstate); if (playstate == VIDEO_PLAYING) return 0; if (playstate == VIDEO_FREEZED) /* in theory better, but not in practice :-) */ @@ -262,7 +263,7 @@ int cVideo::Start(void * /*PcrChannel*/, unsigned short /*PcrPid*/, unsigned sho int cVideo::Stop(bool blank) { - //fprintf(stderr, "cVideo::Stop %d\n", blank); + lt_debug("cVideo::Stop %d\n", blank); if (blank) { playstate = VIDEO_STOPPED; From 6863fae5d8b656ced12db988e7571c07f76ba174 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 29 Aug 2010 21:57:28 +0200 Subject: [PATCH 0018/1070] libtriple: add support for MPEG1 files to cPlayback Now we can play the "Warriors of the Net" clip :-) http://ftp.sunet.se/pub/tv+movies/warriors/warriors-700-VBR.mpg Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/a07e6a3a309623c23fcd0699378f4f9669398cad Author: Stefan Seyfried Date: 2010-08-29 (Sun, 29 Aug 2010) ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp index 8338d6018..066f66199 100644 --- a/lib/libtriple/playback_td.cpp +++ b/lib/libtriple/playback_td.cpp @@ -31,6 +31,7 @@ static pthread_cond_t playback_ready_cond = PTHREAD_COND_INITIALIZER; static pthread_mutex_t playback_ready_mutex = PTHREAD_MUTEX_INITIALIZER; static int dvrfd = -1; +static int streamtype; extern cDemux *videoDemux; extern cDemux *audioDemux; @@ -53,6 +54,7 @@ cPlayback::cPlayback(int) filelist.clear(); curr_fileno = -1; in_fd = -1; + streamtype = 0; } cPlayback::~cPlayback() @@ -265,7 +267,12 @@ void cPlayback::playthread(void) if (ac3) audioDecoder->SetStreamType(AUDIO_FMT_DOLBY_DIGITAL); else - audioDecoder->SetStreamType(AUDIO_FMT_MPEG); + { + if (streamtype == 1) /* mpeg 1 */ + audioDecoder->SetStreamType(AUDIO_FMT_MPG1); + else /* default */ + audioDecoder->SetStreamType(AUDIO_FMT_MPEG); + } audioDemux->pesFilter(apid); videoDemux->pesFilter(vpid); @@ -363,7 +370,12 @@ bool cPlayback::SetAPid(unsigned short pid, bool _ac3) if (ac3) audioDecoder->SetStreamType(AUDIO_FMT_DOLBY_DIGITAL); else - audioDecoder->SetStreamType(AUDIO_FMT_MPEG); + { + if (streamtype == 1) /* mpeg 1 */ + audioDecoder->SetStreamType(AUDIO_FMT_MPG1); + else /* default */ + audioDecoder->SetStreamType(AUDIO_FMT_MPEG); + } audioDemux->pesFilter(apid); videoDemux->Start(); @@ -1033,15 +1045,23 @@ ssize_t cPlayback::read_mpeg() int64_t pts; switch(ppes[3]) { - case 0xba: + case 0xba: //pack header; // fprintf(stderr, "pack start code, 0x%02x\n", ppes[4]); - if ((ppes[4] & 0x3) == 1) // ?? + if ((ppes[4] & 0xf0) == 0x20) /* mpeg 1 */ { - //type = 1; // mpeg1 + streamtype = 1; /* for audio setup */ count += 12; } + else if ((ppes[4] & 0xc0) == 0x40) /* mpeg 2 */ + { + streamtype = 0; + count += 14; /* correct: 14 + (ppes[13] & 0x07) */ + } else - count += 14; + { + INFO("weird pack header: 0x%2x\n", ppes[4]); + count++; + } resync = true; continue; break; From e465c3359d4b25ba954c3b4484408b05de7dba97 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 25 Dec 2010 11:59:02 +0100 Subject: [PATCH 0019/1070] libtriple: add usable dummy cCA class Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/000fbfe74b834f323f1f877002509acdfaea493c Author: Stefan Seyfried Date: 2010-12-25 (Sat, 25 Dec 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/Makefile.am | 1 + lib/libtriple/ca.cpp | 110 ++++++++++++++++++++++++++++++++++++++ lib/libtriple/ca.h | 97 +++++++++++++++++++++++++++++++++ lib/libtriple/ca_cs.h | 1 + lib/libtriple/mmi.h | 23 ++++++++ 5 files changed, 232 insertions(+) create mode 100644 lib/libtriple/ca.cpp create mode 100644 lib/libtriple/ca.h create mode 100644 lib/libtriple/ca_cs.h create mode 100644 lib/libtriple/mmi.h diff --git a/lib/libtriple/Makefile.am b/lib/libtriple/Makefile.am index 5d98bf2db..6c436a258 100644 --- a/lib/libtriple/Makefile.am +++ b/lib/libtriple/Makefile.am @@ -13,6 +13,7 @@ AM_CPPFLAGS = -fno-rtti -fno-exceptions libtriple_a_SOURCES = \ lt_debug.cpp \ dmx_td.cpp \ + ca.cpp \ video_td.cpp \ audio_td.cpp \ init_td.cpp \ diff --git a/lib/libtriple/ca.cpp b/lib/libtriple/ca.cpp new file mode 100644 index 000000000..f8d1bade6 --- /dev/null +++ b/lib/libtriple/ca.cpp @@ -0,0 +1,110 @@ +#include + +#include "ca.h" +#include "lt_debug.h" + +static const char *FILENAME = "ca.cpp"; + +static cCA *inst = NULL; + +/* those are all dummies for now.. */ +cCA::cCA(void) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); +} + +cCA::~cCA() +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); +} + +cCA *cCA::GetInstance() +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); + if (inst == NULL) + inst = new cCA(); + + return inst; +} + +void cCA::MenuEnter(enum CA_SLOT_TYPE, uint32_t p) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +void cCA::MenuAnswer(enum CA_SLOT_TYPE, uint32_t p, uint32_t /*choice*/) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +void cCA::InputAnswer(enum CA_SLOT_TYPE, uint32_t p, uint8_t * /*Data*/, int /*Len*/) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +void cCA::MenuClose(enum CA_SLOT_TYPE, uint32_t p) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +uint32_t cCA::GetNumberCISlots(void) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); + return 0; +} + +uint32_t cCA::GetNumberSmartCardSlots(void) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); + return 0; +} + +void cCA::ModuleName(enum CA_SLOT_TYPE, uint32_t p, char * /*Name*/) +{ + /* TODO: waht to do with *Name? */ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +bool cCA::ModulePresent(enum CA_SLOT_TYPE, uint32_t p) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); + return false; +} + +void cCA::ModuleReset(enum CA_SLOT_TYPE, uint32_t p) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +bool cCA::SendPMT(int, unsigned char *, int, CA_SLOT_TYPE) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); + return true; +} + +bool cCA::SendMessage(const CA_MESSAGE *) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); + return true; +} + +bool cCA::Start(void) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); + return true; +} + +void cCA::Stop(void) +{ + lt_debug("%s:%s\n", FILENAME, __FUNCTION__); +} + +void cCA::Ready(bool p) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} + +void cCA::SetInitMask(enum CA_INIT_MASK p) +{ + lt_debug("%s:%s param:%d\n", FILENAME, __FUNCTION__, (int)p); +} diff --git a/lib/libtriple/ca.h b/lib/libtriple/ca.h new file mode 100644 index 000000000..8a29e5604 --- /dev/null +++ b/lib/libtriple/ca.h @@ -0,0 +1,97 @@ +/* + * dummy functions to implement ca_cs.h interface + */ +#ifndef __CA_LIBTRIPLE_H_ +#define __CA_LIBTRIPLE_H_ + +#include +/* used in cam_menu.cpp */ +typedef uint32_t u32; + +enum CA_INIT_MASK { + CA_INIT_SC = 1, + CA_INIT_CI, + CA_INIT_BOTH +}; + +enum CA_SLOT_TYPE { + CA_SLOT_TYPE_SMARTCARD, + CA_SLOT_TYPE_CI, + CA_SLOT_TYPE_ALL, +}; + +enum CA_MESSAGE_FLAGS { + CA_MESSAGE_EMPTY = (1 << 0), + CA_MESSAGE_HAS_PARAM1_DATA = (1 << 1), // Free after use! + CA_MESSAGE_HAS_PARAM1_INT = (1 << 2), + CA_MESSAGE_HAS_PARAM1_PTR = (1 << 3), + CA_MESSAGE_HAS_PARAM2_INT = (1 << 4), + CA_MESSAGE_HAS_PARAM2_PTR = (1 << 5), + CA_MESSAGE_HAS_PARAM2_DATA = (1 << 6), + CA_MESSAGE_HAS_PARAM3_DATA = (1 << 7), // Free after use! + CA_MESSAGE_HAS_PARAM3_INT = (1 << 8), + CA_MESSAGE_HAS_PARAM3_PTR = (1 << 9), + CA_MESSAGE_HAS_PARAM4_INT = (1 << 10), + CA_MESSAGE_HAS_PARAM4_PTR = (1 << 11), + CA_MESSAGE_HAS_PARAM4_DATA = (1 << 12), + CA_MESSAGE_HAS_PARAM_LONG = (1 << 13), +}; + +enum CA_MESSAGE_MSGID { + CA_MESSAGE_MSG_INSERTED, + CA_MESSAGE_MSG_REMOVED, + CA_MESSAGE_MSG_INIT_OK, + CA_MESSAGE_MSG_INIT_FAILED, + CA_MESSAGE_MSG_MMI_MENU, + CA_MESSAGE_MSG_MMI_MENU_ENTER, + CA_MESSAGE_MSG_MMI_MENU_ANSWER, + CA_MESSAGE_MSG_MMI_LIST, + CA_MESSAGE_MSG_MMI_TEXT, + CA_MESSAGE_MSG_MMI_REQ_INPUT, + CA_MESSAGE_MSG_MMI_CLOSE, + CA_MESSAGE_MSG_INTERNAL, + CA_MESSAGE_MSG_PMT_ARRIVED, + CA_MESSAGE_MSG_CAT_ARRIVED, + CA_MESSAGE_MSG_ECM_ARRIVED, + CA_MESSAGE_MSG_EMM_ARRIVED, + CA_MESSAGE_MSG_CHANNEL_CHANGE, + CA_MESSAGE_MSG_EXIT, +}; + +typedef struct CA_MESSAGE { + uint32_t MsgId; + enum CA_SLOT_TYPE SlotType; + int Slot; + uint32_t Flags; + union { + uint8_t *Data[4]; + uint32_t Param[4]; + void *Ptr[4]; + uint64_t ParamLong; + } Msg; +} CA_MESSAGE; + +class cCA { +private: + cCA(void); +public: + uint32_t GetNumberCISlots(void); + uint32_t GetNumberSmartCardSlots(void); + static cCA *GetInstance(void); + bool SendPMT(int Unit, unsigned char *Data, int Len, CA_SLOT_TYPE SlotType = CA_SLOT_TYPE_ALL); + bool SendMessage(const CA_MESSAGE *Msg); + void SetInitMask(enum CA_INIT_MASK InitMask); + bool Start(void); + void Stop(void); + void Ready(bool Set); + void ModuleReset(enum CA_SLOT_TYPE, uint32_t Slot); + bool ModulePresent(enum CA_SLOT_TYPE, uint32_t Slot); + void ModuleName(enum CA_SLOT_TYPE, uint32_t Slot, char *Name); + void MenuEnter(enum CA_SLOT_TYPE, uint32_t Slot); + void MenuAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint32_t choice); + void InputAnswer(enum CA_SLOT_TYPE, uint32_t Slot, uint8_t * Data, int Len); + void MenuClose(enum CA_SLOT_TYPE, uint32_t Slot); + virtual ~cCA(); +}; + +#endif // __CA_LIBTRIPLE_H_ diff --git a/lib/libtriple/ca_cs.h b/lib/libtriple/ca_cs.h new file mode 100644 index 000000000..dae70d6f1 --- /dev/null +++ b/lib/libtriple/ca_cs.h @@ -0,0 +1 @@ +#include "ca.h" diff --git a/lib/libtriple/mmi.h b/lib/libtriple/mmi.h new file mode 100644 index 000000000..76ff99279 --- /dev/null +++ b/lib/libtriple/mmi.h @@ -0,0 +1,23 @@ +#ifndef __MMI_H_ +#define __MMI_H_ + +#define MAX_MMI_ITEMS 40 +#define MAX_MMI_TEXT_LEN 255 +#define MAX_MMI_CHOICE_TEXT_LEN 255 + +typedef struct { + int choice_nb; + char title[MAX_MMI_TEXT_LEN]; + char subtitle[MAX_MMI_TEXT_LEN]; + char bottom[MAX_MMI_TEXT_LEN]; + char choice_item[MAX_MMI_ITEMS][MAX_MMI_CHOICE_TEXT_LEN]; +} MMI_MENU_LIST_INFO; + +typedef struct { + int blind; + int answerlen; + char enguiryText[MAX_MMI_TEXT_LEN]; +} MMI_ENGUIRY_INFO; + +#endif // __MMI_H_ + From 799b500b74ded767d78c403f31effdce8e226767 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Fri, 20 Aug 2010 00:48:25 +0200 Subject: [PATCH 0020/1070] libtriple/framebuffer: use DirectFB acceleration Use a hack, almost as ugly as the original Coolstream code ;), to accelerate drawing of boxes and blitting with DirectFB functions. Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/9fc1d89563758bed3916c332d68171aa63b6b9fa Author: Stefan Seyfried Date: 2010-08-20 (Fri, 20 Aug 2010) ------------------ This commit was generated by Migit --- lib/libtriple/init_td.cpp | 17 ++++-- src/driver/Makefile.am | 3 +- src/driver/framebuffer.cpp | 119 +++++++++++++++++++++++++++++++++++++ src/driver/framebuffer.h | 4 ++ 4 files changed, 137 insertions(+), 6 deletions(-) diff --git a/lib/libtriple/init_td.cpp b/lib/libtriple/init_td.cpp index d56714bf3..c575091fb 100644 --- a/lib/libtriple/init_td.cpp +++ b/lib/libtriple/init_td.cpp @@ -21,11 +21,12 @@ static const char * FILENAME = "init_td.cpp"; static bool initialized = false; /* the super interface */ -static IDirectFB *dfb; +IDirectFB *dfb; /* the primary surface */ static IDirectFBSurface *primary; -static IDirectFBSurface *dest; +IDirectFBSurface *dfbdest; static IDirectFBDisplayLayer *layer; +int gfxfd = -1; #define DFBCHECK(x...) \ err = x; \ @@ -74,13 +75,13 @@ static void dfb_init() primary->GetPixelFormat(primary, &pixelformat); primary->GetSize(primary, &SW, &SH); primary->Clear(primary, 0, 0, 0, 0); - primary->GetSubSurface(primary, NULL, &dest); - dest->Clear(dest, 0, 0, 0, 0); + primary->GetSubSurface(primary, NULL, &dfbdest); + dfbdest->Clear(dfbdest, 0, 0, 0, 0); } static void dfb_deinit() { - dest->Release(dest); + dfbdest->Release(dfbdest); primary->Release(primary); layer->Release(layer); dfb->Release(dfb); @@ -119,6 +120,9 @@ void init_td_api() if (setpgid(0, pid)) perror("setpgid"); rc_init(); + gfxfd = open("/dev/stb/tdgfx", O_RDWR); + if (gfxfd < 0) + perror("open /dev/stb/tdgfx"); } initialized = true; fprintf(stderr, "%s:%s end\n", FILENAME, __FUNCTION__); @@ -129,5 +133,8 @@ void shutdown_td_api() fprintf(stderr, "%s:%s, initialized = %d\n", FILENAME, __FUNCTION__, (int)initialized); if (initialized) dfb_deinit(); + if (gfxfd > -1) + close(gfxfd); + gfxfd = -1; initialized = false; } diff --git a/src/driver/Makefile.am b/src/driver/Makefile.am index 480080a76..21a1d02d2 100644 --- a/src/driver/Makefile.am +++ b/src/driver/Makefile.am @@ -50,7 +50,8 @@ libneutrino_driver_a_SOURCES += \ lcdd.cpp INCLUDES += \ - -I$(top_srcdir)/lib/libtriple + -I$(top_srcdir)/lib/libtriple \ + @DIRECTFB_CFLAGS@ endif libneutrino_driver_netfile_a_SOURCES = netfile.cpp diff --git a/src/driver/framebuffer.cpp b/src/driver/framebuffer.cpp index d1588a160..a68207f45 100644 --- a/src/driver/framebuffer.cpp +++ b/src/driver/framebuffer.cpp @@ -149,6 +149,27 @@ void CFrameBuffer::waitForIdle(void) } #endif /* USE_NEVIS_GXA */ +#if HAVE_TRIPLEDRAGON +#include +#include +extern IDirectFB *dfb; +extern IDirectFBSurface *dfbdest; +extern int gfxfd; +void CFrameBuffer::waitForIdle(void) +{ +#if 0 + struct timeval ts, te; + gettimeofday(&ts, NULL); +#endif + /* does not work: DFBResult r = dfb->WaitForSync(dfb); */ + ioctl(gfxfd, STB04GFX_ENGINE_SYNC); +#if 0 + gettimeofday(&te, NULL); + printf("STB04GFX_ENGINE_SYNC took %lld us\n", (te.tv_sec * 1000000LL + te.tv_usec) - (ts.tv_sec * 1000000LL + ts.tv_usec)); +#endif +} +#endif + /*******************************************************************************/ static uint8_t * virtual_fb = NULL; @@ -632,9 +653,14 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int int corner_bl = (type & CORNER_BOTTOM_LEFT) ? 1 : 0; int corner_br = (type & CORNER_BOTTOM_RIGHT) ? 1 : 0; +#if HAVE_TRIPLEDRAGON + char *c = (char *)&col; + dfbdest->SetColor(dfbdest, c[1], c[2], c[3], c[0]); +#else #ifndef USE_NEVIS_GXA int swidth = stride / sizeof(fb_pixel_t); fb_pixel_t *fbp = getFrameBufferPointer() + (swidth * y); +#endif #endif /* this table contains the x coordinates for a quarter circle (the bottom right quarter) with fixed @@ -720,6 +746,16 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int ofl = corner_bl ? ofs : 0; ofr = corner_br ? ofs : 0; } +#if HAVE_TRIPLEDRAGON + else + { + int height = dy - ((corner_tl|corner_tr) + (corner_bl|corner_br)) * radius; + dfbdest->FillRectangle(dfbdest, x, y + line, dx, height); + line += height; + continue; + } + dfbdest->DrawLine(dfbdest, x + ofl, y + line, x + dx - ofr - 1, y + line); +#else #ifdef USE_NEVIS_GXA _write_gxa(gxa_base, cmd, GXA_POINT(x + dx - ofr, y + line)); /* endig point */ _write_gxa(gxa_base, cmd, GXA_POINT(x + ofl, y + line)); /* start point */ @@ -729,12 +765,14 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int *(fbp + pos) = col; } fbp += swidth; +#endif #endif line++; } } else { +#if !HAVE_TRIPLEDRAGON while (line < dy) { #ifdef USE_NEVIS_GXA @@ -749,6 +787,9 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int #endif line++; } +#else + dfbdest->FillRectangle(dfbdest, x, y + line, dx, dy - line); +#endif } #ifdef USE_NEVIS_GXA /* the GXA seems to do asynchronous rendering, so we add a sync marker @@ -757,6 +798,7 @@ void CFrameBuffer::paintBoxRel(const int x, const int y, const int dx, const int #endif } +#if !HAVE_TRIPLEDRAGON void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col) { if (!getActive()) @@ -850,6 +892,43 @@ void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col) *(dest++) = col; #endif /* USE_NEVIS_GXA */ } +#else /* TRIPLEDRAGON */ +void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col) +{ + paintLine(x, y, x, y, col); +} + +void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col) +{ + if (!getActive()) + return; + + char *c = (char *)&col; + dfbdest->SetColor(dfbdest, c[1], c[2], c[3], c[0]); + dfbdest->DrawLine(dfbdest, xa, ya, xb, yb); + return; +} + +void CFrameBuffer::paintVLine(int x, int ya, int yb, const fb_pixel_t col) +{ + paintLine(x, ya, x, yb, col); +} + +void CFrameBuffer::paintVLineRel(int x, int y, int dy, const fb_pixel_t col) +{ + paintLine(x, y, x, y + dy, col); +} + +void CFrameBuffer::paintHLine(int xa, int xb, int y, const fb_pixel_t col) +{ + paintLine(xa, y, xb, y, col); +} + +void CFrameBuffer::paintHLineRel(int x, int dx, int y, const fb_pixel_t col) +{ + paintLine(x, y, x + dx, y, col); +} +#endif /* TRIPLEDRAGON */ void CFrameBuffer::setIconBasePath(const std::string & iconPath) { @@ -1127,6 +1206,7 @@ void CFrameBuffer::loadPal(const std::string & filename, const unsigned char off close(lfd); } +#if !HAVE_TRIPLEDRAGON void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col) { if (!getActive()) @@ -1142,6 +1222,7 @@ void CFrameBuffer::paintPixel(const int x, const int y, const fb_pixel_t col) *pos = col; #endif } +#endif void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const int dy, const int px, const fb_pixel_t col, const int rad) { @@ -1204,6 +1285,7 @@ void CFrameBuffer::paintBoxFrame(const int sx, const int sy, const int dx, const } +#if !HAVE_TRIPLEDRAGON void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t col) { if (!getActive()) @@ -1291,6 +1373,7 @@ void CFrameBuffer::paintLine(int xa, int ya, int xb, int yb, const fb_pixel_t co } } } +#endif void CFrameBuffer::setBackgroundColor(const fb_pixel_t color) { @@ -1677,6 +1760,7 @@ void * CFrameBuffer::convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, uns return int_convertRGB2FB(rgbbuff, x, y, 0, true); } +#if !HAVE_TRIPLEDRAGON void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) { int xc, yc; @@ -1729,6 +1813,41 @@ void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32 } #endif } +#else +void CFrameBuffer::blit2FB(void *fbbuff, uint32_t width, uint32_t height, uint32_t xoff, uint32_t yoff, uint32_t xp, uint32_t yp, bool transp) +{ + DFBRectangle src; + DFBResult err; + IDirectFBSurface *surf; + DFBSurfaceDescription dsc; + + src.x = xp; + src.y = yp; + src.w = width - xp; + src.h = height - yp; + + dsc.flags = (DFBSurfaceDescriptionFlags)(DSDESC_CAPS | DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PREALLOCATED); + dsc.caps = DSCAPS_NONE; + dsc.width = width; + dsc.height = height; + dsc.preallocated[0].data = fbbuff; + dsc.preallocated[0].pitch = width * sizeof(fb_pixel_t); + err = dfb->CreateSurface(dfb, &dsc, &surf); + /* TODO: maybe we should not die if this fails? */ + if (err != DFB_OK) { + fprintf(stderr, "CFrameBuffer::blit2FB: "); + DirectFBErrorFatal("dfb->CreateSurface(dfb, &dsc, &surf)", err); + } + + if (transp) + surf->SetSrcColorKey(surf, 0, 0, 0); + + dfbdest->SetBlittingFlags(dfbdest, DSBLIT_SRC_COLORKEY); + dfbdest->Blit(dfbdest, surf, &src, xoff, yoff); + surf->Release(surf); + return; +} +#endif void CFrameBuffer::displayRGB(unsigned char *rgbbuff, int x_size, int y_size, int x_pan, int y_pan, int x_offs, int y_offs, bool clearfb, int transp) { diff --git a/src/driver/framebuffer.h b/src/driver/framebuffer.h index e971dabc1..529633eaf 100644 --- a/src/driver/framebuffer.h +++ b/src/driver/framebuffer.h @@ -214,8 +214,12 @@ class CFrameBuffer #ifdef USE_NEVIS_GXA void add_gxa_sync_marker(void); void waitForIdle(void); +#else +#if HAVE_TRIPLEDRAGON + void waitForIdle(void); #else inline void waitForIdle(void) {}; +#endif #endif void* convertRGB2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y, int transp = 0xFF); void* convertRGBA2FB(unsigned char *rgbbuff, unsigned long x, unsigned long y); From 0693eef8c2f351e4eab08210a33fe6f970bb1dcb Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Mon, 1 Feb 2010 21:16:52 +0100 Subject: [PATCH 0021/1070] various assorted build fixes / hacks Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/5e86416ccbc4464591886a889ba1743aa44dde32 Author: Stefan Seyfried Date: 2010-02-01 (Mon, 01 Feb 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/neutrino.cpp | 4 ++++ src/system/setting_helpers.cpp | 7 +++++++ src/zapit/include/zapit/settings.h | 2 ++ 3 files changed, 13 insertions(+) diff --git a/src/neutrino.cpp b/src/neutrino.cpp index bc3a25219..61e023abe 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -2902,6 +2902,7 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) system("/bin/umount -a"); sleep(1); { +#if HAVE_COOL_HARDWARE standby_data_t standby; time_t mtime = time(NULL); struct tm *tmtime = localtime(&mtime); @@ -2955,6 +2956,9 @@ void CNeutrinoApp::ExitRun(const bool /*write_si*/, int retcode) while(true) sleep(1); } } +#else + reboot(LINUX_REBOOT_CMD_RESTART); +#endif } #if 0 neutrino_msg_t msg; diff --git a/src/system/setting_helpers.cpp b/src/system/setting_helpers.cpp index 79bb7d926..14eb437de 100644 --- a/src/system/setting_helpers.cpp +++ b/src/system/setting_helpers.cpp @@ -925,6 +925,7 @@ bool CLedControlNotifier::changeNotify(const neutrino_locale_t, void* /*data*/) return true; } +#if HAVE_COOL_HARDWARE bool CFanControlNotifier::changeNotify(const neutrino_locale_t, void * data) { int cfd, ret; @@ -945,6 +946,12 @@ bool CFanControlNotifier::changeNotify(const neutrino_locale_t, void * data) } return true; } +#else +bool CFanControlNotifier::changeNotify(const neutrino_locale_t, void *) +{ + return true; +} +#endif bool CCpuFreqNotifier::changeNotify(const neutrino_locale_t, void * data) { diff --git a/src/zapit/include/zapit/settings.h b/src/zapit/include/zapit/settings.h index c70c58fd2..b72dc214f 100644 --- a/src/zapit/include/zapit/settings.h +++ b/src/zapit/include/zapit/settings.h @@ -48,10 +48,12 @@ #define CABLES_XML CONFIGDIR "/cables.xml" #define SATELLITES_XML CONFIGDIR "/satellites.xml" +#if HAVE_TRIPLEDRAGON == 0 #define AUDIO_DEVICE "/dev/dvb/adapter0/audio0" #define DEMUX_DEVICE "/dev/dvb/adapter0/demux0" #define FRONTEND_DEVICE "/dev/dvb/adapter0/frontend0" #define VIDEO_DEVICE "/dev/dvb/adapter0/video0" +#endif #define CAMD_UDS_NAME "/tmp/camd.socket" From 96db3ade8c26b46158ee5e359128c35c310fd823 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 28 Feb 2010 19:20:57 +0100 Subject: [PATCH 0022/1070] neutrino: fix black rectangle on screen The 'starting neutrino...' hintbox was hidden too late, so that it overlapped with the 'reloading channels' box which caused a black rectangle to stay on screen. Fix ordering. Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/9142326043e205187571eb6ff8fba4a7debef0dc Author: Stefan Seyfried Date: 2010-02-28 (Sun, 28 Feb 2010) ------------------ This commit was generated by Migit --- src/neutrino.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 61e023abe..d45f869c8 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -1853,6 +1853,9 @@ int CNeutrinoApp::run(int argc, char **argv) hdd->exec(NULL, ""); delete hdd; + hintBox->hide(); // InitZapper also displays a hintbox + delete hintBox; + g_volume = CVolume::getInstance(); cCA::GetInstance()->Ready(true); InitZapper(); @@ -1860,9 +1863,6 @@ int CNeutrinoApp::run(int argc, char **argv) g_volume->AudioMute(current_muted, true); SHTDCNT::getInstance()->init(); - hintBox->hide(); - delete hintBox; - RealRun(personalize.getWidget(0)/**main**/); ExitRun(true, (cs_get_revision() > 7)); From 11751055860a8ff976b63f0c03c67ab2d63a361b Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 28 Feb 2010 19:54:00 +0100 Subject: [PATCH 0023/1070] yhttpd: try to fix shutdown problems, probably directfb related Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/a42b1ca51220fdb5d3670457ef62091219a03f51 Author: Stefan Seyfried Date: 2010-02-28 (Sun, 28 Feb 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/nhttpd/yhttpd.cpp | 1 + src/nhttpd/yhttpd_core/ywebserver.cpp | 2 ++ 2 files changed, 3 insertions(+) diff --git a/src/nhttpd/yhttpd.cpp b/src/nhttpd/yhttpd.cpp index 17997aaf5..bac6a74d8 100644 --- a/src/nhttpd/yhttpd.cpp +++ b/src/nhttpd/yhttpd.cpp @@ -107,6 +107,7 @@ void yhttpd_reload_config() { #ifndef Y_CONFIG_BUILD_AS_DAEMON void * nhttpd_main_thread(void *) { pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, 0); + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); aprintf("Webserver %s tid %ld\n", WEBSERVERNAME, syscall(__NR_gettid)); yhttpd = new Cyhttpd(); //CLogging::getInstance()->setDebug(true); diff --git a/src/nhttpd/yhttpd_core/ywebserver.cpp b/src/nhttpd/yhttpd_core/ywebserver.cpp index 601b966a3..2b9c1e503 100644 --- a/src/nhttpd/yhttpd_core/ywebserver.cpp +++ b/src/nhttpd/yhttpd_core/ywebserver.cpp @@ -218,6 +218,8 @@ bool CWebserver::run(void) { CySocket *newConnectionSock; if (!(newConnectionSock = listenSocket.accept())) //Now: Blocking wait { + pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); + pthread_testcancel(); dperror("Socket accept error. Continue.\n"); continue; } From 2976ad44667b1cf05e1d885ebccad3158b8c759f Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 28 Feb 2010 19:56:58 +0100 Subject: [PATCH 0024/1070] zapit: do not spam with useless debug messages Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/56f963ad735f8a9e13a2be1939e38f8e01d31555 Author: Stefan Seyfried Date: 2010-02-28 (Sun, 28 Feb 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/zapit/src/getservices.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/zapit/src/getservices.cpp b/src/zapit/src/getservices.cpp index ca23ed59a..49b2e1b5c 100644 --- a/src/zapit/src/getservices.cpp +++ b/src/zapit/src/getservices.cpp @@ -628,7 +628,7 @@ bool CServiceManager::LoadServices(bool only_current) printf("[zapit] %d services loaded (%d)...\n", service_count, allchans.size()); TIMER_STOP("[zapit] service loading took"); - if(zapit_debug) {//FIXME + if(0) { //zapit_debug) {//FIXME sat_iterator_t sit; for(sit = satellitePositions.begin(); sit != satellitePositions.end(); sit++) printf("satelliteName = %s (%d), satellitePosition = %d motor position = %d usals %d\n", sit->second.name.c_str(), sit->second.name.size(), sit->first, sit->second.motor_position, sit->second.use_usals); From c5a62b2e8d2f7537e7d45f8e1070af28940f3592 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 6 Mar 2010 14:08:35 +0100 Subject: [PATCH 0025/1070] neutrino: fix framebuffer transparency issue Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/4405bb367c7ffd5edd0e9489d2287c724069a0cc Author: Stefan Seyfried Date: 2010-03-06 (Sat, 06 Mar 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/neutrino.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/neutrino.cpp b/src/neutrino.cpp index d45f869c8..47dabad66 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -222,7 +222,11 @@ CNeutrinoApp::CNeutrinoApp() frameBuffer = CFrameBuffer::getInstance(); frameBuffer->setIconBasePath(DATADIR "/neutrino/icons/"); - +#if HAVE_TRIPLEDRAGON + /* this needs to happen before the framebuffer is set up */ + init_td_api(); + // shutdown_td_api(); +#endif SetupFrameBuffer(); mode = mode_unknown; From cf647ad8d36c0426a47e88e30c51e25a0b19ca53 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 28 Nov 2010 19:08:57 +0100 Subject: [PATCH 0026/1070] neutrino: show only usable video modes and video options on TD Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/bb3e8ebe23cf6165bc328af4b16725e4b48f7acb Author: Stefan Seyfried Date: 2010-11-28 (Sun, 28 Nov 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/videosettings.cpp | 35 +++++++++++++++++++++++++++++------ src/neutrino.cpp | 2 ++ src/system/settings.h | 5 +++++ 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/gui/videosettings.cpp b/src/gui/videosettings.cpp index 2790b7fe3..4bf0bf0e2 100644 --- a/src/gui/videosettings.cpp +++ b/src/gui/videosettings.cpp @@ -143,6 +143,14 @@ const CMenuOptionChooser::keyval VIDEOMENU_VIDEOSIGNAL_HD1PLUS_CINCH_OPTIONS[VID { ANALOG_HD_YPRPB_CINCH, LOCALE_VIDEOMENU_ANALOG_HD_YPRPB_CINCH } }; +#if HAVE_TRIPLEDRAGON +CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_OPTION_COUNT] = +{ + { VID_DISPFMT_PAL, NONEXISTANT_LOCALE, "PAL" }, + { VID_DISPFMT_SECAM, NONEXISTANT_LOCALE, "SECAM" }, + { VID_DISPFMT_NTSC, NONEXISTANT_LOCALE, "NTSC" } +}; +#else /* numbers corresponding to video.cpp from zapit */ CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_OPTION_COUNT] = { @@ -160,13 +168,20 @@ CMenuOptionChooser::keyval_ext VIDEOMENU_VIDEOMODE_OPTIONS[VIDEOMENU_VIDEOMODE_O { VIDEO_STD_1080I60, NONEXISTANT_LOCALE, "1080i 60Hz" }, { VIDEO_STD_AUTO, NONEXISTANT_LOCALE, "Auto" } }; +#endif +#if HAVE_TRIPLEDRAGON +#define VIDEOMENU_VIDEOFORMAT_OPTION_COUNT 2 +#else #define VIDEOMENU_VIDEOFORMAT_OPTION_COUNT 3//2 +#endif const CMenuOptionChooser::keyval VIDEOMENU_VIDEOFORMAT_OPTIONS[VIDEOMENU_VIDEOFORMAT_OPTION_COUNT] = { { DISPLAY_AR_4_3, LOCALE_VIDEOMENU_VIDEOFORMAT_43 }, { DISPLAY_AR_16_9, LOCALE_VIDEOMENU_VIDEOFORMAT_169 }, +#if !HAVE_TRIPLEDRAGON { DISPLAY_AR_14_9, LOCALE_VIDEOMENU_VIDEOFORMAT_149 } +#endif }; #define VIDEOMENU_DBDR_OPTION_COUNT 3 @@ -213,8 +228,12 @@ int CVideoSettings::showVideoSetup() //dbdr options CMenuOptionChooser * vs_dbdropt_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_DBDR, &g_settings.video_dbdr, VIDEOMENU_DBDR_OPTIONS, VIDEOMENU_DBDR_OPTION_COUNT, true, this); - //video system modes submenue - CMenuWidget* videomodes = new CMenuWidget(LOCALE_MAINSETTINGS_VIDEO, NEUTRINO_ICON_SETTINGS); + //video system modes submenue + CMenuWidget *videomodes = NULL; + CMenuForwarder *vs_videomodes_fw = NULL; + if (system_rev != 0x01) /* Tripledragon */ + { + videomodes = new CMenuWidget(LOCALE_MAINSETTINGS_VIDEO, NEUTRINO_ICON_SETTINGS); videomodes->addIntroItems(LOCALE_VIDEOMENU_ENABLED_MODES); CAutoModeNotifier * anotify = new CAutoModeNotifier(); @@ -222,8 +241,9 @@ int CVideoSettings::showVideoSetup() videomodes->addItem(new CMenuOptionChooser(VIDEOMENU_VIDEOMODE_OPTIONS[i].valname, &g_settings.enabled_video_modes[i], OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, anotify)); anotify->changeNotify(NONEXISTANT_LOCALE, 0); - CMenuForwarder * vs_videomodes_fw = new CMenuForwarder(LOCALE_VIDEOMENU_ENABLED_MODES, true, NULL, videomodes, NULL, CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED ); - + vs_videomodes_fw = new CMenuForwarder(LOCALE_VIDEOMENU_ENABLED_MODES, true, NULL, videomodes, NULL, CRCInput::RC_red, NEUTRINO_ICON_BUTTON_RED ); + } + //--------------------------------------- videosetup->addIntroItems(LOCALE_MAINSETTINGS_VIDEO, LOCALE_VIDEOMENU_TV_SCART); //--------------------------------------- @@ -239,8 +259,11 @@ int CVideoSettings::showVideoSetup() videosetup->addItem(vs_43mode_ch); //4:3 mode videosetup->addItem(vs_dispformat_ch); //display format videosetup->addItem(vs_videomodes_ch); //video system - videosetup->addItem(vs_dbdropt_ch); //dbdr options - videosetup->addItem(vs_videomodes_fw); //video modes submenue + if (system_rev != 0x01) /* TRIPLEDRAGON hack... :-) */ + { + videosetup->addItem(vs_dbdropt_ch); //dbdr options + videosetup->addItem(vs_videomodes_fw); //video modes submenue + } int res = videosetup->exec(NULL, ""); videosetup->hide(); diff --git a/src/neutrino.cpp b/src/neutrino.cpp index 47dabad66..bf8056ce6 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -354,8 +354,10 @@ int CNeutrinoApp::loadSetup(const char * fname) sprintf(cfg_key, "enabled_video_mode_%d", i); g_settings.enabled_video_modes[i] = configfile.getInt32(cfg_key, 0); } +#if VIDEOMENU_VIDEOMODE_OPTION_COUNT > 3 g_settings.enabled_video_modes[3] = 1; // 720p 50Hz g_settings.enabled_video_modes[4] = 1; // 1080i 50Hz +#endif g_settings.cpufreq = configfile.getInt32("cpufreq", 0); g_settings.standby_cpufreq = configfile.getInt32("standby_cpufreq", 100); diff --git a/src/system/settings.h b/src/system/settings.h index 7c71b2192..5acde9f60 100644 --- a/src/system/settings.h +++ b/src/system/settings.h @@ -32,6 +32,7 @@ #ifndef __settings__ #define __settings__ +#include "config.h" #include #include #include @@ -39,7 +40,11 @@ #include +#if !HAVE_TRIPLEDRAGON #define VIDEOMENU_VIDEOMODE_OPTION_COUNT 12 +#else +#define VIDEOMENU_VIDEOMODE_OPTION_COUNT 3 +#endif struct SNeutrinoSettings { From 35e3d88c1f033af3b7e9bf35db5525d3a307c4f1 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 6 Nov 2010 11:57:13 +0100 Subject: [PATCH 0027/1070] neutrino: hide Dolby/HDMI and SRS options on Tripledragon Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/084cf9d9f98696bd1009bcb6ec963aedb694b0a9 Author: Stefan Seyfried Date: 2010-11-06 (Sat, 06 Nov 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/audio_setup.cpp | 29 ++++++++++++++++++++++------- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/src/gui/audio_setup.cpp b/src/gui/audio_setup.cpp index b6483b232..a98a9dc27 100644 --- a/src/gui/audio_setup.cpp +++ b/src/gui/audio_setup.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include @@ -121,6 +122,7 @@ const CMenuOptionChooser::keyval AUDIOMENU_HDMI_DD_OPTIONS[AUDIOMENU_HDMI_DD_OPT /* audio settings menu */ int CAudioSetup::showAudioSetup() { + unsigned int system_rev = cs_get_revision(); //menue init CMenuWidget* audioSettings = new CMenuWidget(LOCALE_MAINSETTINGS_HEAD, NEUTRINO_ICON_SETTINGS, width); audioSettings->setSelected(selected); @@ -133,7 +135,11 @@ int CAudioSetup::showAudioSetup() CMenuOptionChooser * as_oj_ddsubchn = new CMenuOptionChooser(LOCALE_AUDIOMENU_DOLBYDIGITAL, &g_settings.audio_DolbyDigital, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, audioSetupNotifier); //dd via hdmi - CMenuOptionChooser * as_oj_dd_hdmi = new CMenuOptionChooser(LOCALE_AUDIOMENU_HDMI_DD, &g_settings.hdmi_dd, AUDIOMENU_HDMI_DD_OPTIONS, AUDIOMENU_HDMI_DD_OPTION_COUNT, true, audioSetupNotifier); + CMenuOptionChooser *as_oj_dd_hdmi = NULL; + /* system_rev == 0x01 is a hack: no Coolstream box has this value, but libtriple + defines it for the Tripledragon, so 0x01 identifies the TD. */ + if (system_rev != 0x01) + as_oj_dd_hdmi = new CMenuOptionChooser(LOCALE_AUDIOMENU_HDMI_DD, &g_settings.hdmi_dd, AUDIOMENU_HDMI_DD_OPTIONS, AUDIOMENU_HDMI_DD_OPTION_COUNT, true, audioSetupNotifier); //dd via spdif CMenuOptionChooser * as_oj_dd_spdif = new CMenuOptionChooser(LOCALE_AUDIOMENU_SPDIF_DD, &g_settings.spdif_dd, OPTIONS_OFF0_ON1_OPTIONS, OPTIONS_OFF0_ON1_OPTION_COUNT, true, audioSetupNotifier); @@ -172,7 +178,8 @@ int CAudioSetup::showAudioSetup() audioSettings->addItem(as_oj_analogmode); audioSettings->addItem(GenericMenuSeparatorLine); //--------------------------------------------------------- - audioSettings->addItem(as_oj_dd_hdmi); + if (system_rev != 0x01) + audioSettings->addItem(as_oj_dd_hdmi); audioSettings->addItem(as_oj_dd_spdif); audioSettings->addItem(as_oj_ddsubchn); audioSettings->addItem(GenericMenuSeparatorLine); @@ -181,11 +188,19 @@ int CAudioSetup::showAudioSetup() audioSettings->addItem(as_oj_vsteps); // audioSettings->addItem(as_clockrec); //--------------------------------------------------------- - audioSettings->addItem(GenericMenuSeparatorLine); - audioSettings->addItem(as_oj_srsonoff); - audioSettings->addItem(as_oj_algo); - audioSettings->addItem(as_oj_noise); - audioSettings->addItem(as_oj_volrev); + if (system_rev != 0x01) { + audioSettings->addItem(GenericMenuSeparatorLine); + audioSettings->addItem(as_oj_srsonoff); + audioSettings->addItem(as_oj_algo); + audioSettings->addItem(as_oj_noise); + audioSettings->addItem(as_oj_volrev); + } else { + /* if it's not added, we need to delete it manually */ + delete as_oj_srsonoff; + delete as_oj_algo; + delete as_oj_noise; + delete as_oj_volrev; + } #if 0 audioSettings->addItem(mf); #endif From 207948b1bdb64ea874740c62d4b12befd6bc4ae3 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 7 Aug 2010 22:50:12 +0200 Subject: [PATCH 0028/1070] neutrino: remove screen type selection for Tripledragon Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/beb10241ad10c6c2de31350fc72a8c37df1225d6 Author: Stefan Seyfried Date: 2010-08-07 (Sat, 07 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/osd_setup.cpp | 4 +++- src/neutrino.cpp | 13 ++++++++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/src/gui/osd_setup.cpp b/src/gui/osd_setup.cpp index 16527cdab..fc0f4ff7c 100644 --- a/src/gui/osd_setup.cpp +++ b/src/gui/osd_setup.cpp @@ -56,6 +56,7 @@ #include #include +#include "cs_api.h" static CTimingSettingsNotifier timingsettingsnotifier; @@ -428,7 +429,8 @@ int COsdSetup::showOsdSetup() //monitor //CScreenPresetNotifier * presetNotify = new CScreenPresetNotifier(); //osd_menu->addItem(new CMenuOptionChooser(LOCALE_COLORMENU_OSD_PRESET, &g_settings.screen_preset, OSD_PRESET_OPTIONS, OSD_PRESET_OPTIONS_COUNT, true, presetNotify)); - osd_menu->addItem(new CMenuOptionChooser(LOCALE_COLORMENU_OSD_PRESET, &g_settings.screen_preset, OSD_PRESET_OPTIONS, OSD_PRESET_OPTIONS_COUNT, true, this)); + if (cs_get_revision() != 1) /* 1 == Tripledragon */ + osd_menu->addItem(new CMenuOptionChooser(LOCALE_COLORMENU_OSD_PRESET, &g_settings.screen_preset, OSD_PRESET_OPTIONS, OSD_PRESET_OPTIONS_COUNT, true, this)); osd_menu->addItem(GenericMenuSeparatorLine); //options diff --git a/src/neutrino.cpp b/src/neutrino.cpp index bf8056ce6..dc3fea1c7 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -293,10 +293,17 @@ const lcd_setting_struct_t lcd_setting[SNeutrinoSettings::LCD_SETTING_COUNT] = /************************************************************************************** * CNeutrinoApp - loadSetup, load the application-settings * **************************************************************************************/ +#if HAVE_TRIPLEDRAGON +#define DEFAULT_X_START_SD 32 +#define DEFAULT_Y_START_SD 26 +#define DEFAULT_X_END_SD 694 +#define DEFAULT_Y_END_SD 570 +#else #define DEFAULT_X_START_SD 60 #define DEFAULT_Y_START_SD 20 #define DEFAULT_X_END_SD 1220 #define DEFAULT_Y_END_SD 560 +#endif #define DEFAULT_X_START_HD 40 //5 #define DEFAULT_Y_START_HD 25 //5 @@ -622,8 +629,12 @@ int CNeutrinoApp::loadSetup(const char * fname) g_settings.screen_StartY_lcd = configfile.getInt32( "screen_StartY_lcd", DEFAULT_Y_START_HD ); g_settings.screen_EndX_lcd = configfile.getInt32( "screen_EndX_lcd", DEFAULT_X_END_HD); g_settings.screen_EndY_lcd = configfile.getInt32( "screen_EndY_lcd", DEFAULT_Y_END_HD); +#if HAVE_TRIPLEDRAGON + /* does not make sense to have two configurations for that... */ + g_settings.screen_preset = 0; +#else g_settings.screen_preset = configfile.getInt32( "screen_preset", 1); - +#endif g_settings.screen_StartX = g_settings.screen_preset ? g_settings.screen_StartX_lcd : g_settings.screen_StartX_crt; g_settings.screen_StartY = g_settings.screen_preset ? g_settings.screen_StartY_lcd : g_settings.screen_StartY_crt; g_settings.screen_EndX = g_settings.screen_preset ? g_settings.screen_EndX_lcd : g_settings.screen_EndX_crt; From 8bf2b19954bed72521d955cd9c3d35210f253ff6 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 8 Aug 2010 15:08:40 +0200 Subject: [PATCH 0029/1070] neutrino: add video output format setting for TD Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/e5180c47328987174a47219c465ff30a92340b86 Author: Stefan Seyfried Date: 2010-08-08 (Sun, 08 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/videosettings.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/gui/videosettings.cpp b/src/gui/videosettings.cpp index 4bf0bf0e2..7a98d8634 100644 --- a/src/gui/videosettings.cpp +++ b/src/gui/videosettings.cpp @@ -104,6 +104,13 @@ const CMenuOptionChooser::keyval VIDEOMENU_43MODE_OPTIONS[VIDEOMENU_43MODE_OPTIO //{ 2, LOCALE_VIDEOMENU_AUTO } // whatever is this auto mode, it seems its totally broken }; +#define VIDEOMENU_VIDEOSIGNAL_TD_OPTION_COUNT 2 +const CMenuOptionChooser::keyval VIDEOMENU_VIDEOSIGNAL_TD_OPTIONS[VIDEOMENU_VIDEOSIGNAL_TD_OPTION_COUNT] = +{ + { ANALOG_SD_RGB_SCART, LOCALE_VIDEOMENU_ANALOG_SD_RGB_SCART }, + { ANALOG_SD_YPRPB_SCART, LOCALE_VIDEOMENU_ANALOG_SD_YPRPB_SCART } +}; + #define VIDEOMENU_VIDEOSIGNAL_HD1_OPTION_COUNT 8 const CMenuOptionChooser::keyval VIDEOMENU_VIDEOSIGNAL_HD1_OPTIONS[VIDEOMENU_VIDEOSIGNAL_HD1_OPTION_COUNT] = { @@ -215,6 +222,10 @@ int CVideoSettings::showVideoSetup() vs_chinch_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_CINCH, &g_settings.analog_mode2, VIDEOMENU_VIDEOSIGNAL_HD1PLUS_CINCH_OPTIONS, VIDEOMENU_VIDEOSIGNAL_HD1PLUS_CINCH_OPTION_COUNT, true, this); } + else if (system_rev == 0x01) /* TRIPLEDRAGON hack... :-) */ + { + vs_scart_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_SCART, &g_settings.analog_mode1, VIDEOMENU_VIDEOSIGNAL_TD_OPTIONS, VIDEOMENU_VIDEOSIGNAL_TD_OPTION_COUNT, true, this); + } //4:3 mode CMenuOptionChooser * vs_43mode_ch = new CMenuOptionChooser(LOCALE_VIDEOMENU_43MODE, &g_settings.video_43mode, VIDEOMENU_43MODE_OPTIONS, VIDEOMENU_43MODE_OPTION_COUNT, true, this); From 2d0230b7adbd58328314eae67a36d96cbf4e2a68 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 15 Aug 2010 22:37:20 +0200 Subject: [PATCH 0030/1070] movieplayer: add vdr files filter for TD, remove avi & co Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/4732ba9ddfc5b92babb1c47a12bc900a82e50b44 Author: Stefan Seyfried Date: 2010-08-15 (Sun, 15 Aug 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/movieplayer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gui/movieplayer.cpp b/src/gui/movieplayer.cpp index 7b7af2963..814238cb4 100644 --- a/src/gui/movieplayer.cpp +++ b/src/gui/movieplayer.cpp @@ -100,11 +100,15 @@ void CMoviePlayerGui::Init(void) bookmarkmanager = new CBookmarkManager(); tsfilefilter.addFilter("ts"); +#if HAVE_TRIPLEDRAGON + tsfilefilter.addFilter("vdr"); +#else tsfilefilter.addFilter("avi"); tsfilefilter.addFilter("mkv"); tsfilefilter.addFilter("wav"); tsfilefilter.addFilter("asf"); tsfilefilter.addFilter("aiff"); +#endif tsfilefilter.addFilter("mpg"); tsfilefilter.addFilter("mpeg"); tsfilefilter.addFilter("m2p"); From dfab53b2b61ac4b8a5192a97eefc342d355f3cf1 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 19 Sep 2010 17:54:56 +0200 Subject: [PATCH 0031/1070] neutrino: let the "AUX" key switch to SCART input on TD Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/67e7915bf258f5a87a3b7cb72243ff64f26ee8f5 Author: Stefan Seyfried Date: 2010-09-19 (Sun, 19 Sep 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/neutrino.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/neutrino.cpp b/src/neutrino.cpp index dc3fea1c7..dbe4f7ae4 100644 --- a/src/neutrino.cpp +++ b/src/neutrino.cpp @@ -2154,6 +2154,8 @@ void CNeutrinoApp::RealRun(CMenuWidget &mainMenu) CTimerList Timerlist; Timerlist.exec(NULL, ""); } + else if (msg == CRCInput::RC_aux) + scartMode(true); else { if (msg == CRCInput::RC_home) { if(g_settings.mode_clock && g_settings.key_zaphistory == CRCInput::RC_home) { @@ -2167,7 +2169,7 @@ void CNeutrinoApp::RealRun(CMenuWidget &mainMenu) } else { // mode == mode_scart - if( msg == CRCInput::RC_home ) { + if (msg == CRCInput::RC_home || msg == CRCInput::RC_aux) { if( mode == mode_scart ) { // Scart-Mode verlassen scartMode( false ); @@ -3126,13 +3128,22 @@ void CNeutrinoApp::scartMode( bool bOnOff ) frameBuffer->paintBackground(); //g_Controld->setScartMode( 1 ); +#if HAVE_TRIPLEDRAGON + /* would this hurt on Coolstream? */ + videoDecoder->Stop(true); + videoDecoder->Standby(true); +#endif CVFD::getInstance()->setMode(CVFD::MODE_SCART); lastMode = mode; mode = mode_scart; } else { // SCART AUS //g_Controld->setScartMode( 0 ); - +#if HAVE_TRIPLEDRAGON + /* could actually go into radioMode() and tvMode()? */ + videoDecoder->Standby(false); + videoDecoder->Start(); +#endif mode = mode_unknown; //re-set mode if( lastMode == mode_radio ) { From eff49450c7d033e2c0c6dc927e9178133934bcd0 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 6 Nov 2010 23:27:42 +0100 Subject: [PATCH 0032/1070] hdd_menu: create mountpoint for formatted partition Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/f6fb3ba6acff8687c3fd1b0ec75eda3bcd086671 Author: Stefan Seyfried Date: 2010-11-06 (Sat, 06 Nov 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/hdd_menu.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/hdd_menu.cpp b/src/gui/hdd_menu.cpp index 7609e2c6b..3c23fbf24 100644 --- a/src/gui/hdd_menu.cpp +++ b/src/gui/hdd_menu.cpp @@ -425,9 +425,11 @@ _remount: switch(g_settings.hdd_fs) { case 0: + safe_mkdir(dst); res = mount(src, dst, "ext3", 0, NULL); break; case 1: + safe_mkdir(dst); res = mount(src, dst, "reiserfs", 0, NULL); break; default: From ef6c5a830c6faf7ab2b1949ee48379f413f2c843 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 6 Nov 2010 23:28:21 +0100 Subject: [PATCH 0033/1070] hdd_menu: support the Tripledragon's old kernel Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/d70c00c3556c273a2a31e7a1a4d4804f1c6fcae3 Author: Stefan Seyfried Date: 2010-11-06 (Sat, 06 Nov 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/hdd_menu.cpp | 54 ++++++++++++++++++++++++++++++++++++++------ 1 file changed, 47 insertions(+), 7 deletions(-) diff --git a/src/gui/hdd_menu.cpp b/src/gui/hdd_menu.cpp index 3c23fbf24..fcc6a4a76 100644 --- a/src/gui/hdd_menu.cpp +++ b/src/gui/hdd_menu.cpp @@ -64,9 +64,9 @@ #include -static int my_filter(const struct dirent * dent) +static int my_filter(const struct dirent *d) { - if(dent->d_name[0] == 's' && dent->d_name[1] == 'd') + if ((d->d_name[0] == 's' || d->d_name[0] == 'h') && d->d_name[1] == 'd') return 1; return 0; } @@ -138,6 +138,7 @@ int CHDDMenuHandler::doMenu () int64_t bytes; int64_t megabytes; int removable = 0; + bool oldkernel = false; bool isroot = false; printf("HDD: checking /sys/block/%s\n", namelist[i]->d_name); @@ -164,13 +165,19 @@ int CHDDMenuHandler::doMenu () snprintf(str, sizeof(str), "/sys/block/%s/device/vendor", namelist[i]->d_name); f = fopen(str, "r"); if(!f) { - printf("Cant open %s\n", str); - continue; + oldkernel = true; + strcpy(vendor, ""); + } else { + fscanf(f, "%s", vendor); + fclose(f); + strcat(vendor, "-"); } - fscanf(f, "%s", vendor); - fclose(f); - snprintf(str, sizeof(str), "/sys/block/%s/device/model", namelist[i]->d_name); + /* the Tripledragon only has kernel 2.6.12 available.... :-( */ + if (oldkernel) + snprintf(str, sizeof(str), "/proc/ide/%s/model", namelist[i]->d_name); + else + snprintf(str, sizeof(str), "/sys/block/%s/device/model", namelist[i]->d_name); f = fopen(str, "r"); if(!f) { printf("Cant open %s\n", str); @@ -451,6 +458,39 @@ _remount: snprintf(cmd, sizeof(cmd), "%s/music", dst); safe_mkdir((char *) cmd); sync(); +#if HAVE_TRIPLEDRAGON + /* on the tripledragon, we mount via fstab, so we need to add an + fstab entry for dst */ + FILE *g; + char *line = NULL; + unlink("/etc/fstab.new"); + g = fopen("/etc/fstab.new", "w"); + f = fopen("/etc/fstab", "r"); + if (!g) + perror("open /etc/fstab.new"); + else { + if (f) { + int ret; + while (true) { + size_t dummy; + ret = getline(&line, &dummy, f); + if (ret < 0) + break; + /* remove lines that start with the same disk we formatted + src is "/dev/xda1", we only compare "/dev/xda" */ + if (strncmp(line, src, strlen(src)-1) != 0) + fprintf(g, "%s", line); + } + free(line); + fclose(f); + } + /* now add our new entry */ + fprintf(g, "%s %s auto defaults 0 0\n", src, dst); + fclose(g); + rename("/etc/fstab", "/etc/fstab.old"); + rename("/etc/fstab.new", "/etc/fstab"); + } +#endif } _return: if(!srun) system("smbd"); From ddc71fbffc02181b9cf36cca0edc6e6bead28a89 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 27 Nov 2010 11:26:11 +0100 Subject: [PATCH 0034/1070] neutrino: improve boxinfo for Tripledragon Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/432dc5e0e34d3635133ab5a5bb04b435086117c9 Author: Stefan Seyfried Date: 2010-11-27 (Sat, 27 Nov 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/gui/dboxinfo.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gui/dboxinfo.cpp b/src/gui/dboxinfo.cpp index 1f66372f8..32acd252f 100644 --- a/src/gui/dboxinfo.cpp +++ b/src/gui/dboxinfo.cpp @@ -243,7 +243,12 @@ void CDBoxInfoWidget::paint() size_t len = 0; ssize_t read; while ((read = getline(&buffer, &len, fd)) != -1) { - if (!(strncmp(const_cast("Hardware"),buffer,8))) { +#if HAVE_TRIPLEDRAGON + if (!(strncmp(const_cast("machine"),buffer,7))) +#else + if (!(strncmp(const_cast("Hardware"),buffer,8))) +#endif + { char *t=rindex(buffer,'\n'); if (t) *t='\0'; @@ -257,7 +262,11 @@ void CDBoxInfoWidget::paint() break; } i++; +#if HAVE_TRIPLEDRAGON + if (i == 1 || i > 3) +#else if (i > 2) +#endif continue; if (read > 0 && buffer[read-1] == '\n') buffer[read-1] = '\0'; From 94e8fca27b11079940f14bb58552dcd29e86754a Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 25 Dec 2010 14:54:37 +0100 Subject: [PATCH 0035/1070] libtriple: add cVideo::VideoParamWatchdog() Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/5ae19e4e4971005222eec433bda2847b475da03e Author: Stefan Seyfried Date: 2010-12-25 (Sat, 25 Dec 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/video_td.cpp | 22 ++++++++++++++++++++-- lib/libtriple/video_td.h | 1 + 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index 1e2b30b0e..845ea3ffa 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -492,8 +492,9 @@ int cVideo::setZoom(int zoom) memset(&s, 0, sizeof(s)); if (zoom > 100) { - vidDispSize_t x = (vidDispSize_t)getAspectRatio(); - if (x == VID_DISPSIZE_4x3 && croppingMode == VID_DISPMODE_NORM) + /* 1 = 4:3, 3 = 16:9, 4 = 2.21:1, 0 = unknown */ + int x = getAspectRatio(); + if (x < 3 && croppingMode == VID_DISPMODE_NORM) { s.src.hori_size = 720; s.des.hori_size = 720 * 3/4 * zoom / 100; @@ -550,6 +551,23 @@ void cVideo::setZoomAspect(int index) } #endif +/* this function is regularly called, checks if video parameters + changed and triggers appropriate actions */ +void cVideo::VideoParamWatchdog(void) +{ + static unsigned int _v_info = (unsigned int) -1; + unsigned int v_info; + if (fd == -1) + return; + fop(ioctl, MPEG_VID_GET_V_INFO_RAW, &v_info); + if (_v_info != v_info) + { + lt_debug("cVideo::VPWdog: params changed. old: %08x new: %08x\n", _v_info, v_info); + setAspectRatio(-1, -1); + } + _v_info = v_info; +} + void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/) { /* x = y = w = h = -1 -> reset / "hide" PIG */ diff --git a/lib/libtriple/video_td.h b/lib/libtriple/video_td.h index 8a9f4f03b..fb88c6290 100644 --- a/lib/libtriple/video_td.h +++ b/lib/libtriple/video_td.h @@ -175,6 +175,7 @@ class cVideo void Pig(int x, int y, int w, int h, int osd_w = 1064, int osd_h = 600); void SetControl(int, int) { return; }; int setZoom(int); + void VideoParamWatchdog(void); void setContrast(int val); void SetVideoMode(analog_mode_t mode); void SetDBDR(int) { return; }; From 829d6a0daa5a17af0414446588cd1e2e4bb85e8f Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Mon, 27 Dec 2010 00:23:21 +0100 Subject: [PATCH 0036/1070] libtriple: fix up cVideo::setAspectRatio() Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/65b46d56f20eae3c1bf1a9bd1c0834b91e2d03ef Author: Stefan Seyfried Date: 2010-12-27 (Mon, 27 Dec 2010) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/video_td.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index 845ea3ffa..523ba563e 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -147,20 +147,24 @@ int cVideo::setAspectRatio(int aspect, int mode) } if (_mode != -1) { + int zoom = 100 * 16 / 14; /* 16:9 vs 14:9 */ switch(_mode) { - case DISPLAY_AR_MODE_PANSCAN: + case DISPLAY_AR_MODE_NONE: if (v_ar < 3) dsize = VID_DISPSIZE_4x3; + else + dsize = VID_DISPSIZE_16x9; break; case DISPLAY_AR_MODE_LETTERBOX: dmode = VID_DISPMODE_LETTERBOX; break; + case DISPLAY_AR_MODE_PANSCAN: + zoom = 100 * 5 / 4; case DISPLAY_AR_MODE_PANSCAN2: if ((v_ar < 3 && _aspect == 3) || (v_ar >= 3 && _aspect == 1)) { /* unfortunately, this partly reimplements the setZoom code... */ - int zoom = 100 * 16 / 14; /* 16:9 vs 14:9 */ dsize = VID_DISPSIZE_UNKNOWN; dmode = VID_DISPMODE_SCALE; SCALEINFO s; @@ -187,6 +191,8 @@ int cVideo::setAspectRatio(int aspect, int mode) default: break; } + if (dmode != VID_DISPMODE_SCALE) + fop(ioctl, MPEG_VID_SCALE_OFF); setCroppingMode(dmode); } const char *ds[] = { "4x3", "16x9", "2.21", "unknown" }; @@ -574,6 +580,7 @@ void cVideo::Pig(int x, int y, int w, int h, int /*osd_w*/, int /*osd_h*/) if (x == -1 && y == -1 && w == -1 && h == -1) { setZoom(-1); + setAspectRatio(-1, -1); return; } SCALEINFO s; From 2072babc6f5941690a4e6e9e254f0cd5cc212887 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 2 Jan 2011 16:07:00 +0100 Subject: [PATCH 0037/1070] libtriple: fix filedescriptor leak in cVideo::routeVideo() Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/e786a4ef75f9ae7ee8919f4d51ba6aabdfc72a97 Author: Stefan Seyfried Date: 2011-01-02 (Sun, 02 Jan 2011) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/video_td.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/lib/libtriple/video_td.cpp b/lib/libtriple/video_td.cpp index 523ba563e..cd0eb401e 100644 --- a/lib/libtriple/video_td.cpp +++ b/lib/libtriple/video_td.cpp @@ -654,16 +654,16 @@ void cVideo::routeVideo(int standby) perror("IOC_AVS_SCART_PIN8_FOLLOW_VCR"); if (ioctl(avsfd, IOC_AVS_ROUTE_VCR2TV) < 0) perror("IOC_AVS_ROUTE_VCR2TV"); - return; + } else { + unsigned char fblk = 1; + printf("[%s] setting fastblank to %d, pin8 to %dV, routing encoder to TV\n", __FUNCTION__, fblk, scartvoltage); + if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, fblk) < 0) + perror("IOC_AVS_FASTBLANK_SET, fblk"); + if (ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) + perror("IOC_AVS_SCART_PIN8_SET"); + if (ioctl(avsfd, IOC_AVS_ROUTE_ENC2TV) < 0) + perror("IOC_AVS_ROUTE_ENC2TV"); } - unsigned char fblk = 1; - printf("[%s] setting fastblank to %d, pin8 to %dV, routing encoder to TV\n", __FUNCTION__, fblk, scartvoltage); - if (ioctl(avsfd, IOC_AVS_FASTBLANK_SET, fblk) < 0) - perror("IOC_AVS_FASTBLANK_SET, fblk"); - if (ioctl(avsfd, IOC_AVS_SCART_PIN8_SET, scartvoltage) < 0) - perror("IOC_AVS_SCART_PIN8_SET"); - if (ioctl(avsfd, IOC_AVS_ROUTE_ENC2TV) < 0) - perror("IOC_AVS_ROUTE_ENC2TV"); close(avsfd); } From 729206b5c573ae1c75e4e0e787a5a525dd791213 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 2 Jan 2011 19:16:12 +0100 Subject: [PATCH 0038/1070] libtriple: improve cPlayback() * avoid race conditions by using a mutex to protect curr_pos, fixing artefacts during timeshift playback * make GetPosition() cheaper by interpolating end_pts and only fetching the "real" end_pts after the file has grown by 10MB Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/ec2ad396c0a017a80e62d2916fe6d6116e156b73 Author: Stefan Seyfried Date: 2011-01-02 (Sun, 02 Jan 2011) Origin message was: ------------------ libtriple: improve cPlayback() * avoid race conditions by using a mutex to protect curr_pos, fixing artefacts during timeshift playback * make GetPosition() cheaper by interpolating end_pts and only fetching the "real" end_pts after the file has grown by 10MB ------------------ This commit was generated by Migit --- lib/libtriple/playback_td.cpp | 55 +++++++++++++++++++++++++++-------- lib/libtriple/playback_td.h | 1 + 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/lib/libtriple/playback_td.cpp b/lib/libtriple/playback_td.cpp index 066f66199..90e62e6c3 100644 --- a/lib/libtriple/playback_td.cpp +++ b/lib/libtriple/playback_td.cpp @@ -10,6 +10,7 @@ #include "dmx_td.h" #include "audio_td.h" #include "video_td.h" +#include "lt_debug.h" #include #define DVR "/dev/" DEVICE_NAME_PVR @@ -30,6 +31,8 @@ static void playthread_cleanup_handler(void *); 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 int dvrfd = -1; static int streamtype; @@ -77,6 +80,7 @@ bool cPlayback::Open(playmode_t mode) filetype = FILETYPE_TS; playback_speed = 0; last_size = 0; + _pts_end = 0; numpida = 0; memset(&apids, 0, sizeof(apids)); memset(&ac3flags, 0, sizeof(ac3flags)); @@ -441,11 +445,16 @@ bool cPlayback::GetPosition(int &position, int &duration) if (filetype == FILETYPE_TS && filelist.size() == 1) { off_t tmppos = currsize - PESBUF_SIZE; - if (currsize != last_size && tmppos > 0) + if (currsize > last_size && (currsize - last_size) < 10485760 && + bytes_per_second > 0 && _pts_end > 0) { - update = true; - /* file size has changed => update endpts */ - last_size = currsize; + /* guess the current endpts... */ + tmppts = (currsize - last_size) * 90000 / bytes_per_second; + pts_end = _pts_end + tmppts; + } + else if (currsize != last_size && tmppos > 0) + { + pthread_mutex_lock(&currpos_mutex); off_t oldpos = curr_pos; ssize_t n, r; int s; @@ -462,11 +471,16 @@ bool cPlayback::GetPosition(int &position, int &duration) { DBG("n: %d s: %d endpts %lld size: %lld\n", n, s, tmppts, currsize); pts_end = tmppts; + _pts_end = tmppts; + update = true; + /* file size has changed => update endpts */ + last_size = currsize; break; } } } mf_lseek(oldpos); + pthread_mutex_unlock(&currpos_mutex); } } if (pts_end != -1 && pts_start > pts_end) /* should trigger only once ;) */ @@ -480,10 +494,11 @@ bool cPlayback::GetPosition(int &position, int &duration) { position = tmppts / 90; duration = (pts_end - pts_start) / 90; - if (update && duration >= 1000) + if (update && duration >= 4000) { bytes_per_second = currsize / (duration / 1000); - INFO("updated bps: %lld size: %lld duration %d\n", bytes_per_second, currsize, duration); + lt_debug("cPlayback:%s: updated bps: %lld size: %lld duration %d\n", + __FUNCTION__, bytes_per_second, currsize, duration); } return true; } @@ -786,6 +801,7 @@ ssize_t cPlayback::read_ts() int n, skipped = 0; bool skip = false; bool eof = true; + pthread_mutex_lock(&currpos_mutex); while (toread > 0) { ssize_t done = 0; @@ -801,6 +817,7 @@ ssize_t cPlayback::read_ts() if (ret < 0) { INFO("failed: %m\n"); + pthread_mutex_unlock(&currpos_mutex); return ret; } if (ret == 0 && eof) @@ -815,6 +832,7 @@ ssize_t cPlayback::read_ts() INFO("out of sync: %d\n", sync); if (sync < 0) { + pthread_mutex_unlock(&currpos_mutex); return -1; } memmove(pesbuf, pesbuf + sync, ret - sync); @@ -861,11 +879,13 @@ ssize_t cPlayback::read_ts() } } out: + pthread_mutex_unlock(&currpos_mutex); if (eof) return 0; } else { + pthread_mutex_lock(&currpos_mutex); while(true) { ret = read(in_fd, inbuf + inbuf_pos, toread); @@ -877,15 +897,16 @@ ssize_t cPlayback::read_ts() } break; } - if (ret < 0) + if (ret <= 0) { - INFO("failed: %m\n"); + pthread_mutex_unlock(&currpos_mutex); + if (ret < 0) + INFO("failed: %m\n"); return ret; } - if (ret == 0) - return ret; inbuf_pos += ret; curr_pos += ret; + pthread_mutex_unlock(&currpos_mutex); sync = sync_ts(inbuf + inbuf_sync, INBUF_SIZE - inbuf_sync); if (sync < 0) @@ -1002,6 +1023,7 @@ ssize_t cPlayback::read_mpeg() INFO("adjusting toread to %d due to inbuf full (old: %zd)\n", INBUF_SIZE - inbuf_pos, toread); toread = INBUF_SIZE - inbuf_pos; } + pthread_mutex_lock(&currpos_mutex); while(true) { ret = read(in_fd, pesbuf + pesbuf_pos, toread); @@ -1015,11 +1037,13 @@ ssize_t cPlayback::read_mpeg() } if (ret < 0) { + pthread_mutex_unlock(&currpos_mutex); INFO("failed: %m, pesbuf_pos: %zd, toread: %zd\n", pesbuf_pos, toread); return ret; } pesbuf_pos += ret; curr_pos += ret; + pthread_mutex_unlock(&currpos_mutex); int i; int count = 0; @@ -1232,6 +1256,7 @@ off_t cPlayback::mp_seekSync(off_t pos) off_t ret; uint8_t pkt[1024]; + pthread_mutex_lock(&currpos_mutex); ret = mf_lseek(npos); if (ret < 0) INFO("lseek ret < 0 (%m)\n"); @@ -1277,6 +1302,7 @@ off_t cPlayback::mp_seekSync(off_t pos) npos += s; INFO("sync after %lld\n", npos - pos); ret = mf_lseek(npos); + pthread_mutex_unlock(&currpos_mutex); if (ret < 0) INFO("lseek ret < 0 (%m)\n"); return ret; @@ -1285,7 +1311,9 @@ off_t cPlayback::mp_seekSync(off_t pos) break; } INFO("could not sync to PES offset: %d r: %zd\n", offset, r); - return mf_lseek(pos); + ret = mf_lseek(pos); + pthread_mutex_unlock(&currpos_mutex); + return ret; } /* TODO: use bigger buffer here, too and handle EOF / next splitfile */ @@ -1301,6 +1329,7 @@ off_t cPlayback::mp_seekSync(off_t pos) if(pkt[188-1] == 0x47) { ret = mf_lseek(npos - 1); // assume sync ok + pthread_mutex_unlock(&currpos_mutex); if (ret < 0) INFO("lseek ret < 0 (%m)\n"); return ret; @@ -1320,7 +1349,9 @@ off_t cPlayback::mp_seekSync(off_t pos) } //-- on error stay on actual position -- - return mf_lseek(pos); + ret = mf_lseek(pos); + pthread_mutex_unlock(&currpos_mutex); + return ret; } static int sync_ts(uint8_t *p, int len) diff --git a/lib/libtriple/playback_td.h b/lib/libtriple/playback_td.h index 0ebd45b2e..b6e30f11e 100644 --- a/lib/libtriple/playback_td.h +++ b/lib/libtriple/playback_td.h @@ -77,6 +77,7 @@ class cPlayback int64_t pts_start; int64_t pts_end; + int64_t _pts_end; /* last good endpts */ int64_t pts_curr; int64_t get_pts(uint8_t *p, bool pes, int bufsize); From 50fede66bdc32f07c09c4eedd6976052d578d6a4 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 26 Jan 2011 21:03:08 +0100 Subject: [PATCH 0039/1070] neutrino: port "EPG title in LCD" from tuxbox Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/a99ff05934ce7482b1e16dd559b91efcef424f26 Author: Stefan Seyfried Date: 2011-01-26 (Wed, 26 Jan 2011) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/daemonc/remotecontrol.cpp | 2 +- src/driver/vfd.h | 1 + src/gui/channellist.cpp | 4 ++++ src/gui/infoviewer.cpp | 43 +++++++++++++++++++++++++++++++++++ 4 files changed, 49 insertions(+), 1 deletion(-) diff --git a/src/daemonc/remotecontrol.cpp b/src/daemonc/remotecontrol.cpp index 3399d7b0b..5e38188ec 100644 --- a/src/daemonc/remotecontrol.cpp +++ b/src/daemonc/remotecontrol.cpp @@ -203,7 +203,7 @@ int CRemoteControl::handleMsg(const neutrino_msg_t msg, neutrino_msg_data_t data { //printf("[neutrino] channel match\n"); //CURRENT-EPG fr den aktuellen Kanal bekommen!; - + CVFD::getInstance()->setEPGTitle(info_CN->current_name); if ( info_CN->current_uniqueKey != current_EPGid ) { //printf("[neutrino] info_CN->current_uniqueKey != current_EPGid\n"); diff --git a/src/driver/vfd.h b/src/driver/vfd.h index 4bbe70e60..2fb7b6ad8 100644 --- a/src/driver/vfd.h +++ b/src/driver/vfd.h @@ -110,6 +110,7 @@ class CVFD void setMode(const MODES m, const char * const title = ""); void showServicename(const std::string & name); // UTF-8 + void setEPGTitle(const std::string) { return; }; void showTime(bool force = false); /** blocks for duration seconds */ void showRCLock(int duration = 2); diff --git a/src/gui/channellist.cpp b/src/gui/channellist.cpp index 9bf59ec4c..9cf2048a0 100644 --- a/src/gui/channellist.cpp +++ b/src/gui/channellist.cpp @@ -1189,6 +1189,8 @@ void CChannelList::zapTo(int pos, bool /* forceStoreToLastChannels */) } tuned = pos; + CVFD::getInstance()->setEPGTitle(""); + CVFD::getInstance()->showServicename(chan->name); g_RemoteControl->zapTo_ChannelID(chan->channel_id, chan->name, !chan->bAlwaysLocked); // UTF-8 // TODO check is it possible bouquetList is NULL ? if (bouquetList != NULL) { @@ -1226,6 +1228,8 @@ void CChannelList::NewZap(t_channel_id channel_id) printf("**************************** CChannelList::NewZap me %p %s tuned %d new %s -> %llx\n", this, name.c_str(), tuned, chan->name.c_str(), chan->channel_id); if(selected_chid != chan->getChannelID()) { + CVFD::getInstance()->setEPGTitle(""); + CVFD::getInstance()->showServicename(chan->name); selected_chid = chan->getChannelID(); g_RemoteControl->zapTo_ChannelID(chan->getChannelID(), chan->name, !chan->bAlwaysLocked); /* remove recordModeActive from infobar */ diff --git a/src/gui/infoviewer.cpp b/src/gui/infoviewer.cpp index a77f767b4..5a58ce14e 100644 --- a/src/gui/infoviewer.cpp +++ b/src/gui/infoviewer.cpp @@ -1425,6 +1425,8 @@ int CInfoViewer::handleMsg (const neutrino_msg_t msg, neutrino_msg_data_t data) show_Data (true); } showLcdPercentOver (); + eventname = info_CurrentNext.current_name; + CVFD::getInstance()->setEPGTitle(eventname); return messages_return::handled; } else if (msg == NeutrinoMessages::EVT_ZAP_SUB_FAILED) { chanready = 1; @@ -2133,6 +2135,46 @@ int CInfoViewer::showChannelLogo(const t_channel_id logo_channel_id, const int c return res; } +#if HAVE_TRIPLEDRAGON +/* the cheap COOLSTREAM display cannot do this, so keep the routines separate */ +void CInfoViewer::showLcdPercentOver() +{ + if (g_settings.lcd_setting[SNeutrinoSettings::LCD_SHOW_VOLUME] != 1) + { + if (fileplay || NeutrinoMessages::mode_ts == CNeutrinoApp::getInstance()->getMode()) { + CVFD::getInstance()->showPercentOver(CMoviePlayerGui::getInstance().file_prozent); + return; + } + static long long old_interval = 0; + int runningPercent = -1; + time_t jetzt = time(NULL); + long long interval = 60000000; /* 60 seconds default update time */ + if (info_CurrentNext.flags & CSectionsdClient::epgflags::has_current) { + if (jetzt < info_CurrentNext.current_zeit.startzeit) + runningPercent = 0; + else if (jetzt > (int)(info_CurrentNext.current_zeit.startzeit + + info_CurrentNext.current_zeit.dauer)) + runningPercent = -2; /* overtime */ + else { + runningPercent = MIN((jetzt-info_CurrentNext.current_zeit.startzeit) * 100 / + info_CurrentNext.current_zeit.dauer, 100); + interval = info_CurrentNext.current_zeit.dauer * 1000LL * (1000/100); // update every percent + if (is_visible && interval > 60000000) // if infobar visible, update at + interval = 60000000; // least once per minute (radio mode) + if (interval < 5000000) + interval = 5000000; // but update only every 5 seconds + } + } + if (interval != old_interval) { + g_RCInput->killTimer(lcdUpdateTimer); + lcdUpdateTimer = g_RCInput->addTimer(interval, false); + //printf("lcdUpdateTimer: interval %lld old %lld\n",interval/1000000,old_interval/1000000); + old_interval = interval; + } + CLCD::getInstance()->showPercentOver(runningPercent); + } +} +#else void CInfoViewer::showLcdPercentOver () { if (g_settings.lcd_setting[SNeutrinoSettings::LCD_SHOW_VOLUME] != 1) { @@ -2156,6 +2198,7 @@ void CInfoViewer::showLcdPercentOver () CVFD::getInstance ()->showPercentOver (runningPercent); } } +#endif void CInfoViewer::showEpgInfo() //message on event change { From 82bae5cc25974f401f010bc4d54c24be8f10d8ff Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 5 Feb 2011 11:52:14 +0100 Subject: [PATCH 0040/1070] libtriple: remember the filedescriptor belonging to each pid in cDemux() Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/bb78f6d4eb3a5cf648d1f99b32a490dc41c8bbe0 Author: Stefan Seyfried Date: 2011-02-05 (Sat, 05 Feb 2011) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/dmx_td.cpp | 35 ++++++++++++++++++----------------- lib/libtriple/dmx_td.h | 8 +++++++- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/lib/libtriple/dmx_td.cpp b/lib/libtriple/dmx_td.cpp index 5e6474e78..6fbe96bef 100644 --- a/lib/libtriple/dmx_td.cpp +++ b/lib/libtriple/dmx_td.cpp @@ -102,12 +102,12 @@ void cDemux::Close(void) return; } - for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) + for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) { - lt_debug("cDemux::Close: stopping and closing demux fd %d\n", *i); - if (ioctl(*i, DEMUX_STOP) < 0) + lt_debug("cDemux::Close: stopping and closing demux fd %d pid 0x%04x\n", (*i).fd, (*i).pid); + if (ioctl((*i).fd, DEMUX_STOP) < 0) perror("DEMUX_STOP"); - if (close(*i) < 0) + if (close((*i).fd) < 0) perror("close"); } pesfds.clear(); @@ -124,10 +124,10 @@ bool cDemux::Start(void) return false; } - for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) + for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) { - lt_debug("cDemux::Start: starting demux fd %d\n", *i); - if (ioctl(*i, DEMUX_START) < 0) + lt_debug("cDemux::Start: starting demux fd %d pid 0x%04x\n", (*i).fd, (*i).pid); + if (ioctl((*i).fd, DEMUX_START) < 0) perror("DEMUX_START"); } ioctl(fd, DEMUX_START); @@ -141,10 +141,10 @@ bool cDemux::Stop(void) fprintf(stderr, "cDemux::%s #%d: not open!\n", __FUNCTION__, num); return false; } - for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) + for (std::vector::const_iterator i = pesfds.begin(); i != pesfds.end(); ++i) { - lt_debug("cDemux::Stop: stopping demux fd %d\n", *i); - if (ioctl(*i, DEMUX_STOP) < 0) + lt_debug("cDemux::Stop: stopping demux fd %d pid 0x%04x\n", (*i).fd, (*i).pid); + if (ioctl((*i).fd, DEMUX_STOP) < 0) perror("DEMUX_STOP"); } ioctl(fd, DEMUX_STOP); @@ -381,7 +381,7 @@ void *cDemux::getChannel() void cDemux::addPid(unsigned short Pid) { - int pfd; + pes_pids pfd; int ret; struct demux_pes_para p; if (dmx_type != DMX_TP_CHANNEL) @@ -391,8 +391,8 @@ void cDemux::addPid(unsigned short Pid) } if (fd == -1) fprintf(stderr, "cDemux::%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid); - pfd = open(devname[num], O_RDWR); - if (pfd < 0) + pfd.fd = open(devname[num], O_RDWR); + if (pfd.fd < 0) { fprintf(stderr, "cDemux::%s #%d Pid = %hx open failed (%m)\n", __FUNCTION__, num, Pid); return; @@ -406,22 +406,23 @@ void cDemux::addPid(unsigned short Pid) p.unloader.unloader_type = UNLOADER_TYPE_BUCKET; p.unloader.threshold = 128; - ioctl(pfd, DEMUX_SELECT_SOURCE, INPUT_FROM_CHANNEL0); - ret = ioctl(pfd, DEMUX_SET_BUFFER_SIZE, 0x10000); // 64k + ioctl(pfd.fd, DEMUX_SELECT_SOURCE, INPUT_FROM_CHANNEL0); + ret = ioctl(pfd.fd, DEMUX_SET_BUFFER_SIZE, 0x10000); // 64k if (ret == -1) perror("DEMUX_SET_BUFFER_SIZE"); else { - ret = ioctl(pfd, DEMUX_FILTER_PES_SET, &p); + ret = ioctl(pfd.fd, DEMUX_FILTER_PES_SET, &p); if (ret == -1) perror("DEMUX_FILTER_PES_SET"); } + pfd.pid = Pid; if (ret != -1) /* success! */ pesfds.push_back(pfd); else /* error! */ - close(pfd); + close(pfd.fd); return; } diff --git a/lib/libtriple/dmx_td.h b/lib/libtriple/dmx_td.h index f36758684..db2a61927 100644 --- a/lib/libtriple/dmx_td.h +++ b/lib/libtriple/dmx_td.h @@ -23,6 +23,12 @@ typedef enum DMX_PCR_ONLY_CHANNEL } DMX_CHANNEL_TYPE; +typedef struct +{ + int fd; + unsigned short pid; +} pes_pids; + class cDemux { private: @@ -30,7 +36,7 @@ class cDemux int fd; int buffersize; DMX_CHANNEL_TYPE dmx_type; - std::vector pesfds; + std::vector pesfds; public: bool Open(DMX_CHANNEL_TYPE pes_type, void * x = NULL, int y = 0); From 0271b55ee858a53e5c7247d8085fe55b9ff43456 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 5 Feb 2011 11:54:04 +0100 Subject: [PATCH 0041/1070] libtriple: add getPesPids() and removePid() to cDemux Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/7ff71707c0c05b3990aa26f1987e8b0ce1f4cf46 Author: Stefan Seyfried Date: 2011-02-05 (Sat, 05 Feb 2011) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/dmx_td.cpp | 22 ++++++++++++++++++++++ lib/libtriple/dmx_td.h | 5 ++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/lib/libtriple/dmx_td.cpp b/lib/libtriple/dmx_td.cpp index 6fbe96bef..3f72b1724 100644 --- a/lib/libtriple/dmx_td.cpp +++ b/lib/libtriple/dmx_td.cpp @@ -426,6 +426,28 @@ void cDemux::addPid(unsigned short Pid) return; } +void cDemux::removePid(unsigned short Pid) +{ + if (dmx_type != DMX_TP_CHANNEL) + { + fprintf(stderr, "cDemux::%s pes_type!=DMX_TP_CHANNEL (%s) not implemented yet! pid=%hx\n", __FUNCTION__, DMX_T[dmx_type], Pid); + return; + } + for (std::vector::iterator i = pesfds.begin(); i != pesfds.end(); ++i) + { + if ((*i).pid == Pid) { + lt_debug("cDemux::removePid: removing demux fd %d pid 0x%04x\n", (*i).fd, Pid); + if (ioctl((*i).fd, DEMUX_STOP) < 0) + perror("DEMUX_STOP"); + if (close((*i).fd) < 0) + perror("close"); + pesfds.erase(i); + return; /* TODO: what if the same PID is there multiple times */ + } + } + fprintf(stderr, "cDemux::removePid: pid 0x%04x not found\n", Pid); +} + void cDemux::getSTC(int64_t * STC) { lt_debug("cDemux::%s #%d\n", __FUNCTION__, num); diff --git a/lib/libtriple/dmx_td.h b/lib/libtriple/dmx_td.h index db2a61927..368f04c14 100644 --- a/lib/libtriple/dmx_td.h +++ b/lib/libtriple/dmx_td.h @@ -54,7 +54,10 @@ class cDemux void addPid(unsigned short pid); void getSTC(int64_t * STC); int getUnit(void); - int getFD(void) { return fd; }; /* needed by cPlayback class */ + // TD only functions + int getFD(void) { return fd; }; /* needed by cPlayback class */ + void removePid(unsigned short Pid); /* needed by cRecord class */ + std::vector getPesPids(void) { return pesfds; }; // cDemux(int num = 0); ~cDemux(); From f67eaf6a4fdd0efbfc7bacba93088117cd39f965 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 5 Feb 2011 11:55:51 +0100 Subject: [PATCH 0042/1070] libtriple: add ChangePids() to cRecord This is pretty much untested for now, handle with care! Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/d812673a4e45c27ba7865147d831b4e4e3ae5545 Author: Stefan Seyfried Date: 2011-02-05 (Sat, 05 Feb 2011) ------------------ This commit was generated by Migit --- lib/libtriple/record_td.cpp | 39 +++++++++++++++++++++++++++++++++++++ lib/libtriple/record_td.h | 1 + 2 files changed, 40 insertions(+) diff --git a/lib/libtriple/record_td.cpp b/lib/libtriple/record_td.cpp index 1ab9ed70a..69ae5510b 100644 --- a/lib/libtriple/record_td.cpp +++ b/lib/libtriple/record_td.cpp @@ -119,6 +119,45 @@ bool cRecord::Stop(void) return true; } +bool cRecord::ChangePids(unsigned short /*vpid*/, unsigned short *apids, int numapids) +{ + std::vector pids; + int j; + bool found; + unsigned short pid; + INFO("\n"); + if (!dmx) { + INFO("DMX = NULL\n"); + return false; + } + pids = dmx->getPesPids(); + /* the first PID is the video pid, so start with the second PID... */ + for (std::vector::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) { + found = false; + pid = (*i).pid; + for (j = 0; j < numapids; j++) { + if (pid == apids[j]) { + found = true; + break; + } + } + if (!found) + dmx->removePid(pid); + } + for (j = 0; j < numapids; j++) { + found = false; + for (std::vector::const_iterator i = pids.begin() + 1; i != pids.end(); ++i) { + if ((*i).pid == apids[j]) { + found = true; + break; + } + } + if (!found) + dmx->addPid(apids[j]); + } + return true; +} + void cRecord::RecordThread() { INFO("begin\n"); diff --git a/lib/libtriple/record_td.h b/lib/libtriple/record_td.h index 3ee61c317..fc1261f98 100644 --- a/lib/libtriple/record_td.h +++ b/lib/libtriple/record_td.h @@ -28,6 +28,7 @@ class cRecord bool Open(int numpids); bool Start(int fd, unsigned short vpid, unsigned short *apids, int numpids); bool Stop(void); + bool ChangePids(unsigned short vpid, unsigned short *apids, int numapids); void RecordThread(); #if 0 From 16fa06d9cb4d11c25028ae29a2fa1ef2cea4dcc5 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 5 Feb 2011 16:02:34 +0100 Subject: [PATCH 0043/1070] libtriple: implement PCM playback in cAudio() Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/6eae455676a31458f160a91366a82a16afc921f6 Author: Stefan Seyfried Date: 2011-02-05 (Sat, 05 Feb 2011) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- lib/libtriple/audio_td.cpp | 57 ++++++++++++++++++++++++++++++++++---- lib/libtriple/audio_td.h | 2 ++ 2 files changed, 54 insertions(+), 5 deletions(-) diff --git a/lib/libtriple/audio_td.cpp b/lib/libtriple/audio_td.cpp index 49cf07db2..e3ce4edbb 100644 --- a/lib/libtriple/audio_td.cpp +++ b/lib/libtriple/audio_td.cpp @@ -10,11 +10,14 @@ #include "audio_td.h" #include "lt_debug.h" +#include + cAudio * audioDecoder = NULL; cAudio::cAudio(void *, void *, void *) { fd = -1; + clipfd = -1; openDevice(); Muted = false; } @@ -40,6 +43,9 @@ void cAudio::closeDevice(void) if (fd >= 0) close(fd); fd = -1; + if (clipfd >= 0) + close(clipfd); + clipfd = -1; } int cAudio::do_mute(bool enable, bool remember) @@ -152,21 +158,62 @@ int cAudio::setChannel(int /*channel*/) return 0; }; -int cAudio::PrepareClipPlay(int /*uNoOfChannels*/, int /*uSampleRate*/, int /*uBitsPerSample*/, int /*bLittleEndian*/) +int cAudio::PrepareClipPlay(int ch, int srate, int bits, int little_endian) { - lt_debug("cAudio::%s\n", __FUNCTION__); + int fmt; + lt_debug("cAudio::%s ch %d srate %d bits %d le %d\n", __FUNCTION__, ch, srate, bits, little_endian); + if (clipfd >= 0) { + fprintf(stderr, "cAudio::%s: clipfd already opened (%d)\n", __FUNCTION__, clipfd); + return -1; + } + /* the dsp driver seems to work only on the second open(). really. */ + clipfd = open("/dev/sound/dsp", O_WRONLY); + close(clipfd); + clipfd = open("/dev/sound/dsp", O_WRONLY); + if (clipfd < 0) { + perror("cAudio::PrepareClipPlay open /dev/sound/dsp"); + return -1; + } + /* no idea if we ever get little_endian == 0 */ + if (little_endian) + fmt = AFMT_S16_BE; + else + fmt = AFMT_S16_LE; + if (ioctl(clipfd, SNDCTL_DSP_SETFMT, &fmt)) + perror("SNDCTL_DSP_SETFMT"); + if (ioctl(clipfd, SNDCTL_DSP_CHANNELS, &ch)) + perror("SNDCTL_DSP_CHANNELS"); + if (ioctl(clipfd, SNDCTL_DSP_SPEED, &srate)) + perror("SNDCTL_DSP_SPEED"); + if (ioctl(clipfd, SNDCTL_DSP_RESET)) + perror("SNDCTL_DSP_RESET"); + return 0; }; -int cAudio::WriteClip(unsigned char * /*buffer*/, int /*size*/) +int cAudio::WriteClip(unsigned char *buffer, int size) { - lt_debug("cAudio::%s\n", __FUNCTION__); - return 0; + int ret; + // lt_debug("cAudio::%s\n", __FUNCTION__); + if (clipfd <= 0) { + fprintf(stderr, "cAudio::%s: clipfd not yet opened\n", __FUNCTION__); + return -1; + } + ret = write(clipfd, buffer, size); + if (ret < 0) + fprintf(stderr, "cAudio::%s: write error (%m)\n", __FUNCTION__); + return ret; }; int cAudio::StopClip() { lt_debug("cAudio::%s\n", __FUNCTION__); + if (clipfd <= 0) { + fprintf(stderr, "cAudio::%s: clipfd not yet opened\n", __FUNCTION__); + return -1; + } + close(clipfd); + clipfd = -1; return 0; }; diff --git a/lib/libtriple/audio_td.h b/lib/libtriple/audio_td.h index 7178ecfb9..d59fb7c1a 100644 --- a/lib/libtriple/audio_td.h +++ b/lib/libtriple/audio_td.h @@ -36,6 +36,8 @@ class cAudio int fd; bool Muted; + int clipfd; /* for pcm playback */ + AUDIO_FORMAT StreamType; AUDIO_SYNC_MODE SyncMode; bool started; From 35cd176265ec9ac5ca1c186b7db8f20bcbd0fd6f Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 6 Feb 2011 01:39:54 +0100 Subject: [PATCH 0044/1070] neutrino: add rcsim Origin commit data ------------------ Branch: ni/coolstream Commit: https://github.com/neutrino-images/ni-neutrino/commit/716b1c96b938de8562a65bd7082741c5f1ccd3a3 Author: Stefan Seyfried Date: 2011-02-06 (Sun, 06 Feb 2011) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- src/Makefile.am | 4 +- src/create_rcsim_h.sh | 56 ++++++++++ src/rcsim.c | 246 ++++++++++++++++++++++++++++++++++++++++++ src/rcsim.h | 174 ++++++++++++++++++++++++++++++ 4 files changed, 479 insertions(+), 1 deletion(-) create mode 100644 src/create_rcsim_h.sh create mode 100644 src/rcsim.c create mode 100644 src/rcsim.h diff --git a/src/Makefile.am b/src/Makefile.am index 3f3d13361..b2efb30f7 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -30,10 +30,12 @@ else VORBISLIBS = -lvorbisfile -lvorbis -logg endif -bin_PROGRAMS = neutrino +bin_PROGRAMS = neutrino rcsim neutrino_SOURCES = neutrino_menue.cpp neutrino.cpp +rcsim_SOURCES = rcsim.c rcsim.h + AM_CPPFLAGS = if ENABLE_FLAC diff --git a/src/create_rcsim_h.sh b/src/create_rcsim_h.sh new file mode 100644 index 000000000..90bcab10e --- /dev/null +++ b/src/create_rcsim_h.sh @@ -0,0 +1,56 @@ +#!/bin/sh +# +# create a rcsim.h file from the rcinput header +# (C) 2011 Stefan Seyfried +# License: GPL v2 +# +# usage: sh ./create_rcsim_h.sh > rcsim.h + +cat << EOF +#ifndef KEY_GAMES +#define KEY_GAMES 0x1a1 /* Media Select Games */ +#endif + +#ifndef KEY_TOPLEFT +#define KEY_TOPLEFT 0x1a2 +#endif + +#ifndef KEY_TOPRIGHT +#define KEY_TOPRIGHT 0x1a3 +#endif + +#ifndef KEY_BOTTOMLEFT +#define KEY_BOTTOMLEFT 0x1a4 +#endif + +#ifndef KEY_BOTTOMRIGHT +#define KEY_BOTTOMRIGHT 0x1a5 +#endif + +#define KEY_POWERON KEY_FN_F1 +#define KEY_POWEROFF KEY_FN_F2 +#define KEY_STANDBYON KEY_FN_F3 +#define KEY_STANDBYOFF KEY_FN_F4 +#define KEY_MUTEON KEY_FN_F5 +#define KEY_MUTEOFF KEY_FN_F6 +#define KEY_ANALOGON KEY_FN_F7 +#define KEY_ANALOGOFF KEY_FN_F8 + +enum { +EOF +sed -n '/^[[:space:]]*RC_0/,/^[[:space:]]*RC_analog_off/s/^[[:space:]]*/ /p' driver/rcinput.h +cat << EOF +}; + +struct key{ + char *name; + unsigned long code; +}; + +static const struct key keyname[] = { +EOF +sed -n '/^[[:space:]]*RC_0/,/^[[:space:]]*RC_analog_off/ s/^.*=[[:space:]]*\(KEY_.*\),.*/ { "\1", \1 },/p' driver/rcinput.h +cat << EOF +}; + +EOF diff --git a/src/rcsim.c b/src/rcsim.c new file mode 100644 index 000000000..841cdf083 --- /dev/null +++ b/src/rcsim.c @@ -0,0 +1,246 @@ +/****************************************************************************** + * rcsim - rcsim.c + * + * simulates the remote control, sends the requested key + * + * (c) 2003 Carsten Juttner (carjay@gmx.net) + * (c) 2009 Stefan Seyfried, add code to use the neutrino socket instead + * of the input subsystem for dreambox / tripledragon + * (c) 2011 Stefan Seyfried, convert driver/rcinput.h via script to + * rcsim.h for automated import of new keys + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * The Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, 51 Franklin Street, Fifth Floor Boston, MA 02110-1301, USA. + * + ******************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* if you want use HAVE_XX_HARDWARE, better include config.h :-) */ +#include "config.h" + +#ifdef HAVE_DBOX_HARDWARE +#define EVENTDEV "/dev/input/event0" +#else +/* dreambox and tripledragon do not use a "normal" input device, so we cannot + (ab-)use the event repeating function of it. use the neutrino socket instead. */ +#include +#include +#define NEUTRINO_SOCKET "/tmp/neutrino.sock" + +/* those structs / values are stolen from libeventserver */ +struct eventHead +{ + unsigned int eventID; + unsigned int initiatorID; + unsigned int dataSize; +}; + +enum initiators +{ + INITID_CONTROLD, + INITID_SECTIONSD, + INITID_ZAPIT, + INITID_TIMERD, + INITID_HTTPD, + INITID_NEUTRINO, + INITID_GENERIC_INPUT_EVENT_PROVIDER +}; +#endif + +enum { // not defined in input.h but used like that, at least in 2.4.22 + KEY_RELEASED = 0, + KEY_PRESSED, + KEY_AUTOREPEAT +}; + +#include "rcsim.h" + +void usage(char *n){ + unsigned int keynum = sizeof(keyname)/sizeof(struct key); + unsigned int i; + printf ("rcsim v1.1\nUsage: %s [