/// <summary> /// Close the output and release the variables /// </summary> public void Close() { if (m_Init) //We are currently writing { if (m_pWMWriter != null) { // Close the file try { m_pWMWriter.EndWriting(); } catch { } } m_Init = false; } if (m_pInputProps != null) { Marshal.ReleaseComObject(m_pInputProps); m_pInputProps = null; } if (m_pWMWriter != null) { Marshal.ReleaseComObject(m_pWMWriter); m_pWMWriter = null; } }
/// <summary> /// Dispose of everything that may need disposing. /// </summary> public void Cleanup() { scriptBitrate = 0; writerAdvanced = null; writer = null; netSink = null; fileSink = null; audioProps = null; videoProps = null; audioInput = 0; videoInput = 0; scriptStreamNumber = 0; profileManager = null; }
public WMWriter(MediaBuffer mb) { eventLog = new EventLog("WMG", ".", "WMGCore"); mb.OnSampleReady += new MediaBuffer.sampleReadyHandler(ReceiveSample); scriptBitrate = 0; writerAdvanced = null; writer = null; netSink = null; fileSink = null; audioProps = null; videoProps = null; audioInput = 0; videoInput = 0; scriptStreamNumber = 0; lastWriteTime = 0; profileManager = null; writeFailed = false; }
/// <summary> /// Create filename from specified profile using specified framerate /// </summary> /// <param name="lpszFileName">File name to create</param> /// <param name="guidProfileID">WM Profile to use for compression</param> /// <param name="iFrameRate">Frames Per Second</param> public CwmvFile(string lpszFileName, ref Guid guidProfileID, int iFrameRate) { Guid guidInputType; int dwInputCount; IWMProfileManager pWMProfileManager = null; IWMProfile pWMProfile = null; // Initialize all member variables m_iFrameRate = iFrameRate; m_dwVideoInput = -1; m_dwCurrentVideoSample = 0; m_msVideoTime = 0; m_pWMWriter = null; m_pInputProps = null; m_Init = false; try { // Open the profile manager WMUtils.WMCreateProfileManager(out pWMProfileManager); // Convert pWMProfileManager to a IWMProfileManager2 IWMProfileManager2 pProfileManager2 = (IWMProfileManager2)pWMProfileManager; // Specify the version number of the profiles to use pProfileManager2.SetSystemProfileVersion(WMVersion.V8_0); // Load the profile specified by the caller pProfileManager2.LoadProfileByID(guidProfileID, out pWMProfile); // Create a writer. This is the interface we actually write with WMUtils.WMCreateWriter(IntPtr.Zero, out m_pWMWriter); // Set the profile we got into the writer. This controls compression, video // size, # of video channels, # of audio channels, etc m_pWMWriter.SetProfile(pWMProfile); // Find out how many inputs are in the current profile m_pWMWriter.GetInputCount(out dwInputCount); // Assume we won't find any video pins m_dwVideoInput = -1; // Find the first video input on the writer for (int i = 0; i < dwInputCount; i++) { // Get the properties of channel #i m_pWMWriter.GetInputProps(i, out m_pInputProps); // Read the type of the channel m_pInputProps.GetType(out guidInputType); // If it is video, we are done if (guidInputType == MediaType.Video) { m_dwVideoInput = i; break; } } // Didn't find a video channel if (m_dwVideoInput == -1) { throw new Exception("Profile does not accept video input"); } // Specify the file name for the output m_pWMWriter.SetOutputFilename(lpszFileName); } catch { Close(); throw; } finally { // Release the locals if (pWMProfile != null) { Marshal.ReleaseComObject(pWMProfile); pWMProfile = null; } if (pWMProfileManager != null) { Marshal.ReleaseComObject(pWMProfileManager); pWMProfileManager = null; } } }
public bool FindAudioInputFormat(uint inputNum, Guid subtype, WaveFormat readerWaveFormat) { bool success = false; IWMInputMediaProps writerInputProps = null; WM_MEDIA_TYPE mediaType; uint bufferSize = (uint)(Marshal.SizeOf(typeof(WM_MEDIA_TYPE)) + Marshal.SizeOf(typeof(WaveFormat))); uint formatCount; Logger.WriteLogMessage("Finding audio input formats for writer, input [" + inputNum + "]."); _writer.GetInputFormatCount(inputNum, out formatCount); Logger.WriteLogMessage("Audio writer can consume " + formatCount + " possible audio input formats."); IntPtr buffer = Marshal.AllocCoTaskMem((int)bufferSize); try { for (uint j = 0; j < formatCount; j++) { uint size = 0; try { _writer.GetInputFormat(inputNum, j, out writerInputProps); writerInputProps.GetMediaType(IntPtr.Zero, ref size); if (size > bufferSize) { bufferSize = size; Marshal.FreeCoTaskMem(buffer); buffer = Marshal.AllocCoTaskMem((int)bufferSize); } writerInputProps.GetMediaType(buffer, ref size); mediaType = (WM_MEDIA_TYPE)Marshal.PtrToStructure(buffer, typeof(WM_MEDIA_TYPE)); if (mediaType.formattype == FormatTypes.WMFORMAT_WaveFormatEx) { Logger.WriteLogMessage("Found writer audio input format [" + j + "], format type [" + GetFormatTypeName(mediaType.formattype) + "], subtype [" + GetSubTypeName(mediaType.subtype) + "], sample size [" + mediaType.lSampleSize + "]."); WaveFormat waveFormat = (WaveFormat)Marshal.PtrToStructure(mediaType.pbFormat, typeof(WaveFormat)); WaveFormats format = (WaveFormats)waveFormat.wFormatTag; Logger.WriteLogMessage("Found audio stream, format [" + format + "], sample rate [" + waveFormat.nSamplesPerSec + "], bits per sample [" + waveFormat.wBitsPerSample + "], bytes/sec [" + waveFormat.nAvgBytesPerSec + "], channels [" + waveFormat.nChannels + "]."); if (waveFormat.nSamplesPerSec == readerWaveFormat.nSamplesPerSec && waveFormat.nChannels == readerWaveFormat.nChannels && waveFormat.wBitsPerSample == readerWaveFormat.wBitsPerSample && waveFormat.wFormatTag == readerWaveFormat.wFormatTag) { writerInputProps.SetMediaType(ref mediaType); _writer.SetInputProps(inputNum, writerInputProps); success = true; break; } } } catch (Exception) { // error handle throw; } finally { Marshal.ReleaseComObject(writerInputProps); writerInputProps = null; } } } catch (Exception) { // error handle throw; } finally { Marshal.FreeCoTaskMem(buffer); } return(success); }
public bool FindVideoInputFormat(uint inputNum, Guid subtype, ref VideoInfoHeader inputVideoInfoHeader, bool enableCompressedSamples) { bool success = false; IWMInputMediaProps writerInputProps = null; WM_MEDIA_TYPE mediaType; uint bufferSize = (uint)(Marshal.SizeOf(typeof(WM_MEDIA_TYPE)) + Marshal.SizeOf(typeof(VideoInfoHeader))); uint formatCount; Logger.WriteLogMessage("Finding video input formats for writer, input [" + inputNum + "]."); _writer.GetInputFormatCount(inputNum, out formatCount); Logger.WriteLogMessage("Video writer can consume " + formatCount + " possible video input formats."); IntPtr buffer = Marshal.AllocCoTaskMem((int)bufferSize); try { for (uint j = 0; j < formatCount; j++) { uint size = 0; try { _writer.GetInputFormat(inputNum, j, out writerInputProps); writerInputProps.GetMediaType(IntPtr.Zero, ref size); if (size > bufferSize) { bufferSize = size; Marshal.FreeCoTaskMem(buffer); buffer = Marshal.AllocCoTaskMem((int)bufferSize); } writerInputProps.GetMediaType(buffer, ref size); mediaType = (WM_MEDIA_TYPE)Marshal.PtrToStructure(buffer, typeof(WM_MEDIA_TYPE)); if (mediaType.formattype == FormatTypes.WMFORMAT_VideoInfo) { Logger.WriteLogMessage("Found video writer input format [" + j + "], format type [" + GetFormatTypeName(mediaType.formattype) + "], subtype [" + GetSubTypeName(mediaType.subtype) + "], sample size [" + mediaType.lSampleSize + "]."); inputVideoInfoHeader = (VideoInfoHeader)Marshal.PtrToStructure(mediaType.pbFormat, typeof(VideoInfoHeader)); Logger.WriteLogMessage("Found input video stream, width [" + inputVideoInfoHeader.bmiHeader.biWidth + "], height [" + inputVideoInfoHeader.bmiHeader.biHeight + "], bit count [" + inputVideoInfoHeader.bmiHeader.biBitCount + "], image size [" + inputVideoInfoHeader.bmiHeader.biSizeImage + "]."); if (mediaType.subtype == subtype) { writerInputProps.SetMediaType(ref mediaType); if (!enableCompressedSamples) { _writer.SetInputProps(inputNum, writerInputProps); } else { _writer.SetInputProps(inputNum, null); } success = true; break; } } } catch (Exception) { // error handle throw; } finally { Marshal.ReleaseComObject(writerInputProps); writerInputProps = null; } } } catch (Exception) { // error handle throw; } finally { Marshal.FreeCoTaskMem(buffer); } return(success); }
/// <summary> /// Load a WM Profile (system or custom). /// </summary> /// <param name="prxFile"></param> /// <param name="prIndex"></param> /// <returns></returns> public bool ConfigProfile(String prxFile, uint prIndex) { IWMProfile profile; uint hr = WMFSDKFunctions.WMCreateProfileManager(out profileManager); if (prxFile == "") { //use system profile Guid prg = ProfileIndexToGuid(prIndex); if (prg == Guid.Empty) { profile = null; Debug.WriteLine("Unsupported Profile index."); return(false); } try { GUID prG = WMGuids.ToGUID(prg); profileManager.LoadProfileByID(ref prG, out profile); } catch (Exception e) { eventLog.WriteEntry("Failed to load system profile: " + e.ToString(), EventLogEntryType.Error, 1000); Debug.WriteLine("Failed to load system profile: " + e.ToString()); profile = null; return(false); } } else { //use custom profile profile = LoadCustomProfile(prxFile); if (profile == null) { return(false); } } /// Tell the writer to use this profile. try { writer.SetProfile(profile); string name = GetProfileName(profile); Debug.WriteLine("Using profile: " + name); } catch (Exception e) { eventLog.WriteEntry("Failed to set writer profile: " + e.ToString(), EventLogEntryType.Error, 1000); Debug.WriteLine("Failed to set writer profile: " + e.ToString()); profile = null; return(false); } /// A slightly confusing point: Streams are subobjects of the profile, /// while inputs are subobjects of the Writer. The difference is in the /// multi-bitrate scenario where there may be multiple streams per input. /// Stream numbers start with 1, while input numbers and stream indexes begin at 0. /// If we have a profile that supports scripts, we need the stream number of /// the script stream. For audio and video, we just need input number. scriptBitrate = 0; audioInput = videoInput = 0; scriptStreamNumber = 0; audioProps = videoProps = null; /// If the profile has a script stream, find the bitrate and stream number. uint cStreams; IWMStreamConfig streamConfig; GUID streamType; profile.GetStreamCount(out cStreams); for (uint i = 0; i < cStreams; i++) { profile.GetStream(i, out streamConfig); streamConfig.GetStreamType(out streamType); if (WMGuids.ToGuid(streamType) == WMGuids.WMMEDIATYPE_Script) { streamConfig.GetStreamNumber(out scriptStreamNumber); streamConfig.GetBitrate(out scriptBitrate); } } /// Iterate over writer inputs, holding on to the IWMInputMediaProps* for each, /// so we can later configure them. Also save input numbers for audio and video here. uint cInputs; writer.GetInputCount(out cInputs); GUID guidInputType; IWMInputMediaProps inputProps = null; for (uint i = 0; i < cInputs; i++) { writer.GetInputProps(i, out inputProps); inputProps.GetType(out guidInputType); if (WMGuids.ToGuid(guidInputType) == WMGuids.WMMEDIATYPE_Audio) { audioProps = inputProps; audioInput = i; } else if (WMGuids.ToGuid(guidInputType) == WMGuids.WMMEDIATYPE_Video) { videoProps = inputProps; videoInput = i; } else if (WMGuids.ToGuid(guidInputType) == WMGuids.WMMEDIATYPE_Script) { } else { Debug.WriteLine("Profile contains unrecognized media type."); return(false); } } // We require an audio input, since that drives the timing for the whole stream. if (audioProps == null) { Debug.WriteLine("Profile should contain at least one audio input."); return(false); } return(true); }