Ответ 1
Я понял это. Поэтому я размещаю его здесь для любой другой бедной души, которая проходит мимо, задаваясь вопросом, почему она не работает.
-
Загрузите источник WPFMediaKit, вам нужно будет изменить код.
-
Перейдите в папку DirectShow > MediaPlayers и откройте VideoCapturePlayer.cs
-
Найдите функцию SetVideoCaptureParameters и замените ее следующим образом:
/// <summary> /// Sets the capture parameters for the video capture device /// </summary> private bool SetVideoCaptureParameters(ICaptureGraphBuilder2 capGraph, IBaseFilter captureFilter, Guid mediaSubType) { /* The stream config interface */ object streamConfig; /* Get the stream configuration interface */ int hr = capGraph.FindInterface(PinCategory.Capture, MediaType.Video, captureFilter, typeof(IAMStreamConfig).GUID, out streamConfig); DsError.ThrowExceptionForHR(hr); var videoStreamConfig = streamConfig as IAMStreamConfig; /* If QueryInterface fails... */ if (videoStreamConfig == null) { throw new Exception("Failed to get IAMStreamConfig"); } ///* Make the VIDEOINFOHEADER 'readable' */ var videoInfo = new VideoInfoHeader(); int iCount = 0, iSize = 0; videoStreamConfig.GetNumberOfCapabilities(out iCount, out iSize); IntPtr TaskMemPointer = Marshal.AllocCoTaskMem(iSize); AMMediaType pmtConfig = null; for (int iFormat = 0; iFormat < iCount; iFormat++) { IntPtr ptr = IntPtr.Zero; videoStreamConfig.GetStreamCaps(iFormat, out pmtConfig, TaskMemPointer); videoInfo = (VideoInfoHeader)Marshal.PtrToStructure(pmtConfig.formatPtr, typeof(VideoInfoHeader)); if (videoInfo.BmiHeader.Width == DesiredWidth && videoInfo.BmiHeader.Height == DesiredHeight) { ///* Setup the VIDEOINFOHEADER with the parameters we want */ videoInfo.AvgTimePerFrame = DSHOW_ONE_SECOND_UNIT / FPS; if (mediaSubType != Guid.Empty) { int fourCC = 0; byte[] b = mediaSubType.ToByteArray(); fourCC = b[0]; fourCC |= b[1] << 8; fourCC |= b[2] << 16; fourCC |= b[3] << 24; videoInfo.BmiHeader.Compression = fourCC; // pmtConfig.subType = mediaSubType; } /* Copy the data back to unmanaged memory */ Marshal.StructureToPtr(videoInfo, pmtConfig.formatPtr, true); hr = videoStreamConfig.SetFormat(pmtConfig); break; } } /* Free memory */ Marshal.FreeCoTaskMem(TaskMemPointer); DsUtils.FreeAMMediaType(pmtConfig); if (hr < 0) return false; return true; }
Теперь, когда вы будете сортировать свой экранный экран по желаемому разрешению, при условии, что ваша камера поддерживает его.
Затем вы скоро поймете, что этот новый правильный захват, который вы используете, не применяется при записи видео на диск.
Так как метод ICaptureBuilder2 поддерживает только Avi и Asf (это wmv), вам нужно установить свой медиатип для одного из них.
hr = graphBuilder.SetOutputFileName(MediaSubType.Asf, this.m_fileName, out mux, out sink);
Вы найдете эту строку в функции SetupGraph.
Asf будет выводиться только в 320x240, но Avi будет выводить требуемое разрешение, но несжатое (значение 50-60 МБ в секунду для видеосигнала 1280x720), которое слишком велико.
Итак, у вас есть 2 варианта
-
Выясните, как добавить кодер (фильтр сжатия) к выходному AVI
-
Выясните, как изменить профиль WMV
Я пробовал 1, без успеха. Главным образом из-за того, что это мой первый опыт работы с DirectShow и просто понять смысл графиков.
Но я был успешным С# 2, и вот как я это сделал.
Особая благодарность (http://www.codeproject.com/KB/audio-video/videosav.aspx). Я вынул необходимый код здесь.
- Создайте новый класс в той же папке с именем WMLib.cs и поместите в него следующее
Загрузите демонстрационный проект из http://www.codeproject.com/KB/audio-video/videosav.aspx и скопируйте и вставьте WMLib.cs в свой проект (при необходимости измените пространство имен)
-
Создайте функцию в классе VideoCapturePlayer.cs
/// <summary> /// Configure profile from file to Asf file writer /// </summary> /// <param name="asfWriter"></param> /// <param name="filename"></param> /// <returns></returns> public bool ConfigProfileFromFile(IBaseFilter asfWriter, string filename) { int hr; //string profilePath = "test.prx"; // Set the profile to be used for conversion if ((filename != null) && (File.Exists(filename))) { // Load the profile XML contents string profileData; using (StreamReader reader = new StreamReader(File.OpenRead(filename))) { profileData = reader.ReadToEnd(); } // Create an appropriate IWMProfile from the data // Open the profile manager IWMProfileManager profileManager; IWMProfile wmProfile = null; hr = WMLib.WMCreateProfileManager(out profileManager); if (hr >= 0) { // error message: The profile is invalid (0xC00D0BC6) // E.g. no <prx> tags hr = profileManager.LoadProfileByData(profileData, out wmProfile); } if (profileManager != null) { Marshal.ReleaseComObject(profileManager); profileManager = null; } // Config only if there is a profile retrieved if (hr >= 0) { // Set the profile on the writer IConfigAsfWriter configWriter = (IConfigAsfWriter)asfWriter; hr = configWriter.ConfigureFilterUsingProfile(wmProfile); if (hr >= 0) { return true; } } } return false; }
-
В функции SetupGraph найдите SetOutputFileName и под ним поставьте
ConfigProfileFromFile (mux, "c:\wmv.prx" );
-
Теперь создайте файл с именем wmv.prx на своем диске c: и поместите в него соответствующую информацию.
Здесь вы можете увидеть образец файла PRX из демонстрационного проекта: http://www.codeproject.com/KB/audio-video/videosav.aspx (Pal90.prx)
И теперь наслаждайтесь вашим файлом .wmv, выведенным в нужном размере. Да, я знаю, что код, который я разместил, был довольно лоскутным, но я оставлю его вам, чтобы отполировать его.