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]) { 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) { Console.WriteLine("Skipped decoding video frame, as decoder was disposed. (Therefore the frame probably wasn't wanted)"); return(null); } resultCode = FFmpegVideoPInvoke.DecodeFrame(_decoderHandle, (IntPtr)rawBufferPtr, rawVideoFrame.FrameSegment.Count, out int width, out int height, out FFmpegPixelFormat pixelFormat); 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)); } }
public unsafe bool TryDecode(RawVideoFrame rawVideoFrame, out DecodedVideoFrameParameters frameParameters) { Debug.Assert(rawVideoFrame.FrameSegment.Array != null, "rawVideoFrame.FrameSegment.Array != null"); 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]) { 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}"); } } } } resultCode = FFmpegVideoPInvoke.DecodeFrame(_decoderHandle, (IntPtr)rawBufferPtr, rawVideoFrame.FrameSegment.Count, out int width, out int height, out FFmpegPixelFormat pixelFormat); if (resultCode != 0) { frameParameters = null; return(false); } _currentDecodedFrameTimestamp = rawVideoFrame.Timestamp; if (_currentFrameParameters.Width != width || _currentFrameParameters.Height != height || _currentFrameParameters.PixelFormat != pixelFormat) { _currentFrameParameters = new DecodedVideoFrameParameters(width, height, pixelFormat); DropAllVideoScalers(); } frameParameters = _currentFrameParameters; return(true); } }
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)); } }
private FFmpegVideoDecoder GetDecoderForFrame(RawVideoFrame videoFrame) { FFmpegVideoCodecId codecId = DetectCodecId(videoFrame); if (!_videoDecodersMap.TryGetValue(codecId, out FFmpegVideoDecoder decoder)) { decoder = FFmpegVideoDecoder.CreateDecoder(codecId); _videoDecodersMap.Add(codecId, decoder); } return(decoder); }
private VideoCodecId DetectCodecId(RawVideoFrame videoFrame) { if (videoFrame is RawJpegFrame) { return(VideoCodecId.MJPEG); } if (videoFrame is RawH264Frame) { return(VideoCodecId.H264); } throw new ArgumentOutOfRangeException(nameof(videoFrame)); }
/// <summary> /// Creates a new network frame. /// </summary> /// <param name="systemName">System name.</param> /// <param name="streamName">Stream name.</param> /// <param name="totalFramesReceived">Total number of frames received by the media stream so far.</param> /// <param name="mediaFrame">Media frame.</param> /// <param name="metadataRequired">Indicates whether to include metadata.</param> /// <returns>A new network frame.</returns> private static NetworkFrame CreateNetworkFrame(string systemName, string streamName, int totalFramesReceived, RawFrame mediaFrame, bool metadataRequired) { byte interpretation = mediaFrame switch { RawAudioFrame _ => 1, RawVideoFrame _ => 2, _ => 0 }; return(new NetworkFrame( (ulong)Chrono.GetUniqueTimestamp64(), (uint)totalFramesReceived, interpretation, systemName, streamName, CreateDataSegments(mediaFrame, metadataRequired))); }
public IDecodedVideoFrame TryDecode(RawVideoFrame rawVideoFrame) { var decoder = GetDecoderForFrame(rawVideoFrame); return(decoder.TryDecode(rawVideoFrame)); }
public IDecodedVideoFrame Decode(RawVideoFrame frame) { VideoDecoder decoder = GetDecoderForFrame(frame); return(decoder?.TryDecode(frame)); }
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)); } }