当前位置:网站首页>A troubleshooting record of DirectShow playback problems
A troubleshooting record of DirectShow playback problems
2022-07-25 11:14:00 【Fighting Horse】
Playback scheme
stay Windows platform , be based on ActiveMovie Play . ActiveMovie yes Windows Media Player A component of , The bottom layer uses DirectShow frame .
Problem phenomenon
What is the problem : Once you click the play button , After loading for a while ( Loading complete ), The whole program is stuck ,UI The does not respond to any input , The playback did not start , No image comes out .( Here's the picture )
But most users , This function is normal . But the number of individuals with problems also exceeds 3%. And the more real users , The higher the proportion , So I have to be tough to solve this difficult and miscellaneous disease .
After various attempts to analyze , A variety of methods have been used , Although because of lack of experience , Many methods have come to a dead end , But it took a whole 3 Days later , Finally caught his tail .
The process and method , It is worth recording and sharing with you . So-called “ Nothing is difficult in the world , I'm just afraid that those who have a mind ”, The most important lesson is not to give up , Do what you know is difficult .
Now I have sorted out the methods used to eliminate this problem , But in fact 3 Days of troubleshooting and analysis , I also try everywhere , Try your luck , There are not many rules . Here is the analysis and summary later , Only then have some relatively clear logic . I hope it can be helpful to solve the difficult problems encountered later .
Preliminary analysis
Since there is no response , Let's see where the stuck code is . Debugging is not started when problems are found , So it needs to be in the task manager , Export process dump file (xxx.DMP). stay Visual Studio Open it inside , function . The stack of the main thread is as follows :

The main route is stuck in d3d9.dll Of CLockD3D in , And prompt to wait for a lock , This lock is locked by another thread 6612 hold . that 6612 What is the thread doing ? Here is 6612 The call stack for threads :

Actually, I'm not doing anything ,Nt..Wait..Ex This function is relatively low-level , Generally, I just wait for news here , There won't be any tasks to deal with .
stay Visual Studio Thread stack of “[ External code ]” It can be expanded , The expanded call stack of locked threads is as follows :( Stuck state of another operation )
[ Waiting for thread lock With the 17368, Double click or press Enter Can switch to thread ] Annotated frames
ntdll.dll!NtWaitForAlertByThreadId() Unknown Non-user code . Symbols loaded .
ntdll.dll!RtlpWaitOnAddressWithTimeout() Unknown Non-user code . Symbols loaded .
ntdll.dll!RtlpWaitOnAddress() Unknown Non-user code . Symbols loaded .
ntdll.dll!RtlpWaitOnCriticalSection() Unknown Non-user code . Symbols loaded .
ntdll.dll!RtlpEnterCriticalSectionContended() Unknown Non-user code . Symbols loaded .
ntdll.dll!RtlEnterCriticalSection() Unknown Non-user code . Symbols loaded .
d3d9.dll!CLockD3D::CLockD3D(class CLockOwner *,int) Unknown Non-user code . Symbols loaded .
d3d9.dll!CDxva2Container::GetVideoProcessorDeviceGuidCount(struct _DXVA2_VideoDesc const *,unsigned int *) Unknown Non-user code . Symbols loaded .
dxva2.dll!CVideoAccelerationService::GetVideoProcessorDeviceGuids() Unknown Non-user code . Symbols loaded .
evr.dll!CMFVideoMixer9::AllocateResources() Unknown Non-user code . Symbols loaded .
evr.dll!CMFVideoMixer::MFTProcessMessage() Unknown Non-user code . Symbols loaded .
evr.dll!CMFVideoMixer9::MFTProcessMessage(enum _MFT_MESSAGE_TYPE,unsigned __int64) Unknown Non-user code . Symbols loaded .
evr.dll!CEVRFilter::ProcessMessageMixer(enum _MFT_MESSAGE_TYPE,unsigned __int64) Unknown Non-user code . Symbols loaded .
evr.dll!CEVRFilter::StartStreaming(void) Unknown Non-user code . Symbols loaded .
evr.dll!CEVRFilter::Pause(void) Unknown Non-user code . Symbols loaded .
quartz.dll!CFilterGraph::Pause(void) Unknown Non-user code . Symbols loaded .
quartz.dll!CFGControl::Cue(void) Unknown Non-user code . Symbols loaded .
quartz.dll!CFGControl::CueThenRun(void) Unknown Non-user code . Symbols loaded .
quartz.dll!CFGControl::CImplMediaControl::StepRun(void) Unknown Non-user code . Symbols loaded .
quartz.dll!CFGControl::CImplMediaControl::Run(void) Unknown Non-user code . Symbols loaded .
wmp.dll!00007ff8f390c3b3() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f390d9d0() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37a32a3() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37a2834() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37a27ae() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37a2568() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f372e327() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f372e70f() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f372e83c() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37c6d3f() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37c6bb8() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f37c6c9f() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f3908388() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f390861c() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f390d3c2() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f390d74e() Unknown Non-user code . Cannot find or open PDB file .
wmp.dll!00007ff8f390d0c4() Unknown Non-user code . Cannot find or open PDB file .
user32.dll!UserCallWinProcCheckWow() Unknown Non-user code . Symbols loaded .Debug analysis
Only through DMP analysis , Basically, I can't see why it's stuck . Fortunately, we also have one PC There is the same phenomenon . So you can use real-time debugging to further explore what happened .
In use Visual Studio During real-time debugging , You will encounter an exception , Continue operation 3 Next time , It's stuck . The exception stack is like this :
> d3d9.dll!CSwapChain::CreateWindowed(unsigned int,unsigned int,enum _D3DFORMAT,unsigned int,enum _D3DMULTISAMPLE_TYPE,unsigned long,int,int,int,int,int,int) Unknown
d3d9.dll!CSwapChain::Reset(struct D3DPRESENT_PARAMETERS *,struct D3DDISPLAYMODEEX const *,int,int) Unknown
d3d9.dll!CSwapChain::Init(struct D3DPRESENT_PARAMETERS *,struct D3DDISPLAYMODEEX const *,long *,int,int) Unknown
d3d9.dll!CBaseDevice::CreateAdditionalSwapChain(struct D3DPRESENT_PARAMETERS *,struct IDirect3DSwapChain9 * *) Unknown
evr.dll!CMFVideoPresenter9FlipMode::CreateFlipModeSwapChain() Unknown
evr.dll!CMFVideoPresenter9FlipMode::ProcessOutput() Unknown
evr.dll!CMFVideoPresenter::RepaintVideo() Unknown
rpcrt4.dll!Invoke() Unknown
rpcrt4.dll!Ndr64StubWorker(void *,void *,struct RPC_MESSAGE *,struct _MIDL_SERVER_INFO *,long (*const *)(void),struct _MIDL_SYNTAX_INFO *,unsigned long *) Unknown
rpcrt4.dll!NdrStubCall3() Unknown
combase.dll!CStdStubBuffer_Invoke(IRpcStubBuffer * This, tagRPCOLEMESSAGE * prpcmsg, IRpcChannelBuffer * pRpcChannelBuffer) That's ok 1458 C++
rpcrt4.dll!CStdStubBuffer_Invoke() Unknown
[ Inline framework ] combase.dll!InvokeStubWithExceptionPolicyAndTracing::__l6::<lambda_c9f3956a20c9da92a64affc24fdd69ec>::operator()() That's ok 1279 C++The exception information indicates that the memory access is abnormal , Memory pointer is a small value , Should be null Caused by pointer . stay d3d9 In such an important library , Didn't handle null The pointer , I really shouldn't have . But for our troubleshooting , Instead, we can observe more details , It's a good thing . You can see such a detailed call stack , I have to admire Microsoft's debugging framework , as well as pdb Completeness of symbols .
according to D3D Information ,CreateAdditionalSwapChain It seems to be creating D3D Exchange of equipment Buffer, Use on image display . But even if you know the principle , But there's no source code , It's impossible to know which line of code has the problem , It is not clear how to avoid this problem .
comparative analysis
Comparison of different devices
The first thought is to compare normal equipment 、 Different abnormal devices . I suspect that normal devices use different methods , So the program didn't run to d3d9 On the code with problems in the block .
I'm in logical order , stay “ rendering pipeline ”、“ The call stack ”、“ Call parameters ” They are compared respectively , In the end, I found no difference . Casualness is useless for solving problems , But in terms of methods, it is still worth recording and learning .
rendering pipeline
Rendering pipeline is the connection of various components used in video playback ( It is generally a pipe chain structure , stay DirectShow called Filter Graph, Filter It's the components ,Graph Is the connection diagram ). In general , The pipe contains at least three components : Source , decoder 、 Renderers ). Need to know DirectShow What components are used , Need to traverse IFilterGraph Everything in it Filter, Output its information ,Filter There are more Pin, Also output Pin Information about ,Filter adopt Pin Connect with each other .
Because the source component of the three components is implemented by ourselves , So insert some code into the source component , You get the following information :
The call stack
We know the exception stack , Can the same call stack be reproduced on normal devices ?
How to reproduce , That is, of course, to add breakpoints in the same place , Just see if it can be disconnected . But we have no source code , however Visual Studio It provides the function of directly entering the function name to set the breakpoint .
But in the CSwapChain::CreateWindowed(...) Breakpoints cannot be set , One level on the call stack CSwapChain::Rest(...) Yes. . The reason is not clear , It may be the only method visible outside the module , To set breakpoints . It should be noted that , No parameter information is required when entering the method name .
stay Reset After the breakpoint pauses , After many single steps , Can enter the CreateWindowed Method , At this point, you can add CreateWindowed The breakpoint of . Then run... Again , Directly in CreateWindowed Break point pause .
So it can be proved , Normal call stack , It is no different from the abnormal situation .
Call parameters
Since the call stack is normal , I can only suspect that the different input parameters lead to abnormal problems .
Through the analysis of stack memory , It can be inferred that it is passed to CreateAdditionalSwapChain Parameters of . although Visial Studio Call parameter analysis without source code is not supported , But we also have a stupid and clever way . stay x86_64 Systematically , Stack pointer register rsp Indicates the position of the call stack frame , On the same call stack and instruction location , Parameter memory is equivalent to rsp The offset of is fixed .
What is the offset ? We can deduce from the known parameter values . First construct a same way to call ( Call parameters are known ), Breakpoint pause at the same instruction location , And then in rsp Find the known parameter value in the backward memory , You will know the offset .
Finally, it is inferred that it is passed to CreateAdditionalSwapChain The parameter is :
Comparison of different procedures
Deal with the comparison of different equipment environments , On the problem device , You can also check problems by comparing the performance of different programs .
GraphStudioNext
To check 、 verification DirectShow Playback problem of ,GraphStudioNext Is the most commonly used tool ( Not one of them. ).
adopt GraphStudioNext Play our source , It can be played on the problem device .

Although you can play , But in the image rendering scheme , Somewhat different . GraphStudioNext It uses VMR (Video Mixing Renderer), And our program ( That is to say Windwos Media Player) It uses EVR (Enhanced Video Renderer),EVR It's better than VMR Updated technical solutions .
stay GraphStudioNext in , That's not a problem . For comparative verification EVR, Just delete VMR, add to EVR That's it . Can verify , Even using EVR , On the problem device ,GraphStudioNext It can also be played .
Simple program
however GraphStudioNext After all, with Windwos Media Player (WMP) There's a difference , Do not rule out the problem is caused by WMP Caused by the .
Instead of checking step by step , Simply separate the code of the playback part of our program , Build a simple program , Look at the different performances .
Although there are some repetitions , Can't play at first , Even gave up this idea for a time . But later, it was confirmed that the simple program playback is normal , This also contributed to the later exclusion analysis .
Exclusion analysis
Since simple programs can be played , Naturally, we suspect that other functions of our program have affected the playback function , So the exclusion method just popped out .
Elimination is the ultimate weapon to solve many difficult problems , The premise is to have a normal control . But the elimination method is very tiring , Remove some functions step by step , And let the whole program run . And with failure again and again , Less and less confidence , It's a test of endurance .
I have gradually eliminated the following functional effects , I didn't expect that the problem could still recur .
- OpenGL function ( Just skip OpenGL The initialization )
- WebView function ( Use fake implementations instead )
- Bottom network module
- Irrelevant interface ( each Tab page )
- main interface ( It has been completely replaced with a simple program interface )
- The function library related to the underlying algorithm
- Most of the code of program entry initialization
The next suspect is loading through runtime DLL The way of the . Our main function is DLL To realize , The launcher is just a shell .
I move the functions of simple programs to the startup program and directly realize , Added some link configurations , Run up . But there is still the same exception .
Can't , Since we have embarked on a road of no return , I can only go on with it . Next, you can only doubt the compilation configuration , Compare the compiled configuration . The different ones are link libraries and precompiled macros . Make it the same , It's really normal , Real shit , This is the first time to encounter problems caused by precompiled macros .
Add back the suspected precompiled macros one by one , Locate the SLIC3R_GUI This macro is the culprit . After further confirmation , Let's see what code it affects .
One of the pieces of code is very suspicious :
#ifdef SLIC3R_GUI
extern "C"
{
// Let the NVIDIA and AMD know we want to use their graphics card
// on a dual graphics card system.
__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
__declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
}
#endif /* SLIC3R_GUI */Get rid of this code, and sure enough OK.
ha-ha , Finally, the root of the problem has been found . See what the hell these two things are .
Sure enough, I'm still inexperienced , These two export symbols are often used in game development , It can be used on devices with independent graphics cards , Speed up game operations , Lifting performance .
Check the hardware configuration of the faulty device , Sure enough, there is a graphics adapter ( The graphics card ), An integrated , An independent . And we have no faulty equipment , There is only one integrated graphics card . Users of our program , His equipment , Most people also use better configurations , Therefore, it also explains the reason why the proportion of real users with problems is higher .
About the above two configurations , If you are interested, you can see the relevant information :
| NVIDIA Optimus |
| Selecting the Best Graphics Device to Run a 3D Intensive Application |
边栏推荐
- Flask框架——flask-caching缓存
- MySQL advanced statement (I) (there is always someone who will make your life no longer bad)
- [information system project manager] thought map series essence summary
- 接口流量突增,如何做好性能调优?
- 信号完整性(SI)电源完整性(PI)学习笔记(三十四)100条估计信号完整性效应的经验法则
- Electromagnetic field and electromagnetic wave experiment I familiar with the application of MATLAB software in the field of electromagnetic field
- HCIA实验(10)NAT
- Microwave technology homework course design - Discrete capacitance and inductance + microstrip single stub + microstrip double stub
- Basic experiment of microwave technology - Filter Design
- Hcip experiment (03)
猜你喜欢

STM32CubeMX学习记录--安装配置与使用
Learn NLP with Transformer (Chapter 2)

Esp32c3 based on the example tutorial of esp32 Rainmaker development under Arduino framework

【flask高级】结合源码详解flask的运行机制(出入栈)

Analysis of event channel principle in Kraken

Electromagnetic field and electromagnetic wave experiment I familiar with the application of MATLAB software in the field of electromagnetic field

SQL语言(四)

SQL语言(一)

HCIP(13)

Flask框架——flask-caching缓存
随机推荐
Flask framework -- flask caching
Reinforcement Learning 强化学习(三)
Learn NLP with Transformer (Chapter 3)
Flask框架——Flask-WTF表单:数据验证、CSRF保护
【信息系统项目管理师】思维导图系列精华汇总
HCIP (01)
【Servlet】请求的解析
Use three.js to realize the cool cyberpunk style 3D digital earth large screen
HCIP(13)
Leetcode 560 prefix and + hash table
HCIA experiment (06)
mysql事务是什么
信号完整性(SI)电源完整性(PI)学习笔记(三十三)102条使信号完整性问题最小化的通用设计规则
ESP8266 使用 DRV8833驱动板驱动N20电机
SQL语言(一)
2021 scenery written examination summary
MySQL advanced statement (I) (there is always someone who will make your life no longer bad)
Learning Weekly - total issue 63 - an open source local code snippet management tool
Visual thematic map of American airport go style: ArcGIS Pro version
HCIA experiment (09)
