2013年1月31日木曜日

mp4から映像データをoffにする。

youtubeのデータがmp4であることが(たぶん)確定したので、映像データを取り去りたいとおもいます。

まず、大前提として、mp4データなんですが次のような書式になっています。
1:データはボックスという形のまとまりになっている。
2:ボックスは子ボックスを内部に持つことができるが、それはボックスのタイプ次第
3:ボックスの形式は次のとおり。
[4バイト(ボックスのデータ量)][4バイト(ヘッダ文字列)][内容]
となっています。

で、大まかな構成ですが・・・
[ftyp]
[moov]
[mdat]
これらが一番ベースとなるボックス。
でmoovはコーデック情報として、trakという子ボックスを持っています。

さて、ここから映像データを取り去るかというと、映像用のtrakデータをoffにしてやればいいみたいです。とりあえず動作しました。
で、offのやり方。
[ftyp]
[moov]
  [trak(映像用)]
  [trak(音声用)]
[mdat]
という形になっていたので、映像用のtrakをfreeに書き換えます。するとあら不思議、映像用のtrakの内容がそっくりそのままskip用の除外データになっちゃいます。


[ftyp]
[moov]
  [free(映像用だがキャンセル)]
  [trak(音声用)]
[mdat]

で、再生してみたところ、音楽のみのデータになりました。
もちろんiOS6.1(iPhone4S)で、バックグラウンド音楽再生もできました。
シーク等もばっちり。

あとはyoutubeのデータをプロキシするサーバーをぱぱっと書けば、なんとかなりそうです。

youtubeのデータについて調べる。

youtubeをBGMにして流したい。でもiOS6.1でできなくなった・・・

というわけで、どうやればいいか調べます。

まず、youtubeでつかっているデータについて調べます。
とりあえず、iPhoneとiMacのsafariを接続して、データアクセスについて調べました。


http://r11---sn-3pm7en7k.c.youtube.com/videoplayback?id=01e3e19fd.....
というURLであることがわかりました。
以前の調査から、youtubeのアドレスは一度アクセス可になった場合、同じIPアドレスからのアクセスは許可されることになるみたいです。

というわけで、同じLANネットワークにあるところからこのURLをたたいてみます。
手持ちのiMacにはwgetコマンドがはいっていないみたいだったので、ぱぱっとjavaのプログラムを書いてみました。

ものすごい乱暴ですが、こんなコード

String url = "http://r11---sn-3pm7en7k.c.youtube.com/videoplayback?id=01e3e19fd......youtube_mobile";
URL urlObj;
HttpURLConnection urlCon;
urlObj = new URL(url);
urlCon = (HttpURLConnection)urlObj.openConnection();
urlCon.setRequestMethod("GET");
ReadableByteChannel rbc = Channels.newChannel(urlCon.getInputStream());
FileChannel fc = new FileOutputStream("test.mp4").getChannel();
while(true) {
  ByteBuffer buffer = ByteBuffer.allocate(65536);
  rbc.read(buffer);
  buffer.flip();
  if(buffer.remaining() == 0) {
    break;
  }
  fc.write(buffer);
}
fc.close();
rbc.close();
urlCon.disconnect();

これでとりいそぎ、test.mp4が取得でき、vlcで再生してみたところ、問題なく再生できました。

内容を確認してみたところ、やっぱりmp4でしたね。
Video: mpeg4 (Simple Profile) 映像データがh.264じゃなかったのが少々気になりますが・・・

一応、万一httpLiveStreamingでiPhoneがやりとりしていたら困るので(そっちをとった方が音声のみにできる公算がたかかった)、wiresharkで確認してみましたが、やっぱりmp4のようでした。

ここまでで、youtubeのデータはmp4であることがほぼ決定的になりました。


HttpLiveStreamingとかの話(iOS6.1でのバックグラウンド音楽再生について)

iOS6.1になって、safari標準搭載のquickTimeで動画をBGMとして再生しつつ、他のアプリをいじるということができなくなりました。

困るんですが・・・

で、なんとかしてくて、いろいろ調べてみました。

