V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
feast
V2EX  ›  程序员

C 程序单步调试问题

  •  
  •   feast · 2018-03-03 22:04:30 +08:00 · 3631 次点击
    这是一个创建于 2238 天前的主题,其中的信息可能已经有所发展或是发生改变。

    为何 mingw 跨平台编译 linux 原生 C 代码程序进行单步调试输出结果完全跟直接执行完全不同? 调用了一个外部 dll 的 openh264.dll ,执行后无数据输出,dbg 单步调试不过,哪位高人帮忙改下代码,非软件专业实在感觉编写吃力

    #include<stdio.h>
    #include<stdlib.h>
    #include<stdint.h>
    #include<string.h>
    #include<wels/codec_api.h>
    int WinMain(){
        int width=176;
        int height=144;
        int inputwidth=width;
        int inputheight=height;
        size_t yuvsize=inputwidth*inputheight*3/2;
        FILE*FSoucre=fopen("source.yuv","rb");
        FILE*FSink=fopen("output.264","wb");
        ISVCEncoder*pEncoder=NULL;
        SEncParamBase param;
        SFrameBSInfo info;
        SSourcePicture pic;
        int i=0;
        int ret=0;
        char*buffer=(char*)malloc(yuvsize);
        memset (&param, 0, sizeof (SEncParamBase));
        memset (&info, 0, sizeof (SFrameBSInfo));
        memset (&pic, 0, sizeof (SSourcePicture));
        ret=WelsCreateSVCEncoder(&pEncoder);
        printf("WelsCreateSVCEncoder:%d\n",ret);
        param.iPicHeight=inputheight;
        param.iPicWidth=inputwidth;
        param.fMaxFrameRate=25;
        param.iUsageType=CAMERA_VIDEO_REAL_TIME;
        param.iTargetBitrate = 1000000;
        ret=(*pEncoder)->Initialize(pEncoder,&param);
        printf("Initialize:%d\n",ret);
    do{
        int videoFormat = videoFormatI420;
        (*pEncoder)->SetOption (pEncoder,ENCODER_OPTION_DATAFORMAT, &videoFormat);
    }while(0);
        pic.iPicWidth = width;
        pic.iPicHeight = height;
        pic.iColorFormat = videoFormatI420;
        pic.iStride[0] = pic.iPicWidth;
        pic.iStride[1] = pic.iStride[2] = pic.iPicWidth >> 1;
        pic.pData[0] = buffer;
        pic.pData[1] = pic.pData[0] + width * height;
        pic.pData[2] = pic.pData[1] + (width * height >> 2);
    while(fread(buffer,1,yuvsize,FSoucre)==yuvsize){
        pic.uiTimeStamp=40*i;
        i++;
        (*pEncoder)->EncodeFrame (pEncoder,&pic, &info);
        if (info.eFrameType != videoFrameTypeSkip) {
            //output bitstream
              int iLayerNum=0;
              while(iLayerNum<info.iLayerNum){
                int iNalCount=0;
                int pos=0;
                while (iNalCount<info.sLayerInfo[iLayerNum].iNalCount){
    #if 0
                  printf("I:%d LayerNum:%d(%d) Size:%d Type:%d NalCount:%d(%d) NalSize:%d\n",i,
                  iLayerNum,info.iLayerNum,info.iFrameSizeInBytes,
                  info.sLayerInfo[iLayerNum].eFrameType,
                  iNalCount,info.sLayerInfo[iLayerNum].iNalCount,info.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount]);
    #endif            
                  fwrite(info.sLayerInfo[iLayerNum].pBsBuf+pos,1,info.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount],FSink);
                  pos+=info.sLayerInfo[iLayerNum].pNalLengthInByte[iNalCount];
                  iNalCount++;
                }
                iLayerNum++;
              }
        }
    }
        (*pEncoder)->Uninitialize(pEncoder);
        WelsDestroySVCEncoder(pEncoder);
        fclose(FSoucre);
        fclose(FSink);
    return 0;
    }
    
    21 条回复    2018-03-05 11:23:34 +08:00
    feast
        1
    feast  
    OP
       2018-03-03 22:14:00 +08:00
    程序直接执行后 输出
    ```
    WelsCreateSVCEncoder:0
    Initialize:0
    ```
    razerhell
        2
    razerhell  
       2018-03-03 22:24:07 +08:00 via iPhone
    会不会是工作目录之类的问题呢?
    feast
        3
    feast  
    OP
       2018-03-03 22:46:16 +08:00
    @razerhell 应该不是,fsink 指针可以成功生成 0 字节的目标文件,问题是看不到动态调用 dll 的过程,之前解决一些跨平台编译的语法问题还能行,碰到内部执行的毫无头绪了
    feast
        4
    feast  
    OP
       2018-03-03 22:48:04 +08:00
    @razerhell 你可以直接保存代码用 gcc 链接思科发布的 dll 编译看看,难道这份代码只能 linux 下用
    zhuangzhuang1988
        5
    zhuangzhuang1988  
       2018-03-03 22:50:14 +08:00
    好好的 visualstudio 不用。
    feast
        6
    feast  
    OP
       2018-03-03 22:59:10 +08:00
    @zhuangzhuang1988 我的错,想省事直接用 linux 原生代码,没法解决的话明天看看能不能移植到 VS 上去编译吧………
    wevsty
        7
    wevsty  
       2018-03-03 23:12:23 +08:00
    什么叫 dbg 单步调试不过?我不太明白,意思是程序执行不对?还是说没办法进行单步调试?
    不是做这方面开发的人可能真的不明白这个程序干嘛的,问的问题太笼统也没办法回答。
    从结果来看
    WelsCreateSVCEncoder 和 Initialize 返回 0 是执行成功的意思
    zhuangzhuang1988
        8
    zhuangzhuang1988  
       2018-03-03 23:39:11 +08:00   ❤️ 1
    看了下 有没有平台相关的代码, 应该先用 visualstudio 搞定 再去用 mingw 啥的测试。
    而且现在的 visualstudio 已经支持 mingw 了 包括调试 https://channel9.msdn.com/Shows/C9-GoingNative/GoingNative-59-MinGW-in-Visual-Studio
    没必要苦行僧一样的编程, 有好的工具就用
    ysc3839
        9
    ysc3839  
       2018-03-04 00:47:44 +08:00
    WinMain? 你的 "linux 原生 C 代码" 支持这个?
    MCVector
        10
    MCVector  
       2018-03-04 07:15:05 +08:00 via Android
    之前写过 OpenH264 的 wrapper。 用 vs2008 编译的 ,应该是可以用的。
    pkookp8
        11
    pkookp8  
       2018-03-04 09:24:23 +08:00 via Android   ❤️ 1
    1.函数指针是不是注册了
    2.两个打印返回值是 0,除非代码比较沙皮不遵守一般的约定,否则说明成功了
    3.可读文件的那个 source,是不是有权限。比如是不是挂载目录下的,是的话先给个 777 的权限再试试
    4.代码不多,加打印先看看是哪里失败了
    feast
        12
    feast  
    OP
       2018-03-04 12:14:06 +08:00
    @wevsty 23
    ~~~
    printf("WelsCreateSVCEncoder:%d\n",ret);
    (gdb)
    WelsCreateSVCEncoder:0
    24 param.iPicHeight=inputheight;
    (gdb)
    25 param.iPicWidth=inputwidth;
    (gdb)
    26 param.fMaxFrameRate=25;
    (gdb)
    27 param.iUsageType=CAMERA_VIDEO_REAL_TIME;
    (gdb)
    28 param.iTargetBitrate = 1000000;
    (gdb)
    29 ret=(*pEncoder)->Initialize(pEncoder,&param);
    (gdb)
    0x7406acb0 in gmpopenh264!WelsDestroySVCEncoder ()
    from G:\h264enc\openh264.dll
    0x7409c060 in gmpopenh264!WelsCreateDecoder () from G:\h264enc\gmpopenh264.dll
    (gdb)
    Single stepping until exit from function openh264!WelsCreateDecoder,
    which has no line number information.
    ~~~
    这是 gdb 的单步输出,再往下执行直接就退出了,跟直接执行程序结果不一样
    feast
        13
    feast  
    OP
       2018-03-04 12:14:57 +08:00
    @zhuangzhuang1988 我尝试下用 VS 吧,GUN CLI 实在有点蛋疼,特别是对于我这种主业不是 coding 的
    feast
        14
    feast  
    OP
       2018-03-04 12:15:42 +08:00
    @ysc3839 ooops,当然需要修改一部分来适应 MSVC runtime
    feast
        15
    feast  
    OP
       2018-03-04 12:16:16 +08:00
    @MCVector 有没有相关 code? github 分享一下? YUV 输入的就可以了
    feast
        16
    feast  
    OP
       2018-03-04 12:22:19 +08:00
    @pkookp8 首先我说下基本情况,我是在网上找的一份别人写的,应该是用于 Linux 系统的代码,我对其做了部分修改,在 windows 下使用 mingw 工具编译通过,执行后只能够生成 0 字节的 Output.264,至于源文件,win 下应该不存在权限问题吧,现在不知道为啥已经把各种参数都已经传递给 pEncoder 了,然而根本程序就没有实际编码操作,如何 debug?毫无头绪,gdb 根本就反馈的不是一个错误,之前有看到 incorrect parameters passed to C runtime,难道是 MSVC 不兼容 Linux 下的语法?表示作为非程序员专业,修改压力很大
    ysc3839
        17
    ysc3839  
       2018-03-04 12:42:51 +08:00
    @feast 你前面说的可是 mingw 啊。显然你没了解过,WinMain 是给 GUI 程序用的,CLI 程序还是 main。
    MCVector
        18
    MCVector  
       2018-03-04 12:45:32 +08:00 via Android   ❤️ 1
    @feast 公司代码不方便公开。但是 Linux 和 Win 下的代码几乎都是一样的,当时我写的是跨平台的。
    另外法律方面注意要用 OpenH264 提供的 binary 才能避免 MPEG LA 的 loyalty fee。
    pkookp8
        19
    pkookp8  
       2018-03-04 13:12:22 +08:00 via Android   ❤️ 1
    @feast windows 也有权限问题的。源文件如果可以打开那这里就不是权限问题了
    感觉程序在
    int videoFormat = videoFormatI420;
    (*pEncoder)->SetOption (pEncoder,ENCODER_OPTION_DATAFORMAT, &videoFormat);
    这个地方出错了
    feast
        20
    feast  
    OP
       2018-03-05 11:22:35 +08:00
    @pkookp8 谢谢。我再研究下这个 Int 的问题
    feast
        21
    feast  
    OP
       2018-03-05 11:23:34 +08:00
    @MCVector CISCO 很早就强调了只对他的 binary 负责,这个注意到的,不然也不会想办法去调用 dll 了
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   3528 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 459ms · UTC 00:09 · PVG 08:09 · LAX 17:09 · JFK 20:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.