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);