changeset 18:84ff6ef710ea

- support stdout for output - changed representation for indefinite recording to '-' - handles EPIPE error
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Wed, 25 Feb 2009 17:22:31 +0900
parents 52c7c7c64ba6
children 5cd8212bea78
files recpt1/recpt1.c recpt1/recpt1.h
diffstat 2 files changed, 314 insertions(+), 185 deletions(-) [+]
line wrap: on
line diff
--- a/recpt1/recpt1.c	Wed Feb 25 03:07:50 2009 +0900
+++ b/recpt1/recpt1.c	Wed Feb 25 17:22:31 2009 +0900
@@ -10,6 +10,8 @@
 #include <unistd.h>
 #include <getopt.h>
 #include <signal.h>
+#include <errno.h>
+#include <sys/time.h>
 
 #include <netdb.h>
 #include <arpa/inet.h>
@@ -29,12 +31,18 @@
     struct sockaddr_in addr;
 } sock_data;
 
-typedef struct thread_data {
+typedef struct reader_thread_data {
     QUEUE_T *queue;
     decoder *decoder;
     int wfd;    /* output file fd */
     sock_data *sock_data;
-} thread_data;
+    pthread_t signal_thread;
+} reader_thread_data;
+
+typedef struct signal_thread_data {
+    QUEUE_T *queue;
+    int tfd;    /* tuner fd */
+} signal_thread_data;
 
 /* lookup frequency conversion table*/
 ISDB_T_FREQ_CONV_TABLE *
@@ -64,11 +72,11 @@
 
     if(p_queue != NULL) {
         p_queue->size = size;
-        p_queue->no_full = size;
-        p_queue->no_empty = 0;
+        p_queue->num_avail = size;
+        p_queue->num_used = 0;
         pthread_mutex_init(&p_queue->mutex, NULL);
-        pthread_cond_init(&p_queue->cond_full, NULL);
-        pthread_cond_init(&p_queue->cond_empty, NULL);
+        pthread_cond_init(&p_queue->cond_avail, NULL);
+        pthread_cond_init(&p_queue->cond_used, NULL);
     }
 
     return p_queue;
@@ -81,8 +89,8 @@
         return;
 
     pthread_mutex_destroy(&p_queue->mutex);
-    pthread_cond_destroy(&p_queue->cond_full);
-    pthread_cond_destroy(&p_queue->cond_empty);
+    pthread_cond_destroy(&p_queue->cond_avail);
+    pthread_cond_destroy(&p_queue->cond_used);
     free(p_queue);
 }
 
