ofxHttpを使って、WindowsでMJpegの動画ストリーミングサーバーを作る(その2)libjpeg-turboを使って高速化
OpenFrameworksとても便利なんですけれど、画像処理をするときはOpenCVネイティブに書きたいことがよくあるため、わざわざofImageやofPixelsやofBufferなどを使いたいとは思いません。ofHTTPのofIPVideoServerも画像の受け渡しが基本的にOpenFrameworks用のコンテナなので、便利ですけど、不便です。しかも、ソースコードを追って読んでいくと、ToDoとしてlibjpeg-turboによる高速化があげられています。じゃあ、これを実装してしまいましょう(乱暴な方法で)。
server->send(img.getPixelsRef());
の代わりに、
cv::imencode(".jpg",mat,buff,param);
server->send( (char*)buff.data(), buff.size() );
のように自前でエンコードしたJpegのバッファを直渡しできるようにします。
1.OpenCV3.0アルファにlibjpeg-turboを組み込む
openCVを自前でソースからビルドしなおす必要があります。
・BUILD_JPEGのチェックを外す
・WITH_JPEGのチェックは入れたまま
・ADDENTRYボタンで、JPEG_LIBRARY JPEG_INCLUDE_DIRを指定する
JPEG_LIBRARY FILEPATH C:\libjpeg-turbo\lib\turbojpeg-static.lib
JPEG_INCLUDE_DIR PATH C:\libjpeg-turbo\include
Generateとして普通にビルド。
2.ofHTTPの改造
BasicIPVideoServer.hに宣言を追加
void send(ofPixels& pix);
void send(char* buf, unsigned int bufsize);
BasicIPVideoServer.cppに実装を追加
void BasicIPVideoServer::send(char* buf, unsigned int bufsize)
{
_ipVideoRoute->send(buf, bufsize);
}
IPVideoRoute.hに宣言を追加
void send(ofPixels& pix);
void send(char* buf, unsigned int bufsize);
IPVideoRoute.cppに実装を追加
void IPVideoRoute::send(char* buf, unsigned int bufsize)
{
if(bufsize)
{
unsigned long long timestamp = ofGetElapsedTimeMillis();ofBuffer compressedPixels;
// TODO: turbo jpeg an option here?
ofScopedLock lock(_mutex);ConnectionsIter iter = _connections.begin();
IPVideoFrameSettings settings;
compressedPixels.append(buf, bufsize);
IPVideoFrame::SharedPtr frame = IPVideoFrame::makeShared(settings, timestamp, compressedPixels);while(iter != _connections.end())
{
if(*iter)
{
(*iter)->push(frame);
}
else
{
ofLogError("IPVideoRoute::send") << "Found a NULL IPVideoRouteHandler*. This should not happen.";
}
++iter;
}
} else {
ofLogError("ofxIpVideoServerRoute::pushFrame") << "Pushing unallocated pixels.";
}
}
受け渡しともOpenCVにするなら、BGR2RGBの変換等が不要になって、倍ぐらい早くなります。