root/trunk/tvheadend/src/rawtsinput.c @ 3083

Revision 3083, 5.4 KB (checked in by andoma, 15 months ago)

Figure out if we need to re-save a transport configuration instead of relying on if we've seen it once, it can not change

Line 
1/*
2 *  Raw TS input (for debugging)
3 *  Copyright (C) 2009 Andreas Öman
4 *
5 *  This program is free software: you can redistribute it and/or modify
6 *  it under the terms of the GNU General Public License as published by
7 *  the Free Software Foundation, either version 3 of the License, or
8 *  (at your option) any later version.
9 *
10 *  This program is distributed in the hope that it will be useful,
11 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 *  GNU General Public License for more details.
14 *
15 *  You should have received a copy of the GNU General Public License
16 *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17 */
18
19#include <pthread.h>
20#include <stdint.h>
21#include <sys/types.h>
22#include <sys/stat.h>
23#include <unistd.h>
24#include <fcntl.h>
25#include <stdio.h>
26#include <string.h>
27#include <errno.h>
28
29#include "tvhead.h"
30#include "transports.h"
31#include "rawtsinput.h"
32#include "psi.h"
33#include "tsdemux.h"
34
35typedef struct rawts {
36  int rt_fd;
37
38  char *rt_identifier;
39  psi_section_t rt_pat;
40
41  struct th_transport_list rt_transports;
42
43} rawts_t;
44
45
46/**
47 *
48 */
49static int
50rawts_transport_start(th_transport_t *t, unsigned int weight, int status,
51                      int force_start)
52{
53  return 0; // Always ok
54}
55
56/**
57 *
58 */
59static void
60rawts_transport_stop(th_transport_t *t)
61{
62 
63}
64
65/**
66 *
67 */
68static void
69rawts_transport_save(th_transport_t *t)
70{
71}
72
73
74/**
75 *
76 */
77static int
78rawts_transport_quality(th_transport_t *t)
79{
80  return 100;
81}
82
83
84/**
85 * Generate a descriptive name for the source
86 */
87static const char *
88rawts_transport_sourcename(th_transport_t *t)
89{
90  return "rawts";
91}
92
93
94/**
95 * Generate a descriptive name for the source
96 */
97static const char *
98rawts_transport_networkname(th_transport_t *t)
99{
100  return "rawts";
101}
102
103
104
105/**
106 *
107 */
108static th_transport_t *
109rawts_transport_add(rawts_t *rt, uint16_t sid, int pmt_pid)
110{
111  th_transport_t *t;
112  channel_t *ch;
113
114  char tmp[200];
115
116  LIST_FOREACH(t, &rt->rt_transports, tht_mux_link) {
117    if(t->tht_dvb_service_id == sid)
118      return t;
119  }
120 
121  snprintf(tmp, sizeof(tmp), "%s_%04x", rt->rt_identifier, sid);
122
123  t = transport_create(tmp, TRANSPORT_DVB, THT_MPEG_TS);
124  t->tht_flags |= THT_DEBUG;
125
126  t->tht_dvb_service_id = sid;
127  t->tht_pmt_pid        = pmt_pid;
128
129  t->tht_start_feed = rawts_transport_start;
130  t->tht_stop_feed  = rawts_transport_stop;
131  t->tht_config_change = rawts_transport_save;
132  t->tht_sourcename = rawts_transport_sourcename;
133  t->tht_networkname = rawts_transport_networkname;
134  t->tht_quality_index = rawts_transport_quality;
135
136  t->tht_svcname = strdup(tmp);
137
138  tvhlog(LOG_NOTICE, "rawts", "Added service %d (pmt: %d)", sid, pmt_pid);
139
140  LIST_INSERT_HEAD(&rt->rt_transports, t, tht_mux_link);
141
142  ch = channel_find_by_name(tmp, 1);
143
144  transport_map_channel(t, ch);
145  return t;
146}
147
148
149/*
150 *
151 */
152
153static void
154got_pmt(struct th_transport *t, th_stream_t *st,
155        uint8_t *table, int table_len)
156{
157  if(table[0] != 2)
158    return;
159
160  pthread_mutex_lock(&global_lock);
161  psi_parse_pmt(t, table + 3, table_len - 3, 1);
162  pthread_mutex_unlock(&global_lock);
163}
164
165
166
167/**
168 *
169 */
170static void
171got_pat(rawts_t *rt)
172{
173  th_transport_t *t;
174  th_stream_t *st;
175  int len = rt->rt_pat.ps_offset;
176  uint8_t *ptr = rt->rt_pat.ps_data;
177  uint16_t prognum;
178  uint16_t pid;
179
180  len -= 8;
181  ptr += 8;
182
183  if(len < 0)
184    return;
185
186  pthread_mutex_lock(&global_lock);
187
188  while(len >= 4) {
189   
190    prognum =  ptr[0]         << 8 | ptr[1];
191    pid     = (ptr[2] & 0x1f) << 8 | ptr[3];
192
193    if(prognum != 0) {
194      t = rawts_transport_add(rt, prognum, pid);
195
196      if(t != NULL) {
197        pthread_mutex_lock(&t->tht_stream_mutex);
198
199        if(transport_stream_find(t, pid) == NULL) {
200          st = transport_stream_create(t, pid, SCT_PMT);
201          st->st_section_docrc = 1;
202          st->st_got_section = got_pmt;
203        }
204        pthread_mutex_unlock(&t->tht_stream_mutex);
205      }
206    }
207    ptr += 4;
208    len -= 4;
209  } 
210  pthread_mutex_unlock(&global_lock);
211}
212
213/**
214 *
215 */
216static void
217rawts_pat(rawts_t *rt, uint8_t *tsb)
218{
219  int off  = tsb[3] & 0x20 ? tsb[4] + 5 : 4;
220  int pusi = tsb[1] & 0x40;
221  int len;
222
223  if(off >= 188)
224    return;
225
226  if(pusi) {
227    len = tsb[off++];
228    if(len > 0) {
229      if(len > 188 - off)
230        return;
231      if(!psi_section_reassemble(&rt->rt_pat, tsb + off, len, 0, 1))
232        got_pat(rt);
233      off += len;
234    }
235  }
236   
237  if(!psi_section_reassemble(&rt->rt_pat, tsb + off, 188 - off, pusi, 1))
238    got_pat(rt);
239}
240
241
242/**
243 *
244 */
245static void
246process_ts_packet(rawts_t *rt, uint8_t *tsb)
247{
248  uint16_t pid;
249  th_transport_t *t;
250
251  pid = ((tsb[1] & 0xf) << 8) | tsb[2];
252
253  if(pid == 0) {
254    /* PAT */
255    rawts_pat(rt, tsb);
256    return;
257  }
258 
259  LIST_FOREACH(t, &rt->rt_transports, tht_mux_link)
260    ts_recv_packet1(t, tsb);
261}
262
263
264/**
265 *
266 */
267static void *
268raw_ts_reader(void *aux)
269{
270  rawts_t *rt = aux;
271  uint8_t tsblock[188];
272  int c = 0;
273  int i;
274
275  while(1) {
276
277    for(i = 0; i < 2; i++) {
278      if(read(rt->rt_fd, tsblock, 188) != 188) {
279        lseek(rt->rt_fd, 0, SEEK_SET);
280        continue;
281      }
282      c++;
283      process_ts_packet(rt, tsblock);
284    }
285    usleep(1000);
286  }
287
288  return NULL;
289}
290
291
292/**
293 *
294 */
295void
296rawts_init(const char *filename)
297{
298  pthread_t ptid;
299  rawts_t *rt;
300  int fd = open(filename, O_RDONLY);
301
302  if(fd == -1) {
303    fprintf(stderr, "Unable to open %s -- %s\n", filename, strerror(errno));
304    return;
305  }
306
307  rt = calloc(1, sizeof(rawts_t));
308  rt->rt_fd = fd;
309
310  rt->rt_identifier = strdup("rawts");
311
312  pthread_create(&ptid, NULL, raw_ts_reader, rt);
313}
Note: See TracBrowser for help on using the browser.