Алгоритм сжатия видео 'pixel behaviour check'

Информация - Компьютеры, программирование

Другие материалы по предмету Компьютеры, программирование

re InitFrame;

var

W: Word; // ширина

H: Word; // высота

I: DWord; // индекс плоскости в массиве опорного кадра

begin

// читаем заголовок видеопотока из некоторого файла

BlockRead(F1, Header, SizeOf(Header));

// устанавливаем размер массива опорного кадра

I := Header.Width * Header.Height * 3;

SetLength(Frame, I);

// сначала обнулим остальные поля элементов массива опорного кадра

// (поле cpIndex обнуляем значением 0FFFFh)

repeat

Dec(I);

Frame[I].cpIndex := $FFFF;

Frame[I].cpBehaviour := 0;

Frame[I].cpCode := 0;

Frame[I].cpRepeat := 0;

Frame[I].cpExtent := 0;

until I = 0;

// теперь занесем значения полей StartRCr, StartGY и StartBCb

// в соответствующие цветовые плоскости опорного кадра

for H := 1 to Header.Height do begin

for W := 1 to Header.Width do begin

// вычисляем в переменной I индекс элемента массива

// опорного кадра, с которого расположены подряд

// три цветовых плоскости пикселя с координатами W и H

// (где W = X, H = Y)

I := (H-1) * Header.Width * 3 + (W-1) * 3;

// а теперь заносим в три плоскости пикселя

// начальные цветовые значения

Frame[I].cpCurrent := Header.StartRCr;

Frame[I+1].cpCurrent := Header.StartGY;

Frame[I+2].cpCurrent := Header.StartBCb;

end;

end;

// читаем массив поведений из файла в переменную Behaviours

ReadBehavioursData(F1, Behaviours);

// сбрасываем внутренний счетчик декодированных кадров,

// а по нему будем определять, что видеопоток закончился

FrameNum := 0;

end;

За заголовком декодер должен прочитать из видеопотока массив поведений. Это обычный массив и декодер должен "сложить" его где-нибудь у себя в памяти, чтобы иметь к нему быстрый доступ в случае кодирования поведения цветовой плоскости пикселя набором поведений из массива. В конце приведенного фрагмента кода указан вызов якобы уже написанной процедуры ReadBehavioursData, которая загружает массив поведений из файла в переменную с именем Behaviours. Эта переменная содержит в себе количество элементов в массиве (поле ItemCount) и массив Behaviours с элементами, представляющими собой наборы поведений. У каждого набора есть поле Count (количество поведений в наборе) и поле Behaviour с набором этих поведений. Отмечу, что в наборе поведений всегда есть хотя бы одно поведение, поэтому поле Count со значение 0 обозначает одно поведение, со значением 1 - два поведения, и так далее до 255, что обозначает 256 поведений.

За массивом поведений следует набор сведений о поведении конкретных цветовых плоскостей пикселей изображения - общий видеопоток. Декодер извлекает эти сведения, опираясь на данные элементов массива опорного кадра. Если в некотором элементе массива поле cpIndex равно 0FFFFh (поведение цветовой плоскости пикселя было взято прямо из видеопотока) и поле cpRepeat равно нулю (повторы поведения закончились), значит, сейчас в видеопотоке находятся данные о следующем поведении текущей цветовой плоскости пикселя, и эти данные нужно извлечь и занести в текущий элемент массива. Если же это не так, и поле cpRepeat не равно нулю (еще остались повторы поведения), тогда нужно в текущем элементе массива уменьшить на 1 поле cpRepeat и, в зависимости от поля cpCode (00, 01 или 10), либо оставить без изменения, либо увеличить или уменьшить поле cpCurrent на величину поля cpExtent.

Образно говоря, декодирование каждого кадра начинается с того, что декодер проходит последовательно все элементы массива опорного кадра - от первого до последнего элемента (фактически проходит по всем цветовым плоскостям пикселей видеокадра). Если в поле cpRepeat остались повторы, тогда уменьшить поле cpRepeat на 1, а к полю cpCurrent прибавить или отнять (в зависимости от значения поля cpCode) значение поля cpExtent. Новое значение поля cpCurrent и будет тем, что заносится в соответствующую цветовую плоскость пикселя реального кадра на экране. Но перед этим значение поля должно быть еще обработано, о чем будет рассказано ниже.

// глобальные переменные

var

Header: PBCvideoHeader; // заголовок видеопотока

Behaviours: PBCvideoBehaviours; // массив поведений

Frame: array of ColorPlane; // опорный кадр

procedure CreateNextFrame;

var

I: DWord; // индекс плоскости в массиве опорного кадра

L: DWord; // количество элементов в массиве опорного кадра

C: Byte; // код только что прочитанного поведения

R: Word; // количество повторов поведения

E: Byte; // величина изменения плоскости за весь период поведения

begin

L := Length(Frame);

I := 0;

while I < L do begin

// если еще остались повторы для текущей цветовой плоскости,

// тогда вычислить значение цветовой плоскости для

// текущего кадра

if Frame[I].cpRepeat <> 0 then begin

Dec(Frame[I].cpRepeat);

// при поведении 00 цветовая плоскость не изменяется,

// поэтому в структуре CASE не используется проверка на 00,

// а код 11 всегда заменяется реальным поведением из набора поведений,

// поэтому его проверка тоже не нужна

case Frame[I].cpCode of

01: Frame[I].cpCurrent := Frame[I].cpCurrent + Frame[I].cpExtent;

10: Frame[I].cpCurrent := Frame[I].cpCurrent - Frame[I].cpExtent;

end;

end else begin

// этот фрагмент смотрите ниже, где рассматривается, что происходит,

// если в поле cpRepeat не осталось повторов

end;

Inc(I);

end;

end;

Когда же в поле cpRepeat не осталось повторов, декодер должен проанализировать поле cpIndex. Если там не указан индекс обслуживаемого набора поведений цветовой плоскости пикселя (cpIndex = 0FFFFh), тогда нужно взять следующее поведение прямо из видеопотока и занести его данные в текущий элемент массива опорного кадра. Как уже было сказано ранее, декодер должен уметь обслуживать специальный код внедрения других данных в видеопоток, и продолжать декодирование видео после внедренного блока данных. Заметьте, что в элементах опорного кадра хранятся коды реальных поведений, чтобы знать, что в действительно?/p>