まずBGM再生になる条件について調べてみました。
ためしたこと。
・mp3の場合→ok
・m4aの場合→ok
・mp3準拠のhttpLiveStreamingの場合→ok
・mp4の場合→ng
・h.264 + aac or mp3のhttpLiveStreamingの場合→ng
・aac準拠のhttpLiveStreamingの場合→ok
とこんな感じになりました。

これだけみると、コーデックに動画コーデックがはいっているデータならアウトみたいですね。


で、仕事しながらyoutubeを聴きたかった僕としては、httpLiveStreamingから動画データを取り去って動作するようなプロキシを書いてやろうとおもっていたわけです。
が、youtubeのデータを確認したところ、どうやらmp4でやってるみたいですね。rangeリクエストが飛んでましたし、先頭データにftypがきたので、あーmp4だってわかりました。(バイナリを見てみただけで判定つくところがすばらしいですね。)

で、結局やらなかったmpegtsから動画コーデックを排除する動作ですが、たぶん次のようにすればできると思います。
1:mpegtsのヘッダ情報から、動画データのtrackIDを取得します。
2:PMTから動画のトラックデータを排除する。
3:PCRのtrackIDを確認しておく。たぶん、動画データのtrackIDになってる。
4:3でもし、音声データがPCRになっているなら、動画データの188バイトごとのパケットをすべて削除してしまえば、たぶんOK
5:3でもし、PCRが動画データになっている場合(たぶんたいていのデータでは、PCRは動画データ)、音声パケット(PCRデータのみで実体はなし)をねつ造してやって、はさみこめば出来上がり

となる予定でした。

ただ、非常に残念なことに、youtubeでは動画データがmp4だったので、しばらくmp4から動画データを排除する方法について調べたいと思います。

とりあえず、BGMとして再生できるようにしたい場合は、以前つくったjsegmenterをつかって、m4aやmp3のデータをつくってから、分割してやってHttpLiveStreamingをつくってもらえれば、とりあえずは、BGMとして流しつつ他のアプリをいじれることはわかりました。

2013年1月30日水曜日

flvのmetaデータについてちょっと調査しておく。

flvにはmetaデータというのがあります。0x12からはじまるタグですね。
だいたいは次のような形式になっています。

1バイト データタイプ 0x12固定
3バイト タグサイズ
4バイト timestamp
3バイト トラック番号(0固定)
以降タグデータ
4バイト 終端データ
という形になっています。

で、タグデータの内容ですが、どうやら以下のようになっているみたいですね。

数値
[00] [8バイト] 8バイトのデータの部分はDoubleで書き込むみたいです。
JavaでやるならDoublteToLongBits(数値)で取り出せてlong(javaでは8バイト)で書き込めばOK

Boolean値
[01] [1バイト] 0x01でtrue 0x00でfalse

String値
[02] [2バイト] [データ] 2バイトの部分がshortの形での文字列長、データは単に文字列
日本語が扱えるかは不明

Object型
[03] [文字列の内容データ] [別の要素データ] [文字列の内容データ] [別の要素データ]...
最後は00 00 09でおわる。
という形[文字列の内容データ]という部分は[2バイト] [データ]の塊のこと。

NULL型
[05] これだけ

UNDEFINED型
[06]が予約されている不明

MAP型
[08] [4バイト] [文字列の内容データ] [別の要素データ] の繰り返し Object型の中身と同じ
終わりが00 00 09でおわるところも同じ
始めの4バイトは数値要素数がはいっているのだろうか?Flazrでは0でうめているみたい。


ARRAY型
[0A] [4バイト] [別の要素のデータ]... 4バイトの部分は要素数

DATE型
[0B] [8バイト] [2バイト] 8バイトの部分はunixミリ秒をDoubleのbyte配列にしたもの。
うしろの2バイトは0でうめるみたい。(後ろ2バイトはtimezone?)

LONG_STRING
[0C] [4バイト] [データ] stringと同じだが、長さ指定が4バイトになってる。

UNSUPPORTED
[0D] 不明

で、実際の構成は以下みたいです。
まずonMetaDataという文字列が入ります。
そこに続いてMap型が挿入されます。Map型の中身は上記のデータに従います。
たとえばdurationなら
「00 08 64 75 72 61 74 69 6F 6E」 8バイトでdurationという文字列(key)が入り
「00 40 60 74 39 58 10 62 4E」先頭に0x00があるのでNumber型 うしろの8バイトより131.632という数値であることがわかります。

