【视频播放闪烁问题】闪烁发生于设置播放位置时.比较郁闷,大家拉我一把吧....

嗷嗷叫的老马 2009-06-23 04:02:58
起因:

要做一个视频相关的应用,其视频为N多段具有相同开始与结束画面的小视频组成.
程序根据界面上的选择来动态地组织视频文件.

目前所有逻辑功能均正常,但是遇到一个软故障,伤透了脑筋.....

具体情况就是,闪烁.

由于需要动态组织视频,因此需要不断地设置播放位置,以使画面看起来是"连续"的.

但是在设置的一瞬间的闪烁,是绝对不能出现的......不然那不就露馅了么?

我做过的尝试:

一,使用MCI相关API播放,即mciSendString.

二,使用系统里的WMP控件播放,Windows Media Player.....

三,使用ActiveMovie control type library播放,引用C:\WINDOWS\system32\quartz.dll.

无一例外,都会闪烁.

然后使用SPY++观察了一下闪烁发生后的目标容器(一个PictureBox)里的播放窗口句柄,发现多了一个......

经证实,每闪一次就多一个.....如图:



闪烁,应该是切换显示目标时产生的瞬间黑帧.

以上三种播放方式均如此.

然后使用单独的播放器,无论是暴风,还是WMP,均无此现象.证明还是我的实现方式有问题.

容器的AutoRedraw为True,窗体的AutoRedraw也是True,发现为True时出现闪烁的机率要低一点点,不知道是不是心理作用...

我不明白:

一,为什么闪烁是随机发生的?
有时闪,有时不闪.
不闪的时候,播放半小时,都没问题,让我误以为解决了;闪的时候,半小时内会多出来八到十来个新句柄.

二,为什么独立的播放器就没有问题?比如同样是WMP,我在工程里使用控件,与WMP自己独立的区别在哪?

三,有没有办法让播放部分不新建窗口?这闪来闪去烦人啊!!

大家拉我一把~~~~~~~~~- -#
...全文
793 30 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
30 条回复
切换为时间正序
请发表友善的回复…
发表回复
klimaa 2012-08-02
  • 打赏
  • 举报
回复
怎么截的DX窗口?我怎么截不了啊?!
xd393020755 2010-10-15
  • 打赏
  • 举报
回复
高级东西 哦 看不懂~~~~~
东方之珠 2009-06-24
  • 打赏
  • 举报
回复
设置播放位置要这样才行,在你的类模块中加一个属性(我试了一下不会闪):

'窗体上7个命令按钮,1个图片框控件
Option Explicit

'Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" (ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long

'定义DirectShow播放类
Dim PlayClass As cPlayFile

'后退
Private Sub Command1_Click()
Dim backCJL As Single
'PlayClass.PausePlay
backCJL = PlayClass.Position - 1
If backCJL >= 0 Then
PlayClass.Position = backCJL
Else
PlayClass.Position = 0
End If
End Sub

'前进
Private Sub Command2_Click()
Dim forwordCJL As Single
'PlayClass.PausePlay
forwordCJL = PlayClass.Position + 1
If forwordCJL <= PlayClass.Duration Then
PlayClass.Position = forwordCJL
Else
PlayClass.Position = PlayClass.Duration
End If
End Sub

'暂停
Private Sub Command3_Click()
PlayClass.PausePlay
End Sub

'停止
Private Sub Command4_Click()
PlayClass.StopPlay
End Sub

'关闭窗体
Private Sub Command5_Click()
Set PlayClass = Nothing
Unload Me
End Sub
'打开文件
Private Sub Command6_Click()
'打开文件
PlayClass.OpenFile "E:\中国航天\中国航天员首次出舱活动.mpg", Picture1
End Sub

'开始播放
Private Sub Command7_Click()
PlayClass.PlayFile
End Sub

Private Sub Form_Load()
Me.ScaleMode = 3
Picture1.ScaleMode = 3
Set PlayClass = New cPlayFile
Command1.Caption = "后退"
Command2.Caption = "前进"
Command3.Caption = "暂停"
Command4.Caption = "停止"
Command5.Caption = "退出"
Command6.Caption = "打开"
Command7.Caption = "播放"
End Sub


类模块:cPlayFile.cls
Option Explicit

'文件播放类,只要装了解码器,就可播放大部分文件.
'需要引用ActiveMovie control type library,文件名:C:\WINDOWS\system32\quartz.dll

Dim pMC As FilgraphManager
Dim pVW As IVideoWindow
Dim pMP As IMediaPosition
Dim mFileName As String
Dim mObjPic As PictureBox

Public Sub OpenFile(ByVal sFilename As String, ByRef objPic As PictureBox)
'打开一个文件并处于暂停状态.
On Error GoTo ErrHandle

