概要
http://qiita.com/taktod/items/0d87e511388fde7ffe2d
これの続き2日目
建設地はこちら
https://github.com/taktod/ttLibGo
使い方は
$ go get github.com/taktod/ttLibGo
で取得できて
func TestAvcodecVideoDecode(t *testing.T) {
{
targetCodec := "h264"
t.Log(targetCodec)
in, err := os.Open(os.Getenv("HOME") + "/tools/data/source/test.h264.aac.mkv")
if err != nil {
panic(err)
}
var count uint32
var reader ttLibGo.Reader
if !reader.Init("mkv") {
t.Errorf("reader初期化失敗")
}
defer reader.Close()
var decoder ttLibGoFfmpeg.AvcodecDecoder
defer decoder.Close()
for {
buffer := make([]byte, 65536)
length, err := in.Read(buffer)
if err != nil {
panic(err)
}
if !reader.ReadFrame(
buffer,
uint64(length),
func(frame *ttLibGo.Frame) bool {
if frame.CodecType == targetCodec {
decoder.InitVideo(targetCodec, frame.Width, frame.Height)
return decoder.Decode(
frame,
func(frame *ttLibGo.Frame) bool {
count++
return true
})
}
return true
}) {
t.Errorf("コンテナ読み込み失敗")
return
}
if length < 65536 {
break
}
}
if count == 0 {
t.Errorf("デコードされませんでした")
return
}
t.Logf("デコードされた数:%d", count)
}
}
こんな感じでフレームを取得して変換できます。
今日はひたすら実装してました。
注意:とりあえず書く動作のメモ書き書いておきますが、かならずしも正しいとは限りませんので、鵜呑みにしないでください。
ttLibGo
こちらは自分で全部書いた動作
Reader
コンテナ読み込み動作
flv mpegts mp4 matroska webmの動作書いてあります。
ライブストリーミングで利用することを前提にしてます
Writer
コンテナ書き出し動作
こっちもflv mpegts mp4 matroska webmの書き出し書いてあります。
hlsのための書き出しを実施したり、mp4データを吐き出してh264 / aacのデータをMediaSource extensionに流してvideoタグで動画を再生したりしてます。
AudioResampler
signed int16で実装されているpcmS16とsigned float32で実装されているpcmF32の相互変換するリサンプラ
ImageResampler
bgrとyuvの相互変換を実施するリサンプラ
ImageResizeResampler
yuvイメージデータの拡大縮小を実施するリサンプラ
3つとも質はよくないので、普通にswscaleResamplerとかswresampleResamplerとか使う方がいいと自分でも思います。
ttLibGoFaac
faacEncoder
faacを使ってencodeするaacのencoder
とりあえずLowプロファイルで96kbpsで動作させれば、どこでも使えるaacができると思います。
ttLibGoFdkaac
fdkaacEncoder
なかなか質の良いaacのencoderらしいです。
利用できるプロファイルもたくさんあったはず。
とりあえずステレオとモノラルでそれっぽいaacができたら問題ないので・・・というコード書いてあります。
"AOT_AAC_LC"をプロファイルに設定して、やっぱりLowプロファイルでエンコードしておけば、間違いないかなと思います。
こちらは、SetBitrate関数を実装してあるので、中途でbitrateを変えたい場合は変更できるようにしてます。
ttLibGoFfmpeg
avcodecDecoder
ほぼなんでもエンコード・デコードできるffmpegのデコード動作を借りてデコードする動作
h264 flv1 vp6、aac mp3 nellymoserとrtmpの処理するのにとってもお世話になってます。
swresampleResampler
pcmのデータをいろいろ変換できるリサンプラ
ポテンシャルは高いのですが、まだ自分はそこまでお世話になってないリサンプラです。
swscaleResampler
映像データをいろいろ変換できるリサンプラ
僕の中でサーバーサイドで画像をいじるなら使えるんじゃないかな?と思ってるリサンプラ
少なくとも自分で書いたImageResizeResamplerよりは使えるはず。
ttLibGoJpeg
JpegDecoder
libjpegをつかって動作するjpegのdecoder
まぁ、あまり使わない
あとyuv422やyuv444になるjpegデータは扱えません。
そのようなデータはffmpegのavcodecDecoderで処理してます。
JpegEncoder
こっちは非常に有用
とにかく画像を保存したかったら、jpegにencodeしてframeからGetBinaryBufferを実施して[]byteデータをとってしまえば、あとはファイルに書き出すだけ
楽チン
ただ、コードを書いて実行すると大量の画像ができるのが玉に瑕。
ttLibGoMp3lame
Mp3lameDecoder
有名なmp3lameをつかって動作するmp3のデコーダー
ライセンス的にはこっちはGPLv3、エンコーダーだけだとLGPLv3
まぁ、v2の方かもしれない。
つかってもいいですが、avcodecで十分
なお、golangには実装してませんが、appleのAudioConverterやWindowsのMediaFoundationを使ってデコードするという選択肢もあります。
いずれにせよ、積極的にmp3lameでデコードする・・・ことはないんじゃないかな
Mp3lameEncoder
有名なmp3lameをつかって動作するmp3エンコーダー
mp3作りたかったら使う。
できたmp3のbinaryデータをそのまま順番にファイルに書き出せばmp3ファイルの一丁あがりとなります。
jpegと同じく単に音がどうなったか確認したいときに便利
ttLibGoOpenh264
Openh264Decoder
ciscoが出してくれたh264実装
ciscoが提供してるライブラリを直接DLして使わせればh264のパテントも対処してくれるという太っ腹なやつ。
あとsvcという規格のデータも積極的に対応していると思ってます。
bframe入りのh264が扱えなかったりと足りない部分もありますが、svcを使ったデータでffmpegのavcodecがデコードできなかったデータがデコードできたりということもありました。
まぁ、細かい動作したかったら今回のgoの実装では力不足なので、cでちゃんと書き直す必要があります。
Openh264Encoder
こちらはh264にencodeする実装
以前svcで複数の解像度のデータを同時に出力するとかであそんだことがあります。
まぁ、decoderと同じく、そういうことしたい場合は、このgoの実装では無理なので、それようにプログラムを書き直す必要があります。
なお、僕の実装として
- 非常に細かい設定がmapを利用することで定義可能になっている
- 画像をエンコードする前に該当画像をkeyFrameとして強制的に変換することが可能になっている
- keyFrame間隔を任意のタイミングで変更できる。GOPが変更可能といった方がいいかもしれません。
- RCモードの変更が可能(bitrate重視 -> quality重視)になっている
というのがあります。
ttLibGoOpus
OpusDecoder
低遅延で高音質を実現する。すばらしい音声コーデック
ちょっと面白いコーデックでデコーダー側でサンプルレートとチャンネル数を指定して
どういうデータを出力させるか決めることができます。
48kHz 2chでエンコードしたけど、端末の処理能力が低いので
24kHz 1chでデコードして再生させるとかができます。
あと44.1kHzとか設定できません。
OpusEncoder
こっちはそのopusのencoder
こっちが面白いのは処理単位のサンプル数を指定できるところですね。
サンプル数を小さくするとそれだけリアルタイムに処理できる能力があることになります。
普通は48kHzで、処理単位480でやるイメージがあります。
こちらにも特殊処理があり
- SetBitrateで出力のbitrateを途中で変更する
- SetComplexityで、内部の設定を変更できる
ようになってます。
ttLibGoSoundtouch
SoundtouchResampler
soundtouchという音声の処理ライブラリを利用したリサンプラ
これを利用すると音の高さはそのままで早送りしたり
動作速度はそのままで音のpitchだけ上げ下げしたりとなかなか面白いことができます。
ttLibGoSpeex
SpeexDecoder
古いVoIPの処理でよく使われてたイメージのあるspeex
公式でもspeexよりopus使いましょうっていわれるようなコーデックです。
中身が3つのbandから構成されています。
narrow - wide - superwide
このコーデックで面白いところは、3つのbandから構成される32kHzの音声データのうち、narrowbandのところだけでもなんとか手に入れることができたら、(音質は悪くなりますし8kHzになりますが)ちゃんと音にデコードできるところが面白いです。
なお、モノラルのみ対応です。
ステレオのspeexも存在しますが、そちらはavcodecDecoderでデコードしてほしいところ
SpeexEncoder
そのspeexのencoder
ttLibGoSpeexdsp
SpeexdspResampler
そのspeexのおまけ実装にある音声のリサンプラ動作
他にエコーキャンセルとかもありますね。
これはお世話になりました。ライセンスもちょうどいいですからね。
ttLibGoTheora
TheoraDecoder
theoraによるdecoder実装
これはどちらかというとここで使うより、emscriptenでjavascript化してiOSのsafariとかで動作させると面白い。
まぁ、もうすぐiOSのsafariでwebrtc実装はいるので、そうなったらいらないか
TheoraEncoder
そのtheoraによるencode実装
これでencodeしてやって、できたフレームをwebsocketでiOSに送信、iOS側でdecodeしてcanvasに描画
するとめちゃくちゃ低遅延なライブ配信できたりします。
音声はopusかspeexでやれば良い感じにできました。
ttLibGoVorbis
VorbisDecoder
昔のwebmの音声をになってたやつ。
初めに送らないといけないデータが非常に大きいので、あまり好きではない。
まぁ、theoraもそういう点では同じだけど
VorbisEncoder
そのvorbisのencoder実装
まぁ、初期化実装にsampleRateとチャンネル数しかない時点で察してください状態です。
ttLibGoX264
X264Encoder
まぁ有名なやつですね。
このx264にはparam_parseという動作が実装されていて、文字列を割り当てることで任意のパラメーターの設定を更新することができるようになってます。
それに影響されて、openh264等の処理に同じようなものを書いてみました。
ttLibGoX265
X265Encoder
こっちは最新のやつですね。
ただライセンスやパテントがアレなんで流行るのかな・・・
# まとめ
という感じで今日は書きまくってました。
明日はnode-gypの実装でも書きなおしておこうかな。