こんな感じでかかれているみたいですね。

機会があったらCuePointとかKeyFramesついても調査しておきたいところですね。
http://www.buraks.com/captionate/helpfile/e05.html
http://ismano.com/media/documentation/flvmdi.html
この2つがkeyframesの参考になるかな?
どうやら先頭に余計なメッセージをいれることで、シーク可能にするみたいですね。

たしかs3って指定した場所からのデータダウンロードをサポートしているので、keyframe情報をきちんといれておけば
s3からflvの先頭をDL、その後必要なrangeのデータをDLして中途再生とかできそうな予感です。

では、metaデータはこのくらいにして、takStreamingの続きをやるとしよう。

2013年1月29日火曜日

Flashによるh.264出力についてのメモ

FlashPlayer11以降でしたか、Flash単体でh.264のデータ出力ができるようになりました。
で、以前webで見つけた。
これを私は重宝しています。
前にもブログに書いたことあったはずです。

で、ですが、このswfプレーヤー、なぜかTakStreamingとの相性がすこぶるわるかったんです。
再生してもうまく動作しなかったり、いろいろと不具合があったわけですが、やっと理由がわかりました。
たぶん、FlashPlayer11以降によるh.264の映像出力全般にいえることだと思います。

1つ目、h.264のmediaSequenceHeaderがキーフレームごとにくる。
mediaSequenceHeaderというのは、h.264やaacのデータの特殊なflvTagです。詳しくは学習がすすんでいないのですが、mediaに関する特別な情報が載っているみたいです。HttpTakStreamingではこのデータを伝搬するために、flhファイルに必要があれば、追記してあります。FlashMediaLiveEncoderで放送した場合や、Flazrをつかってflvデータからライブストリーミングをした場合には、かならず先頭にtimestamp0でやってくるのですが、Flashのh.264放送では、キーフレームごとに送信されるみたいです。

いままでのtakFlazrのプログラムでは、mediaSequenceHeaderはうけとったまま保持していました。これだと、このheaderがはいっている場合にtimestampが0にならず、複合したときに矛盾がでるみたいです。

2つ目、放送をあきらめるタイミングが早すぎる。
TranscodeWriterの中で、ある程度データ転送がない場合に、動作していないと判定して、とめてやり直す処理があります。
このソースの80行目あたりです。
このあきらめる処理、現状の動作では必要ありません。が、いれたままにしてあります。

どうして入っているかというと、ffmpegやxuggleにつないでコンバートさせるとき、コンバートするのをあきらめるタイミングがわからないため、こうなっています。

いままでは、メディアデータの書き込みが1.5秒ない場合は、動作がおかしくなったと判定して、あきらめるようにしていたのですが、Flashからのflvの出力はこの部分が少々あやしくなっていると思ったので、とりいそぎ3秒にあげてみました。

というわけで、メディアデータの取り扱いを見直すことで、また1つ動作が安定したと思います。

2013年1月28日月曜日

p2pを利用したライブストリームの動画をつくって公開してみました。

FlashMediaLiveEncoderを利用してrtmpに配信したデータをrtmfpのp2pを利用したネットワークに流すプログラムがきちんと動作するようになったので、動画を撮ってyoutubeに置いてみました。

動作のおさらいは次のような感じです。
動画は以下
構成は
データサーバーには、Sakuraのvpsを利用
FlashMediaLiveEncoder3.2で配信
Red5のpublisherのデモがrtmpの配信データ確認
PC上でslave.htmlのプログラムを開いて始めにhttpTakStreamingを実行
そのあとでrtmfpを利用したp2pのstreaming混在もためしています。

いいところ
・FlexのプログラムはFactoryクラスからデータを抜き出すだけなので、非常に簡単。
・http通信がベースになっているので、冗長化が非常に簡単。
・rtmfpのネットワーク網を構築することで、可能であればp2pによるデータ通信による補助を行う。
・ネットワーク状態がかわってもシームレスにつながって動作する。

わるいところ
・FlashPlayerにかかる負担が少々大きい。
・いまのところ、globalネットワークでのrtmfpの通信に成功していない
(たぶん、僕のルーターの設定に不備があるんだと思う)

