为啥 DirectShow 加载视频字幕文件?
Posted
技术标签:
【中文标题】为啥 DirectShow 加载视频字幕文件?【英文标题】:Why DirectShow load video subtitle file?为什么 DirectShow 加载视频字幕文件? 【发布时间】:2017-06-30 01:31:20 【问题描述】:我使用这个类(来自 CodeProject 的found,删除了一些方法和属性以减少代码)通过 DirectShow 播放视频文件,它工作正常。但如果字幕文件存在于文件正在播放的同一文件夹中,则字幕会自动显示。
我想知道哪部分代码与字幕文件有关。如何删除或自定义它?! (如颜色、字体大小、字体名称)
它在 SampleGrabber 过滤器内吗?!
class MediaPlayer : IDisposable
public enum FileType
Video,
Audio,
Invalid
public enum GraphState
Stopped,
Paused,
Running,
Exiting
public IVideoFrameStep frameStep = null;
public FileType fileType = FileType.Invalid;
public IGraphBuilder graphBuilder = null;
public IMediaControl mediaControl = null;
public IVideoWindow videoWindow = null;
public IBasicVideo basicVideo = null;
public ISampleGrabber sampleGrabber = null;
public IMediaSeeking mediaSeeking = null;
public IMediaPosition mediaPosition = null;
public IMediaDet mediaDet = null;
public IBasicAudio basicAudio = null;
public IMediaEventEx mediaEvent;
public Control control;
public MediaInfo mediaInfo = new MediaInfo();
public List<Frames> segmentationImages;
private string filename;
private ManualResetEvent manualResetEvent = null;
volatile private GraphState currentState = GraphState.Stopped;
public event HotMediaEvent StopPlay;
public void Dispose()
CloseInterfaces();
~MediaPlayer()
CloseInterfaces();
public MediaPlayer(string fileName)
try
IntPtr eventHandler;
this.filename = fileName;
this.SetupInterfaces(fileName);
DsError.ThrowExceptionForHR(mediaEvent.GetEventHandle(out eventHandler));
manualResetEvent = new ManualResetEvent(false);
manualResetEvent.SafeWaitHandle = new Microsoft.Win32.SafeHandles.SafeWaitHandle(eventHandler, true);
Thread t = new Thread(new ThreadStart(this.EventWait));
t.Name = "HotMediaEvent Thread";
t.Start();
catch
Dispose();
throw;
public void SetupInterfaces(string fileName)
this.graphBuilder = (IGraphBuilder)new FilterGraph();
this.sampleGrabber = (ISampleGrabber)new SampleGrabber();
ConfigSampleGrabber(this.sampleGrabber);
this.graphBuilder.AddFilter((IBaseFilter)sampleGrabber, "SampleGrabber");
DsError.ThrowExceptionForHR(this.graphBuilder.RenderFile(fileName, null));
this.mediaControl = (IMediaControl)this.graphBuilder;
this.mediaEvent = (IMediaEventEx)this.graphBuilder;
this.mediaSeeking = (IMediaSeeking)this.graphBuilder;
this.mediaPosition = (IMediaPosition)this.graphBuilder;
this.videoWindow = this.graphBuilder as IVideoWindow;
this.basicVideo = this.graphBuilder as IBasicVideo;
this.basicAudio = this.graphBuilder as IBasicAudio;
this.frameStep = this.graphBuilder as IVideoFrameStep;
this.mediaDet = (IMediaDet)new MediaDet();
this.mediaDet.put_Filename(fileName);
this.CheckFileType();
if (this.fileType == FileType.Video)
this.GetMediaInfo();
public void SetupVideoWindow(Control control)
int hr = 0;
this.control = control;
if (this.fileType == FileType.Video)
//this.sampleGrabber.SetCallback(((MainForm)this.control.Parent.Parent), 1);
this.GetMediaInfo();
hr = this.videoWindow.put_Owner(control.Handle);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_WindowStyle((WindowStyle.Child | WindowStyle.ClipChildren | WindowStyle.ClipSiblings));
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_Visible(OABool.True);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_MessageDrain(control.Handle);
this.SizeWindow();
DsError.ThrowExceptionForHR(hr);
public void ClearVideoWindow()
int hr = 0;
if (this.fileType == FileType.Video)
hr = this.videoWindow.put_Owner(IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_Visible(OABool.False);
DsError.ThrowExceptionForHR(hr);
hr = this.videoWindow.put_MessageDrain(IntPtr.Zero);
DsError.ThrowExceptionForHR(hr);
private void CheckFileType()
int hr;
if ((this.videoWindow != null) || (this.basicVideo != null))
this.fileType = FileType.Video;
else if ((this.basicAudio != null))
this.fileType = FileType.Audio;
else
this.fileType = FileType.Invalid;
OABool lVisible;
hr = this.videoWindow.get_Visible(out lVisible);
if (hr < 0)
if (hr == unchecked((int)0x80004002)) //E_NOINTERFACE
this.fileType = FileType.Audio;
else
DsError.ThrowExceptionForHR(hr);
private void EventWait()
int hr;
//WS UPDATED changed int to IntPtr
IntPtr firstParameter, secondParameter;
EventCode eventCode;
do
manualResetEvent.WaitOne(-1, true);
lock (this)
if (currentState != GraphState.Exiting)
hr = mediaEvent.GetEvent(out eventCode, out firstParameter, out secondParameter, 0);
while (hr >= 0)
if (eventCode == EventCode.Complete)
Stop();
if (StopPlay != null)
StopPlay(this);
hr = mediaEvent.FreeEventParams(eventCode, firstParameter, secondParameter);
DsError.ThrowExceptionForHR(hr);
hr = mediaEvent.GetEvent(out eventCode, out firstParameter, out secondParameter, 0);
if (hr != unchecked((int)0x80004004))
DsError.ThrowExceptionForHR(hr);
else
break;
while (true);
public void SizeWindow()
int hr;
Rectangle rc = control.ClientRectangle;
int windowWidth, windowHeight;
windowWidth = rc.Width;
windowHeight = rc.Height;
int videoWidth = this.mediaInfo.MediaWidth;
int videoHeight = this.mediaInfo.MediaHeight;
int x, y, width, height;
double videoRatio = (double)videoWidth / (double)videoHeight;
double windowRatio = (double)windowWidth / (double)windowHeight;
if (videoRatio > windowRatio)
double ratio = (double)windowWidth / (double)videoWidth;
x = (int)((windowWidth - videoWidth * ratio) / 2);
y = (int)((windowHeight - videoHeight * ratio) / 2);
width = (int)(videoWidth * ratio);
height = (int)(videoHeight * ratio);
hr = videoWindow.SetWindowPosition(x, y, width, height);
else
double ratio = (double)windowHeight / (double)videoHeight;
x = (int)((windowWidth - videoWidth * ratio) / 2);
y = (int)((windowHeight - videoHeight * ratio) / 2);
width = (int)(videoWidth * ratio);
height = (int)(videoHeight * ratio);
hr = videoWindow.SetWindowPosition(x, y, width, height);
DsError.ThrowExceptionForHR(hr);
void ConfigSampleGrabber(ISampleGrabber sampGrabber)
AMMediaType media;
media = new AMMediaType();
media.majorType = MediaType.Video;
media.subType = MediaSubType.RGB24;
media.formatType = FormatType.VideoInfo;
this.sampleGrabber.SetMediaType(media);
DsUtils.FreeAMMediaType(media);
media = null;
int hr = sampGrabber.SetBufferSamples(true);
DsError.ThrowExceptionForHR(hr);
private void GetMediaInfo()
AMMediaType media = new AMMediaType();
this.sampleGrabber.GetConnectedMediaType(media);
if ((media.formatType != FormatType.VideoInfo) || (media.formatPtr == IntPtr.Zero))
throw new Exception("Format type incorrect");
int videoWidth, videoHeight, videoStride;
this.basicVideo.GetVideoSize(out videoWidth, out videoHeight);
VideoInfoHeader videoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(media.formatPtr, typeof(VideoInfoHeader));
videoStride = videoWidth * (videoInfoHeader.BmiHeader.BitCount / 8);
this.mediaInfo.MediaWidth = videoWidth;
this.mediaInfo.MediaHeight = videoHeight;
this.mediaInfo.MediaStride = videoStride;
this.mediaInfo.MediaBitCount = videoInfoHeader.BmiHeader.BitCount;
this.mediaInfo.fps = this.getFramePerSecond();
this.mediaInfo.duration = this.getDuration();
this.mediaInfo.sFilePath = this.filename.ToString();
DsUtils.FreeAMMediaType(media);
media = null;
private void CloseInterfaces()
lock (this)
int hr;
try
if (this.mediaControl != null)
hr = this.mediaControl.StopWhenReady();
this.mediaControl = null;
if (currentState != GraphState.Exiting)
currentState = GraphState.Exiting;
if (manualResetEvent != null)
manualResetEvent.Set();
if (this.videoWindow != null)
hr = this.videoWindow.put_Visible(OABool.False);
hr = this.videoWindow.put_Owner(IntPtr.Zero);
this.videoWindow = null;
this.mediaSeeking = null;
this.mediaPosition = null;
this.basicVideo = null;
this.basicAudio = null;
this.mediaDet = null;
if (this.graphBuilder != null)
Marshal.ReleaseComObject(this.graphBuilder);
this.graphBuilder = null;
catch (Exception e)
MessageBox.Show(e.Message);
return;
GC.Collect();
public void Start()
if (this.currentState == GraphState.Stopped || this.currentState == GraphState.Paused)
DsError.ThrowExceptionForHR(mediaControl.Run());
this.currentState = GraphState.Running;
public void Stop()
if (this.currentState == GraphState.Running || this.currentState == GraphState.Paused)
DsError.ThrowExceptionForHR(mediaControl.Stop());
currentState = GraphState.Stopped;
public void End()
double endPosition = 0;
this.mediaDet.get_StreamLength(out endPosition);
DsError.ThrowExceptionForHR(mediaPosition.put_CurrentPosition(endPosition));
【问题讨论】:
可以给codeproject的链接吗? 【参考方案1】:很可能是您安装了 DirectVobSub 过滤器(通常作为某些编解码器包的一部分),它以高品质(优先级)注册自己,这允许它在过滤器图构建过程中闯入并将自己插入您的管道甚至不是您代码的一部分。
过滤器会查找字幕文件并自动加载它们,然后更新视频源。
DirectVobSub(以前称为 VSFilter)是 Microsoft Windows 的软件插件(DirectShow 过滤器),能够读取外部字幕文件并将它们叠加在正在播放的视频文件上。
您想卸载它,或禁用它的自动自激活功能。
另见:
Understanding Your DirectShow Filter Graph - 了解哪些过滤器在您的管道中有效【讨论】:
以上是关于为啥 DirectShow 加载视频字幕文件?的主要内容,如果未能解决你的问题,请参考以下文章