土日になると体調崩す。 かといって無駄に休日出勤するわけにも……つっても忙しいのでそれ程無駄でもないんだが。
最近は仕事とmkv読み込みしかしてないので特に日記書くこともない。あ、ゲームマーケットにちょこっと行ったくらい。
PeerCastStation自体は手を入れてないんだが。Matroska(.mkv)読み込みをずっとやってた。
MatroskaはEBMLというバイナリ化XMLみたいなもので構成されてるのでまずはそれを読み込み。 要素のIDやらサイズが可変長整数なのが面倒だが難しくはなかった。
一点だけ、整数は可変長整数なんだーと思って要素のデータがuintやintの物も可変長整数としてパースしてたら間違っていた。こいつらも可変長であることは違いないが、サイズは事前にわかるので普通に1〜8バイトのビッグエンディアン固定長整数として読んでやればいいだけだった。ちゃんと仕様を読んでなかったのが悪いが紛らわしい。
書けはしたのでじゃあいざテストファイルを読み込みましょうとやってみたら上手くいかん。 単純なファイルtest1.mkvは大丈夫だったんだが、当初の目的であるライブストリーミング用ファイルtest4.mkvを読むと途中でおかしなデータにぶちあたって止まってしまう。バイナリエディタで見るとSegmentタグのあとに0xA0が130バイトちょい連続していてファイル壊れてるっぽく見えるんだが、壊れてるテストファイルはtest7.mkvだと言うし、検証アプリのmkvvalidateでも文句言われないしじゃあこれは正当なのかと。
しばらく悩んでると、同じこと言ってるForumのスレを教えてもらったので読んでみた。確かにぶっこわれてるけどストリーミングなら壊れるもんなんだから頑張れ、的なことが書いてあった。このくらいのゴミデータはぶっこわれてるうちに入らないので検証器も普通に通るようだ。あと普通にGStreamerから吐かれたファイルらしい。いつのか知らんがGStreamerぶっこわれてますよそれ……。
壊れてるファイルを読むのはまあいいんだけど、復帰方法が具体的に書かれてるところないんだよね……。一応Streaming方法のページにも上記スレにも次のClusterタグを探せよと書かれているんだが、Segmentの直後なのでここからClusterまで飛ばしてしまうとTrackとかのコーデック情報が入ってるタグもすっとばすので再生できないっすよ。
仕方ないのでmkv読み込むCとかC++のライブラリソースを眺めてみよう。 するとすっごいめんどくさいのがわかった。 不正な要素が来たと判断するのに必要な項目がたくさんある。
上記の場合は問答無用でおかしい。ただしIDもサイズも最大長はファイル先頭のEBMLタグ内に書かれてるので本当はそれを参照すべき。
上記の場合は一個親のタグにくっつかないかなーというのを再帰的に調べる必要がある。というわけで親の読取り開始位置と親のサイズと親のIDとそれに仕様的にくっつくと思われるID一覧を知ってないといけない。
上記の場合の処理がよくわかってない。特に後者。知らないタグなのかぶっこわれたデータなのか判別できないんだが、どうもタグによって子に知らないタグを許可するかどうか切り替えてるっぽい?やっぱりよくわかってないが。
というわけでなかなか難しいことはわかった。OGGやMPEG-2 TSなんかと比べると明らかにストリーミング向けじゃないのな。階層構造とストリーミングは相性悪いわ。mp4でライブストリーミングできない理由がわかった気がする。まああっちは仕様上mkvみたいに不定サイズのタグを持てないからってのもあるんだけど、やったとしても破壊に弱いから対応しないんだろうな。
さてはて困ったな、と言いたいところだが、PeerCastで扱う限りはそんなに難しいことしなくていい。TCPでしか通信できないんでパケット破壊とかそうそう起きるものではない1。 さらに言うならPeerCastでコンテナのパースをしないといけないのは配信開始の部分だし、そこもヘッダとそのあとのボディに分けるだけ。 というわけで 判別が必要そうなところだけ見てあとは出来る限りすっとばそう。
これだけだ。ちゃんとパースして再生するのはプレイヤーの役目なので、途中で受け渡しするだけのPeerCastではあまり構造については深く考えないことにして、ごく少数の知ってるデータ以外は何も見ずに右から左に流すだけにした。 ただしどこからがヘッダ部でどこまでがボディ部、というかどこからまた新しいヘッダが流れてきたのかを判別はする必要はあるのである程度同期はとってる感じ。 同期をとるワードが状態によって変わるけどね。
あとはこれC#で書くだけか。うーん、まあすごい大変ってほどではないかな……。
生成されたストリームが既にぶっこわれてるのは仕方ないんで対処しないといけないんですけどね。 ↩