|
SASC
DVBSoftCAM
|
00001 /* 00002 DVBLoopback 00003 Copyright Alan Nisota 2006 00004 00005 This file is part of DVBLoopback. 00006 00007 DVBLoopback is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 DVBLoopback is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with DVBLoopback; if not, write to the Free Software 00019 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 #ifdef USE_DSS 00022 00023 #include <stdlib.h> 00024 #include <stdio.h> 00025 #include <stdint.h> 00026 #include <fcntl.h> 00027 #include <sys/ioctl.h> 00028 #include <signal.h> 00029 #include <string.h> 00030 #include <getopt.h> 00031 #include <unistd.h> 00032 #include <errno.h> 00033 #include <assert.h> 00034 #include <pthread.h> 00035 00036 #include <netinet/in.h> 00037 00038 #include "list.h" 00039 #include <linux/dvb/dmx.h> 00040 #include <linux/dvb/frontend.h> 00041 #include "msg_passing.h" 00042 #include "process_req.h" 00043 00044 #define PLUGIN_ID 14 00045 #define DBG_NAME "DSS" 00046 #include "debug.h" //This is required to happen AFTER PLUGIN_ID is defined 00047 00048 #define DSS_SYMBOLRATE 22211000 00049 #define DSS_PMTPID 0x20 00050 #define DSS_NITPID 0x10 00051 #define DSS_NETWORKID 0x1f0f 00052 #define TS_SIZE 188 00053 #define PTS_ONLY 0x80 00054 #define PTS_DTS 0xC0 00055 00056 struct dss_hdr { 00057 int packet_framing; 00058 int bundle_boundary; 00059 int control_flag; 00060 int control_sync; 00061 int scid; 00062 int continuity_counter; 00063 int header_designator_type; 00064 int header_designator_id; 00065 int toggle_flag; 00066 }; 00067 00068 struct dss_pkt { 00069 struct list_head list; 00070 struct dss_hdr hdr; 00071 int64_t rts; 00072 uint8_t buf[184+127+1]; 00073 int buf_len; 00074 int cont; 00075 int start; 00076 int fd; 00077 //Audio related stuff 00078 int is_video; 00079 int audio_len; 00080 int audio_packlen; 00081 uint8_t audio_pack[16]; 00082 int audio_tmp_len; 00083 uint8_t audio_tmp[4]; 00084 }; 00085 00086 struct cir { 00087 int pip_flag; 00088 int dip_flag; 00089 int use_heap; 00090 int long_name_flag; 00091 int logo_flag; 00092 int scid_size_flag; 00093 int service_paradigm_indicator; 00094 int number_of_scids; 00095 int pip_transponder; 00096 int dip_transponder; 00097 int channel_transponder; 00098 int virt_channel_number; 00099 int network_id; 00100 uint8_t short_name[4]; 00101 int scid[16]; 00102 int scid_type[16]; 00103 }; 00104 00105 struct cssm { 00106 int number_of_channels; 00107 int segment_size; 00108 int buf_len; 00109 uint8_t buf[65536]; 00110 }; 00111 00112 struct segment_list { 00113 int number_of_segments; 00114 int up_scid; 00115 int pip_scid; 00116 int dip_scid; 00117 int default_network_id; 00118 int provider_id; 00119 int checksum; 00120 }; 00121 00122 struct mpg { 00123 struct segment_list segl; 00124 struct cssm cssm; 00125 struct cir *cir; 00126 int cir_len; 00127 int num_channels; 00128 int current_transponder; 00129 }; 00130 00131 struct dss { 00132 struct list_head list; 00133 int adapt; 00134 pthread_mutex_t lock; 00135 struct list_head pkt_ll; //struct dss_pkt 00136 struct mpg mpg; 00137 uint32_t old_standard; 00138 int is_dss; 00139 uint8_t *buf; 00140 uint32_t buf_len; 00141 uint32_t buf_used; 00142 uint8_t unused[131]; 00143 uint8_t unused_len; 00144 00145 }; 00146 00147 static int dss_opt = 0; 00148 static int opt_enable = 0; 00149 static char * opt_file = NULL; 00150 static struct option dss_Opts[] = { 00151 {"dss-enable", 0, &dss_opt, 'e'}, 00152 {"dss-file", 1, &dss_opt, 'f'}, 00153 {0, 0, 0, 0}, 00154 }; 00155 00156 LIST_HEAD(dsslist); 00157 LIST_HEAD(dsspkt_empty_queue); 00158 00159 //taken and adapted from libdtv, (c) Rolf Hakenes 00160 // CRC32 lookup table for polynomial 0x04c11db7 00161 static unsigned int crc_table[256] = { 00162 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 00163 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 00164 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, 00165 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, 00166 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, 00167 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, 00168 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, 00169 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, 00170 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, 00171 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, 00172 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, 00173 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, 00174 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, 00175 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, 00176 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, 00177 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, 00178 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, 00179 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, 00180 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, 00181 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, 00182 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, 00183 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, 00184 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, 00185 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, 00186 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, 00187 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, 00188 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, 00189 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, 00190 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, 00191 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, 00192 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, 00193 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, 00194 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, 00195 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, 00196 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, 00197 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, 00198 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, 00199 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, 00200 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, 00201 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, 00202 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, 00203 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, 00204 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4}; 00205 00206 unsigned int crc32_04c11db7 (const unsigned char *d, int len, unsigned int crc) 00207 { 00208 register int i; 00209 const unsigned char *u=(unsigned char*)d; // Saves '& 0xff' 00210 00211 for (i=0; i<len; i++) 00212 crc = (crc << 8) ^ crc_table[((crc >> 24) ^ *u++)]; 00213 00214 return crc; 00215 } 00216 static void get_pespts(uint8_t *spts,uint8_t *pts) 00217 { 00218 00219 pts[0] = 0x01 | 00220 ((spts[0] & 0xC0) >>5); 00221 pts[1] = ((spts[0] & 0x3F) << 2) | 00222 ((spts[1] & 0xC0) >> 6); 00223 pts[2] = 0x01 | ((spts[1] & 0x3F) << 2) | 00224 ((spts[2] & 0x80) >> 6); 00225 pts[3] = ((spts[2] & 0x7F) << 1) | 00226 ((spts[3] & 0x80) >> 7); 00227 pts[4] = 0x01 | ((spts[3] & 0x7F) << 1); 00228 } 00229 static int write_pes_header(uint8_t id, int length , uint64_t PTS, uint64_t DTS, 00230 uint8_t *obuf, int stuffing, uint8_t ptsdts) 00231 { 00232 uint8_t le[2]; 00233 uint8_t dummy[3]; 00234 uint8_t *pts; 00235 uint8_t ppts[5]; 00236 uint32_t lpts; 00237 uint8_t *dts; 00238 uint8_t pdts[5]; 00239 uint32_t ldts; 00240 int c; 00241 uint8_t headr[3] = {0x00, 0x00, 0x01}; 00242 00243 lpts = htonl((PTS/300ULL) & 0x00000000FFFFFFFFULL); 00244 pts = (uint8_t *) &lpts; 00245 get_pespts(pts,ppts); 00246 if ((PTS/300ULL) & 0x0000000100000000ULL) ppts[0] |= 0x80; 00247 00248 ldts = htonl((DTS/300ULL) & 0x00000000FFFFFFFFULL); 00249 dts = (uint8_t *) &ldts; 00250 get_pespts(dts,pdts); 00251 if ((DTS/300ULL) & 0x0000000100000000ULL) pdts[0] |= 0x80; 00252 00253 c = 0; 00254 memcpy(obuf+c,headr,3); 00255 c += 3; 00256 memcpy(obuf+c,&id,1); 00257 c++; 00258 00259 le[0] = 0; 00260 le[1] = 0; 00261 length -= 6; 00262 00263 le[0] |= ((uint8_t)(length >> 8) & 0xFF); 00264 le[1] |= ((uint8_t)(length) & 0xFF); 00265 memcpy(obuf+c,le,2); 00266 c += 2; 00267 00268 dummy[0] = 0x80; 00269 dummy[1] = 0; 00270 dummy[2] = stuffing; 00271 00272 if (ptsdts == PTS_ONLY){ 00273 dummy[2] += 5; 00274 dummy[1] |= PTS_ONLY; 00275 ppts[0] |= 0x20; 00276 } else if (ptsdts == PTS_DTS){ 00277 dummy[2] += 10; 00278 dummy[1] |= PTS_DTS; 00279 ppts[0] |= 0x30; 00280 pdts[0] |= 0x10; 00281 } 00282 00283 00284 memcpy(obuf+c,dummy,3); 00285 c += 3; 00286 00287 if (ptsdts == PTS_ONLY){ 00288 memcpy(obuf+c,ppts,5); 00289 c += 5; 00290 } else if ( ptsdts == PTS_DTS ){ 00291 memcpy(obuf+c,ppts,5); 00292 c += 5; 00293 memcpy(obuf+c,pdts,5); 00294 c += 5; 00295 } 00296 00297 memset(obuf+c,0xFF,stuffing); 00298 c += stuffing; 00299 00300 return c; 00301 } 00302 static int write_ts_header(int pid, int payload_start, int count, 00303 int64_t SCR, uint8_t *obuf, int stuff) 00304 { 00305 int c = 0; 00306 uint8_t *scr; 00307 uint32_t lscr; 00308 uint16_t scr_ext = 0; 00309 00310 obuf[c++] = 0x47; 00311 obuf[c++] = (payload_start ? 0x40 : 0x00) | ((pid >> 8) & 0x1f); 00312 obuf[c++] = pid & 0xff; 00313 obuf[c++] = ((SCR >= 0 || stuff) ? 0x30 : 0x10) | count; 00314 if (SCR >= 0|| stuff) { 00315 if (stuff) 00316 stuff--; 00317 int size = stuff; 00318 unsigned char flags = 0; 00319 if(SCR >= 0) { 00320 if(size < 7) 00321 size = 7; 00322 flags |= 0x10; 00323 } 00324 obuf[c++] = size; 00325 if(size) { 00326 obuf[c++] = flags; 00327 size--; 00328 } 00329 if(SCR >= 0) { 00330 uint8_t bit; 00331 lscr = (uint32_t) ((SCR/300ULL) & 0xFFFFFFFFULL); 00332 bit = (lscr & 0x01) << 7; 00333 lscr = htonl(lscr >> 1); 00334 00335 scr = (uint8_t *) 𝓁 00336 scr_ext = (uint16_t) ((SCR%300ULL) & 0x1FFULL); 00337 obuf[c++] = scr[0]; 00338 obuf[c++] = scr[1]; 00339 obuf[c++] = scr[2]; 00340 obuf[c++] = scr[3]; 00341 obuf[c++] = bit | 0x7e | (scr_ext >> 8); 00342 obuf[c++] = scr_ext & 0xff; 00343 size -= 6; 00344 } 00345 while(size-- > 0) 00346 obuf[c++] = 0xff; 00347 } 00348 return c; 00349 } 00350 //extract PTS from Picture frame 00351 int get_ptsdts(unsigned char *buf, int len, uint64_t *pts, uint64_t *dts) 00352 { 00353 int picture_coding_type; 00354 int hdr_len; 00355 uint32_t pts1, dts1; 00356 picture_coding_type = (buf[5] >> 3) & 0x07; 00357 hdr_len = (picture_coding_type > 1) ? 9 : 8; 00358 if(buf[hdr_len + 3] == 0xb5) 00359 hdr_len += 9; 00360 if(buf[hdr_len + 3] == 0xb2) { 00361 pts1 = ((buf[hdr_len+6] & 0x03) << 30) + 00362 ((buf[hdr_len+7] & 0x7f) << 23) + 00363 ((buf[hdr_len+8]) << 15) + 00364 ((buf[hdr_len+9] & 0x7f) << 8) + 00365 buf[hdr_len+10]; 00366 dts1 = ((buf[hdr_len+13] & 0x03) << 30) + 00367 ((buf[hdr_len+14] & 0x7f) << 23) + 00368 ((buf[hdr_len+15]) << 15) + 00369 ((buf[hdr_len+16] & 0x7f) << 8) + 00370 buf[hdr_len+17]; 00371 //NOTE: This is wrong. DSS timestamps only have a resolution of 2^32/300 00372 dprintf2("pts: %08x/%f dts: %08x/%f\n", pts1, pts1 / 27000000.0, dts1, dts1 / 27000000.0); 00373 *pts = pts1; 00374 *dts = dts1; 00375 return 1; 00376 } 00377 return 0; 00378 } 00379 struct dss_pkt *parse_dss_hdr(unsigned char *buf, struct dss *dss) 00380 { 00381 struct dss_pkt *pkt; 00382 int scid = ((buf[1] << 8) + buf[2]) & 0x0fff; 00383 00384 ll_find_elem(pkt, dss->pkt_ll, hdr.scid, scid, struct dss_pkt); 00385 if(! pkt) { 00386 //dprintf0("Found unexpected scid: %d %02x %02x %02x ...\n", scid, buf[0], buf[1], buf[2]); 00387 return NULL; 00388 } 00389 pkt->hdr.packet_framing = buf[1] >> 7; 00390 pkt->hdr.bundle_boundary = (buf[1] >> 6) & 0x01; 00391 pkt->hdr.control_flag = (buf[1] >> 5) & 0x01; 00392 pkt->hdr.control_sync = (buf[1] >> 4) & 0x01; 00393 pkt->hdr.continuity_counter = (buf[3] >> 4); 00394 pkt->hdr.header_designator_type = (buf[3] >> 2) & 0x03; 00395 pkt->hdr.header_designator_id = buf[3] & 0x03; 00396 return pkt; 00397 } 00398 00399 void write_dummy_ts(uint8_t *ts) 00400 { 00401 static const uint8_t data[TS_SIZE] = {0x47, 0x1f, 0xff, 0x10}; 00402 memcpy(ts, data, TS_SIZE); 00403 } 00404 00405 00406 //We should always write out a frame here 00407 int write_ts_frame(struct dss_pkt *pkt, uint8_t *ts) 00408 { 00409 int len; 00410 int stuff; 00411 int pos = 0; 00412 00413 stuff = (pkt->buf_len < TS_SIZE - 4) ? TS_SIZE - 4 - pkt->buf_len : 0; 00414 00415 pos = write_ts_header(pkt->hdr.scid, pkt->start, pkt->cont, 00416 pkt->rts, ts, stuff); 00417 pkt->cont = (pkt->cont + 1) & 0x0f; 00418 len = TS_SIZE - pos; 00419 pkt->rts = -1; 00420 pkt->start = 0; 00421 memcpy(ts+pos, pkt->buf, len); 00422 pkt->buf_len -= len; 00423 //This is horribly inefficient! 00424 if(pkt->buf_len > 0) 00425 memmove(pkt->buf, pkt->buf + len, pkt->buf_len); 00426 else 00427 pkt->buf_len = 0; 00428 return 1; 00429 } 00430 00431 void write_ts(uint8_t **out, uint8_t *buf, int len, struct dss_pkt *pkt) 00432 { 00433 uint8_t ts[188]; 00434 00435 if(pkt->hdr.bundle_boundary) { 00436 while(pkt->buf_len != 0) { 00437 if(write_ts_frame(pkt, ts)) { 00438 memcpy(*out, ts, TS_SIZE); 00439 *out += TS_SIZE; 00440 } 00441 } 00442 pkt->start = 1; 00443 pkt->hdr.bundle_boundary = 0; 00444 } 00445 memcpy(pkt->buf + pkt->buf_len, buf, len); 00446 pkt->buf_len += len; 00447 if(pkt->buf_len >= 184) { 00448 if(write_ts_frame(pkt, ts)) { 00449 memcpy(*out, ts, TS_SIZE); 00450 *out += TS_SIZE; 00451 } 00452 } 00453 } 00454 00455 int make_pes(uint8_t *outbuf, uint8_t *inbuf, struct dss_pkt *pkt) 00456 { 00457 int ptsdts; 00458 uint64_t pts, dts; 00459 if(get_ptsdts(inbuf, 127, &pts, &dts)) 00460 ptsdts = PTS_DTS; 00461 else 00462 ptsdts = 0; 00463 if(ptsdts && pkt) 00464 pkt->rts = dts; 00465 return write_pes_header(0xE0, 6, pts, dts, outbuf, 0, ptsdts); 00466 } 00467 00468 void parse_aux(uint8_t *buf, struct dss_pkt *pkt) 00469 { 00470 if((buf[0] & 0x3f) > 0x01) 00471 return; 00472 pkt->rts = (buf[3] << 24) | (buf[4] << 16) | (buf[5] << 8) | buf[6]; 00473 } 00474 void get_scids(struct cir *cir, int basescid) 00475 { 00476 static const uint8_t sc[16][17] = { 00477 {}, //0x00 00478 {2, 0x0f, 0}, //0x01 00479 {9, 0x0f, 0, 1, 2, 3, 4, 5, 6, 7}, //0x02 00480 {9, 0x0f, 1, 1, 2, 3, 4, 5, 6, 7}, //0x03 00481 {9, 0x0f, 2, 1, 2, 3, 4, 5, 6, 7}, //0x04 00482 {9, 0x0f, 3, 1, 2, 3, 4, 5, 6, 7}, //0x05 00483 {}, //0x06 00484 {}, //0x07 00485 {}, //0x08 00486 {}, //0x09 00487 {9, 0x0f, 0, 1, 2, 3, 4, 5, 6, 7}, //0x0a 00488 {}, //0x0b 00489 {1, 0x00}, //0x0c 00490 {1, 0x0d}, //0x0d 00491 {1, 0x0c}, //0x0e 00492 {1, 0x0f}, //0x0f 00493 }; 00494 int spi = cir->service_paradigm_indicator; 00495 int i; 00496 00497 for(i = 0; i < cir->number_of_scids; i++) { 00498 cir->scid[i] = basescid+i; 00499 if(i < sc[spi][0]) 00500 cir->scid_type[i] = sc[spi][i+1]; 00501 else 00502 cir->scid_type[i] = sc[spi][sc[spi][0]]; 00503 } 00504 if(spi == 0x0a) 00505 cir->scid_type[cir->number_of_scids-1] = 0x09; 00506 } 00507 void read_extended_chaninfo(struct cir *cir, uint8_t *heap) 00508 { 00509 int i, offset; 00510 00511 if(cir->service_paradigm_indicator == 0) { 00512 for(i=0; i < cir->number_of_scids; i++) { 00513 if(! cir->scid_size_flag) { 00514 if((i & 0x01) == 0) { 00515 cir->scid[i] = heap[0]; 00516 cir->scid_type[i] = heap[1] >> 4; 00517 heap++; 00518 } else { 00519 cir->scid[i] = heap[1]; 00520 cir->scid_type[i] = heap[0] & 0x0f; 00521 heap+=2; 00522 } 00523 } else { 00524 if((i & 0x01) == 0) { 00525 cir->scid[i] = (heap[0] << 4) | (heap[1] >> 4); 00526 cir->scid_type[i] = heap[1] & 0x0f; 00527 } else { 00528 cir->scid[i] = ((heap[0] << 8) | heap[1] >> 4) & 0xfff; 00529 cir->scid_type[i] = heap[0] >> 4; 00530 } 00531 heap+=2; 00532 } 00533 } 00534 } else { 00535 int basescid; 00536 basescid = cir->scid_size_flag ? ((heap[0] << 4) | (heap[1] >> 4)) : 00537 heap[0]; 00538 get_scids(cir, basescid); 00539 heap+=2; 00540 } 00541 if(cir->pip_flag == 0x02) 00542 heap+=2; 00543 if(cir->dip_flag == 0x02) 00544 heap+=2; 00545 if(cir->long_name_flag) { 00546 //we could do a strcpy here 00547 while(*heap) 00548 heap++; 00549 heap++; 00550 } 00551 if(cir->logo_flag) 00552 heap++; 00553 offset = 1; 00554 if(*heap & 0x20) offset+=2; //altcn_flag 00555 if(*heap & 0x10) offset+=2; //ext4_flag 00556 if(*heap & 0x08) offset+=1; //altci_flag 00557 if(*heap & 0x04) cir->network_id = heap[offset]; //altni_flag 00558 } 00559 00560 void process_cir(struct cir *cir, uint8_t *cssm, int satid, 00561 int provid, uint8_t *heap) 00562 { 00563 int i; 00564 int offset = provid ? 1 : 0; 00565 cir->network_id = satid; 00566 cir->pip_flag = (cssm[0] >> 2) & 0x03; 00567 cir->dip_flag = cssm[0] & 0x03; 00568 cir->use_heap = cssm[1] & 0x80 ? 1 : 0; 00569 cir->long_name_flag = cssm[1] & 0x40; 00570 cir->logo_flag = cssm[1] & 0x20; 00571 cir->scid_size_flag = (cssm[1] >> 4) & 0x01; 00572 cir->service_paradigm_indicator = cssm[1] & 0x0f; 00573 cir->number_of_scids = cssm[2+offset]; 00574 cir->pip_transponder = cssm[3+offset]; 00575 cir->dip_transponder = cssm[4+offset]; 00576 cir->channel_transponder = cssm[5+offset]; 00577 cir->virt_channel_number = cssm[6+offset] << 8 | cssm[7+offset]; 00578 memcpy(cir->short_name, &cssm[8+offset], 4); 00579 if(cir->use_heap) { 00580 int index = (cssm[15+4*offset] << 8) | cssm[16+4*offset]; 00581 read_extended_chaninfo(cir, heap + index); 00582 } else { 00583 get_scids(cir, cssm[15+4*offset]); 00584 } 00585 //we have added a channel 00586 dprintf2("%d(%c%c%c%c) tp:%d sat:%02x", cir->virt_channel_number, 00587 cir->short_name[0], cir->short_name[1], cir->short_name[2], 00588 cir->short_name[3], cir->channel_transponder, cir->network_id); 00589 for(i = 0; i < cir->number_of_scids; i++) 00590 dprintf2(" %03x:%02x", cir->scid[i], cir->scid_type[i]); 00591 dprintf2("\n"); 00592 } 00593 00594 int get_avail_chan(struct mpg *mpg, uint32_t *indices, int max_chan) 00595 { 00596 int i, j = 0; 00597 int cur_tp = mpg->current_transponder; 00598 dprintf2("Searching %d channels on sat:%d tp:%d\n", mpg->num_channels, mpg->segl.default_network_id, cur_tp); 00599 for(i = 0; i < mpg->num_channels && j < max_chan; i++) { 00600 if(mpg->cir[i].network_id != mpg->segl.default_network_id || 00601 mpg->cir[i].channel_transponder != cur_tp) 00602 continue; 00603 indices[j++] = i; 00604 dprintf2(" Found channel: %d\n", mpg->cir[i].virt_channel_number); 00605 } 00606 dprintf2("Found %d channels\n", j); 00607 return j; 00608 } 00609 00610 void write_chaninfo(uint8_t **out, struct mpg *mpg) 00611 { 00612 static int patcount = 0, pmtcount = 0, nitcount = 0; 00613 int pos, i, j, pmtpos, patpos = 9, chan_cnt; 00614 uint8_t buf[188]; 00615 //PMT Program number = 1 00616 //PMT PID = 0x20 00617 uint8_t pat[184] = {0x00, 0x00, 0xb0, 0x00, 0xfe, 0xef, 0xc1, 0x00, 0x00}; 00618 uint8_t pmt[184] ={0x00, 0x02, 0xb0, 0x00, 0x00, 0x00, 0xc1, 0x00, 0x00, 00619 0x00, 0x00, 0xf0, 0x00}; 00620 uint8_t nit[184] ={0x00, 0x40, 0xf0, 0x0d, 0x00, 0x00, 0xff, 0x00, 0x00, 00621 0xf0, 0x00, 0xf0, 0x00}; 00622 uint32_t chanidx[40]; //40 is max channels in a single PAT frame 00623 00624 chan_cnt = get_avail_chan(mpg, chanidx, 40); 00625 if(!chan_cnt) 00626 return; 00627 patcount = (patcount + 1) & 0x0f; 00628 //PAT 00629 //add NIT info 00630 pat[patpos++] = 0; 00631 pat[patpos++] = 0; 00632 pat[patpos++] = 0xe0 | ((DSS_NITPID >> 8) & 0x1f); 00633 pat[patpos++] = DSS_NITPID & 0xff; 00634 for(i = 0; i < chan_cnt; i++) { 00635 pat[patpos++] = (mpg->cir[chanidx[i]].virt_channel_number >> 8) & 0xff; 00636 pat[patpos++] = mpg->cir[chanidx[i]].virt_channel_number & 0xff; 00637 pat[patpos++] = 0xe0 | ((DSS_PMTPID >> 8) & 0x1f); 00638 pat[patpos++] = DSS_PMTPID & 0xff; 00639 } 00640 pat[3] = (patpos + 4 - 3 - 1); 00641 *(uint32_t *)(pat+patpos)= htonl(crc32_04c11db7(pat+1, patpos-1, 0xffffffff)); 00642 patpos+=4; 00643 pos = write_ts_header(0x00, 1, patcount, -1, buf, 0); 00644 memcpy(buf+pos, pat, patpos); 00645 pos += patpos; 00646 memset(buf+pos, 0xff, TS_SIZE - pos); 00647 memcpy(*out, buf, TS_SIZE); 00648 *out += TS_SIZE; 00649 //PMT 00650 for(i = 0; i < chan_cnt; i++) { 00651 pos = 0; 00652 pmtpos = 13; 00653 pos += write_ts_header(DSS_PMTPID, 1, pmtcount, -1, buf+pos, 0); 00654 for(j = 0; j < mpg->cir[i].number_of_scids; j++) { 00655 uint8_t type; 00656 uint32_t pid = mpg->cir[i].scid[j]; 00657 uint8_t lang[3] = {0, 0, 0}; 00658 switch(mpg->cir[i].scid_type[j]) { 00659 case 0x08: 00660 case 0x0f: 00661 type = 0x02; 00662 break; 00663 case 0x09: 00664 type = 0x81; 00665 break; 00666 case 0x00: 00667 type = 0x04; 00668 lang[0] = 'e'; lang[1] = 'n'; lang[2] = 'g'; 00669 break; 00670 case 0x01: 00671 type = 0x04; 00672 lang[0] = 's'; lang[1] = 'p'; lang[2] = 'a'; 00673 break; 00674 case 0x02: 00675 type = 0x04; 00676 lang[0] = 'f'; lang[1] = 'r'; lang[2] = 'e'; 00677 break; 00678 case 0x03: 00679 type = 0x04; 00680 lang[0] = 'd'; lang[1] = 'e'; lang[2] = 'u'; 00681 break; 00682 case 0x04: 00683 type = 0x04; 00684 lang[0] = 'i'; lang[1] = 't'; lang[2] = 'a'; 00685 break; 00686 case 0x05: 00687 type = 0x04; 00688 lang[0] = 'j'; lang[1] = 'p'; lang[2] = 'n'; 00689 break; 00690 case 0x06: 00691 type = 0x04; 00692 lang[0] = 'k'; lang[1] = 'o'; lang[2] = 'r'; 00693 break; 00694 case 0x07: 00695 type = 0x04; 00696 lang[0] = 'z'; lang[1] = 'h'; lang[2] = 'o'; 00697 break; 00698 } 00699 pmt[pmtpos++] = type; 00700 pmt[pmtpos++] = 0xe0 | (0xff & (pid >> 8)); 00701 pmt[pmtpos++] = 0xff & pid; 00702 pmt[pmtpos++] = 0xf0; 00703 if(lang[0]) { 00704 pmt[pmtpos++] = 0x06; 00705 pmt[pmtpos++] = 0x0a; 00706 pmt[pmtpos++] = 0x04; 00707 pmt[pmtpos++] = lang[0]; 00708 pmt[pmtpos++] = lang[1]; 00709 pmt[pmtpos++] = lang[2]; 00710 pmt[pmtpos++] = 0x00; 00711 } else { 00712 pmt[pmtpos++] = 0x00; 00713 } 00714 } 00715 pmt[3] = pmtpos + 4/*crc*/ - 3 - 1/*pointer_field*/; 00716 pmt[4] = (mpg->cir[i].virt_channel_number >> 8) & 0xff; 00717 pmt[5] = mpg->cir[i].virt_channel_number & 0xff; 00718 pmt[9] = 0xf0 | (0xff & (mpg->cir[i].scid[0] >> 8)); 00719 pmt[10] = 0xff & mpg->cir[i].scid[0]; 00720 *(uint32_t *)&pmt[pmtpos] = htonl(crc32_04c11db7(&pmt[1], pmtpos -1, 00721 0xffffffff)); 00722 pmtpos+=4; 00723 memcpy(buf+pos, pmt, pmtpos); 00724 pos += pmtpos; 00725 memset(buf+pos, 0xff, TS_SIZE - pos); 00726 memcpy(*out, buf, TS_SIZE); 00727 *out += TS_SIZE; 00728 pmtcount = (pmtcount+1) & 0x0f; 00729 } 00730 //NIT 00731 pos = 0; 00732 nit[4] |= (DSS_NETWORKID >> 8) & 0xff; 00733 nit[5] |= DSS_NETWORKID & 0xff; 00734 *(uint32_t *)&nit[13] = htonl(crc32_04c11db7(&nit[1], 12, 0xffffffff)); 00735 pos += write_ts_header(DSS_NITPID, 1, nitcount, -1, *out, 0); 00736 memcpy(*out + pos, nit, 17); 00737 pos+=17; 00738 memset(*out+pos, 0xff, TS_SIZE - pos); 00739 *out += TS_SIZE; 00740 nitcount = (nitcount+1) & 0x0f; 00741 } 00742 00743 void parse_mpg(uint8_t **out, struct mpg *mpg, uint8_t *buf) 00744 { 00745 uint8_t seg_sync[4] = {0xaa, 0x55, 0xa5, 0xa5}; 00746 uint32_t *segsync = (uint32_t *)seg_sync; 00747 uint8_t cssm_sync[4] = {0x55, 0xaa, 0x5a, 0x5a}; 00748 uint32_t *cssmsync = (uint32_t *)cssm_sync; 00749 struct segment_list *segl = &mpg->segl; 00750 struct cssm *cssm = &mpg->cssm; 00751 uint8_t *p, *heap; 00752 int i, offset; 00753 00754 if(segl->number_of_segments == 0) { 00755 if (*(uint32_t *)buf == *segsync && (buf[4] & 0xf0) == 0) { 00756 segl->number_of_segments = buf[19]; 00757 segl->up_scid = (buf[53] << 8 | buf[54]) & 0xfff; 00758 segl->pip_scid = (buf[55] << 8 | buf[56]) & 0xfff; 00759 segl->dip_scid = (buf[57] << 8 | buf[58]) & 0xfff; 00760 segl->default_network_id = buf[97]; 00761 segl->provider_id = buf[107]; 00762 segl->checksum = buf[125] << 8 | buf[126]; 00763 segl->number_of_segments--; 00764 mpg->num_channels = 0; 00765 } 00766 return; 00767 } 00768 if(cssm->segment_size == 0 && *(uint32_t *)buf == *cssmsync) { 00769 cssm->number_of_channels = buf[5]; 00770 cssm->segment_size = buf[6] << 8 | buf[7]; 00771 cssm->buf_len = 0; 00772 dprintf2("Searching for %d channels in %d bytes (ns:%d)\n", 00773 cssm->number_of_channels, cssm->segment_size,segl->number_of_segments); 00774 } 00775 if(cssm->segment_size) { 00776 memcpy(cssm->buf + cssm->buf_len, buf, 127); 00777 cssm->buf_len += 127; 00778 if(cssm->segment_size > 127) { 00779 cssm->segment_size -= 127; 00780 return; 00781 } 00782 p = &cssm->buf[8]; 00783 offset = segl->provider_id ? 1 : 0; 00784 heap = &p[(17 + 4 * offset) * cssm->number_of_channels]; 00785 mpg->num_channels += cssm->number_of_channels; 00786 if(mpg->cir_len < mpg->num_channels) { 00787 dprintf1("Reallocating CIR: %d < %d\n", mpg->cir_len, mpg->num_channels); 00788 mpg->cir = (struct cir *)realloc(mpg->cir, 00789 mpg->num_channels * sizeof(struct cir)); 00790 mpg->cir_len = mpg->num_channels; 00791 } 00792 for(i = cssm->number_of_channels; i > 0; i--) { 00793 process_cir(&mpg->cir[mpg->num_channels-i], p, segl->default_network_id, 00794 segl->provider_id, heap); 00795 p += 17 + 4*offset; 00796 } 00797 cssm->segment_size = 0; 00798 } 00799 if(--segl->number_of_segments == 0) 00800 write_chaninfo(out, mpg); 00801 } 00802 00803 void write_audio_pack(uint8_t **out, uint8_t *pack, struct dss_pkt *pkt) 00804 { 00805 pkt->audio_len = (pack[4] << 8) | pack[5]; 00806 assert(pkt->audio_len); 00807 pkt->hdr.bundle_boundary = 1; 00808 if(pack[3] == 0xbf) { 00809 //This is already a PES stream 00810 write_ts(out, pack, 11, pkt); 00811 } else { 00812 //Need to convert MPEG1 pkt to MPEG2-PES 00813 //for our purpose the only difference is that the PES is 3 bytes longer 00814 int i, len; 00815 for(i = 10; i >= 6; i--) 00816 pack[i+3] = pack[i]; 00817 len = pkt->audio_len + 3; 00818 pack[4] = (len >> 8) & 0xff; 00819 pack[5] = len & 0xff; 00820 pack[6] = 0x80; 00821 pack[7] = 0x80; 00822 pack[8] = 0x05; 00823 write_ts(out, pack, 14, pkt); 00824 } 00825 pkt->audio_len -=5; 00826 pkt->audio_packlen = 0; 00827 } 00828 00829 //Try to find a start code, since audio frames aren't aligned to DSS 00830 //boundaries 00831 void find_audio(uint8_t **out, uint8_t *buf, int buflen, struct dss_pkt *pkt) 00832 { 00833 int len; 00834 int ok = 0; 00835 if(pkt->audio_packlen) { 00836 memcpy(pkt->audio_pack + pkt->audio_packlen, buf, 11 - pkt->audio_packlen); 00837 buf += 11 - pkt->audio_packlen; 00838 buflen -= 11 - pkt->audio_packlen; 00839 write_audio_pack(out, pkt->audio_pack, pkt); 00840 } 00841 len = (pkt->audio_len < buflen) ? pkt->audio_len : buflen; 00842 if(len) { 00843 write_ts(out, buf, len, pkt); 00844 pkt->audio_len -= len; 00845 ok = 1; 00846 } 00847 if(len == buflen || pkt->audio_len) 00848 return; 00849 if(pkt->audio_tmp_len) { 00850 //we know there are 4 bytes of header in front of buf, so let's overwrite 00851 buf = buf - pkt->audio_tmp_len; 00852 buflen += pkt->audio_tmp_len; 00853 memcpy(buf, pkt->audio_tmp, pkt->audio_tmp_len); 00854 pkt->audio_tmp_len = 0; 00855 } 00856 while(len + 4 <= buflen) { 00857 if(buf[len] == 0x00 && buf[len+1] == 0x00 && buf[len+2] == 0x01 && 00858 ((buf[len+3] & 0xe0) == 0xc0 || buf[len+3] == 0xbf)) { 00859 int packlen = (11 < buflen - len) ? 11 : buflen - len; 00860 memcpy(pkt->audio_pack, buf + len, packlen); 00861 pkt->audio_packlen = packlen; 00862 if(packlen == 11) { 00863 write_audio_pack(out, pkt->audio_pack, pkt); 00864 len += 11; 00865 if(len < buflen) { 00866 write_ts(out, buf + len, buflen - len, pkt); 00867 pkt->audio_len -= buflen - len; 00868 } 00869 } 00870 return; 00871 } 00872 assert(ok != 1); 00873 len++; 00874 } 00875 if (len == buflen) 00876 return; 00877 pkt->audio_tmp_len = buflen - len; 00878 memcpy(pkt->audio_tmp, buf + len, pkt->audio_tmp_len); 00879 return; 00880 } 00881 00882 void parse_dss(struct dss *dss, uint8_t *data, int len) { 00883 int pos; 00884 uint8_t *buf, *nextbuf, *out = dss->buf + dss->buf_used; 00885 struct dss_pkt *pktptr; 00886 if(dss->unused_len) { 00887 memcpy(dss->unused + dss->unused_len, data, 131 - dss->unused_len); 00888 nextbuf = dss->unused; 00889 pos = -dss->unused_len; 00890 } else { 00891 nextbuf = data; 00892 pos = 0; 00893 } 00894 while (pos <= len - 131) { 00895 pos+= 131; 00896 buf = nextbuf; 00897 if(dss->unused_len) { 00898 nextbuf = data + (131 - dss->unused_len); 00899 dss->unused_len = 0; 00900 } else { 00901 nextbuf = buf + 131; 00902 } 00903 if((pktptr = parse_dss_hdr(buf, dss)) == NULL) 00904 continue; 00905 if(pktptr->hdr.control_flag == 0) { 00906 //can't handle encrypted streams 00907 continue; 00908 } 00909 if(pktptr->hdr.header_designator_type == 0) { 00910 //Check the aux packet to see if there's an RTS in there 00911 //We're currently using the DTS for the SCR, so no need to parse 00912 //AUX packets at the moment 00913 //parse_aux(buf+4, pktptr); 00914 continue; 00915 } 00916 if(pktptr->hdr.scid == 0x009) { 00917 //do pat/pmt stuff here 00918 parse_mpg(&out, &dss->mpg, buf+4); 00919 continue; 00920 } 00921 if(pktptr->hdr.bundle_boundary) { 00922 //We should only get here for PES or ES data packets 00923 pktptr->is_video = 1; 00924 if(buf[7] >= 0xb9) { 00925 //This is a PES packet nothing else to do 00926 write_ts(&out, buf+4, 127, pktptr); 00927 } else { 00928 //This is an ES frame, and we need to add a PES to it 00929 uint8_t peshdr[TS_SIZE]; 00930 int peslen; 00931 peslen = make_pes(peshdr, buf+4, pktptr); 00932 write_ts(&out, peshdr, peslen, pktptr); 00933 write_ts(&out, buf+4, 127, pktptr); 00934 } 00935 } else { 00936 //This is a continuation of the previous frame 00937 //Do we need to find the end 1st? 00938 if(! pktptr->is_video) { 00939 find_audio(&out, buf+4, 127, pktptr); 00940 } else { 00941 write_ts(&out, buf+4, 127, pktptr); 00942 } 00943 } 00944 } 00945 dss->buf_used = out - dss->buf; 00946 if(pos < len) { 00947 dprintf3("Storing %d bytes %02x %02x %02x...\n", len - pos, data[pos], data[pos+1], data[pos+2]); 00948 memcpy(dss->unused, data + pos, len - pos); 00949 dss->unused_len = len - pos; 00950 } 00951 } 00952 00953 static uint32_t get_transponder(uint32_t freq) 00954 { 00955 #define DSS_LOF 11250000L 00956 int i; 00957 static uint32_t freqmap[] = { 00958 12224, 12239, 12253, 12268, 12282, 12297, 12311, 12326, 12341, 12355, 00959 12370, 12381, 12399, 12414, 12428, 12443, 12457, 12472, 12486, 12501, 00960 12516, 12530, 12545, 12559, 12574, 12588, 12603, 12618, 12632, 12647, 00961 12661, 12676}; 00962 freq = (freq + DSS_LOF) / 1000L; 00963 for(i = 0; i < 32; i++) { 00964 if(freq >= freqmap[i] - 2 && freq <= freqmap[i] + 2) { 00965 dprintf0("Tuned to transponder: %d\n", i); 00966 return i; 00967 } 00968 } 00969 return 32; 00970 } 00971 static struct dss *find_dss_from_pc(struct parser_cmds *pc) 00972 { 00973 struct list_head *ptr; 00974 list_for_each(ptr, &dsslist) { 00975 struct dss *dss = list_entry(ptr, struct dss); 00976 if(dss->adapt == pc->common->virt_adapt); 00977 return dss; 00978 } 00979 return NULL; 00980 } 00981 static void fe_tune(struct parser_cmds *pc, struct poll_ll *fdptr, 00982 cmdret_t *result, int *ret, 00983 unsigned long int cmd, unsigned char *data) 00984 { 00985 int is_dss = 0; 00986 uint32_t freq; 00987 struct dvb_frontend_parameters_new fep2; 00988 struct dss *dss = find_dss_from_pc(pc); 00989 00990 if(cmd == FE_SET_FRONTEND) { 00991 dprintf1("Tuning frontend\n"); 00992 struct dvb_frontend_parameters *fep =(struct dvb_frontend_parameters *)data; 00993 is_dss = (fep->u.qpsk.symbol_rate == DSS_SYMBOLRATE); 00994 freq = fep->frequency; 00995 } else if(cmd == FE_SET_FRONTEND2) { 00996 dprintf1("Tuning frontend\n"); 00997 struct dvb_frontend_parameters_new *fep = 00998 (struct dvb_frontend_parameters_new *)data; 00999 if(dss->old_standard == FE_DVB_S || dss->old_standard == FE_QPSK) 01000 is_dss = (fep->u.qpsk.symbol_rate == DSS_SYMBOLRATE); 01001 else if(dss->old_standard == FE_DVB_S2) 01002 is_dss = (fep->u.qpsk2.symbol_rate == DSS_SYMBOLRATE); 01003 else 01004 return; 01005 freq = fep->frequency; 01006 } else if(cmd == FE_SET_STANDARD) { 01007 dprintf1("Setting standard to %u\n", (uint32_t)data); 01008 dss->old_standard = (*(unsigned long *)data) & 0xffffffff; 01009 return; 01010 } 01011 if(! is_dss) { 01012 dprintf1("Got non DSS frontend message\n"); 01013 // if(dss->is_dss) 01014 // ioctl(fdptr->fd, FE_SET_STANDARD, dss->old_standard); 01015 return; 01016 } 01017 pthread_mutex_lock(&dss->lock); 01018 if(ioctl(fdptr->fd, FE_SET_STANDARD, FE_DSS)) 01019 return; 01020 dss->mpg.current_transponder = get_transponder(freq); 01021 dss->is_dss = 1; 01022 dss->buf_used = 0; 01023 dss->unused_len = 0; 01024 fep2.frequency = freq; 01025 fep2.inversion = INVERSION_AUTO; 01026 fep2.u.qpsk2.symbol_rate = 20000000; 01027 fep2.u.qpsk2.fec_inner = FEC_5_6; 01028 fep2.u.qpsk2.modulation = MOD_DSS_QPSK; 01029 usleep(200000); 01030 *ret = ioctl(fdptr->fd, FE_SET_FRONTEND2, &fep2); 01031 usleep(200000); 01032 pthread_mutex_unlock(&dss->lock); 01033 *result = CMD_STOPALL; 01034 dprintf0("Switched to DSS mode\n"); 01035 return; 01036 } 01037 01038 static void fe_close(struct parser_cmds *pc, struct poll_ll *fdptr, 01039 cmdret_t *result, int *ret, 01040 unsigned long int cmd, unsigned char *data) 01041 { 01042 struct dss *dss = find_dss_from_pc(pc); 01043 dss->is_dss = 0; 01044 pthread_mutex_lock(&dss->lock); 01045 while(! list_empty(&dss->pkt_ll)) { 01046 struct dss_pkt * pkt = list_entry(dss->pkt_ll.next, struct dss_pkt); 01047 list_del(&pkt->list); 01048 list_add(&pkt->list, &dsspkt_empty_queue); 01049 } 01050 pthread_mutex_unlock(&dss->lock); 01051 } 01052 01053 static void close_demux(struct parser_cmds *pc, struct poll_ll *fdptr, 01054 cmdret_t *result, int *ret, 01055 unsigned long int cmd, unsigned char *data) 01056 { 01057 struct dss_pkt *pkt; 01058 struct dss *dss = find_dss_from_pc(pc); 01059 pthread_mutex_lock(&dss->lock); 01060 ll_find_elem(pkt, dss->pkt_ll, fd, fdptr->fd, struct dss_pkt); 01061 if(pkt) { 01062 list_del(&pkt->list); 01063 list_add(&pkt->list, &dsspkt_empty_queue); 01064 } 01065 pthread_mutex_unlock(&dss->lock); 01066 } 01067 static void set_demux(struct parser_cmds *pc, struct poll_ll *fdptr, 01068 cmdret_t *result, int *ret, 01069 unsigned long int cmd, unsigned char *data) 01070 { 01071 struct dss_pkt *pkt; 01072 struct dmx_pes_filter_params *dmx; 01073 struct dss *dss= find_dss_from_pc(pc); 01074 if(! dss->is_dss) { 01075 dprintf2("Ignoring demux ioctl\n"); 01076 return; 01077 } 01078 if(cmd == DMX_SET_PES_FILTER) { 01079 dmx = (struct dmx_pes_filter_params *)data; 01080 if(dmx->output != DMX_OUT_TS_TAP) { 01081 dprintf0("Tried to open DMX in non TAP mode\n"); 01082 *ret = 1; 01083 *result = CMD_STOPALL; 01084 return; 01085 } 01086 if(dmx->pid == 0x00) { 01087 //PAT requested let's open 009 01088 ll_find_elem(pkt, dss->pkt_ll, hdr.scid, 0x009, struct dss_pkt); 01089 if(pkt) { 01090 *ret = 0; 01091 *result = CMD_STOPALL; 01092 return; 01093 } 01094 dmx->pid = 0x009; 01095 } else if(dmx->pid == DSS_PMTPID) { 01096 *ret = 0; 01097 *result = CMD_STOPALL; 01098 return; 01099 } 01100 pthread_mutex_lock(&dss->lock); 01101 pop_entry_from_queue(pkt, &dsspkt_empty_queue, struct dss_pkt); 01102 bzero(pkt, sizeof( struct dss_pkt)); 01103 pkt->hdr.scid = dmx->pid; 01104 pkt->fd = fdptr->fd; 01105 pkt->rts = -1; 01106 list_add(&pkt->list, &dss->pkt_ll); 01107 *ret = ioctl(fdptr->fd, cmd, dmx); 01108 pthread_mutex_unlock(&dss->lock); 01109 *result = CMD_STOPALL; 01110 dprintf0("Set demux ioctl on pid %d\n", pkt->hdr.scid); 01111 } 01112 } 01113 01114 static void dvr_open(struct parser_cmds *pc, struct poll_ll *fdptr, 01115 cmdret_t *result, int *ret, 01116 unsigned long int cmd, unsigned char *data) 01117 { 01118 struct dss *dss= find_dss_from_pc(pc); 01119 dss->buf_used = 0; 01120 dss->unused_len = 0; 01121 } 01122 static void dvr_preread(struct parser_cmds *pc, struct poll_ll *fdptr, 01123 cmdret_t *result, int *ret, 01124 unsigned long int cmd, unsigned char *data) 01125 { 01126 struct dss *dss= find_dss_from_pc(pc); 01127 struct dvblb_custommsg *ci = (struct dvblb_custommsg *)data; 01128 static int fd = -1; 01129 int bytes; 01130 01131 if(! dss->is_dss) 01132 return; 01133 if(fd == -1) { 01134 fd = open(opt_file, O_RDONLY); 01135 } 01136 bytes = read(fd, pc->mmap, ci->u.count); 01137 if(bytes == 0) 01138 lseek(fd, 0, SEEK_SET); 01139 ci->u.count = bytes; 01140 *ret = bytes; 01141 *result = CMD_SKIPCALL; 01142 } 01143 //NOTE: This is very broken. We don't return the number of bytes requested ever 01144 static void dvr_read(struct parser_cmds *pc, struct poll_ll *fdptr, 01145 cmdret_t *result, int *ret, 01146 unsigned long int cmd, unsigned char *data) 01147 { 01148 struct dvblb_custommsg *ci = (struct dvblb_custommsg *)data; 01149 struct dss *dss= find_dss_from_pc(pc); 01150 if(! dss->is_dss) 01151 return; 01152 if(dss->buf_len < ci->u.count + dss->buf_used) { 01153 dprintf2("Reallocating %d < %d\n", dss->buf_len + dss->buf_used, ci->u.count); 01154 dss->buf = (uint8_t *)realloc(dss->buf, dss->buf_used + ci->u.count); 01155 dss->buf_len = ci->u.count; 01156 } 01157 if(*ret > 0) { 01158 dprintf3("Reading %d bytes(%08x): %02x %02x %02x %02x ...\n", *ret, pc->mmap, pc->mmap[0], pc->mmap[1], pc->mmap[2], pc->mmap[3]); 01159 parse_dss(dss, pc->mmap, *ret); 01160 if(dss->buf_used) { 01161 int max = ((int)dss->buf_used < *ret) ? dss->buf_used : *ret; 01162 memcpy(pc->mmap, dss->buf, max); 01163 *ret = max; 01164 memmove(dss->buf, dss->buf + max, dss->buf_used - max); 01165 dss->buf_used -= max; 01166 } else { 01167 write_dummy_ts(pc->mmap); 01168 if(*ret < TS_SIZE) { 01169 memcpy(dss->buf, pc->mmap + *ret, TS_SIZE - *ret); 01170 dss->buf_used = TS_SIZE - *ret; 01171 } else { 01172 *ret = TS_SIZE; 01173 } 01174 } 01175 dprintf3("Writing %d bytes(%08x): %02x %02x %02x %02x ...\n", *ret, pc->mmap, pc->mmap[0], pc->mmap[1], pc->mmap[2], pc->mmap[3]); 01176 } 01177 } 01178 01179 static void connect_dss(struct parser_adpt *pc_all) 01180 { 01181 struct cmd_list *fe_preioctl = register_cmd(fe_tune); 01182 struct cmd_list *demux_preioctl = register_cmd(set_demux); 01183 struct cmd_list *demux_postclose = register_cmd(close_demux); 01184 struct cmd_list *fe_postclose = register_cmd(fe_close); 01185 struct cmd_list *dvr_postread = register_cmd(dvr_read); 01186 struct cmd_list *dvr_preread1 = register_cmd(dvr_preread); 01187 struct cmd_list *dvr_postopen = register_cmd(dvr_open); 01188 struct dss *dss; 01189 01190 if(! opt_enable) 01191 return; 01192 dprintf0("Enabling DSS for adapter %d\n", pc_all->frontend->common->virt_adapt); 01193 dss = (struct dss *)malloc(sizeof(struct dss)); 01194 bzero(dss, sizeof(struct dss)); 01195 INIT_LIST_HEAD(&dss->pkt_ll); 01196 dss->buf = (uint8_t *)malloc(2000000); 01197 dss->buf_len = 2000000; 01198 dss->adapt = pc_all->frontend->common->virt_adapt; 01199 pthread_mutex_init(&dss->lock, NULL); 01200 list_add(&fe_preioctl->list, &pc_all->frontend->pre_ioctl); 01201 list_add(&fe_postclose->list, &pc_all->frontend->post_close); 01202 list_add(&demux_preioctl->list, &pc_all->demux->pre_ioctl); 01203 list_add(&demux_postclose->list, &pc_all->demux->post_close); 01204 list_add(&dvr_postread->list, &pc_all->dvr->post_read); 01205 list_add(&dvr_postopen->list, &pc_all->dvr->post_open); 01206 if(opt_file != NULL) 01207 list_add(&dvr_preread1->list, &pc_all->dvr->pre_read); 01208 list_add_tail(&dss->list, &dsslist); 01209 } 01210 01211 static struct option *parseopt_dss(arg_enum_t cmd) 01212 { 01213 if(cmd == ARG_INIT) { 01214 return dss_Opts; 01215 } 01216 if(cmd == ARG_HELP) { 01217 printf(" --dss-file <file> : Read DSS stream from <file> instead of adapter\n"); 01218 printf(" --dss-enable : Enable DSS to DVB mapping\n"); 01219 } 01220 if(! dss_opt) 01221 return NULL; 01222 01223 switch(dss_opt) { 01224 case 'e': 01225 opt_enable = 1; 01226 break; 01227 case 'f': 01228 opt_file = optarg; 01229 break; 01230 } 01231 dss_opt = 0; 01232 return NULL; 01233 } 01234 01235 //list, plugin_id, name, parse_args, connect, launch, message, send_msg 01236 static struct plugin_cmd plugin_cmds = {{NULL, NULL}, PLUGIN_ID, "dss", 01237 parseopt_dss, connect_dss, NULL, NULL, NULL, NULL, NULL}; 01238 int __attribute__((constructor)) __dss_init(void) 01239 { 01240 list_add(&plugin_cmds.list, &plugin_cmdlist); 01241 return 0; 01242 } 01243 #endif