private IBaseFilter ConfigAsf(ICaptureGraphBuilder2 capGraph, string szOutputFileName) { IFileSinkFilter pTmpSink = null; IBaseFilter asfWriter = null; int hr = capGraph.SetOutputFileName(MediaSubType.Asf, szOutputFileName, out asfWriter, out pTmpSink); Marshal.ThrowExceptionForHR(hr); try { IConfigAsfWriter lConfig = asfWriter as IConfigAsfWriter; // Windows Media Video 8 for Dial-up Modem (No audio, 56 Kbps) // READ THE README for info about using guids Guid cat = new Guid(0x6E2A6955, 0x81DF, 0x4943, 0xBA, 0x50, 0x68, 0xA9, 0x86, 0xA7, 0x08, 0xF6); hr = lConfig.ConfigureFilterUsingProfileGuid(cat); Marshal.ThrowExceptionForHR(hr); } finally { Marshal.ReleaseComObject(pTmpSink); } return(asfWriter); }
private void Configure() { int hr; m_FilterGraph = (IFilterGraph2) new FilterGraph(); m_asfw = (IConfigAsfWriter) new WMAsfWriter(); hr = m_FilterGraph.AddFilter((IBaseFilter)m_asfw, "asdf"); DsError.ThrowExceptionForHR(hr); }
/// <summary> /// 初始化图表 /// </summary> public bool InitGraph(string sViewPath) { if (!VerStarPreview()) { MessageBox.Show("请先开始预览!"); return(false); } mediaControl.Stop(); CreateGraph(_Resolution, _Frames); int hr; if (sVideoType == "wmv") { hr = captureGraphBuilder.SetOutputFileName(MediaSubType.Asf, sViewPath, out mux, out sink); Marshal.ThrowExceptionForHR(hr); try { IConfigAsfWriter lConfig = mux as IConfigAsfWriter; // Windows Media Video (audio, 700 Kbps) // READ THE README for info about using guids Guid cat = new Guid("ec298949-639b-45e2-96fd-4ab32d5919c2"); hr = lConfig.ConfigureFilterUsingProfileGuid(cat); Marshal.ThrowExceptionForHR(hr); } finally { Marshal.ReleaseComObject(sink); } } else if (sVideoType == "avi") { hr = captureGraphBuilder.SetOutputFileName(MediaSubType.Avi, sViewPath, out mux, out sink); DsError.ThrowExceptionForHR(hr); } //将设备和压缩器连接到mux,以呈现图形的捕获部分 hr = captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Interleaved, theDevice, theDeviceCompressor, mux); //DsError.ThrowExceptionForHR(hr); if (hr < 0) { hr = captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Video, theDevice, theDeviceCompressor, mux); if (hr < 0) { DsError.ThrowExceptionForHR(hr); } } //将音频添加进去 hr = captureGraphBuilder.RenderStream(PinCategory.Capture, MediaType.Audio, theAudio, theAudioCompressor, mux); DsError.ThrowExceptionForHR(hr); Marshal.ReleaseComObject(mux); Marshal.ReleaseComObject(sink); return(true); }
/// <summary> /// Update Asf audio/video item information /// </summary> /// <param name="asfWriter"></param> /// <param name="asfItem"></param> /// <returns></returns> public bool UpdateAsfAVFormat(IBaseFilter asfWriter, int asfItem) { if (asfWriter != null) { IConfigAsfWriter lConfig = asfWriter as IConfigAsfWriter; int hr = 0; // Set Windows Media Audio/Video format first if (asfItem >= 0) { // Get Guid for this item Guid guid = GetAsfItemGuid(asfItem); if (guid != Guid.Empty) { // Obsolete interface ??? hr = lConfig.ConfigureFilterUsingProfileGuid(guid); if (hr < 0) { MessageBox.Show("Problems with updating Windows Media audio/video format information via Guid."); return(false); } else { this.CurrentAsfItem = asfItem; } } else if (this[asfItem].Filename.Length > 0) { if (!this.ConfigProfileFromFile(asfWriter, this[asfItem].Filename)) { MessageBox.Show("Problems with updating Windows Media audio/video format information via prx file."); } else { this.CurrentAsfItem = asfItem; } } } // Set other (more general) settings, if needed // Set index hr = lConfig.SetIndexMode(this.UseIndex); if (hr < 0) { MessageBox.Show("Problems with updating Windows Media index information."); } } return(true); }
// End of NEW /// <summary> /// Configure profile from file to Asf file writer /// </summary> /// <param name="asfWriter"></param> /// <param name="filename"></param> /// <returns></returns> public bool ConfigProfileFromFile(IBaseFilter asfWriter, string filename) { int hr; //string profilePath = "test.prx"; // Set the profile to be used for conversion if ((filename != null) && (File.Exists(filename))) { // Load the profile XML contents string profileData; using (StreamReader reader = new StreamReader(File.OpenRead(filename))) { profileData = reader.ReadToEnd(); } // Create an appropriate IWMProfile from the data // Open the profile manager IWMProfileManager profileManager; IWMProfile wmProfile = null; hr = WMLib.WMCreateProfileManager(out profileManager); if (hr >= 0) { // error message: The profile is invalid (0xC00D0BC6) // E.g. no <prx> tags hr = profileManager.LoadProfileByData(profileData, out wmProfile); } if (profileManager != null) { Marshal.ReleaseComObject(profileManager); profileManager = null; } // Config only if there is a profile retrieved if (hr >= 0) { // Set the profile on the writer IConfigAsfWriter configWriter = (IConfigAsfWriter)asfWriter; hr = configWriter.ConfigureFilterUsingProfile(wmProfile); if (hr >= 0) { return(true); } } } return(false); }
private void InitAsfWriter(out IBaseFilter asfWriter, bool shittyQuality = false) { int hr; asfWriter = (IBaseFilter) new WMAsfWriter(); hr = m_FilterGraph.AddFilter(asfWriter, "ASF Writer"); Marshal.ThrowExceptionForHR(hr); if (shittyQuality) { return; } // Create an appropriate IWMProfile from the data // Open the profile manager IWMProfileManager profileManager; IWMProfile wmProfile = null; WMUtils.WMCreateProfileManager(out profileManager); // error message: The profile is invalid (0xC00D0BC6) // E.g. no <prx> tags string profile = System.Text.Encoding.ASCII.GetString(Convert.FromBase64String(customGoodProfile)); profileManager.LoadProfileByData(profile, out wmProfile); if (profileManager != null) { Marshal.ReleaseComObject(profileManager); profileManager = null; } // Config only if there is a profile retrieved // Set the profile on the writer IConfigAsfWriter configWriter = (IConfigAsfWriter)asfWriter; configWriter.ConfigureFilterUsingProfile(wmProfile); }
private bool AddWmAsfWriter(string fileName, Quality quality, Standard standard) { //add asf file writer IPin pinOut0, pinOut1; IPin pinIn0, pinIn1; Log.Info("DVRMS2WMV: add WM ASF Writer to graph"); string monikerAsfWriter = @"@device:sw:{083863F1-70DE-11D0-BD40-00A0C911CE86}\{7C23220E-55BB-11D3-8B16-00C04FB6BD3D}"; fileWriterbase = Marshal.BindToMoniker(monikerAsfWriter) as IBaseFilter; if (fileWriterbase == null) { Log.Error("DVRMS2WMV:FAILED:Unable to create ASF WM Writer"); Cleanup(); return(false); } int hr = graphBuilder.AddFilter(fileWriterbase, "WM ASF Writer"); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:Add ASF WM Writer to filtergraph :0x{0:X}", hr); Cleanup(); return(false); } IFileSinkFilter2 fileWriterFilter = fileWriterbase as IFileSinkFilter2; if (fileWriterFilter == null) { Log.Error("DVR2XVID:FAILED:Add unable to get IFileSinkFilter for filewriter"); Cleanup(); return(false); } hr = fileWriterFilter.SetFileName(fileName, null); hr = fileWriterFilter.SetMode(AMFileSinkFlags.OverWrite); Log.Info("DVRMS2WMV: connect audio/video codecs outputs -> ASF WM Writer"); //connect output #0 of videocodec->asf writer pin 1 //connect output #0 of audiocodec->asf writer pin 0 pinOut0 = DsFindPin.ByDirection((IBaseFilter)Mpeg2AudioCodec, PinDirection.Output, 0); pinOut1 = DsFindPin.ByDirection((IBaseFilter)Mpeg2VideoCodec, PinDirection.Output, 0); if (pinOut0 == null || pinOut1 == null) { Log.Error("DVRMS2WMV:FAILED:unable to get outpins of video codec"); Cleanup(); return(false); } pinIn0 = DsFindPin.ByDirection(fileWriterbase, PinDirection.Input, 0); if (pinIn0 == null) { Log.Error("DVRMS2WMV:FAILED:unable to get pins of asf wm writer"); Cleanup(); return(false); } hr = graphBuilder.Connect(pinOut0, pinIn0); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:unable to connect audio pins :0x{0:X}", hr); Cleanup(); return(false); } pinIn1 = DsFindPin.ByDirection(fileWriterbase, PinDirection.Input, 1); if (pinIn1 == null) { Log.Error("DVRMS2WMV:FAILED:unable to get pins of asf wm writer"); Cleanup(); return(false); } hr = graphBuilder.Connect(pinOut1, pinIn1); if (hr != 0) { Log.Error("DVRMS2WMV:FAILED:unable to connect video pins :0x{0:X}", hr); Cleanup(); return(false); } IConfigAsfWriter config = fileWriterbase as IConfigAsfWriter; IWMProfileManager profileManager = null; IWMProfileManager2 profileManager2 = null; IWMProfile profile = null; hr = WMLib.WMCreateProfileManager(out profileManager); string strprofileType = ""; switch (quality) { case Quality.HiDef: //hr = WMLib.WMCreateProfileManager(out profileManager); if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHiDef-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHiDef-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHiDef-PAL.prx"); } Log.Info("DVRMS2WMV: set WMV HiDef quality profile {0}", strprofileType); break; case Quality.VeryHigh: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPVeryHigh-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPVeryHigh-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPVeryHigh-PAL.prx"); } Log.Info("DVRMS2WMV: set WMV Very High quality profile {0}", strprofileType); break; case Quality.High: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHigh-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHigh-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPHigh-PAL.prx"); } Log.Info("DVRMS2WMV: set WMV High quality profile {0}", strprofileType); break; case Quality.Medium: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPMedium-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPMedium-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPMedium-PAL.prx"); } Log.Info("DVRMS2WMV: set WMV Medium quality profile {0}", strprofileType); break; case Quality.Low: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPLow-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPLow-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPLow-PAL.prx"); } Log.Info("DVRMS2WMV: set WMV Low quality profile {0}", strprofileType); break; case Quality.Portable: if (standard == Standard.Film) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPPortable-FILM.prx"); } if (standard == Standard.NTSC) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPPortable-NTSC.prx"); } if (standard == Standard.PAL) { strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPPortable-PAL.prx"); } Log.Info("DVRMS2WMV: set WMV Portable quality profile {0}", strprofileType); break; case Quality.Custom: //load custom profile string customBitrate = ""; //Adjust the parameters to suit the custom settings the user has selected. switch (bitrate) { case 0: customBitrate = "100Kbs"; break; case 1: customBitrate = "256Kbs"; break; case 2: customBitrate = "384Kbs"; break; case 3: customBitrate = "768Kbs"; break; case 4: customBitrate = "1536Kbs"; break; case 5: customBitrate = "3072Kbs"; break; case 6: customBitrate = "5376Kbs"; break; } Log.Info("DVRMS2WMV: custom bitrate = {0}", customBitrate); //TODO: get fps values & frame size //TODO: adjust settings required //Call the SetCutomPorfile method to load the custom profile, adjust it's params from user settings & then save it. //SetCutomProfile(videoBitrate, audioBitrate, videoHeight, videoWidth, videoFps); //based on user inputs //We then reload it after as per other quality settings / profiles. strprofileType = Config.GetFile(Config.Dir.Base, @"Profiles\MPCustom.prx"); Log.Info("DVRMS2WMV: set WMV Custom quality profile {0}", strprofileType); break; } //Loads profile from the above quality selection. using (StreamReader prx = new StreamReader(strprofileType)) { String profileContents = prx.ReadToEnd(); profileManager2 = profileManager as IWMProfileManager2; hr = profileManager2.LoadProfileByData(profileContents, out profile); if (hr != 0) { Log.Info("DVRMS2WMV: get WMV profile - FAILED! {0}", hr); Cleanup(); return(false); } } Log.Info("DVRMS2WMV: load profile - SUCCESS!"); //configures the WM ASF Writer to the chosen profile hr = config.ConfigureFilterUsingProfile(profile); if (hr != 0) { Log.Info("DVRMS2WMV: configure profile - FAILED! {0}", hr); Cleanup(); return(false); } Log.Info("DVRMS2WMV: configure profile - SUCCESS!"); //TODO: Add DB recording information into WMV. //Release resorces if (profile != null) { Marshal.ReleaseComObject(profile); profile = null; } if (profileManager != null) { Marshal.ReleaseComObject(profileManager); profileManager = null; } return(true); }
/// <summary> /// WMV 形式ファイル保存用: ビデオのフレームサイズを設定します。 /// </summary> /// <param name="config">ASF Writer から取得したインターフェース</param> /// <param name="size">設定値</param> /// <remarks> /// 第一引数の <c>config</c> は下記のように取得してください。<br/> /// <example lang="c#"> /// var filetype = new Guid(GUID.MEDIASUBTYPE_Asf); /// builder.SetOutputFileName(new IntPtr(&filetype), filename, ref videoRenderer, ref fileSink); /// var config = (IConfigAsfWriter)videoRenderer; /// </example> /// <br/> /// 詳細は下記に記載されています。(但し、言語は C++ です。) <br/> /// <br/> /// <list type="bullet"> /// <item> /// Capturing Video to a Windows Media File <br/> /// https://msdn.microsoft.com/en-us/library/windows/desktop/dd318630(v=vs.85).aspx /// </item> /// <item> /// Creating ASF Files in DirectShow <br/> /// https://msdn.microsoft.com/en-us/library/windows/desktop/dd375008(v=vs.85).aspx /// <list type="bullet"> /// <item> /// Configuring the ASF Writer <br/> /// https://msdn.microsoft.com/en-us/library/windows/desktop/dd387911(v=vs.85).aspx /// </item> /// </list> /// </item> /// <item> /// Using Windows Media in DirectShow <br/> /// https://msdn.microsoft.com/en-us/library/windows/desktop/dd407300(v=vs.85).aspx /// <list type="bullet"> /// <item> /// WM ASF Writer Filter <br/> /// https://msdn.microsoft.com/en-us/library/windows/desktop/dd390985(v=vs.85).aspx /// </item> /// </list> /// </item> /// </list> /// <br/> /// しかし、上記の説明だけでは解決できないので、下記も参考にしています。<br/> /// Social <br/> /// https://social.msdn.microsoft.com/Forums/sqlserver/en-US/962d4370-5fde-4d23-83bc-b8f6191b375e/asf-writer-creates-a-file-that-appears-not-to-match-the-encoding-profile-settings?forum=windowsdirectshowdevelopment <br/> /// https://social.msdn.microsoft.com/forums/windowsdesktop/en-us/fb0a6151-d916-422a-966b-ee1fb164df5f/asf-profile-configurations-fails <br/> /// </remarks> public static void SetVideoFrameSize(IConfigAsfWriter config, Size size) { try { HRESULT hr; // 現在のプロファイルを取得します. IWMProfile profile; hr = (HRESULT)config.GetCurrentProfile(out profile); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // ストリームの個数を取得します. uint stream_num; hr = (HRESULT)profile.GetStreamCount(out stream_num); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // 映像入力のストリームを探索してフレームサイズを設定します. for (uint index = 0; index < stream_num; index++) { // ストリームを取得します. IWMStreamConfig stream_config; hr = (HRESULT)profile.GetStream(index, out stream_config); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // ストリームのメディアタイプを確認します. Guid stream_type; hr = (HRESULT)stream_config.GetStreamType(out stream_type); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // 映像以外は無視します. if (stream_type != new Guid(GUID.MEDIATYPE_Video)) { continue; } // メディアタイプ情報を格納するために必要なサイズ (bytes) を取得します. var props = (IWMMediaProps)stream_config; int cbType = 0; hr = (HRESULT)props.GetMediaType(IntPtr.Zero, ref cbType); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // メディアタイプ情報を格納する領域を確保します. var pwmt = Marshal.AllocHGlobal(cbType); if (pwmt != IntPtr.Zero) { try { // メディアタイプ情報を取得します. hr = (HRESULT)props.GetMediaType(pwmt, ref cbType); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } // フレームサイズを指定された値に書き替えます. unsafe { var wmt = (WM_MEDIA_TYPE *)pwmt; var vih = (VIDEOINFOHEADER *)wmt->pbFormat; vih->bmiHeader.biWidth = size.Width; // 幅. vih->bmiHeader.biHeight = size.Height; // 高さ. } // メディアタイプを設定します. hr = (HRESULT)props.SetMediaType(pwmt); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } finally { Marshal.FreeHGlobal(pwmt); } } // ストリームを再構成します. hr = (HRESULT)profile.ReconfigStream(stream_config); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } // プロファイルを再構成します. hr = (HRESULT)config.ConfigureFilterUsingProfile(profile); if (hr < HRESULT.S_OK) { throw new CxDSException(hr); } } catch (System.Exception ex) { throw ex; } }