【ffmpeg-0.11.1移植到windows】【网络方面遇到的问题】【中文设备名问题】

该文章叙述的一些问题,主要偏windows方面,不着重与linux的比较,接续在如何用vs08编译ffmpeg这件事情之后。内容大多搜集于网上,为转载。

————————————————————————————————————————————————————

这篇文章列举了些数据结构与接口的相关:windows下网络编程笔记之linux到windows程序移植

————————————————————————————————————————————————————

1. 小问题,其实也不是网络技术问题了:if ((int)fds[i].fd > n),条件真还是假(int n = -1;)?

看看linux下pollfd结构的定义:

struct pollfd {
    int fd;              /* file des to poll */
    short events;  /* events to look for */
    short revents; /* events that occurred */
};

看看windows下pollfd结构的定义:

typedef struct pollfd {

    SOCKET  fd;
    SHORT   events;
    SHORT   revents;

} WSAPOLLFD, *PWSAPOLLFD, FAR *LPWSAPOLLFD;

typedef UINT_PTR        SOCKET;

类型不匹配,导致的隐式转换,在windows下,题中的条件表达式基本恒为真。


2. WSAStartup函数

int WSAStartup(
  WORD wVersionRequested,
  LPWSADATA lpWSAData
);

3. ffmpeg代码中getaddrinfo函数的使用

#if defined(_WIN32)
	{
		int (WSAAPI *win_getaddrinfo)(const char *node, const char *service,
									  const struct addrinfo *hints,
									  struct addrinfo **res);

		char moduleName[36] = {0};
		int num_chars = 0;
		wchar_t moduleName_w[36] = {0};

		snprintf(moduleName, sizeof(moduleName), "ws2_32.dll");//
		/* convert UTF-8 to wide chars */
		num_chars = MultiByteToWideChar(CP_UTF8, 0, moduleName, -1, NULL, 0);
		if (num_chars <= 0)
			return -1;
		MultiByteToWideChar(CP_UTF8, 0, moduleName, -1, moduleName_w, num_chars);

		HMODULE ws2mod = GetModuleHandle((const WCHAR *)moduleName_w);
		win_getaddrinfo = GetProcAddress(ws2mod, "getaddrinfo");
		if (win_getaddrinfo)
			return win_getaddrinfo(node, service, hints, res);
	}
	#endif

4. 在ioctlsocket设置非阻塞之后,connect 10035(WSAEWOULDBLOCK)错误?

可参考:connect 10035错误

non   blocking模式,connect不会等到成功,而是马上返回。你需要再select()来判断成功与否。
   for (i = 0; i < TotalSockets; i++)         
            FD_SET(SocketArray[i]->Socket, &ReadSet);
   if ((Total = select(0, &ReadSet, NULL, NULL, NULL)) == SOCKET_ERROR)
      {
         printf("select() returned with error %d\n", WSAGetLastError());
         return;
      }

10035不是错误。改变为nonblock模式后第一个改变的观念就是:不能认为凡是遇到SOCKET_ERROR都认为遇到错误了。WSAEWOULDBLOCK是一种正常性的错误码,他告诉你现在这个操作无法立即完成,必须等待后续的通知。你可以通过楼上说的select方式去检查是否链接成功建立

或看:http://www.verydemo.com/demo_c173_i9565.html

SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);//先创建套接字
if(sock == INVALID_SOCKET)
{
  AfxMessageBox("创建套接字失败!");
  return 0;
}
SOCKADDR_IN addrTo;
addrTo.sin_family=AF_INET;
addrTo.sin_port=htons(4000);
addrTo.sin_addr.S_un.S_addr=inet_addr(ip);
//--------------------------------------------------------------------------
//设置为非阻塞方式连接
unsigned long ul = 1;
int err;
int ret = ioctlsocket(sock, FIONBIO, (unsigned long*)&ul);
if(ret == SOCKET_ERROR)
{
	err = WSAGetLastError();
  closesocket(sock);
  sock = NULL;
  return FALSE;
}

TIMEVAL timeval;
fd_set r;                      

FD_ZERO(&r);
FD_SET(sock, &r);
timeval.tv_sec = 1;   //秒
timeval.tv_usec =200;  //毫秒

//上面的代码是要connect在1.2秒之后返回,不管是否已经连接上,这样就不会阻塞啦,简单吧

connect(sock, (SOCKADDR*)&addrTo, sizeof(SOCKADDR));

ret = select(0, 0, &r, 0, &timeval);  
if ( ret <= 0 )
{
  char ch[20] = {0};
  sprintf(ch, "和%s连接超时, 取原参数失败", ip);
  MessageBox(ch, "错误", MB_ICONSTOP);
  err = WSAGetLastError();
  closesocket(sock);
  sock = NULL;
  return FALSE;
}

顺便记录这个问题: How to set a socket connection timeout

