読者です 読者をやめる 読者になる 読者になる

cvl-robot's diary

研究ノート メモメモ https://github.com/dotchang/

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の変換等が不要になって、倍ぐらい早くなります。