@@ -90,65 +98,85 @@
 void
 enqueue(QUEUE_T *p_queue, BUFSZ *data)
 {
+    struct timeval now;
+    struct timespec spec;
+
+    gettimeofday(&now, NULL);
+    spec.tv_sec = now.tv_sec + 1;
+    spec.tv_nsec = now.tv_usec * 1000;
+
     pthread_mutex_lock(&p_queue->mutex);
     /* entered critical section */
 
-    /* wait until queue is not full */
-    while(!p_queue->no_full) {
-        pthread_cond_wait(&p_queue->cond_full, &p_queue->mutex);
-        fprintf(stderr, "Full\n");
+    /* wait while queue is full */
+    while(p_queue->num_avail == 0) {
+        pthread_cond_timedwait(&p_queue->cond_avail,
+                               &p_queue->mutex, &spec);
+        if(f_exit)
+            return;
     }
 
     p_queue->buffer[p_queue->in] = data;
 
+    /* move position marker for input to next position */
     p_queue->in++;
     p_queue->in %= p_queue->size;
 
-    p_queue->no_full--;
-    p_queue->no_empty++;
+    /* update counters */
+    p_queue->num_avail--;
+    p_queue->num_used++;
 
     /* leaving critical section */
     pthread_mutex_unlock(&p_queue->mutex);
-    pthread_cond_signal(&p_queue->cond_empty);
+    pthread_cond_signal(&p_queue->cond_used);
 }
 
 /* dequeue data. this function will block if queue is empty. */
 BUFSZ *
 dequeue(QUEUE_T *p_queue)
 {
+    struct timeval now;
+    struct timespec spec;
     BUFSZ *buffer;
 
+    gettimeofday(&now, NULL);
+    spec.tv_sec = now.tv_sec + 1;
+    spec.tv_nsec = now.tv_usec * 1000;
+
     pthread_mutex_lock(&p_queue->mutex);
     /* entered the critical section*/
 
-    /* wait until queue is filled */
-    while (!p_queue->no_empty) {
-        pthread_cond_wait(&p_queue->cond_empty, &p_queue->mutex);
+    /* wait while queue is empty */
+    while(p_queue->num_used == 0) {
+        pthread_cond_timedwait(&p_queue->cond_avail,
+                               &p_queue->mutex, &spec);
+        if(f_exit)
+            return NULL;
     }
 
     /* take buffer address */
     buffer = p_queue->buffer[p_queue->out];
 
-    /* move location marker to next position */
+    /* move position marker for output to next position */
     p_queue->out++;
     p_queue->out %= p_queue->size;
 
-    /* update flags */
-    p_queue->no_full++;
-    p_queue->no_empty--;
+    /* update counters */
+    p_queue->num_avail++;
+    p_queue->num_used--;
 
     /* leaving the critical section */
     pthread_mutex_unlock(&p_queue->mutex);
-    pthread_cond_signal(&p_queue->cond_full);
+    pthread_cond_signal(&p_queue->cond_avail);
 
     return buffer;
 }
 
 /* this function will be reader thread */
 void *
-write_func(void *p)
+reader_func(void *p)
 {
-    thread_data *data = (thread_data *)p;
+    reader_thread_data *data = (reader_thread_data *)p;
     QUEUE_T *p_queue = data->queue;
     decoder *dec = data->decoder;
     int wfd = data->wfd;
@@ -156,6 +184,7 @@
     int use_udp = data->sock_data ? TRUE : FALSE;
     int fileless = FALSE;
     int sfd = -1;
+    pthread_t signal_thread = data->signal_thread;
     struct sockaddr *addr = NULL;
     BUFSZ *buf;
     ARIB_STD_B25_BUFFER sbuf, dbuf;
@@ -205,12 +234,11 @@
             }
 
             /* normal exit */
-            if((f_exit) && (!p_queue->no_empty)) {
+            if((f_exit) && (!p_queue->num_used)) {
                 if(use_b25) {
                     code = b25_finish(dec, &sbuf, &dbuf);
                     if(code < 0) {
                         fprintf(stderr, "b25_finish failed\n");
-                        close(sfd);
                         break;
                     }
 
@@ -219,16 +247,15 @@
                                addr, sizeof(struct sockaddr_in));
                     }
                 }
-                close(sfd);
                 break;
             }
-        } /* fileless */
+        } /* end of fileless */
         else {
 
+            ssize_t wc;
             buf = dequeue(p_queue);
             /* no entry in the queue */
             if(buf == NULL) {
-                close(wfd);
                 break;
             }
 
@@ -240,10 +267,12 @@
                 code = b25_decode(dec, &sbuf, &dbuf);
                 if(code < 0) {
                     fprintf(stderr, "b25_decode failed\n");
-                    close(wfd);
                     break;
                 }
-                write(wfd, dbuf.data, dbuf.size);
+                wc = write(wfd, dbuf.data, dbuf.size);
+                if(wc <= 0 && errno == EPIPE) {
+                    pthread_kill(signal_thread, SIGPIPE);
+                }
 
                 if(use_udp && sfd != -1) {
                     sendto(sfd, dbuf.data, dbuf.size, 0,
@@ -252,7 +281,10 @@
                 free(buf);
             }
             else {
-                write(wfd, sbuf.data, sbuf.size);
+                wc = write(wfd, sbuf.data, sbuf.size);
+                if(wc <= 0 && errno == EPIPE) {
+                    pthread_kill(signal_thread, SIGPIPE);
+                }
 
                 if(use_udp && sfd != -1) {
                     sendto(sfd, sbuf.data, sbuf.size, 0,
@@ -262,24 +294,23 @@
             }
 
             /* normal exit */
-            if((f_exit) && (!p_queue->no_empty)) {
+            if((f_exit) && (!p_queue->num_used)) {
                 if(use_b25) {
                     code = b25_finish(dec, &sbuf, &dbuf);
                     if(code < 0) {
                         fprintf(stderr, "b25_finish failed\n");
-                        close(wfd);
-                        close(sfd);
                         break;
                     }
-                    write(wfd, dbuf.data, dbuf.size);
+                    wc = write(wfd, dbuf.data, dbuf.size);
+                    if(wc <= 0 && errno == EPIPE) {
+                        pthread_kill(signal_thread, SIGPIPE);
+                    }
 
                     if(use_udp && sfd != -1) {
                         sendto(sfd, dbuf.data, dbuf.size, 0,
                                addr, sizeof(struct sockaddr_in));
                     }
                 }
-                close(wfd);
-                close(sfd);
                 break;
             }
         }
@@ -294,6 +325,10 @@
     fprintf(stderr, "\n");
     fprintf(stderr, "Usage: \n%s [--b25 [--round N] [--strip] [--EMM]] [--udp [--addr hostname --port portnumber]] channel recsec destfile\n", cmd);
     fprintf(stderr, "\n");
+    fprintf(stderr, "Remarks:\n");
+    fprintf(stderr, "if recsec   is '-', records indefinitely.\n");
+    fprintf(stderr, "if destfile is '-', stdout is used for output.\n");
+    fprintf(stderr, "\n");
 }
 
 void
@@ -401,10 +436,10 @@
 }
 
 void
-cleanup(int tfd)
+cleanup(signal_thread_data *sdata)
 {
     /* stop recording */
-    ioctl(tfd, STOP_REC, 0);
+    ioctl(sdata->tfd, STOP_REC, 0);
 
     /* restore LNB state */
 #if 0
@@ -414,8 +449,11 @@
         }
     }
 #endif
-    /* xxx really need mutex? */
+    /* xxx need mutex? */
     f_exit = TRUE;
+
+    pthread_cond_signal(&sdata->queue->cond_avail);
+    pthread_cond_signal(&sdata->queue->cond_used);
 }
 
 /* will be signal handler thread */
@@ -424,22 +462,28 @@
 {
     sigset_t waitset;
     int sig;
-    int tfd = *(int *)data;
+    signal_thread_data *sdata;
+    sdata = (signal_thread_data *)data;
 
     sigemptyset(&waitset);
+    sigaddset(&waitset, SIGPIPE);
     sigaddset(&waitset, SIGINT);
     sigaddset(&waitset, SIGTERM);
 
     sigwait(&waitset, &sig);
 
     switch(sig) {
+    case SIGPIPE:
+        fprintf(stderr, "\nSIGPIPE received. cleaning up...\n");
+        cleanup(sdata);
+        break;
     case SIGINT:
         fprintf(stderr, "\nSIGINT received. cleaning up...\n");
-        cleanup(tfd);
+        cleanup(sdata);
         break;
     case SIGTERM:
         fprintf(stderr, "\nSIGTERM received. cleaning up...\n");
-        cleanup(tfd);
+        cleanup(sdata);
         break;
     }
 
@@ -447,21 +491,19 @@
 }
 
 void
