Как кодировщик h.264 определяет, куда помещать i-кадры?

Я немного читаю об I-кадрах и их аналогах, P-кадрах и B-кадрах. Я понимаю использование. I-кадры являются ключом к сжатию, а последующие P- и B-кадры могут использовать данные в I-кадрах для экономии битов.

Однако мне было бы интересно узнать, как кодировщик определяет, какие кадры должны быть I-кадрами, а какие должны быть P и B, и извлекает из них свои данные. Как кодер решает, какие кадры будут I-кадрами?


Побочные мысли (отвечать не обязательно, но они мне интересны и полезны в будущем): I-кадры проще, например, быстрее находить и извлекать, чем, скажем, извлекать каждый 30-й кадр? Если видео представляет собой слайд-шоу со звуком и без анимации слайдов, могут ли I-кадры совпадать со сменой слайдов? Будет ли сжатие лучше для видео, сделанного из изображений слайдов, чем для тех же изображений, снятых через поток в реальном времени?

Должен ли я использовать тег ключевых кадров ? Должен ли быть тег i-frames или это должен быть синоним?
В дополнение к прекрасному ответу @Mulvya, есть случай, когда более старые кодеки и кодеры размещают I-кадры через фиксированные интервалы независимо от необходимости. Это была эпоха «GOP фиксированной длины».
«Ключевой кадр» используется в After Effects и других анимационных приложениях для описания точки на временной шкале, где установлено значение. «I-Frame» более конкретен
Тот же термин используется в коде ffmpeg и x264, и я подозреваю, что в большинстве/всех других кодеках.

Ответы (1)

Это сложная тема, и точный алгоритм уникален для каждого кодировщика.

Ниже приведено объяснение псевдокода от разработчика x264. B-кадры не учитываются, но основная логика должна быть аналогичной.

encode current frame as (a really fast approximation of) a P-frame and an I-frame.

if ((distance from previous keyframe) > keyint) then
    set IDR-frame
else if (1 - (bit size of P-frame) / (bit size of I-frame) < (scenecut / 100) * (distance from previous keyframe) / keyint) then
    if ((distance from previous keyframe) >= minkeyint) then
        set IDR-frame
    else
        set I-frame
else
    set P-frame

encode frame for real.

scenecutпороговое значение смены сцены. 0означает, что текущий кадр идентичен предыдущему кадру, а 100означает, что он полностью отличается.

keyintмаксимально допустимое расстояние между двумя ключевыми кадрами; minkeyintэто минимум.

IDRкадры (мгновенное обновление декодера) являются ключевыми кадрами, так что никакой будущий кадр не требует обращения к кадру, предшествующему IDR-кадру для декодирования. Не обязательно верно для простых I-кадров.