public unsafe IDecodedVideoFrame GetDecodedFrame(ArraySegment <byte> bufferSegment,
                                                         PostVideoDecodingParameters parameters)
        {
            if (!_scalersMap.TryGetValue(parameters, out FFmpegDecodedVideoScaler videoScaler))
            {
                videoScaler = FFmpegDecodedVideoScaler.Create(_currentFrameParameters, parameters);
                _scalersMap.Add(parameters, videoScaler);
            }

            int resultCode;

            Debug.Assert(bufferSegment.Array != null, "bufferSegment.Array != null");

            fixed(byte *scaledBuffer = &bufferSegment.Array[bufferSegment.Offset])
            resultCode = FFmpegVideoPInvoke.ScaleDecodedVideoFrame(_decoderHandle, videoScaler.Handle,
                                                                   (IntPtr)scaledBuffer, videoScaler.ScaledStride);

            if (resultCode != 0)
            {
                throw new DecoderException(
                          $"An error occurred while converting decoding video frame, {_videoCodecId} codec, code: {resultCode}");
            }

            return(new DecodedVideoFrame(_currentDecodedFrameTimestamp, bufferSegment, _currentFrameParameters.Width,
                                         _currentFrameParameters.Height,
                                         videoScaler.ScaledWidth, videoScaler.ScaledHeight, videoScaler.ScaledPixelFormat,
                                         videoScaler.ScaledStride));
        }
        public unsafe IDecodedVideoFrame GetDecodedFrame(PostVideoDecodingParameters parameters)
        {
            if (!_scalersMap.TryGetValue(parameters, out FFmpegDecodedVideoScaler videoScaler))
            {
                videoScaler = FFmpegDecodedVideoScaler.Create(_currentFrameParameters, parameters);
                _scalersMap.Add(parameters, videoScaler);
            }

            int resultCode;

            int bufferSize = parameters.TargetFrameSize.Height *
                             ImageUtils.GetStride(parameters.TargetFrameSize.Width, parameters.TargetFormat);

            if (_decodedFrameBuffer.Length < bufferSize)
            {
                _decodedFrameBuffer = new byte[bufferSize];

                fixed(byte *scaledBuffer = _decodedFrameBuffer)
                resultCode = FFmpegVideoPInvoke.ScaleDecodedVideoFrame(_decoderHandle, videoScaler.Handle, (IntPtr)scaledBuffer, videoScaler.ScaledStride);

                if (resultCode != 0)
                {
                    throw new DecoderException(
                              $"An error occurred while converting decoding video frame, {_videoCodecId} codec, code: {resultCode}");
                }

                return(new DecodedVideoFrame(_currentDecodedFrameTimestamp, new ArraySegment <byte>(_decodedFrameBuffer, 0, bufferSize), _currentFrameParameters.Width,
                                             _currentFrameParameters.Height,
                                             videoScaler.ScaledWidth, videoScaler.ScaledHeight, videoScaler.ScaledPixelFormat,
                                             videoScaler.ScaledStride));
        }
Пример #3
0
        private void OnFrameReceived(object sender, RawFrame rawFrame)
        {
            if (!(rawFrame is RawVideoFrame rawVideoFrame))
            {
                return;
            }

            FFmpegVideoDecoder decoder = GetDecoderForFrame(rawVideoFrame);

            if (!decoder.TryDecode(rawVideoFrame, out DecodedVideoFrameParameters decodedFrameParameters))
            {
                return;
            }

            //long desiredSize = (long)rawFrame. << 32 | (uint)height;

            //long desiredSize = Interlocked.Read(ref _desiredSize);

            int targetWidth;
            int targetHeight;

            int bufferSize;

            //if (desiredSize == 0)
            //{
            targetWidth  = decodedFrameParameters.Width;
            targetHeight = decodedFrameParameters.Height;

            bufferSize = decodedFrameParameters.Height *
                         ImageUtils.GetStride(decodedFrameParameters.Width, PixelFormat.Bgr24);
            //}
            //else
            //{
            //    targetWidth = (int)(desiredSize >> 32);
            //    targetHeight = (int)desiredSize;

            //    bufferSize = targetHeight *
            //                 ImageUtils.GetStride(targetWidth, PixelFormat.Bgr24);
            //}


            if (_decodedFrameBuffer.Length != bufferSize)
            {
                _decodedFrameBuffer = new byte[bufferSize];
            }

            var bufferSegment = new ArraySegment <byte>(_decodedFrameBuffer);

            var postVideoDecodingParameters = new PostVideoDecodingParameters(RectangleF.Empty,
                                                                              new Size(targetWidth, targetHeight),
                                                                              ScalingPolicy.Stretch, PixelFormat.Bgr24, ScalingQuality.Bicubic);

            IDecodedVideoFrame decodedFrame = decoder.GetDecodedFrame(bufferSegment, postVideoDecodingParameters);

            FrameReceived?.Invoke(this, decodedFrame);
        }
Пример #4
0
        private void OnFrameReceived(object sender, RawFrame rawFrame)
        {
            if (!(rawFrame is RawVideoFrame rawVideoFrame))
            {
                return;
            }

            FFmpegVideoDecoder decoder = GetDecoderForFrame(rawVideoFrame);

            if (!decoder.TryDecode(rawVideoFrame, out DecodedVideoFrameParameters decodedFrameParameters))
            {
                return;
            }

            int targetWidth  = decodedFrameParameters.Width;
            int targetHeight = decodedFrameParameters.Height;

            int bufferSize = decodedFrameParameters.Height *
                             ImageUtils.GetStride(decodedFrameParameters.Width, PixelFormat.Bgr24);

            if (_decodedFrameBuffer.Length != bufferSize)
            {
                _decodedFrameBuffer = new byte[bufferSize];
            }

            var bufferSegment = new ArraySegment <byte>(_decodedFrameBuffer);

            if (_postVideoDecodingParameters.TargetFrameSize.Width != targetWidth ||
                _postVideoDecodingParameters.TargetFrameSize.Height != targetHeight)
            {
                _postVideoDecodingParameters = new PostVideoDecodingParameters(RectangleF.Empty,
                                                                               new Size(targetWidth, targetHeight),
                                                                               ScalingPolicy.Stretch, PixelFormat.Bgr24, ScalingQuality.Nearest);
            }

            IDecodedVideoFrame decodedFrame = decoder.GetDecodedFrame(bufferSegment, _postVideoDecodingParameters);

            FrameReceived?.Invoke(this, decodedFrame);
        }
Пример #5
0
        private void OnFrameReceived(object sender, RawFrame rawFrame)
        {
            if (!(rawFrame is RawVideoFrame rawVideoFrame))
            {
                return;
            }

            FFmpegVideoDecoder decoder = GetDecoderForFrame(rawVideoFrame);

            if (!decoder.TryDecode(rawVideoFrame, out DecodedVideoFrameParameters decodedFrameParameters))
            {
                return;
            }

            long desiredSize = Interlocked.Read(ref _desiredSize);

            int targetWidth;
            int targetHeight;

            if (desiredSize == 0)
            {
                targetWidth  = decodedFrameParameters.Width;
                targetHeight = decodedFrameParameters.Height;
            }
            else
            {
                targetWidth  = (int)(desiredSize >> 32);
                targetHeight = (int)desiredSize;
            }

            var postVideoDecodingParameters = new PostVideoDecodingParameters(RectangleF.Empty,
                                                                              new Size(targetWidth, targetHeight),
                                                                              ScalingPolicy.Stretch, PixelFormat.Bgr24, ScalingQuality.Bicubic);

            IDecodedVideoFrame decodedFrame = decoder.GetDecodedFrame(postVideoDecodingParameters);

            FrameReceived?.Invoke(this, decodedFrame);
        }
Пример #6
0
        /// <exception cref="DecoderException"></exception>
        public static FFmpegDecodedVideoScaler Create(DecodedVideoFrameParameters decodedVideoFrameParameters,
                                                      PostVideoDecodingParameters postVideoDecodingParameters)
        {
            if (decodedVideoFrameParameters == null)
            {
                throw new ArgumentNullException(nameof(decodedVideoFrameParameters));
            }
            if (postVideoDecodingParameters == null)
            {
                throw new ArgumentNullException(nameof(postVideoDecodingParameters));
            }

            int sourceLeft   = 0;
            int sourceTop    = 0;
            int sourceWidth  = decodedVideoFrameParameters.Width;
            int sourceHeight = decodedVideoFrameParameters.Height;
            int scaledWidth  = decodedVideoFrameParameters.Width;
            int scaledHeight = decodedVideoFrameParameters.Height;

            if (!postVideoDecodingParameters.RegionOfInterest.IsEmpty)
            {
                sourceLeft =
                    (int)(decodedVideoFrameParameters.Width * postVideoDecodingParameters.RegionOfInterest.Left);
                sourceTop =
                    (int)(decodedVideoFrameParameters.Height * postVideoDecodingParameters.RegionOfInterest.Top);
                sourceWidth =
                    (int)(decodedVideoFrameParameters.Width * postVideoDecodingParameters.RegionOfInterest.Width);
                sourceHeight =
                    (int)(decodedVideoFrameParameters.Height * postVideoDecodingParameters.RegionOfInterest.Height);
            }

            if (!postVideoDecodingParameters.TargetFrameSize.IsEmpty)
            {
                scaledWidth  = postVideoDecodingParameters.TargetFrameSize.Width;
                scaledHeight = postVideoDecodingParameters.TargetFrameSize.Height;

                ScalingPolicy scalingPolicy = postVideoDecodingParameters.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       = postVideoDecodingParameters.TargetFormat;
            FFmpegPixelFormat    scaledFFmpegPixelFormat = GetFFmpegPixelFormat(scaledPixelFormat);
            FFmpegScalingQuality scaleQuality            = GetFFmpegScaleQuality(postVideoDecodingParameters.ScaleQuality);

            int resultCode = FFmpegVideoPInvoke.CreateVideoScaler(sourceLeft, sourceTop, sourceWidth, sourceHeight,
                                                                  decodedVideoFrameParameters.PixelFormat,
                                                                  scaledWidth, scaledHeight, scaledFFmpegPixelFormat, scaleQuality, out var handle);

            if (resultCode != 0)
            {
                throw new DecoderException(@"An error is occurred while creating scaler, code: {resultCode}");
            }

            return(new FFmpegDecodedVideoScaler(handle, scaledWidth, scaledHeight, scaledPixelFormat));
        }