我正在嘗試使用Windows Media .Net庫複製asf文件的音頻/視頻文件。我對Windows Media Format SDK比較陌生,所以我不確定我是否做得對。我瀏覽了下載中包含的一些示例項目,並查看了C++版本的文檔,但似乎無法弄清楚爲什麼當我調用EndWriting時它會崩潰。所以如果有人能夠幫助指出我在這裏做錯了什麼,我會非常感激。嘗試調用IWMWriter的EndWriting時出現無法解釋的「災難性故障」錯誤
我有一個WinForm,它將有一個按鈕開始錄製,另一個按鈕結束錄製。我的類實現了IWMReaderCallback,並使用一個名爲SampleProp的私有類來保存這些指針的值,並且這些值將在OnSample方法中返回。所以在OnSample方法中,我用正在返回的樣本的副本填充SampleProp實例的byte []成員。然後,我將SampleProp的實例添加到將用於另一個名爲ProcessReaderSample的方法中的集合。在這個其他方法中,我創建了IWMReader和IWMWriter對象,並有一個while循環,它將調用BeginWriting,AllocateSample,WriteSample和EndWriting。這就是它崩潰的地方。這裏是我的代碼,我使用...
public class MyClass : IWMReaderCallback
{
static readonly string _streamingFileName = "C:\\tmpStream.asf";
static readonly string _streamingURL = @"http://localhost:8080";
static readonly string _recordingFileName = "C:\\tmpRecording.asf";
IWMReader _reader = null;
IWMReaderAdvanced _readerAdvanced = null;
IWMHeaderInfo _readerHeaderInfo = null;
IWMProfile _readerProfile = null;
IWMWriter _writer = null;
IWMWriterAdvanced _writerAdvanced = null;
IWMHeaderInfo _writerHeaderInfo = null;
int _streamCount = 0;
Guid[] _guidStreamType = null;
short[] _streamNumber = null;
void GetReader()
{
WMUtils.WMCreateReader(IntPtr.Zero, Rights.Playback, out _reader);
_readerAdvanced = _reader as IWMReaderAdvanced;
_readerHeaderInfo = _reader as IWMHeaderInfo;
_reader.Open(_streamingFileName, this, IntPtr.Zero);
_readerAdvanced.SetUserProvidedClock(true);
_readerAdvanced.SetManualStreamSelection(true);
}
void GetWritter()
{
WMUtils.WMCreateWriter(IntPtr.Zero, out _writer);
_writerAdvanced = _writer as IWMWriterAdvanced;
_writerHeaderInfo = _writer as IWMHeaderInfo;
_writer.SetProfile(_readerProfile);
_writer.SetOutputFilename(_recordingFileName);
int inputCount = 0;
_writer.GetInputCount(out inputCount);
for (int i = 0; i < inputCount; i++)
{
_writer.SetInputProps(i, null);
}
}
class SampleProp
{
public int OutputNum { get; private set; }
public long SampleTime { get; private set; }
public SampleFlag Flag { get; private set; }
public byte[] Sample;
public int Size { get; private set; }
public SampleProp(int size, int outputNum, long sampleTime, SampleFlag flag)
{
Size = size;
OutputNum = outputNum;
SampleTime = sampleTime;
Flag = flag;
Sample = new byte[size];
}
}
List<SampleProp> _writableSamples = null;
public void OnSample(int dwOutputNum, long cnsSampleTime, long cnsSampleDuration, SampleFlag dwFlags, INSSBuffer pSample, IntPtr pvContext)
{
int size = 0;
pSample.GetLength(out size);
var prop = new SampleProp(size, dwOutputNum, cnsSampleTime, dwFlags);
IntPtr ptr = IntPtr.Zero;
pSample.GetBuffer(out ptr);
Marshal.Copy(ptr, prop.Sample, 0, size);
_writableSamples.Add(prop);
}
void ProcessReaderSample()
{
_event.Reset();
GetReader();
GetProfileInfo();
GetWritter();
_reader.Start(0, 0, 1.0f, IntPtr.Zero);
_isRecording = true;
var hasStarted = false;
while (_isRecording || _writableSamples.Count > 0)
{
if (_writableSamples.Count > 0)
{
_writer.BeginWriting();
INSSBuffer buffer;
_writer.AllocateSample(_writableSamples[0].Size, out buffer);
IntPtr ptr = IntPtr.Zero;
buffer.GetBuffer(out ptr);
Marshal.Copy(_writableSamples[0].Sample, 0, ptr, _writableSamples[0].Size);
buffer.SetLength(_writableSamples[0].Size);
_writer.WriteSample(_writableSamples[0].OutputNum, _writableSamples[0].SampleTime, _writableSamples[0].Flag, buffer);
Marshal.ReleaseComObject(buffer);
_writableSamples.RemoveAt(0);
_writer.EndWriting();
}
}
}
bool _isRecording = false;
public void StartRecording()
{
if (_isRecording) return;
_writableSamples = new List<SampleProp>();
Thread writingThread = new Thread(new ThreadStart(ProcessReaderSample));
writingThread.Start();
}
public void StopRecording()
{
if (!_isRecording) return;
_isRecording = false;
}
所以,如果有人可以請幫我這。先謝謝你。
我不知道你的具體問題是什麼,但我可以給你兩個指針。首先是「Cestrophic Failure」幾乎總是COM調用COM對象返回的COM HRESULT「E_UNEXPECTED」的結果。第二個是許多COM對象是單元線程的,並且當從一個意外的線程調用時將返回E_UNEXPECTED。 (但是,這只是返回E_UNEXPECTED的一個原因 - 基本上,這是當調用者做了一些被調用者沒有想到的事情時返回的錯誤。) –
首先刪除Marshal.ReleaseComObject(),這是要求麻煩的。 –
@Eric - 你認爲這可能是因爲我正在創建一個新的主題?我試圖在OnSample事件中調用寫入器,但它在Com_Object上拋出了一些轉換異常。 – jhorton