public MediaFilterGraph() { unsafe { pFilterGraph = ffmpeg.avfilter_graph_alloc(); } }
public FilterGraph() { this.pointer = ffmpeg.avfilter_graph_alloc(); if (this.pointer == null) { throw new Exception("AVFilterGraph was not allocated"); } }
public void Dispose() { ffmpeg.avfilter_free(_pBufferSinkCtx); ffmpeg.avfilter_free(_pBufferSrcCtx); var filterGraph = _pFilterGraph; ffmpeg.avfilter_graph_free(&filterGraph); _pFilterGraph = null; }
/// <summary> /// Destroys the filtergraph releasing unmanaged resources. /// </summary> private void DestroyFiltergraph() { if (FilterGraph != null) { fixed(AVFilterGraph **filterGraph = &FilterGraph) ffmpeg.avfilter_graph_free(filterGraph); FilterGraph = null; SinkInput = null; SourceOutput = null; } }
/// <summary> /// Destroys the filter graph releasing unmanaged resources. /// </summary> private void DestroyFilterGraph() { if (FilterGraph == null) { return; } RC.Current.Remove(FilterGraph); var filterGraphRef = FilterGraph; ffmpeg.avfilter_graph_free(&filterGraphRef); FilterGraph = null; SinkInput = null; SourceOutput = null; }
public void Build() { _rawFilterGraph = ffmpeg.avfilter_graph_alloc(); if (_rawFilterGraph == null) { throw new FFmpegException("Unable to create filter graph."); } var aBuffer = ffmpeg.avfilter_get_by_name("abuffer"); if (aBuffer == null) { throw new FFmpegException("Could not find the abuffer filter."); } _src = ffmpeg.avfilter_graph_alloc_filter(_rawFilterGraph, aBuffer, "src"); if (_src == null) { throw new FFmpegException("Could not allocate the abuffer instance."); } ffmpeg.av_opt_set(_src, "channel_layout", _sourceStream.ChannelLayout !, ffmpeg.AV_OPT_SEARCH_CHILDREN); ffmpeg.av_opt_set( _src, "sample_fmt", ffmpeg.av_get_sample_fmt_name(_sourceStream.SampleFormat), ffmpeg.AV_OPT_SEARCH_CHILDREN); ffmpeg.av_opt_set_q(_src, "time_base", _sourceStream.TimeBase, ffmpeg.AV_OPT_SEARCH_CHILDREN); ffmpeg.av_opt_set_int(_src, "sample_rate", _sourceStream.SampleRate, ffmpeg.AV_OPT_SEARCH_CHILDREN); ffmpeg.avfilter_init_str(_src, null).ThrowExceptionIfError(); var aBufferSink = ffmpeg.avfilter_get_by_name("abuffersink"); if (aBufferSink == null) { throw new FFmpegException("Could not find the abuffersink filter."); } _dst = ffmpeg.avfilter_graph_alloc_filter(_rawFilterGraph, aBufferSink, "dst"); ffmpeg.avfilter_init_str(_dst, null).ThrowExceptionIfError(); LinkFilterGraph(_rawFilterGraph, _src, _dst); ffmpeg.avfilter_graph_config(_rawFilterGraph, null).ThrowExceptionIfError(); }
public VideoFlipperConverter(int width, int height, AVPixelFormat inputPixelFormat, StreamerSettings settings) { string filters = $"buffer=width={width}:height={height}:pix_fmt={(int)inputPixelFormat}:time_base=1/1:pixel_aspect=1/1 [in]; [out] buffersink;[in] format=pix_fmts=0 [in1];"; int inputCount = 1; if (settings.FlipY) { filters += $"[in{inputCount}] vflip [in{++inputCount}];"; } if (settings.FlipX) { filters += $"[in{inputCount}] hflip [in{++inputCount}];"; } filters += $"[in{inputCount}] copy [out]"; AVFilterInOut *gis = null; AVFilterInOut *gos = null; _filterGraph = ffmpeg.avfilter_graph_alloc(); ffmpeg.avfilter_graph_parse2(_filterGraph, filters, &gis, &gos).ThrowExceptionIfError(); ffmpeg.avfilter_graph_config(_filterGraph, null).ThrowExceptionIfError(); _filterSourceContext = ffmpeg.avfilter_graph_get_filter(_filterGraph, "Parsed_buffer_0"); _filterSinkContext = ffmpeg.avfilter_graph_get_filter(_filterGraph, "Parsed_buffersink_1"); if (_filterSourceContext == null || _filterSinkContext == null) { throw new Exception("Failed to create filter sinks"); } _flippedFrame = ffmpeg.av_frame_alloc(); var flippedFrameBuffer = (byte *)ffmpeg.av_malloc((ulong)ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_YUV420P, width, height, 1)); var dataArr = new byte_ptrArray4(); dataArr.UpdateFrom(_flippedFrame->data); var linesizeArr = new int_array4(); linesizeArr.UpdateFrom(_flippedFrame->linesize); ffmpeg.av_image_fill_arrays(ref dataArr, ref linesizeArr, flippedFrameBuffer, AVPixelFormat.AV_PIX_FMT_YUV420P, width, height, 1); _flippedFrame->data.UpdateFrom(dataArr); _flippedFrame->linesize.UpdateFrom(linesizeArr); }
public FFmpegFilter(AVStream *stream, System.Drawing.Size vsize) { var p = stream->codecpar; var frate = stream->r_frame_rate; filterLen = 0; filterGraph = ffmpeg.avfilter_graph_alloc(); buffersrcCtx = AddFilter("buffer", "in", string.Format("video_size={0}x{1}:pix_fmt={2}:time_base={3}/{4}", p->width, p->height, p->format, frate.num, frate.den)); buffersinkCtx = AddFilter("buffersink", "out", string.Empty); avFrame = ffmpeg.av_frame_alloc(); avFrame->width = vsize.Width; avFrame->height = vsize.Height; AVFilterContext *srcScale = AddFilter("scale", string.Empty, string.Format("w={0}:h={1}", avFrame->width, avFrame->height)); ffmpeg.avfilter_link(buffersrcCtx, 0, srcScale, 0); lastFilter = srcScale; convertedFrameBufferSize = ffmpeg.av_image_get_buffer_size(AVPixelFormat.AV_PIX_FMT_BGRA, avFrame->width, avFrame->height, 1); convertedFrameBufferPtr = Marshal.AllocHGlobal(convertedFrameBufferSize); }
public void Dispose(bool disposing) { if (isDisposed) { return; } Console.WriteLine("Disposing FilterGraph"); fixed(AVFilterGraph **p = &pointer) { ffmpeg.avfilter_graph_free(p); } Inputs?.Dispose(); Outputs?.Dispose(); pointer = null; isDisposed = true; }
private void DestroyFilterGraph() { try { if (FilterGraph == null) { return; } RC.Current.Remove(FilterGraph); var filterGraphRef = FilterGraph; ffmpeg.avfilter_graph_free(&filterGraphRef); FilterGraph = null; SinkInput = null; SourceOutput = null; } finally { AppliedFilterString = null; CurrentFilterArguments = null; } }
public override unsafe void LinkFilterGraph(AVFilterGraph *filterGraph, AVFilterContext *src, AVFilterContext *dst) { var aformatFilter = ffmpeg.avfilter_get_by_name("aformat"); if (aformatFilter == null) { throw new FFmpegException("Could not find aformat filter"); } AVFilterContext *aformat; ffmpeg.avfilter_graph_create_filter( &aformat, aformatFilter, "aformat", _args, null, filterGraph) .ThrowExceptionIfError(); ffmpeg.avfilter_link(src, 0, aformat, 0); ffmpeg.avfilter_link(aformat, 0, dst, 0); }
/// <summary> /// Adds the specified filtergraph. /// </summary> /// <param name="filtergraph">The filtergraph.</param> /// <param name="location">The location.</param> public void Add(AVFilterGraph *filtergraph, string location) => Add(UnmanagedType.FilterGraph, (IntPtr)filtergraph, location);
private void InitializeFilterGraph(AVFrame *frame) { // References: https://www.ffmpeg.org/doxygen/2.0/doc_2examples_2filtering_audio_8c-example.html const string SourceFilterName = "abuffer"; const string SourceFilterInstance = "audio_buffer"; const string SinkFilterName = "abuffersink"; const string SinkFilterInstance = "audio_buffersink"; // Get a snapshot of the FilterString var filterString = FilterString; // For empty filter strings ensure filtegraph is destroyed if (string.IsNullOrWhiteSpace(filterString)) { DestroyFilterGraph(); return; } // Recreate the filtergraph if we have to if (filterString != AppliedFilterString) { DestroyFilterGraph(); } // Ensure the filtergraph is compatible with the frame var filterArguments = ComputeFilterArguments(frame); if (filterArguments != CurrentFilterArguments) { DestroyFilterGraph(); } else { return; } FilterGraph = ffmpeg.avfilter_graph_alloc(); RC.Current.Add(FilterGraph); try { AVFilterContext *sourceFilterRef = null; AVFilterContext *sinkFilterRef = null; var result = ffmpeg.avfilter_graph_create_filter( &sourceFilterRef, ffmpeg.avfilter_get_by_name(SourceFilterName), SourceFilterInstance, filterArguments, null, FilterGraph); if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_graph_create_filter)} ({SourceFilterInstance}) failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } result = ffmpeg.avfilter_graph_create_filter( &sinkFilterRef, ffmpeg.avfilter_get_by_name(SinkFilterName), SinkFilterInstance, null, null, FilterGraph); if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_graph_create_filter)} ({SinkFilterInstance}) failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } SourceFilter = sourceFilterRef; SinkFilter = sinkFilterRef; if (string.IsNullOrWhiteSpace(filterString)) { result = ffmpeg.avfilter_link(SourceFilter, 0, SinkFilter, 0); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_link)} failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } } else { var initFilterCount = FilterGraph->nb_filters; SourceOutput = ffmpeg.avfilter_inout_alloc(); SourceOutput->name = ffmpeg.av_strdup("in"); SourceOutput->filter_ctx = SourceFilter; SourceOutput->pad_idx = 0; SourceOutput->next = null; SinkInput = ffmpeg.avfilter_inout_alloc(); SinkInput->name = ffmpeg.av_strdup("out"); SinkInput->filter_ctx = SinkFilter; SinkInput->pad_idx = 0; SinkInput->next = null; result = ffmpeg.avfilter_graph_parse(FilterGraph, filterString, SinkInput, SourceOutput, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_parse)} failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } // Reorder the filters to ensure that inputs of the custom filters are merged first for (var i = 0; i < FilterGraph->nb_filters - initFilterCount; i++) { var sourceAddress = FilterGraph->filters[i]; var targetAddress = FilterGraph->filters[i + initFilterCount]; FilterGraph->filters[i] = targetAddress; FilterGraph->filters[i + initFilterCount] = sourceAddress; } } result = ffmpeg.avfilter_graph_config(FilterGraph, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_config)} failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } } catch (Exception ex) { this.LogError(Aspects.Component, $"Audio filter graph could not be built: {filterString}.", ex); DestroyFilterGraph(); } finally { CurrentFilterArguments = filterArguments; AppliedFilterString = filterString; } }
private int open_input(string path) { try { int ret; var _timeoutMicroSeconds = Math.Max(5000000, TIMEOUT * 1000); AVDictionary* options = null; if (path.Contains(":")) { var prefix = path.ToLower().Substring(0, path.IndexOf(":", StringComparison.Ordinal)); ffmpeg.av_dict_set_int(&options, "rw_timeout", _timeoutMicroSeconds, 0); ffmpeg.av_dict_set_int(&options, "tcp_nodelay", 1, 0); switch (prefix) { case "https": case "http": case "mmsh": case "mms": ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); ffmpeg.av_dict_set_int(&options, "stimeout", _timeoutMicroSeconds, 0); break; case "rtsp": case "rtmp": ffmpeg.av_dict_set_int(&options, "stimeout", _timeoutMicroSeconds, 0); ffmpeg.av_dict_set(&options, "rtsp_flags", "prefer_tcp", 0); break; default: ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); break; case "tcp": ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); break; case "udp": ffmpeg.av_dict_set_int(&options, "timeout", _timeoutMicroSeconds, 0); break; } ffmpeg.av_dict_set_int(&options, "buffer_size", BUFSIZE, 0); } fmt_ctx = ffmpeg.avformat_alloc_context(); fmt_ctx->max_analyze_duration = 0; //0 = auto fixed (AVFormatContext** at = &fmt_ctx) { ret = ffmpeg.avformat_open_input(at, path, null, &options); } if (ret < 0) { throw new ApplicationException("Failed to open input."); } ret = ffmpeg.avformat_find_stream_info(fmt_ctx, null); if (ret < 0) { throw new ApplicationException("Failed to find stream information."); } AVCodec* dec; ret = ffmpeg.av_find_best_stream(fmt_ctx, AVMediaType.AVMEDIA_TYPE_AUDIO, -1, -1, &dec, 0); if (ret < 0) { throw new ApplicationException("Failed to find an audio stream in input."); } audio_stream_index = ret; _audioCodecContext = fmt_ctx->streams[audio_stream_index]->codec; _audioStream = fmt_ctx->streams[audio_stream_index]; fmt_ctx->flags |= ffmpeg.AVFMT_FLAG_DISCARD_CORRUPT; fmt_ctx->flags |= ffmpeg.AVFMT_FLAG_NOBUFFER; if (_audioStream != null) { var audiocodec = ffmpeg.avcodec_find_decoder(_audioCodecContext->codec_id); if (audiocodec != null) { ffmpeg.av_opt_set_int(_audioCodecContext, "refcounted_frames", 1, 0); /* init the audio decoder */ if ((ret = ffmpeg.avcodec_open2(_audioCodecContext, audiocodec, null)) < 0) { throw new ApplicationException("Failed to open audio decoder."); } if (filtersAudio.Count > 0) { fixed (AVFilterContext** bsrc = &buffersrc_ctx) { fixed (AVFilterContext** bsink = &buffersink_ctx) { // build a filter graph if ((int)(filter_graph = init_filter_graph(fmt_ctx, _audioCodecContext, audio_stream_index, bsrc, bsink)) == 0) { throw new ApplicationException("Failed to create the filter graph."); } } } } var outlayout = ffmpeg.av_get_default_channel_layout(channels); _audioCodecContext->request_sample_fmt = AVSampleFormat.AV_SAMPLE_FMT_S16; _audioCodecContext->request_channel_layout = (ulong)outlayout; //var chans = 1; //if (_audioCodecContext->channels > 1) //downmix // chans = 2; _swrContext = ffmpeg.swr_alloc_set_opts(null, outlayout, AVSampleFormat.AV_SAMPLE_FMT_S16, rate, ffmpeg.av_get_default_channel_layout(_audioCodecContext->channels), _audioCodecContext->sample_fmt, _audioCodecContext->sample_rate, 0, null); ret = ffmpeg.swr_init(_swrContext); if (ret < 0) { throw new ApplicationException("Failed to create swrContext."); } } } return ret; } catch (Exception ex) { throw ex; } //return -1; }
public void ReadSamples(string inputAudio, Func<byte[], int, bool> readSampleCallback) { if (readSampleCallback == null) return; const int EAGAIN = 11; var brk = false; var packet = new AVPacket(); try { int ret = open_input(inputAudio); if (ret < 0) { return; } byte[] buffer = null, tbuffer = null; while (true) { ffmpeg.av_init_packet(&packet); if (_audioCodecContext != null && buffer == null) { buffer = new byte[_audioCodecContext->sample_rate * 2]; tbuffer = new byte[_audioCodecContext->sample_rate * 2]; } ret = ffmpeg.av_read_frame(fmt_ctx, &packet); if (ret < 0) { break; } if ((packet.flags & ffmpeg.AV_PKT_FLAG_CORRUPT) == ffmpeg.AV_PKT_FLAG_CORRUPT) { break; } if (packet.stream_index == audio_stream_index) { var s = 0; fixed (byte** outPtrs = new byte*[32]) { fixed (byte* bPtr = &tbuffer[0]) { outPtrs[0] = bPtr; AVFrame* _af = null; var af = ffmpeg.av_frame_alloc(); var ff = ffmpeg.av_frame_alloc(); ffmpeg.avcodec_send_packet(_audioCodecContext, &packet); do { ret = ffmpeg.avcodec_receive_frame(_audioCodecContext, af); if (ret == 0) { if (filter_graph != null) { // add the frame into the filter graph ffmpeg.av_buffersrc_add_frame(buffersrc_ctx, af); // get the frame out from the filter graph ret = ffmpeg.av_buffersink_get_frame(buffersink_ctx, ff); if (ret == -EAGAIN) break; _af = ff; } else { _af = af; } fixed (byte** datptr = _af->data.ToArray()) { var numSamplesOut = ffmpeg.swr_convert(_swrContext, outPtrs, _audioCodecContext->sample_rate, datptr, _af->nb_samples); if (numSamplesOut > 0) { var l = numSamplesOut * 2 * channels; Buffer.BlockCopy(tbuffer, 0, buffer, s, l); s += l; } else { ret = numSamplesOut; //(error) } } if (_af->decode_error_flags > 0) break; } } while (ret == 0); ffmpeg.av_frame_free(&ff); ffmpeg.av_frame_free(&af); if (s > 0) { var ba = new byte[s]; Buffer.BlockCopy(buffer, 0, ba, 0, s); if (readSampleCallback(ba, s)) { brk = true; break; } } } } } ffmpeg.av_packet_unref(&packet); if (ret == -EAGAIN) { Thread.Sleep(10); } if (brk) break; } } catch (Exception ex) { throw ex; } finally { if (_audioCodecContext != null) { ffmpeg.avcodec_close(_audioCodecContext); } if (fmt_ctx != null) { fixed (AVFormatContext** at = &fmt_ctx) { ffmpeg.avformat_close_input(at); } } fmt_ctx = null; _audioCodecContext = null; _audioStream = null; if (_swrContext != null) { fixed (SwrContext** s = &_swrContext) { ffmpeg.swr_free(s); } _swrContext = null; } if (filter_graph != null) { fixed (AVFilterGraph** f = &filter_graph) { ffmpeg.avfilter_graph_free(f); } filter_graph = null; buffersink_ctx = null; buffersrc_ctx = null; filtersAudio.Clear(); } } }
public static extern int avfilter_graph_request_oldest(AVFilterGraph * @graph);
public static extern int avfilter_graph_add_filter(AVFilterGraph * @graphctx, AVFilterContext * @filter);
public static extern int avfilter_graph_queue_command(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @target, [MarshalAs(UnmanagedType.LPStr)] string @cmd, [MarshalAs(UnmanagedType.LPStr)] string @arg, int @flags, double @ts);
private void InitializeFilterGraph(AVFrame *frame) { /* * References: * http://libav-users.943685.n4.nabble.com/Libav-user-yadif-deinterlace-how-td3606561.html * https://www.ffmpeg.org/doxygen/trunk/filtering_8c-source.html * https://raw.githubusercontent.com/FFmpeg/FFmpeg/release/3.2/ffplay.c */ const string SourceFilterName = "buffer"; const string SourceFilterInstance = "video_buffer"; const string SinkFilterName = "buffersink"; const string SinkFilterInstance = "video_buffersink"; // Get a snapshot of the FilterString var filterString = FilterString; // For empty filter strings ensure filtegraph is destroyed if (string.IsNullOrWhiteSpace(filterString)) { DestroyFilterGraph(); return; } // Recreate the filtergraph if we have to if (filterString != AppliedFilterString) { DestroyFilterGraph(); } // Ensure the filtergraph is compatible with the frame var filterArguments = ComputeFilterArguments(frame); if (filterArguments != CurrentFilterArguments) { DestroyFilterGraph(); } else { return; } FilterGraph = ffmpeg.avfilter_graph_alloc(); RC.Current.Add(FilterGraph); try { // Get a couple of pointers for source and sink buffers AVFilterContext *sourceFilterRef = null; AVFilterContext *sinkFilterRef = null; // Create the source filter var result = ffmpeg.avfilter_graph_create_filter( &sourceFilterRef, ffmpeg.avfilter_get_by_name(SourceFilterName), SourceFilterInstance, filterArguments, null, FilterGraph); // Check filter creation if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_graph_create_filter)} ({SourceFilterName}) failed. " + $"Error {result}: {FFInterop.DecodeMessage(result)}"); } // Create the sink filter result = ffmpeg.avfilter_graph_create_filter( &sinkFilterRef, ffmpeg.avfilter_get_by_name(SinkFilterName), SinkFilterInstance, null, null, FilterGraph); // Check filter creation if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_graph_create_filter)} ({SinkFilterName}) failed. " + $"Error {result}: {FFInterop.DecodeMessage(result)}"); } // Save the filter references SourceFilter = sourceFilterRef; SinkFilter = sinkFilterRef; // TODO: from ffplay, ffmpeg.av_opt_set_int_list(sink, "pixel_formats", (byte*)&f0, 1, ffmpeg.AV_OPT_SEARCH_CHILDREN) if (string.IsNullOrWhiteSpace(filterString)) { result = ffmpeg.avfilter_link(SourceFilter, 0, SinkFilter, 0); if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_link)} failed. " + $"Error {result}: {FFInterop.DecodeMessage(result)}"); } } else { var initFilterCount = FilterGraph->nb_filters; SourceOutput = ffmpeg.avfilter_inout_alloc(); SourceOutput->name = ffmpeg.av_strdup("in"); SourceOutput->filter_ctx = SourceFilter; SourceOutput->pad_idx = 0; SourceOutput->next = null; SinkInput = ffmpeg.avfilter_inout_alloc(); SinkInput->name = ffmpeg.av_strdup("out"); SinkInput->filter_ctx = SinkFilter; SinkInput->pad_idx = 0; SinkInput->next = null; result = ffmpeg.avfilter_graph_parse(FilterGraph, filterString, SinkInput, SourceOutput, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_parse)} failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } // Reorder the filters to ensure that inputs of the custom filters are merged first for (var i = 0; i < FilterGraph->nb_filters - initFilterCount; i++) { var sourceAddress = FilterGraph->filters[i]; var targetAddress = FilterGraph->filters[i + initFilterCount]; FilterGraph->filters[i] = targetAddress; FilterGraph->filters[i + initFilterCount] = sourceAddress; } } result = ffmpeg.avfilter_graph_config(FilterGraph, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_config)} failed. Error {result}: {FFInterop.DecodeMessage(result)}"); } } catch (Exception ex) { this.LogError(Aspects.Component, $"Video filter graph could not be built: {filterString}.", ex); DestroyFilterGraph(); } finally { CurrentFilterArguments = filterArguments; AppliedFilterString = filterString; } }
/// <summary> /// Adds the specified filtergraph. /// </summary> /// <param name="filtergraph">The filtergraph.</param> /// <param name="location">The location.</param> public void Add(AVFilterGraph *filtergraph, string location) { Add(UnmanagedType.FilterGraph, new IntPtr(filtergraph), location); }
public static extern void avfilter_graph_set_auto_convert(AVFilterGraph * @graph, uint @flags);
public static extern int avfilter_graph_create_filter(AVFilterContext ** @filt_ctx, AVFilter * @filt, [MarshalAs(UnmanagedType.LPStr)] string @name, [MarshalAs(UnmanagedType.LPStr)] string @args, void * @opaque, AVFilterGraph * @graph_ctx);
/// <summary> /// Adds the specified pointer. /// </summary> /// <param name="pointer">The pointer.</param> /// <param name="memberName">Name of the member.</param> /// <param name="filePath">The file path.</param> /// <param name="lineNumber">The line number.</param> public void Add(AVFilterGraph *pointer, [CallerMemberName] string memberName = null, [CallerFilePath] string filePath = null, [CallerLineNumber] int lineNumber = 0) => AddInternal(UnmanagedType.FilterGraph, (IntPtr)pointer, memberName, filePath, lineNumber);
public static extern sbyte *avfilter_graph_dump(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @options);
public static extern int avfilter_graph_config(AVFilterGraph * @graphctx, void * @log_ctx);
public static extern AVFilterContext *avfilter_graph_get_filter(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @name);
/// <summary> /// If necessary, disposes the existing filtergraph and creates a new one based on the frame arguments. /// </summary> /// <param name="frame">The frame.</param> /// <exception cref="MediaContainerException"> /// avfilter_graph_create_filter /// or /// avfilter_graph_create_filter /// or /// avfilter_link /// or /// avfilter_graph_parse /// or /// avfilter_graph_config /// </exception> private void InitializeFilterGraph(AVFrame *frame) { /* * References: * http://libav-users.943685.n4.nabble.com/Libav-user-yadif-deinterlace-how-td3606561.html * https://www.ffmpeg.org/doxygen/trunk/filtering_8c-source.html * https://raw.githubusercontent.com/FFmpeg/FFmpeg/release/3.2/ffplay.c */ var frameArguments = ComputeFilterArguments(frame); if (string.IsNullOrWhiteSpace(CurrentFilterArguments) || frameArguments.Equals(CurrentFilterArguments) == false) { DestroyFiltergraph(); } else { return; } FilterGraph = ffmpeg.avfilter_graph_alloc(); RC.Current.Add(FilterGraph, $"144: {nameof(VideoComponent)}.{nameof(InitializeFilterGraph)}()"); CurrentFilterArguments = frameArguments; try { var result = 0; fixed(AVFilterContext **source = &SourceFilter) fixed(AVFilterContext **sink = &SinkFilter) { result = ffmpeg.avfilter_graph_create_filter(source, ffmpeg.avfilter_get_by_name("buffer"), "video_buffer", CurrentFilterArguments, null, FilterGraph); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_create_filter)} (buffer) failed. Error {result}: {Utils.DecodeFFmpegMessage(result)}"); } result = ffmpeg.avfilter_graph_create_filter(sink, ffmpeg.avfilter_get_by_name("buffersink"), "video_buffersink", null, null, FilterGraph); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_create_filter)} (buffersink) failed. Error {result}: {Utils.DecodeFFmpegMessage(result)}"); } // TODO: from ffplay, ffmpeg.av_opt_set_int_list(sink, "pix_fmts", (byte*)&f0, 1, ffmpeg.AV_OPT_SEARCH_CHILDREN); } if (string.IsNullOrWhiteSpace(FilterString)) { result = ffmpeg.avfilter_link(SourceFilter, 0, SinkFilter, 0); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_link)} failed. Error {result}: {Utils.DecodeFFmpegMessage(result)}"); } } else { var initFilterCount = FilterGraph->nb_filters; SourceOutput = ffmpeg.avfilter_inout_alloc(); SourceOutput->name = ffmpeg.av_strdup("in"); SourceOutput->filter_ctx = SourceFilter; SourceOutput->pad_idx = 0; SourceOutput->next = null; SinkInput = ffmpeg.avfilter_inout_alloc(); SinkInput->name = ffmpeg.av_strdup("out"); SinkInput->filter_ctx = SinkFilter; SinkInput->pad_idx = 0; SinkInput->next = null; result = ffmpeg.avfilter_graph_parse(FilterGraph, FilterString, SinkInput, SourceOutput, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_parse)} failed. Error {result}: {Utils.DecodeFFmpegMessage(result)}"); } // Reorder the filters to ensure that inputs of the custom filters are merged first for (var i = 0; i < FilterGraph->nb_filters - initFilterCount; i++) { var sourceAddress = FilterGraph->filters[i]; var targetAddress = FilterGraph->filters[i + initFilterCount]; FilterGraph->filters[i] = targetAddress; FilterGraph->filters[i + initFilterCount] = sourceAddress; } } result = ffmpeg.avfilter_graph_config(FilterGraph, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_config)} failed. Error {result}: {Utils.DecodeFFmpegMessage(result)}"); } } catch (Exception ex) { Container.Logger?.Log(MediaLogMessageType.Error, $"Video filter graph could not be built: {FilterString}.\r\n{ex.Message}"); DestroyFiltergraph(); } }
public static extern int avfilter_graph_parse2(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @filters, AVFilterInOut ** @inputs, AVFilterInOut ** @outputs);
/// <summary> /// If necessary, disposes the existing filtergraph and creates a new one based on the frame arguments. /// </summary> /// <param name="frame">The frame.</param> /// <exception cref="MediaContainerException"> /// avfilter_graph_create_filter /// or /// avfilter_graph_create_filter /// or /// avfilter_link /// or /// avfilter_graph_parse /// or /// avfilter_graph_config /// </exception> private void InitializeFilterGraph(AVFrame *frame) { /* * References: * https://www.ffmpeg.org/doxygen/2.0/doc_2examples_2filtering_audio_8c-example.html */ var frameArguments = ComputeFilterArguments(frame); if (string.IsNullOrWhiteSpace(CurrentFilterArguments) || frameArguments.Equals(CurrentFilterArguments) == false) { DestroyFiltergraph(); } else { return; } FilterGraph = ffmpeg.avfilter_graph_alloc(); RC.Current.Add(FilterGraph, $"264: {nameof(AudioComponent)}.{nameof(InitializeFilterGraph)}()"); CurrentFilterArguments = frameArguments; try { var result = 0; fixed(AVFilterContext **source = &SourceFilter) fixed(AVFilterContext **sink = &SinkFilter) { result = ffmpeg.avfilter_graph_create_filter(source, ffmpeg.avfilter_get_by_name("abuffer"), "audio_buffer", CurrentFilterArguments, null, FilterGraph); if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_graph_create_filter)} (audio_buffer) failed. Error {result}: {FFmpegEx.GetErrorMessage(result)}"); } result = ffmpeg.avfilter_graph_create_filter(sink, ffmpeg.avfilter_get_by_name("abuffersink"), "audio_buffersink", null, null, FilterGraph); if (result != 0) { throw new MediaContainerException( $"{nameof(ffmpeg.avfilter_graph_create_filter)} (audio_buffersink) failed. Error {result}: {FFmpegEx.GetErrorMessage(result)}"); } } if (string.IsNullOrWhiteSpace(FilterString)) { result = ffmpeg.avfilter_link(SourceFilter, 0, SinkFilter, 0); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_link)} failed. Error {result}: {FFmpegEx.GetErrorMessage(result)}"); } } else { var initFilterCount = FilterGraph->nb_filters; SourceOutput = ffmpeg.avfilter_inout_alloc(); SourceOutput->name = ffmpeg.av_strdup("in"); SourceOutput->filter_ctx = SourceFilter; SourceOutput->pad_idx = 0; SourceOutput->next = null; SinkInput = ffmpeg.avfilter_inout_alloc(); SinkInput->name = ffmpeg.av_strdup("out"); SinkInput->filter_ctx = SinkFilter; SinkInput->pad_idx = 0; SinkInput->next = null; result = ffmpeg.avfilter_graph_parse(FilterGraph, FilterString, SinkInput, SourceOutput, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_parse)} failed. Error {result}: {FFmpegEx.GetErrorMessage(result)}"); } // Reorder the filters to ensure that inputs of the custom filters are merged first for (var i = 0; i < FilterGraph->nb_filters - initFilterCount; i++) { var sourceAddress = FilterGraph->filters[i]; var targetAddress = FilterGraph->filters[i + initFilterCount]; FilterGraph->filters[i] = targetAddress; FilterGraph->filters[i + initFilterCount] = sourceAddress; } } result = ffmpeg.avfilter_graph_config(FilterGraph, null); if (result != 0) { throw new MediaContainerException($"{nameof(ffmpeg.avfilter_graph_config)} failed. Error {result}: {FFmpegEx.GetErrorMessage(result)}"); } } catch (Exception ex) { Container.Logger?.Log(MediaLogMessageType.Error, $"Audio filter graph could not be built: {FilterString}.\r\n{ex.Message}"); DestroyFiltergraph(); } }
public static extern int avfilter_graph_send_command(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @target, [MarshalAs(UnmanagedType.LPStr)] string @cmd, [MarshalAs(UnmanagedType.LPStr)] string @arg, IntPtr @res, int @res_len, int @flags);