今後やること
・任意のrtmp配信ツールで動作確認できるデモをつくって公開する。
・PC上にあるflvファイルをベースにしたtakStreamingの生成とrtmfpでの共有動作
(動画をどこにもアップロードすることなく他のユーザーと共有できるようにするつもり)
・httpではなくrtmpベースの動作
(httpのダウンロードファイルがうっとおしいのと、timerによるファイル監視動作が良くないのでなんとかする。
もちろんrtmfpの動作時の欠損補完もできるように、また、rtmpの動作補完をhttpに背負わせることも可能にする。)
・crcによる動画データの整合性確認処理の追加
(現状の動作では、rtmfpとhttpのソース動画が一致していることを前提にして動作していますので、他の動画データが混入したらたぶんおかしくなる。)

あと、できたら手伝ってくださる方、募集したいですね。

興味ある方おられましたら、このブログのコメントなり、twitterなりでコンタクトよろしくおねがいします。

2013年1月27日日曜日

segment分割のやり方について

httpTakStreamingで利用しているsegment分割ですが、ちょっと動作をかえようと思っています。

現在の動作では、設定秒数以上で、動画のキーフレームがきた時点で分割するように調整してあります。
これを、キーフレームでなくても、指定時間以上経ったら分割する方向ですすめようと思います。

現状の動作では、たまにsegmentの長さが長くなっちゃいます。
上図でも1.0程度のセグメントもあれば、2秒超えているものもあります。
実験ではカメラとの相性もありますが、ひどいときには、4秒近いセグメントになることもありました。
サーバー内部での設定では、durationを1秒にしてあるので、4秒近いセグメントができているということは、4秒間動画のkeyframeがこなかったということになります。
このままでは、追いつかなくなった場合に、動画再生がとまってしまうという不具合が発生しまうので、flmデータの生成時に、keyFrameがこなくても指定してある以上の動画フレームを取得した場合に分割するように調整してみたいとおもいます。

さて、なぜkeyFrameが先頭にくるようにしているかというと、HttpLiveStreamingがベースだからです。
httpLiveStreamingの場合、先頭にキーフレームがこない場合は、次のようになるみたいです。(デバイス依存なので、確実にそうなるわけではないといっておきます。)

1:動画データをうけとった場合、映像が再生可能になるまで音声だけ流れます。
2:その後、映像が再生できるようになったら、動画として再生されます。

という動作になることがあります。
単に映像を見せるだけのサービスならまぁいいんですが、ここにお金が絡んでくると映像がみれないのに、お金を取られたという話が入ってきちゃうんですよね。
というわけで、確実に動画として始めから再生させるために、いろいろ調べるうちに、keyFrameを強制的に先頭になるようにするというのが、デフォルトになっていました。

さて、今回のHttpTakStreamingですが、flvデータの根幹的な部分の解釈を行う、BaseStream.asの中で、動画のkeyFrameを取得するまで、すべてのデータを捨てるようにしてあります。
という動作をするようにしてあるので、問題のあるデータがあったとしても、まぁ大丈夫な動作になるであろうということが期待できます。


で、これを書いている間にFlazrのプログラムをちょっと書き換えてみました。
で、実際にためしてみたところ次のようになりました。

ほぼすべてのデータが1.055秒のセグメントになっていますね。
動作もBuffer.length=2にしたときとほぼ同じ動作になった感じになりました。

めでたしめでたしといったところ。

2013年1月25日金曜日

p2pの動作をいろいろと更新しました。

前回、p2pの動作が暴走する原因がわかったので、修正したわけですが
またいろいろと更新しました。

できあがったプレーヤーは次のようなもの。
コード:https://github.com/taktod/TakStreaming2/tree/flashCode3
デモ1:http://49.212.39.17/betaplayer/http.html
デモ2:http://49.212.39.17/betaplayer/master.html
デモ3:http://49.212.39.17/betaplayer/slave.html

デモ1はHttp Segmentで動作するストリーミング、やっていることはiOSのhttpLiveStreamingやAdobeが出しているhttpDynamicStreamingと同じですが、メディアデータ等は独自実装です。

