Mercurial > pt1.oyama
comparison recpt1/recpt1.c @ 13:003fe2470af8
reorganized options:
- 0 as recsec means indefinite recording.
- now --udp option works as switch to enable udp broadcasting.
- --host option has been added. this option specifies hostname to connect via udp socket.
- when --udp option is specified, output file may not be specified.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 24 Feb 2009 17:22:06 +0900 |
parents | 4615eaf04415 |
children | cad940a903f5 |
comparison
equal
deleted
inserted
replaced
12:0a6b831f4b89 | 13:003fe2470af8 |
---|---|
149 { | 149 { |
150 thread_data *data = (thread_data *)p; | 150 thread_data *data = (thread_data *)p; |
151 QUEUE_T *p_queue = data->queue; | 151 QUEUE_T *p_queue = data->queue; |
152 decoder *dec = data->decoder; | 152 decoder *dec = data->decoder; |
153 int wfd = data->wfd; | 153 int wfd = data->wfd; |
154 int use_b25 = dec ? 1 : 0; | 154 int use_b25 = dec ? TRUE : FALSE; |
155 int use_udp = data->sock_data ? 1 : 0; | 155 int use_udp = data->sock_data ? TRUE : FALSE; |
156 int sfd = 0; | 156 int fileless = FALSE; |
157 int sfd = -1; | |
157 struct sockaddr *addr = NULL; | 158 struct sockaddr *addr = NULL; |
158 BUFSZ *buf; | 159 BUFSZ *buf; |
159 ARIB_STD_B25_BUFFER sbuf, dbuf; | 160 ARIB_STD_B25_BUFFER sbuf, dbuf; |
160 int code; | 161 int code; |
161 | 162 |
163 if(wfd == -1) | |
164 fileless = TRUE; | |
165 | |
162 if(use_udp) { | 166 if(use_udp) { |
163 sfd = data->sock_data->sfd; | 167 sfd = data->sock_data->sfd; |
164 addr = (struct sockaddr *)&data->sock_data->addr; | 168 addr = (struct sockaddr *)&data->sock_data->addr; |
165 } | 169 } |
166 | 170 |
167 while(1) { | 171 while(1) { |
168 buf = dequeue(p_queue); | 172 |
169 /* no entry in the queue */ | 173 if(fileless) { |
170 if(buf == NULL){ | 174 |
171 close(wfd); | 175 buf = dequeue(p_queue); |
172 break; | 176 /* no entry in the queue */ |
173 } | 177 if(buf == NULL) { |
174 | 178 break; |
175 sbuf.data = buf->buffer; | 179 } |
176 sbuf.size = buf->size; | 180 |
177 | 181 sbuf.data = buf->buffer; |
178 if(use_b25) { | 182 sbuf.size = buf->size; |
179 /* write data to output file*/ | 183 |
180 code = b25_decode(dec, &sbuf, &dbuf); | 184 if(use_b25) { |
181 if(code < 0) { | 185 /* write data to output file*/ |
182 fprintf(stderr, "b25_decode failed\n"); | 186 code = b25_decode(dec, &sbuf, &dbuf); |
187 if(code < 0) { | |
188 fprintf(stderr, "b25_decode failed\n"); | |
189 break; | |
190 } | |
191 | |
192 if(use_udp && sfd != -1) { | |
193 sendto(sfd, dbuf.data, dbuf.size, 0, | |
194 addr, sizeof(struct sockaddr_in)); | |
195 } | |
196 free(buf); | |
197 } else { | |
198 if(use_udp && sfd != -1) { | |
199 sendto(sfd, sbuf.data, sbuf.size, 0, | |
200 addr, sizeof(struct sockaddr_in)); | |
201 } | |
202 free(buf); | |
203 } | |
204 | |
205 /* normal exit */ | |
206 if((f_exit) && (!p_queue->no_empty)) { | |
207 if(use_b25) { | |
208 code = b25_finish(dec, &sbuf, &dbuf); | |
209 if(code < 0) { | |
210 fprintf(stderr, "b25_finish failed\n"); | |
211 close(sfd); | |
212 break; | |
213 } | |
214 | |
215 if(use_udp && sfd != -1) { | |
216 sendto(sfd, dbuf.data, dbuf.size, 0, | |
217 addr, sizeof(struct sockaddr_in)); | |
218 } | |
219 } | |
220 close(sfd); | |
221 break; | |
222 } | |
223 } /* fileless */ | |
224 else { | |
225 | |
226 buf = dequeue(p_queue); | |
227 /* no entry in the queue */ | |
228 if(buf == NULL) { | |
183 close(wfd); | 229 close(wfd); |
184 break; | 230 break; |
185 } | 231 } |
186 write(wfd, dbuf.data, dbuf.size); | 232 |
187 | 233 sbuf.data = buf->buffer; |
188 if(use_udp && sfd) { | 234 sbuf.size = buf->size; |
189 sendto(sfd, dbuf.data, dbuf.size, 0, | 235 |
190 addr, sizeof(struct sockaddr_in)); | |
191 } | |
192 free(buf); | |
193 } else { | |
194 write(wfd, sbuf.data, sbuf.size); | |
195 | |
196 if(use_udp && sfd) { | |
197 sendto(sfd, sbuf.data, sbuf.size, 0, | |
198 addr, sizeof(struct sockaddr_in)); | |
199 } | |
200 free(buf); | |
201 } | |
202 | |
203 /* normal exit */ | |
204 if((f_exit) && (!p_queue->no_empty)) { | |
205 if(use_b25) { | 236 if(use_b25) { |
206 code = b25_finish(dec, &sbuf, &dbuf); | 237 /* write data to output file*/ |
238 code = b25_decode(dec, &sbuf, &dbuf); | |
207 if(code < 0) { | 239 if(code < 0) { |
208 fprintf(stderr, "b25_finish failed\n"); | 240 fprintf(stderr, "b25_decode failed\n"); |
209 close(wfd); | 241 close(wfd); |
210 close(sfd); | |
211 break; | 242 break; |
212 } | 243 } |
213 write(wfd, dbuf.data, dbuf.size); | 244 write(wfd, dbuf.data, dbuf.size); |
214 | 245 |
215 if(use_udp && sfd) { | 246 if(use_udp && sfd != -1) { |
216 sendto(sfd, dbuf.data, dbuf.size, 0, | 247 sendto(sfd, dbuf.data, dbuf.size, 0, |
217 addr, sizeof(struct sockaddr_in)); | 248 addr, sizeof(struct sockaddr_in)); |
218 } | 249 } |
219 } | 250 free(buf); |
220 close(wfd); | 251 } else { |
221 close(sfd); | 252 write(wfd, sbuf.data, sbuf.size); |
222 break; | 253 |
254 if(use_udp && sfd != -1) { | |
255 sendto(sfd, sbuf.data, sbuf.size, 0, | |
256 addr, sizeof(struct sockaddr_in)); | |
257 } | |
258 free(buf); | |
259 } | |
260 | |
261 /* normal exit */ | |
262 if((f_exit) && (!p_queue->no_empty)) { | |
263 if(use_b25) { | |
264 code = b25_finish(dec, &sbuf, &dbuf); | |
265 if(code < 0) { | |
266 fprintf(stderr, "b25_finish failed\n"); | |
267 close(wfd); | |
268 close(sfd); | |
269 break; | |
270 } | |
271 write(wfd, dbuf.data, dbuf.size); | |
272 | |
273 if(use_udp && sfd != -1) { | |
274 sendto(sfd, dbuf.data, dbuf.size, 0, | |
275 addr, sizeof(struct sockaddr_in)); | |
276 } | |
277 } | |
278 close(wfd); | |
279 close(sfd); | |
280 break; | |
281 } | |
223 } | 282 } |
224 } | 283 } |
225 | 284 |
226 return NULL; | 285 return NULL; |
227 } | 286 } |
228 | 287 |
229 void | 288 void |
230 show_usage(char *cmd) | 289 show_usage(char *cmd) |
231 { | 290 { |
232 fprintf(stderr, "Usage: %s [--b25 [--round N] [--strip] [--EMM]] [--udp hostname [--port port]] channel recsec destfile\n", cmd); | 291 fprintf(stderr, "Usage: %s [--b25 [--round N] [--strip] [--EMM]] [--udp [--host hostname --port port]] channel recsec destfile\n", cmd); |
292 } | |
293 | |
294 void | |
295 show_channels(void) | |
296 { | |
297 printf("Channel List:\n"); | |
298 printf("151ch:BS Asahi\n"); | |
299 printf("161ch:BS-i\n"); | |
300 printf("191ch:WOWOW\n"); | |
301 printf("171ch:BS Japan\n"); | |
302 printf("200ch:Star Channel\n"); | |
303 printf("211ch:BS11 Digital\n"); | |
304 printf("222ch:TwellV\n"); | |
305 printf("141ch:BS Nittele\n"); | |
306 printf("181ch:BS Fuji\n"); | |
307 printf("101ch:NHK BS1\n"); | |
308 printf("102ch:NHK BS2\n"); | |
309 printf("103ch:NHK BShi\n"); | |
310 printf("CS2-CS24:CS Channels\n"); | |
233 } | 311 } |
234 | 312 |
235 float | 313 float |
236 getsignal_isdb_s(int signal) | 314 getsignal_isdb_s(int signal) |
237 { | 315 { |
238 // 線形補完で近似する | 316 /* apply linear interpolation */ |
239 static const float afLevelTable[] = { | 317 static const float afLevelTable[] = { |
240 24.07f, // 00 00 0 24.07dB | 318 24.07f, // 00 00 0 24.07dB |
241 24.07f, // 10 00 4096 24.07dB | 319 24.07f, // 10 00 4096 24.07dB |
242 18.61f, // 20 00 8192 18.61dB | 320 18.61f, // 20 00 8192 18.61dB |
243 15.21f, // 30 00 12288 15.21dB | 321 15.21f, // 30 00 12288 15.21dB |
256 unsigned char sigbuf[4]; | 334 unsigned char sigbuf[4]; |
257 memset(sigbuf, '\0', sizeof(sigbuf)); | 335 memset(sigbuf, '\0', sizeof(sigbuf)); |
258 sigbuf[0] = (((signal & 0xFF00) >> 8) & 0XFF); | 336 sigbuf[0] = (((signal & 0xFF00) >> 8) & 0XFF); |
259 sigbuf[1] = (signal & 0xFF); | 337 sigbuf[1] = (signal & 0xFF); |
260 | 338 |
261 // 信号レベル計算 | 339 /* calculate signal level */ |
262 if(sigbuf[0] <= 0x10U){ | 340 if(sigbuf[0] <= 0x10U){ |
263 // 最大クリップ | 341 /* clipped maximum */ |
264 return 24.07f; | 342 return 24.07f; |
265 } else if (sigbuf[0] >= 0xB0U) { | 343 } else if (sigbuf[0] >= 0xB0U) { |
266 // 最小クリップ | 344 /* clipped minimum */ |
267 return 0.0f; | 345 return 0.0f; |
268 } else { | 346 } else { |
269 // 線形補完 | 347 /* linear interpolation */ |
270 const float fMixRate = | 348 const float fMixRate = |
271 (float)(((unsigned short)(sigbuf[0] & 0x0FU) << 8) | | 349 (float)(((unsigned short)(sigbuf[0] & 0x0FU) << 8) | |
272 (unsigned short)sigbuf[0]) / 4096.0f; | 350 (unsigned short)sigbuf[0]) / 4096.0f; |
273 return afLevelTable[sigbuf[0] >> 4] * (1.0f - fMixRate) + | 351 return afLevelTable[sigbuf[0] >> 4] * (1.0f - fMixRate) + |
274 afLevelTable[(sigbuf[0] >> 4) + 0x01U] * fMixRate; | 352 afLevelTable[(sigbuf[0] >> 4) + 0x01U] * fMixRate; |
276 } | 354 } |
277 | 355 |
278 void | 356 void |
279 calc_cn(int fd, int type) | 357 calc_cn(int fd, int type) |
280 { | 358 { |
281 | |
282 int rc ; | 359 int rc ; |
283 double P ; | 360 double P ; |
284 double CNR; | 361 double CNR; |
285 | 362 |
286 if(ioctl(fd, GET_SIGNAL_STRENGTH, &rc) < 0) { | 363 if(ioctl(fd, GET_SIGNAL_STRENGTH, &rc) < 0) { |
303 main(int argc, char **argv) | 380 main(int argc, char **argv) |
304 { | 381 { |
305 int tfd, wfd; | 382 int tfd, wfd; |
306 int lp; | 383 int lp; |
307 int recsec; | 384 int recsec; |
385 int indefinite = FALSE; | |
308 time_t start_time, cur_time; | 386 time_t start_time, cur_time; |
309 FREQUENCY freq; | 387 FREQUENCY freq; |
310 ISDB_T_FREQ_CONV_TABLE *ptr; | 388 ISDB_T_FREQ_CONV_TABLE *ptr; |
311 pthread_t dequeue_threads; | 389 pthread_t dequeue_threads; |
312 QUEUE_T *p_queue = create_queue(MAX_QUEUE); | 390 QUEUE_T *p_queue = create_queue(MAX_QUEUE); |
326 { "B25", 0, NULL, 'b'}, | 404 { "B25", 0, NULL, 'b'}, |
327 { "round", 1, NULL, 'r'}, | 405 { "round", 1, NULL, 'r'}, |
328 { "strip", 0, NULL, 's'}, | 406 { "strip", 0, NULL, 's'}, |
329 { "emm", 0, NULL, 'm'}, | 407 { "emm", 0, NULL, 'm'}, |
330 { "EMM", 0, NULL, 'm'}, | 408 { "EMM", 0, NULL, 'm'}, |
331 { "udp", 1, NULL, 'u'}, | 409 { "udp", 0, NULL, 'u'}, |
332 { "port", 1, NULL, 'p'} | 410 { "host", 1, NULL, 'h'}, |
411 { "port", 1, NULL, 'p'}, | |
412 {0, 0, 0, 0} /* terminate */ | |
333 }; | 413 }; |
334 | 414 |
335 int use_b25 = 0; | 415 int use_b25 = FALSE; |
336 int use_udp = 0; | 416 int use_udp = FALSE; |
417 int fileless = FALSE; | |
337 char *host_to = NULL; | 418 char *host_to = NULL; |
338 int port_to = 1234; | 419 int port_to = 1234; |
339 sock_data *sdata = NULL; | 420 sock_data *sdata = NULL; |
340 | 421 |
341 while((result = getopt_long(argc, argv, "br:sm" "u:p:", long_options, &option_index)) != -1) { | 422 while((result = getopt_long(argc, argv, "br:smuh:p:", long_options, &option_index)) != -1) { |
342 switch(result) { | 423 switch(result) { |
343 case 'b': | 424 case 'b': |
344 use_b25 = 1; | 425 use_b25 = TRUE; |
345 fprintf(stderr, "using B25...\n"); | 426 fprintf(stderr, "using B25...\n"); |
346 break; | 427 break; |
347 case 's': | 428 case 's': |
348 dopt.strip = 1; | 429 dopt.strip = TRUE; |
349 fprintf(stderr, "enable B25 strip\n"); | 430 fprintf(stderr, "enable B25 strip\n"); |
350 break; | 431 break; |
351 case 'm': | 432 case 'm': |
352 dopt.emm = 1; | 433 dopt.emm = TRUE; |
353 fprintf(stderr, "enable B25 emm processing\n"); | 434 fprintf(stderr, "enable B25 emm processing\n"); |
354 break; | 435 break; |
436 case 'u': | |
437 use_udp = TRUE; | |
438 host_to = "localhost"; | |
439 fprintf(stderr, "enable UDP broadcasting\n"); | |
440 break; | |
441 /* | |
442 case ':': | |
443 fprintf(stderr, "%c needs value\n", result); | |
444 break; | |
445 */ | |
446 case '?': | |
447 show_usage(argv[0]); | |
448 break; | |
449 | |
450 | |
451 /* following options require argument */ | |
355 case 'r': | 452 case 'r': |
356 dopt.round = atoi(optarg); | 453 dopt.round = atoi(optarg); |
357 fprintf(stderr, "set round %d\n", dopt.round); | 454 fprintf(stderr, "set round %d\n", dopt.round); |
358 break; | 455 break; |
359 case ':': | 456 case 'h': |
360 fprintf(stderr, "%c needs value\n", result); | 457 use_udp = TRUE; |
361 break; | |
362 case '?': | |
363 show_usage(argv[0]); | |
364 break; | |
365 case 'u': | |
366 use_udp = 1; | |
367 host_to = optarg; | 458 host_to = optarg; |
368 fprintf(stderr, "UDP destination address: %s\n", host_to); | 459 fprintf(stderr, "UDP destination address: %s\n", host_to); |
369 break; | 460 break; |
370 case 'p': | 461 case 'p': |
371 port_to = atoi(optarg); | 462 port_to = atoi(optarg); |
373 break; | 464 break; |
374 } | 465 } |
375 } | 466 } |
376 | 467 |
377 if(argc - optind < 3) { | 468 if(argc - optind < 3) { |
378 show_usage(argv[0]); | 469 if(argc - optind == 2 && use_udp) { |
379 printf("channel =\n"); | 470 fprintf(stderr, "fileless udp broadcasting\n"); |
380 printf("151ch:BS朝日\n"); | 471 fileless = TRUE; |
381 printf("161ch:BS-i\n"); | 472 wfd = -1; |
382 printf("191ch:WOWOW\n"); | 473 } |
383 printf("171ch:BSジャパン\n"); | 474 else { |
384 printf("200ch:スターチャンネル\n"); | 475 show_usage(argv[0]); |
385 printf("211ch:BS11デジタル\n"); | 476 show_channels(); |
386 printf("222ch:TwellV\n"); | 477 return 1; |
387 printf("141ch:BS日テレ\n"); | 478 } |
388 printf("181ch:BSフジ\n"); | 479 } |
389 printf("101ch:NHK衛星第1放送(BS1)\n"); | 480 |
390 printf("102ch:NHK衛星第2放送(BS2)\n"); | 481 /* get channel */ |
391 printf("103ch:NHKハイビジョン(BShi)\n"); | |
392 printf("CS2-CS24:CSチャンネル\n"); | |
393 return 1; | |
394 } | |
395 ptr = searchrecoff(argv[optind]); | 482 ptr = searchrecoff(argv[optind]); |
396 if(ptr == NULL){ | 483 if(ptr == NULL){ |
397 printf("Channel Select Error(%s)\n", argv[optind]); | 484 fprintf(stderr, "Channel Select Error(%s)\n", argv[optind]); |
398 return 1; | 485 return 1; |
399 } | 486 } |
400 | 487 |
401 freq.frequencyno = ptr->set_freq; | 488 freq.frequencyno = ptr->set_freq; |
402 freq.slot = ptr->add_freq; | 489 freq.slot = ptr->add_freq; |
422 if(tfd < 0) { | 509 if(tfd < 0) { |
423 fprintf(stderr, "Device Open Error\n"); | 510 fprintf(stderr, "Device Open Error\n"); |
424 return 1; | 511 return 1; |
425 } | 512 } |
426 } | 513 } |
514 | |
515 /* get recsec */ | |
427 recsec = atoi(argv[optind + 1]); | 516 recsec = atoi(argv[optind + 1]); |
517 if(recsec == 0) | |
518 indefinite = TRUE; | |
428 | 519 |
429 /* initialize decoder */ | 520 /* initialize decoder */ |
430 if(use_b25) { | 521 if(use_b25) { |
431 dec = b25_startup(&dopt); | 522 dec = b25_startup(&dopt); |
432 if(!dec) { | 523 if(!dec) { |
457 return 1; | 548 return 1; |
458 } | 549 } |
459 } | 550 } |
460 | 551 |
461 /* open output file */ | 552 /* open output file */ |
462 wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); | 553 if(!fileless) { |
463 if(wfd < 0) { | 554 wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); |
464 fprintf(stderr, "Output File Open Error(%s)\n", argv[optind + 2]); | 555 if(wfd < 0) { |
465 return 1; | 556 fprintf(stderr, "Output File Open Error(%s)\n", argv[optind + 2]); |
466 } | 557 return 1; |
467 | 558 } |
559 } | |
468 if(ptr->type == CHTYPE_SATELLITE){ | 560 if(ptr->type == CHTYPE_SATELLITE){ |
469 if(ioctl(tfd, LNB_ENABLE, 0) < 0){ | 561 if(ioctl(tfd, LNB_ENABLE, 0) < 0){ |
470 return 0 ; | 562 return 0 ; |
471 } | 563 } |
472 } | 564 } |
497 while(1) { | 589 while(1) { |
498 time(&cur_time); | 590 time(&cur_time); |
499 bufptr = malloc(sizeof(BUFSZ)); | 591 bufptr = malloc(sizeof(BUFSZ)); |
500 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE); | 592 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE); |
501 if(bufptr->size <= 0) { | 593 if(bufptr->size <= 0) { |
502 if((cur_time - start_time) >= recsec) { | 594 if((cur_time - start_time) >= recsec && !indefinite) { |
503 f_exit = TRUE; | 595 f_exit = TRUE; |
504 enqueue(p_queue, NULL); | 596 enqueue(p_queue, NULL); |
505 break; | 597 break; |
506 } else { | 598 } else { |
507 continue; | 599 continue; |
508 } | 600 } |
509 } | 601 } |
510 enqueue(p_queue, bufptr); | 602 enqueue(p_queue, bufptr); |
511 | 603 |
512 /* stop recording */ | 604 /* stop recording */ |
513 if((cur_time - start_time) >= recsec) { | 605 if((cur_time - start_time) >= recsec && !indefinite) { |
514 ioctl(tfd, STOP_REC, 0); | 606 ioctl(tfd, STOP_REC, 0); |
515 /* read remaining data */ | 607 /* read remaining data */ |
516 while(1) { | 608 while(1) { |
517 bufptr = malloc(sizeof(BUFSZ)); | 609 bufptr = malloc(sizeof(BUFSZ)); |
518 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE); | 610 bufptr->size = read(tfd, bufptr->buffer, MAX_READ_SIZE); |