0
|
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 }
|