📄 dmx_tspidscan.c
字号:
/*$Id: dmx_tspidscan.c,v 1.18 2004/10/12 20:37:47 rasc Exp $ DVBSNOOP a dvb sniffer and mpeg2 stream analyzer tool http://dvbsnoop.sourceforge.net/ (c) 2001-2004 Rainer.Scherg@gmx.de (rasc) -- Brute force scan all pids on a transponder -- scanpids principle is based on the sourcefile getpids.c from 'obi'$Log: dmx_tspidscan.c,v $Revision 1.18 2004/10/12 20:37:47 rasc - Changed: TS pid filtering from file, behavior changed - New: new cmdline option -maxdmx <n> (replaces -f using pidscan) - misc. changesRevision 1.17 2004/09/01 20:20:34 rascnew cmdline option: -buffersize KB (set demux buffersize in KBytes)Revision 1.16 2004/04/05 17:32:13 rascmass typo fix adaption --> adaptationRevision 1.15 2004/01/31 01:24:26 rascPIDSCAN redesign,try to show pid content (PES streamID, SECTION tableID)Revision 1.14 2004/01/13 21:04:20 rascBUGFIX: getbits overflow fixed...Revision 1.13 2004/01/11 21:01:32 rascPES stream directory, PES restructuredRevision 1.12 2004/01/02 00:00:37 rascerror output for buffer overflowRevision 1.11 2004/01/01 20:09:23 rascDSM-CC INT/UNT descriptorsPES-sync changed, TS sync changed,descriptor scopeother changesRevision 1.10 2003/12/28 14:00:26 rascbugfix: section read from input filesome changes on packet header outputRevision 1.9 2003/12/15 22:41:28 rascpidscan improved, problems with max filters on demuxRevision 1.8 2003/12/15 22:29:27 rascpidscan improved, problems with max filters on demuxRevision 1.7 2003/12/15 20:09:48 rascno messageRevision 1.6 2003/12/14 18:29:56 rascno messageRevision 1.5 2003/12/10 23:18:10 rascimprove pidscanRevision 1.4 2003/12/10 20:07:15 rascminor stuffRevision 1.3 2003/12/09 20:34:23 rasctransponder pid-scan improved (should be sufficient now)Revision 1.2 2003/12/09 18:27:48 rascpidscan on transponderRevision 1.1 2003/12/07 23:36:13 rascpidscan on transponder- experimental(!)*/#include <fcntl.h>#include <sys/ioctl.h>#include <sys/poll.h>#include <unistd.h>#include "dvbsnoop.h"#include "strings/dvb_str.h"#include "misc/cmdline.h"#include "misc/helper.h"#include "misc/output.h"#include "dvb_api.h"#include "dmx_error.h"#include "dmx_tspidscan.h"/* * some definition */// min. buffer collect time before read/poll// has to be below timeouts!!!#define PID_TIME_WAIT 100// timeout in ms// TimoutHIGH will be used on PIDs < 0x20#define PID_TIMEOUT_LOW (250 - PID_TIME_WAIT)#define PID_TIMEOUT_HIGH (30100 - PID_TIME_WAIT)// max filters (will be checked dynamically)#define MAX_PID_FILTER 256// highest pid#define MAX_PID 0x1FFF#define TS_LEN 188#define TS_SYNC_BYTE 0x47#define TS_BUF_SIZE (TS_LEN * 2048) /* fix buffer size */enum TS_TYPE { TS_NOPID, TS_SECTION, TS_PES, TS_UNKNOWN };typedef struct _TS_PID { int count; int type; int id;} TS_PID;static TS_PID *pidArray;static int analyze_ts_pid (u_char *buf, int len);static TS_PID *ts_payload_check (u_char *b, TS_PID *tspid);int ts_pidscan (OPTION *opt){ u_char buf[TS_BUF_SIZE]; struct pollfd pfd; struct dmx_pes_filter_params flt; int *dmxfd; int timeout; int timeout_corr; int pid,pid_low; int i; int filters; int max_pid_filter; int pid_found; int rescan; indent (0); out_nl (2,""); out_nl (2,"---------------------------------------------------------"); out_nl (2,"Transponder PID-Scan..."); out_nl (2,"---------------------------------------------------------"); // -- max demux filters to use... max_pid_filter = MAX_PID_FILTER; if (opt->max_dmx_filter > 0) max_pid_filter = opt->max_dmx_filter; // -maxdmx opt // alloc pids pidArray = (TS_PID *) malloc ( (MAX_PID+1) * sizeof(TS_PID) ); if (!pidArray) { IO_error("malloc"); return -1; } for (i=0; i <= MAX_PID ; i++) { (pidArray+i)->count = 0; (pidArray+i)->type = TS_NOPID; } dmxfd = (int *) malloc(sizeof(int) * MAX_PID_FILTER); if (!dmxfd) { free (pidArray); IO_error("malloc"); return -1; } for (i = 0; i < max_pid_filter; i++) dmxfd[i] = -1; pid = 0; while (pid <= MAX_PID) { pid_low = pid; timeout_corr = 0; rescan = 0; do { pid = pid_low; // -- open DVR device for reading pfd.events = POLLIN | POLLPRI; if((pfd.fd = open(opt->devDvr,O_RDONLY|O_NONBLOCK)) < 0){ IO_error(opt->devDvr); free (pidArray); free (dmxfd); return -1; } // -- set multi PID filter // -- try to get as many dmx filters as possible // -- error messages only if filter 0 fails filters = 0; for (i = 0; (i < max_pid_filter) && (pid <= MAX_PID); i++) { if (dmxfd[i] < 0) { if ((dmxfd[i]=open(opt->devDemux,O_RDWR)) < 0) { // -- no filters??? if (i == 0) IO_error(opt->devDemux); break; } } // -- default buffer should be sufficient // ioctl (dmxfd[i],DMX_SET_BUFFER_SIZE, sizeof(buf)); // -- skip already scanned pids (rescan-mode) while ( ((pidArray+pid)->type != TS_NOPID) && (pid < MAX_PID) ) pid++; flt.pid = pid; flt.input = DMX_IN_FRONTEND; flt.output = DMX_OUT_TS_TAP; flt.pes_type = DMX_PES_OTHER; flt.flags = DMX_IMMEDIATE_START; if (ioctl(dmxfd[i], DMX_SET_PES_FILTER, &flt) < 0) { if (i == 0) IO_error("DMX_SET_PES_FILTER"); break; } pid ++; filters ++; } // -- ieek, no dmx filters available??? // -- there is something terribly wrong here... - abort if (filters == 0) { pid = MAX_PID+1; // abort criteria for loop } else { // -- calc timeout; // -- on lower pids: higher timeout // -- (e.g. TOT/TDT will be sent within 30 secs) timeout = (opt->timeout_ms) ? opt->timeout_ms : PID_TIMEOUT_LOW; if ( (pid_low) < 0x20) timeout = PID_TIMEOUT_HIGH; if (rescan) out (8,"re-"); out (8,"scanning pid 0x%04x to 0x%04x",pid_low, pid-1); out (9," (got %d dmx filters) ",filters); out_NL (8); // give read a chance to collect _some_ pids usleep ((unsigned long) PID_TIME_WAIT * 1000); pid_found = 0; if (poll(&pfd, 1, timeout) > 0) { if (pfd.revents & POLLIN) { int len; len = read(pfd.fd, buf, sizeof(buf)); if (len >= TS_LEN) { pid_found = analyze_ts_pid (buf, len); } } } // rescan should to be done? if (pid_found) { rescan++; if (rescan > filters ) rescan = 0; // abort rescans (if no TS-PUSI) } else { rescan = 0; } } // if (filters==0) // -- close dmx, filters for (i = 0; i < max_pid_filter; i++) { if (dmxfd[i] >= 0) { ioctl(dmxfd[i], DMX_STOP); // ignore any errors close(dmxfd[i]); dmxfd[i] = -1; } } close(pfd.fd); } while (rescan); // -- output for (i = pid_low; i < pid; i++) { TS_PID *p = pidArray+i; if ( p->count > 0) { out (1,"PID found: %4d (0x%04x) ",i,i); switch (p->type) { case TS_SECTION: out (3,"[SECTION: %s]",dvbstrTableID(p->id) ); break; case TS_PES: out (3,"[PES: %s]",dvbstrPESstream_ID(p->id) ); break; case TS_UNKNOWN: out (3,"[unknown]"); break; default: break; } out_NL (1); } } } // while free (dmxfd); free (pidArray); return 0;}static int analyze_ts_pid (u_char *buf, int len){ int i; int pid; int found = 0; // find TS sync byte... // SYNC ...[188 len] ...SYNC... for (i=0; i < len; i++) { if (buf[i] == TS_SYNC_BYTE) { if ((i+TS_LEN) < len) { if (buf[i+TS_LEN] != TS_SYNC_BYTE) continue; } break; } } for (; i < len; i += TS_LEN) { if (buf[i] == TS_SYNC_BYTE) { pid = getBits (buf, i, 11, 13); (pidArray+pid)->count++; if ((pidArray+pid)->type == TS_NOPID) { found = 1; ts_payload_check (buf+i, (pidArray+pid)); } } // if syncbyte } return found;}static TS_PID *ts_payload_check (u_char *b, TS_PID *tspid){ int payload_start = getBits (b, 0, 9, 1); if (payload_start != 0) { int j; int err_bit = getBits (b, 0, 8, 1); int scrambled = getBits (b, 0,24, 2); if (err_bit == 0 && scrambled == 0) { int adaptation_field_ctrl = getBits (b, 0,26, 2); j = 4; if (adaptation_field_ctrl & 0x2) j += b[j] + 1; // add adapt.field.len if (adaptation_field_ctrl & 0x1) { if (b[j]==0x00 && b[j+1]==0x00 && b[j+2]==0x01 && b[j+3]>=0xBC) { // -- PES tspid->type = TS_PES; tspid->id = b[j+3]; } else { // -- section (eval pointer field) int offset = j + b[j] +1; tspid->type = TS_SECTION; tspid->id = b[offset]; } return tspid; } } tspid->type = TS_UNKNOWN; return tspid; } return (TS_PID *) NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -