Beispiel #1
0
        /// <summary>
        /// Destroys the filtergraph releasing unmanaged resources.
        /// </summary>
        private void DestroyFiltergraph()
        {
            if (FilterGraph != null)
            {
                RC.Current.Remove(FilterGraph);

                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 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);
        }
Beispiel #4
0
        public static MediaFilterGraph CreateMediaFilterGraph(string graphDesc)
        {
            MediaFilterGraph filterGraph = new MediaFilterGraph();
            AVFilterInOut *  inputs;
            AVFilterInOut *  outputs;

            ffmpeg.avfilter_graph_parse2(filterGraph, graphDesc, &inputs, &outputs).ThrowExceptionIfError();
            AVFilterInOut *cur = inputs;

            for (cur = inputs; cur != null; cur = cur->next)
            {
                Trace.TraceInformation($"{((IntPtr)cur->name).PtrToStringUTF8()}");
                filterGraph.inputs.Add(new MediaFilterContext(cur->filter_ctx));
            }
            for (cur = outputs; cur != null; cur = cur->next)
            {
                Trace.TraceInformation($"{((IntPtr)cur->name).PtrToStringUTF8()}");
                filterGraph.outputs.Add(new MediaFilterContext(cur->filter_ctx));
            }

            foreach (var item in filterGraph)
            {
                Trace.TraceInformation($"{item.Name}");
                for (int i = 0; i < item.NbInputs; i++)
                {
                    Trace.TraceInformation(ffmpeg.avfilter_pad_get_name(item.AVFilterContext.input_pads, i));
                }
                Trace.TraceInformation("++++");
                for (int i = 0; i < item.NbOutputs; i++)
                {
                    Trace.TraceInformation(ffmpeg.avfilter_pad_get_name(item.AVFilterContext.output_pads, i));
                }
                Trace.TraceInformation("---------");
            }
            // TODO: Link
            filterGraph.Initialize();
            ffmpeg.avfilter_inout_free(&inputs);
            ffmpeg.avfilter_inout_free(&outputs);
            return(filterGraph);
        }
        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;
            }
        }
Beispiel #6
0
        public static MediaFilterGraph CreateMediaFilterGraph(string graphDesc)
        {
            unsafe
            {
                MediaFilterGraph filterGraph = new MediaFilterGraph();
                AVFilterInOut *  inputs;
                AVFilterInOut *  outputs;
                ffmpeg.avfilter_graph_parse2(filterGraph, graphDesc, &inputs, &outputs).ThrowExceptionIfError();
                AVFilterInOut *cur = inputs;
                for (cur = inputs; cur != null; cur = cur->next)
                {
                    ffmpeg.av_log(null, (int)LogLevel.Debug, $"{((IntPtr)cur->name).PtrToStringUTF8()}{Environment.NewLine}");
                    filterGraph.inputs.Add(new MediaFilterContext(cur->filter_ctx));
                }
                for (cur = outputs; cur != null; cur = cur->next)
                {
                    ffmpeg.av_log(null, (int)LogLevel.Debug, $"{((IntPtr)cur->name).PtrToStringUTF8()}{Environment.NewLine}");
                    filterGraph.outputs.Add(new MediaFilterContext(cur->filter_ctx));
                }

                foreach (var item in filterGraph)
                {
                    ffmpeg.av_log(null, (int)LogLevel.Debug, $"{item.Name}{Environment.NewLine}");
                    for (int i = 0; i < item.NbInputs; i++)
                    {
                        ffmpeg.av_log(null, (int)LogLevel.Debug, $"{ffmpeg.avfilter_pad_get_name(item.AVFilterContext.input_pads, i)}{Environment.NewLine}");
                    }
                    for (int i = 0; i < item.NbOutputs; i++)
                    {
                        ffmpeg.av_log(null, (int)LogLevel.Debug, $"{ffmpeg.avfilter_pad_get_name(item.AVFilterContext.output_pads, i)}{Environment.NewLine}");
                    }
                }
                // TODO: Link
                filterGraph.Initialize();
                ffmpeg.avfilter_inout_free(&inputs);
                ffmpeg.avfilter_inout_free(&outputs);
                return(filterGraph);
            }
        }
Beispiel #7
0
        /// <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();
            }
        }
        /// <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();
            }
        }
        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;
            }
        }
 public static extern int avfilter_graph_parse(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @filters, AVFilterInOut * @inputs, AVFilterInOut * @outputs, void * @log_ctx);
Beispiel #11
0
        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;
            }
        }
Beispiel #12
0
            unsafe public void InitFilter(AVFilterGraph *_filter_graph,
                                          String filter_desc,
                                          AVFilterContext *_filter_ctx_src_spk,
                                          AVFilterContext *_filter_ctx_src_mic,
                                          AVFilterContext *_filter_ctx_sink,
                                          Openfile openfile1,
                                          Openfile openfile2,
                                          Openfile outfile)
            {
                AVFilter *filter_src_spk = ffmpeg.avfilter_get_by_name("abuffer");
                AVFilter *filter_src_mic = ffmpeg.avfilter_get_by_name("abuffer");
                AVFilter *filter_sink    = ffmpeg.avfilter_get_by_name("abuffersink");

                AVFilterInOut *filter_output_spk = ffmpeg.avfilter_inout_alloc();
                AVFilterInOut *filter_output_mic = ffmpeg.avfilter_inout_alloc();
                AVFilterInOut *filter_input      = ffmpeg.avfilter_inout_alloc();

                _filter_graph = ffmpeg.avfilter_graph_alloc();
                string args_spk = "time_base=1/44100:sample_rate=44100:sample_fmt=8:channel_layout=3";


                // 5.1 创建输出滤镜的上下文
                //_filter_ctx_sink = ffmpeg.avfilter_graph_alloc_filter(_filter_graph, filter_sink, "sink");

                int ret = ffmpeg.avfilter_graph_create_filter(&_filter_ctx_src_spk, filter_src_spk, "in0", args_spk, null, _filter_graph);

                ret = ffmpeg.avfilter_graph_create_filter(&_filter_ctx_src_mic, filter_src_mic, "in1", args_spk, null, _filter_graph);
                ret = ffmpeg.avfilter_graph_create_filter(&_filter_ctx_sink, filter_sink, "out", null, null, _filter_graph);

                AVCodecContext *encodec_ctx = outfile._pCodecContext;

                //过滤器上下文输出参数配置

                //ret = ffmpeg.av_opt_set_bin(_filter_ctx_sink, "sample_rates", (byte*)outfile._pCodecContext->sample_rate, (int)8, 1);
                //if (ret < 0)
                //{
                //    Console.WriteLine("Filter: failed to call av_opt_set_bin -- sample_rates\n");
                //}

                ret = ffmpeg.av_opt_set_bin(_filter_ctx_sink, "sample_fmts", (byte *)&encodec_ctx->sample_fmt, (int)8, 1);
                if (ret < 0)
                {
                    Console.WriteLine("Filter: failed to call av_opt_set_bin -- sample_fmts\n");
                }
                ret = ffmpeg.av_opt_set_bin(_filter_ctx_sink, "channel_layouts", (byte *)&encodec_ctx->channel_layout, (int)8, 1);

                if (ret < 0)
                {
                    Console.WriteLine("Filter: failed to call av_opt_set_bin -- channel_layouts\n");
                }

                ret = ffmpeg.av_opt_set_bin(_filter_ctx_src_spk, "sample_fmts", (byte *)&encodec_ctx->sample_fmt, (int)8, 1);
                if (ret < 0)
                {
                    Console.WriteLine("Filter: failed to call _filter_ctx_src_spk -- sample_fmts\n");
                }



                filter_output_spk->name       = ffmpeg.av_strdup("in0");
                filter_output_spk->filter_ctx = _filter_ctx_src_spk;
                filter_output_spk->pad_idx    = 0;
                filter_output_spk->next       = filter_output_mic;

                filter_output_mic->name       = ffmpeg.av_strdup("in1");
                filter_output_mic->filter_ctx = _filter_ctx_src_mic;
                filter_output_mic->pad_idx    = 0;
                filter_output_mic->next       = null;

                filter_input->name       = ffmpeg.av_strdup("out");
                filter_input->filter_ctx = _filter_ctx_sink;
                filter_input->pad_idx    = 0;
                filter_input->next       = null;

                AVFilterInOut *[] filter_outputs = new AVFilterInOut *[2];
                filter_outputs[0] = filter_output_spk;
                filter_outputs[1] = filter_output_mic;

                fixed(AVFilterInOut **outs = &filter_outputs[0])
                {
                    ret = ffmpeg.avfilter_graph_parse_ptr(_filter_graph, filter_desc, &filter_input, outs, null);
                    ret = ffmpeg.avfilter_graph_config(_filter_graph, null);
                    if (ret < 0)
                    {
                        Console.WriteLine("Filter: failed to call avfilter_graph_config -- avfilter_graph_config\n");
                    }
                    byte *ff = ffmpeg.avfilter_graph_dump(_filter_graph, null);



                    Console.WriteLine("Filter: failed to call avfilter_graph_dump -- avfilter_graph_dump\n" + *ff);
                }

                this._filter_ctx_src_spk = _filter_ctx_src_spk;
                this._filter_ctx_src_mic = _filter_ctx_src_mic;
                this._filter_ctx_sink    = _filter_ctx_sink;
            }
 public extern static int avfilter_graph_parse(AVFilterGraph *graph, [MarshalAs(UnmanagedType.LPStr)] string filters, AVFilterInOut *inputs, AVFilterInOut *outputs, void *log_ctx);