// These routines are for testing IWMWriterAdvanced private void TestAdvanced(Bitmap b) { IWMWriterAdvanced adv = m_Writer as IWMWriterAdvanced; WriterStatistics ws; adv.GetStatistics(0, out ws); Debug.Assert(ws.dwCurrentBitrate > 0); INSSBuffer pSample = WriteOne(b); adv.WriteStreamSample(1, 1234, 5678, 101001, SampleFlag.CleanPoint, pSample); }
public static void CopyWmv(string inputFilePath, string outputFilePath, ulong startTime, long duration) { IWMWriterAdvanced writerAdvanced = null; IWMProfile profile = null; IWMStreamConfig streamConfig = null; uint streamCount = 0; uint inputCount = 0; ushort[] streamNumbers = null; WMT_STREAM_SELECTION[] streamSelections = null; ulong sampleTime, sampleDuration; uint flags, outputNum; ushort streamNum; INSSBuffer sample = null; IWMSyncReader reader = Helpers.CreateSyncReader(WMT_RIGHTS.WMT_RIGHT_NO_DRM); IWMWriter writer = Helpers.CreateWriter(); try { reader.Open(inputFilePath); Logger.WriteLogMessage("Opened file [" + inputFilePath + "] for reading."); profile = (IWMProfile)reader; profile.GetStreamCount(out streamCount); streamNumbers = new ushort[streamCount]; streamSelections = new WMT_STREAM_SELECTION[streamCount]; for (uint i = 0; i < streamCount; i++) { profile.GetStream(i, out streamConfig); streamConfig.GetStreamNumber(out streamNumbers[i]); streamSelections[i] = WMT_STREAM_SELECTION.WMT_ON; // // Read compressed samples // reader.SetReadStreamSamples(streamNumbers[i], true); } // // select all streams // reader.SetStreamsSelected((ushort)streamCount, streamNumbers, streamSelections); writer.SetProfile(profile); writer.GetInputCount(out inputCount); for (uint i = 0; i < inputCount; i++) { writer.SetInputProps(i, null); // write compressed samples } writer.SetOutputFilename(outputFilePath); Logger.WriteLogMessage("Set output filename [" + outputFilePath + "] for writing."); writerAdvanced = (IWMWriterAdvanced)writer; // Copy attributes avoided // Copy Codec Info avoided // Copy all scripts in the header avoided writer.BeginWriting(); // // startTime, duration are in 100-nsec ticks // reader.SetRange(startTime, duration); // seek Logger.WriteLogMessage("Set range on reader, startTime [" + startTime + "], duration [" + duration + "]."); for (uint streamsRead = 0; streamsRead < streamCount;) { try { streamNum = 0; reader.GetNextSample(0, out sample, out sampleTime, out sampleDuration, out flags, out outputNum, out streamNum); Logger.WriteLogMessage("Grabbed next video sample, sampleTime [" + sampleTime + "], duration [" + sampleDuration + "], flags [" + flags + "], outputNum [" + outputNum + "], streamNum [" + streamNum + "]."); writerAdvanced.WriteStreamSample(streamNum, sampleTime, 0, sampleDuration, flags, sample); Logger.WriteLogMessage("Wrote sample, sampleTime [" + sampleTime + "], duration [" + sampleDuration + "], flags [" + flags + "], outputNum [" + outputNum + "], streamNum [" + streamNum + "]."); } catch (COMException e) { if (e.ErrorCode == Constants.NS_E_NO_MORE_SAMPLES) { streamsRead++; } else { throw; } } } writer.EndWriting(); } finally { reader.Close(); } }
//------------------------------------------------------------------------------ // Name: CWMVCopy::OnStreamSample() // Desc: Implementation of IWMReaderCallbackAdvanced::OnStreamSample. //------------------------------------------------------------------------------ public void OnStreamSample( short wStreamNum, long cnsSampleTime, long cnsSampleDuration, SampleFlag dwFlags, INSSBuffer pSample, IntPtr pvContext) { bool fMoveScript = false; while (m_dwProgress <= cnsSampleTime * 50 / m_qwDuration) { m_dwProgress++; Console.Write("*"); } if (m_qwMaxDuration > 0 && cnsSampleTime > m_qwMaxDuration) { m_hEvent.Set(); return; } if (m_fMoveScriptStream) { // // We may have multiple script streams in this file. // for (int i = 0; i < m_dwStreamCount; i++) { if (m_pwStreamNumber[i] == wStreamNum) { if (MediaType.ScriptCommand == m_pguidStreamType[i]) { fMoveScript = true; } break; } } } try { if (fMoveScript) { int dwBufferLength; int nStringLength; IntPtr pwszTypeIP = IntPtr.Zero; StringBuilder pwszType = null; StringBuilder pwszCommand = null; // // Read the buffer and length of the script stream sample // pSample.GetBufferAndLength(out pwszTypeIP, out dwBufferLength); pwszType = new StringBuilder(Marshal.PtrToStringUni(pwszTypeIP)); //todo - this won't work if the string doesn't have a final \0 nStringLength = dwBufferLength / 2; if (nStringLength > 0) { // // Get the command string of this script // // Todo - maybe the format of pwszTypeIP is Type\0Command\0 ??? #if false pwszCommand = wcschr(pwszType, null); if (pwszCommand - pwszType < nStringLength - 1) { pwszCommand++; } else { pwszCommand = " "; } #else pwszCommand = new StringBuilder(" "); #endif // // Add the script to the script list. We cannot write scripts // directly to the writer after writing has begun. // m_ScriptList.Add(new CScript(pwszType.ToString(), pwszCommand.ToString(), cnsSampleTime)); } } else { m_pWriterAdvanced.WriteStreamSample(wStreamNum, cnsSampleTime, 0, cnsSampleDuration, dwFlags, pSample); } } catch (Exception e) { int hr = Marshal.GetHRForException(e); m_hr = hr; m_hEvent.Set(); } finally { Marshal.ReleaseComObject(pSample); } }
/// <summary> /// Write a script command into the stream /// </summary> /// <param name="type"></param> /// <param name="script"></param> /// <param name="packScript">Use both bytes of the unicode script string. This is /// used to more efficiently transmit Base64 encoded data in a script.</param> /// <returns></returns> /// The writer expects two null terminated WCHARs (two bytes per character). public bool SendScript(String type, String script, bool packScript) { IntPtr typePtr, scriptPtr, bufPtr; byte[] sampleBuf; INSSBuffer sample; ulong curTime; uint typesz, scriptsz, nulls; //ScriptStreamNumber == 0 means there is no script stream in the profile. if (scriptStreamNumber == 0) { return(false); } if (packScript) { typesz = (uint)(2 * (type.Length + 1)); //To make the script looks like unicode, need to terminate with two nulls, and //the total length needs to be an even number. scriptsz = (uint)script.Length; if (scriptsz % 2 == 0) { nulls = 2; } else { nulls = 3; } sampleBuf = new byte[typesz + scriptsz + nulls]; typePtr = Marshal.StringToCoTaskMemUni(type); scriptPtr = Marshal.StringToCoTaskMemAnsi(script); Marshal.Copy(typePtr, sampleBuf, 0, (int)typesz); Marshal.Copy(scriptPtr, sampleBuf, (int)typesz, (int)scriptsz); for (uint i = typesz + scriptsz + nulls - 1; i >= typesz + scriptsz; i--) { sampleBuf[i] = 0; } scriptsz += nulls; Marshal.FreeCoTaskMem(typePtr); Marshal.FreeCoTaskMem(scriptPtr); } else { //Marshal both strings as unicode. typesz = (uint)(2 * (type.Length + 1)); scriptsz = (uint)(2 * (script.Length + 1)); sampleBuf = new byte[typesz + scriptsz]; typePtr = Marshal.StringToCoTaskMemUni(type); scriptPtr = Marshal.StringToCoTaskMemUni(script); Marshal.Copy(typePtr, sampleBuf, 0, (int)typesz); Marshal.Copy(scriptPtr, sampleBuf, (int)typesz, (int)scriptsz); Marshal.FreeCoTaskMem(typePtr); Marshal.FreeCoTaskMem(scriptPtr); } try { lock (this) { writer.AllocateSample((typesz + scriptsz), out sample); sample.GetBuffer(out bufPtr); Marshal.Copy(sampleBuf, 0, bufPtr, (int)(typesz + scriptsz)); // Let the writer tell us what time it wants to use to avoid // rebuffering and other nastiness. Can this cause a loss of sync issue? writerAdvanced.GetWriterTime(out curTime); //writerAdvanced.WriteStreamSample(scriptStreamNumber,curTime,0,0,0,sample); if (lastWriteTime == 0) { lastWriteTime = curTime; } //Write to one second later than last AV write. This seems to give good sync?? writerAdvanced.WriteStreamSample(scriptStreamNumber, lastWriteTime + 10000000, 0, 0, 0, sample); Marshal.ReleaseComObject(sample); } } catch (Exception e) { eventLog.WriteEntry("Failed to write script: " + e.ToString(), EventLogEntryType.Error, 1000); Debug.WriteLine("Failed to write script: " + e.ToString()); return(false); } return(true); }