Подтвердить что ты не робот

Как я могу найти номер X с ffmpeg?

Я пишу видеоредактор, и мне нужно искать точный кадр, зная номер кадра.

Другие сообщения в stackoverflow сказали мне, что ffmpeg может дать мне несколько сломанных кадров после поиска, что не является проблемой для воспроизведения, но большая проблема для видеоредакторов.

И мне нужно искать по номеру кадра, а не по времени, что станет неточным при преобразовании в номер кадра.

Я читал о том, как теребят (теперь устаревшие), и в итоге:

av_seek_frame(fmt_ctx, video_stream_id, frame, AVSEEK_FLAG_ANY);

Он всегда ищет рамку No. 0 и всегда return 0, что означает успех. Затем я попытался прочитать исходный код Blender и нашел его очень сложным (может быть, я должен реализовать буфер изображения?).

Итак, есть ли простой способ поиска кадра с помощью простого вызова типа seek(context, frame_number) (при получении полного кадра, а не сломанного)? Или, есть ли облегченная библиотека, которая упрощает это?

EDIT: Благодаря praks411, я нашел решение:

void AV_seek(AV * av, size_t frame)
{
    int frame_delta = frame - av->frame_id;
    if (frame_delta < 0 || frame_delta > 5)
        av_seek_frame(av->fmt_ctx, av->video_stream_id,
                frame, AVSEEK_FLAG_BACKWARD);
    while (av->frame_id != frame)
        AV_read_frame(av);
}

void AV_read_frame(AV * av)
{
    AVPacket packet;
    int frame_done;

    while (av_read_frame(av->fmt_ctx, &packet) >= 0) {
        if (packet.stream_index == av->video_stream_id) {
            avcodec_decode_video2(av->codec_ctx, av->frame, &frame_done, &packet);
            if (frame_done) {
                ...
                av->frame_id = packet.dts;
                av_free_packet(&packet);
                return;
            }
        }
        av_free_packet(&packet);
    }
}
4b9b3361

Ответ 1

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

Однако, если вы имеете дело с фиксированным значением FPS, вы можете легко сопоставить временную метку с индексом кадра.

Перед поиском вам нужно будет преобразовать свое время в единицы AVStream.time_base, если вы указали поток. Прочитайте документацию ffmpeg av_seek_frame в avformat.h.

Например, если вы хотите искать 1.23 секунды клипа:

 double m_out_start_time = 1.23;
 int flgs = AVSEEK_FLAG_ANY;
 int seek_ts = (m_out_start_time*(m_in_vid_strm->time_base.den))/(m_in_vid_strm->time_base.num);
 if(av_seek_frame(m_informat, m_in_vid_strm_idx,seek_ts, flgs) < 0)
 {
     PRINT_MSG("Failed to seek Video ")
 }