123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351 |
- using System.Diagnostics;
- using System.Reflection;
- using System.Runtime.InteropServices;
- using Bmp.Core.FFMpeg.CsCorePorts.FFMpegWrap.Interops;
- namespace Bmp.Core.FFMpeg.CsCorePorts.FFMpegWrap;
- internal class FfmpegCalls
- {
- [Flags]
- public enum SeekFlags
- {
- SeekSet = 0,
- SeekCur = 1,
- SeekEnd = 2,
- SeekSize = 0x10000,
- SeekForce = 0x20000
- }
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate int AvioReadData(nint opaque, nint buffer, int bufferSize);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate int AvioWriteData(nint opaque, nint buffer, int bufferSize);
- [UnmanagedFunctionPointer(CallingConvention.Cdecl)]
- public delegate long AvioSeek(nint opaque, long offset, SeekFlags whence);
- static FfmpegCalls()
- {
- string platform;
- switch (Environment.OSVersion.Platform)
- {
- case PlatformID.Win32NT:
- case PlatformID.Win32S:
- case PlatformID.Win32Windows:
- platform = "windows";
- break;
- case PlatformID.Unix:
- case PlatformID.MacOSX:
- platform = "unix";
- break;
- default:
- throw new PlatformNotSupportedException();
- }
- var assemblyDirectory = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location);
- if (assemblyDirectory != null)
- {
- var path = Path.Combine(
- assemblyDirectory,
- //"FFmpeg"
- Path.Combine("FFmpeg", Path.Combine("bin", Path.Combine(platform, nint.Size == 8 ? "x64" : "x86")))
- );
- InteropHelper.RegisterLibrariesSearchPath(path);
- }
- //FfmpegConfigurationSection ffmpegSettings =
- // (FfmpegConfigurationSection)ConfigurationManager.GetSection("ffmpeg");
- //if (ffmpegSettings != null)
- //{
- // if (!String.IsNullOrEmpty(ffmpegSettings.HttpProxy))
- // {
- // Environment.SetEnvironmentVariable("http_proxy", ffmpegSettings.HttpProxy);
- // Environment.SetEnvironmentVariable("no_proxy", ffmpegSettings.ProxyWhitelist);
- // }
- // if (ffmpegSettings.LogLevel != null)
- // {
- // FfmpegUtils.LogLevel = ffmpegSettings.LogLevel.Value;
- // }
- //}
- FFMPEG.av_register_all();
- FFMPEG.avcodec_register_all();
- FFMPEG.avformat_network_init();
- }
- internal static unsafe AVOutputFormat[] GetOutputFormats()
- {
- var formats = new List<AVOutputFormat>();
- var format = FFMPEG.av_oformat_next(null);
- while (format != null)
- {
- formats.Add(*format);
- format = FFMPEG.av_oformat_next(format);
- }
- return formats.ToArray();
- }
- internal static unsafe AVInputFormat[] GetInputFormats()
- {
- var formats = new List<AVInputFormat>();
- var format = FFMPEG.av_iformat_next(null);
- while (format != null)
- {
- formats.Add(*format);
- format = FFMPEG.av_iformat_next(format);
- }
- return formats.ToArray();
- }
- internal static unsafe List<AvCodecId> GetCodecOfCodecTag(AVCodecTag** codecTag)
- {
- var codecs = new List<AvCodecId>();
- uint i = 0;
- AvCodecId codecId;
- while ((codecId = FFMPEG.av_codec_get_id(codecTag, i++)) != AvCodecId.None)
- {
- codecs.Add(codecId);
- }
- return codecs;
- }
- internal static unsafe nint AvMalloc(int bufferSize)
- {
- var buffer = FFMPEG.av_malloc((ulong)bufferSize);
- var ptr = new nint(buffer);
- if (ptr == nint.Zero)
- throw new OutOfMemoryException("Could not allocate memory.");
- return ptr;
- }
- internal static unsafe void AvFree(nint buffer)
- {
- FFMPEG.av_free((void*)buffer);
- }
- internal static unsafe AVIOContext* AvioAllocContext(AvioBuffer buffer, bool writeable, nint userData,
- AvioReadData readData, AvioWriteData writeData, AvioSeek seek)
- {
- var bufferPtr = (byte*)buffer.Buffer;
- var avioContext = FFMPEG.avio_alloc_context(
- bufferPtr,
- buffer.BufferSize,
- writeable ? 1 : 0,
- (void*)userData,
- readData, writeData, seek);
- if (avioContext == null)
- {
- throw new FfmpegException("Could not allocate avio-context.", "avio_alloc_context");
- }
- return avioContext;
- }
- internal static unsafe AVFormatContext* AvformatAllocContext()
- {
- var formatContext = FFMPEG.avformat_alloc_context();
- if (formatContext == null)
- {
- throw new FfmpegException("Could not allocate avformat-context.", "avformat_alloc_context");
- }
- return formatContext;
- }
- internal static unsafe void AvformatOpenInput(AVFormatContext** formatContext, AvioContext avioContext)
- {
- (*formatContext)->pb = (AVIOContext*)avioContext.ContextPtr;
- var result = FFMPEG.avformat_open_input(formatContext, "DUMMY-FILENAME", null, null);
- FfmpegException.Try(result, "avformat_open_input");
- }
- internal static unsafe void AvformatOpenInput(AVFormatContext** formatContext, string url)
- {
- var result = FFMPEG.avformat_open_input(formatContext, url, null, null);
- FfmpegException.Try(result, "avformat_open_input");
- }
- internal static unsafe void AvformatCloseInput(AVFormatContext** formatContext)
- {
- FFMPEG.avformat_close_input(formatContext);
- }
- internal static unsafe void AvFormatFindStreamInfo(AVFormatContext* formatContext)
- {
- var result = FFMPEG.avformat_find_stream_info(formatContext, null);
- FfmpegException.Try(result, "avformat_find_stream_info");
- }
- internal static unsafe int AvFindBestStreamInfo(AVFormatContext* formatContext)
- {
- var result = FFMPEG.av_find_best_stream(
- formatContext,
- AVMediaType.AVMEDIA_TYPE_AUDIO,
- -1, -1, null, 0);
- FfmpegException.Try(result, "av_find_best_stream");
- return result; //stream index
- }
- internal static unsafe AVCodec* AvCodecFindDecoder(AvCodecId codecId)
- {
- var decoder = FFMPEG.avcodec_find_decoder(codecId);
- if (decoder == null)
- {
- throw new FfmpegException(
- string.Format("Failed to find a decoder for CodecId {0}.", codecId),
- "avcodec_find_decoder");
- }
- return decoder;
- }
- internal static unsafe void AvCodecOpen(AVCodecContext* codecContext, AVCodec* codec)
- {
- var result = FFMPEG.avcodec_open2(codecContext, codec, null);
- FfmpegException.Try(result, "avcodec_open2");
- }
- internal static unsafe void AvCodecClose(AVCodecContext* codecContext)
- {
- FFMPEG.avcodec_close(codecContext);
- }
- internal static unsafe AVFrame* AvFrameAlloc()
- {
- var frame = FFMPEG.av_frame_alloc();
- if (frame == null)
- {
- throw new FfmpegException("Could not allocate frame.", "av_frame_alloc");
- }
- return frame;
- }
- internal static unsafe void AvFrameFree(AVFrame* frame)
- {
- FFMPEG.av_frame_free(&frame);
- }
- internal static unsafe void InitPacket(AVPacket* packet)
- {
- FFMPEG.av_init_packet(packet);
- }
- internal static unsafe void FreePacket(AVPacket* packet)
- {
- FFMPEG.av_packet_unref(packet);
- }
- internal static unsafe bool AvReadFrame(AvFormatContext formatContext, AVPacket* packet)
- {
- var result = FFMPEG.av_read_frame((AVFormatContext*)formatContext.FormatPtr, packet);
- return result >= 0;
- }
- internal static unsafe bool AvCodecDecodeAudio4(AVCodecContext* codecContext, AVFrame* frame, AVPacket* packet, out int bytesConsumed)
- {
- int gotFrame;
- var result = FFMPEG.avcodec_decode_audio4(codecContext, frame, &gotFrame, packet);
- FfmpegException.Try(result, "avcodec_decode_audio4");
- bytesConsumed = result;
- return gotFrame != 0;
- }
- internal static int AvGetBytesPerSample(AVSampleFormat sampleFormat)
- {
- var dataSize = FFMPEG.av_get_bytes_per_sample(sampleFormat);
- if (dataSize <= 0)
- {
- throw new FfmpegException("Could not calculate data size.");
- }
- return dataSize;
- }
- internal static unsafe int AvSamplesGetBufferSize(AVFrame* frame)
- {
- var result = FFMPEG.av_samples_get_buffer_size(null, frame->channels, frame->nb_samples,
- (AVSampleFormat)frame->format, 1);
- FfmpegException.Try(result, "av_samples_get_buffer_size");
- return result;
- }
- internal static unsafe void AvFormatSeekFile(AvFormatContext formatContext, double time)
- {
- var result = FFMPEG.avformat_seek_file((AVFormatContext*)formatContext.FormatPtr,
- formatContext.BestAudioStreamIndex, long.MinValue, (long)time, (long)time, 0);
- FfmpegException.Try(result, "avformat_seek_file");
- }
- internal static unsafe string AvStrError(int errorCode)
- {
- var buffer = stackalloc byte[500];
- var result = FFMPEG.av_strerror(errorCode, new nint(buffer), 500);
- if (result < 0)
- return "No description available.";
- var errorMessage = Marshal.PtrToStringAnsi(new nint(buffer), 500).Trim('\0').Trim();
- #if DEBUG
- Debug.WriteLineIf(Debugger.IsAttached, errorMessage);
- #endif
- return errorMessage;
- }
- internal static void SetLogLevel(LogLevel level)
- {
- FFMPEG.av_log_set_level((int)level);
- }
- internal static LogLevel GetLogLevel()
- {
- return (LogLevel)FFMPEG.av_log_get_level();
- }
- internal unsafe delegate void LogCallback(void* ptr, int level, byte* fmt, nint vl);
- internal static unsafe void SetLogCallback(LogCallback callback)
- {
- FFMPEG.av_log_set_callback(Marshal.GetFunctionPointerForDelegate(callback));
- }
- internal static unsafe LogCallback GetDefaultLogCallback()
- {
- return (ptr, level, fmt, vl) =>
- {
- FFMPEG.av_log_default_callback(ptr, level, Marshal.PtrToStringAnsi(new nint(fmt)), (sbyte*)vl);
- };
- }
- internal static unsafe string FormatLine(void* avcl, int level, string fmt, nint vl,
- ref int printPrefix)
- {
- var line = string.Empty;
- const int bufferSize = 0x400;
- var buffer = stackalloc byte[bufferSize];
- fixed (int* ppp = &printPrefix)
- {
- var result = FFMPEG.av_log_format_line2(avcl, level, fmt, (sbyte*)vl, (nint)buffer, bufferSize, ppp);
- if (result < 0)
- {
- Debug.WriteLine("av_log_format_line2 failed with " + result.ToString("x8"));
- return line;
- }
- line = Marshal.PtrToStringAnsi((nint)buffer);
- if (line != null && result > 0)
- line = line.Substring(0, result);
- return line;
- }
- }
- }
|