comparison recpt1/recpt1.c @ 8:6da603afd363

added udp capability
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 23 Feb 2009 03:06:17 +0900
parents 407af34cfbd9
children 4615eaf04415
comparison
equal deleted inserted replaced
7:407af34cfbd9 8:6da603afd363
7 #include <string.h> 7 #include <string.h>
8 #include <pthread.h> 8 #include <pthread.h>
9 #include <unistd.h> 9 #include <unistd.h>
10 #include <getopt.h> 10 #include <getopt.h>
11 11
12 #include <netdb.h>
13 #include <arpa/inet.h>
14 #include <netinet/in.h>
15
12 #include <sys/ioctl.h> 16 #include <sys/ioctl.h>
13 #include "pt1_ioctl.h" 17 #include "pt1_ioctl.h"
14 18
15 #include "recpt1.h" 19 #include "recpt1.h"
16 #include "decoder.h" 20 #include "decoder.h"
17 21
18 /* globals */ 22 /* globals */
19 int f_exit = FALSE; 23 int f_exit = FALSE;
24
25 typedef struct sock_data {
26 int sfd; /* socket fd */
27 struct sockaddr_in addr;
28 } sock_data;
20 29
21 typedef struct thread_data { 30 typedef struct thread_data {
22 QUEUE_T *queue; 31 QUEUE_T *queue;
23 decoder *decoder; 32 decoder *decoder;
24 int fd; 33 int wfd; /* output file fd */
34 sock_data *sock_data;
25 } thread_data; 35 } thread_data;
26 36
27 /* lookup frequency conversion table*/ 37 /* lookup frequency conversion table*/
28 ISDB_T_FREQ_CONV_TABLE * 38 ISDB_T_FREQ_CONV_TABLE *
29 searchrecoff(char *channel) 39 searchrecoff(char *channel)
44 54
45 QUEUE_T * 55 QUEUE_T *
46 create_queue(size_t size) 56 create_queue(size_t size)
47 { 57 {
48 QUEUE_T *p_queue; 58 QUEUE_T *p_queue;
49 int memsize = sizeof(QUEUE_T) + size * sizeof(BUFSZ); 59 int memsize = sizeof(QUEUE_T) + size * sizeof(BUFSZ);
50 60
51 p_queue = (QUEUE_T*)calloc(memsize, sizeof(char)); 61 p_queue = (QUEUE_T*)calloc(memsize, sizeof(char));
52 62
53 if(p_queue != NULL) { 63 if(p_queue != NULL) {
54 p_queue->size = size; 64 p_queue->size = size;
102 112
103 /* dequeue data. this function will block if queue is empty. */ 113 /* dequeue data. this function will block if queue is empty. */
104 BUFSZ * 114 BUFSZ *
105 dequeue(QUEUE_T *p_queue) 115 dequeue(QUEUE_T *p_queue)
106 { 116 {
107 BUFSZ *buffer; 117 BUFSZ *buffer;
108 118
109 pthread_mutex_lock(&p_queue->mutex); 119 pthread_mutex_lock(&p_queue->mutex);
110 /* entered the critical section*/ 120 /* entered the critical section*/
111 121
112 /* wait until queue is filled */ 122 /* wait until queue is filled */
137 write_func(void *p) 147 write_func(void *p)
138 { 148 {
139 thread_data *data = (thread_data *)p; 149 thread_data *data = (thread_data *)p;
140 QUEUE_T *p_queue = data->queue; 150 QUEUE_T *p_queue = data->queue;
141 decoder *dec = data->decoder; 151 decoder *dec = data->decoder;
142 int wfd = data->fd; 152 int wfd = data->wfd;
143 int use_b25 = dec ? 1 : 0; 153 int use_b25 = dec ? 1 : 0;
144 BUFSZ *buf; 154 int use_udp = data->sock_data ? 1 : 0;
155 int sfd = 0;
156 struct sockaddr *addr = NULL;
157 BUFSZ *buf;
145 ARIB_STD_B25_BUFFER sbuf, dbuf; 158 ARIB_STD_B25_BUFFER sbuf, dbuf;
146 int code; 159 int code;
160
161 if(use_udp) {
162 sfd = data->sock_data->sfd;
163 addr = (struct sockaddr *)&data->sock_data->addr;
164 }
147 165
148 while(1) { 166 while(1) {
149 buf = dequeue(p_queue); 167 buf = dequeue(p_queue);
150 /* no entry in the queue */ 168 /* no entry in the queue */
151 if(buf == NULL){ 169 if(buf == NULL){
163 fprintf(stderr, "b25_decode failed\n"); 181 fprintf(stderr, "b25_decode failed\n");
164 close(wfd); 182 close(wfd);
165 break; 183 break;
166 } 184 }
167 write(wfd, dbuf.data, dbuf.size); 185 write(wfd, dbuf.data, dbuf.size);
186
187 if(use_udp && sfd) {
188 sendto(sfd, dbuf.data, dbuf.size, 0,
189 addr, sizeof(struct sockaddr_in));
190 }
168 free(buf); 191 free(buf);
169 } else { 192 } else {
170 write(wfd, sbuf.data, sbuf.size); 193 write(wfd, sbuf.data, sbuf.size);
194
195 if(use_udp && sfd) {
196 sendto(sfd, sbuf.data, sbuf.size, 0,
197 addr, sizeof(struct sockaddr_in));
198 }
171 free(buf); 199 free(buf);
172 } 200 }
173 201
174 /* normal exit */ 202 /* normal exit */
175 if((f_exit) && (!p_queue->no_empty)) { 203 if((f_exit) && (!p_queue->no_empty)) {
176 if(use_b25) { 204 if(use_b25) {
177 code = b25_finish(dec, &sbuf, &dbuf); 205 code = b25_finish(dec, &sbuf, &dbuf);
178 if(code < 0) { 206 if(code < 0) {
179 fprintf(stderr, "b25_finish failed\n"); 207 fprintf(stderr, "b25_finish failed\n");
180 close(wfd); 208 close(wfd);
209 close(sfd);
181 break; 210 break;
182 } 211 }
183 write(wfd, dbuf.data, dbuf.size); 212 write(wfd, dbuf.data, dbuf.size);
213
214 if(use_udp && sfd) {
215 sendto(sfd, dbuf.data, dbuf.size, 0,
216 addr, sizeof(struct sockaddr_in));
217 }
184 } 218 }
185 close(wfd); 219 close(wfd);
220 close(sfd);
186 break; 221 break;
187 } 222 }
188 } 223 }
189 224
190 return NULL; 225 return NULL;
226 }
227
228 void
229 show_usage(char *cmd)
230 {
231 fprintf(stderr, "Usage: %s [--b25 [--round N] [--strip] [--EMM]] [--udp hostname [--port port]] channel recsec destfile\n", cmd);
191 } 232 }
192 233
193 int 234 int
194 main(int argc, char **argv) 235 main(int argc, char **argv)
195 { 236 {
196 int fd, wfd; 237 int tfd, wfd;
197 int lp; 238 int lp;
198 int recsec; 239 int recsec;
199 time_t start_time, cur_time; 240 time_t start_time, cur_time;
200 FREQUENCY freq; 241 FREQUENCY freq;
201 ISDB_T_FREQ_CONV_TABLE *ptr; 242 ISDB_T_FREQ_CONV_TABLE *ptr;
202 pthread_t dequeue_threads; 243 pthread_t dequeue_threads;
203 QUEUE_T *p_queue = create_queue(MAX_QUEUE); 244 QUEUE_T *p_queue = create_queue(MAX_QUEUE);
204 BUFSZ *bufptr; 245 BUFSZ *bufptr;
205 decoder *dec = NULL; 246 decoder *dec = NULL;
206 thread_data tdata; 247 thread_data tdata;
207 decoder_options dopt; 248 decoder_options dopt = {
208 249 4, /* round */
209 int use_b25 = 0; 250 0, /* strip */
251 0 /* emm */
252 };
253
210 int result; 254 int result;
211 int option_index; 255 int option_index;
212 struct option long_options[] = { 256 struct option long_options[] = {
213 { "b25", 0, NULL, 'b'}, 257 { "b25", 0, NULL, 'b'},
214 { "B25", 0, NULL, 'b'}, 258 { "B25", 0, NULL, 'b'},
215 { "round", 1, NULL, 'r'}, 259 { "round", 1, NULL, 'r'},
216 { "strip", 0, NULL, 's'}, 260 { "strip", 0, NULL, 's'},
217 { "emm", 0, NULL, 'm'}, 261 { "emm", 0, NULL, 'm'},
218 { "EMM", 0, NULL, 'm'} 262 { "EMM", 0, NULL, 'm'},
263 { "udp", 1, NULL, 'u'},
264 { "port", 1, NULL, 'p'}
219 }; 265 };
220 266
221 dopt.round = 4; 267 int use_b25 = 0;
222 dopt.strip = 0; 268 int use_udp = 0;
223 dopt.emm = 0; 269 char *host_to = NULL;
224 270 int port_to = 1234;
225 while((result = getopt_long(argc, argv, "br:sm", long_options, &option_index)) != -1) { 271 sock_data *sdata = NULL;
272
273 while((result = getopt_long(argc, argv, "br:sm" "u:p:", long_options, &option_index)) != -1) {
226 switch(result) { 274 switch(result) {
227 case 'b': 275 case 'b':
228 use_b25 = 1; 276 use_b25 = 1;
229 fprintf(stderr, "using B25...\n"); 277 fprintf(stderr, "using B25...\n");
230 break; 278 break;
231 case 's': 279 case 's':
232 dopt.strip = 1; 280 dopt.strip = 1;
233 fprintf(stderr, "enable B25 strip\n"); 281 fprintf(stderr, "enable B25 strip\n");
234 break; 282 break;
235 case 'm': 283 case 'm':
236 dopt.emm = 1; 284 dopt.emm = 1;
237 fprintf(stderr, "enable B25 emm processing\n"); 285 fprintf(stderr, "enable B25 emm processing\n");
238 break; 286 break;
239 case 'r': 287 case 'r':
240 dopt.round = atoi(optarg); 288 dopt.round = atoi(optarg);
241 fprintf(stderr, "set round %d\n", dopt.round); 289 fprintf(stderr, "set round %d\n", dopt.round);
242 break; 290 break;
243 case ':': 291 case ':':
244 fprintf(stderr, "%c needs value\n", result); 292 fprintf(stderr, "%c needs value\n", result);
245 break; 293 break;
246 case '?': 294 case '?':
247 fprintf(stderr, "Usage: [--b25 [--round N] [--strip] [--EMM]] channel recsec destfile\n"); 295 show_usage(argv[0]);
248 break; 296 break;
249 } 297 case 'u':
250 } 298 use_udp = 1;
251 299 host_to = optarg;
252 if(argc - optind < 3) { 300 fprintf(stderr, "UDP destination address: %s\n", host_to);
253 printf("Usage %s: [--b25 [--round N] [--strip] [--EMM]] channel recsec destfile\n", argv[0]); 301 break;
302 case 'p':
303 port_to = atoi(optarg);
304 fprintf(stderr, "UDP port: %d\n", port_to);
305 break;
306 }
307 }
308
309 if(argc - optind < 3) {
310 show_usage(argv[0]);
254 printf("channel =\n"); 311 printf("channel =\n");
255 printf("151ch:BS朝日\n"); 312 printf("151ch:BS朝日\n");
256 printf("161ch:BS-i\n"); 313 printf("161ch:BS-i\n");
257 printf("191ch:WOWOW\n"); 314 printf("191ch:WOWOW\n");
258 printf("171ch:BSジャパン\n"); 315 printf("171ch:BSジャパン\n");
265 printf("102ch:NHK衛星第2放送(BS2)\n"); 322 printf("102ch:NHK衛星第2放送(BS2)\n");
266 printf("103ch:NHKハイビジョン(BShi)\n"); 323 printf("103ch:NHKハイビジョン(BShi)\n");
267 printf("CS2-CS24:CSチャンネル\n"); 324 printf("CS2-CS24:CSチャンネル\n");
268 return 1; 325 return 1;
269 } 326 }
270 ptr = searchrecoff(argv[optind]); 327 ptr = searchrecoff(argv[optind]);
271 if(ptr == NULL){ 328 if(ptr == NULL){
272 printf("Channel Select Error(%s)\n", argv[optind]); 329 printf("Channel Select Error(%s)\n", argv[optind]);
273 return 1; 330 return 1;
274 } 331 }
275 332
276 freq.frequencyno = ptr->set_freq; 333 freq.frequencyno = ptr->set_freq;
277 freq.slot = ptr->add_freq; 334 freq.slot = ptr->add_freq;
278 335
279 if(ptr->type == CHTYPE_SATELLITE) { 336 if(ptr->type == CHTYPE_SATELLITE) {
280 for(lp = 0; lp < 2; lp++) { 337 for(lp = 0; lp < 2; lp++) {
281 fd = open(bsdev[lp], O_RDONLY); 338 tfd = open(bsdev[lp], O_RDONLY);
282 if(fd >= 0) { 339 if(tfd >= 0) {
283 break; 340 break;
284 } 341 }
285 } 342 }
286 if(fd < 0) { 343 if(tfd < 0) {
287 fprintf(stderr, "Device Open Error\n"); 344 fprintf(stderr, "Device Open Error\n");
288 return 1; 345 return 1;
289 } 346 }
290 } else { 347 } else {
291 for(lp = 0; lp < 2; lp++) { 348 for(lp = 0; lp < 2; lp++) {
292 fd = open(isdb_t_dev[lp], O_RDONLY); 349 tfd = open(isdb_t_dev[lp], O_RDONLY);
293 if(fd >= 0) { 350 if(tfd >= 0) {
294 break; 351 break;
295 } 352 }
296 } 353 }
297 if(fd < 0) { 354 if(tfd < 0) {
298 fprintf(stderr, "Device Open Error\n"); 355 fprintf(stderr, "Device Open Error\n");
299 return 1; 356 return 1;
300 } 357 }
301 } 358 }
302 recsec = atoi(argv[optind + 1]); 359 recsec = atoi(argv[optind + 1]);
303 360
304 /* initialize decoder */ 361 /* initialize decoder */
305 if(use_b25) { 362 if(use_b25) {
306 dec = b25_startup(&dopt); 363 dec = b25_startup(&dopt);
307 if(!dec) { 364 if(!dec) {
309 fprintf(stderr, "fall back to encrypted recording\n"); 366 fprintf(stderr, "fall back to encrypted recording\n");
310 use_b25 = 0; 367 use_b25 = 0;
311 } 368 }
312 } 369 }
313 370
371 /* initialize udp connection */
372 if(use_udp) {
373 sdata = calloc(1, sizeof(sock_data));
374 struct in_addr ia;
375 ia.s_addr = inet_addr(host_to);
376 if(ia.s_addr == INADDR_NONE) {
377 struct hostent *hoste = gethostbyname(host_to);
378 if(!hoste) {
379 perror("failed to get host by name");
380 return 1;
381 }
382 ia.s_addr = *(in_addr_t*) (hoste->h_addr_list[0]);
383 }
384 sdata->addr.sin_family = AF_INET;
385 sdata->addr.sin_port = htons (port_to);
386 sdata->addr.sin_addr.s_addr = ia.s_addr;
387 if((sdata->sfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
388 perror("socket");
389 return 1;
390 }
391 }
392
314 /* open output file */ 393 /* open output file */
315 wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); 394 wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666);
316 if(wfd < 0) { 395 if(wfd < 0) {
317 fprintf(stderr, "Output File Open Error(%s)\n", argv[optind + 2]); 396 fprintf(stderr, "Output File Open Error(%s)\n", argv[optind + 2]);
318 return 1; 397 return 1;
319 } 398 }
320 399
321 if(ioctl(fd, SET_CHANNEL, &freq) < 0) { 400 if(ioctl(tfd, SET_CHANNEL, &freq) < 0) {
322 fprintf(stderr, "Tuner Select Error\n"); 401 fprintf(stderr, "Tuner Select Error\n");
323 return 1; 402 return 1;
324 } 403 }
325 404
326 /* make reader thread */ 405 /* make reader thread */
327 tdata.queue = p_queue; 406 tdata.queue = p_queue;
328 tdata.decoder = dec; 407 tdata.decoder = dec;
329 tdata.fd = wfd; 408 tdata.wfd = wfd;
409 tdata.sock_data = sdata;
330 pthread_create(&dequeue_threads, NULL, write_func, &tdata); 410 pthread_create(&dequeue_threads, NULL, write_func, &tdata);
331 411
332 /* start recording */ 412 /* start recording */
333 if(ioctl(fd, START_REC, 0) < 0) { 413 if(ioctl(tfd, START_REC, 0) < 0) {
334 fprintf(stderr, "Tuner Start Error\n"); 414 fprintf(stderr, "Tuner Start Error\n");
335 return 1; 415 return 1;
336 } 416 }
337 417
338 time(&start_time); 418 time(&start_time);
339 419
340 /* read from tuner */ 420 /* read from tuner */
341 while(1) { 421 while(1) {
342 time(&cur_time); 422 time(&cur_time);
343 bufptr = malloc(sizeof(BUFSZ)); 423 bufptr = malloc(sizeof(BUFSZ));
344 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE); 424 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE);
345 if(bufptr->size <= 0) { 425 if(bufptr->size <= 0) {
346 if((cur_time - start_time) >= recsec) { 426 if((cur_time - start_time) >= recsec) {
347 f_exit = TRUE; 427 f_exit = TRUE;
348 enqueue(p_queue, NULL); 428 enqueue(p_queue, NULL);
349 break; 429 break;
353 } 433 }
354 enqueue(p_queue, bufptr); 434 enqueue(p_queue, bufptr);
355 435
356 /* stop recording */ 436 /* stop recording */
357 if((cur_time - start_time) >= recsec) { 437 if((cur_time - start_time) >= recsec) {
358 ioctl(fd, STOP_REC, 0); 438 ioctl(tfd, STOP_REC, 0);
359 /* read remaining data */ 439 /* read remaining data */
360 while(1) { 440 while(1) {
361 bufptr = malloc(sizeof(BUFSZ)); 441 bufptr = malloc(sizeof(BUFSZ));
362 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE); 442 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE);
363 if(bufptr->size <= 0) { 443 if(bufptr->size <= 0) {
364 f_exit = TRUE; 444 f_exit = TRUE;
365 enqueue(p_queue, NULL); 445 enqueue(p_queue, NULL);
366 break; 446 break;
367 } 447 }
369 } 449 }
370 break; 450 break;
371 } 451 }
372 } 452 }
373 /* close tuner */ 453 /* close tuner */
374 close(fd); 454 close(tfd);
375 455
376 /* wait reader thread */ 456 /* wait reader thread */
377 pthread_join(dequeue_threads, NULL); 457 pthread_join(dequeue_threads, NULL);
378 destroy_queue(p_queue); 458 destroy_queue(p_queue);
379 459
460 /* close socket */
461 if(use_udp) {
462 close(sdata->sfd);
463 free(sdata);
464 }
465
380 /* release decoder */ 466 /* release decoder */
381 if(use_b25) { 467 if(use_b25) {
382 b25_shutdown(dec); 468 b25_shutdown(dec);
383 } 469 }
384 470