You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Canon EDSDK:C++解码Evf内存流失败,Python版本正常求助

佳能EDSDK C++版本Evf图像解码失败排查

已通过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.11 10:37:03