Открытый поток с FFmpeg libavformat завершает работу с ошибкой ввода-вывода один раз в приложении Android

Я пытаюсь открыть видеопоток в приложении для Android. В первый раз, когда я открываю поток, он открывается, и все работает нормально. Однако, если я нажму кнопку «Назад» и снова открою поток, приложение выйдет из строя.

Я новичок в этом, поэтому я использовал операторы журнала, чтобы увидеть, могут ли значения аргументов для методов привести меня к проблеме. Я понял, что avformat_open_input(&ic, is->filename, is->iformat, NULL) возвращает ошибку ввода-вывода. Однако я не могу понять, в чем заключается ошибка, имя файла и формат совпадают, но я не уверен в &ic, который принадлежит is->ic = (AVFormatContext*) avformat_alloc_context(), я был бы признателен за любую помощь!

void get_video_info(int p_debug, const char* path) {

    int flags;
    //VideoState *is;
    int err, i, orig_nb_streams, ret;
    isquit = 0;
    av_log_set_flags(AV_LOG_SKIP_REPEATED);
    int st_index[3];
    st_index[AVMEDIA_TYPE_AUDIO]=-1;
    st_index[AVMEDIA_TYPE_VIDEO]=-1;
    /* register all codecs, demux and protocols */
    avcodec_register_all();
#if CONFIG_AVDEVICE
    avdevice_register_all();
#endif
#if CONFIG_AVFILTER
    avfilter_register_all();
#endif
    av_register_all();
#if CONFIG_NETWORK
    ret = avformat_network_init();
#endif
     if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO | SDL_INIT_TIMER)) {
            fprintf(stderr, "Could not initialize SDL - %s\n", SDL_GetError());
            exit(1);
          }

    av_init_packet(&flush_pkt);
    flush_pkt.data = "FLUSH";

    // open video stream
    is = av_mallocz(sizeof(VideoState));
    if (!is) {
        do_exit(NULL);
        return;
    }

    is->abort_request = 0; // FIXME: abort_request changes when on closing or exit
    is->pictq_mutex = SDL_CreateMutex();
    is->pictq_cond = SDL_CreateCond();
    is->pictq_size = 0;
    is->pictq_rindex = 0;
    is->pictq_windex = 0;
    is->av_sync_type = av_sync_type;//AV_SYNC_AUDIO_MASTER;//

    if(path != NULL)
    {
        av_strlcpy(is->filename, path, sizeof(is->filename));
    }
    else
    {
        if(streamProtocal==0) {
            av_strlcpy(is->filename, "/sdcard/download/sdp_file.sdp", sizeof(is->filename));
        }
        else
        {
            av_strlcpy(is->filename, "udp://@:3001", sizeof(is->filename));
            is->iformat = av_find_input_format("m4v");
        }
    }
    is->ic = (AVFormatContext*) avformat_alloc_context();
    //It is assumed that server always sends m4v data, so that codec search can be avoided
    AVFormatContext *ic = is->ic;

    if ((err = avformat_open_input(&ic, is->filename, is->iformat, NULL))
            != 0) {
        LOGE(1, "Error open video file: %s", is->filename);
        char* error = (char*)malloc(1024);
        av_strerror(err, error, 1024);
        LOGE(1, "Error open video file: %s", error);
        do_exit(is);
    }
    LOGE(1, "entered get_video_info");
    is->ic = ic;

    orig_nb_streams = ic->nb_streams;
    if ((err = avformat_find_stream_info(is->ic, NULL)) < 0) {
        LOGE(1, "Error find stream information: %d", err);
        return;
    }
    LOGE(1, "avformat_find_stream_info");
    if(is->ic->pb)
        is->ic->pb->eof_reached= 0;//FIXME hack, ffplay maybe should not use url_feof() to test for the end
    AVCodec *lvideoCodec;

int g_audio_file_type = 0;
    // Find the first video stream
        for (i=0; i<is->ic->nb_streams; i++) {
            //take video stream only for video file types
            if (g_audio_file_type == 0)  {
                if (is->ic->streams[i]->codec->codec_type==AVMEDIA_TYPE_VIDEO &&
                        st_index[AVMEDIA_TYPE_VIDEO] < 0)
                {
                    st_index[AVMEDIA_TYPE_VIDEO]=i;
                }
            }

            if(is->ic->streams[i]->codec->codec_type==AVMEDIA_TYPE_AUDIO &&
                    st_index[AVMEDIA_TYPE_AUDIO] < 0)
            {
                st_index[AVMEDIA_TYPE_AUDIO]=i;
            }

        }
    if (st_index[AVMEDIA_TYPE_AUDIO] >= 0) {
        stream_component_open(is, st_index[AVMEDIA_TYPE_AUDIO]);
    }
    if (st_index[AVMEDIA_TYPE_VIDEO] >= 0) {
        stream_component_open(is, st_index[AVMEDIA_TYPE_VIDEO]);
    }
    if (is->video_stream < 0) {
        do_exit(is);
        return;
    }
    is->read_tid = SDL_CreateThread(read_thread, is);
    rgb_frame = avcodec_alloc_frame();
}

person miazima    schedule 15.02.2015    source источник
comment
в зависимости от того, как jni структурирован над показанным собственным методом, вы можете просмотреть это: stackoverflow.com/questions/10649119/, вы должны будьте очень осторожны с интерфейсом и его состоянием в отношении последовательных вызовов к нему. Не то, чтобы дополнительный помощник (загрузчик, разгрузчик) требовался для библиотеки   -  person Robert Rowntree    schedule 16.02.2015
comment
@RobertRacentree Спасибо, что направили меня к этому посту, я думаю, это должно быть проблемой, с которой я столкнулся. Однако у меня возникли проблемы с реализацией предоставленного решения, было бы очень полезно, если бы вы могли проверить мой вопрос   -  person miazima    schedule 20.02.2015
comment
Некоторые другие ответы SO ffmpeg входят в подробности MorE о командах макроса закрытия загрузки для библиотеки, когда вы делаете последовательные вызовы   -  person Robert Rowntree    schedule 21.02.2015
comment
stackoverflow.com/questions/10649119/ подробнее ...   -  person Robert Rowntree    schedule 24.02.2015