デモ2はデモ1と同じHttp経由の動作ですが、p2pで接続している相手がいる場合にp2p経由でデータの伝搬を行います。

デモ3はp2pで接続してデモ2からデータをうけとり再生する動作です。

実行した修正内容の主なものは次のような感じです。

1:rtmfpのネットワークを利用する場合、登録するだけで、自動的にnetGroupにログインするようにした。
これにより、Flashのアクセス確認ダイアログが、視聴開始する前に発生するようになりました。
(ユーザビリティ向上)

2:ネットストリームの情報が乗っている部分で、データソースがp2pかhttpかわかるようにしました。
これは単なる確認用。p2pネットワークの調子がわるいと、p2pとhttpをいったりきたりします。

(開発用)


3:p2pSourceStreamでping通信用につかっていた、netStreamの生成動作を始めにつくったそれようのnetStreamを使い回す形にした。
ActionScriptでオブジェクトを無駄に作成→削除を繰り返すとGCが走るまで大量にオブジェクトが生成されるみたいで、CPUを食うようになるみたいです。
https://github.com/taktod/TakStreaming2/commit/678d8f2a5c71e06e0c70e0a6452a9c5f9481efc9
(PC負荷低減)

4:放送側で放送再開したり、とまったりした場合の動作不良の改善。
flfファイルのindexがリセットされたときの計算方法がまちがっていたみたいです。
おかげで余計なDLが混入したりする懸念があった模様。
(動作安定性向上 & PC負荷軽減)

5:1つのプレーヤーのみでtree構造のp2pノードクラスタができあがるようにした。
1桁のnodeでしかつかっていないので、実際にはうまくいかないことがあるかもしれませんが、ノード構成ができるようにしてみました。

(サーバー帯域節約)


と、これだけ作業してみました。


デモ3ができたことでとりあえずやりたかったことはほぼできたことになります。
やりたかったことというのは
1:ちいさなセグメントの集合でライブ再生すること
2:セグメントが一致するなら、別のネットワークから取得しても同じデータになること。
3:そして、ネットワークがかわったりしても、映像が切れずにシームレスにつながること。

とりあえず満たせたかな・・・と。

あとは、はやいところ、誰でもrtmpの配信ツールつかって放送テストできるデモ公開したいですね。

ではでは

p2p動作が暴走していた原因がわかりました。

つくっていた動作のrtmfpの動作が暴走した原因がわかりました。

com.ttProject.tak.data.RtmfpConnectionのonNetStatusEventの部分で
NetConnection.Connect.Close
NetConnection.Connect.NetworkChanged
のイベント時に強制再接続していたのが、原因だったみたいです。

https://github.com/taktod/TakStreaming2/blob/cbc1b2e2e8eea24735bafbf1c7460b82867eeaad/src/com/ttProject/tak/data/RtmfpConnection.as
これの85行目あたり

問題が発生した場合(データ転送がおくれているなど)のときに、再接続を実行するんですが、前の動作がこの処理のおかげで暴走したみたいですね。

まだデモプレーヤーの更新はしていませんが、ソースコードだけ修正してあります。

あとはhttp動作の安定化をすすめて、cumulusでrtmfpがうまくいかないっぽいので原因さぐって・・・

結構やることてんこもりですw

2013年1月22日火曜日

timerを極力排除した動作のデモも公開してみました。

前回の記事でかいた、timerEventを排除した方が動作いいんじゃない?というやつのデモを作成したので公開しました。

動作は前のとあんまりかわらない。
大量にwindowを開いたりして、負荷をかけたらちょっとは違うか?というのはあるもののどうなんだろうか。

もともとeventListenerにくっつけたのが妙にのこっている風だったのを嫌ってやった変更ですが・・・

前のプレーヤー
http://49.212.39.17/betaplayer/master.html
http://49.212.39.17/betaplayer/slave.html

新しいプレーヤー
http://49.212.39.17/betaplayer2/master.html
http://49.212.39.17/betaplayer2/slave.html

ちなみに、swf形式のデータを外部で読み込んで利用する動作をwonderflでつくってみました。
親 http://wonderfl.net/c/l9v8
子 http://wonderfl.net/c/333s
どうやら、p2pのアドレスにrtmfp:を指定しているからかもしれませんが、ドメインが違うと同じp2pアクセスと認めてくれないっぽいですね。
前のプレーヤーと新しいプレーヤーでは、通信できたんですが、wonderfl上のプレーヤーでは通信できませんでした。

