Кодировать rgb в yuv420p с помощью libav

Я пытаюсь преобразовать вектор данных изображения RGB (полученный из изображения .png) в формат YUV420p, используя libav.

В примере кода libav для создания фиктивного образа используется следующее:

/* prepare a dummy image */
static void fill_yuv_image(AVFrame *pict, int frame_index, int width, int height)
{
    int x, y, i;

    i = frame_index;

    /* Y */
    for(y=0;y<height;y++) {
        for(x=0;x<width;x++) {
            pict->data[0][y * pict->linesize[0] + x] = x + y + i * 3;
        }
    }

    /* Cb and Cr */
    for(y=0;y<height/2;y++) {
        for(x=0;x<width/2;x++) {
            pict->data[1][y * pict->linesize[1] + x] = 128 + y + i * 2;
            pict->data[2][y * pict->linesize[2] + x] = 64 + x + i * 5;
        }
    }
}

Мне не ясно несколько вещей здесь:

Во-первых, нужно ли переупорядочивать данные RGB во входном векторе, чтобы они подходили для кодирования как YUV420p?

Во-вторых, я понимаю, что для каждого пикселя есть значение Y и что значения Cb и Cr используются для четырех (2x2) пикселей. Чего я не понимаю, так это того, как данные RGB «сокращаются» до значений Cb и Cr — есть ли где-нибудь пример того, как это сделать?


person user2063909    schedule 12.02.2013    source источник


Ответы (1)


Я не совсем уверен, чего именно вы пытаетесь достичь, поэтому я просто отвечу на ваши вопросы, насколько смогу (не стесняйтесь добавлять уточняющие комментарии):

1) Вы будете преобразовывать данные RGB в YUV, что потребует некоторой перестановки. Упакованные данные RGB прекрасны там, где они есть. Вам действительно не нужно его настраивать. На самом деле, вероятно, было бы лучше оставить его упакованным из соображений локальности кеша.

2) Как вы уже поняли, YUV 4:2:0 кодирует образец Y для каждого пикселя, но каждый блок 2x2 имеет общие значения Cb и Cr. Однако есть и данные YUV 4:4:4. Здесь каждый пиксель получает свой собственный образец Y, Cb и Cr. Простая стратегия преобразования RGB -> YUV 4:2:0 заключается в преобразовании RGB -> YUV 4:4:4 и последующем усреднении (среднем арифметическом) каждого блока 2x2 выборок Cb. Существуют и другие алгоритмы (например, фильтры, включающие больше окружающих сэмплов), но этот должен работать, если вы просто экспериментируете с тем, как работает этот материал.

Другая стратегия для экспериментов (и скорости) состоит в том, чтобы вычислять только плоскость Y и поддерживать плоскости Cb и Cr постоянными на уровне 128. Это приведет к изображению в градациях серого.

Для реальной работы вы, вероятно, захотите использовать встроенные средства преобразования, которые может предложить libav.

person Multimedia Mike    schedule 13.02.2013
comment
Во-первых, спасибо за ваш ответ. Я работаю над программой анимации ОС Pencil2D. На данный момент я пытаюсь заставить работать экспорт файлов. В качестве теста я хотел закодировать файл фильма, используя одно изображение (т.е. 2 секунды статического изображения). - person user2063909; 13.02.2013