请教DShow数据线程的详细流程

凤朝凰 2010-09-03 10:12:52
用DShow架构做的程序,自己写的RenderFilter和它的Pin类和Allocator类。RenderFilter直接连到采集卡的包装Filter的输出pin上。
现在程序基本正常了。只是有时候打开后会采集一两帧就不动了。因为硬件是公司自己做的。驱动和应用程序都是我自己写的。现在也不知道不能运行是因为哪部分的问题。根据log来看最后有一帧驱动完成后,RenderFilter却没有调用DoRenderSample方法。
想请问下各位数据线程的详细流程,然后继续跟进找找程序是在哪里出现问题的。或者直接给个检测问题的方法或思路。
...全文
294 26 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
凤朝凰 2010-09-14
  • 打赏
  • 举报
回复
今天在做一个实验,我把显存用内存替换了。程序到目前为止还没有出现这个问题。认为基本可以肯定是显存这边出现的问题了吧。
meteor_an 2010-09-14
  • 打赏
  • 举报
回复
每天回帖即可获得10分可用分!
学习。。。
dengzikun 2010-09-13
  • 打赏
  • 举报
回复
可以试试先不走内核流,把sample数据取到内存,然后再塞给显卡.
凤朝凰 2010-09-13
  • 打赏
  • 举报
回复
再问一下:Ksproxy.ax中获得Sample之后做了点什么呢?有什么原因可能造成阻塞?
凤朝凰 2010-09-09
  • 打赏
  • 举报
回复
你的意思是说:有Sample的引用计数没有被置零。造成Allocator的空闲列表中没有可用的Sample了?
但是我的Allocator::GetBuffer确实正确返回了呀,说明取到Sample了,在那之后程序才停止的。
凤朝凰 2010-09-08
  • 打赏
  • 举报
回复
因为不清楚数据线程中都有哪些函数被调用了,所以来这里问的...
可能是我看书不认真,陆其名的书看完一遍也没有看到这部分内容。现在在继续看智慧的鱼的DShow笔记
dengzikun 2010-09-08
  • 打赏
  • 举报
回复
那就先把数据流线程中的函数调用都加上调试信息,逐个排除了。
凤朝凰 2010-09-08
  • 打赏
  • 举报
回复
[Quote=引用 14 楼 dengzikun 的回复:]打开控制台:
AllocConsole("CONOUT$", "a", stdout) ;
freopen () ;

然后在怀疑有问题的地方用
printf打印信息。
特别是在怀疑有问题的函数的调用前后
分别打印信息,确认函数是否被阻塞。[/Quote]我有办法看到调试信息,是不是就不用控制台了?
只是现在只在函数入口位置加了调试信息,我再去再退出的位置添加信息看看。不过现在的问题就是我不知道哪里有问题,怀疑都不知道去怀疑哪儿
dengzikun 2010-09-08
  • 打赏
  • 举报
回复
也许是有的地方Sample被AddRef后,没有Release,导致无Sample可用.
凤朝凰 2010-09-08
  • 打赏
  • 举报
回复
看了几次出问题的情况,好像是从Allocator::GetBuffer退出之后就没有反应了。我怀疑是不是Sample在传递到Ksproxy之后阻塞了,因为Sample中传递的内存是在显卡上的显存,通过D3D得到的纹理地址。是不是有什么地方不符合要求?
之前曾经遇到过调试程序进入源Filter后就没反应了,后来对纹理进行锁定之后就可以了。但是这次能够看出纹理已经是锁定了的,就是不明白为什么又成这样了:mple进入源Filter之后进入驱动之前数据线程阻塞。
dengzikun 2010-09-08
  • 打赏
  • 举报
回复
如果我记的不错的话,DSHOW的文档中,有 关于数据流线程所能调用的函数的一个列表.
dengzikun 2010-09-07
  • 打赏
  • 举报
回复
写错了

