Canon EDSDK:C++解码Evf内存流失败,Python版本正常求助
已通过PySide和edsdk-python实现佳能EDSDK的Evf图像功能,但C++版本解码Evf内存流数据时遇到问题:执行后stream_length从0变为约280000,说明下载成功,但QImage.loadFromData返回download ok QImage::Format_Invalid;若采用Python中的CreateMemoryStreamFromPointer方式,loadFromData会出现大量"bogus DQT"提示,问题出在内存流、数据指针处理或传递给QImage.loadFromData的方式上。
C++项目相关代码
EdsStreamRef evfStream; EdsEvfImageRef evfImage; uchar * image_data; QImage qimg; EdsUInt64 stream_length; EdsUInt32 evfMode = 1; EdsUInt32 outDev = 2; EdsOpenSession(selected_cam); EdsSetPropertyData(selected_cam, kEdsPropID_Evf_Mode, 0, sizeof(evfMode), &evfMode); EdsSetPropertyData(selected_cam, kEdsPropID_Evf_OutputDevice, 0, sizeof(outDev), &outDev); EdsCreateMemoryStream(0, &evfStream); EdsCreateEvfImageRef(evfStream, &evfImage); QThread::usleep(1000 * 750); EdsGetLength(evfStream, &stream_length); qDebug() << "length" << stream_length; EdsDownloadEvfImage(selected_cam, evfImage); EdsGetLength(evfStream, &stream_length); qDebug() << "length" << stream_length; image_data = new uchar[stream_length]; EdsGetPointer(evfStream, (EdsVoid**) image_data); qimg.loadFromData(image_data, stream_length, "JPG"); qDebug() << "download ok" << qimg.format();
可正常运行的Python版本代码
qimg = QImage() edsdk.OpenSession(selected_cam) edsdk.SetPropertyData(selected_cam, PropID.Evf_Mode, 0, 1) edsdk.SetPropertyData(selected_cam, PropID.Evf_OutputDevice, 0, 2) image_data = bytes(960*640*3) mem_stream = edsdk.CreateMemoryStreamFromPointer(image_data) evfImage = edsdk.CreateEvfImageRef(mem_stream) time.sleep(.75) edsdk.DownloadEvfImage(selected_cam, image) qimg.loadFromData(image_data, "JPEG") pixmap = QPixmap.fromImage(qimg) mainWindow.imageLabel.setPixmap(pixmap)
问题排查与修复方案
修复内存流指针获取逻辑:
你的C++代码中EdsGetPointer的调用方式错误,该函数需要传入指针的指针来接收内存流的内部缓冲区地址,而非传入自己分配的数组地址。修改代码如下:// 不需要手动new数组,直接获取内存流内部缓冲区 EdsVoid* buffer = nullptr; EdsGetPointer(evfStream, &buffer); qimg.loadFromData(static_cast<const uchar*>(buffer), stream_length, "JPG");原代码中手动分配数组不仅多余,还会因指针覆盖导致无效内存访问,同时存在内存泄漏风险。
匹配内存流创建方式的缓冲区要求:
若使用EdsCreateMemoryStreamFromPointer(对应Python的CreateMemoryStreamFromPointer),需确保预分配的缓冲区大小足够容纳Evf图像数据。Python中用960*640*3作为缓冲区大小,C++中需分配相同或更大的空间,避免数据截断导致JPEG结构损坏("bogus DQT"即为此类错误)。优化格式检测逻辑:
尝试移除loadFromData的"JPG"参数,让QImage自动检测图像格式;或通过EDSDK接口确认Evf图像的实际编码格式,确保传递给QImage的格式参数正确。替换固定延迟为事件通知:
固定延迟可能因相机响应速度差异导致数据未完全下载,建议使用EDSDK的事件回调机制(如EdsSetCameraStateEventHandler)监听Evf图像就绪事件,替代QThread::usleep,提升可靠性。
内容的提问来源于stack exchange,提问作者Marshall Eubanks

