2011年9月11日日曜日

directshow開発--问题篇

最近,通过开发一个视频音频实时网络传送(类似视频聊天)的项目,对directshow有了一些了解,遇到以下问题并解决方法.
1.音频采样数据大小的控制
现象:
程序中音频采样正确,通过tcp传送没有问题,通过udp先发送(sendto)头数据,发送成功,紧接着发送音频数据始终出错.
分析:
数据头sendto可以成功,说明发送代码没问题,问题应该就是数据大小问题.先打印出数据大小为88200,然后通过以下代码可知道udp所能传输包的最大数据大小
int optlen = sizeof(int);
int optvalmax;
getsockopt(sock, SOL_SOCKET, SO_MAX_MSG_SIZE, (char *)&optvalmax, &optlen);
结果知道最大为65507,显然正如我们所分析的,是数据包太大一起发送失败.
解决:
通过以上分析,知道要缩小音频数据,才有可能udp发送成功.
通过网上了解到,通过修改以下接口的属性,可实现采样数据量大小的控制
参照url:http://www.pcdog.com/edu/sjjg-sffx/2006/10/q146793_2.html
1.1通过IAMStreamConfig接口,修改的音频采样属性
注:该接口只针对输入pin

IAMStreamConfig *pPinSConfig;

hr = pin->QueryInterface(IID_IAMStreamConfig, (void **)&pPinSConfig);
if (FAILED(hr))
{
ErrorPrint("Get pin pPinSConfig error",hr);
}
else
{
AM_MEDIA_TYPE *pmt={0};
hr = pPinSConfig->GetFormat(&pmt);
if (SUCCEEDED(hr))
{

WAVEFORMATEX *pWF = (WAVEFORMATEX *) pmt->pbFormat;
pWF->nChannels = 1;
//pWF->nSamplesPerSec = 44100;
//pWF->wBitsPerSample = 16;
pWF->nBlockAlign = (WORD) ((pWF->wBitsPerSample * pWF->nChannels) / 8);
pWF->nAvgBytesPerSec = (pWF->nSamplesPerSec * pWF->nBlockAlign);

// Set the new formattype for the output pin
hr = pPinSConfig->SetFormat(pmt);

DeleteMediaType(pmt);
}
// Release interfaces
pPinSConfig->Release();
}

通过以上方法,将采集的声道数(nChannels)由2改为1,数据量减半为44100,测试后确实能发送成功了!
1.2.通过IAMBufferNegotiation接口,改变音频捕捉缓冲的大小,以减少声音播放的延迟。
注:该接口只针对输出pin,且在connect以前有效
以下设置是50ms延时

nFrequency = USE_SAMPLE_RATE;//48000;

// Find number of bytes in one second
long lBytesPerSecond = (long) (nBytesPerSample * nFrequency * nChannels);

// Set to 50ms worth of data
long lBufferSize = (long) ((float) lBytesPerSecond * 0.05);
pCapturePin->QueryInterface(IID_IAMBufferNegotiation, (void **)&pNeg);

// Set the buffer size based on selected settings
ALLOCATOR_PROPERTIES prop={0};
prop.cbBuffer = lBufferSize;
prop.cBuffers = 6;
prop.cbAlign = nBytesPerSample * nChannels;
hr = pNeg->SuggestAllocatorProperties(&prop);
pNeg->Release();

2.本地音频采集,本地播放时的回音问题
这个不是程序问题,是测试方法的问题.
本地音频采集,本地播放时,因为音箱的声音传入麦克,产生回音,不断叠加,出现干扰噪音.
解决办法就是用没有麦克的耳机代替音箱.