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);
            }
        }
Esempio n. 3
0
        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));
            }
        }
Esempio n. 4
0
        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);
        }
Esempio n. 5
0
 private VideoCodecId DetectCodecId(RawVideoFrame videoFrame)
 {
     if (videoFrame is RawJpegFrame)
     {
         return(VideoCodecId.MJPEG);
     }
     if (videoFrame is RawH264Frame)
     {
         return(VideoCodecId.H264);
     }
     throw new ArgumentOutOfRangeException(nameof(videoFrame));
 }
Esempio n. 6
0
        /// <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)));
        }
Esempio n. 7
0
        public IDecodedVideoFrame TryDecode(RawVideoFrame rawVideoFrame)
        {
            var decoder = GetDecoderForFrame(rawVideoFrame);

            return(decoder.TryDecode(rawVideoFrame));
        }
Esempio n. 8
0
        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));
            }
        }