public static FFmpegVideoDecoder CreateDecoder(FFmpegVideoCodecId videoCodecId) { int resultCode; IntPtr decoderPtr; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { resultCode = FFmpegVideoPInvokeWin.CreateVideoDecoder(videoCodecId, out decoderPtr); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { resultCode = FFmpegVideoPInvokeLinux.CreateVideoDecoder(videoCodecId, out decoderPtr); } else { throw new PlatformNotSupportedException(); } if (resultCode != 0) { throw new DecoderException( $"CreateDecoder say: An error occurred while creating video decoder for {videoCodecId} codec, code: {resultCode}"); } return(new FFmpegVideoDecoder(videoCodecId, decoderPtr)); }
private void TransformTo(IntPtr buffer, int bufferStride, TransformParameters parameters) { if (!_scalersMap.TryGetValue(parameters, out FFmpegDecodedVideoScaler videoScaler)) { videoScaler = FFmpegDecodedVideoScaler.Create(_currentFrameParameters, parameters); _scalersMap.Add(parameters, videoScaler); } int resultCode; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { resultCode = FFmpegVideoPInvokeWin.ScaleDecodedVideoFrame(_decoderHandle, videoScaler.Handle, buffer, bufferStride); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { resultCode = FFmpegVideoPInvokeLinux.ScaleDecodedVideoFrame(_decoderHandle, videoScaler.Handle, buffer, bufferStride); } else { throw new PlatformNotSupportedException(); } if (resultCode != 0) { throw new DecoderException($"An error occurred while converting decoding video frame, {_videoCodecId} codec, code: {resultCode}"); } }
public void Dispose() { if (_disposed) { return; } _disposed = true; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { FFmpegVideoPInvokeWin.RemoveVideoScaler(Handle); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { FFmpegVideoPInvokeLinux.RemoveVideoScaler(Handle); } else { throw new PlatformNotSupportedException(); } GC.SuppressFinalize(this); }
public unsafe IDecodedVideoFrame TryDecode(RawVideoFrame rawVideoFrame) { fixed(byte *rawBufferPtr = &rawVideoFrame.FrameSegment.Array[rawVideoFrame.FrameSegment.Offset]) { int resultCode; if (rawVideoFrame is RawH264IFrame rawH264IFrame) { if (rawH264IFrame.SpsPpsSegment.Array != null && !_extraData.SequenceEqual(rawH264IFrame.SpsPpsSegment)) { if (_extraData.Length != rawH264IFrame.SpsPpsSegment.Count) { _extraData = new byte[rawH264IFrame.SpsPpsSegment.Count]; } Buffer.BlockCopy(rawH264IFrame.SpsPpsSegment.Array, rawH264IFrame.SpsPpsSegment.Offset, _extraData, 0, rawH264IFrame.SpsPpsSegment.Count); fixed(byte *initDataPtr = &_extraData[0]) { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { resultCode = FFmpegVideoPInvokeWin.SetVideoDecoderExtraData(_decoderHandle, (IntPtr)initDataPtr, _extraData.Length); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { resultCode = FFmpegVideoPInvokeLinux.SetVideoDecoderExtraData(_decoderHandle, (IntPtr)initDataPtr, _extraData.Length); } else { throw new PlatformNotSupportedException(); } if (resultCode != 0) { throw new DecoderException( $"TryDecode say: An error occurred while setting video extra data, {_videoCodecId} codec, code: {resultCode}"); } } } } FFmpegPixelFormat pixelFormat; int width, height; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { resultCode = FFmpegVideoPInvokeWin.DecodeFrame(_decoderHandle, (IntPtr)rawBufferPtr, rawVideoFrame.FrameSegment.Count, out width, out height, out pixelFormat); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { resultCode = FFmpegVideoPInvokeLinux.DecodeFrame(_decoderHandle, (IntPtr)rawBufferPtr, rawVideoFrame.FrameSegment.Count, out width, out height, out pixelFormat); } else { throw new PlatformNotSupportedException(); } if (resultCode != 0) { return(null); } if (_currentFrameParameters.Width != width || _currentFrameParameters.Height != height || _currentFrameParameters.PixelFormat != pixelFormat) { _currentFrameParameters = new DecodedVideoFrameParameters(width, height, pixelFormat); DropAllVideoScalers(); } return(new DecodedVideoFrame(TransformTo)); } }
/// <exception cref="DecoderException"></exception> public static FFmpegDecodedVideoScaler Create(DecodedVideoFrameParameters decodedVideoFrameParameters, TransformParameters transformParameters) { if (decodedVideoFrameParameters == null) { throw new ArgumentNullException(nameof(decodedVideoFrameParameters)); } if (transformParameters == null) { throw new ArgumentNullException(nameof(transformParameters)); } int sourceLeft = 0; int sourceTop = 0; int sourceWidth = decodedVideoFrameParameters.Width; int sourceHeight = decodedVideoFrameParameters.Height; int scaledWidth = decodedVideoFrameParameters.Width; int scaledHeight = decodedVideoFrameParameters.Height; if (!transformParameters.RegionOfInterest.IsEmpty) { sourceLeft = (int)(decodedVideoFrameParameters.Width * transformParameters.RegionOfInterest.Left); sourceTop = (int)(decodedVideoFrameParameters.Height * transformParameters.RegionOfInterest.Top); sourceWidth = (int)(decodedVideoFrameParameters.Width * transformParameters.RegionOfInterest.Width); sourceHeight = (int)(decodedVideoFrameParameters.Height * transformParameters.RegionOfInterest.Height); } if (!transformParameters.TargetFrameSize.IsEmpty) { scaledWidth = transformParameters.TargetFrameSize.Width; scaledHeight = transformParameters.TargetFrameSize.Height; ScalingPolicy scalingPolicy = transformParameters.ScalePolicy; float srcAspectRatio = (float)sourceWidth / sourceHeight; float destAspectRatio = (float)scaledWidth / scaledHeight; if (scalingPolicy == ScalingPolicy.Auto) { float relativeChange = Math.Abs(srcAspectRatio - destAspectRatio) / srcAspectRatio; scalingPolicy = relativeChange > MaxAspectRatioError ? ScalingPolicy.RespectAspectRatio : ScalingPolicy.Stretch; } if (scalingPolicy == ScalingPolicy.RespectAspectRatio) { if (destAspectRatio < srcAspectRatio) { scaledHeight = sourceHeight * scaledWidth / sourceWidth; } else { scaledWidth = sourceWidth * scaledHeight / sourceHeight; } } } PixelFormat scaledPixelFormat = transformParameters.TargetFormat; FFmpegPixelFormat scaledFFmpegPixelFormat = GetFFmpegPixelFormat(scaledPixelFormat); FFmpegScalingQuality scaleQuality = GetFFmpegScaleQuality(transformParameters.ScaleQuality); int resultCode; IntPtr handle; if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { resultCode = FFmpegVideoPInvokeWin.CreateVideoScaler(sourceLeft, sourceTop, sourceWidth, sourceHeight, decodedVideoFrameParameters.PixelFormat, scaledWidth, scaledHeight, scaledFFmpegPixelFormat, scaleQuality, out handle); } else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) { resultCode = FFmpegVideoPInvokeLinux.CreateVideoScaler(sourceLeft, sourceTop, sourceWidth, sourceHeight, decodedVideoFrameParameters.PixelFormat, scaledWidth, scaledHeight, scaledFFmpegPixelFormat, scaleQuality, out handle); } else { throw new PlatformNotSupportedException(); } if (resultCode != 0) { throw new DecoderException(@"An error occurred while creating scaler, code: {resultCode}"); } return(new FFmpegDecodedVideoScaler(handle, scaledWidth, scaledHeight, scaledPixelFormat)); }