If sFilename = mFileName Then Exit Sub

mFileName = sFilename
Set mObjPic = objPic
pMC.RenderFile mFileName

On Error Resume Next

Set pVW = pMC
Set pMP = pMC

pVW.WindowStyle = CLng(&H6000000)

'设置图象区域大小
pVW.Left = 0: pVW.Top = 0
pVW.Width = mObjPic.ScaleWidth
pVW.Height = mObjPic.ScaleHeight

pVW.Owner = mObjPic.hWnd

Exit Sub
ErrHandle:
End Sub

Public Function PlayFile()
pMC.Run
End Function

Public Sub StopPlay()
'停止播放
pMC.Stop
End Sub

Public Sub PausePlay()
'暂停播放
pMC.Pause
End Sub

Private Sub Class_Initialize()
On Error Resume Next

Set pMC = New FilgraphManager
pMC.Stop
pMC.RenderFile ""
End Sub

Private Sub Class_Terminate()
Set pMP = Nothing
Set pVW = Nothing
Set pMC = Nothing
End Sub
'持续时间
Public Property Get Duration() As Single
On Error Resume Next
Duration = pMP.Duration
End Property

Public Property Let Duration(ByVal vNewValue As Single)
pMP.Duration = vNewValue
End Property
'位置
Public Property Get Position() As Single
On Error Resume Next
Position = pMP.CurrentPosition
End Property

Public Property Let Position(ByVal vNewValue As Single)
pMP.CurrentPosition = vNewValue
End Property

Public Property Get FileName() As String
FileName = mFileName
End Property

Public Property Let FileName(ByVal vNewValue As String)
mFileName = vNewValue
End Property

'以上代码为cPlayFile.cls
Tiger_Zhao 2009-06-24
  • 打赏
  • 举报
回复
你先用计时器确认一下,从你发出切换命令到控件产生播放进度消息之间,是否有延时?

如果有,用卑鄙的招数了:
切换时先将当前播放窗口画面截下拉,用另外一个窗口在相同位置覆盖显示截图,当控件正真播放时隐藏截图窗口。
嗷嗷叫的老马 2009-06-24
  • 打赏
  • 举报
回复
我咋就没想到这种思路呢,哈哈.

也许是害怕截图截不到,毕竟是DX窗口.

没想到居然能截到图.........
嗷嗷叫的老马 2009-06-24
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 tiger_zhao 的回复:]
你先用计时器确认一下,从你发出切换命令到控件产生播放进度消息之间,是否有延时?

如果有,用卑鄙的招数了:
切换时先将当前播放窗口画面截下拉,用另外一个窗口在相同位置覆盖显示截图,当控件正真播放时隐藏截图窗口。
[/Quote]
哈哈哈哈哈哈

感谢赵兄!!

这种"卑鄙"的招数居然是最管用的!!

现在暂时就用这招吧!!

另外也同样感谢楼上的各位!

因为每段视频结束时与开始时的画面都是相同的,这种招数完全可行,而且绝对可靠,哈哈哈哈!!!!
ScottYj 2009-06-24
  • 打赏
  • 举报
回复
老马都搞不定,只有帮顶了
舉杯邀明月 2009-06-23
  • 打赏
  • 举报
回复
还没玩过这东东呢,Mark..........
toury 2009-06-23
  • 打赏
  • 举报
回复
O,忘记说了,释放资源时别忘了pVW.Owner=0,不然要黑一下下的
zzyong00 2009-06-23
  • 打赏
  • 举报
回复
mark
嗷嗷叫的老马 2009-06-23
  • 打赏
  • 举报
回复
谢谢楼上的回答.

所谓"动态组织",就是从一个视频时间表里读到特定的时间,再根据程序逻辑跳转到相应的视频的进度那里去播放.

等效于不断地拖动播放进度条.....

但播放软件无论怎么拖动都不会有黑帧.

另外,黑帧基本上已经确认是播放组件新创建播放窗口时产生的....每黑的时候,使用SPY++都能看到多了一个播放窗口的句柄...

这个很让人郁闷.
toury 2009-06-23
  • 打赏
  • 举报
回复
你的第一段DSHOW播放的代码中,“动态组织视频”的相关代码在哪里?当你重新播放“动态组织”后的视频时是否初始化了FilgraphManager?

不妨这样试一下:

1、 With pVW
.AutoShow = True
.WindowStyle = CLng(&H40000000)
.Owner = mObjPic.hwnd
.MessageDrain = mObjPic.hwnd'加上这句看看
end with
2、 或者可以考虑在适当的时候临时把视频窗口销毁:pVW.Owner=0,然后再.Owner = mObjPic.hwnd
3、实在不行,调试的时候用pVW.visible=false/true来确定黑帧的来源(应该不是黑的,深棕的吧)

