2

我正在使用 libjpeg(Windows Mobile 6.5 上的 C/C++ 编程)来解码来自 IP 摄像机的图像(以 MJPEG 流形式发送),然后再将它们推送到 DirectShow 图形中。

到目前为止,我一直在使用一个函数:接收流,手动解析它(以便找到 JPEG 数据的起点和终点),解码数据(即初始化 libjpeg 结构,读取 JPEG 标头,进行实际解码...)并最终将其推入图表。这可以正常工作,但为了使事情更顺畅和更整洁,我想使用一个函数进行接收,该函数调用另一个函数(后来是一个线程)进行解码/推送。

因此,作为第一步,我不是在找到流中的数据后立即执行所有 JPEG 工作,而是简单地调用另一个函数来负责 JPEG 结构的初始化/标头读取/解码/推送。

这就是我得到一个我无法破译的错误的地方:“在状态 205 中对 jpeg 库的调用不当”

// 为清晰而编辑

现在,我的代码如下所示:

无效接收1(){
    而(1)
    {
        if(recvfrom(/* ... */) > 0)
        {
            /* 解析接收到的 JPEG 开始和结束数据 */

            /* 解码 JPEG */
            //声明
            结构 jpeg_decompress_struct cinfo;
            结构 my_error_mgr jerr;

            // 第一步:分配/初始化
            cinfo.err = jpeg_std_error(&jerr.pub);
            jerr.pub.error_exit = my_error_exit;
            如果(setjmp(jerr.setjmp_buffer))
            {
                printf("--错误 LIBJPEG\n");
                /* 退出并返回错误码 */
            }

            // 下一步:继续解码和显示...
            jpeg_create_decompress(&cinfo);
            /* ... */
        }
    }
}

我想让我的代码看起来像:

无效接收2(){
  而(1)
  {
    if(recvfrom(/* ... */) > 0)
    {
        /* 解析接收到的 JPEG 开始和结束数据 */

        解码(数据);
    }
  }
}  

诠释解码(字符*数据){
    /* 解码 JPEG */
    //声明
    结构 jpeg_decompress_struct cinfo;
    结构 my_error_mgr jerr;

    // 第一步:分配/初始化
    cinfo.err = jpeg_std_error(&jerr.pub);
    jerr.pub.error_exit = my_error_exit;
    if(setjmp(jerr.setjmp_buffer)) // 这就是“state 205”错误发生的地方
    {
        printf("--错误 LIBJPEG\n");
        /* 退出并返回错误码 */
    }

    // 下一步:继续解码和显示...
    jpeg_create_decompress(&cinfo);
    /* ... */

    返回0;
}

任何帮助将不胜感激。非常感谢 !

// 编辑

我意识到我在原始帖子中省略了很多信息。以下是一些(也许)有用的细节:

  • 我正在使用 VS2008,但由于许多原因,我不使用内置调试器或仿真器。而是直接在 Windows Mobile 设备上部署和测试 exe 文件,使用自定义的类似 dos 的命令提示符。
  • libjpeg 最初读取和写入文件,但我使用的是补丁(和自定义错误处理程序),可以直接从缓冲区读取数据,而无需打开文件。代码可以在这里找到,它使用以这种方式定义的“扩展错误处理程序”:
typedef 结构 my_error_mgr * my_error_ptr;  

结构 my_error_mgr
{
    结构 jpeg_error_mgr pub;
    jmp_buf setjmp_buffer;
};  

方法(无效)my_error_exit(j_common_ptr cinfo)
{
    my_error_ptr myerr = (my_error_ptr) cinfo->err;   

    /* 始终显示消息。*/
    (*cinfo->err->output_message) (cinfo);

    /* 将控制返回到 setjmp 点 */
    longjmp(myerr->setjmp_buffer, 1);
}
4

2 回答 2

1

205是0xCD,这是VS在调试模式下放在未初始化内存中的标准值,所以我认为cinfo你在调用解码器时没有正确初始化。使用时发布代码。

另外,setjump()你使用的让我觉得它是 IJG 库。小心它,因为它不是标准功能。当您进行调用时,它会记住线程和堆栈的确切状态,并且能够从任何地方返回到该位置,除非该状态不再有效,例如:

int init_fn(){
     if (setjump(my_state)){
        // ERROR!
     };
return 0;
};

int decode(){
     init_fn();
     do_work();
};

此处保存的状态在您调用实际解码器时无效。对于 MT 情况,您必须setjump()从与longjmp().

于 2010-10-25T10:15:49.027 回答
0

找到了我的问题的答案,部分归功于 ruslik。事实证明,我确实在两个函数之间初始化了 cinfo 和 jerr 。

但是当我更正这一点时,我仍然有“状态205”错误,并认为它在同一个地方。在我的日志中挖掘,我发现错误消息是在代码执行后期发出的,并且是由函数指针问题引起的。我自己的丑陋错误...

无论如何,非常感谢!

于 2010-10-27T09:21:34.417 回答