GV-MVP/RX2(ハードウェアMPEG2エンコード+TVチューナ付 キャプチャボード) で動画を見る

GV-MVP/RX2 のインストール

GV-MVP/RX2 を入手したので Linuxでの導入の流れをレポートします
(2008年 Linux-2.6.24, 2011年 Linux-3.0, 2013年 Linux-3.7.8 で検証しました)

Linuxで ハードウェアエンコード可能な TVキャプチャボードは数が限られていて
この GV-MVP/RX2 もその数少ない1つ

GV-MVP/RX2
画像は 別のHPのを拾ってきた物なので注意 モノはもう中古ショップかオークションでしか手に入りません

GV-MVP/RX2 の構成
名称 GV-MVP/RX2 (生産終了)
MPEG2エンコーダ CONEXANT CX23416-12
デコーダ Philips SAA7173HL
Y/C分離 NEC uPD64084
ゴーストリデューサ NEC uPD64031
チューナ Panasonic VP27S/ENGE4324D
音声 XWM8739 (I2Sバス)
ADコンバータ KHTEK AD1180

GV-MVP/RX と同等の構成のようです また GV-MVP/RX2E は Y/C分離やゴーストリデューサの機能が外れた簡易版のようです
これらの構成チップが システム上で認識されるようにドライバモジュールを準備する必要があります

また 2011年以降の 64bit環境では
すでに アナログTV放送が終了してしまっているので チューナの正常動作を確認していません
S-VIDEO + 音声端子入力 の正常動作確認のみです

参考になる情報サイトとしては ぱ研ここFedora関係のページ

マシン構成
2008年 Linux-2.6.24
CPU Turion(tm)64-MT37 2.0GHz
マザーボード KV8 Pro 3rd Eye
グラフィック GeForce6600GT
OS Linux kernel-2.6.24 (32bit)
GCC 4.1.2
glibc 2.5
2011年 Linux-3.0
CPU PhenomII X4 905e 2.5GHz 4コア
マザーボード GA-880GM-USB3
グラフィック Radeon HD 4250 オンボード
OS Linux kernel-3.0 (64bit)
GCC 4.5.2
glibc 2.13
2013年 Linux-3.7.8
CPU PhenomII X4 905e 2.5GHz 4コア
マザーボード GA-880GM-USB3
グラフィック Radeon HD 4250 オンボード
OS Linux kernel-3.7.8 (64bit)
GCC 4.5.2
glibc 2.13

カーネルのコンパイル

先に Linuxカーネルとして必要なモジュールを掲載しておきます 下記の表を参照ください

カーネルコンフィグ (Linux-2.6.24)
i2c-core 「I2C support」カーネルに組込めばOK
i2c-dev 「I2C device interface」カーネルに組込めばOK
i2c-algo-bit 「I2C bit-banging interfaces」カーネルに組込めばOK
videodev 「Video For Linux」カーネルに組込む CONFIG_VIDEO_V4L2 も自動で設定される
v4l1-compat 「Enable Video For Linux API 1 (DEPRECATED)」 と 「Enable Video For Linux API 1 compatible Layer」 をカーネルに組込み
ivtv, cx2341x 「Video capture adapters」を組み込んだ上で 「Conexant cx23416/cx23415 MPEG encoder/decoder support」をモジュールとしてビルドする ivtv.koモジュールが作られる
ちなみに ivtvfb は不要 (GV-MVP/RX2以外のチューナ用?)
tuner_simple 「Customize analog tuner modules to build」した上で 「Simple tuner support」のみをカーネルに組込み (Customize〜 を選択しない方法もあり 全てチューナモジュールがモジュール生成されるがそれはそれで動作する)
upd64031a 「Autoselect pertinent encoders/decoders and other helper chips」を外した上で 「Encoders/decoders and other helper chips」の 「NEC Electronics uPD64031A Ghost Reduction」 をモジュール組込む
upd64083 「Autoselect pertinent encoders/decoders and other helper chips」を外した上で 「Encoders/decoders and other helper chips」の 「NEC Electronics uPD64083 3-Dimensional Y/C separation」 をモジュールとしてビルドする
カーネルコンフィグ (Linux-3.0 差分)
rc_core ivtvモジュールに必要 「Device Drivers」→「Multimedia support」→「Remote Controller adapters」をカーネルに組込めばOK
カーネルコンフィグ (Linux-3.7.8 差分)
MEDIA_ANALOG_TV_SUPPORT もしくは
MEDIA_DIGITAL_TV_SUPPORT
「Device Drivers」→「Multimedia support」を有効にした上で 「Analog TV support」もしくは「Digital TV support」を指定
VIDEO_IVTV 「Media PCI Adapters」→「Conexant cx23416/cx23415 MPEG encoder/decoder support」を選択する まったく別の「Conexant CX2341x MPEG encoders」という項目がありこちらは全く動かないので注意
VIDEO_UPD64031A 「Encoders, decoders, sensors and other helper chips」→「NEC Electronics uPD64031A Ghost Reduction」が選択されていることを確認 ゴースト低減モジュール
VIDEO_UPD64083 「Encoders, decoders, sensors and other helper chips」→「NEC Electronics uPD64083 3-Dimensional Y/C separation」が選択されていることを確認 3次元Y/C分離モジュール

具体的にカーネルコンフィグ(make menuconfig)を キャプチャイメージで紹介します
まず Linux-2.6.24 から
I2C support
「I2C support」に *チェックをいれた上で 「I2C device interface」にも *チェック入れます
I2C Algorithms
「I2C Algorithms」では 「I2C bit-banging interfaces」にチェックをいれます
M 指定して i2c_algo_bit モジュールとして作ってもかまいません
Multimedia devices
「Video For Linux」「Enable Video For Linux API 1」「同 compatible Layer」をチェックし
「customize analog tuner modules to build」のチェックを外しておけば
tuner モジュールをいれた場合に適切な チューナ用モジュールを選択してくれるようです
(customize analog tuner modules にチェックを入れて 不要なチューナを省略指定できるかも)
また 「Video capture adapters」を *選択したうえで次に
Video capture adapters
「Conexant cx23416/cx23415 MPEG encoder/decoder support」(ivtv)を M モジュール化します
カーネルで ivtv.ko モジュールを作らせてインストールしておいて
後で 外部の ivtv.ko で置き換えるという方針です

