javacpp-presets icon indicating copy to clipboard operation
javacpp-presets copied to clipboard

Impossible to convert between the formats supported by the filter 'Parsed_ebur128_0' and the filter 'auto_resampler_0'

Open wsourabh opened this issue 5 years ago • 1 comments

Hi facing some issue with code . Which I have written after seeing this example : https://github.com/FFmpeg/FFmpeg/blob/master/doc/examples/filtering_audio.c program mentioned in link works fine.

but below mentioned java code is having some issue while linking filters.

import org.bytedeco.javacpp.BytePointer;
import org.bytedeco.javacpp.avcodec;
import org.bytedeco.javacpp.avfilter;
import org.bytedeco.javacpp.avformat;
import org.bytedeco.javacpp.avutil;

import java.nio.ByteBuffer;

import static org.bytedeco.javacpp.avcodec.av_packet_unref;
import static org.bytedeco.javacpp.avcodec.avcodec_alloc_context3;
import static org.bytedeco.javacpp.avcodec.avcodec_free_context;
import static org.bytedeco.javacpp.avcodec.avcodec_open2;
import static org.bytedeco.javacpp.avcodec.avcodec_parameters_to_context;
import static org.bytedeco.javacpp.avcodec.avcodec_receive_frame;
import static org.bytedeco.javacpp.avcodec.avcodec_send_packet;
import static org.bytedeco.javacpp.avfilter.AV_BUFFERSRC_FLAG_KEEP_REF;
import static org.bytedeco.javacpp.avfilter.av_buffersink_get_frame;
import static org.bytedeco.javacpp.avfilter.av_buffersrc_add_frame_flags;
import static org.bytedeco.javacpp.avfilter.avfilter_get_by_name;
import static org.bytedeco.javacpp.avfilter.avfilter_graph_alloc;
import static org.bytedeco.javacpp.avfilter.avfilter_graph_config;
import static org.bytedeco.javacpp.avfilter.avfilter_graph_create_filter;
import static org.bytedeco.javacpp.avfilter.avfilter_graph_free;
import static org.bytedeco.javacpp.avfilter.avfilter_graph_parse_ptr;
import static org.bytedeco.javacpp.avfilter.avfilter_inout_alloc;
import static org.bytedeco.javacpp.avfilter.avfilter_inout_free;
import static org.bytedeco.javacpp.avformat.av_dump_format;
import static org.bytedeco.javacpp.avformat.av_find_best_stream;
import static org.bytedeco.javacpp.avformat.av_read_frame;
import static org.bytedeco.javacpp.avformat.avformat_alloc_context;
import static org.bytedeco.javacpp.avformat.avformat_close_input;
import static org.bytedeco.javacpp.avformat.avformat_find_stream_info;
import static org.bytedeco.javacpp.avformat.avformat_open_input;
import static org.bytedeco.javacpp.avutil.AVERROR_EOF;
import static org.bytedeco.javacpp.avutil.AVMEDIA_TYPE_AUDIO;
import static org.bytedeco.javacpp.avutil.AV_CH_LAYOUT_MONO;
import static org.bytedeco.javacpp.avutil.AV_LOG_DEBUG;
import static org.bytedeco.javacpp.avutil.AV_LOG_ERROR;
import static org.bytedeco.javacpp.avutil.AV_LOG_INFO;
import static org.bytedeco.javacpp.avutil.AV_OPT_SEARCH_CHILDREN;
import static org.bytedeco.javacpp.avutil.AV_SAMPLE_FMT_S16;
import static org.bytedeco.javacpp.avutil.av_frame_alloc;
import static org.bytedeco.javacpp.avutil.av_frame_free;
import static org.bytedeco.javacpp.avutil.av_frame_unref;
import static org.bytedeco.javacpp.avutil.av_get_channel_layout_string;
import static org.bytedeco.javacpp.avutil.av_get_default_channel_layout;
import static org.bytedeco.javacpp.avutil.av_get_sample_fmt_name;
import static org.bytedeco.javacpp.avutil.av_log;
import static org.bytedeco.javacpp.avutil.av_log_set_level;
import static org.bytedeco.javacpp.avutil.av_make_error_string;
import static org.bytedeco.javacpp.avutil.av_opt_set_bin;
import static org.bytedeco.javacpp.avutil.av_strdup;


public class Ebur128Filter {
    private String fileURI;
    private String filterString = "ebur128=metadata=1:peak=true";
    private avformat.AVFormatContext fmt_ctx;
    private int audio_stream_index;
    private avcodec.AVCodecContext dec_ctx;
    private avfilter.AVFilterGraph filter_graph;
    private avfilter.AVFilterContext buffersrc_ctx;
    private avfilter.AVFilterContext buffersink_ctx;

