Я разрабатываю специальный видеоплеер, который применяет «фильтры» для каждого декодированного кадра. Моя текущая цель - масштабировать декодированный кадр (без ограничений, за исключением предела памяти).Масштабирование IDirect3DSurface9
Часть декодирования выполняется с использованием ffmpeg (av_read_frame, avcodec_send_packet, avcodec_receive_frame). EVR из Media Foundation используется в качестве рендеринга видео. Точнее, я извлекаю «образец» (который является всего лишь оберткой вокруг обычной экранной поверхности d3d), ffmpeg использует этот буфер для хранения декодированного фрейма, и я даю этот «образец» визуализатору, который кэширует его, а затем представляет его на экране при необходимости (время представления из временной метки образца, скорости воспроизведения и системных часов).
я получить поверхности (формат = X8R8G8B8, тип = D3DRTYPE_SURFACE, использование = 0, бассейн = D3DPOOL_DEFAULT, Мультисэмпл = DDMULTISAMPLE_NONE) из пула доступных поверхностей (через IMFVideoSampleAllocator). Работа с данными RGB32 является требованием, и декодированные кадры преобразуются при необходимости.
Что касается функции масштабирования/масштабирования, я сначала использовал функцию libswscale (функция sws_scale) с SWS_FAST_BILINEAR, но для изменения размера моего кадра с 1920x800 до 1920x400 требуется ~ 80 мс (фиксированные значения для целей тестирования). Затем я попытался сделать масштабирование себя, используя наивный билинейный алгоритм, но это было хуже и уходило на пол.
Я выполнил минимальный тестовый пример, который загружает BMP-файл, масштабирует его и записывает масштабированные данные в другой BMP. Удивительно, что тот же код занимает ~ 15 мс (libswcale) или ~ 30 мс (наивный билинейный).
Затем я модифицировал свой видеоплеер, используя av_image_alloc и av_image_copy_to_buffer. Выделение не требует времени, копирование занимает целую секунду, а масштабирование занимает 5 мс. Вся часть слишком медленная, чтобы делать масштабирование в реальном времени, но это показывает, что существует большая разница между «происхождением» памяти (поверхность malloc'ed или d3d).
Выравнивание данных может быть причиной медленности, но мой тестовый пример использует тот же шаблон в памяти (шаг = ширина * 4, снизу вверх), и это намного быстрее. Я печатал входной и выходной буфер% 16, и это 0, поэтому мне кажется безопасным.
Я также пробовал использовать метод StretchRect, но он не работает между внешними поверхностями.
Есть идеи? NB: Я планирую создавать поверхности и представлять их самостоятельно, поэтому часть рендеринга является слабой зависимостью для меня. Итак, если у вас есть простой образец D3D в качестве ссылки, я возьму его.
Я думаю, вы можете использовать DXVA2/DXVA-HD для масштабирования. – VuVirt