是说,有时候connect当目标不能到达,超时太久。就先设置非阻塞,connect立即返回,然后重新设为阻塞,最后做select看看socket是否准备好。


5. 在ffmpeg的dshow中,去枚举设备名,与上层传下来的设备名匹配。

如:汉字的unicode编码常用汉字的UTF-8编码汉字GBK编码表。上层获取的是GBK码,下面却用UTF-8去匹配,所以总是失败。


引自 文字编码 ASCII 汉字GB2312 UTF-8解析

ASCII,美国信息交换标准代码(America standard code of Information Interchange),用一个字节的7位,美国专用。欧洲也要编码,于是字节的8位全用上,有了IBM/ISO Latin-1。然后是第三世界国家,中国,韩国等,于是就必须得扩展了,我们中文辐射区的文字表示甚是复杂,于是两个字节的UNICODE出世。但是在几种编码的兼容问题出现了,怎样让中文的一个文件能在美国读出来呢?一种权衡方案出台--UTF系列。UTF,Universal Transformation Format,通用转换格式。UTF-8是一种非定长的字符表示方式,具体实现可以参见相关资料。


引自 汉字怎样转换成ascii码

ascii码是根据http编码得出的,首先要知道这个字的http编码,先进入百度贴吧,把你想查看的字输入,点击搜索,比如说我输入“牛”,因为地址太长了,再点一下左上角百度贴吧旁的“牛吧”,就会出现比较短的地址,这个地址是 http://tieba.baidu.com/f?kw=%C5%A3 kw=后面的%C5%A3就是http编码,把%去掉,变成C5A3,使用系统自带的计算器把他变为10进制(开始——所有程序——附件——计算器),查看——科学型,先选择十六进制,再输入C5A3,然后选择十进制,上面的数字就会变成50595,也就说alt+50595能打出“牛”


下面贴两段代码,gbk与utf-8的转换,调用了windows下的接口,代码丑陋与否无所谓了。

//using c
char *gbk_to_utf8_c(const char *src_gbk, void *(* local_malloc)(size_t), void (* local_free)(void *))
{
	int n;
	char *dst_utf8 = NULL;
	wchar_t *tmp = NULL;

	if (!src_gbk || !local_malloc || !local_free)
	{
		return NULL;
	}
	
	n = MultiByteToWideChar(CP_ACP, 0, src_gbk, -1, NULL, 0);
	tmp = (wchar_t *)local_malloc(n*2+2);
	memset(tmp, 0, n * 2 + 2);
	MultiByteToWideChar(CP_ACP, 0, src_gbk, -1, tmp, n);

	n = WideCharToMultiByte(CP_UTF8, 0, tmp, -1, NULL, 0, NULL, NULL);
	dst_utf8 = (char *)local_malloc(n+1);
	memset(dst_utf8, 0, n + 1);
	WideCharToMultiByte(CP_UTF8, 0, tmp, -1, dst_utf8, n, NULL, NULL);

	local_free((void *)tmp);
	return dst_utf8;
}
char *utf8_to_gbk_c(const char *src_utf8, void *(* local_malloc)(size_t), void (* local_free)(void *))
{
	int n = MultiByteToWideChar(CP_UTF8, 0, src_utf8, -1, NULL, 0);
	wchar_t *tmp = (wchar_t *)local_malloc(n*2+2);
	char *dst_gbk = NULL;

	memset(tmp, 0, n * 2 + 2);
	MultiByteToWideChar(CP_UTF8, 0, (LPCSTR)src_utf8, -1, (LPWSTR)tmp, n);

	n = WideCharToMultiByte(CP_ACP, 0, (LPCWSTR)tmp, -1, NULL, 0, NULL, NULL);
	dst_gbk = (char *)local_malloc(n+1);

	memset(dst_gbk, 0, n + 1);
	WideCharToMultiByte(CP_ACP,0, (LPCWSTR)tmp, -1, dst_gbk, n, NULL, NULL);

	local_free((void *)tmp);
	return dst_gbk;
}

还可以参考: UTF-8, Unicode, GB2312格式串转换之C语言版

除了编码问题,在dshow接口调用的时候,(对于一些硬件设备名,xp win7下不同,win7下通常会有前缀,这样使设备名很长),设备友好名获取不完整,而用dsound接口获取又是没有问题的。下面是dshow调用的部分接口:

*.读取设备名的属性

step1:  Call IMoniker::BindToStorage to get a pointer to the IPropertyBag interface.

        IPropertyBag *pPropBag;

        HRESULT hr = pMoniker->BindToStorage(0, 0, IID_PPV_ARGS(&pPropBag));

 

step2:   Call IPropertyBag::Read to read the property.

        VARIANT var;

        VariantInit(&var);

        // Get description or friendly name.

        hr = pPropBag->Read(L"Description", &var, 0);

没辙,在这里做名字匹配的时候,只好通过,两个字串是否包含的关系,去做比较。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值