    public Ebur128Filter(String fileURI) {
        this.fileURI = fileURI;
    }

    public void start() throws Exception {
        av_log_set_level(AV_LOG_DEBUG);
        avutil.AVFrame frame = null;
        avutil.AVFrame filt_frame = null;
        avcodec.AVPacket packet = null;
        int ret = 0;
        try {


            frame = av_frame_alloc();
            filt_frame = av_frame_alloc();
            packet = new avcodec.AVPacket();

            if (frame.isNull() || filt_frame.isNull()) {
                throw new OutOfMemoryError();
            }

            open_input_file(fileURI);
            init_filters(filterString);

            av_dump_format(fmt_ctx, 0, fileURI, 0);
            /* start reading frames*/
            while (true) {
                if ((ret = av_read_frame(fmt_ctx, packet)) < 0) {
                    break;
                }
                //av_dump_format(fmt_ctx, 0, fileURI, 0);

                /*packet is from the best stream selected */
                if (packet.stream_index() == audio_stream_index) {
                    /* send packet to decoder*/
                    ret = avcodec_send_packet(dec_ctx, packet);
                    if (ret < 0) {
                        av_log(null, AV_LOG_ERROR, "Error while sending a packet to the decoder\n");
                        break;
                    }

                    /* till methods keep on returning success codes */
                    while (ret >= 0) {
                        av_frame_unref(frame);
                        ret = avcodec_receive_frame(dec_ctx, frame);
                        if (ret == 35/*EAGAIN*/ || ret == AVERROR_EOF) {
                            break;
                        } else if (ret < 0) {
                            av_log(null, AV_LOG_ERROR, "Error while receiving a frame from the decoder\n");
                            throw new Exception();
                        }

                        if (ret >= 0) {
                            /* push the audio data from decoded frame into the filtergraph */
                            if ((ret = av_buffersrc_add_frame_flags(buffersrc_ctx, frame, AV_BUFFERSRC_FLAG_KEEP_REF)
                            ) < 0) {
                                System.out.println("av_buffersrc_add_frame_flags: Error occurred: "
                                        + av_make_error_string(new BytePointer(256), 256, ret).getString());
                                av_log(null, AV_LOG_ERROR, "Error while feeding the audio filtergraph\n");
                                break;
                            }

                            /* pull filtered audio from the filtergraph */
                            while (true) {
                                av_frame_unref(filt_frame);
                                ret = av_buffersink_get_frame(buffersink_ctx, filt_frame);
                                if (ret == 35 /*EAGAIN*/ || ret == AVERROR_EOF) {
                                    break;
                                }
                                if (ret < 0) {
                                    throw new Exception();
                                }
                                print_frame(filt_frame);
                                av_frame_unref(filt_frame);

                            }
                        }
                    }

                }

                av_packet_unref(packet);

            }

        } finally {
            avfilter_graph_free(filter_graph);
            avcodec_free_context(dec_ctx);
            avformat_close_input(fmt_ctx);
            av_frame_free(frame);
            av_frame_free(filt_frame);

            if (ret < 0 && ret == AVERROR_EOF) {
                System.out.println(": Error occurred: "
                        + av_make_error_string(new BytePointer(256), 256, ret).getString());
            }
        }


    }

    private void print_frame(avutil.AVFrame filt_frame) {

    }

