尝试调用IWMWriter的EndWriting时出现无法解释的“灾难性故障”错误

时间:2011-09-19 13:28:43

标签: c# .net windows-media-format-sdk

我正在尝试使用Windows Media .Net库来复制一个asf文件的音频/视频文件。我对Windows Media Format SDK比较陌生,所以我不确定我是否做得对。我已经查看了下载中包含的一些示例项目,并查看了C ++版本的文档,但是当我调用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;
    }  

所以如果有人可以帮我解决这个问题。提前谢谢。

1 个答案:

答案 0 :(得分:0)

我为这个问题的解决方案走了一个完全不同的方向。我决定不单独使用WM .Net Framework,而是使用实现WM Asf Reader and Writer的DirectShow.Net框架。这是我的问题和答案的链接。

Is it possible to use an http url as your source location of a Source Filter in DirectShow .Net?