test_dvr.c 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /* test_dvr.c - Test recording a TS from the dvr device.
  2. * usage: test_dvr PID [more PIDs...]
  3. *
  4. * Copyright (C) 2003 convergence GmbH
  5. * Johannes Stezenbach <js@convergence.de>
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU Lesser General Public License
  9. * as published by the Free Software Foundation; either version 2.1
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU Lesser General Public License
  18. * along with this program; if not, write to the Free Software
  19. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  20. */
  21. //hm, I haven't tested writing large files yet... maybe it works
  22. #define _LARGEFILE64_SOURCE
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <unistd.h>
  27. #include <sys/types.h>
  28. #include <sys/stat.h>
  29. #include <fcntl.h>
  30. #include <sys/ioctl.h>
  31. #include <errno.h>
  32. #include <inttypes.h>
  33. #include <linux/dvb/dmx.h>
  34. static unsigned long BUF_SIZE = 64 * 1024;
  35. static unsigned long long total_bytes;
  36. static void usage(void)
  37. {
  38. fprintf(stderr, "usage: test_dvb file PID [more PIDs...]\n"
  39. " record a partial TS stream consisting of TS packets\n"
  40. " with the selected PIDs to the given file.\n"
  41. " Use PID 0x2000 to record the full TS stream (if\n"
  42. " the hardware supports it).\n"
  43. " The demux and dvr devices used can be changed by setting\n"
  44. " the environment variables DEMUX and DVR.\n"
  45. " You can override the input buffer size by setting BUF_SIZE to\n"
  46. " the number of bytes wanted.\n"
  47. " Note: There is no output buffering, so writing to stdout is\n"
  48. " not really supported, but you can try something like:\n"
  49. " BUF_SIZE=188 ./test_dvr /dev/stdout 0 2>/dev/null | xxd\n"
  50. " ./test_dvr /dev/stdout 0x100 0x110 2>/dev/null| xine stdin://mpeg2\n"
  51. "\n");
  52. exit(1);
  53. }
  54. static void process_data(int dvrfd, int tsfd)
  55. {
  56. uint8_t buf[BUF_SIZE];
  57. int bytes, b2;
  58. bytes = read(dvrfd, buf, sizeof(buf));
  59. if (bytes < 0) {
  60. perror("read");
  61. if (errno == EOVERFLOW)
  62. return;
  63. fprintf(stderr, "exiting due to read() error\n");
  64. exit(1);
  65. }
  66. total_bytes += bytes;
  67. b2 = write(tsfd, buf, bytes);
  68. if (b2 == -1) {
  69. perror("write");
  70. exit(1);
  71. } else if (b2 < bytes)
  72. fprintf(stderr, "warning: read %d, but wrote only %d bytes\n", bytes, b2);
  73. else
  74. fprintf(stderr, "got %d bytes (%llu total)\n", bytes, total_bytes);
  75. }
  76. static int add_filter(unsigned int pid, const char* dmxdev)
  77. {
  78. int fd;
  79. struct dmx_pes_filter_params f;
  80. fd = open(dmxdev, O_RDONLY);
  81. if (fd == -1) {
  82. perror("cannot open demux device");
  83. return 1;
  84. }
  85. memset(&f, 0, sizeof(f));
  86. f.pid = (uint16_t) pid;
  87. f.input = DMX_IN_FRONTEND;
  88. f.output = DMX_OUT_TS_TAP;
  89. f.pes_type = DMX_PES_OTHER;
  90. f.flags = DMX_IMMEDIATE_START;
  91. if (ioctl(fd, DMX_SET_PES_FILTER, &f) == -1) {
  92. perror("DMX_SET_PES_FILTER");
  93. return 1;
  94. }
  95. fprintf(stderr, "set filter for PID 0x%04x on fd %d\n", pid, fd);
  96. //FIXME: don't leak the fd
  97. return 0;
  98. }
  99. int main(int argc, char *argv[])
  100. {
  101. int dvrfd, tsfd;
  102. unsigned int pid;
  103. char *dmxdev = "/dev/dvb/adapter0/demux0";
  104. char *dvrdev = "/dev/dvb/adapter0/dvr0";
  105. int i;
  106. char *chkp;
  107. if (argc < 3)
  108. usage();
  109. if (getenv("DEMUX"))
  110. dmxdev = getenv("DEMUX");
  111. if (getenv("DVR"))
  112. dvrdev = getenv("DVR");
  113. fprintf(stderr, "using '%s' and '%s'\n"
  114. "writing to '%s'\n", dmxdev, dvrdev, argv[1]);
  115. tsfd = open(argv[1], O_WRONLY | O_CREAT | O_TRUNC | O_LARGEFILE, 0664);
  116. if (tsfd == -1) {
  117. perror("cannot write output file");
  118. return 1;
  119. }
  120. dvrfd = open(dvrdev, O_RDONLY);
  121. if (dvrfd == -1) {
  122. perror("cannot open dvr device");
  123. return 1;
  124. }
  125. if (getenv("BUF_SIZE") && ((BUF_SIZE = strtoul(getenv("BUF_SIZE"), NULL, 0)) > 0))
  126. fprintf(stderr, "BUF_SIZE = %lu\n", BUF_SIZE);
  127. for (i = 2; i < argc; i++) {
  128. pid = strtoul(argv[i], &chkp, 0);
  129. if (pid > 0x2000 || chkp == argv[i])
  130. usage();
  131. fprintf(stderr, "adding filter for PID 0x%04x\n", pid);
  132. //FIXME: stop & close filters later...
  133. if (add_filter(pid, dmxdev) != 0)
  134. return 1;
  135. }
  136. for (;;) {
  137. process_data(dvrfd, tsfd);
  138. }
  139. close(dvrfd);
  140. return 0;
  141. }