comparison recpt1/test.c @ 0:67e8eca28a80

initial import
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Mon, 16 Feb 2009 15:41:49 +0900
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:67e8eca28a80
1 #include <stdio.h>
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <fcntl.h>
5 #include <time.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <pthread.h>
9 #include <unistd.h>
10
11 #include <sys/ioctl.h>
12 #include "pt1_ioctl.h"
13
14 char *bsdev[2] = {
15 "/dev/pt1video1",
16 "/dev/pt1video0"
17 };
18 char *isdb_t_dev[2] = {
19 "/dev/pt1video2",
20 "/dev/pt1video3"
21 };
22
23 #define CHTYPE_SATELLITE 0 // 衛星デジタル放送
24 #define CHTYPE_GROUND 1 // 地上デジタル放送
25 #define MAX_QUEUE 8192
26
27 #define MAX_READ_SIZE (1024 * 16)
28 #define WRITE_SIZE (1024 * 1024 * 2)
29 #define TRUE 1
30 #define FALSE 0
31
32 typedef struct _BUFSZ{
33 int size ;
34 u_char buffer[MAX_READ_SIZE];
35 }BUFSZ;
36
37 typedef struct _QUEUE_T{
38 unsigned int in; // 次に入れるインデックス
39 unsigned int out; // 次に出すインデックス
40 unsigned int size; // キューのサイズ
41 unsigned int no_full; // 満タンになると 0 になる
42 unsigned int no_empty; // 空っぽになると 0 になる
43 pthread_mutex_t mutex;
44 pthread_cond_t cond_full; // データが満タンのときに待つための cond
45 pthread_cond_t cond_empty; // データが空のときに待つための cond
46 BUFSZ *buffer[1]; // バッファポインタ
47 }QUEUE_T;
48
49 int wfd; // ファイル書き込み用
50 int f_exit = FALSE ;
51
52 typedef struct _ISDB_T_FREQ_CONV_TABLE {
53 int set_freq ; // 実際にioctl()を行う値
54 int type ; // チャンネルタイプ
55 int add_freq ; // 追加する周波数(BS/CSの場合はスロット番号)
56 char *parm_freq ; // パラメータで受ける値
57 }ISDB_T_FREQ_CONV_TABLE;
58
59 // 変換テーブル(ISDB-T用)
60 #define MAX_CHANNEL_SELECT 123
61 // 実際にioctl()を行う値の部分はREADMEを参照の事。
62 // BS/CSの設定値およびスロット番号は
63 // http://www5e.biglobe.ne.jp/~kazu_f/digital-sat/index.htmlより取得。
64 //
65
66 ISDB_T_FREQ_CONV_TABLE isdb_t_conv_table[MAX_CHANNEL_SELECT] = {
67 { 0, CHTYPE_SATELLITE, 0, "151"}, // 151ch:BS朝日
68 { 0, CHTYPE_SATELLITE, 1, "161"}, // 161ch:BS-i
69 { 1, CHTYPE_SATELLITE, 1, "171"}, // 171ch:BSジャパン
70 { 4, CHTYPE_SATELLITE, 0, "211"}, // 211ch:BS11デジタル
71 { 4, CHTYPE_SATELLITE, 2, "222"}, // 222ch:TwellV
72 { 6, CHTYPE_SATELLITE, 0, "141"}, // 141ch:BS日テレ
73 { 6, CHTYPE_SATELLITE, 1, "181"}, // 181ch:BSフジ
74 { 7, CHTYPE_SATELLITE, 0, "101"}, // 101ch:NHK衛星第1放送(BS1)
75 { 7, CHTYPE_SATELLITE, 0, "102"}, // 102ch:NHK衛星第2放送(BS2)
76 { 7, CHTYPE_SATELLITE, 1, "103"}, // 103ch:NHKハイビジョン(BShi)
77 { 0, CHTYPE_GROUND, 0, "1"}, { 1, CHTYPE_GROUND, 0, "2"},
78 { 2, CHTYPE_GROUND, 0, "3"}, { 3, CHTYPE_GROUND, 0, "C13"},
79 { 4, CHTYPE_GROUND, 0, "C14"}, { 5, CHTYPE_GROUND, 0, "C15"},
80 { 6, CHTYPE_GROUND, 0, "C16"}, { 7, CHTYPE_GROUND, 0, "C17"},
81 { 8, CHTYPE_GROUND, 0, "C18"}, { 9, CHTYPE_GROUND, 0, "C19"},
82 { 10, CHTYPE_GROUND, 0, "C20"}, { 11, CHTYPE_GROUND, 0, "C21"},
83 { 12, CHTYPE_GROUND, 0, "C22"}, { 13, CHTYPE_GROUND, 0, "4"},
84 { 14, CHTYPE_GROUND, 0, "5"}, { 15, CHTYPE_GROUND, 0, "6"},
85 { 16, CHTYPE_GROUND, 0, "7"}, { 17, CHTYPE_GROUND, 0, "8"},
86 { 18, CHTYPE_GROUND, 0, "9"}, { 19, CHTYPE_GROUND, 0, "10"},
87 { 20, CHTYPE_GROUND, 0, "11"}, { 21, CHTYPE_GROUND, 0, "12"},
88 { 22, CHTYPE_GROUND, 0, "C23"}, { 23, CHTYPE_GROUND, 0, "C24"},
89 { 24, CHTYPE_GROUND, 0, "C25"}, { 25, CHTYPE_GROUND, 0, "C26"},
90 { 26, CHTYPE_GROUND, 0, "C27"}, { 27, CHTYPE_GROUND, 0, "C28"},
91 { 28, CHTYPE_GROUND, 0, "C29"}, { 29, CHTYPE_GROUND, 0, "C30"},
92 { 30, CHTYPE_GROUND, 0, "C31"}, { 31, CHTYPE_GROUND, 0, "C32"},
93 { 32, CHTYPE_GROUND, 0, "C33"}, { 33, CHTYPE_GROUND, 0, "C34"},
94 { 34, CHTYPE_GROUND, 0, "C35"}, { 35, CHTYPE_GROUND, 0, "C36"},
95 { 36, CHTYPE_GROUND, 0, "C37"}, { 37, CHTYPE_GROUND, 0, "C38"},
96 { 38, CHTYPE_GROUND, 0, "C39"}, { 39, CHTYPE_GROUND, 0, "C40"},
97 { 40, CHTYPE_GROUND, 0, "C41"}, { 41, CHTYPE_GROUND, 0, "C42"},
98 { 42, CHTYPE_GROUND, 0, "C43"}, { 43, CHTYPE_GROUND, 0, "C44"},
99 { 44, CHTYPE_GROUND, 0, "C45"}, { 45, CHTYPE_GROUND, 0, "C46"},
100 { 46, CHTYPE_GROUND, 0, "C47"}, { 47, CHTYPE_GROUND, 0, "C48"},
101 { 48, CHTYPE_GROUND, 0, "C49"}, { 49, CHTYPE_GROUND, 0, "C50"},
102 { 50, CHTYPE_GROUND, 0, "C51"}, { 51, CHTYPE_GROUND, 0, "C52"},
103 { 52, CHTYPE_GROUND, 0, "C53"}, { 53, CHTYPE_GROUND, 0, "C54"},
104 { 54, CHTYPE_GROUND, 0, "C55"}, { 55, CHTYPE_GROUND, 0, "C56"},
105 { 56, CHTYPE_GROUND, 0, "C57"}, { 57, CHTYPE_GROUND, 0, "C58"},
106 { 58, CHTYPE_GROUND, 0, "C59"}, { 59, CHTYPE_GROUND, 0, "C60"},
107 { 60, CHTYPE_GROUND, 0, "C61"}, { 61, CHTYPE_GROUND, 0, "C62"},
108 { 62, CHTYPE_GROUND, 0, "C63"}, { 63, CHTYPE_GROUND, 0, "13"},
109 { 64, CHTYPE_GROUND, 0, "14"}, { 65, CHTYPE_GROUND, 0, "15"},
110 { 66, CHTYPE_GROUND, 0, "16"}, { 67, CHTYPE_GROUND, 0, "17"},
111 { 68, CHTYPE_GROUND, 0, "18"}, { 69, CHTYPE_GROUND, 0, "19"},
112 { 70, CHTYPE_GROUND, 0, "20"}, { 71, CHTYPE_GROUND, 0, "21"},
113 { 72, CHTYPE_GROUND, 0, "22"}, { 73, CHTYPE_GROUND, 0, "23"},
114 { 74, CHTYPE_GROUND, 0, "24"}, { 75, CHTYPE_GROUND, 0, "25"},
115 { 76, CHTYPE_GROUND, 0, "26"}, { 77, CHTYPE_GROUND, 0, "27"},
116 { 78, CHTYPE_GROUND, 0, "28"}, { 79, CHTYPE_GROUND, 0, "29"},
117 { 80, CHTYPE_GROUND, 0, "30"}, { 81, CHTYPE_GROUND, 0, "31"},
118 { 82, CHTYPE_GROUND, 0, "32"}, { 83, CHTYPE_GROUND, 0, "33"},
119 { 84, CHTYPE_GROUND, 0, "34"}, { 85, CHTYPE_GROUND, 0, "35"},
120 { 86, CHTYPE_GROUND, 0, "36"}, { 87, CHTYPE_GROUND, 0, "37"},
121 { 88, CHTYPE_GROUND, 0, "38"}, { 89, CHTYPE_GROUND, 0, "39"},
122 { 90, CHTYPE_GROUND, 0, "40"}, { 91, CHTYPE_GROUND, 0, "41"},
123 { 92, CHTYPE_GROUND, 0, "42"}, { 93, CHTYPE_GROUND, 0, "43"},
124 { 94, CHTYPE_GROUND, 0, "44"}, { 95, CHTYPE_GROUND, 0, "45"},
125 { 96, CHTYPE_GROUND, 0, "46"}, { 97, CHTYPE_GROUND, 0, "47"},
126 { 98, CHTYPE_GROUND, 0, "48"}, { 99, CHTYPE_GROUND, 0, "49"},
127 { 100, CHTYPE_GROUND, 0, "50"}, { 101, CHTYPE_GROUND, 0, "51"},
128 { 102, CHTYPE_GROUND, 0, "52"}, { 103, CHTYPE_GROUND, 0, "53"},
129 { 104, CHTYPE_GROUND, 0, "54"}, { 105, CHTYPE_GROUND, 0, "55"},
130 { 106, CHTYPE_GROUND, 0, "56"}, { 107, CHTYPE_GROUND, 0, "57"},
131 { 108, CHTYPE_GROUND, 0, "58"}, { 109, CHTYPE_GROUND, 0, "59"},
132 { 110, CHTYPE_GROUND, 0, "60"}, { 111, CHTYPE_GROUND, 0, "61"},
133 { 112, CHTYPE_GROUND, 0, "62"}
134 };
135
136 // 周波数テーブル変換
137 ISDB_T_FREQ_CONV_TABLE *searchrecoff(char *channel)
138 {
139 int lp ;
140
141 for(lp = 0 ; lp < 113 ; lp++){
142 // 文字列&長さ一致したら周波数テーブル番号を返却する
143 if((memcmp(isdb_t_conv_table[lp].parm_freq, channel, strlen(channel)) == 0) &&
144 (strlen(channel) == strlen(isdb_t_conv_table[lp].parm_freq))){
145 return &isdb_t_conv_table[lp] ;
146 }
147 }
148 return NULL ;
149 }
150
151 QUEUE_T* create_queue(size_t size)
152 {
153 QUEUE_T* p_queue;
154 int memsize = sizeof(QUEUE_T) + (size * sizeof(BUFSZ));
155
156 p_queue = (QUEUE_T*)calloc(memsize, sizeof(char));
157
158 if(p_queue != NULL){
159 p_queue->size = size;
160 p_queue->no_full = size;
161 p_queue->no_empty = 0;
162 pthread_mutex_init(&p_queue->mutex, NULL);
163 pthread_cond_init(&p_queue->cond_full, NULL);
164 pthread_cond_init(&p_queue->cond_empty, NULL);
165 }
166
167 return p_queue;
168 }
169
170 void destroy_queue(QUEUE_T *p_queue)
171 {
172 if(p_queue != NULL){
173 pthread_mutex_destroy(&p_queue->mutex);
174 pthread_cond_destroy(&p_queue->cond_full);
175 pthread_cond_destroy(&p_queue->cond_empty);
176 free(p_queue);
177 }
178 }
179
180 // 関数名: enqueue
181 // キューにデータを入れる
182 // データが満タンな場合は、ブロックします
183 void enqueue(QUEUE_T *p_queue, BUFSZ *data)
184 {
185 pthread_mutex_lock(&p_queue->mutex);
186 // -- ここから、クリティカルセクション --
187
188 // 満タンじゃなくなるまで待つ
189 while(!p_queue->no_full) {
190 pthread_cond_wait(&p_queue->cond_full, &p_queue->mutex);
191 printf("Full\n");
192 }
193
194 p_queue->buffer[p_queue->in] = data;
195
196 p_queue->in++;
197 p_queue->in %= p_queue->size;
198
199 p_queue->no_full--;
200 p_queue->no_empty++;
201
202 pthread_mutex_unlock(&p_queue->mutex);
203 pthread_cond_signal(&p_queue->cond_empty);
204 }
205
206 // 関数名: dequeue
207 // キューにデータを入れる
208 // データが満タンな場合は、ブロックします
209 BUFSZ *dequeue(QUEUE_T *p_queue)
210 {
211 void *result;
212
213 pthread_mutex_lock(&p_queue->mutex);
214 // -- ここから、クリティカルセクション --
215
216 // 空っぽじゃなくなるまで待つ
217 while (!p_queue->no_empty) {
218 pthread_cond_wait(&p_queue->cond_empty, &p_queue->mutex);
219 }
220
221 // データを取り出す
222 result = p_queue->buffer[p_queue->out];
223
224 // 次にデータを取り出す場所をインクリメント
225 p_queue->out++;
226 p_queue->out %= p_queue->size;
227
228 // フラグの更新
229 p_queue->no_full++;
230 p_queue->no_empty--;
231
232 // -- ここまで、クリティカルセクション --
233 pthread_mutex_unlock(&p_queue->mutex);
234 pthread_cond_signal(&p_queue->cond_full);
235
236 return result;
237 }
238
239
240 void *write_func(void *p)
241 {
242 QUEUE_T *p_queue = (QUEUE_T*)p;
243 int size = 0 ;
244 BUFSZ *ptr ;
245 #if 0
246 u_char *buffer ;
247
248 buffer = calloc(WRITE_SIZE, sizeof(char));
249 if(buffer == NULL){
250 return NULL ;
251 }
252 #endif
253
254 while(1){
255 ptr = dequeue(p_queue);
256 if(ptr == NULL){
257 close(wfd);
258 break ;
259 }
260 #if 0
261 if((size + ptr->size) < WRITE_SIZE){
262 memcpy((buffer + size) , ptr->buffer, ptr->size);
263 size += ptr->size ;
264 }else{
265 write(wfd, buffer, size);
266 size = ptr->size ;
267 }
268 #endif
269 write(wfd, ptr->buffer, ptr->size);
270 free(ptr);
271 if((f_exit) && (!p_queue->no_empty)){
272 #if 0
273 if(size){
274 write(wfd, buffer, size);
275 }
276 #endif
277 close(wfd);
278 break ;
279 }
280 }
281 return NULL;
282 }
283
284 int main(int argc, char **argv)
285 {
286 int fd ;
287 int rc ;
288 int lp ;
289 int channel ;
290 int recsec ;
291 time_t start_time ;
292 time_t cur_time ;
293 FREQUENCY freq;
294 ISDB_T_FREQ_CONV_TABLE *ptr ;
295 pthread_t dequeue_threads;
296 QUEUE_T *p_queue = create_queue(MAX_QUEUE);
297 BUFSZ *bufptr ;
298
299 if(argc < 4){
300 printf("Usage %s: channel recsec destfile\n", argv[0]);
301 printf("channel =\n");
302 printf("151ch:BS朝日\n");
303 printf("161ch:BS-i\n");
304 printf("171ch:BSジャパン\n");
305 printf("211ch:BS11デジタル\n");
306 printf("222ch:TwellV\n");
307 printf("141ch:BS日テレ\n");
308 printf("181ch:BSフジ\n");
309 printf("101ch:NHK衛星第1放送(BS1)\n");
310 printf("102ch:NHK衛星第2放送(BS2)\n");
311 printf("103ch:NHKハイビジョン(BShi)\n");
312 return 1;
313 }
314 ptr = searchrecoff(argv[1]);
315 if(ptr == NULL){
316 printf("Channel Select Error(%s)\n", argv[1]);
317 return 1 ;
318 }
319
320 freq.frequencyno = ptr->set_freq ;
321 freq.slot = ptr->add_freq ;
322
323 if(ptr->type == CHTYPE_SATELLITE){
324 for(lp = 0 ; lp < 2 ; lp++){
325 fd = open(bsdev[lp], O_RDONLY);
326 if(fd >= 0){
327 break ;
328 }
329 }
330 if(fd < 0){
331 printf("Device Open Error\n");
332 return 1;
333 }
334 }else{
335 for(lp = 0 ; lp < 2 ; lp++){
336 fd = open(isdb_t_dev[lp], O_RDONLY);
337 if(fd >= 0){
338 break ;
339 }
340 }
341 if(fd < 0){
342 printf("Device Open Error\n");
343 return 1;
344 }
345 }
346 recsec = atoi(argv[2]);
347
348 wfd = open64(argv[3], (O_RDWR | O_CREAT | O_TRUNC), 0666);
349 if(wfd < 0){
350 printf("Output File Open Error(%s)\n", argv[3]);
351 return 0;
352 }
353
354 if(ioctl(fd, SET_CHANNEL, &freq) < 0){
355 printf("Tuner Select Error\n");
356 return 0 ;
357 }
358 pthread_create(&dequeue_threads, NULL, write_func, p_queue);
359 if(ioctl(fd, START_REC, 0) < 0){
360 printf("Tuner Start Error\n");
361 return 0 ;
362 }
363
364 time(&start_time);
365 while(1){
366 time(&cur_time);
367 bufptr = calloc(1, sizeof(BUFSZ));
368 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE);
369 if(bufptr->size <= 0){
370 if((cur_time - start_time) >= recsec){
371 f_exit = TRUE ;
372 enqueue(p_queue, NULL);
373 break ;
374 }else{
375 continue ;
376 }
377 }
378 enqueue(p_queue, bufptr);
379
380 if((cur_time - start_time) >= recsec){
381 ioctl(fd, STOP_REC, 0);
382 //なくなるまでデータを読み出す
383 while(1){
384 bufptr = calloc(1, sizeof(BUFSZ));
385 bufptr->size = read(fd, bufptr->buffer, MAX_READ_SIZE);
386 if(bufptr->size <= 0){
387 f_exit = TRUE ;
388 enqueue(p_queue, NULL);
389 break ;
390 }
391 enqueue(p_queue, bufptr);
392 }
393 break ;
394 }
395 }
396 close(fd);
397 pthread_join(dequeue_threads, NULL);
398 destroy_queue(p_queue);
399 return 0 ;
400 }