From: gn64_jp Date: Fri, 17 Feb 2012 12:58:52 +0000 (+0000) Subject: add tunerec X-Git-Url: http://git.osdn.net/view?p=rec10%2Frec10-git.git;a=commitdiff_plain;h=a1d60fbe4caf0077d90c0ca109b6a1619eb54d85 add tunerec git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/rec10@921 4e526526-5e11-4fc0-8910-f8fd03428081 --- diff --git a/tunerec/Makefile b/tunerec/Makefile new file mode 100755 index 0000000..4d5310d --- /dev/null +++ b/tunerec/Makefile @@ -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 index 0000000..01b2426 --- /dev/null +++ b/tunerec/README.ja @@ -0,0 +1,169 @@ +DVB PT1 ドライバ用tuneプログラム(rec10用改変版) + +2012-01-08版 + +このプログラムはDVB PT1付属のtuneプログラムを、 +rec10にて使いやすいように改変を行った物です。 + +変更点 +チャンネルリストを無効化、周波数およびtsIDの指定で動作するようにしました。 + +使い方 +$ ./tune <周波数> [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 <リモコンキー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 index 0000000..c4a6688 --- /dev/null +++ b/tunerec/tunerec.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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; +}