编者:李国帅

qq:9611153 微信lgs9611153

时间:2014/2/26 13:19:55

背景原因:

数年前资料,使用directshow播放录像文件,发生过快现象。其中一个原因是由质量控制引起的。

问题分析:

如果快速播放文件的话,也不能正常显示视频。

远程回放的时候快放现象,实际播放的时间比想要播放的时间短很多。

不能使用sleep暂停播放,那样的话视频也不会正常显示。

并且可能出现EC_QUALITY_CHANGE事件,一旦出现视频就会出现快放,直到文件结束,并且图像不再继续。

[1520] CMyPlayer::OnNotifyGraph eventCode=EC_QUALITY_CHANGE 11

[1520] CVideoOutPin::FillBuffer:Last WasteInMS Need=39 True=6,rtBeginPos=1199888 m_rtlastBeginPos=800000 rtEndPos=1999888,TimeStamp last=39600,now=46800

[1520] CVideoOutPin::FillBuffer:Last WasteInMS Need=80 True=6,rtBeginPos=1999888 m_rtlastBeginPos=1199888 rtEndPos=2799888,TimeStamp last=46800,now=54000

[1520] CVideoOutPin::FillBuffer:Last WasteInMS Need=80 True=6,rtBeginPos=2799888 m_rtlastBeginPos=1999888 rtEndPos=3200000,TimeStamp last=54000,now=57601

下面的消耗时间全部是6毫秒。对于从网络获取的数据,丢上一两帧是正常的,但是因此就不再播放是不合理的。

所以,播放的时候最好按照帧率进行播放,而不是推测帧率按照帧率来播放,太复杂,并且难以控制。

A filter sends this event if it drops samples in response to a quality control message.

It sends the event only when it adjusts the quality level, not for each sample that it

drops. For more information, see Quality-Control Management.

EC_QUALITY_CHANGE

(过滤图为了质量控制丢桢)

The graph is dropping samples, for quality control.

A filter sends this event if it drops samples in response to a quality control message.

It sends the event only when it adjusts the quality level, not for each sample that it drops.

This message means normally that the renderer is dropping samples (i.e. they are arriving too late, meaning the CPU is overloaded).

如果调高远程桌面venderer的显示效果。

需要调低分辨率,帧率吗? 使用cif也没有效果,依然显示一帧。

如果遇到这样的消息,需要重新建立graph吗?

到底是在解码filter丢帧还是在显示filter丢帧?加入中间过滤器看看。

质量控制 Microsoft DirectX 9.0 chm文档内容

http://www.directshows.ru/htm/defaultqualitycontrol.htm

Quality-Control Management

This is preliminary documentation and subject to change.

Quality control is a mechanism for adjusting the rate of data flow through the filter graph in response to run-time performance.

If a renderer filter is receiving too much data or too little data, it can send a quality message.数据太多太少就会发送质量消息

The quality message requests an adjustment in the data rate.

By default, quality messages travel upstream from the renderer until they reach a filter that can respond (if any).

An application can also implement a custom quality manager. In that case, the renderer passes quality messages directly to the application's quality manager.

--

Default Quality Control

This is preliminary documentation and subject to change.

The DirectShow Base Classes implement some default behaviors for video quality control.

Quality messages start at the renderer. The base class for video renderers is CBaseVideoRenderer, which has the following behavior:

When the video renderer receives a sample, it compares the time stamp on the sample with the current reference time.

The video renderer generates a quality message. In the base class, the Proportion member of the quality message is limited to a range of 500 (50%) to 2000 (200%). Values outside this range could result in abrupt quality changes.

By default, the video renderer sends the quality message to the upstream output pin (the pin connected to its input pin). Applications can override this behavior by calling the SetSink method.

What happens next depends on the upstream filter. Typically, this is a transform filter. The base class for transform filters is CTransformFilter, which uses the CTransformInputPin and CTransformOutputPin classes to implement input and output pins. Together, these classes have the following behavior:

The CTransformOutputPin::Notify method calls CTransformFilter::AlterQuality, a private method on the filter base class.

Derived filters can override AlterQuality to handle the quality message. By default, AlterQuality ignores the quality message.

If AlterQuality does not handle the quality message, the output pin calls CBaseInputPin::PassNotify, a private method on the filter's input pin.

PassNotify passes the quality message to the appropriate place—the next upstream output pin, or a custom quality manager.

Assuming that no transform filter handles the quality message, the message eventually reaches the output pin on the source filter. In the base classes, CBasePin::Notify returns E_NOTIMPL. How a particular source filter handles quality messages depends on the nature of the source. Some sources, such as live video capture, cannot perform meaningful quality control. Other sources can adjust the rate at which they deliver samples.