    private void init_filters(String filter_descr) throws Exception {
        int ret;
        avfilter.AVFilter abuffersrc;
        avfilter.AVFilter abuffersink;
        avfilter.AVFilterInOut outputs = null;
        avfilter.AVFilterInOut inputs = null;

        try {
            abuffersrc = avfilter_get_by_name("abuffer");
            abuffersink = avfilter_get_by_name("abuffersink");
            outputs = avfilter_inout_alloc();
            inputs = avfilter_inout_alloc();
            int[] out_sample_fmts = {AV_SAMPLE_FMT_S16, -1};
            long[] out_channel_layouts = {AV_CH_LAYOUT_MONO, -1};
            int[] out_sample_rates = {8000, -1};

            avfilter.AVFilterLink outlink = new avfilter.AVFilterLink();
            avutil.AVRational time_base = fmt_ctx.streams(audio_stream_index).time_base();


            buffersrc_ctx = new avfilter.AVFilterContext();
            buffersink_ctx = new avfilter.AVFilterContext();

            filter_graph = avfilter_graph_alloc();
            if (outputs == null || outputs.isNull()
                    || inputs == null || inputs.isNull()
                    || filter_graph == null || filter_graph.isNull()) {
                throw new OutOfMemoryError();
            }

            print_buffersink();
            /*buffer audio src: the decoded frames from the decoder will be inserted here */
            if (dec_ctx.channel_layout() == 0) {
                dec_ctx.channel_layout(av_get_default_channel_layout(dec_ctx.channels()));
            }
            String args = String.format("time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%08X",
                    time_base.num(), time_base.den(), dec_ctx.sample_rate(),
                    av_get_sample_fmt_name(dec_ctx.sample_fmt()).getString(),
                    dec_ctx.channel_layout());

            ret = avfilter_graph_create_filter(buffersrc_ctx, abuffersrc, "in", args, null, filter_graph);
            print_buffersink();

            if (ret < 0) {
                System.out.println("cannot create audio buffer src: Error occurred: "
                        + av_make_error_string(new BytePointer(256), 256, ret).getString());
                throw new Exception("avfilter_graph_create_filter: Error occurred: "
                        + av_make_error_string(new BytePointer(256), 256, ret).getString());
            }
            /*buffer audio sink : to terminate the filter chain */
            ret = avfilter_graph_create_filter(buffersink_ctx, abuffersink, "out", null, null,
                    filter_graph);
            print_buffersink();

            if (ret < 0) {
                System.out.println("cannot create audio buffer sink: Error occurred: "
                        + av_make_error_string(new BytePointer(256), 256, ret).getString());
                throw new Exception("avfilter_graph_create_filter: Error occurred: "
                        + av_make_error_string(new BytePointer(256), 256, ret).getString());
            }

            //ret = av_opt_set_int_list(buffersink_ctx, "sample_fmts", out_sample_fmts, -1, AV_OPT_SEARCH_CHILDREN);
            ByteBuffer bb = ByteBuffer.allocate((out_sample_fmts.length * 4));
            for (final int val : out_sample_fmts) {
                bb.putInt(val);
            }

            ret = av_opt_set_bin(buffersink_ctx, "sample_fmts", bb.array(),
                    4 * out_sample_fmts.length, AV_OPT_SEARCH_CHILDREN);

            if (ret < 0) {
                //TODO raise error
            }

            bb = ByteBuffer.allocate((out_channel_layouts.length * 8));
            for (final long val : out_channel_layouts) {
                bb.putLong(val);
            }

            ret = av_opt_set_bin(buffersink_ctx, "channel_layouts", bb.array(),
                    8 * out_channel_layouts.length, AV_OPT_SEARCH_CHILDREN);

            if (ret < 0) {
                //TODO raise error
            }

            bb = ByteBuffer.allocate((out_sample_rates.length * 4));
            for (final int val : out_sample_rates) {
                bb.putInt(val);
            }

            ret = av_opt_set_bin(buffersink_ctx, "channel_layouts", bb.array(),
                    4 * out_sample_rates.length, AV_OPT_SEARCH_CHILDREN);

            if (ret < 0) {
                //TODO raise error
            }

            /*
             * Set the endpoints for the filter graph. The filter_graph will
             * be linked to the graph described by filters_descr.
             */

            /*
             * The buffer source output must be connected to the input pad of
             * the first filter described by filters_descr; since the first
             * filter input label is not specified, it is set to "in" by
             * default.
             */

            outputs.name(av_strdup(new BytePointer("in")));
            outputs.filter_ctx(buffersrc_ctx);
            outputs.pad_idx(0);
            outputs.next(null);

            /*
             * The buffer sink input must be connected to the output pad of
             * the last filter described by filters_descr; since the last
             * filter output label is not specified, it is set to "out" by
             * default.
             */
            inputs.name(av_strdup(new BytePointer("out")));
            inputs.filter_ctx(buffersink_ctx);
            inputs.pad_idx(0);
            inputs.next(null);

            if ((ret = avfilter_graph_parse_ptr(filter_graph, filter_descr,
                    inputs, outputs, null)) < 0) {
                //TODO raise error
            }

            if ((ret = avfilter_graph_config(filter_graph, null)) < 0) {
                //TODO raise error
            }

            /* Print summary of the sink buffer*/
            print_buffersink();

        } finally {
            avfilter_inout_free(inputs);
            avfilter_inout_free(outputs);
        }
    }

    private void print_buffersink() {
        avfilter.AVFilterLink outlink;
        ByteBuffer buffer = ByteBuffer.allocateDirect(512);
        BytePointer ptr = new BytePointer(buffer);
        if (buffersink_ctx != null && !buffersink_ctx.isNull()
                && buffersink_ctx.nb_inputs() > 0
                && buffersink_ctx.inputs(0) !=null && !buffersink_ctx.inputs(0).isNull()) {
            outlink = buffersink_ctx.inputs(0);
            av_get_channel_layout_string(ptr, 512, -1, outlink.channel_layout());
            av_log(null, AV_LOG_INFO, String.format("Output: srate:%dHz fmt:%s chlayout:%s\n",
                    (int) outlink.sample_rate(),
                    av_get_sample_fmt_name(outlink.format()),
                    ptr.getString()));
        }
    }