globalのrtmfpサーバーの場合はまた話がちがってくるのかもしれませんね。

ま、いいや。

2013年1月21日月曜日

p2pのライブデータshare動作からtimerEventを極力排除してみました。

p2pの動作ですが、なかなかいい感じにならなかったので、chromeのタスクマネージャーをみていました。

見ていると、CPUがどんどん食われていく感じでした。

前々から、EventListenerでくっつけている動作があやしい気がしていたので、ちょっといじってみました。

timerをつかった一定期間ごとの動作が必要なのは、主に以下
・httpStreamの新しいデータ取得まわり。
・p2pSupplyStreamの生死判定用ping処理
・p2pSourceStreamの生死判定用ping処理
・rtmfpConnectionの接続相手探しの状態管理処理
・dataManagerのstreamのデータ監視処理
この5つがtimerが必要なところでした。

一番はじめにつくったのは、それぞれのクラスの中でtimerオブジェクトをつくって動作させるというものでした。
これが結構重くて、使い物になりませんでした。
プレーヤーの再生もやっていたらだんだんと悪くなっていくという・・・

そこで思ったのがtimerをいっぱいつくらなくても1つのタイマーを使い回してそれぞれのクラスでaddEventListenerをすればいいじゃないかというもの。
この動作に変えてみたところ、まぁまぁまともな動作をするようになったので、いいかなと思っていたんですが、今日タスクマネージャーをみつつ動作を確認していたところ、どうやらp2pの切断等が発生したときに、オブジェクトが残っているみたいで、CPUの利用量がじわじわあがっていく感じでした。

で、先ほどdataManagerのtimerイベントから、他のstreamのデータをキックする形にしてみたところ、いい感じの動作になりました。

うーん、やっぱりeventDispatcher関連は好きになれないねぇ・・・

2013年1月20日日曜日

p2pベースで動作するプレーヤーをとりあえず公開してみました。

とりあえず、ある程度動作を向上させたので公開してみます。
ここまでくるのに3年くらいかかったわ・・・

■概要
ソースコード:https://github.com/taktod/TakStreaming2/tree/flashCode3
rtmfpの親:http://49.212.39.17/betaplayer/master.html
rtmfpの子:http://49.212.39.17/betaplayer/slave.html

構成的にはこんな感じ

いまのところ家のLAN内でしか動作確認していないので、適当なときに有志募っていつか動作確認したいところ。

ipMulticastMemberUpdatesEnabledを有効にして、ローカルネットワークでのみp2pが成立するようになっています。

■確認の仕方。
1:master用ページslave用ページを開きます。
2:それぞれplayをクリックしてplay実行します。
3:ブラウザのファイルダウンロード状況を確認して、httpによるflfやflmのダウンロードがなくなっているのに再生が続くようになったら、p2p経由でデータの共有がうまくいっていることになります。


■見所
1:簡単に扱えるようにしてある。
導入しやすいように、プログラムは極力簡単に扱えるようにしてあります。
参考:master.mxml
Factoryクラスにsource(データ元)とsupply(提供先:なくてもいい)を設定してから
netStreamとvideoを抜き出して利用するだけ。

2:安定化
segmentのダウンロードが実行できれば問題なく動作するようにつくってあります。
複数のデータソースを共存できるように設計してありますので、基本http経由で、可能ならばrtmfpでデータを共有するというような形で動作できます。
よってサーバーと回線のコストを極力落とすことが可能です。

3:既存のrtmpとの親和性
flazrを利用しrtmpサーバーから放送データを取得したり、red5のアプリケーションとして導入できるようになっています。

■いまのところわかっている問題
 致命的なもの
・放送が停止すると、最終パケットがループで繰り返し放送される。
・slaveのみでのネットワーク構築動作未実装(自動master選出処理)
・タイミングによっては、とまったりする?

・rtmpベースやflvファイルベースの動作が未実装
・回線の弱いクライアント処理の未実装


