当前位置:网站首页>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 |
边栏推荐
- Kraken中事件通道原理分析
- SQL语言(一)
- How to notify users of wechat applet version update?
- mysql事务是什么
- Learn NLP with Transformer (Chapter 8)
- PostgreSQL踩坑 | ERROR: operator does not exist: uuid = character varying
- Learn NLP with Transformer (Chapter 4)
- UE4 framework introduction
- Analysis of event channel principle in Kraken
- Reinforcement Learning 强化学习(三)
猜你喜欢

SQL语言(六)

Flask framework - session and cookies

Flask框架——Flask-WTF表单:数据验证、CSRF保护

The practice of asynchronous servlet in image service

mysql主从复制与读写分离

The most detailed MySQL index analysis (mind map is attached at the end of the article)
![[flask advanced] solve the classic error reporting of flask by combining the source code: working outside of application context](/img/3e/2cc3ff7e6e45ba4fcf3a0f5c2bf478.png)
[flask advanced] solve the classic error reporting of flask by combining the source code: working outside of application context

NB-IOT控制液晶屏(日期的设置与读取)

机智云物联网平台 STM32 ESP8266-01S 简单无线控灯

【IJCAI 2022】参数高效的大模型稀疏训练方法,大幅减少稀疏训练所需资源
随机推荐
SQL语言(一)
Learn NLP with Transformer (Chapter 4)
Google Earth engine -- Statistics on the frequency of land classification year by year
HCIA实验(06)
MySQL master-slave replication and read-write separation
HCIA experiment (10) nat
MySQL advanced statement (I) (there is always someone who will make your life no longer bad)
学习周刊 - 总第 63 期 - 一款开源的本地代码片段管理工具
学习路之PHP--TP5.0使用中文当别名,报“不支持的数据表达式”
史上最全的立创元器件封装库导入AD详细教程(一直白嫖一直爽)
redis 哨兵,高可用的执行者
【flask高级】从源码深入理解flask的应用上下文和请求上下文
【信息系统项目管理师】思维导图系列精华汇总
【域泛化】2022 IJCAI领域泛化教程报告
Learn NLP with Transformer (Chapter 5)
HCIA实验(08)
I, AI doctoral student, online crowdfunding research topic
信号完整性(SI)电源完整性(PI)学习笔记(三十三)102条使信号完整性问题最小化的通用设计规则
数字孪生万物可视 | 联接现实世界与数字空间
C3d model pytorch source code sentence by sentence analysis (III)
