OSDN Git Service

add tunerec
authorgn64_jp <gn64_jp@4e526526-5e11-4fc0-8910-f8fd03428081>
Fri, 17 Feb 2012 12:58:52 +0000 (12:58 +0000)
committergn64_jp <gn64_jp@4e526526-5e11-4fc0-8910-f8fd03428081>
Fri, 17 Feb 2012 12:58:52 +0000 (12:58 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/rec10@921 4e526526-5e11-4fc0-8910-f8fd03428081

tunerec/Makefile [new file with mode: 0755]
tunerec/README.ja [new file with mode: 0755]
tunerec/tunerec.c [new file with mode: 0755]

diff --git a/tunerec/Makefile b/tunerec/Makefile
new file mode 100755 (executable)
index 0000000..4d5310d
--- /dev/null
@@ -0,0 +1,36 @@
+PREFIX          = /usr/local
+TARGETS = tunerec
+#OBJ_TARGETS     = 
+#HEDDERDEPEND    = eit.h sdt.h aribstr.h ts.h util.h
+
+LANG            = C
+CC              = gcc
+
+#CFLAGS         = -std=c99 -O2 -Wall -g
+CFLAGS          = -std=c99 -O2 -Wall -ggdb
+
+LIBS            =
+
+.c.o:                   ${CC} ${CFLAGS} -c $<
+
+all:                    ${TARGETS}
+
+
+tunerec:               tunerec.c
+                       ${CC} ${CFLAGS} -o ${TARGETS} tunerec.c
+
+clean:
+                       rm -f core ${TARGETS} *.o
+
+install:                ${TARGETS}
+                       install -m755 ${TARGETS} ${PREFIX}/bin
+
+uninstall:              ${TARGETS}
+                       rm ${PREFIX}/bin/${TARGETS}
+
+
+
+#tune: tune.c
+#      gcc -O2 -Wall -I../dvb-pt1/linux/include -o tunerec tune.c
+
+
diff --git a/tunerec/README.ja b/tunerec/README.ja
new file mode 100755 (executable)
index 0000000..01b2426
--- /dev/null
@@ -0,0 +1,169 @@
+DVB PT1 ドライバ用tuneプログラム(rec10用改変版)
+
+2012-01-08版
+
+このプログラムはDVB PT1付属のtuneプログラムを、
+rec10にて使いやすいように改変を行った物です。
+
+変更点
+チャンネルリストを無効化、周波数およびtsIDの指定で動作するようにしました。
+
+使い方
+$ ./tune <DVBアダプタ番号> <周波数> [tsid(省略可)]
+
+ライセンス
+>7. 使用上の注意
+>
+>このソフトウェアは、 sourceforge.jp で開発されている独自仕様のドライバ
+>を改竄し v4l-dvb の仕様に合わせようとしているものです。これは単に AS
+>IS で提供しているもので、開発途上であり、完全に無保証です。テストプログ
+>ラムは MIT ライセンスで提供します。
+
+gn64_jp(gn64@rec10.org)
+
+DVB PT1 ドライバ
+
+2009-03-07 版
+
+1. このドキュメントについて
+
+このドキュメントは DVB ベース の PT1 ドライバのチェックアウト、コンパイ
+ル、インストールおよびテスト方法を説明するものです。
+
+
+2. ドライバのチェックアウト
+
+DVB ベースの PT1 ドライバのソースコードは現在 mercurial で管理されてい
+ます。開発マシンに mercurial をインストールした上で、次のコマンドでチェッ
+クアウトしてください。
+
+       $ hg clone http://bitbucket.org/hiranotaka/dvb-pt1/
+
+一度チェックアウトを行うと二度めからは dvb-pt1 ディレクトリにて次のコマ
+ンドを実行することで更新することができます。ただし次の更新は 3 月下旬以
+降の予定です。
+
+              $ hg pull && hg update
+
+詳しくは mercurial のマニュアルや bitbucket.org のマニュアルを参照して
+ください。
+
+
+3. ドライバのコンパイル
+
+ターゲットとなるカーネルと同じバージョンのカーネルヘッダまたはソースが
+必要です。 linux-headers-$(uname -r) パッケージなどで入手してください。
+準備ができたら、v4l ディレクトリ下に .config という名前のファイルを作成
+し、
+
+       CONFIG_DVB_CORE=m
+       CONFIG_DVB_PT1=m
+
+のように記述します。後は、 /lib/modules/$(uname -r)/source または
+/lib/modules/$(uname -r)/build にカーネルヘッダまたはソースが展開されて
+いる場合、同じ v4l ディレクトリにて、
+
+$ make
+
+するだけで OK です。うまくいけば dvb-core.ko と pt1_drv.ko という二つの
+モジュールができるはずです。
+
+なお、カーネルヘッダやソースが違うディレクトリに展開されている場合は、
+SRCDIR オプションが必要です。
+
+
+4. ドライバのロード
+
+コンパイルでできた 2 つのモジュールを順にロードします。
+
+       $ sudo insmod dvb-core.ko
+       $ sudo insmod pt1_drv.ko
+
+無事ロードされると次のようになるはずです。
+
+       $ dmesg
+       ...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 0 frontend 0 (VA1J5JF8007 ISDB-S)...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 1 frontend 0 (VA1J5JF8007 ISDB-T)...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 2 frontend 0 (VA1J5JF8007 ISDB-S)...
+       DVB: registering new adapter (pt1-pci)
+       DVB: registering adapter 3 frontend 0 (VA1J5JF8007 ISDB-T)...
+       pt1_thread run
+
+現在、一部のマシンで DMA 領域の確保に失敗する事象が確認されています。こ
+の場合、デバッグ用のスタックトレースなどとともに、次のように表示されま
+す。
+
+       $ dmesg
+       ...
+       PT1:DMA ALLOC ERROR
+       pt1-pci: probe of 0000:01:0a.0 failed with error -5
+
+これは特に 32 ビットマシンにおいて貴重な LOWMEM 領域(DMA 可能な領域で、
+最大でも 756 MB)にその 1/6 にあたる 128 MB もの巨大な領域を確保している
+ためと考えられます。うまい対処方法があれば教えて下さい。
+
+
+5. テストプログラムのビルド
+
+簡単なテストプログラムを用意しました。先ほどチェックアウトした dvb-pt1
+と同じ階層にこの README.ja を含むディレクトリを移動します。別の言い方を
+すると、このディレクトリから見てドライバが ../dvb-pt1 の位置に来るよう
+にします。その状態で
+
+       $ make
+
+してください。
+
+
+6. テストプログラムの実行
+
+チャンネルを設定するには、
+
+       $ ./tune <DVBアダプタ番号> <リモコンキーID>
+
+とします。設定がうまくいけば
+
+       Successfully tuned to NHK東京 総合 .
+
+などと表示されます。
+
+       Failed to tune to NHK BS-1 (status 03).
+
+などと表示された場合は、ステータスによって次の原因が考えられます。
+
+       00: PLL に問題がある
+       01: 指定された周波数に信号がない
+       03: 他の TS-ID の信号はあるが、指定された TS-ID のものはない
+
+DVB アダプタ番号は、他にアダプタが無い場合、チューナ 0 の ISDB-S が 0
+、チューナ 0 の ISDB-T が 1 、チューナ 1 の ISDB-S が 2 、チューナ 1 の
+ISDB-T が 3 になります。 アダプタが ISDB-T か ISDB-S かは自動判定され、
+ISDB-T であればリモコンキー ID は地上波のものと、 ISDB-S であれば衛星の
+ものと解釈されます。
+
+リモコンキー ID と周波数の対応表は、東京都のものになっています。東京都
+以外では、 tune.c の上部にある対応表の書き換えが必要になります。
+
+テストプログラムを実行したままの状態で、
+
+       $ cat /dev/dvb/adapter1/dvr > dump.ts
+
+などとすれば録画できます(例はアダプタ番号 1 の場合)。また同様に
+
+       $ b25 -v 0 /dev/dvb/adapter1/dvr /dev/stdout | \
+               mplayer -cache 8192 -
+
+とすればリアルタイムで視聴できると思います。ただしリアルタイム視聴には
+それなりの CPU 性能が求められます。
+
+
+7. 使用上の注意
+
+このソフトウェアは、 sourceforge.jp で開発されている独自仕様のドライバ
+を改竄し v4l-dvb の仕様に合わせようとしているものです。これは単に AS
+IS で提供しているもので、開発途上であり、完全に無保証です。テストプログ
+ラムは MIT ライセンスで提供します。
diff --git a/tunerec/tunerec.c b/tunerec/tunerec.c
new file mode 100755 (executable)
index 0000000..c4a6688
--- /dev/null
@@ -0,0 +1,191 @@
+#include <linux/dvb/frontend.h>
+#include <linux/dvb/dmx.h>
+#include <linux/dvb/audio.h>
+#include <linux/dvb/version.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+
+#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
+
+struct channel {
+       int id;
+       const char *name;
+       unsigned int frequency;
+       unsigned int ts_id;
+};
+static int search(int adapter_nr,struct channel *ch)
+{
+       char file[256];
+       int fd;
+       struct dvb_frontend_info info;
+       struct channel *channel;
+       struct dtv_property prop[3];
+       struct dtv_properties props;
+       int i;
+       fe_status_t status;
+
+       sprintf(file, "/dev/dvb/adapter%d/frontend0", adapter_nr);
+       if ((fd = open(file, (O_RDWR | O_CREAT | O_TRUNC), 0666)) < 0) {
+               perror("open");
+               return -1;
+       }
+
+       if (ioctl(fd, FE_GET_INFO, &info) < 0) {
+               perror("ioctl FE_GET_INFO");
+               goto out;
+       }
+
+       if (info.type == FE_QPSK) {
+               channel = ch;
+               //channel = lookup_channel(channel_id, isdbs_channels,
+               //                       ARRAY_SIZE(isdbs_channels));
+       } else if (info.type == FE_OFDM) {
+               channel = ch;
+               //channel = lookup_channel(channel_id, isdbt_channels,
+               //                       ARRAY_SIZE(isdbt_channels));
+       } else {
+               fprintf(stderr, "Unknown type of adapter\n");
+               goto out;
+       }
+       if (channel == NULL) {
+               fprintf(stderr, "Unknown id of channel\n");
+               goto out;
+       }
+
+       prop[0].cmd = DTV_FREQUENCY;
+       prop[0].u.data = channel->frequency;
+       prop[1].cmd = DTV_ISDBS_TS_ID;
+       prop[1].u.data = channel->ts_id;
+       prop[2].cmd = DTV_TUNE;
+
+       props.props = prop;
+       props.num = 3;
+
+       if ((ioctl(fd, FE_SET_PROPERTY, &props)) < 0) {
+               perror("ioctl FE_SET_PROPERTY");
+               goto out;
+       }
+
+       for (i = 0; i < 4; i++) {
+               if (ioctl(fd, FE_READ_STATUS, &status) < 0) {
+                       perror("ioctl FE_READ_STATUS");
+                       goto out;
+               }
+               if (status & FE_HAS_LOCK) {
+                       fprintf(stderr, "Successfully tuned to %d(%d) .\n",
+                               channel->frequency,channel->ts_id);
+                       return 0;
+               }
+               usleep(250 * 1000);
+       }
+
+       fprintf(stderr, "Failed to tune to %s (status %02x).\n",
+               channel->name, status);
+
+out:
+       close(fd);
+       return -1;
+}
+
+static int track(int adapter_nr)
+{
+       char file[256];
+       int fd;
+       struct dmx_pes_filter_params filter;
+
+       filter.pid = 0x2000;
+       filter.input = DMX_IN_FRONTEND;
+       filter.output = DMX_OUT_TS_TAP;
+       filter.pes_type =  DMX_PES_VIDEO;
+       filter.flags = DMX_IMMEDIATE_START;
+
+       sprintf(file, "/dev/dvb/adapter%d/demux0", adapter_nr);
+       if ((fd = open(file, O_RDWR)) < 0) {
+               perror("open");
+               return -1;
+       }
+
+
+       if (ioctl(fd, DMX_SET_PES_FILTER, &filter) < 0) {
+               perror("ioctl DMX_SET_PES_FILTER");
+               close(fd);
+               return -1;
+       }
+}
+
+void record(int adapter_nr, char* output, int rectime) {
+       int fin, fout;
+       char input[256];
+       time_t start_time, current_time;
+       char buf[1316];
+       ssize_t rt, wt;
+       int size_remain;
+
+       fout = open(output, (O_WRONLY | O_CREAT | O_TRUNC));
+       if ( fout < 0 ) {
+               printf("output file open failed\n");
+               return;
+       }
+       sprintf(input, "/dev/dvb/adapter%d/dvr0", adapter_nr);
+       start_time = time(NULL);
+       fin = open(input, (O_RDONLY));
+       while ( rt = read(fin, buf, 1316) ) {
+               while ( wt = write(fout, buf, rt) ) {
+                       rt -= wt;
+                       if ( rt == 0 ) break;
+                       if ( wt == 0 ) {
+                               printf("output file write failed\n");
+                               goto error;
+                       }
+               }
+               current_time = time(NULL);
+               if ( current_time - start_time > rectime ) {
+                       break;
+               }
+       }
+
+       error:
+       close(fin);
+       close(fout);
+}
+
+int main(int argc, char *argv[]) {
+       int adapter_nr;
+       int channel_id;
+       int channel_freq;
+       int fd;
+       int ret;
+       int rectime;
+
+       if (argc <= 2) {
+               fprintf(stderr, "Usage: %s adapter_nr freq [tsid]\n", argv[0]);
+               return 1;
+       }
+       struct channel *ch;
+       adapter_nr = strtol(argv[1], NULL, 0);
+       channel_freq = strtol(argv[2], NULL, 10);
+       channel_id=0;
+       if (argc >= 4){
+               channel_id = strtol(argv[3], NULL, 10);
+       }
+       if ( argc == 5 ) {
+               rectime = atoi(argv[4]);
+       }
+       struct channel ch1 ={0,"",channel_freq,channel_id};
+       ch = &ch1;
+       //struct channel ch;//{   1, "NHK BS-1",          1318000, 0x40f1 }
+       //ch={0,"",argv}
+       fd = search(adapter_nr, ch);
+       if (fd < 0)
+               return 1;
+
+       ret = track(adapter_nr);
+       record(adapter_nr, argv[3], rectime);
+       close(fd);
+
+       return ret < 0;
+}