The following diagram illustrates the default behavior.

The base video renderer implements IQualityControl::Notify, which means you can pass quality messages to the renderer itself. If you set the Proportion member to a value less than 1000, the video renderer inserts a wait period between each frame that it renders, in effect slowing down the renderer. (You might do this to reduce system usage, for example.) For more information, see CBaseVideoRenderer::ThrottleWait. Setting the Proportion member to a value greater than 1000 has no effect.

----

EC_QUALITY_CHANGE 网络资料

Windows 7 - Intercept EC_QUALITY_CHANGE event

Asked By fungi821 on 12-Jul-07 01:06 AMHi,

On the document it says EC_QUALITY_CHANGE event originates from the

Video Renderer. I have a situation that whenever FGM receives such event,

decoder drops frames constantly.

If i want to intercept such event, such that so it won't be sent to the

decoder, how should i come about to achieve this? Write a trans-in-place

filter between the renderer and the decoder? Which function do i need to

override?

thanks!

In fact although the event message and the dropped frames occur at the same time, they are not directly cause and effect.

The quality message that causes the decoder to drop frames is a signal directly from the VR to the decoder's Notify function.

You can trap this, but if you just want to avoid dropping frames you are better off turning off the graph clock

(query the graph itself for IMediaFilter and call SetSyncSource(NULL)).

---------------msdn 时钟

http://msdn.microsoft.com/en-us/library/windows/desktop/dd407202(v=vs.85).aspx

The IBaseFilter interface inherits from IMediaFilter.

IMediaFilter::SetSyncSource method

HRESULT SetSyncSource(  [in]  IReferenceClock *pClock);

pClock [in]

Pointer to the clock's IReferenceClock interface, or NULL. If this parameter is NULL, the filter graph does not use a reference clock, and all filters run as quickly as possible.


IGraphBuilder *pGraph = 0;
IReferenceClock *pClock = 0;CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,  IID_IGraphBuilder, (void **)&pGraph);// Build the graph.
pGraph->RenderFile(L"C:\\Example.avi", 0);// Create your clock.
hr = CreateMyPrivateClock(&pClock);
if (SUCCEEDED(hr))
{// Set the graph clock.IMediaFilter *pMediaFilter = 0;pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter);pMediaFilter->SetSyncSource(pClock);pClock->Release();pMediaFilter->Release();
}

You can also set the filter graph to run with no clock, by calling SetSyncSource with the value NULL. If there is no clock, the graph runs as quickly as possible. With no clock, renderer filters do not wait for a sample's presentation time. Instead, they render each sample as soon as it arrives. Setting the graph to run without a clock is useful if you want to process data quickly, rather than previewing it in real time.

----------------------

sathaadj问题

Is there a possibility that the MJPEG Decompressor can generate EC_QUALITY_CHANGE event on its own.

I considered that it could be derived from the CVideoTransformFilter base class code which by default has

a quality management code. According to this code (vtrans.cpp) the filter which derives from it should call

ShouldSkipFrame() every time before sending the frame to the output pin.

The ShouldSkipFrame() code in vtrans.cpp is written such a way that it will not consider doing quality control

when there are no time stamps set on the incoming samples, so i decided to put a transform filter inbetween

Camera and the MJPEG Decompressor which would remove the timestamps from the IMediaSample by using

SetTime(NULL,NULL);

BOOL CVideoTransformFilter::ShouldSkipFrame( IMediaSample * pIn)

{

...

NotifyEvent(EC_QUALITY_CHANGE,0,0);

...

return m_bSkipping;

}

if i set the timestamps as NULL then GetTime should have returned failure and hence there should not have

been any frame drops by the MJPEG Decompressor filter. But i still have the same problems, i also coded AlterQuality()

function for my new filter which is inbetween camera and MJPG Decompressor but i never received any indication to it,

does that mean it has been handled in the MJPEG Decompressor filter itself?

I also tried SetSyncPoint(TRUE) on every sample sent to the MJPEG Decompressor which also doesn't work MJPEG Decompressor still drops all the key frames?!!!

I have previously tried to set the quality sink to my encoder filter also which also doesnt get any notification about quality change.

Can any one please help me in narrowing down this problem?????

--Stefan 回答

If you CPU hits 100 % the VMR7 will most likely send quality messages.

So if you override AlterQuality() it will be called. I just wrote a message killer filter which returns S_OK to stop quality messages being sent downstream, and it works.

Here are some questions to consider:

How do you know that the MJPG Decompressor freezes ?

Does this also happen with just the VMR7 connected to the Encoder ?

What transformation performs the Encoder ?

How does the Encoder react to quality messages ?

----sathaadj 再问

