OpenCV - RTSP流损坏的宏块

时间:2015-02-02 11:39:02

标签: android c++ opencv video rtsp

我有一个Android程序,通过RTSP将视频流式传输到Wowza媒体服务器,我的OpenCV程序然后获取此RTSP源进行处理。

问题是视频Feed几乎立即被破坏,并输出以下错误:

[h264 @ 0x1f05320] Invalid level prefix
[h264 @ 0x1f05320] error while decoding MB 5 5
[h264 @ 0x1dfb940] Invalid level prefix
[h264 @ 0x1dfb940] error while decoding MB 6 1
[h264 @ 0x1dfbde0] corrupted macroblock 7 5 (total_coeff=-1)
[h264 @ 0x1dfbde0] error while decoding MB 7 5
[h264 @ 0x1dfafe0] corrupted macroblock 7 6 (total_coeff=-1)
 ...

我尝试在网址的末尾添加?tcp,这会删除损坏的框架但会留下大量延迟,导致Feed无用(这是实时应用程序)。

我有一个不同的程序用于测试流,RTSP提要在该程序中运行正常(也使用OpenCV),只有当我尝试在单独的程序中使用相同的feed来计算ORB功能时饲料被腐蚀得无法辨认。我正在收到这样的视频:

  cv::Mat gray;
  CvCapture* img_scene = cvCaptureFromFile("rtsp://193.61.148.73:1935/serg/android_test"); //?tcp
  while(1) { //Create infinte loop for live streaming
    cv::Mat image = cvQueryFrame(img_scene);
    cvtColor(image, gray, CV_BGR2GRAY);

该程序还使用ffmeg选项在tcp中正常流式传输。

编辑:

捕获线程:

Mat captureThread() {
  if(captureOpen == false){
    img_scene = cvCaptureFromFile("rtsp://193.61.148.73:1935/serg/android_test?tcp");
  }
  while(1) {
    image = cvQueryFrame(img_scene);
    cvtColor(image, gray, CV_BGR2GRAY);
    return gray;
  }

}

处理线程:

Mat processingThread(Mat gray, Mat img_object) {
  //calculate keypoint and descriptors
  //match keypoints and descriptors
  //draw good matches
  //draw homography
    return imgMatches;
}

主:

int main(int argc, char *argv[]) {
  img_object = imread( argv[1], CV_LOAD_IMAGE_GRAYSCALE );
  while(1) {
    thread t1(captureThread); 
    t1.join();
    captureOpen = true;
    thread t2(processingThread, gray, img_object);
    t2.join();
    imshow("Output", imgMatches);
    key = cvWaitKey(5);
    if (char(key) == 27) {
      break;
    }  
  }
  return 0;
}

2 个答案:

答案 0 :(得分:1)

尝试使用单独的线程进行捕获和处理。我之前也遇到过这个问题,一旦我将它们分成两个线程,它就会消失。 (我直接使用ffmpeg,但它应该类似)。您可以通过在您提到的opencv程序中使用sleep()函数来实现这种情况。您应该立即看到腐败开始发生。

因此,每当消费网络订阅源出现延迟时,这种类型的损坏似乎要频繁得多。此外,如果你的cpu太慢而无法处理流,它也会发生。如果直接使用ffmpeg,则可以丢弃那些损坏的帧,因为它们会影响结果,特别是在进行运动检测时。

修改

好的,这只是伪代码,但通常看起来应该是这样。

bool imgready=false;
Mat sharedmat;
mutex mtx;

Mat captureThread() {
  if(captureOpen == false){
    img_scene = cvCaptureFromFile("rtsp://193.61.148.73:1935/serg/android_test?tcp");
  }
  while(1) {

    mtx.lock();
    sharedmat = cvQueryFrame(img_scene);
    imgready=true;
    mtx.unlock();

  }

}

void processFunction(Mat im)
{
  //do whatever
}

void processingThread() {
  while(1)
  {
    if(imgready)
    {
      mtx.lock();
      Mat localmat=sharedmat.clone();
      processFunction(localmat);
      imgready=false;

      mtx.unlock();
    }else
      sleep(1000);//sleep 1 millisecond


  }
}


int main(int argc, char *argv[]) {

  thread t1(captureThread);
  thread t2(processingThread);

  t1.join();
  t2.join();

  return 0;
}

答案 1 :(得分:0)

事实证明,由于findHomography内的一个昂贵的函数调用,导致视频输入速度变慢的原因非常严重:

Mat H = findHomography( obj, scene, CV_RANSAC, 3, mask );

我已将CV_RANSAC参数更改为0,因此该行现在如下所示:

Mat H = findHomography(obj,scene,0,0,mask);

N.B。第四个参数也更改为0,因为它是使用CV_RANSAC时的阈值,更多信息可以在文档here中找到。

对于其他任何发现这一点的人也要注意Zaw Lin的答案,因为它也有助于消除视频输入中的腐败问题。