internal static string ErrorMessage( int sourceWidth, int sourceHeight, PixelFormat sourcePixelFormat, int destWidth, int destHeight, PixelFormat destPixelFormat, ScaleFlag flags) => string.Format("Impossible to create scale context for the conversion fmt:{0} s:{1}x{2} -> fmt:{3} s:{4}x{5} (sws_flags: {6})", PixelUtils.GetPixelFormatName(sourcePixelFormat), sourceWidth, sourceHeight, PixelUtils.GetPixelFormatName(destPixelFormat), destWidth, destHeight, flags);
/// <summary> /// <see cref="sws_getContext(int, int, AVPixelFormat, int, int, AVPixelFormat, int, SwsFilter*, SwsFilter*, double*)"/> /// </summary> public PixelConverter( int sourceWidth, int sourceHeight, PixelFormat sourcePixelFormat, int destWidth, int destHeight, PixelFormat destPixelFormat, ScaleFlag flags = ScaleFlag.Bilinear) { _nativePointer = NativeUtils.NotNull( ptr: (IntPtr)sws_getContext( sourceWidth, sourceHeight, (AVPixelFormat)sourcePixelFormat, destWidth, destHeight, (AVPixelFormat)destPixelFormat, flags: (int)flags, srcFilter: null, dstFilter: null, param: null), message: ErrorMessage(sourceWidth, sourceHeight, sourcePixelFormat, destWidth, destHeight, destPixelFormat, flags)); _isOwner = true; }
/// <summary> /// <see cref="sws_getCachedContext(SwsContext*, int, int, AVPixelFormat, int, int, AVPixelFormat, int, SwsFilter*, SwsFilter*, double*)"/> /// <see cref="sws_scale(SwsContext*, byte*[], int[], int, int, byte*[], int[])"/> /// </summary> public void ConvertFrame(Frame sourceFrame, Frame destFrame, ScaleFlag flags = ScaleFlag.Bilinear) { _nativePointer = NativeUtils.NotNull( ptr: (IntPtr)sws_getCachedContext(this, sourceFrame.Width, sourceFrame.Height, (AVPixelFormat)sourceFrame.Format, destFrame.Width, destFrame.Height, (AVPixelFormat)destFrame.Format, flags: (int)flags, srcFilter: null, dstFilter: null, param: null), message: PixelConverter.ErrorMessage( sourceFrame.Width, sourceFrame.Height, (PixelFormat)sourceFrame.Format, destFrame.Width, destFrame.Height, (PixelFormat)destFrame.Format, flags)); sws_scale(this, srcSlice: ((Ptr4)sourceFrame.Data).ToBytePtrArray(), srcStride: ((Int32x4)sourceFrame.Linesize).ToArray(), srcSliceY: 0, srcSliceH: sourceFrame.Height, dst: ((Ptr4)destFrame.Data).ToBytePtrArray(), ((Int32x4)destFrame.Linesize).ToArray()).ThrowIfError(); }
/// <summary> /// <see cref="sws_getCachedContext(SwsContext*, int, int, AVPixelFormat, int, int, AVPixelFormat, int, SwsFilter*, SwsFilter*, double*)"/> /// <see cref="sws_scale(SwsContext*, byte*[], int[], int, int, byte*[], int[])"/> /// </summary> public static IEnumerable <Frame> ConvertFrames(this CodecContext c, IEnumerable <Frame> sourceFrames, ScaleFlag flags = ScaleFlag.Bilinear) { using var destFrame = c.CreateFrame(); int pts = 0; if (c.Codec.Type == MediaType.Video) { using var frameConverter = new FrameConverter(); foreach (var sourceFrame in sourceFrames) { frameConverter.ConvertFrame(sourceFrame, destFrame, flags); destFrame.Pts = pts++; yield return(destFrame); } } else if (c.Codec.Type == MediaType.Audio) { using var frameConverter = new SampleConverter(); foreach (var sourceFrame in sourceFrames) { frameConverter.ConvertFrame(destFrame, sourceFrame); destFrame.Pts = pts += c.FrameSize; yield return(destFrame); } } }