Mercurial > pt1
comparison recpt1/recpt1.c @ 5:97fd2315114e
- now it can handle options.
- applied channel patch.
- some cleanups.
author | Yoshiki Yazawa <yaz@honeyplanet.jp> |
---|---|
date | Tue, 17 Feb 2009 05:58:36 +0900 |
parents | 43d177fa65c9 |
children | d898fd27547f |
comparison
equal
deleted
inserted
replaced
4:43d177fa65c9 | 5:97fd2315114e |
---|---|
1 #include <stdio.h> | |
1 #include <fcntl.h> | 2 #include <fcntl.h> |
2 #include <sys/types.h> | 3 #include <sys/types.h> |
3 #include <sys/stat.h> | 4 #include <sys/stat.h> |
4 #include <time.h> | 5 #include <time.h> |
5 #include <stdlib.h> | 6 #include <stdlib.h> |
6 #include <string.h> | 7 #include <string.h> |
7 #include <pthread.h> | 8 #include <pthread.h> |
8 #include <unistd.h> | 9 #include <unistd.h> |
9 #include <stdio.h> | 10 #include <getopt.h> |
10 | 11 |
11 #include <sys/ioctl.h> | 12 #include <sys/ioctl.h> |
12 #include "pt1_ioctl.h" | 13 #include "pt1_ioctl.h" |
13 | 14 |
14 #include "recpt1.h" | 15 #include "recpt1.h" |
15 #include "decoder.h" | 16 #include "decoder.h" |
16 | 17 |
17 /* globals */ | 18 /* globals */ |
18 int wfd; /* for output file */ | 19 int f_exit = FALSE; |
19 int f_exit = FALSE ; | |
20 | 20 |
21 typedef struct thread_data { | 21 typedef struct thread_data { |
22 QUEUE_T *queue; | 22 QUEUE_T *queue; |
23 decoder *decoder; | 23 decoder *decoder; |
24 int fd; | |
24 } thread_data; | 25 } thread_data; |
25 | 26 |
26 // 周波数テーブル変換 | 27 // 周波数テーブル変換 |
27 ISDB_T_FREQ_CONV_TABLE * | 28 ISDB_T_FREQ_CONV_TABLE * |
28 searchrecoff(char *channel) | 29 searchrecoff(char *channel) |
29 { | 30 { |
30 int lp ; | 31 int lp; |
31 | 32 |
32 for(lp = 0 ; lp < 113 ; lp++){ | 33 for(lp = 0; isdb_t_conv_table[lp].parm_freq != NULL; lp++){ |
33 // 文字列&長さ一致したら周波数テーブル番号を返却する | 34 // 文字列&長さ一致したら周波数テーブル番号を返却する |
34 if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, | 35 if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, |
35 strlen(channel)) == 0) && | 36 strlen(channel)) == 0) && |
36 (strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))){ | 37 (strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))){ |
37 return &isdb_t_conv_table[lp] ; | 38 return &isdb_t_conv_table[lp]; |
38 } | 39 } |
39 } | 40 } |
40 return NULL ; | 41 return NULL; |
41 } | 42 } |
42 | 43 |
43 QUEUE_T * | 44 QUEUE_T * |
44 create_queue(size_t size) | 45 create_queue(size_t size) |
45 { | 46 { |
46 QUEUE_T *p_queue; | 47 QUEUE_T *p_queue; |
47 int memsize = sizeof(QUEUE_T) + size * sizeof(BUFSZ); | 48 int memsize = sizeof(QUEUE_T) + size * sizeof(BUFSZ); |
48 | 49 |
49 p_queue = (QUEUE_T*)calloc(memsize, sizeof(char)); | 50 p_queue = (QUEUE_T*)calloc(memsize, sizeof(char)); |
50 | 51 |
51 if(p_queue != NULL){ | 52 if(p_queue != NULL) { |
52 p_queue->size = size; | 53 p_queue->size = size; |
53 p_queue->no_full = size; | 54 p_queue->no_full = size; |
54 p_queue->no_empty = 0; | 55 p_queue->no_empty = 0; |
55 pthread_mutex_init(&p_queue->mutex, NULL); | 56 pthread_mutex_init(&p_queue->mutex, NULL); |
56 pthread_cond_init(&p_queue->cond_full, NULL); | 57 pthread_cond_init(&p_queue->cond_full, NULL); |
61 } | 62 } |
62 | 63 |
63 void | 64 void |
64 destroy_queue(QUEUE_T *p_queue) | 65 destroy_queue(QUEUE_T *p_queue) |
65 { | 66 { |
66 if(p_queue != NULL) { | 67 if(!p_queue) |
67 pthread_mutex_destroy(&p_queue->mutex); | 68 return; |
68 pthread_cond_destroy(&p_queue->cond_full); | 69 |
69 pthread_cond_destroy(&p_queue->cond_empty); | 70 pthread_mutex_destroy(&p_queue->mutex); |
70 free(p_queue); | 71 pthread_cond_destroy(&p_queue->cond_full); |
71 } | 72 pthread_cond_destroy(&p_queue->cond_empty); |
73 free(p_queue); | |
72 } | 74 } |
73 | 75 |
74 /* enqueue data. this function will block if queue is full. */ | 76 /* enqueue data. this function will block if queue is full. */ |
75 void | 77 void |
76 enqueue(QUEUE_T *p_queue, BUFSZ *data) | 78 enqueue(QUEUE_T *p_queue, BUFSZ *data) |
79 /* entered critical section */ | 81 /* entered critical section */ |
80 | 82 |
81 /* wait until queue is not full */ | 83 /* wait until queue is not full */ |
82 while(!p_queue->no_full) { | 84 while(!p_queue->no_full) { |
83 pthread_cond_wait(&p_queue->cond_full, &p_queue->mutex); | 85 pthread_cond_wait(&p_queue->cond_full, &p_queue->mutex); |
84 printf("Full\n"); | 86 fprintf(stderr, "Full\n"); |
85 } | 87 } |
86 | 88 |
87 p_queue->buffer[p_queue->in] = data; | 89 p_queue->buffer[p_queue->in] = data; |
88 | 90 |
89 p_queue->in++; | 91 p_queue->in++; |
134 write_func(void *p) | 136 write_func(void *p) |
135 { | 137 { |
136 thread_data *data = (thread_data *)p; | 138 thread_data *data = (thread_data *)p; |
137 QUEUE_T *p_queue = data->queue; | 139 QUEUE_T *p_queue = data->queue; |
138 decoder *dec = data->decoder; | 140 decoder *dec = data->decoder; |
139 BUFSZ *buf ; | 141 int wfd = data->fd; |
142 int use_b25 = dec ? 1 : 0; | |
143 BUFSZ *buf; | |
140 ARIB_STD_B25_BUFFER sbuf, dbuf; | 144 ARIB_STD_B25_BUFFER sbuf, dbuf; |
145 int code; | |
141 | 146 |
142 while(1) { | 147 while(1) { |
143 buf = dequeue(p_queue); | 148 buf = dequeue(p_queue); |
144 /* no entry in the queue */ | 149 /* no entry in the queue */ |
145 if(buf == NULL){ | 150 if(buf == NULL){ |
146 close(wfd); | 151 close(wfd); |
147 break ; | 152 break; |
148 } | 153 } |
149 | 154 |
150 sbuf.data = buf->buffer; | 155 sbuf.data = buf->buffer; |
151 sbuf.size = buf->size; | 156 sbuf.size = buf->size; |
152 | 157 |
153 /* write data to output file*/ | 158 if(use_b25) { |
154 b25_decode(dec, &sbuf, &dbuf); | 159 /* write data to output file*/ |
155 write(wfd, dbuf.data, dbuf.size); | 160 code = b25_decode(dec, &sbuf, &dbuf); |
156 free(buf); | 161 if(code < 0) { |
162 fprintf(stderr, "b25_decode failed\n"); | |
163 close(wfd); | |
164 break; | |
165 } | |
166 write(wfd, dbuf.data, dbuf.size); | |
167 free(buf); | |
168 } else { | |
169 write(wfd, sbuf.data, sbuf.size); | |
170 free(buf); | |
171 } | |
157 | 172 |
158 /* normal exit */ | 173 /* normal exit */ |
159 if((f_exit) && (!p_queue->no_empty)){ | 174 if((f_exit) && (!p_queue->no_empty)) { |
160 b25_finish(dec, &sbuf, &dbuf); | 175 if(use_b25) { |
161 write(wfd, dbuf.data, dbuf.size); | 176 code = b25_finish(dec, &sbuf, &dbuf); |
177 if(code < 0) { | |
178 fprintf(stderr, "b25_finish failed\n"); | |
179 close(wfd); | |
180 break; | |
181 } | |
182 write(wfd, dbuf.data, dbuf.size); | |
183 } | |
162 close(wfd); | 184 close(wfd); |
163 break ; | 185 break; |
164 } | 186 } |
165 } | 187 } |
166 | 188 |
167 return NULL; | 189 return NULL; |
168 } | 190 } |
169 | 191 |
170 int | 192 int |
171 main(int argc, char **argv) | 193 main(int argc, char **argv) |
172 { | 194 { |
173 int fd ; | 195 int fd, wfd; |
174 int lp ; | 196 int lp; |
175 int recsec ; | 197 int recsec; |
176 time_t start_time ; | 198 time_t start_time, cur_time; |
177 time_t cur_time ; | |
178 FREQUENCY freq; | 199 FREQUENCY freq; |
179 ISDB_T_FREQ_CONV_TABLE *ptr ; | 200 ISDB_T_FREQ_CONV_TABLE *ptr; |
180 pthread_t dequeue_threads; | 201 pthread_t dequeue_threads; |
181 QUEUE_T *p_queue = create_queue(MAX_QUEUE); | 202 QUEUE_T *p_queue = create_queue(MAX_QUEUE); |
182 BUFSZ *bufptr ; | 203 BUFSZ *bufptr; |
183 decoder *dec; | 204 decoder *dec = NULL; |
184 thread_data tdata; | 205 thread_data tdata; |
185 | 206 decoder_options dopt; |
186 if(argc < 4) { | 207 |
187 printf("Usage %s: channel recsec destfile\n", argv[0]); | 208 int use_b25 = 0; |
209 int result; | |
210 int option_index; | |
211 struct option long_options[] = { | |
212 { "b25", 0, NULL, 'b'}, | |
213 { "B25", 0, NULL, 'b'}, | |
214 { "round", 1, NULL, 'r'}, | |
215 { "strip", 0, NULL, 's'}, | |
216 { "emm", 0, NULL, 'm'}, | |
217 { "EMM", 0, NULL, 'm'} | |
218 }; | |
219 | |
220 dopt.round = 4; | |
221 dopt.strip = 0; | |
222 dopt.emm = 0; | |
223 | |
224 while((result = getopt_long(argc, argv, "br:sm", long_options, &option_index)) != -1) { | |
225 switch(result) { | |
226 case 'b': | |
227 use_b25 = 1; | |
228 fprintf(stderr, "using B25...\n"); | |
229 break; | |
230 case 's': | |
231 dopt.strip = 1; | |
232 fprintf(stderr, "enable B25 strip\n"); | |
233 break; | |
234 case 'm': | |
235 dopt.emm = 1; | |
236 fprintf(stderr, "enable B25 emm processing\n"); | |
237 break; | |
238 case 'r': | |
239 dopt.round = atoi(optarg); | |
240 fprintf(stderr, "set round %d\n", dopt.round); | |
241 break; | |
242 case ':': | |
243 fprintf(stderr, "%c needs value\n", result); | |
244 break; | |
245 case '?': | |
246 fprintf(stderr, "Usage: [--b25 [--round N] [--strip] [--EMM]] channel recsec destfile\n"); | |
247 break; | |
248 } | |
249 } | |
250 | |
251 if(argc - optind < 3) { | |
252 printf("Usage %s: [--b25 [--round N] [--strip] [--EMM]] channel recsec destfile\n", argv[0]); | |
188 printf("channel =\n"); | 253 printf("channel =\n"); |
189 printf("151ch:BS朝日\n"); | 254 printf("151ch:BS朝日\n"); |
190 printf("161ch:BS-i\n"); | 255 printf("161ch:BS-i\n"); |
256 printf("191ch:WOWOW\n"); | |
191 printf("171ch:BSジャパン\n"); | 257 printf("171ch:BSジャパン\n"); |
258 printf("200ch:スターチャンネル\n"); | |
192 printf("211ch:BS11デジタル\n"); | 259 printf("211ch:BS11デジタル\n"); |
193 printf("222ch:TwellV\n"); | 260 printf("222ch:TwellV\n"); |
194 printf("141ch:BS日テレ\n"); | 261 printf("141ch:BS日テレ\n"); |
195 printf("181ch:BSフジ\n"); | 262 printf("181ch:BSフジ\n"); |
196 printf("101ch:NHK衛星第1放送(BS1)\n"); | 263 printf("101ch:NHK衛星第1放送(BS1)\n"); |
197 printf("102ch:NHK衛星第2放送(BS2)\n"); | 264 printf("102ch:NHK衛星第2放送(BS2)\n"); |
198 printf("103ch:NHKハイビジョン(BShi)\n"); | 265 printf("103ch:NHKハイビジョン(BShi)\n"); |
266 printf("CS2-CS24:CSチャンネル\n"); | |
199 return 1; | 267 return 1; |
200 } | 268 } |
201 ptr = searchrecoff(argv[1]); | 269 ptr = searchrecoff(argv[optind]); |
202 if(ptr == NULL) { | 270 if(ptr == NULL){ |
203 printf("Channel Select Error(%s)\n", argv[1]); | 271 printf("Channel Select Error(%s)\n", argv[optind]); |
204 return 1 ; | 272 return 1; |
205 } | 273 } |
206 | 274 |
207 freq.frequencyno = ptr->set_freq ; | 275 freq.frequencyno = ptr->set_freq; |
208 freq.slot = ptr->add_freq ; | 276 freq.slot = ptr->add_freq; |
209 | 277 |
210 if(ptr->type == CHTYPE_SATELLITE) { | 278 if(ptr->type == CHTYPE_SATELLITE) { |
211 for(lp = 0 ; lp < 2 ; lp++) { | 279 for(lp = 0; lp < 2; lp++) { |
212 fd = open(bsdev[lp], O_RDONLY); | 280 fd = open(bsdev[lp], O_RDONLY); |
213 if(fd >= 0) { | 281 if(fd >= 0) { |
214 break ; | 282 break; |
215 } | 283 } |
216 } | 284 } |
217 if(fd < 0) { | 285 if(fd < 0) { |
218 printf("Device Open Error\n"); | 286 fprintf(stderr, "Device Open Error\n"); |
219 return 1; | 287 return 1; |
220 } | 288 } |
221 } else { | 289 } else { |
222 for(lp = 0 ; lp < 2 ; lp++) { | 290 for(lp = 0; lp < 2; lp++) { |
223 fd = open(isdb_t_dev[lp], O_RDONLY); | 291 fd = open(isdb_t_dev[lp], O_RDONLY); |
224 if(fd >= 0) { | 292 if(fd >= 0) { |
225 break ; | 293 break; |
226 } | 294 } |
227 } | 295 } |
228 if(fd < 0) { | 296 if(fd < 0) { |
229 printf("Device Open Error\n"); | 297 fprintf(stderr, "Device Open Error\n"); |
230 return 1; | 298 return 1; |
231 } | 299 } |
232 } | 300 } |
233 recsec = atoi(argv[2]); | 301 recsec = atoi(argv[optind + 1]); |
234 | 302 |
235 /* initialize decoder */ | 303 /* initialize decoder */ |
236 dec = b25_startup(); | 304 if(use_b25) { |
305 dec = b25_startup(&dopt); | |
306 if(!dec) { | |
307 fprintf(stderr, "cannot start b25 decoder\n"); | |
308 return 1; | |
309 } | |
310 } | |
237 | 311 |
238 /* open output file */ | 312 /* open output file */ |
239 wfd = open(argv[3], (O_RDWR | O_CREAT | O_TRUNC), 0666); | 313 wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666); |
240 if(wfd < 0) { | 314 if(wfd < 0) { |
241 printf("Output File Open Error(%s)\n", argv[3]); | 315 fprintf(stderr, "Output File Open Error(%s)\n", argv[optind + 2]); |
242 return 0; | 316 return 1; |
243 } | 317 } |
244 | 318 |
245 if(ioctl(fd, SET_CHANNEL, &freq) < 0) { | 319 if(ioctl(fd, SET_CHANNEL, &freq) < 0) { |
246 printf("Tuner Select Error\n"); | 320 fprintf(stderr, "Tuner Select Error\n"); |
247 return 0 ; | 321 return 1; |
248 } | 322 } |
249 | 323 |
250 /* make reading thread */ | 324 /* make reader thread */ |
251 tdata.queue = p_queue; | 325 tdata.queue = p_queue; |
252 tdata.decoder = dec; | 326 tdata.decoder = dec; |
327 tdata.fd = wfd; | |
253 pthread_create(&dequeue_threads, NULL, write_func, &tdata); | 328 pthread_create(&dequeue_threads, NULL, write_func, &tdata); |
254 | 329 |
255 /* start recording*/ | 330 /* start recording */ |
256 if(ioctl(fd, START_REC, 0) < 0) { | 331 if(ioctl(fd, START_REC, 0) < 0) { |
257 printf("Tuner Start Error\n"); | 332 fprintf(stderr, "Tuner Start Error\n"); |
258 return 0 ; | 333 return 1; |
259 } | 334 } |
260 | 335 |
261 time(&start_time); | 336 time(&start_time); |
262 | 337 |
263 /* read from tuner */ | 338 /* read from tuner */ |
265 time(&cur_time); | 340 time(&cur_time); |
266 bufptr = malloc(sizeof(BUFSZ)); | 341 bufptr = malloc(sizeof(BUFSZ)); |
267 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE); | 342 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE); |
268 if(bufptr->size <= 0) { | 343 if(bufptr->size <= 0) { |
269 if((cur_time - start_time) >= recsec) { | 344 if((cur_time - start_time) >= recsec) { |
270 f_exit = TRUE ; | 345 f_exit = TRUE; |
271 enqueue(p_queue, NULL); | 346 enqueue(p_queue, NULL); |
272 break ; | 347 break; |
273 } else { | 348 } else { |
274 continue ; | 349 continue; |
275 } | 350 } |
276 } | 351 } |
277 enqueue(p_queue, bufptr); | 352 enqueue(p_queue, bufptr); |
278 | 353 |
279 /* stop recording */ | 354 /* stop recording */ |
282 /* read remaining data */ | 357 /* read remaining data */ |
283 while(1) { | 358 while(1) { |
284 bufptr = malloc(sizeof(BUFSZ)); | 359 bufptr = malloc(sizeof(BUFSZ)); |
285 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE); | 360 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE); |
286 if(bufptr->size <= 0) { | 361 if(bufptr->size <= 0) { |
287 f_exit = TRUE ; | 362 f_exit = TRUE; |
288 enqueue(p_queue, NULL); | 363 enqueue(p_queue, NULL); |
289 break ; | 364 break; |
290 } | 365 } |
291 enqueue(p_queue, bufptr); | 366 enqueue(p_queue, bufptr); |
292 } | 367 } |
293 break ; | 368 break; |
294 } | 369 } |
295 } | 370 } |
296 /* close tuner */ | 371 /* close tuner */ |
297 close(fd); | 372 close(fd); |
298 | 373 |
299 /* wait reading thread */ | 374 /* wait reading thread */ |
300 pthread_join(dequeue_threads, NULL); | 375 pthread_join(dequeue_threads, NULL); |
301 destroy_queue(p_queue); | 376 destroy_queue(p_queue); |
302 | 377 |
303 /* release decoder */ | 378 /* release decoder */ |
304 b25_shutdown(dec); | 379 if(use_b25) { |
305 | 380 b25_shutdown(dec); |
306 return 0 ; | 381 } |
307 } | 382 |
383 return 0; | |
384 } |