aboutsummaryrefslogtreecommitdiffstats
path: root/test
diff options
context:
space:
mode:
authoretobi <git@e-tobi.net>2013-09-03 09:48:38 +0200
committeretobi <git@e-tobi.net>2013-09-03 09:48:38 +0200
commit6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d (patch)
tree024bef311226653bdd1da4fa588becf5098bcff7 /test
downloadlinux-dvb-apps-6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d.tar.gz
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'test')
-rw-r--r--test/Makefile37
-rw-r--r--test/README51
-rwxr-xr-xtest/dia7
-rw-r--r--test/diseqc.c140
-rw-r--r--test/hex_dump.c63
-rw-r--r--test/hex_dump.h28
-rw-r--r--test/sendburst.c55
-rw-r--r--test/set22k.c50
-rw-r--r--test/setpid.c87
-rw-r--r--test/setvoltage.c47
-rw-r--r--test/test.c281
-rw-r--r--test/test_audio.c345
-rw-r--r--test/test_av.c574
-rw-r--r--test/test_av_play.c310
-rw-r--r--test/test_dvr.c164
-rw-r--r--test/test_dvr_play.c144
-rw-r--r--test/test_front.c328
-rw-r--r--test/test_pes.c137
-rw-r--r--test/test_sec_ne.c165
-rw-r--r--test/test_sections.c197
-rw-r--r--test/test_stc.c74
-rw-r--r--test/test_stillimage.c103
-rw-r--r--test/test_switch.c355
-rw-r--r--test/test_tt.c205
-rw-r--r--test/test_vevent.c125
-rw-r--r--test/test_video.c368
-rw-r--r--test/video.c182
27 files changed, 4622 insertions, 0 deletions
diff --git a/test/Makefile b/test/Makefile
new file mode 100644
index 0000000..ddff9ab
--- /dev/null
+++ b/test/Makefile
@@ -0,0 +1,37 @@
+# Makefile for Linux DVB API Version 3 test programs
+
+CC = gcc
+CFLAGS = -g -O2 -W -Wall -I../include
+
+TARGETS = \
+ diseqc \
+ set22k \
+ sendburst \
+ setvoltage \
+ setpid \
+ video \
+ test_sections \
+ test_sec_ne \
+ test_pes \
+ test_dvr \
+ test_dvr_play \
+ test_tt \
+ test_av \
+ test_av_play \
+ test_vevent \
+ test_stc \
+ test_stillimage
+
+# test \
+# test_audio \
+# test_front \
+# test_switch \
+# test_video \
+
+all: $(TARGETS)
+
+test_sections test_sec_ne test_pes test_tt: hex_dump.o
+
+clean:
+ rm -f $(TARGETS) *.o
+
diff --git a/test/README b/test/README
new file mode 100644
index 0000000..b3f0cac
--- /dev/null
+++ b/test/README
@@ -0,0 +1,51 @@
+Various small test/sample programs for the Linux DVB API Version 2
+
+The default devices used by the test programs are generally
+/dev/dvb/adapter0/*0, and can be overridden using environment
+variables:
+
+ FRONTEND=/dev/dvb/adapter0/frontend0
+ DEMUX=/dev/dvb/adapter0/demux0
+ DVR=/dev/dvb/adapter0/dvr0
+ AUDIO=/dev/dvb/adapter0/audio0
+ VIDEO=/dev/dvb/adapter0/video0
+ NET=/dev/dvb/adapter0/net0
+
+
+diseqc : Send various diseqc sequences on a SAT frontend.
+ Best used with a diseqc test box with some LEDs to
+ show the result of the commands.
+set22k : Legacy tone switching for SAT frontends.
+setvoltage : Legacy voltage switching for SAT frontends.
+
+setpid : Set video and audio PIDs in the demux; useful only
+ if you have a hardware MPEG decoder.
+video : A tiny video watching application, just starts capturing /dev/video
+ into /dev/fb0.
+ WARNING: May crash your box or mess up your console!
+
+test_sections : Hex dump of section data from stream.
+test_sec_ne : Like test_sections, but also test Not-Equal filter mode.
+test_pes : Hex dump of PES data from stream.
+test_tt : Demonstrate teletext decoding from PES data.
+test_av : Test audio and video MPEG decoder API.
+test_vevent : Test VIDEO_GET_EVENT and poll() for video events
+test_stc : Test DMX_GET_STC.
+
+test_stillimage : Display single iframes as stillimages
+ iframes can be created with the 'convert' tool from
+ imagemagick and mpeg2encode from ftp.mpeg.org, and must
+ have a supported size, e.g. 702x576
+ ($ convert -sample 702x576\! test.jpg test.mpg)
+
+(test_av_play : Test playing MPEG TS from a file (apparently broken))
+
+
+test :
+test_audio :
+test_dmx :
+test_dvr :
+test_front :
+test_switch :
+test_video :
+
diff --git a/test/dia b/test/dia
new file mode 100755
index 0000000..5cb2600
--- /dev/null
+++ b/test/dia
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+for f in $@
+do /usr/X11R6/bin/convert -geomtry 702x576 $f test.mpg
+test_video test.mpg
+rm test.mpg
+done \ No newline at end of file
diff --git a/test/diseqc.c b/test/diseqc.c
new file mode 100644
index 0000000..8f2e411
--- /dev/null
+++ b/test/diseqc.c
@@ -0,0 +1,140 @@
+/*
+ * Test sending DiSEqC commands on a SAT frontend.
+ *
+ * usage: FRONTEND=/dev/dvb/adapterX/frontendX diseqc [test_seq_no]
+ */
+
+#include <pthread.h>
+#include <time.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/dvb/frontend.h>
+
+
+struct diseqc_cmd {
+ struct dvb_diseqc_master_cmd cmd;
+ uint32_t wait;
+};
+
+
+struct diseqc_cmd switch_cmds[] = {
+ { { { 0xe0, 0x10, 0x38, 0xf0, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf2, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf1, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf3, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf4, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf6, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf5, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf7, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf8, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xfa, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xf9, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xfb, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xfc, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xfe, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xfd, 0x00, 0x00 }, 4 }, 0 },
+ { { { 0xe0, 0x10, 0x38, 0xff, 0x00, 0x00 }, 4 }, 0 }
+};
+
+
+/*--------------------------------------------------------------------------*/
+
+static inline
+void msleep(uint32_t msec)
+{
+ struct timespec req = { msec / 1000, 1000000 * (msec % 1000) };
+
+ while (nanosleep(&req, &req))
+ ;
+}
+
+
+static
+void diseqc_send_msg(int fd, fe_sec_voltage_t v, struct diseqc_cmd **cmd,
+ fe_sec_tone_mode_t t, fe_sec_mini_cmd_t b)
+{
+ ioctl(fd, FE_SET_TONE, SEC_TONE_OFF);
+ ioctl(fd, FE_SET_VOLTAGE, v);
+
+ msleep(15);
+ while (*cmd) {
+ printf("msg: %02x %02x %02x %02x %02x %02x\n",
+ (*cmd)->cmd.msg[0], (*cmd)->cmd.msg[1],
+ (*cmd)->cmd.msg[2], (*cmd)->cmd.msg[3],
+ (*cmd)->cmd.msg[4], (*cmd)->cmd.msg[5]);
+
+ ioctl(fd, FE_DISEQC_SEND_MASTER_CMD, &(*cmd)->cmd);
+ msleep((*cmd)->wait);
+ cmd++;
+ }
+
+ printf("%s: ", __FUNCTION__);
+
+ printf(" %s ", v == SEC_VOLTAGE_13 ? "SEC_VOLTAGE_13" :
+ v == SEC_VOLTAGE_18 ? "SEC_VOLTAGE_18" : "???");
+
+ printf(" %s ", b == SEC_MINI_A ? "SEC_MINI_A" :
+ b == SEC_MINI_B ? "SEC_MINI_B" : "???");
+
+ printf(" %s\n", t == SEC_TONE_ON ? "SEC_TONE_ON" :
+ t == SEC_TONE_OFF ? "SEC_TONE_OFF" : "???");
+
+ msleep(15);
+ ioctl(fd, FE_DISEQC_SEND_BURST, b);
+
+ msleep(15);
+ ioctl(fd, FE_SET_TONE, t);
+}
+
+
+int main(int argc, char **argv)
+{
+ struct diseqc_cmd *cmd[2] = { NULL, NULL };
+ char *fedev = "/dev/dvb/adapter0/frontend0";
+ int fd;
+
+ if (getenv("FRONTEND"))
+ fedev = getenv("FRONTEND");
+
+ printf("diseqc test: using '%s'\n", fedev);
+
+ if ((fd = open(fedev, O_RDWR)) < 0) {
+ perror("open");
+ return -1;
+ }
+
+ if (argc > 1) {
+ int i = atol(argv[1]);
+ cmd[0] = &switch_cmds[i];
+ diseqc_send_msg(fd,
+ i % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13,
+ cmd,
+ (i/2) % 2 ? SEC_TONE_ON : SEC_TONE_OFF,
+ (i/4) % 2 ? SEC_MINI_B : SEC_MINI_A);
+ } else {
+ unsigned int j;
+
+ for (j=0; j<sizeof(switch_cmds)/sizeof(struct diseqc_cmd); j++)
+ {
+ cmd[0] = &switch_cmds[j];
+ diseqc_send_msg(fd,
+ j % 2 ? SEC_VOLTAGE_18 : SEC_VOLTAGE_13,
+ cmd,
+ (j/2) % 2 ? SEC_TONE_ON : SEC_TONE_OFF,
+ (j/4) % 2 ? SEC_MINI_B : SEC_MINI_A);
+ msleep (1000);
+ }
+ }
+
+ close(fd);
+
+ return 0;
+}
+
+
diff --git a/test/hex_dump.c b/test/hex_dump.c
new file mode 100644
index 0000000..c7c8ede
--- /dev/null
+++ b/test/hex_dump.c
@@ -0,0 +1,63 @@
+/* hex_dump.h -- simple hex dump routine
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "hex_dump.h"
+
+
+void hex_dump(uint8_t data[], int bytes)
+{
+ int i, j;
+ uint8_t c;
+
+ for (i = 0; i < bytes; i++) {
+ if (!(i % 8) && i)
+ printf(" ");
+ if (!(i % 16) && i) {
+ printf(" ");
+ for (j = 0; j < 16; j++) {
+ c = data[i+j-16];
+ if ((c < 0x20) || (c >= 0x7f))
+ c = '.';
+ printf("%c", c);
+ }
+ printf("\n");
+ }
+ printf("%.2x ", data[i]);
+ }
+ j = (bytes % 16);
+ j = (j != 0 ? j : 16);
+ for (i = j; i < 16; i++) {
+ if (!(i % 8) && i)
+ printf(" ");
+ printf(" ");
+ }
+ printf(" ");
+ for (i = bytes - j; i < bytes; i++) {
+ c = data[i];
+ if ((c < 0x20) || (c >= 0x7f))
+ c = '.';
+ printf("%c", c);
+ }
+ printf("\n");
+}
+
diff --git a/test/hex_dump.h b/test/hex_dump.h
new file mode 100644
index 0000000..030cc37
--- /dev/null
+++ b/test/hex_dump.h
@@ -0,0 +1,28 @@
+#ifndef _HEXDUMP_H_
+#define _HEXDUMP_H_
+/* hex_dump.h -- simple hex dump routine
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdint.h>
+
+extern void hex_dump(uint8_t data[], int bytes);
+
+
+#endif /* _HEXDUMP_H_ */
diff --git a/test/sendburst.c b/test/sendburst.c
new file mode 100644
index 0000000..a96b68c
--- /dev/null
+++ b/test/sendburst.c
@@ -0,0 +1,55 @@
+/*
+ * Test sending the burst mini command A/B on a SAT frontend.
+ *
+ * usage: FRONTEND=/dev/dvb/adapterX/frontendX sendburst {a|b}
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <linux/dvb/frontend.h>
+
+
+int main (int argc, char **argv)
+{
+ char *fedev = "/dev/dvb/adapter0/frontend0";
+ int fd, r;
+
+ if (argc != 2 || (strcmp(argv[1], "a") && strcmp(argv[1], "b"))) {
+ fprintf (stderr, "usage: %s <a|b>\n", argv[0]);
+ return 1;
+ }
+
+ if (getenv("FRONTEND"))
+ fedev = getenv("FRONTEND");
+
+ printf("set22k: using '%s'\n", fedev);
+
+ if ((fd = open (fedev, O_RDWR)) < 0) {
+ perror ("open");
+ return 1;
+ }
+
+ ioctl (fd, FE_SET_TONE, SEC_TONE_OFF);
+
+ usleep (30000); /* 30ms according to DiSEqC spec */
+
+ if (strcmp(argv[1], "a") == 0)
+ r = ioctl (fd, FE_DISEQC_SEND_BURST, SEC_MINI_A);
+ else
+ r = ioctl (fd, FE_DISEQC_SEND_BURST, SEC_MINI_B);
+
+ if (r == -1)
+ perror("ioctl FE_SET_TONE");
+
+ close (fd);
+
+ return 0;
+}
+
diff --git a/test/set22k.c b/test/set22k.c
new file mode 100644
index 0000000..51ffa1c
--- /dev/null
+++ b/test/set22k.c
@@ -0,0 +1,50 @@
+/*
+ * Test switching the 22kHz tone signal on and off on a SAT frontend.
+ * (Note: DiSEqC equipment ignores this after it has once seen a diseqc
+ * sequence; reload the driver or unplug/replug the SAT cable to reset.)
+ *
+ * usage: FRONTEND=/dev/dvb/adapterX/frontendX set22k {on|off}
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include <linux/dvb/frontend.h>
+
+
+int main (int argc, char **argv)
+{
+ char *fedev = "/dev/dvb/adapter0/frontend0";
+ int fd, r;
+
+ if (argc != 2 || (strcmp(argv[1], "on") && strcmp(argv[1], "off"))) {
+ fprintf (stderr, "usage: %s <on|off>\n", argv[0]);
+ return 1;
+ }
+ if (getenv("FRONTEND"))
+ fedev = getenv("FRONTEND");
+ printf("set22k: using '%s'\n", fedev);
+
+ if ((fd = open (fedev, O_RDWR)) < 0) {
+ perror ("open");
+ return 1;
+ }
+
+ if (strcmp(argv[1], "on") == 0)
+ r = ioctl (fd, FE_SET_TONE, SEC_TONE_ON);
+ else
+ r = ioctl (fd, FE_SET_TONE, SEC_TONE_OFF);
+ if (r == -1)
+ perror("ioctl FE_SET_TONE");
+
+ close (fd);
+
+ return 0;
+}
+
diff --git a/test/setpid.c b/test/setpid.c
new file mode 100644
index 0000000..fa0333c
--- /dev/null
+++ b/test/setpid.c
@@ -0,0 +1,87 @@
+/*
+ * Set video and audio PIDs in the demux; useful only if you have
+ * a hardware MPEG decoder and you're tuned to a transport stream.
+ *
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX setpid video_pid audio_pid
+ */
+
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <linux/dvb/dmx.h>
+
+
+static
+int setup_demux (char *dmxdev, int video_pid, int audio_pid)
+{
+ int vfd, afd;
+ struct dmx_pes_filter_params pesfilter;
+
+ printf ("video_pid == 0x%04x\n", video_pid);
+ printf ("audio_pid == 0x%04x\n", audio_pid);
+
+ if ((vfd = open (dmxdev, O_RDWR)) < 0) {
+ perror("open 1");
+ return -1;
+ }
+
+ pesfilter.pid = video_pid;
+ pesfilter.input = DMX_IN_FRONTEND;
+ pesfilter.output = DMX_OUT_DECODER;
+ pesfilter.pes_type = DMX_PES_VIDEO;
+ pesfilter.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl (vfd, DMX_SET_PES_FILTER, &pesfilter) < 0) {
+ perror("ioctl DMX_SET_PES_FILTER (video)");
+ return -1;
+ }
+
+ close (vfd);
+
+ if ((afd = open (dmxdev, O_RDWR)) < 0) {
+ perror("open 1");
+ return -1;
+ }
+
+ pesfilter.pid = audio_pid;
+ pesfilter.input = DMX_IN_FRONTEND;
+ pesfilter.output = DMX_OUT_DECODER;
+ pesfilter.pes_type = DMX_PES_AUDIO;
+ pesfilter.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl (afd, DMX_SET_PES_FILTER, &pesfilter) < 0) {
+ perror("ioctl DMX_SET_PES_FILTER (audio)");
+ return -1;
+ }
+
+ close (afd);
+ return 0;
+}
+
+
+int main (int argc, char **argv)
+{
+ char *dmxdev = "/dev/dvb/adapter0/demux0";
+ int video_pid, audio_pid;
+
+ if (argc != 3) {
+ printf ("\nusage: %s <video pid> <audio pid>\n\n", argv[0]);
+ exit (1);
+ }
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ printf("setpid: using '%s'\n", dmxdev);
+
+ video_pid = strtol(argv[1], NULL, 0);
+ audio_pid = strtol(argv[2], NULL, 0);
+ if (setup_demux (dmxdev, video_pid, audio_pid) < 0)
+ return 1;
+
+ return 0;
+}
+
+
diff --git a/test/setvoltage.c b/test/setvoltage.c
new file mode 100644
index 0000000..1d14a4c
--- /dev/null
+++ b/test/setvoltage.c
@@ -0,0 +1,47 @@
+/*
+ * Test switching the voltage signal high and low on a SAT frontend.
+ * (Note: DiSEqC equipment ignores this after it has once seen a diseqc
+ * sequence; reload the driver or unplug/replug the SAT cable to reset.)
+ *
+ * usage: FRONTEND=/dev/dvb/adapterX/frontendX setvoltage {13|18}
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/dvb/frontend.h>
+
+
+int main (int argc, char **argv)
+{
+ char *fedev = "/dev/dvb/adapter0/frontend0";
+ int fd, r;
+
+ if (argc != 2 || (strcmp(argv[1], "13") && strcmp(argv[1], "18"))) {
+ fprintf (stderr, "usage: %s <13|18>\n", argv[0]);
+ return -1;
+ }
+ if (getenv("FRONTEND"))
+ fedev = getenv("FRONTEND");
+ printf("setvoltage: using '%s'\n", fedev);
+
+ if ((fd = open (fedev, O_RDWR)) < 0)
+ perror ("open");
+
+ if (strcmp(argv[1], "13") == 0)
+ r = ioctl (fd, FE_SET_VOLTAGE, SEC_VOLTAGE_13);
+ else
+ r = ioctl (fd, FE_SET_VOLTAGE, SEC_VOLTAGE_18);
+ if (r == -1)
+ perror ("ioctl FE_SET_VOLTAGE");
+
+ close (fd);
+
+ return 0;
+}
+
diff --git a/test/test.c b/test/test.c
new file mode 100644
index 0000000..6c9af51
--- /dev/null
+++ b/test/test.c
@@ -0,0 +1,281 @@
+/*
+ * test.c - Test program for new API
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend_old.h>
+#include <linux/dvb/sec.h>
+#include <linux/dvb/video.h>
+
+uint8_t reverse[] = {
+0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+};
+
+inline t2a(uint8_t c)
+{
+ c=reverse[c]&0x7f;
+ if (c<0x20)
+ c=0x20;
+
+ return c;
+}
+
+void testpesfilter(void)
+{
+ uint8_t buf[4096], id;
+ int i,j;
+ int len;
+ int fd=open("/dev/ost/demux1", O_RDWR);
+ struct dmx_pes_filter_params pesFilterParams;
+
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_TS_TAP;
+ pesFilterParams.pes_type = DMX_PES_TELETEXT;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+
+ pesFilterParams.pid = 0x2c ;
+ if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
+ printf("Could not set PES filter\n");
+ close(fd);
+ return;
+ }
+ ioctl(fd, DMX_STOP, 0);
+/*
+ pesFilterParams.pid = 54;
+ if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
+ printf("Could not set PES filter\n");
+ close(fd);
+ return;
+ }
+ ioctl(fd, DMX_STOP, 0);
+
+ pesFilterParams.pid = 55;
+ if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0) {
+ printf("Could not set PES filter\n");
+ close(fd);
+ return;
+ }
+*/
+ while(1) {
+ len=read(fd, buf, 4096);
+ if (len>0) write(1, buf, len);
+ }
+
+ do {
+ read(fd, buf, 4);
+ if (htonl(*(uint32_t *)buf)!=0x00001bd)
+ continue;
+ read(fd, buf+4, 2);
+ len=(buf[4]<<8)|buf[5];
+ read(fd, buf+6, len);
+ fprintf(stderr,"read %d bytes PES\n", len);
+ write (1, buf, len+6);
+
+ id=buf[45];
+ fprintf(stderr,"id=%02x\n", id);
+
+ for (i=0; i<(len+6-46)/46; i++) {
+ for (j=6; j<46; j++) {
+ fprintf(stderr,"%c", t2a(buf[i*46+46+j]));
+ }
+ fprintf(stderr,"\n");
+ }
+
+ } while (1);
+
+
+ /*
+ pesFilterParams.pid = 55;
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_DECODER;
+ pesFilterParams.pes_type = DMX_PES_TELETEXT;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+
+ ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams);
+ close(fd);
+ */
+}
+
+
+senf()
+{
+ int ret;
+ int len;
+ struct secCommand scmd;
+ struct secCmdSequence scmds;
+ struct dmx_pes_filter_params pesFilterParams;
+ struct dmx_sct_filter_params secFilterParams;
+ FrontendParameters frp;
+ uint8_t buf[4096];
+
+ int vout=open("qv", O_RDWR|O_CREAT);
+ int aout=open("qa", O_RDWR|O_CREAT);
+
+ int fd_video=open("/dev/ost/video", O_RDWR);
+ int fd_audio=open("/dev/ost/audio", O_RDWR);
+ int fd_tt=open("/dev/ost/demux", O_RDWR);
+ int fd_frontend=open("/dev/ost/frontend", O_RDWR);
+ int fd_sec=open("/dev/ost/sec", O_RDWR);
+ int fd_demux=open("/dev/ost/demux", O_RDWR|O_NONBLOCK);
+ int fd_demux2=open("/dev/ost/demux", O_RDWR|O_NONBLOCK);
+ int fd_section=open("/dev/ost/demux", O_RDWR);
+ int fd_section2=open("/dev/ost/demux", O_RDWR);
+
+ printf("%d\n",fd_section);
+
+ //if (ioctl(fd_sec, SEC_SET_VOLTAGE, SEC_VOLTAGE_13) < 0) return;
+ //if (ioctl(fd_sec, SEC_SET_TONE, SEC_TONE_ON) < 0) return;
+#if 0
+ scmd.type=0;
+ scmd.u.diseqc.addr=0x10;
+ scmd.u.diseqc.cmd=0x38;
+ scmd.u.diseqc.numParams=1;
+ scmd.u.diseqc.params[0]=0xf0;
+
+ scmds.voltage=SEC_VOLTAGE_13;
+ scmds.miniCommand=SEC_MINI_NONE;
+ scmds.continuousTone=SEC_TONE_ON;
+ scmds.numCommands=1;
+ scmds.commands=&scmd;
+ if (ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds) < 0) return;
+ printf("SEC OK\n");
+
+ frp.Frequency=(12666000-10600000);
+ frp.u.qpsk.SymbolRate=22000000;
+ frp.u.qpsk.FEC_inner=FEC_AUTO;
+
+ if (ioctl(fd_frontend, FE_SET_FRONTEND, &frp) < 0) return;
+ printf("QPSK OK\n");
+#endif
+
+#if 0
+ ret=ioctl(fd_demux2, DMX_SET_BUFFER_SIZE, 64*1024);
+ if (ret<0)
+ perror("DMX_SET_BUFFER_SIZE\n");
+ printf("Audio filter size OK\n");
+ pesFilterParams.pid = 0x60;
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_DECODER;
+ pesFilterParams.pes_type = DMX_PES_AUDIO;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl(fd_demux2, DMX_SET_PES_FILTER, &pesFilterParams) < 0) return(1);
+ printf("Audio filter OK\n");
+
+ if (ioctl(fd_demux, DMX_SET_BUFFER_SIZE, 64*1024) < 0) return(1);
+ pesFilterParams.pid = 0xa2;
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_DECODER;
+ pesFilterParams.pes_type = DMX_PES_VIDEO;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd_demux, DMX_SET_PES_FILTER, &pesFilterParams) < 0) return(1);
+ printf("Video filter OK\n");
+#endif
+ /*
+ pesFilterParams.pid = 56;
+ pesFilterParams.input = DMX_IN_FRONTEND;
+ pesFilterParams.output = DMX_OUT_DECODER;
+ pesFilterParams.pes_type = DMX_PES_TELETEXT;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd_tt, DMX_SET_PES_FILTER, &pesFilterParams) < 0) return(1);
+ printf("TT filter OK\n");
+ */
+ //while (1);
+ /* {
+ len=read(fd_demux, buf, 4096);
+ if (len>0) write (vout, buf, len);
+ len=read(fd_demux2, buf, 4096);
+ if (len>0) write (aout, buf, len);
+ }*/
+
+
+ memset(&secFilterParams.filter.filter, 0, DMX_FILTER_SIZE);
+ memset(&secFilterParams.filter.mask, 0, DMX_FILTER_SIZE);
+ secFilterParams.filter.filter[0]=0x00;
+ secFilterParams.filter.mask[0]=0x00;
+ secFilterParams.timeout=5000;
+ secFilterParams.flags=DMX_IMMEDIATE_START;
+
+ /*
+ // this one should timeout after 2 seconds
+ secFilterParams.pid=0xa4;
+ if (ioctl(fd_section, DMX_SET_FILTER, &secFilterParams) < 0) return;
+ len=read(fd_section, buf, 4096);
+ */
+
+ /*
+ {
+ int32_t snr, str;
+ ioctl(fd_frontend, FE_READ_SNR, &snr);
+ ioctl(fd_frontend, FE_READ_SIGNAL_STRENGTH, &str);
+
+ printf("snr=%d, str=%d\n", snr, str);
+ }
+ */
+
+ secFilterParams.pid=0x11;
+ //printf("section filter\n");
+ if (ioctl(fd_section, DMX_SET_FILTER, &secFilterParams) < 0) return;
+ //if (ioctl(fd_section2, DMX_SET_FILTER, &secFilterParams) < 0) return;
+ //close(fd_section2);
+ //while (1)
+{
+ len=read(fd_section, buf, 4096);
+ if (len>0) write(1, buf, len);
+ //printf("read section with length %d\n", len);
+ //if (len>0) write(1,buf,len);
+ //len=read(fd_section2, buf, 4096);
+ //if (len>0) write(1,buf,len);
+ //printf("read section with length %d\n", len);
+ }
+
+}
+
+main()
+{
+ //senf();
+ testpesfilter();
+}
+
diff --git a/test/test_audio.c b/test/test_audio.c
new file mode 100644
index 0000000..0abb734
--- /dev/null
+++ b/test/test_audio.c
@@ -0,0 +1,345 @@
+/*
+ * test_audio.c - Test program for new API
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <ost/dmx.h>
+#include <ost/frontend_old.h>
+#include <ost/sec.h>
+#include <ost/audio.h>
+#include <sys/poll.h>
+
+int audioStop(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_STOP,0) < 0)){
+ perror("AUDIO STOP: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int audioPlay(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_PLAY) < 0)){
+ perror("AUDIO PLAY: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int audioPause(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_PAUSE) < 0)){
+ perror("AUDIO PAUSE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int audioContinue(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_CONTINUE) < 0)){
+ perror("AUDIO CONTINUE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int audioSelectSource(int fd, audio_stream_source_t source)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SELECT_SOURCE, source) < 0)){
+ perror("AUDIO SELECT SOURCE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+int audioSetMute(int fd, boolean state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SET_MUTE, state) < 0)){
+ perror("AUDIO SET MUTE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int audioSetAVSync(int fd,boolean state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SET_AV_SYNC, state) < 0)){
+ perror("AUDIO SET AV SYNC: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int audioSetBypassMode(int fd,boolean mode)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SET_BYPASS_MODE, mode) < 0)){
+ perror("AUDIO SET BYPASS MODE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int audioChannelSelect(int fd, audio_channel_select_t select)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_CHANNEL_SELECT, select) < 0)){
+ perror("AUDIO CHANNEL SELECT: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int audioGetStatus(int fd)
+{
+ struct audio_status stat;
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_GET_STATUS, &stat) < 0)){
+ perror("AUDIO GET STATUS: ");
+ return -1;
+ }
+
+ printf("Audio Status:\n");
+ printf(" Sync State : %s\n",
+ (stat.AV_sync_state ? "SYNC" : "NO SYNC"));
+ printf(" Mute State : %s\n",
+ (stat.mute_state ? "muted" : "not muted"));
+ printf(" Play State : ");
+ switch ((int)stat.play_state){
+ case AUDIO_STOPPED:
+ printf("STOPPED (%d)\n",stat.play_state);
+ break;
+ case AUDIO_PLAYING:
+ printf("PLAYING (%d)\n",stat.play_state);
+ break;
+ case AUDIO_PAUSED:
+ printf("PAUSED (%d)\n",stat.play_state);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.play_state);
+ break;
+ }
+
+ printf(" Stream Source : ");
+ switch((int)stat.stream_source){
+ case AUDIO_SOURCE_DEMUX:
+ printf("DEMUX (%d)\n",stat.stream_source);
+ break;
+ case AUDIO_SOURCE_MEMORY:
+ printf("MEMORY (%d)\n",stat.stream_source);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.stream_source);
+ break;
+ }
+
+ printf(" Channel Select : ");
+ switch((int)stat.channel_select){
+ case AUDIO_STEREO:
+ printf("Stereo (%d)\n",stat.channel_select);
+ break;
+ case AUDIO_MONO_LEFT:
+ printf("Mono left(%d)\n",stat.channel_select);
+ break;
+ case AUDIO_MONO_RIGHT:
+ printf("Mono right (%d)\n",stat.channel_select);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.channel_select);
+ break;
+ }
+ printf(" Bypass Mode : %s\n",
+ (stat.bypass_mode ? "ON" : "OFF"));
+
+ return 0;
+
+}
+
+#define BUFFY 100000
+#define NFD 2
+play_file_audio(int filefd, int fd)
+{
+ char buf[BUFFY];
+ int count;
+ int written;
+ int ch;
+ struct pollfd pfd[NFD];
+ int stopped = 0;
+ boolean mute = false;
+ boolean sync = false;
+
+ pfd[0].fd = STDIN_FILENO;
+ pfd[0].events = POLLIN;
+
+ pfd[1].fd = fd;
+ pfd[1].events = POLLOUT;
+
+
+ while ( (count = read(filefd,buf,BUFFY)) >= 0 ){
+ written = 0;
+ while(written < count){
+ if (poll(pfd,NFD,1)){
+ if (pfd[1].revents & POLLOUT){
+ written += write(fd,buf+written,
+ count-written);
+ }
+ if (pfd[0].revents & POLLIN){
+ int c = getchar();
+ switch(c){
+ case 'z':
+ audioPause(fd);
+ printf("playback paused\n");
+ stopped = 1;
+ break;
+
+ case 's':
+ audioStop(fd);
+ printf("playback stopped\n");
+ stopped = 1;
+ break;
+
+ case 'c':
+ audioContinue(fd);
+ printf("playback continued\n");
+ stopped = 0;
+ break;
+
+ case 'p':
+ audioPlay(fd);
+ printf("playback started\n");
+ stopped = 0;
+ break;
+
+ case 'm':
+ if (mute==false)mute=true;
+ else mute=false;
+ audioSetMute(fd,mute);
+ printf("mute %d\n",mute);
+ break;
+
+ case 'a':
+ if (sync==false)sync=true;
+ else sync=false;
+ audioSetAVSync(fd,sync);
+ printf("AV sync %d\n",sync);
+ stopped = 0;
+ break;
+
+ case 'q':
+ audioContinue(fd);
+ exit(0);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+
+}
+
+
+main(int argc, char **argv)
+{
+ int fd;
+ int filefd;
+ boolean mute = false;
+ boolean sync = false;
+
+ if (argc < 2) return -1;
+
+ if ( (filefd = open(argv[1],O_RDONLY)) < 0){
+ perror("File open:");
+ return -1;
+ }
+
+ if((fd = open("/dev/ost/audio",O_RDWR|O_NONBLOCK)) < 0){
+ perror("AUDIO DEVICE: ");
+ return -1;
+ }
+
+
+
+ audioSetMute(fd,mute);
+ // audioSetBypassMode(fd,false); // not implemented
+ //audioContinue(fd);
+ audioSelectSource(fd,AUDIO_SOURCE_MEMORY);
+ audioPlay(fd);
+ //sleep(4);
+ //audioPause(fd);
+ //sleep(3);
+ //audioContinue(fd);
+ //sleep(3);
+ //audioStop(fd);
+ //audioChannelSelect(fd,AUDIO_STEREO);
+ //audioSetAVSync(fd,sync);
+ audioGetStatus(fd);
+
+ play_file_audio(filefd,fd);
+
+ close(fd);
+ return 0;
+
+
+}
+
diff --git a/test/test_av.c b/test/test_av.c
new file mode 100644
index 0000000..5d77000
--- /dev/null
+++ b/test/test_av.c
@@ -0,0 +1,574 @@
+/*
+ * test_av.c - Test for audio and video MPEG decoder API.
+ *
+ * Copyright (C) 2000 - 2002 convergence GmbH
+ * Ralph Metzler <rjkm@convergence.de>
+ * Marcus Metzler <mocm@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/dvb/audio.h>
+#include <linux/dvb/video.h>
+
+int audioStop(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, AUDIO_STOP) == -1)
+ perror("AUDIO_STOP");
+ return 0;
+}
+
+int audioPlay(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, AUDIO_PLAY) == -1)
+ perror("AUDIO_PLAY");
+ return 0;
+}
+
+int audioPause(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, AUDIO_PAUSE) == -1)
+ perror("AUDIO_PAUSE");
+ return 0;
+}
+
+
+int audioContinue(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, AUDIO_CONTINUE) == -1)
+ perror("AUDIO_CONTINUE");
+ return 0;
+}
+
+int audioSelectSource(int fd, char *arg)
+{
+ int source;
+ if (!arg)
+ return -1;
+ source = atoi(arg);
+ if (ioctl(fd, AUDIO_SELECT_SOURCE, source) == -1)
+ perror("AUDIO_SELECT_SOURCE");
+ return 0;
+}
+
+int audioSetMute(int fd, char *arg)
+{
+ int mute;
+ if (!arg)
+ return -1;
+ mute = atoi(arg);
+ if (ioctl(fd, AUDIO_SET_MUTE, mute) == -1)
+ perror("AUDIO_SET_MUTE");
+ return 0;
+}
+
+int audioSetAVSync(int fd, char *arg)
+{
+ int sync;
+ if (!arg)
+ return -1;
+ sync = atoi(arg);
+ if (ioctl(fd, AUDIO_SET_AV_SYNC, sync) == -1)
+ perror("AUDIO_SET_AV_SYNC");
+ return 0;
+}
+
+int audioSetBypassMode(int fd, char *arg)
+{
+ int byp;
+ if (!arg)
+ return -1;
+ byp = atoi(arg);
+ if (ioctl(fd, AUDIO_SET_BYPASS_MODE, byp) == -1)
+ perror("AUDIO_SET_BYPASS_MODE");
+ return 0;
+}
+
+int audioChannelSelect(int fd, char *arg)
+{
+ int chan;
+ if (!arg)
+ return -1;
+ chan = atoi(arg);
+ if (ioctl(fd, AUDIO_CHANNEL_SELECT, chan) == -1)
+ perror("AUDIO_CHANNEL_SELECT");
+ return 0;
+}
+
+int audioGetStatus(int fd, char *arg)
+{
+ struct audio_status stat;
+
+ if (arg)
+ return -1;
+ if (ioctl(fd, AUDIO_GET_STATUS, &stat) == -1) {
+ perror("AUDIO_GET_STATUS");
+ return 0;
+ }
+
+ printf("Audio Status:\n");
+ printf(" Sync State : %s\n",
+ (stat.AV_sync_state ? "SYNC" : "NO SYNC"));
+ printf(" Mute State : %s\n",
+ (stat.mute_state ? "muted" : "not muted"));
+ printf(" Play State : ");
+ switch ((int)stat.play_state){
+ case AUDIO_STOPPED:
+ printf("STOPPED (%d)\n",stat.play_state);
+ break;
+ case AUDIO_PLAYING:
+ printf("PLAYING (%d)\n",stat.play_state);
+ break;
+ case AUDIO_PAUSED:
+ printf("PAUSED (%d)\n",stat.play_state);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.play_state);
+ break;
+ }
+
+ printf(" Stream Source : ");
+ switch((int)stat.stream_source){
+ case AUDIO_SOURCE_DEMUX:
+ printf("DEMUX (%d)\n",stat.stream_source);
+ break;
+ case AUDIO_SOURCE_MEMORY:
+ printf("MEMORY (%d)\n",stat.stream_source);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.stream_source);
+ break;
+ }
+
+ printf(" Channel Select : ");
+ switch((int)stat.channel_select){
+ case AUDIO_STEREO:
+ printf("Stereo (%d)\n",stat.channel_select);
+ break;
+ case AUDIO_MONO_LEFT:
+ printf("Mono left(%d)\n",stat.channel_select);
+ break;
+ case AUDIO_MONO_RIGHT:
+ printf("Mono right (%d)\n",stat.channel_select);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.channel_select);
+ break;
+ }
+ printf(" Bypass Mode : %s\n",
+ (stat.bypass_mode ? "ON" : "OFF"));
+
+ return 0;
+
+}
+
+int videoStop(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_STOP) == -1)
+ perror("VIDEO_STOP");
+ return 0;
+}
+
+int videoPlay(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_PLAY) == -1)
+ perror("VIDEO_PLAY");
+ return 0;
+}
+
+
+int videoFreeze(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_FREEZE) == -1)
+ perror("VIDEO_FREEZE");
+ return 0;
+}
+
+
+int videoContinue(int fd, char *arg)
+{
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_CONTINUE) == -1)
+ perror("VIDEO_CONTINUE");
+ return 0;
+}
+
+int videoFormat(int fd, char *arg)
+{
+ int format;
+ if (!arg)
+ return -1;
+ format = atoi(arg);
+ if (ioctl(fd, VIDEO_SET_FORMAT, format) == -1)
+ perror("VIDEO_SET_FORMAT");
+ return 0;
+}
+
+int videoDisplayFormat(int fd, char *arg)
+{
+ int format;
+ if (!arg)
+ return -1;
+ format = atoi(arg);
+ if (ioctl(fd, VIDEO_SET_DISPLAY_FORMAT, format) == -1)
+ perror("VIDEO_SET_DISPLAY_FORMAT");
+ return 0;
+}
+
+int videoSelectSource(int fd, char *arg)
+{
+ int source;
+ if (!arg)
+ return -1;
+ source = atoi(arg);
+ if (ioctl(fd, VIDEO_SELECT_SOURCE, source) == -1)
+ perror("VIDEO_SELECT_SOURCE");
+ return 0;
+}
+
+
+
+int videoSetBlank(int fd, char *arg)
+{
+ int blank;
+ if (!arg)
+ return -1;
+ blank = atoi(arg);
+ if (ioctl(fd, VIDEO_SET_BLANK, blank) == -1)
+ perror("VIDEO_SET_BLANK");
+ return 0;
+}
+
+int videoFastForward(int fd, char *arg)
+{
+ int frames;
+ if (!arg)
+ return -1;
+ frames = atoi(arg);
+ if (ioctl(fd, VIDEO_FAST_FORWARD, frames) == -1)
+ perror("VIDEO_FAST_FORWARD");
+ return 0;
+}
+
+int videoSlowMotion(int fd, char *arg)
+{
+ int frames;
+ if (!arg)
+ return -1;
+ frames = atoi(arg);
+ if (ioctl(fd, VIDEO_SLOWMOTION, frames) == -1)
+ perror("VIDEO_SLOWMOTION");
+ return 0;
+}
+
+int videoGetStatus(int fd, char *arg)
+{
+ struct video_status stat;
+
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_GET_STATUS, &stat) == -1){
+ perror("VIDEO_GET_STATUS");
+ return 0;
+ }
+
+ printf("Video Status:\n");
+ printf(" Blank State : %s\n",
+ (stat.video_blank ? "BLANK" : "STILL"));
+ printf(" Play State : ");
+ switch ((int)stat.play_state){
+ case VIDEO_STOPPED:
+ printf("STOPPED (%d)\n",stat.play_state);
+ break;
+ case VIDEO_PLAYING:
+ printf("PLAYING (%d)\n",stat.play_state);
+ break;
+ case VIDEO_FREEZED:
+ printf("FREEZED (%d)\n",stat.play_state);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.play_state);
+ break;
+ }
+
+ printf(" Stream Source : ");
+ switch((int)stat.stream_source){
+ case VIDEO_SOURCE_DEMUX:
+ printf("DEMUX (%d)\n",stat.stream_source);
+ break;
+ case VIDEO_SOURCE_MEMORY:
+ printf("MEMORY (%d)\n",stat.stream_source);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.stream_source);
+ break;
+ }
+
+ printf(" Format (Aspect Ratio): ");
+ switch((int)stat.video_format){
+ case VIDEO_FORMAT_4_3:
+ printf("4:3 (%d)\n",stat.video_format);
+ break;
+ case VIDEO_FORMAT_16_9:
+ printf("16:9 (%d)\n",stat.video_format);
+ break;
+ case VIDEO_FORMAT_221_1:
+ printf("2.21:1 (%d)\n",stat.video_format);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.video_format);
+ break;
+ }
+
+ printf(" Display Format : ");
+ switch((int)stat.display_format){
+ case VIDEO_PAN_SCAN:
+ printf("Pan&Scan (%d)\n",stat.display_format);
+ break;
+ case VIDEO_LETTER_BOX:
+ printf("Letterbox (%d)\n",stat.display_format);
+ break;
+ case VIDEO_CENTER_CUT_OUT:
+ printf("Center cutout (%d)\n",stat.display_format);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.display_format);
+ break;
+ }
+ return 0;
+}
+
+int videoGetSize(int fd, char *arg)
+{
+ video_size_t size;
+
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_GET_SIZE, &size) == -1){
+ perror("VIDEO_GET_SIZE");
+ return 0;
+ }
+
+ printf("Video Size: %ux%u ", size.w, size.h);
+ switch (size.aspect_ratio) {
+ case VIDEO_FORMAT_4_3:
+ printf("4:3 (%d)\n", size.aspect_ratio);
+ break;
+ case VIDEO_FORMAT_16_9:
+ printf("16:9 (%d)\n", size.aspect_ratio);
+ break;
+ case VIDEO_FORMAT_221_1:
+ printf("2.21:1 (%d)\n", size.aspect_ratio);
+ break;
+ default:
+ printf("unknown aspect ratio (%d)\n", size.aspect_ratio);
+ break;
+ }
+ return 0;
+}
+
+int videoStillPicture(int fd, char *arg)
+{
+ int sifd;
+ struct stat st;
+ struct video_still_picture sp;
+
+ if (!arg)
+ return -1;
+ sifd = open(arg, O_RDONLY);
+ if (sifd == -1) {
+ perror("open stillimage file");
+ printf("(%s)\n", arg);
+ return 0;
+ }
+ fstat(sifd, &st);
+
+ sp.iFrame = (char *) malloc(st.st_size);
+ sp.size = st.st_size;
+ printf("I-frame size: %d\n", sp.size);
+
+ if(!sp.iFrame) {
+ printf("No memory for I-Frame\n");
+ return 0;
+ }
+
+ printf("read: %d bytes\n",read(sifd,sp.iFrame,sp.size));
+ if (ioctl(fd, VIDEO_STILLPICTURE, &sp) == -1)
+ perror("VIDEO_STILLPICTURE");
+ return 0;
+}
+
+typedef int (* cmd_func_t)(int fd, char *args);
+typedef struct {
+ char *cmd;
+ char *param_help;
+ cmd_func_t cmd_func;
+} cmd_t;
+cmd_t audio_cmds[] =
+{
+ { "stop", "", audioStop },
+ { "play", "", audioPlay },
+ { "pause", "", audioPause },
+ { "continue", "", audioContinue },
+ { "source", "n: 0 demux, 1 memory", audioSelectSource },
+ { "mute", "n: 0 unmute, 1 mute", audioSetMute },
+ { "avsync", "n: 0 unsync, 1 sync", audioSetAVSync },
+ { "bypass", "n: 0 normal, 1 bypass", audioSetBypassMode },
+ { "channel", "n: 0 stereo, 1 left, 2 right", audioChannelSelect },
+ { "status", "", audioGetStatus },
+ { NULL, NULL, NULL }
+};
+cmd_t video_cmds[] =
+{
+ { "stop", "", videoStop },
+ { "play", "", videoPlay },
+ { "freeze", "", videoFreeze },
+ { "continue", "", videoContinue },
+ { "source", "n: 0 demux, 1 memory", videoSelectSource },
+ { "blank", "n: 0 normal, 1 blank", videoSetBlank },
+ { "ff", "n: number of frames", videoFastForward },
+ { "slow", "n: number of frames", videoSlowMotion },
+ { "status", "", videoGetStatus },
+ { "size", "", videoGetSize },
+ { "stillpic", "filename", videoStillPicture},
+ { "format", "n: 0 4:3, 1 16:9", videoFormat},
+ { "dispformat", "n: 0 pan&scan, 1 letter box, 2 center cut out", videoDisplayFormat},
+ { NULL, NULL, NULL }
+};
+int usage(void)
+{
+ int i;
+ printf ("commands begin with a for audio and v for video:\n\n"
+ "q : quit\n");
+ for (i=0; audio_cmds[i].cmd; i++)
+ printf("a %s %s\n", audio_cmds[i].cmd, audio_cmds[i].param_help);
+ for (i=0; video_cmds[i].cmd; i++)
+ printf("v %s %s\n", video_cmds[i].cmd, video_cmds[i].param_help);
+ printf("\n");
+ return 0;
+}
+
+int syntax_error(void)
+{
+ fprintf(stderr, "syntax error\n");
+ return 0;
+}
+
+int process_kbd_input(int vfd, int afd)
+{
+ char buf[256], *cmd;
+ int i;
+
+ if (!fgets(buf, sizeof(buf), stdin))
+ return -1;
+ cmd = strtok(buf, " \n\t");
+ if (!cmd) {
+ printf("enter command or h + enter for help\n");
+ return 0;
+ }
+ if (cmd[0] == 'q' || !strcmp(cmd, "quit"))
+ return -1;
+ if (cmd[0] == 'h' || !strcmp(cmd, "help"))
+ return usage();
+ if (cmd[0] == 'a' || !strcmp(cmd, "audio")) {
+ cmd = strtok(NULL, " \n\t");
+ if (!cmd)
+ return syntax_error();
+ for (i=0; audio_cmds[i].cmd; i++) {
+ if (!strcmp(cmd, audio_cmds[i].cmd)) {
+ cmd = strtok(NULL, " \n\t");
+ printf("calling '%s', arg '%s'\n", audio_cmds[i].cmd, cmd);
+ if (audio_cmds[i].cmd_func(afd, cmd))
+ syntax_error();
+ return 0;
+ }
+ }
+ return syntax_error();
+ } else if (buf[0] == 'v') {
+ cmd = strtok(NULL, " \n\t");
+ if (!cmd)
+ return usage();
+ for (i=0; video_cmds[i].cmd; i++) {
+ if (!strcmp(cmd, video_cmds[i].cmd)) {
+ cmd = strtok(NULL, " \n\t");
+ printf("calling '%s', arg '%s'\n", video_cmds[i].cmd, cmd);
+ if (video_cmds[i].cmd_func(vfd, cmd))
+ syntax_error();
+ return 0;
+ }
+ }
+ return syntax_error();
+ } else
+ return syntax_error();
+ return 0;
+}
+
+int main(void)
+{
+ int vfd, afd;
+ char *videodev = "/dev/dvb/adapter0/video0";
+ char *audiodev = "/dev/dvb/adapter0/audio0";
+
+ if (getenv("VIDEO"))
+ videodev = getenv("VIDEO");
+ if (getenv("AUDIO"))
+ videodev = getenv("AUDIO");
+
+ printf("using video device '%s'\n", videodev);
+ printf("using audio device '%s'\n", audiodev);
+ printf("enter command or h + enter for help\n");
+
+ if((vfd = open(videodev, O_RDWR | O_NONBLOCK)) < 0) {
+ perror("open video device");
+ return 1;
+ }
+ if((afd = open(audiodev, O_RDWR | O_NONBLOCK)) < 0) {
+ perror("open audio device");
+ return 1;
+ }
+
+ while (process_kbd_input(vfd, afd) == 0)
+ ;
+
+ close(vfd);
+ close(afd);
+ return 0;
+}
+
diff --git a/test/test_av_play.c b/test/test_av_play.c
new file mode 100644
index 0000000..293d6d8
--- /dev/null
+++ b/test/test_av_play.c
@@ -0,0 +1,310 @@
+/*
+ * test_av_play.c - Test playing an MPEG A+V PES (e.g. VDR recordings) from a file.
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ * for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/video.h>
+#include <linux/dvb/audio.h>
+#include <sys/poll.h>
+
+static int audioPlay(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_PLAY) < 0)){
+ perror("AUDIO PLAY: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int audioSelectSource(int fd, audio_stream_source_t source)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SELECT_SOURCE, source) < 0)){
+ perror("AUDIO SELECT SOURCE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+static int audioSetMute(int fd, int state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SET_MUTE, state) < 0)){
+ perror("AUDIO SET MUTE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int audioSetAVSync(int fd, int state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,AUDIO_SET_AV_SYNC, state) < 0)){
+ perror("AUDIO SET AV SYNC: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int videoStop(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_STOP,0) < 0)){
+ perror("VIDEO STOP: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int videoPlay(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_PLAY) < 0)){
+ perror("VIDEO PLAY: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int videoFreeze(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_FREEZE) < 0)){
+ perror("VIDEO FREEZE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int videoContinue(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_CONTINUE) < 0)){
+ perror("VIDEO CONTINUE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int videoSelectSource(int fd, video_stream_source_t source)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_SELECT_SOURCE, source) < 0)){
+ perror("VIDEO SELECT SOURCE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+static int videoFastForward(int fd,int nframes)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_FAST_FORWARD, nframes) < 0)){
+ perror("VIDEO FAST FORWARD: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int videoSlowMotion(int fd,int nframes)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_SLOWMOTION, nframes) < 0)){
+ perror("VIDEO SLOWMOTION: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define BUFFY 32768
+#define NFD 2
+static void play_file_av(int filefd, int vfd, int afd)
+{
+ char buf[BUFFY];
+ int count;
+ int written;
+ struct pollfd pfd[NFD];
+ int stopped = 0;
+
+ pfd[0].fd = STDIN_FILENO;
+ pfd[0].events = POLLIN;
+
+ pfd[1].fd = vfd;
+ pfd[1].events = POLLOUT;
+
+ pfd[2].fd = afd;
+ pfd[2].events = POLLOUT;
+
+ videoSelectSource(vfd,VIDEO_SOURCE_MEMORY);
+ audioSelectSource(afd,AUDIO_SOURCE_MEMORY);
+
+ // FIXME: only seems to work if starting audio first!
+ audioPlay(afd);
+ videoPlay(vfd);
+
+ count = read(filefd,buf,BUFFY);
+ write(vfd,buf,count);
+
+ while ( (count = read(filefd,buf,BUFFY)) >= 0 ){
+ written = 0;
+ while(written < count){
+ if (poll(pfd,NFD,1)){
+ if (pfd[1].revents & POLLOUT){
+ written += write(vfd,buf+written,
+ count-written);
+ }
+ if (pfd[0].revents & POLLIN){
+ int c = getchar();
+ switch(c){
+ case 'z':
+ videoFreeze(vfd);
+ printf("playback frozen\n");
+ stopped = 1;
+ break;
+
+ case 's':
+ videoStop(vfd);
+ printf("playback stopped\n");
+ stopped = 1;
+ break;
+
+ case 'c':
+ videoContinue(vfd);
+ printf("playback continued\n");
+ stopped = 0;
+ break;
+
+ case 'p':
+ videoPlay(vfd);
+ audioPlay(afd);
+ audioSetAVSync(afd, 1);
+ audioSetMute(afd, 0);
+ printf("playback started\n");
+ stopped = 0;
+ break;
+
+ case 'f':
+ audioSetAVSync(afd, 0);
+ audioSetMute(afd, 1);
+ videoFastForward(vfd,0);
+ printf("fastforward\n");
+ stopped = 0;
+ break;
+
+ case 'm':
+ audioSetAVSync(afd, 0);
+ audioSetMute(afd, 1);
+ videoSlowMotion(vfd,2);
+ printf("slowmotion\n");
+ stopped = 0;
+ break;
+
+ case 'q':
+ videoContinue(vfd);
+ exit(0);
+ break;
+ }
+ }
+ }
+ }
+ }
+}
+
+int main(int argc, char **argv)
+{
+ int vfd, afd;
+ int filefd;
+ char *videodev = "/dev/dvb/adapter0/video0";
+ char *audiodev = "/dev/dvb/adapter0/audio0";
+
+ if (argc < 2) {
+ fprintf(stderr, "usage: test_av_play mpeg_A+V_PES_file\n");
+ return 1;
+ }
+
+ if (getenv("VIDEO"))
+ videodev = getenv("VIDEO");
+ if (getenv("AUDIO"))
+ videodev = getenv("AUDIO");
+
+ printf("using video device '%s'\n", videodev);
+ printf("using audio device '%s'\n", audiodev);
+
+ if ( (filefd = open(argv[1],O_RDONLY)) < 0){
+ perror("File open:");
+ return -1;
+ }
+ if((vfd = open(videodev,O_RDWR|O_NONBLOCK)) < 0){
+ perror("VIDEO DEVICE: ");
+ return -1;
+ }
+ if((afd = open(audiodev,O_RDWR|O_NONBLOCK)) < 0){
+ perror("AUDIO DEVICE: ");
+ return -1;
+ }
+ play_file_av(filefd, vfd, afd);
+ close(vfd);
+ close(afd);
+ close(filefd);
+ return 0;
+
+
+}
+
diff --git a/test/test_dvr.c b/test/test_dvr.c
new file mode 100644
index 0000000..4cee62f
--- /dev/null
+++ b/test/test_dvr.c
@@ -0,0 +1,164 @@
+/* test_dvr.c - Test recording a TS from the dvr device.
+ * usage: test_dvr PID [more PIDs...]
+ *
+ * Copyright (C) 2003 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+//hm, I haven't tested writing large files yet... maybe it works
+#define _LARGEFILE64_SOURCE
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+#include <inttypes.h>
+
+#include <linux/dvb/dmx.h>
+
+static unsigned long BUF_SIZE = 64 * 1024;
+static unsigned long long total_bytes;
+
+static void usage(void)
+{
+ fprintf(stderr, "usage: test_dvb file PID [more PIDs...]\n"
+ " record a partial TS stream consisting of TS packets\n"
+ " with the selected PIDs to the given file.\n"
+ " Use PID 0x2000 to record the full TS stream (if\n"
+ " the hardware supports it).\n"
+ " The demux and dvr devices used can be changed by setting\n"
+ " the environment variables DEMUX and DVR.\n"
+ " You can override the input buffer size by setting BUF_SIZE to\n"
+ " the number of bytes wanted.\n"
+ " Note: There is no output buffering, so writing to stdout is\n"
+ " not really supported, but you can try something like:\n"
+ " BUF_SIZE=188 ./test_dvr /dev/stdout 0 2>/dev/null | xxd\n"
+ " ./test_dvr /dev/stdout 0x100 0x110 2>/dev/null| xine stdin://mpeg2\n"
+ "\n");
+ exit(1);
+}
+
+
+static void process_data(int dvrfd, int tsfd)
+{
+ uint8_t buf[BUF_SIZE];
+ int bytes, b2;
+
+ bytes = read(dvrfd, buf, sizeof(buf));
+ if (bytes < 0) {
+ perror("read");
+ if (errno == EOVERFLOW)
+ return;
+ fprintf(stderr, "exiting due to read() error\n");
+ exit(1);
+ }
+ total_bytes += bytes;
+ b2 = write(tsfd, buf, bytes);
+ if (b2 == -1) {
+ perror("write");
+ exit(1);
+ } else if (b2 < bytes)
+ fprintf(stderr, "warning: read %d, but wrote only %d bytes\n", bytes, b2);
+ else
+ fprintf(stderr, "got %d bytes (%llu total)\n", bytes, total_bytes);
+}
+
+static int add_filter(unsigned int pid, const unsigned char* dmxdev)
+{
+ int fd;
+ struct dmx_pes_filter_params f;
+
+ fd = open(dmxdev, O_RDONLY);
+ if (fd == -1) {
+ perror("cannot open demux device");
+ return 1;
+ }
+
+ memset(&f, 0, sizeof(f));
+ f.pid = (uint16_t) pid;
+ f.input = DMX_IN_FRONTEND;
+ f.output = DMX_OUT_TS_TAP;
+ f.pes_type = DMX_PES_OTHER;
+ f.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl(fd, DMX_SET_PES_FILTER, &f) == -1) {
+ perror("DMX_SET_PES_FILTER");
+ return 1;
+ }
+ fprintf(stderr, "set filter for PID 0x%04x on fd %d\n", pid, fd);
+
+ //FIXME: don't leak the fd
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int dvrfd, tsfd;
+ unsigned int pid;
+ char *dmxdev = "/dev/dvb/adapter0/demux0";
+ char *dvrdev = "/dev/dvb/adapter0/dvr0";
+ int i;
+ char *chkp;
+
+ if (argc < 3)
+ usage();
+
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ if (getenv("DVR"))
+ dvrdev = getenv("DVR");
+
+ fprintf(stderr, "using '%s' and '%s'\n"
+ "writing to '%s'\n", dmxdev, dvrdev, argv[1]);
+ tsfd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0664);
+ if (tsfd == -1) {
+ perror("cannot write output file");
+ return 1;
+ }
+
+ dvrfd = open(dvrdev, O_RDONLY);
+ if (dvrfd == -1) {
+ perror("cannot open dvr device");
+ return 1;
+ }
+
+ if (getenv("BUF_SIZE") && ((BUF_SIZE = strtoul(getenv("BUF_SIZE"), NULL, 0)) > 0))
+ fprintf(stderr, "BUF_SIZE = %lu\n", BUF_SIZE);
+
+ for (i = 2; i < argc; i++) {
+ pid = strtoul(argv[i], &chkp, 0);
+ if (pid > 0x2000 || chkp == argv[i])
+ usage();
+ fprintf(stderr, "adding filter for PID 0x%04x\n", pid);
+ //FIXME: stop & close filters later...
+ if (add_filter(pid, dmxdev) != 0)
+ return 1;
+ }
+
+ for (;;) {
+ process_data(dvrfd, tsfd);
+ }
+
+ close(dvrfd);
+ return 0;
+}
+
diff --git a/test/test_dvr_play.c b/test/test_dvr_play.c
new file mode 100644
index 0000000..af963d9
--- /dev/null
+++ b/test/test_dvr_play.c
@@ -0,0 +1,144 @@
+/*
+ * test_dvr_play.c - Play TS file via dvr device.
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ * for convergence integrated media GmbH
+ * Copyright (C) 2003 Convergence GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/poll.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdlib.h>
+
+#include <linux/dvb/dmx.h>
+
+
+#define BUFSIZE (512*188)
+
+void play_file_dvr(int filefd, int dvrfd)
+{
+ char buf[BUFSIZE];
+ int count, written, bytes, total = 0;
+
+ while ((count = read(filefd, buf, BUFSIZE)) > 0) {
+ total += count;
+ fprintf(stderr, "read %d (%d total)\n", count, total);
+ written = 0;
+ while (written < count) {
+ bytes = write(dvrfd, buf + written, count - written);
+ fprintf(stderr, "write %d\n", bytes);
+ if (bytes < 0) {
+ perror("write dvr");
+ return;
+ }
+ else if (bytes == 0) {
+ fprintf(stderr, "write dvr: 0 bytes !");
+ return;
+ }
+ written += bytes;
+ }
+ }
+}
+
+void set_pid(int fd, int pid, int type)
+{
+ struct dmx_pes_filter_params pesFilterParams;
+
+ fprintf(stderr, "set PID 0x%04x (%d)\n", pid, type);
+ if (ioctl(fd, DMX_STOP) < 0)
+ perror("DMX STOP:");
+
+ if (ioctl(fd, DMX_SET_BUFFER_SIZE, 64*1024) < 0)
+ perror("DMX SET BUFFER:");
+
+ pesFilterParams.pid = pid;
+ pesFilterParams.input = DMX_IN_DVR;
+ pesFilterParams.output = DMX_OUT_DECODER;
+ pesFilterParams.pes_type = type;
+ pesFilterParams.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd, DMX_SET_PES_FILTER, &pesFilterParams) < 0)
+ perror("DMX SET FILTER");
+}
+
+int main(int argc, char **argv)
+{
+ char *dmxdev = "/dev/dvb/adapter0/demux0";
+ char *dvrdev = "/dev/dvb/adapter0/dvr0";
+ int vpid, apid;
+ int filefd, dvrfd, vfd, afd;
+
+ if (argc < 4) {
+ fprintf(stderr, "usage: test_dvr_play TS-file video-PID audio-PID\n");
+ return 1;
+ }
+ vpid = strtoul(argv[2], NULL, 0);
+ apid = strtoul(argv[3], NULL, 0);
+
+ filefd = open(argv[1], O_RDONLY);
+ if (filefd == -1) {
+ fprintf(stderr, "Failed to open '%s': %d %m\n", argv[1], errno);
+ return 1;
+ }
+
+ fprintf(stderr, "Playing '%s', video PID 0x%04x, audio PID 0x%04x\n",
+ argv[1], vpid, apid);
+
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ if (getenv("DVR"))
+ dvrdev = getenv("DVR");
+
+ if ((dvrfd = open(dvrdev, O_WRONLY)) == -1) {
+ fprintf(stderr, "Failed to open '%s': %d %m\n", dvrdev, errno);
+ return 1;
+ }
+
+ if ((vfd = open(dmxdev, O_WRONLY)) == -1) {
+ fprintf(stderr, "Failed to open video '%s': %d %m\n", dmxdev, errno);
+ return 1;
+ }
+ if ((afd = open(dmxdev, O_WRONLY)) == -1) {
+ fprintf(stderr, "Failed to open audio '%s': %d %m\n", dmxdev, errno);
+ return 1;
+ }
+
+ /* playback timing is controlled via A/V PTS, so we cannot start
+ * writing to the DVR device before the PIDs are set...
+ */
+ set_pid(afd, apid, DMX_PES_AUDIO);
+ set_pid(vfd, vpid, DMX_PES_VIDEO);
+
+ play_file_dvr(filefd, dvrfd);
+
+ close(dvrfd);
+ close(afd);
+ close(vfd);
+ close(filefd);
+ return 0;
+}
+
diff --git a/test/test_front.c b/test/test_front.c
new file mode 100644
index 0000000..1d08fc6
--- /dev/null
+++ b/test/test_front.c
@@ -0,0 +1,328 @@
+/*
+ * test_front.c - Test program for new API
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <ost/dmx.h>
+#include <ost/frontend_old.h>
+#include <ost/sec.h>
+#include <ost/audio.h>
+#include <sys/poll.h>
+
+int OSTSelftest(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,OST_SELFTEST,0) < 0)){
+ perror("OST SELF TEST: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int OSTSetPowerState(int fd, uint32_t state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,OST_SET_POWER_STATE,state) < 0)){
+ perror("OST SET POWER STATE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int OSTGetPowerState(int fd, uint32_t *state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,OST_GET_POWER_STATE,state) < 0)){
+ perror("OST GET POWER STATE: ");
+ return -1;
+ }
+
+ switch(*state){
+ case OST_POWER_ON:
+ printf("POWER ON (%d)\n",*state);
+ break;
+ case OST_POWER_STANDBY:
+ printf("POWER STANDBY (%d)\n",*state);
+ break;
+ case OST_POWER_SUSPEND:
+ printf("POWER SUSPEND (%d)\n",*state);
+ break;
+ case OST_POWER_OFF:
+ printf("POWER OFF (%d)\n",*state);
+ break;
+ default:
+ printf("unknown (%d)\n",*state);
+ break;
+ }
+
+ return 0;
+}
+
+int FEReadStatus(int fd)
+{
+ int ans;
+ feStatus stat;
+
+ if ( (ans = ioctl(fd,FE_READ_STATUS,&stat) < 0)){
+ perror("FE READ STATUS: ");
+ return -1;
+ }
+
+ if (stat & FE_HAS_POWER)
+ printf("FE HAS POWER\n");
+
+ if (stat & FE_HAS_SIGNAL)
+ printf("FE HAS SIGNAL\n");
+
+ if (stat & QPSK_SPECTRUM_INV)
+ printf("QPSK SPEKTRUM INV\n");
+
+ return 0;
+}
+
+int FEReadBER(int fd, uint32_t *ber)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_READ_BER, ber) < 0)){
+ perror("FE READ_BER: ");
+ return -1;
+ }
+ printf("BER: %d\n",*ber);
+
+ return 0;
+}
+
+int FEReadSignalStrength(int fd, int32_t *strength)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_READ_SIGNAL_STRENGTH, strength) < 0)){
+ perror("FE READ SIGNAL STRENGTH: ");
+ return -1;
+ }
+ printf("SIGNAL STRENGTH: %d\n",*strength);
+
+ return 0;
+}
+
+int FEReadSNR(int fd, int32_t *snr)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_READ_SNR, snr) < 0)){
+ perror("FE READ_SNR: ");
+ return -1;
+ }
+ printf("SNR: %d\n",*snr);
+
+ return 0;
+}
+
+
+int FEReadUncorrectedBlocks(int fd, uint32_t *ucb)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_READ_UNCORRECTED_BLOCKS, ucb) < 0)){
+ perror("FE READ UNCORRECTED BLOCKS: ");
+ return -1;
+ }
+ printf("UBLOCKS: %d\n",*ucb);
+
+ return 0;
+}
+
+int FEGetNextFrequency(int fd, uint32_t *nfr)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_GET_NEXT_FREQUENCY, nfr) < 0)){
+ perror("FE GET NEXT FREQUENCY: ");
+ return -1;
+ }
+ printf("Next Frequency: %d\n",*nfr);
+
+ return 0;
+}
+
+int FEGetNextSymbolRate(int fd, uint32_t *nsr)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_GET_NEXT_SYMBOL_RATE, nsr) < 0)){
+ perror("FE GET NEXT SYMBOL RATE: ");
+ return -1;
+ }
+ printf("Next Symbol Rate: %d\n",*nsr);
+
+ return 0;
+}
+
+int QPSKTune(int fd, struct qpskParameters *param)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,QPSK_TUNE, param) < 0)){
+ perror("QPSK TUNE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int QPSKGetEvent (int fd, struct qpskEvent *event)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,QPSK_GET_EVENT, event) < 0)){
+ perror("QPSK GET EVENT: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int QPSKFEInfo (int fd, struct qpskFrontendInfo *info)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,QPSK_FE_INFO, info) < 0)){
+ perror("QPSK FE INFO: ");
+ return -1;
+ }
+
+ printf("min Frequency : %d\n", info->minFrequency);
+ printf("max Frequency : %d\n", info->maxFrequency);
+ printf("min Symbol Rate : %d\n", info->minSymbolRate);
+ printf("max Symbol Rate : %d\n", info->maxSymbolRate);
+ printf("Hardware Type : %d\n", info->hwType);
+ printf("Hardware Version: %d\n", info->hwVersion);
+
+ return 0;
+}
+
+int SecGetStatus (int fd, struct secStatus *state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,SEC_GET_STATUS, state) < 0)){
+ perror("QPSK GET EVENT: ");
+ return -1;
+ }
+
+ switch (state->busMode){
+ case SEC_BUS_IDLE:
+ printf("SEC BUS MODE: IDLE (%d)\n",state->busMode);
+ break;
+ case SEC_BUS_BUSY:
+ printf("SEC BUS MODE: BUSY (%d)\n",state->busMode);
+ break;
+ case SEC_BUS_OFF:
+ printf("SEC BUS MODE: OFF (%d)\n",state->busMode);
+ break;
+ case SEC_BUS_OVERLOAD:
+ printf("SEC BUS MODE: OVERLOAD (%d)\n",state->busMode);
+ break;
+ default:
+ printf("SEC BUS MODE: unknown (%d)\n",state->busMode);
+ break;
+ }
+
+
+ switch (state->selVolt){
+ case SEC_VOLTAGE_OFF:
+ printf("SEC VOLTAGE: OFF (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_LT:
+ printf("SEC VOLTAGE: LT (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_13:
+ printf("SEC VOLTAGE: 13 (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_13_5:
+ printf("SEC VOLTAGE: 13.5 (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_18:
+ printf("SEC VOLTAGE: 18 (%d)\n",state->selVolt);
+ break;
+ case SEC_VOLTAGE_18_5:
+ printf("SEC VOLTAGE: 18.5 (%d)\n",state->selVolt);
+ break;
+ default:
+ printf("SEC VOLTAGE: unknown (%d)\n",state->selVolt);
+ break;
+ }
+
+ printf("SEC CONT TONE: %s\n", (state->contTone ? "ON" : "OFF"));
+ return 0;
+}
+
+
+main(int argc, char **argv)
+{
+ int fd,fd_sec;
+ uint32_t state;
+ int32_t strength;
+ struct qpskFrontendInfo info;
+ struct secStatus sec_state;
+
+ if((fd = open("/dev/ost/qpskfe",O_RDWR)) < 0){
+ perror("FRONTEND DEVICE: ");
+ return -1;
+ }
+ if((fd_sec = open("/dev/ost/sec",O_RDWR)) < 0){
+ perror("SEC DEVICE: ");
+ return -1;
+ }
+
+ OSTSelftest(fd);
+ OSTSetPowerState(fd, OST_POWER_ON);
+ OSTGetPowerState(fd, &state);
+ FEReadStatus(fd);
+ FEReadBER(fd, &state);
+ FEReadSignalStrength(fd, &strength);
+ FEReadSNR(fd, &state);
+ FEReadUncorrectedBlocks(fd, &state);
+ state = 12567000;
+ FEGetNextFrequency(fd, &state);
+ FEGetNextSymbolRate(fd, &state);
+ QPSKFEInfo (fd, &info);
+ SecGetStatus (fd_sec, &sec_state);
+
+ close(fd);
+ close(fd_sec);
+}
+
diff --git a/test/test_pes.c b/test/test_pes.c
new file mode 100644
index 0000000..bd5a53e
--- /dev/null
+++ b/test/test_pes.c
@@ -0,0 +1,137 @@
+/* test_pes.c - Test for PES filters.
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX test_pes PID
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/dvb/dmx.h>
+
+#include "hex_dump.h"
+
+#define MAX_PES_SIZE (4*1024)
+
+
+void usage(void)
+{
+ fprintf(stderr, "usage: test_pes PID [filename]\n");
+ fprintf(stderr, " Print a hexdump of PES packets from PID to stdout.\n");
+ fprintf(stderr, " filename : Write binary PES data to file (no hexdump).\n");
+ fprintf(stderr, " The default demux device used can be changed\n");
+ fprintf(stderr, " using the DEMUX environment variable\n");
+ exit(1);
+}
+
+void process_pes(int fd, FILE *out)
+{
+ uint8_t buf[MAX_PES_SIZE];
+ int bytes;
+
+ bytes = read(fd, buf, sizeof(buf));
+ if (bytes < 0) {
+ if (errno == EOVERFLOW) {
+ fprintf(stderr, "read error: buffer overflow (%d)\n",
+ EOVERFLOW);
+ return;
+ }
+ else {
+ perror("read");
+ exit(1);
+ }
+ }
+ if (out == stdout) {
+ hex_dump(buf, bytes);
+ printf("\n");
+ }
+ else {
+ printf("got %d bytes\n", bytes);
+ if (fwrite(buf, 1, bytes, out) == 0)
+ perror("write output");
+ }
+}
+
+int set_filter(int fd, unsigned int pid)
+{
+ struct dmx_pes_filter_params f;
+
+ f.pid = (uint16_t) pid;
+ f.input = DMX_IN_FRONTEND;
+ f.output = DMX_OUT_TAP;
+ f.pes_type = DMX_PES_OTHER;
+ f.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd, DMX_SET_PES_FILTER, &f) == -1) {
+ perror("ioctl DMX_SET_PES_FILTER");
+ return 1;
+ }
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int dmxfd;
+ unsigned long pid;
+ char *dmxdev = "/dev/dvb/adapter0/demux0";
+ FILE *out = stdout;
+
+ if (argc != 2 && argc != 3)
+ usage();
+
+ pid = strtoul(argv[1], NULL, 0);
+ if (pid > 0x1fff)
+ usage();
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+
+ fprintf(stderr, "test_pes: using '%s'\n", dmxdev);
+ fprintf(stderr, " PID 0x%04lx\n", pid);
+
+ if (argc == 3) {
+ out = fopen(argv[2], "wb");
+ if (!out) {
+ perror("open output file");
+ exit(1);
+ }
+ fprintf(stderr, " output to '%s'\n", argv[2]);
+ }
+
+ if ((dmxfd = open(dmxdev, O_RDWR)) < 0){
+ perror("open");
+ return 1;
+ }
+
+ if (set_filter(dmxfd, pid) != 0)
+ return 1;
+
+ for (;;) {
+ process_pes(dmxfd, out);
+ }
+
+ close(dmxfd);
+ return 0;
+}
diff --git a/test/test_sec_ne.c b/test/test_sec_ne.c
new file mode 100644
index 0000000..9fcc8b3
--- /dev/null
+++ b/test/test_sec_ne.c
@@ -0,0 +1,165 @@
+/* test_sec_ne.c - Test for Not-Equal section filters.
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX test_sec_ne pid [tid [tid_ext]]
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/dvb/dmx.h>
+
+#include "hex_dump.h"
+
+#define MAX_SECTION_SIZE 8192
+
+static unsigned int version_number;
+
+void usage(void)
+{
+ fprintf(stderr, "usage: test_sec_ne pid [tid [tid_ext]]\n");
+ fprintf(stderr, " Read the version_number from the first section\n");
+ fprintf(stderr, " and sec a filter to wait for it to change.\n");
+ fprintf(stderr, " The default demux device used can be changed\n");
+ fprintf(stderr, " using the DEMUX environment variable;\n");
+ exit(1);
+}
+
+
+void process_section(int fd)
+{
+ uint8_t buf[MAX_SECTION_SIZE];
+ int bytes;
+
+ bytes = read(fd, buf, sizeof(buf));
+ if (bytes < 0) {
+ perror("read");
+ if (bytes != ETIMEDOUT)
+ exit(1);
+ }
+ hex_dump(buf, bytes);
+ version_number = ((buf[5] >> 1) & 0x1f);
+ printf("current version_number: %u\n\n", version_number);
+}
+
+int set_filter(int fd, unsigned int pid, unsigned int tid,
+ unsigned int tid_ext, unsigned int version_number)
+{
+ struct dmx_sct_filter_params f;
+ unsigned long bufsz;
+
+ if (getenv("BUFFER")) {
+ bufsz=strtoul(getenv("BUFFER"), NULL, 0);
+ if (bufsz > 0 && bufsz <= MAX_SECTION_SIZE) {
+ fprintf(stderr, "DMX_SET_BUFFER_SIZE %lu\n", bufsz);
+ if (ioctl(fd, DMX_SET_BUFFER_SIZE, bufsz) == -1) {
+ perror("DMX_SET_BUFFER_SIZE");
+ return 1;
+ }
+ }
+ }
+ memset(&f.filter, 0, sizeof(struct dmx_filter));
+ f.pid = (uint16_t) pid;
+ if (tid < 0x100) {
+ f.filter.filter[0] = (uint8_t) tid;
+ f.filter.mask[0] = 0xff;
+ }
+ if (tid_ext < 0x10000) {
+ f.filter.filter[1] = (uint8_t) (tid_ext >> 8);
+ f.filter.filter[2] = (uint8_t) (tid_ext & 0xff);
+ f.filter.mask[1] = 0xff;
+ f.filter.mask[2] = 0xff;
+ }
+ if (version_number < 0x20) {
+ f.filter.filter[3] = (uint8_t) (version_number << 1);
+ f.filter.mask[3] = 0x3e;
+ f.filter.mode[3] = 0x3e;
+ }
+ f.timeout = 0;
+ f.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl(fd, DMX_SET_FILTER, &f) == -1) {
+ perror("DMX_SET_FILTER");
+ return 1;
+ }
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int dmxfd;
+ unsigned long pid, tid, tid_ext;
+ char * dmxdev = "/dev/dvb/adapter0/demux0";
+
+ if (argc < 2 || argc > 4)
+ usage();
+
+ pid = strtoul(argv[1], NULL, 0);
+ if (pid > 0x1fff)
+ usage();
+ if (argc > 2) {
+ tid = strtoul(argv[2], NULL, 0);
+ if (tid > 0xff)
+ usage();
+ } else
+ tid = 0x100;
+ if (argc > 3) {
+ tid_ext = strtoul(argv[3], NULL, 0);
+ if (tid_ext > 0xffff)
+ usage();
+ } else
+ tid_ext = 0x10000;
+
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ fprintf(stderr, "test_sec_ne: using '%s'\n", dmxdev);
+ fprintf(stderr, " PID 0x%04lx\n", pid);
+ if (tid < 0x100)
+ fprintf(stderr, " TID 0x%02lx\n", tid);
+ if (tid_ext < 0x10000)
+ fprintf(stderr, " TID EXT 0x%04lx\n", tid_ext);
+
+ if ((dmxfd = open(dmxdev, O_RDWR)) < 0){
+ perror("open");
+ return 1;
+ }
+
+ if (set_filter(dmxfd, pid, tid, tid_ext, 0xff) != 0)
+ return 1;
+ process_section(dmxfd);
+ while (1) {
+ if (set_filter(dmxfd, pid, tid, tid_ext, version_number) != 0)
+ return 1;
+ process_section(dmxfd);
+ }
+ for (;;) {
+ process_section(dmxfd);
+ }
+
+ close(dmxfd);
+ return 0;
+}
+
diff --git a/test/test_sections.c b/test/test_sections.c
new file mode 100644
index 0000000..d567db0
--- /dev/null
+++ b/test/test_sections.c
@@ -0,0 +1,197 @@
+/* test_sections.c - Test for section filters.
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX test_sections [PID [TID]]
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/dvb/dmx.h>
+
+#include "hex_dump.h"
+
+#define MAX_SECTION_SIZE 8192
+
+
+#if !defined(DMX_FILTER_SIZE)
+#define DMX_FILTER_SIZE 16
+#endif
+
+static void parse_filter(unsigned char* filter, const char* filter_desc)
+{
+ int filter_idx;
+ char* end_ptr;
+
+ memset(filter, '\0', DMX_FILTER_SIZE);
+
+ for (filter_idx = 1; /* Leave first byte for tid */
+ filter_idx < DMX_FILTER_SIZE-1; ++filter_idx) {
+ filter[filter_idx] = strtoul(filter_desc, &end_ptr, 0);
+
+ if (*end_ptr == '\0' || end_ptr == filter_desc)
+ break;
+
+ filter_desc = end_ptr;
+ }
+}
+
+void usage(void)
+{
+ fprintf(stderr, "usage: test_sections PID [TID] [FILTER] [MASK]\n");
+ fprintf(stderr, " The default demux device used can be changed\n");
+ fprintf(stderr, " using the DEMUX environment variable;\n");
+ fprintf(stderr, " set env BUFFER to play with DMX_SET_BUFFER_SIZE\n");
+ fprintf(stderr, "\n");
+ fprintf(stderr, " The optional filter and mask may be used to filter on\n");
+ fprintf(stderr, " additional bytes. These bytes may be given in hex or dec\n");
+ fprintf(stderr, " separated by spaces (hint: you may have to use quotes around\n");
+ fprintf(stderr, " FILTER and MASK). TID is always the first byte of the filter,\n");
+ fprintf(stderr, " and the first byte from FILTER applies to byte 3 of the section\n");
+ fprintf(stderr, " data (i.e. the first byte after the section length)\n");
+ exit(1);
+}
+
+
+void process_section(int fd)
+{
+ uint8_t buf[MAX_SECTION_SIZE];
+ int bytes;
+
+ bytes = read(fd, buf, sizeof(buf));
+ if (bytes < 0) {
+ perror("read");
+ if (errno != EOVERFLOW)
+ exit(1);
+ }
+ hex_dump(buf, bytes);
+ printf("\n");
+}
+
+int set_filter(int fd, unsigned int pid,
+ const unsigned char* filter, const unsigned char* mask)
+{
+ struct dmx_sct_filter_params f;
+ unsigned long bufsz;
+
+ if (getenv("BUFFER")) {
+ bufsz=strtoul(getenv("BUFFER"), NULL, 0);
+ if (bufsz > 0 && bufsz <= MAX_SECTION_SIZE) {
+ fprintf(stderr, "DMX_SET_BUFFER_SIZE %lu\n", bufsz);
+ if (ioctl(fd, DMX_SET_BUFFER_SIZE, bufsz) == -1) {
+ perror("DMX_SET_BUFFER_SIZE");
+ return 1;
+ }
+ }
+ }
+ memset(&f.filter, 0, sizeof(struct dmx_filter));
+ f.pid = (uint16_t) pid;
+
+ memcpy(f.filter.filter, filter, DMX_FILTER_SIZE);
+ memcpy(f.filter.mask, mask, DMX_FILTER_SIZE);
+ f.timeout = 0;
+ f.flags = DMX_IMMEDIATE_START | DMX_CHECK_CRC;
+
+ if (ioctl(fd, DMX_SET_FILTER, &f) == -1) {
+ perror("DMX_SET_FILTER");
+ return 1;
+ }
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int dmxfd;
+ unsigned long pid, tid;
+ char * dmxdev = "/dev/dvb/adapter0/demux0";
+ unsigned char filter[DMX_FILTER_SIZE];
+ unsigned char mask[DMX_FILTER_SIZE];
+ int filter_idx;
+
+ if (argc < 2 || argc > 5)
+ usage();
+
+ pid = strtoul(argv[1], NULL, 0);
+ if (pid > 0x1fff)
+ usage();
+ if (argc > 2) {
+ tid = strtoul(argv[2], NULL, 0);
+ if (tid > 0xff)
+ usage();
+ } else
+ tid = 0x100;
+
+ if (argc > 3)
+ parse_filter(filter, argv[3]);
+ else
+ memset(filter, '\0', sizeof(filter));
+
+ if (argc > 4)
+ parse_filter(mask, argv[4]);
+ else
+ memset(mask, '\0', sizeof(mask));
+
+ if (tid < 0x100) {
+ filter[0] = tid;
+ mask[0] = 0xff;
+ }
+
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ fprintf(stderr, "test_sections: using '%s'\n", dmxdev);
+ fprintf(stderr, " PID 0x%04lx\n", pid);
+ if (tid < 0x100)
+ fprintf(stderr, " TID 0x%02lx\n", tid);
+
+
+ fprintf(stderr, " Filter ");
+
+ for (filter_idx = 0; filter_idx < DMX_FILTER_SIZE; ++filter_idx)
+ fprintf(stderr, "0x%.2x ", filter[filter_idx]);
+ fprintf(stderr, "\n");
+
+ fprintf(stderr, " Mask ");
+
+ for (filter_idx = 0; filter_idx < DMX_FILTER_SIZE; ++filter_idx)
+ fprintf(stderr, "0x%.2x ", mask[filter_idx]);
+
+ fprintf(stderr, "\n");
+
+ if ((dmxfd = open(dmxdev, O_RDWR)) < 0){
+ perror("open");
+ return 1;
+ }
+
+ if (set_filter(dmxfd, pid, filter, mask) != 0)
+ return 1;
+
+ for (;;) {
+ process_section(dmxfd);
+ }
+
+ close(dmxfd);
+ return 0;
+}
+
diff --git a/test/test_stc.c b/test/test_stc.c
new file mode 100644
index 0000000..89f141d
--- /dev/null
+++ b/test/test_stc.c
@@ -0,0 +1,74 @@
+/* test_stc.c - Test for DMX_GET_STC.
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX test_stc
+ *
+ * Copyright (C) 2003 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/dvb/dmx.h>
+
+
+void usage(void)
+{
+ fprintf(stderr, "usage: test_stc\n");
+ fprintf(stderr, " The default demux device used can be changed\n");
+ fprintf(stderr, " using the DEMUX environment variable;\n");
+ fprintf(stderr, "\n");
+ exit(1);
+}
+
+
+int main(int argc, char *argv[])
+{
+ int dmxfd;
+ char * dmxdev = "/dev/dvb/adapter0/demux0";
+ struct dmx_stc stc;
+
+ if (argc != 1 || argv[1])
+ usage();
+
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ fprintf(stderr, "test_stc: using '%s'\n", dmxdev);
+
+ if ((dmxfd = open(dmxdev, O_RDWR)) < 0) {
+ perror("open");
+ return 1;
+ }
+
+ stc.num = 0;
+ if (ioctl(dmxfd, DMX_GET_STC, &stc) == -1) {
+ perror("DMX_GET_STC");
+ return 1;
+ }
+
+ printf("STC = %llu (%llu / %u)\n", stc.stc / stc.base, stc.stc, stc.base);
+
+ close(dmxfd);
+ return 0;
+}
+
diff --git a/test/test_stillimage.c b/test/test_stillimage.c
new file mode 100644
index 0000000..264b2c4
--- /dev/null
+++ b/test/test_stillimage.c
@@ -0,0 +1,103 @@
+/* display single iframes as stillimages
+ * iframes can be created with the 'convert' tool from imagemagick
+ * and mpeg2encode from ftp.mpeg.org, and must have a supported
+ * size, e.g. 702x576:
+ * $ convert -sample 702x576\! test.jpg test.mpg
+ *
+ * or more advanced using netpbm and mpeg2enc (not mpeg2encode) :
+ * $ cat image.jpg | jpegtopnm | pnmscale -xsize=704 -ysize=576 |\
+ * ppmntsc --pal | ppmtoy4m -F 25:1 -A 4:3 |\
+ * mpeg2enc -f 7 -T 90 -F 3 -np -a 2 -o "image.mpg"
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/dvb/video.h>
+
+
+static const char *usage_string = "\n\t"
+ "usage: %s <still.mpg> [still.mpg ...]\n"
+ "\n\t"
+ "to use another videodev than the first, set the environment variable VIDEODEV\n\t"
+ "e.g.[user@linux]$ export VIDEODEV=\"/dev/dvb/adapter1/video1\".\n\t"
+ "to display the image <n> seconds, instead of 10, set the variable SSTIME\n\t"
+ "e.g. [user@linux]$ export SSTIME=\"60\" to display the still for 1 minute.\n\t"
+ "this options can be set in the same line as the %s command:\n\t"
+ "e.g. $ SSTIME=25 VIDEODEV=/dev/dvb/adapter1/video1 %s ...\n";
+
+
+int main (int argc, char **argv)
+{
+ int fd;
+ int filefd;
+ struct stat st;
+ struct video_still_picture sp;
+ char *videodev = "/dev/dvb/adapter0/video0";
+ char *env_sstime;
+ int i = 1;
+ int tsec = 10;
+
+ if (argc < 2) {
+ fprintf (stderr, usage_string, argv[0],argv[0],argv[0]);
+ return -1;
+ }
+
+ if (getenv ("VIDEODEV"))
+ videodev = getenv("VIDEODEV");
+
+ if (getenv ("SSTIME")) {
+ env_sstime = getenv("SSTIME");
+ tsec = atoi(env_sstime);
+ }
+
+ if ((fd = open(videodev, O_RDWR)) < 0) {
+ perror(videodev);
+ return -1;
+ }
+
+next_pic:
+ printf("I-frame : '%s'\n", argv[i]);
+ if ((filefd = open(argv[i], O_RDONLY)) < 0) {
+ perror(argv[i]);
+ return -1;
+ }
+
+ fstat(filefd, &st);
+
+ sp.iFrame = (char *) malloc (st.st_size);
+ sp.size = st.st_size;
+ printf("I-frame size: %d\n", sp.size);
+
+ if (!sp.iFrame) {
+ fprintf (stderr, "No memory for I-Frame\n");
+ return -1;
+ }
+
+ printf ("read: %d bytes\n", read(filefd, sp.iFrame, sp.size));
+ close(filefd);
+
+ if ((ioctl(fd, VIDEO_STILLPICTURE, &sp) < 0)) {
+ perror("ioctl VIDEO_STILLPICTURE");
+ return -1;
+ }
+ free(sp.iFrame);
+
+ printf("Display image %d seconds ...\n",tsec);
+ sleep(tsec);
+ printf("Done.\n");
+ if (argc > ++i)
+ goto next_pic;
+
+ return 0;
+}
+
+
diff --git a/test/test_switch.c b/test/test_switch.c
new file mode 100644
index 0000000..7f80891
--- /dev/null
+++ b/test/test_switch.c
@@ -0,0 +1,355 @@
+/*
+ * test_switch.c - Test program for new API
+ *
+ * Copyright (C) 2001 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <sys/poll.h>
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend_old.h>
+#include <linux/dvb/sec.h>
+#include <linux/dvb/video.h>
+
+int fd_frontend;
+int fd_sec;
+int fd_demuxa;
+int fd_demuxv;
+int fd_demuxtt;
+
+struct dmx_sct_filter_params sctFilterParams;
+
+struct secCommand scmd;
+struct secCmdSequence scmds;
+struct dmx_pes_filter_params pesFilterParams;
+struct dmx_pes_filter_params pesFilterParamsV;
+struct dmx_pes_filter_params pesFilterParamsA;
+struct dmx_pes_filter_params pesFilterParamsTT;
+FrontendParameters frp;
+int front_type;
+
+
+set_front(void)
+{
+ fe_status_t stat = 0;
+ int i, freq;
+ uint32_t soff;
+
+ scmds.miniCommand = SEC_MINI_NONE;
+ scmds.numCommands = 1;
+ scmds.commands = &scmd;
+
+ soff = frp.u.qpsk.SymbolRate/16000;
+
+ if (ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds) < 0)
+ perror("setfront sec");
+ usleep(100000);
+
+ freq = frp.Frequency;
+
+ while(tune_it(&frp));
+}
+
+set_diseqc_nb(int nr)
+{
+ scmd.type=0;
+ scmd.u.diseqc.addr = 0x10;
+ scmd.u.diseqc.cmd = 0x38;
+ scmd.u.diseqc.numParams = 1;
+ scmd.u.diseqc.params[0] = 0xF0 | ((nr * 4) & 0x0F) |
+ (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
+ (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
+}
+
+set_ttpid(ushort ttpid)
+{
+ if (ttpid==0 || ttpid==0xffff || ttpid==0x1fff) {
+ ioctl(fd_demuxtt, DMX_STOP, 0);
+ return;
+ }
+
+ pesFilterParamsTT.pid = ttpid;
+ pesFilterParamsTT.input = DMX_IN_FRONTEND;
+ pesFilterParamsTT.output = DMX_OUT_DECODER;
+ pesFilterParamsTT.pes_type = DMX_PES_TELETEXT;
+ pesFilterParamsTT.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd_demuxtt, DMX_SET_PES_FILTER,
+ &pesFilterParamsTT) < 0) {
+ printf("PID=%04x\n", ttpid);
+ perror("set_ttpid");
+ }
+}
+
+set_vpid(ushort vpid)
+{
+ if (vpid==0 || vpid==0xffff || vpid==0x1fff) {
+ ioctl(fd_demuxv, DMX_STOP, 0);
+ return;
+ }
+
+ pesFilterParamsV.pid = vpid;
+ pesFilterParamsV.input = DMX_IN_FRONTEND;
+ pesFilterParamsV.output = DMX_OUT_DECODER;
+ pesFilterParamsV.pes_type = DMX_PES_VIDEO;
+ pesFilterParamsV.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd_demuxv, DMX_SET_PES_FILTER,
+ &pesFilterParamsV) < 0)
+ perror("set_vpid");
+}
+
+set_apid(ushort apid)
+{
+ if (apid==0 || apid==0xffff || apid==0x1fff) {
+ ioctl(fd_demuxa, DMX_STOP, apid);
+ return;
+ }
+ pesFilterParamsA.pid = apid;
+ pesFilterParamsA.input = DMX_IN_FRONTEND;
+ pesFilterParamsA.output = DMX_OUT_DECODER;
+ pesFilterParamsA.pes_type = DMX_PES_AUDIO;
+ pesFilterParamsA.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd_demuxa, DMX_SET_PES_FILTER,
+ &pesFilterParamsA) < 0)
+ perror("set_apid");
+}
+
+int tune_it(FrontendParameters *frp)
+{
+ fe_status_t stat = 0;
+ int res;
+ FrontendEvent event;
+ int count = 0;
+ struct pollfd pfd[1];
+
+ if (ioctl(fd_frontend, FE_SET_FRONTEND, frp) <0)
+ perror("setfront front");
+
+
+
+ pfd[0].fd = fd_frontend;
+ pfd[0].events = POLLIN;
+
+ if (poll(pfd,1,3000)){
+ if (pfd[0].revents & POLLIN){
+ printf("Getting QPSK event\n");
+ if ( ioctl(fd_frontend, FE_GET_EVENT, &event)
+
+ == -EOVERFLOW){
+ perror("qpsk get event");
+ return -1;
+ }
+ printf("Received ");
+ switch(event.type){
+ case FE_UNEXPECTED_EV:
+ printf("unexpected event\n");
+ return -1;
+ case FE_FAILURE_EV:
+ printf("failure event\n");
+ return -1;
+
+ case FE_COMPLETION_EV:
+ printf("completion event\n");
+ }
+ }
+ }
+ return 0;
+}
+
+set_tp(uint *freq, int ttk, int pol, uint srate, int dis)
+{
+ if (*freq < 11700000) {
+ frp.Frequency = (*freq - 9750000);
+ scmds.continuousTone = SEC_TONE_OFF;
+ } else {
+ frp.Frequency = (*freq - 10600000);
+ scmds.continuousTone = SEC_TONE_ON;
+ }
+ if (pol) scmds.voltage = SEC_VOLTAGE_18;
+ else scmds.voltage = SEC_VOLTAGE_13;
+ set_diseqc_nb(dis);
+ frp.u.qpsk.SymbolRate = srate;
+ frp.u.qpsk.FEC_inner = 0;
+}
+
+get_front(void)
+{
+ set_vpid(0);
+ set_apid(0);
+ set_ttpid(0);
+ scmds.voltage = SEC_VOLTAGE_18;
+ scmds.miniCommand = SEC_MINI_NONE;
+ scmds.continuousTone = SEC_TONE_OFF;
+ scmds.numCommands=1;
+ scmds.commands=&scmd;
+
+ frp.Frequency=(12073000-10600000);
+ frp.u.qpsk.SymbolRate=25378000;
+ frp.u.qpsk.FEC_inner=(fe_code_rate_t)5;
+}
+
+
+void get_sect(int fd)
+{
+ u_char sec[4096];
+ int len, i;
+ uint16_t cpid = 0;
+ uint16_t length;
+ struct pollfd pfd;
+
+ pfd.fd = fd;
+ pfd.events = POLLIN;
+
+ while (1){
+ if (poll(&pfd, 1, 5000) != POLLIN) {
+ printf("not found\n");
+ printf("Timeout\n");
+ } else {
+ len = read(fd, sec, 4096);
+
+ length = (sec[1]& 0x0F)<<8;
+ length |= (sec[2]& 0xFF);
+
+
+ for (i= 0; i < length+3; i++) {
+ printf("0x%02x ",sec[i]);
+ if ( !((i+1)%8))
+ printf("\n");
+ }
+ printf("\n");
+ }
+ }
+}
+
+int FEReadStatus(int fd, fe_status_t *stat)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,FE_READ_STATUS,stat) < 0)){
+ perror("FE READ STATUS: ");
+ return -1;
+ }
+
+ if (*stat & FE_HAS_POWER)
+ printf("FE HAS POWER\n");
+
+ if (*stat & FE_HAS_SIGNAL)
+ printf("FE HAS SIGNAL\n");
+
+ if (*stat & FE_SPECTRUM_INV)
+ printf("QPSK SPEKTRUM INV\n");
+
+ return 0;
+}
+
+int has_signal()
+{
+ fe_status_t stat;
+
+ FEReadStatus(fd_frontend, &stat);
+ if (stat & FE_HAS_SIGNAL)
+ return 1;
+ else {
+ printf("Tuning failed\n");
+ return 0;
+ }
+}
+
+main()
+{
+ int freq;
+
+ fd_demuxtt = open("/dev/ost/demux", O_RDWR|O_NONBLOCK);
+ fd_frontend = open("/dev/ost/frontend", O_RDWR);
+ fd_sec = open("/dev/ost/sec", O_RDWR);
+ fd_demuxa = open("/dev/ost/demux", O_RDWR|O_NONBLOCK);
+ fd_demuxv = open("/dev/ost/demux", O_RDWR|O_NONBLOCK);
+
+// get_front();
+// set_vpid(0x7d0);
+// set_apid(0x7d2);
+// set_ttpid(0);
+// freq = 12073000;
+// set_tp(&freq, 1, 1, 25378000, 3);
+// set_diseqc_nb(dis);
+
+ scmds.voltage = SEC_VOLTAGE_18;
+// scmds.voltage = SEC_VOLTAGE_13;
+ scmds.miniCommand = SEC_MINI_NONE;
+ scmds.continuousTone = SEC_TONE_OFF;
+ scmds.numCommands=1;
+ scmds.commands=&scmd;
+ frp.Frequency = (12073000 - 10600000);
+// frp.Frequency = (11975000 - 10600000);
+ scmds.continuousTone = SEC_TONE_ON;
+ frp.u.qpsk.SymbolRate = 25378000;
+// frp.u.qpsk.SymbolRate = 27500000;
+// frp.u.qpsk.FEC_inner = FEC_AUTO;
+ frp.u.qpsk.FEC_inner = (fe_code_rate_t)5;
+ scmd.type=0;
+ scmd.u.diseqc.addr = 0x10;
+ scmd.u.diseqc.cmd = 0x38;
+ scmd.u.diseqc.numParams = 1;
+ scmd.u.diseqc.params[0] = 0xF0 | ((3 * 4) & 0x0F) |
+ (scmds.continuousTone == SEC_TONE_ON ? 1 : 0) |
+ (scmds.voltage==SEC_VOLTAGE_18 ? 2 : 0);
+
+ if (ioctl(fd_sec, SEC_SEND_SEQUENCE, &scmds) < 0)
+ perror("setfront sec");
+
+ while(tune_it(&frp));
+
+
+/*
+ if ((fd_demuxa=open("/dev/ost/demux", O_RDWR|O_NONBLOCK))
+ < 0){
+ perror("DEMUX DEVICE: ");
+ return -1;
+ }
+ memset(&sctFilterParams.filter, 0, sizeof(struct dmx_filter));
+ sctFilterParams.pid = 0x1fff;
+ sctFilterParams.filter.filter[0] = 0x00;
+ sctFilterParams.filter.mask[0] = 0x00;
+ sctFilterParams.timeout = 0;
+ sctFilterParams.flags = DMX_IMMEDIATE_START;
+
+ if (ioctl(fd_demuxa, DMX_SET_FILTER, &sctFilterParams) < 0)
+ perror("DMX SET FILTER:");
+
+
+ get_sect(fd_demuxa);
+*/
+ pesFilterParamsA.pid = 0x1fff;
+ pesFilterParamsA.input = DMX_IN_FRONTEND;
+ pesFilterParamsA.output = DMX_OUT_TS_TAP;
+ pesFilterParamsA.pes_type = DMX_PES_OTHER;
+ pesFilterParamsA.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd_demuxa, DMX_SET_PES_FILTER,
+ &pesFilterParamsA) < 0)
+ perror("set_apid");
+
+ while(1);
+}
diff --git a/test/test_tt.c b/test/test_tt.c
new file mode 100644
index 0000000..6511f39
--- /dev/null
+++ b/test/test_tt.c
@@ -0,0 +1,205 @@
+/* test_tt.c - example of using PES filter for teletext output.
+ * c.f. ETSI EN-300-472
+ *
+ * usage: DEMUX=/dev/dvb/adapterX/demuxX test_tt PID
+ *
+ * Copyright (C) 2002 convergence GmbH
+ * Johannes Stezenbach <js@convergence.de> based on code by
+ * Ralph Metzler <ralph@convergence.de> and Marcus Metzler <marcus@convergence.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#include <linux/dvb/dmx.h>
+
+#include "hex_dump.h"
+
+#define MAX_PES_SIZE (4*1024)
+
+
+uint8_t reverse[] = {
+0x00,0x80,0x40,0xC0,0x20,0xA0,0x60,0xE0,0x10,0x90,0x50,0xD0,0x30,0xB0,0x70,0xF0,
+0x08,0x88,0x48,0xC8,0x28,0xA8,0x68,0xE8,0x18,0x98,0x58,0xD8,0x38,0xB8,0x78,0xF8,
+0x04,0x84,0x44,0xC4,0x24,0xA4,0x64,0xE4,0x14,0x94,0x54,0xD4,0x34,0xB4,0x74,0xF4,
+0x0C,0x8C,0x4C,0xCC,0x2C,0xAC,0x6C,0xEC,0x1C,0x9C,0x5C,0xDC,0x3C,0xBC,0x7C,0xFC,
+0x02,0x82,0x42,0xC2,0x22,0xA2,0x62,0xE2,0x12,0x92,0x52,0xD2,0x32,0xB2,0x72,0xF2,
+0x0A,0x8A,0x4A,0xCA,0x2A,0xAA,0x6A,0xEA,0x1A,0x9A,0x5A,0xDA,0x3A,0xBA,0x7A,0xFA,
+0x06,0x86,0x46,0xC6,0x26,0xA6,0x66,0xE6,0x16,0x96,0x56,0xD6,0x36,0xB6,0x76,0xF6,
+0x0E,0x8E,0x4E,0xCE,0x2E,0xAE,0x6E,0xEE,0x1E,0x9E,0x5E,0xDE,0x3E,0xBE,0x7E,0xFE,
+0x01,0x81,0x41,0xC1,0x21,0xA1,0x61,0xE1,0x11,0x91,0x51,0xD1,0x31,0xB1,0x71,0xF1,
+0x09,0x89,0x49,0xC9,0x29,0xA9,0x69,0xE9,0x19,0x99,0x59,0xD9,0x39,0xB9,0x79,0xF9,
+0x05,0x85,0x45,0xC5,0x25,0xA5,0x65,0xE5,0x15,0x95,0x55,0xD5,0x35,0xB5,0x75,0xF5,
+0x0D,0x8D,0x4D,0xCD,0x2D,0xAD,0x6D,0xED,0x1D,0x9D,0x5D,0xDD,0x3D,0xBD,0x7D,0xFD,
+0x03,0x83,0x43,0xC3,0x23,0xA3,0x63,0xE3,0x13,0x93,0x53,0xD3,0x33,0xB3,0x73,0xF3,
+0x0B,0x8B,0x4B,0xCB,0x2B,0xAB,0x6B,0xEB,0x1B,0x9B,0x5B,0xDB,0x3B,0xBB,0x7B,0xFB,
+0x07,0x87,0x47,0xC7,0x27,0xA7,0x67,0xE7,0x17,0x97,0x57,0xD7,0x37,0xB7,0x77,0xF7,
+0x0F,0x8F,0x4F,0xCF,0x2F,0xAF,0x6F,0xEF,0x1F,0x9F,0x5F,0xDF,0x3F,0xBF,0x7F,0xFF
+};
+
+
+
+void usage(void)
+{
+ fprintf(stderr, "usage: test_tt PID\n");
+ fprintf(stderr, " The default demux device used can be changed\n");
+ fprintf(stderr, " using the DEMUX environment variable\n");
+ exit(1);
+}
+
+void safe_read(int fd, void *buf, int count)
+{
+ int bytes;
+
+ do {
+ bytes = read(fd, buf, count);
+ if (bytes < 0) {
+ if (errno == EOVERFLOW)
+ fprintf(stderr, "read error: buffer overflow (%d)\n",
+ EOVERFLOW);
+ else {
+ perror("read");
+ exit(1);
+ }
+ }
+ else if (bytes == 0) {
+ fprintf(stderr, "got EOF on demux!?\n");
+ exit(1);
+ }
+ } while (bytes < count);
+}
+
+void process_pes(int fd)
+{
+ uint8_t buf[MAX_PES_SIZE];
+ int i, plen, hlen, sid, lines, l;
+
+ /* search for start of next PES data block 0x000001bd */
+ for (;;) {
+ safe_read(fd, buf, 1);
+ if (buf[0] != 0) continue;
+ safe_read(fd, buf, 1);
+ if (buf[0] != 0) continue;
+ safe_read(fd, buf, 1);
+ if (buf[0] != 1) continue;
+ safe_read(fd, buf, 1);
+ if (buf[0] == 0xbd)
+ break;
+ }
+
+ safe_read(fd, buf, 5);
+ /* PES packet length */
+ plen = ((buf[0] << 8) | buf[1]) & 0xffff;
+
+ /* PES header data length */
+ hlen = buf[4];
+ if (hlen != 0x24) {
+ fprintf(stderr, "error: PES header data length != 0x24 (0x%02x)\n", hlen);
+ return;
+ }
+ /* skip rest of PES header */
+ safe_read(fd, buf, hlen);
+
+ /* read stream ID */
+ safe_read(fd, buf, 1);
+ sid = buf[0];
+ if (sid < 0x10 || sid > 0x1f) {
+ fprintf(stderr, "error: non-EBU stream ID 0x%02x\n", sid);
+ return;
+ }
+
+ /* number of VBI lines */
+ lines = (plen + 6) / 46 - 1;
+
+ /* read VBI data */
+ for (l = 0; l < lines; l++) {
+ safe_read(fd, buf, 46);
+ if (buf[1] != 44) {
+ fprintf(stderr, "error: VBI line has invalid length\n");
+ return;
+ }
+ /* bit twiddling */
+ for (i = 2; i < 46; i++)
+ buf[i] = reverse[buf[i]];
+ /* framing code, should be 11100100b */
+ if (buf[3] != 0x27) {
+ fprintf(stderr, "error: wrong framing code\n");
+ return;
+ }
+ /* remaining data needs to be hamming decoded, but we should
+ * be able to read some partial strings */
+ hex_dump(buf, 46);
+ printf("\n");
+ }
+}
+
+int set_filter(int fd, unsigned int pid)
+{
+ struct dmx_pes_filter_params f;
+
+ f.pid = (uint16_t) pid;
+ f.input = DMX_IN_FRONTEND;
+ f.output = DMX_OUT_TAP;
+ f.pes_type = DMX_PES_OTHER; /* DMX_PES_TELETEXT if you want vbi insertion */
+ f.flags = DMX_IMMEDIATE_START;
+ if (ioctl(fd, DMX_SET_PES_FILTER, &f) == -1) {
+ perror("ioctl DMX_SET_PES_FILTER");
+ return 1;
+ }
+ return 0;
+}
+
+
+int main(int argc, char *argv[])
+{
+ int dmxfd;
+ unsigned long pid;
+ char * dmxdev = "/dev/dvb/adapter0/demux0";
+
+ if (argc != 2)
+ usage();
+
+ pid = strtoul(argv[1], NULL, 0);
+ if (pid > 0x1fff)
+ usage();
+ if (getenv("DEMUX"))
+ dmxdev = getenv("DEMUX");
+ fprintf(stderr, "test_tt: using '%s'\n", dmxdev);
+ fprintf(stderr, " PID 0x%04lx\n", pid);
+
+ if ((dmxfd = open(dmxdev, O_RDWR)) < 0){
+ perror("open");
+ return 1;
+ }
+
+ if (set_filter(dmxfd, pid) != 0)
+ return 1;
+
+ for (;;) {
+ process_pes(dmxfd);
+ }
+
+ close(dmxfd);
+ return 0;
+}
+
diff --git a/test/test_vevent.c b/test/test_vevent.c
new file mode 100644
index 0000000..f61143e
--- /dev/null
+++ b/test/test_vevent.c
@@ -0,0 +1,125 @@
+/*
+ * test_vevent.c - Test VIDEO_GET_EVENT and poll(9 for video events
+ *
+ * Copyright (C) 2003 convergence GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/poll.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/dvb/video.h>
+
+
+int videoGetSize(int fd, char *arg)
+{
+ video_size_t size;
+
+ if (arg)
+ return -1;
+ if (ioctl(fd, VIDEO_GET_SIZE, &size) == -1){
+ perror("VIDEO_GET_SIZE");
+ return 0;
+ }
+
+ printf("Video Size: %ux%u ", size.w, size.h);
+ switch (size.aspect_ratio) {
+ case VIDEO_FORMAT_4_3:
+ printf("4:3 (%d)\n", size.aspect_ratio);
+ break;
+ case VIDEO_FORMAT_16_9:
+ printf("16:9 (%d)\n", size.aspect_ratio);
+ break;
+ case VIDEO_FORMAT_221_1:
+ printf("2.21:1 (%d)\n", size.aspect_ratio);
+ break;
+ default:
+ printf("unknown aspect ratio (%d)\n", size.aspect_ratio);
+ break;
+ }
+ return 0;
+}
+
+int main(void)
+{
+ int vfd, rc;
+ char *videodev = "/dev/dvb/adapter0/video0";
+ struct pollfd pfd[1];
+ struct video_event event;
+
+ if (getenv("VIDEO"))
+ videodev = getenv("VIDEO");
+
+ printf("using video device '%s'\n", videodev);
+
+ if((vfd = open(videodev, O_RDONLY | O_NONBLOCK)) < 0) {
+ perror("open video device");
+ return 1;
+ }
+
+ videoGetSize(vfd, NULL);
+
+ pfd[0].fd = vfd;
+ pfd[0].events = POLLPRI;
+
+ for (;;) {
+ rc = poll(pfd, 1, -1);
+ if (rc == -1) {
+ perror("poll");
+ return -1;
+ }
+ printf("poll events: %#x\n", pfd[0].revents);
+ if (pfd[0].revents & POLLPRI) {
+ rc = ioctl(vfd, VIDEO_GET_EVENT, &event);
+ if (rc == -1) {
+ perror("VIDEO_GET_EVENT");
+ return -1;
+ }
+ printf("video event %d\n", event.type);
+ if (event.type == VIDEO_EVENT_SIZE_CHANGED) {
+ printf(" VIDEO_EVENT_SIZE_CHANGED %ux%u ",
+ event.u.size.w, event.u.size.h);
+ switch (event.u.size.aspect_ratio) {
+ case VIDEO_FORMAT_4_3:
+ printf("4:3 (%d)\n", event.u.size.aspect_ratio);
+ break;
+ case VIDEO_FORMAT_16_9:
+ printf("16:9 (%d)\n", event.u.size.aspect_ratio);
+ break;
+ case VIDEO_FORMAT_221_1:
+ printf("2.21:1 (%d)\n", event.u.size.aspect_ratio);
+ break;
+ default:
+ printf("unknown aspect ratio (%d)\n",
+ event.u.size.aspect_ratio);
+ break;
+ }
+ }
+ }
+ }
+
+ close(vfd);
+ return 0;
+}
+
diff --git a/test/test_video.c b/test/test_video.c
new file mode 100644
index 0000000..09c2be1
--- /dev/null
+++ b/test/test_video.c
@@ -0,0 +1,368 @@
+/*
+ * test_video.c - Test program for new API
+ *
+ * Copyright (C) 2000 Ralph Metzler <ralph@convergence.de>
+ * & Marcus Metzler <marcus@convergence.de>
+ for convergence integrated media GmbH
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public License
+ * as published by the Free Software Foundation; either version 2.1
+ * 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 Lesser General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include <sys/ioctl.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/frontend_old.h>
+#include <linux/dvb/sec.h>
+#include <linux/dvb/video.h>
+#include <sys/poll.h>
+
+int videoStop(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_STOP,0) < 0)){
+ perror("VIDEO STOP: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int videoPlay(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_PLAY) < 0)){
+ perror("VIDEO PLAY: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int videoFreeze(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_FREEZE) < 0)){
+ perror("VIDEO FREEZE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+int videoContinue(int fd)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_CONTINUE) < 0)){
+ perror("VIDEO CONTINUE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int videoSelectSource(int fd, video_stream_source_t source)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_SELECT_SOURCE, source) < 0)){
+ perror("VIDEO SELECT SOURCE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+
+
+int videoSetBlank(int fd, boolean state)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_SET_BLANK, state) < 0)){
+ perror("VIDEO SET BLANK: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int videoFastForward(int fd,int nframes)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_FAST_FORWARD, nframes) < 0)){
+ perror("VIDEO FAST FORWARD: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int videoSlowMotion(int fd,int nframes)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_SLOWMOTION, nframes) < 0)){
+ perror("VIDEO SLOWMOTION: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+int videoGetStatus(int fd)
+{
+ struct video_status stat;
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_GET_STATUS, &stat) < 0)){
+ perror("VIDEO GET STATUS: ");
+ return -1;
+ }
+
+ printf("Video Status:\n");
+ printf(" Blank State : %s\n",
+ (stat.video_blank ? "BLANK" : "STILL"));
+ printf(" Play State : ");
+ switch ((int)stat.play_state){
+ case VIDEO_STOPPED:
+ printf("STOPPED (%d)\n",stat.play_state);
+ break;
+ case VIDEO_PLAYING:
+ printf("PLAYING (%d)\n",stat.play_state);
+ break;
+ case VIDEO_FREEZED:
+ printf("FREEZED (%d)\n",stat.play_state);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.play_state);
+ break;
+ }
+
+ printf(" Stream Source : ");
+ switch((int)stat.stream_source){
+ case VIDEO_SOURCE_DEMUX:
+ printf("DEMUX (%d)\n",stat.stream_source);
+ break;
+ case VIDEO_SOURCE_MEMORY:
+ printf("MEMORY (%d)\n",stat.stream_source);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.stream_source);
+ break;
+ }
+
+ printf(" Format (Aspect Ratio): ");
+ switch((int)stat.video_format){
+ case VIDEO_FORMAT_4_3:
+ printf("4:3 (%d)\n",stat.video_format);
+ break;
+ case VIDEO_FORMAT_16_9:
+ printf("16:9 (%d)\n",stat.video_format);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.video_format);
+ break;
+ }
+
+ printf(" Display Format : ");
+ switch((int)stat.display_format){
+ case VIDEO_PAN_SCAN:
+ printf("Pan&Scan (%d)\n",stat.display_format);
+ break;
+ case VIDEO_LETTER_BOX:
+ printf("Letterbox (%d)\n",stat.display_format);
+ break;
+ case VIDEO_CENTER_CUT_OUT:
+ printf("Center cutout (%d)\n",stat.display_format);
+ break;
+ default:
+ printf("unknown (%d)\n",stat.display_format);
+ break;
+ }
+ return 0;
+}
+
+int videoStillPicture(int fd, struct video_still_picture *sp)
+{
+ int ans;
+
+ if ( (ans = ioctl(fd,VIDEO_STILLPICTURE, sp) < 0)){
+ perror("VIDEO STILLPICTURE: ");
+ return -1;
+ }
+
+ return 0;
+}
+
+#define BUFFY 32768
+#define NFD 2
+void play_file_video(int filefd, int fd)
+{
+ char buf[BUFFY];
+ int count;
+ int written;
+ struct pollfd pfd[NFD];
+ int stopped = 0;
+ int ch;
+
+ pfd[0].fd = STDIN_FILENO;
+ pfd[0].events = POLLIN;
+
+ pfd[1].fd = fd;
+ pfd[1].events = POLLOUT;
+
+ videoSelectSource(fd,VIDEO_SOURCE_MEMORY);
+ videoPlay(fd);
+
+
+ count = read(filefd,buf,BUFFY);
+ write(fd,buf,count);
+
+ while ( (count = read(filefd,buf,BUFFY)) >= 0 ){
+ written = 0;
+ while(written < count){
+ if (poll(pfd,NFD,1)){
+ if (pfd[1].revents & POLLOUT){
+ written += write(fd,buf+written,
+ count-written);
+ }
+ if (pfd[0].revents & POLLIN){
+ int c = getchar();
+ switch(c){
+ case 'z':
+ videoFreeze(fd);
+ printf("playback frozen\n");
+ stopped = 1;
+ break;
+
+ case 's':
+ videoStop(fd);
+ printf("playback stopped\n");
+ stopped = 1;
+ break;
+
+ case 'c':
+ videoContinue(fd);
+ printf("playback continued\n");
+ stopped = 0;
+ break;
+
+ case 'p':
+ videoPlay(fd);
+ printf("playback started\n");
+ stopped = 0;
+ break;
+
+ case 'f':
+ videoFastForward(fd,0);
+ printf("fastforward\n");
+ stopped = 0;
+ break;
+
+ case 'm':
+ videoSlowMotion(fd,2);
+ printf("slowmotion\n");
+ stopped = 0;
+ break;
+
+ case 'q':
+ videoContinue(fd);
+ exit(0);
+ break;
+ }
+ }
+
+ }
+ }
+ }
+}
+
+void load_iframe(int filefd, int fd)
+{
+ struct stat st;
+ struct video_still_picture sp;
+
+ fstat(filefd, &st);
+
+ sp.iFrame = (char *) malloc(st.st_size);
+ sp.size = st.st_size;
+ printf("I-frame size: %d\n", sp.size);
+
+ if(!sp.iFrame) {
+ printf("No memory for I-Frame\n");
+ return;
+ }
+
+ printf("read: %d bytes\n",read(filefd,sp.iFrame,sp.size));
+ videoStillPicture(fd,&sp);
+
+ sleep(3);
+ videoPlay(fd);
+}
+
+main(int argc, char **argv)
+{
+ int fd;
+ int filefd;
+
+ if (argc < 2) return -1;
+
+ if ( (filefd = open(argv[1],O_RDONLY)) < 0){
+ perror("File open:");
+ return -1;
+ }
+ if((fd = open("/dev/ost/video1",O_RDWR|O_NONBLOCK)) < 0){
+ perror("VIDEO DEVICE: ");
+ return -1;
+ }
+
+
+
+
+// videoSetBlank(fd,false);
+ //videoPlay(fd);
+ //sleep(4);
+ //videoFreeze(fd);
+ //sleep(3);
+ //videoContinue(fd);
+ //sleep(3);
+ //videoStop(fd);
+ videoGetStatus(fd);
+
+
+ //load_iframe(filefd, fd);
+ play_file_video(filefd, fd);
+ close(fd);
+ close(filefd);
+ return 0;
+
+
+}
+
diff --git a/test/video.c b/test/video.c
new file mode 100644
index 0000000..ea9e4a2
--- /dev/null
+++ b/test/video.c
@@ -0,0 +1,182 @@
+ /**
+ * A tiny video watching application, just starts capturing /dev/video
+ * into /dev/fb0.
+ * Be shure to have >8Bit/pixel color resolution and r/w access for
+ * /dev/video0, /dev/fb0 and /dev/tty0 to let this work...
+ *
+ * compile with
+ *
+ * $ gcc -g -Wall -O2 -o video video.c -I../../ost/include
+ */
+
+#include <sys/mman.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <linux/fb.h>
+#include <linux/videodev.h>
+
+#define VIDEO_DEV "/dev/video0"
+#define FB_DEV "/dev/fb0"
+#define VT_DEV "/dev/tty0"
+
+static char *video_devname = VIDEO_DEV;
+
+#define min(a,b) (a) < (b) ? (a) : (b)
+
+static int zero = 0;
+static int one = 1;
+
+static struct fb_var_screeninfo fb_var;
+static struct fb_fix_screeninfo fb_fix;
+
+
+int init_fb (void)
+{
+ const char blankoff_str[] = "\033[9;0]";
+ int fd, vt_fd;
+
+ fd = open (FB_DEV, O_RDWR);
+ if (fd < 0) {
+ perror("Could not open " FB_DEV ", please check permissions\n");
+ return 1;
+ }
+
+ if ((vt_fd = open( VT_DEV, O_RDWR )) < 0) {
+ perror("Could not open " VT_DEV ", please check permissions\n");
+ return 1;
+ }
+
+ write( vt_fd, blankoff_str, strlen(blankoff_str) );
+
+ if (ioctl (fd, FBIOGET_VSCREENINFO, &fb_var) < 0) {
+ perror("Could not get variable screen information (fb_var)\n");
+ return 1;
+ }
+
+ if (ioctl (fd, FBIOGET_FSCREENINFO, &fb_fix) < 0) {
+ perror("Could not get fixed screen information (fb_fix)\n");
+ return 1;
+ }
+
+ close (fd);
+ return 0;
+}
+
+
+int init_video (int stop)
+{
+ int fd;
+ struct video_capability vcap;
+
+ if ((fd = open (video_devname, O_RDWR)) < 0) {
+ fprintf (stderr,
+ "%s: Could not open %s, please check permissions\n",
+ __FUNCTION__, video_devname);
+ return -1;
+ }
+
+ ioctl(fd, VIDIOCGCAP, &vcap);
+
+ if (ioctl(fd, VIDIOCCAPTURE, &zero) < 0) {
+ perror("Could not stop capturing (VIDIOCCAPTURE failed)\n");
+ return -2;
+ }
+
+ if (stop)
+ return 0;
+
+ {
+ struct video_buffer b;
+ b.base = (void*) fb_fix.smem_start;
+ b.width = fb_var.xres;
+ b.height = fb_var.yres;
+ b.depth = fb_var.bits_per_pixel;
+ b.bytesperline = fb_var.xres*((fb_var.bits_per_pixel+7)/8);
+ if (ioctl(fd, VIDIOCSFBUF, &b) < 0) {
+ fprintf(stderr, "VIDIOCSFBUF failed, must run as root?\n");
+ return -3;
+ }
+ }
+
+ {
+ struct video_picture p;
+ if (ioctl(fd, VIDIOCGPICT, &p) < 0) {
+ perror("VIDIOCGPICT failed\n");
+ return -4;
+ }
+ p.depth = fb_var.bits_per_pixel;
+ switch (fb_var.bits_per_pixel) {
+ case 16:
+ p.palette = VIDEO_PALETTE_RGB565;
+ break;
+ case 24:
+ p.palette = VIDEO_PALETTE_RGB24;
+ break;
+ case 32:
+ p.palette = VIDEO_PALETTE_RGB32;
+ break;
+ }
+ //p.contrast = 0x8000;
+ //p.colour = 0x6000;
+ if (ioctl(fd, VIDIOCSPICT, &p) < 0) {
+ perror("VIDIOCSPICT failed\n");
+ return -5;
+ }
+ }
+
+ {
+ struct video_window win;
+ win.width = min((__u32) vcap.maxwidth, fb_var.xres);
+ win.height = min((__u32) vcap.maxheight, fb_var.yres);
+ win.x = 0;
+ win.y = 0;
+ win.flags = 0;
+ win.clips = NULL;
+ win.clipcount = 0;
+ win.chromakey = 0;
+ if (ioctl(fd, VIDIOCSWIN, &win) < 0) {
+ perror("VIDIOCSWIN failed\n");
+ return -6;
+ }
+ }
+
+ if (ioctl(fd, VIDIOCCAPTURE, &one) < 0) {
+ perror("Could not start capturing (VIDIOCCAPTURE failed)\n");
+ return -7;
+ }
+
+ close (fd);
+
+ return 0;
+}
+
+int main (int argc, char **argv)
+{
+ int err = 0, stop = 0;
+
+ if ((err = init_fb()))
+ return err;
+
+ if ((argc == 2 && strcmp(argv[1], "stop") == 0) ||
+ (argc == 3 && strcmp(argv[2], "stop") == 0))
+ stop = 1;
+
+ if ((argc == 2 && !stop) || argc == 3)
+ video_devname = argv[1];
+
+ if (argc != 1 && argc != 2 && !(argc == 3 && stop)) {
+ fprintf (stderr, "usage: %s <devname> <stop>\n", argv[0]);
+ exit (-1);
+ }
+
+ return init_video (stop);
+}
+