что делает функция write_back_intra_pred_mode() из libavcodec?

Ниже приведена функция из ffmpeg, определенная в libavcodec/h264.h:

static av_always_inline void write_back_intra_pred_mode(const H264Context *h,
                                                        H264SliceContext *sl)
{
    int8_t *i4x4       = sl->intra4x4_pred_mode + h->mb2br_xy[sl->mb_xy];
    int8_t *i4x4_cache = sl->intra4x4_pred_mode_cache;

    AV_COPY32(i4x4, i4x4_cache + 4 + 8 * 4);
    i4x4[4] = i4x4_cache[7 + 8 * 3];
    i4x4[5] = i4x4_cache[7 + 8 * 2];
    i4x4[6] = i4x4_cache[7 + 8 * 1];
}

Что делает эта функция?

Можете ли вы объяснить тело функции?


person firoozg    schedule 12.01.2016    source источник


Ответы (1)


Функция обновляет кеш режимов внутреннего предсказания на уровне кадра (с разрешением блока 4x4), расположенный в переменной sl->intra4x4_pred_mode для среза или h->intra4x4_pred_mode для всего кадра. Этот кеш позже используется в h264_mvpred.h, в частности в функции fill_decode_caches() вокруг строки 510-528. , чтобы установить контекстную (левый/над соседним) информацию о блоке для декодирования последующих блоков intra4x4, расположенных ниже или справа от текущего набора блоков 4x4.

[редактировать]

Хорошо, еще немного о дизайне переменных здесь. sl->mb_xy равно sl->mb_x + sl->mb_y * mb_stride. Думайте о mb_stride как о расширенной версии ширины (в мегабайтах) изображения. Таким образом, mb_xy — это растровый индекс текущего макроблока. Некоторые переменные индексируются в блочном разрешении (4x4), а не в макроблоке (16x16), поэтому для преобразования между единицами измерения используется mb2br_xy. Это должно объяснить расположение кэша на уровне кадра (intra4x4_pred_mode/i4x4).

Теперь, локальный кэш для каждого макроблока, он содержит записи 4x4 для текущего макроблока, плюс записи слева/над краем, так что 5x5. Однако умножение чего-то на 5 занимает 2 регистра в инструкции lea, тогда как 8 занимает только один, поэтому мы предпочитаем 8 (в более общем случае мы предпочитаем степень двойки). Таким образом, разрешение становится 8(ширина)x5(высота) для всего 40 элементов, из которых 3 левых в каждой строке не используются, четвертый является левым краем, а 4 правых являются фактическими элементами текущего макроблока. Верхняя строка находится выше, а 4 строки ниже — это фактические записи текущего макроблока.

Из-за этого обратная копия из кеша в кеш всего кадра использует 8 в качестве шага, 4/3/2/1 в качестве индексов для y=3/2/1/0 и 4-7 в качестве индексов для x=0-3. В резервной копии вы заметите, что мы на самом деле копируем не весь блок 4x4, а только последнюю строку (AVCOPY32 копирует 4 записи, offset=4[y=3]+8[шаг]*4[x=0] ) и самая правая запись для каждой из остальных строк (7[x=3]+8[шаг]*1-3[y=0-2]). Это потому, что только правый/нижний край интересен как верхний/левый контекст для будущего декодирования макроблока, поэтому остальное не нужно.

В качестве иллюстрации макет i4x4_pred_mode_cache выглядит следующим образом:

x x x TL T0 T1 T2 T3
x x x L0 00 01 02 03
x x x L1 10 11 12 13
x x x L2 20 21 22 23
x x x L3 30 31 32 33

x означает неиспользуемый, TL — верхний левый, Ln — левый [n], Tn — верхний [n], а пронумерованные элементы ab равны y=a,x=b для блоков 4x4 в макроблоке 16x16.

Вам может быть интересно, почему TL помещается в [3] вместо [0], т.е. почему он не TL T0-3 x x x (и так далее для остальных строк); причина этого в том, что в кадровом и блочном кэше T0-3 (и 00-03, 10-13, 20-23, 30-33) представляют собой 4-байтовые выровненные наборы из 4 режимов, что означает что копирование 4 записей в одной инструкции (COPY32) выполняется значительно быстрее на большинстве машин. Если бы мы сделали невыровненную копию, это добавило бы дополнительных накладных расходов и замедлило бы декодирование (немного).

person Ronald S. Bultje    schedule 12.01.2016
comment
Но что такое 40 членов sl->intra4x4_pred_mode и почему эта функция копирует некоторые из своих членов в другой индекс? - person firoozg; 14.01.2016
comment
intra_pred_mode_cache для текущего блока (16x16 пикселей). intra_pred_mode — контекст для всего кадра. Он копирует его, чтобы все соответствующие элементы в цикле блочного декодирования находились в меньшей области памяти, что повышает производительность благодаря улучшенному кэшированию памяти, но по-прежнему имеет доступ ко всем членам уровня кадра для последующих итераций блочного декодирования. - person Ronald S. Bultje; 14.01.2016
comment
если intra_pred_mode_cache для текущего макроблока, почему он имеет 40 элементов, а не 16? и все же я не понимаю индексы в приведенной выше функции, а также массив h->mb2br_xy. - person firoozg; 14.01.2016
comment
У меня есть видео с размером кадра 854x480. 854/16 = 53,375, поэтому mb_stride должно быть 54. Но если я напечатаю значение mb_stide, я получу 55. Что происходит? - person firoozg; 14.01.2016
comment
ffmpeg.org/doxygen/trunk/h264__slice_8c_source.html#l01348 — наиболее контекстуальный массивам требуется одно заполнение слева, чтобы его можно было инициализировать в контекстных целях для самого левого макроблока в каждой строке. - person Ronald S. Bultje; 14.01.2016