ffmpeg avcodec_receive_packet возвращает -11

Я попытался создать видео из последовательности входных изображений с помощью API ffmpeg.

Сначала я читаю AVFrame из входного файла, затем перехожу к avcodec_send_frame(), но когда я вызываю avcodec_get_packet() для получения закодированного пакета, он возвращает -11 (в текущем состоянии вывод недоступен).

Я просто новичок, поэтому я не знаю, если что-то не так в моем коде.

Вот мой исходный код:

for (unsigned int i = 0; i < nb_input; ++i) {
        const char *item = input[i];
        ret = open_input_file(item);
        if(ret < 0) {
            goto end;
        }
        packet = av_packet_alloc();
        if(packet == NULL) {
            _log_e("Cannot allocate packet");
            goto end;
        }
        ret = av_read_frame(_ifmt_ctx, packet);
        if(ret < 0) {
            goto end;
        }
        av_packet_rescale_ts(packet,
                             _ifmt_ctx->streams[0]->time_base,
                             _decode_ctx->time_base);

        ret = avcodec_send_packet(_decode_ctx, packet);
        if (ret < 0) {           
            goto end;
        }

        frame = av_frame_alloc();
        if(frame == NULL) {
            ret = AVERROR(ENOMEM);
            _log_e_2("Failed to allocate frame variable for this file : %s ", item);
            goto end;
        }
        ret = avcodec_receive_frame(_decode_ctx, frame);
        if (ret == 0) {
            /*
             * DO FILTER PROCESSING HERE
             */
        } 

        for (int j = 0; j < 25; ++j) {
            ret = avcodec_send_frame(_encode_ctx, frame);
            if (ret < 0) {
                _log_e_2("Failed to send frame at pts = %d", pts);
                goto end;
            }
            AVPacket *out_packet;
            out_packet = av_packet_alloc();
            if(out_packet == NULL) {
                _log_e_2("Failed to allocate output packet at pts = %d" , pts);
                goto end;
            }
            ret = avcodec_receive_packet(_encode_ctx, out_packet);
            if(ret < 0) {
                _log_e_2("Failed to receive encoded packet at pts = %d" , pts);
                if (ret == AVERROR(EAGAIN)) {
                    _log_e(" output is not available in the current state - user must try to send input");
                }
                else if (ret == AVERROR_EOF) {
                    _log_e(" the encoder has been fully flushed, and there will be no more output packets");
                }
                else if (ret == AVERROR(EINVAL)) {
                    _log_e(" codec is not opened");
                }
                av_packet_unref(out_packet);
                goto end;
            }
            _log_v_2("Write encoded packet at pts = %d to output file", pts);
            ret = av_interleaved_write_frame(_ofmt_ctx, out_packet);
            if (ret < 0) {
                _log_e_2("Failed to write encoded packet at pts = %d to output file", pts);
                goto end;
            }
            av_packet_unref(out_packet);
            pts++;
        }

person tainguyen    schedule 09.07.2018    source источник
comment
См. Как спросить. Ваш код должен быть минимально воспроизводимым примером и находиться в теле вопроса. Редактируйте вопрос и сообщите нам, что вы хотите сделать, покажите, что вы пробовали, и сообщите, какой результат вы получили.   -  person    schedule 09.07.2018
comment
@jdv Я отредактировал свой вопрос, извините за это.   -  person tainguyen    schedule 09.07.2018
comment
Кстати, в вашем коде нет ссылок на avcodec_get_packet() или avcodec_send_frame(). Можете ли вы показать точное сообщение об ошибке или неожиданные результаты, которые вы получаете? При этом -11 звучит подозрительно похоже на EAGAIN, что, вероятно, связано с буферизацией, согласно blogs.gentoo.org/lu_zero/2016/03/29/new-avcodec-api   -  person    schedule 09.07.2018
comment
о, извините, я исправил свой исходный код. Это во втором цикле for функции main(), и сообщение об ошибке выводится недоступно в текущем состоянии - пользователь должен попытаться отправить ввод. Я не знаю, что это значит?   -  person tainguyen    schedule 09.07.2018
comment
Убедитесь, что вы показываете полное сообщение об ошибке (и это ошибка во время выполнения или во время компиляции? Будьте ясны!) В самом вопросе. Вопросы должны быть автономными, а комментарии могут быть удалены. Это поможет вашему вопросу привлечь больше внимания людей, которые в состоянии дать полный ответ.   -  person    schedule 09.07.2018
comment
Таким образом, это сообщение об ошибке выводится во время выполнения из вашего собственного кода и в ответ на получение сообщения EAGAIN. Вам нужно вернуться к документации по API и выяснить, почему вы получите такой результат в данный момент и что с этим делать. Есть несколько других ресурсов, если вы ищете этот API и этот результат. В ссылке, которую я предоставил, есть очень хороший намек, кстати.   -  person    schedule 09.07.2018


Ответы (1)


Кодеру требуется несколько входных кадров, прежде чем он выведет первый закодированный кадр. Вы должны игнорировать EAGAIN и просто подавать следующий входной кадр.

person micha137    schedule 10.07.2018
comment
Итак, сколько входных кадров требуется кодировщику для вывода первого закодированного кадра? - person tainguyen; 10.07.2018
comment
Это зависит от количества кадров B - person micha137; 10.07.2018
comment
можно поподробнее об этом, я только новичок - person tainguyen; 10.07.2018
comment
H.264 кодирует кадры в кадры I B или P. Кадры I используют только внутреннее кодирование, аналогично изображению jpg. P-кадры представляют собой предсказанные кадры, которые кодируются с использованием одного или нескольких опорных изображений, то есть I или других P-кадров, которые были закодированы ранее. Наконец, кадры B представляют собой кадры с двойным предсказанием, которые могут использовать другие кадры I, P и B. Таким образом, чтобы закодировать B-кадр, кодер сначала должен закодировать P-кадр, который следует за ним. Он может кодировать этот P-кадр только после того, как вы его передали. Часто используются только два последовательных B-кадра, поэтому для кодирования первого из них кодеру необходимо предоставить еще 2 кадра. - person micha137; 10.07.2018