DirectShow音视频同步实验报告
DirectShow音视频同步实验报告
陆其明 2004-09-09
一. 单一音频流
Filter Graph如图1:

图1 单一音频流的Filter Graph
注意:紧靠Audio Renderer的上一级Filter的Audio输出Pin,其GetMediaType函数提供的Media Type的WAVEFORMATEX结构要求填写完整,不仅包括音频格式(wFormatTag须指定为WAVE_FORMAT_PCM)、采样频率(nSamplesPerSec)、通道数(nChannels)、量化精度(wBitsPerSample),还包括由上述几个参数可以计算获得的 nBlockAlign和nAvgBytesPerSec。代码参考如下:
WAVEFORMATEX mWaveInfo;
ZeroMemory(&mWaveInfo, sizeof(WAVEFORMATEX));
mWaveInfo.wFormatTag = WAVE_FORMAT_PCM;
mWaveInfo.nSamplesPerSec = 44100;
mWaveInfo.nChannels = 2;
mWaveInfo.wBitsPerSample = 16;
mWaveInfo.nBlockAlign = mWaveInfo.nChannels * mWaveInfo.wBitsPerSample / 8;
mWaveInfo.nAvgBytesPerSec = mWaveInfo.nSamplesPerSec * mWaveInfo.nBlockAlign;
1. 使用Filter Graph Manager默认的参考时钟(Audio Renderer作为参考时钟)
确认Filter Graph的参考时钟
HRESULT CheckReferenceClock(void)
{
if (!m_pClock)
{
DbgLog((LOG_TRACE, 0, TEXT("No reference clock.")));
return E_FAIL;
}
// Get downstream connected filter
IPin * pin = mAudioOutPin->GetConnected();
PIN_INFO pinInfo;
HRESULT hr = pin->QueryPinInfo(&pinInfo);
if (SUCCEEDED(hr))
{
// Audio renderer acts as reference clock
pinInfo.pFilter->Release();
BOOL isSame = IsEqualObject(m_pClock, pinInfo.pFilter);
if (isSame)
{
DbgLog((LOG_TRACE, 0, TEXT("Audio renderer acts as reference clock.")));
return NOERROR;
}
}
// Is CLSID_SystemClock?
IPersist * pPersist = NULL;
hr = m_pClock->QueryInterface(IID_IPersist, (void**) &pPersist);
if (SUCCEEDED(hr))
{
pPersist->Release();
CLSID clsid;
pPersist->GetClassID(&clsid);
BOOL isSame = (CLSID_SystemClock == clsid);
if (isSame)
{
DbgLog((LOG_TRACE, 0, TEXT("System clock acts as reference clock.")));
return NOERROR;
}
}
return NOERROR;
}
1.1 Audio Sample(0.25s数据)不打时间戳、连续送出
现象:播放正常。流时间(从参考时钟获得)线性增加。
MsiRlsrc.ax(tid 870) 10980 : stream time: 90920000
MsiRlsrc.ax(tid 870) 11181 : stream time: 92930000
MsiRlsrc.ax(tid 870) 11483 : stream time: 95950000
MsiRlsrc.ax(tid 870) 11684 : stream time: 97960000
MsiRlsrc.ax(tid 870) 11986 : stream time: 100980000
……
MsiRlsrc.ax(tid 870) 29113 : stream time: 270520000(最后一个Sample)
注:上述流时间均在输出Pin数据线程调用FillBuffer函数时获取。(下同。)
1.2 Audio Sample不打时间戳、间隙送出(模拟网络阻塞情况)
现象:有数据时播放正常,间隙性静音。流时间线性增加,间隙休眠的时间反映在前后两次获得的流时间上。
MsiRlsrc.ax(tid 578) 12292 : stream time: 106000000
MsiRlsrc.ax(tid 578) 12493 : stream time: 108010000
MsiRlsrc.ax(tid 578) 15494 : Sleep(3000)... (出现声音播放的间隙静音)
MsiRlsrc.ax(tid 578) 15511 : stream time: 138190000(反映出Sleep的3s,Sleep的时候流时间仍然在走)
MsiRlsrc.ax(tid 578) 15612 : stream time: 139200000
……
MsiRlsrc.ax(tid 578) 38727 : stream time: 374570000(最后一个Sample)
1.3 Audio Sample打(连续)时间戳、连续送出
现象:播放正常。流时间折线上升(周期性出现几个连续Sample发送时流时间停止不走)。
MsiRlsrc.ax(tid 4b0) 11282 : stream time: 93489570
MsiRlsrc.ax(tid 4b0) 11483 : stream time: 102985035
MsiRlsrc.ax(tid 4b0) 11785 : stream time: 103507279
MsiRlsrc.ax(tid 4b0) 11986 : stream time: 103507279
MsiRlsrc.ax(tid 4b0) 12187 : stream time: 103507279
MsiRlsrc.ax(tid 4b0) 12489 : stream time: 113049003
MsiRlsrc.ax(tid 4b0) 12690 : stream time: 113049003
MsiRlsrc.ax(tid 4b0) 12992 : stream time: 113078028
MsiRlsrc.ax(tid 4b0) 13193 : stream time: 113078028
……
MsiRlsrc.ax(tid 4b0) 28351 : stream time: 263460114 (最后一个Sample)
1.4 Audio Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
现象:播放正常。当时间戳复位后,流时间停止走动,直到复位后重打的时间戳再次达到复位时的流时间,之后流时间继续走动。Audio Sample上的时间戳会影响流时间!
MsiRlsrc.ax(tid 954) 9448 : stream time: 82866667
MsiRlsrc.ax(tid 954) 9750 : stream time: 83388005
MsiRlsrc.ax(tid 954) 9951 : stream time: 83388005
MsiRlsrc.ax(tid 954) 9952 : Reset time stamp...
MsiRlsrc.ax(tid 954) 10253 : stream time: 83424286
MsiRlsrc.ax(tid 954) 10454 : stream time: 83424286
MsiRlsrc.ax(tid 954) 10756 : stream time: 83424286
MsiRlsrc.ax(tid 954) 10957 : stream time: 83424286
MsiRlsrc.ax(tid 954) 11259 : stream time: 83424286
MsiRlsrc.ax(tid 954) 11460 : stream time: 83424286
MsiRlsrc.ax(tid 954) 11762 : stream time: 83424286
…… (流时间停止在83424286)
……
MsiRlsrc.ax(tid 954) 19205 : stream time: 83424286
MsiRlsrc.ax(tid 954) 19507 : stream time: 83458527 (流时间继续走动)
MsiRlsrc.ax(tid 954) 19708 : stream time: 83458527
MsiRlsrc.ax(tid 954) 20010 : stream time: 83488005
MsiRlsrc.ax(tid 954) 20211 : stream time: 83488005
MsiRlsrc.ax(tid 954) 20412 : stream time: 92508844
……
MsiRlsrc.ax(tid 954) 28258 : stream time: 163470091(最后一个Sample)
1.5 Audio Sample打时间戳(时间戳超前流时间一个delta)、连续送出
现象:声音等待delta之后再播放,播放正常。(设delta=5s)整个流时间为:原始流时间+delta。
MsiRlsrc.ax(tid 25c) 4077 : stream time: 340000
MsiRlsrc.ax(tid 25c) 4178 : stream time: 1350000(这个Sample送出后阻塞)
MsiRlsrc.ax(tid 25c) 9308 : stream time: 52700000(delta在此反映出来)
MsiRlsrc.ax(tid 25c) 9610 : stream time: 53213402
MsiRlsrc.ax(tid 25c) 9811 : stream time: 53213402
MsiRlsrc.ax(tid 25c) 10113 : stream time: 53241520
MsiRlsrc.ax(tid 25c) 10314 : stream time: 62750567
MsiRlsrc.ax(tid 25c) 10616 : stream time: 63270998
MsiRlsrc.ax(tid 25c) 10817 : stream time: 63270998
MsiRlsrc.ax(tid 25c) 11118 : stream time: 63290477
……
MsiRlsrc.ax(tid 25c) 36064 : stream time: 313247642(最后一个Sample)
1.6 Audio Sample打时间戳(时间戳随机乱序)、连续送出
现象:播放正常。播放中,即使时间戳不对,声音照常播放。如果新Sample的时间戳比上一个Sample的时间戳超前,流时间会被修正到新Sample的时间;如果新Sample的时间戳滞后上一个Sample的时间戳,则流时间在当前时刻停止,直到Sample时间戳再次达到停止时刻的流时间。这一次取得流时间总是大于或等于上一次取得流时间,不可能小于!
MsiRlsrc.ax(tid 8f4) 4863 : stream time: 33095488
MsiRlsrc.ax(tid 8f4) 5064 : stream time: 33095488
MsiRlsrc.ax(tid 8f4) 5065 : Add 5 second delta...
MsiRlsrc.ax(tid 8f4) 5366 : stream time: 33129502
MsiRlsrc.ax(tid 8f4) 5567 : stream time: 92632200(5sdelta修正在流时间上,仍连续播放)
……
MsiRlsrc.ax(tid 8f4) 10094 : stream time: 133389819
MsiRlsrc.ax(tid 8f4) 10096 : Add -3 second delta...
MsiRlsrc.ax(tid 8f4) 10395 : stream time: 133424740(流时间停止不走)
MsiRlsrc.ax(tid 8f4) 10597 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 10898 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 11100 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 11401 : stream time: 133424740
……
MsiRlsrc.ax(tid 8f4) 18046 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 18247 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 18549 : stream time: 143400477(流时间继续走动)
MsiRlsrc.ax(tid 8f4) 18750 : stream time: 143400477
MsiRlsrc.ax(tid 8f4) 18750 : Do not add delta...(时间戳不加delta)
MsiRlsrc.ax(tid 8f4) 19052 : stream time: 143435397
MsiRlsrc.ax(tid 8f4) 19253 : stream time: 172941724(流时间根据Sample时间戳进行修正?)
MsiRlsrc.ax(tid 8f4) 19555 : stream time: 183459887
MsiRlsrc.ax(tid 8f4) 19756 : stream time: 183459887
MsiRlsrc.ax(tid 8f4) 20058 : stream time: 183489819
……
MsiRlsrc.ax(tid 8f4) 28306 : stream time: 263471452(最后一个Sample)
1.7 Audio Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
现象:有数据时播放正常,间隙性静音。在无数据时,流时间并不走动!(请同时参考1.2进行比较。)
MsiRlsrc.ax(tid 86c) 4177 : stream time: 23056939
MsiRlsrc.ax(tid 86c) 4378 : stream time: 32565080
MsiRlsrc.ax(tid 86c) 4679 : stream time: 33075964
MsiRlsrc.ax(tid 86c) 4881 : stream time: 33075964
MsiRlsrc.ax(tid 86c) 7882 : Sleep(3000)...(出现声音播放的间隙静音)
MsiRlsrc.ax(tid 86c) 7899 : stream time: 40170000(没有反映出Sleep的3s,说明Sleep的时候流时间没有走动)
MsiRlsrc.ax(tid 86c) 8000 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8100 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8201 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8302 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8503 : stream time: 53315874
……
MsiRlsrc.ax(tid 86c) 38578 : stream time: 263365556(最后一个Sample)
1.8 将音频的采样频率写错(原来44.1K,现改成32K或48K)
现象:声音播放变调。
2. Filter Graph使用系统时钟(组件)
2.1 Audio Sample(0.25s数据)不打时间戳、连续送出
现象:同1.1。
2.2 Audio Sample不打时间戳、间隙送出(模拟网络阻塞情况)
现象:同1.2。
2.3 Audio Sample打(连续)时间戳、连续送出
现象:播放正常。流时间线性增加,没有出现1.3的“折线上升”现象。另外一个特点,流时间的尾数比较“干净”。
Msiavsrc.ax(tid 714) 14505 : stream time: 91880000
Msiavsrc.ax(tid 714) 14807 : stream time: 94900000
Msiavsrc.ax(tid 714) 15008 : stream time: 96910000
Msiavsrc.ax(tid 714) 15310 : stream time: 99930000
Msiavsrc.ax(tid 714) 15511 : stream time: 101940000
Msiavsrc.ax(tid 714) 15812 : stream time: 104950000
Msiavsrc.ax(tid 714) 16014 : stream time: 106970000
Msiavsrc.ax(tid 714) 16315 : stream time: 109980000
……
Msiavsrc.ax(tid 714) 16315 : stream time: 267900000(最后一个Sample)
2.4 Audio Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
现象:时间戳复位后播放不连续,有部分数据没有被播放。短暂波动后,后续数据仍能正常播放。时间戳复位后的一段时间内流时间仍在缓慢走动。(注:“缓慢走动”说明输出Pin发送Sample的速度很快,也就是说这些Sample达到Audio Renderer后可能被直接丢弃,而并没有根据Sample上的时间戳去安排播放。)
Msiavsrc.ax(tid 21c) 12998 : stream time: 82820000
Msiavsrc.ax(tid 21c) 13199 : stream time: 84830000
Msiavsrc.ax(tid 21c) 13501 : stream time: 87850000
Msiavsrc.ax(tid 21c) 13502 : Reset time stamp...
Msiavsrc.ax(tid 21c) 13702 : stream time: 89860000(流时间仍在缓慢走动)
Msiavsrc.ax(tid 21c) 13703 : stream time: 89870000
Msiavsrc.ax(tid 21c) 13705 : stream time: 89890000
Msiavsrc.ax(tid 21c) 13705 : stream time: 89890000
Msiavsrc.ax(tid 21c) 13706 : stream time: 89900000
Msiavsrc.ax(tid 21c) 13707 : stream time: 89910000
Msiavsrc.ax(tid 21c) 13707 : stream time: 89910000
……
Msiavsrc.ax(tid 21c) 13707 : stream time: 220620000(最后一个Sample)
2.5 Audio Sample打时间戳(时间戳超前流时间一个delta)、连续送出
现象:同1.5。
2.6 Audio Sample打时间戳(时间戳随机乱序)、连续送出
现象:播放断断续续。如果新Sample的时间戳比上一个Sample的时间戳超前,静音等待,直到流时间达到Sample上时间戳再开始播放;如果新 Sample的时间戳滞后上一个Sample的时间戳,则流时间非常缓慢地增加,跳过部分数据不播放,直到Sample时间戳达到当前的流时间。
Msiavsrc.ax(tid 794) 8169 : stream time: 37570000
Msiavsrc.ax(tid 794) 8171 : Add 5 second delta...
Msiavsrc.ax(tid 794) 8471 : stream time: 40590000(此Sample发出后就阻塞(静音),等待流时间达到Sample上的时间戳再开始播放)
Msiavsrc.ax(tid 794) 13701 : stream time: 92890000(5sdelta反映在流时间上,后续数据连续播放)
Msiavsrc.ax(tid 794) 13902 : stream time: 94900000
……
Msiavsrc.ax(tid 794) 18127 : stream time: 137150000
Msiavsrc.ax(tid 794) 18127 : Add -3 second delta...
Msiavsrc.ax(tid 794) 18328 : stream time: 139160000(流时间仍在缓慢走动,声音播放不正常,一些数据没有播放)
Msiavsrc.ax(tid 794) 18329 : stream time: 139170000
Msiavsrc.ax(tid 794) 18329 : stream time: 139170000
Msiavsrc.ax(tid 794) 18330 : stream time: 139180000
Msiavsrc.ax(tid 794) 18331 : stream time: 139190000
Msiavsrc.ax(tid 794) 18331 : stream time: 139190000
Msiavsrc.ax(tid 794) 19133 : stream time: 147210000
……
Msiavsrc.ax(tid 794) 19133 : Do not add delta...
Msiavsrc.ax(tid 794) 19334 : stream time: 149220000(此Sample发出后就阻塞(静音),等待流时间达到Sample上的时间戳再开始播放)
Msiavsrc.ax(tid 794) 21849 : stream time: 174370000(与上次流时间有个较大跨度)
Msiavsrc.ax(tid 794) 22854 : stream time: 184420000
Msiavsrc.ax(tid 794) 23056 : stream time: 186440000
……
Msiavsrc.ax(tid 794) 31505 : stream time: 270930000(最后一个Sample)
2.7 Audio Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
现象:播放断断续续。无数据时,静音等待,此时流时间仍正常走动;随后数据到来时一部分数据会被跳过不播放,数据不播放时流时间走动非常缓慢;最新的Sample时间戳赶上流时间候仍然能正常播放。
Msiavsrc.ax(tid 768) 9092 : stream time: 32520000
Msiavsrc.ax(tid 768) 9394 : stream time: 35540000
Msiavsrc.ax(tid 768) 9595 : stream time: 37550000
Msiavsrc.ax(tid 768) 12596 : Sleep(3000)...(静音等待,流时间在走动)
Msiavsrc.ax(tid 768) 12596 : stream time: 67560000(流时间非常缓慢增加,一些数据不播放)
Msiavsrc.ax(tid 768) 12597 : stream time: 67570000
Msiavsrc.ax(tid 768) 12597 : stream time: 67570000
Msiavsrc.ax(tid 768) 12598 : stream time: 67580000
Msiavsrc.ax(tid 768) 12599 : stream time: 67590000
Msiavsrc.ax(tid 768) 12600 : stream time: 67600000
Msiavsrc.ax(tid 768) 12600 : stream time: 67600000
Msiavsrc.ax(tid 768) 12601 : stream time: 67610000
Msiavsrc.ax(tid 768) 12602 : stream time: 67620000
Msiavsrc.ax(tid 768) 12613 : stream time: 67730000(流时间增加幅度增大,开始慢慢正常播放)
Msiavsrc.ax(tid 768) 12713 : stream time: 68730000
Msiavsrc.ax(tid 768) 12814 : stream time: 69740000
Msiavsrc.ax(tid 768) 12915 : stream time: 70750000
Msiavsrc.ax(tid 768) 13015 : stream time: 71750000
Msiavsrc.ax(tid 768) 13216 : stream time: 73760000
Msiavsrc.ax(tid 768) 13417 : stream time: 75770000
Msiavsrc.ax(tid 768) 13719 : stream time: 78790000
Msiavsrc.ax(tid 768) 13920 : stream time: 80800000
Msiavsrc.ax(tid 768) 14222 : stream time: 83820000
Msiavsrc.ax(tid 768) 14423 : stream time: 85830000
Msiavsrc.ax(tid 768) 17424 : Sleep(3000)... (静音等待,流时间在走动)
Msiavsrc.ax(tid 768) 17424 : stream time: 115840000(流时间非常缓慢增加,一些数据不播放)
Msiavsrc.ax(tid 768) 17425 : stream time: 115850000
Msiavsrc.ax(tid 768) 17426 : stream time: 115860000
Msiavsrc.ax(tid 768) 17427 : stream time: 115870000
Msiavsrc.ax(tid 768) 17427 : stream time: 115870000
……
Msiavsrc.ax(tid 768) 32328 : stream time: 264880000(最后一个Sample)
3. Filter Graph不使用参考时钟
现象:不管Audio Sample打不打时间戳,也不管时间戳打得是否正确,声音都能正常播放。如果Audio Sample送出过程中有间隙性停顿,声音播放也会有间隙性的静音。
小结:
v Filter Graph使用Audio Renderer作为参考时钟时,Audio Sample上的时间戳可能会影响整个Filter Graph的流时间;使用系统时钟作为参考时钟时则不会。
v 以Audio Renderer作为参考时钟,音频数据的播放性能较好;不管Audio Sample上有无时间戳,不管时间戳是否正确,一般都能连续播放。但以系统时钟作为参考时钟时,Audio Renderer会严格按照Sample上的时间戳来播放,早到的数据会被阻塞,直到流时间到达Sample时间后再播放,晚到的数据会被直接丢弃,因此整体的播放效果不佳。
v 以Audio Renderer作为参考时钟,Audio Sample打时间戳,Audio数据流如果中途短缺(如果数据源自网络,可能出现网络阻塞情况),将导致Filter Graph的流时间停止不走。如果Audio Sample一开始就不打时间戳的,则Audio数据的中途短缺不会影响Filter Graph的流时间。
二. 单一视频流
Filter Graph如图2:

图2 单一视频流的Filter Graph
注意:紧靠Video Renderer的上一级Filter的Video输出Pin,其GetMediaType函数提供的Media Type的VIDEOINFOHEADER结构要求填写完整,不仅包括图像的宽度、高度、像素位数,还包括BITMAPINFOHEADER结构的大小(biSize,指定为sizeof(BITMAPINFOHEADER))、平面数(biPlanes,指定为1)。如果需要调色板, BITMAPINFOHEADER数据结构后面还要带上调色板数据;如果是16位的RGB格式,BITMAPINFOHEADER数据结构后面则要带上 RGB分量提取的掩码。代码参考如下:
VIDEOINFO mVideoInfo;
ZeroMemory(&mVideoInfo, sizeof(mVideoInfo));
mVideoInfo.AvgTimePerFrame = 333667;
mVideoInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
mVideoInfo.bmiHeader.biWidth = 352;
mVideoInfo.bmiHeader.biHeight = 240;
mVideoInfo.bmiHeader.biBitCount = 16;
mVideoInfo.bmiHeader.biPlanes = 1;
mVideoInfo.bmiHeader.biCompression = BI_BITFIELDS;
mVideoInfo.bmiHeader.biSizeImage = mVideoInfo.bmiHeader.biWidth *
mVideoInfo.bmiHeader.biHeight * mVideoInfo.bmiHeader.biBitCount / 8;
for (int i = 0; i < 3; i++) // Important for 16 bit RGB!
{
mVideoInfo.dwBitMasks[i] = bits565[i];
}
1. 使用Filter Graph Manager默认的参考时钟
注:如果Filter Graph中没有一个Filter实现IReferenceClock接口,则该Filter Graph默认使用系统时钟作为参考时钟。
1.1 Video Sample不打时间戳、连续送出
现象:视频以最快的速度播放。Video Renderer不发送Quality Control消息。流时间线性增加。
Msiavsrc.ax(tid 920) 2307 : stream time: 120000
Msiavsrc.ax(tid 920) 2309 : stream time: 140000
Msiavsrc.ax(tid 920) 2311 : stream time: 160000
Msiavsrc.ax(tid 920) 2314 : stream time: 190000
Msiavsrc.ax(tid 920) 2316 : stream time: 210000
Msiavsrc.ax(tid 920) 2318 : stream time: 230000
Msiavsrc.ax(tid 920) 2320 : stream time: 250000
……
Msiavsrc.ax(tid 920) 3569 : stream time: 12740000(最后一个Sample)
1.2 Video Sample不打时间戳、间隙送出(模拟网络阻塞情况)
现象:视频播放一顿一顿。Video Renderer不发送Quality Control消息。视频数据流的阻塞不会影响流时间。流时间线性增加,间隙休眠的时间反映在前后两次获得的流时间上。
Msiavsrc.ax(tid 970) 2385 : stream time: 680000
Msiavsrc.ax(tid 970) 2389 : stream time: 720000
Msiavsrc.ax(tid 970) 4390 : Sleep(2000)...(出现视频播放的停顿)
Msiavsrc.ax(tid 970) 4391 : stream time: 20740000(流时间反映出Sleep的2s)
Msiavsrc.ax(tid 970) 4393 : stream time: 20760000
Msiavsrc.ax(tid 970) 4395 : stream time: 20780000
……
Msiavsrc.ax(tid 970) 39826 : stream time: 375090000(最后一个Sample)
1.3 Video Sample打(连续)时间戳、连续送出
现象:视频连续播放。Video Renderer发送Quality Control消息进行反馈控制。流时间线性增加,两次获取的流时间差大致是一帧的显示时间。
Msiavsrc.ax(tid 970) 4105 : stream time: 3600000
Msiavsrc.ax(tid 970) 4106 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4139 : stream time: 3940000
Msiavsrc.ax(tid 970) 4140 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4171 : stream time: 4260000
Msiavsrc.ax(tid 970) 4172 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4205 : stream time: 4600000
Msiavsrc.ax(tid 970) 4206 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4238 : stream time: 4930000
Msiavsrc.ax(tid 970) 4239 : Quality control (Famine) received.
……
Msiavsrc.ax(tid 970) 21922 : stream time: 181770000(最后一个Sample)
1.4 Video Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
现象:播放较连续。Video Renderer发送Quality Control消息进行反馈控制。时间戳复位后有一个“快镜头”,相邻两次Sample发送的时间差较小(正常时应该是一帧图像的显示时间),说明 Video Renderer收到Sample后马上返回,以最快速度处理Sample,使Sample时间戳能够再次赶上流时间。
Msiavsrc.ax(tid 964) 2133 : stream time: 12280000
Msiavsrc.ax(tid 964) 2165 : stream time: 12600000
Msiavsrc.ax(tid 964) 2166 : Reset time stamp...
Msiavsrc.ax(tid 964) 2199 : stream time: 12940000(流时间递增缓慢)
Msiavsrc.ax(tid 964) 2201 : stream time: 12960000
Msiavsrc.ax(tid 964) 2203 : stream time: 12980000
Msiavsrc.ax(tid 964) 2205 : stream time: 13000000
Msiavsrc.ax(tid 964) 2208 : stream time: 13030000
Msiavsrc.ax(tid 964) 2210 : stream time: 13050000
Msiavsrc.ax(tid 964) 2212 : stream time: 13070000
Msiavsrc.ax(tid 964) 2214 : stream time: 13090000
……
Msiavsrc.ax(tid 964) 17748 : stream time: 168430000(最后一个Sample)
1.5 Video Sample打时间戳(时间戳超前流时间一个delta)、连续送出
现象:等待delta后播放连续。Video Renderer发送Quality Control消息进行反馈控制。
Msiavsrc.ax(tid 848) 821 : stream time: 4167195720000(随机值,此Sample送出后被Video Renderer阻塞)
Msiavsrc.ax(tid 848) 5828 : stream time: 49940000(delta在此反映出来)
Msiavsrc.ax(tid 848) 5860 : stream time: 50250000
Msiavsrc.ax(tid 848) 5892 : stream time: 50580000
Msiavsrc.ax(tid 848) 5927 : stream time: 50930000
……
Msiavsrc.ax(tid 848) 22677 : stream time: 218430000(最后一个Sample)
1.6 Video Sample打时间戳(时间戳随机乱序)、连续送出
现象:播放有断续、有快镜头。Video Renderer发送Quality Control消息进行反馈控制。整个播放过程中,如果新Sample的时间戳比流时间超前,则Sample会被Video Renderer阻塞住,直到流时间到达Sample时间后才开始播放;如果新Sample的时间戳比流时间滞后,Sample到达Video Renderer后会被立即播放,因此出现快镜头,直到Sample的时间戳赶上流时间后视频才恢复正常速度。总之,视频流不会影响参考时钟的正常运作。
Msiavsrc.ax(tid 610) 1774 : stream time: 5590000
Msiavsrc.ax(tid 610) 1807 : stream time: 5930000
Msiavsrc.ax(tid 610) 1808 : Add 5 second delta...
Msiavsrc.ax(tid 610) 1841 : stream time: 6270000(此Sample送出后阻塞)
Msiavsrc.ax(tid 610) 6873 : stream time: 56590000(流时间到达Sample上的时间戳后再继续播放)
Msiavsrc.ax(tid 610) 6906 : stream time: 56920000
Msiavsrc.ax(tid 610) 6940 : stream time: 57260000
……
Msiavsrc.ax(tid 610) 7440 : stream time: 62260000
Msiavsrc.ax(tid 610) 7473 : stream time: 62590000
Msiavsrc.ax(tid 610) 7474 : Add -3 second delta...
Msiavsrc.ax(tid 610) 7508 : stream time: 62940000(出现快镜头,Sample以很快的速度发送给Video Renderer)
Msiavsrc.ax(tid 610) 7509 : stream time: 62950000
Msiavsrc.ax(tid 610) 7511 : stream time: 62970000
Msiavsrc.ax(tid 610) 7512 : stream time: 62980000
Msiavsrc.ax(tid 610) 7513 : stream time: 62990000
……
Msiavsrc.ax(tid 610) 7563 : stream time: 63490000
Msiavsrc.ax(tid 610) 7564 : stream time: 63500000
Msiavsrc.ax(tid 610) 7566 : Do not add delta...
Msiavsrc.ax(tid 610) 7566 : stream time: 63520000
Msiavsrc.ax(tid 610) 7567 : stream time: 63530000
Msiavsrc.ax(tid 610) 7568 : stream time: 63540000
Msiavsrc.ax(tid 610) 7570 : stream time: 63560000
……
Msiavsrc.ax(tid 610) 7719 : stream time: 65050000
Msiavsrc.ax(tid 610) 7721 : stream time: 65070000
Msiavsrc.ax(tid 610) 7722 : stream time: 65080000
Msiavsrc.ax(tid 610) 7746 : stream time: 65320000(Sample时间戳终于赶上了流时间)
Msiavsrc.ax(tid 610) 7779 : stream time: 65650000
……
Msiavsrc.ax(tid 610) 19390 : stream time: 181760000(最后一个Sample)
1.7 Video Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
现象:视频播放一顿一顿。Video Renderer发送Quality Control消息进行反馈控制。无数据时,流时间仍然在走;于是紧接着下一个Sample到达Video Renderer时已经“迟到”,所以会出现快镜头。
Msiavsrc.ax(tid 678) 1667 : stream time: 8940000
Msiavsrc.ax(tid 678) 1700 : stream time: 9270000
Msiavsrc.ax(tid 678) 3701 : Sleep(2000)...(此时阻塞显示上一个Sample的图像)
Msiavsrc.ax(tid 678) 3702 : stream time: 29290000(出现快镜头)
Msiavsrc.ax(tid 678) 3704 : stream time: 29310000
Msiavsrc.ax(tid 678) 3706 : stream time: 29330000
……
Msiavsrc.ax(tid 678) 3762 : stream time: 29890000
Msiavsrc.ax(tid 678) 3766 : stream time: 29930000
Msiavsrc.ax(tid 678) 5767 : Sleep(2000)... (此时阻塞显示上一个Sample的图像)
Msiavsrc.ax(tid 678) 5768 : stream time: 49950000(出现快镜头)
Msiavsrc.ax(tid 678) 5770 : stream time: 49970000
Msiavsrc.ax(tid 678) 5772 : stream time: 49990000
……
Msiavsrc.ax(tid 678) 38788 : stream time: 380150000(最后一个Sample)
2. Filter Graph不使用参考时钟
现象:不管Video Sample打不打时间戳,也不管时间戳打得是否正确,视频都是以最快的速度播放。并且Video Renderer不发送Quality Control消息。如果Video Sample送出过程中有间隙性停顿,视频也会出现间隙性的停顿。
3. Filter Graph中残留(处于未连接状态)一个Audio Renderer
注:默认情况下,Audio Renderer会被选中为Filter Graph的参考时钟。
Filter Graph如图3:

图3 残留一个Audio Renderer的单一视频流Filter Graph
测试结果均与以系统时钟作为Filter Graph的参考时钟的情况类似。
小结:
v 在任何时候,Video Sample上的时间戳都不会影响Filter Graph的流时间。
v 如果Video Sample上没有时间戳,则Video Renderer以最快速度处理Sample数据;如果有时间戳,则根据时间戳以及当前的流时间来安排Sample内容(视频图像)的显示。若 Sample上的时间戳超前流时间,Video Renderer将该Sample阻塞,直到流时间到达Sample时间戳后再开始播放;若Sample上的时间戳滞后于流时间,Video Renderer将Sample内容立即显示后返回,以最快速度处理Sample,以使Sample时间戳尽快追赶流时间。
v 视频流播放过程中有一个Quality Control机制;Quality Control消息发送者是Video Renderer,反馈给数据发送线程,以加快或减慢数据发送速度,试图提高服务质量。
三. 混合音视频流
注:既然视频流不会影响Filter Graph的流时间,则视频流的播放情况不会影响到音频流的播放。本节主要讨论音频流播放情况对视频流播放的影响。
Filter Graph如图4:

图4 混合音视频流的Filter Graph
1. Filter Graph不使用参考时钟
现象:音频正常、连续播放,视频快镜头播放。音视频不同步!
2. Filter Graph使用参考时钟
2.1 Audio Sample不打时间戳
Audio Sample不打时间戳,音频流就不会影响Filter Graph的流时间。不管以Audio Renderer还是以系统时钟作为参考时钟,音视频均能同步、连续播放。
2.2 Audio Sample正常打时间戳
(1)Audio Renderer作为参考时钟
现象:音视频同步、连续播放。
(2)系统时钟作为参考时钟
现象:音视频同步、连续播放。
2.3 Audio Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
(1)Audio Renderer作为参考时钟
现象:Audio Sample时间戳复位后音视频不同步。由于Audio Sample时间戳复位后流时间不走了,所以视频播放停止(Video Sample的时间戳因超前流时间而被阻塞住),但音频仍然正常播放。因此造成音视频不同步。
(2)系统时钟作为参考时钟
现象:视频能够不受干扰地连续播放。音频在时间戳复位后有一部分数据(时间戳小于流时间的数据)被丢弃,所以播放中有一个跳变。
2.4 Audio Sample打时间戳(时间戳随机乱序)、连续送出
(1)Audio Renderer作为参考时钟
现象:音频连续播放。由于Audio Sample的时间戳将影响Filter Graph的流时间,导致视频的播放有时候出现快镜头,有时候出现停顿。最终音视频不同步。
(2)系统时钟作为参考时钟
现象:视频连续播放,音频播放不连续。因为Filter Graph的流时间独立运行,所以视频能连续播放。音频数据Sample时间戳小于流时间的将被丢弃,大于流时间的将被阻塞,因此总的播放效果就是断断续续。
2.5 Audio Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
(1)Audio Renderer作为参考时钟
现象:音视频均不能连续播放。因为在音频无数据送出时,Filter Graph的流时间是不走的,导致视频也停止播放(Video Sample的时间戳因超前流时间而被阻塞住);直到音频有数据了,流时间继续走动,视频也恢复播放。音频数据虽不能连续播放,但音频数据没有被丢失。
(2)系统时钟作为参考时钟
现象:视频连续播放,音频断断续续,并且部分音频数据被跳过不播放。因为Filter Graph的流时间独立运行,所以视频能连续播放。音频数据Sample时间戳小于流时间的将被丢弃。
陆其明 2004-09-09
一. 单一音频流
Filter Graph如图1:

图1 单一音频流的Filter Graph
注意:紧靠Audio Renderer的上一级Filter的Audio输出Pin,其GetMediaType函数提供的Media Type的WAVEFORMATEX结构要求填写完整,不仅包括音频格式(wFormatTag须指定为WAVE_FORMAT_PCM)、采样频率(nSamplesPerSec)、通道数(nChannels)、量化精度(wBitsPerSample),还包括由上述几个参数可以计算获得的 nBlockAlign和nAvgBytesPerSec。代码参考如下:
WAVEFORMATEX mWaveInfo;
ZeroMemory(&mWaveInfo, sizeof(WAVEFORMATEX));
mWaveInfo.wFormatTag = WAVE_FORMAT_PCM;
mWaveInfo.nSamplesPerSec = 44100;
mWaveInfo.nChannels = 2;
mWaveInfo.wBitsPerSample = 16;
mWaveInfo.nBlockAlign = mWaveInfo.nChannels * mWaveInfo.wBitsPerSample / 8;
mWaveInfo.nAvgBytesPerSec = mWaveInfo.nSamplesPerSec * mWaveInfo.nBlockAlign;
1. 使用Filter Graph Manager默认的参考时钟(Audio Renderer作为参考时钟)
确认Filter Graph的参考时钟
HRESULT CheckReferenceClock(void)
{
if (!m_pClock)
{
DbgLog((LOG_TRACE, 0, TEXT("No reference clock.")));
return E_FAIL;
}
// Get downstream connected filter
IPin * pin = mAudioOutPin->GetConnected();
PIN_INFO pinInfo;
HRESULT hr = pin->QueryPinInfo(&pinInfo);
if (SUCCEEDED(hr))
{
// Audio renderer acts as reference clock
pinInfo.pFilter->Release();
BOOL isSame = IsEqualObject(m_pClock, pinInfo.pFilter);
if (isSame)
{
DbgLog((LOG_TRACE, 0, TEXT("Audio renderer acts as reference clock.")));
return NOERROR;
}
}
// Is CLSID_SystemClock?
IPersist * pPersist = NULL;
hr = m_pClock->QueryInterface(IID_IPersist, (void**) &pPersist);
if (SUCCEEDED(hr))
{
pPersist->Release();
CLSID clsid;
pPersist->GetClassID(&clsid);
BOOL isSame = (CLSID_SystemClock == clsid);
if (isSame)
{
DbgLog((LOG_TRACE, 0, TEXT("System clock acts as reference clock.")));
return NOERROR;
}
}
return NOERROR;
}
1.1 Audio Sample(0.25s数据)不打时间戳、连续送出
现象:播放正常。流时间(从参考时钟获得)线性增加。
MsiRlsrc.ax(tid 870) 10980 : stream time: 90920000
MsiRlsrc.ax(tid 870) 11181 : stream time: 92930000
MsiRlsrc.ax(tid 870) 11483 : stream time: 95950000
MsiRlsrc.ax(tid 870) 11684 : stream time: 97960000
MsiRlsrc.ax(tid 870) 11986 : stream time: 100980000
……
MsiRlsrc.ax(tid 870) 29113 : stream time: 270520000(最后一个Sample)
注:上述流时间均在输出Pin数据线程调用FillBuffer函数时获取。(下同。)
1.2 Audio Sample不打时间戳、间隙送出(模拟网络阻塞情况)
现象:有数据时播放正常,间隙性静音。流时间线性增加,间隙休眠的时间反映在前后两次获得的流时间上。
MsiRlsrc.ax(tid 578) 12292 : stream time: 106000000
MsiRlsrc.ax(tid 578) 12493 : stream time: 108010000
MsiRlsrc.ax(tid 578) 15494 : Sleep(3000)... (出现声音播放的间隙静音)
MsiRlsrc.ax(tid 578) 15511 : stream time: 138190000(反映出Sleep的3s,Sleep的时候流时间仍然在走)
MsiRlsrc.ax(tid 578) 15612 : stream time: 139200000
……
MsiRlsrc.ax(tid 578) 38727 : stream time: 374570000(最后一个Sample)
1.3 Audio Sample打(连续)时间戳、连续送出
现象:播放正常。流时间折线上升(周期性出现几个连续Sample发送时流时间停止不走)。
MsiRlsrc.ax(tid 4b0) 11282 : stream time: 93489570
MsiRlsrc.ax(tid 4b0) 11483 : stream time: 102985035
MsiRlsrc.ax(tid 4b0) 11785 : stream time: 103507279
MsiRlsrc.ax(tid 4b0) 11986 : stream time: 103507279
MsiRlsrc.ax(tid 4b0) 12187 : stream time: 103507279
MsiRlsrc.ax(tid 4b0) 12489 : stream time: 113049003
MsiRlsrc.ax(tid 4b0) 12690 : stream time: 113049003
MsiRlsrc.ax(tid 4b0) 12992 : stream time: 113078028
MsiRlsrc.ax(tid 4b0) 13193 : stream time: 113078028
……
MsiRlsrc.ax(tid 4b0) 28351 : stream time: 263460114 (最后一个Sample)
1.4 Audio Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
现象:播放正常。当时间戳复位后,流时间停止走动,直到复位后重打的时间戳再次达到复位时的流时间,之后流时间继续走动。Audio Sample上的时间戳会影响流时间!
MsiRlsrc.ax(tid 954) 9448 : stream time: 82866667
MsiRlsrc.ax(tid 954) 9750 : stream time: 83388005
MsiRlsrc.ax(tid 954) 9951 : stream time: 83388005
MsiRlsrc.ax(tid 954) 9952 : Reset time stamp...
MsiRlsrc.ax(tid 954) 10253 : stream time: 83424286
MsiRlsrc.ax(tid 954) 10454 : stream time: 83424286
MsiRlsrc.ax(tid 954) 10756 : stream time: 83424286
MsiRlsrc.ax(tid 954) 10957 : stream time: 83424286
MsiRlsrc.ax(tid 954) 11259 : stream time: 83424286
MsiRlsrc.ax(tid 954) 11460 : stream time: 83424286
MsiRlsrc.ax(tid 954) 11762 : stream time: 83424286
…… (流时间停止在83424286)
……
MsiRlsrc.ax(tid 954) 19205 : stream time: 83424286
MsiRlsrc.ax(tid 954) 19507 : stream time: 83458527 (流时间继续走动)
MsiRlsrc.ax(tid 954) 19708 : stream time: 83458527
MsiRlsrc.ax(tid 954) 20010 : stream time: 83488005
MsiRlsrc.ax(tid 954) 20211 : stream time: 83488005
MsiRlsrc.ax(tid 954) 20412 : stream time: 92508844
……
MsiRlsrc.ax(tid 954) 28258 : stream time: 163470091(最后一个Sample)
1.5 Audio Sample打时间戳(时间戳超前流时间一个delta)、连续送出
现象:声音等待delta之后再播放,播放正常。(设delta=5s)整个流时间为:原始流时间+delta。
MsiRlsrc.ax(tid 25c) 4077 : stream time: 340000
MsiRlsrc.ax(tid 25c) 4178 : stream time: 1350000(这个Sample送出后阻塞)
MsiRlsrc.ax(tid 25c) 9308 : stream time: 52700000(delta在此反映出来)
MsiRlsrc.ax(tid 25c) 9610 : stream time: 53213402
MsiRlsrc.ax(tid 25c) 9811 : stream time: 53213402
MsiRlsrc.ax(tid 25c) 10113 : stream time: 53241520
MsiRlsrc.ax(tid 25c) 10314 : stream time: 62750567
MsiRlsrc.ax(tid 25c) 10616 : stream time: 63270998
MsiRlsrc.ax(tid 25c) 10817 : stream time: 63270998
MsiRlsrc.ax(tid 25c) 11118 : stream time: 63290477
……
MsiRlsrc.ax(tid 25c) 36064 : stream time: 313247642(最后一个Sample)
1.6 Audio Sample打时间戳(时间戳随机乱序)、连续送出
现象:播放正常。播放中,即使时间戳不对,声音照常播放。如果新Sample的时间戳比上一个Sample的时间戳超前,流时间会被修正到新Sample的时间;如果新Sample的时间戳滞后上一个Sample的时间戳,则流时间在当前时刻停止,直到Sample时间戳再次达到停止时刻的流时间。这一次取得流时间总是大于或等于上一次取得流时间,不可能小于!
MsiRlsrc.ax(tid 8f4) 4863 : stream time: 33095488
MsiRlsrc.ax(tid 8f4) 5064 : stream time: 33095488
MsiRlsrc.ax(tid 8f4) 5065 : Add 5 second delta...
MsiRlsrc.ax(tid 8f4) 5366 : stream time: 33129502
MsiRlsrc.ax(tid 8f4) 5567 : stream time: 92632200(5sdelta修正在流时间上,仍连续播放)
……
MsiRlsrc.ax(tid 8f4) 10094 : stream time: 133389819
MsiRlsrc.ax(tid 8f4) 10096 : Add -3 second delta...
MsiRlsrc.ax(tid 8f4) 10395 : stream time: 133424740(流时间停止不走)
MsiRlsrc.ax(tid 8f4) 10597 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 10898 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 11100 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 11401 : stream time: 133424740
……
MsiRlsrc.ax(tid 8f4) 18046 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 18247 : stream time: 133424740
MsiRlsrc.ax(tid 8f4) 18549 : stream time: 143400477(流时间继续走动)
MsiRlsrc.ax(tid 8f4) 18750 : stream time: 143400477
MsiRlsrc.ax(tid 8f4) 18750 : Do not add delta...(时间戳不加delta)
MsiRlsrc.ax(tid 8f4) 19052 : stream time: 143435397
MsiRlsrc.ax(tid 8f4) 19253 : stream time: 172941724(流时间根据Sample时间戳进行修正?)
MsiRlsrc.ax(tid 8f4) 19555 : stream time: 183459887
MsiRlsrc.ax(tid 8f4) 19756 : stream time: 183459887
MsiRlsrc.ax(tid 8f4) 20058 : stream time: 183489819
……
MsiRlsrc.ax(tid 8f4) 28306 : stream time: 263471452(最后一个Sample)
1.7 Audio Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
现象:有数据时播放正常,间隙性静音。在无数据时,流时间并不走动!(请同时参考1.2进行比较。)
MsiRlsrc.ax(tid 86c) 4177 : stream time: 23056939
MsiRlsrc.ax(tid 86c) 4378 : stream time: 32565080
MsiRlsrc.ax(tid 86c) 4679 : stream time: 33075964
MsiRlsrc.ax(tid 86c) 4881 : stream time: 33075964
MsiRlsrc.ax(tid 86c) 7882 : Sleep(3000)...(出现声音播放的间隙静音)
MsiRlsrc.ax(tid 86c) 7899 : stream time: 40170000(没有反映出Sleep的3s,说明Sleep的时候流时间没有走动)
MsiRlsrc.ax(tid 86c) 8000 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8100 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8201 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8302 : stream time: 48500000
MsiRlsrc.ax(tid 86c) 8503 : stream time: 53315874
……
MsiRlsrc.ax(tid 86c) 38578 : stream time: 263365556(最后一个Sample)
1.8 将音频的采样频率写错(原来44.1K,现改成32K或48K)
现象:声音播放变调。
2. Filter Graph使用系统时钟(组件)
2.1 Audio Sample(0.25s数据)不打时间戳、连续送出
现象:同1.1。
2.2 Audio Sample不打时间戳、间隙送出(模拟网络阻塞情况)
现象:同1.2。
2.3 Audio Sample打(连续)时间戳、连续送出
现象:播放正常。流时间线性增加,没有出现1.3的“折线上升”现象。另外一个特点,流时间的尾数比较“干净”。
Msiavsrc.ax(tid 714) 14505 : stream time: 91880000
Msiavsrc.ax(tid 714) 14807 : stream time: 94900000
Msiavsrc.ax(tid 714) 15008 : stream time: 96910000
Msiavsrc.ax(tid 714) 15310 : stream time: 99930000
Msiavsrc.ax(tid 714) 15511 : stream time: 101940000
Msiavsrc.ax(tid 714) 15812 : stream time: 104950000
Msiavsrc.ax(tid 714) 16014 : stream time: 106970000
Msiavsrc.ax(tid 714) 16315 : stream time: 109980000
……
Msiavsrc.ax(tid 714) 16315 : stream time: 267900000(最后一个Sample)
2.4 Audio Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
现象:时间戳复位后播放不连续,有部分数据没有被播放。短暂波动后,后续数据仍能正常播放。时间戳复位后的一段时间内流时间仍在缓慢走动。(注:“缓慢走动”说明输出Pin发送Sample的速度很快,也就是说这些Sample达到Audio Renderer后可能被直接丢弃,而并没有根据Sample上的时间戳去安排播放。)
Msiavsrc.ax(tid 21c) 12998 : stream time: 82820000
Msiavsrc.ax(tid 21c) 13199 : stream time: 84830000
Msiavsrc.ax(tid 21c) 13501 : stream time: 87850000
Msiavsrc.ax(tid 21c) 13502 : Reset time stamp...
Msiavsrc.ax(tid 21c) 13702 : stream time: 89860000(流时间仍在缓慢走动)
Msiavsrc.ax(tid 21c) 13703 : stream time: 89870000
Msiavsrc.ax(tid 21c) 13705 : stream time: 89890000
Msiavsrc.ax(tid 21c) 13705 : stream time: 89890000
Msiavsrc.ax(tid 21c) 13706 : stream time: 89900000
Msiavsrc.ax(tid 21c) 13707 : stream time: 89910000
Msiavsrc.ax(tid 21c) 13707 : stream time: 89910000
……
Msiavsrc.ax(tid 21c) 13707 : stream time: 220620000(最后一个Sample)
2.5 Audio Sample打时间戳(时间戳超前流时间一个delta)、连续送出
现象:同1.5。
2.6 Audio Sample打时间戳(时间戳随机乱序)、连续送出
现象:播放断断续续。如果新Sample的时间戳比上一个Sample的时间戳超前,静音等待,直到流时间达到Sample上时间戳再开始播放;如果新 Sample的时间戳滞后上一个Sample的时间戳,则流时间非常缓慢地增加,跳过部分数据不播放,直到Sample时间戳达到当前的流时间。
Msiavsrc.ax(tid 794) 8169 : stream time: 37570000
Msiavsrc.ax(tid 794) 8171 : Add 5 second delta...
Msiavsrc.ax(tid 794) 8471 : stream time: 40590000(此Sample发出后就阻塞(静音),等待流时间达到Sample上的时间戳再开始播放)
Msiavsrc.ax(tid 794) 13701 : stream time: 92890000(5sdelta反映在流时间上,后续数据连续播放)
Msiavsrc.ax(tid 794) 13902 : stream time: 94900000
……
Msiavsrc.ax(tid 794) 18127 : stream time: 137150000
Msiavsrc.ax(tid 794) 18127 : Add -3 second delta...
Msiavsrc.ax(tid 794) 18328 : stream time: 139160000(流时间仍在缓慢走动,声音播放不正常,一些数据没有播放)
Msiavsrc.ax(tid 794) 18329 : stream time: 139170000
Msiavsrc.ax(tid 794) 18329 : stream time: 139170000
Msiavsrc.ax(tid 794) 18330 : stream time: 139180000
Msiavsrc.ax(tid 794) 18331 : stream time: 139190000
Msiavsrc.ax(tid 794) 18331 : stream time: 139190000
Msiavsrc.ax(tid 794) 19133 : stream time: 147210000
……
Msiavsrc.ax(tid 794) 19133 : Do not add delta...
Msiavsrc.ax(tid 794) 19334 : stream time: 149220000(此Sample发出后就阻塞(静音),等待流时间达到Sample上的时间戳再开始播放)
Msiavsrc.ax(tid 794) 21849 : stream time: 174370000(与上次流时间有个较大跨度)
Msiavsrc.ax(tid 794) 22854 : stream time: 184420000
Msiavsrc.ax(tid 794) 23056 : stream time: 186440000
……
Msiavsrc.ax(tid 794) 31505 : stream time: 270930000(最后一个Sample)
2.7 Audio Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
现象:播放断断续续。无数据时,静音等待,此时流时间仍正常走动;随后数据到来时一部分数据会被跳过不播放,数据不播放时流时间走动非常缓慢;最新的Sample时间戳赶上流时间候仍然能正常播放。
Msiavsrc.ax(tid 768) 9092 : stream time: 32520000
Msiavsrc.ax(tid 768) 9394 : stream time: 35540000
Msiavsrc.ax(tid 768) 9595 : stream time: 37550000
Msiavsrc.ax(tid 768) 12596 : Sleep(3000)...(静音等待,流时间在走动)
Msiavsrc.ax(tid 768) 12596 : stream time: 67560000(流时间非常缓慢增加,一些数据不播放)
Msiavsrc.ax(tid 768) 12597 : stream time: 67570000
Msiavsrc.ax(tid 768) 12597 : stream time: 67570000
Msiavsrc.ax(tid 768) 12598 : stream time: 67580000
Msiavsrc.ax(tid 768) 12599 : stream time: 67590000
Msiavsrc.ax(tid 768) 12600 : stream time: 67600000
Msiavsrc.ax(tid 768) 12600 : stream time: 67600000
Msiavsrc.ax(tid 768) 12601 : stream time: 67610000
Msiavsrc.ax(tid 768) 12602 : stream time: 67620000
Msiavsrc.ax(tid 768) 12613 : stream time: 67730000(流时间增加幅度增大,开始慢慢正常播放)
Msiavsrc.ax(tid 768) 12713 : stream time: 68730000
Msiavsrc.ax(tid 768) 12814 : stream time: 69740000
Msiavsrc.ax(tid 768) 12915 : stream time: 70750000
Msiavsrc.ax(tid 768) 13015 : stream time: 71750000
Msiavsrc.ax(tid 768) 13216 : stream time: 73760000
Msiavsrc.ax(tid 768) 13417 : stream time: 75770000
Msiavsrc.ax(tid 768) 13719 : stream time: 78790000
Msiavsrc.ax(tid 768) 13920 : stream time: 80800000
Msiavsrc.ax(tid 768) 14222 : stream time: 83820000
Msiavsrc.ax(tid 768) 14423 : stream time: 85830000
Msiavsrc.ax(tid 768) 17424 : Sleep(3000)... (静音等待,流时间在走动)
Msiavsrc.ax(tid 768) 17424 : stream time: 115840000(流时间非常缓慢增加,一些数据不播放)
Msiavsrc.ax(tid 768) 17425 : stream time: 115850000
Msiavsrc.ax(tid 768) 17426 : stream time: 115860000
Msiavsrc.ax(tid 768) 17427 : stream time: 115870000
Msiavsrc.ax(tid 768) 17427 : stream time: 115870000
……
Msiavsrc.ax(tid 768) 32328 : stream time: 264880000(最后一个Sample)
3. Filter Graph不使用参考时钟
现象:不管Audio Sample打不打时间戳,也不管时间戳打得是否正确,声音都能正常播放。如果Audio Sample送出过程中有间隙性停顿,声音播放也会有间隙性的静音。
小结:
v Filter Graph使用Audio Renderer作为参考时钟时,Audio Sample上的时间戳可能会影响整个Filter Graph的流时间;使用系统时钟作为参考时钟时则不会。
v 以Audio Renderer作为参考时钟,音频数据的播放性能较好;不管Audio Sample上有无时间戳,不管时间戳是否正确,一般都能连续播放。但以系统时钟作为参考时钟时,Audio Renderer会严格按照Sample上的时间戳来播放,早到的数据会被阻塞,直到流时间到达Sample时间后再播放,晚到的数据会被直接丢弃,因此整体的播放效果不佳。
v 以Audio Renderer作为参考时钟,Audio Sample打时间戳,Audio数据流如果中途短缺(如果数据源自网络,可能出现网络阻塞情况),将导致Filter Graph的流时间停止不走。如果Audio Sample一开始就不打时间戳的,则Audio数据的中途短缺不会影响Filter Graph的流时间。
二. 单一视频流
Filter Graph如图2:

图2 单一视频流的Filter Graph
注意:紧靠Video Renderer的上一级Filter的Video输出Pin,其GetMediaType函数提供的Media Type的VIDEOINFOHEADER结构要求填写完整,不仅包括图像的宽度、高度、像素位数,还包括BITMAPINFOHEADER结构的大小(biSize,指定为sizeof(BITMAPINFOHEADER))、平面数(biPlanes,指定为1)。如果需要调色板, BITMAPINFOHEADER数据结构后面还要带上调色板数据;如果是16位的RGB格式,BITMAPINFOHEADER数据结构后面则要带上 RGB分量提取的掩码。代码参考如下:
VIDEOINFO mVideoInfo;
ZeroMemory(&mVideoInfo, sizeof(mVideoInfo));
mVideoInfo.AvgTimePerFrame = 333667;
mVideoInfo.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
mVideoInfo.bmiHeader.biWidth = 352;
mVideoInfo.bmiHeader.biHeight = 240;
mVideoInfo.bmiHeader.biBitCount = 16;
mVideoInfo.bmiHeader.biPlanes = 1;
mVideoInfo.bmiHeader.biCompression = BI_BITFIELDS;
mVideoInfo.bmiHeader.biSizeImage = mVideoInfo.bmiHeader.biWidth *
mVideoInfo.bmiHeader.biHeight * mVideoInfo.bmiHeader.biBitCount / 8;
for (int i = 0; i < 3; i++) // Important for 16 bit RGB!
{
mVideoInfo.dwBitMasks[i] = bits565[i];
}
1. 使用Filter Graph Manager默认的参考时钟
注:如果Filter Graph中没有一个Filter实现IReferenceClock接口,则该Filter Graph默认使用系统时钟作为参考时钟。
1.1 Video Sample不打时间戳、连续送出
现象:视频以最快的速度播放。Video Renderer不发送Quality Control消息。流时间线性增加。
Msiavsrc.ax(tid 920) 2307 : stream time: 120000
Msiavsrc.ax(tid 920) 2309 : stream time: 140000
Msiavsrc.ax(tid 920) 2311 : stream time: 160000
Msiavsrc.ax(tid 920) 2314 : stream time: 190000
Msiavsrc.ax(tid 920) 2316 : stream time: 210000
Msiavsrc.ax(tid 920) 2318 : stream time: 230000
Msiavsrc.ax(tid 920) 2320 : stream time: 250000
……
Msiavsrc.ax(tid 920) 3569 : stream time: 12740000(最后一个Sample)
1.2 Video Sample不打时间戳、间隙送出(模拟网络阻塞情况)
现象:视频播放一顿一顿。Video Renderer不发送Quality Control消息。视频数据流的阻塞不会影响流时间。流时间线性增加,间隙休眠的时间反映在前后两次获得的流时间上。
Msiavsrc.ax(tid 970) 2385 : stream time: 680000
Msiavsrc.ax(tid 970) 2389 : stream time: 720000
Msiavsrc.ax(tid 970) 4390 : Sleep(2000)...(出现视频播放的停顿)
Msiavsrc.ax(tid 970) 4391 : stream time: 20740000(流时间反映出Sleep的2s)
Msiavsrc.ax(tid 970) 4393 : stream time: 20760000
Msiavsrc.ax(tid 970) 4395 : stream time: 20780000
……
Msiavsrc.ax(tid 970) 39826 : stream time: 375090000(最后一个Sample)
1.3 Video Sample打(连续)时间戳、连续送出
现象:视频连续播放。Video Renderer发送Quality Control消息进行反馈控制。流时间线性增加,两次获取的流时间差大致是一帧的显示时间。
Msiavsrc.ax(tid 970) 4105 : stream time: 3600000
Msiavsrc.ax(tid 970) 4106 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4139 : stream time: 3940000
Msiavsrc.ax(tid 970) 4140 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4171 : stream time: 4260000
Msiavsrc.ax(tid 970) 4172 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4205 : stream time: 4600000
Msiavsrc.ax(tid 970) 4206 : Quality control (Famine) received.
Msiavsrc.ax(tid 970) 4238 : stream time: 4930000
Msiavsrc.ax(tid 970) 4239 : Quality control (Famine) received.
……
Msiavsrc.ax(tid 970) 21922 : stream time: 181770000(最后一个Sample)
1.4 Video Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
现象:播放较连续。Video Renderer发送Quality Control消息进行反馈控制。时间戳复位后有一个“快镜头”,相邻两次Sample发送的时间差较小(正常时应该是一帧图像的显示时间),说明 Video Renderer收到Sample后马上返回,以最快速度处理Sample,使Sample时间戳能够再次赶上流时间。
Msiavsrc.ax(tid 964) 2133 : stream time: 12280000
Msiavsrc.ax(tid 964) 2165 : stream time: 12600000
Msiavsrc.ax(tid 964) 2166 : Reset time stamp...
Msiavsrc.ax(tid 964) 2199 : stream time: 12940000(流时间递增缓慢)
Msiavsrc.ax(tid 964) 2201 : stream time: 12960000
Msiavsrc.ax(tid 964) 2203 : stream time: 12980000
Msiavsrc.ax(tid 964) 2205 : stream time: 13000000
Msiavsrc.ax(tid 964) 2208 : stream time: 13030000
Msiavsrc.ax(tid 964) 2210 : stream time: 13050000
Msiavsrc.ax(tid 964) 2212 : stream time: 13070000
Msiavsrc.ax(tid 964) 2214 : stream time: 13090000
……
Msiavsrc.ax(tid 964) 17748 : stream time: 168430000(最后一个Sample)
1.5 Video Sample打时间戳(时间戳超前流时间一个delta)、连续送出
现象:等待delta后播放连续。Video Renderer发送Quality Control消息进行反馈控制。
Msiavsrc.ax(tid 848) 821 : stream time: 4167195720000(随机值,此Sample送出后被Video Renderer阻塞)
Msiavsrc.ax(tid 848) 5828 : stream time: 49940000(delta在此反映出来)
Msiavsrc.ax(tid 848) 5860 : stream time: 50250000
Msiavsrc.ax(tid 848) 5892 : stream time: 50580000
Msiavsrc.ax(tid 848) 5927 : stream time: 50930000
……
Msiavsrc.ax(tid 848) 22677 : stream time: 218430000(最后一个Sample)
1.6 Video Sample打时间戳(时间戳随机乱序)、连续送出
现象:播放有断续、有快镜头。Video Renderer发送Quality Control消息进行反馈控制。整个播放过程中,如果新Sample的时间戳比流时间超前,则Sample会被Video Renderer阻塞住,直到流时间到达Sample时间后才开始播放;如果新Sample的时间戳比流时间滞后,Sample到达Video Renderer后会被立即播放,因此出现快镜头,直到Sample的时间戳赶上流时间后视频才恢复正常速度。总之,视频流不会影响参考时钟的正常运作。
Msiavsrc.ax(tid 610) 1774 : stream time: 5590000
Msiavsrc.ax(tid 610) 1807 : stream time: 5930000
Msiavsrc.ax(tid 610) 1808 : Add 5 second delta...
Msiavsrc.ax(tid 610) 1841 : stream time: 6270000(此Sample送出后阻塞)
Msiavsrc.ax(tid 610) 6873 : stream time: 56590000(流时间到达Sample上的时间戳后再继续播放)
Msiavsrc.ax(tid 610) 6906 : stream time: 56920000
Msiavsrc.ax(tid 610) 6940 : stream time: 57260000
……
Msiavsrc.ax(tid 610) 7440 : stream time: 62260000
Msiavsrc.ax(tid 610) 7473 : stream time: 62590000
Msiavsrc.ax(tid 610) 7474 : Add -3 second delta...
Msiavsrc.ax(tid 610) 7508 : stream time: 62940000(出现快镜头,Sample以很快的速度发送给Video Renderer)
Msiavsrc.ax(tid 610) 7509 : stream time: 62950000
Msiavsrc.ax(tid 610) 7511 : stream time: 62970000
Msiavsrc.ax(tid 610) 7512 : stream time: 62980000
Msiavsrc.ax(tid 610) 7513 : stream time: 62990000
……
Msiavsrc.ax(tid 610) 7563 : stream time: 63490000
Msiavsrc.ax(tid 610) 7564 : stream time: 63500000
Msiavsrc.ax(tid 610) 7566 : Do not add delta...
Msiavsrc.ax(tid 610) 7566 : stream time: 63520000
Msiavsrc.ax(tid 610) 7567 : stream time: 63530000
Msiavsrc.ax(tid 610) 7568 : stream time: 63540000
Msiavsrc.ax(tid 610) 7570 : stream time: 63560000
……
Msiavsrc.ax(tid 610) 7719 : stream time: 65050000
Msiavsrc.ax(tid 610) 7721 : stream time: 65070000
Msiavsrc.ax(tid 610) 7722 : stream time: 65080000
Msiavsrc.ax(tid 610) 7746 : stream time: 65320000(Sample时间戳终于赶上了流时间)
Msiavsrc.ax(tid 610) 7779 : stream time: 65650000
……
Msiavsrc.ax(tid 610) 19390 : stream time: 181760000(最后一个Sample)
1.7 Video Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
现象:视频播放一顿一顿。Video Renderer发送Quality Control消息进行反馈控制。无数据时,流时间仍然在走;于是紧接着下一个Sample到达Video Renderer时已经“迟到”,所以会出现快镜头。
Msiavsrc.ax(tid 678) 1667 : stream time: 8940000
Msiavsrc.ax(tid 678) 1700 : stream time: 9270000
Msiavsrc.ax(tid 678) 3701 : Sleep(2000)...(此时阻塞显示上一个Sample的图像)
Msiavsrc.ax(tid 678) 3702 : stream time: 29290000(出现快镜头)
Msiavsrc.ax(tid 678) 3704 : stream time: 29310000
Msiavsrc.ax(tid 678) 3706 : stream time: 29330000
……
Msiavsrc.ax(tid 678) 3762 : stream time: 29890000
Msiavsrc.ax(tid 678) 3766 : stream time: 29930000
Msiavsrc.ax(tid 678) 5767 : Sleep(2000)... (此时阻塞显示上一个Sample的图像)
Msiavsrc.ax(tid 678) 5768 : stream time: 49950000(出现快镜头)
Msiavsrc.ax(tid 678) 5770 : stream time: 49970000
Msiavsrc.ax(tid 678) 5772 : stream time: 49990000
……
Msiavsrc.ax(tid 678) 38788 : stream time: 380150000(最后一个Sample)
2. Filter Graph不使用参考时钟
现象:不管Video Sample打不打时间戳,也不管时间戳打得是否正确,视频都是以最快的速度播放。并且Video Renderer不发送Quality Control消息。如果Video Sample送出过程中有间隙性停顿,视频也会出现间隙性的停顿。
3. Filter Graph中残留(处于未连接状态)一个Audio Renderer
注:默认情况下,Audio Renderer会被选中为Filter Graph的参考时钟。
Filter Graph如图3:

图3 残留一个Audio Renderer的单一视频流Filter Graph
测试结果均与以系统时钟作为Filter Graph的参考时钟的情况类似。
小结:
v 在任何时候,Video Sample上的时间戳都不会影响Filter Graph的流时间。
v 如果Video Sample上没有时间戳,则Video Renderer以最快速度处理Sample数据;如果有时间戳,则根据时间戳以及当前的流时间来安排Sample内容(视频图像)的显示。若 Sample上的时间戳超前流时间,Video Renderer将该Sample阻塞,直到流时间到达Sample时间戳后再开始播放;若Sample上的时间戳滞后于流时间,Video Renderer将Sample内容立即显示后返回,以最快速度处理Sample,以使Sample时间戳尽快追赶流时间。
v 视频流播放过程中有一个Quality Control机制;Quality Control消息发送者是Video Renderer,反馈给数据发送线程,以加快或减慢数据发送速度,试图提高服务质量。
三. 混合音视频流
注:既然视频流不会影响Filter Graph的流时间,则视频流的播放情况不会影响到音频流的播放。本节主要讨论音频流播放情况对视频流播放的影响。
Filter Graph如图4:

图4 混合音视频流的Filter Graph
1. Filter Graph不使用参考时钟
现象:音频正常、连续播放,视频快镜头播放。音视频不同步!
2. Filter Graph使用参考时钟
2.1 Audio Sample不打时间戳
Audio Sample不打时间戳,音频流就不会影响Filter Graph的流时间。不管以Audio Renderer还是以系统时钟作为参考时钟,音视频均能同步、连续播放。
2.2 Audio Sample正常打时间戳
(1)Audio Renderer作为参考时钟
现象:音视频同步、连续播放。
(2)系统时钟作为参考时钟
现象:音视频同步、连续播放。
2.3 Audio Sample打时间戳(中途复位一次,时间戳从0重打)、连续送出
(1)Audio Renderer作为参考时钟
现象:Audio Sample时间戳复位后音视频不同步。由于Audio Sample时间戳复位后流时间不走了,所以视频播放停止(Video Sample的时间戳因超前流时间而被阻塞住),但音频仍然正常播放。因此造成音视频不同步。
(2)系统时钟作为参考时钟
现象:视频能够不受干扰地连续播放。音频在时间戳复位后有一部分数据(时间戳小于流时间的数据)被丢弃,所以播放中有一个跳变。
2.4 Audio Sample打时间戳(时间戳随机乱序)、连续送出
(1)Audio Renderer作为参考时钟
现象:音频连续播放。由于Audio Sample的时间戳将影响Filter Graph的流时间,导致视频的播放有时候出现快镜头,有时候出现停顿。最终音视频不同步。
(2)系统时钟作为参考时钟
现象:视频连续播放,音频播放不连续。因为Filter Graph的流时间独立运行,所以视频能连续播放。音频数据Sample时间戳小于流时间的将被丢弃,大于流时间的将被阻塞,因此总的播放效果就是断断续续。
2.5 Audio Sample打(连续)时间戳、间隙送出(模拟网络阻塞情况)
(1)Audio Renderer作为参考时钟
现象:音视频均不能连续播放。因为在音频无数据送出时,Filter Graph的流时间是不走的,导致视频也停止播放(Video Sample的时间戳因超前流时间而被阻塞住);直到音频有数据了,流时间继续走动,视频也恢复播放。音频数据虽不能连续播放,但音频数据没有被丢失。
(2)系统时钟作为参考时钟
现象:视频连续播放,音频断断续续,并且部分音频数据被跳过不播放。因为Filter Graph的流时间独立运行,所以视频能连续播放。音频数据Sample时间戳小于流时间的将被丢弃。

浙公网安备 33010602011771号