Hi Stefan,

Thanks for your reply. I have removed the VMR7 from the graph by which my graph looks like

Camera ---> MJPG Decompressor --> Inf Tee Filter --> Encoder --> Network

There are no VMR's in this graph even then i am getting this event and the MJPG Decompressor freezes.

Here are the answers to your questions:

>>>>How do you know that the MJPG Decompressor freezes ?

I have checked whether i get any data in the encoder's input pin after the EC_QUALITY_CHANGE change message,

i dont get any buffers after the event occurs.

>>>>Does this also happen with just the VMR7 connected to the Encoder ?

>>>>What transformation performs the Encoder ?

My Encoder converts the RGB24 input to a network streamable video (H.264) which is streamed through my network sink filter.

So i have given NULL media types for my encoder's ouput pin, which makes it impossible to connect with the VMR7.

>>>>How does the Encoder react to quality messages ?

I just wanted to check whether they originate from the VMR7 filter so i just returned S_OK from the encoder's AlterQuality() function

anyways i did not get the EC_QUALITY_CHANGE event there.

Any sort of help is most welcome.... ;)

--------

That sounds as if quality messages are not part of your problem.

Did you try

Camera ---> MJPG Decompressor --> Inf Tee Filter --> Encoder-> Null Renderer ?

and

Camera ---> MJPG Decompressor --> Inf Tee Filter --> Null-Renderer ?

That should give you a direction which filter causes the problem.

The infinitee filter uses a queue on every output pin which can switch from direct sample delivery to asynchronous (threaded) delivery.

This behaviour depends on the implementation of the ReceiveCanBlock() method of the downstream filters. What does your encoder and network sink return in this ?

Regards,

Stefan.

2009年3月25日 13:20

----------sathaadj

Stefan,

The graph is meant to see the local video as well as send it to the far end. When the camera is connected for VGA to the

MJPG Decompressor filter i am able to see the local video through the VMR7 properly. But only when i start the encoder to

give out the data to the network i see the problem.

There are no problems when the camera runs for QVGA or CIF(untill the CPU is less utilized). So only when the resolution

is high (640*480) onwards, i start to see the problems. I have tested in another system where VGA encoding does not take

more CPU and it works fine there.

Is there a way to find out which filter has sent this EC_QUALITY_CHANGE event other than setting the quality sink, which

wont be passed through if the filter can handle the event on its own?

I still believe that MJPG decoder does some performance measurement on its own and decides to stop the streaming. Any

inputs on this view? Are there any other hidden interfaces not documented in MSDN to support these situations?

>>>>>>>What does your encoder and network sink return in this ?

The encoder filter is derived from the CTransformFilter and i haven't coded ReceiveCanBlock() function. The nework sink

filter is derived from CBaseFilter and i have overridden CBaseInputPin::ReceiveCanBlock() function to return S_FALSE; So when i start

the graph i hit the network sink's ReceiveCanBlock function call, i hope that the Infinite Pin Tee Filter will see this result and take action.

Will Infinite Tee start a new thread to deliver data for the encoder filter if it sees S_OK on a ReceiveCanBlocK() function call? I have

coded ReceiveCanBlock in encoder as well as the network sink to return S_OK and found the same results.

Thanks for your timely reply,

Satheesh.

--------------------------------------------------------------------------------

问题最后的解决方法:

在所有的过滤器连接之后,取消时间戳同步,避免graph根据图像的实际帧率和调整图像的质量,导致远程桌面无法播放视频。

HRESULT CGraphBase::ConnectFilters()
{
//... 连接graph中的所有过滤器,然后if (mMediaFilter && m_pVideoRenderer->GetRendererType() == Try_VMR7){mMediaFilter->SetSyncSource(NULL);}return NOERROR;
//...
}
IMediaFilter*       mMediaFilter;
mMediaFilter = NULL;HRESULT CGraphBase::CreateGraph(HWND inWindow)
{
//... 创建graphhr |= m_pGraph->QueryInterface(IID_IMediaFilter, (void **)&mMediaFilter);ATLASSERT(mMediaFilter != NULL);
//..
}
HRESULT CGraphBase::ReleaseGraph()
{
//...SAFE_RELEASE(mMediaFilter);
//.. 销毁graph
}

