TV録画サーバーを更新したい
前回からあっという間に3年経過してます。そして毎回ブログが更新できていないことを書いている気がする...。
たしか2年前くらいに録画サーバーを一新しました。理由はメインPCのupdateによって1台PCが組めるだけのパーツが揃ったためだったような。 その結果、下記のようなサーバが現在動いています。
- PC: 自作 / i7-4790K / Memroy24GB / GTX660Ti
- OS: Ubuntu18.04
- Storage:
- TV tuner: PT3
ソフトウェアの構成 * Mirakurun / Chinachuで録画 * 録画ファイルをffmpegでH264でエンコードして保存 * エンコードにはNVENCを使用
他にもforked-daapdやminidlnaなども動いてますが、その辺はあんまり使えてないので割愛。 大体この録画をTVに繋いでいるAmazon Fire Cubeに入れたKodi経由で見るようなことをしてます。
ただ、最近録画に失敗したりエンコードに失敗したりしていて、最近だとMirakurun/EPGStationなど他の選択肢も出てきているし、TrueNASのLinux版(True NAS Scale)というものも出てきているようなので、いっそのこと全部入れ替えてみようかな、とか考えてたりします。
下記の構成ができないか考え中 * PCはそのまま * OS: True NAS Scale * その上でVMでUbuntuを動かす * 録画はMirakurun/EPG Station * エンコードはEPG Stationからnvenccでエンコード
あと最近Orange Pi 5買ってみたりもしたので、これもうまいこと使えないかなーとか考えてますがまだ妙案はない。
このGWでやりたかったが子供が風邪ひいたり自分が風邪ひいたりして結局時間がほとんどとれず進んでないんだよね...。 e-Paperもちょっと買ってみてて、表示までは割とすんなりできたけど、どう活用するかはこちらも特に妙案はなく。
ゆっくり考える時間が欲しい...。
TV録画サーバーの話
うちには数年前から動いているTV録画サーバがあります。 構成はこんなかんじ。
- PC:HP ProLiant MicroServer (2万円くらいで買えるやつ)
- OS:CentOS7(最初CentOS6で動かしてましたが、7に更新しました)
- TVチューナー:PT3(販売終了 もうひとつくらい買っておけばよかった...)
- ストレージ:
- 録画管理ソフト:chinachu
基本的には問題ないのですが、いかんせんCPUが弱いのでエンコードが遅いし、エンコードと録画同時にちゃんと動くかとか不安だった(実際試してちゃんと動かなかったような...)ので自動エンコードさせてないところが不満点ですかね。 で。最近(といっても2年前くらい...)ivy bridgeを載せたPC一式が手に入りまして。こいつにTV録画+エンコードの機能を入れ、サーバーはデータ保存専用としようかな、と思っています。
まぁつまりは、記事を書くための事前準備記事でした。 そのうちやったら記事書きたいと思います。 今更感のある記事になるかと思いますが。書くことが大事。
他にもサーバにmt-daapを入れてiTunesサーバ化する、とかkodiいれてみる、とかやりたいなーと思いながら結構経ってます。。
ひさびさのブログ
やっぱりブログが続かない。
仕事と関係ある内容なら勉強にもなるし非定期でもかけるかなーとか思ってましたが全然かけない。 時間が取れないのが問題ですな。
独身のときの自由な時間が100だとすると 結婚後→40 子ども生まれた後→1~5 もうすぐ1歳→10くらい? って感じ。
書きたいことはあるつもりなんだけどなー・・・(遠い目)
ま、こんなのでも少しでもアップしていけばいいのかな。。
Bluetooth v5.0, Vol1, 1.2 Overview of Bluetooth Low Energy Operation
1.2 Overview of Bluetooth Low Energy Operation
- BR/EDRと同様に2.4GHz帯を使用
- 周波数ホッピングを採用している
- 複雑さを避けるために2値周波数変調を採用
- 必須(mandatory)シンボルレートは1Msym/s (LE 1M PHY)
- 1sym=1bitでデータレートは1Mbit/s
- オプションでエラー訂正
- S=2; 2sym=1bit→500kbit/s
- S=8; 8sym=1bit→125kbit/s
- オプションでエラー訂正
- 1sym=1bitでデータレートは1Mbit/s
- オプショナルシンボルレートは2Msym/s
- 1sym=1bitでデータレートは2Mbit/s
- エラー訂正オプションはない
- 1sym=1bitでデータレートは2Mbit/s
- Sec 3.2.2に詳細
多重化とチャネル
- LEは2つの多元接続方式を採用
イベント
- 物理チャネルはイベントと呼ばれる時間単位に分割される
- パケットはイベントに配置されて送信される
- イベントは4種類
- Advertising
- Extended Advertising
- Periodic Advertising
- Connection Events
AdvertisersとScanners
- Advertisers: advertising(以下、adv.)物理チャネルでadv.パケットを送信するデバイス
- Scanners: adv.物理チャネルでadv.パケットを受信するデバイス
- adv.物理チャネルにおける通信はadv.イベント内で行われる
- adv.物理チャネルは同じadv.イベント内でもAdvertiserが次のadv.パケットを送るときに変更される
- Advertiserはイベント中いつでもadv.イベントを終了させることができる
- 次のadv.イベントの始まりは最初に使用されたadv.物理チャネルが使用されます
Communication
- LEデバイスはadvertising eventで2つ以上の機器間で単方向(unidirectional)通信もしくはブロードキャスト(broadcast)通信が可能
- LEデバイスはadvertising eventを使用してペアを確立し、data channelを使用した双方向通信や、secondary advertising channelを使用して定期的にブロードキャストする事ができる
Connection event
- Initiators: 他の機器と接続するためにconnectable advertising(以下、conn. adv.)パケットを監視(listen)している機器
- 接続手順
- Advertiserがconn. adv.イベントを発信している場合、Initiatorはconnection requestを同物理チャネル上に送付できる
- Advertiserが接続を了承(accept)したら、adv.イベントは終了ののちconnectionイベントが開始される
- 接続後はピコネット(piconet)内において、InitiatorはMasterデバイスに、AdvertiserデバイスはSlaveデバイスになる
- Connection(以下、Conn.) eventはMaster-Slave間でデータパケットを送受信するために使用される
- Connection eventについて
Frequency Hopping
- ピコネット内のデバイスは擬似ランダムパターンによって生成された特定の周波数ホッピングパターンを使用する
- LEの場合は37の周波数帯をホッピングし、これによってISMバンド内におけるBluetoothの共存性能を向上させている
Link, Channel, Transport
- 物理チャネルからL2CAPまでの構造(詳細はSec. 3.3 ~ 3.6)
L2CAP Channel |
Logical Link |
Logical Transport |
Physical Link |
Physical Channel |
- 同じ物理チャネル内で2つのデバイスがつながると物理リンクが形成される
- アクティブな物理リンクはMaster-Slave間で双方向パケットトランスポートを提供する
- LE物理チャネルは複数のSlaveデバイスを含むので、デバイスが物理リンクを形成するのには制限がある
- SlaveはMasterデバイスへの物理リンクを1つ以上持つことができる
- デバイスはMasterとSlaveに同時になることができる
- 同じpiconet内のSlave間で物理リンクを形成することはできない
- 物理リンクは1つ以上の非同期通信論理リンクのトランスポートとして使用される
論理リンク上の通信はリソースマネージャのスケジューリング機能によって物理リンク上に多重化される
論理リンク上でLInk Layer(LL)プロトコルが実行される
ピコネット上でアクティブなデバイスはLLプロトコル信号を送るためにLE asynchronous connection logical transport (LE ACL)を持っている
BR/EDRのように、Link Layerの上にはL2CAPレイヤがチャンネルベースの抽象化をアプリケーションやサービスに提供している
- L2CAPはアプリケーションデータを分解(fragmentation)/結合(de-fragmentation)を行い、また論理リンク上で複数チャネルの多重化(multiplexing)と非多重化(de-multiplexing)を行う
LEではL2CAPの上にさらに2つのプロトコルレイヤが存在する
- Security Manager Protocol(SMP)
- fixed L2CAP channelを用いてデバイス間のセキュリティ機能を受け持つ
- Attribute Protocol (ATT)
- fixed L2CAP channel上で小出しでコミュニケーションを取るメソッドを提供する
- Security Manager Protocol(SMP)
1.3 Overview of AMP Operation
こちらは省略…
Bluetooth Spec v5.0, Vol.1, 1.1 Overview of BR/EDR Operation
1.1 Overview of BR/EDR Operation
- BR/EDRはISMバンド(2.4GHz帯)を使用
- 周波数ホッピングを採用している
- 複雑さを避けるために2値周波数変調を採用
- シンボルレートは1Msym/s
- ビットレートは1Mbit/sだが、EDRなら2Mbit/sか3Mbit/s
- piconet間はクロックと周波数ホッピングパターンが同期される
周波数ホッピング
- 擬似ランダムパターン
- 1MHz分割で79チャネル
スロット
- 各チャネルは時間方向にも「スロット」という単位で分かれている
- Bluetoothデバイス間のデータはパケットとしてスロットに配置されて通信する
- Time-Division Duplex(TDD)によって全二重通信が可能
物理チャネル(physical channel)と物理リンク(physical link)
- 物理チャネル内にはmaster-slave間で物理リンクが形成される
- 物理リンクはmaster-slave間で双方向パケット通信を提供する
- 物理チャネルには複数のslaveデバイスが含まれる可能性があるので、物理リンク形成には制限が生じる可能性がある
- 物理リンクは各slaveとmasterの間に形成されるが、slave間には形成されない
論理リンク(logical link)
- 物理リンクはトランスポートとして1つ以上の論理リンクに使用される
- 論理リンクはユニキャストなsynchronous, asynchronous, isochronous通信をサポートする
- 論理リンクの通信路は物理リンク上で多重化され、リソースマネージャのスケジュール機能によって物理リンク上のスロットに配置される
Link Manager Protocol(LMP)
- ピコネット上のデバイスはdefault asynchronous connection-oriented logical transport (ACL logical transport)でLMP protocol signalingを伝送する
- ACL logical transportはデバイスがピコネットに参加するたびに作成される
- 追加の論理トランスポートは要求されれば作成される
L2CAP
- ベースバンド層の上でL2CAP層はチャネルベースの抽象化を提供
- データの分割(segmentation)と再結合(reassembly)、共有論理リンク上におけるマルチチャネルの多重化(multiplexing)と分離(de-multiplexing)を実行
Bluetooth Spec v5.0 Vol1 1 General Description
1 General Description
- Bluetoothは短距離における有線通信を無線化することを目的として策定された無線規格
- 特徴:ロバスト性/低消費電力/低コスト
- BluetoothにはBasic Rate(BR)とLow Energy(LE)の2つのシステム
- BRはEnhanced Data Rate(EDR), Alternate Media Access Control (MAC)、Physical(PHY) layer extensionsをオプションとして持っている
- BRには同期通信と非同期通信がある
- データ通信速度
- BR: 721.2kbit/s
- EDR: 2.1Mbit/s
- 802.11 AMP: 54Mbit/s
- LE systemはBR/EDRよりさらに低消費電力、低複雑性、低コストな設計になっている
- デバイスは両方のシステムを実装して両方別々に通信することができる。
- Bluetooth Core systemはHostと1つ以上のControllerで構成されている
- HostはHost Controller Interface(HCI)から上の層
- ControllerはHCIより下の層
- ControllerにはPrimary ControllerとSecondary Controllerの2つが定義されている
Memo
Bluetooth Spec v5.0 Vol.1
では Vol.1 Architecture & Terminology OverviewArchitecture & Terminology Overview から見ていきましょうか。
前回Vol.0って書いた気がしますが、Vol.1です。
1. General Description 1.1 Overview of BR/EDR Operation 1.2 Overview of Bluetooth Low Energy Operation 1.3 Overview of AMP Operation 1.4 Nomenclature 2. Core System Architecture 3. Data Transport Architecture 3.1 Core Traffic Bearers 3.2 Transport Architecture Entities 3.3 Physical Channels 3.4 Physical Links 3.5 Logical Links and Logical Transports 3.6 L2CAP Channels 4. Communication Topology and Operation 4.1 Piconet Topology 4.2 Operational Procedures and Modes 5. Security Overview 5.1 Security Architecture 5.2 BR/EDR Secure Simple Pairing 5.3 Secure Connections Only Mode 5.4 LE Security 5.5 AMP Security 5.6 Key Generation Between BR/EDR and LE Physical Transports 6. Bluetooth Application Architecture 6.1 Bluetooth Profiles 6.2 Generic Access Profile 6.3 Profile Hierarchy 6.4 Generic Attribute Profile 6.5 GATT-Based Profile Hierarcy 7 Coexistence and Collocation
目次書くだけで大変ですね…。
Bluetoothの仕様を把握する
結局前回の更新からずいぶん時間が空いてしまいました。
もう子供生まれてから1か月以上たつんですねぇ。。
突然ですが、Bluetooth core specを読んでいきたいと思います。
Bluetoothヘッドセットが流行り始めてから結構経ちますが、技術的なBluetoothの話ってあんまりネットで調べても出てこないので、勉強の意味も込めて書いていきたいと思います。
BLEだと個人でも結構いろいろできるので解説しているブログなどヒットしますが、いかんせん仕様がややこしくてですね。。
できるだけわかりやすく書くつもりですが、間違いありましたらご指摘いただけると嬉しいです。
Core Specは Bluetooth SIGの仕様→コア仕様 の中にあります。
ちなみに、実に2822ページあります。(絶望)
全体は大項目Vol 0~Vol7まで分けられており、それぞれに中項目Part A, B, ...、さらにその下に 小項目1, 2, ...と分けられています。
- Vol.0: 全体の目次とか、Bluetooth認証の話とか。あまり見ない…
- Vol.1: BR/EDR、BLEとはなにかとか、下層から上層まで全体のつながりとか、全体の話。Vol.2以降がそれぞれの層に分かれた詳細仕様になっている
- Vol.2: BR/EDRの物理層(RF), Baseband, LMP, HCIなど、下層まわりについて記されている。
- Vol.3: L2CAP, SDP, GAP, ATT, GATTなどについて記されている。BR/EDRもBLEも記述されている。よくお世話になる。
- Vol.4: 外部マイコンとやりとりするHCIのTransport Layerについて。UARTとか。
- Vol5: AMP Controllerについて。使わないから読んだことない…
- Vol6: BLEの下層の話。
- Vol7: ほかの無線規格との共存の話。Mobile Wireless Standard(MWS)とのやりとりについて書かれているっぽい。どうやらv4.1から追加された模様。使わないので読んだことない…。
時間ができて気が向いたら更新されます。 最初はVol0からかなぁ…。
タイトル変えました。
やっぱり更新が滞ってしまう…。
原因を考えたところ、やはり意気込んで記事を持続して書き続けるのは性に合わないのだと言う結論に至りました。
なので、これからはたまに意気込んだ記事を書いて、それ以外はその日に思ったこととか、最近のニュースについてとかを誰に見られることも考えずに書いていきたいと思います。
あと最近子供生まれたので、育児についても書いていければと思います。
まずは書き続けることができるようになることが目標です。
では。
ポインタとメモリ その2
前回:ポインタとメモリ その1 - プログラム書いたり、もの作ったり。あと育児とか。
値渡しと参照渡し
C言語では、色んな所で実は同じように値のコピーが行われます。
ここに、ポインタの有用性が出てきます。
一番わかりやすいのは関数の引数における「値渡しと参照渡し」でしょう。
// 値渡し void func_val(int fa, int fb) { fb = fa; return; } // 参照渡し void func_ref(int *pa, int *pb) { *fb = *fa; return; } int a = 0x10; int b = 0x20; func_val(a, b); printf("a=%d, b=%d", a, b); // a=16, b=32となり、func_valではbの値は更新されない func_ref(&a, &b); printf("a=%d, b=%d", a, b); // a=16, b=16となり、func_refではbの値は更新される
値渡しの場合は、関数の中でfb=faとやっても、もともとの変数には影響を与えません。これは関数が呼ばれるときに引数の値はスタック領域と呼ばれるメモリ上の別な場所にコピーされるため、関数の中の引数(faとかpa)と関数を呼ぶ前の引数(aとかb)の実体は別々のものになります。
つまり、アドレスが異なると思ってもらって良いです。
例:もとのaとbのアドレスが0x2000, 0x2001、関数引数のfaとfbのアドレスが0x2100と0x2101、などそんな感じ
アドレスが異なっていれば、そりゃあ関数の中で書き換えを行ってももとの変数には影響与えませんよね。
メモリのイメージで説明するとこんな感じです。
func_val()呼ぶ前
0x2000 | 10 20 xx xx xx xx xx xx ... 0x2100 | xx xx xx xx xx xx xx xx
func_val()に入った直後
0x2000 | 10 20 xx xx xx xx xx xx ... 0x2100 | 10 20 xx xx xx xx xx xx
b=aの直後
0x2000 | 10 20 xx xx xx xx xx xx ... 0x2100 | 10 10 xx xx xx xx xx xx
func_val()を抜けたあと
0x2000 | 10 20 xx xx xx xx xx xx ... 0x2100 | xx xx xx xx xx xx xx xx
じゃあ、参照渡しの場合はどうなるんでしょう。
func_ref()呼ぶ前
0x2000 | 10 20 xx xx xx xx xx xx ... 0x2100 | xx xx xx xx xx xx xx xx
func_ref()に入った直後
0x2000 | 10 20 xx xx xx xx xx xx ... 0x2100 | 00 20 01 20 xx xx xx xx
pb=paの直後
0x2000 | 10 10 xx xx xx xx xx xx ... 0x2100 | 00 20 01 20 xx xx xx xx
func_ref()を抜けたあと
0x2000 | 10 10 xx xx xx xx xx xx ... 0x2100 | xx xx xx xx xx xx xx xx
func_refに入った直後、
0x2100 | 00 20 01 20 xx xx xx xx
こうなってますけど、まさにこれこそがポインタなのです。
(仮定として、16ビット系、リトルエンディアンとして書いてます。)
つまりpa(0x2100) = 0x2000, pb(0x2102) = 0x2001が代入されており、paがポインタなので*paと書くと、もともとの変数(0x2000の変数)に対して操作することができるわけです。
あくまで、関数がコールされるときにスタックに値がコピーされることは同じです。ですが、そのコピーされるものが値ではなくアドレスであり、さらにポインタという仕組みがあるため、そのアドレスの値にアクセスすることができるのです。
これによって関数の外側の変数を変更することができるというわけです。
ポインタの利点
これがわかると、ポインタがなぜ利用されるのかがわかってきます。
例えば、構造体。
構造体を関数の引数に渡すとき、そのまま渡したら構造体の中身がすべてスタックにコピーされる事になります。構造体の大きさがそこまで大きくなければ影響も少ないかもしれませんが、大きくなってくるとスタックにコピーされる量も大きくなり、メモリ的にも動作的にも無駄が大きくなってきます。
ところが、これをポインタで渡すようにすると、構造体の先頭アドレスをコピーするだけ済みます。
typedef struct sample_s { int num1; // 2byte int num2; // 2byte char str[16]; // 16byte } sample_t; void proc_sample_val(sample_t sample) { // コピーされたsampleにアクセスする // スタックへ20byte分すべてコピーされる // 元の変数sample1は変更されない sample.num2 = sample.num1; sprintf(sample.str, "val"); } void proc_sample_ref(sample_t *sample) { // sample1のアドレスにアクセスする // スタックはsampleのアドレスサイズ分(今回は2byte)だけ消費される // 元の変数sample1も変更される sample->num2 = sample->num1; sprintf(sample->str, "ref"); } sample_t sample1; sample1.num1 = 10; sample1.num2 = 20; proc_sample_val(sample1); printf("val: %d, %d", sample1.num1, sample1.num2); // val: 10, 20 proc_sample_ref(&sample1); printf("ref: %d, %d", sample1.num1, sample1.num2); // ref: 10, 10