次に Linux-3.0 でのカーネルコンフィグです
I2C support
まず 「Device Drivers」→「I2C support」を組込みにします
I2C supportのサブメニューは 上記のようにしました
Multimedia support
「Device Drivers」→「Multimedia support」の中で必要なのは
「Video For Linux」「Remote Controller adapters」「Video capture adapters」です

Remote Controller adapters のサブメニューでは
各メーカーの赤外線プロトコルがデフォルトで組み込まれていますが 不要なので解除して構いません
Video capture adapters
Video capture adapters もサブメニューになっています
ここでは GV-MVP/RX2のモジュールとなる ivtv.ko を作るために
「Conexant cx23416/cx23415 MPEG encoder/decoder support」をモジュール選択します
Linux-2.6.24のときとは異なり カーネル付属のドライバで動作したため
後から ivtv.ko を差し替える必要はありません 従ってモジュールでなく組込みでも構いません

さらに 「Autoselect pertinent encoders/decoders and other helper chips」を
組込みにすることで チューナやデコーダなど幾つかサブモジュールを自動選択してくれるようです
(GV-MVP/RX2の場合 Conexant cx23416/cx23415 を選択した時点で
自動的に必要なサブモジュールを選択済にしてくれます)

最後に ファームウェアの対応として (ファームウェアについては後述します)
Generic Driver Options
「Device Drivers」→「Generic Driver Options」で
「path to uevent helper」を /sbin/hotplug に設定します

次に Linux-3.7.8 でのカーネルコンフィグです
I2C support
I2Cの基本機能は必須です
Analog TV support
キャプチャでは Analog TV support / Digital TV support 両方有効にしてますが
Analog TV supportのみでもいけるはずです
Conexant cx23416/cx23415 MPEG encoder/decoder support
Analog TV supportを選択していないと この選択肢が見えてこないので注意

上記のコンフィグでカーネルをビルド
モジュールもインストール(make modules_install)し再起動しましょう
ファームウェアをまだ入れてないので この時点では下記のようにエラーとなるはずです
(Linux-2.6.24の場合)

$ lsmod
Module                  Size  Used by
nvidia               4702512  22 
 

この時点でまだ ビデオキャプチャ系のモジュールは見えません

$ dmesg
〜
i2c /dev entries driver
〜
 

I2Cドライバは モジュール化せずに組み込んだので ブート時に認識されています

しかしここで ivtvモジュールをロード(insmod)すると しばらく固まったあと
dmesg出力に下記のエラーが表示され ファームウェアのロードに失敗したことが分かります

fw_setup_device() : name=v4l-cx2341x-enc.fw uevent=1 return=0<3>ivtv0: Unable to open firmware v4l-cx2341x-enc.fw (must be 376836 bytes)
ivtv0: Did you put the firmware in the hotplug firmware directory?
ivtv0: Retry loading firmware
fw_setup_device() : name=v4l-cx2341x-enc.fw uevent=1 return=0<3>ivtv0: Unable to open firmware v4l-cx2341x-enc.fw (must be 376836 bytes)
ivtv0: Did you put the firmware in the hotplug firmware directory?
ivtv0: Failed to initialize on minor 0
 

(Linux-3.0の場合)
同様に dmesgでエラーメッセージが確認できます

