From 824c35104fef735d5d45eab4c38e2dfd074e6a15 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 11 Nov 2012 16:53:18 +0100 Subject: [PATCH 01/14] add pic2m2v for bulk-creating the still-mpegs Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/1466524bc512b23f924983f9c9e58b3779a757b1 Author: Stefan Seyfried Date: 2012-11-11 (Sun, 11 Nov 2012) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- tools/Makefile.am | 3 ++ tools/pic2m2v.c | 85 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 88 insertions(+) create mode 100644 tools/pic2m2v.c diff --git a/tools/Makefile.am b/tools/Makefile.am index 3e83dba..5ee4d5b 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -4,3 +4,6 @@ if BOXTYPE_SPARK bin_PROGRAMS += spark_fp spark_fp_SOURCES = spark_fp.c endif + +bin_PROGRAMS += pic2m2v +pic2m2v_SOURCES = pic2m2v.c diff --git a/tools/pic2m2v.c b/tools/pic2m2v.c new file mode 100644 index 0000000..d99ddc1 --- /dev/null +++ b/tools/pic2m2v.c @@ -0,0 +1,85 @@ +/* + * (C) 2012 Stefan Seyfried + * + * 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, see . + */ + +#ifdef HAVE_CONFIG_H +#include +#endif +#include +#include +#include +#include +#include +#include + +#if HAVE_TRIPLEDRAGON +#define TARGETRES "704x576" +#else +#define TARGETRES "1280x720" +#endif + +int main(int argc, char **argv) +{ + char destname[512]; + char cmd[512]; + char *p; + char *fname; + struct stat st, st2; + + if (argc < 2) + { + fprintf(stderr, "usage: pic2m2v /path/pic1.jpg [/path/pic2.jpg...]\n\n"); + return 1; + } + strcpy(destname, "/var/cache"); + mkdir(destname, 0755); + argv++; + for (fname = *argv; fname != NULL; fname = *++argv) + { + if (stat(fname, &st2)) + { + fprintf(stderr, "pic2m2v: could not stat '%s' (%m)\n", fname); + continue; + } + strcpy(destname, "/var/cache"); + /* 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... */ + if (stat(destname, &st) || (st.st_mtime != st2.st_mtime) || (st.st_size == 0)) + { + struct utimbuf u; + u.actime = time(NULL); + u.modtime = st2.st_mtime; + printf("converting %s -> %s\n", fname, destname); + /* it does not exist or has a different date, so call ffmpeg... */ + sprintf(cmd, "ffmpeg -v 31 -y -f mjpeg -i '%s' -s %s '%s' Date: Fri, 16 Nov 2012 23:20:27 +0100 Subject: [PATCH 02/14] lt_debug: add HAL_* constants to allow renaming Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/75d4d5021b742aa12d0fe99a1525de71b67c79d5 Author: Stefan Seyfried Date: 2012-11-16 (Fri, 16 Nov 2012) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- common/lt_debug.h | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/common/lt_debug.h b/common/lt_debug.h index 42464b9..296152b 100644 --- a/common/lt_debug.h +++ b/common/lt_debug.h @@ -11,6 +11,16 @@ #define TRIPLE_DEBUG_RECORD 7 #define TRIPLE_DEBUG_ALL ((1<<8)-1) +#define HAL_DEBUG_AUDIO 0 +#define HAL_DEBUG_VIDEO 1 +#define HAL_DEBUG_DEMUX 2 +#define HAL_DEBUG_PLAYBACK 3 +#define HAL_DEBUG_PWRMNGR 4 +#define HAL_DEBUG_INIT 5 +#define HAL_DEBUG_CA 6 +#define HAL_DEBUG_RECORD 7 +#define HAL_DEBUG_ALL ((1<<8)-1) + extern int debuglevel; void _lt_debug(int facility, const void *, const char *fmt, ...) __attribute__ ((format (printf, 3, 4))); From 3795c452c12bc2a8a2ca94cc60741755b61b9cc4 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Fri, 16 Nov 2012 23:42:45 +0100 Subject: [PATCH 03/14] azbox: rework cPlayback rmfp_player wrapper it now actually plays something, but will need more love Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/fea8d10c36689762d09cf0d8ba75dd5932448cae Author: Stefan Seyfried Date: 2012-11-16 (Fri, 16 Nov 2012) ------------------ This commit was generated by Migit --- azbox/playback.cpp | 307 ++++++++++++++++++++++++++++++++++++--------- azbox/playback.h | 4 +- 2 files changed, 250 insertions(+), 61 deletions(-) diff --git a/azbox/playback.cpp b/azbox/playback.cpp index f925e3d..7e1d294 100644 --- a/azbox/playback.cpp +++ b/azbox/playback.cpp @@ -1,15 +1,22 @@ +#include #include #include #include #include #include #include +#include +#include #include +#include +#include + +#include #define FIFO_CMD "/tmp/rmfp.cmd" #define FIFO_IN "/tmp/rmfp.in" #define FIFO_OUT "/tmp/rmfp.out" -#define FIFO_EVENT "/tmp/rmfp.event" +//#define FIFO_EVENT "/tmp/rmfp.event" #include "playback.h" @@ -19,34 +26,110 @@ extern "C"{ static const char * FILENAME = "playback_cs.cpp"; +static bool open_success = false; +static int last_pos; +static time_t last_pos_time; + + +static time_t monotonic_ms(void) +{ + struct timespec t; + time_t ret; + if (clock_gettime(CLOCK_MONOTONIC, &t)) + { + perror("monotonic_ms clock_gettime"); + return -1; + } + ret = ((t.tv_sec + 604800)& 0x01FFFFF) * 1000; /* avoid overflow */ + ret += t.tv_nsec / 1000000; + return ret; +} + +int cPlayback::rmfp_command(int cmd, int param, bool has_param, int reply_len) +{ + char reply[100]; + int ret = -1; + pthread_mutex_lock(&mutex); + dprintf(fd_cmd, "%i", cmd); + if (has_param) + dprintf(fd_in, "%i", param); + if (reply_len > 0) + { + int n = 0; + while (n <= 0) + n = read(fd_out, &reply, 100); + reply[reply_len - 1] = '\0'; + ret = atoi(reply); + } + pthread_mutex_unlock(&mutex); + return ret; +} void cPlayback::RuaThread() { -printf("Starting RUA thread\n"); + printf("Starting RUA thread\n"); + //Watch for the space at the end + std::string base = "rmfp_player -dram 1 -ve 1 -waitexit "; + std::string filename(mfilename); + std::string file = '"' + filename + '"'; + std::string final = base + file; + if (setduration == 1 && mduration != 0) + { + std::stringstream duration; + duration << (mduration * 60000); + final = base + "-duration " + duration.str() + " " + file; + } + pid_t pid = 0; + int master; + pid = forkpty(&master, NULL, NULL, NULL); + if (! pid) { + execl("/bin/sh", "sh", "-c", final.c_str(), (char *)0); + perror("exec"); + exit(0); + } -//Watch for the space at the end -std::string base = "/usr/bin/rmfp_player -dram 1 -ve 1 -waitexit "; -std::string filename(mfilename); -std::string file = '"' + filename + '"'; -std::string final = base + file; + if (pid > 0) { + char *output=NULL; + size_t n = 0; + ssize_t len; + FILE *f = fdopen(master, "r"); + while ((len = getline(&output, &n, f)) != -1) + { + while (len > 0) + { + len--; + if (!isspace(output[len])) + break; + output[len] = '\0'; + } + printf("rmfp: '%s'\n", output); + if (!strcmp(output, "Playback has started...")) + { + fd_cmd = open(FIFO_CMD, O_WRONLY); + fd_in = open(FIFO_IN, O_WRONLY); + playing = true; + printf("===================> playing = true\n"); + } + else if (!strcmp(output, "End of file...")) + { + eof_reached = true; + printf("===================> eof_reached = true\n"); + } + } + fclose(f); + int s; + while (waitpid(pid, &s, WNOHANG) > 0) {}; + if (output) + free(output); + } -if ( setduration == 1 && mduration != 0) -{ - mduration *= 60000; - std::stringstream duration; - duration << mduration; - final = base + "-duration " + duration.str() + " " + file; -} - -system(final.c_str()); - -printf("Terminating RUA thread\n"); -thread_active = 0; -playing = false; -eof_reached = 1; -pthread_exit(NULL); + printf("Terminating RUA thread\n"); + thread_active = 0; + playing = false; + eof_reached = 1; + pthread_exit(NULL); } /* helper function to call the cpp thread loop */ @@ -63,6 +146,7 @@ void* execute_rua_thread(void *c) return NULL; } +#if 0 void cPlayback::EventThread() { @@ -126,12 +210,13 @@ void* execute_event_thread(void *c) { cPlayback *obj=(cPlayback*)c; - printf("Executing RUA Thread\n"); + printf("Executing Event Thread\n"); obj->EventThread(); return NULL; } +#endif //Used by Fileplay bool cPlayback::Open(playmode_t PlayMode) @@ -148,18 +233,44 @@ bool cPlayback::Open(playmode_t PlayMode) setduration = 1; } +#if 0 + while (access("/tmp/continue", R_OK)) + sleep(1); +#endif + + char c[2] = "0"; + int i = 0; + + for(;;) + { + proc_get("/proc/player", c, 2); + if (c[0] != '0') + break; + i++; + if (i > 10) + { + printf("player is not getting idle after 10 seconds!\n"); + open_success = false; + return false; + } + sleep(1); + } + + proc_put("/proc/player", "2", 2); + printf("%s:%s - PlayMode=%s\n", FILENAME, __FUNCTION__, aPLAYMODE[PlayMode]); //Making Fifo's for message pipes mknod(FIFO_CMD, S_IFIFO | 0666, 0); mknod(FIFO_IN, S_IFIFO | 0666, 0); mknod(FIFO_OUT, S_IFIFO | 0666, 0); - mknod(FIFO_EVENT, S_IFIFO | 0666, 0); +// mknod(FIFO_EVENT, S_IFIFO | 0666, 0); //Open pipes we read from. The fd_in pipe will be created once test_rmfp has been started fd_out = open(FIFO_OUT, O_RDONLY | O_NONBLOCK); - fd_event = open(FIFO_EVENT, O_RDONLY | O_NONBLOCK); +// fd_event = open(FIFO_EVENT, O_RDONLY | O_NONBLOCK); + open_success = true; return 0; } @@ -180,6 +291,10 @@ bool cPlayback::Start(char * filename, unsigned short vpid, int vtype, unsigned printf("%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d duration=%i\n", FILENAME, __FUNCTION__, filename, vpid, vtype, apid, ac3, duration); + if (!open_success) + return false; + + eof_reached = 0; //create playback path mAudioStream=0; mfilename = filename; @@ -189,12 +304,15 @@ bool cPlayback::Start(char * filename, unsigned short vpid, int vtype, unsigned printf("[movieplayer]: error creating file_thread! (out of memory?)\n"); ret = false; } +#if 0 if (pthread_create(&event_thread, 0, execute_event_thread, this) != 0) { printf("[movieplayer]: error creating file_thread! (out of memory?)\n"); ret = false; } - +#endif + while (! playing) + sleep(1); return ret; } @@ -204,20 +322,33 @@ bool cPlayback::Stop(void) printf("%s:%s playing %d %d\n", FILENAME, __FUNCTION__, playing, thread_active); if(playing==false && thread_active == 0) return false; - msg = KEY_COMMAND_QUIT_ALL; - dprintf(fd_cmd, "%i", msg); + rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, 0); if (pthread_join(rua_thread, NULL)) { printf("error joining rua thread\n"); } - +#if 0 if (pthread_join(event_thread, NULL)) { printf("error joining event thread\n"); } - +#endif playing = false; + + if (open_success) + proc_put("/proc/player", "1", 2); + usleep(1000000); + + if (fd_in > -1) + close(fd_in); + if (fd_cmd > -1) + close(fd_cmd); + if (fd_out > -1) + close(fd_out); + fd_in = -1; + fd_cmd = -1; + fd_out = -1; return true; } @@ -225,9 +356,7 @@ bool cPlayback::SetAPid(unsigned short pid, bool /*ac3*/) { printf("%s:%s pid %i\n", FILENAME, __FUNCTION__, pid); if (pid != mAudioStream) { - msg = KEY_COMMAND_SWITCH_AUDIO; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", pid); + rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, 0); mAudioStream = pid; } return true; @@ -238,9 +367,12 @@ bool cPlayback::SetSPid(int pid) printf("%s:%s pid %i\n", FILENAME, __FUNCTION__, pid); if(pid!=mSubStream) { + rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, 0); +/* msg = KEY_COMMAND_SWITCH_SUBS; dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", pid); +*/ mSubStream=pid; } return true; @@ -259,19 +391,29 @@ bool cPlayback::SetSpeed(int speed) if (speed > 1 || speed < 0) { + rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, 0); +/* msg = CUSTOM_COMMAND_TRICK_SEEK; dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", speed); +*/ } else if (speed == 0) { + rmfp_command(KEY_COMMAND_PAUSE, 0, false, 0); +/* msg = KEY_COMMAND_PAUSE; dprintf(fd_cmd, "%i", msg); +*/ } else { + rmfp_command(KEY_COMMAND_PLAY, 0, false, 0); +/* msg = KEY_COMMAND_PLAY; dprintf(fd_cmd, "%i", msg); + _GetPosition(); +*/ } // if (result != 0) @@ -290,14 +432,38 @@ bool cPlayback::GetSpeed(int &/*speed*/) const */ return true; } +int cPlayback::__GetPosition(void) +{ + printf("cPlayback::_GetPosition()--->\n"); +#if 0 + struct pollfd pfd; + pfd.fd = fd_out; + pfd.events = POLLIN|POLLPRI; + pfd.revents = 0; + if (poll(&pfd, 1, 0) > 0) + while(read(fd_out, ×tring, 100) <= 0){}; +#endif + last_pos = rmfp_command(CUSTOM_COMMAND_GETPOSITION, 0, false, 11); + last_pos_time = monotonic_ms(); + printf("cPlayback::_GetPosition()<--- %d\n", last_pos); + return last_pos; +} + + // in milliseconds bool cPlayback::GetPosition(int &position, int &duration) { - printf("%s:%s %d %d\n", FILENAME, __FUNCTION__, position, duration); + printf("%s:%s pos %d dur %d play %d\n", FILENAME, __FUNCTION__, position, duration, playing); //Azbox eof if (eof_reached == 1) { + if (setduration) + { + position = mduration; + duration = mduration; + return true; + } position = -5; duration = -5; return true; @@ -305,33 +471,34 @@ bool cPlayback::GetPosition(int &position, int &duration) if(playing==false) return false; - //Position - char timestring[11]; - - msg = CUSTOM_COMMAND_GETPOSITION; - dprintf(fd_cmd, "%i", msg); - - int n = 0; - while ( n <= 0 ) { - n = read(fd_out, ×tring, 100); + if (nPlaybackSpeed == 1 && setduration) { + time_t time_diff = monotonic_ms() - last_pos_time; + position = last_pos + time_diff; + } + else + position = __GetPosition(); + + if (setduration) + { + duration = mduration; + return true; } - timestring[10] = '\0'; - position = atoi(timestring); - //Duration int length; +/* char durationstring[11]; msg = CUSTOM_COMMAND_GETLENGTH; dprintf(fd_cmd, "%i", msg); - n = 0; + int n = 0; while ( n <= 0 ) { n = read(fd_out, &durationstring, 10); } durationstring[10] = '\0'; length = atoi(durationstring); - +*/ + length = rmfp_command(CUSTOM_COMMAND_GETLENGTH, 0, false, 11); if(length <= 0) { duration = duration+1000; } else { @@ -343,35 +510,44 @@ bool cPlayback::GetPosition(int &position, int &duration) bool cPlayback::SetPosition(int position, bool absolute) { - printf("%s:%s %d\n", FILENAME, __FUNCTION__,position); + printf("%s:%s %d playing %d\n", FILENAME, __FUNCTION__,position, playing); if(playing==false) return false; - int seconds; + int seconds = position / 1000;; if (absolute == true) { + rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, 0); +/* msg = KEY_COMMAND_SEEK_TO_TIME; seconds = position / 1000; dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", seconds); +*/ } else { if (position > 0 ) { + rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, 0); +/* msg = CUSTOM_COMMAND_SEEK_RELATIVE_FWD; seconds = position / 1000; dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", seconds); +*/ } else if ( position < 0 ) { + rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, 0); +/* msg = CUSTOM_COMMAND_SEEK_RELATIVE_BWD; seconds = position / 1000; seconds *= -1; printf("sending seconds %i\n", seconds); dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", seconds); +*/ } } return true; @@ -382,18 +558,20 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t printf("%s:%s\n", FILENAME, __FUNCTION__); unsigned int audio_count = 0; - char audio_countstring[3]; +// char audio_countstring[3]; + audio_count = rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, 3); +/* msg = CUSTOM_COMMAND_AUDIO_COUNT; dprintf(fd_cmd, "%i", msg); int n = 0; while ( n <= 0 ) { - n = read(fd_out, &audio_countstring, 2); + n = read(fd_out, &audio_countstring, 2); } audio_countstring[2] = '\0'; audio_count = atoi(audio_countstring); - +*/ *numpida = audio_count; if (audio_count > 0 ) { @@ -401,16 +579,17 @@ void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t { char streamidstring[11]; char audio_lang[21]; - + pthread_mutex_lock(&mutex); msg = CUSTOM_COMMAND_GET_AUDIO_BY_ID; dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", audio_id); - n = 0; + int n = 0; while ( n <= 0 ) { n = read(fd_out, &streamidstring, 10); } read(fd_out, &audio_lang, 20); + pthread_mutex_unlock(&mutex); streamidstring[10] = '\0'; audio_lang[20] = '\0'; @@ -426,6 +605,8 @@ void cPlayback::FindAllSPids(int *spids, uint16_t *numpids, std::string *languag printf("%s:%s\n", FILENAME, __FUNCTION__); unsigned int spu_count = 0; + spu_count = rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, 3); +/* char spu_countstring[3]; msg = CUSTOM_COMMAND_SUBS_COUNT; @@ -437,7 +618,7 @@ void cPlayback::FindAllSPids(int *spids, uint16_t *numpids, std::string *languag } spu_countstring[2] = '\0'; spu_count = atoi(spu_countstring); - +*/ *numpids = spu_count; if (spu_count > 0 ) @@ -448,16 +629,18 @@ void cPlayback::FindAllSPids(int *spids, uint16_t *numpids, std::string *languag //int streamid; char streamidstring[11]; char spu_lang[21]; - + + pthread_mutex_lock(&mutex); msg = CUSTOM_COMMAND_GET_SUB_BY_ID; dprintf(fd_cmd, "%i", msg); dprintf(fd_in, "%i", spu_id); - n = 0; + int n = 0; while ( n <= 0 ) { n = read(fd_out, &streamidstring, 10); } read(fd_out, &spu_lang, 20); + pthread_mutex_unlock(&mutex); streamidstring[10] = '\0'; spu_lang[20] = '\0'; @@ -476,9 +659,13 @@ void cPlayback::FindAllSPids(int *spids, uint16_t *numpids, std::string *languag cPlayback::cPlayback(int /*num*/) { printf("%s:%s\n", FILENAME, __FUNCTION__); - playing=false; + playing = false; thread_active = 0; - eof_reached=0; + eof_reached = 0; + fd_in = -1; + fd_out = -1; + fd_cmd = -1; + pthread_mutex_init(&mutex, NULL); } cPlayback::~cPlayback() diff --git a/azbox/playback.h b/azbox/playback.h index 44498ec..a3acf2b 100644 --- a/azbox/playback.h +++ b/azbox/playback.h @@ -24,7 +24,7 @@ class cPlayback CS_PLAYBACK_PDATA * privateData; pthread_t rua_thread; - pthread_t event_thread; + // pthread_t event_thread; bool enabled; bool paused; @@ -43,6 +43,8 @@ class cPlayback int mduration; playmode_t playMode; + int __GetPosition(void); + int rmfp_command(int cmd, int param, bool has_param, int reply_len); // public: bool Open(playmode_t PlayMode); From e0e06d27c22f1b160573fbf03be527560cc3f952 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 18 Nov 2012 19:29:00 +0100 Subject: [PATCH 04/14] azbox: mostly rewrite cPlayback rmfp_player wrapper * use the file based /tmp/rmfp.{cmd2,in2,out2} interface instead of the previously used FIFOs, this seems more reliable * convert code to lt_debug/lt_info infrastructure Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/af6f6512552e4a6fd732857f557c0d994caa7602 Author: Stefan Seyfried Date: 2012-11-18 (Sun, 18 Nov 2012) Origin message was: ------------------ azbox: mostly rewrite cPlayback rmfp_player wrapper * use the file based /tmp/rmfp.{cmd2,in2,out2} interface instead of the previously used FIFOs, this seems more reliable * convert code to lt_debug/lt_info infrastructure ------------------ This commit was generated by Migit --- azbox/e2mruainclude.h | 2 +- azbox/playback.cpp | 686 ++++++++++++++++-------------------------- azbox/playback.h | 91 +++--- 3 files changed, 288 insertions(+), 491 deletions(-) diff --git a/azbox/e2mruainclude.h b/azbox/e2mruainclude.h index 23c091a..27a1859 100644 --- a/azbox/e2mruainclude.h +++ b/azbox/e2mruainclude.h @@ -80,4 +80,4 @@ EVENT_MSG_EOS, EVENT_MSG_SUB_CHANGED, }; -int fd_cmd, fd_in, fd_out, fd_event, msg; +//int fd_cmd, fd_in, fd_out, fd_event, msg; diff --git a/azbox/playback.cpp b/azbox/playback.cpp index 7e1d294..f7c922e 100644 --- a/azbox/playback.cpp +++ b/azbox/playback.cpp @@ -1,3 +1,30 @@ +/* + * cPlayback implementation for azbox + * this is actually just a wrapper around rmfp_player which does + * all the heavy listing + * + * based on the original aztrino implementation, but almost + * completely rewritten since then + * + * some of the methods and constants were found by stracing the + * AZPlay enigma2 plugin... + * + * (C) 2012 Stefan Seyfried + * + * 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, see . + */ + #include #include #include @@ -11,12 +38,17 @@ #include #include +#include "lt_debug.h" +#define lt_debug(args...) _lt_debug(TRIPLE_DEBUG_PLAYBACK, this, args) +#define lt_info(args...) _lt_info(TRIPLE_DEBUG_PLAYBACK, this, args) +#define lt_info_c(args...) _lt_info(TRIPLE_DEBUG_PLAYBACK, NULL, args) + #include -#define FIFO_CMD "/tmp/rmfp.cmd" -#define FIFO_IN "/tmp/rmfp.in" -#define FIFO_OUT "/tmp/rmfp.out" -//#define FIFO_EVENT "/tmp/rmfp.event" +/* the file-based commands work better than the FIFOs... */ +#define CMD_FILE "/tmp/rmfp.cmd2" +#define IN_FILE "/tmp/rmfp.in2" +#define OUT_FILE "/tmp/rmfp.out2" #include "playback.h" @@ -24,13 +56,8 @@ extern "C"{ #include "e2mruainclude.h" } -static const char * FILENAME = "playback_cs.cpp"; - -static bool open_success = false; -static int last_pos; -static time_t last_pos_time; - - +#if 0 +/* useful for debugging */ static time_t monotonic_ms(void) { struct timespec t; @@ -44,40 +71,90 @@ static time_t monotonic_ms(void) ret += t.tv_nsec / 1000000; return ret; } +#endif -int cPlayback::rmfp_command(int cmd, int param, bool has_param, int reply_len) +/* the mutex makes sure that commands are not interspersed */ +bool cPlayback::rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen) { - char reply[100]; - int ret = -1; - pthread_mutex_lock(&mutex); - dprintf(fd_cmd, "%i", cmd); - if (has_param) - dprintf(fd_in, "%i", param); - if (reply_len > 0) + lt_info("%s: %d %d %d %d\n", __func__, cmd, param, has_param, buflen); + bool ret = true; + int fd; + if (cmd == 222) { - int n = 0; - while (n <= 0) - n = read(fd_out, &reply, 100); - reply[reply_len - 1] = '\0'; - ret = atoi(reply); + if (pthread_mutex_trylock(&rmfp_cmd_mutex)) + return false; } - pthread_mutex_unlock(&mutex); + else + pthread_mutex_lock(&rmfp_cmd_mutex); + unlink(OUT_FILE); + if (has_param) + { + fd = open(IN_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666); + dprintf(fd, "%i", param); + close(fd); + } + fd = open(CMD_FILE, O_WRONLY|O_CREAT|O_TRUNC, 0666); + dprintf(fd, "%i", cmd); + close(fd); + int n = 0, m = 0; + if (buflen > 0) + { + while ((fd = open(OUT_FILE, O_RDONLY)) == -1) { + if (++m > 500) { /* don't wait more than 5 seconds */ + lt_info("%s: timed out waiting for %s (cmd %d par %d buflen %d\n", + __func__, OUT_FILE, cmd, param, buflen); + ret = false; + goto out; + } + usleep(10000); + } + unlink(OUT_FILE); + n = read(fd, buf, buflen); + close(fd); + /* some commands (CUSTOM_COMMAND_GET_AUDIO_BY_ID for example) actually + * return the answer in two successive writes, as we are not using the + * FIFO, we need to make sure that the file is deleted immediately, because + * rmfp_player will not overwrite it if it exists */ + while ((fd = open(OUT_FILE, O_RDONLY)) == -1) { + if (++m > 10) + break; + usleep(1000); + } + if (fd > -1) + { + read(fd, buf + n, buflen - n); + unlink(OUT_FILE); + close(fd); + } + buf[buflen - 1] = '0'; + } + out: + pthread_mutex_unlock(&rmfp_cmd_mutex); + if (cmd != 222) /* called tooo often :-) */ + lt_info("%s: reply: '%s' ret: %d m:%d\n", __func__, buf?buf:"(none)", ret, m); return ret; } -void cPlayback::RuaThread() +/* + * runs the rmfp_player in a terminal + * just doing popen() or similar does not work because then + * the output will be buffered after starting up and we will only + * see "Playback has started..." after the player exits + */ +void cPlayback::run_rmfp() { - printf("Starting RUA thread\n"); + lt_debug("%s: starting\n", __func__); + thread_started = true; //Watch for the space at the end std::string base = "rmfp_player -dram 1 -ve 1 -waitexit "; std::string filename(mfilename); std::string file = '"' + filename + '"'; std::string final = base + file; - if (setduration == 1 && mduration != 0) + if (playMode == PLAYMODE_TS && mduration != 0) { std::stringstream duration; - duration << (mduration * 60000); + duration << (mduration /** 60000LL*/); final = base + "-duration " + duration.str() + " " + file; } @@ -86,7 +163,7 @@ void cPlayback::RuaThread() pid = forkpty(&master, NULL, NULL, NULL); if (! pid) { execl("/bin/sh", "sh", "-c", final.c_str(), (char *)0); - perror("exec"); + lt_info("%s: execl returned: %m\n", __func__); exit(0); } @@ -104,18 +181,17 @@ void cPlayback::RuaThread() break; output[len] = '\0'; } - printf("rmfp: '%s'\n", output); - if (!strcmp(output, "Playback has started...")) + lt_info("%s out: '%s'\n", __func__, output); + if (strstr(output, "Playback has started...")) { - fd_cmd = open(FIFO_CMD, O_WRONLY); - fd_in = open(FIFO_IN, O_WRONLY); playing = true; - printf("===================> playing = true\n"); + lt_info("%s: ===================> playing = true\n", __func__); } - else if (!strcmp(output, "End of file...")) + else if (strstr(output, "End of file...")) { + playing = true; /* this can happen without "Playback has started..." */ eof_reached = true; - printf("===================> eof_reached = true\n"); + lt_info("%s: ===================> eof_reached = true\n", __func__); } } fclose(f); @@ -125,114 +201,38 @@ void cPlayback::RuaThread() free(output); } - printf("Terminating RUA thread\n"); - thread_active = 0; + lt_info("%s: terminating\n", __func__); playing = false; - eof_reached = 1; + eof_reached = true; pthread_exit(NULL); } /* helper function to call the cpp thread loop */ -void* execute_rua_thread(void *c) +void *execute_rua_thread(void *c) { - cPlayback *obj=(cPlayback*)c; - - printf("Executing RUA Thread\n"); - - obj->RuaThread(); - - free(obj); + cPlayback *obj = (cPlayback *)c; + lt_info_c("%s\n", __func__); + obj->run_rmfp(); + /* free(obj); // this is most likely wrong */ return NULL; } -#if 0 -void cPlayback::EventThread() -{ - - printf("Starting Event thread\n"); - - thread_active = 1; - eof_reached = 0; - while (thread_active == 1) - { - struct timeval tv; - fd_set readfds; - int retval; - - tv.tv_sec = 1; - tv.tv_usec = 0; - - FD_ZERO(&readfds); - FD_SET(fd_event, &readfds); - retval = select(fd_event + 1, &readfds, NULL, NULL, &tv); - - //printf("retval is %i\n", retval); - if (retval) - { - - char eventstring[4]; - int event; - - read(fd_event, &eventstring, 3); - eventstring[3] = '\0'; - event = atoi(eventstring); - - printf("Got event message %i\n", event); - - switch(event) - { - case EVENT_MSG_FDOPEN: - fd_cmd = open(FIFO_CMD, O_WRONLY); - fd_in = open(FIFO_IN, O_WRONLY); - printf("Message FD Opened %i", fd_in); - break; - case EVENT_MSG_PLAYBACK_STARTED: - printf("Got playing event \n"); - playing = true; - break; - case EVENT_MSG_EOS: - printf("Got EOF event \n"); - eof_reached = 1; - break; - } - } - usleep(100000); - } - - printf("Terminating Event thread\n"); - playing = false; - pthread_exit(NULL); -} - -/* helper function to call the cpp thread loop */ -void* execute_event_thread(void *c) -{ - cPlayback *obj=(cPlayback*)c; - - printf("Executing Event Thread\n"); - - obj->EventThread(); - - return NULL; -} -#endif - //Used by Fileplay bool cPlayback::Open(playmode_t PlayMode) { - const char *aPLAYMODE[] = { + static const char *aPLAYMODE[] = { "PLAYMODE_TS", "PLAYMODE_FILE" }; - - setduration = 0; - if (PlayMode == 0) + playMode = PlayMode; + if (playMode > 1) { - printf("RECORDING PLAYING BACK\n"); - setduration = 1; + lt_info("%s: PlayMode %d out of range!\n", __func__, PlayMode); + playMode = PLAYMODE_FILE; } + lt_info("%s: mode %d (%s)\n", __func__, PlayMode, aPLAYMODE[PlayMode]); #if 0 while (access("/tmp/continue", R_OK)) sleep(1); @@ -249,7 +249,7 @@ bool cPlayback::Open(playmode_t PlayMode) i++; if (i > 10) { - printf("player is not getting idle after 10 seconds!\n"); + lt_info("%s: ERROR - player is not idle after 10 seconds!\n", __func__); open_success = false; return false; } @@ -257,430 +257,248 @@ bool cPlayback::Open(playmode_t PlayMode) } proc_put("/proc/player", "2", 2); + lt_info("%s: /proc/player switched to '2'\n", __func__); - printf("%s:%s - PlayMode=%s\n", FILENAME, __FUNCTION__, aPLAYMODE[PlayMode]); - - //Making Fifo's for message pipes - mknod(FIFO_CMD, S_IFIFO | 0666, 0); - mknod(FIFO_IN, S_IFIFO | 0666, 0); - mknod(FIFO_OUT, S_IFIFO | 0666, 0); -// mknod(FIFO_EVENT, S_IFIFO | 0666, 0); - - //Open pipes we read from. The fd_in pipe will be created once test_rmfp has been started - fd_out = open(FIFO_OUT, O_RDONLY | O_NONBLOCK); -// fd_event = open(FIFO_EVENT, O_RDONLY | O_NONBLOCK); + unlink(CMD_FILE); + unlink(IN_FILE); + unlink(OUT_FILE); open_success = true; return 0; } //Used by Fileplay -void cPlayback::Close(void) -{ - printf("%s:%s\n", FILENAME, __FUNCTION__); - -//Dagobert: movieplayer does not call stop, it calls close ;) - Stop(); -} - -//Used by Fileplay -bool cPlayback::Start(char * filename, unsigned short vpid, int vtype, unsigned short apid, bool ac3, int duration) +bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned short _apid, + int ac3, unsigned int duration) { bool ret = true; - - printf("%s:%s - filename=%s vpid=%u vtype=%d apid=%u ac3=%d duration=%i\n", - FILENAME, __FUNCTION__, filename, vpid, vtype, apid, ac3, duration); + + lt_info("%s: filename=%s\n", __func__, filename); + lt_info("%s: vpid=%u vtype=%d apid=%u ac3=%d duration=%i open_success=%d\n", + __func__, vpid, vtype, _apid, ac3, duration, open_success); if (!open_success) return false; - eof_reached = 0; + eof_reached = false; //create playback path - mAudioStream=0; + apid = 0; + subpid = 0; mfilename = filename; mduration = duration; - if (pthread_create(&rua_thread, 0, execute_rua_thread, this) != 0) + if (pthread_create(&thread, 0, execute_rua_thread, this) != 0) { - printf("[movieplayer]: error creating file_thread! (out of memory?)\n"); + lt_info("%s: error creating rmfp_player thread! (out of memory?)\n", __func__); ret = false; } -#if 0 - if (pthread_create(&event_thread, 0, execute_event_thread, this) != 0) - { - printf("[movieplayer]: error creating file_thread! (out of memory?)\n"); - ret = false; - } -#endif while (! playing) sleep(1); return ret; } -//Used by Fileplay -bool cPlayback::Stop(void) +void cPlayback::Close(void) { - printf("%s:%s playing %d %d\n", FILENAME, __FUNCTION__, playing, thread_active); - if(playing==false && thread_active == 0) return false; + lt_info("%s: playing %d thread_started %d\n", __func__, playing, thread_started); - rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, 0); + if (thread_started) + { + rmfp_command(KEY_COMMAND_QUIT_ALL, 0, false, NULL, 0); - if (pthread_join(rua_thread, NULL)) - { - printf("error joining rua thread\n"); + if (pthread_join(thread, NULL)) + lt_info("%s: error joining rmfp thread (%m)\n", __func__); + playing = false; + thread_started = false; } -#if 0 - if (pthread_join(event_thread, NULL)) - { - printf("error joining event thread\n"); - } -#endif - playing = false; + else + lt_info("%s: Warning: thread_started == false!\n", __func__); if (open_success) + { proc_put("/proc/player", "1", 2); - usleep(1000000); - - if (fd_in > -1) - close(fd_in); - if (fd_cmd > -1) - close(fd_cmd); - if (fd_out > -1) - close(fd_out); - fd_in = -1; - fd_cmd = -1; - fd_out = -1; - return true; + lt_info("%s: /proc/player switched to '1'\n", __func__); + usleep(1000000); + } } -bool cPlayback::SetAPid(unsigned short pid, bool /*ac3*/) +bool cPlayback::SetAPid(unsigned short pid, int /*ac3*/) { - printf("%s:%s pid %i\n", FILENAME, __FUNCTION__, pid); - if (pid != mAudioStream) { - rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, 0); - mAudioStream = pid; + lt_info("%s: pid %i\n", __func__, pid); + if (pid != apid) { + rmfp_command(KEY_COMMAND_SWITCH_AUDIO, pid, true, NULL, 0); + apid = pid; } return true; } bool cPlayback::SetSPid(int pid) { - printf("%s:%s pid %i\n", FILENAME, __FUNCTION__, pid); - if(pid!=mSubStream) + lt_info("%s: pid %i\n", __func__, pid); + if (pid != subpid) { - rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, 0); -/* - msg = KEY_COMMAND_SWITCH_SUBS; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", pid); -*/ - mSubStream=pid; + rmfp_command(KEY_COMMAND_SWITCH_SUBS, pid, true, NULL, 0); + subpid = pid; } return true; } bool cPlayback::SetSpeed(int speed) { - printf("%s:%s playing %d speed %d\n", FILENAME, __FUNCTION__, playing, speed); + lt_info("%s: playing %d speed %d\n", __func__, playing, speed); - if(playing==false) - return false; + if (!playing) + return false; -// int result = 0; + playback_speed = speed; - nPlaybackSpeed = speed; - if (speed > 1 || speed < 0) - { - rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, 0); -/* - msg = CUSTOM_COMMAND_TRICK_SEEK; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", speed); -*/ - } + rmfp_command(CUSTOM_COMMAND_TRICK_SEEK, speed, true, NULL, 0); else if (speed == 0) - { - rmfp_command(KEY_COMMAND_PAUSE, 0, false, 0); -/* - msg = KEY_COMMAND_PAUSE; - dprintf(fd_cmd, "%i", msg); -*/ - } + rmfp_command(KEY_COMMAND_PAUSE, 0, false, NULL, 0); else - { - rmfp_command(KEY_COMMAND_PLAY, 0, false, 0); -/* - msg = KEY_COMMAND_PLAY; - dprintf(fd_cmd, "%i", msg); - _GetPosition(); -*/ - } - -// if (result != 0) -// { -// printf("returning false\n"); -// return false; -// } + rmfp_command(KEY_COMMAND_PLAY, 0, false, NULL, 0); return true; } bool cPlayback::GetSpeed(int &/*speed*/) const { -/* printf("%s:%s\n", FILENAME, __FUNCTION__); - speed = nPlaybackSpeed; -*/ return true; -} - -int cPlayback::__GetPosition(void) -{ - printf("cPlayback::_GetPosition()--->\n"); #if 0 - struct pollfd pfd; - pfd.fd = fd_out; - pfd.events = POLLIN|POLLPRI; - pfd.revents = 0; - if (poll(&pfd, 1, 0) > 0) - while(read(fd_out, ×tring, 100) <= 0){}; + lt_info("%s:\n", __func__); + speed = playback_speed; #endif - last_pos = rmfp_command(CUSTOM_COMMAND_GETPOSITION, 0, false, 11); - last_pos_time = monotonic_ms(); - printf("cPlayback::_GetPosition()<--- %d\n", last_pos); - return last_pos; + return true; } - // in milliseconds bool cPlayback::GetPosition(int &position, int &duration) { - printf("%s:%s pos %d dur %d play %d\n", FILENAME, __FUNCTION__, position, duration, playing); - - //Azbox eof - if (eof_reached == 1) - { - if (setduration) - { - position = mduration; - duration = mduration; - return true; - } - position = -5; - duration = -5; - return true; - } - - if(playing==false) return false; + lt_debug("%s: playing %d\n", __func__, playing); - if (nPlaybackSpeed == 1 && setduration) { - time_t time_diff = monotonic_ms() - last_pos_time; - position = last_pos + time_diff; - } - else - position = __GetPosition(); - - if (setduration) + if (eof_reached) { + position = mduration; duration = mduration; return true; } - //Duration - int length; -/* - char durationstring[11]; - - msg = CUSTOM_COMMAND_GETLENGTH; - dprintf(fd_cmd, "%i", msg); - - int n = 0; - while ( n <= 0 ) { - n = read(fd_out, &durationstring, 10); + + if (!playing) + return false; + + char buf[32]; + /* custom command 222 returns "12345\n1234\n", + * first line is duration, second line is position */ + if (! rmfp_command(222, 0, false, buf, 32)) + return false; + duration = atoi(buf); + char *p = strchr(buf, '\n'); + if (!p) + return false; + position = atoi(++p); + + if (playMode == PLAYMODE_TS) + { + if (position > mduration) + mduration = position + 1000; + duration = mduration; + return true; } - durationstring[10] = '\0'; - length = atoi(durationstring); -*/ - length = rmfp_command(CUSTOM_COMMAND_GETLENGTH, 0, false, 11); - if(length <= 0) { - duration = duration+1000; - } else { - duration = length; - } - return true; } bool cPlayback::SetPosition(int position, bool absolute) { - printf("%s:%s %d playing %d\n", FILENAME, __FUNCTION__,position, playing); - if(playing==false) return false; - + lt_info("%s: pos %d abs %d playing %d\n", __func__, position, absolute, playing); + + if (!playing) + return false; + int seconds = position / 1000;; - - if (absolute == true) + + if (absolute) { - rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, 0); -/* - msg = KEY_COMMAND_SEEK_TO_TIME; - seconds = position / 1000; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", seconds); -*/ - } - else - { - if (position > 0 ) - { - rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, 0); -/* - msg = CUSTOM_COMMAND_SEEK_RELATIVE_FWD; - seconds = position / 1000; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", seconds); -*/ - } - else if ( position < 0 ) - { - rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, 0); -/* - msg = CUSTOM_COMMAND_SEEK_RELATIVE_BWD; - seconds = position / 1000; - seconds *= -1; - printf("sending seconds %i\n", seconds); - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", seconds); -*/ - } + rmfp_command(KEY_COMMAND_SEEK_TO_TIME, seconds, true, NULL, 0); + return true; } + + if (position > 0) + rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_FWD, seconds, true, NULL, 0); + else if (position < 0) + rmfp_command(CUSTOM_COMMAND_SEEK_RELATIVE_BWD, seconds, true, NULL, 0); return true; } void cPlayback::FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language) { - printf("%s:%s\n", FILENAME, __FUNCTION__); + lt_info("%s\n", __func__); + char buf[32]; + rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, buf, 3); + unsigned int audio_count = atoi(buf); - unsigned int audio_count = 0; -// char audio_countstring[3]; - - audio_count = rmfp_command(CUSTOM_COMMAND_AUDIO_COUNT, 0, false, 3); -/* - msg = CUSTOM_COMMAND_AUDIO_COUNT; - dprintf(fd_cmd, "%i", msg); - - int n = 0; - while ( n <= 0 ) { - n = read(fd_out, &audio_countstring, 2); - } - audio_countstring[2] = '\0'; - audio_count = atoi(audio_countstring); -*/ *numpida = audio_count; - if (audio_count > 0 ) + if (audio_count > 0) { - for ( unsigned int audio_id = 0; audio_id < audio_count; audio_id++ ) + for (unsigned int aid = 0; aid < audio_count; aid++) { char streamidstring[11]; char audio_lang[21]; - pthread_mutex_lock(&mutex); - msg = CUSTOM_COMMAND_GET_AUDIO_BY_ID; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", audio_id); - - int n = 0; - while ( n <= 0 ) { - n = read(fd_out, &streamidstring, 10); - } - read(fd_out, &audio_lang, 20); - pthread_mutex_unlock(&mutex); + memset(buf, 0, sizeof(buf)); + rmfp_command(CUSTOM_COMMAND_GET_AUDIO_BY_ID, aid, true, buf, 32); + memcpy(streamidstring, buf, 10); streamidstring[10] = '\0'; + memcpy(audio_lang, buf + 10, 20); audio_lang[20] = '\0'; - - apids[audio_id] = atoi(streamidstring); - ac3flags[audio_id] = 0; - language[audio_id] = audio_lang; + apids[aid] = atoi(streamidstring); + ac3flags[aid] = 0; + language[aid] = audio_lang; + lt_info("%s: #%d apid:%d lang: %s\n", __func__, aid, apids[aid], audio_lang); } } } void cPlayback::FindAllSPids(int *spids, uint16_t *numpids, std::string *language) { - printf("%s:%s\n", FILENAME, __FUNCTION__); + lt_info("%s\n", __func__); + char buf[32]; - unsigned int spu_count = 0; - spu_count = rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, 3); -/* - char spu_countstring[3]; - - msg = CUSTOM_COMMAND_SUBS_COUNT; - dprintf(fd_cmd, "%i", msg); - - int n = 0; - while ( n <= 0 ) { - n = read(fd_out, &spu_countstring, 2); - } - spu_countstring[2] = '\0'; - spu_count = atoi(spu_countstring); -*/ + rmfp_command(CUSTOM_COMMAND_SUBS_COUNT, 0, false, buf, 3); + unsigned int spu_count = atoi(buf); *numpids = spu_count; - if (spu_count > 0 ) + if (spu_count > 0) { - - for ( unsigned int spu_id = 0; spu_id < spu_count; spu_id++ ) + for (unsigned int sid = 0; sid < spu_count; sid++) { - //int streamid; char streamidstring[11]; char spu_lang[21]; - - pthread_mutex_lock(&mutex); - msg = CUSTOM_COMMAND_GET_SUB_BY_ID; - dprintf(fd_cmd, "%i", msg); - dprintf(fd_in, "%i", spu_id); - - int n = 0; - while ( n <= 0 ) { - n = read(fd_out, &streamidstring, 10); - } - read(fd_out, &spu_lang, 20); - pthread_mutex_unlock(&mutex); + memset(buf, 0, sizeof(buf)); + rmfp_command(CUSTOM_COMMAND_GET_SUB_BY_ID, sid, true, buf, 32); + memcpy(streamidstring, buf, 10); streamidstring[10] = '\0'; + memcpy(spu_lang, buf + 10, 20); spu_lang[20] = '\0'; - - spids[spu_id] = atoi(streamidstring); - language[spu_id] = spu_lang; + spids[sid] = atoi(streamidstring); + language[sid] = spu_lang; + lt_info("%s: #%d apid:%d lang: %s\n", __func__, sid, spids[sid], spu_lang); } } - //Add streamid -1 to be able to disable subtitles - *numpids = spu_count + 1; - spids[spu_count] = -1; - language[spu_count] = "Disable"; - + //Add streamid -1 to be able to disable subtitles + *numpids = spu_count + 1; + spids[spu_count] = -1; + language[spu_count] = "Disable"; } - cPlayback::cPlayback(int /*num*/) { - printf("%s:%s\n", FILENAME, __FUNCTION__); + lt_info("%s: constructor\n", __func__); playing = false; - thread_active = 0; - eof_reached = 0; - fd_in = -1; - fd_out = -1; - fd_cmd = -1; - pthread_mutex_init(&mutex, NULL); + thread_started = false; + eof_reached = false; + open_success = false; + pthread_mutex_init(&rmfp_cmd_mutex, NULL); } cPlayback::~cPlayback() { - printf("%s:%s\n", FILENAME, __FUNCTION__); -} - -bool cPlayback::IsEOF(void) const -{ -// printf("%s:%s\n", FILENAME, __FUNCTION__); - return eof_reached; -} - -int cPlayback::GetCurrPlaybackSpeed(void) const -{ - printf("%s:%s\n", FILENAME, __FUNCTION__); - return nPlaybackSpeed; + lt_info("%s\n", __func__); + pthread_mutex_destroy(&rmfp_cmd_mutex); } diff --git a/azbox/playback.h b/azbox/playback.h index a3acf2b..32c15c9 100644 --- a/azbox/playback.h +++ b/azbox/playback.h @@ -4,79 +4,58 @@ #include #include -#ifndef CS_PLAYBACK_PDATA -typedef struct { - int nothing; -} CS_PLAYBACK_PDATA; -#endif - typedef enum { PLAYMODE_TS = 0, PLAYMODE_FILE, -} playmode_t; +} playmode_t; class cPlayback { private: - int timeout; - pthread_cond_t read_cond; - pthread_mutex_t mutex; - CS_PLAYBACK_PDATA * privateData; - - pthread_t rua_thread; - // pthread_t event_thread; - - bool enabled; - bool paused; + pthread_mutex_t rmfp_cmd_mutex; bool playing; - int unit; - int nPlaybackFD; - int video_type; - int nPlaybackSpeed; - int mSpeed; - int mAudioStream; - int mSubStream; - char* mfilename; - int thread_active; - int eof_reached; - int setduration; - int mduration; - + bool eof_reached; + int playback_speed; playmode_t playMode; - int __GetPosition(void); - int rmfp_command(int cmd, int param, bool has_param, int reply_len); - // + bool open_success; + uint16_t apid; + uint16_t subpid; + char *mfilename; + int mduration; + pthread_t thread; + bool thread_started; + /* private functions */ + bool rmfp_command(int cmd, int param, bool has_param, char *buf, int buflen); public: - bool Open(playmode_t PlayMode); - void Close(void); - bool Start(char * filename, unsigned short vpid, int vtype, unsigned short apid, bool ac3, int duration); - bool Stop(void); - bool SetAPid(unsigned short pid, bool ac3); - bool SetSPid(int pid); - bool SetSpeed(int speed); - bool GetSpeed(int &speed) const; - bool GetPosition(int &position, int &duration); - bool SetPosition(int position, bool absolute = false); - bool IsEOF(void) const; - int GetCurrPlaybackSpeed(void) const; - void FindAllPids(uint16_t *apids, unsigned short *ac3flags, uint16_t *numpida, std::string *language); - void FindAllSPids(int *spids, uint16_t *numpids, std::string *language); - // cPlayback(int num = 0); ~cPlayback(); - void RuaThread(); - void EventThread(); + void run_rmfp(); + + bool Open(playmode_t PlayMode); + void Close(void); + bool Start(char *filename, unsigned short vpid, int vtype, unsigned short apid, + int ac3, unsigned int duration); + bool SetAPid(unsigned short pid, int 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); + // AZbox specific + void FindAllSPids(int *spids, uint16_t *numpids, std::string *language); + bool SetSPid(int pid); #if 0 - /* not used */ + // Functions that are not used by movieplayer.cpp: + bool Stop(void); bool GetOffset(off64_t &offset); - void PlaybackNotify (int Event, void *pData, void *pTag); - void DMNotify(int Event, void *pTsBuf, void *Tag); - bool IsPlaying(void) const; - bool IsEnabled(void) const; + 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 14f6a44507774c0a19f6f1564f25ec5c88f10adf Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 21 Nov 2012 13:29:16 +0100 Subject: [PATCH 05/14] atbox: make cDemux more robust * workaround hanging Read() if frontend loses and regains lock * set DMX_ONESHOT for TDT and TOT sections (this is the same as commit 77ef60e121 for spark) Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/6b9d6af7fadab75566b44ee6a816c1b8fda73169 Author: Stefan Seyfried Date: 2012-11-21 (Wed, 21 Nov 2012) ------------------ This commit was generated by Migit --- azbox/dmx.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/azbox/dmx.cpp b/azbox/dmx.cpp index 5d05b2a..099901a 100644 --- a/azbox/dmx.cpp +++ b/azbox/dmx.cpp @@ -211,17 +211,31 @@ int cDemux::Read(unsigned char *buff, int len, int timeout) __FUNCTION__, num, fd, DMX_T[dmx_type], len, timeout); #endif int rc; + int to = timeout; struct pollfd ufds; ufds.fd = fd; ufds.events = POLLIN|POLLPRI|POLLERR; ufds.revents = 0; - if (timeout > 0) + /* hack: if the frontend loses and regains lock, the demuxer often will not + * return from read(), so as a "emergency exit" for e.g. NIT scan, set a (long) + * timeout here */ + if (dmx_type == DMX_PSI_CHANNEL && timeout <= 0) + to = 60 * 1000; + + if (to > 0) { retry: - rc = ::poll(&ufds, 1, timeout); + rc = ::poll(&ufds, 1, to); if (!rc) + { + if (timeout == 0) /* we took the emergency exit */ + { + dmx_err("timed out for timeout=0!, %s", "", 0); + return -1; /* this timeout is an error */ + } return 0; // timeout + } else if (rc < 0) { dmx_err("poll: %s,", strerror(errno), 0) @@ -323,6 +337,7 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte /* 0x60 - 0x6F: event_information_section - other_transport_stream, schedule */ case 0x70: /* time_date_section */ s_flt.flags &= ~DMX_CHECK_CRC; /* section has no CRC */ + s_flt.flags |= DMX_ONESHOT; //s_flt.pid = 0x0014; to = 30000; break; @@ -335,6 +350,7 @@ bool cDemux::sectionFilter(unsigned short pid, const unsigned char * const filte to = 0; break; case 0x73: /* time_offset_section */ + s_flt.flags |= DMX_ONESHOT; //s_flt.pid = 0x0014; to = 30000; break; From a5a025d6f081db00e64f20cc1744122a4eac429a Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 21 Nov 2012 18:20:43 +0100 Subject: [PATCH 06/14] azbox: disable video output on standby Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/64c24b743fb7a325e745141dfab7dec58e5f3d72 Author: Stefan Seyfried Date: 2012-11-21 (Wed, 21 Nov 2012) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- azbox/video.cpp | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/azbox/video.cpp b/azbox/video.cpp index 0e679c2..335c15e 100644 --- a/azbox/video.cpp +++ b/azbox/video.cpp @@ -60,7 +60,6 @@ cVideo * videoDecoder = NULL; int system_rev = 0; -static bool hdmi_enabled = true; static bool stillpicture = false; static unsigned char *blank_data; static ssize_t blank_size; @@ -425,20 +424,11 @@ void cVideo::Standby(unsigned int bOn) if (bOn) { closeDevice(); - //hdmi_out(false); + proc_put("/proc/stb/avs/0/input", "aux", 4); } else { - /* only enable HDMI output when coming from standby, not on - * start. I have no idea why, but enabling it on startup leads - * to strange locking problems of the framebuffer driver :-( */ - if (!hdmi_enabled) - { - //hdmi_out(true); - /* make sure the driver has time to settle. - * again - lame, but makes it work... */ - //sleep(1); - } + proc_put("/proc/stb/avs/0/input", "encoder", 8); openDevice(); } video_standby = bOn; From b6a1b302189affffcf500ad5e85d6019033bfcf4 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 24 Nov 2012 15:48:59 +0100 Subject: [PATCH 07/14] azbox: handle rmfp_player failures/features more graceful Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/929acbae43affaf25758521dabf8778125d0c5cf Author: Stefan Seyfried Date: 2012-11-24 (Sat, 24 Nov 2012) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- azbox/playback.cpp | 19 ++++++++++++++----- azbox/playback.h | 2 +- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/azbox/playback.cpp b/azbox/playback.cpp index f7c922e..4523192 100644 --- a/azbox/playback.cpp +++ b/azbox/playback.cpp @@ -184,12 +184,12 @@ void cPlayback::run_rmfp() lt_info("%s out: '%s'\n", __func__, output); if (strstr(output, "Playback has started...")) { - playing = true; + playing = 1; lt_info("%s: ===================> playing = true\n", __func__); } else if (strstr(output, "End of file...")) { - playing = true; /* this can happen without "Playback has started..." */ + playing = 1; /* this can happen without "Playback has started..." */ eof_reached = true; lt_info("%s: ===================> eof_reached = true\n", __func__); } @@ -202,7 +202,10 @@ void cPlayback::run_rmfp() } lt_info("%s: terminating\n", __func__); - playing = false; + if (playing == 0) /* playback did not start */ + playing = 2; + else + playing = 0; eof_reached = true; pthread_exit(NULL); } @@ -293,6 +296,8 @@ bool cPlayback::Start(char *filename, unsigned short vpid, int vtype, unsigned s } while (! playing) sleep(1); + if (playing == 2) + playing = 0; return ret; } @@ -306,7 +311,7 @@ void cPlayback::Close(void) if (pthread_join(thread, NULL)) lt_info("%s: error joining rmfp thread (%m)\n", __func__); - playing = false; + playing = 0; thread_started = false; } else @@ -315,6 +320,7 @@ void cPlayback::Close(void) if (open_success) { proc_put("/proc/player", "1", 2); + open_success = false; lt_info("%s: /proc/player switched to '1'\n", __func__); usleep(1000000); } @@ -394,6 +400,9 @@ bool cPlayback::GetPosition(int &position, int &duration) if (!p) return false; position = atoi(++p); + /* some mpegs return length 0... which would lead to "eof" after 10 seconds */ + if (duration == 0) + duration = position + 1000; if (playMode == PLAYMODE_TS) { @@ -490,7 +499,7 @@ void cPlayback::FindAllSPids(int *spids, uint16_t *numpids, std::string *languag cPlayback::cPlayback(int /*num*/) { lt_info("%s: constructor\n", __func__); - playing = false; + playing = 0; thread_started = false; eof_reached = false; open_success = false; diff --git a/azbox/playback.h b/azbox/playback.h index 32c15c9..d75a76f 100644 --- a/azbox/playback.h +++ b/azbox/playback.h @@ -13,7 +13,7 @@ class cPlayback { private: pthread_mutex_t rmfp_cmd_mutex; - bool playing; + int playing; bool eof_reached; int playback_speed; playmode_t playMode; From d01bf34af330928a72897994a0606a13abf62dbf Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 1 Dec 2012 13:29:27 +0100 Subject: [PATCH 08/14] deuglify library build * build intermediate libraries for each subdirectory * link those libs in main directory instead of single objects * ugly hack in configure.ac to disable dynamic lib for now Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/7c46077051e6ba5acde097daec3acdd280210274 Author: Stefan Seyfried Date: 2012-12-01 (Sat, 01 Dec 2012) ------------------ This commit was generated by Migit --- Makefile.am | 97 +++++++---------------------------------- azbox/Makefile.am | 5 +-- common/Makefile.am | 4 +- configure.ac | 4 ++ generic-pc/Makefile.am | 5 +-- libeplayer3/Makefile.am | 6 +-- libspark/Makefile.am | 4 +- libtriple/Makefile.am | 4 +- 8 files changed, 33 insertions(+), 96 deletions(-) diff --git a/Makefile.am b/Makefile.am index c3e03eb..8ff5959 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,16 +1,16 @@ -noinst_LIBRARIES = libstb-hal.a -libstb_hal_a_SOURCES = +ACLOCAL_AMFLAGS = -I m4 + +lib_LTLIBRARIES = libstb-hal.la +libstb_hal_la_SOURCES = SUBDIRS = common tools bin_PROGRAMS = libstb-hal-test -libstb_hal_a_LIBADD = \ - common/ca.o \ - common/lt_debug.o \ - common/proc_tools.o +libstb_hal_la_LIBADD = \ + common/libcommon.la libstb_hal_test_SOURCES = libtest.cpp libstb_hal_test_LDADD = \ - libstb-hal.a \ + libstb-hal.la \ -lpthread if BOXTYPE_TRIPLE @@ -21,87 +21,22 @@ endif # there has to be a better way to do this... if BOXTYPE_TRIPLE SUBDIRS += libtriple -libstb_hal_a_LIBADD += \ - libtriple/audio_td.o \ - libtriple/dmx_td.o \ - libtriple/hardware_caps.o \ - libtriple/init_td.o \ - libtriple/lt_dfbinput.o \ - libtriple/playback_td.o \ - libtriple/pwrmngr.o \ - libtriple/record_td.o \ - libtriple/video_td.o +libstb_hal_la_LIBADD += \ + libtriple/libtriple.la endif if BOXTYPE_AZBOX SUBDIRS += azbox -libstb_hal_a_LIBADD += \ - azbox/audio.o \ - azbox/dmx.o \ - azbox/hardware_caps.o \ - azbox/init.o \ - azbox/playback.o \ - azbox/pwrmngr.o \ - azbox/record.o \ - azbox/video.o +libstb_hal_la_LIBADD += \ + azbox/libazbox.la endif if BOXTYPE_GENERIC SUBDIRS += generic-pc -libstb_hal_a_LIBADD += \ - generic-pc/audio.o \ - generic-pc/dmx.o \ - generic-pc/hardware_caps.o \ - generic-pc/init.o \ - generic-pc/playback.o \ - generic-pc/pwrmngr.o \ - generic-pc/record.o \ - generic-pc/video.o +libstb_hal_la_LIBADD += \ + generic-pc/libgeneric.la endif if BOXTYPE_SPARK SUBDIRS += libspark libeplayer3 -libstb_hal_a_LIBADD += \ - libspark/audio.o \ - libspark/dmx.o \ - libspark/hardware_caps.o \ - libspark/init.o \ - libspark/irmp.o \ - libspark/lirmp_input.o \ - libspark/playback_libeplayer3.o \ - libspark/pwrmngr.o \ - libspark/record.o \ - libspark/video.o - -# this is a hack to build the libeplayer3 objs statically into -# libstb-hal... -libstb_hal_a_LIBADD += \ - libeplayer3/container.o \ - libeplayer3/container_ffmpeg.o \ - libeplayer3/text_srt.o \ - libeplayer3/text_ssa.o \ - libeplayer3/container_ass.o \ - libeplayer3/audio.o \ - libeplayer3/manager.o \ - libeplayer3/subtitle.o \ - libeplayer3/video.o \ - libeplayer3/output_subtitle.o \ - libeplayer3/linuxdvb.o \ - libeplayer3/output.o \ - libeplayer3/playback.o \ - libeplayer3/writer.o \ - libeplayer3/aac.o \ - libeplayer3/wmv.o \ - libeplayer3/ac3.o \ - libeplayer3/divx.o \ - libeplayer3/wma.o \ - libeplayer3/pes.o \ - libeplayer3/dts.o \ - libeplayer3/mpeg2.o \ - libeplayer3/mp3.o \ - libeplayer3/misc.o \ - libeplayer3/h264.o \ - libeplayer3/h263.o \ - libeplayer3/vc1.o \ - libeplayer3/framebuffer.o \ - libeplayer3/vorbis.o \ - libeplayer3/flac.o \ - libeplayer3/pcm.o +libstb_hal_la_LIBADD += \ + libspark/libspark.la \ + libeplayer3/libeplayer3.la endif diff --git a/azbox/Makefile.am b/azbox/Makefile.am index f234200..46a3f6c 100644 --- a/azbox/Makefile.am +++ b/azbox/Makefile.am @@ -1,13 +1,12 @@ INCLUDES = \ -I$(top_srcdir)/common -# this library is not used for linking, so call it libdummy... -noinst_LIBRARIES = libdummy.a +noinst_LTLIBRARIES = libazbox.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing AM_LDFLAGS = -lpthread -libdummy_a_SOURCES = \ +libazbox_la_SOURCES = \ hardware_caps.c \ dmx.cpp \ video.cpp \ diff --git a/common/Makefile.am b/common/Makefile.am index 200f85d..f44757c 100644 --- a/common/Makefile.am +++ b/common/Makefile.am @@ -1,8 +1,8 @@ -noinst_LIBRARIES = libcommon.a +noinst_LTLIBRARIES = libcommon.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing -libcommon_a_SOURCES = \ +libcommon_la_SOURCES = \ ca.cpp \ lt_debug.cpp \ proc_tools.c diff --git a/configure.ac b/configure.ac index 5082cb3..c7ef49e 100644 --- a/configure.ac +++ b/configure.ac @@ -2,6 +2,10 @@ AC_INIT(libstb-hal,0.1.1) AM_INIT_AUTOMAKE(libstb-hal,0.1.1) m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES]) AC_CONFIG_MACRO_DIR([m4]) +LT_INIT + +## ugly, disables shared library build (not wanted yet) +enable_shared=no TUXBOX_APPS TUXBOX_APPS_DIRECTORY diff --git a/generic-pc/Makefile.am b/generic-pc/Makefile.am index f234200..d85bc75 100644 --- a/generic-pc/Makefile.am +++ b/generic-pc/Makefile.am @@ -1,13 +1,12 @@ INCLUDES = \ -I$(top_srcdir)/common -# this library is not used for linking, so call it libdummy... -noinst_LIBRARIES = libdummy.a +noinst_LTLIBRARIES = libgeneric.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing AM_LDFLAGS = -lpthread -libdummy_a_SOURCES = \ +libgeneric_la_SOURCES = \ hardware_caps.c \ dmx.cpp \ video.cpp \ diff --git a/libeplayer3/Makefile.am b/libeplayer3/Makefile.am index 3a1f167..cb31f9d 100644 --- a/libeplayer3/Makefile.am +++ b/libeplayer3/Makefile.am @@ -1,11 +1,11 @@ -noinst_LIBRARIES = libeplayer3.a +noinst_LTLIBRARIES = libeplayer3.la CXXFLAGS = -Wall INCLUDES = \ -I$(srcdir)/include -libeplayer3_a_SOURCES = \ +libeplayer3_la_SOURCES = \ container/container.c container/container_ffmpeg.c container/text_srt.c \ container/text_ssa.c container/container_ass.c \ manager/audio.c manager/manager.c manager/subtitle.c manager/video.c \ @@ -28,7 +28,7 @@ AM_CPPFLAGS = -Dattribute_deprecated='' #libeplayer3_la_LIBADD = -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng -LIBEPLAYER3_LIBS = libeplayer3.a -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng +LIBEPLAYER3_LIBS = libeplayer3.la -lpthread -lavformat -lavcodec -lavutil -lz -lass -lm -lpng bin_PROGRAMS = eplayer3 meta eplayer3_SOURCES = tools/eplayer2.c eplayer3_LDADD = $(LIBEPLAYER3_LIBS) diff --git a/libspark/Makefile.am b/libspark/Makefile.am index f35318e..ffb7195 100644 --- a/libspark/Makefile.am +++ b/libspark/Makefile.am @@ -2,12 +2,12 @@ INCLUDES = \ -I$(top_srcdir)/common \ -I$(top_srcdir)/libeplayer3/include -noinst_LIBRARIES = libspark.a +noinst_LTLIBRARIES = libspark.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing AM_LDFLAGS = -lpthread -libspark_a_SOURCES = \ +libspark_la_SOURCES = \ irmp.c \ hardware_caps.c \ lirmp_input.cpp \ diff --git a/libtriple/Makefile.am b/libtriple/Makefile.am index 6ef7656..697be37 100644 --- a/libtriple/Makefile.am +++ b/libtriple/Makefile.am @@ -2,11 +2,11 @@ INCLUDES = \ -I$(top_srcdir)/common \ @DIRECTFB_CFLAGS@ -noinst_LIBRARIES = libtriple.a +noinst_LTLIBRARIES = libtriple.la AM_CXXFLAGS = -fno-rtti -fno-exceptions -fno-strict-aliasing -libtriple_a_SOURCES = \ +libtriple_la_SOURCES = \ hardware_caps.c \ lt_dfbinput.cpp \ dmx_td.cpp \ From c4497221bb15016a0736276e7785fc94a7da6990 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sat, 12 Jan 2013 19:18:23 +0100 Subject: [PATCH 09/14] triple: implement cVideo::GetScreenImage Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/ae74fe2d0fd66e34b51363804c489a7c94bed1fe Author: Stefan Seyfried Date: 2013-01-12 (Sat, 12 Jan 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libtriple/video_td.cpp | 368 ++++++++++++++++++++++++++++++++++++++++- libtriple/video_td.h | 1 + 2 files changed, 365 insertions(+), 4 deletions(-) diff --git a/libtriple/video_td.cpp b/libtriple/video_td.cpp index 356b023..079bfa4 100644 --- a/libtriple/video_td.cpp +++ b/libtriple/video_td.cpp @@ -1,10 +1,10 @@ /* * (C) 2002-2003 Andreas Oberritter - * (C) 2010-2011 Stefan Seyfried + * (C) 2010-2013 Stefan Seyfried * * 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 3 of the License, or + * 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, @@ -13,12 +13,13 @@ * 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, Suite 500 Boston, MA 02110-1335 USA + * along with this program. If not, see . */ #include +#include #include +#include #include #include #include @@ -32,6 +33,7 @@ #include #include +#include #include "video_td.h" #include #define VIDEO_DEVICE "/dev/" DEVICE_NAME_VIDEO @@ -732,3 +734,361 @@ void cVideo::FastForwardMode(int mode) lt_debug("%s\n", __FUNCTION__); fop(ioctl, MPEG_VID_FASTFORWARD, mode); } + +/* get an image of the video screen + * this code is inspired by dreambox AIO-grab, + * git://schwerkraft.elitedvb.net/aio-grab/aio-grab.git */ +/* static lookup tables for faster yuv2rgb conversion */ +static const int yuv2rgbtable_y[256] = { + 0xFFED5EA0, 0xFFEE88B6, 0xFFEFB2CC, 0xFFF0DCE2, 0xFFF206F8, 0xFFF3310E, 0xFFF45B24, 0xFFF5853A, + 0xFFF6AF50, 0xFFF7D966, 0xFFF9037C, 0xFFFA2D92, 0xFFFB57A8, 0xFFFC81BE, 0xFFFDABD4, 0xFFFED5EA, + 0x00000000, 0x00012A16, 0x0002542C, 0x00037E42, 0x0004A858, 0x0005D26E, 0x0006FC84, 0x0008269A, + 0x000950B0, 0x000A7AC6, 0x000BA4DC, 0x000CCEF2, 0x000DF908, 0x000F231E, 0x00104D34, 0x0011774A, + 0x0012A160, 0x0013CB76, 0x0014F58C, 0x00161FA2, 0x001749B8, 0x001873CE, 0x00199DE4, 0x001AC7FA, + 0x001BF210, 0x001D1C26, 0x001E463C, 0x001F7052, 0x00209A68, 0x0021C47E, 0x0022EE94, 0x002418AA, + 0x002542C0, 0x00266CD6, 0x002796EC, 0x0028C102, 0x0029EB18, 0x002B152E, 0x002C3F44, 0x002D695A, + 0x002E9370, 0x002FBD86, 0x0030E79C, 0x003211B2, 0x00333BC8, 0x003465DE, 0x00358FF4, 0x0036BA0A, + 0x0037E420, 0x00390E36, 0x003A384C, 0x003B6262, 0x003C8C78, 0x003DB68E, 0x003EE0A4, 0x00400ABA, + 0x004134D0, 0x00425EE6, 0x004388FC, 0x0044B312, 0x0045DD28, 0x0047073E, 0x00483154, 0x00495B6A, + 0x004A8580, 0x004BAF96, 0x004CD9AC, 0x004E03C2, 0x004F2DD8, 0x005057EE, 0x00518204, 0x0052AC1A, + 0x0053D630, 0x00550046, 0x00562A5C, 0x00575472, 0x00587E88, 0x0059A89E, 0x005AD2B4, 0x005BFCCA, + 0x005D26E0, 0x005E50F6, 0x005F7B0C, 0x0060A522, 0x0061CF38, 0x0062F94E, 0x00642364, 0x00654D7A, + 0x00667790, 0x0067A1A6, 0x0068CBBC, 0x0069F5D2, 0x006B1FE8, 0x006C49FE, 0x006D7414, 0x006E9E2A, + 0x006FC840, 0x0070F256, 0x00721C6C, 0x00734682, 0x00747098, 0x00759AAE, 0x0076C4C4, 0x0077EEDA, + 0x007918F0, 0x007A4306, 0x007B6D1C, 0x007C9732, 0x007DC148, 0x007EEB5E, 0x00801574, 0x00813F8A, + 0x008269A0, 0x008393B6, 0x0084BDCC, 0x0085E7E2, 0x008711F8, 0x00883C0E, 0x00896624, 0x008A903A, + 0x008BBA50, 0x008CE466, 0x008E0E7C, 0x008F3892, 0x009062A8, 0x00918CBE, 0x0092B6D4, 0x0093E0EA, + 0x00950B00, 0x00963516, 0x00975F2C, 0x00988942, 0x0099B358, 0x009ADD6E, 0x009C0784, 0x009D319A, + 0x009E5BB0, 0x009F85C6, 0x00A0AFDC, 0x00A1D9F2, 0x00A30408, 0x00A42E1E, 0x00A55834, 0x00A6824A, + 0x00A7AC60, 0x00A8D676, 0x00AA008C, 0x00AB2AA2, 0x00AC54B8, 0x00AD7ECE, 0x00AEA8E4, 0x00AFD2FA, + 0x00B0FD10, 0x00B22726, 0x00B3513C, 0x00B47B52, 0x00B5A568, 0x00B6CF7E, 0x00B7F994, 0x00B923AA, + 0x00BA4DC0, 0x00BB77D6, 0x00BCA1EC, 0x00BDCC02, 0x00BEF618, 0x00C0202E, 0x00C14A44, 0x00C2745A, + 0x00C39E70, 0x00C4C886, 0x00C5F29C, 0x00C71CB2, 0x00C846C8, 0x00C970DE, 0x00CA9AF4, 0x00CBC50A, + 0x00CCEF20, 0x00CE1936, 0x00CF434C, 0x00D06D62, 0x00D19778, 0x00D2C18E, 0x00D3EBA4, 0x00D515BA, + 0x00D63FD0, 0x00D769E6, 0x00D893FC, 0x00D9BE12, 0x00DAE828, 0x00DC123E, 0x00DD3C54, 0x00DE666A, + 0x00DF9080, 0x00E0BA96, 0x00E1E4AC, 0x00E30EC2, 0x00E438D8, 0x00E562EE, 0x00E68D04, 0x00E7B71A, + 0x00E8E130, 0x00EA0B46, 0x00EB355C, 0x00EC5F72, 0x00ED8988, 0x00EEB39E, 0x00EFDDB4, 0x00F107CA, + 0x00F231E0, 0x00F35BF6, 0x00F4860C, 0x00F5B022, 0x00F6DA38, 0x00F8044E, 0x00F92E64, 0x00FA587A, + 0x00FB8290, 0x00FCACA6, 0x00FDD6BC, 0x00FF00D2, 0x01002AE8, 0x010154FE, 0x01027F14, 0x0103A92A, + 0x0104D340, 0x0105FD56, 0x0107276C, 0x01085182, 0x01097B98, 0x010AA5AE, 0x010BCFC4, 0x010CF9DA, + 0x010E23F0, 0x010F4E06, 0x0110781C, 0x0111A232, 0x0112CC48, 0x0113F65E, 0x01152074, 0x01164A8A +}; +static const int yuv2rgbtable_ru[256] = { + 0xFEFDA500, 0xFEFFA9B6, 0xFF01AE6C, 0xFF03B322, 0xFF05B7D8, 0xFF07BC8E, 0xFF09C144, 0xFF0BC5FA, + 0xFF0DCAB0, 0xFF0FCF66, 0xFF11D41C, 0xFF13D8D2, 0xFF15DD88, 0xFF17E23E, 0xFF19E6F4, 0xFF1BEBAA, + 0xFF1DF060, 0xFF1FF516, 0xFF21F9CC, 0xFF23FE82, 0xFF260338, 0xFF2807EE, 0xFF2A0CA4, 0xFF2C115A, + 0xFF2E1610, 0xFF301AC6, 0xFF321F7C, 0xFF342432, 0xFF3628E8, 0xFF382D9E, 0xFF3A3254, 0xFF3C370A, + 0xFF3E3BC0, 0xFF404076, 0xFF42452C, 0xFF4449E2, 0xFF464E98, 0xFF48534E, 0xFF4A5804, 0xFF4C5CBA, + 0xFF4E6170, 0xFF506626, 0xFF526ADC, 0xFF546F92, 0xFF567448, 0xFF5878FE, 0xFF5A7DB4, 0xFF5C826A, + 0xFF5E8720, 0xFF608BD6, 0xFF62908C, 0xFF649542, 0xFF6699F8, 0xFF689EAE, 0xFF6AA364, 0xFF6CA81A, + 0xFF6EACD0, 0xFF70B186, 0xFF72B63C, 0xFF74BAF2, 0xFF76BFA8, 0xFF78C45E, 0xFF7AC914, 0xFF7CCDCA, + 0xFF7ED280, 0xFF80D736, 0xFF82DBEC, 0xFF84E0A2, 0xFF86E558, 0xFF88EA0E, 0xFF8AEEC4, 0xFF8CF37A, + 0xFF8EF830, 0xFF90FCE6, 0xFF93019C, 0xFF950652, 0xFF970B08, 0xFF990FBE, 0xFF9B1474, 0xFF9D192A, + 0xFF9F1DE0, 0xFFA12296, 0xFFA3274C, 0xFFA52C02, 0xFFA730B8, 0xFFA9356E, 0xFFAB3A24, 0xFFAD3EDA, + 0xFFAF4390, 0xFFB14846, 0xFFB34CFC, 0xFFB551B2, 0xFFB75668, 0xFFB95B1E, 0xFFBB5FD4, 0xFFBD648A, + 0xFFBF6940, 0xFFC16DF6, 0xFFC372AC, 0xFFC57762, 0xFFC77C18, 0xFFC980CE, 0xFFCB8584, 0xFFCD8A3A, + 0xFFCF8EF0, 0xFFD193A6, 0xFFD3985C, 0xFFD59D12, 0xFFD7A1C8, 0xFFD9A67E, 0xFFDBAB34, 0xFFDDAFEA, + 0xFFDFB4A0, 0xFFE1B956, 0xFFE3BE0C, 0xFFE5C2C2, 0xFFE7C778, 0xFFE9CC2E, 0xFFEBD0E4, 0xFFEDD59A, + 0xFFEFDA50, 0xFFF1DF06, 0xFFF3E3BC, 0xFFF5E872, 0xFFF7ED28, 0xFFF9F1DE, 0xFFFBF694, 0xFFFDFB4A, + 0x00000000, 0x000204B6, 0x0004096C, 0x00060E22, 0x000812D8, 0x000A178E, 0x000C1C44, 0x000E20FA, + 0x001025B0, 0x00122A66, 0x00142F1C, 0x001633D2, 0x00183888, 0x001A3D3E, 0x001C41F4, 0x001E46AA, + 0x00204B60, 0x00225016, 0x002454CC, 0x00265982, 0x00285E38, 0x002A62EE, 0x002C67A4, 0x002E6C5A, + 0x00307110, 0x003275C6, 0x00347A7C, 0x00367F32, 0x003883E8, 0x003A889E, 0x003C8D54, 0x003E920A, + 0x004096C0, 0x00429B76, 0x0044A02C, 0x0046A4E2, 0x0048A998, 0x004AAE4E, 0x004CB304, 0x004EB7BA, + 0x0050BC70, 0x0052C126, 0x0054C5DC, 0x0056CA92, 0x0058CF48, 0x005AD3FE, 0x005CD8B4, 0x005EDD6A, + 0x0060E220, 0x0062E6D6, 0x0064EB8C, 0x0066F042, 0x0068F4F8, 0x006AF9AE, 0x006CFE64, 0x006F031A, + 0x007107D0, 0x00730C86, 0x0075113C, 0x007715F2, 0x00791AA8, 0x007B1F5E, 0x007D2414, 0x007F28CA, + 0x00812D80, 0x00833236, 0x008536EC, 0x00873BA2, 0x00894058, 0x008B450E, 0x008D49C4, 0x008F4E7A, + 0x00915330, 0x009357E6, 0x00955C9C, 0x00976152, 0x00996608, 0x009B6ABE, 0x009D6F74, 0x009F742A, + 0x00A178E0, 0x00A37D96, 0x00A5824C, 0x00A78702, 0x00A98BB8, 0x00AB906E, 0x00AD9524, 0x00AF99DA, + 0x00B19E90, 0x00B3A346, 0x00B5A7FC, 0x00B7ACB2, 0x00B9B168, 0x00BBB61E, 0x00BDBAD4, 0x00BFBF8A, + 0x00C1C440, 0x00C3C8F6, 0x00C5CDAC, 0x00C7D262, 0x00C9D718, 0x00CBDBCE, 0x00CDE084, 0x00CFE53A, + 0x00D1E9F0, 0x00D3EEA6, 0x00D5F35C, 0x00D7F812, 0x00D9FCC8, 0x00DC017E, 0x00DE0634, 0x00E00AEA, + 0x00E20FA0, 0x00E41456, 0x00E6190C, 0x00E81DC2, 0x00EA2278, 0x00EC272E, 0x00EE2BE4, 0x00F0309A, + 0x00F23550, 0x00F43A06, 0x00F63EBC, 0x00F84372, 0x00FA4828, 0x00FC4CDE, 0x00FE5194, 0x00100564A +}; +static const int yuv2rgbtable_gu[256] = { + 0xFFCDD300, 0xFFCE375A, 0xFFCE9BB4, 0xFFCF000E, 0xFFCF6468, 0xFFCFC8C2, 0xFFD02D1C, 0xFFD09176, + 0xFFD0F5D0, 0xFFD15A2A, 0xFFD1BE84, 0xFFD222DE, 0xFFD28738, 0xFFD2EB92, 0xFFD34FEC, 0xFFD3B446, + 0xFFD418A0, 0xFFD47CFA, 0xFFD4E154, 0xFFD545AE, 0xFFD5AA08, 0xFFD60E62, 0xFFD672BC, 0xFFD6D716, + 0xFFD73B70, 0xFFD79FCA, 0xFFD80424, 0xFFD8687E, 0xFFD8CCD8, 0xFFD93132, 0xFFD9958C, 0xFFD9F9E6, + 0xFFDA5E40, 0xFFDAC29A, 0xFFDB26F4, 0xFFDB8B4E, 0xFFDBEFA8, 0xFFDC5402, 0xFFDCB85C, 0xFFDD1CB6, + 0xFFDD8110, 0xFFDDE56A, 0xFFDE49C4, 0xFFDEAE1E, 0xFFDF1278, 0xFFDF76D2, 0xFFDFDB2C, 0xFFE03F86, + 0xFFE0A3E0, 0xFFE1083A, 0xFFE16C94, 0xFFE1D0EE, 0xFFE23548, 0xFFE299A2, 0xFFE2FDFC, 0xFFE36256, + 0xFFE3C6B0, 0xFFE42B0A, 0xFFE48F64, 0xFFE4F3BE, 0xFFE55818, 0xFFE5BC72, 0xFFE620CC, 0xFFE68526, + 0xFFE6E980, 0xFFE74DDA, 0xFFE7B234, 0xFFE8168E, 0xFFE87AE8, 0xFFE8DF42, 0xFFE9439C, 0xFFE9A7F6, + 0xFFEA0C50, 0xFFEA70AA, 0xFFEAD504, 0xFFEB395E, 0xFFEB9DB8, 0xFFEC0212, 0xFFEC666C, 0xFFECCAC6, + 0xFFED2F20, 0xFFED937A, 0xFFEDF7D4, 0xFFEE5C2E, 0xFFEEC088, 0xFFEF24E2, 0xFFEF893C, 0xFFEFED96, + 0xFFF051F0, 0xFFF0B64A, 0xFFF11AA4, 0xFFF17EFE, 0xFFF1E358, 0xFFF247B2, 0xFFF2AC0C, 0xFFF31066, + 0xFFF374C0, 0xFFF3D91A, 0xFFF43D74, 0xFFF4A1CE, 0xFFF50628, 0xFFF56A82, 0xFFF5CEDC, 0xFFF63336, + 0xFFF69790, 0xFFF6FBEA, 0xFFF76044, 0xFFF7C49E, 0xFFF828F8, 0xFFF88D52, 0xFFF8F1AC, 0xFFF95606, + 0xFFF9BA60, 0xFFFA1EBA, 0xFFFA8314, 0xFFFAE76E, 0xFFFB4BC8, 0xFFFBB022, 0xFFFC147C, 0xFFFC78D6, + 0xFFFCDD30, 0xFFFD418A, 0xFFFDA5E4, 0xFFFE0A3E, 0xFFFE6E98, 0xFFFED2F2, 0xFFFF374C, 0xFFFF9BA6, + 0x00000000, 0x0000645A, 0x0000C8B4, 0x00012D0E, 0x00019168, 0x0001F5C2, 0x00025A1C, 0x0002BE76, + 0x000322D0, 0x0003872A, 0x0003EB84, 0x00044FDE, 0x0004B438, 0x00051892, 0x00057CEC, 0x0005E146, + 0x000645A0, 0x0006A9FA, 0x00070E54, 0x000772AE, 0x0007D708, 0x00083B62, 0x00089FBC, 0x00090416, + 0x00096870, 0x0009CCCA, 0x000A3124, 0x000A957E, 0x000AF9D8, 0x000B5E32, 0x000BC28C, 0x000C26E6, + 0x000C8B40, 0x000CEF9A, 0x000D53F4, 0x000DB84E, 0x000E1CA8, 0x000E8102, 0x000EE55C, 0x000F49B6, + 0x000FAE10, 0x0010126A, 0x001076C4, 0x0010DB1E, 0x00113F78, 0x0011A3D2, 0x0012082C, 0x00126C86, + 0x0012D0E0, 0x0013353A, 0x00139994, 0x0013FDEE, 0x00146248, 0x0014C6A2, 0x00152AFC, 0x00158F56, + 0x0015F3B0, 0x0016580A, 0x0016BC64, 0x001720BE, 0x00178518, 0x0017E972, 0x00184DCC, 0x0018B226, + 0x00191680, 0x00197ADA, 0x0019DF34, 0x001A438E, 0x001AA7E8, 0x001B0C42, 0x001B709C, 0x001BD4F6, + 0x001C3950, 0x001C9DAA, 0x001D0204, 0x001D665E, 0x001DCAB8, 0x001E2F12, 0x001E936C, 0x001EF7C6, + 0x001F5C20, 0x001FC07A, 0x002024D4, 0x0020892E, 0x0020ED88, 0x002151E2, 0x0021B63C, 0x00221A96, + 0x00227EF0, 0x0022E34A, 0x002347A4, 0x0023ABFE, 0x00241058, 0x002474B2, 0x0024D90C, 0x00253D66, + 0x0025A1C0, 0x0026061A, 0x00266A74, 0x0026CECE, 0x00273328, 0x00279782, 0x0027FBDC, 0x00286036, + 0x0028C490, 0x002928EA, 0x00298D44, 0x0029F19E, 0x002A55F8, 0x002ABA52, 0x002B1EAC, 0x002B8306, + 0x002BE760, 0x002C4BBA, 0x002CB014, 0x002D146E, 0x002D78C8, 0x002DDD22, 0x002E417C, 0x002EA5D6, + 0x002F0A30, 0x002F6E8A, 0x002FD2E4, 0x0030373E, 0x00309B98, 0x0030FFF2, 0x0031644C, 0x0031C8A6 +}; +static const int yuv2rgbtable_gv[256] = { + 0xFF97E900, 0xFF98B92E, 0xFF99895C, 0xFF9A598A, 0xFF9B29B8, 0xFF9BF9E6, 0xFF9CCA14, 0xFF9D9A42, + 0xFF9E6A70, 0xFF9F3A9E, 0xFFA00ACC, 0xFFA0DAFA, 0xFFA1AB28, 0xFFA27B56, 0xFFA34B84, 0xFFA41BB2, + 0xFFA4EBE0, 0xFFA5BC0E, 0xFFA68C3C, 0xFFA75C6A, 0xFFA82C98, 0xFFA8FCC6, 0xFFA9CCF4, 0xFFAA9D22, + 0xFFAB6D50, 0xFFAC3D7E, 0xFFAD0DAC, 0xFFADDDDA, 0xFFAEAE08, 0xFFAF7E36, 0xFFB04E64, 0xFFB11E92, + 0xFFB1EEC0, 0xFFB2BEEE, 0xFFB38F1C, 0xFFB45F4A, 0xFFB52F78, 0xFFB5FFA6, 0xFFB6CFD4, 0xFFB7A002, + 0xFFB87030, 0xFFB9405E, 0xFFBA108C, 0xFFBAE0BA, 0xFFBBB0E8, 0xFFBC8116, 0xFFBD5144, 0xFFBE2172, + 0xFFBEF1A0, 0xFFBFC1CE, 0xFFC091FC, 0xFFC1622A, 0xFFC23258, 0xFFC30286, 0xFFC3D2B4, 0xFFC4A2E2, + 0xFFC57310, 0xFFC6433E, 0xFFC7136C, 0xFFC7E39A, 0xFFC8B3C8, 0xFFC983F6, 0xFFCA5424, 0xFFCB2452, + 0xFFCBF480, 0xFFCCC4AE, 0xFFCD94DC, 0xFFCE650A, 0xFFCF3538, 0xFFD00566, 0xFFD0D594, 0xFFD1A5C2, + 0xFFD275F0, 0xFFD3461E, 0xFFD4164C, 0xFFD4E67A, 0xFFD5B6A8, 0xFFD686D6, 0xFFD75704, 0xFFD82732, + 0xFFD8F760, 0xFFD9C78E, 0xFFDA97BC, 0xFFDB67EA, 0xFFDC3818, 0xFFDD0846, 0xFFDDD874, 0xFFDEA8A2, + 0xFFDF78D0, 0xFFE048FE, 0xFFE1192C, 0xFFE1E95A, 0xFFE2B988, 0xFFE389B6, 0xFFE459E4, 0xFFE52A12, + 0xFFE5FA40, 0xFFE6CA6E, 0xFFE79A9C, 0xFFE86ACA, 0xFFE93AF8, 0xFFEA0B26, 0xFFEADB54, 0xFFEBAB82, + 0xFFEC7BB0, 0xFFED4BDE, 0xFFEE1C0C, 0xFFEEEC3A, 0xFFEFBC68, 0xFFF08C96, 0xFFF15CC4, 0xFFF22CF2, + 0xFFF2FD20, 0xFFF3CD4E, 0xFFF49D7C, 0xFFF56DAA, 0xFFF63DD8, 0xFFF70E06, 0xFFF7DE34, 0xFFF8AE62, + 0xFFF97E90, 0xFFFA4EBE, 0xFFFB1EEC, 0xFFFBEF1A, 0xFFFCBF48, 0xFFFD8F76, 0xFFFE5FA4, 0xFFFF2FD2, + 0x00000000, 0x0000D02E, 0x0001A05C, 0x0002708A, 0x000340B8, 0x000410E6, 0x0004E114, 0x0005B142, + 0x00068170, 0x0007519E, 0x000821CC, 0x0008F1FA, 0x0009C228, 0x000A9256, 0x000B6284, 0x000C32B2, + 0x000D02E0, 0x000DD30E, 0x000EA33C, 0x000F736A, 0x00104398, 0x001113C6, 0x0011E3F4, 0x0012B422, + 0x00138450, 0x0014547E, 0x001524AC, 0x0015F4DA, 0x0016C508, 0x00179536, 0x00186564, 0x00193592, + 0x001A05C0, 0x001AD5EE, 0x001BA61C, 0x001C764A, 0x001D4678, 0x001E16A6, 0x001EE6D4, 0x001FB702, + 0x00208730, 0x0021575E, 0x0022278C, 0x0022F7BA, 0x0023C7E8, 0x00249816, 0x00256844, 0x00263872, + 0x002708A0, 0x0027D8CE, 0x0028A8FC, 0x0029792A, 0x002A4958, 0x002B1986, 0x002BE9B4, 0x002CB9E2, + 0x002D8A10, 0x002E5A3E, 0x002F2A6C, 0x002FFA9A, 0x0030CAC8, 0x00319AF6, 0x00326B24, 0x00333B52, + 0x00340B80, 0x0034DBAE, 0x0035ABDC, 0x00367C0A, 0x00374C38, 0x00381C66, 0x0038EC94, 0x0039BCC2, + 0x003A8CF0, 0x003B5D1E, 0x003C2D4C, 0x003CFD7A, 0x003DCDA8, 0x003E9DD6, 0x003F6E04, 0x00403E32, + 0x00410E60, 0x0041DE8E, 0x0042AEBC, 0x00437EEA, 0x00444F18, 0x00451F46, 0x0045EF74, 0x0046BFA2, + 0x00478FD0, 0x00485FFE, 0x0049302C, 0x004A005A, 0x004AD088, 0x004BA0B6, 0x004C70E4, 0x004D4112, + 0x004E1140, 0x004EE16E, 0x004FB19C, 0x005081CA, 0x005151F8, 0x00522226, 0x0052F254, 0x0053C282, + 0x005492B0, 0x005562DE, 0x0056330C, 0x0057033A, 0x0057D368, 0x0058A396, 0x005973C4, 0x005A43F2, + 0x005B1420, 0x005BE44E, 0x005CB47C, 0x005D84AA, 0x005E54D8, 0x005F2506, 0x005FF534, 0x0060C562, + 0x00619590, 0x006265BE, 0x006335EC, 0x0064061A, 0x0064D648, 0x0065A676, 0x006676A4, 0x006746D2 +}; +static const int yuv2rgbtable_bv[256] = { + 0xFF33A280, 0xFF353B3B, 0xFF36D3F6, 0xFF386CB1, 0xFF3A056C, 0xFF3B9E27, 0xFF3D36E2, 0xFF3ECF9D, + 0xFF406858, 0xFF420113, 0xFF4399CE, 0xFF453289, 0xFF46CB44, 0xFF4863FF, 0xFF49FCBA, 0xFF4B9575, + 0xFF4D2E30, 0xFF4EC6EB, 0xFF505FA6, 0xFF51F861, 0xFF53911C, 0xFF5529D7, 0xFF56C292, 0xFF585B4D, + 0xFF59F408, 0xFF5B8CC3, 0xFF5D257E, 0xFF5EBE39, 0xFF6056F4, 0xFF61EFAF, 0xFF63886A, 0xFF652125, + 0xFF66B9E0, 0xFF68529B, 0xFF69EB56, 0xFF6B8411, 0xFF6D1CCC, 0xFF6EB587, 0xFF704E42, 0xFF71E6FD, + 0xFF737FB8, 0xFF751873, 0xFF76B12E, 0xFF7849E9, 0xFF79E2A4, 0xFF7B7B5F, 0xFF7D141A, 0xFF7EACD5, + 0xFF804590, 0xFF81DE4B, 0xFF837706, 0xFF850FC1, 0xFF86A87C, 0xFF884137, 0xFF89D9F2, 0xFF8B72AD, + 0xFF8D0B68, 0xFF8EA423, 0xFF903CDE, 0xFF91D599, 0xFF936E54, 0xFF95070F, 0xFF969FCA, 0xFF983885, + 0xFF99D140, 0xFF9B69FB, 0xFF9D02B6, 0xFF9E9B71, 0xFFA0342C, 0xFFA1CCE7, 0xFFA365A2, 0xFFA4FE5D, + 0xFFA69718, 0xFFA82FD3, 0xFFA9C88E, 0xFFAB6149, 0xFFACFA04, 0xFFAE92BF, 0xFFB02B7A, 0xFFB1C435, + 0xFFB35CF0, 0xFFB4F5AB, 0xFFB68E66, 0xFFB82721, 0xFFB9BFDC, 0xFFBB5897, 0xFFBCF152, 0xFFBE8A0D, + 0xFFC022C8, 0xFFC1BB83, 0xFFC3543E, 0xFFC4ECF9, 0xFFC685B4, 0xFFC81E6F, 0xFFC9B72A, 0xFFCB4FE5, + 0xFFCCE8A0, 0xFFCE815B, 0xFFD01A16, 0xFFD1B2D1, 0xFFD34B8C, 0xFFD4E447, 0xFFD67D02, 0xFFD815BD, + 0xFFD9AE78, 0xFFDB4733, 0xFFDCDFEE, 0xFFDE78A9, 0xFFE01164, 0xFFE1AA1F, 0xFFE342DA, 0xFFE4DB95, + 0xFFE67450, 0xFFE80D0B, 0xFFE9A5C6, 0xFFEB3E81, 0xFFECD73C, 0xFFEE6FF7, 0xFFF008B2, 0xFFF1A16D, + 0xFFF33A28, 0xFFF4D2E3, 0xFFF66B9E, 0xFFF80459, 0xFFF99D14, 0xFFFB35CF, 0xFFFCCE8A, 0xFFFE6745, + 0x00000000, 0x000198BB, 0x00033176, 0x0004CA31, 0x000662EC, 0x0007FBA7, 0x00099462, 0x000B2D1D, + 0x000CC5D8, 0x000E5E93, 0x000FF74E, 0x00119009, 0x001328C4, 0x0014C17F, 0x00165A3A, 0x0017F2F5, + 0x00198BB0, 0x001B246B, 0x001CBD26, 0x001E55E1, 0x001FEE9C, 0x00218757, 0x00232012, 0x0024B8CD, + 0x00265188, 0x0027EA43, 0x002982FE, 0x002B1BB9, 0x002CB474, 0x002E4D2F, 0x002FE5EA, 0x00317EA5, + 0x00331760, 0x0034B01B, 0x003648D6, 0x0037E191, 0x00397A4C, 0x003B1307, 0x003CABC2, 0x003E447D, + 0x003FDD38, 0x004175F3, 0x00430EAE, 0x0044A769, 0x00464024, 0x0047D8DF, 0x0049719A, 0x004B0A55, + 0x004CA310, 0x004E3BCB, 0x004FD486, 0x00516D41, 0x005305FC, 0x00549EB7, 0x00563772, 0x0057D02D, + 0x005968E8, 0x005B01A3, 0x005C9A5E, 0x005E3319, 0x005FCBD4, 0x0061648F, 0x0062FD4A, 0x00649605, + 0x00662EC0, 0x0067C77B, 0x00696036, 0x006AF8F1, 0x006C91AC, 0x006E2A67, 0x006FC322, 0x00715BDD, + 0x0072F498, 0x00748D53, 0x0076260E, 0x0077BEC9, 0x00795784, 0x007AF03F, 0x007C88FA, 0x007E21B5, + 0x007FBA70, 0x0081532B, 0x0082EBE6, 0x008484A1, 0x00861D5C, 0x0087B617, 0x00894ED2, 0x008AE78D, + 0x008C8048, 0x008E1903, 0x008FB1BE, 0x00914A79, 0x0092E334, 0x00947BEF, 0x009614AA, 0x0097AD65, + 0x00994620, 0x009ADEDB, 0x009C7796, 0x009E1051, 0x009FA90C, 0x00A141C7, 0x00A2DA82, 0x00A4733D, + 0x00A60BF8, 0x00A7A4B3, 0x00A93D6E, 0x00AAD629, 0x00AC6EE4, 0x00AE079F, 0x00AFA05A, 0x00B13915, + 0x00B2D1D0, 0x00B46A8B, 0x00B60346, 0x00B79C01, 0x00B934BC, 0x00BACD77, 0x00BC6632, 0x00BDFEED, + 0x00BF97A8, 0x00C13063, 0x00C2C91E, 0x00C461D9, 0x00C5FA94, 0x00C7934F, 0x00C92C0A, 0x00CAC4C5 +}; + +#define CLAMP(x) ((x < 0) ? 0 : ((x > 255) ? 255 : x)) +#define SWAP(x,y) { x ^= y; y ^= x; x ^= y; } +#define VIDEO_MEM _MPEG_VIDEO_MEM_BASE +#define VIDEO_SIZE _MPEG_VIDEO_MEM_SIZE +#define WIDTH_OFF (VID_USER_MEM_BASE + 0x0100) +#define HEIGHT_OFF (VID_USER_MEM_BASE + 0x0102) +#define GFXFB_MEM _GFX_FB_MEM_BASE +#define GFXFB_SIZE _GFX_FB_MEM_SIZE +/* TODO: aspect ratio correction and PIP */ +bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool get_video, bool get_osd, bool /*scale_to_video*/) +{ + lt_info("%s: get_video: %d get_osd: %d\n", __func__, get_video, get_osd); + uint8_t *map; + int mfd = open("/dev/mem", O_RDWR); + if (mfd < 0) { + lt_info("%s: cannot open open /dev/mem (%m)\n", __func__); + return false; + } + /* this hints at incorrect usage */ + if (video != NULL) + lt_info("%s: WARNING, video != NULL?\n", __func__); + + if (get_video) + { + map = (uint8_t *)mmap(NULL, VIDEO_SIZE, PROT_READ, MAP_SHARED, mfd, VIDEO_MEM); + if (map == MAP_FAILED) { + lt_info("%s: cannot mmap /dev/mem vor VIDEO (%m)\n", __func__); + close(mfd); + return false; + } + uint16_t w = *(uint16_t *)(map + WIDTH_OFF); + uint16_t h = *(uint16_t *)(map + HEIGHT_OFF); + uint8_t *luma, *chroma; + int needmem = w * h * 5 / 4; /* chroma is 1/4 in size of luma */ + int lumasize = w * h; + int chromasize = needmem - lumasize; + uint8_t *buf = (uint8_t *)malloc(needmem); + if (!buf) { + lt_info("%s: cannot allocate %d bytes (%m)\n", __func__, needmem); + munmap(map, VIDEO_SIZE); + close(mfd); + return false; + } + /* luma is at the beginning of the buffer */ + memcpy(buf, map, lumasize); + /* it looks like the chroma plane is always 720*576 bytes offset to the luma plane */ + memcpy(buf + lumasize, map + 720 * 576, chromasize); + /* release the video buffer */ + munmap(map, VIDEO_SIZE); + + if (get_osd) + { /* in this case, the framebuffer determines the output resolution */ + xres = 720; + yres = 576; + } + else + { + xres = w; + yres = h; + } + video = (unsigned char *)malloc(xres * yres * 4); + if (!video) { + lt_info("%s: cannot allocate %d bytes for video buffer (%m)\n", __func__, yres * yres * 4); + free(buf); + close(mfd); + return false; + } + + luma = buf; + chroma = buf + lumasize; + + int Y, U, V, y, x, out1, pos, RU, GU, GV, BV, rgbstride, i; + + // yuv2rgb conversion (4:2:0) + lt_info("%s: converting Video from YUV to RGB color space\n", __func__); + out1 = pos = 0; + rgbstride = w * 4; + + for (y = h; y != 0; y -= 2) + { + for (x = w; x != 0; x -= 4) + { + U = *chroma++; + V = *chroma++; + RU = yuv2rgbtable_ru[U]; // use lookup tables to speedup the whole thing + GU = yuv2rgbtable_gu[U]; + GV = yuv2rgbtable_gv[V]; + BV = yuv2rgbtable_bv[V]; + // now we do 8 pixels on each iteration this is more code but much faster + for (i = 0; i < 4; i++) + { + Y = yuv2rgbtable_y[luma[pos]]; + video[out1 ] = CLAMP((Y + RU) >> 16); + video[out1 + 1] = CLAMP((Y - GV - GU) >> 16); + video[out1 + 2] = CLAMP((Y + BV) >> 16); + video[out1 + 3] = 0xff; + + Y = yuv2rgbtable_y[luma[w + pos]]; + video[out1 + rgbstride] = CLAMP((Y + RU) >> 16); + video[out1 + 1 + rgbstride] = CLAMP((Y - GV - GU) >> 16); + video[out1 + 2 + rgbstride] = CLAMP((Y + BV) >> 16); + video[out1 + 3 + rgbstride] = 0xff; + + pos++; + out1 += 4; + } + } + out1 += rgbstride; + pos += w; + } + if (get_osd && (w < xres || h < yres)) + { + /* most trivial scaling algorithm: + * - no smoothing/antialiasing or similar + * - only upscaling + * more or less just memcpy + * works "backwards" (from bottom right up left), + * so that no extra buffer is needed */ + int j, k; + uint32_t *v = (uint32_t *)video; /* int pointer to the video buffer */ + uint32_t *srcline; /* the start of the current line (unscaled) */ + uint32_t *dst = v + xres * yres; /* the current scaled pixel */ + for (j = yres -1 ; j >= 0; j--) + { + srcline = v + (((j * h) / yres) * w); + for (k = xres - 1; k >= 0; k--) { + dst--; + *dst = *(srcline + ((k * w) / xres)); + } + } + } + lt_info("%s: Video-Size: %d x %d\n", __func__, xres, yres); + free(buf); + } + if (get_osd) + { + if (! get_video) + { + /* we don't use other framebuffer resolutions */ + xres = 720; + yres = 576; + video = (unsigned char *)calloc(xres * yres, 4); + if (!video) + { + lt_info("%s: cannot allocate %d bytes for video buffer (%m)\n", __func__, yres * yres * 4); + close(mfd); + return false; + } + } + /* we don't need the framebufferdevice, we know where the FB is located */ + map = (uint8_t *)mmap(NULL, GFXFB_SIZE, PROT_READ, MAP_SHARED, mfd, GFXFB_MEM); + if (map == MAP_FAILED) { + lt_info("%s: cannot mmap /dev/mem for GFXFB (%m)\n", __func__); + close(mfd); + return false; + } + unsigned int i, r, g, b, a, a2; + uint8_t *p = map; + uint8_t *q = video; + for (i = xres * yres; i != 0; i--) + { + a = *p++; + r = *p++; + g = *p++; + b = *p++; + a2 = 0xff - a; + /* blue */ + *q = ((*q * a2 ) + (b * a)) >> 8; + q++; + /* green */ + *q = ((*q * a2 ) + (g * a)) >> 8; + q++; + /* red */ + *q = ((*q * a2 ) + (r * a)) >> 8; + q++; + q++; /* skip alpha byte */ + } + munmap(map, GFXFB_SIZE); + } + close(mfd); + return true; +} diff --git a/libtriple/video_td.h b/libtriple/video_td.h index 831dc93..8f4893b 100644 --- a/libtriple/video_td.h +++ b/libtriple/video_td.h @@ -186,6 +186,7 @@ class cVideo int CloseVBI(void) { return 0; }; int StartVBI(unsigned short) { return 0; }; int StopVBI(void) { return 0; }; + bool GetScreenImage(unsigned char * &data, int &xres, int &yres, bool get_video = true, bool get_osd = false, bool scale_to_video = false); }; #endif From 94ffffb6daa8af475989addafe955bc43319bcb7 Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 13 Jan 2013 18:11:36 +0100 Subject: [PATCH 10/14] triple: add a sanity check to cVideo::GetScreenImage Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/e6fefa10c1f21ece6e0b8e5dee68dc4dc0efee86 Author: Stefan Seyfried Date: 2013-01-13 (Sun, 13 Jan 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libtriple/video_td.cpp | 6 ++++++ libtriple/video_td.h | 2 ++ 2 files changed, 8 insertions(+) diff --git a/libtriple/video_td.cpp b/libtriple/video_td.cpp index 079bfa4..f3dfaa7 100644 --- a/libtriple/video_td.cpp +++ b/libtriple/video_td.cpp @@ -942,6 +942,12 @@ bool cVideo::GetScreenImage(unsigned char * &video, int &xres, int &yres, bool g } uint16_t w = *(uint16_t *)(map + WIDTH_OFF); uint16_t h = *(uint16_t *)(map + HEIGHT_OFF); + if (w > 720 || h > 576) { + lt_info("%s: unhandled resolution %dx%d, is the tuner locked?\n", __func__, w, h); + munmap(map, VIDEO_SIZE); + close(mfd); + return false; + } uint8_t *luma, *chroma; int needmem = w * h * 5 / 4; /* chroma is 1/4 in size of luma */ int lumasize = w * h; diff --git a/libtriple/video_td.h b/libtriple/video_td.h index 8f4893b..f73bb04 100644 --- a/libtriple/video_td.h +++ b/libtriple/video_td.h @@ -6,6 +6,8 @@ //#define video_displayformat_t vidDispMode_t #include "../common/cs_types.h" +#define STB_HAL_VIDEO_HAS_GETSCREENIMAGE 1 + typedef enum { ANALOG_SD_RGB_SCART = 0x00, ANALOG_SD_YPRPB_SCART, From 103108c3c8b3122f0b0d6f7572888f8aa431b16d Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Sun, 13 Jan 2013 18:46:26 +0100 Subject: [PATCH 11/14] video_td.h: add compat define for SCREENSHOT Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/393f5452f46bd370c8c191ba6c9b8710b3b653bd Author: Stefan Seyfried Date: 2013-01-13 (Sun, 13 Jan 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- include/video_td.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/video_td.h b/include/video_td.h index 1e81f2f..71718c1 100644 --- a/include/video_td.h +++ b/include/video_td.h @@ -10,3 +10,7 @@ #else #error neither HAVE_TRIPLEDRAGON nor HAVE_SPARK_HARDWARE defined #endif + +#if STB_HAL_VIDEO_HAS_GETSCREENIMAGE +#define SCREENSHOT 1 +#endif From 113c5128079ca152367b8aa3765c19d14d99c1da Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 23 Jan 2013 21:29:27 +0100 Subject: [PATCH 12/14] libtriple: fix neutrino streamdev Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/5cb4a9d274321d313bd02c16ad7ea0f718776088 Author: Stefan Seyfried Date: 2013-01-23 (Wed, 23 Jan 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libtriple/dmx_td.cpp | 7 ++++--- libtriple/dmx_td.h | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libtriple/dmx_td.cpp b/libtriple/dmx_td.cpp index 35efade..a491879 100644 --- a/libtriple/dmx_td.cpp +++ b/libtriple/dmx_td.cpp @@ -91,13 +91,14 @@ cDemux::~cDemux() bool cDemux::Open(DMX_CHANNEL_TYPE pes_type, void * /*hVideoBuffer*/, int uBufferSize) { - int devnum = num; + devnum = num; int flags = O_RDWR; if (fd > -1) lt_info("%s FD ALREADY OPENED? fd = %d\n", __FUNCTION__, fd); if (pes_type == DMX_TP_CHANNEL) { - if (num == 0) /* streaminfo measurement, let's cheat... */ + /* see neutrino's src/gui/streaminfo2.cpp for the buffer size */ + if (num == 0 && uBufferSize == 3 * 3008 * 62) /* streaminfo measurement, let's cheat... */ { lt_info("%s num=0 and DMX_TP_CHANNEL => measurement demux\n", __func__); devnum = 2; /* demux 0 is used for live, demux 1 for recording */ @@ -535,7 +536,7 @@ bool cDemux::addPid(unsigned short Pid) } if (fd == -1) lt_info("%s bucketfd not yet opened? pid=%hx\n", __FUNCTION__, Pid); - pfd.fd = open(devname[num], O_RDWR); + pfd.fd = open(devname[devnum], O_RDWR); if (pfd.fd < 0) { lt_info("%s #%d Pid = %hx open failed (%m)\n", __FUNCTION__, num, Pid); diff --git a/libtriple/dmx_td.h b/libtriple/dmx_td.h index 2656ca9..4b35ece 100644 --- a/libtriple/dmx_td.h +++ b/libtriple/dmx_td.h @@ -36,6 +36,7 @@ class cDemux { private: int num; + int devnum; int fd; int buffersize; bool measure; From b8f48b0cabd1fabfed10581cd8a193ddca9522bb Mon Sep 17 00:00:00 2001 From: Stefan Seyfried Date: Wed, 23 Jan 2013 21:31:03 +0100 Subject: [PATCH 13/14] libtriple: fix measurement demux speed Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/65478d9e855f8ec16c5e1a800b5822729f739e05 Author: Stefan Seyfried Date: 2013-01-23 (Wed, 23 Jan 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libtriple/dmx_td.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libtriple/dmx_td.cpp b/libtriple/dmx_td.cpp index a491879..3c4b1e1 100644 --- a/libtriple/dmx_td.cpp +++ b/libtriple/dmx_td.cpp @@ -245,6 +245,8 @@ int cDemux::Read(unsigned char *buff, int len, int timeout) if (measure) { + if (timeout) + usleep(timeout * 1000); uint64_t now; struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); From bd3e4720e07aab3819a40ce8b913b242acbb1d6d Mon Sep 17 00:00:00 2001 From: graugans Date: Fri, 25 Jan 2013 10:25:47 +0100 Subject: [PATCH 14/14] fixed the debug output to match the correct device Origin commit data ------------------ Branch: master Commit: https://github.com/neutrino-images/ni-libstb-hal/commit/6b9726992630f9a8570d8d2a1122d013c96bcc3a Author: graugans Date: 2013-01-25 (Fri, 25 Jan 2013) ------------------ No further description and justification available within origin commit message! ------------------ This commit was generated by Migit --- libspark/video.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libspark/video.cpp b/libspark/video.cpp index 49aae66..6cb7228 100644 --- a/libspark/video.cpp +++ b/libspark/video.cpp @@ -115,7 +115,7 @@ static int hdmi_out(bool enable) int fb = open("/dev/fb0", O_RDWR); if (fb < 0) { - lt_debug_c("%s: can't open /dev/fb/0 (%m)\n", __func__); + lt_debug_c("%s: can't open /dev/fb0 (%m)\n", __func__); return -1; } out.outputid = STMFBIO_OUTPUTID_MAIN;