static av_cold int movie_common_init(AVFilterContext *ctx)

{

    MovieContext *movie = ctx->priv;

    AVInputFormat *iformat = NULL;

    int64_t timestamp;

    int nb_streams = 1, ret, i;

    char default_streams[16], *stream_specs, *spec, *cursor;

    char name[16];

    AVStream *st;



    if (!movie->file_name) {

        av_log(ctx, AV_LOG_ERROR, "No filename provided!\n");

        return AVERROR(EINVAL);

    }



    movie->seek_point = movie->seek_point_d * 1000000 + 0.5;



    stream_specs = movie->stream_specs;

    if (!stream_specs) {

        snprintf(default_streams, sizeof(default_streams), "d%c%d",

                 !strcmp(ctx->filter->name, "amovie") ? 'a' : 'v',

                 movie->stream_index);

        stream_specs = default_streams;

    }

    for (cursor = stream_specs; *cursor; cursor++)

        if (*cursor == '+')

            nb_streams++;



    if (movie->loop_count != 1 && nb_streams != 1) {

        av_log(ctx, AV_LOG_ERROR,

               "Loop with several streams is currently unsupported\n");

        return AVERROR_PATCHWELCOME;

    }



    av_register_all();



    // Try to find the movie format (container)

    iformat = movie->format_name ? av_find_input_format(movie->format_name) : NULL;



    movie->format_ctx = NULL;

    if ((ret = avformat_open_input(&movie->format_ctx, movie->file_name, iformat, NULL)) < 0) {

        av_log(ctx, AV_LOG_ERROR,

               "Failed to avformat_open_input '%s'\n", movie->file_name);

        return ret;

    }

    if ((ret = avformat_find_stream_info(movie->format_ctx, NULL)) < 0)

        av_log(ctx, AV_LOG_WARNING, "Failed to find stream info\n");



    // if seeking requested, we execute it

    if (movie->seek_point > 0) {

        timestamp = movie->seek_point;

        // add the stream start time, should it exist

        if (movie->format_ctx->start_time != AV_NOPTS_VALUE) {

            if (timestamp > 0 && movie->format_ctx->start_time > INT64_MAX - timestamp) {

                av_log(ctx, AV_LOG_ERROR,

                       "%s: seek value overflow with start_time:%"PRId64" seek_point:%"PRId64"\n",

                       movie->file_name, movie->format_ctx->start_time, movie->seek_point);

                return AVERROR(EINVAL);

            }

            timestamp += movie->format_ctx->start_time;

        }

        if ((ret = av_seek_frame(movie->format_ctx, -1, timestamp, AVSEEK_FLAG_BACKWARD)) < 0) {

            av_log(ctx, AV_LOG_ERROR, "%s: could not seek to position %"PRId64"\n",

                   movie->file_name, timestamp);

            return ret;

        }

    }



    for (i = 0; i < movie->format_ctx->nb_streams; i++)

        movie->format_ctx->streams[i]->discard = AVDISCARD_ALL;



    movie->st = av_calloc(nb_streams, sizeof(*movie->st));

    if (!movie->st)

        return AVERROR(ENOMEM);



    for (i = 0; i < nb_streams; i++) {

        spec = av_strtok(stream_specs, "+", &cursor);

        if (!spec)

            return AVERROR_BUG;

        stream_specs = NULL; /* for next strtok */

        st = find_stream(ctx, movie->format_ctx, spec);

        if (!st)

            return AVERROR(EINVAL);

        st->discard = AVDISCARD_DEFAULT;

        movie->st[i].st = st;

        movie->max_stream_index = FFMAX(movie->max_stream_index, st->index);

        movie->st[i].discontinuity_threshold =

            av_rescale_q(movie->discontinuity_threshold, AV_TIME_BASE_Q, st->time_base);

    }

    if (av_strtok(NULL, "+", &cursor))

        return AVERROR_BUG;



    movie->out_index = av_calloc(movie->max_stream_index + 1,

                                 sizeof(*movie->out_index));

    if (!movie->out_index)

        return AVERROR(ENOMEM);

    for (i = 0; i <= movie->max_stream_index; i++)

        movie->out_index[i] = -1;

    for (i = 0; i < nb_streams; i++) {

        AVFilterPad pad = { 0 };

        movie->out_index[movie->st[i].st->index] = i;

        snprintf(name, sizeof(name), "out%d", i);

        pad.type          = movie->st[i].st->codecpar->codec_type;

        pad.name          = av_strdup(name);

        if (!pad.name)

            return AVERROR(ENOMEM);

        pad.config_props  = movie_config_output_props;

        pad.request_frame = movie_request_frame;

        ff_insert_outpad(ctx, i, &pad);

        if ( movie->st[i].st->codecpar->codec_type == AVMEDIA_TYPE_AUDIO &&

            !movie->st[i].st->codecpar->channel_layout) {

            ret = guess_channel_layout(&movie->st[i], i, ctx);

            if (ret < 0)

                return ret;

        }

        ret = open_stream(ctx, &movie->st[i]);

        if (ret < 0)

            return ret;

    }



    av_log(ctx, AV_LOG_VERBOSE, "seek_point:%"PRIi64" format_name:%s file_name:%s stream_index:%d\n",

           movie->seek_point, movie->format_name, movie->file_name,

           movie->stream_index);



    return 0;

}
