我正在尝试使用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;
}
所以如果有人可以帮我解决这个问题。提前谢谢。
答案 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?