private VideoDecoder(VideoCodecId videoCodecId, IntPtr decoderHandle) { this.videoCodecId = videoCodecId; this.decoderHandle = decoderHandle; currentFrameParms = new DecodedVideoFrameParameters(0, 0, FFmpegPixelFormat.None); scalersMap = new Dictionary <TransformParameters, DecodedVideoScaler>(); }
public unsafe IDecodedVideoFrame TryDecode(RawVideoFrame frame) { fixed(byte *rawBufferPtr = &frame.Segment.Array[frame.Segment.Offset]) { int resultCode; if (frame 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]) { resultCode = FFmpegVideoPInvoke.SetVideoDecoderExtraData(decoderHandle, (IntPtr)initDataPtr, extraData.Length); if (resultCode != 0) { throw new DecoderException($"An error occurred while setting video extra data, {videoCodecId} codec, code: {resultCode}"); } } } } lock (disposalLock) { if (disposed) { return(null); } resultCode = FFmpegVideoPInvoke.DecodeFrame(decoderHandle, (IntPtr)rawBufferPtr, frame.Segment.Count, out int width, out int height, out FFmpegPixelFormat pixelFormat); if (resultCode != 0) { return(null); } if (!currentFrameParms.Equals(width, height, pixelFormat)) { currentFrameParms = new DecodedVideoFrameParameters(width, height, pixelFormat); DropAllVideoScalers(); } } return(new DecodedVideoFrame(TransformTo, currentFrameParms)); } }
/// <exception cref="DecoderException"></exception> public static DecodedVideoScaler Create(DecodedVideoFrameParameters decodedVideoFrameParms, TransformParameters transformParms) { if (decodedVideoFrameParms == null) { throw new ArgumentNullException(nameof(decodedVideoFrameParms)); } if (transformParms == null) { throw new ArgumentNullException(nameof(transformParms)); } int sourceLeft = 0; int sourceTop = 0; int sourceWidth = decodedVideoFrameParms.Width; int sourceHeight = decodedVideoFrameParms.Height; int scaledWidth = decodedVideoFrameParms.Width; int scaledHeight = decodedVideoFrameParms.Height; if (!transformParms.Region.IsEmpty) { sourceLeft = transformParms.Region.Left; sourceTop = transformParms.Region.Top; sourceWidth = transformParms.Region.Width; sourceHeight = transformParms.Region.Height; } if (!transformParms.TargetSize.IsEmpty) { scaledWidth = transformParms.TargetSize.Width; scaledHeight = transformParms.TargetSize.Height; ScalingPolicy scalingPolicy = transformParms.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; } } } FFmpegPixelFormat pixelFormat = ToFFmpegPixelFormat(transformParms.PixelFormat); FFmpegScalingQuality scaleQuality = ToFFmpegScaleQuality(transformParms.ScaleQuality); int resultCode = FFmpegVideoPInvoke.CreateVideoScaler ( sourceLeft, sourceTop, sourceWidth, sourceHeight, decodedVideoFrameParms.PixelFormat, scaledWidth, scaledHeight, pixelFormat, scaleQuality, out var handle ); if (resultCode != 0) { throw new DecoderException(@"An error occurred while creating scaler, code: {resultCode}"); } return(new DecodedVideoScaler(handle, scaledWidth, scaledHeight, transformParms.PixelFormat)); }
public DecodedVideoFrame(Action <IntPtr, int, TransformParameters> transformAction, DecodedVideoFrameParameters frameParms) { this.transformAction = transformAction ?? throw new ArgumentNullException(nameof(transformAction)); FrameParms = frameParms ?? throw new ArgumentNullException(nameof(frameParms)); }