ivtv: Start initialization, version 1.4.2
ivtv0: Initializing card 0
ivtv0: Autodetected I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner) card (cx23416 based)
ivtv 0000:04:07.0: PCI INT A -> GSI 21 (level, low) -> IRQ 21
ivtv0: Unreasonably low latency timer, setting to 64 (was 32)
saa7115 1-0021: saa7115 found (1f7115d0e100000) @ 0x42 (ivtv i2c driver #0)
i2c-core: driver [tuner] using legacy suspend method
i2c-core: driver [tuner] using legacy resume method
tda9887 1-0043: creating new instance
tda9887 1-0043: tda988[5/6/7] found
tuner 1-0043: Tuner 74 found with type(s) Radio TV.
All bytes are equal. It is not a TEA5767
tuner 1-0060: Tuner -1 found with type(s) Radio TV.
upd64031a 1-0012: chip found @ 0x24 (ivtv i2c driver #0)
upd64083 1-005c: chip found @ 0xb8 (ivtv i2c driver #0)
wm8739 1-001a: chip found @ 0x34 (ivtv i2c driver #0)
vp27smpx 1-005b: chip found @ 0xb6 (ivtv i2c driver #0)
tuner-simple 1-0060: creating new instance
tuner-simple 1-0060: type set to 46 (Panasonic VP27s/ENGE4324D)
ivtv0: Registered device video0 for encoder MPG (4096 kB)
ivtv0: Registered device video32 for encoder YUV (2048 kB)
ivtv0: Registered device vbi0 for encoder VBI (1024 kB)
ivtv0: Registered device video24 for encoder PCM (320 kB)
ivtv0: Initialized card: I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)
ivtv: End initialization
ivtv0: Unable to open firmware v4l-cx2341x-enc.fw (must be 376836 bytes)
ivtv0: Did you put the firmware in the hotplug firmware directory?
ivtv0: Retry loading firmware
ivtv0: Unable to open firmware v4l-cx2341x-enc.fw (must be 376836 bytes)
ivtv0: Did you put the firmware in the hotplug firmware directory?
ivtv0: Failed to initialize on device video32
ivtv0: Failed to initialize on device vbi0
ivtv0: Failed to initialize on device video24
ivtv0: Failed to initialize on device video0
 

Linux-3.0では GV-MVP/RX2のカードが認識され 各種サブモジュールも初期化されています
ただし最後の方で v4l-cx2341x-enc.fw が見付からずカード初期化に失敗しています
これは カーネルコンフィグで設定した ueventヘルパがファームウェアロードに失敗しているためです

ファームウェアは見付からないものの ここまででカーネルのコンフィグは完了です

ファームウェアのインストール

実際のところ カーネルコンフィグよりもこちらの方が苦労しました
ファームウェアのインストール方法です

まずファームウェアのイメージを用意します
IVTVプロジェクトの firmware.tar.gz を使いました(ドライバCDから抽出する方法もあるらしい)

$ su
# mkdir /lib/firmware
# cd /lib/firmware
# tar -xzf ~admin/firmware.tar.gz
# ls -l
合計 824
-rw-r--r--  1 505 502 262144  5月 26  2006 v4l-cx2341x-dec.fw
-rw-r--r--  1 505 502 376836  2月 17  2007 v4l-cx2341x-enc.fw
-rw-r--r--  1 505 502 155648  5月 26  2006 v4l-cx2341x-init.mpg
-rw-r--r--  1 505 502  16382  5月 26  2006 v4l-cx25840.fw
-rw-r--r--  1 505 502   8192 10月  6  2006 v4l-pvrusb2-24xxx-01.fw
-rw-r--r--  1 505 502   8192  7月  1  2006 v4l-pvrusb2-29xxx-01.fw
#
 

実際に使われるのは v4l-cx2341x-dec.fw v4l-cx2341x-enc.fw くらいだと思います
検証の環境では /lib/firmware/ に配置しましたが
ディストリビューションによっては /usr/lib/hotplug/firmware/ などに配置する例もあります

以上でイメージは準備できました

では ファームウェアをロードする仕組みと環境構築方法について説明します
ivtvドライバ動作としてはファームウェアを要求するのに request_firmware() が使われます

(Linux-2.6.24の場合)
2007年くらいの Linuxでは
HOTPLUG と sysfs の機能により request_firmware() が処理されます
まず hotplug の確認から

$ cat /proc/sys/kernel/hotplug
/sbin/hotplug
 

カーネルの機能により /sbin/hotplug スクリプトが読み込まれる設定となっています
実際の hotplugスクリプトの内容は以下のとおりです

$ cat /sbin/hotplug
〜
DIR="/etc/hotplug.d"

# echo '/sbin/hotplug debug: ' $1 >> /ram/hotpluglog

for I in "${DIR}/$1/"*.hotplug "${DIR}/"default/*.hotplug ; do
        if [ -f $I ]; then
                test -x $I && $I $1 ;
        fi
done

exit 1
 

数行のシェルスクリプトで /etc/hotplug.d/引数/*.hotplug のスクリプトを呼び出す仕様
であることがわかります ちなみに 引数は 「firmware」 が指定されるようです

対応して /etc/hotplug.d/firmware/firmware.hotplug (755) を以下の内容で記述します

#!/bin/sh
#
# Firmware-specific hotplug policy agent.
#
# Kernel firmware hotplug params include:
#
#       ACTION=%s [add or remove]
#       DEVPATH=%s [in 2.5 kernels, /sys/$DEVPATH]
#       FIRMWARE=%s
#
# HISTORY:
#
# 24-Jul-2003   Initial version of "new" hotplug agent.
#
# $Id: firmware.agent,v 1.1 2003/10/07 19:34:19 kroah Exp $
#

cd /etc/hotplug
. hotplug.functions
# DEBUG=yes export DEBUG

# directory of the firmware files
FIRMWARE_DIR=/lib/firmware

# mountpoint of sysfs
SYSFS=$(sed -n 's/^.* \([^ ]*\) sysfs .*$/\1/p' /proc/mounts)

# use /proc for 2.4 kernels
if [ "$SYSFS" = "" ]; then
    SYSFS=/proc
fi

#
# What to do with this firmware hotplug event?
#
# new code
echo "ECHOING DEVICE PATH";
echo $DEVPATH;
echo $ACTION;
echo $SYSFS;
echo $FIRMWARE;

case "$ACTION" in

add)
    if [ ! -e $SYSFS/$DEVPATH/loading ]; then
        sleep 1
    fi

    if [ -f $FIRMWARE_DIR/$FIRMWARE ]; then
        echo 1 > $SYSFS/$DEVPATH/loading
        cp $FIRMWARE_DIR/$FIRMWARE $SYSFS/$DEVPATH/data
        echo 0 > $SYSFS/$DEVPATH/loading
    else
        echo -1 > $SYSFS/$DEVPATH/loading
    fi

    ;;

remove)
    ;;

*)
    mesg "Firmware '$ACTION' event not supported"
    exit 1
    ;;

esac
 

ちなみに このスクリプトは どっかのホームページからのパクリです
hotplugが呼び出されるときに $DEVPATH $ACTION $SYSFS $FIRMWARE の環境変数がセットされるようでそれを組み合わせて適切なファームウェアを /sys/〜/data にアップロードする仕組みです

では ここまでで作成したカーネルモジュールを実際にロードしてみます
関連するチップのモジュールをロードしてから ivtvモジュールをロードします
tuner=46 と ntsc=j のオプション指定は必須です

$ su
# modprobe saa7115
# modprobe upd64031a
# modprobe upd64083
# modprobe wm8739
# modprobe cx2341x
# modprobe tuner
# modprobe ivtv tuner=46 ntsc=j
# chmod 666 /dev/video0
# exit
 

一般ユーザでも video0 にアクセスできるように アクセス権限を設定しています
モジュールとしては以下のように見えます

$ lsmod
Module                  Size  Used by
ivtv                  114752  0 
tveeprom               13328  1 ivtv
tuner                  36768  0 
tea5767                 4804  1 tuner
tda8290                10116  1 tuner
tuner_simple            7048  1 tuner
mt20xx                 10760  1 tuner
tea5761                 4036  1 tuner
cx2341x                10052  1 ivtv
wm8739                  5520  0 
upd64083                4688  0 
upd64031a               4944  0 
saa7115                13392  0 
nvidia               4702512  22 
 

tunerのサブモジュールが複数読み込まれているのが見えます(使われているかどうかわかりませんが)
tveepromは tuner用の EEPROM処理モジュールです

$ dmesg
ivtv:  Start initialization, version 1.1.0
ivtv0: Initializing card #0
ivtv0: Autodetected I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner) card (cx23416 based)
ACPI: PCI Interrupt 0000:00:0b.0[A] -> GSI 19 (level, low) -> IRQ 21
ivtv0: Unreasonably low latency timer, setting to 64 (was 32)
saa7115 3-0021: saa7115 found (1f7115d0e100000) @ 0x42 (ivtv i2c driver #0)
upd64031a 3-0012: chip found @ 0x24 (ivtv i2c driver #0)
upd64083 3-005c: chip found @ 0xb8 (ivtv i2c driver #0)
wm8739 3-001a: chip found @ 0x34 (ivtv i2c driver #0)
tuner 3-0043: chip found @ 0x86 (ivtv i2c driver #0)
tda9887 3-0043: tda988[5/6/7] found @ 0x43 (tuner)
tuner 3-0043: type set to tda9887
All bytes are equal. It is not a TEA5767
tuner 3-0060: chip found @ 0xc0 (ivtv i2c driver #0)
ivtv0: Failed to load module tuner
ivtv0: Failed to load module saa7115
ivtv0: Failed to load module upd64031a
ivtv0: Failed to load module upd64083
ivtv0: Failed to load module vp27smpx
ivtv0: Failed to load module wm8739
tuner-simple 3-0060: type set to 46 (Panasonic VP27s/ENGE4324D)
tuner 3-0060: type set to Panasonic VP27s/ENG
ivtv0: Registered device video0 for encoder MPG (4096 kB)
ivtv0: Registered device video32 for encoder YUV (2048 kB)
ivtv0: Registered device vbi0 for encoder VBI (1024 kB)
ivtv0: Registered device video24 for encoder PCM (320 kB)
ivtv0: Initialized card #0: I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)
ivtv:  End initialization
 

ivtvモジュールをロードした瞬間に dmesg的に 各種チップが認識されます
デバイスの初期化まで完了し /dev/ 以下に次のファイルが作られます

$ ls -l /dev/
〜
crw-rw----  1 root root 89,   0  3月 25 22:36 i2c-0
crw-rw----  1 root root 89,   1  3月 25 22:36 i2c-1
crw-rw----  1 root root 89,   2  3月 25 22:36 i2c-2
crw-rw----  1 root root 89,   3  3月 25 23:06 i2c-3
〜
crw-rw----  1 root root 81, 224  3月 25 23:06 vbi0
crw-rw-rw-  1 root root 81,   0  3月 25 23:06 video0
crw-rw-rw-  1 root root 81,  24  3月 25 23:06 video24
crw-rw-rw-  1 root root 81,  32  3月 25 23:06 video32
〜
 

udevの設定で アクセス権の許可を与える設定にしているので
パーミッションの見えかたが多少異なるかもしれません
i2c-0 〜 i2c-3 は I2Cアダプタを表します
vbi0 は VBI(アナログ放送の垂直帰線期間中に埋め込まれるデータで テレテキストとか言われる)
video0 は エンコード済のデータ(この場合 MPEG2)
video24 は PCMサウンドのようです(未確認)
video32 は 非圧縮YUVデータのようです(未確認)

(Linux-3.0以降の場合)
2011年頃のLinuxでは

$ cat /proc/sys/kernel/hotplug

$
 

既に hotplugが無効化されています
カーネルコンフィグのところで設定したように ueventヘルパ という形で
/sbin/hotplug を呼び出す仕組みとなっています

2011年時点では netlinkというデバイス能動監視の仕組みが使われていて
ueventヘルパ を使うケースは推奨されていません
さらに (2010年提供の Gentooイメージでは) /sbin/hotplug /etc/hotplug.d/ もありません

ivtvドライバが request_firmware() を使っている以上
/sbin/hotplug スクリプトを用意する必要があります
この辺りの動作や 下記の対処方法は カーネル付属のドキュメント
Documentation/firmware_class/README に記載されています

下記のように /sbin/hotplug (root) 0755 を作成しましょう

# Both $DEVPATH and $FIRMWARE are already provided in the environment.

HOTPLUG_FW_DIR=/lib/firmware/

echo 1 > /sys/$DEVPATH/loading
cat $HOTPLUG_FW_DIR/$FIRMWARE > /sys/$DEVPATH/data
echo 0 > /sys/$DEVPATH/loading
 

このスクリプトはファームウェアロード専用スクリプトになります
2.6.24版に比べて かなり簡易な内容です /etc/hotplug.d/ 配下を呼び出すこともしません
動作としては /sys/該当ディレクトリ/data にファームイメージをコピーする機能だけです

これでリブート後の dmesgは下記のように

ivtv: Start initialization, version 1.4.2
ivtv0: Initializing card 0
ivtv0: Autodetected I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner) card (cx23416 based)
ivtv 0000:04:07.0: PCI INT A -> GSI 21 (level, low) -> IRQ 21
ivtv0: Unreasonably low latency timer, setting to 64 (was 32)
saa7115 1-0021: saa7115 found (1f7115d0e100000) @ 0x42 (ivtv i2c driver #0)
i2c-core: driver [tuner] using legacy suspend method
i2c-core: driver [tuner] using legacy resume method
tda9887 1-0043: creating new instance
tda9887 1-0043: tda988[5/6/7] found
tuner 1-0043: Tuner 74 found with type(s) Radio TV.
All bytes are equal. It is not a TEA5767
tuner 1-0060: Tuner -1 found with type(s) Radio TV.
upd64031a 1-0012: chip found @ 0x24 (ivtv i2c driver #0)
upd64083 1-005c: chip found @ 0xb8 (ivtv i2c driver #0)
wm8739 1-001a: chip found @ 0x34 (ivtv i2c driver #0)
vp27smpx 1-005b: chip found @ 0xb6 (ivtv i2c driver #0)
tuner-simple 1-0060: creating new instance
tuner-simple 1-0060: type set to 46 (Panasonic VP27s/ENGE4324D)
ivtv0: Registered device video0 for encoder MPG (4096 kB)
ivtv0: Registered device video32 for encoder YUV (2048 kB)
ivtv0: Registered device vbi0 for encoder VBI (1024 kB)
ivtv0: Registered device video24 for encoder PCM (320 kB)
ivtv0: Initialized card: I/O Data GV-MVP/RX, GV-MVP/RX2W (dual tuner)
ivtv: End initialization
ivtv0: Loaded v4l-cx2341x-enc.fw firmware (376836 bytes)
ivtv0: Encoder revision: 0x02060039
 

ファームウェアが正常にロードされたメッセージに変わりました

$ lsmod
Module                  Size  Used by
vp27smpx                2278  1 
wm8739                  2892  1 
upd64083                2577  1 
upd64031a               2838  1 
tuner                  13377  2 
saa7115                11966  1 
ivtv                  122790  0 
cx2341x                13774  1 ivtv
tveeprom               12705  1 ivtv
$ ls /dev/v4l/
by-path  vbi0  video0  video24  video32
$
 

ivtvのモジュールと 関連するサブモジュールも自動的に読み込まれています

次に 2013年時点 Linux-3.7.8では
カーネルドキュメントでも「UDEVの仕組みを見直します」な状況で
まだまだ ホットプラグ関連の仕様は流動的なようですが

ivtv0: Loaded v4l-cx2341x-enc.fw firmware (376836 bytes)
pt1_thread run
ivtv0: Encoder revision: 0x02060039
tuner 0-0043: Tuner has no way to set tv freq
tuner 0-0043: Tuner has no way to set tv freq
v4l_id (2742) used greatest stack depth: 3624 bytes left
 

Linux-3.0 と同じ仕組みで ファームウェアは正常にロードされています
TVチューナが正常に動作していませんが
これは カーネルのコンフィグの段階で不要な選択肢として除外しているためです

ivtvパッケージの導入

カーネルとファームウェアの設定後は IVTVプロジェクト より録画関連ツールを取得します

(Linux-2.6.24の場合)
ivtv-1.0.3.tar.gz を使います
Linux-2.6.24の場合 録画ツールを作成する以外にも
ivtv.ko を Linuxカーネルのものから置き換える重要な目的があります
またこのパッケージでは saa717x.ko モジュールも提供されますがこれは必要ないかもしれません
カーネルに付属の saa7115.ko モジュールで動作しました

ivtv-1.0.3のインストールはおよそ下記の通りです

$ tar -xzf ivtv-1.0.3.tar.gz
$ cd ivtv-1.0.3/
$ tar -xzf f9ivtv33.tar.gz
$ CC=gcc make
make -C driver all
make[1]: Entering directory `/home/admin/ivtv-1.0.3/driver'
created ivtv-svnversion.h
make -C /lib/modules/2.6.24/build M=/home/admin/ivtv-1.0.3/driver modules
make[2]: Entering directory `/usr/src/linux-2.6.24'
  CC [M]  /home/admin/ivtv-1.0.3/driver/ivtv-routing.o
  CC [M]  /home/admin/ivtv-1.0.3/driver/ivtv-cards.o
  CC [M]  /home/admin/ivtv-1.0.3/driver/ivtv-controls.o
  CC [M]  /home/admin/ivtv-1.0.3/driver/ivtv-driver.o
〜
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  vbi.c   -o vbi
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  wss.c   -o wss
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  vbi-passthrough.c   -o vbi-passthrough
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  vbi-detect.c   -o vbi-detect
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  ivtv-pcm-tester.c   -o ivtv-pcm-tester
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  mpeg-read-test.c   -o mpeg-read-test
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  mpeg-freq-test.c   -o mpeg-freq-test
gcc -I../driver -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  mpeg-read-sleep-test.c   -o mpeg-read-sleep-test
make[1]: Leaving directory `/home/admin/ivtv-1.0.3/test'
$ su
# CC=gcc make install
〜
# exit
$
 

f9ivtv33.tar.gz
かってにLinuxで配布されています
最終的に ivtv.ko が既存のものと置き換わり saa717x.ko モジュールも追加されます
また /usr/local/bin/ 以下に v4l2-ctl ivtvctl ivtv-tune などコマンドが追加されます

(Linux-3.0の場合)
ivtv-utils-1.4.0.tar.gz で動作確認 (S-Videoでの録画) がとれました

  • チューナを利用する TV番組録画は(アナログ放送終了したので)検証していない
  • Linux-2.6.24の時と異なり ivtv.ko モジュールを置き換える必要はありませんでした
  • 同梱の録画用ツール record-v4l2.pl を活用することにしましたが スクリプト修正が必要

では ivtv-utils-1.4.0のインストールの状況は下記の通りです

$ tar -xzf ivtv-utils-1.4.0.tar.gz
$ cd ivtv-utils-1.4.0
$ make CC=gcc
make -C utils all
make[1]: ディレクトリ `/home/admin/ivtv-utils-1.4.0/utils' に入ります
g++ -D_GNU_SOURCE -O2 -Wall -g -I.   -c -o v4l2-ctl.o v4l2-ctl.cpp
In file included from ./linux/videodev2.h:61:0,
                 from v4l2-ctl.cpp:41:
/usr/include/linux/types.h:13:2: 警告: #warning "Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders"

〜

In file included from ivtv-fb-16-bit-test.c:10:0:
../utils/linux/ivtvfb.h:35:0: 警告: "FBIO_WAITFORVSYNC" が再定義されました
/usr/include/linux/fb.h:41:0: note: ここが以前の宣言がある位置です
g++ -I../utils -D_GNU_SOURCE -O2 -Wall  -lm  ps-analyzer.cpp   -o ps-analyzer
In file included from ../utils/linux/videodev2.h:61:0,
                 from ps-analyzer.cpp:44:
/usr/include/linux/types.h:13:2: 警告: #warning "Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders"
make[1]: ディレクトリ `/home/admin/ivtv-utils-1.4.0/test' から出ます
$
$ find . -type f -perm +1
./utils/ivtv-mpegindex
./utils/ivtvplay
./utils/ivtv-radio
./utils/ivtv-ctl
./utils/v4l2-ctl
./utils/perl/ptune.pl
./utils/perl/record-v4l2.pl
./utils/perl/ptune-ui.pl
./utils/perl/config-editor.pl
./utils/ivtvfwextract.pl
./utils/cx25840ctl/cx25840ctl
./utils/ivtv-tune/ivtv-tune
./test/ps-analyzer
./test/ivtv-fb-16-bit-test
./test/ivtv-fb-colormap-test
./test/ivtv-osd-dma-test
./test/ivtv-yuv-dma-test
./test/mpeg-enc-stop-start-test
./test/mpeg-read-sleep-test
./test/mpeg-freq-test
./test/mpeg-read-test
./test/ivtv-pcm-tester
./test/vbi-detect
./test/vbi-passthrough
./test/wss
./test/vbi
$
 

実行ファイルがいくつか作成されましたが 実際に使いそうな下記ツールのみ手動コピーしました
ivtv-ctl v4l2-ctl record-v4l2.pl ivtv-tune cx25840ctl

$ su
# cp utils/ivtv-ctl /usr/bin/
# cp utils/v4l2-ctl /usr/bin/
# cp utils/perl/record-v4l2.pl /usr/bin/
# cp utils/ivtv-tune/ivtv-tune /usr/bin/
# cp utils/cx25840ctl/cx25840ctl /usr/bin/
# cp utils/cx25840ctl/cx25840ctl.1 /usr/share/man/man1/
#
 

record-v4l2.pl は番組の録画を行うスクリプトです
ただし実際の利用では 下記のコンパイルチェックで Perlモジュールが不足してることが分かります

$ perl -c /usr/bin/record-v4l2.pl
Can't locate Video/Frequencies.pm in @INC (@INC contains: /etc/perl /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux /usr/lib64/perl5/site_perl/5.12.2 /usr/lib64/perl5/vendor_perl/5.12.2/x86_64-linux /usr/lib64/perl5/vendor_perl/5.12.2 /usr/lib64/perl5/5.12.2/x86_64-linux /usr/lib64/perl5/5.12.2 /usr/lib64/perl5/site_perl /usr/lib64/perl5/vendor_perl /usr/local/lib/site_perl .) at /usr/bin/record-v4l2.pl line 115.
BEGIN failed--compilation aborted at /usr/bin/record-v4l2.pl line 115.
$
 

まず Config/IniFiles が必要です これはCPANから取得できます
(インストールの過程は割愛します)
ivtvdriver.org で配布去れている2つのモジュールも導入する必要があります
インストールの過程は 下記の通りです

$ gzip -dv Video-Frequencies-0.03.tar.gz
Video-Frequencies-0.03.tar.gz:    2.8% -- replaced with Video-Frequencies-0.03.tar
$ tar -xf Video-Frequencies-0.03.tar
$ cd Video-Frequencies-0.03
$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for Video::Frequencies
$ make
cp Frequencies.pm blib/lib/Video/Frequencies.pm
Manifying blib/man3/Video::Frequencies.3pm
$ su
# make install
Installing /usr/lib64/perl5/site_perl/5.12.2/Video/Frequencies.pm
Installing /usr/share/man/man3/Video::Frequencies.3pm
Appending installation info to /usr/lib64/perl5/5.12.2/x86_64-linux/perllocal.pod
# exit
$ cd ..
$ gzip -dv Video-ivtv-0.13.tar.gz
Video-ivtv-0.13.tar.gz:   0.0% -- replaced with Video-ivtv-0.13.tar
$ tar -xf Video-ivtv-0.13.tar
$ cd Video-ivtv-0.13
$ perl Makefile.PL
Checking if your kit is complete...
Looks good
Writing Makefile for Video::ivtv
$ make
cp ivtv.pm blib/lib/Video/ivtv.pm
/usr/bin/perl5.12.2 /usr/lib64/perl5/5.12.2/ExtUtils/xsubpp  -typemap /usr/lib64/perl5/5.12.2/ExtUtils/typemap  ivtv.xs > ivtv.xsc && mv ivtv.xsc ivtv.c
Please specify prototyping behavior for ivtv.xs (see perlxs manual)
gcc -c  -I. -fno-strict-aliasing -pipe -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -O2 -pipe   -DVERSION=\"0.13\" -DXS_VERSION=\"0.13\" -fPIC "-I/usr/lib64/perl5/5.12.2/x86_64-linux/CORE"   ivtv.c
In file included from ivtv.xs:5:0:
/usr/include/linux/types.h:13:2: 警告: #warning "Attempt to use kernel headers from user space, see http://kernelnewbies.org/KernelHeaders"
Running Mkbootstrap for Video::ivtv ()
chmod 644 ivtv.bs
rm -f blib/arch/auto/Video/ivtv/ivtv.so
gcc  -shared -O2 -pipe -Wl,-O1 -Wl,--as-needed ivtv.o  -o blib/arch/auto/Video/ivtv/ivtv.so     \
                \
          
chmod 755 blib/arch/auto/Video/ivtv/ivtv.so
cp ivtv.bs blib/arch/auto/Video/ivtv/ivtv.bs
chmod 644 blib/arch/auto/Video/ivtv/ivtv.bs
Manifying blib/man3/Video::ivtv.3pm
$ su
# make install
Files found in blib/arch: installing files in blib/lib into architecture dependent library tree
Installing /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux/auto/Video/ivtv/ivtv.bs
Installing /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux/auto/Video/ivtv/ivtv.so
Installing /usr/lib64/perl5/site_perl/5.12.2/x86_64-linux/Video/ivtv.pm
Installing /usr/share/man/man3/Video::ivtv.3pm
Appending installation info to /usr/lib64/perl5/5.12.2/x86_64-linux/perllocal.pod
#
 

さらに実際に record-v4l2.pl により録画しようとすると
下記のエラーが出たため record-v4l2.pl の修正が必要でした

$ record-v4l2.pl -d /dev/v4l/video0 -I 'S-Video 1' -D /mnt/share/movie --directory-format "" -o test.mpg -t 10
Error calling setEndGOP(1)!
$
 

setEndGOP() や setCodecInfo() が失敗します ioctl() 処理で失敗しているようです
ドライバの問題でしょうか
対処としては 録画データに異常はなかったのでこのエラーを無視するしかありません
record-v4l2.pl を修正しておきます 合計下記4箇所です

1307   if ($ivtvVersion > 265) # > 0.1.9
1308   {
1309     $result = setEndGOP->($tunerFD, $settings{CaptureLastGOP});
1310     if ($result==0)
1311     {
1312 #      die "Error calling setEndGOP($settings{CaptureLastGOP})!\n";
1313     }
1314   }

1329 if ($changedSettings{codec})
1330 {
1331   $result = $ivtvObj->setCodecInfo($tunerFD, @newCodecInfo);
1332   if (!$result)
1333   {
1334 #    die "Error calling setCodecInfo()!\n";
1335   }
1336 }

1355   if ($changedSettings{codec})
1356   {
1357     $result = $ivtvObj->setCodecInfo($tunerFD, @codecInfo);
1358     if (!$result)
1359     {
1360 #      die "Error calling setCodecInfo()!\n";
1361     }
1362   }

1528   # open the file for writing.
1529 
1530   sysopen(OUTPUT, "$fname", O_CREAT | O_TRUNC | O_WRONLY | O_LARGEFILE) or die "Error creating file '$fname': $!\n";
1531 
1532   alarm($RecordDuration);

 

die でプログラムを終了させる箇所をコメントアウトしました 合計3箇所です

最後に録画データの出力時 sysopen() のオプションに O_TRUNC フラグを追加しています
これは同名のファイルに書き込む場合 一旦ファイルを削除する動作とするためです
(これをしないと 動画の最後にごみが残るケースがある)

ひとまず以上で必要なツールがインストールされたことになります
record-v4l2.pl の使い勝手については下記で説明しています

チャンネル選択

先ほどインストールしたツールを使って 各種チャンネルの選択 動画の試聴を試してみます

入力ソースとしては コンポジット入力 S端子入力 TVチューナー のいずれかを選択できます

$ v4l2-ctl -d /dev/video0 -i 2
Video input set to 2 (Composite 1)
 
$ v4l2-ctl -d /dev/video0 -i 1
Video input set to 1 (S-Video 1)
 
$ v4l2-ctl -d /dev/video0 -i 0
Video input set to 0 (Tuner 1)
 

チューナーの場合はさらにチャンネルを選択できます japan-bcaet と japan-cable が選択できます

$ ivtv-tune -d /dev/video0 -t japan-bcast -l
1       91.250
2       97.250
3       103.250
4       171.250
5       177.250
〜
57      735.250
58      741.250
59      747.250
60      753.250
61      759.250
62      765.250
 

アナログ放送周波数の一覧が確認できます

$ ivtv-tune -d /dev/video0 -t japan-cable -l
13      109.250
14      115.250
15      121.250
16      127.250
17      133.250
18      139.250
19      145.250
〜
57      427.250
58      433.250
59      439.250
60      445.250
61      451.250
62      457.250
63      463.250
 

ケーブルテレビの周波数テーブルも同様に確認できます
実際にチャンネルを選択するには -c オプションです

$ ivtv-tune -d /dev/video0 -t japan-bcast -c 12
/dev/video0: 217.250 MHz
 

映像を確認

/dev/video0 は読みだしで MPEG2ストリームとして読み出せます
手元の環境には Xineがインストールされているので それで観賞できます

アナログキャプチャ
japan-bcastのキャプチャ画像です
コンポジットキャプチャ
コンポジット(ストリートファイター3 3rd on Dreamcast)のキャプチャ画像です
実際の映像と 最終的にディスプレイに出力される映像とでは 2秒ほどの遅延があるため
ゲームでの利用は残念ながら現実的ではありません

Xine以外では Xawtvも 試してみましたが
nvidiaドライバ(Depth 24までしか指定できない?)との相性からか
「32bppでないとダメっす」みたいなことを言われて見れませんでした

あと オーバーレイ表示できると低速CPUにとってうれしい状況ですが 確認とれませんでした

画質の調整

実際の ビデオキャプチャの使用についてレポートします

v4l2-ctl コマンドで画質をコントロールできるようです
文法としては v4l2-ctl -d /dev/video0 -c 項目名=値
項目名 とその意味と 値の範囲は以下のコマンドで情報がとれます

$ v4l2-ctl -d /dev/video0 -L

User Controls

                     brightness (int)  : min=0 max=255 step=1 default=128 value=128 flags=slider
                       contrast (int)  : min=0 max=127 step=1 default=64 value=64 flags=slider
                     saturation (int)  : min=0 max=127 step=1 default=64 value=64 flags=slider
                            hue (int)  : min=-128 max=127 step=1 default=0 value=0 flags=slider
                         volume (int)  : min=0 max=65535 step=655 default=58880 value=50736
                        balance (int)  : min=0 max=65535 step=655 default=32768 value=32768
                           mute (bool) : default=1 value=0

MPEG Encoder Controls

                    stream_type (menu) : min=0 max=5 default=0 value=0 flags=update
                                0: MPEG-2 Program Stream
                                2: MPEG-1 System Stream
                                3: MPEG-2 DVD-compatible Stream
                                4: MPEG-1 VCD-compatible Stream
                                5: MPEG-2 SVCD-compatible Stream
              stream_vbi_format (menu) : min=0 max=1 default=0 value=0
                                0: No VBI
                                1: Private packet, IVTV format
       audio_sampling_frequency (menu) : min=0 max=2 default=1 value=1
                                0: 44.1 kHz
                                1: 48 kHz
                                2: 32 kHz
           audio_encoding_layer (menu) : min=1 max=1 default=1 value=1 flags=update
                                1: Layer II
         audio_layer_ii_bitrate (menu) : min=9 max=13 default=10 value=10
                                9: 192 kbps
                                10: 224 kbps
                                11: 256 kbps
                                12: 320 kbps
                                13: 384 kbps
              audio_stereo_mode (menu) : min=0 max=3 default=0 value=0 flags=update
                                0: Stereo
                                1: Joint Stereo
                                2: Dual
                                3: Mono
    audio_stereo_mode_extension (menu) : min=0 max=3 default=0 value=0 flags=inactive
                                0: Bound 4
                                1: Bound 8
                                2: Bound 12
                                3: Bound 16
                 audio_emphasis (menu) : min=0 max=2 default=0 value=0
                                0: No Emphasis
                                1: 50/15 us
                                2: CCITT J17
                      audio_crc (menu) : min=0 max=1 default=0 value=0
                                0: No CRC
                                1: 16-bit CRC
                     audio_mute (bool) : default=0 value=0
                 video_encoding (menu) : min=0 max=1 default=1 value=1 flags=readonly
                                0: MPEG-1
                                1: MPEG-2
                   video_aspect (menu) : min=0 max=3 default=1 value=1
                                0: 1x1
                                1: 4x3
                                2: 16x9
                                3: 2.21x1
                 video_b_frames (int)  : min=0 max=33 step=1 default=2 value=2 flags=update
                 video_gop_size (int)  : min=1 max=34 step=1 default=12 value=15
              video_gop_closure (bool) : default=1 value=1
             video_bitrate_mode (menu) : min=0 max=1 default=0 value=0 flags=update
                                0: Variable Bitrate
                                1: Constant Bitrate
                  video_bitrate (int)  : min=0 max=27000000 step=1 default=6000000 value=6000000
             video_peak_bitrate (int)  : min=0 max=27000000 step=1 default=8000000 value=8000000
      video_temporal_decimation (int)  : min=0 max=255 step=1 default=0 value=0
                     video_mute (bool) : default=0 value=0
                 video_mute_yuv (int)  : min=0 max=16777215 step=1 default=32896 value=32896
            spatial_filter_mode (menu) : min=0 max=1 default=0 value=0 flags=update
                                0: Manual
                                1: Auto
                 spatial_filter (int)  : min=0 max=15 step=1 default=0 value=0 flags=slider
       spatial_luma_filter_type (menu) : min=0 max=4 default=0 value=1
                                0: Off
                                1: 1D Horizontal
                                2: 1D Vertical
                                3: 2D H/V Separable
                                4: 2D Symmetric non-separable
     spatial_chroma_filter_type (menu) : min=0 max=1 default=0 value=1
                                0: Off
                                1: 1D Horizontal
           temporal_filter_mode (menu) : min=0 max=1 default=0 value=0 flags=update
                                0: Manual
                                1: Auto
                temporal_filter (int)  : min=0 max=31 step=1 default=0 value=8 flags=slider
             median_filter_type (menu) : min=0 max=4 default=0 value=0 flags=update
                                0: Off
                                1: Horizontal
                                2: Vertical
                                3: Horizontal/Vertical
                                4: Diagonal
     median_luma_filter_minimum (int)  : min=0 max=255 step=1 default=0 value=0 flags=inactive slider
     median_luma_filter_maximum (int)  : min=0 max=255 step=1 default=255 value=255 flags=inactive slider
   median_chroma_filter_minimum (int)  : min=0 max=255 step=1 default=0 value=0 flags=inactive slider
   median_chroma_filter_maximum (int)  : min=0 max=255 step=1 default=255 value=255 flags=inactive slider
      insert_navigation_packets (bool) : default=0 value=0
 

具体的には 例えば MPEG2のビットレートを落としてキャプチャ動画のサイズを落とすなどが考えられます

$ v4l2-ctl -d /dev/video0 -c video_bitrate=2000000
 

ハードディスクレコーダとして利用する場合は 事前に画質やチャンネルをチューニングした上で

$ cat /dev/video0 > movie.mpg
 

と単純にストリームをファイルにコピーするだけです
実際はスクリプトやツールなどを利用する形となるでしょう

ivtv-utils-1.4.0 では record-v4l2.pl を利用していますので紹介します

まずは record-v4l2.pl の情報表示機能からです

$ record-v4l2.pl --list-inputs
record-v4l2.pl 1.33 for use with http://ivtv.sf.net/
Available Inputs:
0: Tuner 1
1: S-Video 1
2: Composite 1
$
 

上記の感じで入力ソースの情報が取得できます シェルでコマンドラインを叩く点は一緒です
また 「record-v4l2.pl –help」 でオプション説明が得られます

S-Videoで 10秒間録画してみます

$ record-v4l2.pl -d /dev/v4l/video0 -I 'S-Video 1' -D /mnt/share/movie --directory-format "" -o test.mpg -t 10
$
 

オプションの説明ですが
-I 'S-Video 1' でキャプチャカードと入力ソースを指定します
-D は録画したファイルの置き場所となるベースディレクトリの指定です
–directory-format を空白に設定しています
録画毎にベースディレクトリにサブディレクトリを別けて保存したい場合はフォーマットを指定します
S-Video_1-20110828-0959/ みたいな感じでディレクトリを別けることが可能です
空白を設定することで ベースディレクトリ直下に録画ファイルを保存してくれます

キャプチャした映像は下記のように保存されていました
ひかりTV アナログキャプチャ画像
ソースの映像は フレッツ光のひかりTVです
綺麗にキャプチャできていますが ソースがHDのためキャプチャの上下部分に非映像領域があります

Linux-3.7.8では下記のエラーが出ました

record-v4l2.pl 1.33 for use with http://ivtv.sf.net/
Error:  Video Standard = 'NTSC' is invalid!
Valid Standards are: NTSC-M
 

「record-v4l2.pl --list-standard」 で指定可能な映像規格が表示されます
Linux-3.7.8では NTSCが使えなくなっているようです
対処として record-v4l2.pl に -s NTSC-M オプションを指定すれば問題なく
録画できます

 

ファームウェアのロードタイミングについて

↑でファームウェアのロードの仕組みについて触れましたが
実際にファームウェアを ロード/アンロード するタイミングは /dev/video0 を open()/close()するタイミングのようです
具体的には Xineを開いたり閉じたりしたとき キャプチャの開始/終了時 となります

hotplug動作ログ
open()時 DEVPATH=/devices/pci0000:00/0000:00:0b.0/firmware/firmware-0000:00:0b ACTION=add SYSFS=/sys FIRMWARE=v4l-cx2341x-enc.fw
close()時 DEVPATH=/devices/pci0000:00/0000:00:0b.0/firmware/firmware-0000:00:0b ACTION=remove SYSFS=/sys FIRMWARE=v4l-cx2341x-enc.fw