private static string GetInputFps(LocalVideoSourceCapability cap, int fps)
        {
            int result = -1;

            if (cap.MinF <= fps && fps <= cap.MaxF)
            {
                result = fps;
            }
            else if (cap.MinF > fps && cap.MinF == Math.Round(cap.MinF, 0))
            {
                result = (int)Math.Round(cap.MinF, 0);
            }
            else if (fps > cap.MaxF && cap.MaxF == Math.Round(cap.MaxF, 0))
            {
                result = (int)Math.Round(cap.MaxF, 0);
            }

            if (result > 0)
            {
                return($"framerate{Eq}{result}{Sep}");
            }
            else
            {
                return("");
            }
        }
 private static string GetVideoOptions(LocalVideoSourceCapability cap, int fps)
 {
     return($"video_size{Eq}{cap.W}x{cap.H}{Sep}" +
            GetInputFps(cap, fps) +
            $"fflags{Eq}nobuffer{Sep}" +
            GetFormatString(cap) +
            $"rtbufsize{Eq}{GetVideoBufferSize(cap.Fmt, cap.W)}");
 }
        private static int GetScore(LocalVideoSourceCapability c, int fps, Resolution resolution)
        {
            int score = 0;

            if (fps < c.MinF)
            {
                score -= ((int)c.MinF - fps);
            }
            else if (fps > c.MaxF)
            {
                score -= (fps - (int)c.MaxF) * 2;
            }

            if ((double)resolution.Height / resolution.Width != (double)c.H / c.W)
            {
                score -= 10;
            }

            double diff = (double)c.W / resolution.Width;

            if (diff < 1.0)                        //cap lower
            {
                score -= (int)((1.0 - diff) * 30); // half of width = -15 score
            }
            else
            {
                score -= (int)((diff - 1.0) * 15); // twice bigger = -15 score
            }
            switch (c.Fmt)
            {
            case LocalVideoSourceCapabilityFormat.Raw:
                break;

            case LocalVideoSourceCapabilityFormat.MJpeg:
                score -= 2;
                break;

            case LocalVideoSourceCapabilityFormat.I420:
            case LocalVideoSourceCapabilityFormat.NV12:
                score -= 3;
                break;

            case LocalVideoSourceCapabilityFormat.Empty:
                score -= 100;
                break;

            default:
                score -= 200;
                break;
            }

            return(score);
        }
        private static string GetFormatString(LocalVideoSourceCapability cap)
        {
            switch (cap.Fmt)
            {
            case LocalVideoSourceCapabilityFormat.Raw:      return($"pixel_format{Eq}yuyv422{Sep}");

            case LocalVideoSourceCapabilityFormat.Empty:    return($"pixel_format{Eq}bgr24{Sep}");

            case LocalVideoSourceCapabilityFormat.MJpeg:    return($"vcodec{Eq}mjpeg{Sep}");

            case LocalVideoSourceCapabilityFormat.I420:     return($"pixel_format{Eq}yuv420p{Sep}");

            case LocalVideoSourceCapabilityFormat.NV12:     return($"pixel_format{Eq}nv12{Sep}");

            default: return("");
            }
        }
Example #5
0
        private (LocalVideoSourceCapability[] caps, InputDeviceState state) GetCapabilities(DsDevice device)
        {
            if (_initialLogging)
            {
                Log.Information($"Caps {device.Name}: getting");
            }
            var    list  = new List <LocalVideoSourceCapability>();
            IntPtr pCaps = IntPtr.Zero;

            IFilterGraph2    filterGraph2 = null;
            IBaseFilter      sourceFilter = null;
            IAMStreamConfig  streamConfig = null;
            object           pin          = null;
            InputDeviceState state        = InputDeviceState.Ready;

            try
            {
                filterGraph2 = new FilterGraph() as IFilterGraph2;
                if (filterGraph2 == null)
                {
                    throw new NotSupportedException("filter2 is null");
                }

                LocalVideoSourceManager.AddCaptureFilter(filterGraph2, device, out sourceFilter);

                pin = DsFindPin.ByCategory(sourceFilter, PinCategory.Capture, 0);

                if (pin == null)
                {
                    pin = sourceFilter;
                }

                streamConfig = pin as IAMStreamConfig;
                if (streamConfig == null)
                {
                    throw new NotSupportedException("pin is null");
                }

                int count = 0;
                int size  = 0;
                Checked(() => streamConfig.GetNumberOfCapabilities(out count, out size), "GetNumberOfCapabilities", null);

                if (count <= 0)
                {
                    throw new NotSupportedException("This video source does not report capabilities.");
                }
                if (size != Marshal.SizeOf(typeof(VideoStreamConfigCaps)))
                {
                    throw new NotSupportedException("Unable to retrieve video source capabilities. This video source requires a larger VideoStreamConfigCaps structure.");
                }

                // Alloc memory for structure
                pCaps = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(VideoStreamConfigCaps)));

                for (int i = 0; i < count; i++)
                {
                    AMMediaType mediaType = null;
                    Checked(() => streamConfig.GetStreamCaps(i, out mediaType, pCaps), "GetStreamCaps", null);

                    VideoStreamConfigCaps caps = (VideoStreamConfigCaps)Marshal.PtrToStructure(pCaps, typeof(VideoStreamConfigCaps));

                    var format = GetMediaTypeInfo(mediaType, out var height, out var width, out var compression, out var videoInfoHeader, out var videoInfoHeader2);

                    var result = new LocalVideoSourceCapability()
                    {
                        MaxF = GetFps(caps.MinFrameInterval),
                        MinF = GetFps(caps.MaxFrameInterval),
                        Fmt  = format,
                        W    = width,
                        H    = height,
                    };

                    list.Add(result);
                }
            }
            catch (UnauthorizedAccessException e)
            {
                Log.Warning(e, $"Error during retreiving caps for '{device.Name}' (Locked)");
                state = InputDeviceState.Locked;
            }
            catch (Exception e)
            {
                Log.Error(e, $"Error during retreiving caps for '{device.Name}'");
                state = InputDeviceState.Failed;
            }
            finally
            {
                if (pCaps != IntPtr.Zero)
                {
                    Marshal.FreeCoTaskMem(pCaps);
                }
            }

            try
            {
                ReleaseComObject(sourceFilter);
                ReleaseComObject(filterGraph2);
                ReleaseComObject(streamConfig);
                ReleaseComObject(pin);
            }
            catch (Exception e)
            {
                Log.Error(e, $"ReleaseComObject('{device.Name}') failed");
            }

            if (_initialLogging)
            {
                Log.Information($"Caps {device.Name}: {string.Join("; ", list.Select(s => s.ToString()))}");
            }

            return(list.ToArray(), state);
        }