diff options
Diffstat (limited to '')
-rw-r--r-- | test/Makefile | 37 | ||||
-rw-r--r-- | test/README | 51 | ||||
-rwxr-xr-x | test/dia | 7 | ||||
-rw-r--r-- | test/diseqc.c | 140 | ||||
-rw-r--r-- | test/hex_dump.c | 63 | ||||
-rw-r--r-- | test/hex_dump.h | 28 | ||||
-rw-r--r-- | test/sendburst.c | 55 | ||||
-rw-r--r-- | test/set22k.c | 50 | ||||
-rw-r--r-- | test/setpid.c | 87 | ||||
-rw-r--r-- | test/setvoltage.c | 47 | ||||
-rw-r--r-- | test/test.c | 281 | ||||
-rw-r--r-- | test/test_audio.c | 345 | ||||
-rw-r--r-- | test/test_av.c | 574 | ||||
-rw-r--r-- | test/test_av_play.c | 310 | ||||
-rw-r--r-- | test/test_dvr.c | 164 | ||||
-rw-r--r-- | test/test_dvr_play.c | 144 | ||||
-rw-r--r-- | test/test_front.c | 328 | ||||
-rw-r--r-- | test/test_pes.c | 137 | ||||
-rw-r--r-- | test/test_sec_ne.c | 165 | ||||
-rw-r--r-- | test/test_sections.c | 197 | ||||
-rw-r--r-- | test/test_stc.c | 74 | ||||
-rw-r--r-- | test/test_stillimage.c | 103 | ||||
-rw-r--r-- | test/test_switch.c | 355 | ||||
-rw-r--r-- | test/test_tt.c | 205 | ||||
-rw-r--r-- | test/test_vevent.c | 125 | ||||
-rw-r--r-- | test/test_video.c | 368 | ||||
-rw-r--r-- | test/video.c | 182 |
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); +} + |