Changeset 3084
- Timestamp:
- 06/22/09 23:18:09 (8 months ago)
- Location:
- trunk/tvheadend/src/dvb
- Files:
-
- 3 modified
-
dvb.h (modified) (1 diff)
-
dvb_multiplex.c (modified) (1 diff)
-
dvb_tables.c (modified) (18 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/tvheadend/src/dvb/dvb.h
r3040 r3084 57 57 time_t tdmi_time; 58 58 LIST_HEAD(, th_dvb_table) tdmi_tables; 59 TAILQ_HEAD(, th_dvb_table) tdmi_table_queue; 59 60 60 61 enum { -
trunk/tvheadend/src/dvb/dvb_multiplex.c
r2544 r3084 129 129 TAILQ_INSERT_TAIL(tdmi->tdmi_scan_queue, tdmi, tdmi_scan_link); 130 130 131 TAILQ_INIT(&tdmi->tdmi_table_queue); 132 131 133 tdmi->tdmi_transport_stream_id = tsid; 132 134 tdmi->tdmi_adapter = tda; -
trunk/tvheadend/src/dvb/dvb_tables.c
r3056 r3084 29 29 #include <stdlib.h> 30 30 #include <string.h> 31 #include <assert.h> 31 32 32 33 #include <linux/dvb/frontend.h> … … 44 45 #define TDT_CRC 0x1 45 46 #define TDT_QUICKREQ 0x2 46 #define TDT_FREE_OPAQUE 0x4 47 #define TDT_INC_TABLE_HDR 0x8 48 49 static int tid_tally; 50 47 #define TDT_INC_TABLE_HDR 0x4 48 49 static int tdt_id_tally; 51 50 52 51 /** … … 54 53 */ 55 54 typedef struct th_dvb_table { 55 /** 56 * Flags, must never be changed after creation. 57 * We inspect it without holding global_lock 58 */ 59 int tdt_flags; 60 61 /** 62 * Cycle queue 63 * Tables that did not get a fd or filter in hardware will end up here 64 * waiting for any other table to be received so it can reuse that fd. 65 * Only linked if fd == -1 66 */ 67 TAILQ_ENTRY(th_dvb_table) tdt_pending_link; 68 69 /** 70 * File descriptor for filter 71 */ 72 int tdt_fd; 73 56 74 LIST_ENTRY(th_dvb_table) tdt_link; 75 57 76 char *tdt_name; 58 77 … … 61 80 uint8_t tableid, void *opaque); 62 81 63 int tdt_fd;64 82 65 83 int tdt_count; 84 int tdt_pid; 85 86 struct dmx_sct_filter_params *tdt_fparams; 87 66 88 int tdt_id; 67 int tdt_pid; 68 int tdt_flags; 89 69 90 } th_dvb_table_t; 70 91 … … 109 130 * 110 131 */ 132 static void 133 tdt_open_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) 134 { 135 th_dvb_adapter_t *tda = tdmi->tdmi_adapter; 136 struct epoll_event e; 137 138 assert(tdt->tdt_fd == -1); 139 TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); 140 141 tdt->tdt_fd = open(tda->tda_demux_path, O_RDWR); 142 143 if(tdt->tdt_fd != -1) { 144 145 tdt->tdt_id = ++tdt_id_tally; 146 147 e.events = EPOLLIN; 148 e.data.u64 = ((uint64_t)tdt->tdt_fd << 32) | tdt->tdt_id; 149 150 if(epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_ADD, tdt->tdt_fd, &e)) { 151 close(tdt->tdt_fd); 152 tdt->tdt_fd = -1; 153 } else { 154 if(ioctl(tdt->tdt_fd, DMX_SET_FILTER, tdt->tdt_fparams)) { 155 close(tdt->tdt_fd); 156 tdt->tdt_fd = -1; 157 } 158 } 159 } 160 161 if(tdt->tdt_fd == -1) 162 TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); 163 } 164 165 166 /** 167 * Close FD for the given table and put table on the pending list 168 */ 169 static void 170 tdt_close_fd(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt) 171 { 172 th_dvb_adapter_t *tda = tdmi->tdmi_adapter; 173 174 assert(tdt->tdt_fd != -1); 175 176 epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL); 177 close(tdt->tdt_fd); 178 179 tdt->tdt_fd = -1; 180 TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); 181 } 182 183 184 /** 185 * 186 */ 187 static void 188 dvb_proc_table(th_dvb_mux_instance_t *tdmi, th_dvb_table_t *tdt, uint8_t *sec, 189 int r) 190 { 191 int chkcrc = tdt->tdt_flags & TDT_INC_TABLE_HDR; 192 int tableid, len; 193 uint8_t *ptr; 194 195 /* It seems some hardware (or is it the dvb API?) does not 196 honour the DMX_CHECK_CRC flag, so we check it again */ 197 if(chkcrc && psi_crc32(sec, r)) 198 return; 199 200 r -= 3; 201 tableid = sec[0]; 202 len = ((sec[1] & 0x0f) << 8) | sec[2]; 203 204 if(len < r) 205 return; 206 207 ptr = &sec[3]; 208 if(chkcrc) len -= 4; /* Strip trailing CRC */ 209 210 if(tdt->tdt_flags & TDT_INC_TABLE_HDR) 211 tdt->tdt_callback(tdmi, sec, len + 3, tableid, tdt->tdt_opaque); 212 else 213 tdt->tdt_callback(tdmi, ptr, len, tableid, tdt->tdt_opaque); 214 215 dvb_table_fastswitch(tdmi); 216 } 217 218 /** 219 * 220 */ 111 221 static void * 112 222 dvb_table_input(void *aux) 113 223 { 114 224 th_dvb_adapter_t *tda = aux; 115 int r, i, tid, fd, tableid, len,x;225 int r, i, tid, fd, x; 116 226 struct epoll_event ev[1]; 117 uint8_t sec[4096] , *ptr;227 uint8_t sec[4096]; 118 228 th_dvb_mux_instance_t *tdmi; 119 229 th_dvb_table_t *tdt; 120 int chkcrc;121 230 122 231 while(1) { 123 232 x = epoll_wait(tda->tda_table_epollfd, ev, sizeof(ev) / sizeof(ev[0]), -1); 233 124 234 for(i = 0; i < x; i++) { 235 236 tid = ev[i].data.u64 & 0xffffffff; 237 fd = ev[i].data.u64 >> 32; 238 239 if(!(ev[i].events & EPOLLIN)) 240 continue; 241 242 if((r = read(fd, sec, sizeof(sec))) < 3) 243 continue; 244 245 pthread_mutex_lock(&global_lock); 246 tdmi = tda->tda_mux_current; 125 247 126 chkcrc = ev[i].data.u64 & 1; 127 fd = (ev[i].data.u64 >> 16) & 0xffff; 128 tid = ev[i].data.u64 >> 32; 129 130 if(ev[i].events & EPOLLIN) { 131 132 if((r = read(fd, sec, sizeof(sec))) < 3) 133 continue; 134 135 /* It seems some hardware (or is it the dvb API?) does not 136 honour the DMX_CHECK_CRC flag, so we check it again */ 137 if(chkcrc && psi_crc32(sec, r)) 138 continue; 139 140 r -= 3; 141 tableid = sec[0]; 142 len = ((sec[1] & 0x0f) << 8) | sec[2]; 143 144 if(len < r) 145 continue; 146 147 ptr = &sec[3]; 148 if(chkcrc) len -= 4; /* Strip trailing CRC */ 149 150 pthread_mutex_lock(&global_lock); 151 152 tdmi = tda->tda_mux_current; 153 154 LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) 155 if(tdt->tdt_id == tid) 156 break; 157 158 if(tdt != NULL) { 159 if(tdt->tdt_flags & TDT_INC_TABLE_HDR) 160 tdt->tdt_callback(tdmi, sec, len + 3, tableid, tdt->tdt_opaque); 161 else 162 tdt->tdt_callback(tdmi, ptr, len, tableid, tdt->tdt_opaque); 163 dvb_table_fastswitch(tdmi); 248 LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) 249 if(tdt->tdt_id == tid) 250 break; 251 252 if(tdt != NULL) { 253 dvb_proc_table(tdmi, tdt, sec, r); 254 255 /* Any tables pending (that wants a filter/fd) */ 256 if(TAILQ_FIRST(&tdmi->tdmi_table_queue) != NULL) { 257 tdt_close_fd(tdmi, tdt); 258 259 tdt = TAILQ_FIRST(&tdmi->tdmi_table_queue); 260 assert(tdt != NULL); 261 262 tdt_open_fd(tdmi, tdt); 164 263 } 165 166 pthread_mutex_unlock(&global_lock);167 168 } else {169 fprintf(stderr, "%s: spurious poll event %x on fd %d\n",170 tda->tda_identifier, ev[i].events, fd);171 264 } 265 266 pthread_mutex_unlock(&global_lock); 172 267 } 173 268 } … … 188 283 } 189 284 285 190 286 /** 191 287 * 192 288 */ 193 289 static void 194 dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_table_t *tdt) 195 { 196 epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL); 197 if(tdt->tdt_flags & TDT_FREE_OPAQUE) 198 free(tdt->tdt_opaque); 290 dvb_tdt_destroy(th_dvb_adapter_t *tda, th_dvb_mux_instance_t *tdmi, 291 th_dvb_table_t *tdt) 292 { 293 LIST_REMOVE(tdt, tdt_link); 294 295 if(tdt->tdt_fd == -1) { 296 TAILQ_REMOVE(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); 297 } else { 298 epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_DEL, tdt->tdt_fd, NULL); 299 close(tdt->tdt_fd); 300 } 199 301 200 302 free(tdt->tdt_name); 201 LIST_REMOVE(tdt, tdt_link); 202 close(tdt->tdt_fd); 303 free(tdt->tdt_fparams); 203 304 free(tdt); 204 305 } … … 214 315 void (*callback)(th_dvb_mux_instance_t *tdmi, uint8_t *buf, int len, 215 316 uint8_t tableid, void *opaque), void *opaque, 216 const char *name, int flags, int pid) 217 { 218 th_dvb_adapter_t *tda = tdmi->tdmi_adapter; 219 th_dvb_table_t *tdt; 220 int fd; 221 struct epoll_event e; 222 223 LIST_FOREACH(tdt, &tdmi->tdmi_tables, tdt_link) 224 if(pid == tdt->tdt_pid) { 317 const char *name, int flags, int pid, th_dvb_table_t *tdt) 318 { 319 th_dvb_table_t *t; 320 321 LIST_FOREACH(t, &tdmi->tdmi_tables, tdt_link) { 322 if(pid == t->tdt_pid) { 323 free(tdt); 225 324 free(fparams); 226 if(flags & TDT_FREE_OPAQUE)227 free(opaque);228 325 return; 229 326 } 230 231 if((fd = open(tda->tda_demux_path, O_RDWR)) == -1) {232 free(fparams);233 if(flags & TDT_FREE_OPAQUE)234 free(opaque);235 return;236 327 } 237 328 … … 243 334 fparams->pid = pid; 244 335 245 tdt = calloc(1, sizeof(th_dvb_table_t)); 246 tdt->tdt_fd = fd; 336 337 if(tdt == NULL) 338 tdt = calloc(1, sizeof(th_dvb_table_t)); 339 247 340 tdt->tdt_name = strdup(name); 248 341 tdt->tdt_callback = callback; 249 342 tdt->tdt_opaque = opaque; 250 tdt->tdt_id = ++tid_tally;251 343 tdt->tdt_pid = pid; 252 344 tdt->tdt_flags = flags; 253 254 e.events = EPOLLIN; 255 e.data.u64 = ((uint64_t)tdt->tdt_id << 32) | (fd << 16) | 256 (flags & TDT_CRC ? 1 : 0); 257 258 epoll_ctl(tda->tda_table_epollfd, EPOLL_CTL_ADD, fd, &e); 259 260 ioctl(fd, DMX_SET_FILTER, fparams); 261 free(fparams); 345 tdt->tdt_fparams = fparams; 262 346 LIST_INSERT_HEAD(&tdmi->tdmi_tables, tdt, tdt_link); 347 tdt->tdt_fd = -1; 348 TAILQ_INSERT_TAIL(&tdmi->tdmi_table_queue, tdt, tdt_pending_link); 349 350 tdt_open_fd(tdmi, tdt); 263 351 } 264 352 … … 618 706 619 707 typedef struct ca_stream { 708 th_dvb_table_t tdt; 620 709 int cs_caid; 621 710 } ca_stream_t; … … 662 751 cs->cs_caid = caid; 663 752 tdt_add(tdmi, NULL, dvb_ca_callback, cs, "CA", 664 TDT_ FREE_OPAQUE | TDT_INC_TABLE_HDR, pid);753 TDT_INC_TABLE_HDR, pid, &cs->tdt); 665 754 break; 666 755 … … 906 995 fp->filter.mask[0] = 0xff; 907 996 tdt_add(tdmi, fp, dvb_pat_callback, NULL, "pat", 908 TDT_QUICKREQ | TDT_CRC, 0 );997 TDT_QUICKREQ | TDT_CRC, 0, NULL); 909 998 910 999 /* Conditional Access Table */ … … 914 1003 fp->filter.mask[0] = 0xff; 915 1004 tdt_add(tdmi, fp, dvb_cat_callback, NULL, "cat", 916 TDT_CRC, 1 );1005 TDT_CRC, 1, NULL); 917 1006 918 1007 /* Network Information Table */ … … 922 1011 fp->filter.mask[0] = 0xff; 923 1012 tdt_add(tdmi, fp, dvb_nit_callback, NULL, "nit", 924 TDT_QUICKREQ | TDT_CRC, 0x10 );1013 TDT_QUICKREQ | TDT_CRC, 0x10, NULL); 925 1014 926 1015 /* Service Descriptor Table */ … … 930 1019 fp->filter.mask[0] = 0xff; 931 1020 tdt_add(tdmi, fp, dvb_sdt_callback, NULL, "sdt", 932 TDT_QUICKREQ | TDT_CRC, 0x11 );1021 TDT_QUICKREQ | TDT_CRC, 0x11, NULL); 933 1022 934 1023 /* Event Information table */ … … 936 1025 fp = dvb_fparams_alloc(); 937 1026 tdt_add(tdmi, fp, dvb_eit_callback, NULL, "eit", 938 TDT_CRC, 0x12 );1027 TDT_CRC, 0x12, NULL); 939 1028 940 1029 /* Running Status Table */ … … 944 1033 fp->filter.mask[0] = 0xff; 945 1034 tdt_add(tdmi, fp, dvb_rst_callback, NULL, "rst", 946 TDT_CRC, 0x13 );1035 TDT_CRC, 0x13, NULL); 947 1036 948 1037 } … … 965 1054 fp->filter.mask[0] = 0xff; 966 1055 tdt_add(tdmi, fp, dvb_pmt_callback, t, pmtname, 967 TDT_CRC | TDT_QUICKREQ, pmt_pid );1056 TDT_CRC | TDT_QUICKREQ, pmt_pid, NULL); 968 1057 } 969 1058 … … 979 1068 980 1069 while((tdt = LIST_FIRST(&tdmi->tdmi_tables)) != NULL) 981 dvb_tdt_destroy(tda, td t);1070 dvb_tdt_destroy(tda, tdmi, tdt); 982 1071 983 1072 }