110,533
社区成员
发帖
与我相关
我的任务
分享
int hr;
IAMTimeline m_pTimeline = (IAMTimeline)new AMTimeline();
hr = m_pTimeline.SetDefaultFPS(30);
DESError.ThrowExceptionForHR(hr);
IAMTimelineObj pGroupObj;
hr = m_pTimeline.CreateEmptyNode(out pGroupObj, TimelineMajorType.Group);
DESError.ThrowExceptionForHR(hr);
IAMTimelineGroup pGroup = (IAMTimelineGroup)pGroupObj;
AMMediaType m_pMediaType = GetVideoMediaType(24, 800, 600);
hr = pGroup.SetMediaType(m_pMediaType);
DESError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(m_pMediaType);
hr = m_pTimeline.AddGroup(pGroupObj);
DESError.ThrowExceptionForHR(hr);
IAMTimelineObj pTrack1Obj;
hr = m_pTimeline.CreateEmptyNode(out pTrack1Obj, TimelineMajorType.Track);
DESError.ThrowExceptionForHR(hr);
IAMTimelineComp pRootComp = (IAMTimelineComp)pGroupObj;
hr = pRootComp.VTrackInsBefore(pTrack1Obj, -1);
DESError.ThrowExceptionForHR(hr);
IAMTimelineObj pSource1Obj;
hr = m_pTimeline.CreateEmptyNode(out pSource1Obj, TimelineMajorType.Source);
DESError.ThrowExceptionForHR(hr);
//...
private long GetLength(String m_FileName)
{
int hr;
double d;
long i;
IMediaDet imd = (IMediaDet)new MediaDet();
// Set the name
hr = imd.put_Filename(m_FileName);
DESError.ThrowExceptionForHR(hr);
// Read from stream zero
hr = imd.put_CurrentStream(0);
DESError.ThrowExceptionForHR(hr);
// Get the length in seconds
hr = imd.get_StreamLength(out d);
DESError.ThrowExceptionForHR(hr);
Marshal.ReleaseComObject(imd);
// Convert to UNITS
i = (long)(d * (1000000000/100));
return i;
}
private bool IsVideo(IPin pPin)
{
int hr;
bool bRet = false;
AMMediaType[] pmt = new AMMediaType[1];
IEnumMediaTypes ppEnum;
// Walk the MediaTypes for the pin
hr = pPin.EnumMediaTypes(out ppEnum);
DESError.ThrowExceptionForHR(hr);
try
{
// Just read the first one
hr = ppEnum.Next(1, pmt, IntPtr.Zero);
DESError.ThrowExceptionForHR(hr);
bRet = pmt[0].majorType == MediaType.Video;
}
finally
{
Marshal.ReleaseComObject(ppEnum);
}
DsUtils.FreeAMMediaType(pmt[0]);
return bRet;
}
public interface IDESCombineCB
{
int BufferCB(
string sFileName,
double SampleTime,
System.IntPtr pBuffer,
int BufferLen
);
}
public class MyCallbacks : IDESCombineCB
{
private int m_FrameCount;
private long m_TotBytes;
private DateTime m_StartTime;
private double m_LastSampleTime;
private bool m_KeepTime;
public MyCallbacks()
{
}
~MyCallbacks()
{
}
public void KeepTime()
{
m_KeepTime = true;
}
public int BufferCB(string sFilename, double SampleTime, System.IntPtr pBuffer, int BufferLen)
{
return 0;
}
}
internal class MyCallback : ISampleGrabberCB
{
#region Data members
protected IDESCombineCB m_pCallback;
protected IMediaEventSink m_pEventSink;
protected EventCode m_ec;
protected int m_iCurFile;
protected int m_iCurFrame;
protected int m_iMaxFrame;
protected string m_CurFileName;
#endregion
public MyCallback(
IDESCombineCB pCallback,
IMediaEventSink pEventSink,
EventCode ec,
String mCurFileName,
int miMaxFrame
)
{
m_pCallback = pCallback;
m_pEventSink = pEventSink;
m_ec = ec;
m_iCurFrame = 0;
m_iCurFile = 0;
m_CurFileName = mCurFileName;
m_iMaxFrame = miMaxFrame;
}
public int SampleCB(double SampleTime, IMediaSample pSample)
{
Marshal.ReleaseComObject(pSample);
return 0;
}
public int BufferCB(double SampleTime, System.IntPtr pBuffer, int BufferLen)
{
int iRet;
if (m_pCallback != null)
{
iRet = m_pCallback.BufferCB(m_CurFileName, SampleTime, pBuffer, BufferLen);
}
else
{
iRet = 0;
}
m_iCurFrame++;
// Have we finished the current file?
if (m_iCurFrame >= m_iMaxFrame)
{
int hr = m_pEventSink.Notify(m_ec, new IntPtr(m_iCurFile), new IntPtr(m_iCurFrame));
m_iCurFile++;
}
return iRet;
}
}
private AMMediaType GetVideoMediaType(short BitCount, int Width, int Height)
{
Guid mediaSubType;
AMMediaType VideoGroupType = new AMMediaType();
// Calculate the SubType from the Bit count
switch (BitCount)
{
case 16:
mediaSubType = MediaSubType.RGB555;
break;
case 24:
mediaSubType = MediaSubType.RGB24;
break;
case 32:
mediaSubType = MediaSubType.RGB32;
break;
default:
throw new Exception("Unrecognized bit format");
}
VideoGroupType.majorType = MediaType.Video;
VideoGroupType.subType = mediaSubType;
VideoGroupType.formatType = FormatType.VideoInfo;
VideoGroupType.fixedSizeSamples = true;
VideoGroupType.formatSize = Marshal.SizeOf(typeof(VideoInfoHeader));
VideoInfoHeader vif = new VideoInfoHeader();
vif.BmiHeader = new BitmapInfoHeader();
// The HEADER macro returns the BITMAPINFO within the VIDEOINFOHEADER
vif.BmiHeader.Size = Marshal.SizeOf(typeof(BitmapInfoHeader));
vif.BmiHeader.Compression = 0;
vif.BmiHeader.BitCount = BitCount;
vif.BmiHeader.Width = Width;
vif.BmiHeader.Height = Height;
vif.BmiHeader.Planes = 1;
int iSampleSize = vif.BmiHeader.Width * vif.BmiHeader.Height * (vif.BmiHeader.BitCount / 8);
vif.BmiHeader.ImageSize = iSampleSize;
VideoGroupType.sampleSize = iSampleSize;
VideoGroupType.formatPtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(vif));
Marshal.StructureToPtr(vif, VideoGroupType.formatPtr, false);
return VideoGroupType;
}
public void getTest()
{
int hr;
IAMTimeline m_pTimeline = (IAMTimeline)new AMTimeline();
hr = m_pTimeline.SetDefaultFPS(30);
DESError.ThrowExceptionForHR(hr);
AMMediaType m_pMediaType = GetVideoMediaType(24, 320, 240);
IAMTimelineObj pGroupObj;
hr = m_pTimeline.CreateEmptyNode(out pGroupObj, TimelineMajorType.Group);
DESError.ThrowExceptionForHR(hr);
IAMTimelineGroup pGroup = (IAMTimelineGroup)pGroupObj;
hr = pGroup.SetMediaType(m_pMediaType);
DESError.ThrowExceptionForHR(hr);
DsUtils.FreeAMMediaType(m_pMediaType);
hr = m_pTimeline.AddGroup(pGroupObj);
DESError.ThrowExceptionForHR(hr);
IAMTimelineObj pTrack1Obj;
hr = m_pTimeline.CreateEmptyNode(out pTrack1Obj, TimelineMajorType.Track);
DESError.ThrowExceptionForHR(hr);
IAMTimelineComp pRootComp = (IAMTimelineComp)pGroupObj;
hr = pRootComp.VTrackInsBefore(pTrack1Obj, -1);
DESError.ThrowExceptionForHR(hr);
IAMTimelineObj pSource1Obj;
hr = m_pTimeline.CreateEmptyNode(out pSource1Obj, TimelineMajorType.Source);
DESError.ThrowExceptionForHR(hr);
String mFileName = @"G:\cake.mpeg";
long lStart = 0;
long lEnd = GetLength(mFileName);
hr = pSource1Obj.SetStartStop(lStart, lEnd);
DESError.ThrowExceptionForHR(hr);
IAMTimelineSrc pSource1Src = (IAMTimelineSrc)pSource1Obj;
hr = pSource1Src.SetMediaName(mFileName);
DESError.ThrowExceptionForHR(hr);
hr = pSource1Src.SetMediaTimes(lStart, lEnd);
DESError.ThrowExceptionForHR(hr);
IAMTimelineTrack m_Track = (IAMTimelineTrack)pTrack1Obj;
hr = m_Track.SrcAdd(pSource1Obj);
DESError.ThrowExceptionForHR(hr);
hr = pSource1Src.FixMediaTimes(ref lStart, ref lEnd);
DESError.ThrowExceptionForHR(hr);
IRenderEngine m_pRenderEngine = (IRenderEngine)new RenderEngine();
hr = m_pRenderEngine.SetTimelineObject(m_pTimeline);
DESError.ThrowExceptionForHR(hr);
hr = m_pRenderEngine.ConnectFrontEnd();
DESError.ThrowExceptionForHR(hr);
IGraphBuilder m_pGraph;
hr = m_pRenderEngine.GetFilterGraph(out m_pGraph);
DESError.ThrowExceptionForHR(hr);
ICaptureGraphBuilder2 icgb = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
hr = icgb.SetFiltergraph(m_pGraph);
DESError.ThrowExceptionForHR(hr);
IPin pPin = null;
int NumGroups;
IAMTimelineObj pGroupz;
hr = m_pTimeline.GetGroupCount(out NumGroups);
DESError.ThrowExceptionForHR(hr);
for (int i = 0; i < NumGroups; i++)
{
hr = m_pTimeline.GetGroup(out pGroupz, i);
DESError.ThrowExceptionForHR(hr);
IAMTimelineGroup pTLGroup = (IAMTimelineGroup)pGroupz;
hr = pTLGroup.SetPreviewMode(true);
DESError.ThrowExceptionForHR(hr);
hr = m_pRenderEngine.GetGroupOutputPin(i, out pPin);
DESError.ThrowExceptionForHR(hr);
if (IsVideo(pPin))
{
IBaseFilter ibfVideoRenderer = (IBaseFilter)new VideoRenderer();
//MyCallback mcb = new MyCallback(m_Video, pVideoCallback, (IMediaEventSink)m_pGraph, EC_VideoFileComplete);
hr = m_pGraph.AddFilter(ibfVideoRenderer, "Video Renderer");
DESError.ThrowExceptionForHR(hr);
IBaseFilter ibfSampleGrabber = null;
ISampleGrabber isg = (ISampleGrabber)new SampleGrabber();
MyCallbacks cb = new MyCallbacks();
MyCallback pCallback = new MyCallback(cb, (IMediaEventSink)m_pGraph, (EventCode)0x8000, mFileName, 1951);
hr = isg.SetCallback(pCallback, 1);
DESError.ThrowExceptionForHR(hr);
ibfSampleGrabber = (IBaseFilter)isg;
hr = m_pGraph.AddFilter(ibfSampleGrabber, "Video sample grabber");
DESError.ThrowExceptionForHR(hr);
hr = icgb.RenderStream(null, null, pPin, ibfSampleGrabber, ibfVideoRenderer);
DESError.ThrowExceptionForHR(hr);
}
}
IVideoWindow pVidWindow;
pVidWindow = (IVideoWindow)m_pGraph;
hr = pVidWindow.put_Caption("Video Rendering Window");
DESError.ThrowExceptionForHR(hr);
WindowStyle lStyle = 0;
hr = pVidWindow.get_WindowStyle(out lStyle);
DESError.ThrowExceptionForHR(hr);
lStyle &= ~(WindowStyle.MinimizeBox | WindowStyle.MaximizeBox | WindowStyle.SysMenu);
hr = pVidWindow.put_WindowStyle(lStyle);
DESError.ThrowExceptionForHR(hr);
IMediaControl m_pControl;
m_pControl = (IMediaControl)m_pGraph;
hr = m_pControl.Run( );
DESError.ThrowExceptionForHR(hr);
}
要使 C# 代码引用 COM 对象和接口,需要在 C# 内部版本中包含 COM 接口的 .NET 框架定义。完成此操作的最简单方法是使用 TlbImp.exe(类型库导入程序),它是一个包括在 .NET 框架 SDK 中的命令行工具。TlbImp 将 COM 类型库转换为 .NET 框架元数据,从而有效地创建一个可以从任何托管语言调用的托管包装。用 TlbImp 创建的 .NET 框架元数据可以通过 /R 编译器选项包括在 C# 内部版本中。如果使用 Visual Studio 开发环境,则只需添加对 COM 类型库的引用,将为您自动完成此转换。
例如,我们要播放当前目录下的demo.avi文件,需要用到包含在位于 Windows 系统目录中的 Quartz.dll 中的媒体播放机。(c:\winnt\system32\quartz.dll)。可在命令行中运行TlbImp文件(D:\ Microsoft Visual Studio .NET\FrameworkSDK\Bin\Tlbimp.exe)
tlbimp c:\winnt\system32\quartz.dll /out:QuartzTypeLib.dll
请注意,得到的 DLL 需要命名为 QuartzTypeLib,以便 .NET 框架可以在运行时正确加载包含类型。
生成程序时使用 C# 编译器选项 /R 以包含 QuartzTypeLib.dll 文件;如果使用 Visual Studio 开发环境,直接添加引用即可(using QuartzTypeLib)。
然后就可以使用此程序显示影片了。
具体编写代码时,用到了RenderFile 和 Run 方法。例:
private void menuItemOpen_Click(object sender, System.EventArgs e)
{
FilgraphManager m_FilGraphManager = null;
IBasicAudio m_BasicAudio = null;
IVideoWindow m_VideoWindow = null;
IMediaEvent m_MediaEvent = null;
IMediaEventEx m_MediaEventEx = null;
IMediaPosition m_MediaPosition = null;
IMediaControl m_MediaControl = null;
OpenFileDialog OpenDialog = new OpenFileDialog();
OpenDialog.Filter = "Media Files|*.mpg;*.avi;*.wma;*.mov;*.wav;*.mp2;*.mp3|All Files|*.*"; //本例用对话框读入要显示的影片文件名
if (DialogResult.OK == OpenDialog.ShowDialog())
{
m_FilGraphManager = new FilgraphManager();
m_FilGraphManager.RenderFile(OpenDialog.FileName);
m_BasicAudio = m_FilGraphManager as IBasicAudio ;
try
{
m_VideoWindow = m_FilGraphManager as IVideoWindow;
m_VideoWindow.Owner = (int) panel1.Handle;
m_VideoWindow.WindowStyle = WS_CHILD | WS_CLIPCHILDREN;
//此设置可以不显示播放器的title,使播放器像嵌在窗体中。
//可设置 private const int WS_CHILD = 0x40000000;
// private const int WS_CLIPCHILDREN = 0x2000000;
m_VideoWindow.SetWindowPosition(panel1.ClientRectangle.Left,
panel1.ClientRectangle.Top,
panel1.ClientRectangle.Width,
panel1.ClientRectangle.Height);
// 在panel1中显示,要求影片可随panel1大小而变化。
}
catch (Exception)
{
m_VideoWindow = null;
}
m_MediaEvent = m_FilGraphManager as IMediaEvent;
m_MediaEventEx = m_FilGraphManager as IMediaEventEx;
m_MediaEventEx.SetNotifyWindow((int) this.Handle,WM_GRAPHNOTIFY, 0);
m_MediaPosition = m_FilGraphManager as IMediaPosition;
m_MediaControl = m_FilGraphManager as IMediaControl;
this.Text = "DirectShow - [" + OpenDialog.FileName + "]";
m_MediaControl.Run();
}
}
也可以加入pause,stop命令来控制影片的播放。
m_MediaControl.Pause()
m_MediaControl.Stop()