Я работал над приложением, использующим Directshow.NET, и решил начать возиться с GraphEd.exe. чтобы определить точный маршрут, по которому мне нужно идти.
Самая простая версия того, что я хочу, представлена на изображении выше (где «test.mpeg» — это фильтр «Запись файлов»).
Конечно же, то, что выглядит просто в GraphEd, не так просто, как кодирование. Через несколько секунд я понял, что директ-шоу — это то, чего я просто не понимаю. Вот моя попытка кода С#:
int hr;
IBaseFilter cameraStream = null;
IBaseFilter mpegEncoder = null;
IBaseFilter fileWriter = null;
ICaptureGraphBuilder2 capGraph = null;
filterGraph = (IFilterGraph2)new FilterGraph();
try
{
capGraph = (ICaptureGraphBuilder2)new CaptureGraphBuilder2();
hr = capGraph.SetFiltergraph(filterGraph);
Marshal.ThrowExceptionForHR(hr);
hr = filterGraph.AddSourceFilterForMoniker(dev.Mon, null, dev.Name, out cameraStream);
Marshal.ThrowExceptionForHR(hr);
IPin cameraData = null;
hr = capGraph.FindPin(cameraStream, PinDirection.Output, PinCategory.Capture, MediaType.Video, true, 0, out cameraData );
//hr = cameraStream.FindPin("Capture", out cameraData);
Marshal.ThrowExceptionForHR(hr);
mpegEncoder = (IBaseFilter)new MJPGEnc();
hr = filterGraph.AddFilter(mpegEncoder, "mpeg encoder");
//hr = filterGraph.FindFilterByName("Microsoft MPEG-2 Video Encoder", out mpegEncoder);
Marshal.ThrowExceptionForHR(hr);
IPin mpegInput = null;
//hr = mpegEncoder.FindPin("Input0", out mpegInput);
hr = capGraph.FindPin(mpegEncoder, PinDirection.Input, null, null, true, 0, out mpegInput);
Marshal.ThrowExceptionForHR(hr);
filterGraph.Connect(cameraData, mpegInput);
IPin mpegOutput = null;
//hr = mpegEncoder.FindPin("Output", out mpegOutput);
hr = capGraph.FindPin(mpegEncoder, PinDirection.Output, null, null, true, 0, out mpegOutput);
Marshal.ThrowExceptionForHR(hr);
//hr = filterGraph.FindFilterByName("File writer", out fileWriter);
fileWriter = (IBaseFilter)new FileWriter();
IFileSinkFilter test = fileWriter as IFileSinkFilter2;
AMMediaType mtype = new AMMediaType();
mtype.majorType = MediaType.Video;
mtype.subType = MediaSubType.RGB24;
mtype.formatPtr = IntPtr.Zero;
test.SetFileName(videoPath, mtype );
IPin fwriterIn = null;
//hr = fileWriter.FindPin("in", out fwriterIn);
hr = capGraph.FindPin(fileWriter, PinDirection.Input, null, null, true, 0, out fwriterIn);
Marshal.ThrowExceptionForHR(hr);
filterGraph.Connect(mpegOutput, fwriterIn);
hr = capGraph.RenderStream(null, null, cameraStream, null, fileWriter); // *** Breaks on this line! ***
Marshal.ThrowExceptionForHR(hr);
mediaControl = filterGraph as IMediaControl;
}
finally
{
if (cameraStream != null)
{
Marshal.ReleaseComObject(cameraStream);
cameraStream = null;
}
if (mpegEncoder != null)
{
Marshal.ReleaseComObject(mpegEncoder);
mpegEncoder = null;
}
if (fileWriter != null)
{
Marshal.ReleaseComObject(fileWriter);
fileWriter = null;
}
if (capGraph != null)
{
Marshal.ReleaseComObject(capGraph);
capGraph = null;
}
}
Написав и посмотрев на то, насколько нелепым был мой код (с точки зрения логики программирования), я понял, что мне нужна помощь.
Может ли кто-нибудь направить меня к какому-то структурированному учебному пособию по директ-шоу, которое объясняет мне вещи, как если бы я был большим новичком, или, возможно, связать меня с какой-то библиотекой C #, которая обрабатывает веб-камеру для записи в файл? Обычно я не программист win32, поэтому все, что облегчает боль, должно быть хорошим :)
Кроме того, у меня есть код перечисления устройств камеры, который, кажется, работает:
private void rescan_camera()
{
comboBox1.Items.Clear();
DsDevice[] cameraDevices = DsDevice.GetDevicesOfCat(FilterCategory.VideoInputDevice);
for(int i=0; i < cameraDevices.Length; i++) {
comboBox1.Items.Add(cameraDevices[i].Name);
}
if (comboBox1.Items.Count > 0) comboBox1.SelectedIndex = 0;
}
Я могу получить данные псевдонима из DsDevice, которые, как я знаю, являются ключевой частью для указания графу фильтра directshow, откуда я хочу записывать, но это примерно то, что я знаю.
Изменить: обновленный код, показывает точное место разрыва строки.
1
В вашей последней строке естьIFileSinkFilter test
, аtest.SetFileName
настроит средство записи, см. заголовок stackoverflow.com/questions/6416957/ - person Roman R.   schedule 18.10.20122
В библиотеке DirectShow.NET есть помощники, например. обратите внимание на использованиеByConnectionStatus
здесьpin =DsFindPin.ByConnectionStatus(Source,DirectShowLib.PinConnectedStatus.Unconnected, 0);
tech-archive.net/Archive/Development/ - person Roman R.   schedule 18.10.2012HRESULT
или исключением? Не совсем понятно. По сути, если у вас это работает в GraphEdit, вы можете сделать это и в коде. - person Roman R.   schedule 18.10.2012hr = capGraph.RenderStream(null, null, cameraStream, cameraEncoder, fileWriter);
. - person OzBarry   schedule 18.10.2012RenderStream
. Вся цель этого состоит в том, чтобы быть помощником, ловко соединяющим фитлеры и штифты. Однако вы уже сделали всю эту работу. Закомментируйте его иIMediaControl.Run
график. - person Roman R.   schedule 18.10.2012Run
. Вам также понадобитсяWaitForCompletion
, чтобы дождаться завершения обработки (илиThread.Sleep(10000)
, чтобы записать 10 секунд, если вы захватываете из живого источника, как это кажется в случае). - person Roman R.   schedule 18.10.2012MyCapture recording(device, "c:\Users\<username>\Roaming\Recording\<unix timestamp>\camera.mjpeg"); recording.StartRecording(); /* .. waits for user to click stop recording button .. */ recording.StopRecording();
- person OzBarry   schedule 18.10.2012