opencv读取网络摄像头的rtsp流时发生断流现象,以及该问题的解决

最近在使用python版的opencv调用网络摄像头做人脸识别时遇到了一些问题,命令行报错导致rtsp断流。

报错如下:

[h264 @ 0x7fd990026040] left block unavailable for requested intra4x4 mode -1
[h264 @ 0x7fd990026040] error while decoding MB 0 18, bytestream 269

1.开始的想法

代码中的表现为程序运行一段时间后,程序报了以上的错。百度这个错误后,了解到FFMPEGlib对rtsp的H264格式不支持。所以处理方式应该写两个不同的线程,一个接收每一帧图像,另一个线程处理图像。于是学习了别人的方法构造了一个队列,使用两个线程处理程序

链接如下:
[双线程处理rtsp流](https://blog.youkuaiyun.com/darkeyers/article/details/84865363)

2.使用双线程也行不通以及最终解决方法

改成双线程后,运行一段时间后还是报这个错,除了这个错误,还遇到了这个错误

cv2.error: OpenCV(3.4.3) /io/opencv/modules/imgproc/src/resize.cpp:4044: error: (-215:Assertion failed) !ssize.empty() in function 'resize'

看到这个错误,我知道肯定是帧没获取到,于是打断点debug。发现运行一段时间之后,capture.read()返回的ret是False,frame是none。原来是断流了,这可咋整,只能在接收帧图信息时重新建立rtsp流了

def Receive():
    print("start Reveive")
    cap = cv2.VideoCapture(rtsp)
    ret, frame = cap.read()
    q.put(frame)
    while ret:
        ret, frame = cap.read()
        if not(ret): #若没有帧返回,则重新刷新rtsp视频流
            cap = cv2.VideoCapture(rtsp)
            ret, frame = cap.read()
            continue
        q.put(frame)

不过该方法会导致网络摄像头在视频流过程中丢失1-2秒的视频信息,幸好小规模的应用上数据衔接也没有什么问题,在实时视频上的表现就是卡了1-2秒,并没有什么影响。

如果有大佬有更好的解决方法请告知一下,多谢了。

应该是内存覆盖了,函数被调用三次,初始化了三次,现在我想使用你上面提到的方案方案1:为每个摄像头创建独立 Decoder 实例,std::unique_ptr<MppDecoder> mppDecoderPerStream = createDecoderForStream(stream1);告诉我具体怎么做?void *open_media(void *argv){ __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "open_media xxxxxxxxxx"); ThreadData *data = static_cast<ThreadData *>(argv); const char *rurl = data->url; std::string cstr = std::string(data->cameraId); int cameraId = std::stoi(cstr); std::string istr = std::string(data->indexStr); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "open_media xxxxxxxxxx %s", istr.c_str()); int index = std::stoi(istr); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "open_media %d %s %i", cameraId, rurl, index); int retries = 0; // 初始化 MPP 解码器 auto mppDecoder = std::make_shared<RKMpp>(); if (mppDecoder->initCodec("video/avc", false) != 0) { __LOG_PRINT(ANDROID_LOG_ERROR, "rtsp", "MPP 初始化失败"); delete data; return nullptr; } __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "MPP 初始化成功!"); mppDecoder->createInputBuffers(); while (retries < MAX_RETRIES) { cv::VideoCapture stream1(rurl, cv::CAP_FFMPEG); if (!stream1.isOpened()) { __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "Cannot open RTSP stream!"); std::cerr << "无法打开 RTSP 流,尝试第 " << retries + 1 << " 次重连..." << std::endl; retries++; std::this_thread::sleep_for(std::chrono::seconds(RETRY_INTERVAL)); continue; } __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "oooooooooooo!"); cv::Mat encodedPacket; // 假设存储编码数据(如 H.264 包) while (true) { // 从流中读取编码数据包(需验证 OpenCV 是否支持直接读包) if (!stream1.grab()) { // 处理断流重连 break; } __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "kkkkkkkkkk!"); // 获取 MPP 输入缓冲区 int inputIndex = mppDecoder->dequeueInputBuffer(500000); if (inputIndex < 0) continue; __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "ppppppppppp!"); // 读取编码数据到缓冲区 if (stream1.retrieve(encodedPacket)) { __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "iiiiiiiiii!"); char *inputBuf = mppDecoder->getInputBuffer(inputIndex); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "uuuuuuuuuuu!"); size_t dataSize = encodedPacket.total() * encodedPacket.elemSize(); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "ffffffffff!"); memcpy(inputBuf, encodedPacket.data, dataSize); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "aaaaaaaaa!"); std::lock_guard<std::mutex> lock(decoderMutex); mppDecoder->queueInputBuffer(inputIndex, 0, dataSize, 0); __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "sssssssssss!"); } __LOG_PRINT(ANDROID_LOG_DEBUG, "rtsp", "jjjjjjjjjjjj!"); // 获取解码后的帧 int outputIndex = mppDecoder->dequeueOutputBuffer(100000); // if (outputIndex >= 0) { // char *decodedFrame = mppDecoder.getFrame(); // screenShot(num, cameraId, index, decodedFrame); // 修改后的截图函数 // } } } }
03-25
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值