广州快速建站公司推荐短网址在线生成短网址

当前位置: 首页 > news >正文

广州快速建站公司推荐,短网址在线生成短网址,wordpress查看购物车不管用,免费如何创建网站平台目录 1、问题说明 2、初步分析 3、字符串字符编码说明 4、进一步分析 5、为啥在日常测试时没有遇到切换摄像头失败的问题呢#xff1f; 6、华为MateBook笔记本使用高通的CPU 7、最后 VC常用功能开发汇总#xff08;专栏文章列表#xff0c;欢迎订阅#xff0c;持续更…目录 1、问题说明 2、初步分析 3、字符串字符编码说明 4、进一步分析 5、为啥在日常测试时没有遇到切换摄像头失败的问题呢 6、华为MateBook笔记本使用高通的CPU 7、最后 VC常用功能开发汇总专栏文章列表欢迎订阅持续更新…https://blog.csdn.net/chenlycly/article/details/124272585C软件异常排查从入门到精通系列教程专栏文章列表欢迎订阅持续更新…https://blog.csdn.net/chenlycly/article/details/125529931C软件分析工具从入门到精通案例集锦专栏文章正在更新中…https://blog.csdn.net/chenlycly/article/details/131405795C/C基础与进阶专栏文章持续更新中…https://blog.csdn.net/chenlycly/category_11931267.html开源组件及数据库技术专栏文章持续更新中…https://blog.csdn.net/chenlycly/category_12458859.html网络编程与网络问题分享专栏文章持续更新中…https://blog.csdn.net/chenlycly/category_2276111.html       最近在项目中遇到了一个因字符串编码转换时发生内存越界引发摄像头切换失败的问题今天就来分享这个问题的排查过程以供借鉴或参考。 1、问题说明 最近在某个项目中将软件部署到客户的环境中后有台华为MateBook笔记本后经证实这是华为新出的Pad平板电脑在使用我们客户端音视频软件时发现切换笔记本前置摄像头时有问题。打开软件时默认使用的是后置摄像头客户在设置中将摄像头由后置摄像头切换到前置摄像头时 发现没有反应显示的还是后置摄像头图像应该是摄像头切换失败了。 2、初步分析 系统当前的摄像头列表的获取以及摄像头的切换最终都是程序底层的音视频模块去执行的所以优先从音视频模块查起。 这里的摄像头包括机器内置的摄像头以及USB摄像头通过USB接口接到系统中的摄像头。 1台式机电脑一般使用的都是外接的USB摄像头 2笔记本电脑使用的是内置摄像头也可以使用外界的USB摄像头更清晰一点角度可所以调整 3Pad平板一般会像手机一样内置两个摄像头一个前置摄像头一个后置摄像头。 经过客户允许我们使用远程桌面软件远程连接到出问题的客户笔记本上。首先查看音视频模块的打印日志发现调用音视频模块切换摄像头时上层传下来的摄像头id是空的日志打印是排查问题最重要、最常用的手段之一 正常的摄像头id是类似于这样的字符串\?\usb#vid_046dpid_0825mi_00#6259ee56200000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}{bbefb6c7-2fc4-4139-bb8b-a58bba724083} 音视频模块是通过上层传下来的设备id去匹配对应的摄像头设备找到目标摄像头后将摄像头源切换过去。根据打印上层在调用音视频模块切换摄像头的接口时传入的是摄像头id为空肯定匹配不到摄像头设备所以没法切换到目标摄像头摄像头切换失败了。 客户端UI层模块也会保存摄像头列表数据包含摄像头名和idUI层调用切换摄像头的接口时是从UI层的内存中去找对应的设备id然后将要切换到的目标摄像头id传递给底层。难道UI层内存中保存的摄像头列表中的id有问题id为空于是去查看UI层的打印日志通过日志得知UI层保存的摄像头列表数据是正常的id也不为空是有效的 3、字符串字符编码说明 本案例中的问题与字符编码转换有关所以此处给大家大概地介绍一下字符编码及相互转换的相关内容。 很多人在处理字符串编码及转换时可能会有不解或疑惑甚至有多年工作经验的朋友也搞不清楚所以这个地方很有必要给大家介绍一下字符编码相关的内容 有字符串的地方就会涉及到字符编码是对字符串的编码。常用的字符编码有ANSI窄字节编码、UNICODE宽字节编码和UTF8可变长度编码其中UNICODE编码在Windows系统中普遍的使用。 ANSI编码是本地语言编码不是全球统一编码不同国家语言文字的ANSI编码可能是相同的。中文字符的ANSI编码也被成为GBK编码是对GB2312编码的扩展。 UNICODE编码则是全球统一的双字节编码1个字符使用两个字节编码来表示不同国家文字字符的UNICODE编码是全球唯一的不重复的。在Windows平台上开发的软件要支持多国语言则软件中的字符要使用UNICODE编码。用Visual Studio开发的软件如果要使用UNICODE编码一般需要工程属性中需要字符集设置为“使用 Unicode 字符集”VS会在工程中自动添加UNICODE宏 涉及到字符串参数的系统API函数一般都有两个版本一个ANSI窄字节版本一个UNICODE宽字节版本比如获取窗口文字的API函数GetWindowText的声明如下 int WINAPI GetWindowTextA(In HWND hWnd,_Outwrites(nMaxCount) LPSTR lpString,In int nMaxCount); _Retrange(0, nMaxCount)WINUSERAPI int WINAPI GetWindowTextW(In HWND hWnd,_Outwrites(nMaxCount) LPWSTR lpString,In int nMaxCount);#ifdef UNICODE #define GetWindowText GetWindowTextW #else #define GetWindowText GetWindowTextA #endif // !UNICODE 如果有定义UNICODE则指向宽字节版本。如果在Visual Studio的字符集选项中选择“使用多字节字符集”则对应ANSI窄字节编码。 UTF8编码是可变长字符编码也是一种全球统一编码之所以称之为可变长编码因为不同类型的字符的编码长度是不同的比如一个数字或英文字母的编码只占1个字节一个中文文字的编码则占3个字节。 UTF8编码一般用于客户端和服务器之间交互的字符数据的统一编码格式比如服务器中的Linux系统支持直接操作UTF8编码的字符数据对于Windows客户端程序在UI界面展现字符串数据时需要先将服务器给过来的UTF8编码的字符转换成ANSI或UNICODE编码的字符然后再将字符串拿到UI界面上显示。 软件中可能会涉及到不同字符编码的转换关于常用字符编码的详细说明以及编码之间转换的源码实现可以参见我之前写的文章 一文带你弄懂C中的ANSI、Unicode和UTF8三种字符编码及相互转换https://blog.csdn.net/chenlycly/article/details/121070073VC中ANSI、UNICODE与UTF-8字符编码之间的转换附源码https://blog.csdn.net/chenlycly/article/details/123589349 4、进一步分析 这就奇怪了UI层的摄像头列表数据没问题音视频模块中的摄像头列表数据也没问题为啥上层调用音视频模块的切换摄像头接口时传入的目标摄像有id为空呢其实在UI层与音视频模块之间还有个业务组件模块难道是中间的业务组件模块的代码有问题 音视频模块库是业务组件层封装起来的即音视频模块的接口是业务组件层调用的于是到业务组件层中查看调用音视频模块的切换摄像头接口的函数如下所示 因为上层与组件层之间交互涉及到字符串的都统一使用UTF8字符编码而音视频模块切换摄像头的接口声明如下 // 选择视频源 unsigned short SelectVideoSource(const TVideoCapParam  *ptVideoCapParam, const wchar_t *pszDevName NULL, const wchar_t *pszDevGUID NULL); 该函数的第二个参数pszDevName摄像头名称和第三个参数pszDevGUID摄像头id都是wchar_t类型宽字节字符在Windows平台上就是上面讲的UNICODE。而上层传过来的摄像头名称和id字符串都是UTF8编码的所以在调用上述SelectVideoSource之前需要将UTF8编码的字符串转换成UNICODE编码的字符串代码中确实调用了UTF8转换到UNICODE的接口Utf8Tolnicode。 看到这里突然想到是不是摄像头id比较长在进行字符编码转换时存放转换后的字符串的buffer长度不足导致内存越界了我们经常与字符编码打交道对这方面的问题比较敏感所以导致底层音视频模块的切换摄像头接口中收到的id为空的问题于是将之前在日志中看到的目标摄像头的id拷贝到notepad中查看到字符串的长度 全选拷贝进来的摄像头id字符串然后再notepad状态栏显示的字符个数得知摄像头id字符串的字符个数为130个这些字符是键盘上的数字、字母等字符的组合在UTF8编码中保存的是ASCII码只占用1个字节。 如果将上述字符串转成UNICODE编码的字符串在UNICODE编码中一个字符占两个字节对于数字和字母其编码值就是ACSII码只需要一个字节就能存放了但还是要固定的占两个字节高位填充0。所以上述130个字符的字符串转成UNICODE编码后需要1302 260字节如果要包含字符串\0结尾符那就需要262字节了而编码转换的代码中却使用了256字节的buffer去接收转换出来的UNICODE编码 所以在调用Utf8Tolnicode接口转换时肯定发生内存越界了所以引发了音视频模块的切换摄像头的接口内部收到的id为空的问题。 按讲此处即使有越界按讲传入的id不应该为空因为在打印字符串时会直到找到字符串\0结尾符才会结束此处就没再深究了反正是存放转换出的UNICODE字符串的buffer长度不够导致的问题修改后就正常了。 解决办法很简单直接将接收UNICODE字符串的buffer长度由256改成512就可以了。 此外在Windows平台上主要是调用API函数MultiByteToWideChar实现的其实我们在调用MultiByteToWideChar接口时第五个参数接收转码后的字符串buffer地址传入NULLMultiByteToWideChar返回的就是转码后字符串的长度然后再调用一次MultiByteToWideChar进行转换相关代码如下所示 int nTmpLen MultiByteToWideChar( CP_UTF8, 0, pchSrc, -1, NULL, 0 ); WCHAR pWTemp new WCHAR[nTmpLen1]; memset( pWTemp, 0, (nTmpLen1)*sizeof(WCHAR) ); MultiByteToWideChar( CP_UTF8, 0, pchSrc, -1, pWTemp, nTmpLen1 ); 5、为啥在日常测试时没有遇到切换摄像头失败的问题呢 遇到问题时我们要多思考要搞清楚问题的来龙去脉甚至可以和正常的场景做比较。本案例中的问题以前从来没遇到过这个到底有什么不一样的地方呢我们的音视频软件需要使用到摄像头不管是内置的摄像头还是外插的USB摄像头。我们的软件已经有很多年了为啥到现在才暴露出这个问题呢 于是到使用USB摄像头的测试电脑上看看USB摄像头id和客户的摄像头id有什么不同。通过打印日志拿到USB摄像头id的打印当前用的是外接的USB摄像头id中包含usb字样 \?\usb#vid_046dpid_0825mi_00#6259ee56200000#{65e8773d-8f56-11d0-a3b9-00a0c9223196}{bbefb6c7-2fc4-4139-bb8b-a58bba724083} 把这个id串拷贝到notepad中 选中所有字符看到一共有127个字符那么将这个字符串转成UNICODE编码需要127*2 254字节如果要包含\0结尾符则需要256个字节所以上述代码中给出256字节是够用的没有问题。 但在本案例中的客户笔记本电脑上出问题的摄像头id为笔记本自带摄像头是内置的id中包含了display字样 \?\display#qcom_avstream_8180#31716c7e72uid32768#{65e8773d-8f56-11d0-a3b9-00a0c9223196}{4faeafd4-041b-4e46-85fd-400473891182} 比较两个摄像头id字符串得知id字符串的前半部分是不同的。 6、华为MateBook笔记本使用高通的CPU 在我们的印象中高通主要是做手机CPU芯片的没想到华为的MateBook笔记本也使用高通的Snapdragon骁龙CPU相关截图如下 高通CPU是基于ARM架构的Windows系统也是支持ARM架构的CPU的。 笔记本电脑的CPU一般使用Intel或AMD的CPU第一次见到用高通CPU的很是好奇于是以Snapdragon 8cx Gen 2型号到网上搜索这款CPU的说明在CPUBenchmark测评工具的官网上看到了该CPU的说明 这款CPU 8核8线程支持平台有移动端、嵌入式和笔记本电脑Laptop。 这款笔记本型号是MateBook E Go后来到华为商城上搜了一下这个是类似微软Surface的平板电脑屏幕和键盘是可以分开的本质上还属于Pad平板电脑和一般意义上的笔记本还是有些不一样的。 7、最后 这个问题其实相对比较简单但其中涉及到的字符编码及编码转换的部分内容正好趁此机会给大家普及一下希望能给大家提供一定的借鉴或参考。