顺便说一下,你发的代码里没有释放部分,是没发还是没写?
嗷嗷叫的老马 2009-06-23
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 chenjl1031 的回复:]
不断地设置播放位置是什么意思?
是拖动窗口移动位置?还是拖动窗口放大与缩小?

另外,用quartz.dll播放视频文件时,ActiveMovie Window播放窗口是系统默认的播放窗口。我曾经想在每加载一个视频时把这个窗口关闭了,但无法关闭该窗口,如果你有自己应用播放窗口,这个窗口不会显示,只是一直存在,关闭视频文件时有时(很少时候)会出现瞬间的黑帧,就是因为那个默认窗口的原因。
[/Quote]

是设置播放进度....两种方式我都指定了一个图片框为播放目标,就是那黑帧整死我了....

[Quote=引用 4 楼 tiger_zhao 的回复:]
mciSendString 播放用默认窗口还是自己指定窗口?
自己指定窗口不需要不停初始化,大概能避免闪烁。
[/Quote]

自己指定窗体是指的哪种方式?是不是像我上面的那种给出一个句柄的方式?

[Quote=引用 5 楼 aisac 的回复:]
老马,代码我复制一份保留,会留你的原作者信息,可以不?

现在没时间看,想抽时间看下 - -
[/Quote]

这个...两份都不是我的原创.

一个是从chenjl1031的BLOG里播放GIF的代码参考而来,封装一下而已;另一个直接就是复制的别人的,所以把版权保留了......

忘了给出处,抱歉:

http://blog.csdn.net/chenjl1031/archive/2008/05/04/2383674.aspx
嗷嗷叫的老马 2009-06-23
  • 打赏
  • 举报
回复
以上两份代码的使用示例忘了发上来.......昨晚真的太困了....

示例一,使用cMCI.cls完成视频播放:

(示例中的Pic1为一PictureBox,内部坐标单位已经设置为象素.)

dim objPlayVideo as New cMCI

objPlayVideo.OpenFile("xxxx.mpg",Pic1.hWnd) '打开文件,并处于暂停状态

objPlayVideo.Position=500 '设置播放位置为500秒

示例二,使用cPlayVideo.cls完成视频播放:

dim objPlayVideo as New cPlayVideo

objPlayVideo.OpenFile("xxxx.mpg",Pic1) '打开文件,并处于暂停状态

objPlayVideo.Position=500 '设置播放位置为500秒


代码就上面两种,还一种是WMP的,就不贴了.

我所说的情况是,不断地设置.Position属性,以使视频能以程序逻辑顺序播放.

逻辑上都没有任何问题了,可是总出现偶尔黑帧,真烦人!

连WMP控件在内,它们都是重建了播放窗口,每黑一次,多建立一个

而且又是偶尔的,我郁闷~~~~~~~~~~~~~~~~~~

到底独立播放器是如何实现的?
神马都能聊 2009-06-23
  • 打赏
  • 举报
回复
老马,代码我复制一份保留,会留你的原作者信息,可以不?

现在没时间看,想抽时间看下 - -
Tiger_Zhao 2009-06-23
  • 打赏
  • 举报
回复
mciSendString 播放用默认窗口还是自己指定窗口?
自己指定窗口不需要不停初始化,大概能避免闪烁。
simon__sun 2009-06-23
  • 打赏
  • 举报
回复
完全不懂,瞎说说!!呵呵

好像很多视频播放软件都可以缓存的,不知道你在动态组织视频时是不是也可以预先缓存再播放
东方之珠 2009-06-23
  • 打赏
  • 举报
回复
不断地设置播放位置是什么意思?
是拖动窗口移动位置?还是拖动窗口放大与缩小?

另外,用quartz.dll播放视频文件时,ActiveMovie Window播放窗口是系统默认的播放窗口。我曾经想在每加载一个视频时把这个窗口关闭了,但无法关闭该窗口,如果你有自己应用播放窗口,这个窗口不会显示,只是一直存在,关闭视频文件时有时(很少时候)会出现瞬间的黑帧,就是因为那个默认窗口的原因。
liguicd 2009-06-23
  • 打赏
  • 举报
回复
只负责帮老马顶顶!
嗷嗷叫的老马 2009-06-23
  • 打赏
  • 举报
回复
貌似无用.

我现在尝试使用两个窗口播放,前台是当前视频,后台是下一段视频.....

每次切换视频后再交换.....

可是貌似也没多大改善.

真郁闷.
加载更多回复(10)

808

社区成员

发帖
与我相关
我的任务
社区描述
VB 多媒体
社区管理员
  • 多媒体
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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