とこんな感じのプログラムに仕上がってきました。
まだまだ突っ込みどころは多いので、どんどん改良していかないとねw

2013年1月14日月曜日

とりあえずなp2pができた。

まだまだ、いろいろと問題があるけど、とりあえずな動作はできたのでブログに書いときます。
構成はこんな感じ
サーバー内部
[flazrでlocalhostのFMSにrtype-finalの動画をliveでpublish]
[別のFlazrでTakStreaming化(http用)]
[apache経由でデータを提供]
クライアント側(送信側)
[httpStreamとしてデータをDL]
[BaseStreamにデータを渡すことで自身のプレーヤー上で再生]
[rtmfpのsupplyStreamにデータを転送]
クライアント側(受信側)
[rtmfpのsourceStreamでデータをDL]
[BaseStreamにデータを渡すことで自身のプレーヤー上で再生]


左がhttpStreamで動作しているmaster接続、自分ところで再生したあとに、rtmfpのSupplyStreamに受け流してます。
 右がrtmfpのSourceStreamで動作しているslave接続
いまのところ4ウィンドウくらい開くとPCが悲鳴をあげるっぽいです。

いまのところの問題点は以下
致命的なもの
・p2pネットワークが切断したときに、暴走する。(ない接続にデータを送ろうとしてるっぽい。)
・500秒ほど見続けていると、非常に重くなってくる(どこかでデータ解放わすれてる?)


まずいもの
・p2p受けて側にflmデータcacheがないので、たまにおいつく(http側では、2データ先行してDLすることでおいつかないようにしてある。)
→netStream.bufferTimeでコントロールできるので、そちらに任せることにする。

やっときたいもの
・httpとrtmfpを併用する動作未実装
・回線負荷低減処置が未実装
・rtmpをデータソースとする動作
・生flvをデータソースとする動作
その他もろもろ。

さて、もうちょっと開発をすすめますかね^-^

2013年1月12日土曜日

Flashが急に再生されなくなった。対処法メモ

iMac(Moutain Lion) + FlashBuilder4で開発しています。
でコンパイル後の出力確認はChromeでやっていたわけですが

急にコンパイルしたあとに動作しなくなりました。
Flashは読み込まれているみたいなんですが、真っ白で動作してません。

どうやらgoogle独自のchrome用のflashがわるいみたいです。
なので、chrome://pluginsにアクセスして設定を書き換えます。
before
after

で、実行すると動作するようになりました。

PPAPI邪魔っす。

まぁ、あとでPPAPIでも動作するようにしないとリリースできないから、調整しないとなぁと思ってはいますけどね。

追記:一応気になったのでもうちょっと調べてみたんですが、http://localhost/~[user]/player.swfでアクセスしたところPPAPIのFlashでも動作できました。なんかのサンドボックスが問題になる感じですかね。
僕的には、気にせずにほっとけばいいかなといった感じです。

Flashで流しているデータのコーデック情報を調べる

FlashのnetStreamに流れているデータのコーデックを調べる術が一応あるっぽいですが、
公式のドキュメントをひっくり返してもないみたいです。

信用してもいい情報なんでしょうか・・・
audioコーデックはこんな感じ
 videoコーデックも同じような感じ
uintで定義されているので、コーデックID番号がはいっているみたいですね。

10:AAC 7:AVC(h.264)みたいな感じ?
実際に実装してみた。

audioCodec:2(mp3だったっけ?) videoCodec:7(AVC)
ちゃんととれてます。

2013年1月3日木曜日

動画再生させてみる。

前回の記事の続きです。

動画再生をやらせてみます。
動画再生には、2つ方法があるらしくMPMoviePlayerControllerを使うやり方と
AVPlayerを使う方法の2つがあるみたいです。

まだ理解が進んでいないので、とりあえずMPMoviePlayerControllerをつかって動作させてみます。
まずはライブラリの取り込みが必要です。
Frameworkの項目にデータを追加するのですが、きちんとした手順でやらないとだめみたいです。
ダメな例
一番はじめにやってみたのは、frameworkをそのまま追加するやり方
この方法だとリンクまわりがきちんと設定できず、コンパイルエラーになってしまいました。

