📄 scan.c
字号:
break; case 0x09://ITU-T Rec. H.222.0 | ISO/IEC 13818-1/11172-1 auxiliary moreverbose(" ITU-T Rec. H.222.0 | ISO/IEC 13818-1/11172-1 auxiliary : PID 0x%04x\n", elementary_pid); break; case 0x0A://ISO/IEC 13818-6 Multiprotocol encapsulation moreverbose(" ISO/IEC 13818-6 Multiprotocol encapsulation : PID 0x%04x\n", elementary_pid); break; case 0x0B: /* Digital storage media command and control (DSM-CC) is a toolkit for control channels associated with MPEG-1 and MPEG-2 streams. It is defined in part 6 of the MPEG-2 standard (Extensions for DSM-CC). DSM-CC may be used for controlling the video reception, providing features normally found on VCR (fast-forward, rewind, pause, etc). It may also be used for a wide variety of other purposes including packet data transport. MPEG-2 ISO/IEC 13818-6 (part 6 of the MPEG-2 standard). DSM-CC defines or extends five distinct protocols: * User-User * User-Network * MPEG transport profiles (profiles to the standard MPEG transport protocol ISO/IEC 13818-1 to allow transmission of event, synchronization, download, and other information in the MPEG transport stream) * Download * Switched Digital Broadcast-Channel Change Protocol (SDB/CCP) Enables a client to remotely switch from channel to channel in a broadcast environment. Used to attach a client to a continuous-feed session (CFS) or other broadcast feed. Sometimes used in pay-per-view. */ moreverbose(" DSM-CC U-N Messages : PID 0x%04x\n", elementary_pid); break; case 0x0C://ISO/IEC 13818-6 Stream Descriptors moreverbose(" ISO/IEC 13818-6 Stream Descriptors : PID 0x%04x\n", elementary_pid); break; case 0x0D://ISO/IEC 13818-6 Sections (any type, including private data) moreverbose(" ISO/IEC 13818-6 Sections (any type, including private data) : PID 0x%04x\n", elementary_pid); break; case 0x0E://ISO/IEC 13818-1 auxiliary moreverbose(" ISO/IEC 13818-1 auxiliary : PID 0x%04x\n", elementary_pid); break; case 0x0F: moreverbose(" ADTS Audio Stream (usually AAC) : PID 0x%04x\n", elementary_pid); if (output_format == OUTPUT_VDR) break; /* not supported by VDR up to now. */ if (s->audio_num < AUDIO_CHAN_MAX) { s->audio_pid[s->audio_num] = elementary_pid; parse_descriptors (PMT, buf + 5, ES_info_len, s); s->audio_num++; } else warning("more than %i audio channels, truncating\n", AUDIO_CHAN_MAX); break; case 0x10://ISO/IEC 14496-2 Visual moreverbose(" ISO/IEC 14496-2 Visual : PID 0x%04x\n", elementary_pid); break; case 0x11: moreverbose(" ISO/IEC 14496-3 Audio with LATM transport syntax as def. in ISO/IEC 14496-3/AMD1 : PID 0x%04x\n", elementary_pid); if (output_format == OUTPUT_VDR) break; /* not supported by VDR up to now. */ if (s->audio_num < AUDIO_CHAN_MAX) { s->audio_pid[s->audio_num] = elementary_pid; parse_descriptors (PMT, buf + 5, ES_info_len, s); s->audio_num++; } else warning("more than %i audio channels, truncating\n", AUDIO_CHAN_MAX); break; case 0x12: moreverbose(" ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in PES packets : PID 0x%04x\n", elementary_pid); break; case 0x13: moreverbose(" ISO/IEC 14496-1 SL-packetized stream or FlexMux stream carried in ISO/IEC 14496 sections : PID 0x%04x\n", elementary_pid); break; case 0x14: moreverbose(" ISO/IEC 13818-6 DSM-CC synchronized download protocol : PID 0x%04x\n", elementary_pid); break; case 0x15: moreverbose(" Metadata carried in PES packets using the Metadata Access Unit Wrapper : PID 0x%04x\n", elementary_pid); break; case 0x16: moreverbose(" Metadata carried in metadata_sections : PID 0x%04x\n", elementary_pid); break; case 0x17: moreverbose(" Metadata carried in ISO/IEC 13818-6 (DSM-CC) Data Carousel : PID 0x%04x\n", elementary_pid); break; case 0x18: moreverbose(" Metadata carried in ISO/IEC 13818-6 (DSM-CC) Object Carousel : PID 0x%04x\n", elementary_pid); break; case 0x19: moreverbose(" Metadata carried in ISO/IEC 13818-6 Synchronized Download Protocol using the Metadata Access Unit Wrapper : PID 0x%04x\n", elementary_pid); break; case 0x1A: moreverbose(" IPMP stream (defined in ISO/IEC 13818-11, MPEG-2 IPMP) : PID 0x%04x\n", elementary_pid); break; case 0x1B: moreverbose(" AVC Video stream, ITU-T Rec. H.264 | ISO/IEC 14496-10 : PID 0x%04x\n", elementary_pid); if (s->video_pid == 0) { if (output_format == OUTPUT_VDR) //Offsets of 10000 are used to indicate special video codings inside VDR s->video_pid = (elementary_pid + 10000); else s->video_pid = elementary_pid; } break; case 0x81: moreverbose(" Audio per ATSC A/53B [2] Annex B : PID 0x%04x\n", elementary_pid); if (output_format == OUTPUT_VDR) break; /* not supported by VDR up to now. */ if (s->audio_num < AUDIO_CHAN_MAX) { s->audio_pid[s->audio_num] = elementary_pid; parse_descriptors (PMT, buf + 5, ES_info_len, s); s->audio_num++; } else warning("more than %i audio channels, truncating\n", AUDIO_CHAN_MAX); break; default: moreverbose(" OTHER : PID 0x%04x TYPE 0x%02x\n", elementary_pid, buf[0]); }; buf += ES_info_len + 5; section_length -= ES_info_len + 5; }; tmp = msg_buf; tmp += sprintf(tmp, "0x%04x (%.4s)", s->audio_pid[0], s->audio_lang[0]); if (s->audio_num > AUDIO_CHAN_MAX) { warning("more than %i audio channels: %i, truncating to %i\n", AUDIO_CHAN_MAX, s->audio_num, AUDIO_CHAN_MAX); s->audio_num = AUDIO_CHAN_MAX; } for (i=1; i<s->audio_num; i++) tmp += sprintf(tmp, ", 0x%04x (%.4s)", s->audio_pid[i], s->audio_lang[i]); debug("0x%04x 0x%04x: %s -- %s, pmt_pid 0x%04x, vpid 0x%04x, apid %s\n", s->transport_stream_id, s->service_id, s->provider_name, s->service_name, s->pmt_pid, s->video_pid, msg_buf);}static void parse_nit (const unsigned char *buf, int section_length, int network_id){ int descriptors_loop_len = ((buf[0] & 0x0f) << 8) | buf[1]; if (section_length < descriptors_loop_len + 4) { warning("section too short: network_id == 0x%04x, section_length == %i, " "descriptors_loop_len == %i\n", network_id, section_length, descriptors_loop_len); return; } parse_descriptors (NIT, buf + 2, descriptors_loop_len, NULL); section_length -= descriptors_loop_len + 4; buf += descriptors_loop_len + 4; while (section_length > 6) { int transport_stream_id = (buf[0] << 8) | buf[1]; struct transponder *t, tn; descriptors_loop_len = ((buf[4] & 0x0f) << 8) | buf[5]; if (section_length < descriptors_loop_len + 4) { warning("section too short: transport_stream_id == 0x%04x, " "section_length == %i, descriptors_loop_len == %i\n", transport_stream_id, section_length, descriptors_loop_len); break; } debug("transport_stream_id 0x%04x\n", transport_stream_id); memset(&tn, 0, sizeof(tn)); tn.type = -1; tn.network_id = network_id; tn.original_network_id = (buf[2] << 8) | buf[3]; /* onid patch by Hartmut Birr */ tn.transport_stream_id = transport_stream_id; parse_descriptors (NIT, buf + 6, descriptors_loop_len, &tn); if (tn.type == fe_info.type) { /* only add if develivery_descriptor matches FE type */ t = find_transponder(tn.param.frequency); if ((!t) && (add_frequencies)) { info("found new transponder (%d)\n",tn.param.frequency/1000); t = alloc_transponder(tn.param.frequency); } if (t) { info("copying transponder info (%d)\n", tn.param.frequency/1000); copy_transponder(t, &tn); } } section_length -= descriptors_loop_len + 6; buf += descriptors_loop_len + 6; };}static void parse_sdt (const unsigned char *buf, int section_length, int transport_stream_id){ buf += 3; /* skip original network id + reserved field */ while (section_length > 4) { int service_id = (buf[0] << 8) | buf[1]; int descriptors_loop_len = ((buf[3] & 0x0f) << 8) | buf[4]; struct service *s; if (section_length < descriptors_loop_len || !descriptors_loop_len) { warning("section too short: service_id == 0x%02x, section_length == %i, " "descriptors_loop_len == %i\n", service_id, section_length, descriptors_loop_len); break; } s = find_service(current_tp, service_id); if (!s) /* maybe PAT has not yet been parsed... */ s = alloc_service(current_tp, service_id); s->running = (buf[3] >> 5) & 0x7; s->scrambled = (buf[3] >> 4) & 1; parse_descriptors (SDT, buf + 5, descriptors_loop_len, s); section_length -= descriptors_loop_len + 5; buf += descriptors_loop_len + 5; };}static int get_bit (uint8_t *bitfield, int bit){ return (bitfield[bit/8] >> (bit % 8)) & 1;}static void set_bit (uint8_t *bitfield, int bit){ bitfield[bit/8] |= 1 << (bit % 8);}/** * returns 0 when more sections are expected * 1 when all sections are read on this pid * -1 on invalid table id */static int parse_section (struct section_buf *s){ const unsigned char *buf = s->buf; int table_id; int section_syntax_indicator; int section_length; int table_id_ext; int section_version_number; int current_next_indicator; int section_number; int last_section_number; int pcr_pid; int program_info_length; int i; table_id = buf[0]; if (s->table_id != table_id) return -1; section_syntax_indicator = buf[1] & 0x80; section_length = (((buf[1] & 0x0f) << 8) | buf[2]) - 11; table_id_ext = (buf[3] << 8) | buf[4]; // p.program_number section_version_number = (buf[5] >> 1) & 0x1f; // p.version_number = getBits (b, 0, 42, 5); -> 40 + 1 -> 5 bit weit? -> version_number = buf[5] & 0x3e; current_next_indicator = buf[5] & 0x01; section_number = buf[6]; last_section_number = buf[7]; pcr_pid = ((buf[8] & 0x1f) << 8) | buf[9]; program_info_length = ((buf[10] & 0x0f) << 8) | buf[11]; if (s->segmented && s->table_id_ext != -1 && s->table_id_ext != table_id_ext) { /* find or allocate actual section_buf matching table_id_ext */ while (s->next_seg) { s = s->next_seg; if (s->table_id_ext == table_id_ext) break; } if (s->table_id_ext != table_id_ext) { assert(s->next_seg == NULL); s->next_seg = calloc(1, sizeof(struct section_buf)); s->next_seg->segmented = s->segmented; s->next_seg->run_once = s->run_once; s->next_seg->timeout = s->timeout; s = s->next_seg; s->table_id = table_id; s->table_id_ext = table_id_ext; s->section_version_number = section_version_number; } } if (s->section_version_number != section_version_number || s->table_id_ext != table_id_ext) { struct section_buf *next_seg = s->next_seg; if (s->section_version_number != -1 && s->table_id_ext != -1) debug("section version_number or table_id_ext changed " "%d -> %d / %04x -> %04x\n", s->section_version_number, section_version_number, s->table_id_ext, table_id_ext); s->table_id_ext = table_id_ext; s->section_version_number = section_version_number; s->sectionfilter_done = 0; memset (s->section_done, 0, sizeof(s->section_done)); s->next_seg = next_seg; } buf += 8; if (!get_bit(s->section_done, section_number)) { set_bit (s->section_done, section_number); debug("pid 0x%02x tid 0x%02x table_id_ext 0x%04x, " "%i/%i (version %i)\n", s->pid, table_id, table_id_ext, section_number, last_section_number, section_version_number); switch (table_id) { case 0x00: verbose("PAT\n"); parse_pat (buf, section_length, table_id_ext); break; case 0x02: verbose("PMT 0x%04x for service 0x%04x\n", s->pid, table_id_ext); parse_pmt (buf, section_length, table_id_ext); break; case 0x41: verbose("////////////////////////////////////////////// NIT other\n"); case 0x40: verbose("NIT (%s TS)\n", table_id == 0x40 ? "actual":"other"); parse_nit (buf, section_length, table_id_ext); break; case 0x42: case 0x46: verbose("SDT (%s TS)\n", table_id == 0x42 ? "actual":"other"); parse_sdt (buf, section_length, table_id_ext); break; default: ; }; for (i = 0; i <= last_section_number; i++) if (get_bit (s->section_done, i) == 0) break; if (i > last_section_number) s->sectionfilter_done = 1; } if (s->segmented) { /* always wait for timeout; this is because we don't now how * many segments there are */ return 0; } else if (s->sectionfilter_done) return 1; return 0;}static int read_sections (struct section_buf *s){ int section_length, count; if (s->sectionfilter_done && !s->segmented) return 1; /* the section filter API guarantess that we get one full section * per read(), provided that the buffer is large enough (it is) */ if (((count = read (s->fd, s->buf, sizeof(s->buf))) < 0) && errno == EOVERFLOW) count = read (s->fd, s->buf, sizeof(s->buf)); if (count < 0) { errorn("read_sections: read error"); return -1; } if (count < 4) return -1; section_length = ((s->buf[1] & 0x0f) << 8) | s->buf[2]; if (count != section_length + 3) return -1; if (parse_section(s) == 1) return 1; return 0;}static LIST_HEAD(running_filters);static LIST_HEAD(waiting_filters);static int n_running;// see http://www.linuxtv.org/pipermail/linux-dvb/2005-October/005577.html:// #define MAX_RUNNING 32#define MAX_RUNNING 27static struct pollfd poll_fds[MAX_RUNNING];static struct section_buf* poll_section_bufs[MAX_RUNNING];static void setup_filter (struct section_buf* s, const char *dmx_devname, int pid, int tid, int run_once, int segmented, int timeout){ memset (s, 0, sizeof(struct section_buf)); s->fd = -1; s->dmx_devname = dmx_devname; s->pid = pid;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -