예제 #1
0
 public MediaFilterGraph()
 {
     unsafe
     {
         pFilterGraph = ffmpeg.avfilter_graph_alloc();
     }
 }
예제 #2
0
        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;
        }
예제 #4
0
        /// <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;
        }
예제 #6
0
    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);
        }
예제 #8
0
        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);
        }
예제 #9
0
        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;
        }
예제 #10
0
        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;
            }
        }
예제 #11
0
    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);
    }
예제 #12
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);
예제 #13
0
        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;
            }
        }
예제 #14
0
        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;
        }
예제 #15
0
        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();
                }
            }
        }
예제 #16
0
 public static extern int avfilter_graph_request_oldest(AVFilterGraph * @graph);
예제 #17
0
 public static extern int avfilter_graph_add_filter(AVFilterGraph * @graphctx, AVFilterContext * @filter);
예제 #18
0
 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);
예제 #19
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;
            }
        }
예제 #20
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, new IntPtr(filtergraph), location);
 }
예제 #21
0
 public static extern void avfilter_graph_set_auto_convert(AVFilterGraph * @graph, uint @flags);
예제 #22
0
 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);
예제 #23
0
 /// <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);
예제 #24
0
 public static extern sbyte *avfilter_graph_dump(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @options);
예제 #25
0
 public static extern int avfilter_graph_config(AVFilterGraph * @graphctx, void * @log_ctx);
예제 #26
0
 public static extern AVFilterContext *avfilter_graph_get_filter(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @name);
예제 #27
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:
             * 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();
            }
        }
예제 #28
0
 public static extern int avfilter_graph_parse2(AVFilterGraph * @graph, [MarshalAs(UnmanagedType.LPStr)] string @filters, AVFilterInOut ** @inputs, AVFilterInOut ** @outputs);
예제 #29
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();
            }
        }
예제 #30
0
 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);