で、きちんと動く正しいと思われるやり方
1:アプリケーションのプロパティーを開く。
2:Build PhasesのLink Binary With Librariesを選択する。
3:+をクリックして、iOS用のMdiaPlayer.frameworkを選択する。
すると追加ができます。

さて、ViewControllerの部分で、動画の表示をさせたいので、プログラミングをすすめていきます。
まず、ViewController.hの部分でライブラリをimportします。
続いてViewController.mに記述を追加していきます。
1:controllerのpropertyとしてMPMoviePlayerControllerを定義しておく。(local変数として定義するとコントロールできなくなる。)

2:プログラムを記述する。

- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
    NSURL* url = [NSURL URLWithString:@"http://49.212.39.17/mario/mario.m3u8"];
    self.videoPlayer = [[MPMoviePlayerController alloc] initWithContentURL:url];
    self.videoPlayer.view.frame = CGRectMake(0, 0, 320, 240);
    [self.videoPlayer prepareToPlay];
    [self.view addSubview:self.videoPlayer.view];

    UILabel* label = [[UILabel alloc] init];
    label.text = @"aiueo";
    [label sizeToFit];
    [self.view addSubview:label];
}

urlで適当なhttpLiveStreamingのデータを指定
で、それを利用して、MPMoviePlayerControllerを作成。
viewのframeのところに適当なサイズを指定して、動作するようにした後に
videoPlayerのprepareToPlayメソッドを呼び出して準備させる。
viewに結びつけてデータを表示するようにする。
で完成


コメントがながれるようにしたいので、labelを上に載せてみた。問題なさそうですね。

あとはurlスキーム対応やったり、webSocketあたりでリアルタイムでコメント追記できるようにやったり、コメントをtwitterに投稿できるようにやったり、srtファイルを字幕として取り込めるようにやったりすれば、いい感じのアプリがつくれないこともなさそう。

labelを追加してみる。

前回の記事でつくったプロジェクトで、まず適当な文字列を追加してみます。

表示の部分はViewControllerで実行しているので、まずViewController.mを開きます。
今回は適当な文字列を表示したいので、viewDidLoadの関数内で、UILabelを定義して、追加することにします。
というわけでコード追加

- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
    UILabel* label = [[UILabel alloc] init];
    label.text = @"aiueo";
    label.frame = CGRectMake(0, 0, 100, 100);
    [self.view addSubview:label];
}

これでaiueoというデータが表示されるようになります。
余談だと今回はaiueoという文字列の設定とframeサイズの設定をおこなっています。
デフォルトでは、フレームサイズが0になるみたいですね。
今回はrectMakeで表示領域を指定しましたが、labelに定義されているメソッドのsizeToFitを使うこともできます。
- (void)viewDidLoad
{
    [super viewDidLoad];
 // Do any additional setup after loading the view, typically from a nib.
    UILabel* label = [[UILabel alloc] init];
    label.text = @"aiueo";
    [label sizeToFit];
    [self.view addSubview:label];
}

他にもセンタリング用のメソッドがあったりといろいろ便利なものがあるみたいですね。
この表示周りは、動画を再生したりするときにも利用できるので、これからきちっと学習しておきたいところ・・・

objective-Cやってみる。

以前からiPhone用のプログラム作成には、興味ありました。
でも、年間99ドル出すのがなんかおしかったので、jqmobiとかsencha touchとかhtml5で満足していたのですが、iOS6がでてもvideoの非全画面動作がでてこないので、年明けにobjective-Cに手をだすことにしました。

で、そのやったことメモ
1:xcode 4.5.2をapple storeから入手する。
2:iOSSDKも入手する。
どちらもダウンロードしてくればOKなので割愛

まずは起動する。

Create a new Xcode projectを選択する。
するとこんな画面がでてくる。
左側でiOS Applicationを選択。
右のアイコン一覧からSingle View Applicationを選択。
で、Nextをクリックして進む。
すると情報記入のところにたどり着くので適当な情報を載せる。
保存先を尋ねてくるのでdesktopにでもつくっておく。
Createをクリックすると作成完了。
するとプロジェクトが出来上がるのでさっそく左上のRunをクリックして起動してみる。
するとiOSのシミュレーターが立ち上がって動作が確認できる。
これでとりあえずの動作確認はOKということになります。