-init_signal_handlers(pthread_t *signal_thread, int tfd)
+init_signal_handlers(pthread_t *signal_thread, signal_thread_data *sdata)
 {
     sigset_t blockset;
-    static int tunerfd;
-
-    tunerfd = tfd;
 
     sigemptyset(&blockset);
+    sigaddset(&blockset, SIGPIPE);
     sigaddset(&blockset, SIGINT);
     sigaddset(&blockset, SIGTERM);
 
     if(pthread_sigmask(SIG_BLOCK, &blockset, NULL))
         fprintf(stderr, "pthread_sigmask() failed.\n");
 
-    pthread_create(signal_thread, NULL, process_signals, &tunerfd);
+    pthread_create(signal_thread, NULL, process_signals, sdata);
 }
 
 int
@@ -479,7 +521,8 @@
     QUEUE_T *p_queue = create_queue(MAX_QUEUE);
     BUFSZ   *bufptr;
     decoder *dec = NULL;
-    thread_data tdata;
+    static reader_thread_data tdata;
+    static signal_thread_data sdata;
     decoder_options dopt = {
         4,  /* round */
         0,  /* strip */
@@ -499,15 +542,16 @@
         { "addr",      1, NULL, 'a'},
         { "port",      1, NULL, 'p'},
         { "help",      0, NULL, 'h'},
-        {0, 0, 0, 0} /* terminate */
+        {0, 0, NULL, 0} /* terminate */
     };
 
     int use_b25 = FALSE;
     int use_udp = FALSE;
     int fileless = FALSE;
+    int use_stdout = FALSE;
     char *host_to = NULL;
     int port_to = 1234;
-    sock_data *sdata = NULL;
+    sock_data *sockdata = NULL;
 
     while((result = getopt_long(argc, argv, "br:smua:p:h",
                                 long_options, &option_index)) != -1) {
@@ -601,9 +645,30 @@
     }
 
     /* get recsec */