AllocConsole () ;
freopen ( "CONOUT$", "a", stdout ) ;
dengzikun 2010-09-07
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 wangbinds 的回复:]
引用 8 楼 dengzikun 的回复:
你的是实时流,可以先不考虑时间戳,收到视频帧就播放,
看看问题出在哪了。估计是线程死锁了。把信息打印出来,确定
哪个调用里产生死锁了。
class CTextureRenderer : public CBaseVideoRenderer
class CTexturePin : public CRendererInputPin
{
pub……
[/Quote]

打开控制台:
AllocConsole("CONOUT$", "a", stdout) ;
freopen () ;

然后在怀疑有问题的地方用
printf打印信息。
特别是在怀疑有问题的函数的调用前后
分别打印信息,确认函数是否被阻塞。
凤朝凰 2010-09-07
  • 打赏
  • 举报
回复
00000031	0.19856195	TestCap: Completing Stream        SRB 82316A50
00000032 0.19893076 [3292] LockTexture hr = 8876086C //Allocator::GetBuffer
00000033 0.19931599 TestCap: Receiving Stream Data SRB FFB08000, 0 //驱动中收到Buffer
00000034 0.19936953 [3292] LockTexture hr = 8876086C //Allocator::GetBuffer
00000035 0.19972663 TestCap: Receiving Stream Data SRB FFB03000, 0 //驱动中收到Buffer
00000036 0.20492421 帧率为:0
00000037 0.24522485 VideoGetProperty
00000038 0.24523222 TestCap: Completing Stream SRB 82316A50
00000039 0.24526237 TestCap: Completing Stream SRB 82316A50
00000040 0.24536033 VideoGetProperty
00000041 0.24536446 TestCap: Completing Stream SRB 82316A50
00000042 0.24539022 TestCap: Completing Stream SRB 82316A50
00000043 0.28834051 TestCap: Completing Stream SRB FFB08000 //驱动完成一帧,提交Buffer
00000044 0.28852260 [3292] CTexturePin::Receive //Pin::Receive
00000045 0.28900352 [3292] 两帧间隔时间为:3484 //Render::DoRenderSample
00000046 0.30569807 TestCap: Completing Stream SRB FFB03000 //驱动中收到Buffer
00000047 0.61391217 [3292] LockTexture hr = 0 //Allocator::GetBuffer
00000048 1.20499861 帧率为:2
00000049 2.20489955 帧率为:0
00000050 3.20484424 帧率为:0
00000051 4.20495749 帧率为:0
在pin的Receive方法开头添加调试信息后出错的情况。
从上面可以看到:驱动首先得到了两个Sample,然后完成了第一个Sample。Pin的Receive方法被调用,Renderer的DoRenderSample方法被调用。之后驱动完成了第二帧图像。然后取下一个Sample。
这个时候数据线程就没有反应了。但是程序能够正常关闭,所以主线程应该是没问题的。但是我还是不明白问题到底出在哪儿了,驱动完成一个Sample之后为什么就不再调用Pin的Receive方法了呢?
dengzikun 2010-09-06
  • 打赏
  • 举报
回复
你的是实时流,可以先不考虑时间戳,收到视频帧就播放,
看看问题出在哪了。估计是线程死锁了。把信息打印出来,确定
哪个调用里产生死锁了。
凤朝凰 2010-09-06
  • 打赏
  • 举报
回复
自己再次顶起
顺便回复一楼:程序不是停止一段时间,我现在发现的问题是,一旦出错程序数据线程就好像被完全阻塞。无论等多久都不会再次渲染新的帧。
SuperKan 2010-09-06
  • 打赏
  • 举报
回复
你直接把receive函数重载了,在里面dump一下yuv数据,然后直接return S_OK(表示渲染完毕),看看是否都收到了。然后再一步步去调查,慢慢定位问题原因。
凤朝凰 2010-09-06
  • 打赏
  • 举报
回复

00000023 0.11297119 VideoGetProperty
00000024 0.11297394 TestCap: Completing Stream SRB 81DBA418
00000025 0.11299246 TestCap: Completing Stream SRB 81DBA418
00000026 0.11338749 [3136] LockTexture hr = 8876086C //Allocator::GetBuffer中的调试信息
00000027 0.11377739 TestCap: Receiving Stream Data SRB FF958000, 0 //驱动中收到视频帧时的调试信息
00000028 0.11383578 [3136] LockTexture hr = 8876086C //Allocator::GetBuffer中的调试信息
00000029 0.11418910 TestCap: Receiving Stream Data SRB FF954000, 0 //驱动中收到视频帧时的调试信息
00000030 0.19685031 VideoGetProperty
00000031 0.19685850 TestCap: Completing Stream SRB 81DBA418
00000032 0.19689466 TestCap: Completing Stream SRB 81DBA418
00000033 0.19700518 VideoGetProperty
00000034 0.19700968 TestCap: Completing Stream SRB 81DBA418
00000035 0.19703914 TestCap: Completing Stream SRB 81DBA418
00000036 0.24575698 TestCap: Completing Stream SRB FF958000 //驱动中完成一个视频帧时的调试信息
00000037 0.24599297 [3136] 两帧间隔时间为:2984 //Render::DoRenderSample中的调试信息
00000038 0.25254071 [3136] LockTexture hr = 0 //Allocator::GetBuffer中的调试信息
00000039 0.25298366 TestCap: Receiving Stream Data SRB FF950000, 0 //驱动中收到视频帧时的调试信息
00000040 0.26476935 TestCap: Completing Stream SRB FF954000 //驱动中完成一个视频帧时的调试信息
00000041 0.29753977 TestCap: Completing Stream SRB FF950000 //驱动中完成一个视频帧时的调试信息
00000042 0.41126558 帧率为:25
00000043 0.64312959 [3136] 两帧间隔时间为:16 //Render::DoRenderSample中的调试信息
00000044 0.65822351 [3136] LockTexture hr = 0 //Allocator::GetBuffer中的调试信息
00000045 1.41126752 帧率为:0
00000046 2.41146803 帧率为:0
00000047 3.41131306 帧率为:0
00000048 4.41125107 帧率为:0
00000049 5.41134596 帧率为:0
00000050 6.41123438 帧率为:0
按照经验看,下面该是再次调用Render::DoRenderSample来显示后面接受到的一帧了,却没有反应了
凤朝凰 2010-09-06
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 dengzikun 的回复:]
你的是实时流,可以先不考虑时间戳,收到视频帧就播放,
看看问题出在哪了。估计是线程死锁了。把信息打印出来,确定
哪个调用里产生死锁了。
[/Quote]class CTextureRenderer : public CBaseVideoRenderer
class CTexturePin : public CRendererInputPin
{
public:
CTexturePin( CBaseRenderer *pRenderer, HRESULT *phr, LPCWSTR pPinName );
STDMETHODIMP GetAllocator( IMemAllocator ** ppAllocator );
};以上是Render的声明和Pin的定义。
我现在是直接在Render的DoRenderSample方法里显示的,并且在里面加入了调试信息。按我的理解驱动完成视频帧后就该调用DoRenderSample之后是Allocator的GetBuffer方法。但是在出现问题的时候驱动中完成视频帧后就是没有DoRenderSample中的调试信息出来,这个线程中的信息都没有了。
不知道我还应该怎么添加信息,在什么地方添加。请明示...
凤朝凰 2010-09-03
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 tufaqing 的回复:]
先把时间戳打印出来看看,是不是递增的,不能出现倒退的情况,否则render会卡住的,也不能递增太多了,否则也会停在一帧画面上很长时间。
[/Quote]打时间戳怎么做?新手没有见过例子不知道怎么做了...
下午检查了一下驱动里好像打了时间戳了,因为是在例子的基础上改来的,所以不是很熟悉。
加载更多回复(5)
"管家婆加密狗读写工具"是一款专门针对管家婆软件的辅助工具,旨在帮助用户进行加密狗的读取和写入操作。加密狗是一种硬件设备,通常用于软件的授权管理,确保只有拥有正确密钥的用户才能运行特定的软件。在IT行业中,这种技术被称为硬件锁或USB Dongle,它通过USB接口连接到计算机,存储了软件的许可证信息。 管家婆软件是一款广泛应用于中小企业财务管理、进销存管理、生产管理等领域的应用软件。它的不同版本可能需要不同的加密狗来验证用户的使用权。"适用于多种版本"表明这款工具兼容管家婆的多个产品版本,为用户提供了一站式的加密狗管理解决方案。 "已测试可用"意味着开发者或提供者已经对这个工具进行了实际的测试,确保它在实际环境中可以正常工作。这是非常重要的,因为它给用户带来了一定程度的信任,表明该工具在使用时不会出现严重的兼容性问题或功能失效。 "要有狗才能用哦"这一提示强调了加密狗是必不可少的,没有加密狗,这个读写工具将无法执行其功能。这意味着用户必须拥有合法的管家婆加密狗才能使用这个工具,否则将无法进行任何读写操作。 从压缩包中的文件名"管家婆写狗(R4ND全集)无壳版.exe"可以看出,这是一个针对管家婆软件的写狗工具,而且是"无壳版"。"无壳版"通常指的是软件去除了保护壳,即没有额外的防逆向工程措施,这可能使工具更易于理解和使用,但同时也可能让软件更容易被破解。"R4ND全集"可能表示这个工具包含了针对各种随机情况的全面支持,比如处理各种类型的加密狗或者各种数据写入需求。 "管家婆加密狗读写工具"是为了解决管家婆软件用户在加密狗管理上的问题而设计的,它具备广泛的版本兼容性,并经过了实际测试,确保功能的稳定性和可靠性。用户需要拥有管家婆的加密狗才能使用此工具进行读写操作,而提供的无壳版本可能方便了用户进行更深入的使用或调试。然而,使用无壳版工具也需谨慎,因为这可能会增加软件被非法利用的风险。
【PA1实验报告1】是关于计算机系统和软件开发的一个实验项目,主要涵盖了以下几个关键知识点: 1. **指令集架构**:实验的目标之一是熟悉指令集的架构。指令集是计算机处理器理解和执行的基本命令集合,它定义了处理器如何处理数据和控制硬件。在这里,虽然可以选择不同的指令集,如RISC-V或x86,但因为实现多个指令集的复杂性,实验选择了x86。x86架构是一种复杂的CISC(复杂指令集计算)架构,包含了大量的单条指令,可以执行多种操作。 2. **图灵机原理**:图灵机是一种理论计算模型,用于描述通用计算能力的极限。在实验中,探究图灵机的运行原理意味着理解其基本操作,包括如何读取和修改存储带上的符号,以及如何根据当前状态和读取的符号来改变状态和移动读写头。 3. **调试器的工作原理**:调试器是软件开发中的重要工具,用于检查和控制程序的执行。实验要求用代码模拟寄存器结构,实现调试器的基本功能。这包括设置断点、单步执行、查看寄存器和内存状态等。调试器的工作原理涉及追踪程序执行流程,中断执行以便分析,并能恢复执行以继续调试。 4. **寄存器结构模拟**:在x86架构中,有不同大小的寄存器,如32位、16位和8位寄存器。实验要求使用`union`结构来模拟这些寄存器,因为`union`可以在同一内存空间中存储不同大小的数据类型,从而反映x86寄存器的共用特性。例如,EAX寄存器可以视为AX、AH和AL的组合。 5. **NEMU模拟器**:NEMU是一个程序模拟器,它的目的是使其他程序能够在NEMU上运行,就像在真实的硬件上一样。实验中提到的`init_monitor()`函数是NEMU启动时调用的关键初始化函数,负责处理参数解析、日志文件初始化、镜像加载和ISA相关的初始化工作。`load_img()`函数用于加载客户程序的镜像,而`init_isa()`则涉及CPU状态的初始化,包括寄存器的设置。 6. **内存管理**:实验中提到了固定内存位置0x10000来加载客户镜像,以及抽象出来的API如`isa_default_img[]`和`isa_default_img_size`,这些API简化了镜像加载和内存管理。 7. **设备初始化**:`init_device()`函数用于初始化设备,这是模拟真实计算机环境的关键部分,因为模拟器需要模拟I/O设备以处理输入输出操作。 8. **断点和监视点**:实验还要求实现监视点功能,即断点。断点是调试中的一个关键元素,允许在特定代码行暂停程序执行,以便检查程序的状态。 这个实验全面地覆盖了计算机系统的基础知识,从底层的指令集到高级的调试技术,旨在加深学生对计算机系统运行机制的理解,并提供实践经验。通过这样的实验,学生不仅能够学习到理论知识,还能提升实际编程和解决问题的能力。

2,554

社区成员

发帖
与我相关
我的任务
社区描述
专题开发/技术/项目 多媒体/流媒体开发
社区管理员
  • 多媒体/流媒体开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