因质量控制导致回放录像过快的原因分析相关推荐

  1. 华大 MCU 之七 DMA 导致 SPI 异常停止的原因分析、DMA 配置的那些坑

    缘起   在最近的项目测试中发现,SPI 通信总是莫名其妙的失败,查看寄存器发现 SPI 已经被停止了.根据手册,SPI 在异常情况下会被强制停止(SPI 的使能为被清零),而根据波形显示通信过程没有 ...

  2. python项目运行,导致内存越来越大的原因分析

    内存越来越大的原因分析 问题描述: 程序运行现象分析: 尝试解决: 原因分析: 解决方法: 问题描述: 目前遇到的问题是这样的,爬虫程序部署到K8S服务器上运行,但是会过几个小时之后,程序就会被主动杀 ...

  3. WPF--Dispatcher.BeginInvoke()方法使用不当导致UI界面卡死的原因分析

    原文地址: http://www.tuicool.com/articles/F7reem http://blog.csdn.net/yl2isoft/article/details/11711833 ...

  4. RK3288 android添加HAL 层导致无法进入主界面原因分析,重复打印 camsys_marvin(deaa1510) is closed

    1.一般在添加HAL层的时候,都会写到JNI 层(namespace android) ,如果形参对应不上,或者JNINativeMethod格式写的  不对就会导致开机无法进入主界面,以下是终端重复 ...

  5. max_binlog_cache_size 导致数据数据更新失败的原因分析

    再一次执行update语句的过程中发现执行失败并且报错: ERROR 1197 (HY000): Multi-statement transaction required more than 'max ...

  6. EasyCVR接入Ehome协议的设备,无法观看设备录像是什么原因?

    EasyCVR平台支持海量视频汇聚与管理.处理与分发.智能分析等视频能力,在接入协议上,不仅支持国标GB28181协议.RTSP/Onvif.RTMP等标准协议,还支持HIKSDK.大华SDK.海康E ...

  7. EasyNVR开启录像后,录像回看无数据的原因分析及解决办法

    EasyNVR平台优秀的视频能力在于通过RTSP/ONVIF协议,将前端接入设备的音视频资源进行采集,并转码成适合全平台.全终端分发的视频流格式,包括RTMP.FLV.HLS.WebRTC等格式,从而 ...

  8. EasyDSS修改RTMP推流端口后直播无法回放录像问题优化

    EasyDSS-Kernel是一款高性能流媒体音视频服务软件,是整个TSINGSEE青犀视频流媒体核心服务,用户可基于EasyDSS-Kernel开发各种各样的流媒体应用.部分情况下,EasyDSS视 ...

  9. 对PInvoke函数函数调用导致堆栈不对称。原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配。...

    C#引入外部非托管类库时,有时候会出现"对PInvoke函数调用导致堆栈不对称.原因可能是托管的 PInvoke 签名与非托管的目标签名不匹配"的报错. 通常在DllImport标 ...

最新文章

  1. Kong APIGW — Plugins — Traffic Control
  2. linux:apt的源
  3. Javascript综合应用小案例(续)
  4. 自旋锁和互斥锁实例_自旋锁和互斥锁的实现以及使用区别
  5. mysql访问60s出现timeout_websocket 每60s报WsHttpUpgradeHandler.timeoutAsync
  6. linux php项目启动_Linux上实现Node.js项目自启动
  7. 机器学习中生成模型和判别模型
  8. Android Studio下载
  9. 《深入Ajax架构和最佳实践》读书笔记
  10. elementUI中input的使用
  11. 蓝湖 for Mac(自动切图sketch插件)中文版
  12. spring中bean的自动装配(详细)
  13. Stuck Stack成过去时,OpenStack升级还可以这样玩?!
  14. 情感在语文教育中的作用
  15. 两个自变量和一个因变量spss_两个自变量(离散)对一个因变量(连续)的影响(SPSS:双因素方差分析)...
  16. 求html写一个羽毛球拍的代码,一种组合式羽毛球拍的制作方法
  17. 基于Go语言Iris+Xorm的OA办公系统
  18. Poseidon(海神号)
  19. Tessent scan ATPG(7) 设计规则检查 (DRC)
  20. 调用“elm_kernel_adda>kernel_matrix3“时,未对输出参数“omega“ (可能还包括其他参数)赋值。

热门文章

  1. 线程与进程,http、https(post、get),socket(tcp、udp)的拆包和粘包,protocol buffer、大头小头简述
  2. 【图像融合】基于RP、CVT、DTCWT、NSCT-SR+DWT-SR+拉普拉斯金字塔算法-SR等实现MRT图像融合附matlab源码
  3. 数据与分析发展趋势怎么样?值得入行么
  4. org.hibernate.ObjectNotFoundException
  5. 如何申请网站的SSL证书
  6. CTF 学习信息中转站
  7. Java中带标签的break和continue
  8. 【Unity2DMobileGame_PirateBomb06】—— 制作炸弹以及炸弹的爆炸动画
  9. php小程序支付获取prepay_id,小程序支付流程JSAPI
  10. 基于SECS协议开发的简明教程(5)