Ejemplo n.º 1
0
 private VideoDecoder(VideoCodecId videoCodecId, IntPtr decoderHandle)
 {
     this.videoCodecId  = videoCodecId;
     this.decoderHandle = decoderHandle;
     currentFrameParms  = new DecodedVideoFrameParameters(0, 0, FFmpegPixelFormat.None);
     scalersMap         = new Dictionary <TransformParameters, DecodedVideoScaler>();
 }
Ejemplo n.º 2
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));
            }
        }
Ejemplo n.º 3
0
        /// <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));
        }
Ejemplo n.º 4
0
 public DecodedVideoFrame(Action <IntPtr, int, TransformParameters> transformAction, DecodedVideoFrameParameters frameParms)
 {
     this.transformAction = transformAction ?? throw new ArgumentNullException(nameof(transformAction));
     FrameParms           = frameParms ?? throw new ArgumentNullException(nameof(frameParms));
 }