Source Filter 输出桢数的问题,如何指定每秒钟输出的桢数?

sungengyu 2005-03-24 03:31:07
在小球的基础上写了一个 Source Filter ,用于视频采集源。

如果 Source Filter 直接和 Renderer Filter 相连,可以设定每秒钟输出的桢数。

但是当 Source Filter 和 ffdshow video encoder 连接时,

我就好像对这个输出完全失去控制了,我的 FillBuffer 以每秒钟 28,29 次的频率被调用

除非在 FillBuffer 中加上 Sleep 延迟,否则一直都是这个输率。

因为我每秒钟根本无法提供28桢,所以压缩出来的 avi 视频,播放时的效果就跟快进一样。

每秒钟输出桢数 到底是怎么设定的?

...全文
112 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
sungengyu 2005-03-25
  • 打赏
  • 举报
回复
我又错了。不是 ffdshow video encoder 在向我拼命的要数据,而是
CSourceStream::DoBufferProcessingLoop(void) 循环在拼命的调用 FillBuffer ?
这么说我可以在循环中控制输出为每秒30帧。
但是采集卡并不能提供每秒30帧的数据,就是说我必须丢弃一些帧?

还是另开贴吧……

谢谢陆老师。

也谢谢eyes4(四只眼),虽然你的答案可能是错的 :)
sungengyu 2005-03-25
  • 打赏
  • 举报
回复
问题没有解决,但是我最初对问题的描述是错误的。

所以先结贴,另开贴讨论。


sungengyu 2005-03-25
  • 打赏
  • 举报
回复
我可能找到根源了。

ffdshow video encoder 并不是固定频率调用我的 FillBuffer,而是拼命的调用。
如果我提供数据比较慢(比如加上 Sleep 延时),那么每秒钟可能只是调用十几帧。
如果我提供数据比较快(比如不采集数据,不向buffer中写数据),那么每秒钟可能调用40帧!

问题是压缩成的 avi 文件并不是按照实际采集的帧率播放,而是以每秒钟固定的帧数播放(大概是30)
因为采集卡采集的速度最快只能是每秒25帧(小于播放频率,并且实际采集卡工作时可能会小于每秒20帧),压缩出来的 avi 却以每秒30帧(估计值)播放,看起来就跟快进一样!

问题可能出在 ffdshow video encoder 上,是不是可以设置压缩成的 avi 文件的播放速度?
happydeer 2005-03-25
  • 打赏
  • 举报
回复
ball是通过时间戳来控制每秒钟显示的帧数,如果ball后面接的是video renderer,video renderer也能够根据sample上的时间戳来按照预定的帧率显示。这里建议你了解一下directshow的quality control机制。

如果ball后面接的不是video renderer,quality control机制不起作用(也就是说m_iRepeatTime不起作用),那么按照ball原来的机制就没法控制每秒钟送出去的帧数。我上面说过,ball的output pin上线程是在全速运行的,它在“压迫式”的“拼命”往下发送sample,它每秒钟发送sample的个数取决于下游filter对sample的处理速度。

关于ball例子的改写,你也可以参考一下《ds实务精选》的第4章 4.1视频抠像,特别是P349最后的“提示”部分。

eyes4 2005-03-24
  • 打赏
  • 举报
回复
>>就ball这个例子来说,每秒钟输出多少帧是没法控制的,因为output pin上的数据输出线程在持续不断地运转,除非你加sleep。但加sleep也有问题,可能输出帧之间的间隔是不均匀的。

就我理解,ball这个例子的帧是可以控制的,不知道我理解得对不对:
因为加了时间戳,所以renderer在render时会按照时间戳来render,这样可以保证在
render时,帧率是衡定的。而sample池中,sample缓冲区的数量是有限的,在初期,
ball的output pin上的数据输出线程的确在持续不断地运转,但当sample缓冲区用完时,
程序就阻塞在pms->GetPointer(&pData);上了, 要等到renderer render完一帧,将
sample release掉后才有新的sample缓冲可用,这样无形中就控制了ball在output pin
上的输入帧率了
sungengyu 2005-03-24
  • 打赏
  • 举报
回复
我再改一改小球,是不是把 CSourceStream::DoBufferProcessingLoop 改一下就行了?

我还有一点疑问:直接和 Renderer Filter 连接时,m_iRepeatTime 是有效的,

为什么和 ffdshow video encoder 连接时就无效了呢?

sungengyu 2005-03-24
  • 打赏
  • 举报
回复
我手中只有你的两本书《DirectShow开发指南》《DirectShow实务精选》,再没别的资料
这个小球的 Source Filter 已经折磨我快一个月了,我现在感觉头晕晕的。

感觉好累。

真心期待您的《Windows Media 编程导向》能让我等菜鸟容易上手。

happydeer 2005-03-24
  • 打赏
  • 举报
回复
那不要从ball例子改了,filter父类建议采用CBaseFilter。另外,filter内部要采用一个比较精确的定时器,每次定时到了就从output pin输出一个sample;如果这次定时到了,但上次定时发送的sample还没有处理完,则将这次的sample丢弃、不发送了,这样来模拟实时采集的情况。
sungengyu 2005-03-24
  • 打赏
  • 举报
回复
我希望数据源能够控制每秒钟输出的帧数,大概在十几帧到二十帧左右。

我做的是视频采集的 Filter ,只要能输出数据(UYVY),能控制输出救行。

不用小球,是否可以从别的例子改?实在不行就只能自己写。

麻烦 happydeer 给指条明路,我应该怎样做。谢谢。

happydeer 2005-03-24
  • 打赏
  • 举报
回复
就ball这个例子来说,每秒钟输出多少帧是没法控制的,因为output pin上的数据输出线程在持续不断地运转,除非你加sleep。但加sleep也有问题,可能输出帧之间的间隔是不均匀的。
cluner 2005-03-24
  • 打赏
  • 举报
回复
你在source filter中设定了媒体格式没有?
source filter中有一个CMediaType的成员变量用于保存媒体格式。

2,543

社区成员

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

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