    private void open_input_file(String fileURI) throws Exception {
        int ret;
        avcodec.AVCodec dec = new avcodec.AVCodec();
        fmt_ctx = avformat_alloc_context();
        if ((ret = avformat_open_input(fmt_ctx, fileURI, (avformat.AVInputFormat) null, (avutil.AVDictionary) null)) < 0) {
            System.out.println("avformat_open_input(): Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
            throw new Exception("avformat_open_input(): Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
        }

        if ((ret = avformat_find_stream_info(fmt_ctx, (avutil.AVDictionary) null)) < 0) {
            System.out.println("avformat_find_stream_info(): Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
            throw new Exception("avformat_find_stream_info(): Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
        }

        /* select the best audio stream */
        ret = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, dec, 0);
        if (ret < 0) {
            System.out.println("av_find_best_stream(): Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
            throw new Exception("av_find_best_stream(): Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
        }

        audio_stream_index = ret;

        /* create decoding context */
        dec_ctx = avcodec_alloc_context3(dec);
        if (dec_ctx == null || dec_ctx.isNull()) {
            throw new OutOfMemoryError();
        }

//        if (avcodec_open2(dec_ctx, dec, new avutil.AVDictionary()) < 0) {
//            //TODO raise exception
//        }

        avcodec_parameters_to_context(dec_ctx, fmt_ctx.streams(audio_stream_index).codecpar());

        /*init the audio decoder*/

        if ((ret = avcodec_open2(dec_ctx, dec, (avutil.AVDictionary) null)) < 0) {
            System.out.println("cannot open audio decoder: Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
            throw new Exception("avcodec_open2: Error occurred: "
                    + av_make_error_string(new BytePointer(256), 256, ret).getString());
        }

    }

}

=========================================================== But getting the below trace when running the start method.


[NULL @ 0x7fcefb31c600] Opening 'file://resources/sample.mp3' for reading
[file @ 0x7fcef9f6a100] Setting default whitelist 'file,crypto'
[mp3 @ 0x7fcefb31c600] Format mp3 probed with size=4096 and score=51
id3v2 ver:3 flags:00 len:0
[mp3 @ 0x7fcefb31c600] Skipping 0 bytes of junk at 10.
[mp3 @ 0x7fcefb31c600] Before avformat_find_stream_info() pos: 10 bytes read:65664 seeks:2 nb_streams:1
[mp3 @ 0x7fcefb31c600] All info found
[mp3 @ 0x7fcefb31c600] Estimating duration from bitrate, this may be inaccurate
[mp3 @ 0x7fcefb31c600] After avformat_find_stream_info() pos: 21514 bytes read:65664 seeks:2 frames:50
detected 4 logical cores
[in @ 0x7fcef9e63940] Setting 'time_base' to value '1/14112000'
[in @ 0x7fcef9e63940] Setting 'sample_rate' to value '44100'
[in @ 0x7fcef9e63940] Setting 'sample_fmt' to value 'fltp'
[in @ 0x7fcef9e63940] Setting 'channel_layout' to value '0x00000003'
[in @ 0x7fcef9e63940] tb:1/14112000 samplefmt:fltp samplerate:44100 chlayout:0x00000003
[Parsed_ebur128_0 @ 0x7fcef9e647c0] Setting 'metadata' to value '1'
[Parsed_ebur128_0 @ 0x7fcef9e647c0] Setting 'peak' to value 'true'
[Parsed_ebur128_0 @ 0x7fcef9e647c0] EBU +9 scale
[out @ 0x7fcef9e64040] auto-inserting filter 'auto_resampler_0' between the filter 'Parsed_ebur128_0' and the filter 'out'
Impossible to convert between the formats supported by the filter 'Parsed_ebur128_0' and the filter 'auto_resampler_0'
Output: srate:0Hz fmt:null chlayout:0 channelsInput #0, mp3, from 'file://resources/sample.mp3':
  Duration: 00:00:27.74, start: 0.000000, bitrate: 128 kb/s
    Stream #0:0, 50, 1/14112000: Audio: mp3, 44100 Hz, stereo, fltp, 128 kb/s
[Parsed_ebur128_0 @ 0x7fcef9e647c0] Format change is not supported
av_buffersrc_add_frame_flags: Error occurred: Not yet implemented in FFmpeg, patches welcome

wsourabh avatar Apr 16 '19 17:04 wsourabh

error is raised when calling if ((ret = avfilter_graph_config(filter_graph, null)) < 0) {

wsourabh avatar Apr 16 '19 18:04 wsourabh