В этой статье рассматриваются все операции масштабирования в Intel Media SDK. Масштабирование — одна из самых распространенных операций при обработке видео. Приложение может задать нужную область для каждого видео с помощью конвейера обработки видео (VPP). Используя Intel Media SDK VPP, можно выполнять различные операции масштабирования. Здесь мы описываем две наиболее часто используемые операции и их результаты.
На КДПВ приведена простая блок-схема, показывающая конвейер функций, задействованных при масштабировании.
Обнаружение свободной поверхности кадра — используются поверхности из пула поверхностей, заблокированные поверхности нельзя использовать, поэтому выполняется поиск неиспользуемой поверхности.
int GetFreeSurfaceIndex(mfxFrameSurface1** pSurfacesPool, mfxU16 nPoolSize)
{
if (pSurfacesPool)
for (mfxU16 i = 0; i < nPoolSize; i++)
if (0 == pSurfacesPool[i]->Data.Locked)
return i;
return MFX_ERR_NOT_FOUND;
}
Загрузка необработанного кадра на поверхность — для необработанного кадра считываются плоскости освещенности и цветности, затем загружаются на поверхность.
mfxStatus LoadRawFrame(mfxFrameSurface1* pSurface, FILE* fSource)
{
w = pInfo->Width;
h = pInfo->Height;
pitch = pData->Pitch;
ptr = pData->Y;
//read luminance plane
for (i = 0; i < h; i++) {
nBytesRead = (mfxU32) fread(ptr + i * pitch, 1, w, fSource);
if (w != nBytesRead)
return MFX_ERR_MORE_DATA;
}
mfxU8 buf[2048]; // maximum supported chroma width for nv12
w /= 2;
h /= 2;
ptr = pData->UV;
// load U
sts = ReadPlaneData(w, h, buf, ptr, pitch, 0, fSource);
if (MFX_ERR_NONE != sts)
return sts;
// load V
ReadPlaneData(w, h, buf, ptr, pitch, 1, fSource);
if (MFX_ERR_NONE != sts)
return sts;
}
Операция записи на выходную поверхность — после операции RunFrameVPPSync, асинхронно обрабатывающей кадр. Операция синхронизации вызывается для получения всех выходных данных для их обратной записи в необработанный кадр.
mfxStatus WriteRawFrame(mfxFrameSurface1* pSurface, FILE* fSink)
{
mfxFrameInfo* pInfo = &pSurface->Info;
mfxFrameData* pData = &pSurface->Data;
mfxU32 i, j, h, w;
mfxStatus sts = MFX_ERR_NONE;
for (i = 0; i < pInfo->Height; i++)
sts =
WriteSection(pData->Y, 1, pInfo->Width, pInfo, pData, i, 0,
fSink);
h = pInfo->Height / 2;
w = pInfo->Width;
for (i = 0; i < h; i++)
for (j = 0; j < w; j += 2)
sts =
WriteSection(pData->UV, 2, 1, pInfo, pData, i, j,
fSink);
for (i = 0; i < h; i++)
for (j = 1; j < w; j += 2)
sts =
WriteSection(pData->UV, 2, 1, pInfo, pData, i, j,
fSink);
return sts;
}
Мы будем использовать sample_vpp из учебного руководства на странице Media Solution Portal. Входной файл foreman.yuv можно получить здесь. Загруженный файл будет в формате Y4M, его нужно будет преобразовать в формат YV12 с помощью ffmpeg.
ffmpeg -i input.y4m output.yuv
Для операций масштабирования используются шесть параметров VPP.
- CropX, CropY, CropW, CropH определяют расположение входного и выходного кадров, которое требуется задать явным образом для получения результата.
- Параметры Width и Height следует задать явным образом и для входного, и для выходного кадра. При этом значения высоты и ширины должны быть кратны 16 для кадровых изображений и кратны 32 для полей.
Обрезка — это одна из самых распространенных операций по обработке видео, она часто используется для определения рабочей области (ROI). С ее помощью также можно изменить соотношение сторон видео. Наиболее распространенные изменения: 16:9->4:3 и 4:3->16:9. При изменении соотношения сторон к изображению добавляются черные полосы либо сверху и снизу, либо справа и слева. Ниже приведена таблица входных параметров для обрезки, изменения соотношения сторон с добавлением черных полос сверху и снизу, справа и слева в sample_vpp.
CropX | CropY | CropW | CropH | Ширина | Высота | |
---|---|---|---|---|---|---|
Input | 128 | 128 | 1024 | 464 | 1280 | 720 |
Output_Crop | 0 | 0 | 1024 | 464 | 1024 | 464 |
Output_PillarBoxing | 128 | 0 | 1024 | 720 | 1280 | 720 |
Output_LetterBoxing | 0 | 128 | 1280 | 464 | 1280 | 720 |
Изменение размера — еще одна операция обработки видео, используемая для получения видео изображения нужного размера. Но в этом случае к изображению не добавляются никакие полосы, просто изменяется его разрешение на выходе. Изменение размера возможно и в двух измерениях, и только в одном (можно изменять только ширину или только высоту видео, что соответствует растяжению по горизонтали и по вертикали). Ниже приведена таблица входных параметров изменения размера и растяжения в sample_vpp.
CropX | CropY | CropW | CropH | Ширина | Высота | |
---|---|---|---|---|---|---|
Input | 0 | 0 | 640 | 480 | 640 | 480 |
Output_Re-size | 0 | 0 | 1280 | 720 | 1280 | 720 |
Output_VerticalStretch | 0 | 0 | 640 | 608 | 640 | 608 |
Output_HorizontalStretch | 0 | 0 | 720 | 480 | 720 | 480 |
Более подробные сведения о параметрах и функциях вы найдете в руководстве пользователя, которое находится в папке документов установленной копии MSDK или доступно здесь.
Дополнительные сведения об оптимизации компиляторов см. в нашем уведомлении об оптимизации.
Дополнительные ссылки
Комментарии (2)
MariannaSvetlosanova
16.04.2015 14:47Дублирую ответ от инженеров Intel)
Вместо собственных функций копирования поверхностей нужно использовать инициализацию MediaSDK компонент (кодеков, VPP) с нужным типом памяти.
Если мы говорим о HW имплементации и вам необходимы данные в системной памяти – инициализация с системной памятью, если о SW имплементации и данные необходимы в видео памяти – инициализация с видео памятью
Плюс, нужно избегать случаев, когда происходит неявное копирование, например, используют HW библиотеку и хотят получить данные в видео, но делают следующее: заводят системные поверхности, а потом сами из них копируют в видео – получается двойное копирование
Есть тонкость: для YV12 GPU копирование не работает.
xaoc80
Наш профайлер показывает, что до 60-70%% процессорного времени занимают операции по копированию фреймов (
Вы не пробовали у себя (в т.ч. в примерах) оптимизировать эти операции?
У меня с разверткой циклов, вставками ассемблерных инструкций получалось до 50% оптимизировать, но, похоже это потолок (
А это очень важно, когда речь идет о кодировании десятков каналов на одном сервере
Не получается GPU утилизировать на 100%