test_tapdmx.c 4.4 KB

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