diff options
| author | etobi <git@e-tobi.net> | 2013-09-03 09:48:38 +0200 | 
|---|---|---|
| committer | etobi <git@e-tobi.net> | 2013-09-03 09:48:38 +0200 | 
| commit | 6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d (patch) | |
| tree | 024bef311226653bdd1da4fa588becf5098bcff7 /test | |
| download | linux-dvb-apps-6e40287e2f39a80fc72bd8d0fbc1a8334d688c2d.tar.gz | |
Imported Upstream version 1.1.0upstream/1.1.0
Diffstat (limited to 'test')
| -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); +} + | 