-    recsec = atoi(argv[optind + 1]);
-    if(recsec <= 0)
+    char *recsecstr = argv[optind + 1];
+	if(!strcmp("-", recsecstr)) {
         indefinite = TRUE;
+        recsec = -1;
+	}
+    else {
+        recsec = atoi(recsecstr);
+    }
+
+    /* open output file */
+    char *destfile = argv[optind + 2];
+	if(!strcmp("-", destfile)) {
+        use_stdout = TRUE;
+        wfd = 1; /* stdout */
+	}
+    else {
+        if(!fileless) {
+            wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666);
+            if(wfd < 0) {
+                fprintf(stderr, "Could not open output file(%s)\n", argv[optind + 2]);
+                return 1;
+            }
+        }
+    }
 
     /* initialize decoder */
     if(use_b25) {
@@ -617,34 +682,27 @@
 
     /* initialize udp connection */
     if(use_udp) {
-      sdata = calloc(1, sizeof(sock_data));
+      sockdata = calloc(1, sizeof(sock_data));
       struct in_addr ia;
       ia.s_addr = inet_addr(host_to);
       if(ia.s_addr == INADDR_NONE) {
             struct hostent *hoste = gethostbyname(host_to);
             if(!hoste) {
-                perror("failed to get host by name");
+                perror("gethostbyname");
                 return 1;
             }
             ia.s_addr = *(in_addr_t*) (hoste->h_addr_list[0]);
         }
-        sdata->addr.sin_family = AF_INET;
-        sdata->addr.sin_port = htons (port_to);
-        sdata->addr.sin_addr.s_addr = ia.s_addr;
-        if((sdata->sfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
+        sockdata->addr.sin_family = AF_INET;
+        sockdata->addr.sin_port = htons (port_to);
+        sockdata->addr.sin_addr.s_addr = ia.s_addr;
+        if((sockdata->sfd = socket(PF_INET, SOCK_DGRAM, 0)) < 0) {
             perror("socket");
             return 1;
         }
     }
 
-    /* open output file */
-    if(!fileless) {
-        wfd = open(argv[optind + 2], (O_RDWR | O_CREAT | O_TRUNC), 0666);
-        if(wfd < 0) {
-            fprintf(stderr, "Could not open output file(%s)\n", argv[optind + 2]);
-            return 1;
-        }
-    }
+    /* setup tuner */
     if(ptr->type == CHTYPE_SATELLITE) {
         if(ioctl(tfd, LNB_ENABLE, 0) < 0) {
             return 0 ;
@@ -659,14 +717,17 @@
     calc_cn(tfd, ptr->type);
 
     /* init signal handler thread */
-    init_signal_handlers(&signal_thread, tfd);
+    sdata.queue = p_queue;
+    sdata.tfd = tfd;
+    init_signal_handlers(&signal_thread, &sdata);
 
     /* make reader thread */
     tdata.queue = p_queue;
     tdata.decoder = dec;
     tdata.wfd = wfd;
-    tdata.sock_data = sdata;
-    pthread_create(&dequeue_thread, NULL, write_func, &tdata);
+    tdata.sock_data = sockdata;
+    tdata.signal_thread = signal_thread;
+    pthread_create(&dequeue_thread, NULL, reader_func, &tdata);
 
     /* start recording */
     if(ioctl(tfd, START_REC, 0) < 0) {
@@ -723,25 +784,27 @@
     }
     close(tfd);
 
-    /* wait reader thread */
+    /* wait for threads */
     pthread_join(dequeue_thread, NULL);
-//    fprintf(stderr, "dequeue_thread joined\n");
+    pthread_join(signal_thread, NULL);
 
-    pthread_join(signal_thread, NULL);
-//    fprintf(stderr, "signal_thread joined\n");
-
-    /* relase queue */
+    /* release queue */
     destroy_queue(p_queue);
 
+    /* close output file */
+    if(!use_stdout)
+        close(wfd);
+
     /* free socket data */
-    free(sdata);
+    if(use_udp) {
+        close(sockdata->sfd);
+        free(sockdata);
+    }
 
     /* release decoder */
     if(use_b25) {
         b25_shutdown(dec);
     }
 
-//    fprintf(stderr, "leaving main\n");
-
     return 0;
 }
--- a/recpt1/recpt1.h	Wed Feb 25 03:07:50 2009 +0900
+++ b/recpt1/recpt1.h	Wed Feb 25 17:22:31 2009 +0900
@@ -1,17 +1,17 @@
 #ifndef _RECPT1_H_
 #define _RECPT1_H_
 
-char	*bsdev[2] = {
-	"/dev/pt1video1",
-	"/dev/pt1video0"
+char *bsdev[2] = {
+    "/dev/pt1video1",
+    "/dev/pt1video0"
 };
-char	*isdb_t_dev[2] = {
-	"/dev/pt1video2",
-	"/dev/pt1video3"
+char *isdb_t_dev[2] = {
+    "/dev/pt1video2",
+    "/dev/pt1video3"
 };
 
-#define CHTYPE_SATELLITE    0		// 衛星デジタル放送
-#define CHTYPE_GROUND       1		// 地上デジタル放送
+#define CHTYPE_SATELLITE    0        /* satellite digital */
+#define CHTYPE_GROUND       1        /* terrestrial digital */
 #define MAX_QUEUE           8192
 #define MAX_READ_SIZE       (1024 * 16)
 #define WRITE_SIZE          (1024 * 1024 * 2)
@@ -24,22 +24,22 @@
 } BUFSZ;
 
 typedef struct _QUEUE_T {
-    unsigned int		in;		// 次に入れるインデックス
-    unsigned int		out;		// 次に出すインデックス
-    unsigned int		size;		// キューのサイズ
-    unsigned int		no_full;	// 満タンになると 0 になる
-    unsigned int		no_empty;	// 空っぽになると 0 になる
-    pthread_mutex_t	mutex;
-    pthread_cond_t	cond_full;	// データが満タンのときに待つための cond
-    pthread_cond_t	cond_empty;	// データが空のときに待つための cond
-    BUFSZ			*buffer[1];	// バッファポインタ
+    unsigned int in;        // 次に入れるインデックス
+    unsigned int out;        // 次に出すインデックス
+    unsigned int size;        // キューのサイズ
+    unsigned int num_avail;    // 満タンになると 0 になる
+    unsigned int num_used;    // 空っぽになると 0 になる
+    pthread_mutex_t mutex;
+    pthread_cond_t cond_avail;    // データが満タンのときに待つための cond
+    pthread_cond_t cond_used;    // データが空のときに待つための cond
+    BUFSZ *buffer[1];    // バッファポインタ
 } QUEUE_T;
 
 typedef struct _ISDB_T_FREQ_CONV_TABLE {
-    int	set_freq;	// 実際にioctl()を行う値
-    int	type;		// チャンネルタイプ
-    int	add_freq;	// 追加する周波数(BS/CSの場合はスロット番号)
-    char	*parm_freq;	// パラメータで受ける値
+    int set_freq;    // 実際にioctl()を行う値
+    int type;        // チャンネルタイプ
+    int add_freq;    // 追加する周波数(BS/CSの場合はスロット番号)
+    char *parm_freq;    // パラメータで受ける値
 } ISDB_T_FREQ_CONV_TABLE;
 
 // 変換テーブル(ISDB-T用)
@@ -48,89 +48,155 @@
 // http://www5e.biglobe.ne.jp/~kazu_f/digital-sat/index.htmlより取得。
 //
 
-ISDB_T_FREQ_CONV_TABLE	isdb_t_conv_table[] = {
-	{   0, CHTYPE_SATELLITE, 0, "151"},	// 151ch:BS朝日
-	{   0, CHTYPE_SATELLITE, 1, "161"},	// 161ch:BS-i
-	{   1, CHTYPE_SATELLITE, 0, "191"},	// 191ch:WOWOW
-	{   1, CHTYPE_SATELLITE, 1, "171"},	// 171ch:BSジャパン
-	{   4, CHTYPE_SATELLITE, 0, "211"},	// 211ch:BS11デジタル
-	{   4, CHTYPE_SATELLITE, 1, "200"},	// 200ch:スターチャンネル
-	{   4, CHTYPE_SATELLITE, 2, "222"},	// 222ch:TwellV
-	{   6, CHTYPE_SATELLITE, 0, "141"},	// 141ch:BS日テレ
-	{   6, CHTYPE_SATELLITE, 1, "181"}, // 181ch:BSフジ
-	{   7, CHTYPE_SATELLITE, 0, "101"},	// 101ch:NHK衛星第1放送(BS1)
-	{   7, CHTYPE_SATELLITE, 0, "102"},	// 102ch:NHK衛星第2放送(BS2)
-	{   7, CHTYPE_SATELLITE, 1, "103"}, // 103ch:NHKハイビジョン(BShi)
-	{  12, CHTYPE_SATELLITE, 0, "CS2"},	// ND2:237ch:スター・チャンネル プラス 239ch:日本映画専門チャンネルHD 306ch:フジテレビCSHD
-	{  13, CHTYPE_SATELLITE, 0, "CS4"},	// ND4:100ch:e2プロモ 256ch:J sports ESPN 312ch:FOX 322ch:スペースシャワーTV 331ch:カートゥーン ネットワーク 194ch:インターローカルTV 334ch:トゥーン・ディズニー
-	{  14, CHTYPE_SATELLITE, 0, "CS6"},	// ND6:221ch:東映チャンネル 222ch:衛星劇場 223ch:チャンネルNECO 224ch:洋画★シネフィル・イマジカ 292ch:時代劇専門チャンネル 238ch:スター・チャンネル クラシック 310ch:スーパー!ドラマTV 311ch:AXN 343ch:ナショナル ジオグラフィック チャンネル
-	{  15, CHTYPE_SATELLITE, 0, "CS8"},	// ND8:055ch:ショップ チャンネル
-	{  16, CHTYPE_SATELLITE, 0, "CS10"},	// ND10:228ch:ザ・シネマ 800ch:スカチャンHD800 801ch:スカチャン801 802ch:スカチャン802
-	{  17, CHTYPE_SATELLITE, 0, "CS12"},	// ND12:260ch:ザ・ゴルフ・チャンネル 303ch:テレ朝チャンネル 323ch:MTV 324ch:大人の音楽専門TV◆ミュージック・エア 352ch:朝日ニュースター 353ch:BBCワールドニュース 354ch:CNNj 361ch:ジャスト・アイ インフォメーション
-	{  18, CHTYPE_SATELLITE, 0, "CS14"},	// ND14:251ch:J sports 1 252ch:J sports 2 253ch:J sports Plus 254ch:GAORA 255ch:スカイ・A sports+
-	{  19, CHTYPE_SATELLITE, 0, "CS16"},	// ND16:305ch:チャンネル銀河 333ch:アニメシアターX(AT-X) 342ch:ヒストリーチャンネル 290ch:TAKARAZUKA SKY STAGE 803ch:スカチャン803 804ch:スカチャン804
-	{  20, CHTYPE_SATELLITE, 0, "CS18"},	// ND18:240ch:ムービープラスHD 262ch:ゴルフネットワーク 314ch:LaLa HDHV
-	{  21, CHTYPE_SATELLITE, 0, "CS20"},	// ND20:258ch:フジテレビ739 302ch:フジテレビ721 332ch:アニマックス 340ch:ディスカバリーチャンネル 341ch:アニマルプラネット
-	{  22, CHTYPE_SATELLITE, 0, "CS22"},	// ND22:160ch:C-TBSウェルカムチャンネル 161ch:QVC 185ch:プライム365.TV 293ch:ファミリー劇場 301ch:TBSチャンネル 304ch:ディズニー・チャンネル 325ch:MUSIC ON! TV 330ch:キッズステーション 351ch:TBSニュースバード
-	{  23, CHTYPE_SATELLITE, 0, "CS24"},	// ND24:257ch:日テレG+ 291ch:fashiontv 300ch:日テレプラス 320ch:安らぎの音楽と風景/エコミュージックTV 321ch:Music Japan TV 350ch:日テレNEWS24
-	{   0, CHTYPE_GROUND, 0,   "1"}, {   1, CHTYPE_GROUND, 0,   "2"},
-	{   2, CHTYPE_GROUND, 0,   "3"}, {   3, CHTYPE_GROUND, 0, "C13"},
-	{   4, CHTYPE_GROUND, 0, "C14"}, {   5, CHTYPE_GROUND, 0, "C15"},
-	{   6, CHTYPE_GROUND, 0, "C16"}, {   7, CHTYPE_GROUND, 0, "C17"},
-	{   8, CHTYPE_GROUND, 0, "C18"}, {   9, CHTYPE_GROUND, 0, "C19"},
-	{  10, CHTYPE_GROUND, 0, "C20"}, {  11, CHTYPE_GROUND, 0, "C21"},
-	{  12, CHTYPE_GROUND, 0, "C22"}, {  13, CHTYPE_GROUND, 0,   "4"},
-	{  14, CHTYPE_GROUND, 0,   "5"}, {  15, CHTYPE_GROUND, 0,   "6"},
-	{  16, CHTYPE_GROUND, 0,   "7"}, {  17, CHTYPE_GROUND, 0,   "8"},
-	{  18, CHTYPE_GROUND, 0,   "9"}, {  19, CHTYPE_GROUND, 0,  "10"},
-	{  20, CHTYPE_GROUND, 0,  "11"}, {  21, CHTYPE_GROUND, 0,  "12"},
-	{  22, CHTYPE_GROUND, 0, "C23"}, {  23, CHTYPE_GROUND, 0, "C24"},
-	{  24, CHTYPE_GROUND, 0, "C25"}, {  25, CHTYPE_GROUND, 0, "C26"},
-	{  26, CHTYPE_GROUND, 0, "C27"}, {  27, CHTYPE_GROUND, 0, "C28"},
-	{  28, CHTYPE_GROUND, 0, "C29"}, {  29, CHTYPE_GROUND, 0, "C30"},
-	{  30, CHTYPE_GROUND, 0, "C31"}, {  31, CHTYPE_GROUND, 0, "C32"},
-	{  32, CHTYPE_GROUND, 0, "C33"}, {  33, CHTYPE_GROUND, 0, "C34"},
-	{  34, CHTYPE_GROUND, 0, "C35"}, {  35, CHTYPE_GROUND, 0, "C36"},
-	{  36, CHTYPE_GROUND, 0, "C37"}, {  37, CHTYPE_GROUND, 0, "C38"},
-	{  38, CHTYPE_GROUND, 0, "C39"}, {  39, CHTYPE_GROUND, 0, "C40"},
-	{  40, CHTYPE_GROUND, 0, "C41"}, {  41, CHTYPE_GROUND, 0, "C42"},
-	{  42, CHTYPE_GROUND, 0, "C43"}, {  43, CHTYPE_GROUND, 0, "C44"},
-	{  44, CHTYPE_GROUND, 0, "C45"}, {  45, CHTYPE_GROUND, 0, "C46"},
-	{  46, CHTYPE_GROUND, 0, "C47"}, {  47, CHTYPE_GROUND, 0, "C48"},
-	{  48, CHTYPE_GROUND, 0, "C49"}, {  49, CHTYPE_GROUND, 0, "C50"},
-	{  50, CHTYPE_GROUND, 0, "C51"}, {  51, CHTYPE_GROUND, 0, "C52"},
-	{  52, CHTYPE_GROUND, 0, "C53"}, {  53, CHTYPE_GROUND, 0, "C54"},
-	{  54, CHTYPE_GROUND, 0, "C55"}, {  55, CHTYPE_GROUND, 0, "C56"},
-	{  56, CHTYPE_GROUND, 0, "C57"}, {  57, CHTYPE_GROUND, 0, "C58"},
-	{  58, CHTYPE_GROUND, 0, "C59"}, {  59, CHTYPE_GROUND, 0, "C60"},
-	{  60, CHTYPE_GROUND, 0, "C61"}, {  61, CHTYPE_GROUND, 0, "C62"},
-	{  62, CHTYPE_GROUND, 0, "C63"}, {  63, CHTYPE_GROUND, 0,  "13"},
-	{  64, CHTYPE_GROUND, 0,  "14"}, {  65, CHTYPE_GROUND, 0,  "15"},
-	{  66, CHTYPE_GROUND, 0,  "16"}, {  67, CHTYPE_GROUND, 0,  "17"},
-	{  68, CHTYPE_GROUND, 0,  "18"}, {  69, CHTYPE_GROUND, 0,  "19"},
-	{  70, CHTYPE_GROUND, 0,  "20"}, {  71, CHTYPE_GROUND, 0,  "21"},
-	{  72, CHTYPE_GROUND, 0,  "22"}, {  73, CHTYPE_GROUND, 0,  "23"},
-	{  74, CHTYPE_GROUND, 0,  "24"}, {  75, CHTYPE_GROUND, 0,  "25"},
-	{  76, CHTYPE_GROUND, 0,  "26"}, {  77, CHTYPE_GROUND, 0,  "27"},
-	{  78, CHTYPE_GROUND, 0,  "28"}, {  79, CHTYPE_GROUND, 0,  "29"},
-	{  80, CHTYPE_GROUND, 0,  "30"}, {  81, CHTYPE_GROUND, 0,  "31"},
-	{  82, CHTYPE_GROUND, 0,  "32"}, {  83, CHTYPE_GROUND, 0,  "33"},
-	{  84, CHTYPE_GROUND, 0,  "34"}, {  85, CHTYPE_GROUND, 0,  "35"},
-	{  86, CHTYPE_GROUND, 0,  "36"}, {  87, CHTYPE_GROUND, 0,  "37"},
-	{  88, CHTYPE_GROUND, 0,  "38"}, {  89, CHTYPE_GROUND, 0,  "39"},
-	{  90, CHTYPE_GROUND, 0,  "40"}, {  91, CHTYPE_GROUND, 0,  "41"},
-	{  92, CHTYPE_GROUND, 0,  "42"}, {  93, CHTYPE_GROUND, 0,  "43"},
-	{  94, CHTYPE_GROUND, 0,  "44"}, {  95, CHTYPE_GROUND, 0,  "45"},
-	{  96, CHTYPE_GROUND, 0,  "46"}, {  97, CHTYPE_GROUND, 0,  "47"},
-	{  98, CHTYPE_GROUND, 0,  "48"}, {  99, CHTYPE_GROUND, 0,  "49"},
-	{ 100, CHTYPE_GROUND, 0,  "50"}, { 101, CHTYPE_GROUND, 0,  "51"},
-	{ 102, CHTYPE_GROUND, 0,  "52"}, { 103, CHTYPE_GROUND, 0,  "53"},
-	{ 104, CHTYPE_GROUND, 0,  "54"}, { 105, CHTYPE_GROUND, 0,  "55"},
-	{ 106, CHTYPE_GROUND, 0,  "56"}, { 107, CHTYPE_GROUND, 0,  "57"},
-	{ 108, CHTYPE_GROUND, 0,  "58"}, { 109, CHTYPE_GROUND, 0,  "59"},
-	{ 110, CHTYPE_GROUND, 0,  "60"}, { 111, CHTYPE_GROUND, 0,  "61"},
-	{ 112, CHTYPE_GROUND, 0,  "62"},
-	{ 0, 0, 0, NULL} /* terminator */
+ISDB_T_FREQ_CONV_TABLE    isdb_t_conv_table[] = {
+    {   0, CHTYPE_SATELLITE, 0, "151"},  /* 151ch:BS朝日 */
+    {   0, CHTYPE_SATELLITE, 1, "161"},  /* 161ch:BS-i */
+    {   1, CHTYPE_SATELLITE, 0, "191"},  /* 191ch:WOWOW */
+    {   1, CHTYPE_SATELLITE, 1, "171"},  /* 171ch:BSジャパン */
+    {   4, CHTYPE_SATELLITE, 0, "211"},  /* 211ch:BS11デジタル */
+    {   4, CHTYPE_SATELLITE, 1, "200"},  /* 200ch:スターチャンネル */
+    {   4, CHTYPE_SATELLITE, 2, "222"},  /* 222ch:TwellV */
+    {   6, CHTYPE_SATELLITE, 0, "141"},  /* 141ch:BS日テレ */
+    {   6, CHTYPE_SATELLITE, 1, "181"},  /* 181ch:BSフジ */
+    {   7, CHTYPE_SATELLITE, 0, "101"},  /* 101ch:NHK衛星第1放送(BS1) */
+    {   7, CHTYPE_SATELLITE, 0, "102"},  /* 102ch:NHK衛星第2放送(BS2) */
+    {   7, CHTYPE_SATELLITE, 1, "103"},  /* 103ch:NHKハイビジョン(BShi) */
+    {  12, CHTYPE_SATELLITE, 0, "CS2"},  /* ND2:
+                                          * 237ch:スター・チャンネル プラス
+                                          * 239ch:日本映画専門チャンネルHD
+                                          * 306ch:フジテレビCSHD */
+    {  13, CHTYPE_SATELLITE, 0, "CS4"},  /* ND4:
+                                          * 100ch:e2プロモ
+                                          * 256ch:J sports ESPN
+                                          * 312ch:FOX
+                                          * 322ch:スペースシャワーTV
+                                          * 331ch:カートゥーンネットワーク
+                                          * 194ch:インターローカルTV
+                                          * 334ch:トゥーン・ディズニー */
+    {  14, CHTYPE_SATELLITE, 0, "CS6"},  /* ND6:
+                                          * 221ch:東映チャンネル
+                                          * 222ch:衛星劇場
+                                          * 223ch:チャンネルNECO
+                                          * 224ch:洋画★シネフィル・イマジカ
+                                          * 292ch:時代劇専門チャンネル
+                                          * 238ch:スター・チャンネル クラシック
+                                          * 310ch:スーパー!ドラマTV
+                                          * 311ch:AXN
+                                          * 343ch:ナショナルジオグラフィックチャンネル */
+
+    {  15, CHTYPE_SATELLITE, 0, "CS8"},  /* ND8:
+                                          * 055ch:ショップ チャンネル */
+    {  16, CHTYPE_SATELLITE, 0, "CS10"}, /* ND10:
+                                          * 228ch:ザ・シネマ
+                                          * 800ch:スカチャンHD800
+                                          * 801ch:スカチャン801
+                                          * 802ch:スカチャン802 */
+    {  17, CHTYPE_SATELLITE, 0, "CS12"}, /* ND12:
+                                          * 260ch:ザ・ゴルフ・チャンネル
+                                          * 303ch:テレ朝チャンネル
+                                          * 323ch:MTV 324ch:大人の音楽専門TV◆ミュージック・エア
+                                          * 352ch:朝日ニュースター
+                                          * 353ch:BBCワールドニュース
+                                          * 354ch:CNNj
+                                          * 361ch:ジャスト・アイ インフォメーション */
+    {  18, CHTYPE_SATELLITE, 0, "CS14"}, /* ND14:
+                                          * 251ch:J sports 1
+                                          * 252ch:J sports 2
+                                          * 253ch:J sports Plus
+                                          * 254ch:GAORA
+                                          * 255ch:スカイ・Asports+ */
+    {  19, CHTYPE_SATELLITE, 0, "CS16"}, /* ND16:
+                                          * 305ch:チャンネル銀河
+                                          * 333ch:アニメシアターX(AT-X)
+                                          * 342ch:ヒストリーチャンネル
+                                          * 290ch:TAKARAZUKA SKYSTAGE
+                                          * 803ch:スカチャン803
+                                          * 804ch:スカチャン804 */
+    {  20, CHTYPE_SATELLITE, 0, "CS18"}, /* ND18:
+                                          * 240ch:ムービープラスHD
+                                          * 262ch:ゴルフネットワーク
+                                          * 314ch:LaLa HDHV */
+    {  21, CHTYPE_SATELLITE, 0, "CS20"}, /* ND20:
+                                          * 258ch:フジテレビ739
+                                          * 302ch:フジテレビ721
+                                          * 332ch:アニマックス
+                                          * 340ch:ディスカバリーチャンネル
+                                          * 341ch:アニマルプラネット */
+    {  22, CHTYPE_SATELLITE, 0, "CS22"}, /* ND22:
+                                          * 160ch:C-TBSウェルカムチャンネル
+                                          * 161ch:QVC
+                                          * 185ch:プライム365.TV
+                                          * 293ch:ファミリー劇場
+                                          * 301ch:TBSチャンネル
+                                          * 304ch:ディズニー・チャンネル
+                                          * 325ch:MUSIC ON! TV
+                                          * 330ch:キッズステーション
+                                          * 351ch:TBSニュースバード */
+    {  23, CHTYPE_SATELLITE, 0, "CS24"}, /* ND24:
+                                          * 257ch:日テレG+
+                                          * 291ch:fashiontv
+                                          * 300ch:日テレプラス
+                                          * 320ch:安らぎの音楽と風景/エコミュージックTV
+                                          * 321ch:MusicJapan TV
+                                          * 350ch:日テレNEWS24 */
+    {   0, CHTYPE_GROUND, 0,   "1"}, {   1, CHTYPE_GROUND, 0,   "2"},
+    {   2, CHTYPE_GROUND, 0,   "3"}, {   3, CHTYPE_GROUND, 0, "C13"},
+    {   4, CHTYPE_GROUND, 0, "C14"}, {   5, CHTYPE_GROUND, 0, "C15"},
+    {   6, CHTYPE_GROUND, 0, "C16"}, {   7, CHTYPE_GROUND, 0, "C17"},
+    {   8, CHTYPE_GROUND, 0, "C18"}, {   9, CHTYPE_GROUND, 0, "C19"},
+    {  10, CHTYPE_GROUND, 0, "C20"}, {  11, CHTYPE_GROUND, 0, "C21"},
+    {  12, CHTYPE_GROUND, 0, "C22"}, {  13, CHTYPE_GROUND, 0,   "4"},
+    {  14, CHTYPE_GROUND, 0,   "5"}, {  15, CHTYPE_GROUND, 0,   "6"},
+    {  16, CHTYPE_GROUND, 0,   "7"}, {  17, CHTYPE_GROUND, 0,   "8"},
+    {  18, CHTYPE_GROUND, 0,   "9"}, {  19, CHTYPE_GROUND, 0,  "10"},
+    {  20, CHTYPE_GROUND, 0,  "11"}, {  21, CHTYPE_GROUND, 0,  "12"},
+    {  22, CHTYPE_GROUND, 0, "C23"}, {  23, CHTYPE_GROUND, 0, "C24"},
+    {  24, CHTYPE_GROUND, 0, "C25"}, {  25, CHTYPE_GROUND, 0, "C26"},
+    {  26, CHTYPE_GROUND, 0, "C27"}, {  27, CHTYPE_GROUND, 0, "C28"},
+    {  28, CHTYPE_GROUND, 0, "C29"}, {  29, CHTYPE_GROUND, 0, "C30"},
+    {  30, CHTYPE_GROUND, 0, "C31"}, {  31, CHTYPE_GROUND, 0, "C32"},
+    {  32, CHTYPE_GROUND, 0, "C33"}, {  33, CHTYPE_GROUND, 0, "C34"},
+    {  34, CHTYPE_GROUND, 0, "C35"}, {  35, CHTYPE_GROUND, 0, "C36"},
+    {  36, CHTYPE_GROUND, 0, "C37"}, {  37, CHTYPE_GROUND, 0, "C38"},
+    {  38, CHTYPE_GROUND, 0, "C39"}, {  39, CHTYPE_GROUND, 0, "C40"},
+    {  40, CHTYPE_GROUND, 0, "C41"}, {  41, CHTYPE_GROUND, 0, "C42"},
+    {  42, CHTYPE_GROUND, 0, "C43"}, {  43, CHTYPE_GROUND, 0, "C44"},
+    {  44, CHTYPE_GROUND, 0, "C45"}, {  45, CHTYPE_GROUND, 0, "C46"},
+    {  46, CHTYPE_GROUND, 0, "C47"}, {  47, CHTYPE_GROUND, 0, "C48"},
+    {  48, CHTYPE_GROUND, 0, "C49"}, {  49, CHTYPE_GROUND, 0, "C50"},
+    {  50, CHTYPE_GROUND, 0, "C51"}, {  51, CHTYPE_GROUND, 0, "C52"},
+    {  52, CHTYPE_GROUND, 0, "C53"}, {  53, CHTYPE_GROUND, 0, "C54"},
+    {  54, CHTYPE_GROUND, 0, "C55"}, {  55, CHTYPE_GROUND, 0, "C56"},
+    {  56, CHTYPE_GROUND, 0, "C57"}, {  57, CHTYPE_GROUND, 0, "C58"},
+    {  58, CHTYPE_GROUND, 0, "C59"}, {  59, CHTYPE_GROUND, 0, "C60"},
+    {  60, CHTYPE_GROUND, 0, "C61"}, {  61, CHTYPE_GROUND, 0, "C62"},
+    {  62, CHTYPE_GROUND, 0, "C63"}, {  63, CHTYPE_GROUND, 0,  "13"},
+    {  64, CHTYPE_GROUND, 0,  "14"}, {  65, CHTYPE_GROUND, 0,  "15"},
+    {  66, CHTYPE_GROUND, 0,  "16"}, {  67, CHTYPE_GROUND, 0,  "17"},
+    {  68, CHTYPE_GROUND, 0,  "18"}, {  69, CHTYPE_GROUND, 0,  "19"},
+    {  70, CHTYPE_GROUND, 0,  "20"}, {  71, CHTYPE_GROUND, 0,  "21"},
+    {  72, CHTYPE_GROUND, 0,  "22"}, {  73, CHTYPE_GROUND, 0,  "23"},
+    {  74, CHTYPE_GROUND, 0,  "24"}, {  75, CHTYPE_GROUND, 0,  "25"},
+    {  76, CHTYPE_GROUND, 0,  "26"}, {  77, CHTYPE_GROUND, 0,  "27"},
+    {  78, CHTYPE_GROUND, 0,  "28"}, {  79, CHTYPE_GROUND, 0,  "29"},
+    {  80, CHTYPE_GROUND, 0,  "30"}, {  81, CHTYPE_GROUND, 0,  "31"},
+    {  82, CHTYPE_GROUND, 0,  "32"}, {  83, CHTYPE_GROUND, 0,  "33"},
+    {  84, CHTYPE_GROUND, 0,  "34"}, {  85, CHTYPE_GROUND, 0,  "35"},
+    {  86, CHTYPE_GROUND, 0,  "36"}, {  87, CHTYPE_GROUND, 0,  "37"},
+    {  88, CHTYPE_GROUND, 0,  "38"}, {  89, CHTYPE_GROUND, 0,  "39"},
+    {  90, CHTYPE_GROUND, 0,  "40"}, {  91, CHTYPE_GROUND, 0,  "41"},
+    {  92, CHTYPE_GROUND, 0,  "42"}, {  93, CHTYPE_GROUND, 0,  "43"},
+    {  94, CHTYPE_GROUND, 0,  "44"}, {  95, CHTYPE_GROUND, 0,  "45"},
+    {  96, CHTYPE_GROUND, 0,  "46"}, {  97, CHTYPE_GROUND, 0,  "47"},
+    {  98, CHTYPE_GROUND, 0,  "48"}, {  99, CHTYPE_GROUND, 0,  "49"},
+    { 100, CHTYPE_GROUND, 0,  "50"}, { 101, CHTYPE_GROUND, 0,  "51"},
+    { 102, CHTYPE_GROUND, 0,  "52"}, { 103, CHTYPE_GROUND, 0,  "53"},
+    { 104, CHTYPE_GROUND, 0,  "54"}, { 105, CHTYPE_GROUND, 0,  "55"},
+    { 106, CHTYPE_GROUND, 0,  "56"}, { 107, CHTYPE_GROUND, 0,  "57"},
+    { 108, CHTYPE_GROUND, 0,  "58"}, { 109, CHTYPE_GROUND, 0,  "59"},
+    { 110, CHTYPE_GROUND, 0,  "60"}, { 111, CHTYPE_GROUND, 0,  "61"},
+    { 112, CHTYPE_GROUND, 0,  "62"},
+    { 0, 0, 0, NULL} /* terminate */
 };
 
 #endif